!* !* GPC/DCU driver !* CONSTSTRING (26) VSN=".GDC03 - 3rd April 1985" OWNINTEGER IVSN=M'GDC3' !* RECORDFORMAT PARMF(INTEGER DEST,SRCE,(INTEGER P1,P2,P3,P4,P5,P6 OR C STRING (23)TEXT)) !* !* !* Communications record format - extant from CHOPSUPE 22A onwards * !* RECORDFORMAT COMF(INTEGER OCPTYPE,SLIPL,SBLKS,SEPGS,NDISCS,DLVNADDR, C (INTEGER GPCTABSIZE,GPCA OR INTEGER DCUTABSIZE,DCUA), C INTEGER 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,INTEGER ITINT,CONTYPEA, C (INTEGER GPCCONFA OR INTEGER DCUCONFA), C INTEGER FPCCONFA,SFCCONFA,BLKADDR,RATION, C (INTEGER SMACS OR INTEGER SCUS), C INTEGER 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,PERFORMAD,SP1,SP2,SP3,SP4,SP5,SP6, C LSTL,LSTB,PSTL,PSTB,HKEYS,HOOT,SIM,CLKX,CLKY,CLKZ, C HBIT,SLAVEOFF,INHSSR,SDR1,SDR2,SDR3, C SDR4,SESR,HOFFBIT,BLOCKZBIT,BLKSHIFT,BLKSIZE,END) CONSTRECORD (COMF)NAME COM=X'80000000'!48<<18 !* EXTERNALINTEGERFNSPEC REALISE(INTEGER VAD) EXTERNALROUTINESPEC PON(RECORD (PARMF)NAME P) EXTERNALROUTINESPEC SLAVESONOFF(INTEGER I) EXTERNALROUTINESPEC GET PSTB(INTEGERNAME PSTL,PSTB) EXTERNALROUTINESPEC SEMALOOP(INTEGERNAME SEMA,INTEGER PARM) EXTERNALROUTINESPEC WAIT(INTEGER MILLSECS) EXTERNALROUTINESPEC DUMPTABLE(INTEGER T,A,L) EXTERNALROUTINESPEC PKMONREC(STRING (20)TXT,RECORD (PARMF)NAME P) EXTERNALSTRINGFNSPEC HTOS(INTEGER I,PL) EXTERNALSTRINGFNSPEC STRINT(INTEGER N) EXTERNALROUTINESPEC OPMESS(STRING (63)S) SYSTEMROUTINESPEC MOVE(INTEGER L,F,T) IF MULTI OCP=YES START EXTERNALROUTINESPEC RESERVE LOG EXTERNALROUTINESPEC RELEASE LOG FINISH IF SSERIES=NO START INTEGERFNSPEC GPC INIT(INTEGER CAA,PT,FLAG) RECORDFORMAT CASEF(INTEGER SAW0,SAW1,RESP0,RESP1) RECORDFORMAT CAF(INTEGER MARK,PAW,PIW0,PIW1,CSAW0,CSAW1,CRESP0,CRESP1, C RECORD (CASEF)ARRAY STREAM(0:14)) CONSTINTEGER DO CONTROLLER REQUEST=X'04000000' FINISH !* CONSTINTEGER ABNORMAL TERMINATION=X'00400000' CONSTINTEGER ATTENTION=X'00100000' CONSTINTEGER CONTROLLER DETECTED ERROR=X'00410000' CONSTINTEGER DISCONNECTED=5 CONSTINTEGER ENDLIST=255 CONSTINTEGER FE=14 CONSTINTEGER LOID=X'6E' CONSTINTEGER LP=6 CONSTINTEGER MT=5 CONSTINTEGER MNMASK=X'FFFF30' CONSTINTEGER NORMAL TERMINATION=X'00800000' CONSTINTEGER NOT ALLOCATED=0 CONSTINTEGER OK=0 CONSTINTEGER OP=8 CONSTINTEGER QUEUED=4 CONSTINTEGER READY=1 CONSTINTEGER REQUEST FIRED=2 CONSTINTEGER SLOT SIZE=32 CONSTINTEGER SU=13 CONSTINTEGER TICK INTERVAL=2 constinteger timed out=6 CONSTINTEGER ZX=11 !* OWNBYTEINTEGERARRAYFORMAT BIFT(0:1023) OWNINTEGERARRAYFORMAT IFT(0:1023) !* OWNINTEGER SETUP=NO OWNINTEGER GDCT BASE OWNINTEGER LAST SLOT OWNINTEGER LOCNO OWNINTEGER NO OF GDCS OWNBYTEINTEGERARRAYNAME MECHSLOTS OWNBYTEINTEGERARRAYNAME CSTRM TO SLOT OWNBYTEINTEGERARRAYNAME CNO TO GDC OWNBYTEINTEGERARRAYNAME STRM Q OWNINTEGERARRAYNAME CAAS OWNINTEGERARRAYNAME TABLE OWNINTEGERARRAYNAME STRM SEMAPHORE OWNSTRINGNAME DATE,TIME !* CONSTINTEGER KMONNING=2 IF MONLEVEL&KMONNING#0 START EXTERNALLONGINTEGERSPEC KMON FINISH !* CONSTINTEGER GDC DEST=X'300000' CONSTINTEGER GDC SNO=GDC DEST>>16 IF CSU FITTED=YES START CONSTINTEGER CSU DEST=X'290000' FINISH !* EXTERNALROUTINE GDC(RECORD (PARMF)NAME P) !* IF SSERIES=YES START ; ! DCU specific declarations EXTERNALROUTINESPEC DISC(RECORD (PARMF)NAME P) EXTERNALROUTINESPEC DCU1 RECOVERY(INTEGER PARM) EXTERNALINTEGERSPEC DCU RFLAG; ! reconnect DCU1 streams if non-zero ROUTINESPEC FIRE IDENTIFY RECORDFORMAT DEVICE ENTRY F(INTEGER C SER, DSSMM, PROPADDR, SECS SINCE, CAA, MYCCBA, C BYTEINTEGER MECH,ATTN,SP1,SP2,INTEGER LAST TCB ADDR, C X2, RESP0, X3, SENSE1, SENSE2, SENSE3, SENSE4, C REPSNO, BASE, ID, DLVN, MNEMONIC, C STRING (6) LABEL, BYTE INTEGER HWCODE, C INTEGER ENTSIZE, UCCBA, SENSDAT AD, LOGMASK, TRTAB AD, C UA SIZE, UA AD, TIMEOUT,PROPS0,PROPS1) RECORDFORMAT CCBF(INTEGER COMMAND,STE,LEN,DATA,NTCB,RESP, C INTEGERARRAY PREAMBLE,POSTAMBLE(0:3)) RECORDFORMAT CAF(INTEGER IAWA,SEMA) OWNBYTEINTEGERARRAYFORMAT LBIFT(0:2047) CONSTINTEGER CONNECT TERM=X'00201000' CONSTINTEGER DISCONNECT TERM=X'00202000' CONSTINTEGER DISC DEST=X'200000' CONSTINTEGER EDS100=X'33',FDS640=X'3B' CONSTINTEGER IDENTIFY FIRED=3 CONSTINTEGER INIT FAIL=X'00200000' CONSTINTEGER INVALID ACTIVATE=X'00400000' CONSTINTEGER MSPC=256; ! max streams/DCU CONSTINTEGER POST AMBLE VALID=X'00004000' CONSTINTEGER PRIMITIVE=X'00800000' CONSTINTEGER RESET STREAM=6 CONSTINTEGER SENSE FAIL=X'00100000' CONSTINTEGER START STREAM=2 CONSTINTEGER STOP STREAM=4 CONSTINTEGER STREAM ABTERM=X'00000400' CONSTINTEGER STREAM ATTENTION=X'00004000' CONSTINTEGER STREAM INT=X'00200000' CONSTINTEGER STREAM TTERM=X'00008000' CONSTINTEGER STREAM CTERM=CONNECT TERM!DISCONNECT TERM CONSTINTEGER STREAM IA=STREAM INT!STREAM ATTENTION CONSTINTEGER STREAM ITA=STREAM IA!STREAM TTERM CONSTINTEGER TCB ATTN=X'20000000' CONSTINTEGER TCB CONT=X'00800000' CONSTINTEGER TCB FAIL=X'C0000000' CONSTINTEGER TCB LENGTH=14*4 INTEGER INTWD LONGINTEGER L !* I/O control declarations ROUTINESPEC ACTIVATE(INTEGER ACTWD,TCBAD,ISAD) ROUTINESPEC FIRE DCU2(INTEGER UTAD,TCBAD,ACT) EXTERNALINTEGERFNSPEC NEW PP CELL EXTERNALROUTINESPEC RETURN PP CELL(INTEGER CELL) EXTERNALLONGINTEGERSPEC PARMDES RECORDFORMAT QACT F(INTEGER ACTWD,TCBAD,ISAD,P2,P3,P4,P5,P6,LINK) RECORD (QACT F)NAME QACT RECORD (QACT F)ARRAYFORMAT PARMAF(0:65535) OWNRECORD (QACT F)ARRAYNAME PARM OWNINTEGER QHEAD=0 OWNINTEGER ACTS QD=0,MAX Q=0,ACT CYCLES=0 IF MULTI OCP=YES START OWNINTEGER DCU1 SEMA=-1,DCU2 SEMA=-1 OWNINTEGER RECOVER DCU1S=0 FINISH INTEGER ISAD,SINK !* FINISH ELSE START ; ! GPC specific declarations EXTERNALROUTINESPEC CONTROLLER DUMP(INTEGER CONTYPE,PT) ROUTINESPEC PAW WAIT(RECORD (CAF)NAME CA) ROUTINESPEC CONNECT STREAM(INTEGER PT,CAA,STREAM,CONNECT) INTEGERFNSPEC READ STREAM DATA(INTEGER PT,STRM,CNTR) RECORDFORMAT DEVICE ENTRY F(INTEGER SER, GPTSM, PROPADDR, C SECS SINCE, CA A, MYCCBA, 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 CCB A, SENSE DATA A, LOG MASK, TRTAB AD, UA SIZE, C UA AD, TIMEOUT, PROPS0, PROPS1) RECORDFORMAT CCBF(INTEGER LIMFLAGS,LSTA,LBS,LBA,ALS,ALA,INIT,X1) RECORDFORMAT ALEF(INTEGER S,A) RECORD (CASEF)NAME STREAM OWNBYTEINTEGERARRAYFORMAT LBIFT(0:511) CONSTINTEGER DO STREAM REQUEST=X'01000000' CONSTINTEGER GET STRM DATA=16 CONSTINTEGER MSPC=16; ! max streams/GPC CONSTINTEGER PRIV ONLY=X'4000' CONSTINTEGER RCB BOUND=32 CONSTINTEGER SENSE FIRED=3 STRING (23)WK INTEGER PAW FN,USAW0,PT,PIW0 !* FINISH !* RECORDFORMAT GDCT F(BYTEINTEGER FLAGS,DEVTYPE,ATTN,LINK, C (INTEGER Q OR INTEGER X4), C INTEGER RESPONSE DEST,DEVICE ENTRY A, C (INTEGER CSTATUS,PTSM OR INTEGER UTAD,DSSMM), INTEGER MNEMONIC, C BYTEINTEGER MECHINDEX,PROPS03,SERVRT,STATE) !* RECORD (DEVICE ENTRY F)NAME DEV RECORD (GDCT F)NAME GDCT,GE RECORD (CCBF)NAME CCB RECORD (PARMF) Q RECORD (CAF)NAME CA !* ROUTINESPEC FAIL TRANSFER(RECORD (GDCTF)NAME G,INTEGER SLOT) INTEGERFNSPEC FIND(INTEGER MNEMONIC) STRINGFNSPEC MTOS(INTEGER MNEMONIC) ROUTINESPEC REPLY(INTEGER SRCE,STRING (30)TEXT) INTEGERFNSPEC STATE CHECK(INTEGER MNEMONIC,STATE) ROUTINESPEC STATUS(INTEGER SLOT) INTEGERFNSPEC TRANS MNEMONIC(STRINGNAME S) !* CONSTINTEGER LIMIT=3 CONSTSTRING (4)ARRAY COMMAND(1:LIMIT)="QS ","CDS ","CDM " CONSTSTRING (9)ARRAY STATES(0:6) = "not alloc", "ready", "req fired", "sns fired", "queued", "discncted","timed out" !* !* Declarations for CDM !* CONSTINTEGER CDMDEVLIMIT=7 CONSTINTEGERARRAY CDMDEV(0:CDMDEVLIMIT)=C M'FE',M'LP',M'CR',M'CP',M'PR',M'PT',M'SU',M'CT' CONSTBYTEINTEGERARRAY CDMDEVTYPE(0:CDMDEVLIMIT)=14,6,4,3,2,1,13,12 CONSTINTEGERARRAY CDMDEVTIMEOUT(0:CDMDEVLIMIT)=C X'01FF0003',60,300,600,60,60,10,10; ! top of FEP word is logmask !* 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 !%CONSTINTEGERARRAY LP384REP(0:95)=c !%CONSTBYTEINTEGERARRAY LCLETTS(1:26)=c ENDOFLIST 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'EBBCA1BD', 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' LIST !* SWITCH GDC COMMAND(1:LIMIT) SWITCH ACT(1:12) !* STRING (23)TEXT STRING (15)MNEMOS !* BYTEINTEGERNAME QHD BYTEINTEGERARRAYNAME REP,TRTAB !* INTEGER DACT,SRCE,FLAG INTEGER SLOT,STATE,GDCNO,FLAGS INTEGER MNEMONIC,MNEMONIC1,MNEMONIC2 INTEGER STRM,CAA,UCCBA,CNO,SEMA INTEGER RESP0,RESP1 INTEGER MECH INTEGER I,J !* IF MONLEVEL&KMONNING#0 AND KMON>>GDC SNO&1#0 START IF SSERIES=YES THEN PKMONREC("DCU :",P) ELSE PKMONREC("GPC :",P) FINISH DACT=P_DEST&X'FFFF' ->ACT(DACT) !* ACT(2): ! initialise RETURN UNLESS SETUP=NO SETUP=YES IF SSERIES=YES THEN PARM==ARRAY(INTEGER(ADDR(PARMDES)+4),PARMAF) J=P_P1; ! GDC table address TABLE==ARRAY(J,IFT); ! 1024 words TABLE(42)=P_P2; ! process picture IF SSERIES=NO THEN STRM SEMAPHORE==ARRAY(J+TABLE(40)<<2,IFT) !* ! protem for S series use CA_SEMA - need extra fields in ENTFORM !* GDCT BASE=J+TABLE(1)<<2; ! slot table address LASTSLOT=TABLE(2) NO OF GDCS=TABLE(3) !* reminders ! ! STRMQ addressed as 1) GDCNO<<4!STRM (was GPCNO<<4!STRM) ! or 2) GDCNO<<8!STRM (was DCUNO<<8!STRM) ! where GDCNO is logical GPC/DCU no. ! and got from:- ! ! CNO TO GDC as 1) CNO-LOCNO (was PT TO GPC(PT-LOPT)) ! or 2) CNO-LOCNO (was PT TO GPC(h/w DCU no.-LOPT)) ! ! CSTRM TO SLOT as 1) (PT-LOCNO)<<4!STRM (was PTS TO SLOT((PT-LOPT)<<4!STRM)) ! or 2) ((CNO-LOCNO)<<8!STRM) (was h/w/DCU no.-LOPT)<<8!STRM) !* STRMQ==ARRAY(J+TABLE(4)<<2,LBIFT); ! 1 byte per stream CSTRM TO SLOT==ARRAY(J+TABLE(5)<<2,LBIFT); ! ditto CNO TO GDC==ARRAY(J+TABLE(6)<<2,BIFT); ! CNO is pt for GPC, H/W DCU no. for DCU MECHSLOTS==ARRAY(J+TABLE(7)<<2,BIFT) CAAS==ARRAY(ADDR(TABLE(8)),IFT) LOCNO=255 FOR J=0,1,NO OF GDCS-1 CYCLE I=TABLE(16+J) IF I<LOCNO THEN LOCNO=I REPEAT J=0; ! re-initialise STRMQ heads WHILE J<NO OF GDCS*MSPC CYCLE LONGINTEGER(ADDR(STRMQ(J)))=-1 J=J+8 REPEAT 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 DATE==STRING(ADDR(COM_DATE0)+3) TIME==STRING(ADDR(COM_TIME0)+3) ! re-initialise slots FOR J=0,1,LASTSLOT CYCLE GDCT==RECORD(GDCT BASE+J*SLOT SIZE) GDCT_FLAGS=0 GDCT_LINK=ENDLIST IF GDCT_DEVTYPE=ZX THEN GDCT_STATE=DISCONNECTED C ELSE GDCT_STATE=NOT ALLOCATED GDCT_ATTN=0 GDCT_X4=0 GDCT_RESPONSE DEST=0 IF SSERIES=NO THEN GDCT_CSTATUS=0 GDCT_SERVRT=0 DEV==RECORD(GDCT_DEVICE ENTRY A) DEV_RESP0=0 IF SSERIES=YES AND EDS100<=GDCT_DEVTYPE<=FDS640 START GDCT_STATE=READY GDCT_RESPONSE DEST=DISC DEST!3 DEV_SER=J+LOID FINISH ELSE IF GDCT_DEVTYPE=OP START I=GDCT_MECHINDEX>>4; ! logical OPER no P=0 P_P1=GDCT_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 GDCT_DEVTYPE=FE START P=0 P_P1=GDCT_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 GDCT_DEVTYPE=MT START IF GDCT_PTSM&15=0 START ; ! 1 call per cluster P=0 P_DEST=X'00310004' P_SRCE=X'00300000' P_P1=GDCT_MNEMONIC PON(P) FINISH FINISH ELSE IF CSU FITTED=YES AND GDCT_DEVTYPE=SU START P=0 P_DEST=CSU DEST; ! CSU initialise P_P1=GDCT_MNEMONIC PON(P) FINISH REPEAT IF SSERIES=YES AND COM_NDISCS>0 START P=0 P_DEST=DISC DEST; ! initialise DISC PON(P) FINISH !* PRINTSTRING(VSN) NEWLINE PRINTSTRING("GDC's tables:-") DUMPTABLE(0,ADDR(TABLE(0)),TABLE(0)<<2+4) !* P_DEST=X'A0001'; ! interval timer P_SRCE=0 P_P1=GDC DEST!6 P_P2=TICK INTERVAL PON(P) RETURN !* !* ACT(11): ! allocate device UNLESS FIND(P_P1)<0 START IF GDCT_STATE=NOT ALLOCATED START FLAG=0 DEV==RECORD(GDCT_DEVICE ENTRY A) IF GDCT_DEVTYPE=OP START ; ! extra info for OPERs I=GDCT_MECHINDEX>>4 DEV_SER=TABLE(I+32)&X'FFFF'; ! buffer size DEV_X2=DEV_CAA+TABLE(I+32)>>16; ! buffer address DEV_RESP0=GDCT_MECHINDEX&15; ! screens FINISH ELSE IF GDCT_DEVTYPE=LP THEN DEV_SER=GDCT_RESPONSE DEST; ! & LPs GDCT_STATE=READY GDCT_RESPONSE DEST=P_P2 P_P2=LOID+SLOT P_P3=ADDR(DEV) P_P6=GDCT_MNEMONIC FINISH ELSE FLAG=2 FINISH ELSE FLAG=1 ->ACKNOWLEDGE !* ACT(8): ! special forced allocate (CALL not PON) UNLESS FIND(P_P1)<0 START UNLESS P_P1=M'LP' AND GDCT_STATE=DISCONNECTED START FLAG=0 GDCT_STATE=READY GDCT_RESPONSE DEST=P_P2 P_P2=LOID+SLOT P_P3=GDCT_DEVICE ENTRY A P_P6=GDCT_MNEMONIC FINISH ELSE FLAG=2 FINISH ELSE FLAG=1 P_P1=FLAG RETURN ACT(5): ! deallocate UNLESS P_P1=M'LP' START UNLESS FIND(P_P1)<0 START STATE=GDCT_STATE IF STATE=READY OR (SSERIES=YES AND STATE=IDENTIFY FIRED) START IF P_SRCE<<1>>17>63 START ;! from user process IF 0<GDCT_RESPONSE DEST>>16<64 THEN FLAG=4 AND ->FALL; ! prohibit FINISH IF SSERIES=YES AND STATE=IDENTIFY FIRED THEN C STRMQ(GDCT_DSSMM>>24<<8!(GDCT_DSSMM>>8)&255)=ENDLIST; ! clear identify GDCT_STATE=NOT ALLOCATED GDCT_FLAGS=0 P_P3=GDCT_DEVICE ENTRY A FLAG=0 FINISH ELSE FLAG=STATE<<16!3 FINISH ELSE FLAG=2 FINISH ELSE FLAG=1 FALL: ->ACKNOWLEDGE ACT(6): ! clocktick IF SSERIES=YES AND MULTI OCP=YES AND RECOVER DCU1S#0 START ! DCU1 recovery required in controlling OCP *LSS_(3); *USH_-26; *AND_3; *ST_I IF I=COM_OCPPORT0 START I=RECOVER DCU1S RECOVER DCU1S=0 DCU1 RECOVERY(I) OPMESS("DCU1 recovery initiated") FINISH ELSE START P_SRCE=M'STIK' PON(P); ! try for other OCP FINISH RETURN FINISH IF SSERIES=YES AND DCU RFLAG#0 START ! reconnect of DCU1 streams required P_SRCE=0 P_P1=DCU RFLAG DCU RFLAG=0 ->RECON FINISH FOR SLOT=0,1,LASTSLOT CYCLE GDCT==RECORD(GDCT BASE+SLOT*SLOT SIZE) IF GDCT_STATE=REQUEST FIRED OR C (SSERIES=YES AND GDCT_STATE=IDENTIFY FIRED) OR C (SSERIES=NO AND GDCT_STATE=SENSE FIRED) START DEV==RECORD(GDCT_DEVICE ENTRY A) DEV_SECS SINCE=DEV_SECS SINCE+TICK INTERVAL IF DEV_SECS SINCE>DEV_TIMEOUT START CA==RECORD(DEV_CAA) IF SSERIES=YES AND GDCT_UTAD=0 START ! recover any 'dead' DCU1s ISAD=CA_IAWA IF MULTI OCP=YES START *INCT_DCU1 SEMA *JCC_8,<TSEMAG> SEMALOOP(DCU1 SEMA,0) TSEMAG: FINISH FOR I=1,1,COM_INSPERSEC*2 CYCLE ; ! approx 20 millisecs *LB_ISAD; *LSD_0; *L_(0+B ); *STUH_SINK *JAT_4,<TOK> REPEAT ! activate word not cleared so assume DCU1 has died CNO=GDCT_DSSMM>>16&255 IF MULTI OCP=YES START *TDEC_DCU1 SEMA *LSS_(3); *USH_-26; *AND_3; *ST_I UNLESS I=COM_OCPPORT0 START RECOVER DCU1S=CNO; ! recover DCU1 in controlling OCP RETURN FINISH FINISH DCU1 RECOVERY(CNO) OPMESS("DCU1 recovery initiated") RETURN TOK: IF MULTI OCP=YES START ; *TDEC_DCU1 SEMA; FINISH FINISH ELSE IF SSERIES=NO START SLAVESONOFF(0) FOR I=1,1,COM_INSPERSEC*2 CYCLE ; ! 20 msecs J=CA_PAW EXIT IF J=0 REPEAT SLAVESONOFF(-1) UNLESS J=0 START ; ! presume GPC dead PT=GDCT_PTSM>>8&255 CONTROLLER DUMP(3,PT) I=GPC INIT(ADDR(CA),PT,0) IF I=0 THEN WK=" reinitialised" ELSE WK=" reinit fails" OPMESS("GPC ".HTOS(PT,2).WK) CONNECT STREAM(PT,ADDR(CA),-1,1) FINISH FINISH OPMESS(MTOS(GDCT_MNEMONIC)." timed out") !* !* fail transfer(s) !* IF MULTI OCP=YES START IF SSERIES=YES THEN SEMA=ADDR(CA_SEMA) C ELSE SEMA=ADDR(STRM SEMAPHORE(GDCT_PTSM>>24!GDCT_PTSM>>4&15)) *LXN_SEMA; *INCT_(XNB +0); *JCC_8,<TSEMAGOT> SEMALOOP(INTEGER(SEMA),0) TSEMAGOT: FINISH FAIL TRANSFER(GDCT,SLOT) IF SSERIES=YES THEN STRMQ(GDCT_DSSMM>>24<<8!GDCT_DSSMM>>8&255)=ENDLIST C ELSE STRMQ(GDCT_PTSM>>16<<4!GDCT_PTSM>>4&15)=ENDLIST IF GDCT_DEVTYPE=MT START ; ! fail Q'ed MT requests aussi CYCLE I=GDCT_LINK EXIT IF I=ENDLIST GDCT_LINK=ENDLIST GDCT==RECORD(GDCT BASE+I*SLOT SIZE) FAIL TRANSFER(GDCT,I) REPEAT FINISH IF MULTI OCP=YES START ; *LXN_SEMA; *TDEC_(XNB +0); FINISH FINISH FINISH REPEAT RETURN ACT(12): ! execute request SLOT=P_P2&X'FFFF'-LOID IF 0<=SLOT<=LASTSLOT START ; ! valid slot GDCT==RECORD(GDCT BASE+SLOT*SLOT SIZE) IF SSERIES=YES START I=0; *INCT_I; ! clear operand slaves GDCNO=GDCT_DSSMM>>24 STRM=GDCT_DSSMM>>8&255 FINISH ELSE START GDCNO=GDCT_PTSM>>16 PT=GDCT_PTSM>>8&255 STRM=GDCT_PTSM>>4&15 PAW FN=(P_P3&X'F0')<<20!STRM USAW0=(P_P3&15)<<28!RCB BOUND FINISH DEV==RECORD(GDCT_DEVICE ENTRY A) UCCBA=P_P1 IF SSERIES=YES START IF GDCT_UTAD=0 AND (UCCBA&7#0 OR UCCBA>>18#DEV_UA AD>>18) START FLAG=M'BTCB' P_P3=UCCBA ->ACKNOWLEDGE ! bad TCBs can cause havoc !!! FINISH FINISH ELSE START DEV_IDENT=P_P4; ! returned on chain termination P_P6=P_P4; ! used by TCSS (only?) ! if "S" series TCSS appears then DEV format will have to expand FINISH CA==RECORD(DEV_CAA) IF MULTI OCP=YES START IF SSERIES=YES THEN SEMA=ADDR(CA_SEMA) ELSE C SEMA=ADDR(STRM SEMAPHORE(GDCNO<<4!STRM)) *LXN_SEMA; *INCT_(XNB +0); *JCC_8,<SSEMAGOT> SEMALOOP(INTEGER(SEMA),0) SSEMAGOT: FINISH IF GDCT_STATE=READY START IF SSERIES=YES THEN QHD==STRMQ(GDCNO<<8!STRM) ELSE C QHD==STRMQ(GDCNO<<4!STRM) IF QHD=ENDLIST START ; ! ok to fire I/O GDCT_LINK=ENDLIST QHD=SLOT GDCT_STATE=REQUEST FIRED IF MULTI OCP=YES START ; *LXN_SEMA; *TDEC_(XNB +0); FINISH IF SSERIES=YES START IF GDCT_UTAD=0 THEN ACTIVATE(X'01000000'!STRM,UCCBA,CA_IAWA) C ELSE FIRE DCU2(GDCT_UTAD,UCCBA,START STREAM) FINISH ELSE START STREAM==CA_STREAM(STRM) *LXN_CA+4; *INCT_(XNB +0); *JCC_8,<CAAG> SEMALOOP(CA_MARK,2) CAAG: IF CA_PAW#0 THEN CA_MARK=-1 AND PAW WAIT(CA) CA_PAW=PAW FN STREAM_SAW0=USAW0 STREAM_SAW1=UCCBA CA_MARK=-1 I=X'40000800'!PT<<16 *LB_I; *LSS_1; *ST_(0+B ) FINISH FINISH ELSE IF GDCT_DEVTYPE=MT START I=QHD; ! Q MT request UNTIL I=ENDLIST CYCLE GE==RECORD(GDCT BASE+I*SLOTSIZE) I=GE_LINK REPEAT GDCT_LINK=ENDLIST GE_LINK=SLOT GDCT_STATE=QUEUED IF MULTI OCP=YES START ; *LXN_SEMA; *TDEC_(XNB +0); FINISH FINISH ELSE ->STRM BUSY IF SSERIES=YES START FINISH ELSE START IF P_P3&X'100'=0 THEN GDCT_FLAGS=0 ELSE C GDCT_FLAGS=GET STRM DATA DEV_USAW0=USAW0 DEV_PAW=PAW FN DEV_RESP1=0 FINISH DEV_UCCBA=UCCBA DEV_SECS SINCE=0 P_P1=0 ->OUT FINISH ELSE START IF SSERIES=YES AND GDCT_STATE=IDENTIFY FIRED AND GDCT_Q=0 START !* Q request 'till identify terminates I=NEW PP CELL GDCT_Q=I QACT==PARM(I) IF GDCT_UTAD=0 START QACT_ACTWD=X'01000000'!STRM QACT_ISAD=CA_IAWA FINISH ELSE QACT_ACTWD=GDCT_UTAD QACT_TCBAD=UCCBA QACT_P2=M'IDWT' P_P1=0 IF MULTI OCP=YES START ; *LXN_SEMA; *TDEC_(XNB +0); FINISH ->OUT FINISH STRM BUSY: IF MULTI OCP=YES START ; *LXN_SEMA; *TDEC_(XNB +0); FINISH FLAG=2 P_P3=ADDR(DEV) P_P6=P_P4 FINISH FINISH ELSE FLAG=1 ->ACKNOWLEDGE !* !* !* ACT(3): ! interrupt IF SSERIES=YES START *INCT_I; ! clear operand slaves INTWD=P_P1 STRM=INTWD&255 CNO=INTWD>>24&15 GDCNO=CNO TO GDC(CNO-LOCNO) IF INTWD&PRIMITIVE#0 START ; ! DCU gone primitive (or similar) PKMONREC("DCU gone primitive!",P) !* dump DCU ? IF MULTI OCP=YES THEN RECOVER DCU1S=CNO ELSE START DCU1 RECOVERY(CNO) OPMESS("DCU1 recovery initiated") FINISH ->OUT FINISH UNLESS CONNECT TERM#INTWD&STREAM CTERM#DISCONNECT TERM START ! i.e if INTWD&CTERM = CONNECT or DISCONNECT PKMONREC("DCU control term",P) IF INTWD&DISCONNECT TERM=DISCONNECT TERM START ! DCU1s only (DCU2s give a simulated connect term) CAA=CAAS(GDCNO) CA==RECORD(CAA) ACTIVATE(X'03000000'!STRM,0,CA_IAWA); ! reconnect FINISH ->OUT FINISH QHD==STRMQ(GDCNO<<8!STRM) IF INTWD&STREAM ITA=STREAM IA START ! attention & no TCB termination SLOT=CSTRM TO SLOT((CNO-LOCNO)<<8!STRM) IF SLOT=ENDLIST THEN ->SURPRISE GDCT==RECORD(GDCT BASE+SLOT*SLOT SIZE) DEV==RECORD(GDCT_DEVICE ENTRY A) IF MULTI OCP=YES START CA==RECORD(DEV_CAA) SEMA=ADDR(CA_SEMA) *LXN_SEMA; *INCT_(XNB +0); *JCC_8,<ASEMAGOT> SEMALOOP(INTEGER(SEMA),0) ASEMAGOT: FINISH TRYNMT: IF GDCT_STATE=READY START IF QHD=ENDLIST START FIRE IDENTIFY QHD=SLOT FINISH ELSE START ; ! MT request on another slot GDCT==RECORD(GDCT BASE+QHD*SLOT SIZE) GDCT_ATTN=1 FINISH FINISH ELSE START IF GDCT_STATE=NOT ALLOCATED OR GDCT_STATE=DISCONNECTED START IF GDCT_DEVTYPE=MT START ! must be careful not to lose an attention when ! 1st n decks of a cluster are not allocated etc. SLOT=SLOT+1 IF SLOT<=LASTSLOT START GDCT==RECORD(GDCT BASE+SLOT*SLOTSIZE) DEV==RECORD(GDCT_DEVICE ENTRY A) IF GDCT_DSSMM>>24=GDCNO AND C GDCT_DSSMM>>8&255=STRM THEN ->TRYNMT; ! next deck FINISH FINISH UNLESS GDCT_DEVTYPE=FE START ! dont report spurious FE attentions lest FE in a twist ! & we thus swamp the mainlog BYTEINTEGER(ADDR(P_P3))=GDCT_STATE PKMONREC("DCU attention?:",P) FINISH FINISH ELSE GDCT_ATTN=1; ! identify on termination FINISH IF MULTI OCP=YES START ; *LXN_SEMA; *TDEC_(XNB +0); FINISH ->OUT FINISH SLOT=QHD IF SLOT=ENDLIST THEN ->SURPRISE GDCT==RECORD(GDCT BASE+SLOT*SLOT SIZE) DEV==RECORD(GDCT_DEVICE ENTRY A) IF GDCT_STATE=IDENTIFY FIRED THEN CCB==RECORD(DEV_MYCCBA) ELSE C CCB==RECORD(DEV_UCCBA) WHILE CCB_RESP&TCB CONT#0 CYCLE ; ! find 'stopped' TCB CCB==RECORD(CCB_NTCB) REPEAT IF GDCT_STATE=REQUEST FIRED START IF INTWD&INVALID ACTIVATE#0 START PKMONREC("DCU1 invalid act:",P) RESP0=CONTROLLER DETECTED ERROR RESP1=INTWD INTWD=0 DEV_LAST TCB ADDR=ADDR(CCB) FINISH ELSE START IF CCB_RESP&TCB ATTN#0 THEN GDCT_ATTN=1 ! the above is for DCU2s - is there a better way? RESP0=CCB_RESP>>24<<8; ! primary status RESP1=CCB_RESP&X'FFFF'; ! RBC IF INTWD&STREAM ABTERM=0 START RESP0=RESP0!NORMAL TERMINATION FINISH ELSE START IF DEV_LOGMASK>>8#0 START PRINTSTRING("DT: ".DATE." ".TIME. C " DCU--Abnormal termination - ". C MTOS(GDCT_MNEMONIC)."(".HTOS(GDCT_DSSMM>>8&255,3). C ") TCB RESP = ".HTOS(CCB_RESP,8)." ") DUMPTABLE(0,DEV_UCCBA,14*4*2) FINISH DEV_LAST TCB ADDR=ADDR(CCB) RESP0=RESP0!(CCB_RESP&INIT FAIL)>>4!ABNORMAL TERMINATION ! primary status + init fail + abterm RESP0=RESP0!(((ADDR(CCB)-DEV_UCCBA)//TCB LENGTH)&255) ! failing TCB Q_P4=(CCB_COMMAND&POST AMBLE VALID)>>7!!(CCB_RESP&SENSE FAIL)>>13 ! X'80' if succesful sense done by DCU ! tho' not for discs?? IF Q_P4#0 THEN DEV_SENSDAT AD=ADDR(CCB_POSTAMBLE(0)) FINISH FINISH FINISH ELSE IF GDCT_STATE=IDENTIFY FIRED START IF INTWD&INVALID ACTIVATE#0 OR CCB_RESP&TCB FAIL#0 START PRINTSTRING("DCU identify fails - parm = ".HTOS(INTWD,8). C " TCB_RESP = ".HTOS(CCB_RESP,8)." ") INTWD=0; ! 'lest identify loop ->MORE REQUESTS FINISH ELSE START IF GDCT_DEVTYPE=MT AND DEV_MECH&7#GDCT_DSSMM&7 START I=MECHSLOTS(GDCT_MECHINDEX+DEV_MECH&7) GE==RECORD(GDCT BASE+I*SLOT SIZE) UNLESS GE_STATE=NOT ALLOCATED OR GE_STATE=DISCONNECTED START ! allocated decks only Q_DEST=GE_RESPONSE DEST Q_SRCE=GDC DEST!3 Q_P1=(I+LOID)<<24!ATTENTION!DEV_ATTN<<8 Q_P2=0 Q_P3=GE_DEVICE ENTRY A PON(Q) FINISH ->MORE REQUESTS FINISH RESP0=ATTENTION!DEV_ATTN<<8 RESP1=0 FINISH FINISH ELSE ->SURPRISE FINISH ELSE START PT=P_P1 GDCNO=CNO TO GDC(PT-LOCNO) CAA=CAAS(GDCNO) CA==RECORD(CAA) *LXN_CAA *INCT_(XNB +0) *JCC_8,<CGOT1> SEMALOOP(INTEGER(CAA),2) CGOT1: PIW0=CA_PIW0 CA_PIW0=0 CA_MARK=-1 MORE INTS: *LSS_PIW0 *JAT_4,<OUT>; ! no (more) interrupts *SHZ_STRM PIW0=PIW0!!X'80000000'>>STRM STREAM==CA_STREAM(STRM) *LXN_CAA *INCT_(XNB +0) *JCC_8,<CGOT2> SEMALOOP(INTEGER(CAA),2) CGOT2: RESP0=STREAM_RESP0 RESP1=STREAM_RESP1 STREAM_RESP0=0 STREAM_RESP1=0 CA_MARK=-1 IF RESP0&ATTENTION#0 START SLOT=CSTRM TO SLOT((PT-LOCNO)<<4!STRM) IF SLOT=ENDLIST THEN ->SURPRISE GDCT==RECORD(GDCT BASE+SLOT*SLOT SIZE) IF GDCT_DEVTYPE=MT START SLOT=MECHSLOTS(GDCT_MECHINDEX+RESP0>>24&15) GDCT==RECORD(GDCT BASE+SLOT*SLOT SIZE) FINISH IF GDCT_STATE=NOT ALLOCATED THEN ->SURPRISE IF SSERIES=NO THEN DEV==RECORD(GDCT_DEVICE ENTRY A); ! for _IDENT ->RESPOND FINISH ELSE SLOT=STRMQ(GDCNO<<4!STRM) IF SLOT=ENDLIST THEN ->SURPRISE GDCT==RECORD(GDCT BASE+SLOT*SLOT SIZE) DEV==RECORD(GDCT_DEVICE ENTRY A) IF GDCT_STATE=REQUEST FIRED START DEV_RESP0=RESP0 DEV_RESP1=RESP1 IF RESP0&ABNORMAL TERMINATION#0 AND GDCT_RESPONSE DEST>>16<65 START IF RESP0&X'FF0000'=CONTROLLER DETECTED ERROR OR C DEV_LOGMASK>>8#0 START PRINTSTRING("DT: ".DATE." ".TIME. C " GPC--Abnormal termination - ".MTOS(GDCT_MNEMONIC). C "(".HTOS(PT<<4!STRM,3).") RESP0 = ".HTOS(RESP0,8)." ") J=READ STREAM DATA(PT,STRM,2); ! control stream status J=READ STREAM DATA(PT,STRM,0); ! stream data IF GDCT_DEVTYPE=FE AND RESP0&X'FF0000'=CONTROLLER DETECTED ERROR C THEN CONNECT STREAM(PT,CAA,STRM,1) FINISH IF GDCT_FLAGS&GET STRM DATA#0 START GDCT_CSTATUS=READ STREAM DATA(PT,STRM,1); ! stream's cstatus ->SET SENSE FINISH *LXN_CA+4; *INCT_(XNB +0); *JCC_8,<CAG> SEMALOOP(CA_MARK,2) CAG: IF CA_PAW#0 THEN CA_MARK=-1 AND PAW WAIT(CA) CA_PAW=DO STREAM REQUEST!STRM STREAM_SAW0=X'10000020' STREAM_SAW1=DEV_MYCCBA CA_MARK=-1 I=X'40000800'!PT<<16 *LB_I; *LSS_1; *ST_(0+B ) GDCT_STATE=SENSE FIRED ->MORE INTS FINISH FINISH ELSE IF GDCT_STATE=SENSE FIRED START SET SENSE: IF DEV_LOGMASK&BYTEINTEGER(ADDR(DEV_SENSE1))#0 START IF MULTI OCP=YES THEN RESERVE LOG PRINTSTRING("DT: ".DATE." ".TIME." GPC--device entry after sense:") DUMPTABLE(0,ADDR(DEV),DEV_DEVICE ENTRY S) IF MULTI OCP=YES THEN RELEASE LOG FINISH Q_P4=RESP0>>16 Q_P5=GDCT_CSTATUS RESP0=DEV_RESP0 RESP1=DEV_RESP1 FINISH ELSE ->SURPRISE FINISH RESPOND: ! tell allocatee Q_DEST=GDCT_RESPONSE DEST Q_SRCE=GDC DEST!3 Q_P1=RESP0 BYTEINTEGER(ADDR(Q_P1))=SLOT+LOID Q_P2=RESP1 Q_P3=GDCT_DEVICE ENTRY A IF SSERIES=NO THEN Q_P6=DEV_IDENT; ! not "S" protem - see ACT(12) PON(Q) IF SSERIES=NO AND RESP0&ATTENTION#0 THEN ->MORE INTS !* MORE REQUESTS: IF MULTI OCP=YES START IF SSERIES=YES THEN CA==RECORD(DEV_CAA) AND SEMA=ADDR(CA_SEMA) ELSE C SEMA=ADDR(STRM SEMAPHORE(GDCNO<<4!STRM)) *LXN_SEMA; *INCT_(XNB +0); *JCC_8,<SSEMAG> SEMALOOP(INTEGER(SEMA),0) SSEMAG: FINISH IF SSERIES=YES AND GDCT_Q#0 START ; ! fire waiting I/O I=GDCT_Q GDCT_Q=0 QACT==PARM(I) GDCT_STATE=REQUEST FIRED IF MULTI OCP=YES START ; *LXN_SEMA; *TDEC_(XNB +0); FINISH DEV_SECS SINCE=0 DEV_UCCBA=QACT_TCBAD IF GDCT_UTAD=0 THEN ACTIVATE(QACT_ACTWD,QACT_TCBAD,QACT_ISAD) C ELSE FIRE DCU2(QACT_ACTWD,QACT_TCBAD,START STREAM) RETURN PP CELL(I) ->OUT FINISH IF SSERIES=YES AND (INTWD&STREAM ATTENTION#0 OR GDCT_ATTN#0) START FIRE IDENTIFY IF MULTI OCP=YES START ; *LXN_SEMA; *TDEC_(XNB +0); FINISH ->OUT FINISH GDCT_STATE=READY IF SSERIES=NO THEN QHD==STRMQ(GDCNO<<4!STRM); ! already mapped for S series UNLESS GDCT_DEVTYPE=MT START QHD=ENDLIST IF MULTI OCP=YES START ; *LXN_SEMA; *TDEC_(XNB +0); FINISH IF SSERIES=YES THEN ->OUT ELSE ->MORE INTS FINISH QHD=GDCT_LINK GDCT_LINK=ENDLIST IF QHD#ENDLIST START ; ! request to go SLOT=QHD GDCT==RECORD(GDCT BASE+SLOT*SLOT SIZE) DEV==RECORD(GDCT_DEVICE ENTRY A) CA==RECORD(DEV_CAA) GDCT_STATE=REQUEST FIRED IF MULTI OCP=YES START ; *LXN_SEMA; *TDEC_(XNB +0); FINISH IF SSERIES=YES START IF GDCT_UTAD=0 THEN ACTIVATE(X'01000000'!STRM,DEV_UCCBA,CA_IAWA) C ELSE FIRE DCU2(GDCT_UTAD,DEV_UCCBA,START STREAM) FINISH ELSE START STREAM==CA_STREAM(STRM) *LXN_CA+4; *INCT_(XNB +0); *JCC_8,<CAAGOT>; SEMALOOP(CA_MARK,2) CAAGOT: IF CA_PAW#0 THEN CA_MARK=-1 AND PAW WAIT(CA) CA_PAW=DEV_PAW STREAM_SAW0=DEV_USAW0 STREAM_SAW1=DEV_UCCBA CA_MARK=-1 I=X'40000800'!PT<<16 *LB_I; *LSS_1; *ST_(0+B ) FINISH FINISH ELSE IF MULTI OCP=YES START ; *LXN_SEMA; *TDEC_(XNB +0); FINISH IF SSERIES=YES THEN ->OUT ELSE ->MORE INTS !* SURPRISE: ! unexpexted interrupt IF SSERIES=YES START PRINTSTRING("DT: ".DATE." ".TIME. C " DCU--Surprise interrupt - parm = ".HTOS(INTWD,8)." ".HTOS(P_P2,8)." ") ->OUT FINISH ELSE START PRINTSTRING("DT: ".DATE." ".TIME. C " GPC--Surprise interrupt on ".HTOS(PT<<4!STRM,3)."/".HTOS(RESP0,8)." ") ->MORE INTS FINISH RETURN !* IF SSERIES=YES START ACT(10):RECON: ! reconnect streams ! P_P1 = DCU1 H/W no. or -1 for all DCU1s FOR SLOT=0,1,LASTSLOT CYCLE GDCT==RECORD(GDCT BASE+SLOT*SLOTSIZE) IF GDCT_UTAD=0 AND (P_P1=-1 OR GDCT_DSSMM>>16&255=P_P1) START CONTINUE IF GDCT_DEVTYPE=ZX CONTINUE IF GDCT_DEVTYPE=MT AND GDCT_DSSMM&15>0 DEV==RECORD(GDCT_DEVICE ENTRY A) CA==RECORD(DEV_CAA) ACTIVATE(X'03000000'!GDCT_DSSMM>>8&255,0,CA_IAWA) WAIT(10) FINISH REPEAT ->ACK1 FINISH ELSE START ACT(7): ! entry from reconfigure routine ! P_P1=IDENT,P_P2=SAC I=P_P2 P_P2=0 FOR SLOT=0,1,LASTSLOT CYCLE GDCT==RECORD(GDCT BASE+SLOT*SLOTSIZE) IF GDCT_PTSM>>12&15=I AND GDCT_STATE&15#DISCONNECTED START ; ! SAC in use P_P2=3<<24!GDCT_MNEMONIC EXIT FINISH REPEAT ->ACK1 ACT(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 GDCT==RECORD(GDCT BASE+SLOT*SLOT SIZE) PT=GDCT_PTSM>>8&255 IF PT=P_P1 START DEV==RECORD(GDCT_DEVICE ENTRY A) CCB==RECORD(DEV_MYCCBA) STRM=GDCT_PTSM>>4&15 CA==RECORD(DEV_CAA) STREAM==CA_STREAM(STRM) IF GDCT_DEVTYPE=MT START CCB_LIM FLAGS=X'C000' I=CCB_INIT&X'FF' I=3 IF I=0 CCB_INIT=MECH<<24!I FINISH ELSE CCB_LIM FLAGS=PRIV ONLY INTEGER(CCB_LBA)=X'80F01800' LONGINTEGER(CCB_ALA)=X'5800000481000000' CCB_LBS=4 CCB_ALS=8 *LXN_CA+4; *INCT_(XNB +0); *JCC_8,<GOT1> SEMALOOP(CA_MARK,2) GOT1: CA_PAW=DO STREAM REQUEST!STRM CA_PIW0=0 STREAM_SAW0=3<<28!RCB BOUND STREAM_SAW1=ADDR(CCB) STREAM_RESP0=0 STREAM_RESP1=0 CA_MARK=-1 I=X'40000800'!PT<<16 *LB_I; *LSS_1; *ST_(0+B ) WAIT(10) FINISH REPEAT WAIT(100) ->ACK1 ACT(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 0<=PT<=X'1F' AND BYTEINTEGER(COM_CONTYPEA+PT)=3 START I=GPC INIT(CAAS(CNO TO GDC(PT-LOCNO)),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 FINISH !* ACT(*): IF SSERIES=YES THEN PKMONREC("DCU bad DACT:",P) ELSE PKMONREC("GPC bad DACT:",P) RETURN !* ACKNOWLEDGE: P_P1=FLAG ACK1: IF P_SRCE>0 START ; ! PON reply P_DEST=P_SRCE P_SRCE=GDC DEST!DACT PON(P) FINISH OUT: IF SSERIES=YES AND QHEAD#0 START IF MULTI OCP=YES START *INCT_DCU1SEMA *JCC_8,<DCU1SEMAGOT> SEMALOOP(DCU1 SEMA,0) DCU1SEMAGOT: FINISH WHILE QHEAD#0 CYCLE QACT==PARM(QHEAD) L=LENGTHENI(QACT_TCBAD)<<32!QACT_ACTWD ISAD=QACT_ISAD FOR I=1,1,COM_INSPERSEC CYCLE *LB_ISAD; *LSD_0; *L_(0+B ); *STUH_SINK *JAT_4,<OK> REPEAT ->NOTOK OK: *LSD_L; *ST_(0+B ) I=QHEAD QHEAD=QACT_LINK RETURN PP CELL(I) REPEAT NOTOK: IF MULTI OCP=YES START ; *TDEC_DCU1SEMA; FINISH FINISH RETURN !* ACT(1): ! command (CDS etc) SRCE=P_SRCE<<1>>1 TEXT=P_TEXT IF SSERIES=YES AND TEXT="DIAGS" START REPLY(SRCE,"DCU ACTs Q'd = ".STRINT(ACTS QD)) REPLY(SRCE,"DCU ACT cycs = ".STRINT(ACT CYCLES)) REPLY(SRCE,"DCU max Q'd = ".STRINT(MAX Q)) RETURN FINISH IF TEXT="?" THEN ->GC4 FOR J=1,1,LIMIT CYCLE IF TEXT->(COMMAND(J)).TEXT THEN ->FOUND REPEAT ERR: IF SSERIES=YES THEN REPLY(SRCE,"DCU ??".P_TEXT) ELSE C REPLY(SRCE,"GPC ??".P_TEXT) RETURN FOUND: ! QS,CDS or CDM UNLESS TEXT->MNEMOS.(" ").TEXT START ->ERR UNLESS J=1; ! must be QS MNEMOS<-TEXT FINISH MNEMONIC=TRANS MNEMONIC(MNEMOS); ! to integer IF FIND(MNEMONIC)<0 THEN ->ERR; ! not found DEV==RECORD(GDCT_DEVICE ENTRY A) ->GDC COMMAND(J) GDC COMMAND(1): ! QS dev PRSTATUS: STATUS(SLOT) RETURN GDC COMMAND(2): ! CDS dev ON/OFF LENGTH(TEXT)=LENGTH(TEXT)-1 WHILE CHARNO(TEXT,LENGTH(TEXT))=' ' STATE=GDCT_STATE&15 IF TEXT="OFF" START IF STATE CHECK(MNEMONIC,STATE)=OK START IF SSERIES=YES START ! disconnect DCU1 stream ! (but note that stream is reconnected on disconnect term.) ! no disconnect on DCU2, stream is reset by CDS ON etc. IF GDCT_UTAD=0 START CA==RECORD(DEV_CAA) ACTIVATE(X'02000000'!GDCT_DSSMM>>8&255,0,CA_IAWA) FINISH FINISH ELSE CONNECT STREAM(GDCT_PTSM>>8&255,DEV_CAA,GDCT_PTSM>>4&15,0) IF MNEMONIC>>16=M'M' START ; ! MT cluster I=GDCT BASE FOR J=0,1,LASTSLOT CYCLE GDCT==RECORD(I) IF GDCT_MNEMONIC&MNMASK=MNEMONIC THEN GDCT_STATE=STATE<<4!DISCONNECTED I=I+SLOT SIZE REPEAT FINISH ELSE GDCT_STATE=STATE<<4!DISCONNECTED FINISH ->PRSTATUS FINISH IF TEXT="ON" START IF STATE=DISCONNECTED THEN ->CDS ON ->PRSTATUS FINISH ->ERR GDC COMMAND(3): ! CDM dev1 dev2 MNEMONIC1=MNEMONIC MNEMONIC2=TRANS MNEMONIC(TEXT) J=SLOT; ! save 1st slot UNLESS FIND(MNEMONIC2)<0 THEN ->ERR; ! already exists SLOT=J GDCT==RECORD(GDCT BASE+SLOT*SLOTSIZE); ! 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: GDCT_MNEMONIC=MNEMONIC2 GDCT_DEVTYPE=CDMDEVTYPE(J) DEV_MNEMONIC=MNEMONIC2 IF CDMDEVTYPE(J)=LP START DEV_UA SIZE=DEV_UA SIZE-256; ! TRTAB space DEV_TRTAB AD=DEV_UA AD+DEV_UA SIZE FINISH DEV_TIMEOUT=CDMDEVTIMEOUT(J)&X'FFFF' DEV_LOGMASK=CDMDEVTIMEOUT(J)>>16 IF CDMDEVTYPE(J)=FE THEN COM_FEPS=COM_FEPS!1<<(16+MNEMONIC2&15) ! FEP map FINISH ELSE START ; ! take out device UNLESS MNEMONIC2>>8=M'ZX' THEN ->ERR UNLESS GDCT_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+MNEMONIC1&15))) IF CDMDEVTYPE(J)=LP START DEV_UA SIZE=DEV_UA SIZE+256; ! recover TRTAB space DEV_TRTAB AD=0 FINISH GDCT_MNEMONIC=MNEMONIC2 GDCT_DEVTYPE=ZX FINISH ->PRSTATUS GC4: ! ? FOR SLOT=0,1,LASTSLOT CYCLE STATUS(SLOT) REPEAT RETURN !* CDS ON: BEGIN IF SSERIES=YES START ; ! only on same DSS protem CA==RECORD(DEV_CAA) STRM=GDCT_DSSMM>>8&255 IF GDCT_UTAD=0 THEN ACTIVATE(X'03000000'!STRM,0,CA_IAWA) C ELSE FIRE DCU2(GDCT_UTAD,0,RESET STREAM) WAIT(10) IF GDCT_DEVTYPE=FE START ; ! FEP needs send propcodes to wake it up CCB==RECORD(DEV_MYCCBA) CCB_COMMAND=X'2F40400E'; ! send propcodes CCB_RESP=0 IF GDCT_UTAD=0 START ; ! DCU1 L=LENGTHENI(ADDR(CCB))<<32!X'01000000'!STRM J=CA_IAWA FOR I=1,1,COM_INSPERSEC CYCLE *LB_J; *LSD_0; *L_(0+B ); *STUH_SINK *JAT_4,<CDSOK> REPEAT ->RESET CCB; ! fire fails so report not found CDSOK: *LSD_L; *ST_(0+B ) FINISH ELSE START ; ! DCU2 FIRE DCU2(GDCT_UTAD,ADDR(CCB),START STREAM) FINISH SLAVES ON OFF(0); ! slaves off FOR I=1,1,COM_INSPERSEC*20 CYCLE EXIT IF CCB_RESP#0 REPEAT SLAVES ON OFF(-1); ! back on RESETCCB: CCB_COMMAND=X'2F00400A'; ! identify IF CCB_RESP=0 START REPLY(SRCE,"DCU: ".MTOS(MNEMONIC)." not found") ->RETURN FINISH FINISH GDCT_STATE=GDCT_STATE>>4 OPMESS("DCU: ".MTOS(MNEMONIC)." now on DSS ".HTOS(GDCT_DSSMM>>8,3)) RETURN: FINISH ELSE START INTEGERFNSPEC FIND BYTE(INTEGER BYTE,ADDR,LEN) RECORD (ALEF)ARRAYFORMAT ALEFF(0:3) RECORD (ALEF)ARRAYNAME XALE RECORD (CCB)NAME XCCB RECORD (CAF)NAME XCA RECORD (CASEF)NAME XSTREAM OWNINTEGERARRAY XLBE(0:7)=C X'00F10900',X'04F10800',X'04F00E00',X'00F00402', X'80F02504',X'80F00106',X'82F00500',X'80F00106' OWNINTEGERARRAY X(0:117)=0(*); ! needs to be %OWN for I/O (stack not 'fixed'!) SWITCH CDS(0:7) INTEGER XPT,XGPTSM,XPTS INTEGER XSTRM,XA,XSLOT,XMNEMONIC,XDEVTYPE,XGDC,XCAA,XSTATE,XSRCE INTEGER XCOUNT,XCART,XSTYLE,XLEN,XS XA=ADDR(X(0)); ! set up CCB etc. XCCB==RECORD(XA) XCCB_LIMFLAGS=X'4000'; ! trusted chain XCCB_LSTA=0 XCCB_LB S=32 XCCB_AL S=32 XCCB_AL A=XA+32 XALE==ARRAY(XCCB_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 ! remember what we're looking for! XSRCE=SRCE XSLOT=SLOT XMNEMONIC=MNEMONIC XDEVTYPE=GDCT_DEVTYPE XPTS=GDCT_PTSM>>4&X'FFF' XGDC=0 GLOOP: XPT=TABLE(16+XGDC) 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+XGDC) XCA==RECORD(XCAA) XSTRM=0 SLOOP: XSTATE=-1; ! nothing fired SLOT=CSTRM TO SLOT((XPT-LOCNO)<<4!XSTRM) IF SLOT=255 THEN ->CONNECT GDCT==RECORD(GDCT BASE+SLOT*SLOTSIZE) UNLESS GDCT_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 XSTREAM==XCA_STREAM(XSTRM) X(16)=0 XSTATE=1; ! connect XCOUNT=0; ! connect tries ->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 ELSE IF XCOUNT=0 START ; ! 1st connect always fails for EMLAN feps!! WAIT(10) XCOUNT=1 ->XFIRE FINISH ! response from disconnect CDS(0): SKIP: UNLESS XSTRM=14 THEN XSTRM=XSTRM+1 AND ->SLOOP SKIPG: UNLESS XGDC=NO OF GDCS-1 THEN XGDC=XGDC+1 AND ->GLOOP REPLY(XSRCE,"GPC: ".MTOS(XMNEMONIC)." not found") ->RETURN XFOUND: REPLY(XSRCE,"GPC: ".MTOS(XMNEMONIC)." now on pts ".HTOS( C XPT<<4!XSTRM,3)) CSTRM TO SLOT(XPTS-(LOCNO<<4))=255 CSTRM TO SLOT((XPT-LOCNO)<<4!XSTRM)=XSLOT XGPTSM=(XGDC<<16)!(XPT<<8)!(XSTRM<<4) FOR SLOT=0,1,LASTSLOT CYCLE GDCT==RECORD(GDCT BASE+SLOT*SLOTSIZE) IF (GDCT_PTSM>>4)&X'FFF'=XPTS START ! move everything on this PTS DEV==RECORD(GDCT_DEVICE ENTRY A) DEV_GPTSM=XGPTSM!(DEV_GPTSM&15) GDCT_PTSM=DEV_GPTSM DEV_CAA=XCAA GDCT_STATE=GDCT_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(DEV_TRTAB AD,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 ! 3 we load the 384-char rep for the Bush estate 2980 ! 4 we load the 64-char rep ! 5 we load the 96-char rep for the ERCC-KB 2972s 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)=LP ILLCHAR; ! back '?' for ERCC, autothrow not set XSTATE=5; ! initialise outwards ->XFIRE CDS(5): ! resp from init IF XCART=0 AND X(17)&X'100000'=0 THEN ->CDS4 XSTATE=4; ! loadrep outwards ->XFIRE CDS(4):CDS4: ! 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):XOUT: ! resp from write control ->RETURN XFIRE: ! needs XCAA, XSENT, XPT, XSTRM setting up outside ! uses XSTATE to select required command IF XCA_PAW#0 START PRINTSTRING("DT: ".DATE." ".TIME. C " GPC--PAW not cleared - PT".HTOS(XPT,2).",PAW = ".HTOS(XCA_PAW,8)." ") CONTROLLER DUMP(3,XPT) ->SKIPG; ! give up on this GPC FINISH XCCB_LBA=ADDR(XLBE(XSTATE)) SLAVES ON OFF(0); ! slaves off *LXN_XCAA *INCT_(XNB +0) *JCC_8,<XGOT> SEMALOOP(INTEGER(XCAA),2) XGOT: XCA_PAW=DO STREAM REQUEST!XSTRM XSTREAM_SAW0=X'30000020' XSTREAM_SAW1=ADDR(XCCB) XSTREAM_RESP0=0 XCA_MARK=-1 I=X'40000800'!XPT<<16 *LB_I; *LSS_1; *ST_(0+B ) FOR I=1,1,COM_INSPERSEC*150 CYCLE ; ! wait about 1 sec EXIT IF XSTREAM_RESP0#0 REPEAT XCA_PIW0=XCA_PIW0&(¬(X'80000000'>>XSTRM));! no surprise ints. XSTREAM_RESP0=0 SLAVES ON OFF(-1); ! back on ->CDS(XSTATE); ! process response RETURN: INTEGERFN FIND BYTE(INTEGER BYTE,ADDR,LEN) INTEGER I FOR I=0,1,LEN-1 CYCLE IF BYTE=BYTEINTEGER(ADDR+I) THEN RESULT =I REPEAT RESULT =-1 END FINISH END !* !* ROUTINE FAIL TRANSFER(RECORD (GDCTF)NAME GDCT,INTEGER SLOT) ! CA already mapped RECORD (PARMF) Q INTEGER I IF SSERIES=NO START INTEGER PT,STREAM FINISH IF SSERIES=NO OR (SSERIES=YES AND (GDCT_STATE=REQUEST FIRED OR C GDCT_STATE=QUEUED OR GDCT_Q#0)) START Q_DEST=GDCT_RESPONSE DEST Q_SRCE=GDC DEST!6 Q_P1=ABNORMAL TERMINATION BYTEINTEGER(ADDR(Q_P1))=SLOT+LOID Q_P2=-1; ! timeout Q_P3=GDCT_DEVICE ENTRY A PON(Q) FINISH IF SSERIES=YES THEN GDCT_Q=0 UNLESS GDCT_STATE=QUEUED START IF SSERIES=YES START IF GDCT_UTAD#0 THEN FIRE DCU2(GDCT_UTAD,0,RESET STREAM) C ELSE ACTIVATE(X'02000000'!GDCT_DSSMM>>8&255,0,CA_IAWA) FINISH ELSE START if multi ocp=yes then gdct_state=timed out ! to prevent ints. from stop/connect stream being passed on ! to adaptors if grabbed by the other OCP PT=GDCT_PTSM>>8&255 STREAM=GDCT_PTSM>>4&15 *LXN_CA+4; *INCT_(XNB +0); *JCC_8,<CSEMAG> SEMALOOP(CA_MARK,2) CSEMAG: IF CA_PAW#0 THEN CA_MARK=-1 AND PAW WAIT(CA) CA_PAW=3<<24!STREAM CA_MARK=-1 I=X'40000800'!PT<<16 *LB_I; *LSS_1; *ST_(0+B ) WAIT(10) CONNECT STREAM(PT,ADDR(CA),STREAM,1) FINISH FINISH GDCT_STATE=READY END !* INTEGERFN FIND(INTEGER DEV) INTEGER PTR AGN: PTR=GDCT BASE FOR SLOT=0,1,LAST SLOT CYCLE GDCT==RECORD(PTR) IF DEV=LOID+SLOT OR DEV=GDCT_MNEMONIC C OR (SSERIES=YES AND DEV=GDCT_DSSMM&X'FFFFF') OR C (SSERIES=NO AND DEV=GDCT_PTSM&X'FFFF') C OR (DEV=M'LP' AND GDCT_MNEMONIC>>8=M'LP' C AND GDCT_PROPS03&X'80'=0 AND GDCT_STATE=NOT ALLOCATED) C THEN RESULT =0 PTR=PTR+SLOT SIZE REPEAT IF DEV=M'LP' THEN DEV=M'LP0' AND ->AGN RESULT =-1 END !* STRING (4)FN MTOS(INTEGER M) INTEGER I,J IF M>>24=0 THEN J=M<<8!X'20' ELSE J=M IF SSERIES=YES THEN I=4 ELSE I=3 RESULT =STRING(ADDR(I)+3) END !* ROUTINE REPLY(INTEGER SRCE,STRING (30)TEXT) RECORD (PARMF) Q Q=0 Q_DEST=SRCE Q_TEXT<-TEXT PON(Q) END !* INTEGERFN STATE CHECK(INTEGER MNEMONIC,STATE) RECORD (GDCT)NAME G INTEGER I,PTR IF MNEMONIC>>16=M'M' START ; ! check whole cluster UNLESS MNEMONIC&255=M'0' START IF SSERIES=YES THEN REPLY(SRCE,"DCU: must be MN0") ELSE C REPLY(SRCE,"GPC: must be MN0") RESULT =1 FINISH PTR=GDCT BASE FOR I=0,1,LAST SLOT CYCLE G==RECORD(PTR) IF G_MNEMONIC&MNMASK=MNEMONIC START UNLESS G_STATE=NOT ALLOCATED START IF SSERIES=YES THEN REPLY(SRCE,"DCU: ".MTOS(G_MNEMONIC)." state?") C ELSE REPLY(SRCE,"GPC: ".MTOS(G_MNEMONIC)." state?") RESULT =1 FINISH FINISH PTR=PTR+SLOT SIZE REPEAT RESULT =0 FINISH RESULT =0 IF STATE=NOT ALLOCATED OR (STATE=READY AND MNEMONIC&MNMASK=M'OP0') IF SSERIES=YES THEN REPLY(SRCE,"DCU: ".MTOS(MNEMONIC)." state?") C ELSE REPLY(SRCE,"GPC: ".MTOS(MNEMONIC)." state?") RESULT =1 END !* ROUTINE STATUS(INTEGER SLOT) GDCT==RECORD(GDCT BASE+SLOT*SLOT SIZE) IF SSERIES=YES START REPLY(SRCE,"DCU: ".MTOS(GDCT_MNEMONIC)." ".HTOS(GDCT_DSSMM>>8&X'FFF',3). C " ".STATES(GDCT_STATE&15)) FINISH ELSE START REPLY(SRCE,"GPC: ".MTOS(GDCT_MNEMONIC)." ".HTOS(GDCT_PTSM>>4&X'FFF',3). C " ".STATES(GDCT_STATE&15)) FINISH END !* INTEGERFN TRANS MNEMONIC(STRINGNAME S) INTEGER M,N N=0 IF LENGTH(S)=3 START STRING(ADDR(N))=S BYTEINTEGER(ADDR(N))=0 FINISH ELSE IF LENGTH(S)=4 START STRING(ADDR(M)+3)=S FINISH RESULT =N END IF SSERIES=YES START ROUTINE ACTIVATE(INTEGER ACTWD,TCBAD,ISAD) INTEGERNAME LINK INTEGER I IF MULTI OCP=YES START *INCT_DCU1SEMA *JCC_8,<SEMAGOT> SEMALOOP(DCU1SEMA,0) SEMAGOT: FINISH IF QHEAD=0 START ; ! no I/Os waiting to go *LB_ISAD; *LSD_0; *L_(0+B ); *STUH_SINK *JAT_4,<OK> FOR I=1,1,COM_INSPERSEC CYCLE ; ! 10 millisecs approx *LB_ISAD; *LSD_0; *L_(0+B ); *STUH_SINK *JAT_4,<OKW> REPEAT ->NOT OK OKW: ACT CYCLES=ACT CYCLES+1 *LB_ISAD OK: *LSS_ACTWD; *LUH_TCBAD; *ST_(0+B ) IF MULTI OCP=YES START ; *TDEC_DCU1SEMA; FINISH RETURN FINISH NOTOK: ACTS QD=ACTS QD+1 I=1 LINK==QHEAD WHILE LINK#0 CYCLE QACT==PARM(LINK) LINK==QACT_LINK I=I+1 REPEAT IF MAX Q<I THEN MAX Q=I LINK=NEW PP CELL IF MULTI OCP=YES START ; *TDEC_DCU1SEMA; FINISH QACT==PARM(LINK) QACT=0 QACT_ACTWD=ACTWD QACT_TCBAD=TCBAD QACT_ISAD=ISAD END ROUTINE FIRE DCU2(INTEGER UTAD,TCBAD,ACT) INTEGER I IF MULTI OCP=YES START *INCT_DCU2SEMA *JCC_8,<SEMAGOT> SEMALOOP(DCU2SEMA,0) SEMAGOT: FINISH *PRCL_4 *LSS_ACT *SLSS_TCBAD; *LUH_X'2800000E'; *ST_TOS *LDTB_X'B0000001'; *LDA_UTAD *RALN_8 *CALL_(DR ) *ST_I IF MULTI OCP=YES START ; *TDEC_DCU2SEMA; FINISH UNLESS I=0 START IF MULTI OCP=YES THEN RESERVE LOG PRINTSTRING("DT: ".DATE." ".TIME. C "DCU2 fire fails - resp = ".STRINT(I)." act = ".STRINT(ACT)." Unit table:") DUMPTABLE(0,UTAD,64) PRINTSTRING("TCB:") DUMPTABLE(0,TCBAD,14*4) IF MULTI OCP=YES THEN RELEASE LOG FINISH END ROUTINE FIRE IDENTIFY; ! GDCT & DEV mapped RECORD (CCBF)NAME CCB GDCT_ATTN=0 GDCT_STATE=IDENTIFY FIRED CCB==RECORD(DEV_MYCCBA) CCB_RESP=0 CA==RECORD(DEV_CAA) IF GDCT_UTAD=0 THEN ACTIVATE(X'01000000'!STRM,ADDR(CCB),CA_IAWA) C ELSE FIRE DCU2(GDCT_UTAD,ADDR(CCB),START STREAM) DEV_SECS SINCE=0 END FINISH ELSE START !* ROUTINE CONNECT STREAM(INTEGER PT,CAA,STREAM,CONNECT) OWNRECORD (ALEF) ALE OWNRECORD (CCBF)RCB RECORD (CAF)NAME CA RECORD (CASEF)NAME SENT OWNINTEGER DIS LBE=0,CON LBE=X'00F10800' INTEGER I,J,HI,LO ALE_S=4; ALE_A=ADDR(DIS LBE); ! dummy RCB_LIM FLAGS=PRIV ONLY RCB_LBS=8 RCB_LBA=ADDR(DIS LBE) RCB_ALS=8 RCB_ALA=ADDR(ALE) DIS LBE=X'00F10900'!CONNECT<<26; ! chain on connect if req'd IF STREAM<0 THEN LO=0 AND HI=14 ELSE LO=STREAM AND HI=STREAM CA==RECORD(CAA) SLAVESONOFF(0) FOR J=LO,1,HI CYCLE SENT==CA_STREAM(J) *LXN_CA+4; *INCT_(XNB +0); *JCC_8,<SGOT> SEMALOOP(CA_MARK,2) SGOT: CA_PAW=DO STREAM REQUEST!J SENT=0 SENT_SAW0=X'30000020' SENT_SAW1=ADDR(RCB) CA_MARK=-1 I=X'40000800'!PT<<16 *LB_I; *LSS_1; *ST_(0+B ) FOR I=1,1,COM_INSPERSEC*2 CYCLE EXIT IF SENT_RESP0#0 REPEAT *LXN_CA+4; *INCT_(XNB +0); *JCC_8,<SGOT1> SEMALOOP(CA_MARK,2) SGOT1: SENT_RESP0=0 CA_PIW0=CA_PIW0&(¬(X'80000000'>>J)) CA_MARK=-1 REPEAT SLAVESONOFF(-1) END !* INTEGERFN READ STREAM DATA(INTEGER PT, STREAM, CONTROLLER) CONSTSTRING (24)ARRAY HEADER(0:2)="stream data", C "stream controller status", C "control stream status" CONSTBYTEINTEGERARRAY COMMAND(0:2)=7,3,5 CONSTBYTEINTEGERARRAY LENGTH(0:2)=64,4,64 OWNINTEGERARRAY STREAM DATA(0:63) INTEGER I,CAA,COUNT,GPCNO,SAWFLAGS,LEN RECORD (CAF)NAME CA GPCNO=CNO TO GDC(PT-LOCNO) CAA=CAAS(GPCNO) CA==RECORD(CAA) *LXN_CA+4; *INCT_(XNB +0); *JCC_8,<CAG> SEMALOOP(CA_MARK,2) CAG: IF CA_PAW#0 THEN CA_MARK=-1 AND PAW WAIT(CA) SAWFLAGS=3; ! clear abn & inhibit term int LEN=LENGTH(CONTROLLER) CA_CRESP0=0 CA_PAW=DO CONTROLLER REQUEST CA_CSAW0=SAWFLAGS<<28!COMMAND(CONTROLLER)<<24!STREAM<<16!LEN CA_CSAW1=ADDR(STREAM DATA(0)) CA_MARK=-1 I=X'40000800'!PT<<16 *LB_I; *LSS_1; *ST_(0+B ); ! send channel flag SLAVES ON OFF(0); ! slaves off FOR COUNT=1,1,COM_INSPERSEC*5 CYCLE EXIT IF CA_CRESP0#0 REPEAT SLAVES ON OFF(-1); ! slaves back on 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) PRINTSTRING("CRESP0=".HTOS(CA_CRESP0,8)); NEWLINE IF MULTIOCP=YES START ; RELEASE LOG; FINISH RESULT =STREAM DATA(0); ! useful if controller#0 END ; ! of READ STRM DATA !* ROUTINE PAW WAIT(RECORD (CAF)NAME CA) ! return with semaphore INTEGER I I=0 CYCLE *LXN_CA+4; *INCT_(XNB +0); *JCC_8,<SG> SEMALOOP(CA_MARK,2) SG:RETURN IF CA_PAW=0 EXIT IF I>=5 CA_MARK=-1 I=I+1 WAIT(1) REPEAT PRINTSTRING("DT: ".DATE." ".TIME." GPC--PAW not cleared - PT". C HTOS(PT,2).",PAW = ".HTOS(CA_PAW,8)." ") END !* FINISH !* END ; ! of GDC !* IF SSERIES=NO START EXTERNALINTEGERFN GPC INIT(INTEGER CAA,PT,FLAG) RECORDFORMAT CA0F(INTEGER MARK,PAW,PIW0,PIW1,CSAW0,CSAW1,CRESP0,CRESP1) RECORDFORMAT INIF(INTEGER PSTL,PSTB,CAA,SOE) CONSTINTEGER REAL0AD=X'81000000' CONSTRECORD (CA0F)NAME CA0=REAL0AD RECORD (CAF)NAME CA RECORD (INIF) INI CONSTINTEGER INIT CONTROLLER=X'32000010' CONSTINTEGER LOAD MICROPROGRAM=X'08000000' !* !* 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 !* INTEGER ISA,I ISA=X'40000800'!PT<<16 *LB_ISA; *LSS_2; *ST_(0+B ); ! master clear WAIT(50) IF FLAG=0 THEN SLAVES ON OFF(0); ! FLAG=1 if called from chopsupe CA0=0 CA0_PAW=LOAD MICROPROGRAM CA0_CSAW1=REALISE(ADDR(GPC MPROG(0))) CA0_MARK=-1 *LB_ISA; *LSS_1; *ST_(0+B ) IF FLAG=0 THEN I=100*COM_INSPERSEC ELSE I=100000 I=I-1 UNTIL (CA0_CRESP0#0 AND CA0_MARK=-1) OR I<=0 IF CA0_CRESP0&NORMAL TERMINATION=0 START IF FLAG=0 THEN SLAVES ON OFF(-1) IF MULTI OCP=YES THEN RESERVE LOG PRINTSTRING("DT: ".DATE." ".TIME." GPC--microprogram load fails CA0:") DUMPTABLE(0,REAL0AD,32) IF MULTI OCP=YES THEN RELEASE LOG RESULT =1<<24!CA0_CRESP0 FINISH WAIT(50) CA0=0 CA0_PAW=DO CONTROLLER REQUEST CA0_CSAW0=INIT CONTROLLER CA0_CSAW1=REALISE(ADDR(INI)) GET PSTB(INI_PSTL,INI_PSTB) INI_CAA=CAA INI_SOE=0 CA==RECORD(CAA) CA=0 CA_MARK=-1 CA0_MARK=-1 *LB_ISA; *LSS_1; *ST_(0+B ); ! initialise IF FLAG=0 THEN I=100*COM_INSPERSEC ELSE I=100000 I=I-1 UNTIL (CA_CRESP0#0 AND CA_MARK=-1) OR I<=0 IF FLAG=0 THEN SLAVES ON OFF(-1) I=0 IF CA_CRESP0&NORMAL TERMINATION=0 START IF MULTI OCP=YES THEN RESERVE LOG PRINTSTRING("DT: ".DATE." ".TIME." GPC--INIT fails CA0:") DUMPTABLE(0,REAL0AD,32) PRINTSTRING("CA:") DUMPTABLE(0,INI_CAA,272) PRINTSTRING("INI:") DUMPTABLE(0,ADDR(INI),16) IF MULTI OCP=YES THEN RELEASE LOG IF CA_CRESP0=0 THEN I=2<<24!CA0_CRESP0 C ELSE I=3<<24!CA_CRESP0 FINISH CA_CRESP0=0 CA_MARK=-1 RESULT =I END FINISH !* IF CSU FITTED=YES START EXTERNALROUTINE CSU(RECORD (PARMF)NAME P) RECORDFORMAT DEVICE ENTRY F(INTEGER SER, GPTSM, PROPADDR, C SECS SINCE, CA A, MYCCBA, 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 CCB A, SENSE DATA A, LOG MASK, TRTAB AD, UA SIZE, C UA AD, TIMEOUT, PROPS0, PROPS1) RECORD (PARMF) Q RECORD (DEVICE ENTRY F)NAME DEV 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) RETURN ; ! ignore protem (or forever?) ->ACT(P_DEST&255) ACT(0): ! initialise call from GDC Q=0 Q_DEST=GDC 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 DEV==RECORD(P_P3) DTODA(P_P6&255-'0')=P_P3 RETURN ACT(2): ! deallocate RETURN ACT(3): ! deallocate reply RETURN ACT(5): ! interrupt from GDC RETURN ACT(6): ! switch device RETURN ACT(7): ! switch controller RETURN END FINISH ENDOFFILE