!************************************************** !* * !* 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 PTREC(%RECORDNAME P) %EXTERNALROUTINESPEC PRHEX(%INTEGER N) %EXTERNALROUTINESPEC GPC(%RECORDNAME P) %EXTERNALROUTINESPEC DUMP TABLE(%INTEGER TABNO, START, L) %EXTRINSICLONGINTEGER PARMDES %EXTERNALINTEGERFNSPEC NEWPPCELL %EXTERNALROUTINESPEC RETURNPPCELL (%INTEGER CELL) !! !! 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, %INTEGER COUNT1, COUNT2) %RECORDFORMAT RCBF(%INTEGER LIMFLAGS, LSTBA, LB BYTES, LBA AL, %C ALBYTES, ALA, INITWORD) %RECORDFORMAT TFM(%INTEGER LINK, %C %BYTEINTEGER SNO, DEV, LBSIZE, USERCOUNT, %C %INTEGER LOAD, FAULTS, FLAG, LBE1, LBE2, LBE3, LBE4, ALE1, %C ALE2, STREAMR0, STREAMR1, OPS, EXERRS, %C %STRING (3) MNEM, %C %BYTEINTEGER SSTAT, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, %C T10, T11, NEXT, TYPEMOD, PROP1, PROP2, PROP3, USE, %C %RECORD REQ(REQF), %RECORD RCB(RCBF), %C %INTEGER LAB1, LAB2, %STRING (7) DSN, %C %BYTEINTEGER ORGDIR,SP2, ORGREQ, BITS, %C %INTEGER FIRSTPEND,LASTPEND) %RECORDFORMAT PF(%INTEGER DEST, SRCE, FLAGLINK, P2, %C %STRING (6) DSN, %BYTEINTEGER D1, %INTEGER P5, P6) %RECORDFORMAT GPCTF( %C %BYTEINTEGER FLAGS, TYPEMOD, PAWFN, SAWFLAGS, LINK, NLBES, %C SERVRT, DEVSNO, %INTEGER RESP0, RESP1, RCB OFFSET, PTSM, %C MNEMONIC, SPO) !------------------------------------------------------------------------ %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' %OWNINTEGER FIRSTTP %CONSTINTEGER CALLSRCE = X'80310000', PONSRCE = X'00310000' %CONSTINTEGER ALLOCATE = 4 %CONSTINTEGER DEALLOCATE = 5 %CONSTINTEGER TSIZE = 184 ! SIZE IN BYTES OF ONE TAPE RECORD %CONSTINTEGER BADPARAMS = 1 %CONSTINTEGER OK = 0 %CONSTINTEGER ON = 1, OFF = 0 !! !! 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' !! !! 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 !! !! 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 = 3 %CONSTINTEGER NOT LOADED = 0 %CONSTINTEGER INOP=-2 %CONSTINTEGER UNLOADON=-1 ! %CONSTINTEGER NOSTREAM = -3 !! %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', 0,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 - ATTENTION ! 4 - INITIALISE ,ACCEPT,RELEASE DECKS ! 5 - ABNORMAL TERMINATION ! 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 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) !! !! !*********************************************************************** %ROUTINESPEC TERMINATE(%INTEGER I) %ROUTINESPEC INITIATE %ROUTINESPEC ATTENTION %ROUTINESPEC LOAD ? %ROUTINESPEC INIT %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 CALLGPC(%INTEGER A, MNEM) ? %ROUTINESPEC NEWTAPEENTRY(%INTEGER AMNEM) %ROUTINESPEC MON(%INTEGER MODE, %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 : 2015)(PBF) %OWNRECORDARRAYNAME PB(PBF) %OWNINTEGER RETRY = 15; ! NO OF RETRIES ON READ ! LIMITED IN MAX INTERBLOCK GAP FOR WRITE RETRIES %OWNINTEGER WRETRY = 6; ! NUMBER OF RETRIES ON WRITE %INTEGER NUNITS, MODE, MNEM %STRING (4) SMNEM %CONSTINTEGER XCOM = X'31D0'; ! SELECT SUBSET OF ENTRIES ? %OWNINTEGER INITIALISED = 0; ! TAKE NO ACTION TILL INITED %RECORD REP(PE) %SWITCH ENTRY(1 : 13) ? %RECORDARRAYFORMAT GPCSLFM(1 : 255)(GPCTF) ? %RECORDARRAYNAME GPCSLOT(GPCTF) %INTEGER TMON; ! NON - ZERO IF KMON BIT SET %INTEGER PSTAT %INTEGER REPLIED %INTEGER I, DSNO, DACT, J %OWNINTEGER REPDEST = 0; ! WHO TO REPORT TAPE LOADS TO %OWNINTEGER UNLOADPENDING = 0; ! USE IF BUSY WHEN HOLD SET ! 1 = UNLOAD ! 2 = REWIND !* !* !* %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' ? %IF INITIALISED = 0 %AND DACT # 4 %THEN -> FAULTYP %IF MAXTPS = 0 %AND 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 2 <= DACT <= 3 %OR DACT = 5 %THEN %START; ! TERM. OR ATTN. 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) !----------------------------- ENTRY(1): ! REQUEST %IF T_USE # 0 %THEN PEND %AND %RETURN; ! QUEUE REQ. IF UNIT BUSY I = PREPARE REQUEST(P) REPLY(REJECT) %IF I # 0 %RETURN !----------------------------- ENTRY(2): ENTRY(5): ! TERMINATION : 2 = NORMAL , 5 = ABNORMAL ! TRUE TERMINATION OF REWIND AND TM SKIPS COMES WITH ATTN BT %IF DACT = 2 %AND (REQ_TYPE = REWIND %C %OR REQ_TYPE = SKIPTOTM) %THEN %RETURN TERMINATE(DACT&1) %IF REPLIED = 1 %THEN -> CHPEND %ELSE %RETURN !------------------------------- ENTRY(3): ! ATTENTION ATTENTION %IF REPLIED = 1 %THEN -> CHPEND %ELSE %RETURN !------------------------------------ ENTRY(4): !ACCEPT OR RELEASE TAPE DECKS !! !! 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 !! !! ? %IF P_P1<0 %THEN INIT %AND %RETURN ;! OLD ROUTE %IF P_SRCE&X'FF0000' = GPCSNO %START ? INITIALISED=1 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 MNEM = P_P1 P_P1 = 0 %WHILE NUNITS > 0 %THEN %CYCLE J = MNEM!(3<<24) SMNEM = STRING(ADDR(J)) I = FINDMN(SMNEM) %UNLESS (MODE = OFF %AND I = -1) %OR (MODE = ON %C %AND I # -1) %START PP = 0 %IF MODE = ON %THEN PP_DEST = GPCSNO!ALLOCATE %C %ELSE PP_DEST = GPCSNO!DEALLOCATE PP_SRCE = CALLSRCE PP_P1 = MNEM %IF TMON#0 %OR RLEVEL&2#0 %THEN MON(2,PP) GPC(PP) %IF PP_P1 # 0 %THEN -> NEXT %IF MODE = ON %START MAXTPS = MAXTPS+1 D == RECORD(PP_P3) %UNLESS MAXTPS = 1 %THEN T_LINK = D_UA AD %C %ELSE FIRSTTP = D_UA AD T == RECORD(D_UA AD); ! GIVE THIS DECK AN ENTRY IN THE TABLE T = 0 T_MNEM = SMNEM T_PROP2 = (MNEM&X'FF')-X'30' T_SNO = PP_P2 T_FIRSTPEND = -1 T_LASTPEND = -1 T_EXERRS = 16 REQ == T_REQ LOAD; ! TEST DECK AND READ LABEL IF POSSIBLE. %FINISH %ELSE MAXTPS = MAXTPS-1 %C %AND INTEGER(PREVLINK) = T_LINK %FINISH ! NOTE: IGNORING ALLOCATE/DEALLOCATE FAILURES SINCE THESE ARE !! ENDEMIC WHEN THE NUMBER OF DECKS PER CLUSTER IS UNKNOWN. NEXT: MNEM = MNEM+1 NUNITS = NUNITS-1 %REPEAT ! VOLUMES EXPECTS A REPLY %IF P_SRCE&X'FF0000' # GPCSNO %THEN -> VOLREPLY %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 <= 512 %IF P_P1 = 16 %THEN RETRY = P_P2 !? %IF P_P1 = 16 %THEN OPMESS("READ RETRIES = ".HTOS(P_P2,3)) %IF P_P1 = 17 %THEN WRETRY = P_P2 %FINISH %ELSE RLEVEL = P_P1 %RETURN !------------------------------- 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 %IF TMON # 0 %OR RLEVEL&2#0 %THEN MON(3,P) PON(P) %IF P_DEST >= 0 %RETURN !------------------------------------ ENTRY(13): I = FINDMN("") ;! DISPLAY DECK STATUS. %RETURN !! CHPEND: ! RELEASE NEXT QUEUED REQUEST IF ANY %IF T_FIRSTPEND # -1 %THEN UNPEND(T_FIRSTPEND) %C %AND -> REENTER %RETURN FAULTYP: PRINTSTRING(' TAPE // PARAMS ?? ') PTREC(P) !! !* !************************************************************************ !* ? %ROUTINE INIT ? !* - ACTIVITY 4 ? !!************************************************************* ? !* * ? !* INITIALISATION SEQUENCE - * ? !* A) FIND ANY TAPE DECKS IN THE GPC TABLE (FOUND IN GROPE) * ? !* B) ALLOCATE A RECORD IN THE TAPE TABLE TO EACH DECK. ? !* C) CALL 'LOAD' TO SENSE STATUS ETC AND TO READ ANY LABEL * ? !* NOTE: WE GET LUMBERED WITH AN ENTRY FOR EACH POSSIBLE * ? !* TAPE BECAUSE THE GROPE ROUTINE CANNOT ? !* DISTINGUISH BETWEEN A TAPE IN MANUAL AND AN * ? !* UNUSED TAPE CONNECTION POINT. ? !* P1 - ADDRESS OF GPC SLOT TABLE * ? !* P2 - NUMBER OF LAST SLOT (COUNTING FROM 0)* ? !* P3 - ADDRESS OF QUEUE SPACE ? !* P4 - LENGTH OF QUEUE SPACE ? !* * ? !************************************************************** ? !* ? !* ? %INTEGER I, MNEM, AMNEM ? AMNEM = ADDR(MNEM) ? MAXTPS = 0 ? !! ? !! FIND TAPES IN GPC SLOT TABLE ? !! ? INITIALISED = 1; ! ACCEPT MESSAGES NOW ? PB==ARRAY(INTEGER(ADDR(PARMDES)+4),PBAF) ? GPCSLOT == ARRAY(P_P1,GPCSLFM) ? %CYCLE I = 1,1,P_P2+1 ? MNEM = GPCSLOT(I)_MNEMONIC ? %EXIT %IF MNEM = 0 ? %IF BYTEINTEGER(AMNEM+1) = 'M' %START; ! FIND TAPES ? CALLGPC(ALLOCATE,MNEM) ? %IF PP_P1 = 0 %THEN NEW TAPE ENTRY(AMNEM) ? %FINISH ? %REPEAT ? !! ? %IF MAXTPS = 0 %THEN OPMESS("NO TAPE DECKS!") %C %ELSE T_LINK = 0 ? !! ? %END; ! OF INIT !****************************************************************** !: !* !* !* %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' !! 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' %IF REQ_CONTROL>>7 = 1 %THEN T_BITS = T_BITS!1 REQ_COUNT1 = 0 REQ_COUNT2 = 0 REQ_FAULTS = 0 !! SUPPRESS ERROR RECOVERY ? %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 %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: 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. !! %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 %CYCLE I = 0,1,7 %IF AB&1 = 1 %START %IF AB>>1 # 0 %AND ATTN # X'84' %AND ATTN#X'C0' %START FREPORT(' MULTIPLE ATTNS ') !! 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. !! %IF ATTN&X'40' # 0 %THEN AB = 0 %AND -> ATT(6) ! LOAD IF ON BT !! OTHERWISE LEAVE THINGS ALONE %RETURN %FINISH -> 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' %RETURN ATT(2): ! AVAILABLE T_T0 = T_T0&X'BF' %RETURN ATT(4): ! TAPE MARK FOUND %IF REQ_TYPE = SKIPTOTM %THEN TERMINATE(0) 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 ! 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 T_USE&LOADING = 0 %THEN LOAD ! WHAT IF ALREADY LOADED AND IN USE ?? %FINISH AB = AB>>1 %REPEAT %END; ! OF ATTENTION !********************************************************************** !* !* %ROUTINE UNLOAD !******************************************* !* * !* FIRE OFF UNLOAD - DISCONNECTS DECK * !* (SO RE-CONNECT IS APPENDED) * !* * !******************************************* !* %IF T_USE&8 # 0 %START UNLOADPENDING = 1 %RETURN %FINISH PRINTSTRING(T_MNEM." ".T_DSN." UNLOADING ") T_DSN = '' REQ_TYPE = UNLOADFLASH T_USE = UNLOADING T_LOAD = UNLOADON INITIATE TELLVOLS %END !! %ROUTINE RLSEREWIND !!***************************************** !!* * !!* REWIND TAPE AND RE-READ LABEL AS AN * !!* ALTERNATIVE TO UNLOADING * !!* * !!***************************************** !! %IF T_USE&8 # 0 %THEN 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 : 3) %INTEGER CC !! 3<<16+SENDPROPS !! REWIND !! 96<<16 + READF - NO ERROR RECV. !! REWIND !! %CONSTINTEGERARRAY P2S(0 : 3) = %C X'30014',X'11',X'100E01',X'0011' !! !! FAIL UNLESS FIRST ENTRY OR TERM OK OR S OR L BLOCK READ. %IF T_NEXT = 0 %THEN CC = 0 %C %ELSE CC = REP_P2 -> FAIL %UNLESS CC = 0 %OR CC = 7 %OR CC = 4 %C %OR (CC = 1 %AND T_STREAMR0&X'4300' = 0) PP = 0 T_USE = LOADING PP_SRCE = PONSRCE PP_P2 = P2S(T_NEXT) -> DOP(T_NEXT) !----------------------------------- DOP(0): ! READ PROPERTIES - SPECIFICALLY IF RING OR NOT - INCLUDES SENSE 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 -> STARTP !----------------------------------------------------------------------- DOP(2): ! READ LABEL ON TAPE -> OUT %IF T_LOAD > 0; ! OUT IF GOT LABEL PP_P3 = ADDR(T_LAB1); ! ADDRESS OF CLAIMED PAGE -> 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 %START MOVE(6,ADDR(T_LAB1)+4,ADDR(DSN)+1) LENGTH(DSN) = 6 ETOI(ADDR(DSN)+1,6) LOAD MESSAGE(LOADED WITH LABEL,DSN) -> OUT %FINISH ! REWIND IF UNLABELLED T_LOAD = FAULTY LOAD T_NEXT = 1 STARTP: LENGTH(T_DSN)=6 ;! INSURANCE AGAINST CONC CHECK ON GARBAGE T_NEXT = T_NEXT+1 %IF PREPARE REQUEST(PP) = 0 %THEN %RETURN FAIL: NEWLINE PBYTE(T_SNO) PRINTSTRING(' READ LABEL ABANDONED ') OUT: LENGTH(T_DSN)=6 ;! INSURANCE AGAINST CONC CHECK ON GARBAGE LOADMESSAGE(LOADED NO LABEL,'') %C %IF T_NEXT > 1 %AND T_LOAD # LOADEDWITHLABEL %IF T_LOAD = LOADEDWITHLABEL %C %OR T_LOAD = LOADEDNOLABEL %THEN TELLVOLS 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) %IF TMON # 0 %THEN MON(3,PP) PON(PP) %END !* !* %ROUTINE TERMINATE(%INTEGER ABN) !* - ACTIVITY 2 OR 3 !*********************************************************************** !* 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 !* + IF ABNORMAL !* P3 - SECONDARY STATUS<<24 !* - T1-T3 !* P4 - T4 -> T7 !* P5 - T8 -> T11 !* P6 - T12<<24 ! RESP FLAGS (SENSE) !* !* 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 %STRING (2) S %SWITCH OK, FEND(0 : 24) !! %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 ! BT CAN MEAN ET %IF T_T2&8 # 0 %OR PSTAT&1 = 1 %C %THEN BT = 1 %ELSE BT = 0 ! SET TM IF UNEXPECTED TM ONLY %IF PSTAT&2 > 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 P_P4&X'FF' = X'80' %THEN MOVE(13,D_SENSDATAD,ADDR(T_SSTAT)) %IF ABN = 0 %AND T_T6&X'F0' # 0 %AND T_TYPEMOD = 5 %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) ! DO NOT RETRY IF ONLY FAULT IS WRONG LENGTH BLOCK %IF (1< FAILED !! %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 ;! SUBSEQUENT REQUESTS WILL FAIL 2 %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 FREPORT(' ABNORMAL TERM ') ! AVOID RETRY ETC IF FAILURE BUSY,NRZ OR BLANK TAPE ->FAILED %IF T_T2&2#0 %OR T_T6&4#0 %OR T_T4&X'80'#0 %ORC T_T4&8#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(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 -> 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(10): ! WRITE 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): ! SKIP BACK AFTER TM - HAS TO FAIL ON TM FEND(6): ! (REVERSE READ RETRY FAILED SO MOVING BACK) FAILED FEND(24): ! SKIP BACK FOR ERR REC FAILS FEND(7): ! SKIP TO NEXT BLOCK AFTER ERROR RECOVERY FAILED FAILED: REPLY(1) -> 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 - DO NOT RETRY SHORT BLOCK FAILURES -> FAILED %IF T_SSTAT&X'88' # 0 %OR (REQ_FAULTS > RETRY %ANDC T_FAULTS&1=1) ! 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 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 %IF PSTAT&8 # 0 %THEN REQ_LENGTH = REQ_LENGTH-(T_ %C STREAMR1&X'3FFFF') ! REMEMBER LEN 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 ! RLEVEL = RLEVEL!2 %IF REQ_FAULTS > RETRY %THEN -> FAILED %IF T_FAULTS&1 = 1 %THEN %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(13): ! TEST FOR TM -> BACKTM %IF BT # 0 %OR 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 UNLOADPENDING # 0 %THEN REPLY(1) %AND -> TOUT INITIATE %RETURN TOUT: %IF UNLOADPENDING # 0 %START I = UNLOADPENDING 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 %INTEGER D, S, P1, P2, P3, P4, P5, P6 %OWNINTEGER DUMMY %CONSTBYTEINTEGERARRAY CODES(0 : 24) = %C 27,21,26,0,0,X'F0',23,23, %C 0,0,28,21,25,23,37,0,4,3,11,5,29,4,14,23,23 %CONSTBYTEINTEGERARRAY ADRS(0 : 24) = %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 %CONSTBYTEINTEGERARRAY LENGTHS(0 : 24) = %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 %CONSTBYTEINTEGERARRAY LBSIZE(0 : 24) = %C 8,4,4,0,4,0,8,8,8,4,8,4,4,8,12,0,4,4,8,4,8,8,8,8,8 %CONSTBYTEINTEGERARRAY ALESIZE(0 : 24) = %C 16,8,8,0,8,0,16,16,16,8,16,8,8,16,8,0,8,8,8,8,16,8,8,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)) %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 (CODE < 5 %OR CODE > 8) %AND T_T0&X'C0' # 0 %C %THEN REPLY(REJECT) %AND %RETURN !* ! CLEAR SENSE BITS !* %CYCLE I=0,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 %IF 23 <= CODE <= 24 %OR 27 <= CODE <= 29 %C %THEN T_LBE2 = LBE(SNS)!2 !! !! CONTROL BITS SPECIFY WHETHER SHORT/LONG BLOCK !! CONDITIONS ARE TO BE ALLOWED TO CAUSE !! ABNORMAL TETRMINATIONS. !! 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 %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!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' T_LBSIZE = RCB_LB BYTES RCB_ALA = ADDR(T_ALE1) T_ALE1 = X'18000000'!L; ! BYTE DESCRIPTOR T_STREAMR0 = X'1800000D';! IN USE AS ALE3 T_STREAMR1 = ADDR(T_SSTAT); ! IN USE AS ALE4 ! KEITH FILLS IN DEVICE NUMBER FIRE: RCB_INITWORD=RCB_INITWORD!((T_PROP2&7)<<24) D = X'480000A' S = CALLSRCE P1 = ADDR(RCB_LIMFLAGS) P2 = T_SNO; ! DEVICE SNO %IF TMON#0 %OR RLEVEL&2#0 %THEN MON(2,RECORD(ADDR(D))) %IF RLEVEL&4 > 0 %THEN PRINTSTRING(' TAPE CALLS ON GPC ') %C %AND DUMPTABLE(61,ADDR(T_LINK),TSIZE) T_OPS = T_OPS+1 %IF (1<L2 %IF I=REJECT REP_P2=T_STREAMR0 REP_P3=(T_STREAMR1<<14)!T_SSTAT MOVE(12,ADDR(T_T0),ADDR(REP_P4)) ->L2 %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 (1< 0 %THEN LOAD %ELSE %START BYTEINTEGER(ADDR(REP_P4)+1)=T_ORGREQ %UNLESS X'30' <= (REP_DEST>>16)&X'FF' <= %C X'31' %OR REP_DEST = 0 %START L2: %IF TMON # 0 %OR RLEVEL&2 # 0 %C %THEN MON(3,REP) %IF REP_P2 = 1 %THEN PRINTSTRING(T_MNEM. %C " UNRECOVERED ERROR ".T_DSN." ") PON(REP) %IF T_USERCOUNT>0 %OR REP_P2=2 %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 %C '0'<=CHAR<='9' %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) !* %IF (FINDTP(P_P2&X'FFFF') = 0 %C %OR FINDDSN(P_DSN) = 0) %C %AND T_USERCOUNT > 0 %THEN %START P_P2 = OK T_USERCOUNT = 0 %IF P_P5 = 0 %THEN UNLOAD %ELSE RLSEREWIND LOAD MESSAGE(5,P_DSN) %FINISH %ELSE P_P2 = BAD PARAMS %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_P2 = OK %FINISH %ELSE P_P2 = 2 %AND LOAD MESSAGE(4,P_ %C 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 !! !!************************************************ !! ? %ROUTINE CALLGPC(%INTEGER A, MNEM) ? PP = 0 ? PP_DEST = GPCSNO!A ? PP_SRCE = CALLSRCE ? PP_P1 = MNEM ? %IF TMON # 0 %THEN MON(2,PP) ? GPC(PP) ? %IF PP_P1 # 0 %START ? %IF A = ALLOCATE %THEN OPMESS("ALLOCATE FAILS ON ") %C %ELSE OPMESS("DE-ALLOCATE FAILS ON ") ? OPMESS(STRING(ADDR(MNEM))." - RC= ".HTOS(PP_P1,1)) ? %FINISH ? %END ? !! ? !! ? !************************************************8 ? !! ? ? %ROUTINE NEW TAPE ENTRY(%INTEGER AMNEM) ? !! ? MAXTPS = MAXTPS+1 ? D == RECORD(PP_P3) ? %UNLESS MAXTPS = 1 %THEN T_LINK = D_UA AD ? T == RECORD(D_UA AD) ? %IF MAXTPS = 1 %THEN FIRSTTP = D_UA AD ? T = 0 ? ! T_TYPEMOD=GPCSLOT(I)_TYPEMOD ? BYTEINTEGER(AMNEM) = 3 ? T_MNEM = STRING(AMNEM) ? T_PROP2 = BYTEINTEGER(AMNEM+3)-X'30' ? T_SNO = PP_P2 ? T_FIRSTPEND = -1 ? T_LASTPEND = -1 ? T_EXERRS = 16 ? REQ == T_REQ ? LOAD ? %END ? !********************************************** !* TABLE SEARCH ROUTINES !! %INTEGERFN FINDTP(%INTEGER DSNO) %INTEGER I %RESULT = -1 %IF MAXTPS = 0 T == RECORD(FIRSTTP) %CYCLE %IF T_SNO = DSNO %THEN REQ == T_REQ %C %AND %RESULT = 0 %RESULT = -1 %IF T_LINK = 0 T == RECORD(T_LINK) %REPEAT %END !! !! %INTEGERFN FINDDSN(%STRING (8) DSN) %INTEGER I %RESULT = -1 %IF MAXTPS = 0 T == RECORD(FIRSTTP) %CYCLE %IF T_DSN = DSN %THEN REQ == T_REQ %C %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 I, 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) %IF DISPLAY = 1 %IF REPORT=1 %AND T_LOAD>0 %THEN TELLVOLS %IF T_MNEM = MNEM %THEN REQ == T_REQ %C %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) %INTEGER I ! 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 MON(%INTEGER MODE, %RECORDNAME P) %RECORDSPEC P(PF) %CONSTSTRING (4) %ARRAY MODES(1 : 5) = %C %C 'IN','OUT','PONS','PEND','UNPD' PRINTSTRING(' TAPE( '.MODES(MODE).'): ') PTREC(P) %END !! !******************************************************************* !* !* %ROUTINE FREPORT(%STRING (17) M) !* !************************************************* !* * !* LOG ERROR BEFORE CONTINUING. * !* * !************************************************* !* %INTEGER I, J 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***') %IF T_STREAMR1 = -1 %THEN PRINTSTRING( %C " ***TIME OUT***") 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 DUMP TABLE(61,ADDR(T),TSIZE) %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