CONSTSTRING  (25) VSN="GPC40 15th Mar 1982"
!************************************************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,INTEGER  PARM)
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, <GOT>
      SEMALOOP(INTEGER(CAA),2)
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_ <FOR EACH STREAM>
                                        ! THEN RECONNECT IF REQUIRED
      IF  CONNECT=1 START 
         WAIT(10)
         RCB_LBA=ADDR(CONNECT LBE)
         TXT="connect"
         *JLK_ <FOR EACH STREAM>
      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  GDC(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<NO OF GPCS<<4 CYCLE ;    ! NO OF GPCS*16
         STRMQ(J)=X'FF'
         J=J+1
      REPEAT 
      PREVIOUS PT=0;                    ! to hold PTS really
      FOR  J=0,1,LASTSLOT CYCLE 
         GE==RECORD(GPCTBASE+J*SLOTSI)
         IF  GE_DEVTYPE=OP START 
            I=GE_MECHINDEX>>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  0<DACT<13 THEN  ->GS(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_<FIND>
      IF  SLOT<0 THEN  ->ERR
      *JLK_<DO MAPPINGS>
   FINISH 
   ->G COMMAND(J)
                                        ! QS DEV
G COMMAND(1):

   *JLK_<STATUS>
   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_<FIND>
   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_<STATUS>
   REPEAT 
   RETURN 
!*
                                        ! ALLOCATE   ** NEW VERSION 9/79 **
!*
GS(11):

   MNEMONIC=P_P1
   *JLK_<FIND>
   UNLESS  SLOT<0 START 
      *JLK_<DO MAPPINGS>
      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_<FIND>
   UNLESS  SLOT<0 START 
      *JLK_<DO MAPPINGS>
      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_<FIND>
      FLAG=2
      UNLESS  SLOT<0 START 
         *JLK_<DO MAPPINGS>
         P_P3=ADDR(D)
         FLAG=3!STATE<<16
         IF  STATE=READY START 
            IF  SRCE>>16>63 START ;     ! FROM USER PROCESS
               IF  0<GPCT_RESPONSE DEST>>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_<GET STRM SEMA>
               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_<GET CA>
         CA_PAW=3<<24!STRM;             ! STOP STREAM
         *JLK_<SEND CH FLAG>
         WAIT(50)
         CONNECT STREAMS(PT,CAA,STRM,1,1)
         D_SECS SINCE=0
         MSG("End of timeout")
         IF  MULTI OCP=YES START 
            *JLK_<GET STRM SEMA>
            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_<DO MAPPINGS>
      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_<GET STRM SEMA>
         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_<GET CA>
            CA_PAW=PAW FN
            GPCT_LINK=ENDLIST
            QHD=SLOT
            SENT_SAW0=USAW0
            SENT_SAW1=U RCB A
            *JLK_<SEND CH FLAG>
            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_<GET CA>
   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, <OUT>
   *SHZ_STRM
   PIW0=PIW0!!X'80000000'>>STRM
   SENT==CA_S ENTRY(STRM)
   *JLK_<GET CA>
   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_<DO MAPPINGS>
   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_<RESPOND>
      ->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_<RESPOND>
      ->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_<GET CA>
         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_<SEND CH FLAG>
         GPCT_STATE=SENSE FIRED
         ->MORE INTS
      FINISH 
      ACT=2
      Q_P1=RESP0
      Q_P2=RESP1
      *JLK_<RESPOND>
      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  J<SPURIOUS LIMIT START 
      MSG("GPC spurious int on ".HTOS(PT<<4!STRM,3)."/".HTOS( C 
         RESP0,8))
   FINISH 
   IF  J=SPURIOUS LIMIT AND  BUSY=0 START 
      CONNECT STREAMS(PT,CAA,STRM,0,0)
      UNLESS  SLOT=ENDLIST THEN  GPCT_STATE=DISCONNECTED
   FINISH 
   ->MORE 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_<GET STRM SEMA>
   FINISH 
   GPCT_STATE=READY
   QHD=GPCT_LINK
   GPCT_LINK=ENDLIST
   IF  QHD#ENDLIST START 
      SLOT=QHD
      *JLK_<DO MAPPINGS>
                                        ! TAKE NEXT REQUEST AND INITIATE
      IF  CA_PAW#0 THEN  PAW NOT CLEARED(PT,STRM,CA_PAW)
      *JLK_<GET CA>
      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_<SEND CH FLAG>
      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(9):                                  ! entry from SHUTDOWN routine
                                        ! P_P1 = pt
      IF  COM_NSACS=1 AND  COM_SACPORT0#P_P1>>4 THEN  ->ACK1; ! SAC gone
      FOR  SLOT=0,1,LAST SLOT CYCLE 
         *JLK_<DO MAPPINGS>
         IF  PT=P_P1 START 
            XRCB==RECORD(D_GRCB A)
            IF  GPCT_DEVTYPE=MT START 
               XRCB_LIM FLAGS=X'C000'
               I=XRCB_INIT WORD&X'FF'
               I=3 IF  I=0
               XRCB_INIT WORD=MECH<<24!I
            FINISH  ELSE  XRCB_LIM FLAGS=PRIV ONLY
            INTEGER(XRCB_LBA)=X'80F01800'
            LONGINTEGER(XRCB_ALA)=X'5800000481000000'
            XRCB_LBS=4
            XRCB_ALS=8
            *JLK_<GET CA>
            CA_PAW=DO STREAM REQUEST!STRM
            CA_PIW0=0
            SENT_SAW0=3<<28!RCB BOUND
            SENT_SAW1=ADDR(XRCB)
            SENT_RESP0=0
            SENT_RESP1=0
            *JLK_<SEND CH FLAG>
            WAIT(10)
         FINISH 
      REPEAT 
      WAIT(100)
      ->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  RECONFIGURE=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
   IF  KMONNING=YES AND  GMON=YES THEN  PKMONREC("GPC( PONS):",Q)
   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, <GOT>
   SEMALOOP(INTEGER(CAA),2)
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, <GOT SS>
   SEMALOOP(INTEGER(SEMA),2)
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
!*
IF  CSU FITTED=YES START 
EXTERNALROUTINE  CSU(RECORD (PARMF)NAME  P)
RECORD (PARMF) Q
RECORD (DEVICE ENTRY F)NAME  D
SWITCH  ACT(0:10)
OWNINTEGERARRAY  DTODA(0:9)=NOT ALLOCATED(*)
CONSTINTEGER  CSU SNO=CSU DEST>>16
IF  KMONNING=YES AND  KMON>>CSU SNO&1#0 THEN  PKMONREC("CSU :",P)
->ACT(P_DEST&255)
ACT(0):                                 ! initialise call from GPC
   Q=0
   Q_DEST=GPC DEST!11;                  ! allocate
   Q_SRCE=P_DEST!1
   Q_P1=P_P1
   Q_P2=P_DEST!5;                       ! interrupts to ACT 5
   PON(Q)
   RETURN 
ACT(1):                                 ! reply from allocate
   UNLESS  P_P1=0 START ;               ! failed
      BYTEINTEGER(ADDR(P_P6))=3
      OPMESS(STRING(ADDR(P_P6))." alloc fails ".HTOS(P_P1,1))
      RETURN 
   FINISH 
   D==RECORD(P_P3)
   DTODA(P_P6&255-'0')=P_P3
   RETURN 
ACT(2):                                 ! deallocate
   RETURN 
ACT(3):                                 ! deallocate reply
   RETURN 
ACT(5):                                 ! interrupt from GPC
   RETURN 
ACT(6):                                 ! switch device
   RETURN 
ACT(7):                                 ! switch controller
   RETURN 
END 
FINISH 
ENDOFFILE