PROC L;
# TITLE L - LOW LEVEL REQUEST PROCESSOR DOCUMENTATION. #
BEGIN # L #
#
**** LOW LEVEL REQUEST PROCESSORS.
*
* THE FOLLOWING PROCESSORS CONSTITUTE THE LOW LEVEL REQUEST
* PROCESSORS:
* CPY$DS
* CPY$RS
* CPY$SD
* INIT$HW
* LD$CAR
* RD$LAB
* TEST$YZ
* UNL$CAR
* WT$LAB
*
* THESE PROCESSORS ARE ALL CODED IN A SPECIAL WAY THAT IS TERMED
* "PSEUDO-REENTRANT".
*
* WHEN A LOW LEVEL REQUEST PROCESSOR IS CALLED IT IS PASSED THE
* ADDRESS OF AN *LLRQ* ENTRY (A REQUEST) WHICH IS READY FOR
* FURTHER PROCESSING. ALL THE PARAMETERS THE PROCESSOR NEEDS FOR
* ADVANCING THE REQUEST ARE CONTAINED IN THE *LLRQ* ENTRY. IN
* PARTICULAR, THE PROCESS STATE FIELD (LLR$PS) TELLS THE PROCESSOR
* WHERE IT LEFT OFF THE LAST TIME IT WAS PROCESSING THIS REQUEST,
* AND THUS WHAT TO DO NEXT TO ADVANCE THE REQUEST.
*
* WHEN A LOW LEVEL REQUEST PROCESSOR REACHES A POINT WHERE IT
* CANNOT CONTINUE ADVANCING THE REQUEST WITHOUT A LONG DELAY, IT
* SETS UP SOME CONDITION THAT WILL EVENTUALLY GET THE REQUEST PUT
* BACK ON THE *LLRQ* READY CHAIN, AND THEN DROPS OUT BY
* 1) SETTING THE PROCESS STATE FIELD IN THE *LLRQ* ENTRY TO A
* VALUE THAT WILL ALLOW THE PROCESSOR TO RESTART THE REQUEST
* AT THE CORRECT POINT LATER, AND
* 2) RETURNING CONTROL TO THE *LLRQ* MONITOR.
*
* WHEN A LOW LEVEL REQUEST PROCESSOR COMPLETES THE PROCESSING OF
* A REQUEST, IT CAUSES THE ORIGINATOR OF THE REQUEST TO BE
* NOTIFIED OF THE COMPLETION. IF THE REQUEST ORIGINATED FROM A
* *UCP* THE NOTIFICATION IS DONE BY STORING THE RESPONSE CODE IN
* THE LONG TERM CONNECT TABLE ENTRY FOR THE *UCP* AND THEN
* CALLING *UCP$RES*. IF THE REQUEST ORIGINATED FROM A HIGH LEVEL
* REQUEST PROCESSOR, THE NOTIFICATION IS DONE BY STORING THE
* RESPONSE CODE IN THE *HLRQ* ENTRY FOR THE HIGH LEVEL REQUEST,
* AND PUTTING THE *HLRQ* ENTRY ON THE *HLRQ* READY CHAIN.
*
* WHEN THE PROCESSOR HAS NOTIFIED THE ORIGINATOR, IT THEN SETS
* PROCESS STATE FIELD IN THE *LLRQ* ENTRY TO "COMPLETE" AND
* RETURNS CONTROL TO THE *LLRQ* MONITOR. THE MONITOR THEN ZEROES
* OUT THE *LLRQ* ENTRY AND PUTS IT ON THE *LLRQ* FREE SPACE
* CHAIN.
#
END # L #
TERM
PROC CPY$DS((LLRADR));
# TITLE CPY$DS - COPY DISK TO VOLUME. #
BEGIN # CPY$DS #
#
** CPY$DS - COPY DISK TO VOLUME.
*
* *CPY$DS* COPIES THE DISK FILE (FROM ITS CURRENT POSITION) TO THE
* VOLUME, UNTIL END OF VOLUME OR END OF FILE IS ENCOUNTERED.
*
* PROC CPY$DS((LLRADR))
*
* ENTRY (LLRADR) - ADDRESS OF *LLRQ* ENTRY FOR THE COPY
* CONTAINING THE SMA-ID, YZ COORDINATES,
* ADDRESS OF THE DISK AND M860 FET-S. THE
* FET-S MUST BE INITIALIZED.
*
* EXIT THE PROCESS STATE FIELD IN THE *LLRQ* ENTRY HAS BEEN
* ADVANCED TO INDICATE WHERE PROCESSING OF THIS REQUEST
* LEFT OFF AND THUS WHAT TO DO NEXT TO ADVANCE THE
* REQUEST. WHEN THE COPY IS COMPLETE AN ERROR RESPONSE
* CODE IS RETURNED IN THE *HLRQ* ENTRY WHICH GENERATED
* THE COPY REQUEST.
* (HLR$RESP[0]) - ERROR RESPONSE CODE.
* (VALUES DEFINED IN *COMBCPR*).
* = RESPTYP4"OK4".
* = RESPTYP4"UN$WRT$ERR".
* = RESPTYP4"EX$WRT$ERR".
* = RESPTYP4"M86$HDW$PR".
* = RESPTYP4"RMS$FL$ERR".
*
* NOTES THIS MODULE IS A PSEUDO REENTRANT ROUTINE, CALLED ONLY
* BY *DESTAGR* THRU THE *HLRQ* PROCESSOR.
#
ITEM LLRADR U; # *LLRQ* ENTRY ADDRESS #
ITEM STRPCT U; # NUMBER OF STRIPES #
#
**** PROC CPY$DS - XREF LIST BEGIN.
#
XREF
BEGIN
PROC ADD$LNK; # ADD ENTRY TO CHAIN #
PROC GETBUF; # GET LARGE BUFFER #
PROC RLSBUF; # RELASE LARGE BUFFER #
PROC READCW; # READ WITH CONTROL WORDS #
PROC SETFET; # INITIALIZE LARGE BUFFER #
END
#
**** PROC CPY$DS - XREF LIST END.
#
DEF LISTCON #0#; # DO NOT LIST COMDECKS #
*CALL COMBFAS
*CALL COMBCDD
*CALL COMBCHN
*CALL COMBCPR
*CALL COMBFET
*CALL COMBLRQ
*CALL COMBRCD
*CALL COMXCCB
*CALL COMXHLR
*CALL COMXMSC
ITEM FLAG B; # FLAG #
SWITCH CDSENTR:PROCST # COPY DISK TO VOLUME ENTRIES #
CDSINIT:INITIAL, # INITIAL ENTRY #
CDS1:CONT1, # WAIT LARGE BUFFER #
CDS2:CONT2, # DRIVER VOLUME RETURN #
CDS3:CONT3; # DRIVER RETURN *REWIND/UNLOAD* #
CONTROL EJECT;
P<LLRQ> = LLRADR;
P<HLRQ> = LLR$UCPRA[0];
GOTO CDSENTR[LLR$PRCST[0]];
#
* "INITIAL" PROCESS STATE.
#
CDSINIT: # SET UP COPY CONTROL BLOCK #
GETBUF(LLRADR,HLRQIND,FLAG);
IF NOT FLAG
THEN # NO BUFFER AVAILABLE #
BEGIN
LLR$PRCST[0] = PROCST"CONT1"; # WAIT BUFFER ASSIGNMENT #
ADD$LNK(LLRADR,LCHN"LL$LGBUF",0);
RETURN;
END
#
* *CONT1* PROCESS STATE.
#
CDS1:
SETFET(LLRADR); # INITIALIZE,LARGE BUFFER #
P<HLRQ> = LLR$UCPRA[0];
P<LLRQ> = LLRADR;
P<CCB> = LLR$CCB[0];
P<FETSET> = LLR$DSKFET[0];
P<FETFHB> = LLR$MSFET[0];
CCBOPCODE[0] = CPYC"DISKAU";
FET$RR[0] = HLR$PRU[0];
#
* SET STRIPE INFORMATION IN LARGE BUFFER.
#
FHB$TIME[0] = PDATEV;
FHB$SMIF[0] = LLR$SMIF[0];
FHB$CCSN[0] = HLR$CSNTCU[0];
FHB$SHDWD[0] = HLR$FETMT[0];
FHB$PCSN[0] = HLR$CSNTPS[0];
FHB$PFC[0] = HLR$PFC[0];
FHB$CODE[0] = FCCWW; # CONTROL WORD WRITE #
READCW(FETSET[0],0,NRCL);
LLR$RC[0] = REQCODE"SWRT$VOL"; # ISSUE WRITE VOLUME REQUEST #
LLR$RS[0] = PROCST"INITIAL";
ADD$LNK(CCBLLRQ[0],LCHN"DRQUEUE",0);
LLR$PRCST[0] = PROCST"CONT2";
RETURN;
#
* *CONT2* PROCESS STATE.
* CPU DRIVER RETURN FROM VOLUME MOUNT.
#
CDS2: # PROCESS DRIVER RESPONSE #
IF LLR$DR[0] NQ RESPTYP4"OK4"
THEN
BEGIN # PROCESS DRIVER ERROR RETURN CODE #
IF LLR$DR[0] EQ RESPTYP4"UN$WRT$ERR"
THEN
BEGIN # UNRECOVERED WRITE ERROR #
HLR$AUUD[0] = (LLR$ST$LW[0] - INFTST) / INSPAU + 1;
HLR$HRDE[0] = HLR$HRDE[0] + 1; # SET WRITE ERROR #
END # WRITE ERROR #
GOTO CONT;
END
ADD$LNK(LLR$CCB[0],LCHN"KC$GOING",0);
LLR$PRCST[0] = PROCST"CONT3";
RETURN;
#
* *CONT3* PROCESS STATE.
* KEEP COPY GOING RETURN AFTER REWIND/UNLOAD COMMAND.
#
CDS3:
P<CCB> = LLR$CCB[0];
HLR$AUUD[0] = (LLR$LT$ST[0] - INFTST) / INSPAU + 1;
STRPCT = LLR$LOG$ST[0] / INSPAU;
IF CCBDERR[0]
THEN
BEGIN # DISK ERROR #
LLR$DR[0] = RESPTYP4"RMS$FL$ERR";
GOTO CONT;
END
IF (CCBHDWPM[0])
OR (LLR$DR[0] NQ RESPTYP4"OK4")
OR (HLR$AUUD[0] LS HLR$VOLAU[0])
OR (HLR$AUUD[0] GR (HLR$VOLAU[0] + HLR$VOLLN[0]))
OR (STRPCT GR HLR$VOLLN[0])
THEN # HARDWARE ERROR #
BEGIN
LLR$DR[0] = RESPTYP4"M86$HDW$PR";
LLR$DRFUL[0] = TRUE; # FORCE UNLOAD OF CARTRIDGE #
GOTO CONT;
END
IF CCBTAPPAR
THEN
BEGIN # WRITE PARITY ERROR #
LLR$DR[0] = RESPTYP4"UN$WRT$ERR";
HLR$HRDE[0] = HLR$HRDE[0] + 1; # SET WRITE ERROR #
GOTO CONT;
END
HLR$PRU[0] = LLR$LOG$ST[0] * INPRUS + HLR$PRU[0];
CONT:
HLR$RESP[0] = LLR$DR[0]; # RETURN RESPONSE #
ADD$LNK(LLR$UCPRA[0],LCHN"HL$READY",0);
LLR$MSFET[0] = 0;
LLR$DSKFET[0] = 0;
RLSBUF(LLRADR); # RELEASE BUFFER #
RETURN;
END # CPY$DS #
TERM
PROC CPY$RS((LLRADR));
# TITLE CPY$RS - COPY RAW VOLUME. #
BEGIN # CPY$RS #
#
** CPY$RS - COPY RAW VOLUME.
*
* *CPY$RS* APPENDS A RAW VOLUME TO A FILE, STARTING WITH THE
* CURRENT POSITION ON THE VOLUME TO THE END OF VOLUME.
*
* PROC CPY$RS((LLRADR))
*
* ENTRY (LLRADR) - ADDRESS OF *LLRQ* ENTRY FOR THE COPY
* CONTAINING THE SMA-ID, THE VOLUME
* NUMBER, AND THE YZ COORDINATES.
*
* EXIT THE PROCESS STATE FIELD IN THE *LLRQ* ENTRY HAS BEEN
* ADVANCED TO INDICATE WHERE PROCESSING OF THIS REQUEST
* LEFT OFF AND THUS WHAT TO DO NEXT TO ADVANCE THE
* REQUEST. WHEN THE COPY IS COMPLETE AN ERROR RESPONSE
* CODE IS RETURNED VIA *LTC$RQR[LTCENTRY]*.
* (LTC$RQR[LTCENTRY]) - ERROR RESPONSE CODE.
* (VALUES DEFINED IN *COMBCPR*).
* = RESPTYP4"OK4".
* = RESPTYP4"M86$HDW$PR".
* = RESPTYP4"RMS$FL$ERR".
* = RESPTYP4"DISK$FULL".
*
* MESSAGES * EXEC ABNORMAL, CPY$RS.*.
*
* NOTES THIS MODULE IS A PSEUDO REENTRANT ROUTINE. A COPY RAW
* VOLUME REQUEST ONLY COMES FROM *ASDEBUG* AND IS USED
* TO SALVAGE INFORMATION FROM A VOLUME WITH READ ERRORS.
#
ITEM LLRADR U; # *LLRQ* ENTRY ADDRESS #
#
**** PROC CPY$RS - XREF LIST BEGIN.
#
XREF
BEGIN
PROC ABORT; # ABORT #
PROC ADD$LNK; # ADD ENTRY TO CHAIN #
PROC DELAY; # TIMED DELAY #
PROC GETBUF; # GET LARGE BUFFERS #
PROC MESSAGE; # ISSUE MESSAGE #
PROC PFD; # PERMANENT FILE REQUEST DELAYS #
PROC RETERN; # RETURN FILE #
PROC RLSBUF; # RELEASE LARGE BUFFERS #
PROC SETFET; # INITIALIZE LARGE BUFFER #
PROC SETPFP; # SET PERMANENT FILE PARAMETERS #
PROC SFCALL; # INTERFACE TO *SFCALL* MACRO #
PROC SKIPEI; # SKIP TO *EOI* #
PROC UCP$RESP; # UCP RESPONSE #
PROC WRITE; # WRITE DATA FROM *CIO* BUFFER #
PROC WRITER; # WRITE *EOR* #
END
#
**** PROC CPY$RS - XREF LIST END.
#
DEF LISTCON #0#; # DO NOT LIST COMDECKS #
*CALL COMBFAS
*CALL COMBCHN
*CALL COMBCPR
*CALL COMBFET
*CALL COMBLBL
*CALL COMBLRQ
*CALL COMBPFP
*CALL COMBPFS
*CALL COMBRCD
*CALL COMBUCR
*CALL COMXBST
*CALL COMXIPR
*CALL COMXLTC
*CALL COMXMSC
*CALL COMSPFM
ITEM FLAG B; # FLAG #
SWITCH CRSENTR:PROCST # COPY RAW VOLUME ENTRIES #
CRSINIT:INITIAL, # INITIAL ENTRY #
CRS1:CONT1, # CONTINUATION 1 #
CRS2:CONT2, # CONTINUATION 2 #
CRS3:CONT3, # CONTINUATION 3 #
CRS4:CONT4; # CONTINUATION 4 #
CONTROL EJECT;
P<LLRQ> = LLRADR;
LLR$DR[0] = RESPTYP4"OK4";
GOTO CRSENTR[LLR$PRCST[0]]; # PROCESS REQUEST #
#
* "INITIAL" PROCESS STATE.
#
CRSINIT:
GETBUF(LLRADR,HLRQIND,FLAG);
IF NOT FLAG
THEN # NO BUFFER AVAILABLE #
BEGIN
LLR$PRCST[0] = PROCST"CONT1"; #WAIT BUFFER ASSIGNMENT#
ADD$LNK(LLRADR,LCHN"LL$LGBUF",0);
RETURN;
END
CRS1:
SETFET(LLRADR);
#
* "CONT1" PROCESS STATE.
*
* REREAD THE UCP REQUEST BLOCK TO GET THE FAMILY, USER INDEX,
* AND FILE NAME.
#
CRS2:
IF LLR$UCPABT[0]
THEN
BEGIN
GOTO CRSCOMP;
END
P<FETSET> = LLR$DSKFET[0];
LTCENTRY = LLR$LTCT[0];
LTC$SFUCPA[LTCENTRY] = LLR$UCPRA[0];
LTC$SFSCPA[LTCENTRY] = FET$IN[0];
LTC$SFFP[LTCENTRY] = TYP4$WC + 1;
LTC$SFFC[LTCENTRY] = SFREAD;
SFCALL(LOC(LTC$WORD0[LTCENTRY]),RCL);
IF LTC$SFRC[LTCENTRY] NQ 0
THEN
BEGIN # PROCESS ERROR RESPONSE #
IF LTC$SFRC[LTCENTRY] EQ SFRCSWPOUT
THEN
BEGIN # SWAP IN UCP #
LTC$SFUCPA[LTCENTRY] = 0;
LTC$SFSCPA[LTCENTRY] = 0;
LTC$SFFC[LTCENTRY] = SFSWPI;
SFCALL(LOC(LTC$WORD0[LTCENTRY]),NRCL);
#
* "CONT3" PROCESS STATE.
#
CRS3:
LTCENTRY = LLR$LTCT[0];
IF LTC$SFFCC[LTCENTRY]
THEN # RETRY *SFREAD* #
BEGIN
LLR$PRCST[0] = PROCST"CONT2";
END
ELSE # DELAY FOR REQUEST COMPLETION #
BEGIN
LLR$PRCST[0] = PROCST"CONT3";
DELAY(UCP$INTV,LLRADR,LLRQIND);
END
RETURN;
END # SWAP IN UCP #
ELSE # FATAL ERROR #
BEGIN
GOTO CRSFERR;
END
END # PROCESS ERROR RESPONSE #
P<CPR> = FET$IN[0];
FET$LFN[0] = CPR$PFN[0];
PFP$WRD0[0] = 0; # SET FAMILY AND USER INDEX #
PFP$FAM[0] = CPR$FAM[0];
PFP$UI[0] = CPR$UI[0];
PFP$FG1[0] = TRUE;
PFP$FG4[0] = TRUE;
SETPFP(PFP);
IF PFP$STAT[0] NQ 0
THEN
BEGIN
GOTO CRSFERR;
END
PFD("ATTACH",FET$LFN[0],0,"M","W","RC",PFSTAT,"NA",0,"UP",0,0);
PFP$FAM[0] = DEF$FAM; # RETURN TO DEFAULT FAMILY #
PFP$UI[0] = DEF$UI;
SETPFP(PFP);
IF PFP$STAT[0] NQ 0
THEN
BEGIN
GOTO CRSFERR;
END
IF PFSTAT NQ 0
THEN # IF *ATTACH* ERROR #
BEGIN
LLR$DR[0] = RESPTYP4"ATTACH$ERR";
GOTO CRSCOMP;
END
SKIPEI(FETSET[0],RCL);
#
* SET READ ONE STRIPE AT A TIME.
#
LLR$SAV$HI[0] = LLR$ST$HI[0]; # SAVE LAST STRIPE TO READ #
LLR$ST$HI[0] = LLR$ST$LW[0] + 1;
#
* ISSUE A READ RAW STRIPE REQUEST TO THE DRIVER. WHEN IT IS
* COMPLETED, WRITE THE RAW STRIPE TO THE DISK FILE. THEN LOOP
* BACK TO READ THE NEXT RAW STRIPE. CONTINUE THIS LOOP UNTIL
* THE LAST STRIPE IS READ.
#
LLR$RC[0] = REQCODE"SRDRAW$STP";
LLR$PRCST[0] = PROCST"CONT4";
RDRAWSTP: # ISSUE READ RAW STRIPE REQUEST #
IF LLR$UCPABT[0]
THEN
BEGIN
GOTO CRSCOMP;
END
LLR$DR[0] = 0;
LLR$RS[0] = PROCST"INITIAL";
ADD$LNK(LLRADR,LCHN"DRQUEUE",0);
RETURN;
#
* "CONT4" PROCESS STATE.
#
CRS4:
IF LLR$DR[0] NQ RESPTYP4"OK4" ##
THEN
BEGIN # PROCESS ERROR #
GOTO CRSCOMP;
END
P<FETFHB> = LLR$MSFET[0];
P<FETSET> = LLR$DSKFET[0];
FET$IN[0] = FHB$IN[0];
WRITER(FETSET[0],RCL);
IF FET$AT[0] NQ 0
THEN
BEGIN # WRITE ERROR #
IF FET$AT[0] EQ ATCODE AND FET$DEC[0] EQ DISKFULL
THEN # DISK FULL #
BEGIN
LLR$DR[0] = RESPTYP4"DISK$FULL";
END
ELSE # FILE WRITE ERROR #
BEGIN
LLR$DR[0] = RESPTYP4"RMS$FL$ERR";
END
GOTO CRSCOMP;
END # WRITE ERROR #
LLR$ST$LW[0] = LLR$ST$LW[0] + 1;
LLR$ST$HI[0] = LLR$ST$LW[0] + 1;
IF LLR$ST$LW[0] LQ LLR$SAV$HI[0]
THEN # IF NOT END OF VOLUME #
BEGIN
FHB$IN[0] = FET$FRST[0];
FHB$OUT[0] = FET$FRST[0];
FET$IN[0] = FET$FRST[0];
FET$OUT[0] = FET$FRST[0];
GOTO RDRAWSTP; # CONTINUE READING STRIPES #
END
LLR$DR[0] = RESPTYP4"OK4";
CRSCOMP:
P<FETSET> = LLR$DSKFET[0];
IF FET$LFN[0] NQ 0
THEN
BEGIN
RETERN(FETSET[0],RCL);
END
LLR$MSFET[0] = 0;
LLR$DSKFET[0] =0;
RLSBUF(LLRADR); # RELEASE BUFFERS #
P<LLRQ> = LLRADR;
IF NOT LLR$UCPABT[0]
THEN # ISSUE RESPONSE TO THE UCP #
BEGIN
LTCENTRY = LLR$LTCT[0];
LTC$RQR[LTCENTRY] = LLR$DR[0];
UCP$RESP;
END
ELSE
BEGIN # FORCE UNLOAD OF CARTRIDGE #
LLR$PRCNME[0] = REQTYP4"UNLD$CART";
LLR$PRCST[0] = PROCST"INITIAL";
LLR$RQI[0] = REQNAME"RQIAUCP";
ADD$LNK(LLRADR,LCHN"LL$READY",0);
END # UNLOAD CARTRIDGE #
RETURN;
CRSFERR: # FATAL ERROR #
FE$RTN[0] = "CPY$RS.";
MESSAGE(FEMSG,UDFL1);
ABORT;
END # CPY$RS #
TERM
PROC CPY$SD((LLRADR));
# TITLE CPY$SD - COPY VOLUME TO DISK. #
BEGIN # CPY$SD #
#
** CPY$SD - COPY VOLUME TO DISK.
*
* *CPY$SD* COPIES A VOLUME TO A DISK FILE.
*
* PROC CPY$SD((LLRADR))
*
* ENTRY (LLRADR) - ADDRESS OF *LLRQ* ENTRY FOR THE COPY
* CONTAINING THE SMA-ID, YZ COORDINATES,
* ADDRESS OF THE DISK AND M860 FET-S. THE
* FET-S MUST BE INITIALIZED.
*
* EXIT THE PROCESS STATE FIELD IN THE *LLRQ* ENTRY HAS BEEN
* ADVANCED TO INDICATE WHERE PROCESSING OF THIS REQUEST
* LEFT OFF AND THUS WHAT TO DO NEXT TO ADVANCE THE
* REQUEST. WHEN THE COPY IS COMPLETE AN ERROR RESPONSE
* CODE IS RETURNED IN THE *HLRQ* ENTRY WHICH GENERATED
* THE COPY REQUEST.
* (HLR$RESP[0]) - ERROR RESPONSE CODE.
* (VALUES DEFINED IN *COMBCPR*).
* = RESPTYP4"OK4".
* = RESPTYP4"UNR$RD$ERR".
* = RESPTYP4"M86SYS$ERR".
* = RESPTYP4"M86$HDW$PR".
* = RESPTYP4"RMS$FL$ERR".
* = RESPTYP4"DISK$FULL".
*
* NOTES THIS MODULE IS A PSEUDO REENTRANT ROUTINE, CALLED ONLY
* BY *STAGER* THRU THE *HLRQ* PROCESSOR.
#
ITEM LLRADR U; # *LLRQ* ENTRY ADDRESS #
#
**** PROC CPY$SD - XREF LIST BEGIN.
#
XREF
BEGIN
PROC ADD$LNK; # ADD ENTRY TO CHAIN #
PROC GETBUF; # GET LARGE BUFFER #
PROC RLSBUF; # RELEASE LARGE BUFFER #
PROC SETFET; # INITIALIZE LARGE BUFFER #
END
#
**** PROC CPY$SD - XREF LIST END.
#
DEF LISTCON #0#; # DO NOT LIST COMDECKS #
*CALL COMBFAS
*CALL COMBCDD
*CALL COMBCHN
*CALL COMBCPR
*CALL COMBFET
*CALL COMBLRQ
*CALL COMBRCD
*CALL COMXCCB
*CALL COMXHLR
*CALL COMXMSC
ITEM FLAG B; # FLAG #
SWITCH CSDENTR:PROCST # COPY VOLUME TO DISK ENTRIES #
CSDINIT:INITIAL, # INITIAL ENTRY #
CSD1:CONT1, # WAIT LARGE BUFFER #
CSD2:CONT2, # DRIVER VOLUME RETURN #
CSD3:CONT3; # DRIVER RETURN *REWIND/UNLOAD* #
CONTROL EJECT;
P<LLRQ> = LLRADR;
P<HLRQ> = LLR$UCPRA[0];
GOTO CSDENTR[LLR$PRCST[0]];
#
* "INITIAL" PROCESS STATE.
#
CSDINIT: # SET UP COPY CONTROL BLOCK #
GETBUF(LLRADR,HLRQIND,FLAG);
IF NOT FLAG
THEN # NO BUFFER AVAILABLE #
BEGIN
LLR$PRCST[0] = PROCST"CONT1"; # WAIT BUFFER ASSIGNMENT #
ADD$LNK(LLRADR,LCHN"LL$LGBUF",0);
RETURN;
END
#
* *CONT1* PROCESS STATE.
#
CSD1:
SETFET(LLRADR); # INITIALIZE LARGE BUFFER #
P<LLRQ> = LLRADR;
P<CCB> = LLR$CCB[0];
P<FETSET> = LLR$DSKFET[0];
P<FETFHB> = LLR$MSFET[0];
CCBOPCODE[0] = CPYC"AUDISK";
FHB$CODE[0] = FCCWR;
LLR$RC[0] = REQCODE"SREAD$VOL"; # ISSUE READ VOLUME REQUEST #
LLR$RS[0] = PROCST"INITIAL";
ADD$LNK(CCBLLRQ[0],LCHN"DRQUEUE",0);
LLR$PRCST[0] = PROCST"CONT2";
RETURN;
#
* *CONT2* PROCESS STATE.
* CPU DRIVER MOUNT VOLUME RETURN.
#
CSD2: # PROCESS DRIVER RETURN #
IF LLR$DR[0] NQ RESPTYP4"OK4"
THEN
BEGIN # PROCESS DRIVER ERROR RETURN CODE #
GOTO CONT;
END
ADD$LNK(LLR$CCB[0],LCHN"KC$GOING",0);
LLR$PRCST[0] = PROCST"CONT3";
RETURN;
#
* *CONT3* PROCESS STATE.
* CPU DRIVER RETURN FROM REWIND/UNLOAD COMMAND.
#
CSD3:
P<CCB> = LLR$CCB[0];
P<FETSET> = LLR$DSKFET[0];
P<FETFHB> = LLR$MSFET[0];
IF CCBDERR[0]
THEN # DISK ERROR #
BEGIN
LLR$DR[0] = RESPTYP4"RMS$FL$ERR";
GOTO CONT;
END
IF CCBDFULL[0]
THEN # DISK FULL ERROR #
BEGIN
LLR$DR[0] = RESPTYP4"DISK$FULL";
GOTO CONT;
END
IF CCBHDWPM[0] OR LLR$DR[0] NQ RESPTYP4"OK4"
THEN # IF HARDWARE ERROR #
BEGIN
LLR$DR[0] = RESPTYP4"M86$HDW$PR";
LLR$DRFUL[0] = TRUE; # FORCE UNLOAD OF CARTRIDGE #
GOTO CONT;
END
IF CCBTAPPAR
THEN
BEGIN # READ PARITY ERROR #
LLR$DR[0] = RESPTYP4"UN$RD$ERR";
IF NOT HLR$RETRY[0] # FIRST PARITY ERROR #
THEN
BEGIN # FORCE UNLOAD AND DELINK OF CARTRIDGE #
LLR$DRFUL[0] = TRUE;
END
GOTO CONT;
END
IF CCPPUDCK
THEN
BEGIN # PPU FOUND DATA TRANSFER ERROR #
LLR$DR[0]= RESPTYP4"PPU$D$PROB";
IF NOT HLR$RETRY[0] # FIRST DATA ERROR #
THEN
BEGIN # FORCE UNLOAD AND DELINK OF CARTRIDGE #
LLR$DRFUL[0] = TRUE;
END
GOTO CONT;
END
IF FHB$PVLN[0] NQ HLR$VOLLNP[0] # PREVIOUS VOLUME LENGTH #
OR FHB$PVSN[0] NQ HLR$VOLAUP[0] # PREVIOUS VOLUME NUMBER #
OR FHB$CVSN[0] NQ HLR$VOLAU[0] # VOLUME NUMBER #
OR FHB$PCSN[0] NQ HLR$CSNTPS # CSN OR PREVIOUS VOLUME #
OR FHB$PFC$UI[0] NQ HLR$TDAMUI[0] # USER INDEX #
OR FHB$PFC$DT[0] NQ HLR$TDAMCD[0] # CREATION DATE / TIME #
THEN
BEGIN # SET VOLUME HEADER ERROR #
LLR$DR[0] = RESPTYP4"VOL$HD$ERR";
GOTO CONT;
END
HLR$PRU[0] = FET$CRI[0] + HLR$PRU[0];
IF CCBTPMARK
THEN
BEGIN
HLR$EOI[0] = TRUE;
END
CONT:
HLR$RESP[0] = LLR$DR[0]; # RETURN RESPONSE #
ADD$LNK(LLR$UCPRA[0],LCHN"HL$READY",0);
LLR$MSFET[0] = 0;
LLR$DSKFET[0] = 0;
RLSBUF(LLRADR); # RELEASE BUFFER #
RETURN;
END # CPY$SD #
TERM
PROC INIT$HW((LLRADR));
# TITLE INIT$HW - INITIALIZE M860 HARDWARE. #
BEGIN # INIT$HW #
#
** INIT$HW - INITIALIZE M860 HARDWARE.
*
* *INIT$HW* PASSES M860 HARDWARE INITIALIZATION
* REQUESTS TO THE MSAS DRIVER. IT CLEARS THE
* *INITIALIZE* FLAG TO INDICATE THAT FULL
* INITIALIZATION HAS COMPLETED WHEN IT FINDS THE
* *LLRQ* READY CHAIN AND *DRQUEUE* BOTH INACTIVE, WHILE
* PROCESSING A REQUEST JUST RETURNED FROM THE DRIVER.
*
* PROC INIT$HW((LLRADR))
*
* ENTRY (LLRADR) - *LLRQ* ENTRY ADDRESS CONTAINING
* CONTROLLER ORDINAL FROM WHICH HARDWARE
* INITIALIZATION IS TO BE BASED.
*
* EXIT THE *LLRQ* ENTRY PROCESS STATE FIELD HAS BEEN
* ADVANCED TO INDICATE WHERE SUBSEQUENT PROCESSING OF
* THIS REQUEST IS TO CONTINUE.
*
* NOTES THIS MODULE IS A PSEUDO-REENTRANT ROUTINE.
#
ITEM BYNR U; # OFF SET BIT ADDRESS #
ITEM LLRADR U; # *LLRQ* ENTRY ADDRESS #
ITEM STAT U; # STATUS BIT #
#
**** PROC INIT$HW - XREF LIST BEGIN.
#
XREF
BEGIN
PROC ABORT; # ABORT #
PROC ADD$LNK; # ADD ENTRY TO END OF CHAIN #
PROC MESSAGE; # ISSUE MESSAGE #
PROC UCP$RES; # RETURN RESPONSE TO UCP #
END
#
**** PROC INIT$HW - XREF LIST END.
#
DEF LISTCON #0#; # DO NOT LIST COMDECKS #
*CALL,COMBFAS
*CALL,COMBCHN
*CALL,COMBCPR
*CALL,COMBLRQ
*CALL,COMBRCD
*CALL,COMBUCR
*CALL COMBUDT
*CALL,COMXCTF
*CALL,COMXLTC
*CALL,COMXMSC
BASED
ARRAY UDTBIT [0:0] P(1); # CHECK *UDT* AREA #
BEGIN
ITEM UDT$BIT U(00,00,60);
END
#
* GENERAL MESSAGE BUFFER.
#
ARRAY GMSB [0:0] S(5);
BEGIN # INIT MSGS #
ITEM MSG$LINE C(00,00,40); # MESSAGE LINE #
ITEM MSG$ZERO U(04,00,12) = [0]; # ZERO-BYTE TERMINATOR #
END # INIT MSGS #
SWITCH INITIALS:PROCST # INITIALIZATION ENTRIES #
INIT1:INITIAL, # INITIAL ENTRY #
INIT2:CONT1; # FINAL ENTRY #
CONTROL EJECT;
P<LLRQ> = LLRADR;
GOTO INITIALS[LLR$PRCST[0]];
#
* "INITIAL" PROCESS STATE.
#
INIT1:
LLR$RC[0] = RESTART$CU; # ASSUME DRIVER RESTART REQUEST #
IF NOT INITIALIZE ##
THEN # NO CU RESTART REQUIRED #
BEGIN # RESET #
LLR$RC[0] = INIT$SM;
END # RESET #
LLR$PRCST[0] = PROCST"CONT1";
ADD$LNK(LLRADR,LCHN"DRQUEUE",0);
RETURN;
#
* "COMPLETE" PROCESS STATE.
#
INIT2:
IF CHN$BOC[LCHN"LL$READY"] EQ 0 ##
AND CHN$BOC[LCHN"DRQUEUE"] EQ 0 ##
AND INITIALIZE
THEN # FULL INITIALIZATION COMPLETED #
BEGIN # INIT DONE #
IF UDT$HWOFF[0] EQ 0
THEN # INITIALIZATION WAS SUCCESSFUL #
BEGIN # OK #
INITIALIZE = FALSE;
MSG$LINE[0] = " INITIALIZATION COMPLETE.";
MESSAGE(GMSB,SYSUDF1);
END # OK #
ELSE # NO 7990 HARDWARE ACCESS #
BEGIN # EXIT #
MSG$LINE[0] = " INITIALIZATION HALTED.";
MESSAGE(GMSB,SYSUDF1);
MSG$LINE[0] = "$INITIALIZATION HALTED.";
MESSAGE(GMSB,LINE2);
END # EXIT #
END # INIT DONE #
IF LLR$RQI[0] EQ REQNAME"RQIALTER" # SSALTER WORKING #
AND NOT LLR$UCPABT[0]
THEN # REQUEST FROM UCP #
BEGIN # RETURN #
BYNR = LLR$BYNR[0];
P<UDTBIT> = LLR$UDTQ[0];
STAT = B<BYNR,1> UDT$BIT[0];
LTCENTRY = LLR$LTCT[0];
LTC$RQR[LTCENTRY] = RESPTYP5"OK5";
IF STAT NQ LLR$PMMR[0] # STATUS UNCHANGED #
OR LLR$DR[0] EQ RESPTYP4"M86$HDW$PR" # HARDWARE PROBLEM #
THEN
BEGIN # STATUS REMAINED #
LTC$RQR[LTCENTRY] = RESPTYP5"SSA$ERROR";
END # STATUS REMAINED #
LTC$LLRQA[LTCENTRY] = 0;
UCP$RES; # RETURN RESPONSE TO UCP #
END # RETURN #
LLR$PRCST[0] = PROCST"COMPLETE";
RETURN;
END # INIT$HW #
TERM
PROC KCG;
# TITLE KCG - KEEP COPY GOING. #
BEGIN # KCG #
#
** KCG - KEEP COPY GOING.
*
* *KCG* MONITORS THE PROGRESS OF COPIES BETWEEN DISK AND A
* CARTRIDGE VOLUME, MOVES *IN* AND *OUT* POINTERS BETWEEN THE *CIO*
* AND *1SS* FET AND RESTARTS *CIO* OR *1SS* AS NECESSARY TO
* KEEP THE COPY PROCESS GOING.
*
* PROC KCG
*
* EXIT ALL COPY REQUESTS WHICH HAVE BEEN COMPLETED ARE
* DELETED FROM THE KEEP COPY GOING CHAIN AND ADDED BACK
* ON THE *LLRQ* READY CHAIN.
*
* SENSE SWITCH 2 IS USED TO SET READ AND WRITE 1MS
* CALLS IN THE DAYFILE. THE NUMBER OF TIMES 1MS IS CALLED
* IN A VOLUME CAN BE TRACED BY SETTING SENSE SWITCHS 1 AND 2.
*
* THE STRIPES ARE READ OR WRITTEN IN 13 PRU BLOCKS.
* THE BUFFER HAS BEEN SET FOR 4 PLUS BLOCKS.
* THE BUFFER SIZE IS CHANGED BY *DATABL* IN COMXBST.
*
*
* THE CODE IS SET TO CALL 1MS WHEN A BUFFER IS 1/2 FULL.
*
* THE BUFFER SIZE CAN BE VARIED, BUT 1/3 OF A BUFFER MUST BE
* OVER 13 PRU-S OR A LOCK WILL HAPPEN BETWEEN 1SS AND 1MS.
* DATABL (BUFFER SIZE) HAS BEEN INCREASED FROM 3700 TO
* 6501.
*
* TO CHANGE FROM 1/2 TO 2/3 BUFFER FULL CALLS TO *1MS* -
* ((DATABL-1) / 2) TO ((DATABL-1) / 3) * 2
*
#
DEF BUFSTART #((DATABL-1) / 2)#; # SETS HALF BUFFER START #
DEF EOI$IWRD #O"2000 0000 0000 0000 0000"#; # *EOI* WORD #
#
**** PROC KCG - XREF LIST BEGIN.
#
XREF
BEGIN
PROC ADD$LNK; # ADD ENTRY TO CHAIN #
PROC CALLPPU; # CALL PPU #
PROC DEL$LNK; # DELETE ENTRY FROM CHAIN #
PROC READCW; # READ WITH CONTROL WORDS #
PROC WRITECW; # WRITE WITH CONTROL WORDS #
PROC K8G; # KEEP M860 GOING #
PROC MESSAGE; # ISSUE MESSAGE #
END
#
**** PROC KCG - XREF LIST END.
#
DEF LISTCON #0#; # DO NOT LIST COMDECKS #
*CALL COMBFAS
*CALL COMBCDD
*CALL COMBCHN
*CALL COMBFET
*CALL COMBLRQ
*CALL COMXBST
*CALL COMXCCB
*CALL COMXCTF
*CALL COMXJCA
*CALL COMXMSC
ITEM ENTADR U; # *CCB* ENTRY ADDRESS #
ITEM NEXTADDR U; # NEXT ENTRY ADDRESS #
ITEM TEMP U; # TEMPORARY STORAGE #
ITEM RD$READY B; # READ BUFFER READY #
ITEM WRT$READY B; # WRITE BUFFER READY #
ARRAY WRITEMG [0:0] S(2);
BEGIN
ITEM WRITEMSG C(00,00,12) = [" 1MS WRITE."];
ITEM TERMA U(01,48,12) = [0]; # TERMINATOR #
END
ARRAY READMG [0:0] S(2) ;
BEGIN
ITEM READMSG C(00,00,12) = [" 1MS READ."];
ITEM TERMB U(01,48,12) = [0]; # TERMINATOR #
END
CONTROL EJECT;
ENTADR = CHN$BOC[LCHN"KC$GOING"];
REPEAT WHILE ENTADR NQ 0
DO
BEGIN # MONITOR ENTRIES ON KEEP COPY GOING CHAIN #
P<CCB> = ENTADR;
P<LLRQ> = CCBLLRQ[0];
NEXTADDR = CCBLINK[0];
P<FETSET> = CCBDKFET[0];
P<FETFHB> = CCBM86FET[0];
IF CCBOPCODE[0] EQ CPYC"DISKAU"
THEN
BEGIN # COPY DISK TO M860 #
FHB$IN[0] = FET$IN[0];
FET$OUT[0] = FHB$OUT[0];
END
ELSE
BEGIN # COPY M860 TO DISK #
FET$IN[0] = FHB$IN[0];
FHB$OUT[0] = FET$OUT[0];
END
IF FET$LOCK[0] ##
AND NOT (CCBDERR[0] OR CCBDFULL[0])
THEN # IF MEDIA NOT EMPTY, NO DISK
ERRORS AND *CIO* NOT RUNNING #
BEGIN
IF FET$AT[0] NQ 0
THEN
BEGIN # SET DISK ERROR FLAG #
IF FET$AT[0] EQ 1
THEN
BEGIN # DISK FULL #
CCBDFULL[0] = TRUE;
END
ELSE
BEGIN # DISK ERROR #
CCBDERR[0] = TRUE;
END
END
ELSE
BEGIN # START COPY #
IF CCBOPCODE[0] EQ CPYC"DISKAU"
THEN
BEGIN # DISK INPUT #
IF FET$EOI[0]
THEN
BEGIN # WRITE *EOI* WORD #
RA$WORD[FET$IN[0]] = EOI$IWRD;
IF FET$IN[0] EQ FET$LIM[0] - 1
THEN
BEGIN
FET$IN[0] = FET$FRST[0];
END
ELSE
BEGIN
FET$IN[0] = FET$IN[0] + 1;
END
CCBDEOI[0] = TRUE;
END # END OF *EOI* WRITE #
RD$READY = ((FET$OUT[0] GR FET$IN[0]) ##
AND ((FET$OUT[0] - FET$IN[0]) GR BUFSTART)) ##
OR ((FET$OUT[0] LQ FET$IN[0]) ##
AND (((FET$OUT[0]-FET$FRST[0]) + (FET$LIM[0]-FET$IN[0]))
GR BUFSTART));
IF RD$READY ##
AND (CCBRWCT[0] EQ 0) ##
AND (NOT CCBDEOI[0])
THEN
BEGIN
READCW(FETSET[0],0,NRCL);
IF RA$SW2
THEN
BEGIN
MESSAGE(READMSG,UDFL1);
END
END
END # END OF DISK INPUT #
ELSE
BEGIN # WRITE DISK #
WRT$READY = ((FET$IN[0] GR FET$OUT[0]) ##
AND ((FET$IN[0] - FET$OUT[0]) GR BUFSTART))
OR ((FET$IN[0] LQ FET$OUT[0]) ##
AND ((FET$LIM[0] - FET$OUT[0]) ##
+ (FET$IN[0] - FET$FRST[0]) GR BUFSTART));
IF (WRT$READY OR CCBRWDULD[0] OR (CCBRWCT[0] NQ 0)) ##
AND (NOT FET$IN[0] EQ FET$OUT[0])
THEN
BEGIN
WRITECW(FETSET[0],NRCL);
IF RA$SW2
THEN
BEGIN
MESSAGE(WRITEMSG,UDFL1);
END
END
END # END OF WRITE DISK #
END # END OF COPY #
IF CCBDERR[0] OR CCBDFULL[0]
THEN # STOP *1SS* #
BEGIN
FHB$ST$SS[0] = TRUE;
END
END
IF FHB$LOCK[0] AND NOT CCBRWDULD[0]
THEN # IF *1SS* RUNNING #
BEGIN
K8G(ENTADR); # M860 SIDE OF COPY #
P<CCB> = ENTADR;
P<FETFHB> = CCBM86FET[0];
END
#
* IF THE INPUT COULD NOT BE RESTARTED (BECAUSE THE BUFFER WAS
* FULL OR THE INPUT MEDIA WAS EMPTY OR THERE WAS AN UNRECOVERABLE
* READ ERROR), AND THE OUTPUT COULD NOT BE RESTARTED (BECAUSE THE
* BUFFER WAS EMPTY OR THE OUTPUT MEDIA WAS FULL OR THERE WAS AN
* UNRECOVERABLE WRITE ERROR), THEN THE COPY OPERATION IS COMPLETE.
#
IF FET$LOCK[0] ##
AND ((CCBOPCODE[0] EQ CPYC"DISKAU" AND CCBRWDULD[0]) ##
OR (CCBOPCODE[0] EQ CPYC"AUDISK" AND CCBRWDULD[0] ##
AND FET$IN[0] EQ FHB$IN[0] AND FET$IN[0] EQ FET$OUT[0]) ##
OR (CCBRWDULD[0] AND (CCBDERR[0] OR CCBDFULL[0])))
THEN # INDICATE COPY COMPLETE #
BEGIN
DEL$LNK(ENTADR,LCHN"KC$GOING",0);
LLR$CCF[0] = TRUE;
LLR$RS[0] = PROCST"CONT3";
DRVRRECALL = TRUE; # INSURE DRIVER ACTIVE #
ADD$LNK(CCBLLRQ[0],LCHN"DRQUEUE",0);
IF CCBHDWPM
THEN
BEGIN # DELINK 1SS, NO REWIND/UNLOAD MESSAGE #
LLR$DRFUL[0] = TRUE; # FORCE UNLOAD OF CARTRIDGE #
END # RETURN OF COPY #
END
ENTADR = NEXTADDR;
END # MONITOR ENTRIES ON KEEP COPY GOING CHAIN #
RETURN;
END # KCG #
TERM
PROC K8G((CCBADR));
# TITLE K8G - KEEP M860 COPY GOING. #
BEGIN # K8G #
#
** K8G - KEEP M860 COPY GOING.
*
* *K8G* KEEPS THE M860 COPY SIDE OF A VOLUME OPERATION GOING.
* FLAGS IN THE *CCB* ARE UPDATED TO INDICATE THE STATE OF THE COPY
* OPERATION AND A *1SS* CALL IS ISSUED IF NECESSARY.
*
* PROC K8G((CCBADR))
*
* ENTRY (CCBADR) - ADDRESS OF THE COPY CONTROL BLOCK.
#
ITEM CCBADR U; # COPY CONTROL BLOCK ADDRESS #
#
**** PROC K8G - XREF LIST BEGIN.
#
XREF
BEGIN
PROC ABORT; # ABORT #
PROC FSCLOG; # LOG FSC ERROR MESSAGE #
PROC MESSAGE; # ISSUE MESSAGE #
END
#
**** PROC K8G - XREF LIST END.
#
DEF LISTCON #0#; # DO NOT LIST COMDECKS #
*CALL COMBFAS
*CALL COMBCDD
*CALL COMBCHN
*CALL COMBFET
*CALL COMBRCD
*CALL COMXCCB
*CALL COMXCTF
*CALL COMXMSC
CONTROL EJECT;
#
* SET FLAGS TO INDICATE WHY *1SS* HAS STOPPED.
#
P<CCB> = CCBADR;
P<FETFHB> = CCBM86FET[0];
IF CCBRWCT[0] NQ 0
THEN # FIRST REWIND/UNLOAD EXECUTED #
BEGIN
IF FHB$AT[0] EQ 0
THEN
BEGIN # REWIND/UNLOAD COMPLETED #
CCBRWDULD[0] = TRUE;
RETURN;
END
ELSE
BEGIN # SET FOR ANOTHER TRY #
IF CCBRWCT[0] LQ 5
THEN
BEGIN # TRY AN OTHER REWIND/UNLOAD #
GOTO RWDAUND;
END
ELSE
BEGIN # HARDWARE PROBLEM - REWIND/UNLOAD #
CCBHDWPM[0] = TRUE;
CCBRWDULD[0] = TRUE; # FORCE COMPLETE #
RETURN;
END
END # END OF REWIND/UNLOAD SET UP #
END # IF REWIND/UNLOAD COMPLETED #
IF FHB$EOI[0]
THEN
BEGIN # SET TAPE MARK #
CCBTPMARK[0] = TRUE;
END
IF FHB$AT[0] EQ RCENDV # #
OR FHB$AT[0] EQ RCTBRT
THEN # *TAPE MARK* OR *END OF VOLUME* #
BEGIN
CCBENDVOL[0] = TRUE;
GOTO RWDAUND;
END
IF FHB$AT[0] EQ 0
THEN
BEGIN # NO ERROR #
GOTO RWDAUND;
END
IF FHB$AT[0] EQ RCTERF
THEN
BEGIN
FHB$ST$SS[0] = FALSE;
GOTO RWDAUND;
END
IF FHB$AT[0] EQ RCBFTO
THEN
BEGIN
CCBHDWPM[0] = TRUE;
GOTO BMLRWUL;
END
IF FHB$AT[0] EQ RCSTER # #
AND FHB$ERRCD[0] EQ 0 # #
AND FHB$PYERR[0] EQ 1
THEN
BEGIN # TAPE PARITY ERROR #
CCBTAPPAR[0] = TRUE;
GOTO BMLRWUL;
END
IF FHB$AT[0] EQ RCILLF
OR FHB$AT[0] EQ RCBARG
OR FHB$AT[0] EQ RCILLU
THEN # ABORT ON ERRORS #
BEGIN
FE$RTN[0] = "K8G.";
MESSAGE(FEMSG,UDFL1);
ABORT;
END
IF (FHB$AT[0] EQ RCDLER)
OR (FHB$AT[0] EQ RCCWER)
OR (FHB$AT[0] EQ RCHDER)
THEN
BEGIN # PPU FOUND DATA TRANSFER ERROR #
CCPPUDCK[0] = TRUE;
GOTO BMLRWUL;
END
FSCLOG(DFET); # ERROR LOG MESSAGE #
CCBHDWPM[0] = TRUE; # REMAINING ERRORS #
CCBRWDULD[0] = TRUE;
RETURN;
#
* SEND A *BML* MESSAGE BEFORE REWIND/UNLOAD.
#
BMLRWUL:
FSCLOG(DFET); # ERROR LOG MESSAGE #
#
* RELEASE THE HARDWARE WITH A REWIND/UNLOAD FUNCTION.
#
RWDAUND:
DRVRRECALL = TRUE; # INSURE CPUDRIVER ACTIVE #
FHB$CODE[0] = FCRUN; # SET REWIND/UNLOAD #
CCBRWCT[0] = CCBRWCT[0] + 1;
RETURN;
END # KDG #
TERM
PROC LD$CAR((LLRADR));
# TITLE LD$CAR - LOAD CARTRIDGE. #
BEGIN # LD$CAR #
#
** LD$CAR - LOAD CARTRIDGE.
*
* LOAD CARTRIDGE GETS THE SPECIFIED CARTRIDGE LOADED ON A
* DRD AND THE LABEL VERIFIED BY *SSDRIVER*.
*
* PROC LD$CAR((LLRADR))
*
* ENTRY (LLRADR) - ADDRESS OF *LLRQ* ENTRY FOR THE REQUEST
* CONTAINING THE SMA-ID AND THE YZ
* COORDINATES.
*
* EXIT THE PROCESS STATE FIELD IN THE *LLRQ* ENTRY HAS BEEN
* ADVANCED TO INDICATE WHERE PROCESSING OF THIS REQUEST
* LEFT OFF, AND THUS WHAT TO DO NEXT TO ADVANCE THE
* REQUEST. IF THE MOUNT IS COMPLETE AN ERROR RESPONSE
* CODE IS RETURNED VIA *HLR$RESP[0]* FOR INTERNAL
* REQUESTOR OR *LTC$RQR[LTCENTRY]* FOR EXTERNAL
* REQUESTORS.
* ERROR RESPONSE CODES (VALUES DEFINED IN *COMBCPR*).
* = RESPTYP4"OK4".
* = RESPTYP4"NO$CART".
* = RESPTYP4"M86$HDW$PR".
*
* NOTES THIS MODULE IS A PSEUDO REENTRANT ROUTINE.
*
#
ITEM DRDCOUNT I; # *DRD-S* ACTIVE #
ITEM LLRADR U; # *LLRQ* ENTRY ADDRESS #
ITEM I U; # COUNTER #
ITEM MUCPRA U; # *UCP* OR *HLRQ* ADDRESS #
ITEM RQIID B; # INTERIAL REQUEST #
ITEM SMAO U; # REQUEST SM-ID #
ITEM YZO U; # Y AND Z COORDINATE #
#
**** PROC LD$CAR - XREF LIST BEGIN.
#
XREF
BEGIN
PROC ABORT; # INTERFACE TO *ABORT* MACRO #
PROC ADD$LNK; # ADD ENTRY TO END OF CHAIN #
PROC DELAY; # TIMED DELAY #
PROC KILL$UC; # ABORT A UCP #
PROC MESSAGE; # INTERFACE TO *MESSAGE* MACRO #
PROC SFCALL; # INTERFACE TO *SFCALL* MACRO #
PROC UCP$RES; # SEND RESPONSE TO UCP #
END
#
**** PROC LD$CAR - XREF LIST END.
#
DEF LISTCON #0#; # DO NOT LIST COMDECKS #
*CALL COMBFAS
*CALL COMBCHN
*CALL COMBCPR
*CALL COMBLRQ
*CALL COMBLBL
*CALL COMBMAT
*CALL COMBRCD
*CALL COMBUCR
*CALL COMXHLR
*CALL COMXCTF
*CALL COMBUDT
*CALL COMXIPR
*CALL COMXLTC
*CALL COMXMSC
DEF SKELLAB #" E CSN=CCCCCCCC, SM=A, SF=X, FFFFFFF. "#;
ARRAY MSGS [0:0] S(4);
BEGIN
ITEM MSGS$SKEL C(00,00,36); # TEXT #
ITEM MSGS$TYPE C(00,06,01); # TYPE #
ITEM MSGS$CSN C(00,42,08); # CCCCCCCC #
ITEM MSGS$SM C(02,00,01); # A #
ITEM MSGS$SF C(02,36,01); # SUB FAMILY #
ITEM MSGS$FAM C(02,54,07); # FAMILY #
ITEM MSGS$FI U(03,36,24); # ZERO FILL #
END
BASED
ARRAY CLEAR [0:0] S(1);
BEGIN
ITEM CLN U(00,36,24); # CLEAR DRD ASSIGNMENT #
END
SWITCH LDENTR:PROCST # LOAD CARTRIDGE ENTRIES #
LDINIT:INITIAL, # INITIAL ENTRY INTO PROCESS #
LDCONT:CONT1, # CONTINUE PROCESS #
LDWAIT1:CONT2; # AFTER A SWAPIN DELAY #
CONTROL EJECT;
P<LLRQ> = LLRADR;
GOTO LDENTR[LLR$PRCST[0]];
#
* "INITIAL" PROCESS STATE.
#
LDINIT: # INITIAL ENTRY #
#
* SEARCH THE *LLRQ* FOR AN MATCHING *CSN*. IF AN INTERNAL
* REQUEST, LINK THE NEW REQUEST AT THE END OF THE DUPLICATE
* *CSN* REQUEST. IF THE REQUEST IS FROM A *UCP* RETURN AN
* *CSN$IN$USE* RESPONSE.
#
SMAO = LLR$SMA[0];
YZO = LLR$YZ[0];
RQIID = LLR$RQI[0] EQ REQNAME"RQIINT";
P<LLRQ> = MAT$FWA[MAT$ENTRY"LLRQ"];
SLOWFOR I=0 STEP LLRQENTL WHILE I LS MAT$SPACE[MAT$ENTRY"LLRQ"]
DO
BEGIN # CHECK IF CALL FROM *UCP* #
IF SMAO EQ LLR$SMA[0] ##
AND YZO EQ LLR$YZ[0] ##
AND (LLR$DRDL[0] OR LLR$UNLD[0])
THEN
BEGIN # CHECK FOR *UCP* OR *INTERNAL* CALL #
IF LLR$UNLD[0]
THEN # DUPLICATE CARTRIDGE IN UNLOAD STATE #
BEGIN
P<LLRQ> = LLRADR;
DELAY(UCP$INTV,LLRADR,LLRQIND);
RETURN;
END
IF NOT RQIID
THEN
BEGIN # *UCP* DUPLICATE CARTRIDGE REQUEST #
P<LLRQ> = LLRADR;
LTCENTRY = LLR$LTCT[0];
LTC$RQR[LTCENTRY] = RESPTYP4"CSN$IN$USE";
UCP$RES;
END # END *UCP* DUPLICATE CARTRIDGE #
ELSE
BEGIN # *INTERNAL* DUPLICATE CARTRIDGE REQUEST #
P<LLRQ> = LLRADR;
P<HLRQ> = LLR$UCPRA[0];
HLR$RESP[0] = RESPTYP4"CSN$IN$USE";
P<CLEAR> = HLR$DRDRA[0];
CLN = 0;
HLR$DRDRA[0] = 0;
HLR$LRQADR[0] = 0;
ADD$LNK(LLR$UCPRA[0],LCHN"HL$READY",0);
END
LLR$PRCST[0] = PROCST"COMPLETE";
RETURN;
END # END OF *DUPLICATE* CARTRIDGE FOUND #
P<LLRQ> = P<LLRQ> + LLRQENTL;
END # END OF DUPLICATE CARTRIDGE SEARCH #
P<LLRQ> = LLRADR;
IF NOT RQIID
THEN # ASSIGN *DRD* TO EXTERNAL REQUEST #
BEGIN
SLOWFOR I=1 STEP 1 UNTIL MAXSMUNIT
DO
BEGIN # UNTIL *SM* FOUND #
IF SMAO EQ SM$ID[I]
THEN
BEGIN # *SM* FOUND #
GOTO SMFOUND;
END
END
SMFOUND:
DRDCOUNT = 0;
IF D0$ON[I]
THEN
BEGIN
DRDCOUNT = 1;
END
IF D1$ON[I]
THEN
BEGIN
DRDCOUNT = DRDCOUNT + 1;
END
IF SM$REQRES1[I] NQ 0 ##
AND SM$REQRES2[I] NQ 0
THEN # NO *DRD-S* AVAILABLE #
BEGIN
DELAY(UCP$INTV,LLRADR,LLRQIND);
RETURN;
END
IF DRDCOUNT EQ 1
THEN # ONLY ONE *DRD* ACTIVE #
BEGIN
IF (SM$REQRES1[I] NQ 0) ##
OR (SM$REQRES2[I] NQ 0)
THEN # NO *DRD* AVAILABLE #
BEGIN
DELAY(UCP$INTV,LLRADR,LLRQIND);
RETURN;
END
END # *DRD* = 1 #
IF SM$REQRES1[I] EQ 0
THEN # RESERVE A *DRD* #
BEGIN
SM$REQRES1[I] = LLRADR;
SM$LLRQ1[I] = TRUE;
LLR$DRDRA[0] = LOC(SM$REQRES1[I]);
END
ELSE
BEGIN
SM$REQRES2[I] = LLRADR;
SM$LLRQ2[I] = TRUE;
LLR$DRDRA[0] = LOC(SM$REQRES2[I]);
END
END # EXTERNAL *DRD*ASSIGNMENT #
LLR$RC[0] = REQCODE"SMOUNT"; # ISSUE MOUNT REQUEST TO DRIVER #
LLR$DRDL[0] = TRUE;
ADD$LNK(LLRADR,LCHN"DRQUEUE",0);
LLR$PRCST[0] = PROCST"CONT1";
RETURN;
#
* "CONT1" PROCESS STATE.
*
* RETURN RESPONSE FROM *SSDRVR* TO THE REQUESTOR.
#
LDCONT: # CONTINUE PROCESSING #
LTCENTRY = LLR$LTCT[0];
IF LLR$RQI[0] LQ REQNAME"RQITEST"
THEN
BEGIN # REQUEST IS FROM A UCP #
IF LLR$UCPABT[0]
THEN
BEGIN # UCP HAS ABORTED #
IF LLR$DR[0] EQ RESPTYP4"OK4"
OR (LLR$DR[0] EQ RESPTYP4"M86$HDW$PR" AND NOT LLR$LDERR[0])
THEN
BEGIN # MOUNT WAS OK SO DISMOUNT CARTRIDGE #
GOTO UNLCART;
END # MOUNT WAS OK SO DISMOUNT CARTRIDGE #
ELSE
BEGIN # CLEAR LLRQ #
GOTO CL$EX$UDT;
END
END # UCP HAS ABORTED #
ELSE
BEGIN # UCP IS STILL RUNNING #
IF LLR$DR[0] EQ RESPTYP4"OK4"
OR LLR$DR[0] EQ RESPTYP4"CART$LB$ERR" # #
OR LLR$DR[0] EQ RESPTYP4"UNK$CART"
THEN
BEGIN # MOUNT OK, SET UP *LTC* #
LTC$CART[LTCENTRY] = TRUE;
LTC$DRD[LTCENTRY] = LLR$DRD[0];
LTC$YP[LTCENTRY] = LLR$Y[0];
LTC$ZP[LTCENTRY] = LLR$Z[0];
#
* RETURN THE LABEL TO THE UCP. IF THE UCP IS SWAPPED OUT,
* DELAY THE REQUEST AND TRY AGAIN LATER.
#
WRTLOOP:
LTCENTRY = LLR$LTCT[0];
LTC$SFUCPA[LTCENTRY] = LLR$ADDR2[0];
LTC$SFSCPA[LTCENTRY] = MAT$FWA[MAT$ENTRY"LABBUF"];
LTC$SFFP[LTCENTRY] = LABLEN;
LTC$SFFC[LTCENTRY] = SFWRIT;
SFCALL(LOC(LTC$WORD0[LTCENTRY]),RCL);
IF LTC$SFRC[LTCENTRY] EQ SFRCUCPGON
THEN
BEGIN
GOTO UNLCART;
END
IF LTC$SFRC[LTCENTRY] EQ SFRCBDUCPA
THEN
BEGIN
KILL$UC(KILLCODE"INVADDR");
GOTO UNLCART;
END
IF LTC$SFRC[LTCENTRY] EQ SFRCSWPOUT
THEN
BEGIN
LTC$SFUCPA[LTCENTRY] = 0;
LTC$SFSCPA[LTCENTRY] = 0;
LTC$SFFC[LTCENTRY] = SFSWPI;
SFCALL(LOC(LTC$WORD0[LTCENTRY]),RCL);
#
* "CONT2" PROCESS STATE.
#
LDWAIT1:
LTCENTRY = LLR$LTCT[0];
IF LTC$SFFCC[LTCENTRY]
THEN
BEGIN
GOTO WRTLOOP;
END
LLR$PRCST[0] = PROCST"CONT2";
DELAY(UCP$INTV,LLRADR,LLRQIND);
RETURN;
END
LTC$RQR[LTCENTRY] = LLR$DR[0];
LABELBUSY = FALSE;
UCP$RES;
RETURN;
END # MOUNT WAS OK SO BUILD UTC #
#
* ERROR - CLEAN UP *LTCT*.
#
LLR$RQR[0] = LLR$DR[0];
LTC$LLRQA[LTCENTRY] = 0; # CLEAR *LLRQ* ENTRY #
LTC$RQR[LTCENTRY] = LLR$DR[0];
UCP$RES;
END # UCP IS STILL RUNNING #
LABELBUSY = FALSE;
CL$EX$UDT:
P<CLEAR> = LLR$DRDRA[0]; # CLEAR *DRD* RESERVATION #
CLN = 0;
LLR$PRCST[0] = PROCST"COMPLETE";
RETURN;
END # REQUEST IS FROM A UCP #
IF LLR$RQI[0] EQ REQNAME"RQIINT"
THEN # IF REQUEST IS INTERNAL #
BEGIN
#
* ADD REQUESTING *HLRQ* ENTRY TO THE READY CHAIN.
#
P<HLRQ> = LLR$UCPRA[0];
HLR$RESP[0] = LLR$DR[0];
HLR$ADRD[0] = LLR$DRD[0];
IF LLR$DR[0] NQ RESPTYP4"OK4"
THEN
BEGIN # RETURN THE *LLRQ* #
MSGS$SKEL[0] = SKELLAB;
MSGS$CSN[0] = HLR$CSND[0];
MSGS$SM[0] = HLR$SM[0];
MSGS$SF[0] = O"33" + HLR$SBF[0];
MSGS$FAM[0] = HLR$FAM[0];
MESSAGE(MSGS,SYSUDF1);
IF (LLR$DR[0] NQ RESPTYP4"CELL$EMP") ##
AND (LLR$DR[0] NQ RESPTYP4"SMA$OFF") ##
AND (LLR$DR[0] NQ RESPTYP4"M86$HDW$PR")
THEN
BEGIN # OUTPUT DRIVER LABEL BUFFER #
MSGS$TYPE[0] = "R";
MSGS$CSN[0] = LAB$CSND[0];
MSGS$SM[0] = LAB$SMID;
MSGS$SF[0] = O"33" + LAB$SF;
MSGS$FAM[0] = LAB$FMLY;
MESSAGE(MSGS,SYSUDF1);
END # DRIVER LABEL BUFFER #
IF LLR$DR[0] EQ RESPTYP4"M86$HDW$PR" AND NOT LLR$LDERR[0]
THEN
BEGIN # UNLOAD OF CARTRIDGE #
GOTO INTIALUNL; # LET EXEC UNLOAD CARTRIDGE #
END
#
* DELINK LLRQ FROM HLRQ.
* RELEASE LLRQ.
#
HLR$LRQADR[0] = 0;
LLR$PRCST[0] = PROCST"COMPLETE";
P<CLEAR> = HLR$DRDRA[0]; # CLEAR *DRD* RESERVATION #
CLN = 0;
HLR$DRDRA[0] = 0;
IF LLR$DR[0] EQ RESPTYP4"CELL$EMP" ##
OR LLR$DR[0] EQ RESPTYP4"SMA$OFF" ##
OR LLR$DR[0] EQ RESPTYP4"M86$HDW$PR"
THEN
BEGIN # DO NOT RELEASE LABEL BUFFER #
GOTO NOLABREL;
END # RETURNED #
END
INTIALUNL:
LABELBUSY = FALSE;
NOLABREL:
ADD$LNK(LLR$UCPRA[0],LCHN"HL$READY",0);
RETURN;
END
#
* UNLOAD A CARTRIDGE.
#
UNLCART:
LLR$PRCNME[0] = REQTYP4"UNLD$CART";
LLR$PRCST[0] = PROCST"INITIAL";
LABELBUSY = FALSE;
ADD$LNK(LLRADR,LCHN"LL$READY",0);
RETURN;
END # LD$CAR #
TERM
PROC LLRQENQ(ADDR);
# TITLE LLRQENQ - LOW LEVEL REQUEST QUEUE ENQUEUER. #
BEGIN # LLRQENQ #
#
** LLRQENQ - LOW LEVEL REQUEST QUEUE ENQUEUER.
*
* *LLRQENQ* DELETES AN ENTRY FROM THE FREE SPACE CHAIN AND
* LINKS IT INTO THE *LLRQ* READY CHAIN.
* *LLRQENQ* IS CALLED ONLY IF THE *LLRQ* IS NOT FULL.
*
* PROC LLRQENQ(ADDR)
*
* EXIT (ADDR) - ADDRESS OF ENTRY ADDED TO QUEUE.
*
* MESSAGES * EXEC ABNORMAL, LLRQENQ.*
#
ITEM ADDR U; # ADDRESS OF *LLRQ* ENTRY #
#
**** PROC LLRQENQ - XREF LIST BEGIN.
#
XREF
BEGIN
PROC ABORT; # ABORT #
PROC ADD$LNK; # ADD ENTRY TO END OF CHAIN #
PROC DEL$LNK; # DELETE ENTRY FROM CHAIN #
PROC MESSAGE; # ISSUE MESSAGE #
END
#
**** PROC LLRQENQ - XREF LIST END.
#
DEF LISTCON #0#; # DO NOT LIST COMDECKS #
*CALL COMBFAS
*CALL COMBCHN
*CALL,COMBKDD
*CALL COMBLRQ
*CALL COMXMSC
CONTROL EJECT;
#
* CHECK FOR NO FREE SPACE.
#
ADDR = CHN$BOC[LCHN"LL$FRSPC"];
IF ADDR EQ 0 # IF NO FREE ENTRIES #
THEN
BEGIN
FE$RTN[0] = "LLRQENQ.";
MESSAGE(FEMSG,UDFL1);
ABORT;
END
DEL$LNK(ADDR,LCHN"LL$FRSPC",0); # DELETE ENTRY FROM FREE SPACE
CHAIN #
P<LLRQ> = ADDR;
P<KWORD> = LOC(LLR$KWORDS[0]); # PRESET K-DISPLAY WORDS #
KW$COMP[0] = TRUE;
ADD$LNK(ADDR,LCHN"LL$READY",0); # ADD ENTRY TO READY CHAIN #
RETURN;
END # LLRQENQ #
TERM
PROC LLRQMTR;
# TITLE LLRQMTR - LOW LEVEL REQUEST QUEUE MONITOR. #
BEGIN # LLRQMTR #
#
** LLRQMTR - LOW LEVEL REQUEST QUEUE MONITOR.
*
* THE LOW LEVEL REQUEST QUEUE MONITOR CONTROLS THE ACTIVATION
* OF *LLRQ* PROCESSORS. EACH *LLRQ* ENTRY ON THE READY CHAIN IS
* ACTIVATED BY CALLING THE APPROPRIATE PROCESSOR.
*
* PROC LLRQMTR
*
* EXIT IF THE PROCESS STATE FIELD OF AN *LLRQ* ENTRY IS SET
* TO "COMPLETE" AFTER ITS PROCESSOR IS CALLED, THE ENTRY
* IS CLEARED AND LINKED INTO THE FREE SPACE CHAIN.
* OTHERWISE, THE PROCESSOR HAS SET UP SOME CONDITION
* THAT WILL EVENTUALLY CAUSE THE *LLRQ* ENTRY TO BE
* RELINKED INTO THE *LLRQ* READY CHAIN.
#
#
**** PROC LLRQMTR - XREF LIST BEGIN.
#
XREF
BEGIN
PROC ADD$LNK; # ADD ENTRY TO END OF CHAIN #
PROC CPY$DS; # COPY DISK TO VOLUME #
PROC CPY$RS; # COPY RAW VOLUME #
PROC CPY$SD; # COPY VOLUME TO DISK #
PROC DEL$LNK; # DELETE ENTRY FROM CHAIN #
PROC INIT$HW; # INITIALIZE M860 HARDWARE #
PROC LD$CAR; # LOAD CARTRIDGE #
PROC SSDRVR; # SS DRIVER #
PROC UNL$CAR; # UNLOAD CARTRIDGE #
PROC WT$LAB; # WRITE LABEL #
PROC ZFILL; # ZERO FILL BUFFER #
END
#
**** PROC LLRQMTR - XREF LIST END.
#
DEF LISTCON #0#; # DO NOT LIST COMDECKS #
*CALL COMBFAS
*CALL COMBCHN
*CALL COMBCPR
*CALL COMBLRQ
*CALL COMXMSC
ITEM LLRENT U; # *LLRQ* ENTRY ADDRESS #
SWITCH LLPROC:REQTYP4 # *LLRQ* PROCESSOR CALLS #
LL1:LOAD$CART, # #
LL2:UNLD$CART, # #
LL3:WRT$LAB, # #
LL4:CPY$AD, # #
LL5:CPY$DA, # #
LL6:CP$RAW$AU, # #
LL7:INITHW, # #
ENDLLP:LSTREQTYP4; # END OF *LLRQ* PROCESSOR CALLS #
CONTROL EJECT;
#
* *LLRQMTR* IS CALLED WHEN THERE IS WORK FOR *SSDRVR* TO DO OR
* WHEN THERE ARE ENTRIES ON THE *LLRQ* READY CHAIN TO BE PROCESSED.
* PROCESSING OF ENTRIES ON THE *LLRQ* READY CHAIN CAN CREATE WORK
* FOR *SSDRVR*, AND EXECUTION OF *SSDRVR* CAN PUT ENTRIES BACK
* ON THE *LLRQ* READY CHAIN.
#
IF CHN$BOC[LCHN"LL$READY"] EQ 0
THEN # IF READY CHAIN IS EMPTY #
BEGIN
SSDRVR;
END
#
* TRAVERSE THE *LLRQ* READY CHAIN.
#
REPEAT WHILE CHN$BOC[LCHN"LL$READY"] NQ 0
DO
BEGIN # PROCESS READY *LLRQ* ENTRIES #
LLRENT = CHN$BOC[LCHN"LL$READY"];
DEL$LNK(LLRENT,LCHN"LL$READY",0);
P<LLRQ> = LLRENT;
#
* SIMULATED CASE STATEMENT FOR *LLRQ* PROCESSOR CALLS.
#
GOTO LLPROC[LLR$PRCNME[0]];
LL1: # LOAD CARTRIDGE #
LD$CAR(LLRENT);
GOTO ENDLLP;
LL2: # UNLOAD CARTRIDGE #
UNL$CAR(LLRENT);
GOTO ENDLLP;
LL3: # WRITE LABEL #
WT$LAB(LLRENT);
GOTO ENDLLP;
LL4: # COPY VOLUME TO DISK #
CPY$SD(LLRENT);
GOTO ENDLLP;
LL5: # COPY DISK TO VOLUME #
CPY$DS(LLRENT);
GOTO ENDLLP;
LL6: # COPY RAW VOLUME #
CPY$RS(LLRENT);
GOTO ENDLLP;
LL7: # INITIALIZE M860 HARDWARE #
INIT$HW(LLRENT);
GOTO ENDLLP;
ENDLLP: # CONTINUE #
#
* END SIMULATED CASE STATEMENT FOR *LLRQ* PROCESSOR CALLS.
#
#
* IF A PROCESSOR CREATED WORK FOR THE DRIVER, CALL *SSDRVR*.
#
IF CHN$BOC[LCHN"DRQUEUE"] NQ 0
THEN # IF DRIVER QUEUE NOT EMPTY #
BEGIN
SSDRVR;
END
#
* ADD *LLRQ* ENTRY TO THE FREE SPACE CHAIN IF PROCESS IS COMPLETE.
#
P<LLRQ> = LLRENT;
IF LLR$PRCST[0] EQ PROCST"COMPLETE"
THEN # IF PROCESS IS COMPLETE #
BEGIN
ZFILL(LLRQ,LLRQENTL); # CLEAR *LLRQ* ENTRY #
ADD$LNK(LLRENT,LCHN"LL$FRSPC",0);
END
END # PROCESS READY *LLRQ* ENTRIES #
RETURN;
END # LLRQMTR #
TERM
PROC UNL$CAR((LLRENT));
# TITLE UNL$CAR - RETURN CARTRIDGE TO MATRIX. #
BEGIN # UNL$CAR #
#
** UNL$CAR - RETURN CARTRIDGE TO MATRIX.
*
* *UNL$CAR* RETURNS THE CARTRIDGE FROM THE DRD TO THE
* DESIGNATED MATRIX POSITION. IF THE CARTRIDGE IS ASSIGNED TO THE
* INPUT TRAY ON ENTRY, THE ASSIGNMENT WILL BE CHANGED TO THE
* OUTPUT TRAY PRIOR TO DISMOUNTING THE CARTRIDGE.
*
* PROC UNL$CAR((LLRENT))
*
* ENTRY (LLRENT) - ADDRESS OF *LLRQ* ENTRY FOR THE REQUEST
* CONTAINING THE SMA-ID AND THE YZ
* COORDINATES.
*
* EXIT THE PROCESS STATE FIELD IN THE *LLRQ* ENTRY HAS BEEN
* ADVANCED TO INDICATE WHERE PROCESSING OF THIS REQUEST
* LEFT OFF, AND THUS WHAT TO DO NEXT TO ADVANCE THE
* REQUEST.
*
* WHEN THE PROCESS IS COMPLETED AN ERROR RESPONSE CODE
* IS RETURNED VIA *LTC$RQR[LTCENTRY]* FOR EXTERNAL
* REQUESTORS OR *HLR$RESP[0]* FOR INTERNAL REQUESTORS.
* RESPONSE CODE (VALUES ARE DEFINED IN *COMBCPR*).
* = RESPTYP4"OK4".
*
* THE CARTRIDGE LOAD, PASS, AND ERROR COUNTS ARE
* ALSO RETURNED WHEN THE REQUEST IS COMPLETED.
*
* NOTES THIS MODULE IS A PSEUDO REENTRANT ROUTINE.
#
ITEM LLRENT U; # *LLRQ* ENTRY TO PROCESS #
ITEM LLRENTI U; # WAITTING *LLRQ* ADDRESS #
ITEM SCR1 U; # SCRATCH WORD #
ITEM SCR2 U; # SCRATCH WORD #
ITEM SCR3 U; # SCRATCH WORD #
#
**** PROC UNL$CAR - XREF LIST BEGIN.
#
XREF
BEGIN
PROC ADD$LNK; # ADD ENTRY TO END OF CHAIN #
PROC UCP$RES; # NOTIFY UCP OF REQUEST COMPLETE #
END
#
**** PROC UNL$CAR - XREF LIST END.
#
DEF LISTCON #0#; # DO NOT LIST COMMON DECKS #
*CALL COMBFAS
*CALL COMBCHN
*CALL COMBCPR
*CALL COMBLRQ
*CALL COMBRCD
*CALL COMBUCR
*CALL COMXHLR
*CALL COMXLTC
*CALL COMXMSC
BASED
ARRAY CLEAR [0:0] S(1);
BEGIN
ITEM CLN U(00,36,24); # CLEAR *DRD* ASSIGNMENT #
END
SWITCH UNLENTR:PROCST # UNLOAD CARTRIDGE ENTRIES #
UNLINIT:INITIAL, # INITIAL ENTRY POINT #
UNLC1:CONT1; # CONTINUE AFTER DISMOUNT REQUEST
#
CONTROL EJECT;
P<LLRQ> = LLRENT;
GOTO UNLENTR[LLR$PRCST[0]];
#
* "INITIAL" PROCESS STATE.
*
* ASSIGN THE CARTRIDGE TO THE EXIT TRAY IF THE ORIGINAL
* ASSIGNMENT WAS TH ENTRY TRAY.
#
UNLINIT:
IF LLR$Y[0] EQ SM$ENT$TY ##
AND LLR$Z[0] EQ SM$TY$Z
THEN
BEGIN
LLR$Y[0] = SM$EXIT$TY;
LLR$Z[0] = SM$TY$Z;
END
#
* DISMOUNT THE CARTRIDGE.
#
LLR$RC[0] = REQCODE"SDISMOUNT";
LLR$PRCST[0] = PROCST"CONT1";
LLR$DRDL[0] = FALSE;
LLR$UNLD[0] = TRUE; # UNLOAD STARTED #
LLR$RS[0] = PROCST"INITIAL";
ADD$LNK(LLRENT,LCHN"DRQUEUE",0);
RETURN;
#
* "CONT1" PROCESS STATE.
*
* UPDATE THE APPROPRIATE DATA FIELDS OF THE REQUEST AND PASS
* THE REQUEST ON TO THE NEXT PROCESS.
#
UNLC1:
IF LLR$RQI[0] EQ REQNAME"RQIINT"
THEN
BEGIN # INTERNAL REQUEST #
P<HLRQ> = LLR$UCPRA[0];
HLR$LRQADR[0] = 0; # DELINK *LLRA* FROM *HLRA* #
HLR$RESP[0] = RESPTYP4"OK4";
ADD$LNK(LLR$UCPRA[0],LCHN"HL$READY",0);
END # INTERNAL REQUEST #
ELSE
BEGIN # EXTERNAL REQUEST #
P<CLEAR> = LLR$DRDRA[0]; # CLEAR *DRD* RESERVE #
CLN = 0;
IF NOT LLR$UCPABT[0]
THEN # RETURN RESPONSE TO UCP #
BEGIN
LTCENTRY = LLR$LTCT[0];
LTC$LLRQA[LTCENTRY] = 0;
LTC$CART[LTCENTRY] = FALSE;
LTC$RQR[LTCENTRY] = RESPTYP4"OK4";
UCP$RES;
END
END # EXTERNAL REQUEST #
#
* MARK THE REQUEST COMPLETE AND RETURN TO *LLRQ* MONITOR.
#
LLR$UNLD[0] = FALSE; # UNLOAD COMPLETE #
LLR$PRCST[0] = PROCST"COMPLETE";
RETURN;
END # UNL$CAR #
TERM
PROC SETFET(LLRADR);
# TITLE SETFET - SETS LARGE BUFFER POINTERS #
BEGIN # SETFET #
#
** SETFET - SETS LARGE BUFFER POINTERS.
*
* *SETFET* SETS FET POINTERS FOR CIO AND *1SS*.
*
* PROC SETFET
*
* ENTRY (LLRADR) - ADDRESS OF THE *LLRQ* ENTRY THAT
* CONTAINS THE ADDRESS OF THE DISK
* AND *M860* FET AND BUFFER ADDRESSES.
* (LARGE BUFFER MUST ALREADY EXIST.)
*
* EXIT FETS ARE COMPLETE FOR BOTH CIO AND *1SS*
* PROCESSING. STRIPE HIGH AND LOW SET INTO THE
* *LLRQ*.
*
* NOTES THIS MODULE IS CALLED ONLY BY THE COP$XX ROUTINES.
#
ITEM LLRADR; # *LLRQ* ADDRESS #
#
**** PROC SETFET - XREF LIST BEGIN.
#
XREF
BEGIN
PROC ZFILL; # ZERO FILL BUFFER #
PROC ZSETFET; # INITIALIZE A FET #
END
#
**** PROC SETFET - XFET LIST END.
#
DEF LISTCON #0#; # DO NOT LIST COMDECKS #
*CALL COMBFAS
*CALL COMBCPR
*CALL COMBFET
*CALL COMBLRQ
*CALL COMXBST
*CALL COMXCCB
*CALL COMXHLR
#
* SET *LLRQ* STIPE LOW AND HIGH POINTERS.
#
P<LLRQ> = LLRADR;
P<HLRQ> = LLR$UCPRA[0];
P<CCB> = LLR$CCB[0];
IF LLR$PRCNME[0] NQ REQTYP4"CP$RAW$AU"
THEN
BEGIN
LLR$ST$LW[0] = INSPAU*HLR$VOLAU[0]+(INFTST-INSPAU);
LLR$ST$HI[0] = INSPAU*HLR$VOLLN[0]+LLR$ST$LW[0]-1;
END
#
* INITIALIZE CIO AND *1SS* FETS.
#
CCBDKFET[0] = LLR$DSKFET[0];
CCBM86FET[0] = LLR$MSFET[0];
CCBLLRQ[0] = LLRADR;
CCBCLFG[0] = 0;
CCBRWCT[0] = 0; # CLEAR COUNTER #
ZSETFET(LLR$DSKFET[0],HLR$FLNM[0],LLR$DA[0],DATABL,(RFETL+RFHBL));
P<FETFHB> = LLR$MSFET[0];
P<FETSET> = LLR$DSKFET[0];
FET$EP[0] = TRUE;
FET$R[0] = TRUE;
FET$UP[0] = TRUE;
FHB$FRST[0] = FET$FRST[0];
FHB$IN[0] = FET$IN[0];
FHB$OUT[0] = FET$OUT[0];
FHB$LIM[0] = FET$LIM[0];
END
TERM
PROC WT$LAB((LLRENT));
# TITLE WT$LAB - WRITE CARTRIDGE LABEL. #
BEGIN # WT$LAB #
#
** WT$LAB - WRITE CARTRIDGE LABEL.
*
* *WT$LAB* WRITES THE CARTRIDGE LABEL.
*
* PROC WT$LAB((LLRENT))
*
* ENTRY (LLRENT) - ADDRESS OF *LLRQ* ENTRY FOR THE REQUEST
* CONTAINING THE SMA-ID, THE VOLUME NUMBER,
* AND THE YZ COORDINATES.
*
* EXIT THE PROCESS STATE FIELD IN THE *LLRQ* ENTRY HAS BEEN
* ADVANCED TO INDICATE WHERE PROCESSING OF THIS REQUEST
* LEFT OFF, AND THUS WHAT TO DO NEXT TO ADVANCE THE
* REQUEST.
*
* WHEN THE PROCESS IS COMPLETED AN ERROR RESPONSE CODE
* IS RETURNED VIA LTC$RQR[LTCENTRY] FOR EXTERNAL
* REQUESTORS OR HLR$RESP[0] FOR INTERNAL REQUESTORS.
* IS RETURNED VIA *LTC$RQR[LTCENTRY]* FOR EXTERNAL
* REQUESTORS OR *HLR$RESP[0]* FOR INTERNAL REQUESTORS.
* RESPONSE CODE (VALUES ARE DEFINED IN *COMBCPR*).
* = RESPTYP4"OK4".
* = RESPTYP4"UN$WRT$ERR".
* = RESPTYP4"EX$WRT$ERR".
* = RESPTYP4"MSFHDW$ERR".
*
* MESSAGES * EXEC ABNORMAL, WT$LAB.*
*
* NOTES THIS MODULE IS A PSEUDO REENTRANT ROUTINE.
*
* COMMON BUFFER *LABBUF* WILL BE USED TO TRANSFER
* THE LABEL FROM THE *UCP* TO THE *SSDRIVER*.
#
ITEM LLRENT U; # ADDRESS OF *LLRQ* ENTRY #
#
**** PROC WT$LAB - XREF LIST BEGIN.
#
XREF
BEGIN
PROC ABORT; # INTERFACE TO *ABORT* MACRO #
PROC ADD$LNK; # ADD ENTRY TO END OF CHAIN #
PROC DELAY; # TIMED DELAY #
PROC KILL$UC; # ABORT A UCP #
PROC MESSAGE; # CALLS *MESSAGE* MACRO #
PROC SFCALL; # INTERFACE TO *SFCALL* MACRO #
PROC UCP$RES; # NOTIFY UCP OF REQUEST COMPLETE #
END
#
**** PROC WT$LAB - XREF LIST END.
#
DEF LISTCON #0#; # DO NOT LIST COMMON DECKS #
*CALL COMBFAS
*CALL COMBCHN
*CALL COMBCPR
*CALL COMBFET
*CALL COMBLBL
*CALL COMBLRQ
*CALL COMBMAT
*CALL COMBRCD
*CALL COMBUCR
*CALL COMXCTF
*CALL COMXHLR
*CALL COMXIPR
*CALL COMXLTC
*CALL COMXMSC
ITEM REQTYP B=FALSE; # *LLRQ* ID FOR *GET$SB* #
BASED
ARRAY CLEAR [0:0] S(1);
BEGIN
ITEM CLN U(00,36,24); # CLEAR *DRD* ASSIGNMENT #
END
SWITCH WTENTR:PROCST # WRITE LABEL ENTRIES #
WTINIT:INITIAL, # INITIAL ENTRY POINT #
WTC1:CONT1, # AFTER A SWAPIN DELAY #
WTC2:CONT2; # AFTER WRITE LABEL #
CONTROL EJECT;
P<LLRQ> = LLRENT;
LLR$DR[0] = 0;
LTCENTRY = LLR$LTCT[0];
GOTO WTENTR[LLR$PRCST[0]];
#
* "INITIAL" PROCESS STATE.
#
WTINIT:
#
* CHECK LABEL BUFFER FOR BUSY. IF BUSY, RETURN *LLRQ*
* TO THE DELAY CHAIN.
#
IF LABELBUSY
THEN
BEGIN # EXIT TO DELAY CHAIN #
DELAY(UCP$INTV,LLRENT,LLRQIND);
RETURN;
END # RETURNED TO DELAY CHAIN #
LABELBUSY = TRUE; # RESERVE LABEL BUFFER #
#
* READ THE LABEL FROM THE UCP. IF THE UCP IS SWAPPED OUT, DELAY
* THE REQUEST AND TRY AGAIN LATER.
#
SFLOOP:
LTC$SFUCPA[LTCENTRY] = LLR$ADDR2[0];
LTC$SFSCPA[LTCENTRY] = MAT$FWA[MAT$ENTRY"LABBUF"];
LTC$SFFP[LTCENTRY] = LABLEN;
LTC$SFFC[LTCENTRY] = SFREAD;
SFCALL(LOC(LTC$WORD0[LTCENTRY]),RCL);
IF LTC$SFRC[LTCENTRY] EQ SFRCUCPGON
THEN
BEGIN
GOTO COMPLUCP;
END
IF LTC$SFRC[LTCENTRY] EQ SFRCBDUCPA
THEN
BEGIN
KILL$UC(KILLCODE"INVADDR");
GOTO COMPLUCP;
END
IF LTC$SFRC[LTCENTRY] EQ SFRCSWPOUT
THEN
BEGIN
LTC$SFUCPA[LTCENTRY] = 0;
LTC$SFSCPA[LTCENTRY] = 0;
LTC$SFFC[LTCENTRY] = SFSWPI;
SFCALL(LOC(LTC$WORD0[LTCENTRY]),RCL);
#
* "CONT1" PROCESS STATE.
#
WTC1:
LTCENTRY = LLR$LTCT[0];
IF LTC$SFFCC[LTCENTRY]
THEN
BEGIN
GOTO SFLOOP;
END
LLR$PRCST[0] = PROCST"CONT1";
DELAY(UCP$INTV,LLRENT,LLRQIND);
RETURN;
END
IF LTC$SFRC[LTCENTRY] NQ 0
THEN
BEGIN
FE$RTN[0] = "WT$LAB.";
MESSAGE(FEMSG[0],UDFL1);
ABORT;
END
LLR$PRCST[0] = PROCST"CONT2";
LLR$RC[0] = REQCODE"SWRT$LABEL";
LLR$RS[0] = PROCST"INITIAL";
ADD$LNK(LLRENT,LCHN"DRQUEUE",0);
RETURN;
#
* RETURN THE RESPONSE CODE TO THE *UCP*.
#
COMPLUCP:
LABELBUSY = FALSE;
LLR$DR[0] = 0;
LLR$UCPABT[0] = FALSE;
LLR$Y[0] = SM$EXIT$TY;
LLR$Z[0] = SM$TY$Z;
LLR$PRCNME[0] = REQTYP4"UNLD$CART";
LLR$PRCST[0] = PROCST"INITIAL";
ADD$LNK(LLRENT,LCHN"LL$READY",0);
RETURN;
#
* "CONT2" PROCESS STATE.
#
WTC2:
#
* MARK THE REQUEST COMPLETE AND RETURN TO *LLRQ* MONITOR.
#
IF NOT LLR$UCPABT[0]
THEN
BEGIN # SEND REQUEST BACK TO UCP #
LTC$CART[LTCENTRY] = FALSE;
LTC$LLRQA[LTCENTRY] = 0;
LTC$RQR[LTCENTRY] = LLR$DR[0];
UCP$RES;
END # COMPLETED RETURN REQUEST #
P<CLEAR> = LLR$DRDRA[0]; # CLEAR *DRD* RESERVE #
CLN = 0;
LLR$PRCST[0] = PROCST"COMPLETE";
RETURN;
END # WT$LAB #
TERM