!*********************************************************************** ! ! 2900 TAPE HANDLER ! !*********************************************************************** ! %IF SSERIES=NO %START !..........PSERIES..........PSERIES..........PSERIES..........PSERIES ! %CONSTINTEGER TOP LBE=36 ! { CH FN %CONSTINTEGERARRAY LBES(0:TOP LBE)= %C X'00000200', { 1 RF X'40001200', { 2 RR X'00000200', { 3 RF X'44C01200',X'86800D10',X'00006200', { 4 RR,AS,RFEC X'40001200', { 5 RR X'04C00200',X'86800D10',X'40007200', { 6 RF,AS,RREC X'04C00200',X'04805200',X'86800D10',X'00006200', { 7 RF,SR,AS,RFEC X'44C01200',X'04804200',X'86800D10',X'40007200', { 8 RR,SF,AS,RREC X'00000200', { 9 RF X'40001200', { 10 RR X'80000300', { 11 W X'80802300', { 12 WT X'04A05200',X'80C04300', { 13 SR IGN TM,ER....FOR WRITE(TM) RETRY X'00804200', { 14 SF X'00805200', { 15 SR X'00802200', { 16 STF X'00803200', { 17 STR X'00803800', { 18 RW X'80C04300', { 19 ER X'00A04200', { 20 SF IGN TM....FOR FINAL POSITIONING X'00A05200', { 21 SR IGN TM....DITTO X'04A04200',X'00805200', { 22 SF IGN TM,SR....FOR TM LOOK-AHEAD X'00805800', { 23 UNL....UNLOAD FLASH X'00000E00', { 24 SEND PROPS X'00001E00' { 25 QUALIFIED SPC FOR GTS ! ! ALL LBES WHICH DO NOT INVOLVE A XFER REQUIRE IGNORE SHORT. ! ERASES HAVE SHORT/LONG MASKED OFF FOR GTS DECKS WHICH DO A FIXED LENGTH ! AND THEREFORE DO NOT DECREMENT THE BYTE COUNT ! %FINISHELSESTART !..........SSERIES..........SSERIES..........SSERIES..........SSERIES ! %CONSTINTEGER TOP CW=36 ! { CH FN %CONSTINTEGERARRAY CW(0:TOP CW)= %C X'2000C002', { 1 RF X'2000C012', { 2 RR X'2000C002', { 3 RF X'2C40C012',X'2840408D',X'20004062', { 4 RR,AS,RFEC X'2000C012', { 5 RR X'2C40C002',X'2840408D',X'20004072', { 6 RF,AS,RREC X'2C40C002',X'28404052',X'2840408D',X'20004062', { 7 RF,SR,AS,RFEC X'2C40C012',X'28404042',X'2840408D',X'20004072', { 8 RR,SF,AS,RREC X'2000C002', { 9 RF X'2000C012', { 10 RR X'2000C083', { 11 W X'2800C0A3', { 12 WT X'2A40C052',X'2C0040C3', { 13 SR IGN TM,ER X'2800C042', { 14 SF X'2800C052', { 15 SR X'2800C022', { 16 STF X'2800C032', { 17 STR X'2800C038', { 18 RW X'2C00C0C3', { 19 ER X'2A00C042', { 20 SF IGN TM X'2A00C052', { 21 SR IGN TM X'2A40C042',X'28004052', { 22 SF IG TM,SR X'2800C058', { 23 UNL X'2000C00E', { 24 SPC X'2000C01E' { 25 QSPC ! ! DO WE NEED IGNORE SHORT FOR NON-XFER, IF WERE NOT GOING TO GIVE A ! A DUMMY DATA AREA. DCU TELLS FROM LACK OF FIXED BIT IN STE THAT NO ! AREA REQUIRED. LEAVE IGN SHORT IN ABOVE FOR NOW. IT CANT DO ANY HARM. ! SEE NOTE AFTER LBES ABOVE RE ERASE SHORT/LONG MASK ! %FINISH;!.............................................................. ! %CONSTINTEGER MAX CHAINS=25,PRIVATE=MAX CHAINS+1 ! %CONSTBYTEINTEGERARRAY STATMASK(1:MAX CHAINS)=%C X'FE'(3),X'EC',X'FE',X'EC'(3),X'FE'(2),X'FC'(13),X'7C'(2) ! TERTIARY STATUS MASKS TO GO WITH EACH CHAIN ABOVE. ! FE=T0-T6. INCLUDES ADVISORY. ! EC=T0-T2,T4-T5. EXCLUDES MEDIA AND ADVISORY. ! 7C=T1-T5. EXCLUDES MANUAL/NA FOR SEND PROPS AT STARTUP ! %CONSTINTEGERARRAY CHAIN START(1:MAX CHAINS+1)= %C 0,1,2,3,6,7,10,14,18,19,20,21,22,24,25,26,27,28,29,30,31,32,34,35,36,0 ! THESE ARE THE LBE(CW) INDEX FOR CHAIN STARTS. ! CHAIN MAX+1 IS NOT REAL CHAIN.IT ACCOMMODATES PRIVATE CHAINS. ! SEE ROUTINE TERMINATE. ! %CONSTINTEGERARRAY CHAIN LENGTH(1:MAX CHAINS+1)= %C 1,1,1,3,1,3,4,4,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,0 ! THE NUMBER OF LBES(CWS) IN EACH CHAIN %CONSTINTEGER LAST READ CHAIN=10; ! JUST THAT %CONSTINTEGER LAST RETRY CHAIN=12 ! %CONSTINTEGER POSMASK=X'5A5A5'; ! READ CHAINS ONLY. BIT 2** INDEX SET ! IF THAT LBE(CW) LEAVES US AFTER THE BLOCK, UNSET IF BEFORE. %CONSTINTEGER REVMASK=X'A424A'; ! READ CHAINS ONLY. BIT 2** INDEX SET ! IF THAT LBE(CW) IS REVERSE READ. ! %IF SSERIES=NO %START !..........PSERIES..........PSERIES..........PSERIES..........PSERIES ! %CONSTINTEGER NODATA=X'20000000', MAX XFER=X'3FFFF' %CONSTINTEGERARRAY IGNSHORTLONG(0:3)= %C 0,X'00800000',X'00400000',X'00C00000' %FINISHELSESTART !..........SSERIES..........SSERIES..........SSERIES..........SSERIES ! %CONSTINTEGER NODATA=X'00000200', MAX XFER=X'FFFF' %CONSTINTEGERARRAY IGNSHORTLONG(0:3)= %C 0,X'08000000',X'04000000',X'0C000000' %FINISH;!.............................................................. ! %CONSTLONGINTEGER LONG1=1 ! %CONSTINTEGER OK=0, NOTOK=-1 ! %CONSTINTEGER NOT AVAILABLE=0, MANUAL=1, LOADING=2, LOADED=3, CLAIMED=4 %CONSTINTEGER UNLOADING=5 %CONSTSTRING(11)%ARRAY STATES(0:5)= %C " na ", " manual ", " loading ", " loaded ", " claimed ", " unloading " ! DRIVE STATES. ! %CONSTSTRING(5)%ARRAY OFFLINE SW(0:1)="stop","reset" ! THE NAME OF THE SWITCH ON THE DRIVE TO DO IT FOR MTS AND GTS RESPECTIVELY ! %CONSTBYTEINTEGER TERM EXP=1, ATTN EXP=2 ! %CONSTINTEGER NRZI=2, PE=3, GCR=8 !* %CONSTINTEGER ME=X'310000' ! %CONSTINTEGER CONTROLLER=X'300000'; ! GPC OR DCU AS APPROPRIATE %CONSTINTEGER ALLOC=11, DEALLOC=5, EXEC=12 ! %CONSTINTEGER ON=1, OFF=0 ! %CONSTINTEGER REJECT=2,BAD PARAMS=1,NOT CLAIMED=2,SNO NOT FOUND=4,BUSY=8 ! !------------------------------ FORMATS ------------------------------ ! %RECORDFORMAT PF(%INTEGER DEST,SRCE,P1,P2,P3,P4,P5,P6) ! %RECORDFORMAT SHORTPF(%INTEGER DEST,SRCE,P1,P2,P3,P4) ! %RECORDFORMAT CLF(%INTEGER DEST,SRCE,IDENT, (%HALFINTEGER H1,PERM, %STRING(7) DSN %OR %INTEGER REPLY,SNO,%BYTEINTEGER D1,D2,D3,DEVID), %STRING(3) MNEM,%BYTEINTEGER D4,D5,D6,MODE) ! %RECORDFORMAT REQF(%INTEGER ADDR,LENGTH,LSL,LSTBA, %BYTEINTEGER STATE,CHAIN,FINAL CHAIN, (%BYTEINTEGER TARGET POS %OR %BYTEINTEGER TM), (%INTEGER READORS %OR %INTEGER SKIP TOT), (%INTEGER COUNT %OR %INTEGER PRIVATE ATTN), %INTEGER RETRIES,RETRY LIMIT,%INTEGER COUNT1) ! %IF SSERIES=NO %START !..........PSERIES..........PSERIES..........PSERIES..........PSERIES ! %RECORDFORMAT RCBF(%INTEGER LIMFLAGS,LSTBA,LB BYTES,LBA,AL BYTES, ALA,INITWORD) ! %RECORDFORMAT TF(%INTEGER LINK,LAB1,LAB2,%STRING(7)DSN,%INTEGER LBE1, LBE2,LBE3,LBE4,ALE1,ALE2,STREAMR0,STREAMR1,%STRING(3)MNEM, %RECORD(REQF)REQ,%RECORD(RCBF)RCB,%INTEGER SNO,%RECORD(SHORTPF)REP, (%BYTEINTEGER T0,T1,T2,T3,T4,T5,T6,T7 %OR %LONGINTEGER T07), %BYTEINTEGER T8,T9,T10,T11,T12,T13,T14,GTS,SSTAT,PROP1,PROP2,PROP3, %INTEGER FAULTS,OPS,%BYTEINTEGER STATE,MODE,LOAD STATE,UNLOAD PENDING) ! NOTE THAT TO OBTAIN ALIGNMENT OF RECORD 'REP' AND LONGINTEGER 'T07', ! 'SSTAT' IS FORCED OUT OF ITS NATURAL POSITION PRECEDING 'T0'. ! THE ABOVE RECORD IS MAPPED ONTO THE USER AREA IN THE DEVICE SLOT, ! AND MAY EXTEND UP TO 200 BYTES. ! CURRENT LENGTH OF ABOVE IS - 184 %CONSTINTEGER TFSIZE=184 %FINISHELSESTART !..........SSERIES..........SSERIES..........SSERIES..........SSERIES ! %RECORDFORMAT TCBF(%INTEGER CW,STE,LENGTH,ADDR,NEXT TCB, %BYTEINTEGER PSTAT,RESPONSE,%HALFINTEGER REMBC, %INTEGERARRAY PREAMBLE,POSTAMBLE(1:4)) ! %RECORDFORMAT TF(%INTEGER LINK,%STRING(3) MNEM,%INTEGER LAB1,LAB2, %STRING(7)DSN, %RECORD(REQF)REQ,%RECORD(SHORTPF)REP, (%BYTEINTEGER T0,T1,T2,T3,T4,T5,T6,T7 %OR %LONGINTEGER T07), %BYTEINTEGER T8,T9,T10,T11,T12,T13,T14,GTS,SSTAT,PROP1,PROP2,PROP3, STATE,MODE,LOAD STATE,UNLOAD PENDING, %INTEGER STREAMR0,STREAMR1, %RECORD(TCBF)%ARRAY TCBS(1:6), %INTEGER SNO,FAULTS,OPS) ! SEE NOTE RE ALIGNMENT IN PSERIES FORMAT ABOVE. ! ALSO NB THAT TCBS MUST BE DOUBLE WORD ALIGNED. H/W DOESNT CHECK ! THIS MAY EXTEND TO 480 BYTES. CURRENT LENGTH IS 468 ! ONLY 4 OF THE 6 TCBS ARE USED HERE. UP TO 6 FOR PRIVATE CHAINS. %CONSTINTEGER TFSIZE=468 %FINISH;!.............................................................. ! %RECORDFORMAT DF(%INTEGER SER, PTSM, PROPADDR, TICKS SINCE, CAA, GRCB AD, LBA, ALA, STATE, RESP0, RESP1, SENSE1, SENSE2, SENSE3, SENSE4, REPSNO, BASE, ID, DLVN, MNEMONIC, ENTSIZE, PAW, USAW0, URCB AD, SENSDAT AD, LOGMASK, TRTAB AD, UA SIZE, UA AD, TIMEOUT, PROPS0, PROPS1) ! !------------------------- EXTERNAL SPECS --------------------------- ! %IF MULTIOCP=YES %START %EXTERNALROUTINESPEC RESERVELOG %EXTERNALROUTINESPEC RELEASELOG %FINISH %EXTERNALROUTINESPEC OPMESS(%STRING(23) S) %EXTERNALLONGINTEGERSPEC KMON %EXTERNALROUTINESPEC PKMONREC(%STRING(20)TXT,%RECORD(PF)%NAME P) %EXTERNALROUTINESPEC PON(%RECORD(PF)%NAME P) %EXTERNALSTRINGFNSPEC HTOS(%INTEGER VAL,PLACES) %EXTERNALROUTINESPEC DUMPTABLE(%INTEGER TABNO,ADDR,L) %SYSTEMROUTINESPEC MOVE(%INTEGER L,F,T) %SYSTEMROUTINESPEC ETOI(%INTEGER A,L) %EXTERNALROUTINESPEC PRHEX(%INTEGER N) ! !===================================================================== ! %EXTERNALROUTINE TAPE(%RECORD(PF)%NAME P) ! %OWNINTEGER FIRSTTP=0, VOLUMS=0, INITIALISED=0 %OWNINTEGER READ RETRIES=15,WRITE RETRIES=6 ! WRITE RETRIES ARE LIMITED BY THE MAX INTERBLOCK GAP=300 INCHES. ! 6 ASSUMES A MAX BLOCK SIZE OF @64K AT 1600 BPI(IE 40 INCHES). ! P SERIES BLOCKS CAN BE UP TO 256K, BUT WE CANT CATER FOR THAT WHICH ! WOULD GIVE US ONLY ONE RETRY! IT WOULD BE SMARTER TO MAKE THE RETRIES ! A FUNCTION OF THE WRITTEN LENGTH. %OWNINTEGER RLEVEL=0 ! REPORTING LEVEL: ! 2**0 - REPORT PARM RECORDS IN ! 2**1 - REPORT PARM RECORDS OUT ! 2**2 - DUMP TABLE AFTER CHAIN FIRED %OWNINTEGERNAME LASTLINK %RECORD(DF)%NAME D %RECORD(TF)%NAME T %RECORD(REQF)%NAME REQ %RECORD(SHORTPF)%NAME REP %RECORD(PF)PP %INTEGERNAME PREVLINK %INTEGER I,NDECKS,MODE,ACT,SNO,TMON %STRING(4) M %SWITCH ACTSW(1:13) ! %ROUTINESPEC FIRE CHAIN %ROUTINESPEC TERMINATE(%INTEGER N,B) %ROUTINESPEC TELL VOLUMS(%INTEGER LOAD TYPE) ! %ROUTINE MON(%INTEGER MODE,%RECORD(PF)%NAME P) %CONSTSTRING(4)%ARRAY MODES(1:3)= %C "IN","OUT","IN??" PKMONREC(" TAPE(".MODES(MODE)."): ",P) %END; ! ROUTINE MON ! ! %ROUTINE MYPON(%RECORD(PF)%NAME P) %IF TMON#0 %OR RLEVEL&2#0 %THEN MON(2,P) PON(P) %END; ! ROUTINE MYPON ! ! %ROUTINE REPORT(%STRING(255) MESS) !*********************************************************************** ! REPORTS ABNORMAL CONDITIONS TO LOG !*********************************************************************** %CONSTBYTEINTEGERARRAY HX(0:15)= %C '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' ! %ROUTINE PBYTE(%BYTEINTEGER N) PRINTSYMBOL(HX(N>>4)) PRINTSYMBOL(HX(N&X'F')) %END; ! ROUTINE PBYTE ! %INTEGER I,J,SIZE T_FAULTS=T_FAULTS+1 RESERVELOG %IF MULTIOCP=YES PRINTSTRING(" TAPE ERROR// ABNORMAL TERMINATION - ".MESS." DECK ") PBYTE(T_PROP2) PRINTSTRING(" FAULTS (DECK/REQ) ") PRHEX((T_FAULTS<<16)!REQ_RETRIES) PRINTSTRING(" REQ ID ") PRHEX(REP_P1) SPACE PRINTSTRING(T_DSN) %UNLESS 3<=T_LOAD STATE<=4 ! IT MIGHT BE JUNK IN THAT CASE. %IF REQ_CHAIN<=10 %START MESS=" READ" %FINISHELSEIF REQ_CHAIN<=12 %START MESS=" WRITE" %FINISHELSE MESS=" OTHER" PRINTSTRING(MESS) PRINTSTRING(" SST T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 ") SPACE PBYTE(T_SSTAT) J = ADDR(T_T0) %FOR I=0,1,11 %CYCLE SPACES(2) PBYTE(BYTEINTEGER(J+I)) %REPEAT SIZE=TFSIZE DUMP TABLE(61,ADDR(T),SIZE) RELEASELOG %IF MULTIOCP=YES %END; ! ROUTINE REPORT ! ! %INTEGERFN SEARCH TPS(%INTEGER SWIND,IMATCH,%STRING(6) SMATCH) !********************************************************************** ! CALLED TO SCAN T CHAIN MATCHING IMATCH OR SMATCH RETURNING OK ! OR NOTOK,LEAVING T MAPPED TO MATCHING RECORD. ! OR TO SCAN ENTIRE CHAIN WITHOUT MATCHING, WHEN RESULT IS IRRELEVANT ! AND T IS LEFT MAPPED TO LAST RECORD. ! SWIND=1 - SMATCH MNEMONIC ! =2 - SMATCH DSN ! =3 - IMATCH SNO ! =4 - SCAN AND TELL VOLUMS ! =5 - SCAN AND DISPLAY !********************************************************************** %STRING(7) DSN %SWITCH SW(1:5) %RESULT=NOTOK %IF FIRSTTP=0; ! CHAIN EMPTY T==RECORD(FIRSTTP) PREVLINK==FIRSTTP ! %CYCLE ->SW(SWIND) ! SW(1):; ! MATCH MNEM %IF T_MNEM=SMATCH %THENRESULT=OK ->NEXT ! SW(2):; ! MATCH DSN %IF T_DSN=SMATCH %THENRESULT=OK ->NEXT ! SW(3):; ! MATCH SNO %IF T_SNO=IMATCH %THENRESULT=OK ->NEXT ! SW(4):; ! TELL VOLUMS %IF LOADED<=T_STATE<=CLAIMED %THEN TELL VOLUMS(1) ! COULD IT BE CLAIMED IF VOLUMS ONLY JUST HERE? ->NEXT ! SW(5):; ! TELL OPER %IF LOADED<=T_STATE<=CLAIMED %THEN DSN=T_DSN %ELSE DSN="" OPMESS(HTOS(T_SNO,4)." ".T_MNEM.STATES(T_STATE).DSN) ->NEXT ! NEXT: %RESULT=NOTOK %IF T_LINK=0 PREVLINK==T_LINK T==RECORD(T_LINK) %REPEAT %END; ! FN SEARCH TPS !* !* %ROUTINE TELL VOLUMS(%INTEGER LOAD TYPE) !*********************************************************************** ! TELLS VOLUMS ABOUT LOAD OR UNLOAD OF DRIVE. ! LOAD TYPE=0(NOT LOADED), 1(LOADED) ! VOLUMS ALSO NEEDS TO KNOW LOADED WITH LABEL(1) OR NO LABEL(2) !*********************************************************************** %RECORDFORMAT VF(%INTEGER DEST,SRCE,TYPE,LOAD,%STRING(4)MNEM, %C %STRING(7) DSN,%BYTEINTEGER D1,MODE,PERM) %RECORD(VF) V %IF VOLUMS=0 %THENRETURN; ! VOLUMS NOT THERE %IF LOAD TYPE=1 %AND T_DSN="NOLABEL" %THEN LOAD TYPE=2 V=0 V_DEST=VOLUMS V_SRCE=ME V_TYPE=4 V_LOAD=LOAD TYPE V_DSN=T_DSN %UNLESS LOAD TYPE=0 V_MNEM=T_MNEM V_PERM=2-((T_PROP3>>6)&1) V_MODE=T_MODE MYPON(V) %END; ! ROUTINE TELL VOLUMS ! ! %ROUTINE LOAD !*********************************************************************** ! ENTERED TO GET PROPS AND, IF APPROPRIATE, LOAD EACH DECK SUCCESSFULLY ! ALLOCATED AT START-UP, AND THEREAFTER FOR ANY DECK GIVING AN AUTO ! ATTENTION, AND ! TO UNLOAD OR RELEASE/REWIND A DECK WHEN USER RELEASES IT OR AT ! DISASTER. !*********************************************************************** %CONSTBYTEINTEGERARRAY GTS MODES(0:3)=3,8,2,8 %OWNINTEGER VOL1=X'E5D6D3F1' %INTEGER I,CH %STRING(7) DSN %STRING(40) S %SWITCH LDSW(0:9) ! ->LDSW(T_LOAD STATE) ! LDSW(0):; ! GET PROP CODE. REP=0 REQ=0 REQ_ADDR=ADDR(T_PROP1) REQ_LENGTH=3 REQ_CHAIN=24+T_GTS; ! IE 24 FOR MTS, 25 FOR GTS T_MODE=PE FIRE CHAIN T_LOAD STATE=1 T_STATE=LOADING %RETURN ! LDSW(1):; ! REPLY FROM SEND PROPS %IF REP_P2#0 %START ! SEND PROPS FAILED. INOP MASKED OFF SO SOMETHING ELSE ->LOAD FAIL %FINISH ! AT STARTUP, WE DONT HAVE ANY SENSE BYTES HERE TO TELL WHETHER NOTAVAIL, ! MANUAL OR LOADED. ! WE JUST PLOUGH ON AND DO A REWIND ANYWAY AND SORT IT OUT FROM THAT ! REP_P2=0 REQ=0 REQ_CHAIN=18 REQ_ADDR=X'81000000' REQ_LENGTH=50; ! STANDARD DUMMY ASL FIRE CHAIN T_LOAD STATE=2 %RETURN ! LDSW(2):; ! REPLY FROM INITIAL REWIND %IF REP_P2#0 %START ! WE EXPECT IT TO FAIL FOR UNLOADED DECKS AT START-UP ! (THIS COULD BE DONE AFTER SPC ABOVE EXCEPT FOR GTS DECKS WHICH DONT ! GIVE U/S FOR SPC IN MANUAL). %IF T_T0&X'C0'#0 %START; ! UNAVAIL OR MANUAL %IF T_T0&X'40'#0 %THEN T_STATE=NOT AVAILABLE %ELSE T_STATE=MANUAL ->EXIT %FINISHELSE ->LOAD FAIL %FINISH ! SO ITS LOADED. LETS TRY TO READ SOMETHING LIKE A LABEL. ! FIRST IN PE. GTS DECKS WILL DO THE READ IN THE TAPE MODE AND SAY IF ITS ! DIFFERENT. MTS DECKS WILL FAIL, WHEN IF NRZI IS FITTED, WE'LL TRY THAT. SET UP READ: ! CAUTION*** COME HERE FROM LDSW(1) AND LDSW(4) ALSO ! REP_P2=0 REQ=0 REQ_ADDR=ADDR(T_LAB1) REQ_LENGTH=16 REQ_CHAIN=1; ! READ FORWARD REQ_FINAL CHAIN=9; ! STANDARD REQ_TARGET POS=1 REQ_READORS=IGNSHORTLONG(2); ! IGNORE LONG SINCE IT SURELY WILL BE REQ_RETRY LIMIT=4 ! THIS ACUALLY ONLY GIVES US 2 GOES AT IT, SINCE REVERSE READS LONG ! ARE INEVITABLY FAILURES (SEE OK(1) IN 'TERMINATE') FIRE CHAIN T_LOAD STATE=3 %RETURN ! LDSW(3):; ! REPLY FROM LABEL READ CH=0 %IF REP_P2#0 %AND T_GTS#0 %AND T_T6&64#0 %START ! GTS FAILED 'INCOMPATIBLE MODES'. THIS IS A WARNING ONLY, AND THE READ ! HAS BEEN DONE IN THE MODE OF THE TAPE, THE LATTER BEING ADVISED IN ! T13, BITS 104,105 T_MODE=GTS MODES((T_T13>>6)&3) REP_P2=0; ! MAKE IT LOOK SUCCESSFUL %FINISH %IF REP_P2#0 %START; ! FAILED %IF T_T4&128#0 %START; ! WRONG MODE ! FOR GTS, THIS MEANS NO RECOGNISABLE MODE. FOR MTS IT MAY MEAN ! A MODE RECOGNISED BUT NOT THE REQUESTED ONE. %IF T_GTS=0 %AND T_MODE=PE %AND T_PROP3&16#0 %START ! MTS. WE HAVE TO TRY EACH POSSIBLE MODE TO SEE IF ANY SUCCEEDS. ! THAT WAS PE, AND NRZI IS FITTED, SO TRY THAT ! FIRST A REWIND REP=0 REQ_CHAIN=18 ! PREV ADDR/LENGTH WILL DO IF REQD T_LOAD STATE=4 FIRE CHAIN %RETURN %FINISH ! IF GTS, NO MODE ON TAPE. ! IF MTS, EITHER TRIED BOTH, OR NRZI NOT FITTED. SET MODE UNDEFINED. ! THE ONLY THING THAT CAN BE DONE TO THIS TAPE IS A WRITE AT BT, ! AFTER A MODE OVERRIDE IN 'CLAIM VOLUME'. T_MODE=0 OPMESS(T_MNEM." undefined mode") %FINISH ! SO SOME ERROR OTHER THAN MODE, MAYBE NOISE. RETAIN IT AS 'NOLABEL'. %FINISHELSESTART; ! READ SUCCEEDED. ! IBM LABELS ARE 80 BYTES STARTING 'VOL1' IN EBCDIC. ! ICL MAY BE 86,96 OR GREATER IF IPL BLOCKS. EACH BEGINS WITH INTEGER ! BLOCK COUNT AND HALFINTEGER BYTE LENGTH. %IF T_LAB1=0 %THEN MOVE(10,ADDR(T_LAB1)+6,ADDR(T_LAB1)) ! IE IT WAS A BLOCK COUNT, SO MOVE DATA FIELD DOWN. %IF T_LAB1=VOL1 %START; ! FORMAT OK MOVE(6,ADDR(T_LAB1)+4,ADDR(DSN)+1) LENGTH(DSN)=6 ETOI(ADDR(DSN)+1,6) ! NOW CHECK FOR VALID CHARS IN DSN %FOR I=1,1,6 %CYCLE CH=CHARNO(DSN,I) %UNLESS '0'<=CH<='9' %OR 'A'<=CH<='Z' %OR CH=' ' %START OPMESS(T_MNEM." faulty dsn - ".DSN) CH=0 %EXIT %FINISH %REPEAT %FINISH %FINISH ! SO UNDEFINED MODE, OR READ FAILED OTHER THAN IDENTIFIER, ! OR AN INVALID FORMAT READ, OR AN INVALID DSN READ, ! ALL GET HERE WITH CH=0 AND ARE ALL TREATED AS NOLABEL. ! GET HERE WITH CH#0 ONLY IF GOOD DSN READ. %IF CH#0 %THEN T_DSN=DSN %ELSE T_DSN="NOLABEL" REP=0 REQ_CHAIN=18 ! PREV ADDR AND LENGTH WILL DO FOR DUMMY IF NEEDED FIRE CHAIN T_LOAD STATE=5 %RETURN ! LDSW(4):; ! REWIND AFTER FAILED PE READ, FOR A TRY AT NRZI. %IF REP_P2#0 %THEN ->LOAD FAIL T_MODE=NRZI ->SET UP READ; ! WITH REP_P2=0 ! LDSW(5):; ! FINAL REWIND %IF REP_P2#0 %THEN ->LOAD FAIL ! LOAD OK: T_STATE=LOADED TELL VOLUMS(1) OPMESS(T_MNEM." loaded ".T_DSN) ! EXIT: T_LOAD STATE=0 %RETURN ! LOAD FAIL: OPMESS(T_MNEM." load failed") T_LOAD STATE=6 ! AND DROP THRU' TO ....... ! UNLOAD: LDSW(6):LDSW(8):; ! ENTRY POINT FOR UNLOAD, RELEASE/REWIND %IF LOADED<=T_STATE<=CLAIMED %THEN TELL VOLUMS(0) T_DSN=""; ! JUST TO KEEP 'CLAIM VOLUME' TIDY REP=0 REQ=0 %IF T_LOAD STATE=6 %THEN REQ_CHAIN=23 %ELSE REQ_CHAIN=18 ! DISCONNECT REWIND REQ_ADDR=X'81000000' REQ_LENGTH=50 FIRE CHAIN T_LOAD STATE=T_LOAD STATE+1 T_STATE=UNLOADING %RETURN ! LDSW(7):; ! REPLY FROM UNLOAD %IF REP_P2#0 %AND T_T0&X'C0'=0 %THENC S=" unload fails. Press ".OFFLINE SW(T_GTS)."/unload" %ELSE S=" unloaded" ! IT MIGHT ALREADY BE UNLOADED IF PRIVATE CHAIN USER HAS DONE IT. OPMESS(T_MNEM.S) T_STATE=MANUAL ->EXIT ! LDSW(9):; ! REPLY FROM RLSR/RWND %IF REP_P2#0 %START OPMESS(T_MNEM." rlse/rwnd fails") T_LOAD STATE=6 ->UNLOAD %FINISH ! NOW RE-READ LABEL. WE'RE AT BT AND REP_P2=0 SO GO STRAIGHT TO READ T_MODE=PE T_LOAD STATE=2 T_STATE=LOADING ->LDSW(2) ! ! %END; ! ROUTINE LOAD !* !* %ROUTINE CLAIM VOLUME(%RECORD(CLF)%NAME P) !********************************************************************** ! ALLOCATES VOLUME TO REQUESTING USER. ! P_DSN IS REQUIRED VOLUME, OR P_MNEM IF P_DSN="NOLABEL". ! P_PERM IS REQUIRED PERM, 1=READ, 2=RITE ! P_MODE IS REQUIRED MODE: ! MODE&B'1011'=8(GCR),OR 3(PE),OR 2(NRZI) OVERRIDES MODE ESTABLISHED IN LABEL READ, ! (UNLESS NRZI SPECIFIED AND NOT FITTED, OR GCR AND NOT GTS DECK, WHEN REJECT). ! IF NO OVERRIDE MODE SPECIFIED AND NO MODE ESTABLISHED AT LABEL ! READ (SOME OTHER MODE RECORDED OR BLANK TAPE), THEN REJECT. ! MODE&4 IS COMPRESS EXPAND AND IS ORED INTO TAPE MODE OR OVERRIDE ! AS APPROPRIATE. ! A MODE OF ZERO THUS USES CURRENT TAPE MODE AND NO CE. !********************************************************************** %INTEGER OVERMODE,I %IF P_DSN="NOLABEL" %THEN I=SEARCH TPS(1,0,P_MNEM) %C %ELSE I=SEARCH TPS(2,0,P_DSN) OVERMODE=P_MODE&B'1011' %IF I=NOTOK %OR T_STATE#LOADED %START ! IF SEARCH FAILS, THEN DSN NOT FOUND, OR MNEMONIC NOT PRESENT ! IF SEARCH SUCCEEDS, T MAPPED. IF STATE#LOADED THEN TAPE ALREADY ! CLAIMED. THIS LATTER CHECK IS DONE BY VOLUMS BEFORE COMING HERE, ! BUT WE DO IT HERE FOR CHOPSUPE (NO VOLUMS AROUND YET). P_REPLY=1 %FINISHELSEIF T_PROP3&X'40'#0 %AND P_PERM=2 %START ! N0 RING FITTED AND WRITE REQUESTED P_REPLY=2 %FINISHELSEIF OVERMODE=1 %OR OVERMODE>8 %OR (OVERMODE=0 %AND T_MODE=0) %ORC (OVERMODE=GCR %AND T_GTS=0) %ORC (OVERMODE=NRZI %AND (T_PROP3>>T_GTS)&X'10'=0) %START ! NRZI BIT IS AT X20 FOR GTS DECKS!!!!! ! INVALID OVERRIDE MODE, OR ! NO OVERRIDE MODE AND NONE ESTABLISHED AT LABEL READ, OR ! GCR OVERRIDE MODE AND NOT GTS DECK, OR ! NRZI OVERRIDE MODE AND NOT FITTED P_REPLY=3 %FINISHELSESTART; ! ALL OK T_STATE=CLAIMED %IF OVERMODE#0 %THEN T_MODE=OVERMODE T_MODE=T_MODE!(P_MODE&4); ! INCLUDE CE BIT IF ANY T_SNO=(T_SNO+X'100')&X'FFFF' ! BOTTOM BYTE IS SNO PROVIDED BY CONTROLLER. TOP BYTE IS CYCLIC 0-255. ! SO IF WE LOSE A DECK AND DO NOT GET THE EXPECTED RELEASE FROM USER ! WE CAN REALLOCATE THE DECK WITHOUT FEAR OF THE OUTSTANDING SNO COMING. ! BUT CAUTION*** THE SNO (STREAM ACTUALLY) PROVIDED BY CONTROLLER IS NOT ! GUARANTEED TO BE ONLY A BYTE. IF THERE ARE ENOUGH DEVICES IT COULD ! GO OVER. P_SNO=ME!T_SNO P_DEVID=T_PROP2; ! CONTROLLER/MECH ADDRESS. CAN BE USED BY USER ! IF WRITING, TO SHOW LAST DECK WRITTEN ON. P_MODE=T_MODE P_REPLY=OK %FINISH %END; ! ROUTINE CLAIM VOLUME ! ! %ROUTINE ATTENTION !*********************************************************************** ! ENTERED TO DEAL WITH ATTENTIONS. ! IT IS REPUTEDLY POSSIBLE FOR MULTIPLE INDEPENDENT BITS TO BE SET ! IF SEVERAL STATE CHANGES OCCURRED IN THE DEVICE WHILE THE SYSTEM ! WAS UNINTERRUPTIBLE (NORMALLY THE ONLY TWO WHICH WOULD BE EXPECTED ! TOGETHER ARE AUTO AND BT). THIS CODE ATTEMPTS TO DEAL WITH SUCH ! MULTIPLE OCCURENCES, BUT LACKING THE TIME SEQUENCE OF THE BITS ! THEY ARE NOT NECESSARILY UNAMBIGUOUS AND WE MAY END UP IN A STATE ! DIFFERENT FROM THE DEVICE. HOWEVER THIS SHOULD BE EXCEEDINGLY RARE ! AND IN MOST CASES REMEDIAL BY OPERATOR ACTION. ! ! MTS BITS:- ! X80=AUTO ! X40=BT ! X20=ALWAYS SET ! X10=TM ! X08=ENGINEER ! X04=AVAILABLE ! X02=NOT AVAILABLE ! X01=MANUAL REQUESTED ! ! GTS BITS:- ! X80=AUTO ! X40=BT ! X20=SECONDARY ATTN ! X10=TM ! X08=ALWAYS ZERO ! X04=AVAILABLE(CLUSTER) ! X02=NOT AVAILABLE(CLUSTER) ! X01=ALWAYS ZERO ! ! THE AVAILABLE/NOT AVAILABLE SWITCH AFFECTS ALL DECKS ON A GTS CLUSTER ! BUT ONLY ONE ATTN IS GENERATED BY THE H/W. THIS CODE RELIES ON DCU ! GENERATING ONE ATTN FOR EACH DECK ALLOCATED IN THAT CASE. !*********************************************************************** %CONSTINTEGER AUTO=X'80',BT=X'40',SEC ATTN=X'20',TM=X'10',ENGINR=8,AVAIL=4, NOT AVAIL=2,HOLD=1 %INTEGER ATTN,I %SWITCH SW(0:2) ! %ROUTINE TELL USER REQ_STATE=0 %IF REP_DEST#0 %START; ! BY USER REP_P2=3 MYPON(RECORD(ADDR(REP))); ! MUST DO IT THIS WAY SINCE REP'S LENGTH IS < THAN PARAM SPEC %FINISHELSE T_LOAD STATE=0 ! IE ABORT LOAD OR UNLOAD %END ! %ROUTINE RELEASE TELL VOLUMS(0) %IF LOADED<=T_STATE<=CLAIMED TELL USER %IF REQ_STATE#0; ! IF TERM OR ATTN EXPECTED T_DSN="" T_UNLOAD PENDING=0; ! IN CASE IT ISNT %END; ! ROUTINE RELEASE ! %ROUTINE REPORT PRIVATE ATTN %IF REQ_PRIVATE ATTN=0 %THENRETURN P_DEST=REQ_PRIVATE ATTN ! THE REST IS AS RECEIVED FROM CONTROLLER. PASS IT ON MYPON(P) %END; ! REPORT PRIVATE ATTN ! ATTN=(T_STREAMR0>>8)&X'FF' %IF T_GTS=0 %THEN ATTN=ATTN&X'DF'; ! X20 ALWAYS SET FOR MTS %IF ATTN&ENGINR#0 %THEN ATTN=(ATTN&(\ENGINR))!NOT AVAIL ! WE TREAT ENGINEER STATE AS SYNONYMOUS WITH NOT AVAILABLE? ! AGAIN: %IF ATTN=0 %THENRETURN %IF T_STATE>1 %THEN I=2 %ELSE I=T_STATE ! THUS LOADING,LOADED,CLAIMED AND UNLOADING=AUTO ->SW(I) ! SW(0):; ! NOT AVAILABLE %IF ATTN&AVAIL#0 %START T_STATE=MANUAL ATTN=ATTN&(\AVAIL) OPMESS(T_MNEM." available") ->AGAIN %FINISH ->SPURIOUS ! SW(1):; ! MANUAL %IF ATTN&NOT AVAIL#0 %START T_STATE=NOT AVAILABLE ATTN=ATTN&(\NOT AVAIL) OPMESS(T_MNEM." not available") ->AGAIN %FINISH %IF ATTN&AUTO#0 %START LOAD; ! INITIATE LOAD (SETTING STATE TO LOADING) ATTN=ATTN&(\AUTO) ATTN=ATTN&(\BT) ! IF MTS, BT MAY BE SET IF PREVIOUS TAPE WAS UNLOADED BY STOP/UNLOAD ! RATHER THAN BY SOFTWARE. TO BE IN MANUAL HERE WE MUST ALSO ! HAVE GONE NOT AVAILABLE, AVAILABLE AS WELL SO NO ACTION IS ! REQUIRED ON THE BT. ->AGAIN %FINISH %IF ATTN&SEC ATTN#0 %START ! THIS IS SPURIOUS. GTS DECKS FREQUENTLY FAIL TO DELIVER THE ONLINE ATTN ! IF IT IS PRESSED WHILE LOADING. THE DECK DOES GO TO AUTO HOWEVER. ! OPS THEN DO RESET/ONLINE, AND WE GET THE RESET AS THIS. ATTN=ATTN&(\SEC ATTN) ->AGAIN %FINISH ->SPURIOUS ! SW(2):; ! AUTO %IF ATTN&AUTO#0 %START ! THE DECK HAS GONE TO MANUAL BEHIND OUR BACK. EG STOP IF MTS. ! WE MUST ASSUME THAT A NEW TAPE HAS BEEN LOADED. ATTN=ATTN&(\AUTO) ATTN=ATTN&(\BT); ! MIGHT BE FOR MTS RELEASE LOAD; ! AND INITIATE A RELOAD ->AGAIN %FINISHELSEIF ATTN&BT#0 %START ! BT WITHOUT AUTO %IF REQ_STATE=ATTN EXP %OR REQ_CHAIN=PRIVATE %START ATTN=ATTN&(\BT) %IF REQ_STATE=ATTN EXP %THEN TERMINATE(-1,1) %C %ELSE REPORT PRIVATE ATTN ->AGAIN %FINISH %FINISHELSEIF ATTN&SEC ATTN#0 %START ! MUST BE GTS. THIS BIT IS KNOCKED OUT ABOVE FOR MTS ! GTS USES THIS TO REPORT ! 1) RESET HAS BEEN PRESSED OR VACUUM LOST AND THE DECK IS NOW IN MANUAL ! 2) THE OFFLINE PART OF A SKIP TM HAS FAILED BACUSE OF BLANK TAPE ! OR AN IDENTIFIER ERROR(IF INITIATED AT BT). ! WE DONT HAVE UPDATED STATUS BYTES AT THIS POINT TO TELL US WHICH IT ! WAS AND IT WOULD BE AN ALMIGHTY HASSLE TO FETCH THEM, SO, IF STATE IS ! CLAIMED AND AN ATTENTION EXPECTED, WE DON'T KNOW ! WHETHER THE DECK IS NOW IN MANUAL(CASE 1) OR STILL IN AUTO(2). ! WE MUST FORCE IT INTO A KNOWN STATE, IE UNLOAD IT. THIS IS PRETTY ! DRASTIC, BUT HOPEFULLY VERY VERY RARE. ATTN=ATTN&(\SEC ATTN) %IF T_STATE=CLAIMED %START OPMESS(T_MNEM." manual when in use") %IF REQ_STATE=ATTN EXP %START; ! THIS IS THE DOUBTFUL ONE TELL USER T_LOAD STATE=6 LOAD; ! EVEN IF IT IS ALREADY OFF, THIS RESETS THINGS AND TELLS VOLUMS ->AGAIN %FINISH %FINISH ! SO IF WE GET HERE, IT IS GENUINELY OFF LINE, SINCE 'SKIP TM' IS NOT ! DONE IN 'LOAD'. RELEASE T_STATE=MANUAL OPMESS(T_MNEM." unloaded") ->AGAIN %FINISHELSEIF ATTN&TM#0 %START %IF REQ_STATE=ATTN EXP %OR REQ_CHAIN=PRIVATE %START ATTN=ATTN&(\TM) %IF REQ_STATE=ATTN EXP %THEN TERMINATE(-1,0) %C %ELSE REPORT PRIVATE ATTN ->AGAIN %FINISH %FINISHELSEIF ATTN&NOT AVAIL#0 %START ATTN=ATTN&(\NOT AVAIL) OPMESS(T_MNEM." not available") RELEASE T_STATE=NOT AVAILABLE ->AGAIN %FINISHELSEIF ATTN&HOLD#0 %START %IF T_GTS=0 %START; ! MTS ONLY ATTN=ATTN&(\HOLD) OPMESS(T_MNEM." manual when in use") %IF T_STATE=CLAIMED %IF REQ_STATE=0 %START ! CLAIMED AND IDLE, OR LOADED. NOT LOADING OR UNLOADING. T_LOADSTATE=6 LOAD; ! UNLOAD ENTRY POINT %FINISHELSESTART ! CLAIMED AND IN USE, OR LOADING OR UNLOADING T_UNLOAD PENDING=1 %UNLESS T_STATE=UNLOADING %FINISH ->AGAIN %FINISH %FINISH ! AND DROP THRU' TO.. ! SPURIOUS: REPORT("SPURIOUS ATTENTION(S)") %END; ! ROUTINE ATTENTION ! ! %ROUTINE TERMINATE(%INTEGER NORMAL,BT) !********************************************************************** ! ENTERED ON CHAIN TERMINATION. ! NORMAL=0 FOR NORMAL TERMINATION, ! >0 FOR ABNORMAL TERMINATION, ! =-1 IF WE ENTERED VIA ATTENTION FOR EXPECTED BT OR TM, ! WHEN BT=1 OR 0 RESPECTIVELY. ! THIS ENTRY FOR CHAINS 16,17(SKIP TM FORE AND AFT),18(REWIND) ! AND NOTIONAL CHAIN 0, SEE US(5) BELOW. !********************************************************************** %CONSTINTEGER ERROR CLASSES=7 ! %CONSTSTRING(14)%ARRAY USMESS(1:ERROR CLASSES)= %C "LOST DEVICE", "LOST POSITION", "REV BT", "IRRECOVERABLE", "RECOVERABLE", "STIE/MTIE/RIPE", "UNDEFINED" ! %INTEGER PSTAT,FINAL COMMAND,ERROR CLASS,SKIP,REMBC,FLAG %SWITCH OK(0:MAX CHAINS),US(1:ERROR CLASSES),LS,TM(1:MAX CHAINS) ! %INTEGERFN DIAGNOSE ! ENTERED ON ABTERM WITH UNSUCCESSFUL IN PSTAT TO DIAGNOSE ERROR BITS ! IN TERTIARY STATUS T0-T7 ! RETURNS ERROR CLASS. ! ! THE INTERPRETATION OF THE TERTIARY STATUS BITS FOLLOWS, TOGETHER WITH ! THEIR ASSIGNMENT TO ONE OF SEVEN CLASSES. THE CLASSES ARE: ! ! 1 - LOST DEVICE ! 2 - EITHER LOST POSITION OR SHOULD NEVER HAPPEN SO WE HAVE A BUG. ! 3 - REVERSED INTO BT ! 4 - COMMAND FAILED AND THEIR IS NO POINT IN RETRYING, BUT POSITION ! IS OK, AND THE USER MAY CONTINUE. ! 5 - COMMAND FAILED AND SHOULD BE RETRIED. ! 6 - ADVISORY (JUST LOG IT FOR ENGINEERS SAKE) ! 7 - UNDEFINED. SHOULD NEVER BE SET. ! ! SOME OF THE BITS INDICATE ERRORS IN THE STRUCTURE OF A BLOCK - ! EG 'NON VALID NRZI BLOCK', 'NO PREAMBLE', ETC. ! IT MIGHT BE THOUGHT THAT SINCE A BLOCK, ALBEIT DEFORMED, WAS DETECTED ! IT IS SAFE TO SKIP BACK OVER IT FOR A RETRY. HOWEVER, THE BLOCK MIGHT ! NOT BE DETECTED IN REVERSE AND POSITION WOULD THUS BE LOST. ALL SUCH ! BITS ARE THEREFORE ASSIGNED TO CLASS 2. THIS MAY BE TOO SEVERE IN THE ! LIGHT OF EXPERIENCE. ! 'NO POSTAMBLE' HAS BEEN RECLASSIFIED FROM 2 TO 5. IT WAS FOUND TO OCCUR ! SPURIOUSLY VERY OFTEN WITH UTIE, AND SO FAR HAS BEEN FOUND SAFE TO RETRY. ! ON THE OTHER HAND, EXPERIENCE HAS SHOWN THAT 'NO PREAMBLE' MUST VERY ! DEFINITELY NOT BE RETRIED. ! ! IN THE FOLLOWING CLASSIFICATIONS THE BITS IN LONGINTEGER T07 ARE ! NUMBERED FROM THE MOST SIGNIFICANT END A LA ICL. ! ! MTS TERTIARY STATUS BITS ! --- -------- ------ ---- ! N CLASS MEANING ! ! 0 1 MANUAL ! 1 1 NOT AVAILABLE ! 2-7 7 UNDEFINED ! 8 2 IPE WE DONT KNOW WHETHER THE ERROR ! 9 2 2*RIPE WAS ON THE COMMAND GOING OR DATA ! 10 2 SRNH COMING, SO POSITION IS LOST. ! 11-15 7 UNDEF ! 16 2 ILLEGAL COMMAND A BUG ! 17 2 ILLEGAL MODE DITTO ! 18 4 ILLEGAL DATA CE MODE ONLY ! 19 4 DOUBLE FILLER ONLY WITH A18 ! 20 3 REVERSED INTO BT ! 21 2 NO RING FOR WRITE A BUG ! 22 2 DECK BUSY SHOULD NEVER HAPPEN, SO BUG ! 23 7 UNDEF ! 24 5 VRC ! 25 2 NON VALID NRZI BLOCK ! 26 5 UTIE ! 27 5 SKEW ! 28 2 NO PREAMBLE(PE) ! 5 CRC(NRZI) ! 29 5 DATA SHORT(PE) HAPPENS FOR PARTICULAR DATA PATTERN ! AND STIE CORRECTION ! 5 LRC(NRZI) ! 30 5 NO POSTAMBLE(PE) ! 5 TIE(NRZI) ! 31 5 THRESHOLD ! 32 2 IDENTIFIER A BUG(EXCEPT IN LOAD SEQUENCE ! 33 2 NO DATA WRITTEN WHAT DOES THIS MEAN??? ! 34 2 INVALID NRZI BLOCK OF A DIFFERENT KIND!! ! 35 7 UNDEF ! 36 2 25 FEET BLANK ! 37 2 RETURN FAILED. DEVICE TIME OUT ! 38 2 POOR ERASURE. NOW YOU SEE IT, NOW YOU DONT ! 39-47 7 UNDEF ! 48 6 RIPE ! 49-50 7 UNDEF ! 51 6 STIE ERROR RECOVERED ON FLY ! 52-63 7 UNDEF ! ! SINCE SOME BITS ARE ASSIGNED TO DIFFERENT CLASSES DEPENDING ON THE MODE ! WE NEED TWO SETS OF MASKS ! %CONSTLONGINTEGERARRAY PE ERROR MASKS(1:ERROR CLASSES)= %C X'C000000000000000', X'00E0C608CE000000', X'0000080000000000', X'0000300000000000', X'000000B700000000', X'0000000000009000', X'3F1F014031FF6FFF' %CONSTLONGINTEGERARRAY NRZI ERROR MASKS(1:ERROR CLASSES)= %C X'C000000000000000', X'00E0C640EE000000', X'0000080000000000', X'0000300000000000', X'000000BF00000000', X'0000000000009000', X'3F1F010011FF6FFF' ! ! GTS TERTIARY STATUS BITS: ! --- -------- ------ ---- ! ! N CLASS MEANING ! ! 0 1 MANUAL ! 1 1 NOT AVAILABLE ! 2-7 7 UNDEFINED ! 8 2 IPE ! 9 2 2*IPE ! 10 2 SRNH ! 11 2 BUFFER ERROR ! 12 2 FORMATTER ERROR ! 13 2 BUFFER PE ! 14-15 7 UNDEF ! 16 2 ILLEGAL COMMAND ! 17 2 ILLEGAL MODE ! 18 4 INCOMPLETE CE BURST ! 19 4 DITTO ! 20 3 REVERSED INTO BT ! 21 2 NO RING FOR WRITE ! 22 2 BUSY ! 23 7 UNDEF ! 24 5 ARA ERROR(GCR) ! 25 7 NRZ ERROR THIS SHOULD ALWAYS QUALIFY OTHER BITS ! IN THE MEDIA BYTE, SO WE DONT EXPECT TO ! SEE IT ALONE. IF WE DO, LOG IT. ! 26 5 UNCORRECTABLE ERROR ! 27 7 UNDEF ! 28 5 DATA CHECK THIS IS 'OR' OF 12 OTHER CONDITIONS. ! IE CRC ERROR SOME OF THEM ARE MORE SEVERE THAN CLASS 5 ! WTM CHECK AND ARE SET ELSEWHERE AS WELL, SO WONT ARISE ! LRC ERR(NRZ) HERE. THE REMAINDER ARE ALL CLASS 5. SOME ! MULTI TIE OF THEN APPEAR ELSEWHERE AS WELL, BUT FOUR ! (GCR/PE) CONDITIONS APPEAR ONLY IN STATUS BYTES BEYOND ! 7, SO WE USE THIS TO CATCH THEM. THEY ARE AS ! SHOWN AT LEFT. ! 29 5 END DATA CHECK A29 AND A30 GO TOGETHER TO GIVE:- ! 30 2 PARTIAL RECORD 10=NO PREAMBLE AND 11=NO POSTAMBLE. ! (GCR/PE) WE WOULD LIKE TO TREAT THESE AS CLASS 2 AND ! 5 RESPECTIVELY BUT A30 IS THE WRONG WAY ROUND ! FOR THIS TO WORK ON A 1 BIT MASK BASIS. SO ! IF A29 IS SET, WE INVERT A30 BEFORE MASKING ! 31 5 CRC/ACRC ERROR(NRZ/GCR) ! 32 2 IDENTIFIER ERROR(GCR/PE) NOT SAME AS MTS ! 33 2 NO DATA WRITTEN ! 34 2 CHARACTER IN GAP ! 35 2 VELOCITY ERROR ! 36 2 BLANK TAPE 25' PE/NRZ, 15' GCR ! 37 2 STEP TIMEOUT BYTE 10 HAS REJECT CODES ! 38 2 POOR ERASURE ! 39-47 7 UNDEF ! 48 6 RIPE ! 49 2 INCOMPATIBLE MODE THIS IS SAME AS MTS BIT A32. WE KEEP ! CLOSE CONTROL OF THE MODE SO THIS IS A BUG ! 50 7 UNDEF ! 51 6 STIE(GCR/PE) ! 52 6 MTIE(GCR) ! 53-63 7 UNDEF ! ! BYTES 8-14 HAVE ADDITIONAL INFO, BUT THIS IS EITHER DUPLICATED ABOVE OR ! FOR ADVISORY PURPOSES ONLY AND IS NOT USED IN DIAGNOSIS. ! ! ALTHOUGH THE EXACT INTERPRETATION OF SOME BITS IS MODE DEPENDANT, THERE ! ARE NO DIFFERENCES IN THE RESULTING CLASS ASSIGNMENTS. ! WE ONLE NEED ONE SET OF MASKS THEREFORE. ! %CONSTLONGINTEGERARRAY GTS ERROR MASKS(1:ERROR CLASSES)= %C X'C000000000000000', X'00FCC602FE004000', X'0000080000000000', X'0000300000000000', X'000000AD00000000', X'0000000000009800', X'3F03015001FF27FF' ! ! SINCE ALL POSSIBLE CLASS 5 AND 6 ERRORS ARE MASKED OFF AT THE START ! OF EVERY MULTI-COMMAND READ RETRY CHAIN, EACH SUCH CHAIN CAN ! TERMINATE BEFORE THE LAST COMMAND, ONLY FOR CLASSES 1,2,3 AND 4. ! FOR CLASSES 1 AND 2, POSITION IS ALREADY LOST BY VIRTUE OF THE ERROR, ! SO THE POSITION OF THE FAILING LBE(CW) IS IRRELEVANT. IT LOOKS UNLIKELY ! THAT THE CURRENTLY DEFINED CLASS 4 ERRORS (CONCERNING THE DATA COUNT ! IN CE MODE) COULD ARISE OTHER THAN ON THE PRIMARY READ OF A SEQUENCE, ! BUT IT IS POSSIBLE IF SUCH ERRORS ARE MASKED AT THE DEVICE LEVEL BY ! OTHER ERRORS. IN ANY CASE, TO CATER FOR THE RECLASSIFICATION OF SOME ! BITS, WE ARE PREPARED TO DO A FINAL REPOSITIONING FROM A CLASS 4 ! ERROR OCCURRING ANYWHERE THRU' A MULTI-COMMAND READ CHAIN. IN ALL ! CASES, HOWEVER, WE ASSUME THAT THE FAILING LBE(CW) WILL HAVE BEEN ! EFFECTIVE IN TRAVERSING ITS BLOCK. ! ! THE SAME PROBLEM DOES NOT ARISE FOR WRITE AND WRITE TM RETRIES ! WHICH ARE MUCH LESS COMPLEX. ! ! %LONGINTEGER T07 %INTEGER I %LONGINTEGERARRAYNAME ERROR MASKS ! T07=T_T07 %IF T_GTS=0 %START; ! MTS DECK %IF T_MODE&3=3 %THEN ERROR MASKS==PE ERROR MASKS %C %ELSE ERROR MASKS==NRZI ERROR MASKS %FINISHELSESTART ERROR MASKS==GTS ERROR MASKS ! INVERT A30 IF A29 SET TO GET NO PREAMBLE AND NO POSTAMBLE RIGHT. WE DONT ! EXPECT TO SEE A30 ON ITS OWN BUT IF WE DO,THE EFFECT IS TO GIVE THE MORE SEVERE ! ERROR WHICH IS CORRECT. T07=T07!!((T07&X'0000000400000000')>>1) %FINISH ! %FOR I=1,1,ERROR CLASSES %CYCLE %IF T07&ERROR MASKS(I)#0 %THENEXIT %REPEAT ! SO I HAS ERROR CLASS. %RESULT=I %END; ! FN DIAGNOSE ! !********* TERMINATE STARTS HERE ********** ! %IF REQ_STATE=0 %START REPORT("SPURIOUS TERMINATION") %RETURN %FINISH %IF T_STREAMR1=-1 %START; ! TIMEOUT REPORT("TIME-OUT") REP_P2=3 ->REPLY %FINISHELSESTART; ! NOT TIMOUT %IF NORMAL=-1 %THEN ->OK(REQ_CHAIN) ! IE ENTERED VIA ATTENTION FOR EXPECTED, NON-PRIVATE, TM OR BT ! CHAINS 16,17,18 AND 0 ONLY. PSTAT=(T_STREAMR0>>8)&X'FF' REMBC=T_STREAMR1&X'3FFFF'; ! REMAINING BYTE COUNT. %IF NORMAL=0 %START FINAL COMMAND=CHAIN START(REQ_CHAIN)+CHAIN LENGTH(REQ_CHAIN)-1; ! THE LAST ! REP_P2=0 ->OK(REQ_CHAIN) %UNLESS REQ_CHAIN=PRIVATE ! OTHERWISE DROP THRU' TO 'REPLY'. %FINISHELSESTART; ! ABTERM FINAL COMMAND=CHAIN START(REQ_CHAIN)+T_STREAMR0&X'FF' ! GET GPC SENSE DATA. ! IN DCU CASE, THE H/W SENSE INTO POSTAMBLE IS NOT DONE FOR UNMASKED ! L,S,X,Y, BUT WE DONT NEED IT IN THAT CASE. %IF P_P4&X'FF'=X'80' %START; ! SENSE OK MOVE(15,D_SENSDATAD+1,ADDR(T_T0)) T_SSTAT=BYTEINTEGER(D_SENSDATAD) %FINISHELSESTART ! EITHER GPC SOFTWARE SENSE FAILED, OR DCU H/W SENSE FAILED REPORT("NONSENSE") ! NO IDEA WHAT DEVICE STATE IS. MAYBE LOST DEVICE OR POSITION. REP_P2=3 ->REPLY %FINISH ! NOW CHECK FOR CONTROLLER ERRORS FLAG=(T_STREAMR0>>16)&X'FF' %IF FLAG=X'41' %START REPORT("CDE"); ! THIS IS ACTUALLY ACTIVATE FAILS FOR DCU ! PROBABLY HAVEN'T MOVED TAPE IF IT SHOULD HAVE BEEN. BETTER BAIL OUT REP_P2=3 ->REPLY %FINISHELSEIF FLAG=X'42' %START ! THIS CASE ONLY ARISES FOR DCU REPORT("INITIALISE FAILURE") REP_P2=3 ->REPLY %FINISH ! SO IT MUST BE EITHER U/S OR UNMASKED L,S,X,Y %UNLESS REQ_CHAIN=PRIVATE %START; ! NO DIAGNOSES OR RETRYIES FOR PRIVATE %IF PSTAT&128#0 %START; ! UNSUCCESSFUL ERROR CLASS=DIAGNOSE REPORT(USMESS(ERROR CLASS)) %UNLESSC (ERROR CLASS=1 %AND T_LOAD STATE=2) %ORC (T_LOAD STATE=3 %ANDC ((T_GTS=0 %AND T_T4&128#0) %ORC (T_GTS#0 %AND T_T6&64#0))) ! DONT REPORT NOTAVAIL OR MANUAL FOR INITIAL REWIND IN LOAD. ! WE EXPECT IT FOR DECKS UNLOADED AT START-UP. ! ALSO SUPPRESS REPORT FOR 'ILLEGAL MODE' WHILE ESTABLISHING IT ! DURING LABEL READ. ->US(ERROR CLASS) %FINISHELSEIF PSTAT&3#0 %START; ! TM OR ET ->TM(REQ_CHAIN) %FINISHELSEIF PSTAT&12#0 %START; ! LONG OR SHORT REP_P2=1 ->LS(REQ_CHAIN) %FINISHELSESTART; ! WHAT CAUSED IT THEN ???? REPORT("SPURIOUS ABTERM") REP_P2=3 ->REPLY %FINISH %FINISH; ! NOT PRIVATE. PRIVATE DROPS OUT TO 'REPLY' %FINISH; ! ABTERM %FINISH; ! NOT TIMEOUT ! ! CAUTION. DROP THRU' HERE FOR PRIVATE CHAINS ! REPLY: %IF REQ_CHAIN=PRIVATE %START REP_P3=T_STREAMR0 REP_P4=T_STREAMR1 %FINISH ! NOTOINAL P5 AND P6 ALWAYS GO BACK WITH T0-T7 REQ_STATE=0 MYPON(RECORD(ADDR(REP))) %IF REP_DEST#0; ! REPLY TO USER IF NOT 'LOAD' %IF T_UNLOAD PENDING#0 %START ! ONLY IF STATE IS LOADING OR CLAIMED T_UNLOAD PENDING=0 T_LOAD STATE=6; ! UNLOAD ENTRY. IF WE WERE ABOUT TO REPLY TO LOAD ! THIS TAKES THE PLACE OF THE REPLY. REP_DEST=0; ! IF IT WAS A USER WE WANT TO GO TO 'LOAD AS WELL %FINISH LOAD %IF REP_DEST=0 %RETURN ! ! !*********** OK *********** OK *********** OK *********** OK *********** ! OK(0): ! WE COME HERE VIA 'ATTENTION' AFTER GETTING A REVERSE BT FAILURE AT ! US(5) BELOW, AND THE RESULTING ATTENTION HAS COME. ! THE REPLY IS ALL SET UP. ->REPLY ! !------------------------------------------------------------------ ! OK(1):OK(2):OK(3):OK(4):OK(5):OK(6):OK(7):OK(8):OK(9):OK(10):; ! ALL READS LS(1):LS(2):LS(3):LS(4):LS(5):LS(6):LS(7):LS(8):LS(9):LS(10): ! LONG/SHORT ONLY ABTERM. GOES BACK TO USER WITH P2=1 AND P4 LONG/SHORT. ! THE LATTER DISTINGUISHING IT FROM MEDIA ERROR. ! ! ARE WE ON THE RIGHT SIDE OF THE BLOCK SKIP=REQ_TARGET POS-((POSMASK>>FINAL COMMAND)&1) ! TARGET POS SET IN ACCEPT REQUEST. 2**FINAL LBE(CW) IN POSMASK SET IF THAT ! LBE(CW) LEFT US AFTER BLOCK, ELSE BEFORE. ! SO SKIP=1 MEANS A FORWARD SKIP REQUIRED ! =0 MEANS POSITION CORRECT ! =-1 MEANS A REVERSE SKIP REQUIRED REP_P3=REQ_LENGTH %IF PSTAT&4#0 %START; ! LONG BLOCK %IF SKIP#0 %START ! IT WAS READ IN A DIRECTION OTHER THAN THE ORIGINAL REQUEST. THIS ! CANT BE COUNTED A SUCCESS SINCE WEVE FETCHED THE WRONG END. ! SIMULATE A MEDIA ERROR AND CONTINUE WITH RETRIES. ->US(4) %FINISH ! SO WE READ IN THE RIGHT DIRECTION. TELL USER IT WAS LONG REP_P4=2 ! LENGTH IS CORRECT %FINISHELSEIF PSTAT&8#0 %START; ! SHORT BLOCK REP_P3=REQ_LENGTH-REMBC; ! LATTER IS UNEXPIRED COUNT %IF (REVMASK>>FINAL COMMAND)&1#0 %AND REQ_READORS&NODATA=0 %START ! NOT READCHECK AND READ IN REVERSE. DATA IS AT TOP OF BUFFER REP_P3=-REP_P3; ! INDICATE THIS TO USER %FINISH REP_P4=1; ! SHORT FOR USER %FINISH %IF REQ_READORS&NODATA#0 %AND REP_P2=0 %THEN REP_P4=REQ_RETRIES ! 'NO DATA' SET, SO IT WAS A READCHECK. TELL RETRIES. %UNLESS REQ_RETRIES=0 %START %IF LENGTH(T_DSN)>7 %THEN LENGTH(T_DSN)=0 ! MIGHT BE IF WERE IN LOAD SEQUENCE OF NON-STANDARD LABEL PRINTSTRING(T_MNEM." ".T_DSN." ".HTOS(REQ_RETRIES,3)." READ RETRY OK ") %FINISH ! ! THATS THE REPLY ALL SET UP TEST FINAL SKIP: ! CAUTION. WE COME HERE FROM US(4) ALSO %IF SKIP=0 %THEN ->REPLY ! ! SO FINAL SKIP REQUIRED ! THE ORIGINAL USER'S ASL IS STILL SET UP IN REQ_ADDR ETC, SO NO NEED ! FOR A DUMMY. DO FINAL SKIP: ! CAUTION*** WE COME HERE FROM TM(1) AND TM(2) ALSO. %IF SKIP>0 %THEN REQ_CHAIN=20 %ELSE REQ_CHAIN=21 ! THESE SKIPS IGNORE TMS FIRE CHAIN %RETURN ! !------------------------------------------------------------------ ! OK(11):OK(12):; ! WRITE ,WRITE TM %UNLESS REQ_RETRIES=0 %START REP_P4=REQ_RETRIES PRINTSTRING(T_MNEM." ".T_DSN." ".HTOS(REQ_RETRIES,3)." WRITE RETRY OK ") %FINISH ->REPLY ! !------------------------------------------------------------------ ! OK(13):; ! REPOSITION AND ERASE FOR WRITE AND WRITE TM RETRY ! COME HERE FROM TM(13) ALSO REQ_CHAIN=REQ_FINAL CHAIN; ! SET UP IN 'ACCEPT REQUEST' ! EVERYTHING ELSE REMAINS OK FIRE CHAIN %RETURN ! !------------------------------------------------------------------ ! OK(14):OK(15):; ! SKIP BLOCKS, FORE AND AFT TEST SKIP END:; ! CAUTION. ALSO COME HERE FROM SKIP TM FORE AND AFT %IF T_UNLOAD PENDING#0 %START; ! HOLD HAS BEEN KEYED REP_P2=3 ->REPLY %FINISH REQ_COUNT=REQ_COUNT+1 %IF REQ_COUNTREPLY ! !------------------------------------------------------------------ ! OK(16):OK(17):; ! SKIP TMS, FORE AND AFT %IF REQ_STATE=TERM EXP %THEN REQ_STATE=ATTN EXP %ANDRETURN ! THAT WAS THE TAPE MOVEMENT BEGINNING. WE COME BACK HERE VIA ! ROUTINE ATTENTION WHEN WE HIT TM OR BT. %IF BT#0 %START; ! MUST HAVE NEEN REVERSE REP_P2=4 REP_P3=REQ_COUNT*REQ_TM+REQ_COUNT1 ->REPLY %FINISH ! SO IT WAS A TM %IF REQ_TM=0 %THEN ->TEST SKIP END ! SPECIAL FOR RESTORES. IMPLIES 1 TM/LOGICAL FILE AND NO TM LOOK-AHEAD REQ_COUNT1=REQ_COUNT1+1 %IF REQ_COUNT1=REQ_TM %START; ! ONE FILES WORTH REQ_COUNT1=0 ->TEST SKIP END %FINISH FIRE CHAIN %RETURN ! !------------------------------------------------------------------ ! OK(18):; ! REWIND %IF REQ_STATE=TERM EXP %THEN REQ_STATE=ATTN EXP %ANDRETURN ! THAT WAS START OF MOVEMENT. COME BACK VIA ATTN AT BT. ->REPLY ! !------------------------------------------------------------------ ! OK(19):; ! ERASE ->REPLY ! !------------------------------------------------------------------ ! OK(20):OK(21):; ! FINAL POSITION SKIP. REPLY ALL SET UP ->REPLY ! !------------------------------------------------------------------ ! OK(22):; ! TEST FOR TM. SUCCESS MEANS TM NOT SEEN ON REVERSE SKIP REQ_CHAIN=16; ! REPLACE ORIGINAL CHAIN WHICH WAS SKIP FORE TO TM FIRE CHAIN %RETURN ! !------------------------------------------------------------------ ! OK(23):OK(24):OK(25):; ! UNLOAD, SPC, QSPC ->REPLY ! ! !*********** US *********** US *********** US *********** US *********** ! ! ADMINISTRATIVE SKIPS COME HERE ALSO IF THEY FAIL. THEY SHOULD ONLY APPEAR ! AS CLASSES 1 OR 2. ! US(1):; ! OFFLINE ! WE GET HERE FOR MANUAL/NOTAVAIL DURING A CHAIN. WE COULD DO THE STATE ! CHANGE HERE, BUT FOR CONSISTENCY WE LEAVE IT TO BE DEALT WITH BY ! 'ATTENTION' WHEN THE STATE CHANGE COMES. ! IN THE MEANTIME THE USER WILL CONTINUE TO GET REPLIES OF 3 FROM HERE ! IF HE PERSISTS. ! DROP THRU' TO ..... ! !------------------------------------------------------------------ ! US(2):; ! LOST POSITION ! CAUTION***. COME HERE FROM US(1) ALSO REP_P2=3; ! DISASTER ->REPLY ! !------------------------------------------------------------------ ! US(3):; ! REVERSED INTO BT. READ REV OR SKIP REV ONLY ! THERE IS NOW A BT ATTN TO COME IF NOT GTS %IF REQ_CHAIN=2 %OR REQ_CHAIN=15 %START ! OK. SET UP REPLY COMPLETELY. REP_P2=4 %IF REQ_CHAIN=15 %THEN REP_P3=REQ_COUNT; ! NUMBER SKIPPED BEFORE HERE %FINISHELSESTART PRINTSTRING(T_MNEM."***UNEXPECTED REV BT *** ") REP_P2=3; ! WE HAVEN'T CATERED FOR THIS. ALL HELL MAY NOW BREAK LOOSE %FINISH %IF T_GTS=0 %START; ! MTS. SET UP TO WAIT FOR ATTN REQ_CHAIN=0; ! JUST TO WAIT FOR 'NORMAL' TERM FROM 'ATTENTION' REQ_STATE=ATTN EXP %RETURN %FINISHELSE ->REPLY ! !------------------------------------------------------------------ ! US(4):; ! STRAIGHT BACK ! CAUTION***. COME HERE FROM US(5) ALSO REP_P2=1 %IF T_T2&X'30'#0 %THEN REP_P4=4; ! BAD CE DATA COUNT ! NOW A FINAL REPOSITION MAY BE REQUIRED IF IT WAS A READ %IF REQ_CHAIN<=LAST READ CHAIN %START SKIP=REQ_TARGET POS-((POSMASK>>FINAL COMMAND)&1) ->TEST FINAL SKIP %FINISH ->REPLY ! !------------------------------------------------------------------ ! US(5):; ! RETRIABLE ! WE DO NOT EXPECT TO GET CLASS 5 ERRORS OM COMMANDS OTHER THAN READS ! WRITE AND WRITE TM, FOR ALL OF WHICH RETRIES ARE DEFINED (AND FOR ! WHICH THE EMBEDDED SKIPS INVOLVED IN MULTIPLE RETRY CHAINS HAVE ! CLASS 5 ERRORS MASKED OFF). IF THIS INTERPRETATION OF THE ERROR ! BITS IS INCORRECT AND A CLASS 5 ERROR OCCURS ON A STRAIGHT SKIP, REWIND, ! ERASE, ETC. WE WILL LOG IT HERE AND GIVE THE USER A DISASTER(3) REPLY, ! SINCE WE MAY HAVE LOST POSITION. IN THE LIGHT OF EXPERIENCE WE MAY ! HAVE TO RECLASSIFY THE BITS TAKING INTO ACCOUNT THE ACTUAL DEVICE ! COMMAND IN EXECUTION AT FAILURE. ! %IF REQ_CHAIN<=LAST RETRY CHAIN %START; ! ALL THE ONES WE EXPECT REQ_RETRIES=REQ_RETRIES+1 %IF REQ_RETRIES>REQ_RETRY LIMIT %START %IF LENGTH(T_DSN)>7 %THEN LENGTH(T_DSN)=0 ! MIGHT BE FOR LOAD OF NON-STANDARD LABELLED PRINTSTRING(T_MNEM." UNRECOVERED ERROR ".T_DSN." ") ->US(4) %FINISH ! IE, TEST FOR FINAL SKIP IF READ, OTHERWISE STRAIGHT BACK %IF REQ_CHAIN<=LAST READ CHAIN %START %IF REQ_CHAIN=REQ_FINAL CHAIN %THEN REQ_CHAIN=REQ_CHAIN-7 %C %ELSE REQ_CHAIN=REQ_CHAIN+1 ! SET BACK TO START+1, ELSE NEXT IN BASIC SEQUENCE %FINISHELSESTART; ! WRITE OR WRITE TM REQ_CHAIN=13; ! SKIP REV AND ERASE WRITTEN LENGTH %FINISH FIRE CHAIN %RETURN %FINISH ! ! SO WE SHOULDN'T BE HERE. REP_P2=3 PRINTSTRING(T_MNEM."*** UNEXPECTED RECOVERABLE ERROR *** "); ! ITS 'REPORTED' ABOVE ->REPLY ! !------------------------------------------------------------------ ! US(6):; ! ADVISORY ONLY(SHOULD ONLY BE READS) US(7):; ! UNDEFINED ! HAS BEEN 'REPORTED' ABOVE. TREAT AS SUCCESS OTHERWISE ->OK(REQ_CHAIN) ! ! ! !*********** TM *********** TM *********** TM *********** TM *********** ! TM(1):TM(2):; ! READ FORE AND AFT %IF REQ_RETRIES=0 %START ! JUST TO MAKE SURE WE ARE ON THE PRIMARY READ OF A SEQUENCE %IF REQ_CHAIN=1 %THEN SKIP=-1 %ELSE SKIP=1 REP_P2=4 ->DO FINAL SKIP %FINISH ! ELSE DROP THRU' TO...... ! !------------------------------------------------------------------ ! TM(3):TM(4):TM(5):TM(6):TM(7):TM(8):TM(9):TM(10): TM(16):TM(17):TM(18):TM(20):TM(21):TM(23):TM(24):TM(25): ! READ RETRIES,SKIP TM FORE AND AFT,REWIND,POSITIONING SKIPS, ! UNLOAD,SEND PROPS, QUALIFIED SPC REPORT("UNEXPECTED TM") REP_P2=3 ->REPLY ! !------------------------------------------------------------------ ! TM(11):TM(12):TM(19):; ! MUST BE ET AFTER WRITE, WRITE TM OR ERASE ! THE WRITE WAS OTHERWISE OK. REP_P2=4 ->REPLY ! !------------------------------------------------------------------ ! TM(13):; ! ET ON ERASE DURING WRITE(TM) RETRY 'SKIPREV,ERASE' REP_P2=4; ! THIS REMAINS THE REPLY IF IT FINALLY SUCCEEDS ->OK(13) ! !------------------------------------------------------------------ ! TM(14):TM(15):; ! SKIP FORE AND AFT %IF REQ_TM#0 %THEN->TEST SKIP END ! IE EXACTLY AS SUCCESS IF TMS TO BE TREATED AS BLOCKS %IF REQ_CHAIN=14 %THEN SKIP=-1 %ELSE SKIP=1 REP_P2=4 REP_P3=REQ_COUNT ->DO FINAL SKIP ! !------------------------------------------------------------------ ! ! TM(16,17,18) DEFINED AT TM(3) ABOVE ! !------------------------------------------------------------------ ! ! TM(19) DEFINED AT TM(11) ABOVE ! !------------------------------------------------------------------ ! ! TM(20,21) DEFINED AT TM(3) ABOVE ! !------------------------------------------------------------------ ! TM(22):; ! LOOK-AHEAD FOR TM AFTER SKIP TM FORE. FOUND ONE REP_P2=4 REP_P3=REQ_COUNT*REQ_TM ->REPLY ! !------------------------------------------------------------------ ! ! TM(23,24,25) DEFINED AT TM(3) ABOVE ! !------------------------------------------------------------------ ! !*********** LS *********** LS *********** LS *********** LS *********** ! ! LS(1-10) DEFINED AT OK(1) ABOVE ! !------------------------------------------------------------------ ! LS(11):LS(12):LS(13):LS(14):LS(15):LS(16):LS(17):LS(18):LS(19):LS(20): LS(21):LS(22):LS(23):LS(24):LS(25): REPORT("SPURIOUS LONG/SHORT") REP_P3=3; ! FOR NOW TREAT THIS AS DISASTER SINCE IT SHOULD NEVER HAPPEN ->REPLY; ! AND IF IT DOES THERE MAY BE SOMETHING FUNDAMENTALLY WRONG. ! ! ! %END; ! ROUTINE TERMINATE ! ! %INTEGERFN ACCEPT REQUEST !********************************************************************** ! CHECKS USER REQUEST AND REFORMATS IT FOR USE BY 'FIRE CHAIN'. ! SINCE WE'VE GOT HERE WITH T AND REQ MAPPED VIA THE SNO FROM THE USER ! WE KNOW THE DECK IS LOADED AND CLAIMED. !********************************************************************** ! DEFINED REQUESTS (HISTORICALLY QUAINT) ARE: ! 0=ERASE ! 1=READ ! 2=WRITE ! 3=UNDEF ! 4=READ CHECK ! 5=PRIVATE ! 6=READ REV ! 7=UNDEF ! 8=SKIP BLOCKS ! 9=SKIP TMS ! 10=WRITE TM ! 11-16=UNDEF ! 17=REWIND %CONSTINTEGER TOP REQ=17 %CONSTBYTEINTEGERARRAY CHAIN(0:TOP REQ)= %C 19,1,11,0,1,PRIVATE,2,0,14,16,12,0(6),18 ! THESE ARE THE PRIMARY CHAINS TO EFFECT THE REQUEST.(SEE ARRAYS LBE(CW) ABOVE). %CONSTBYTEINTEGERARRAY FINAL CHAIN(0:TOP REQ)= %C 0,9,11,0,9,0,10,0,0,0,12,0(6),0 ! THESE ARE THE FINAL CHAINS FOR THOSE WHICH CAN BE RETRIED ! %CONSTINTEGER READMASK=X'52'; ! READ,READ REV,READ CHECK %CONSTINTEGER WRITEMASK=X'405';! WRITE,ERASE,WRITETM %CONSTINTEGER XFERMASK=X'57'; ! ALL READS,WRITE,ERASE %CONSTINTEGER SKIPMASK=X'300'; ! SKIP BLOCK,SKIP TM %CONSTINTEGER SPADDRMASK=X'11'; ! ERASE, READ CHECK ! %INTEGER TYPE,TYPE BIT,CTRL ! %IF SSERIES=YES %START !..........SSERIES.........SSERIES..........SSERIES..........SSERIES ! %INTEGER I %INTEGERNAME LINK %RECORD(TCBF)%NAME TCB %FINISH;!.............................................................. ! %INTEGERFN COPY CONTROL BLOCK(%INTEGER VADDR,LEN,STL,STB,TOADDR) ! ! VADDR IS THE VIRTUAL ADDR OF THE USER CONTROL BLOCK. THIS IS SUPPOSED ! TO BE IN A LOCKED AREA (DLOCK), AND STL,STB ARE SUPPOSED TO CONTAIN ! THE ST DELIVERED BY THAT DLOCK, IE A VM CONSISTING SOLELY OF LOCKED SPACE. ! WE WISH TO COPY THE CONTROL BLOCK INTO THE DEVICE RECORD. ! SINCE THE USERS LST IS NOT LOCKED WE NEED TO ACCESS THE CONTROL BLOCK VIA ! THIS STB. ! IF WE VALIDATE THE CONTROL BLOCK VIA THE STB AND IT SUCCEEDS, THEN THE ! FORMER MUST BE IN LOCKED SPACE, AND WE CAN PROCEED TO COPY IT WITHOUT FEAR ! OF A VS ERROR. HOWEVER IT IS POSSIBLE THAT THE STB ITSELF IS RUBBISH ! SO TO CHECK THE EXISTENCE OF THE ST ENTRY ADDRESS WHICH THE CONTROL BLOCK ! VALIDATE WILL GO FOR, WE FIRST VALIDATE IT AS A PUBLIC ADDRESS. IF ! THIS SUCCEEDS THEN THE STE ALL EXISTS AND IN THE SAME SMAC. WE CAN ! THEREFORE GO AHEAD WITH THE CONTROL BLOCK VALIDATE WITHOUT FEAR OF A STORE ! TIMEOUT. ! THE CONTROL BLOCK VALIDATE MAY FAIL EITHER IF ITS SEGMENT IS OUTSIDE THE ! SUPPLIED STB LIMIT(EITHER ONE OR BOTH RUBBISH), OR IF THE CONTROL BLOCK IS ! NOT CONTAINED IN THE LOCKED SPACE DEFINED BY THE STB. ! NONE OF THIS GUARANTEES THAT WE ACTUALLY COPY THE USERS CONTROL BLOCK. ALL ! THE ABOVE CHECKS COULD SUCCEED ON GARBAGE ADDRESSES. HOWEVER, WE WILL NOT ! FALL OVER SETTING IT UP, AND WHAT HAPPENS AFTER DEPENDS ON WHAT THE DEVICE ! CONTROLLER MAKES OF THE SUPPOSED CONTROL BLOCK. %RECORDFORMAT COMF(%INTEGER OCPTYPE,IPLDEV,SBLKS,SEPGS,NDISCS, %C DDTADDR,GPCTABSIZE,GPCA,SFCTABSIZE,SFCA,SFCK,DIRSITE, %C DCODEDA,SUPLVN,KLOKCORRECT,DATE0,DATE1,DATE2, %C TIME0,TIME1,TIME2,EPAGESIZE,USERS,PROCMON,DQADDR, %C SACPORT,OCPPORT,ITINT,CONTYPEA,GPCCONFA,FPCCONFA,SFCCONFA, %C BLKADDR,DPTADDR,SMACS,TRANS,%LONGINTEGER KMON, %C %INTEGER SPDRQ,SMACPOS,SUPVSN,PSTVA,SECSFRMN,SECSTOCD, %C SYNC1DEST,SYNC2DEST,ASYNCDEST,MAXPROCS,INSPERSEC,ELAPHEAD, %C COMMSRECA,%INTEGERARRAY SP(0:13), %INTEGER %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) %CONSTRECORD(COMF)%NAME COM=X'80C00000' %INTEGER VSEG,STEA,LSTL,LSTB,RES,I %LONGINTEGER DR %IF VADDR<0 %THEN MOVE(LEN,VADDR,TOADDR) %ANDRESULT=0 ! IE IT WAS IN PUBLIC SO NO HASSLE ! VSEG=VADDR&X'7FFC0000' %IF STB&X'F0000000'#0 %THENRESULT=1 STEA=STB+(VSEG>>15); ! REAL ADDR OF ST ENTRY DR=X'1800000881000000'+STEA; ! STE, LENGTH 8 VIA PST *LD_DR; *VAL_(%LNB+1); *JCC_14, %RESULT=1; ! VAL GAVE 3, IE INVALID VALID: ! SO STEA EXISTS. NOW VALIDATE CONTROL BLOCK. FIRST SAVE LSTBR I=COM_LSTL *LB_I; *LSS_(0+%B); *ST_LSTL; *LSS_STL; *ST_(0+%B) I=COM_LSTB *LB_I; *LSS_(0+%B); *ST_LSTB; *LSS_STB; *ST_(0+%B) ! NOW DO VALIDATE RES=1 DR=LEN DR=X'1800000000000000'!(DR<<32)!VADDR; ! LEN BYTES *LD_DR; *VAL_(%LNB+1); *JCC_3, ! SO OK. RES=0 MOVE(LEN,VADDR,TOADDR) RESET LSTBR: I=COM_LSTL *LB_I; *LSS_LSTL; *ST_(0+%B) I=COM_LSTB *LB_I; *LSS_LSTB; *ST_(0+%B) %RESULT=RES %END; ! FN COPY CONTROL BLOCK ! ! ********** ACCEPT REQUEST STARTS HERE ********** REQ=0 REP=0; ! REPLY RECORD REP_DEST=P_SRCE REP_SRCE=P_DEST REP_P1=P_P1; ! IDENT ! REQ_LSL=P_P5 REQ_LSTBA=P_P6 ! TYPE=P_P2&X'FF' %IF TYPE>TOP REQ %THENRESULT=NOTOK; ! NOT DEFINED REQ_CHAIN=CHAIN(TYPE) %IF REQ_CHAIN=0 %THENRESULT=NOTOK; ! DITTO %IF TYPE=5 %START; ! PRIVATE CHAIN %IF SSERIES=NO %START !........PSERIES..........PSERIES..........PSERIES..........PSERIES ! ! P_P3=VADDR RCB, P5-P6=STL-STB. RCB IS 28 LONG %IF COPY CONTROL BLOCK(P_P3,28,P_P5,P_P6,ADDR(T_RCB))#0 %THENRESULT=NOTOK %FINISHELSESTART !........SSERIES..........SSERIES..........SSERIES..........SSERIES ! ! P_P3=VADDR OF FIRST OF UP TO 6 CHAINED TCBS. P5-P6=STL-STB. ! EACH TCB IS 56 LONG LINK==P_P3 %FOR I=1,1,6 %CYCLE TCB==T_TCBS(I) %IF COPY CONTROL BLOCK(LINK,56,P_P5,P_P6,ADDR(TCB))#0 %THENRESULT=NOTOK LINK=ADDR(TCB)!X'80000000'; ! INTO PREVIOUS LINK==TCB_NEXT TCB; ! THE USERS LINK TO NEXT %IF LINK=0 %THENEXIT; ! END %REPEAT %UNLESS LINK=0 %THENRESULT=NOTOK; ! NOT TERMINATED IN 6 %FINISH;!............................................................ REQ_PRIVATE ATTN=P_P4; ! ATTN DEST %RESULT=OK %FINISH REQ_FINAL CHAIN=FINAL CHAIN(TYPE) REQ_RETRY LIMIT=WRITE RETRIES ! THIS IS OVERWRITTEN IF IT IS A READ, AND IRRELEVANT FOR OTHERS TYPE BIT=1<>16 %IF REQ_LENGTH&X'8000'#0 %THEN REQ_LENGTH=REQ_LENGTH!X'FFFF0000' %IF REQ_LENGTH=0 %THEN REQ_LENGTH=P_P4 CTRL=(P_P2>>8)&X'FF' %IF TYPE BIT&WRITEMASK#0 %AND T_PROP3&X'40'#0 %THENRESULT=NOTOK; ! NO RING %IF TYPE BIT&XFERMASK#0 %START; ! READ,READREV,READCHECK,WRITE,ERASE %IF TYPE BIT&SPADDRMASK#0 %THEN REQ_ADDR=X'81000000' %ELSEC REQ_ADDR=P_P3 ! ERASE AND READ CHECK NEED A GENUINE FIXED ADDRESS, FOR CONTROLLER ! CHECKS EVEN WHEN NO DATA XFER.THIS IS START OF REAL CORE MAP IN PS 64. %IF TYPE BIT&READMASK#0 %START; ! READ,READREV,READCHECK REQ_RETRY LIMIT=READ RETRIES %IF TYPE=4 %START; ! READCHECK REQ_LENGTH=MAX XFER ! MAX. 256K-1 FOR PSERIES, 64K-1 FOR SSERIES. REQ_READORS=NODATA ! IGNSHORTLONG(1); ! NO DATA, IGNORE SHORT REQ_TARGET POS=1 %FINISHELSESTART; ! READ OR READREV REQ_READORS=IGNSHORTLONG((CTRL>>2)&3); ! IGN NEITHER, SHORT, LONG OR BOTH %IF TYPE=1 %THEN REQ_TARGET POS=1 %ELSE REQ_TARGET POS=0 ! READ READREV %FINISH %FINISH; ! READMASK %IF CTRL&2#0 %THEN REQ_RETRY LIMIT=0 ! NO ERROR RECOVERY. NOTE THAT WRITE TM RECOVERY IS NOT AFFECTED. %UNLESS 00 AND GEN FIXED ADDR. ! HOWEVER, FOR WRITE TM RETRY (SKIPREV, ERASE), THE ERASED ! LENGTH SHOULD BE AT LEAST A TMS WORTH - IE 41 IN PE, 8 IN NRZI. ! SSERIES: ! DUMMY DESCRIPTOR NOT REQUIRED, SINCE ABSENCE OF FIXED BIT IN TCB_STE ! TELLS DCU THAT DESCRIPTOR IS NOT VALID. HOWEVER, AS FOR PSERIES, ! THE WRITE TM RETRY 'ERASE' REQUIRES A SUITABLE LENGTH, AND ITS ! SIMPLER JUST TO DO IT FOR THEM ALL. SKIPS AND REWIND WONT USE IT ! IN 'FIRE CHAIN'. ! FIRST SAVE USER SUPPLIED LENGTH AS THIS IS BLOCKS OR LOGICAL FILES ! FOR SKIP AND SKIP TM RESPECTIVELY. REQ_SKIPTOT=REQ_LENGTH REQ_LENGTH=50 REQ_ADDR=X'81000000' %IF TYPE BIT&SKIPMASK#0 %START; ! SKIP BLOCKS, SKIP TMS %IF REQ_SKIPTOT=0 %THENRESULT=NOTOK %IF REQ_SKIPTOT<0 %THEN REQ_CHAIN=REQ_CHAIN+1 %ANDC REQ_SKIPTOT=-REQ_SKIPTOT %IF TYPE=8 %START; ! SKIP BLOCK REQ_TM=CTRL&1; ! TREAT TM AS BLOCK %FINISHELSESTART; ! SKIP TMS ! CTRL IS NUMBER OF TMS/LOGICAL FILE ! ZERO IMPLIES 1/LOGICAL FILE WITH NO TM LOOKAHEAD REQ_TM=CTRL %FINISH %FINISH %FINISH %RESULT=OK %END; ! FN ACCEPT REQ ! ! %ROUTINE FIRE CHAIN !********************************************************************** ! ENTERED WITH REQUEST SET UP IN T_REQ. SPECIFICALLY REQ_CHAIN IS TO ! BE FIRED. ! %IF PSERIES, SETS UP LBES, ALE AND RCB AND TELLS GPC. ! %ELSE, SETS UP TCBS AND TELLS DCU. !********************************************************************** %CONSTINTEGER READMASK=X'E66EF'; ! 2**N SET IF LBE(CW) IS READ %OWNINTEGER DEST=CONTROLLER+EXEC,SRCE=ME+5,P1,P2,P3=X'11', P4,P5,P6 %INTEGERNAME INITWORD %INTEGER MODE MODE=T_MODE %IF MODE=0 %THEN MODE=PE ! EG A BLANK TAPE BEING REWOUND OR UNLOADED WITHOUT HAVING BEEN CLAIMED. ! %IF SSERIES=NO %START !..........PSERIES..........PSERIES..........PSERIES..........PSERIES ! %INTEGER LBEN,CH START,I %INTEGERNAME LBEWORD %RECORD(RCBF)%NAME RCB RCB==T_RCB INITWORD==RCB_INITWORD %IF REQ_CHAIN=PRIVATE %THEN ->FIRE; ! PRIVATE RCB ALL SET UP RCB=0; ! ******* CAUTION. PARTLY SET UP ONCE AT ALLOCATE ? CH START=CHAIN START(REQ_CHAIN) LBEN=CHAIN LENGTH(REQ_CHAIN) RCB_LB BYTES=LBEN<<2; ! CAN WE SET THIS TO 4 LBES AT ALLOC REGARDLESS ??? MOVE(RCB_LB BYTES,ADDR(LBES(CH START)),ADDR(T_LBE1)) RCB_LBA=ADDR(T_LBE1); !**** DO THIS ONCE AT ALLOCATE %IF REQ_CHAIN<=LAST READ CHAIN %START %FOR I=0,1,LBEN-1 %CYCLE %IF (1<<(CH START+I)&READMASK)#0 %START; ! LBE IS READ ! OR IN BITS FOR 'NO DATA','IGNORE SHORT/LONG' ! THE FIRST READ IN MULTIPLE CHAINS ALREADY HAS LONG/SHORT ! MASKED OFF. HOWEVER SINCE WERE DOING THE 'NO DATA' HERE AS ! WELL, WE MUST DO THEM ALL. LBEWORD==INTEGER(ADDR(T_LBE1)+I<<2) LBEWORD=LBEWORD ! REQ_READORS %FINISH %REPEAT %FINISH %IF REQ_CHAIN<=LAST RETRY CHAIN %THEN T_OPS=T_OPS+1 ! COUNT OF NON-POSITIONING OPERATIONS FOR JOURNAL ! T_ALE1=REQ_LENGTH T_ALE2=REQ_ADDR RCB_AL BYTES=8 RCB_ALA=ADDR(T_ALE1); !*** DO THIS ONCE AT ALLOCATE %IF T_ALE2>0 %START; ! LOCAL ADDR FOR DATA. PUT IN LSTB RCB_LIMFLAGS=REQ_LSL RCB_LSTBA=REQ_LSTBA %FINISH; ! ELSE ALL IN PUBLIC. DO WE NEED ANYTHING HERE? RCB_LIMFLAGS=RCB_LIMFLAGS ! X'8000'; ! INITIALISE BIT IN FLAGS ! TELLS GPC TO USE THE FOLLOWING TO INIT THE DEVICE INITWORD=(STATMASK(REQ_CHAIN)<<8) ! MODE ! TERTIARY STAT MASK MODE ! FIRE: INITWORD=INITWORD ! ((T_PROP2&7)<<24); ! MECHANISM P1=ADDR(RCB) %FINISHELSESTART !..........SSERIES..........SSERIES..........SSERIES..........SSERIES ! %CONSTLONGINTEGER NOADDRMASK=X'7DF608800' %CONSTINTEGER PAGE BIT=X'40000000' %OWNBYTEINTEGER ASBYTE=X'10'; ! ADD STATUS LITERAL BYTE %RECORD(TCBF)%NAME TCB %INTEGER CWS,CWN,CWB,CH START,I,STAD,STEAD,LEN,ADR INITWORD==T_TCBS(1)_PREAMBLE(1) %IF REQ_CHAIN=PRIVATE %THEN ->FIRE; ! TCBS ALL SET UP %IF REQ_CHAIN<=LAST RETRY CHAIN %THEN T_OPS=T_OPS+1 CH START=CHAIN START(REQ_CHAIN) CWS=CHAIN LENGTH(REQ_CHAIN) %FOR I=1,1,CWS %CYCLE TCB==T_TCBS(I) TCB=0 CWN=CH START+I-1 TCB_CW=CW(CWN); ! COMMAND WORD %IF (LONG1<0 %THEN STAD=X'81000000'+REQ_LSTBA %ELSE STAD=PST VA ! PSTVA IS PUBLIC SEG VA. DEFINED IN CTOPT FILE STEAD=STAD+((ADR>>15)&X'FFF8'); ! ACTUALLY (>>18&X'1FFF')<<3 ! TO YIELD BYTE DISPLACEMNT OF ENTRY TCB_STE=(INTEGER(STEAD+4)&X'0FFFFFF8')!1; ! REAL ADDR+FIXED BIT %IF INTEGER(STEAD)&PAGE BIT#0 %THEN TCB_STE=TCB_STE!2 TCB_LENGTH=TCB_LENGTH!LEN; ! REMENBER BACKWARDS BIT MAY BE THERE TCB_ADDR=ADR&X'3FFFF' %FINISH; ! THOSE REQUIRING DATA AREA %UNLESS I=CWS %THEN TCB_NEXT TCB=ADDR(T_TCBS(I+1))!X'80000000' ! CHAIN ON THE NEXT ONE %REPEAT INITWORD=(STATMASK(REQ_CHAIN)<<8)!MODE ! SECONDARY STATUS MODE ! ! FIRE: INITWORD=INITWORD!((T_PROP2&7)<<24) P1=ADDR(T_TCBS(1)) %FINISH;!.............................................................. P2=T_SNO&X'FF' REQ_STATE=TERM EXP MYPON(RECORD(ADDR(DEST))) %IF RLEVEL&4#0 %THEN DUMPTABLE(61,ADDR(T),TFSIZE) %END; ! ROUTINE FIRE CHAIN ! ! !******************* TAPE STARTS HERE ********************************** ! %IF KMON&(LONG1<<49)#0 %THEN TMON=1 %ELSE TMON=0 %IF TMON#0 %OR RLEVEL&1#0 %THEN MON(1,P) ! ACT=P_DEST&X'FFFF' %IF ACT>64 %THEN SNO=ACT %AND ACT=1 %UNLESS (INITIALISED>0 %OR ACT=4) %AND 1<=ACT<=13 %THEN ->FAULTY P ! ->ACTSW(ACT) ! REPLY: P_DEST=P_SRCE P_SRCE=ME!ACT MYPON(P) %RETURN ! ! ACTSW(7):; ! USER RELEASE SNO=P_P2&X'FFFF' ACTSW(1):; ! USER REQUEST, SNO SET FROM P_DEST ABOVE. %IF SEARCH TPS(3,SNO,"")=OK %START; ! FOUND SNO AND MAPPED T REQ==T_REQ REP==T_REP %IF T_STATE=CLAIMED %START; ! THE DECK REMAINS ACCESSIBLE %IF REQ_STATE=0 %START; ! IDLE %IF ACT=1 %START; ! USER REQUEST %IF ACCEPT REQUEST=OK %START; ! CHECKS OK FIRE CHAIN; ! REPLY WHEN TERM COMES %RETURN %FINISHELSE P_P4=BAD PARAMS %FINISHELSESTART; ! USER RELEASE, ACT 7 T_LOAD STATE=6+P_P5<<1; ! IE 6 FOR UNLOAD, 8 FOR RLSE/RWND LOAD P_P4=OK %FINISH %FINISHELSE P_P4=BUSY %FINISHELSE P_P4=NOT CLAIMED %FINISHELSE P_P4=SNO NOT FOUND %IF P_P4=OK %THEN P_P2=OK %ELSE P_P2=REJECT ! ONLY SUCCESSFUL RLSE ALL OTHERS ->REPLY ! ! ACTSW(2):; ! TERMINATION/ATTENTION FROM CONTROLLER ! P_P1=STREAMR0, _P2=STREAMR1 ! P_P3=DEVICE ENTRY ADDRESS ! P_P4=RESPONSE ANAL FLAGS FROM CONTROLLER SENSE IF ORIGINAL REQUEST FAILED D==RECORD(P_P3) T==RECORD(D_UA AD) REQ==T_REQ REP==T_REP T_STREAMR0=P_P1 T_STREAMR1=P_P2 I=(P_P1>>20)&15 %IF I=1 %THEN ATTENTION %ELSE TERMINATE(I&7,0) ! IE 0 FOR NORMAL, >0 FOR ABTERM %RETURN ! ! ACTSW(3):; ! CONTROLLER ALLOCATE/DEALLOCATE REPLIES ! P_P1=0 SUCCESS ! P_P2=SNO (ALLOC ONLY) ! P_P3=DEVICE ENTRY ADDRESS ! P_P6=MNEMONIC(ALLOC ONLY) D==RECORD(P_P3) %IF P_SRCE&X'FF'=ALLOC %START %IF P_P1#OK %THENRETURN; ! ALLOC FAILED. SEE COMMENT AT ACTSW(4) ! SO ALLOCATED OK. SET UP DEVICE RECORD I=P_P6!X'3000000'; ! STRING MNEM M=STRING(ADDR(I)) %IF SEARCH TPS(1,0,M)=OK %START ! IT SHOULDNT ALREADY BE THERE OPMESS(M." allocate twice?") %RETURN %FINISH LASTLINK=D_UA AD T==RECORD(D_UA AD) T=0 T_GTS=(\(D_PROPS0>>10))&1; ! 1=GTS, 0=MTS REQ==T_REQ REP==T_REP LASTLINK==T_LINK; ! THIS IS NOW LAST T_MNEM=M T_PROP2=P_P6&X'FF'-X'30'; ! MECHANISM FROM MNEM TO DO SEND PROPS T_SNO=P_P2 ! T_STATE=0, NOT AVAILABLE ! T_LOAD STATE=0, READY FOR LOAD LOAD; ! GET PROPS AND SEE IF ANYTHING LOADED %FINISHELSESTART; ! DEALLOCATE %IF P_P1#OK %START OPMESS(" Deallocate fails ".HTOS(P_P1,8)) %RETURN %FINISH T==RECORD(D_UA AD) ! DEALLOCS COME VIA VOLUMS WHICH DOESNT ALLOW THEM IF IN USE, SO THERE ! SHOULDNT BE ANY REQUEST OUTSTANDING. WE MIGHT BE IN A LOAD OR UNLOAD ! SEQUENCE BUT THATS IRRELEVANT. NOTHING TO DO BUT UNLINK IT. M=T_MNEM I=SEARCH TPS(1,0,M); ! REALLY JUST TO SET UP 'PREVLINK' %IF I#OK %START; ! DEAR DEAR. WHATS HAPPENED? OPMESS(M." dealloc srch fails?") %RETURN %FINISH PREVLINK=T_LINK; ! UNLINK IT ! AND RESET LAST IF THIS WAS IT %IF T_LINK=0 %THEN LASTLINK==PREVLINK %FINISH %RETURN ! ! ACTSW(4):; ! ONCE/STREAM FROM CONTROLLER AT STARTUP ! P_P1=BASE MNEMONIC. CONTROLLER CREATES STREAMS FOR THE MAX DECKS FOR THE ! STREAM TYPE IE EITHER 8 OR 4. WE DONT KNOW WHICH TYPE, SO WE DO ! ALLOCATE REQUESTS FOR MAX OF THESE. THE EXCESS WILL FAIL FROM CONTROLLER. ! IN FACT, THE DECKS FOR THOSE SUCCESSFULLY ALLOCATED MAY NOT EXIST, ! BUT WE DONT FIND THAT OUT UNTIL WE GET NOT AVAILABLE AT START OF LOAD. ! ! THIS ENTRY ALSO USED BY VOLUMS TO MODE ON/OFF DECK OR CLUSTER. !P_P1=BASE MNEMONIC, P2=ON/OFF(1/0), P3=NUMBER OF DECKS ! %IF P_SRCE&X'FF0000'=CONTROLLER %START ! INITIALISING CALL %IF INITIALISED=0 %START LASTLINK==FIRSTTP INITIALISED=1 %FINISH NDECKS=8 MODE=ON %FINISHELSESTART ! VOLUMS NDECKS=P_P3 MODE=P_P2 %FINISH %IF MODE=ON %THEN PP_DEST=CONTROLLER!ALLOC %C %ELSE PP_DEST=CONTROLLER!DEALLOC PP_SRCE=ME!3; ! WHERE CONTROLLER REPLIES COME PP_P2=ME!2; ! WHERE EVENTS ARE NOTIFIED PP_P1=P_P1; ! BASE MNEM P_P1=0; ! FOR REPLY TO VOLUMS, SEE BELOW %WHILE NDECKS>0 %CYCLE I=PP_P1!X'3000000' I=SEARCH TPS(1,0,STRING(ADDR(I))); ! IS IT THERE %IF (MODE=ON %AND I=OK) %OR (MODE=OFF %AND I=NOTOK) %THENC P_P1=P_P1+1 %ELSE MYPON(PP) ! IE IF ON AND ALREADY THERE, OR OFF AND NOT THERE, THEN INCREMENT ! COUNT OF 'NOT DONE' FOR VOLUMS. OTHERWISE DO IT PP_P1=PP_P1+1; ! NEXT MNEM UP NDECKS=NDECKS-1 %REPEAT %IF P_SRCE&X'FF0000'=CONTROLLER %THENRETURN ! SO IT WAS VOLUMS. REPLY. P1 ALREADY SET ->REPLY ! ! ACTSW(5):; ! EXECUTE REQUEST FAILS ! FAILURES ARE P1=1 - SNO OUT OF RANGE, IE UNKNOWN TO CONTROLLER ! =2 - DEVICE NOT READY ! P2=SNO ! P3=DEVICE ENTRY ADDRESS UNLESS P1=1 ! THE SNO IN P2 IS ONLY THE BOTTOM BYTE OF OUR FULL ONE(SEE FIRE CHAIN) ! SO WE CANNOT USE IT TO SEARCH FOR TP. FURTHER IF P1=1, CONTROLLER CLEARLY ! DOES NOT GIVE A DEVICE ADDR IN P3, SO WE HAVE NO WAY OF TELLING WHICH ! OF OUR ENTRIES WAS USED TO INITIATE THIS REQUEST OPMESS("Controller rejects request") PRINTSTRING("EXECUTE REQUEST FAILS - P1=".HTOS(P_P1,1). %C " P2=".HTOS(P_P2,2)) %IF P_P1#1 %START; ! WE CAN LOCATE IT DUMPTABLE(61,P_P3,TFSIZE) D==RECORD(P_P3) T==RECORD(D_UA AD) REQ==T_REQ REP==T_REP %IF REQ_STATE#0 %START; ! TELL THE USER OR 'LOAD' REQ_STATE=0 REP_P2=REJECT REP_P4=NOT CLAIMED %IF REP_DEST#0 %THEN MYPON(RECORD(ADDR(REP))) %ELSE LOAD %FINISH %FINISH %RETURN ! ! ACTSW(6):; ! VOLUMS REPORTING IN VOLUMS=P_SRCE I=SEARCH TPS(4,0,""); ! REPORT ALL LOADED TO VOLUMS %RETURN ! ! ! ACTSW(7) DEFINED AT ACTSW(1) ABOVE ! ! ACTSW(8):; ! SET REPORTING LEVEL %IF P_P1<=7 %START RLEVEL=P_P1 %FINISHELSEIF 0<=P_P2<=255 %START %IF P_P1=16 %START READ RETRIES=P_P2 %FINISHELSEIF P_P1=17 %START WRITE RETRIES=P_P2 %FINISH %FINISH %RETURN ! ! ACTSW(9):; ! SEND FAILURE DETAILS %IF SEARCH TPS(3,P_P1&X'FFFF',"")=OK %START P_P1=0 P_P2=T_STREAMR0 P_P3=T_STREAMR1 MOVE(12,ADDR(T_T0),ADDR(P_P4)) %FINISHELSESTART P_P1=REJECT P_P4=SNO NOT FOUND %FINISH ->REPLY ! ! ACTSW(10):; ! DUMP TABLE, SNO IN P1 %IF SEARCH TPS(3,P_P1&X'FFFF',"")=OK %START DUMPTABLE(61,ADDR(T),TFSIZE) %FINISH %RETURN ! NO REPLY ! ! ACTSW(11):; ! DUMMY %RETURN ! ! ACTSW(12):; ! CLAIM VOLUME CLAIM VOLUME(P) ! REPLY SET UP ->REPLY ! ! ACTSW(13):; ! DISPLAY TPS STATUS I=SEARCH TPS(5,0,"") %RETURN ! ! FAULTY P: MON(3,P) %END; ! ROUTINE TAPE ! ! %ENDOFFILE