! !************************************************** !* * !* TAPE HANDLER FOR 2900 * !* * !************************************************** !! !! EXTERNAL ROUTINE REFERENCES !! %EXTERNALSTRINGFNSPEC HTOS(%INTEGER VALUE, PLACES) %EXTERNALROUTINESPEC OPMESS(%STRING (23) S) %EXTERNALROUTINESPEC PON(%RECORDNAME P) %SYSTEMROUTINESPEC ETOI(%INTEGER A, L) %SYSTEMROUTINESPEC MOVE(%INTEGER L, FROMAD, TOAD) %EXTERNALROUTINESPEC PRHEX(%INTEGER N) %EXTERNALROUTINESPEC DUMP TABLE(%INTEGER TABNO, START, L) %EXTRINSICLONGINTEGER PARMDES %EXTERNALINTEGERFNSPEC NEWPPCELL %EXTERNALROUTINESPEC RETURNPPCELL(%INTEGER CELL) %IF MULTIOCP=YES %START %EXTERNALROUTINESPEC RESERVELOG %EXTERNALROUTINESPEC RELEASELOG %FINISH %EXTERNALROUTINESPEC PKMONREC(%STRING(20) TEXT, %RECORDNAME P) !! !! RECORD FORMATS !! %RECORDFORMAT PE(%INTEGER DEST, SRCE, P1, P2, P3, P4, P5, P6) %RECORDFORMAT REQF(%INTEGER DEST, SRCE, IDEN, LENGTH, SPAN, %BYTE %C %INTEGER CONTROL, TYPE, DUM1, FAULTS, %C %INTEGER LSL, LSTBA, COUNT1, COUNT2) %RECORDFORMAT RCBF(%INTEGER LIMFLAGS, LSTBA, LB BYTES, LBA AL, %C ALBYTES, ALA, INITWORD) %RECORDFORMAT TFM(%INTEGER LINK, %C %BYTEINTEGER SNO, USE, LAST REPLY, USERCOUNT, %C %INTEGER EXERRS, FAULTS, %STRING(3) MNEM, %C %INTEGER LBE1, LBE2, LBE3, LBE4, %C %BYTEINTEGER NEXT, PROP1,PROP2,PROP3, %C %INTEGER LOAD,STREAMR0,STREAMR1,OPS,ALE1,ALE2,ALE3,ALE4, %C %BYTEINTEGER SSTAT, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, %C T10, T11, %C %RECORD REQ(REQF), %RECORD RCB(RCBF), %C %INTEGER LAB1, LAB2, %STRING (7) DSN, %C %BYTEINTEGER ORGDIR, UNLOADPENDING, ORGREQ, BITS, %C %INTEGER ACTLEN,FIRSTPEND, LASTPEND) %RECORDFORMAT PF(%INTEGER DEST, SRCE, FLAGLINK, P2, %C %STRING (6) DSN, %BYTEINTEGER GROUP NUMBER , %INTEGER P5, P6) !------------------------------------------------------------------------ %RECORDFORMAT ENTFORM(%INTEGER SER, PTSM, PROPADDR, TICKS SINCE, %C CAA, GRCB AD, LBA, ALA, STATE, RESP0, RESP1, SENSE1, SENSE2, %C SENSE3, SENSE4, REPSNO, BASE, ID, DLVN, MNEMONIC, ENTSIZE, %C PAW, USAW0, URCB AD, SENSDAT AD, LOGMASK, TRTAB AD, UA SIZE, %C UA AD, TIMEOUT, PROPS0, PROPS1) !------------------------------------------------------------------------ %EXTRINSICLONGINTEGER KMON !! !! %CONSTINTEGER READMASK = X'441812' %CONSTINTEGER WRITEMASK = X'C00C' %CONSTINTEGER READORWRITE = X'44D81E' %CONSTINTEGER GPCSNO = X'300000' %CONSTINTEGER NORMLSTRA = X'00008080' %CONSTINTEGER PONSRCE = X'00310000' %CONSTINTEGER ALLOCATE = 11 %CONSTINTEGER DEALLOCATE = 5 %CONSTINTEGER TSIZE = 188 ! SIZE IN BYTES OF ONE TAPE RECORD %CONSTINTEGER OK = 0 %CONSTINTEGER ON = 1 %CONSTINTEGER OFF=0 %CONSTINTEGER SHORTBLOCK=8 !! !! VALUES OF LOAD FLAG !! %CONSTINTEGER LOADING = X'10' ! %CONSTINTEGER CHECK TM = 1 ! %CONSTINTEGER DOMORE = 2 ! %CONSTINTEGER REQOK = 4 ! %CONSTINTEGER FIRED = 8 %CONSTINTEGER UNLOADING = X'20' !! !! VALUES OF PERMIT FLAG ! %CONSTINTEGER RITE = 2 %CONSTINTEGER READ = 1 !! ! VALUES OF LOAD STATUS FLAG !! %CONSTINTEGER LOADED WITH LABEL = 1 %CONSTINTEGER LOADED NO LABEL = 2 %CONSTINTEGER FAULTY LOAD = -1 %CONSTINTEGER NOT LOADED = 0 %CONSTINTEGER INOP=-2 !! %CONSTINTEGER REJECT = 2; ! INVALID REQUEST !! !! TAPE PRIMITIVES AS PASSED IN TYPE PARAMETER !! %CONSTINTEGER READR = 6 %CONSTINTEGER READF = 1 %CONSTINTEGER REWIND = 17 %CONSTINTEGER UNLOADFLASH = 16 %CONSTINTEGER SENSE = 19 %CONSTINTEGER ERASE = 0 %CONSTINTEGER WRITETM = 10 %CONSTINTEGER WRITEF = 2 %CONSTINTEGER SENDPROPS = 20 %CONSTINTEGER UNLOAD = 21 %CONSTINTEGER SKIPTOTM = 9 %CONSTINTEGER CHREAD = 4 %CONSTINTEGER PRIVATE CHAIN = 5 %CONSTINTEGER SKIPBLK = 8 %CONSTINTEGER TESTTM = 13 !! !! HANDLER PRIMITIVES INDEXED INTO THE LBE ARRAY FOLLOWING !! !! %CONSTINTEGER RDF = 21; ! READ FORWARDS %CONSTINTEGER RDR = 22; ! READ REVERSE REVERSE ORDER OF DATA %CONSTINTEGER SRB = 24 ! SKIP REVERSE ONE BLOCK %CONSTINTEGER ULD = 4; ! UNLOAD , DISCONNECT %CONSTINTEGER RCH = 29 %CONSTINTEGER RCHR = 30; ! READ CHECK REVERSE ! READ CHECK - DO NOT FORWARD DATA %CONSTINTEGER SNS = 5; ! SENSE - INHIBIT WRITESS %CONSTINTEGER SPC = 29; ! SEND PROPERTY CODE - IGNORE SLXY !! %CONSTINTEGERARRAY LBE(1 : 39) = %C X'00C02200', X'00D03200', X'00F03800', X'00F05800', X'00F00400', 0, 0, 0, 0, X'00F00C00', X'04C04200', X'40101200', 0, X'04D05200', X'00000200', 0, 0,0,0,0, X'00000200', X'40101200', X'04C04200', X'04D05200', X'00006200', X'80000300', X'84F04300', X'84F02300', X'04F00E00', X'00F04200', 0, 0, X'04F05800', X'00F00900', 0,0, X'84F05200', X'84004300', X'80000300' !! !! SAW FLAG VALUES - BIT 0 - INTERRUPT ON INITIATION (ALSO SET BIT1) !! BIT 1 - RESPONSE TO CONTROLLER RESPONSE !! BIT 2 - INHIBIT TERMINATION INTERRUPT !! BIT 3 - CLEAR ABNORMAL CONDITIONS !! NOTE// IF SHORT/LONG BLOCK IS TO !! BE DETECTED THEN THE READ CMND. !! MUST BE THE LAST IN ITS LBE GROUP. !! - AND DO NOT MASK READS AGAINST TMS. !! !! %CONSTBYTEINTEGERARRAY HX(0 : 15) = %C %C '0','1','2','3','4','5','6', %C '7','8','9','A','B','C','D','E','F' !******************************************** !! %ROUTINE PBYTE(%BYTEINTEGER N) SPACE PRINTSYMBOL(HX(N>>4)) PRINTSYMBOL(HX(N&X'F')) %END !! !*********************************************************************** !*********************************************************************** !*********************************************************************** %EXTERNALROUTINE TAPE(%RECORDNAME P) !*********************************************************************** ! PERFORMS THE TAPE OPERATIONS * ! 1 - REQUEST ! 2 - TERMINATION ! 3 - ALLOCATE REQUEST REPLIES ! 4 - INITIALISE ,ACCEPT,RELEASE DECKS ! 5 - EXECUTE REQUEST REPLIES ! 6 - VOLUMES SETS REPORT SRCE FOR LOADS ! 7 - VOLUME DONE (RELEASE DECK) ! 8 - SET REPORTING LEVEL ! 9 - FREE ! 10 - SET LOAD STATE ! 11 - READ TAPE LABEL ! 12 - VOLUME REQUEST ! 13 - DISPLAY STATUS OF ALL DECKS ! PARAMETERS OF A REQUEST ! P1 - PRIVATE IDENTIFIER ! P2 - %SHORT LENGTH OF DATA ! %BYTE CONTROL ! 2**0 - TREAT TM AS BLOCK ! 2**1 - SUPPRESS ERROR RETRY ! 2**2 - SUPPRESS SHORT BLOCK CHECKING ! 2**3 - SUPPRESS LONG BLOCK CHECKING ! 2**7 - NRZ 800BPI MODE ! %BYTE TYPE OF TAPE OPERATION ! P3 - ADDR OF DATA ! P4 - ALTERNATE LENGTH (IF >64K) ! P5 - LOCAL SEGMENT LIMIT ! P6 - LOCAL SEGMENT TABLE BASE !! !! !*********************************************************************** %ROUTINESPEC TERMINATE(%INTEGER I) %ROUTINESPEC INITIATE %ROUTINESPEC ATTENTION %ROUTINESPEC LOAD %INTEGERFNSPEC PREPARE REQUEST(%RECORDNAME P) %ROUTINESPEC UNLOAD %ROUTINESPEC TELLVOLS %ROUTINESPEC REPLY(%INTEGER I) %ROUTINESPEC VOLUME DONE(%RECORDNAME P) %ROUTINESPEC VOL REQUEST(%RECORDNAME P) %ROUTINESPEC FREPORT(%STRING (17) M) %ROUTINESPEC LOAD MESSAGE(%INTEGER N, %STRING (6) DSN) %INTEGERFNSPEC FINDDSN(%STRING (8) S) %INTEGERFNSPEC FINDTP(%INTEGER DSNO) %INTEGERFNSPEC FINDMN(%STRING (4) MNEM) %ROUTINESPEC PEND %ROUTINESPEC UNPEND(%INTEGER FP) %ROUTINESPEC MON(%INTEGER MODE, %RECORDNAME P) %ROUTINESPEC MYPON(%RECORDNAME P) %RECORDNAME D(ENTFORM) %RECORD PP(PE); ! USED TO CONSTRUCT INTERNAL REQUESTS %RECORDSPEC P(PE) %RECORDNAME T(TFM) %RECORDNAME REQ(REQF) %INTEGER PREVLINK %RECORDFORMAT PBF(%RECORD P(PE), %INTEGER LINK) %OWNRECORDARRAYFORMAT PBAF(0 : 4095)(PBF) %OWNRECORDARRAYNAME PB(PBF) %OWNINTEGER RETRY = 15; ! NO OF RETRIES ON READ ! LIMITED IN MAX INTERBLOCK GAP FOR WRITE RETRIES; ! CURRENT NUMBER OF ALLOCATED TAPES %OWNINTEGER WRETRY = 6; ! NUMBER OF RETRIES ON WRITE %INTEGER NUNITS, MODE %CONSTINTEGER XCOM = X'31D0'; ! SELECT SUBSET OF ENTRIES %RECORD REP(PE) ;! REPLY TO USER %SWITCH ENTRY(1 : 13) %INTEGER TMON; ! NON - ZERO IF KMON BIT SET %INTEGER PSTAT ;! PRIMARY STATUS %INTEGER REPLIED %INTEGER I, DSNO, DACT, J,VOLFLAG %OWNINTEGER FIRSTTP = 0 ;! LIST HEAD OF TAPE TABLE %OWNINTEGER REPDEST = 0; ! WHO TO REPORT TAPE LOADS TO !! !! REPORTING LEVEL HAS FOUR BIT SETTINGS AS FOLLOWS: !! !! 2**0 = REPORT PARM RECORDS INPUT TO TAPE !! 2**1 = REPORT PARM RECORDS OUTPUT BY TAPE !! 2**2 = DUMP TAPE TABLE ON LEAVING TAPE RT. !! 2**3 = DUMP TAPE TABLE ON ENTERING TAPE !! %OWNINTEGER RLEVEL = 0; ! REPORTING LEVEL %OWNINTEGER MAXTPS = 0 !* !* !* %IF KMON&(LENGTHENI(1)<<49) # 0 %THEN TMON = 1 %ELSE TMON = 0 %IF TMON # 0 %OR RLEVEL&1 > 0 %THEN MON(1,P) REENTER: REPLIED = 0 DSNO = P_P1>>24 DACT = P_DEST&X'FFFF' %UNLESS MAXTPS > 0 %OR 3 <= DACT <= 4 %THEN -> FAULTYP %IF DACT > 64 %THEN DSNO = DACT %AND DACT = 1 %UNLESS 1 <= DACT <= 13 %THEN -> FAULTYP %IF XCOM&(1< ENTRY(DACT) ! TAKE OFF IF DECK UNKNOWN %IF DACT = 3 %AND P_P1 # 0 %THEN %RETURN; ! ALLOCATE FAILURE %IF 2 <= DACT <= 5 %START; ! INTERRUPT OR REJECT EXEC. D == RECORD(P_P3) T == RECORD(D_UA AD) REQ == T_REQ %IF RLEVEL&8 # 0 %THEN DUMPTABLE(61,ADDR(T_LINK),TSIZE) %FINISH %ELSE %START %IF FINDTP(DSNO) = -1 %THEN -> FAULTYP %FINISH -> ENTRY(DACT) !! !----------------------------- !! REQUEST ENTRY(1): !! %IF T_USE # 0 %THEN PEND %AND %RETURN; ! QUEUE REQ. IF UNIT BUSY REPLY(REJECT) %IF PREPARE REQUEST(P) # 0 %RETURN !! !----------------------------- !! INTERRUPTS - MAY BE ATTENTION , NORMAL, ABNORMAL, ETC. ENTRY(2): J = (P_P1>>20)&15 %IF J = 1 %THEN ATTENTION %ELSE %START %IF J = 8 %START I = 0 ! TRUE TERMINATION OF REWIND AND TM SKIPS COMES WITH ATTN BT %IF I = 0 %AND (REQ_TYPE = REWIND %C %OR REQ_TYPE = SKIPTOTM) %THEN %RETURN %FINISH %ELSE I = 1 TERMINATE(I); ! I=0 - NORMAL TERM %FINISH %IF REPLIED = 1 %THEN -> CHPEND %ELSE %RETURN !! !------------------------------- !! REPLY TO ALLOCATE/DEALLOCATE REQUEST FROM GPC !! ENTRY(3): !! IGNORING ALLOCATE/DEALLOCATE FAILURES BECAUSE THESE !! ARE ENDEMIC WHILE THE NUMBER OF DECKS PER CLUSTER IS !! UNKNOWN. !! !! ALLOCATE REPLY FORMAT: !! !! P1 = 0 - SUCCESSFUL !! = 1 - INVALID MNEMONIC !! = 2 - ALREADY ALLOCATED !! !! P2 = DEVICE SERVICE NUMBER !! P3 = ADDRESS OF DEVICE ENTRY !! P6 = MNEMONIC !! !! DEALLOCATE REPLY FORMAT IS: !! !! P1 = 0 - SUCCESSFUL !! P3 = ADDRESS OF DEVICE ENTRY !! %IF P_SRCE&X'FF' = ALLOCATE %START ! SET UP TAPE TABLE ENTRY J=P_P6!X'3000000' %RETURN %IF FINDMN(STRING(ADDR(J)))=0 ;! ALLOCATE TWICE ? MAXTPS = MAXTPS+1 %IF MAXTPS = 1 %THEN FIRSTTP = D_UA AD %C %ELSE T_LINK = D_UA AD T == RECORD(D_UA AD) REQ == T_REQ T = 0 ;! ZERO TAPE ENTRY RECORD T_MNEM = STRING(ADDR(J)) T_PROP2 = (P_P6&X'FF')-X'30' ;! GET MECHANISM FROM MNEMONIC. ! NOTE: RELIES ON MNEMONICS STARTING AT MX0 AND ! IS RESET BY SEND PROPERTY CODE. T_SNO = P_P2 T_T0=255 ;! SET INOP ( ZERO INTERPRETED AS AUTO) T_FIRSTPEND = -1 T_LASTPEND = -1 T_EXERRS = 16 LOAD; ! TEST DECK AND READ LABEL IF POSSIBLE. %FINISH %ELSE %START ;! DE-ALLOCATE %RETURN %IF FINDMN(T_MNEM)#0 ;! DEALLOCATE UNKNOWN DECK ? MAXTPS = MAXTPS-1 %IF T_USE&15#0 %THEN REPLY(1) ;! IN CASE USER COMMAND OUTSTANDING INTEGER(PREVLINK) = T_LINK %FINISH %RETURN !! !------------------------------------ !ACCEPT OR RELEASE TAPE DECKS ENTRY(4): !! !! MAY BE CALLED BY GPC OR VOLUMES. !! GPC CALLS TO GIVE CONTROL OF A TAPE STREAM( UP TO 8 DECK !! CLUSTER). VOLUMS CALLS TO RECONFIGURE SYSTEM IN RESPONSE TO !! OPERATOR INSTRUCTIONS TO ISOLATE OR ABSORB TAPE !! UNITS OR WHOLE TAPE STREAMS. !! !! REQUEST FORMAT FOR GPC/ !! !! P1 = BASE MNEMONIC (INTEGER) !! !! REQUEST FORMAT FOR VOLUMS. !! !! P1 = BASE MNEMONIC (INTEGER) !! P2 = ON/OFF (1//0) - FLAG ON REPLY !! P3 = NUMBER OF DECKS !! !! VOLFLAG=0 %IF P_SRCE&X'FF0000' = GPCSNO %START PB == ARRAY(INTEGER(ADDR(PARMDES)+4),PBAF) NUNITS = 8; ! GPC GIVES A CLUSTER AT A TIME MODE = ON %FINISH %ELSE NUNITS = P_P3 %AND MODE = P_P2 %IF MODE = ON %THEN PP_DEST = GPCSNO!ALLOCATE %C %ELSE PP_DEST = GPCSNO!DEALLOCATE PP_SRCE = PONSRCE!3 PP_P2 = PONSRCE!2 PP_P1 = P_P1 %WHILE NUNITS > 0 %CYCLE I=PP_P1!X'3000000' I=FINDMN(STRING(ADDR(I))) %IF (MODE=ON %AND I=0) %ORC (MODE=OFF %AND I=-1) %THENC VOLFLAG=VOLFLAG+1 %ELSE MYPON(PP) PP_P1 = PP_P1+1; ! INCREMENT MNEMONIC NUNITS = NUNITS-1 %REPEAT ! VOLUMES EXPECTS A REPLY ! FLAG=0 - OK : FLAG = 'N' - NUMBER OF UNKNOWN DECKS %IF P_SRCE&X'FF0000' # GPCSNO %THEN P_P1 = VOLFLAG %AND -> VOLREPLY %RETURN !! !-------------------------------- !! GPC REJECTS EXECUTE REQUEST !! !! REPLY FORMAT IS: !! !! P1 = 1 - SNO OUT OF RANGE !! = 2 - DEVICE NOT READY !! !! P2 = SNO !! P3 = ADDRESS OF DEVICE ENTRY !! P6 = IDEN !! ENTRY(5): FREPORT("GPC REJECTS".HTOS(P_P1,1)) REPLY(1) %IF T_USE&(LOADING!UNLOADING) = 0 %IF REQ_TYPE = UNLOADFLASH %THEN LOADMESSAGE(7,"") %RETURN !---------------------------- !! VOLUMES SETS DEST TO WHICH TAPE LOADS ARE !! TO BE REPORTED. ENTRY(6): REPDEST = P_SRCE !! DESCRIBE CURRENT TAPES TO VOLUMES I = FINDMN("VOLS") %RETURN !------------------------------ ENTRY(7): ! VOLUME DONE VOLUME DONE(P) -> VOLREPLY !------------------------------- !! SET REPORTING LEVEL ENTRY(8): %IF P_P1 > 15 %START %RETURN %UNLESS 1 <= P_P2 <= 255 %IF P_P1 = 16 %THEN RETRY = P_P2 %IF P_P1 = 17 %THEN WRETRY = P_P2 %FINISH %ELSE RLEVEL = P_P1 %RETURN !------------------------------- ENTRY(9): ;! SEND FAILURE DETAILS P_P2=T_STREAMR0 P_P3=T_STREAMR1 MOVE(12,ADDR(T_SSTAT),ADDR(P_P4)) ->VOLREPLY !*----------------------------------- ENTRY(10): ! SET LOAD STATE T_LOAD = P_P1 %IF P_P1 < 1 %THEN T_DSN = "" %RETURN !-------------------------------- ENTRY(11): ! SENSE AND READ LABEL ON DRIVE P1>>24 T_NEXT = 0 T_LOAD = NOT LOADED LOAD %RETURN !--------------------------------- ENTRY(12): ! VOLUME REQUEST VOL REQUEST(P) VOLREPLY: %RETURN %IF REPLIED = 1; ! REPLIED ALREADY - GET OUT P_DEST = P_SRCE P_SRCE = PONSRCE!DACT MYPON(P) %RETURN !------------------------------------ ENTRY(13): I = FINDMN(""); ! DISPLAY DECK STATUS. %RETURN !! CHPEND: ! RELEASE NEXT QUEUED REQUEST IF ANY %IF T_FIRSTPEND # -1 %THEN UNPEND(T_FIRSTPEND) %AND -> REENTER %RETURN !! FAULTYP: PKMONREC(" TAPE?/ ",P) !! !* !************************************************************************ !* !****************************************************************** !: !* !* !* %INTEGERFN PREPARE REQUEST(%RECORDNAME P) !* !********************************************************** !* * !* CALLED TO CHECK A TAPE REQUEST IS VALID AND TO * !* STORE THE REQUEST AGAINST A REPLY FROM THE DEVICE * !* * !********************************************************** !* %RECORDSPEC P(PE) %CONSTINTEGER TRANSMASK = X'5CC05E' !! %IF T_USERCOUNT=0 %AND T_USE&LOADING=0 %THEN %RESULT=REJECT MOVE(32,ADDR(P_DEST),ADDR(REQ_DEST)) REQ_TYPE = P_P2&X'FF' T_ORGREQ = REQ_TYPE !! ! IF TAPE NOT OK OR LOAD OR UNLOAD ETC FAIL !! %UNLESS T_LOAD >= 1 %OR T_USE&X'F0' # 0 %C %OR SENSE <= REQ_TYPE <= SENDPROPS %C %THEN FREPORT(" REQUEST REJECT ") %AND %RESULT = 1 %IF REQ_TYPE = PRIVATE CHAIN %THEN -> L1 !! !! CHECK WRITE RING PRESENT IF REQUIRED !! %IF (REQ_TYPE = ERASE %OR REQ_TYPE = WRITEF %C %OR REQ_TYPE = WRITETM) %AND T_PROP3&X'40' # 0 %C %THEN LOAD MESSAGE(4,"") %AND %RESULT = 1 %IF REQ_TYPE = CHREAD %THEN REQ_TYPE = READF %IF REQ_TYPE = 3 %THEN REQ_TYPE = WRITEF; ! WRITECH REQ_SPAN = 0 %UNLESS (1<>16 %IF REQ_LENGTH&X'8000' # 0 %C %THEN REQ_LENGTH = REQ_LENGTH!X'FFFF0000' %IF REQ_LENGTH = 0 %THEN REQ_LENGTH = P_P4 %IF REQ_TYPE = READR %THEN REQ_TYPE = READF %C %AND REQ_LENGTH = -REQ_LENGTH %IF REQ_LENGTH<0 %THEN T_ORGDIR=0 %ELSE T_ORGDIR=1 REQ_CONTROL = (P_P2>>8)&X'FF' %UNLESS 8 <= REQ_TYPE <= 9 %THEN %START %IF REQ_CONTROL>>7 = 1 %THEN T_BITS = T_BITS!1 %FINISH REQ_COUNT1 = 0 REQ_COUNT2 = 0 REQ_FAULTS = 0 %IF REQ_TYPE < 4 %AND REQ_CONTROL&2 # 0 %C %THEN REQ_FAULTS = RETRY !! ! IGNORE BACKWARDS SKIP IF BT SET ! COULD CHECK FOR REWIND ALSO, BUT EASIER TO DO NULL OP !! %IF REQ_TYPE = SKIPTOTM %AND (REQ_LENGTH = 0 %C %OR REQ_CONTROL <= 0) %THEN %RESULT = REJECT %IF (SKIPBLK <= REQ_TYPE <= SKIPTOTM %C %AND REQ_LENGTH < 0) %AND T_T6&8 # 0 %C %THEN REPLY(0) %AND %RESULT = 0 !! L1: %IF REQ_TYPE=PRIVATE CHAIN %THEN REQ_COUNT1=P_P4 ;! ATTN DEST T_USE = T_USE!4 INITIATE %RESULT = 0 %END; ! OF PREPARE REQUEST !*********************************************************************** !* !* %ROUTINE ATTENTION !* - ACTIVITY 3 !**************************************************** !* * !* DEAL WITH UNSOLICITED INTERRUPT FROM DEVICE * !* * !* ATTN BYTE: 0 - DEVICE IN AUTO * !* 1 - BT DETECTED * !* 2 - (ALWAYS SET) * !* 3 - TAPE MARK FOUND * !* 4 - ENGINEER STATE * !* 5 - AVAILABLE * !* 6 - UNAVAILABLE * !* 7 - MANUAL REQUIRED * !* * !**************************************************** !* TAKE THE LIBERTY OF SETTING THE SENSE BITS IN THE TABLE ENTRIES !* APPROPRIATELY, BECAUSE IT IS INCONVENIENT TO SENSE THE DEVICE !* AFTER EACH ATTENTION. !! %CONSTSTRING(10) WEIRDATTN="WEIRD ATTN" %INTEGER I, AB, ATTN %SWITCH ATT(0 : 7) ATTN = (P_P1>>8)&X'DF' T_STREAMR0 = P_P1 AB = ATTN; ! GET ATTN BYTE MINUS UNUSED BIT %IF P_P1<<8>>24#16 %THEN FREPORT(WEIRDATTN) %AND %RETURN %CYCLE I = 0,1,7 %IF AB&1 = 1 %START %IF AB>>1 # 0 %AND ATTN # X'84' %AND ATTN#X'C0' %THENC FREPORT(WEIRDATTN) !! MULTIPLE ATTENTIONS !! SHOULD NEVER HAPPEN IF INTERRUPTS ARE TAKEN AS THEY !! OCCUR BY THE SUPERVISOR. BUT IF THE SYSTEM GOES NON- !! INTERRUPTABLE FOR ANY LENGTH OF TIME THEN SUBSEQUENT !! ATTENTION ARE ANDED TOGETHER. !! -> ATT(I) ATT(0): ! MANUAL REQD ! OUT IF UNLOADING ALREADY IN PROGRESS OR COMPLETED %RETURN %IF T_USE&UNLOADING > 0 %OR T_T0&X'C0' # 0 UNLOAD %RETURN ATT(1): ATT(3): ! NOT AVAILABLE + ENGINEER STATE T_T0 = T_T0!X'40' ->LOST %IF T_USERCOUNT#0 %RETURN ATT(2): ! AVAILABLE T_T0 = T_T0&X'BF' ->LOST %IF T_USERCOUNT#0 %RETURN ATT(4): ! TAPE MARK FOUND %IF REQ_TYPE = SKIPTOTM %THEN TERMINATE(0) %IF REQ_TYPE = 5 %AND REQ_COUNT1 # 0 %THEN -> RAT ATT(5): ! UNUSED %RETURN ATT(6): ! BT DETECTED ! IGNORE IF WATING FOR NORMAL TERMINATION INTERRUPT ! MAY MEAN END OF REWIND,SKIPTO TM ETC. T_T6 = T_T6!8; ! SET BT BIT IN SENSE %IF REQ_LENGTH<0 %THEN T_T2=T_T2!8 %IF REQ_TYPE = 5 %AND REQ_COUNT1 # 0 %THEN -> RAT ! LET TERMINATE REPORT OK BUT BT IF UNEXPECTED %IF T_USE # 0 %THEN TERMINATE(0) %AND %RETURN !! IF NOT IN USE %THEN READ LABEL ATT(7): ! DEVICE IN AUTO ! READ LABEL IF ANY T_T0 = T_T0&X'7F'; ! UNSET MANUAL BIT %IF I=7 %AND T_USERCOUNT#0 %THEN ->LOST %IF T_USE&LOADING=0 %THEN LOAD %FINISH AB = AB>>1 %REPEAT %RETURN !* REPORT TMS AND BT TO PRIVATE CHAIN USERS ON ASYNCHRONOUS SERVICE. RAT: P_DEST = REQ_COUNT1 PON(P) %RETURN LOST: %IF T_USE&15#0 %THEN TERMINATE(1) T_LOAD=NOT LOADED TELLVOLS LOAD %IF I=7 %END; ! OF ATTENTION !********************************************************************** !* !* %ROUTINE UNLOAD !******************************************* !* * !* FIRE OFF UNLOAD - DISCONNECTS DECK * !* (SO RE-CONNECT IS APPENDED) * !* * !******************************************* !* %IF T_USE&8 # 0 %START T_UNLOADPENDING = 1 %RETURN %FINISH PRINTSTRING(T_MNEM." ".T_DSN." UNLOADING ") T_DSN = "" REQ_TYPE = UNLOADFLASH T_USE = UNLOADING INITIATE T_LOAD=NOT LOADED TELLVOLS %END !! %ROUTINE RLSEREWIND !!***************************************** !!* * !!* REWIND TAPE AND RE-READ LABEL AS AN * !!* ALTERNATIVE TO UNLOADING * !!* * !!***************************************** !! %IF T_USE&8 # 0 %THEN T_UNLOADPENDING = 2 %AND %RETURN REQ_TYPE = REWIND INITIATE T_BITS = T_BITS&X'FE' T_USE = 0; ! IGNORE REWIND TERMINATION T_DSN = ""; ! STOP ANYONE ELSE USING IT BY NAME T_LOAD = NOT LOADED; ! READ LABEL AT BT %END !! !**************************************************************************** !* !* %ROUTINE LOAD !* - ACTIVITY 11 !********************************************************* !* * !* ESTABLISH IF LABEL EXISTS - IF LEGAL REPORT TO * !* OPERATOR AND MOVE PAST THE LABEL - IF ILLEGAL * !* POSITION AT BT * !* * !********************************************************* !* %STRING (7) DSN %OWNINTEGER VOL1 = X'E5D6D3F1' %SWITCH DOP(0 : 4) %INTEGER CC !! !! FAIL UNLESS FIRST ENTRY OR TERM OK %IF T_NEXT = 0 %THEN CC = 0 %ELSE CC = REP_P2 -> FAIL %UNLESS (CC = 0 %OR CC = 4) %ANDC T_T1!(T_T2&X'F7')!T_T3!T_T4!T_T5!(T_T6&4)=0 PP = 0 T_USE = LOADING PP_SRCE = PONSRCE -> DOP(T_NEXT) !----------------------------------- DOP(0): T_FAULTS=0 T_EXERRS=16 ! READ PROPERTIES - SPECIFICALLY IF RING OR NOT - INCLUDES SENSE PP_P2=X'30014' PP_P3 = ADDR(T_PROP1) -> STARTP !--------------------------------- DOP(1): ! REWIND ! CHECK DECK OPERABLE BEFORE TRYING TO MOVE IT %IF T_T0&X'C0' # 0 %THEN -> OUT %ELSE PP_P2=17 %AND -> STARTP !----------------------------------------------------------------------- DOP(2): ! READ LABEL ON TAPE PP_P2=X'100E01' ;! 16 BYTES - NO ERR REC. PP_P3 = ADDR(T_LAB1); ! ADDRESS IN TABLE -> STARTP !----------------------------------------------------------------------- DOP(3): ! CHECK TAPE LABEL !! IBM LABELS ARE 80 BYTES LONG. !! SYSTEM B GENERATES NON-STANDARD LABELS OF LENGTH 86 ,96 AND GREATER. !! THE >96 LABELS INCORPORATE IPL BLOCKS. EACH IS PREFACED BY !! INTEGER BLOCK COUNT AND SHORTINTEGER BYTE LENGTH. %IF T_LAB1 = 0 %THEN MOVE(10,ADDR(T_LAB1)+6,ADDR(T_LAB1)) %IF T_LAB1 = VOL1 %AND CC = 0 %START MOVE(6,ADDR(T_LAB1)+4,ADDR(DSN)+1) LENGTH(DSN) = 6 ETOI(ADDR(DSN)+1,6) LOAD MESSAGE(LOADED WITH LABEL,DSN) -> OUTL %FINISH PP_P2=17 ;! REWIND IF UNLABELLED STARTP: LENGTH(T_DSN)=6 ;! AVOID CONC CHECK ON GARBAGE LENGTH T_NEXT = T_NEXT+1 %IF PREPARE REQUEST(PP) = 0 %THEN %RETURN FAIL: PRINTSTRING(" ".HTOS(T_SNO,2)." READ LABEL ABANDONED ") DOP(4): ;! END OF SECOND REWIND OUT: T_DSN="" %IF T_NEXT>2 %START LOADMESSAGE(LOADED NO LABEL,"") OUTL: TELLVOLS %FINISHELSE T_LOAD=FAULTY LOAD T_USE = 0 T_NEXT = 0 %END; ! OF LOAD !* !* !* %ROUTINE TELLVOLS !* !*********************************************************** !* REPORT TO VOLUMES THE DETAILS OF ALL TAPES LOADED. !* NOTE, NOT OPERATIONAL UNTIL VOLUMES INITIALISES !* (ENTRY 6) SO OK FOR USE IN CHOP SUPE WITHOUT VOLUMES !* MAY BE USED TO INDICATE TAPE UNLOADED, (LOAD FLAG<=0) !* !* REPLY FORMAT IS: !* !* P1 = 4 !* P2 = LOAD STATUS (0,1,2) !* P3 = STRING DECK MNEMONIC !* P4,P5 = STRING DSN !* P6 = RING !* !************************************************************ !* %RETURN %IF REPDEST = 0 PP_DEST = REPDEST PP_SRCE = PONSRCE PP_P1 = 4 %IF T_LOAD = NOT LOADED %START T_USERCOUNT = 0; ! STOPS TROUBLE WITH VOLUMS PRINTSTRING(T_MNEM." UNLOADED ") %FINISH %IF 0 <= T_LOAD <= 2 %THEN PP_P2 = T_LOAD %ELSE PP_P2 = 0 ! KEEP IT SIMPLE PP_P6 = 2-((T_PROP3>>6)&1) PP_P3 = INTEGER(ADDR(T_MNEM)) MOVE(8,ADDR(T_DSN),ADDR(PP_P4)+1) MYPON(PP) %END !* !* %ROUTINE TERMINATE(%INTEGER ABN) !* - ACTIVITY 2 !*********************************************************************** !* HANDLES THE TERMINATION OF A REQUEST !* ABN=0 - NORMAL TERMINATION !* 1 - ABNORMAL TERMINATPON !* !* PARAMETERS !* P1 - STREAM RESP0 DSNO IN TOP BYTE , PSTAT IN 3RD BYTE !* P2 - STREAM RESP1 !* P3 - ADDRESS OF DEVICE ENTRY !* P4 - RESPONSE FLAGS FROM SENSE (RESP0>>16) !* P5 - CONTROLLER STATUS ( NOT USED ) !* P6 - IDENT - P4 OF EXECUTE REQUEST !* !* PRIMARY STATUS BYTE (PSTAT) !* 0 - UNSUCCESSFUL !* 1 - (NOT USED) !* 2 - ATTENTION !* 3 - TERMINATED !* 4 - SHORT BLOCK !* 5 - LONG BLOCK !* 6 - TAPE MARK ON READ !* 7 - ET ON WRITE !* !*********************************************************************** %INTEGER I %BYTEINTEGER TM, BT %SWITCH OK, FEND(0 : 25) !! %IF T_USE&X'FF' = 0 %THEN FREPORT("UNEXPECTED TERM.") %C %AND -> TOUT %IF P_P2 = -1 %THEN REPLY(1) %AND %RETURN; ! DISASTER - TIME -OUT. PSTAT = (P_P1>>8)&X'FF' T_STREAMR0 = P_P1 T_STREAMR1 = P_P2 %IF (1< 0 %AND REQ_TYPE # SKIPTOTM %C %THEN TM = 1 %ELSE TM = 0 T_USE = T_USE&X'F0'; ! SCRUB BUSY BITS ! AUTOMATIC ERROR CORRECTION FOR SINGLE TRACK IN ERROR ON MT4'S %IF ABN = 0 %AND T_T6&X'F0' # 0 %C %THEN PRINTSTRING(" ".T_MNEM." ".T_DSN. %C " SINGLE TRACK IN ERROR - AUTOMATIC RECOVERY - TRK ". %C HTOS(INTEGER(ADDR(T_T7)),8)." ") %IF ABN = 0 %THEN -> OK(REQ_TYPE) %IF P_P4&X'FF'=X'80' %THEN MOVE(13,D_SENSDATAD,ADDR(T_SSTAT)) !! %IF T_SSTAT&X'80' # 0 %AND T_USERCOUNT = 1 %START ! DECK SWITCHED OFFLINE WHILE IN USE! LOAD MESSAGE(8,""); ! OFFLINE WHEN IN USE T_DSN = "" T_LOAD = NOT LOADED REPLY(1) TELLVOLS %RETURN %FINISH %IF REQ_TYPE # 5 %AND TM = 0 %AND BT = 0 %START T_FAULTS = T_FAULTS+1 %IF T_FAULTS-(T_OPS//10) > T_EXERRS %START OPMESS(T_MNEM." WARNING-ERROR RATE") T_EXERRS = T_EXERRS<<1 %UNLESS T_EXERRS& %C X'40000000' > 0 %FINISH REQ_FAULTS = REQ_FAULTS+1 ! DO NOT RETRY IF ONLY FAULT IS WRONG LENGTH BLOCK %IF (1< FAILED ! NOTE ERROR REPORTING IS SWITCHED OFF TO SAVE LOG FILES FREPORT(" ABNORMAL TERM ") %UNLESS T_EXERRS>16 ->FAILED %IF PSTAT=X'41' %OR T_T2#0 %OR T_T6&4#0 %ORC T_T4&X'88'#0 %FINISH ! LOG FAILED -> FEND(REQ_TYPE) OK(10): ! WRITE TM OK(0): ! ERASE OK EXCEPT FOR ET&TM OK(2): ! WRITE OK OK(14): ! WRITE RETRY HAS WORKED OK(17): OK(19): ! SENSE OK(20): ! SEND PROPERTY CODE REPLY(BT<<2) -> TOUT OK(16): ! UNLOAD OK - TERMINATE AS TAPE STARTS TO MOVE LOAD MESSAGE(3,""); ! DECK IS FREE ASSUMEOPSDOIT: T_BITS = T_BITS&X'FE'; ! SCRUB MODE T_USE = 0; ! SCRUB UNLOADING BIT T_T0 = T_T0!X'80'; ! PREMATURELY SET MANUAL BIT IN SENSE DATA -> TOUT FEND(0): ! ERASE HAS FAILED FEND(2): ! WRITE HAS FAILED FEND(10): ;! WRITE TM FAILS FEND(14): ! WRITE RETRY HAS FAILED %IF PSTAT&1 = 1 %THEN REPLY(4) %AND -> TOUT;! ET ON WRITE I = REQ_TYPE %IF I = 14 %THEN I = 2 ! IF ERASE HAS FAILED - STILL MAY HAVE CLEARED BAD SPOT - SO TRY WRITE %IF REQ_TYPE = 14 %AND T_STREAMR0&15 = 1 %C %THEN REQ_TYPE = I %AND -> DOMORE %IF I = 2 %AND REQ_FAULTS <= WRETRY %C %THEN REQ_TYPE = 14 %AND -> DOMORE ! WRITETM IS FIXED IN INITIALISE -> FAILED FEND(16): ! UNLOAD HAS FAILED ! HAS IT FAILED BECAUSE DECK HAS BEEN PLACED OFF LINE !& NOTE/ THERE IS NO REPLY MADE TO UNLOAD REQUESTS. %IF T_SSTAT&X'80' # 0 %THEN %RETURN ! FAILED FOR SOME OTHER REASON - GET TAPE DOWN SOMEHOW. LOAD MESSAGE(7,""); ! AUTO UNLOAD FAILS PRESS STOP UNLD -> ASSUMEOPSDOIT FEND(23): ! SKIP BACK AFTER TM %IF REQ_TYPE = 23 %AND TM = 1 %C %THEN REPLY(4) %AND -> TOUT %C %ELSE FREPORT(" SKPBFRTM FAILS") !! CAN REPLY TO USER NOW - AVOID RACE APPARENT !! WITH REPLYING ON TM ATTN. FEND(9): ! SKIP TO TM HAS FAILED FEND(13): ! TEST FOR TM HAS FAILED FEND(17): FEND(19): ! SENSE HAS FAILED FEND(20): ! SEND PROPERTY CODE HAS FAILED OK(23): FAILED: REPLY(1) ->TOUT ! SKIP BACK AFTER TM - HAS TO FAIL ON TM FEND(6): ! (REVERSE READ RETRY FAILED SO MOVING BACK) FAILED FEND(24): FEND(25): ! SKIP BACK FOR ERR REC FAILS FEND(7): ! SKIP TO NEXT BLOCK AFTER ERROR RECOVERY FAILED ! IF A SKIP FAILS THEN I CANNOT RECOVER REPLY(1) T_LOAD=NOT LOADED TELLVOLS ->TOUT OK(5): ! PRIVATE CHAINS ARE LIKE FEND(5): ! ROLLS-ROYCES AND NEVER FAIL -> SUCCESS OK(1): BACKTM: ! READ OK(XCPT ET &TM) OK(11): ! READ RETRY HAS WORKED OK(12): ! READ WITH ERR CORRN HAS WORKED OK(7): %IF TM = 0 %THEN REPLY(BT<<2) %AND -> TOUT REQ_TYPE = 23; ! SKIP (_LENGTH HAS OLD DIRECTION) -> REVDOMORE FEND(1): ! READ HAS FAILED FEND(11): ! READ RETRY HAS FAILED FEND(12): ! READ WITH ERR CORRN HAS FAILED -> BACKTM %IF BT # 0 %OR TM # 0 !! GIVE UP IF RECOVERY IMPOSSIBLE ! GIVE LABEL READS ONLY FOUR RETRIES - IT MAY BE AN ENORMOUS IPL BLOCK. -> FAILED %IF T_SSTAT&X'88' # 0 %OR (REQ_FAULTS > RETRY %ANDC T_FAULTS&1=1) %OR (T_USE&LOADING#0 %AND REQ_FAULTS>3) ! SKIP BACK REVERSE DIRN. FOR RETRY OK(6): ! IF SUFFICIENT RETRIES HAVE BEEN MADE AND THE DIRECTION OF ! THE LAST COMMAND WAS THE SAME AS THAT OF THE ! ORIGINAL COMMAND THEN GIVE FAILED. I.E. THE TAPE IS ! POSITIONED AFTER THE UNREADABLE BLOCK. ! %IF ((T_ORGDIR=1 %AND REQ_LENGTH>0 ) %ORC (T_ORGDIR=0 %AND REQ_LENGTH<0) ) %C %AND REQ_FAULTS > RETRY %THEN -> FAILED ! IF LONG BLOCK THEN RETRY IN ORIGINAL DIRECTION ONLY %IF PSTAT&4#0 %THEN REQ_TYPE=25 %ELSEC REQ_TYPE = 24 -> REVDOMORE OK(8): FEND(8): ! SKIP - FILE POSN. -> BACKTM %IF T_T2&8 # 0 %OR (TM # 0 %C %AND REQ_CONTROL&1 = 0) -> FAILED %IF ABN # 0 -> SUCCESS %IF REQ_COUNT1 = IMOD(REQ_LENGTH) -> DOMORE OK(9): ! SKIP TO TM IS OK REPLY(4) %AND -> TOUT %IF BT # 0 %IF REQ_COUNT1 = REQ_CONTROL %THEN %START ! IF ONE FILE SKIPPED REQ_COUNT2 = REQ_COUNT2+1 -> SUCCESS %IF REQ_COUNT2 >= IMOD(REQ_LENGTH) %IF REQ_LENGTH > 0 %THEN REQ_TYPE = TESTTM %C %ELSE REQ_COUNT1 = 0 %FINISH -> DOMORE OK(18): ! REVERSE DIRN READ RETRY OK(22): ! REVERSE DIRN READ RETRY REQ_TYPE = 7; ! SKIP TO NEXT BLOCK FOR READING IN ORIGINAL DIRECTION -> DOMORE FEND(18): FEND(22): REQ_TYPE = 6; ! SKIP BACK TO START OF BLOCK (ORIGINALLY END) -> DOMORE OK(24): ! SKIPPED BACK FOR RETRY OK !! ARRANGE REVERSE DIRECTION READ OCCASIONALLY %IF REQ_FAULTS > RETRY %THEN -> FAILED %IF T_FAULTS&1 = 1 %START; ! EVERY OTHER TRY !! !! THE LENGTH HAS BEEN REVERSED IN ORDER TO GET BACK TO THE !! POSITION AT START OF THE ORIGINAL READ. !! SO L<0 MEANS A FORWARD READ ETC. !! SINCE A REVERSE IS NOW REQD. 18 IS - !! SKIP FORWARD/READ BACKWARD !! AND 22 IS - !! SKIP BACKWARD/READ FORWARD !! %IF REQ_LENGTH < 0 %THEN REQ_TYPE = 18 %ELSE REQ_TYPE = 22 %FINISH %ELSE REQ_TYPE = 11 -> REVDOMORE OK(25): ! SKIPPED BACK FOR RETRY IN ORIGINAL DIRECTION %IF REQ_FAULTS>RETRY %THEN ->FAILED REQ_TYPE=11 ->REVDOMORE OK(13): ! TEST FOR TM -> BACKTM %IF TM # 0 REQ_COUNT1 = 0 REQ_TYPE = SKIPTOTM -> DOMORE SUCCESS: REPLY(0) -> TOUT REVDOMORE: REQ_LENGTH = -REQ_LENGTH DOMORE: T_USE = T_USE!2 %IF T_UNLOADPENDING # 0 %THEN REPLY(1) %AND -> TOUT INITIATE %RETURN TOUT: %IF T_UNLOADPENDING # 0 %START I = T_UNLOADPENDING T_UNLOADPENDING = 0 %IF I = 1 %THEN UNLOAD %ELSE RLSEREWIND %FINISH OK(4): FEND(4): ! UNUSED %END !*********************************************************************** %ROUTINE INITIATE !*********************************************************************** !* !******************************************* !* * !* FORM RCB,LBE'S,ALE'S AND PASS TO * !* GPC WHICH WILL CHECK, MAKE A COPY * !* AND CAUSE CHAINS TO BE EXECUTED * !* * !******************************************* %RECORDNAME RCB(RCBF) %INTEGERNAME LBEWORD %INTEGER CODE, L, C, I ! RECORD TO EXECUTE CHAIN %OWNINTEGER D = X'30000C', S = X'310005', P1, P2, P3 = %C X'11', P4, P5 %OWNINTEGER DUMMY; ! FORMS PART OF ABOVE REC %CONSTBYTEINTEGERARRAY CODES(0 : 25) = %C %C 27,21,26,0,0,X'F0',23,23, %C 0,0,28,21,25,30,37,0,4,3,11,5,29,4,14,23,23,23 %CONSTBYTEINTEGERARRAY ADRS(0 : 25) = %C %C 0,255,255,0,255,X'F0', %C 0,0,0,0,0,255,255,0,255,0,0,0,255,255,255,0,255,0,0,0 %CONSTBYTEINTEGERARRAY LENGTHS(0 : 25) = %C %C 255,255,255,255,255, %C X'F0',0,0,0,0,1,255,2,0,255,255,0,0,255,13, %C 3,0,255,0,0,0 %CONSTBYTEINTEGERARRAY LBSIZE(0 : 25) = %C %C 8,4,4,0,4,0,8,8,8,4,8,4,4,4,12,0,4,4,8,4,8,8,8,8,8,8 %CONSTBYTEINTEGERARRAY ALESIZE(0 : 25) = %C %C 16,8,8,0,8,0,16,16,16,8,16,8,8,8,8,0,8,8,8,8,16,8,8,16,16,16 !! RCB == T_RCB; ! JUST TO SAVE INDIRECTION CODE !! C = REQ_TYPE !! !! GET INDEX INTO LBE ARRAY !! CODE = CODES(C) %IF C = PRIVATE CHAIN %THEN MOVE(28,REQ_SPAN,ADDR(RCB)) %C %AND -> FIRE !! %IF REQ_LENGTH < 0 %START %IF CODE = RDF %THEN CODE = RDR %IF CODE = RCH %THEN CODE = RCHR %IF 23 <= CODE <= 24 %THEN CODE = SRB %FINISH %IF SKIPBLK <= C <= SKIPTOTM %START REQ_COUNT1 = REQ_COUNT1+1 %IF REQ_LENGTH < 0 %THEN CODE = 24 %ELSE CODE = 23 %IF C&1 = 1 %THEN CODE = CODE-22 %FINISH !! !! GET LENGTH !! L = LENGTHS(C) %IF L = 255 %THEN L = REQ_LENGTH !! !! GET ADDRESS !! T_ALE2 = ADRS(C) %IF T_ALE2 = 255 %THEN T_ALE2 = REQ_SPAN !! !* ! CHUCK OUT REQUESTS ON INOPERABLE DEVICES ! - ALLOW CONNECT,SENSE AND SEND PROPERTY CODE !* %IF (C < 19 %OR C > 20) %AND T_T0&X'C0' # 0 %C %THEN REPLY(REJECT) %AND %RETURN !* ! CLEAR SENSE BITS !* %CYCLE I = 2,1,12 BYTEINTEGER(ADDR(T_SSTAT)+I) = 0 %REPEAT !* ! STUPID CONTROLLER GIVES CDE IF ALE NOT VALID WHETHER USED OR NOT ! GIVE IT A DUMMY - MEANS SHORT BLOCK ON SUCH COMMANDS (MASKED OFF) !* L = -L %IF L < 0 L = 4 %IF L = 0 %IF T_ALE2 = 0 %THEN T_ALE2 = ADDR(DUMMY) %AND L = 4 !* RCB_LB BYTES = LBSIZE(C); !! GET SIZE OF LOGIC BLOCK RCB_AL BYTES = ALESIZE(C); ! GET SIZE OF ALE BLOCK !! ! MODE=3 = 1600 BPI PHASE ENCODED : MODE = 2 = 800 BPI NRZ. %IF T_BITS&1 = 1 %THEN RCB_INITWORD = 2 %C %ELSE RCB_INITWORD = 3 !! ! ALLOW CUSTOM VM MAP - TO COPE WITH LARGE TRANSFERS. ! IE NON CONTIGUOUS CLAIMED PAGES APPEAR MAPPED TOGETHERINTO ! ONE LARGE BUFFER. ! REQUESTS SCANNED BY DAVE (DOUT 18) AND APPROPRIATE ! PAGES LOCKED DOWN. FIELDS DESCRIBING LOCAL ! SEGMENT TABLE PASSED IN P5 AND P6 FOR RCB. %IF T_ALE2 > 0 %START; ! LOCAL ADDRESS RCB_LSTBA = REQ_LSTBA RCB_LIMFLAGS = REQ_LSL!X'8000' %FINISH %ELSE %START; ! PUBLIC ADDRESS RCB_LSTBA = NORMLSTRA RCB_LIMFLAGS = X'8000'; ! 8 IS INITIALISE BIT ! ALWAYS INIT DEVICE TO SAVE REMEMBERING WHICH UNIT ! WAS LAST USED ON THE STREAM. %FINISH !! %UNLESS CODE = SNS %OR CODE = SPC %OR CODE = ULD %C %THEN RCB_INITWORD = RCB_INITWORD!X'FC00' MOVE(RCB_LB BYTES,ADDR(LBE(CODE)),ADDR(T_LBE1)) ! TACK SENSE ON END OF THESE ! REMEBER THAT THE SENSE OVERWRITE PSTAT &TM LB,SB IMFO %IF 23 <= CODE <= 24 %OR 27 <= CODE <= 29 %C %THEN T_LBE2 = LBE(SNS)!2 %IF REQ_TYPE=14 %AND T_ORGREQ=WRITETM %THEN %C T_LBE3=X'80F02300' !! !! CONTROL BITS SPECIFY WHETHER SHORT/LONG BLOCK !! CONDITIONS ARE TO BE ALLOWED TO CAUSE !! ABNORMAL TERMINATIONS. !! ALSO LOOK TO INHIBIT DATA TRANSFER ON CHECKREADS. !! %IF REQ_CONTROL&12 # 0 %OR T_ORGREQ = CHREAD %START %CYCLE I = 0,4,12 LBEWORD == INTEGER(ADDR(T_LBE1)+I) %IF LBEWORD&X'0200' = X'0200' %C %OR LBEWORD&X'1200' = X'1200' %START ;! READ OR READ REV %IF REQ_CONTROL&4 = 4 %THEN LBEWORD = LBEWORD! %C X'800000' %IF REQ_CONTROL&8 = 8 %THEN LBEWORD = LBEWORD! %C X'400000' %IF T_ORGREQ = CHREAD %THEN LBEWORD = LBEWORD! %C X'20000000' %FINISH %REPEAT %FINISH RCB_LBA AL = ADDR(T_LBE1) ! IGNORE SLXY FOR LABEL READ %IF T_USE&LOADING # 0 %AND CODE = RDF %C %THEN T_LBE1 = T_LBE1!X'F00000' RCB_ALA = ADDR(T_ALE1) T_ALE1 = X'18000000'!L; ! BYTE DESCRIPTOR T_ALE3 = X'1800000D' ;! SENSE DESCRIPTOR T_ALE4 = ADDR(T_SSTAT) ! GPC FILLS IN PORT,TRUNK AND STREAM FROM GROPE TABLE FIRE: RCB_INITWORD = RCB_INITWORD!((T_PROP2&7)<<24) ;! MECHANISM P1 = ADDR(RCB) P2 = T_SNO; ! DEVICE SNO %IF RLEVEL&4 # 0 %THEN DUMPTABLE(61,ADDR(T_LINK),TSIZE) T_OPS = T_OPS+1 %IF (1< SENDPON %IF I = REJECT REP_P2 = T_STREAMR0 REP_P3 = (T_STREAMR1<<14)!T_SSTAT MOVE(12,ADDR(T_T0),ADDR(REP_P4)) -> SENDPON %FINISH %IF PSTAT&12 # 0 %START; ! REPORT S/L BLOCK %IF PSTAT&8 = 8 %THEN REP_P4 = 1 %IF PSTAT&4 = 4 %THEN REP_P4 = 2 %FINISH !! %IF T_ORGREQ=2 %AND REP_P2=0 %C %AND REQ_FAULTS # 0 %AND REQ_CONTROL&2 = 0 %C %AND T_EXERRS<=16 %THEN PRINTSTRING(" ".T_MNEM." ".T_DSN." ".HTOS(REQ_ %C FAULTS,3)." WRITE RETRY OK ") !! %IF (T_ORGREQ=1 %OR T_ORGREQ=4 %OR T_ORGREQ=6 ) %START ;! READ %IF REP_P2=0 %AND T_EXERRS<=16 %ANDC REQ_FAULTS # 0 %AND REQ_CONTROL&2 = 0 %C %THEN PRINTSTRING(" ".T_MNEM." ".T_DSN." ".HTOS( %C REQ_FAULTS,3)." READ RETRY OK ") !* !* SORT OUT LENGTH OF BLOCK !* LEN = T_ACTLEN !* !* NOTE: A NEGATIVE LENGTH RETURNED TO THE USER INDICATES !* A PARTIAL BLOCK AT THE TOP OF THE BUFFER. !* WITHOUT KNOWING THE FULL LENGTH IT CANNOT BE MOVED. !* %IF (LEN<0 %AND REP_P2=0) %START LEN=-LEN !*MUST MOVE DATA TO START OF BUFFER %IF PSTAT&SHORTBLOCK#0 %THENC MOVE(LEN,(REQ_SPAN+(REQ_LENGTH-LEN)),REQ_SPAN) %FINISH REP_P3=LEN %FINISHELSE REP_P3=REQ_LENGTH !* !! %IF T_ORGREQ=SKIPTOTM %OR T_ORGREQ=SKIPBLK %START %IF T_ORGREQ=SKIPTOTM %AND ( REP_P2=0 %ORC REP_P2=4 ) %THEN REQ_COUNT1=REQ_COUNT1-1 %IF T_ORGREQ = SKIPTOTM %THEN REP_P3 = (REQ_COUNT2*REQ_ %C CONTROL)+REQ_COUNT1 %ELSEC REP_P3=REQ_COUNT1 %FINISH !! ! INTERCEPT INTERNAL CALLS TO SAVE PONS %IF T_USE&LOADING > 0 %THEN LOAD %ELSE %START BYTEINTEGER(ADDR(REP_P4)+1) = T_ORGREQ %UNLESS X'30' <= (REP_DEST>>16)&X'FF' <= X'31' %START SENDPON: %IF REP_P2 = 1 %AND T_EXERRS<=16 %THEN PRINT %C STRING(T_MNEM." UNRECOVERED ERROR ".T_DSN." ") MYPON(REP) %IF T_USERCOUNT>0 %OR REP_P2=2 T_LAST REPLY= REP_P2&255 %FINISH T_USE = 0; ! NOT BUSY REPLIED = 1 %FINISH %END; ! OF REPLY !******************************************************************* !* !* %ROUTINE LOAD MESSAGE(%INTEGER N, %STRING (6) DSN) !!**************************************************************** !* * !* RECEIVES MESSAGES FROM TAPE ABOUT CHANGES IN DEVICE STATUS. * !* OUTPUTS APPROPRIATE MESSAGES TO OPERATOR CONSOLE AND UPDATES * !* TABLES * !* * !***************************************************************** !* %SWITCH IN(1 : 9) %INTEGER CHAR, I %CONSTSTRING (19) %ARRAY MESS(2 : 9) = %C %C "LOADED NO LABEL", "INOPERABLE", "NO WRITE RING", "IS FREE", "AUTO-UNLOAD FAILS", "PRESS STOP/UNLOAD", "OFFLINE WHEN IN USE", "OFFLINE WHEN CLMND" -> IN(N) IN(1): ! DEVICE LOADED WITH LABEL %CYCLE I = 1,1,6 CHAR = CHARNO(DSN,I) OPMESS(T_MNEM." FAULTY DSN ".DSN) %AND %RETURN %C %UNLESS '0' <= CHAR <= '9' %C %OR 'A' <= CHAR <= 'Z' %OR CHAR = ' ' %REPEAT T_DSN = DSN T_LOAD = LOADED WITH LABEL ! TAPE LOADED OPMESS(T_MNEM." LOADED ".DSN) %RETURN IN(2): T_DSN = "NOLABEL"; ! DEVICE LOADED NO LABEL T_LOAD = LOADED NO LABEL -> IN(5) IN(3): T_LOAD = INOP; ! DEVICE INOPERABLE IN(4): ! DEVICE INOPERABLE NO WRITE RING IN(5): IN(6): IN(8): IN(9): OPMESS(T_MNEM." ".MESS(N)) %RETURN IN(7):LOAD MESSAGE(6,"") -> IN(6) %END; ! OF LOAD MESSAGE !* %ROUTINE VOLUME DONE(%RECORDNAME P) !* - ACTIVITY 7 !********************************************************************** !* * !* CALLED WHEN A USER IS FINISHED WITH A VOLUME !* * !********************************************************************** %RECORDSPEC P(PF) !* ! VOLUMES GETS A LOAD STATE MESSAGE TO BRING HIS TABLES UP TO DATE %IF (FINDTP(P_P2&X'FFFF') = 0 %OR FINDDSN(P_DSN) = 0) %C %AND T_USERCOUNT > 0 %THEN %START T_USERCOUNT = 0 REQ = 0; ! REQ_SRCE=0 INSURES NO MESSAGE TO VOLS. IF OP FAILS REQ_DEST = 7; ! JUST TO SHOW WHAT IS GOING ON %IF P_P5 = 0 %THEN UNLOAD %ELSE RLSEREWIND LOAD MESSAGE(5,P_DSN) %FINISH P_P2=OK ;! VOLUMES DOES NOT CARE ABOUT REPLY !! !! CURRENTLY MUST REPLY TO VOLUMES, BUT THIS COULD BE AVOIDED !! IF VOLUMES AND TAPE CHANGED TOGETHER. !! %END; !OF ROUTINE VOLUME DONE !* !* %ROUTINE VOL REQUEST(%RECORDNAME P) !* - ACTIVITY 12 !********************************************************************* !* * !* CALLED BY A REQUEST FROM A USER FOR A VOLUME. IF IT IS AVAILABLE * !* HE GETS IT IF NOT A FAILED REPLY IS RETURNED !* * !********************************************************************* %RECORDSPEC P(PF) %INTEGER I !* %IF P_DSN = "NOLABEL" %OR P_DSN = "" %C %THEN I = FINDMN(STRING(ADDR(P_P5))) %C %ELSE I = FINDDSN(P_DSN) %IF I = 0 %AND T_USERCOUNT = 0 %START %UNLESS (T_PROP3&X'40' # 0 %C %AND P_P2&X'FFFF' # READ) %START T_USERCOUNT = 1 INTEGER(ADDR(P_DSN)) = PONSRCE!T_SNO ! P_P3 P_GROUP NUMBER = T_PROP2 P_P2 = OK %FINISH %ELSE P_P2 = 2 %AND LOAD MESSAGE(4,P_DSN) %FINISH %ELSE P_P2 = 1 !! !! REPLY RECORD FORMAT !! !! P1 -IDEN !! P2 - RETURN CODE !! - 0 = OK !! - 1 BAD PARAMS (CANNOT FIND TAPE) !! - 2 NO RING(IF REQD) !! !! P3 - DEST FIELD TO BE USED TO ACCESS THE TAPE !! %END; !OF ROUTINE VOL REQUEST !! !!************************************************ !! !* TABLE SEARCH ROUTINES !! %INTEGERFN FINDTP(%INTEGER DSNO) %RESULT = -1 %IF MAXTPS <= 0 T == RECORD(FIRSTTP) %CYCLE %IF T_SNO = DSNO %THEN REQ == T_REQ %AND %RESULT = 0 %RESULT = -1 %IF T_LINK = 0 T == RECORD(T_LINK) %REPEAT %END !! !! %INTEGERFN FINDDSN(%STRING (8) DSN) %RESULT = -1 %IF MAXTPS <= 0 T == RECORD(FIRSTTP) %CYCLE %IF T_DSN = DSN %THEN REQ == T_REQ %AND %RESULT = 0 %RESULT = -1 %IF T_LINK = 0 T == RECORD(T_LINK) %REPEAT %END !! !! %INTEGERFN FINDMN(%STRING (4) MNEM) %CONSTSTRING (6) %ARRAY ST(0 : 3) = %C " AUTO "," - "," MAN "," - " %INTEGER DISPLAY, REPORT PREVLINK = ADDR(FIRSTTP) %RESULT = -1 %IF MAXTPS <= 0 %IF MNEM = "" %THEN DISPLAY = 1 %ELSE DISPLAY = 0 %IF MNEM = "VOLS" %THEN REPORT = 1 %ELSE REPORT = 0 T == RECORD(FIRSTTP) %CYCLE OPMESS(HTOS(T_SNO,2)." ".T_MNEM.ST(T_T0>>6).T_DSN) %C %IF DISPLAY = 1 %IF REPORT = 1 %AND T_LOAD > 0 %THEN TELLVOLS %IF T_MNEM = MNEM %THEN REQ == T_REQ %AND %RESULT = 0 %RESULT = -1 %IF T_LINK = 0 PREVLINK = ADDR(T_LINK) T == RECORD(T_LINK) %REPEAT %END !! !!******************************************************** !! !! THE NEXT TWO ROUTINES - PEND AND UNPEND ARE USED TO !! ACCESS A QUEUE OF TAPE REQUESTS. IF A UNIT IS BUSY !! WHEN A REQUEST ARRIVES THEN THE REQUEST IS KEPT !! UNTIL THE UNIT IS FREE. !! REQUIRES CARE BY THE USER IN RESPONDING TO ERRORS !! !!******************************************************** !! %ROUTINE PEND %INTEGER I !! QUEUE A TAPE REQUEST !! %IF TMON # 0 %THEN MON(4,P) I = NEWPPCELL PB(I)_P = P %IF T_FIRSTPEND = -1 %THEN T_FIRSTPEND = I %C %ELSE PB(T_LASTPEND)_LINK = I ! IF NOT FIRST THEN LINK TO PREVIOUS T_LASTPEND = I %END !! !! %ROUTINE UNPEND(%INTEGER FP) ! RELEASE QUEUED REQUEST !! P = PB(FP)_P %IF TMON # 0 %THEN MON(5,P) T_FIRSTPEND = PB(FP)_LINK RETURNPPCELL(FP) %IF FP = T_LASTPEND %THEN T_LASTPEND = -1 %C %AND T_FIRSTPEND = -1 %END; ! OF UNPEND !! !! !! !!*************************************************** !! %ROUTINE MYPON(%RECORDNAME P) %RECORDSPEC P(PE) %RETURN %IF P_DEST = 0; ! JUST IN CASE %IF TMON # 0 %OR RLEVEL&2 # 0 %THEN MON(3,P) PON(P) %END !! !!***************************************************** !! %ROUTINE MON(%INTEGER MODE, %RECORDNAME P) %RECORDSPEC P(PF) %CONSTSTRING (4) %ARRAY MODES(1 : 5) = %C %C "IN","OUT","PONS","PEND","UNPD" PKMONREC(" TAPE( ".MODES(MODE)."): ",P) %END !! !******************************************************************* !* !* %ROUTINE FREPORT(%STRING (17) M) !* !************************************************* !* * !* LOG ERROR BEFORE CONTINUING. * !* * !************************************************* !* %INTEGER I, J,SIZE RESERVELOG %IF MULTIOCP=YES PRINTSTRING(" TAPE ERROR// ".M." DECK ") PBYTE(T_PROP2) PRINTSTRING(" FAULTS (DECK/REQ) ") PRHEX((T_FAULTS<<16)!REQ_FAULTS) PRINTSTRING(" REQ ID ") PRHEX(REQ_IDEN) SPACE PRINTSTRING(T_DSN) %IF (1< L %IF (1< L PRINTSTRING(" OTHER ") L: %IF T_STREAMR0<<8>>24 = X'41' %C %THEN PRINTSTRING(" ***CDE***") PRINTSTRING(" SST T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 ") J = ADDR(T_SSTAT) %CYCLE I = 0,1,12 SPACE PBYTE(BYTEINTEGER(J+I)) %REPEAT ! TRUNCATE TABLE TO JUST WHAT JOURNL NEEDS IN REPITITIOUS ERRORS. %IF REQ_FAULTS<2 %THEN SIZE=TSIZE %ELSE SIZE=64 DUMP TABLE(61,ADDR(T),SIZE) RELEASELOG %IF MULTIOCP=YES %END; ! OF FREPORT %END; ! OF TAPE %ENDOFFILE FREE ASSUMEOPSDOIT: T_USE = 0; ! SCRUB UNLOADING BIT T_T0 = T_T0!X'80'; ! PREMATURELY SET MANUAL BIT IN SENSE DATA ->TOUT FEND(0): ! ERASE HAS FAILED FEND(2): ! WRITE HAS FAILED FEND(3): ! WRITE&CHECK HAS FAILED FEND(14): ! WRITE RETRY HAS FAILED