%CONSTSTRING (25) VSN="GPC38 28th Sept 81" !************************************************GPC GPC GPC !* !* EMAS 2900 SUPERVISOR NOTE !* No: 5 !* Date: 21/05/80 !* Author: A.Gibbons !* !* !* %EXTERNAL ROUTINE GPC(%RECORD(PARMF)%NAME P) !* !* 1. CONVENTIONS !* The record spec for the parameter is !* %RECORDFORMAT PARMF(%INTEGER DEST,SRCE,P1,P2,P3,P4,P5,P6) !* where !* DEST is considered as two half words DSNO and DACT. DSNO !* must be GPC's DSNO !* DACT is set according to the function required. !* !* SRCE is considered as two halfwords SSNO and SACT. !* SSNO is SNO of ORIGINATOR and SACT is DACT for !* the reply. !* !* DEVICE ENTRIES !* Each device on a GPC is allocated an area (a Device Entry) at !* GROPE time. The address of the Device Entry is given by GPC !* in P_P3 each time a response is generated for ALLOCATE, !* DE-ALLOCATE, EXECUTE and INTERRUPT. The format of the Device !* Entry is given elsewhere. !* !* !* !* !* 2. INPUTS TO GPC !* !* DACT = 2 INITIALISATION. This must be the first call !* P1 = ADDR of preprepared CONFIG TABLE !* P2 = address of PROCESS LIST picture !* DEST must contain SNO for GPC !* For each OPER, GPC pons an allocate message to !* itself with !* P2 = X'320005' !* SRCE = X'320002' ! OP<<8 !* For each FE, GPC pons an allocate message to itself !* with !* P2 = X'390005 !* SRCE = X'390002' !* For each TAPE stream, GPC pons a message !* DEST = X'310004' !* SRCE = X'300000' !* P1 = mnemonic !* !* !* DACT = 11 ALLOCATE DEVICE !* P1 = Device Mnemonic !* P2 = full DEST (i.e. DSNO+DACT) to be used for all !* interrupt responses (ATTENTION, TERMINATION, PCI &RI) !* RESPONSE !* P1 = 0 success !* 1 mnemonic invalid !* 2 alreadt allocated !* P2 = SNO for device to be used in EXECUTE !* P3 = address of device entry !* P6 = mnemonic !* additionally, for an OPER : !* D_X2 = buffer area address !* D_RESP0 = number of screens !* D_X1 = size of buffer area !* NOTE: P4 & P5 are not changed and may be used by the !* caller to hold data !* !* !* DACT = 5 DE ALLOCATE DEVICE !* P1 = device mnemonic !* RESPONSE !* P1 = 0 success !* 1 mnemonic 'LP' not allowed !* 2 mnemonic invalid !* 3<<16!STATE device not allocated !* 4 user attempting to dealloc system device !* P3 = address of device entry !* !* !* DACT = 12 EXECUTE CHAIN !* P1 = RCB address !* P2 = SNO for device returned by ALLOCATE in P2 !* P3 = RSD << 8 ! PAW FUNCTION << 4 ! SAWFLAGS !* (RSD is one bit !* 0 = no special action !* 1 = if chain terminates abnormally, do !* 'READ STREAMS CONTROLLER STATUS' !* controller command. The four status bytes are !* returned in P_P5) !* P4 = an ident field to be returned in P_P6 of !* interrupt responses. !* RESPONSE !* NOTE A response !* is sent only if the call fails. The response to !* a successful call is generated when an interrupt !* is received !* P1 = 1 SNO out of range !* 2 device not ready !* P2 = SNO i.e. P2 of request !* P3 = address of device entry (only if P1 > 1) !* P4 = 0 !* P5 = 0 !* P6 = ident i.e. P4 of request !* !* !* DACT = 6 CLOCK INTERRUPT ENTRY, no parameters, no responses !* !* !* DACT = 3 INTERRUPT ENTRY !* P1 = PT (PORT + TRUNK) !* RESPONSE !* A message is ponned to the dest that was !* supplied in P2 of the ALLOCATE !* P1 = stream response word RESP0 with byte0 !* overwritten with device SNO as returned !* by ALLOCATE !* P2 = stream response word RESP1 !* for all interrupts except attentions, !* RESP0 and RESP1 are also written to the !* appropriate fields in the device entry. !* If a chain has timed out, RESP1 is set !* to -1. !* !* P3 = address of device entry !* P4 = response analysis flags from the response !* to SENSE command (RESP0 >> 16) relevant !* only after an abnormal termination or timeout !* if the rightmost byte does not indicate !* successful termination, then the sense !* information is suspect. !* The sense information is pointed to by the field !* SENS AD in the device entry. It is laid out as !* SECONDARY STATUS, TERTIARY STATUS (as many bytes !* as appropriate) and PRIMARY STATUS. !* P5 = controller status, relevant only if RSD bit !* was set in EXECUTE !* P6 = ident i.e. P4 of most recent EXECUTE !* The following logic may be used to analyse the !* interrupt response: !* integer INTERRUPT ANALYSIS FLAGS !* INTERRUPT ANALYSIS FLAGS = P_P1 >> 20 & 15 !* if INTERRUPT ANALYSIS FLAGS = 1 !* then ATTENTION !* else if INTERRUPT ANALYSIS FLAGS & X'C' > 0 !* then TERMINATION !* else SOMETHING ELSE ie PCI, RI !* fi !* fi !* !* !* !* !* !* DACT = 8 SPECIAL ALLOCATE FOR USE BY ENTER & MAINLP, CALLED NOT PON'D !* P1 = PTSM OR LP !* P2 = DEST (If MAINLP) !* RESPONSE !* P1 = 0 success !* 1 mnemonic invalid !* 2 stream disconnected !* P2 = SNO for device to be used in EXECUTE !* P3 = address of device entry (unless P1 = 1) !* P6 = mnemonic !* !* !* !* !* DACT = 7 RE-CONFIGURE SAC !* P1 = IDENT !* P2 = SAC !* RESPONSE !* P1 = IDENT !* P2 = 0 success !* # 0 mnemonic (string(3)) of device in use on SAC !* !* !* DACT = 1 GPC COMMAND !* P1-P6 contain up to 23 characters of string !* The forms recognised are: !* GPC QS mnemonic !* gives the current state of the device: !* NOT ALLOC, READY, REQ FIRED, SNS FIRED, QUEUED or !* DISCNCTED !* GPC CDS mnemonic OFF !* configures a device (stream) off (see Operations !* Note ) !* GPC CDS mnemonic ON !* GPC CDM mnem1 mnem2 !* Configures an ungroped device in or a groped device out !* E.G. GPC CDM ZX0 LP1 or GPC CDM CR0 ZX1 !* GPC ? !* gives the state of all the devices known to GPC !* !* !* !* !* !* 3. MESSAGES PRODUCED ON LOG (L) AND/OR OPER (O) !* ***** OPER MESSAGES REMOVED 18/7/80 (JM) !* !* from 'CONNECT STREAMS' !* (L ) GPC CONNECT STREAMS pts !* (L ) (DIS)CONNECT STRMs RESP0=response !* (L ) SAW FAILS=n PAW FAILS=n !* (L ) ABN TERM FOR GPTSM gptsm !* !* !* from 'GPC DUMP' !* (L ) GPC INIT RES=response !* from 'PAW NOT CLEARED' !* (L ) GPC PAW NOT CLEARED PT=pt, PAW=paw !* (L ) SAW NOT CLEARED !* from 'READ STRM DATA' !* (L ) GPC READ STRM DATA PTS=pts !* (L ) CRESP0=response !* FIRST ENTRY TO GPC !* (L ) GPC VERSION identifier !* WHEN TIMEOUT DETECTED !* (LO) GPC TIMEOUT dev pt !* from AN INVALID CALL ON GPC(ACT=7) DIS/RE-CONNECT STRM !* (L ) GPC DIS/CONNECT DEV P2=i FLAG=f !* from THE INTERRUPT HANDLER !* (LO) GPC ABTERM pts dev response !* (L ) GPC SPURIOUS INTERRUPT PTS=pts RESP0=response !* MONITOR MESSAGES !* (L ) GPC( IN): ptrec !* (L ) GPC( OUT): ptrec !* (L ) GPC( PONS): ptrec !*! !* ! EXTERNAL REFERENCES !* !* %RECORDFORMAT PARMF(%INTEGER DEST, SRCE, P1, P2, P3, P4, P5, %C P6) !* %EXTERNALINTEGERFNSPEC REALISE(%INTEGER I) %EXTERNALROUTINESPEC SLAVESONOFF(%INTEGER ONOFF); ! 0=OFF, -1=ALL ON %EXTERNALROUTINESPEC GET PSTB(%INTEGERNAME PSTB0, PSTB1) %EXTERNALROUTINESPEC SEMALOOP(%INTEGERNAME SEMA) %EXTERNALROUTINESPEC CONTROLLER DUMP(%INTEGER CONTYPE, PT) %EXTERNALROUTINESPEC WAIT(%INTEGER MILLISECONDS) %EXTERNALROUTINESPEC DUMP TABLE(%INTEGER TABNO, ADR, LEN) %EXTERNALROUTINESPEC PKMONREC(%STRING(20)TXT,%RECORD(PARMF)%NAME P) %EXTERNALSTRINGFNSPEC HTOS(%INTEGER I, PL) %EXTERNALROUTINESPEC PON(%RECORD(PARMF)%NAME P) %EXTERNALROUTINESPEC OPMESS(%%STRING(63) S) %SYSTEMROUTINESPEC MOVE(%INTEGER LENGTH, FROM, TO) %IF MULTIOCP=YES %START %EXTERNALROUTINESPEC RESERVE LOG %EXTERNALROUTINESPEC RELEASE LOG %FINISH %IF (MONLEVEL>>1)&1=YES %START ! KMONNING REQUIRED %EXTRINSICLONGINTEGER KMON %CONSTINTEGER KMONNING = YES %FINISH %ELSE %START %CONSTINTEGER KMONNING = NO %FINISH !* %CONSTINTEGER ABNORMAL TERMINATION=X'00400000' %CONSTINTEGER CONTROLLER DETECTED ERROR=X'00410000' %IF CSU FITTED=YES %START %CONSTINTEGER CSU DEST=X'2A0000' %FINISH %CONSTINTEGER DISCONNECTED=5 %CONSTINTEGER DO CONTROLLER REQUEST=X'04000000' %CONSTINTEGER DO STREAM REQUEST=X'01000000' %CONSTINTEGER ENDLIST=255 %CONSTINTEGER FE=14 %CONSTINTEGER GET STRM DATA=16 %CONSTINTEGER PROCESSING INTERRUPT=1 %CONSTINTEGER TIMING OUT=2 %CONSTINTEGER GPC DEST=X'00300000' %CONSTINTEGER GPC SNO=X'30' %CONSTINTEGER INIT CONTROLLER=X'32000010' ! 3=NO TERM INTS ! 2= INIT ! 10=BYTE COUNT FOR INIT WORDS %CONSTINTEGER LIMIT=5 %CONSTINTEGER LOAD MICROPROGRAM=X'08000000' %CONSTINTEGER LOID=X'6E' %CONSTINTEGER LP=6 %CONSTINTEGER MT=5 %CONSTINTEGER NORMAL TERMINATION=X'00800000' %CONSTINTEGER NOT ALLOCATED=0 %CONSTINTEGER OK=0 %CONSTINTEGER OP=8 %CONSTINTEGER PRIV ONLY=X'00004000' %CONSTINTEGER QUEUED=4 %CONSTINTEGER RA0AD=X'81000000' %CONSTINTEGER RCB BOUND=32 %CONSTINTEGER READ STREAM DATA=7 %CONSTINTEGER READ CONTROL STREAM STATUS=5 %CONSTINTEGER READ STREAMS CONTROLLER STATUS=3 %CONSTINTEGER READY=1 %CONSTINTEGER REQUEST FIRED=2 %CONSTINTEGER SENSE FIRED=3 %CONSTINTEGER SLOTSI=32 %CONSTINTEGER SPURIOUS LIMIT=100 %CONSTINTEGER SU=13 %CONSTINTEGER TICK INTERVAL=2 %CONSTINTEGER TRUNKADDR=X'40000800' %CONSTSTRING(4)%ARRAY COMMAND(1:LIMIT) = "QS ", "CDS ", "CDM ", "? ", "SET " %CONSTSTRING(9)%ARRAY STATES(0:5) = "not alloc", "ready", "req fired", "sns fired", "queued", "discncted" !* %OWNINTEGER CAAS BASE %OWNINTEGER GPCT BASE %OWNINTEGER LAST SLOT %OWNINTEGER LOPT,HIPT %OWNINTEGER MECHPT %OWNINTEGER NO OF GPCS %OWNINTEGER PT GPC BASE %OWNINTEGER PTS BASE %OWNINTEGER STRMQ BASE %OWNBYTEINTEGERARRAYNAME MECHSLOTS %OWNBYTEINTEGERARRAYNAME PTS TO SLOT %OWNBYTEINTEGERARRAYNAME PT TO GPC %OWNBYTEINTEGERARRAYNAME STRM Q %OWNINTEGERARRAYNAME CAAS %OWNINTEGERARRAYNAME TABLE %OWNINTEGERARRAYNAME STRM SEMAPHORE %OWNINTEGERARRAY SPURIOUS INTS(0:15) %OWNSTRING (63) WK !* %EXTERNALINTEGER LP ILLCHAR=X'07'; ! ERCC VALUE (ALSO USED BY GROPE) !* !* LP repertoire addresses and lengths for each of 16 cartidge settings %OWNINTEGERARRAY REPERTOIRE A(0:15) %OWNINTEGERARRAY REPERTOIRE S(0:15) !* %CONSTINTEGERARRAY LP96REP(0:23)=%C X'F0F1F2F3',X'F4F5F6F7',X'F8F94B60',X'7B6B614E',X'C1C2C3E9', X'C4E4E2E3',X'C7C57DC8',X'D1D2D85C',X'D4D5D6D7',X'D9C9C6D3', X'E5E6E7E8',X'7E4D505D',X'4C6D3F6E',X'5B7A7C4F',X'6C5E7F6F', X'4AE05F5A',X'A8A979F0',X'81828384',X'85868788',X'89919293', X'94959697',X'9899A2A3',X'A4A5A6A7',X'C06AA1D0' !* %CONSTINTEGERARRAY LP384REP(0:95)= %C X'F0F1F2F3',X'F4F5F6F7',X'F8F94B9C',X'7B6B614E', X'C1C2C3E9',X'C4E4E2E3',X'C7C57DC8',X'D1D2D85C', X'D4D5D6D7',X'D9C9C6D3',X'E5E6E7E8',X'7E4D505D', X'6C5E7F6F',X'4AE05F5A',X'4C6D3F6E',X'5B7A7C4F', X'81828384',X'85868788',X'89919293',X'F0F1F2F3', X'F4F5F6F7',X'F8F94B60',X'94959697',X'9899A2A3', X'A4A5A6A7',X'A8A979F0',X'9EADEFCA',X'7B6B614E', X'C1C2C3E9',X'C4E4E2E3',X'C7C57DC8',X'D1D2D85C', X'D4D5D6D7',X'D9C9C6D3',X'E5E6E7E8',X'7E4D505D', X'6C5E7F6F',X'4AB7A05A',X'F0F1F2F3',X'F4F5F6F7', X'F8F94B60',X'4CF08B6E',X'5B7A7C4F',X'C06AA1D0', X'9A6D749B',X'FCEAAFED',X'ACAB8F8E',X'8DB5B4B3', X'787776DC',X'DDDEDFB8',X'B9BABBB0',X'7B6B614E', X'C1C2C3E9',X'C4E4E2E3',X'C7C57DC8',X'D9C9C6D3', X'D1D2D85C',X'F0F1F2F3',X'F4F5F6F7',X'F8F94B60', X'D4D5D6D7',X'E5E6E7E8',X'7E4D505D',X'6C5E7F6F', X'4AE05F5A',X'4CF08B6E',X'5B7A7C4F',X'A8A979F0', X'81828384',X'85868788',X'89919293',X'94959697', X'9899A2A3',X'A4A5A6A7',X'B1B2FAFB',X'C1C2C3E9', X'F0F1F2F3',X'F4F5F6F7',X'F8F94B60',X'7B6B614E', X'C4E4E2E3',X'C7C57DC8',X'D9C9C6D3',X'D1D2D85C', X'D4D5D6D7',X'E5E6E7E8',X'7E4D505D',X'6C5EDBCB', X'4AB7A05A',X'4CF08B6E',X'5B7A7C4F',X'EBBC75BD', X'8CAEBFBE',X'B6AAFDFE',X'9DEE80DA',X'C06D6AD0' !* %CONSTBYTEINTEGERARRAY LCLETTS(1:26)= %C X'81',X'82',X'83',X'84',X'85',X'86',X'87',X'88',X'89', X'91',X'92',X'93',X'94',X'95',X'96',X'97',X'98',X'99', X'A2',X'A3',X'A4',X'A5',X'A6',X'A7',X'A8',X'A9' !* !* GPC MICROPROGRAM FOLLOWS AS %OWNINTEGERARRAY GPCMPROG(0:511) !* PROGRAM C03 PATCH LEVEL 5 %ENDOFLIST %OWNINTEGERARRAY GPCMPROG(0:511)= %C X'F160F161',X'482049E0',X'4022802C',X'E80AF0C9', X'000AD009',X'80054265',X'9320BE0A',X'100A8005',X'C213CAB3', X'8025CA33',X'8223CA53',X'8275CAD3',X'8005CA93',X'80C2CA73', X'8005CB34',X'8005CAF3',X'82FACAD4',X'80788005',X'C273C2D3', X'80298005',X'C2B38213',X'8210182E',X'93088007',X'4820E00C', X'740C500B',X'930FB725',X'F9C0F16C',X'DEEB21CC',X'EB4BE008', X'29E82C8C',X'61CC2CAC',X'61EC4C6B',X'7968B795',X'F9C00CCC', X'610CFC00',X'61ECFC00',X'70CC0825',X'818F8070',X'48400825', X'C2D4CA93',X'804AA2D4',X'BC091005',X'CAD48059',X'C27383DC', X'9062805F',X'B21AA27A',X'A29A82D9',X'B80983DF',X'10054989', X'C2D48068',X'B2F4A2D4',X'C2F4B2F4',X'EA131013',X'C6732013', X'98019205',X'98020835',X'C2738005',X'A2F44282',X'498C9205', X'8005A83D',X'A9D4F3AC',X'DCAC200C',X'4BC0700E',X'090C4042', X'B3ACE80E',X'240C5006',X'C00680B0',X'782CB795',X'F9C0A335', X'AED45017',X'500C0C17',X'C073A9F4',X'F48C501F',X'640E080C', X'500EC873',X'AAF40D15',X'500C4FE0',X'68972CF5',X'12E1EA57', X'E017C274',X'80A6B795',X'F9C0A673',X'1059C033',X'80ACF800', X'90BAC008',X'BA0ACAF4',X'80054065',X'80DC4BE0',X'BC0A100A', X'4BC0C883',X'81229341',X'8180E41F',X'1122A150',X'C813A011', X'A2D39320',X'BA0AF800',X'98019308',X'BC0A100A',X'A83D9316', X'782CB795',X'F9C0A735',X'5017500C',X'0C17C073',X'AE93501F', X'930F0D15',X'68972D15',X'12E1C033',X'80DCF800',X'90BAC008', X'BA0AAB74',X'A2739341',X'82E1E006',X'5826EFF4',X'50085826', X'32A82768',X'C014AEF4',X'9012ABF2',X'5826F177',X'F168FC00', X'91972C37',X'C1A83C37',X'61770835',X'E40C6908',X'DFEC2173', X'58260CF5',X'501F9341',X'82E1E018',X'5826F177',X'AEB49197', X'58262C37',X'C1DAFC00',X'501F9341',X'82E1E419',X'6077A2B4', X'F573F9C0',X'C21481B4',X'C1F4C9D4',X'82E10835',X'0C06C01F', X'B3B7B01D',X'A15DA17D',X'A1B04298',X'A3144D81',X'10050905', X'8180DEF3',X'200CEB6C',X'E00CF168',X'DDE321C8',X'486829E8', X'2D4C632C',X'0C2C7B8C',X'0C2C70CC',X'0C0DC00E',X'4D00117D', X'0C4C70AC',X'4920F56E',X'117D0C4C',X'70AC0C25',X'70C88180', X'0C2C708C',X'48408170',X'0C2C70AC',X'0C257AC8',X'814B4840', X'0C2C790C',X'920B817D',X'640F0815',X'F575117D',X'09150C1F', X'C006920B',X'817D5C26',X'5004EBA4',X'E004920B',X'817D5C26', X'9002ABE2',X'920B817D',X'5C26500D',X'EBADE01F',X'93478180', X'E00D920B',X'81315406',X'500C49C0',X'C00C49E0',X'81314B20', X'920B817D',X'4B00C0E3',X'817A6E2F',X'08104716',X'117D5E2F', X'50108178',X'4840A500',X'11854840',X'9205A120',X'A1E0A2E4', X'0C07C101',X'DDE321C0',X'4BE0C053',X'A011A3E9',X'A6D31005', X'48409205',X'A2E4B160',X'A1E00C0B',X'C0C083E2',X'EB532418', X'C01F541F',X'501DEBDD',X'42229801',X'C0FD9802',X'E00CA8EC', X'DDF36A8C',X'EF5D200C',X'034C0CB5',X'732C28B5',X'EB5D2418', X'C01F541F',X'501DC8FD',X'980126D3',X'119C0855',X'C9F48287', X'C9D482B9',X'919782E1',X'0835F16C',X'DCFD21CC',X'C1FD81D7', X'C23482E1',X'292CB67A',X'F9A0F17B',X'0C2C612C',X'FC006ACC', X'498842A2',X'A21A4D8F',X'11D1498D',X'09B5A354',X'A233BC0A', X'100A82E1',X'0855282C',X'CA3481E3',X'2CAC628C',X'2C2C62CC', X'2C6C630C',X'FC00634C',X'C0DD81EA',X'A01FA03F',X'B3F70D75', X'11FE0835',X'EB5D075A',X'C00CC7FD',X'706CC2B4',X'82E12419', X'C00C582C',X'0C555017',X'500CA774',X'501F9341',X'82E1E41F', X'60F74284',X'4983A754',X'10112895',X'2D1512E1',X'EA15E00C', X'DCF5686C',X'E0159801',X'2887C007',X'98020887',X'9801B795', X'F9C08217',X'DE5221D5',X'AB55A375',X'A315A335',X'906282F6', X'82E3C053',X'A0110C13',X'C1D0A190',X'BA099801',X'B715F9C0', X'AA33CA5A',X'A2F3CB54',X'8252CB14',X'8238C334',X'823FC2D3', X'8232A633',X'10050855',X'AB34C29A',X'82F082F6',X'82F00835', X'AB149242',X'82D92A35',X'ADB011B4',X'0835A735',X'12F6EA3B', X'E01BF56C',X'689BC09D',X'AA9ADB7A',X'F55DC16C',X'DC6C216C', X'C61A686C',X'CAF49801',X'9802C87D',X'921CAB54',X'924282D9', X'C09D825F',X'C23AC19D',X'82ABA1D4',X'A69310C2',X'C0BD82D7', X'C23AC19D',X'8266A693',X'10C2EB53',X'E00CCA3A',X'082C0C2C', X'C1D3D9F3',X'1C2C200C',X'034C2D35',X'708C2CB5',X'11B982E1', X'C87D921C',X'AA53C19D',X'827DA1F4',X'A69310C2',X'DDF3200C', X'EB4C0753',X'C00C2DD5',X'708C0CB5',X'12E10833',X'919782E1', X'0895C0DD',X'8293A01F',X'A03FB3F7',X'498B0955',X'A7541011', X'EB5D075A',X'C00CC7FD',X'706CC2B4',X'82E12419',X'C00C582C', X'0C555017',X'500CA774',X'501F9341',X'82E1E41F',X'60B7498B', X'A7541011',X'2D1512E1',X'EB53E00C',X'CA3A082C',X'0C2CC1D3', X'D9F31C2C',X'200C034C',X'2D35786C',X'82E128B5',X'919782E1', X'C87D921C',X'C09D82CE',X'C19D82C4',X'A1D4A693',X'10C2DDF3', X'200CEB4C',X'0753C00C',X'0CB5706C',X'82E10C33',X'12B809D5', X'C0BD82D7',X'C19D82D5',X'A69310C2',X'AE3A1266',X'A51012DB', X'A130A2F4',X'EA3BE411',X'F9000C1A',X'C1B082E8',X'498D9205', X'CA138213',X'A2F4A130',X'A1F00C13',X'C1D0C053',X'A011AA73', X'BA09A6D3',X'1011B170',X'0C1AC0F0',X'DCFA21B0',X'82EA9205', X'A170A5F0',X'12DAAAF3',X'CAF48022',X'F17DF17F',X'B3D74284', X'A33483D8',X'8005B715',X'F9C00C75',X'12F64BC0',X'740E5008', X'C8089802',X'4BE08801',X'F08C640E',X'080C540E',X'500C4BE0', X'98014043',X'B7AC131D',X'F3ACDCAC',X'200C090C',X'E80E200C', X'98019316',X'084C540C',X'50061C4E',X'68669308',X'98016C2C', X'0810640C',X'08114067',X'E00C540C',X'5006B806',X'640C0806', X'930FB809',X'AAD3F170',X'C8114880',X'F1719803',X'229F283F', X'A81FD83F',X'09159802',X'EA37E017',X'C43D62B7',X'4137413A', X'EFB4787F',X'EBA40835',X'07BFC008',X'EFBF60A8',X'E4087088', X'9801E008',X'0835A808',X'DFC82008',X'EE92787F',X'EA822008', X'5C28500C',X'5008EE3F',X'900BC374',X'8368DEEC',X'787DDB6C', X'E008EB74',X'0368B708',X'78689801',X'08353828',X'F0CCAA94', X'C82CA294',X'EA3F2637',X'C0082828',X'C9A89801',X'EA28022C', X'AFEB786C',X'98010835',X'C06B8385',X'C02B9801',X'A3EB540B', X'900B837D',X'0835CA94',X'8395C02B',X'9801EA3F',X'C83DEA28', X'E01FB34C',X'382CF1EB',X'D83F0875',X'328B9802',X'08354063', X'2855C02B',X'98010875',X'E81FC83D',X'E008B2AC',X'382CF07F', X'EA37241F',X'C00CABEB',X'F17EDD28',X'21DEEA8B',X'201E282C', X'F168DD2C',X'21C8D928',X'2017B108',X'E8080017',X'B2A8E808', X'000CFC00',X'716C583E',X'C03D285E',X'040C9016',X'C0369801', X'FC007ACC',X'541E9008',X'C0289801',X'C81783CA',X'085EC83D', X'289E200C',X'B12BE80B',X'0017EA88',X'E008A048',X'D82CC03D', X'D83F32C8',X'08359802',X'A273F57A',X'F8604D8A',X'1005C334', X'80058059',X'CAD4A274',X'8005AC53',X'118A0000',X'00000000'(9), X'0000F2B2',X'B80AA213',X'498D9800',X'0C030005',X'F621BEA3' %LIST !* !* COMMUNICATIONS RECORD FORMAT - EXTANT FROM CHOPSUPE 20L ONWARDS * %RECORDFORMAT COMF(%INTEGER OCPTYPE,IPLDEV,SBLKS,SEPGS,NDISCS, %C DLVNADDR,GPCTABSIZE,GPCA,SFCTABSIZE,SFCA,SFCK,DIRSITE, %C DCODEDA,SUPLVN,TOJDAY,DATE0,DATE1,DATE2, %C TIME0,TIME1,TIME2,EPAGESIZE,USERS,CATTAD,SERVAAD, %C %BYTEINTEGER NSACS,RESV1,SACPORT1,SACPORT0, %C NOCPS,RESV2,OCPPORT1,OCPPORT0, %C %INTEGER ITINT,CONTYPEA,GPCCONFA,FPCCONFA,SFCCONFA, %C BLKADDR,RATION,SMACS,TRANS,%LONGINTEGER KMON, %C %INTEGER DITADDR,SMACPOS,SUPVSN,PSTVA,SECSFRMN,SECSTOCD, %C SYNC1DEST,SYNC2DEST,ASYNCDEST,MAXPROCS,INSPERSEC,ELAPHEAD, %C COMMSRECA,STOREAAD,PROCAAD,SFCCTAD,DRUMTAD,TSLICE,FEPS, %C MAXCBT,SP1,SP2,SP3,SP4,SP5,SP6,SP7, %C LSTL,LSTB,PSTL,PSTB,HKEYS,HOOT,SIM,CLKX,CLKY,CLKZ, %C HBIT,SLAVEOFF,INHSSR,SDR1,SDR2,SDR3, %C SDR4,SESR,HOFFBIT,S2,S3,S4,END) %RECORDFORMAT ALEF(%INTEGER S, A) %RECORDFORMAT CA0F(%INTEGER MARK, PAW, PIW0, PIW1, CSAW0, %C CSAW1, CRESP0, CRESP1) %RECORDFORMAT CASEF(%INTEGER SAW0, SAW1, RESP0, RESP1) %RECORDFORMAT CAF(%INTEGER MARK,PAW,PIW0,PIW1,CSAW0,CSAW1,CRESP0,CRESP1, %C %RECORD(CASEF)%ARRAY S ENTRY(0:14)) %RECORDFORMAT DEVICE ENTRY F(%INTEGER X1, GPTSM, PROP A, %C SECS SINCE, CA A, G RCB A, LB A, AL A, X2, RESP0, %C RESP1, SENSE1, SENSE2, SENSE3, SENSE4, X3, X4, IDENT %C , X5, MNEMONIC, DEVICE ENTRY S, PAW, U SAW 0, %C U RCB A, SENSE DATA A, LOG MASK, TR TABLE A, UA S, %C UA A, TIMEOUT, PROPS0, PROPS1) %RECORDFORMAT GPCT F(%BYTEINTEGER FLAGS, DEVTYPE, BUSY, LINK, %C %INTEGER X4, RESPONSE DEST, DEVICE ENTRY A, C STATUS, %C PTSM, MNEMONIC, %C %BYTEINTEGER MECHINDEX, PROPS03, SERVRT, STATE) !* %RECORDFORMAT INIF(%INTEGER PSTS, PSTA, CAA, SOE) !* %RECORDFORMAT RCB F(%INTEGER LIM FLAGS, LSTA, LB S, LB A, AL S, %C AL A, INIT WORD, X1) %OWNBYTEINTEGERARRAYFORMAT BIFT(0:383) %OWNINTEGERARRAYFORMAT IFT(0:1023) !* !* DECLARATIONS FOR CDS DEV ON !* %OWNINTEGER XSTRM = -1, XPT = -1 %OWNINTEGER XINIT, XA, XSLOT, XMNEMONIC, XDEVTYPE, XGPC, XCAA, %C XGPTSM, XPTS, XSTATE, XSRCE %OWNINTEGER XCART, XSTYLE, XLEN, XS %OWNINTEGERARRAY X(0:117) %OWNRECORD(RCBF)%NAME XRCB %OWNRECORD(CAF)%NAME XCA %OWNRECORD(CASEF)%NAME XSENT %OWNRECORD(ALEF)%ARRAYFORMAT ALEFF(0:3) %OWNRECORD(ALEF)%ARRAYNAME XALE %OWNINTEGERARRAY XLBE(0:7) = %C X'00F10900',X'04F10800',X'04F00E00',X'00F00402', X'80F02504',X'80F00106',X'82F00500',X'80F00106' !* !* DECLARATIONS FOR CDM !* %CONSTBYTEINTEGER ZX=11 %CONSTINTEGER CDMDEVLIMIT=6 %CONSTINTEGERARRAY CDMDEV(0:CDMDEVLIMIT)=%C M'FE',M'LP',M'CR',M'CP',M'PR',M'PT',M'SU' %CONSTBYTEINTEGERARRAY CDMDEVTYPE(0:CDMDEVLIMIT)=14,6,4,3,2,1,13 %CONSTINTEGERARRAY CDMDEVTIMEOUT(0:CDMDEVLIMIT)=%C X'01FF0003',60,300,600,60,60,10; ! top of FEP word is logmask !* !* !* !* !* !* ! NOTES ON GPC PROGRAM !* !* !* !* !* !* 1. SOME CALLING SEQUENCES. !* PAW NOT CLEARED/GPC DUMP/GPC INIT !* CONNECT STREAMS/PON GPC INT !* HENCE ROUTINES ARE DECLARED IN REVERSE ORDER !* !* !* 2. SLOTS. !* A SLOT CAN BE IN ONE OF 6 STATES !* DISCONNECTED !* NOT ALLOCATED !* READY !* REQUEST FIRED !* SENSE FIRED !* QUEUED !* !* !* 3. MAG TAPES. !* THEORETICALLY, A MT STREAM CAN HAVE UP TO 8 DRIVES (OR !* MECHANISMS). FOR EACH MT STREAM THEREFORE, 8 BYTES ARE !* ALLOCATED IN THE ARRAY MECHSLOTS. EACH BYTE CONTAINS A !* SLOT NUMBER. THE MECHINDEX FIELD IN A SLOT POINTS TO !* THE FIRST OF THESE 8 BYTES. CONSEQUENTLY, GIVEN PTSM, !* CAN USE PTS_TO_SLOT TO GET SOME SLOT ON STREAM, PICK !* UP MECHINDEX, THEN ADD ON M AND ACCESS MECHSLOTS TO GET !* THE REQUIRED SLOT NUMBER. !* %ROUTINE MSG(%STRING (120) TXT) PRINTSTRING(TXT." ") %END; ! OF MSG !* %ROUTINE REPLY(%INTEGER SRCE, %STRING (63) TXT) %RECORD(PARMF) P P=0 P_DEST=SRCE %IF LENGTH(TXT)>23 %THEN LENGTH(TXT)=23 STRING(ADDR(P_P1))=TXT PON(P) %END; ! OF REPLY !* %ROUTINE SLOTS MSG("GPC's tables:-") DUMPTABLE(0,ADDR(TABLE(0)),TABLE(0)<<2+4) %END; ! OF SLOTS !* %ROUTINE PON GPC INT(%INTEGER PT) %RECORD(PARMF) P P_SRCE=0 P_DEST=GPC DEST!3; ! INTERRUPT ENTRY P_P1=PT PON(P) %END; ! OF PON GPC INT !* %ROUTINE GET CA(%INTEGER CAA) *LXN_CAA *INCT_(%XNB+0) *JCC_8, SEMALOOP(INTEGER(CAA)) GOT: %END; ! OF GET CA !* %ROUTINE SEND CH FLAG(%INTEGER PT) %INTEGER BREG BREG=TRUNKADDR!(PT<<16) *LB_BREG *LSS_1 *ST_(0+%B) %END; ! OF SEND CH FLAG !* !* ! THIS FUNCTION INITIALISES THE GPC BY ! CLEARING IT ! LOADING THE MICROPROGRAM ! INITIALISING THE CONTROLLER AND COMMUNICATION AREA ! PARAMETERS ! CAA COMMUNICATION AREA ADDR ! PT FOR THIS GPC ! CHOPSUPE =1 IF CALLED FROM GROPE ELSE 0 ! IF 1 THEN ! SLAVES NOT SWITCHED OFF/ON ! RESPONSES ! 0 = SUCCESS ! 1 << 24 ! CRESP0 MICROPROGRAM LOAD FAILS ! 2 << 24 ! CRESP0 INITIALISE FAILED, RESPONSE FROM OLD CA ! 3 << 24 ! CRESP0 DITTO, RESPONSE FROM NEW COMMS AREA %EXTERNALINTEGERFN GPC INIT(%INTEGER CAA, PT, CHOPSUPE) %INTEGER BREG %INTEGER COUNT %INTEGER J %INTEGER PSTA %INTEGER PSTS %CONSTRECORD(CA0F)%NAME CA0=RA0AD %RECORD(CAF)%NAME CA %RECORD(INI F) INI ! CLEAR GPC BREG=TRUNKADDR!(PT<<16) *LSS_2 *LB_BREG *ST_(0+%B) WAIT(50); ! MILLISECONDS ! SLAVES OFF IF NOT CALLED FROM GROPE %IF CHOPSUPE=0 %THEN SLAVES ON OFF(0) ! LOAD GPC MICROPROGRAM THE ORIGINAL BOOTSTRAP DID ! CA0_CSAW0 = X1000, ALTHOUGH GPC TECHNICAL DESCR ! 1112732 SHEET 13 SAYS ONLY CSAW1 RELEVANT CA0=0 CA0_PAW=LOAD MICROPROGRAM CA0_CSAW1=REALISE(ADDR(GPCMPROG(0))) CA0_MARK=-1 SEND CH FLAG(PT) COUNT=0 COUNT=COUNT+1 %UNTIL (CA0_CRESP0#0 %AND CA0_MARK=-1) %C %OR COUNT>300000 ! IF NORMAL_REQUEST_TERMINATION BIT NOT SET THEN LOAD FAILED %IF CA0_CRESP0&NORMAL TERMINATION=0 %C %THEN %RESULT =(1<<24)!CA0_CRESP0 WAIT(50); ! MILLISECONDS ! INITIALISE GPC GIVING PST REAL ADDR AND LIMIT CA0=0 CA0_PAW=DO CONTROLLER REQUEST CA0_CSAW0=INIT CONTROLLER CA0_CSAW1=REALISE(ADDR(INI)) GET PSTB(PSTS,PSTA); INI_PSTS=PSTS INI_PSTA=PSTA INI_CAA=CAA INI_SOE=0 ! INITIALISE THE NEW COMMS AREA CA==RECORD(CAA) CA=0 CA_MARK=-1 ! FREE COMMS AREA CA0_MARK=-1 SEND CH FLAG(PT) COUNT=0 COUNT=COUNT+1 %UNTIL (CA_CRESP0#0 %AND CA_MARK=-1) %C %OR COUNT>900000 ! IF NOT CALLED FROM GROPE %IF CHOPSUPE=0 %THEN SLAVES ON OFF(-1);! SLAVES BACK ON ! LOOK FOR NORM TERM BIT %IF CA_CRESP0&NORMAL TERMINATION=0 %START %IF MULTIOCP=YES %START; RESERVE LOG %FINISH MSG("CA0") DUMP TABLE(2,RA0AD,32) MSG("CA") DUMP TABLE(3,CAA,272) MSG("INI") DUMP TABLE(4,ADDR(INI),16) %IF MULTIOCP=YES %START; RELEASE LOG %FINISH %IF CA_CRESP0=0 %THEN %RESULT =(2<<24)!CA0_CRESP0 %RESULT =(3<<24)!CA_CRESP0 %FINISH CA_CRESP0=0 CA_MARK=-1 %RESULT =0 %END; ! OF GPC INIT !* !* ! DISCONNECTS THEN, IF CONNECT=1, CONNECTS ONE OR ALL ! STREAMS ON A GPC. ABNORMAL TERMINATIONS ARE GIVEN FOR ALL ! RELEVANT STREAMS WHICH ARE FOUND TO BE BUSY. ! PARAMETERS ! PT GPC ! CAA COMMUNICATIONS AREA ADDRESS ! STREAM IF < 0 ALL STREAMS ELSE SPECIFIED STREAM ! CONNECT =1 RECONNECTS ELSE ONLY DISCONNECTS ! TIMEOUT =1 FOR SPECIAL ABTERM OF SPECIFIED STREAM ! RESPONSES ! VARIOUS MESSAGES TO SYSTEM LOG %ROUTINE CONNECT STREAMS(%INTEGER PT, CAA, STREAM, CONNECT, %C TIMEOUT) %INTEGER COUNT %INTEGER FAILS %INTEGER HI %INTEGER J %INTEGER LO %INTEGER PAW FAILS %INTEGER STRM %OWNINTEGER DUMMY WORD %OWNRECORD(ALEF) ALE %OWNRECORD(RCBF) RCB %RECORD(CAF)%NAME CA %RECORD(GPCTF)%NAME GPCT %RECORD(CASEF)%NAME SENT %STRING (15) TXT %OWNINTEGER DISCONNECT LBE=X'00F10900' %OWNINTEGER CONNECT LBE=X'00F10800' ! MESSAGE WK="GPC connect streams ".HTOS(PT,2) %UNLESS STREAM<0 %THEN WK=WK.HTOS(STREAM,1) %UNLESS CONNECT=1 %THEN WK=WK." dis" MSG(WK) ! CONSTRUCT RCB ALE_S=4 ALE_A=ADDR(DUMMY WORD) RCB_LIM FLAGS=PRIV ONLY RCB_LBS=4 RCB_LBA=ADDR(DISCONNECT LBE) RCB_ALS=8 RCB_ALA=ADDR(ALE) CA==RECORD(CAA) FAILS=0 PAW FAILS=0 SLAVES ON OFF(0); ! SLAVES OFF %IF STREAM<0 %THEN LO=0 %AND HI=14 %C %ELSE LO=STREAM %AND HI=STREAM ! FIRST DISCONNECT STREAMS TXT="disconnect" *JLK_ ! THEN RECONNECT IF REQUIRED %IF CONNECT=1 %START WAIT(10) RCB_LBA=ADDR(CONNECT LBE) TXT="connect" *JLK_ %FINISH ! SLAVES BACK ON AND PRINT COUNTS SLAVES ON OFF(-1); ! ON MSG("SAW fails=".HTOS(FAILS,1).", PAW fails=".HTOS( %C PAW FAILS,1)) ! NOW GIVE SPECIAL ABNORMAL TERMINATION FOR EACH ! RELEVANT STREAM THAT WAS BUSY %IF TIMEOUT=1 %OR STREAM<0 %START GET CA(CAA) %FOR J=0,1,LASTSLOT %CYCLE GPCT==RECORD(GPCTBASE+J*SLOTSI) STRM=(GPCT_PTSM>>4)&15 %IF (GPCT_PTSM>>8)&255=PT %C %AND (GPCT_STATE=REQUEST FIRED %C %OR GPCT_STATE=SENSE FIRED) %C %AND (STRM=STREAM %OR STREAM<0) %START ! FOUND A RELEVANT STREAM THAT IS BUSY MSG("Abn term for GPTSM ".HTOS(GPCT_PTSM,5)) ! PLACE BIT IN PIW CA_PIW0=CA_PIW0!(X'80000000'>>STRM) ! SET RESPONSE, RESP1=-1 IS AN EMAS SPECIAL SENT==CA_S ENTRY(STRM) SENT_RESP0=ABNORMAL TERMINATION SENT_RESP1=-1 %FINISH %REPEAT %FINISH CA_MARK=-1 PON GPC INT(PT) WAIT(100); ! MILLISECONDS %RETURN !* ! PSEUDO ROUTINE FOR EACH STREAM: %FOR J=LO,1,HI %CYCLE SENT==CA_S ENTRY(J) GET CA(CAA) CA_PAW=DO STREAM REQUEST!J SENT=0 SENT_SAW0=X'30000020'; ! SAW FLAGS + RCB BOUND SENT_SAW1=ADDR(RCB) CA_MARK=-1 SEND CH FLAG(PT) COUNT=0 COUNT=COUNT+1 %UNTIL SENT_RESP0#0 %OR COUNT>100000 %IF SENT_RESP0&NORMAL TERMINATION=0 %START MSG(TXT." STRM".HTOS(J,1)." RESP0=".HTOS(SENT_ %C RESP0,8)) FAILS=FAILS+1 %FINISH SENT_RESP0=0 CA_PIW0=CA_PIW0&(\(X'80000000'>>J));! IF IN DOUBT CLEAR BIT! %IF CA_PAW#0 %THEN PAWFAILS=PAW FAILS+1 %REPEAT *J_%TOS !* END OF PSEUDO ROUTINE 'FOR EACH STREAM' %END; ! OF CONNECT STREAMS !* ! THIS ROUTINE IS INVOKED BY 'PAW NOT CLEARED'. IT ! CALLS 'CONTROLLER DUMP' TO PRODUCE THE DUMP, THEN ! RE-INITS THE GPC. IF CALLED MORE THAN 10 TIMES, ! IT SIMPLY RETURNS. %ROUTINE GPC DUMP(%INTEGER PT) %INTEGER CAA %INTEGER GPCNO %INTEGER RES %OWNINTEGER TIMES=0 %IF TIMES>10 %THEN %RETURN TIMES=TIMES+1 CONTROLLER DUMP(3,PT) GPCNO=PT TO GPC(PT-LOPT) CAA=CAAS(GPCNO) RES=GPC INIT(CAA,PT,0) MSG("GPC init res=".HTOS(RES,8)) CONNECT STREAMS(PT,CAA,-1,1,0) %END; ! OF GPC DUMP !* !* ! CALLED WHEN PAW OR SAW FOUND NON ZERO WHEN ! A CHANNEL FLAG IS ABOUT TO BE ISSUED. IF ! STREAM < 0, SAW IS NOT RELEVANT. %ROUTINE PAW NOT CLEARED(%INTEGER PT, STREAM, PAW) %INTEGER CAA %INTEGER GPCNO %INTEGER SAW %RECORD(CAF)%NAME CA %RECORD(CASEF)%NAME SENT ! SET UP POINTERS GPCNO=PT TO GPC(PT-LOPT) CAA=CAAS(GPCNO) CA==RECORD(CAA) ! SLAVES OFF SLAVES ON OFF(0) %IF CA_PAW#0 %THEN WAIT(100) %IF CA_PAW=0 %THEN SLAVES ON OFF(-1) %AND %RETURN ! OK NOW SEND CH FLAG(PT); ! RE-FIRE I/O WAIT(100) ! SLAVES BACK ON SLAVES ON OFF(-1) MSG("GPC PAW not cleared PT=".HTOS(PT,2).",PAW=".HTOS( %C PAW,8)) SAW=0 %UNLESS STREAM<0 %START SENT==CA_S ENTRY(STREAM) SAW=SENT_SAW0 %FINISH %IF SAW#0 %START MSG("SAW not cleared") %FINISH %UNLESS CA_PAW=0 %AND SAW=0 %THEN GPC DUMP(PT) MSG("end of PAW not cleared") %END; ! OF PAW NOT CLEARED !* !* ! IF CONTROLLER = 0, ISSUES 'READ STREAM DATA' ! 1, 'READ STREAMS CONTROLLER STATUS' ! 2, 'READ CONTROL STREAM STATUS' %INTEGERFN READ STRM DATA(%INTEGER PT, STREAM, CONTROLLER) %CONSTSTRING(24)%ARRAY HEADER(0:2)="stream data", %C "stream controller status", %C "control stream status" %INTEGER CAA %INTEGER COMMAND %INTEGER COUNT %INTEGER GPCNO %INTEGER LEN %INTEGER SAWFLAGS %OWNINTEGERARRAY STREAM DATA(0:63) %RECORD(CAF)%NAME CA %IF CONTROLLER=0 %START LEN=64 COMMAND=READ STREAM DATA %FINISH %ELSE %START %IF CONTROLLER=1 %START LEN=4 COMMAND=READ STREAMS CONTROLLER STATUS %FINISH %ELSE %START LEN=64 COMMAND=READ CONTROL STREAM STATUS %FINISH %FINISH GPCNO=PT TO GPC(PT-LOPT) CAA=CAAS(GPCNO) CA==RECORD(CAA) %IF CA_PAW#0 %START PAW NOT CLEARED(PT,-1,CA_PAW) %RESULT =0 %FINISH ! SLAVES OFF SLAVES ON OFF(0) GET CA(CAA) CA_CRESP0=0 SAWFLAGS=3; ! CLEAR ABN & INHIBIT TERM INT CA_PAW=DO CONTROLLER REQUEST CA_CSAW0=SAWFLAGS<<28!COMMAND<<24!STREAM<<16!LEN CA_CSAW1=ADDR(STREAM DATA(0)) CA_MARK=-1 SEND CH FLAG(PT) ! LOOP AWAITING RESPONSE COUNT=0 COUNT=COUNT+1 %UNTIL CA_CRESP0#0 %OR COUNT>100000 ! SLAVES BACK ON SLAVES ON OFF(-1) %IF MULTIOCP=YES %START; RESERVE LOG %FINISH PRINTSTRING("GPC ".HEADER(CONTROLLER)." pts=".HTOS(PT<<4! %C STREAM,3)) DUMP TABLE(-1,ADDR(STREAM DATA(0)),LEN) MSG("CRESP0=".HTOS(CA_CRESP0,8)) %IF MULTIOCP=YES %START; RELEASE LOG %FINISH ! RESULT USEFUL ONLY IF CONTROLLER # 0 %RESULT =STREAM DATA(0) %END; ! OF READ STRM DATA !* !* %INTEGERFN FIND BYTE(%INTEGER BYTE, ADDR, LEN) %INTEGER I %FOR I=0,1,LEN-1 %CYCLE %IF BYTE=BYTE INTEGER(ADDR+I) %THEN %RESULT =I %REPEAT %RESULT =-1 %END; ! OF FIND BYTE !* %STRINGFN MNEMO(%INTEGER MNEMONIC) %INTEGER I, J I=MNEMONIC J=0 %IF BYTE INTEGER(ADDR(I)+1)=0 %THEN J=1 BYTE INTEGER(ADDR(I)+J)=3-J %RESULT =STRING(ADDR(I)+J) %END; ! OF MNEMO !* %INTEGERFN TRANS MNEMO(%STRINGNAME S) %INTEGER M, A, I, J M=0 A=ADDR(S) %IF CHARNO(S,1)='X' %START S->("X").S %FOR I=1,1,BYTEINTEGER(A) %CYCLE J=BYTE INTEGER(A+I) %UNLESS '0'<=J<='9' %OR 'A'<=J<='F' %C %THEN %RESULT =0 M=M<<4+(9*J>>6)+(J&15) %REPEAT %FINISH %ELSE %START %IF BYTE INTEGER(A)=3 %START %FOR I=1,1,3 %CYCLE BYTE INTEGER(ADDR(M)+I)=BYTE INTEGER(A+I) %REPEAT %FINISH %FINISH %RESULT =M %END; ! OF TRANS MNEMO !* %INTEGERFN STATE CHECK(%INTEGER SRCE, MNEM, STATE) %INTEGER J, A %RECORD(GPCT F)%NAME G %IF MNEM>>16=M'M' %START ! TAPE CLUSTER, INSIST THAT ALL DECKS ! IN CLUSTER ARE 'NOT ALLOC' %UNLESS MNEM&255=M'0' %START REPLY(SRCE,"GPC: must be MN0") %RESULT =1 %FINISH A=GPCT BASE %FOR J=0,1,LASTSLOT %CYCLE G==RECORD(A) %IF G_MNEMONIC&X'FFFF30'=MNEM %START %UNLESS G_STATE=NOT ALLOCATED %START REPLY(SRCE,"GPC: ".MNEMO(G_MNEMONIC). %C " STATE ?") %RESULT =1 %FINISH %FINISH A=A+SLOTSI %REPEAT %RESULT =0 %FINISH %RESULT =0 %IF STATE=NOT ALLOCATED %RESULT =0 %IF STATE=READY %AND MNEM&X'FFFF30'=M'OP0' ! SPECIAL DISPENSATION FOR OPERS REPLY(SRCE,"GPC: ".MNEMO(MNEM)." state ?") %RESULT =1 %END; ! OF STATE CHECK !* %STRINGFN MNS(%RECORD(DEVICE ENTRY F)%NAME D) %INTEGER I I=D_MNEMONIC BYTEINTEGER(ADDR(I))=3 %RESULT =STRING(ADDR(I)) %END; ! MNS !* !* ! MAIN GPC ROUTINE !* %EXTERNALROUTINE GPC(%RECORD(PARMF)%NAME INP) %INTEGER DACT, FLAG, CAA, SLOT, PAWFN, SAWFLAGS, URCB A, USAW0 %INTEGER LAST, MECH, STRM, GPCNO, BREG, PIW0 %INTEGER J, PT, RESP0, RESP1, OSNO, PREVIOUS PT %INTEGER SRCE, CALLED %INTEGER I %INTEGER INTERRUPT ANALYSIS FLAGS %INTEGER FLAGS %INTEGER GPTSM %INTEGER MNEMONIC %INTEGER MNEMONIC1, MNEMONIC2 %INTEGER P3 %INTEGER SEMA %INTEGER SLOT A %INTEGER BUSY %INTEGER STATE %INTEGER GMON %INTEGER ACT %STRING (15) MNEMOS %RECORD(PARMF) P %RECORD(PARMF) Q !* %OWNINTEGER SETUP=0 !* %BYTEINTEGERNAME QHD %BYTEINTEGERARRAYNAME REP, TRTAB !* %SWITCH G COMMAND(1:LIMIT) %SWITCH GS(1:12) %SWITCH CDS(0:7) !* %CONSTRECORD(COMF)%NAME COM=X'80000000'!48<<18 %RECORD(DEVICE ENTRY F)%NAME D %RECORD(CAF)%NAME CA %RECORD(CASEF)%NAME SENT %RECORD(GPCT F)%NAME GPCT,GE !* P=INP %IF KMONNING=YES %START GMON<-(KMON>>GPC SNO)&1 PKMONREC("GPC( in):",P) %IF GMON=YES %FINISH %IF SETUP=0 %START ! IF NOT YET INITIALISED, IGNORE EVERYTHING ! EXCEPT THE INITIALISATION CALL %RETURN %UNLESS P_DEST&X'FFFF'=2 SETUP=1 J=P_P1; ! ADDRESS OF TABLE CONTAINING TABLES TABLE==ARRAY(J,IFT) TABLE(42)=P_P2 %UNLESS P_P2=0; ! ADDR OF PROCESS LIST PICTURE STRM SEMAPHORE==ARRAY(J+TABLE(40)<<2,IFT) GPCTBASE=J+TABLE(1)<<2 LASTSLOT=TABLE(2) NO OF GPCS=TABLE(3) STRMQBASE=J+TABLE(4)<<2 PTSBASE=J+TABLE(5)<<2 PTGPCBASE=J+TABLE(6)<<2 MECHPT=J+TABLE(7)<<2 CAASBASE=ADDR(TABLE(8)) LOPT=TABLE(16) HIPT=TABLE(16+NO OF GPCS-1) PTS TO SLOT==ARRAY(PTSBASE,BIFT) PT TO GPC==ARRAY(PTGPCBASE,BIFT) STRMQ==ARRAY(STRMQBASE,BIFT) CAAS==ARRAY(CAASBASE,IFT) MECHSLOTS==ARRAY(MECHPT,BIFT) GPCT==RECORD(GPCTBASE) %FOR J=0,1,15 %CYCLE REPERTOIRE A(J)=ADDR(LP96REP(0)) REPERTOIRE S(J)=96 %REPEAT REPERTOIRE A(3)=ADDR(LP384REP(0)) REPERTOIRE S(2)=48 REPERTOIRE S(3)=384 REPERTOIRE S(4)=64 ! RE-INITIALISE SLOTS %FOR J=0,1,LASTSLOT %CYCLE GPCT==RECORD(GPCTBASE+J*SLOTSI) GPCT_FLAGS=0 GPCT_LINK=ENDLIST %IF GPCT_DEVTYPE=ZX %THEN GPCT_STATE=DISCONNECTED %C %ELSE GPCT_STATE=NOT ALLOCATED GPCT_BUSY=0 GPCT_X4=0 GPCT_RESPONSE DEST=0 GPCT_C STATUS=0 GPCT_SERVRT=0 D==RECORD(GPCT_DEVICE ENTRY A) D_RESP0=0 D_RESP1=0 %REPEAT ! RE-INITIALISE STREAM Q HEADS J=0 %WHILE J>4; ! LOGICAL OPER NO P=0 P_P1=GE_MNEMONIC P_P2=X'320005'!(I<<8); ! WHERE WE WANT OPER INTERRUPTS P_DEST=X'30000B'; ! ALLOCATE P_SRCE=X'320002'!(I<<8); ! ALLOCATE RESPONSE TO OPER PON(P) %FINISH %ELSE %IF GE_DEVTYPE=FE %START P=0 P_P1=GE_MNEMONIC P_P2=X'390005'; ! WHERE WE WANT FE INTERRUPTS P_DEST=X'30000B'; ! ALLOCATE P_SRCE=X'390002'; ! ALLOCATE RESPONSE TO FE ADAPTOR PON(P) %FINISH %ELSE %IF GE_DEVTYPE=MT %START ! NEW TAPE INIT ! ONE CALL PER CLUSTER ! P_P1 = LOW MNEMONIC FOR STREAM PT=(GE_PTSM>>4)&X'FFF'; ! holds PTS really %IF PREVIOUS PT#PT %START P=0 P_DEST=X'00310004' P_SRCE=X'00300000' P_P1=GE_MNEMONIC; ! RH char must be and should be zero PON(P) PREVIOUS PT=PT %FINISH %FINISH %ELSE %IF CSU FITTED=YES %AND GE_DEVTYPE=SU %START P=0 P_DEST=CSU DEST; ! CSU initialise P_P1=GE_MNEMONIC PON(P) %FINISH %REPEAT !* MSG("...".VSN) SLOTS !* P_DEST=X'A0001'; ! INTERVAL TIMER P_SRCE=1<<31 P_P1=GPC DEST+6 P_P2=TICK INTERVAL PON(P) ->OUT %FINISH !* !* ! MAIN BODY !* DACT=P_DEST&X'FFFF' SRCE=P_SRCE CALLED=SRCE>>31; ! SET #0 IF CALLED, ZERO IF PONNED SRCE=(SRCE<<1)>>1; ! REMOVE TOP BIT FLAG=1 %IF 0GS(DACT) ->ACKNOWLEDGE !* ! COMMAND, FORMS RECOGNISED ARE: ! QS DEV ! CDS DEV ON/OFF ! CDM mnem1 mnem2 ! ? ! SET GS(1): %IF BYTE INTEGER(ADDR(P_P1))>23 %THEN %RETURN; ! RUBBISH STRING WK=STRING(ADDR(P_P1))." * * *" %FOR J=1,1,LIMIT %CYCLE %IF WK->(COMMAND(J)).WK %THEN ->FOUND %REPEAT ERR: REPLY(SRCE,"GPC ??".STRING(ADDR(P_P1))) %RETURN FOUND: %IF J<4 %START WK->MNEMOS.(" ").WK MNEMONIC=TRANS MNEMO(MNEMOS) *JLK_ %IF SLOT<0 %THEN ->ERR *JLK_ %FINISH ->G COMMAND(J) ! QS DEV G COMMAND(1): *JLK_ %RETURN STATUS: REPLY(SRCE,"GPC: ".MNEMO(GPCT_MNEMONIC)." ".HTOS(GPCT_PTSM %C &X'FFFF',4)." ".STATES(GPCT_STATE&15)) *J_%TOS ! CDS DEV ON/OFF G COMMAND(2): %IF WK->("OFF ").WK %START %IF STATE CHECK(SRCE,MNEMONIC,STATE)=OK %START CONNECT STREAMS(PT,CAA,STRM,0,0) %IF MNEMONIC>>16=M'M' %START; ! TAPE CLUSTER I=GPCT BASE %FOR J=0,1,LASTSLOT %CYCLE GPCT==RECORD(I) %IF GPCT_MNEMONIC&X'FFFF30'=MNEMONIC %THEN %C GPCT_STATE=STATE<<4!DISCONNECTED I=I+SLOTSI %REPEAT GPCT==RECORD(GPCT BASE+SLOT*SLOTSI) %FINISH %ELSE GPCT_STATE=STATE<<4!DISCONNECTED %FINISH ->G COMMAND(1) %FINISH %IF WK->("ON ").WK %START %IF STATE=DISCONNECTED %START ->CDS ON %FINISH ->G COMMAND(1) %FINISH ->ERR G COMMAND(3): ! CDM MNEMONIC1=MNEMONIC WK->MNEMOS.(" ").WK MNEMONIC=TRANS MNEMO(MNEMOS) MNEMONIC2=MNEMONIC J=SLOT; ! SAVE 1ST SLOT *JLK_ %UNLESS SLOT<0 %THEN ->ERR; ! ALREADY EXISTS GPCT==RECORD(GPCT BASE+J*SLOTSI); ! REMAP TARGET SLOT %IF MNEMONIC1>>8=M'ZX' %START; ! INTRODUCE DEVICE I=MNEMONIC2>>8 %FOR J=0,1,CDMDEVLIMIT %CYCLE %IF I=CDMDEV(J) %THEN ->IDEV %REPEAT ->ERR; ! INVALID FOR CDM IDEV: GPCT_MNEMONIC=MNEMONIC2 GPCT_DEVTYPE=CDMDEVTYPE(J) D_MNEMONIC=MNEMONIC2 %IF CDMDEVTYPE(J)=LP %START D_UA S=D_UA S-256; ! TRTAB SPACE D_TR TABLE A=D_UA A+D_UA S %FINISH D_TIMEOUT=CDMDEVTIMEOUT(J)&X'FFFF' D_LOGMASK=CDMDEVTIMEOUT(J)>>16 %IF CDMDEVTYPE(J)=FE %THEN COM_FEPS=COM_FEPS!1<<(16+ %C MNEMONIC2&15) ! FEP MAP %FINISH %ELSE %START; ! TAKE OUT DEVICE %UNLESS MNEMONIC2>>8=M'ZX' %THEN ->ERR %UNLESS STATE=DISCONNECTED %THEN ->ERR I=MNEMONIC1>>8 %FOR J=0,1,CDMDEVLIMIT %CYCLE %IF I=CDMDEV(J) %THEN ->TOUT %REPEAT ->ERR TOUT: %IF CDMDEVTYPE(J)=FE %THEN COM_FEPS=COM_FEPS&(\(1<<(16+ %C MNEMONIC1&15))) %IF CDMDEVTYPE(J)=LP %START D_UA S=D_UA S+256; !RECOVER TRTAB SPACE D_TR TABLE A=0 %FINISH GPCT_MNEMONIC=MNEMONIC2 GPCT_DEVTYPE=ZX %FINISH ->G COMMAND(1) ! SET G COMMAND(5): XPT=-1 XSTRM=-1 G COMMAND(4): ! ? %FOR SLOT=0,1,LASTSLOT %CYCLE GPCT==RECORD(GPCT BASE+SLOT*SLOTSI) *JLK_ %REPEAT %RETURN !* ! ALLOCATE ** NEW VERSION 9/79 ** !* GS(11): MNEMONIC=P_P1 *JLK_ %UNLESS SLOT<0 %START *JLK_ FLAG=2 %IF STATE=NOT ALLOCATED %START FLAG=0 %IF GPCT_DEV TYPE=OP %START; ! EXTRA INFORMATION FOR OPERS OSNO=GPCT_MECHINDEX>>4; ! GET LOGICAL NO OF THIS OPER STREAM D_X2=CAA+TABLE(OSNO+32)>>16; ! BUFFER ADDR D_RESP0=GPCT_MECHINDEX&15; ! SCREENS D_X1=TABLE(OSNO+32)&X'FFFF'; ! BUFFER SIZE %FINISH %ELSE %IF GPCT_DEV TYPE=LP %THEN D_X1=GPCT_RESPONSE DEST; ! & LPs GPCT_STATE=READY GPCT_RESPONSE DEST=P_P2 ! NOW CONSTRUCT THE REPLY P_P2=LOID+SLOT P_P3=ADDR(D) P_P6=GPCT_MNEMONIC %FINISH %FINISH ->ACKNOWLEDGE !* GS(8): ! SPECIAL FORCED ALLOCATE CALL (NOT PON) ! FOR USE BY ENTER & MAINLP ! P_P1 = PTSM OR LP ! P_P2 = DEST (IF MAINLP) ! ON RETURN ! P_P1 = 0 SUCCESS ! 1 MNEMONIC NOT KNOWN ! 2 DISCONNECTED ! P_P2 = SNO ! P_P3 = ADDRESS OF DEVICE ENTRY ! P_P6 = MNEMONIC MNEMONIC=P_P1 *JLK_ %UNLESS SLOT<0 %START *JLK_ FLAG=2 %UNLESS STATE=DISCONNECTED %START FLAG=0 GPCT_STATE=READY GPCT_RESPONSE DEST=P_P2 P_P2=LOID+SLOT P_P3=ADDR(D) P_P6=GPCT_MNEMONIC %FINISH %FINISH P_P1=FLAG INP=P %RETURN !* ! DE-ALLOCATE ** NEW VERSION 4/81 ** !* GS(5): %UNLESS P_P1=M'LP' %START MNEMONIC=P_P1 *JLK_ FLAG=2 %UNLESS SLOT<0 %START *JLK_ P_P3=ADDR(D) FLAG=3!STATE<<16 %IF STATE=READY %START %IF SRCE>>16>63 %START; ! FROM USER PROCESS %IF 0>16<64 %C %THEN FLAG=4 %AND ->FALL ! PROHIBIT %FINISH GPCT_FLAGS=0 GPCT_STATE=NOT ALLOCATED FLAG=0 %FINISH %FINISH %FINISH FALL: !* MSG("GPC deallocate ".MNEMO(P_P1). %C !* " FLAG=".HTOS(FLAG,1)) ->ACKNOWLEDGE !* ! CLOCK INTERRUPT ! NO PARAMETERS !* GS(6): ! EACH TIME A CLOCK INTERRUPT OCCURS ! 1 FOR EACH BUSY SLOT, INCREMENT 'SECS SINCE' ! IF THIS BECOMES > TIMEOUT, ISSUE COPIOUS ! WARNINGS/DUMPS AND RECONNECT STREAM %FOR SLOT=0,1,LASTSLOT %CYCLE GE==RECORD(GPCT BASE+SLOT*SLOTSI) GPCNO=GE_PTSM>>16 PT=(GE_PTSM>>8)&255 D==RECORD(GE_DEVICE ENTRY A) CAA=D_CAA CA==RECORD(CAA) %IF GE_STATE=REQUEST FIRED %OR GE_STATE=SENSE FIRED %C %THEN D_SECS SINCE=D_SECS SINCE+TICK INTERVAL %IF D_SECS SINCE>D_TIMEOUT %START STRM=GE_PTSM>>4&15 %IF MULTI OCP=YES %START *JLK_ %UNLESS GE_BUSY=0 %THEN INTEGER(SEMA)=-1 %AND %CONTINUE GE_BUSY=TIMING OUT INTEGER(SEMA)=-1 %FINISH WK="GPC timeout ".MNS(D)." ".HTOS(D_GPTSM,5) MSG(WK) J=READ STRM DATA(PT,STRM,0) *JLK_ CA_PAW=3<<24!STRM; ! STOP STREAM *JLK_ WAIT(50) CONNECT STREAMS(PT,CAA,STRM,1,1) D_SECS SINCE=0 MSG("End of timeout") %IF MULTI OCP=YES %START *JLK_ GE_BUSY=0 INTEGER(SEMA)=-1 %FINISH %FINISH %REPEAT ->OUT !* ! EXECUTE ** NEW VERSION 9/79 ** !* GS(12): SLOT=P_P2-LOID ! CHECK THAT SLOT IN RANGE %IF 0<=SLOT<=LASTSLOT %THEN %START *JLK_ P3=P_P3 P_P3=ADDR(D) D_IDENT=P_P4 P_P6=P_P4 P_P4=0 P_P5=0 FLAG=2 ! CHECK DEVICE STATE FLAGS=GPCT_FLAGS %IF STATE=READY %START PAW FN=(P3&X'F0')<<20!STRM U RCB A=P_P1 SAWFLAGS=P3&15 USAW0=(SAWFLAGS<<28)!RCB BOUND ! IF THIS STREAM IS IDLE, CAN ISSUE REQUEST FORTHWITH %IF MULTI OCP=YES %START *JLK_ %FINISH %IF QHD=ENDLIST %START %IF MULTI OCP=YES %START; !OK TO RELEASE INTEGER(SEMA)=-1 %FINISH %IF CA_PAW#0 %OR SENT_SAW0#0 %C %THEN PAW NOT CLEARED(PT,STRM,CA_PAW) *JLK_ CA_PAW=PAW FN GPCT_LINK=ENDLIST QHD=SLOT SENT_SAW0=USAW0 SENT_SAW1=U RCB A *JLK_ STATE=REQUEST FIRED %FINISH %ELSE %START ! IF DEVICE IS NOT BUSY BUT STREAM IS, WE HAVE ! MULTI MECH STREAM. SO QUEUE THIS REQUEST %IF GPCT_DEVTYPE#MT %START; ! GASP!! MSG("GPC about to Q non-MT dev req!!") DUMPTABLE(79,X'80C00000',4096) %FINISH STATE=QUEUED LAST=QHD %UNTIL LAST=ENDLIST %CYCLE GE==RECORD(GPCT BASE+LAST*SLOTSI) LAST=GE_LINK %REPEAT GPCT_LINK=ENDLIST GE_LINK=SLOT %IF MULTI OCP=YES %START INTEGER(SEMA)=-1; ! RELEASE SEMAPHORE %FINISH %FINISH ! SET GPCT_FLAGS GPCT_STATE=STATE ! %IF P3&X'100'=0 %THEN GPCT_FLAGS=FLAGS&(\ %C ! GET STRM DATA) %ELSE GPCT_FLAGS=FLAGS!GET STRM DATA %IF P3&X'100'=0 %THEN GPCT_FLAGS=0 %ELSE %C GPCT_FLAGS=GET STRM DATA; !** ONLY 1 BIT USED SO SIMPLIFIED VSN OK ! FINALLY, SET FIELDS IN DEVICE ENTRY D_USAW0=USAW0 D_U RCB A=U RCB A D_PAW=PAW FN D_RESP1=0; ! TO CANCEL POSSIBLE TIMEOUT INDICATION D_SECS SINCE=0 CALLED=1 ! FORCES RETURN RATHER THAN PON FLAG=0 %FINISH %FINISH ->ACKNOWLEDGE !* ! INTERRUPT ! P1 = PT !* GS(3): PT=P_P1 GPCNO=PT TO GPC(PT-LOPT) CAA=CAAS(GPCNO) CA==RECORD(CAA) ! PICK UP AND CLEAR PIW *JLK_ PIW0=CA_PIW0 CA_PIW0=0 CA_MARK=-1 MORE INTS: ! DEAL WITH EACH BIT IN PIW0 *LSS_PIW0 ! JUMP OUT IF 'NO BITS SET' *JAT_4, *SHZ_STRM PIW0=PIW0!!X'80000000'>>STRM SENT==CA_S ENTRY(STRM) *JLK_ RESP0=SENT_RESP0 INTERRUPT ANALYSIS FLAGS=(RESP0>>20)&15 RESP1=SENT_RESP1 SENT_RESP0=0 SENT_RESP1=0 CA_MARK=-1 ! IGNORE TOTALLY SPURIOUS INTERRUPTS %IF RESP0=0 %THEN SLOT=ENDLIST %AND ->SPURIOUS INTERRUPT ! XSTRM AND XPT ARE INITIALISED TO -1, THEY ! ASSUME OTHER VALUES DURING CDS ON %IF STRM=XSTRM %AND PT=XPT %START ->MORE INTS %IF INTERRUPT ANALYSIS FLAGS=1; ! THROW AWAY ATTENTION INTERRUPTS ->CDS(XSTATE) %FINISH %IF INTERRUPT ANALYSIS FLAGS=1 %START ! MECH APPEARS IN RESPONSE ONLY FOR ATTENTION INTERRUPTS ! HENCE THE TWO DIFFERENT WAYS OF COMPUTING SLOT MECH=(RESP0>>24)&15 SLOT=PTS TO SLOT(((PT-LOPT)<<4)!STRM) %UNLESS SLOT=ENDLIST %START GPCT==RECORD(GPCT BASE+SLOT*SLOTSI) %IF GPCT_DEV TYPE=MT %START SLOT=MECHSLOTS(GPCT_MECHINDEX+MECH) %FINISH %FINISH %FINISH %ELSE SLOT=STRMQ(GPCNO<<4!STRM) ! IF NO SLOT, ASSUME SPURIOUS FLAG=2 %IF SLOT=ENDLIST %THEN ->SPURIOUS INTERRUPT *JLK_ FLAG=3 %IF MULTI OCP=YES %AND BUSY>0 %START; ! Other OCP doing timeout ->MORE INTS; ! so ignore int. %FINISH %IF STATE=NOT ALLOCATED %THEN ->SPURIOUS INTERRUPT %IF INTERRUPT ANALYSIS FLAGS=1 %START ! ATTENTION ACT=3 Q_P1=RESP0 *JLK_ ->MORE INTS %FINISH ! NOT AN ATTENTION INTERRUPT %IF STATE=SENSE FIRED %START %IF D_LOGMASK&BYTEINTEGER(ADDR(D_SENSE1))#0 %START DUMPTABLE(70+GPCT_DEVTYPE,ADDR(D),D_DEVICE ENTRY S) %FINISH GS3: ACT=5 Q_P1=D_RESP0 Q_P2=D_RESP1 Q_P4=RESP0>>16 Q_P5=GPCT_C STATUS *JLK_ ->TRY NEXT %FINISH %IF STATE=REQUEST FIRED %START D_RESP0=RESP0 D_RESP1=RESP1 %IF RESP0&ABNORMAL TERMINATION#0 %C %AND GPCT_RESPONSE DEST>>16<65 %START ! LEAVE SLOT AS FIRST IN LIST AND ISSUE SENSE J=D_LOGMASK>>8 %IF RESP0&X'00FF0000'=CONTROLLER DETECTED ERROR %C %OR J#0 %START WK="GPC abterm ".HTOS(PT<<4!STRM,3)." ".MNS(D). %C " ".HTOS(RESP0,8) MSG(WK) J=READ STRM DATA(PT,STRM,2);!READ CONTROL STREAM STATUS J=READ STRM DATA(PT,STRM,0);!READ STREAM DATA !* J=READ STRM DATA(PT,STRM,1) !READ STREAM'S CONTROLLER STATUS %IF GPCT_DEV TYPE=FE %AND RESP0&X'FF0000'= %C CONTROLLER DETECTED ERROR %C %THEN CONNECT STREAMS(PT,CAA,STRM,1,0) ! RE CONNECT FE AFTER ABTERM AND CDE %FINISH %IF GPCT_FLAGS&GETSTRMDATA#0 %START GPCT_CSTATUS=READ STRM DATA(PT,STRM,1) ! READ STREAM'S CONTROLLER STATUS ->GS3 %FINISH %IF CA_PAW#0 %THEN PAW NOT CLEARED(PT,STRM,CA_PAW) *JLK_ CA_PAW=DO STREAM REQUEST!STRM SENT_SAW0=X'10000020'; ! INTS + RCB BOUND SENT_SAW1=D_GRCB A ! DO NOT SEND AN INIT WORD (IN THE CASE OF MT WE ARE ADDRESSING THE MECHANISM ! ALREADY SELECTED) *JLK_ GPCT_STATE=SENSE FIRED ->MORE INTS %FINISH ACT=2 Q_P1=RESP0 Q_P2=RESP1 *JLK_ %IF RESP0&NORMAL TERMINATION#0 %C %OR (RESP0&ABNORMAL TERMINATION#0 %C %AND GPCT_RESPONSE DEST>>16>64) %THEN ->TRY NEXT ->MORE INTS %FINISH FLAG=4 ! HM WE APPEAR TO HAVE A NON ATTENTION INTERRUPT WHEN ! STATE IS READY/QUEUED SPURIOUS INTERRUPT: J=SPURIOUS INTS(STRM) SPURIOUS INTS(STRM)=J+1 %IF JMORE INTS TRY NEXT: ! A PREVIOUS REQUEST HAS BEEN COMPLETED (SOMEHOW) SO NOW ! MARK THAT SLOT 'READY' AGAIN AND SEE IF THERE ARE ANY ! OTHER REQUESTS QUEUED FOR THAT STREAM %IF MULTI OCP=YES %START *JLK_ %FINISH GPCT_STATE=READY QHD=GPCT_LINK GPCT_LINK=ENDLIST %IF QHD#ENDLIST %START SLOT=QHD *JLK_ ! TAKE NEXT REQUEST AND INITIATE %IF CA_PAW#0 %THEN PAW NOT CLEARED(PT,STRM,CA_PAW) *JLK_ CA_PAW=D_PAW SENT_SAW0=D_USAW0; ! SAW FLAGS + RCB BOUND SENT_SAW1=D_URCB A ! FREE COMMS AREA SEMAPHORE AND SEND CHANNEL FLAG *JLK_ GPCT_STATE=REQUEST FIRED %FINISH %IF MULTI OCP=YES %START INTEGER(SEMA)=-1; ! RELEASE SEMAPHORE %FINISH ->MORE INTS !* GS(7): ! ENTRY FOR RECONFIGURE ROUTINE ! P_P1 = IDENT ! P_P2 = SAC I=P_P2 P_P2=0 %FOR SLOT=0,1,LASTSLOT %CYCLE GPCT==RECORD(GPCT BASE+SLOT*SLOTSI) %IF GPCT_PTSM>>12&15=I %AND GPCT_STATE&15#DISCONNECTED %START; ! SAC IN USE P_P2=3<<24!GPCT_MNEMONIC %EXIT %FINISH %REPEAT ->ACK1 GS(10): ! Reinit GPC ! P_P1 = PT ! P_P2 = OLD PT IF >=0 PT=P_P1 %IF P_P2>=0 %AND PT#P_P2 %START; ! SAC switch ! *** not implemented protem - grope table requires extension *** OPMESS("Cannot switch GPCs") ->ACK1 %FINISH %IF LOPT<=PT<=HIPT %AND BYTEINTEGER(COM_CONTYPEA+PT)=3 %START GPC NO=PT TO GPC(PT-LOPT) I=GPC INIT(CAAS(GPC NO),PT,0); ! Reinitialise GPC %IF I=0 %THEN WK=" reinitialised" %ELSE WK=" reinit fails" OPMESS("GPC ".HTOS(PT,2).WK) %FINISH %ELSE OPMESS("Cannot reinit GPC ".HTOS(PT,2)) ->ACK1 GS(*): PKMONREC("GPC bad DACT:",P) ->OUT ACKNOWLEDGE: P_P1=FLAG ACK1: P_DEST=SRCE P_SRCE=GPC DEST!DACT %IF CALLED=0 %AND SRCE>>16#0 %THEN PON(P) OUT: INP=P %IF KMONNING=YES %START PKMONREC("GPC( out):",P) %IF GMON=YES %FINISH %RETURN !* ! CDS DEV ON ! 'FIND' AND 'DO MAPPINGS' HAVE BEEN DONE CDS ON: %IF XINIT=0 %START ! ON FIRST CALL, SET UP RCB ETC XINIT=1 XA=ADDR(X(0)) XRCB==RECORD(XA) XRCB_LIMFLAGS=X'4000'; ! TRUSTED CHAIN XRCB_LSTA=0 XRCB_LB S=32 XRCB_AL S=32 XRCB_AL A=XA+32 XALE==ARRAY(XRCB_AL A,ALEFF) XALE(0)_S=8 XALE(0)_A=XA+64; ! PROPSDATA XALE(1)_S=12 XALE(1)_A=XA+72; ! SENSE DATA XALE(2)_S=384 XALE(2)_A=XA+84; ! LP REPERTOIRE XALE(3)_S=4 XALE(3)_A=XA+468; ! LP INITWORD %FINISH %UNLESS XPT<0 %START REPLY(SRCE,"GPC: CDS already active") %RETURN %FINISH ! REMEMBER WHAT WE'RE LOOKING FOR! XSRCE=SRCE PIW0=0; ! SO THAT WE CAN ->MORE INTS WITH IMPUNITY XSLOT=SLOT XMNEMONIC=MNEMONIC XDEVTYPE=GPCT_DEVTYPE XPTS=GPCT_PTSM>>4&X'FFF' XGPC=0 GLOOP: XPT=TABLE(16+XGPC) %IF MULTI OCP=YES %START; ! SAC MAY BE CONFIGURED OUT %IF COM_NSACS=1 %START %UNLESS XPT>>4=COM_SACPORT0 %THEN ->SKIPG; ! SAC GONE %FINISH %FINISH XCAA=TABLE(8+XGPC) XCA==RECORD(XCAA) XSTRM=0 SLOOP: XSTATE=-1; ! NOTHING FIRED SLOT=PTS TO SLOT((XPT-LOPT)<<4!XSTRM) %IF SLOT=255 %THEN ->CONNECT GPCT==RECORD(GPCT BASE+SLOT*SLOTSI) %UNLESS GPCT_STATE&15=DISCONNECTED %THEN ->SKIP CONNECT: ! NOW FOUND A STRM THAT EITHER HAS NO SLOT ! ASSOCIATED WITH IT OR HAS A SLOT WHICH ! HAS BEEN DISCONNECTED XSENT==XCA_S ENTRY(XSTRM) X(16)=0 XSTATE=1; ! CONNECT ->XFIRE ! RESPONSE FROM CONNECT CDS(1): %IF X(16)>>24>0 %START ! FIRST BYTE OF PROPS DATA GIVES DEVTYPE, ! ZERO IF NO DEVICE %IF X(16)>>24=XDEVTYPE %START ! DEV OF RIGHT TYPE ! if MT, next byte gives cluster id ! if FE, next byte gives FE no. ! if SU, next byte gives SU no. %UNLESS (XDEVTYPE=MT %AND XMNEMONIC&X'F00'#X(16)>>12 %C &X'F00') %OR (XDEVTYPE=FE %C %AND XMNEMONIC&15#X(16)<<8>>24) %OR %C (XDEVTYPE=SU %AND XMNEMONIC&15#X(16)<<8>>24) %THEN ->XFOUND %FINISH ! IF FOUND A DEVICE OF WRONG TYPE, DISCONNECT IT XSTATE=0; ! DISCONNECT ->XFIRE %FINISH ! RESPONSE FROM DISCONNECT CDS(0): SKIP: %UNLESS XSTRM=14 %THEN XSTRM=XSTRM+1 %AND ->SLOOP SKIPG: %UNLESS XGPC=NO OF GPCS-1 %THEN XGPC=XGPC+1 %AND ->GLOOP REPLY(XSRCE,"GPC: ".MNEMO(XMNEMONIC)." not found") XPT=-1 XSTRM=-1 %IF XSTATE<0 %THEN %RETURN %ELSE ->MORE INTS XFOUND: REPLY(XSRCE,"GPC: ".MNEMO(XMNEMONIC)." now on pts ".HTOS( %C XPT<<4!XSTRM,3)) PTS TO SLOT(XPTS-(LOPT<<4))=255 PTS TO SLOT((XPT-LOPT)<<4!XSTRM)=XSLOT XGPTSM=(XGPC<<16)!(XPT<<8)!(XSTRM<<4) %FOR SLOT=0,1,LASTSLOT %CYCLE GPCT==RECORD(GPCT BASE+SLOT*SLOTSI) %IF (GPCT_PTSM>>4)&X'FFF'=XPTS %START ! MOVE EVERYTHING ON THIS PTS D==RECORD(GPCT_DEVICE ENTRY A) D_GPTSM=XGPTSM!(D_GPTSM&15) GPCT_PTSM=D_GPTSM D_CAA=XCAA GPCT_STATE=GPCT_STATE>>4 %FINISH %REPEAT %UNLESS XDEVTYPE=LP %THEN ->XOUT ! FIRST BUILD A TRANSLATE TABLE IN ! THE DEVICE ENTRY TO FILTER OUT INVALID CHARACTERS XCART=(X(17)>>16)&15 XA=REPERTOIRE A(XCART) REP==ARRAY(XA,BIFT) XS=REPERTOIRE S(XCART) TRTAB==ARRAY(D_TRTABLE A,BIFT) %FOR I=0,1,255 %CYCLE; TRTAB(I)=I; %REPEAT %UNLESS XCART=0 %START %FOR I=0,1,255 %CYCLE %IF FIND BYTE(I,XA,XS)<0 %START ! NOT IN REP %IF FIND BYTE(I,ADDR(LCLETTS(1)),26)<0 %START TRTAB(I)=LP ILLCHAR %FINISH %ELSE %START TRTAB(I)=I!X'40'; ! MAKE UC LETTER %FINISH %FINISH %REPEAT TRTAB(37)=X'15' TRTAB(21)=X'15' TRTAB(12)=X'0C'; ! NEWLINE TRTAB(13)=X'0D' TRTAB(64)=X'40'; ! SPACE %FINISH ! X(16) HAS BYTES 0-3 OF LP PROPERTIES ! X(17) HAS BYTES 4-5 ! BOTTOM 4 BITS OF BYTE 5 HAS CARTRIDGE NUMBER SET ON FRONT OF LP. ! IF CARTRIDGE NUMBER IS SET ZERO, WE DON'T LOAD ANY REP IF ! THERE'S ONE ALREADY LOADED, ELSE WE LOAD THE 64-CHAR REP ! (BEING THE FIRST 64 CHARS OF THE 96-CHAR REP ABOVE). ! IF THE CARTRIDGE NUMBER IS : ! 2 WE LOAD THE 48-CHAR REP FOR THE PO DPS CRAIGLOCKHART 2970 ! 3 WE LOAD THE 384-CHAR REP FOR THE BUSH ESTATE 2980 ! 4 WE LOAD THE 64-CHAR REP FOR THE PO DPS BARBICAN 2970 ! 5 WE LOAD THE 96-CHAR REP FOR THE ERCC-KB 2970 XSTYLE=X(16)&255 XLEN=(XSTYLE>>4)*10+XSTYLE&15 XLEN=66 %IF XLEN=0 XLBE(6)=(XLBE(6)&(\255))!(XLEN-1) %FOR I=0,XS,384-XS %CYCLE MOVE(XS,XA,ADDR(X(21))+I) %REPEAT X(117)=X'00000010'; ! BACK ? FOR ILLEGAL, AUTOTHROW NOT SET XSTATE=5; ! INITIALISE OUTWARDS ->XFIRE CDS(5): ! RESP FROM INIT %IF XCART=0 %AND X(17)&X'100000'=0 %THEN ->CDS(4) XSTATE=4; ! LOADREP OUTWARDS ->XFIRE CDS(4): ! RESP FROM LOAD REP X(117)=X'0000FC10' XSTATE=7; ! ANOTHER INIT ->XFIRE CDS(7): ! RESP FROM SECOND INIT %IF XSTYLE=X'99' %THEN ->XOUT XSTATE=6; ! WRITE CONTROL ->XFIRE CDS(6): ! RESP FROM WRITE CONTROL XOUT: XPT=-1 XSTRM=-1 ->MORE INTS XFIRE: ! NEEDS XCAA, XSENT, XPT, XSTRM SETTING UP OUTSIDE ! USES XSTATE TO SELECT REQUIRED COMMAND %IF XCA_PAW#0 %OR XSENT_SAW0#0 %START PAW NOT CLEARED(XPT,XSTRM,XCA_PAW) %FINISH XRCB_LBA=ADDR(XLBE(XSTATE)) SLAVES ON OFF(0); ! SLAVES OFF GET CA(XCAA) XCA_PAW=DO STREAM REQUEST!XSTRM XSENT_SAW0=X'30000020' XSENT_SAW1=ADDR(XRCB) XSENT_RESP0=0 XCA_MARK=-1 SEND CH FLAG(XPT) %FOR I=1,1,COM_INSPERSEC*150 %CYCLE; ! wait about 1 sec %EXIT %IF XSENT_RESP0#0 %REPEAT XCA_PIW0=XCA_PIW0&(\(X'80000000'>>XSTRM));! NO SURPRISE INTS. XSENT_RESP0=0 SLAVES ON OFF(-1); ! BACK ON ->CDS(XSTATE); ! PROCESS RESPONSE !* ! PSEUDO ROUTINE ! SENDS A RESPONSE AFTER AN INTERRUPT HAS ! BEEN ANALYSED !* RESPOND: Q_DEST=GPCT_RESPONSE DEST %IF GPCT_DEVTYPE=OP %THEN Q_DEST=Q_DEST!((GPCT_MECHINDEX>>4)<< %C 8) Q_SRCE=GPC DEST!3 BYTEINTEGER(ADDR(Q_P1))=LOID+SLOT Q_P3=ADDR(D) Q_P6=D_IDENT PKMONREC("GPC( PONS):",Q) %IF GMON=YES PON(Q) *J_%TOS !* END OF RESPOND !* ! PSEUDO ROUTINE ! GIVEN MNEMONIC, SEARCHES FOR CORRESPONDING SLOT ! OR, IF NOT FOUND, SETS SLOT TO -1 !* FIND: SLOT A=GPCT BASE %FOR SLOT=0,1,LAST SLOT %CYCLE GPCT==RECORD(SLOTA) %IF MNEMONIC=LOID+SLOT %OR MNEMONIC=GPCT_MNEMONIC %C %OR MNEMONIC=GPCT_PTSM&X'FFFF' %C %OR (MNEMONIC=M'LP' %AND GPCT_MNEMONIC>>8=M'LP' %C %AND GPCT_PROPS03&X'80'=0) %THEN %START *J_%TOS %FINISH SLOT A=SLOT A+SLOTSI %REPEAT %IF MNEMONIC=M'LP' %START MNEMONIC=M'LP0' ->FIND %FINISH SLOT=-1 *J_%TOS !* END OF FIND !* ! PSEUDO ROUTINE ! GIVEN SLOT, SETS VARIOUS POINTERS !* DO MAPPINGS: GPCT==RECORD(GPCT BASE+SLOT*SLOTSI) D==RECORD(GPCT_DEVICE ENTRY A) GPTSM=GPCT_PTSM GPC NO=GPTSM>>16 PT=(GPTSM>>8)&255 STRM=(GPTSM>>4)&15 MECH=GPTSM&15 STATE=GPCT_STATE&15 BUSY=GPCT_BUSY CAA=CAAS(GPC NO) QHD==STRMQ(GPC NO<<4+STRM) CA==RECORD(CAA) SENT==CA_S ENTRY(STRM) *J_%TOS !* END OF DO MAPPINGS !* ! PSEUDO ROUTINE !* GET CA: *LXN_CAA *INCT_(%XNB+0) *JCC_8, SEMALOOP(INTEGER(CAA)) GOT: *J_%TOS !* END OF GET CA !* ! PSEUDO ROUTINE GET STRM SEMA: SEMA=ADDR(STRM SEMAPHORE(GPCNO<<4!STRM)) *LXN_SEMA *INCT_(%XNB + 0) *JCC_8, SEMALOOP(INTEGER(SEMA)) GOT SS: *J_%TOS !* END OF GET STRM SEMA !* ! PSEUDO ROUTINE !* SEND CH FLAG: CA_MARK=-1 BREG=TRUNKADDR!(PT<<16) *LB_BREG *LSS_1 *ST_(0 + %B) *J_%TOS !* END OF SEND CH FLAG !* %END; ! OF GPC %ENDOFFILE