Trailing-Edge
-
PDP-10 Archives
-
BB-H138C-BM
-
galaxy-sources/cdrive.mac
There are 37 other files named cdrive.mac in the archive. Click here to see a list.
TITLE CDRIVE - Multiple Card Reader Spooler
;
;
; COPYRIGHT (c) 1978,1979
; DIGITAL EQUIPMENT CORPORATION
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; AND COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE
; AND WITH THE INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS
; SOFTWARE OR ANY OTHER COPIES THEREOF MAY NOT BE PROVIDED OR
; OTHERWISE MADE AVAILABLE TO ANY OTHER PERSON. NO TITLE TO
; AND OWNERSHIP OF THE SOFTWARE IS HEREBY TRANSFERRED.
;
; THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE
; WITHOUT NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT
; BY DIGITAL EQUIPMENT CORPORATION.
;
; DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY
; OF ITS SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY
; DIGITAL.
SEARCH GLXMAC,ORNMAC,QSRMAC
SEARCH D60UNV ;GET DN60 SYMBOLS
PROLOG (CDRIVE)
.DIRECT FLBLST
IF1,<
TOPS10 <PRINTX Assembling Galaxy-10 Card Reader Spooler>
TOPS20 <PRINTX Assembling Galaxy-20 Card Reader Spooler>
>
SALL
;VERSION INFORMATION
RDRVER==1
RDRMIN==0
RDREDT==31
RDRWHO==0
%RDR==<BYTE (3)RDRWHO (9)RDRVER (6)RDRMIN (18)RDREDT>
LOC 137
EXP %RDR
RELOC 0
SUBTTL SETUP REMOTE STATION PARAMETERS
;IF WE HAVE RJE SUPPORT, GET JSYS SIMULATION PACKAGE
FTRMTE==FTRJE!FTDN60 ;SEE IF ANY REMOTES GEN'D
IFN FTRJE,<.REQUIRE NURD.REL> ;GET DN200 I/O PACKAGE
IFN FTDN60,<.REQUIRE D60JSY.REL ;GET DN60 I/O PACKAGE
D60ERR> ;GEN D60 ERROR CODES
SUBTTL Revision History
COMMENT \
1 Add Symbols CRDNBR, CRDSIZ. Change the processing routines
to use them.
2 Add SNDSTS routine to send QUASAR current device status information
3 Change IB to new format and add PIB.
4 Delete routine DISPAT. Add DN200 support.
5 Add Status update messages capability
6 Major revision to support DN200 and DN60 readers
7 Fixup minor bugs caused by revision 6
10 Add routine OACSHT for defered reader shutdown.
Make a lot of minor cosmetic modifications.
11 Fix major bugs caused by introduction of DN60 support
12 Add the operator command processor for DN60 remote stations
13 For DN60 card readers, after sleeping for 3 seconds following
an offline condition, when we wake up clear the offline flag
so that we perform another scheduling pass.
14 Change the IPCF send/recieve quotas from max to 20.
15 Change the DN60 open code to support the new port/line handles.
16 Fix a bug which would enable -20 CDRIVE to miss an IPCF interrupt
17 Fix a bug so that the correct error text is displayed on fork
termination
20 Delete the Send/Receive Quotas from the PIB.
21 Make a check for Non-Existant Readers in the Tops20 Open Routine.
22 Delete the call to F%FCHN and use the stream number as the channel
number (TOPS10 Only)
23 Fix a Bug - Move the code to close the spool file to CREATE.
24 Add DN60 line conditioning support.
25 Don't interrupt the superior when re-initing the reader for device EOF.
26 At last, finish up DN60 changes. Delete DB entry .RDCND and replace
it with .RDSUP in which we will now store the SETUP message.
Change the calling parms for D60CND to use the SETUP message
instead of .RDCND
Change all references to .RDCND to .RDSUP
27 Add support for Node-Went-Away message.
30 Fix a bug affecting the -10 only. In SETUP, SETZM the FLAG word
after setting up the card reader data base.
31 Change 'Cancelled' to 'Canceled'
\ ;End of Revision History
SUBTTL CARD READER DATA BASE
FILEMK==17777 ;MASK FIELD FOR FILE NAME SPEC
IBYT60==7 ;INPUT DN60 BYTES ARE ASCII
OBYT60==7 ;OUTPT DN60 BYTES ARE ASCII
IBYTSZ==^D18 ;INPUT LOCAL/DN200 BYTES ARE 16 BITS
OBYTSZ==^D18 ;OUTPT LOCAL/DN200 BYTES ARE 18 BITS
D60RCL==^D82 ;DN60 RECORD LENGTH = 80 + <CRLF>
LOCRCL==^D80 ;LOCAL/DN200 RECORD LENGTH = 80
MAXRDR==^D15 ;MAXIMUM NUMBER OF READERS
PDSIZE==100 ;PDL SIZE
MSBSIZ==30 ;MESSAGE BUFFER SIZE
;AC USAGE
M==13 ;INCOMMING IPCF MESSAGE ADDRESS
RDR==14 ;RDR DATA BASE
AP==15 ;POINTER TO BYTE TRANSLATION TABLE
FLAG==16 ;AC 16 HOLD FLAGS
;STREAM STATUS BITS
JOBCD==1B1 ;JOB CARD READ AND JOB SETUP
INTRPT==1B2 ;READER IS CONNECTED TO INTRPT SYSTEM
ABORT==1B3 ;STREAM ABORT BIT.
GOODBY==1B4 ;STREAM IS ON ITS WAY OUT
CD20==1B6 ;READER LINE IS CD20
EOF==1B8 ;AN EOF CONDITION OCCURED
SYSPRM FDSIZE,FDMSIZ,10 ;SPOOL FILE FD SIZE
SYSPRM CRDNBR,5,5 ;NBR OF CARDS TO BE PROCESSED AT A TIME
SYSPRM BUFSIZ,<<CRDNBR*LOCRCL>/2>,<<<CRDNBR+1>*LOCRCL>/2> ;BUFFER SIZE
SYSPRM DBSIZE,2,1 ;DYNAMIC DATA BASE SIZE (IN PAGES)
DEFINE GETBYT(AC,PTR),<ILDB AC,PTR
XLIST
ANDI AC,7777
LIST
> ;END GETBYT
SUBTTL LOCAL, DN200, & DN60 BYTE DEFINITIONS
LOC 0
JIMGUC:! BLOCK 1 ;UPPER CASE CHARACTER 'J'
JIMGLC:! BLOCK 1 ;LOWER CASE CHARACTER 'j'
OIMGUC:! BLOCK 1 ;UPPER CASE CHARACTER 'O'
OIMGLC:! BLOCK 1 ;LOWER CASE CHARACTER 'o'
BIMGUC:! BLOCK 1 ;UPPER CASE CHARACTER 'B'
BIMGLC:! BLOCK 1 ;LOWER CASE CHARACTER 'b'
DIMGUC:! BLOCK 1 ;UPPER CASE CHARACTER 'D'
DIMGLC:! BLOCK 1 ;LOWER CASE CHARACTER 'd'
EIMGUC:! BLOCK 1 ;UPPER CASE CHARACTER 'E'
EIMGLC:! BLOCK 1 ;LOWER CASE CHARACTER 'e'
$IMAGE:! BLOCK 1 ;CHARACTER '$'
BLANK:! BLOCK 1 ;CHARACTER ' '
ENDIMG:! BLOCK 1 ;END OF JOB CHARACTER
IMGLEN:! ;BLOCK LENGTH
RELOC
;DEFINE THE CHARACTER CODES FOR LOCAL AND DN200
LOC200: $BUILD IMGLEN
$SET(JIMGUC,,2400) ;IMAGE MODE 'J'
$SET(JIMGLC,,6400) ;IMAGE MODE 'j'
$SET(OIMGUC,,2010) ;IMAGE MODE 'O'
$SET(OIMGLC,,6010) ;IMAGE MODE 'o'
$SET(BIMGUC,,4200) ;IMAGE MODE 'B'
$SET(BIMGLC,,5200) ;IMAGE MODE 'b'
$SET(DIMGUC,,4040) ;IMAGE MODE 'D'
$SET(DIMGLC,,5040) ;IMAGE MODE 'd'
$SET(EIMGUC,,4020) ;IMAGE MODE 'E'
$SET(EIMGLC,,5020) ;IMAGE MODE 'e'
$SET($IMAGE,,2102) ;IMAGE MODE '$'
$SET(BLANK,,00000) ;IMAGE MODE ' '
$SET(ENDIMG,,7417) ;IMAGE MODE FOR END OF JOB
$EOB
;DEFINE THE CHARACTER CODES FOR THE DN60
CHAR60: $BUILD IMGLEN
$SET(JIMGUC,,112) ;ASCII MODE 'J'
$SET(JIMGLC,,152) ;ASCII MODE 'j'
$SET(OIMGUC,,117) ;ASCII MODE 'O'
$SET(OIMGLC,,157) ;ASCII MODE 'o'
$SET(BIMGUC,,102) ;ASCII MODE 'B'
$SET(BIMGLC,,142) ;ASCII MODE 'b'
$SET(DIMGUC,,104) ;ASCII MODE 'D'
$SET(DIMGLC,,144) ;ASCII MODE 'd'
$SET(EIMGUC,,105) ;ASCII MODE 'E'
$SET(EIMGLC,,145) ;ASCII MODE 'e'
$SET($IMAGE,,44) ;ASCII MODE '$'
$SET(BLANK,,40) ;ASCII MODE ' '
$SET(ENDIMG,,177) ;ASCII MODE FOR END OF JOB
$EOB
SUBTTL CARD READER DATA BASE
PHASE 0
.RDIPT:! BLOCK 1 ;CARD BUFFER BYTE POINTER
.RDOPT:! BLOCK 1 ;OUTPUT BUFFER POINTER
.RDCAD:! BLOCK 1 ;CARD ADDRESS WITHIN INPUT BUFFER
.RDNBR:! BLOCK 1 ;NUMBER OF CARDS IN THE BUFFER.
.RDSTR:! BLOCK 1 ;READER STREAM NUMBER
.RDBFR:! BLOCK 1 ;READER BUFFER ADDRESS.
.RDSTA:! BLOCK 1 ;DEVICE STATUS WORD
.RDTIM:! BLOCK 1 ;JOB START TIME
.RDINI:! BLOCK 1 ;END RDR INITIALIZATION FLAG
.RDSUP:! BLOCK SUP.SZ ;DEVICE SETUP MESSAGE
.RDREM:! BLOCK 1 ;0=LOCAL,-1=DN200 REMOTE,+1=DN60 REMOTE
.RDOPB:! BLOCK OP$SIZ ;DN60 DEVICE OPEN BLOCK
.RDFLG:! BLOCK 1 ;FLAG WORD FOR DN60
.RDN60:! BLOCK 1 ;HASP CONSOLE INPUT JFN
.RDECT:! BLOCK 1 ;DEVICE ERROR COUNT
.RDIBZ:! BLOCK 1 ;INPUT BYTE SIZE WE'RE PROCESSING
.RDOBZ:! BLOCK 1 ;OUTPT BYTE SIZE WE'RE PROCESSING
.RDRCL:! BLOCK 1 ;RECORD SIZE WE ARE PROCESSSING
.RDREG:! BLOCK 20 ;STREAM AC SAVE AREA
.RDPDL:! BLOCK PDSIZE ;STREAM CONTEXT PDL.
.RDIOA:! BLOCK 1 ;INTERRUPT RETURN ADDRESS.
.CARDS:! BLOCK BUFSIZ ;BUFFER AREA
.RDFD:! BLOCK FDSIZE ;FILE DESCRIPTOR FOR SPOOL FILE
.RDFOB:! BLOCK 4 ;FILE OPEN BLOCK FOR GLXFIL
.RDIFN:! BLOCK 1 ;GALAXY IFN FOR SPOOL FILE.
.RDJBT:! BLOCK 1 ;COUNT OF CARDS IN DECK
.RDJBC:! BLOCK 1 ;COUNT OF TOTAL JOB CARDS FOUND
.RDEOJ:! BLOCK 1 ;COUNT OF TOTAL EOJ CARDS
.RDEND:! BLOCK 1 ;COUNT OF TOTAL END CARDS
.RDREJ:! BLOCK 1 ;COUNT OF REJECTED CARDS
.RDIPC:! BLOCK 1 ;IPCF MESSAGES SENT
.RDSHT:! BLOCK 1 ;SHUTDOWN FLAG -1=SHUTDOWN THE READER
TOPS10 <
.RDBLK:! BLOCK 3 ;TOPS-10 OPEN BLOCK.
.RDIOB:! BLOCK 0 ;CDR BUFFER CONTROL BLOCK.
.RDBUF:! BLOCK 1 ;CDR BUFFER ADDRESS
.RDBPT:! BLOCK 1 ;CDR BYTE POINTER.
.RDBCT:! BLOCK 1 ;CDR BUFFER LENGTH
.RDUDX:! BLOCK 1 ;CARD READER UDX
.RDCHN:! BLOCK 1 ;CDR CHANNEL #
.RDUNT:! BLOCK 1 ;READER UNIT NUMBER
.RDDEV:! BLOCK 1 ;CARD READER DEVICE NUMBER
> ;END TOPS10 CONDITIONAL
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
TOPS20 <
.RDHND:! BLOCK 1 ;INFERIOR PROCESS HANDLE
.RDJFN:! BLOCK 1 ;READER JFN
.RDRFD:! BLOCK 5 ;READER FILE DESCRIPTOR
.RDOFL:! BLOCK 1 ;ONLINE/OFFLINE FLAG (0=ON, -1=OFF)
.RDSTP:! BLOCK 10 ;ERROR MESSAGE BUFFER
.RDSAB:! BLOCK SAB.SZ ;IPCF SAB BLOCK
.RDMSG:! BLOCK MSBSIZ ;IPCF MESSAGE BUFFER
.RDSTS:! BLOCK 1 ;FLAG -1=SEND STATUS UPDT MSG
.RDCAN:! BLOCK 1 ;CANCEL FLAG -1=CANCEL CURRENT JOB
> ;END TOPS20 CONDITIONAL
DEPHASE
SUBTTL Random Impure Storage
PDL: BLOCK PDSIZE ;PUSHDOWN LIST
MESSAG: BLOCK 1 ;ADDRESS OF MESSAGE JUST RECEIVED
SAB: BLOCK SAB.SZ ;A SEND ARGUMENT BLOCK
MSGBLK: BLOCK MSBSIZ ;A BLOCK TO BUILD MESSAGES IN.
BYTPTR: BLOCK 1 ;BYTE POINTER FOR $TEXT ROUTINE
SCHEDL: BLOCK 1 ;STREAM SCHEDULING DATA
CNTSTA: BLOCK 1 ;NUMBER OF THE CENTRAL STATION
RUTINE: BLOCK 1 ;MESSAGE PROCESSING ROUTINE ADDRESS.
NOSAVE: BLOCK 1 ;INDICATOR 0=SAVE FLAG BITS, -1=DONT.
FILENM: BLOCK 1 ;READER SPOOL FILE HASH CODE
FILEXT: 0,,1 ;READER SPOOL FILE EXTENSION
SPOOL: BLOCK 1 ;SPOOL STRUCTURE PPN
PRGSTA: BLOCK 1 ;SPOOLER START ADDRESS (PAGE NUMBER)
RDRSIZ: BLOCK 1 ;SPOOLER LENGTH IN PAGES
TRMFRK: BLOCK 1 ;FORK TERMINATION FLAG
FRKINI: BLOCK 1 ;END FORK INITIALIZATION FLAG
SUBTTL Resident JOB Database
STREAM: BLOCK 1 ;CURRENT STREAM NUMBER
JOBPAG: BLOCK MAXRDR ;ADDRESS OF A TWO PAGE BLOCK
JOBOBA: BLOCK MAXRDR ;TABLE OF OBJECT BLOCK ADDRESSES
JOBSTW: BLOCK MAXRDR ;JOB STATUS WORD
JOBSTS: BLOCK MAXRDR ;STATUS UPDATE FLAG 0=NO,-1=YES
JOBOBJ: BLOCK 3*MAXRDR ;LIST OF SETUP OBJECTS
SUBTTL GLXLIB IB AND HELLO MESSAGE STRUCTURES
TOPS10 <INTVEC==VECTOR>
TOPS20 <INTVEC==:LEVTAB,,CHNTAB>
IB: $BUILD IB.SZ ;
$SET (IB.PRG,,%%.MOD) ;PROGRAM 'CDRIVE'
$SET (IB.FLG,IP.STP,1) ;STOPCODES TO ORION
$SET (IB.PIB,,PIB) ;SET UP PIB ADDRESS
$SET (IB.INT,,INTVEC) ;SETUP INTERRUPT VECTOR ADDRESS
$EOB ;
PIB: $BUILD PB.MNS ;
$SET (PB.HDR,PB.LEN,PB.MNS) ;PIB LENGTH,,0
$SET (PB.FLG,IP.PSI,1) ;PSI ON
$SET (PB.INT,IP.CHN,0) ;INTERRUPT CHANNEL
$SET (PB.SYS,IP.MNP,^D20) ;MAX NUMBER OF PIDS
$EOB ;
HELLO: $BUILD HEL.SZ
$SET(.MSTYP,MS.TYP,.QOHEL) ;MESSAGE TYPE
$SET(.MSTYP,MS.CNT,HEL.SZ) ;MESSAGE LENGTH
$SET(HEL.NM,,<'CDRIVE'>) ;PROGRAM NAME
$SET(HEL.FL,HEFVER,%%.QSR) ;QUASAR VERSION
$SET(HEL.NO,HENNOT,1) ;NUMBER OF OBJ TYPES
$SET(HEL.NO,HENMAX,MAXRDR) ;MAX NUMBER OF JOBS
$SET(HEL.OB,,.OTRDR) ;RDR OBJECT TYPE
$EOB
;SCHEDULER FLAGS
PSF%ID==1B1 ;INPUT DONE WAIT
PSF%DO==1B2 ;DEVICE IS OFF-LINE
PSF%ST==1B3 ;STOPPED BY OPERATOR
PSF%SH==1B4 ;SHUT DOWN A CARD READER
SUBTTL CDRIVE - Multiple card reader spooler.
CDRIVE: RESET ;AS USUAL.
MOVE P,[IOWD PDSIZE,PDL] ;SET UP THE STACK.
MOVEI S1,IB.SZ ;GET THE IB SIZE.
MOVEI S2,IB ;ADDRESS OF THE IB.
PUSHJ P,I%INIT ;SET UP THE WORLD.
PUSHJ P,RDINIT ;GO SETUP READER CONSTANTS
PUSHJ P,INTINI ;SET UP THE INTERRUPT SYSTEM.
PUSHJ P,I%ION ;TURN ON INTERRUPTS.
PUSHJ P,I%NOW ;GET THE DATE/TIME
MOVEM S1,FILENM ;SAVE IT AS THE SPOOL FILE HASH CODE
MOVEI S1,HELLO ;GET ADDRESS OF HELLO MESSAGE.
MOVEI S2,HEL.SZ ;GET LENGTH OF HELLO IN S2
PUSHJ P,SNDQSR ;SAY HI TO QUASAR.
MOVSI P1,-MAXRDR ;SET UP STREAM COUNTER.
JRST MAIN ;GO TO SCHEDULING LOOP
SUBTTL Idle Loop
TOPS10 <
MAIN: SKIPN JOBPAG(P1) ;IS THE STREAM ACTIVE ???
JRST MAIN.2 ;NO,,GET THE NEXT STREAM.
HRRZM P1,STREAM ;RUNNABLE STREAM!!!
MOVE RDR,JOBPAG(P1) ;YES, GET JOB PAGE
SKIPE JOBSTS(P1) ;WANT TO SEND STATUS INFO ???
PUSHJ P,UPDTST ;GO UPDATE AND SEND STATUS INFORMATION
SKIPE JOBSTW(P1) ;IS THE STREAM WAITING ???
JRST MAIN.2 ;YES,,GET THE NEXT STREAM.
MOVEM P1,SCHEDL ;SAVE THE SCHEDULING STREAM.
MOVSI 17,.RDREG(RDR) ;ELSE SETUP TO RESTORE
BLT 17,17 ; SOME ACS
MOVE S1,.RDNBR(RDR) ;GET # OF CARDS IN TEMP BUFFER
CAIL S1,CRDNBR ;HAVE WE READ ENOUGH ???
PUSHJ P,READER ;YES,,GO PROCESS THE CARDS
SKIPE .RDSHT(RDR) ;IS A SHUTDOWN SCHEDULED ???
TXNE FLAG,JOBCD ;YES,,ARE WE PROCESSING A JOB ???
POPJ P, ;YES,,JUST RETURN
PUSHJ P,SHUTIT ;TIME TO SHUTDOWN,,SO DO IT !!!
MAIN.1: MOVE P1,SCHEDL ;GET THE LAST SCHEDULED STREAM.
MAIN.2: AOBJN P1,MAIN ;LOOP BACK FOR SOME MORE.
PUSHJ P,CHKQUE ;CHECK FOR INCOMMING MESSAGES.
MOVEI S1,^D60 ;SLEEP FOR 60 SECONDS.
SKIPN MESSAGE ;IF WE PROCESSED A MESSAGE,,RESCHEDULE.
PUSHJ P,I%SLP ;ELSE,,GO WAIT
MOVE P,[IOWD PDSIZE,PDL] ;RESET THE STACK POINTER.
MOVSI P1,-MAXRDR ;GET LOOP AC.
JRST MAIN ;KEEP ON PROCESSING.
SENDIT: JRST SNDQSR ;SLIGHT CROCK FOR -10/-20 COMPATABILITY
SNDOPR: JRST OPRMSG ;HERE ALSO
SUBTTL OACCAN - Operator CANCEL request.
OACCAN: MOVE S1,STREAM ;GET THE STREAM NUMBER
TXZE FLAG,JOBCD ;TELL READER WE ARE LEAVING.
$ACK (Current Job Aborted,,@JOBOBA(S1),.MSCOD(M))
$RETT
SUBTTL OACPAU - Operator PAUSE Request
OACPAU: MOVX S2,PSF%ST ;GET THE STOPPED BITS
MOVE S1,STREAM ;GET THE STREAM NUMBER
IORM S2,JOBSTW(S1) ;LITE THE STOPPED BITS.
SETOM JOBSTS(S1) ;SEND STATUS TO QUASAR NEXT SCHD PASS
$ACK (Stopped,,@JOBOBA(S1),.MSCOD(M)) ;TELL THE OPERATOR WHAT HE DID
$RETT ;AND RETURN.
SUBTTL OACCON - Operator CONTINUE Request
OACCON: MOVX S2,PSF%ST ;GET THE STOPPED BITS.
MOVE S1,STREAM ;GET THE STREAM NUMBER.
ANDCAM S2,JOBSTW(S1) ;DE-LITE THE STOPPED BITS.
SETOM JOBSTS(S1) ;SEND STATUS TO QUASAR NEXT SCHD PASS
$ACK (Continued,,@JOBOBA(S1),.MSCOD(M)) ;TELL THE OPR WHAT HE DID.
$RETT ;AND RETURN.
SUBTTL OACSHT - ROUTINE TO VALIDATE THE READER SHUTDOWN STATUS
OACSHT: TXNN FLAG,JOBCD ;ARE WE PROCESSING A JOB ???
$RETT ;NO,,THEN SHUTDOWN IS OK.
SETOM .RDSHT(RDR) ;YES,,LITE DEFERED SHUTDOWN FLAG
$RETF ;AND RETURN (NO SHUTDOWN)
SUBTTL RDINIT - ROUTINE TO INITIALIZE SOME READER CONSTANTS
RDINIT: PUSHJ P,I%HOST ;GET OUR SITE ID
MOVEM S2,CNTSTA ;SAVE AS OUR CENTRAL SITE NUMBER
MOVX S1,%LDQUE ;GET THE GETTAB PPN CODE
GETTAB S1, ;GET THE SPOOL PPN
$STOP (CGS,Cannot Get Spool File PPN)
MOVEM S1,SPOOL ;SAVE IT
$RETT ;RETURN
SUBTTL DOJOB - ROUTINE TO PROCESS THE CARD READERS.
DOJOB: HRLZ S1,.RDOBZ(RDR) ;GET THE OUTPUT BYTE SIZE
LSH S1,6 ;POSITION IT
ADD S1,[POINT 0,.CARDS(RDR)] ;MAKE THE BYTE POINTER
MOVEM S1,.RDOPT(RDR) ;AND SAVE IT.
MOVE S1,SPOOL ;GET THE SPOOL PPN
MOVEM S1,.RDFD+.FDPPN(RDR) ;SAVE IT
MOVX S1,FSSSTR ;GET THE SPOOL STRUCTURE NAME
MOVEM S1,.RDFD+.FDSTR(RDR) ;SAVE IT
MOVEI S1,FDSIZE ;GET THE FD SIZE
STORE S1,.RDFD+.FDLEN(RDR),FD.LEN ;SAVE IT
MOVEI S1,.RDFD(RDR) ;GET THE FD ADDRESS
MOVEM S1,.RDFOB+FOB.FD(RDR) ;SAVE IT
MOVE S1,.RDOBZ(RDR) ;GET THE BYTE SIZE
STORE S1,.RDFOB+FOB.CW(RDR),FB.BSZ ;SAVE IT
MOVEI S1,1 ;GET A BIT
STORE S1,.RDFOB+FOB.CW(RDR),FB.NFO ;WANT 'NEW FILE ONLY'
CARDS: PUSHJ P,INCARD ;GET SOME CARDS
JUMPF CRDEOF ;NO MORE,,FINISH UP.
PUSHJ P,PRORDR ;GO PROCESS THE DATA CARDS.
JRST CARDS ;AND GET SOME MORE.
CRDEOF: MOVE S1,ENDIMG(AP) ;GET THE EOF CARD BITS
IDPB S1,.RDOPT(RDR) ;PUT IT IN THE BUFFER
TXO FLAG,EOF ;TURN ON EOF INDICATOR
PUSHJ P,READER ;GO FINISH UP THIS FILE
JRST CARDS ;GO LOOK FOR MORE CARDS.
SUBTTL Deschedule Process
DEFINE $DSCHD(FLAGS),<
PUSHJ P,DSCHD
XLIST
JUMP [EXP FLAGS]
LIST
SALL
> ;END DEFINE $DSCHD
;DSCHD is called by the $DSCHD macro to cause the "current" stream to
; be un-scheduled. The call is:
;
; $DSCHD(flags)
;
;which generates:
;
; PUSHJ P,DSCHD
; JUMP [EXP flags]
DSCHD: MOVEM 0,.RDREG(RDR) ;SAVE AC 0
MOVEI 0,.RDREG+1(RDR) ;PLACE TO PUT AC 1
HRLI 0,1 ;SETUP THE BLT POINTER
BLT 0,.RDREG+17(RDR) ;SAVE AWAY THE ACS
HRRZ S1,0(P) ;GET ADDRESS OF "JUMP [FLAGS]"
MOVE S1,@0(S1) ;GET THE FLAGS
MOVE S2,STREAM ;GET THE STREAM NUMBER
IORM S1,JOBSTW(S2) ;SET THE FLAGS
MOVE P,[IOWD PDSIZE,PDL] ;RESET THE STACK POINTER.
JRST MAIN.1 ;AND CONTINUE SCHEDULING.
SUBTTL PRORDR--READER INPUT PROCESSING
PRORDR: TXNE FLAG,CD20 ;IS THIS A CD20 LINE ???
JRST PROR.4 ;YES,,DO IT DIFFERENTLY
HLLZ P1,.RDBPT(RDR) ;SAVE READERS BYTE SIZE.
MOVEI S1,1400 ;GEN A 12 BIT BYTE SIZE.
SKIPE .RDREM(RDR) ;IS THIS A REMOTE READER ???
ADDI S1,440000 ;IF SO, ADD BYTE POSITION.
HRLM S1,.RDBPT(RDR) ;CREATE A NEW BYTE POINTER.
AOS .RDBPT(RDR) ;POINT TO ACTUAL DATA.
PROR.1: SKIPE .RDREM(RDR) ;IF A LOCAL READER,,SKIP THIS
ILDB T1,.RDBPT(RDR) ;PICK UP A REMOTE CHARACTER.
SKIPN .RDREM(RDR) ;IF A REMOTE READER,,SKIP THIS
LDB T1,.RDBPT(RDR) ;PICK UP A LOCAL BYTE.
JUMPE T1,PROR.2 ;IF A BLANK,,SKIP THIS.
LDB S1,[POINT 7,T1,33] ;GET CDR COLS 1-7.
LSH S1,35 ;LEFT JUSTIFY THOSE BITS.
JFFO S1,.+2 ;GET # OF LEADING 0 BITS.
JRST PROR.2 ;NOTHING THERE,,SO SKIP THIS
ADDI S2,1 ;ADD 1 TO 0 BIT COUNT.
LSH S1,1(S2) ;SHIFT THEM OUT + 1.
SKIPE S1 ;IF S1=0, THEN NO READER ERROR.
ADDI S2,10 ;ELSE TURN ON ERROR BIT.
LSH S2,^D12 ;SHIFT TO CORRECT BIT POSITION.
ADD T1,S2 ;MERGE INTO CORRECTED WORD.
PROR.2: IDPB T1,.RDOPT(RDR) ;AND SAVE THE RESULTING 18 BIT BYTE.
SKIPN .RDREM(RDR) ;IF THIS IS A LOCAL READER, THEN
AOS .RDBPT(RDR) ; ADD 1 TO INPUT ADDRESS.
SOSLE .RDBCT(RDR) ;SUBTRACT 1 FROM BYTE COUNT
JRST PROR.1 ;AND GO PROCESS THE NEXT BYTE.
HLLM P1,.RDBPT(RDR) ;RESTORE ORIGIONAL BYTE SIZE.
PROR.3: AOS S1,.RDNBR(RDR) ;BUMP THE NUMBER OF CARDS BY 1
CAIL S1,CRDNBR ;HAVE WE TRANSLATED ENOUGH YET ???
PUSHJ P,READER ;YES,,GO PROCESS THEM
POPJ P, ;RETURN TO MAIN PROGRAM
PROR.4: MOVE T1,.RDRCL(RDR) ;GET THE BYTE COUNT
HRRZ T2,.RDBPT(RDR) ;GET THE INPUT BUFFER ADDRESS
ADD T2,[POINT 16,1] ;CREATE THE BYTE POINTER
PROR.5: ILDB S1,T2 ;GET AN INPUT BYTE
IDPB S1,.RDOPT(RDR) ;PUT IT OUT
SOJG T1,PROR.5 ;MORE??,,KEEP PROCESSING
JRST PROR.3 ;GO FINISH UP
SUBTTL INCARD - ROUTINE TO READ CARDS FROM THE CARD READER.
INCARD: MOVE S1,.RDCHN(RDR) ;GET THE READERS CHANNEL.
TLO S1,(IN 0,0) ;CREATE AN INPUT UUO.
XCT S1 ;READ SOME DATA CARDS.
$RETT ;NORMAL RETURN,,RETURN OK.
INERR: MOVE S1,.RDCHN(RDR) ;GET THE CHANNEL NUMBER.
IOR S1,[GETSTS .RDSTA(RDR)] ;CREATE A GETSTS UUO.
XCT S1 ;GET THE DEVICE STSTUS.
MOVE S1,.RDSTA(RDR) ;LOAD IT HERE ALSO.
TXNE S1,IO.ERR ;WAS THERE AN ERROR ???
JRST INER.1 ;YES,,GO PROCESS IT.
$DSCHD(PSF%ID) ;BLOCK STREAM FOR INPUT DONE
JRST INCARD ;AND GO TRY AGAIN
INER.1: TXNE S1,IO.EOF ;WAS THE ERROR EOF ???
$RETF ;YES,,RETURN NO MORE DATA.
TRZ S1,IO.ERR ;CLEAR ERROR BITS.
HRLI S1,(SETSTS 0,0) ;CREATE SETSTS UUO.
ADD S1,.RDCHN(RDR) ;ADD THE CHANNEL NUMBER.
XCT S1 ;CLEAR THE ERROR BITS IN STATUS WORD.
JRST INCARD ;OK,,RETRY THE READ.
SUBTTL INPGET -- OPEN the input device
INPGET: SETOM .RDCHN(RDR) ;INDICATE NO OUTPUT CHANNEL YET.
PUSHJ P,GENDEV ;CREATE THE PHYSICAL DEVICE NAME.
MOVEM S1,.RDDEV(RDR) ;AND SAVE IT
MOVX T1,UU.AIO+IO.SIM+.IOIMG ;GET OPEN FLAG BITS.
MOVE T2,.RDDEV(RDR) ;OUTPUT DEVICE NAME
MOVEI T3,.RDIOB(RDR) ;BUFFER HEADER
MOVE S1,STREAM ;USE OUR STREAM NUMBER AS THE CHANNEL #
LSH S1,^D23 ;SHIFT IT TO ITS PROPER POSITION.
MOVEM S1,.RDCHN(RDR) ;SAVE IT FOR LATER
IOR S1,[OPEN T1] ;MAKE IT AN INSTRUCTION
XCT S1 ;AND EXECUTE IT
JRST OUTDNA ;LOSE GIVE ERROR
MOVE S2,STREAM ;AND STREAM NUMBER
MOVE S1,OBJ.UN(S2) ;GET THE UNIT NUMBER
MOVEM S1,.RDUNT(RDR) ;AND SAVE IT FOR CDRIVE
SETZM JOBSTW(S2) ;CLEAR THE STREAM STATUS BITS.
MOVE T1,.RDCHN(RDR) ;NO, GET THE CHANNEL
LSH T1,-^D23 ;PUT IT IN THE RIGHT POSITION.
WHERE T1, ;GET THE LOCATION
SETZ T1, ;ASSUME STATION 0
TLZ T1,-1 ;CLEAR STATION FLAGS
CAME T1,CNTSTA ;IS IT THE CENTRAL STATION?
SETOM .RDREM(RDR) ;NO,,MAKE IT REMOTE
MOVEI T1,.DFHCW ;GET READER HARDWARD CHARACTERISTICS
MOVE T2,.RDDEV(RDR) ;FOR THIS READER
MOVE S1,[2,,T1] ;SET UP DEVOP. PARAMETER LIST
DEVOP. S1, ;GET CHARACTERISTICS...
$STOP (CGC,Cannot Get Reader Hardware Characteristics)
LOAD S2,S1,DF.CLS ;GET THE LINE TYPE
CAXN S2,.DFS20 ;IS IT A CD20 LINE ???
TXO FLAG,CD20 ;YES,,SET IT.
MOVE S1,.RDBFR(RDR) ;GET THE READERS BUFFER ADDRESS.
EXCH S1,.JBFF ;MAKE IT OUT END ADDRESS.
MOVE S2,.RDCHN(RDR) ;GET THE CHANNEL NUMBER
IOR S2,[INBUF CRDNBR] ;MAKE AN INSTRUCTION
XCT S2 ;AND CREATE 'CRDNBR' BUFFERS
MOVEM S1,.JBFF ;RESTORE JOBFF
JRST OUTSOK ;AND CONTINUE ON
GENDEV: MOVE T1,STREAM ;PICK UP STREAM NUMBER.
MOVE T1,JOBOBA(T1) ;PICK UP OBJECT BLOCK ADDRESS.
MOVE S1,OBJ.ND(T1) ;PICK UP THE NODE NUMBER.
IDIVI S1,10 ;SPLIT IT IN HALF.
IMULI S1,100 ;SHIFT LEFT 2 DIGITS.
ADD S1,S2 ;ADD SECOND NODE DIGIT.
IMULI S1,100 ;SHIFT LEFT ANOTHER 2 DIGITS.
ADD S1,OBJ.UN(T1) ;ADD THE UNIT NUMBER.
ADD S1,[SIXBIT/CDR000/] ;CREATE THE PHYSICAL DEVICE NAME.
POPJ P, ;RETURN. . . . .
SUBTTL GENFIL - ROUTINE TO GENERATE THE SPOOL FILENAME
GENFIL: PUSH P,T1 ;SAVE T1
MOVE S1,[POINT 6,.RDFD+.FDNAM(RDR)] ;BYTE PTR FOR FILENAME
MOVEM S1,BYTPTR ;SAVE IT.
$TEXT (CV26BT,<RD^D4L0/FILENM,FILEMK/>) ;CREATE THE SPOOL FILE NAME
AOS FILENM ;CREATE ANOTHER
SETZM .RDFD+.FDEXT(RDR) ;ZERO THE FILENAME EXT.
MOVE S1,FILEXT ;GET THE EXTENSION NUMBER
IDIVI S1,100 ;GET THE THIRD DIGIT
ADDI S1,20 ;MAKE IT SIXBIT.
LSH S1,6 ;SHIFT IT OVER
IDIVI S2,10 ;GET SECOND AND FIRST DIGITS
ADDI S2,20 ;MAKE IT SIXBIT
ADDI T1,20 ;HERE ALSO
ADD S1,S2 ;PUT INTO S1
LSH S1,6 ;SHIFT IT OVER
ADD S1,T1 ;ADD FIRST DIGIT
HRLZM S1,.RDFD+.FDEXT(RDR) ;SAVE IT AS FILE EXT
POP P,T1 ;RETSORE T1
$RETT ;AND RETURN
CV26BT: SUBI S1,40 ;CONVERT TO SIXBIT
ANDI S1,77 ;JUST USE LAST 2 DIGITS
IDPB S1,BYTPTR ;SAVE THE BYTE
$RETT ;AND RETURN
OUTSOK: PUSHJ P,INTCNL ;CONNECT UP THE READER
TXO FLAG,INTRPT ;TURN ON CONNECTED FLAG
MOVE S1,STREAM ;GET THE STREAM NUMBER
$WTO (Started,,@JOBOBA(S1)) ;TELL OPERATOR WE'RE STARTED
MOVX S1,%RSUOK ;LOAD THE CODE
$RETT ;AND RETURN
OUTDNA: MOVE S1,STREAM ;GET THE STREAM NUMBER
$WTO (Not available right now,,@JOBOBA(S1)) ;TELL THE OPERATOR
MOVX S1,%RSUNA ;NOT AVAILABLE RIGHT NOW
$RETF ;AND RETURN
OUTDDE: MOVE S1,STREAM ;GET THE STREAM NUMBER
$WTO (Does not exist,,@JOBOBA(S1)) ;TELL THE OPERATOR
MOVX S1,%RSUDE ;NEVER AVAILABLE
$RETF ;RETURN
SUBTTL INPREL - ROUTINE TO RELEASE A CARD READER
INPREL: TXZE FLAG,INTRPT ;ARE WE CONNECT TO THE INTRPT SYSTEM ??
PUSHJ P,INTDCL ;REMOVE THE READER FROM THE INTRPT SYS
SKIPGE S1,.RDCHN(RDR) ;DID WE INIT A CHANNEL ???
$RETT ;NO,,JUST RETURN
LSH S1,-^D23 ;GET THE CHANNEL NUMBER
RESDV. S1, ;RESET THE CHANNEL
POPJ P, ;IGNORE ERRORS
POPJ P, ;RETURN IF NORMAL
SUBTTL Interrupt Module
; INTINI INITIALIZE INTERRUPT SYSTEM
; INTCNL CONNECT THE CARD READER
; INTDCL DISCONNECT THE CARD READER
; INTIPC INTERRUPT ROUTINE -- IPCF
;INTERRUPT SYSTEM DATABASE
VECTOR: BLOCK 0 ;BEGINNING OF INTERRUPT VECTOR
VECIPC: BLOCK 4 ;IPCF INTERRUPT BLOCK
VECDEV: BLOCK 4*MAXRDR ;DEVICE INTERRUPT BLK
ENDVEC==.-1 ;END OF INTERRUPT VECTOR
DEFINE CDINHD(Z),<
XLIST
$BGINT 1,
MOVEI S1,Z
MOVEI S2,VECDEV+<4*Z>
JRST CDINTR
CDHDSZ==4
LIST
> ;END DEFINE CDINHD
INTINI: MOVEI S1,INTIPC ;GET ADDRESS OF IPCF INT RTN
MOVEM S1,VECIPC+.PSVNP ;SAVE IN VECTOR
Z==0
REPEAT MAXRDR,<XLIST
MOVEI S1,INTDEV+<CDHDSZ*Z> ;GET ADDRESS OF RDR HEADER
MOVEM S1,VECDEV+<4*Z>+.PSVNP ;STORE IN THE VECTOR
Z==Z+1
LIST
> ;END REPEAT MAXRDR
POPJ P, ;AND RETURN
INTDCL: SKIPA S1,[PS.FRC+T1] ;REMOVE CONDITION USINGS ARGS IN T1
INTCNL: MOVX S1,PS.FAC+T1 ;ADD CONDITION USING ARGS IN T1
MOVE T1,.RDCHN(RDR) ;USE CHANNEL AS CONDTION
LSH T1,-^D23 ;MAKE IT RIGHT !!!
MOVE T2,STREAM ;GET STREAM NUMBER
IMULI T2,4 ;GET BLOCK OFFSET
ADDI T2,VECDEV-VECTOR ;GET OFFSET FROM BEGINNING
HRLZS T2 ;GET OFFSET,,0
HRRI T2,PS.RID+PS.RDO+PS.ROL ;AND CONDITIONS
SETZ T3, ;ZERO T3
PISYS. S1, ;TO THE INTERRUPT SYSTEM
$STOP (CAD,CANNOT ADD/DELETE READER TO/FROM INTERRUPT SYSTEM)
POPJ P, ;AND RETURN
;Here on device interrupts on the -10. This routine consists of multiple
; interrupt headers (one for each stream) which load S1 and S2 and
; call the main interrupt body, CDINTR. Note that on the -10, while
; it is assumed that 'input done' and 'on-line' interrupts can happen
; anytime and anywhere, it is also assumed that 'device off-line'
; interrupts ONLY HAPPEN IN THE STREAM CONTEXT.
INTDEV: Z==0
REPEAT MAXRDR,<
CDINHD(Z)
Z==Z+1 >
CDINTR: MOVE RDR,JOBPAG(S1) ;GET THE JOB PARAMETER PAGE
SETOM JOBSTS(S1) ;SEND STATUS INFO BACK ON NEXT SCHD PASS
HRRZ T1,.PSVFL(S2) ;GET I/O REASON FLAGS
ANDCAM T1,.PSVFL(S2) ;AND CLEAR THEM
SETZ T2, ;CLEAR AN AC
TXNE T1,PS.ROL ;IS IT ON-LINE?
MOVX T2,PSF%DO ;YES, GET THE CORRECT FLAG
TXNE T1,PS.RID ;IS IT INPUT DONE?
TXO T2,PSF%ID ;YES, GET SCHEDULER BIT
ANDCAM T2,JOBSTW(S1) ;CLEAR THE SCHEDULER FLAGS
TXNN T1,PS.RDO ;IS IT DEVICE OFF-LINE?
$DEBRK ;NO,,DISMISS THE INTERRUPT.
TXNE T1,PS.ROL ;IF BOTH OFFLINE AND ONLINE,
$DEBRK ;DISMISS THE INTERRUPT.
MOVX T2,PSF%DO ;GET OFF-LINE BIT.
IORM T2,JOBSTW(S1) ; AND SET IT.
MOVEI T1,INPOFF ;LOAD RESTART ADDRESS
EXCH T1,.PSVOP(S2) ;STORE FOR DEBRK AND GET OLD ADRESS
MOVEM T1,.RDIOA(RDR) ;STORE OLD-ADDRESS FOR DEVICE ON AGAIN
INTDON: $DEBRK ;DISMISS THE INTERRUPT.
INPOFF: PUSH P,S1 ;SAVE S1
PUSH P,S2 ;SAVE S2
SKIPE .RDNBR(RDR) ;ANYTHING IN THE BUFFERS ???
PUSHJ P,READER ;GO PROCESS THE BUFFERS
MOVE S1,STREAM ;GET THE STREAM NUMBER
TXNE FLAG,JOBCD ;ARE WE PROCESSING A JOB ???
$WTO (Offline,,@JOBOBA(S1)) ;TELL THE OPERATOR RDR IS OFFLINE.
SKIPE S2,.RDREJ(RDR) ;ARE WE REJECTING CARDS ???
$WTO (< ^D/S2/ Cards Flushed >,,@JOBOBA(S1))
SETZM .RDREJ(RDR) ;ZERO THE REJECT COUNT
$DSCHD(0) ;WAIT FOR ONLINE INTERRUPT.
POP P,S2 ;RESTORE S2
POP P,S1 ;RESTORE S1
JRST @.RDIOA(RDR) ;CONTINUE PROCESSING.
SUBTTL INTIPC - IPCF INTERRUPT PROCESSING ROUTINE
INTIPC: $BGINT 1, ;SETUP FOR INTERRUPT
PUSHJ P,C%INTR ;FLAG THE INTERRUPT
$DEBRK ;RETURN
> ;END OF TOPS-10 CONDITIONAL CODE
SUBTTL CHKQUE - ROUTINE TO CHECK FOR IMCOMMING MESSAGES.
CHKQUE: SETZM MESSAG ;NO MESSAGE YET
PUSHJ P,C%RECV ;RECEIVE A MESSAGE
JUMPF .POPJ ;RETURN,,NOTHING THERE.
LOAD S2,MDB.SI(S1) ;GET SPECIAL INDEX WORD
TXNN S2,SI.FLG ;IS THERE AN INDEX THERE?
JRST CHKQ.1 ;NO, IGNORE IT
ANDX S2,SI.IDX ;AND OUT THE INDEX
CAIE S2,SP.OPR ;IS IT FROM OPR?
CAIN S2,SP.QSR ;IS IT FROM QUASAR?
JRST CHKQ.2 ;YES, CONTINUE ON
CHKQ.1: PUSHJ P,C%REL ;RELEASE THE MESSAGE
POPJ P, ;RETURN TO THE SCHEDULER.
CHKQ.2: LOAD S1,MDB.MS(S1),MD.ADR ;GET THE MESSAGE ADDRESS
MOVEM S1,MESSAG ;SAVE IT AWAY
MOVE M,S1 ;SAVE THE MESSAGE ADDRESS HERE TOO
LOAD S2,.MSTYP(M),MS.TYP ;GET THE MESSAGE TYPE
MOVSI S1,-NMSGT ;MAKE AOBJN POINTER FOR MSG TYPES
CHKQ.3: HRRZ T1,MSGTAB(S1) ;GET A MESSAGE TYPE
CAMN S2,T1 ;MATCH?
JRST CHKQ.4 ;YES, WIN
AOBJN S1,CHKQ.3 ;NO, LOOP
PJRST C%REL ;NO,,RELEASE THE MESSAGE
CHKQ.4: HLRZ T2,MSGTAB(S1) ;PICK UP THE PROCESSING ROUTINE ADDRESS.
MOVEM T2,RUTINE ;SAVE THE ROUTINE ADDRESS.
SETZM NOSAVE ;RESET THE FLAG SAVE FLAG WORD.
PUSHJ P,CHKOBJ ;GO FIND THE OBJECT BLOCK.
PUSHJ P,@RUTINE ;DISPATCH THE MESSAGE PROCESSOR.
SKIPN NOSAVE ;DO WE WANT TO SAVE THE FLAGS ???
MOVEM FLAG,.RDREG+FLAG(RDR) ;YES,,SAVE THE STATUS BITS.
PUSHJ P,C%REL ;RELEASE THE MESSAGE
POPJ P, ;RETURN TO THE SCHEDULER.
MSGTAB: XWD .RETT,.QORCK ;REQUEST-FOR-CHECKPOINT
XWD SETUP,.QOSUP ;SETUP/SHUTDOWN
XWD OACCON,.OMCON ;OPERATOR CONTINUE REQUEST.
XWD OACCAN,.OMCAN ;OPERATOR CANCEL REQUEST.
XWD OACPAU,.OMPAU ;OPERATOR PAUSE/STOP REQUEST.
XWD QSRNWA,.QONWA ;NODE-WENT-AWAY PROCESSOR
NMSGT==.-MSGTAB
SUBTTL - CHKOBJ - ROUTINE TO VALIDATE QUASAR/ORION/OPR MSG OBJ BLKS.
CHKOBJ: CAIE T1,.QORCK ;IS THIS A REQUEST FOR CHECKPOINT ???
CAIN T1,.QOSUP ; OR IS THIS A SETUP/SHUTDOWN MESSAGE ??
$RETT ;YES,,RETURN.
LOAD S2,.OHDRS+ARG.HD(M),AR.TYP ;PICK UP THE MSG BLK TYPE.
CAIE S2,.OROBJ ;IS IT THE OBJ BLK ???
$STOP (NFB,FIRST BLOCK IN MESSAGE NOT THE OBJECT BLOCK)
MOVEI S1,.OHDRS+ARG.DA(M) ;POINT TO THE OBJECT BLOCK.
PUSHJ P,FNDOBJ ;GO FIND THE OBJECT BLOCK.
$RETT ; AND RETURN.
SUBTTL SETUP/SHUTDOWN Message
SETUP: LOAD S1,SUP.FL(M) ;GET THE FLAGS
TXNE S1,SUFSHT ;IS IT A SHUTDOWN?
JRST SHUTDN ;IF SO,,SHUT IT DOWN !!!
SETZ T2, ;CLEAR A LOOP REG
SETU.1: SKIPN JOBPAG(T2) ;A FREE STREAM?
JRST SETU.2 ;YES!!
CAIGE T2,MAXRDR-1 ;NO, LOOP THRU THEM ALL?
AOJA T2,SETU.1 ;NO, KEEP GOING
$STOP(TMS,Too many setups)
SETU.2: MOVEM T2,STREAM ;SAVE THE STREAM NUMBER
MOVEI S1,DBSIZE ;NUMBER OF PAGES NEEDED
PUSHJ P,M%AQNP ;GET THEM
PG2ADR S1 ;CONVERT TO AN ADDRESS
MOVEM S1,JOBPAG(T2) ;AND SAVE IT
MOVE RDR,S1 ;PUT IT IN RDR
SETZM FLAG ;CLEAR THE READER FLAG WORD
MOVEM T2,.RDSTR(RDR) ;SAVE THE STREAM NUMBER
MOVEI S1,.RDPDL-1(RDR) ;SET UP THE STREAM CONTEXT
HRLI S1,-PDSIZE ;STACK POINTER.
PUSH S1,[EXP DOJOB] ;LETS START AT THE RIGHT SPOT.
MOVEM S1,.RDREG+P(RDR) ;SAVE THE STREAM STACK POINTER.
MOVEM RDR,.RDREG+RDR(RDR) ;SAVE RDR AWAY
MOVEI S1,1000(RDR) ;RDR BUFFER ADDRESS or END ADDRESS
MOVEM S1,.RDBFR(RDR) ;STORE IT
MOVE S2,T2 ;COPY OVER THE STREAM NUMBER
IMULI T2,OBJ.SZ ;GET OFFSET OF OBJECT BLOCK
ADDI T2,JOBOBJ ;ADD IN THE BASE
MOVEM T2,JOBOBA(S2) ;STORE OBJECT ADDRESS
MOVE S2,T2 ;GET DESTINATION OF BLT INTO S2
HRLI S2,SUP.TY(M) ;MAKE A BLT POINTER
BLT S2,OBJ.SZ-1(T2) ;BLT THE OBJECT BLOCK
HRL S2,M ;GET THE SETUP MESSAGE ADDRESS
HRRI S2,.RDSUP(RDR) ;WHERE WE WANT IT PUT
BLT S2,.RDSUP+SUP.SZ-1(RDR) ;SAVE THE SETUP MESSAGE IN THE DATA BASE
SETZM .RDREM(RDR) ;ASSUME THAT IT IS LOCAL OR DN200
MOVEI AP,LOC200 ;SINCE LOCAL,,GET LOCAL/DN200 BYTE TABLE
MOVX S1,IBYTSZ ;SINCE LOCAL,,GET INPUT BYTE SIZE
MOVEM S1,.RDIBZ(RDR) ; AND SAVE IT FOR LATER
MOVX S1,OBYTSZ ;SINCE LOCAL,,GET OUTPT BYTE SIZE
MOVEM S1,.RDOBZ(RDR) ; AND SAVE IT FOR LATER
MOVX S1,LOCRCL ;GET LOCAL/DN200 RECORD LENGTH
MOVEM S1,.RDRCL(RDR) ; AND SAVE IT FOR LATER
MOVE S1,SUP.NO(M) ;GET THIS GUYS NODE NAME
CAMN S1,CNTSTA ;IS IT REALLY LOCAL ???
JRST SETU.3 ;YES,,SKIP THIS REMOTE STUFF
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
SKIPN SUP.CN(M) ;IS THIS A DN60 REMOTE ???
JRST [SETOM .RDREM(RDR) ;NO,,MUST BE DN200 - SET DN200 FLAG
JRST SETU.3 ] ;AND CONTINUE PROCESSING
MOVEI S1,1 ;GET A 1 (DN60 FLAG)
MOVEM S1,.RDREM(RDR) ;MAKE THIS A DN60 REMOTE
MOVE S1,SUP.ST(M) ;GET THE DN60 FLAG WORD
MOVEM S1,.RDFLG(RDR) ;SAVE IT FOR LATER
MOVEI AP,CHAR60 ;GET DN60 BYTE TRANSLATION TABLE
MOVX S1,IBYT60 ;GET DN60 INPUT BYTE SIZE
MOVEM S1,.RDIBZ(RDR) ;AND SAVE IT
MOVX S1,OBYT60 ;GET DN60 OUTPUT BYTE SIZE
MOVEM S1,.RDOBZ(RDR) ;AND SAVE IT
MOVX S1,D60RCL ;GET DN60 RECORD LENGTH
MOVEM S1,.RDRCL(RDR) ;AND SAVE IT
SETU.3: MOVEM AP,.RDREG+AP(RDR) ;SAVE AP FOR PROCESSING
PUSHJ P,INPGET ;GET THE INPUT DEVICE.
CAIE S1,%RSUOK ;ALL IS OK?
PJRST SHUTIT ;NO, SHUT IT DOWN AND RETURN
TOPS10< PUSHJ P,RSETUP > ;SEND THE RESPONSE TO SETUP MSG.
$RETT ;RETURN
SUBTTL QSRNWA - ROUTINE TO PROCESS NODE-WENT-AWAY MESSAGES
QSRNWA: MOVX S1,%RSUNA ;GET NOT AVAILABLE RIGHT NOW STATUS
PUSHJ P,RSETUP ;TELL QUASAR HE CAN HAVE OBJECT BACK NOW
SETOM NOSAVE ;DON'T SAVE READER FLAG WORD
PUSHJ P,INPREL ;RELEASE THE READER
MOVE S2,RDR ;GET THE DATA BASE ADDRESS
ADR2PG S2 ;CONVERT TO A PAGE NUMBER
MOVX S1,DBSIZE ;GET THE DATA BASE LENGTH
PUSHJ P,M%RLNP ;RETURN THE PAGES BACK TO MEMORY MANAGER
PUSHJ P,M%CLNC ;REALLY WIPE THEM OUT !!!
MOVE S1,STREAM ;GET OUR STREAM NUMBER
SETZM JOBPAG(S1) ;CLEAR THE DATA BASE POINTER
$RETT ;RETURN
SUBTTL SHUTDN - ROUTINE TO SHUT DOWN A LINE-PRINTER
SHUTDN: MOVEI S1,SUP.TY(M) ;GET THE OBJECT BLOCK ADDRESS
PUSHJ P,FNDOBJ ;GO FIND IT
PUSHJ P,OACSHT ;GO SEE IF ITS OK TO SHUT IT DOWN
JUMPF .RETT ;NO,,RETURN NOW
SHUTIT: PUSHJ P,INPREL ;GO RELEASE THE READER
MOVE S2,RDR ;GET THE JOBPAG ADDRESS
ADR2PG S2 ;CONVERT TO A PAGE NUMBER
MOVEI S1,DBSIZE ;LOAD THE NUMBER OF PAGES
PUSHJ P,M%RLNP ;RETURN THEM
PUSHJ P,M%CLNC ;GET RID OF UNWANTED PAGES.
MOVE S1,STREAM ;GET HIS STREAM NUMBER
SETZM JOBPAG(S1) ;CLEAR THE PAGE WORD
SETOM NOSAVE ;WE DONT WANT STREAM FLAG BITS SAVED.
MOVX S1,%RSUDE ;GET 'DOES NOT EXIST'
PUSHJ P,RSETUP ;TELL QUASAR TO GET RID OF IT
$RETT ;RETURN
SUBTTL RSETUP - ROUTINE TO SEND A RESPONSE-TO-SETUP MSG TO QUASAR
RSETUP: MOVE T2,S1 ;SAVE THE SETUP CONDITION CODE.
MOVEI S1,RSU.SZ ;GET MESSAGE LENGTH
MOVEI S2,MSGBLK ;AND THE ADDRESS OF THE BLOCK
PUSHJ P,.ZCHNK ;ZERO IT OUT
MOVEI T1,MSGBLK ;GET THE BLOCK ADDRESS
MOVX S1,RSU.SZ ;GET MESSAGE SIZE
STORE S1,.MSTYP(T1),MS.CNT ;STORE IT
MOVX S1,.QORSU ;GET FUNCTION CODE
STORE S1,.MSTYP(T1),MS.TYP ;STORE IT
MOVE S1,STREAM ;GET STREAM NUMBER
MOVS S1,JOBOBA(S1) ;GET OBJADR,,0
HRRI S1,RSU.TY(T1) ;AND PLACE TO MOVE IT TO
BLT S1,RSU.TY+OBJ.SZ-1(T1) ;AND MOVE THE OBJECT BLOCK
STORE T2,RSU.CO(T1) ;STORE TH CODE
MOVE S1,T1 ;GET THE MESSAGE ADDRESS.
MOVEI S2,RSU.SZ ;GET THE MESSAGE LENGTH.
PUSHJ P,SNDQSR ;AND SEND THE MESSAGE
$RETT ;RETURN.
SUBTTL FNDOBJ - ROUTINE TO FIND THE OBJ BLK IN THE DATA BASE.
FNDOBJ: MOVE T1,.ROBTY(S1) ;GET OBJECT TYPE
MOVE T2,.ROBAT(S1) ;GET UNIT NUMBER
MOVE T3,.ROBND(S1) ;AND NODE NUMBER
SETZ T4, ;CLEAR AN INDEX REGISTER
FNDO.1: MOVE S2,T4 ;GET THE INDEX
IMULI S2,3 ;MULTIPLY BY OBJECT BLCK SIZE
CAMN T1,JOBOBJ+OBJ.TY(S2) ;COMPARE
CAME T2,JOBOBJ+OBJ.UN(S2) ;COMPARE
JRST FNDO.2 ;NOPE
CAMN T3,JOBOBJ+OBJ.ND(S2) ;COMPARE
JRST FNDO.3 ;WIN, SETUP THE CONTEXT
FNDO.2: ADDI T4,1 ;INCREMENT
CAIL T4,MAXRDR ;THE END OF THE LINE?
$STOP(ONF,Object not found)
JRST FNDO.1 ;OK, LOOP
FNDO.3: MOVEM T4,STREAM ;SAVE STREAM NUMBER
MOVE RDR,JOBPAG(T4) ;GET ADDRESS OF DATA
MOVE FLAG,.RDREG+FLAG(RDR) ;GET HIS 'FLAGS'
$RETT ;AND RETURN
SUBTTL UPDTST - ROUTINE TO SEND READER STATUS INFORMATION TO QUASAR
;CALL: PUSHJ P,UPDTST
;
;RETURN: ALWAYS TRUE +1
UPDTST: PUSHJ P,.SAVE1 ;SAVE P1
MOVEI S1,MSGBLK ;GET THE SOON TO BE MSG BLOCK ADDRESS
MOVE P1,STREAM ;GET THE STREAM NUMBER
SETZM JOBSTS(P1) ;ZAP THE STATUS UPDATE FLAG
HRLZ S2,JOBOBA(P1) ;GET THE STREAM'S OBJ BLOCK ADDRESS
HRRI S2,STU.RB(S1) ;GET THE DESTINATION ADDRESS
BLT S2,STU.RB+OBJ.SZ-1(S1) ;COPY THE OBJ BLK OVER
SETZM .MSCOD(S1) ;NO ACK CODE
SETZM .MSFLG(S1) ;NO FLAG BITS
MOVE S2,JOBSTW(P1) ;GET THE JOB STATUS BITS
MOVX P1,%READN ;DEFAULT TO 'READING'
TXNE S2,PSF%DO ;ARE WE OFFLINE ???
MOVX P1,%OFLNE ;YES,,THEN WE ARE REALLY OFFLINE
TXNE S2,PSF%ST ;ARE WE STOPPED BY THE OPERATOR
MOVX P1,%STOPD ;YES,,THEN SAY SO
STORE P1,STU.CD(S1) ;SAVE THE STATUS CODE
MOVX S2,.QOSTU ;GET THE MESSAGE TYPE
STORE S2,.MSTYP(S1),MS.TYP ;SAVE IT IN THE MSG
MOVX S2,STU.SZ ;GET THE MSG LENGTH
STORE S2,.MSTYP(S1),MS.CNT ;SAVE IT IN THE MSG
PJRST SNDQSR ;SEND IT OFF TO QUASAR
SUBTTL SNDQSR - ROUTINE TO SEND A MESSAGE TO QUASAR.
;CALL: S1/ The message address
; S2/ The message length
;
;RET: TRUE if sent successfully
; Stopcode 'QSF' if the send fails
;
OPRMSG: TDZA TF,TF ;FLAG SEND ORION ENTRY POINT
SNDQSR: SETOM TF ;FLAG SEND QUASAR ENTRY POINT
MOVEM S1,SAB+SAB.MS ;SAVE THE MESSAGE ADDRESS
MOVEM S2,SAB+SAB.LN ;SAVE THE MESSAGE LENGTH
MOVX S1,SP.QSR ;GET QUASAR FLAG
SKIPN TF ;UNLESS WE WANT TO THEN TO THE OPERATOR
MOVX S1,SP.OPR ; THEN GET OPERATOR INDEX
TXO S1,SI.FLG ;SET SPECIAL INDEX FLAG
STORE S1,SAB+SAB.SI ;AND STORE IT
SETZM SAB+SAB.PD ;CLEAR THE PID WORD
MOVEI S1,SAB.SZ ;LOAD THE SIZE
MOVEI S2,SAB ;AND THE ADDRESS
PUSHJ P,C%SEND ;SEND THE MESSAGE
JUMPT .RETT ;AND RETURN
$STOP(QSF,Send to QUASAR FAILED)
TOPS20 <
SUBTTL IDLE LOOP
MAIN: SETZM SCHEDL ;SLEEP AFTER THIS PASS
PUSHJ P,CHKQUE ;GO CHECK THE MESSAGE QUEUE
PUSHJ P,CHKFRK ;GO CHECK FOR FORK TERMINATION
SKIPN MESSAGE ;DID WE PROCESS A MESSAGE ???
SKIPE SCHEDL ;DO WE WANT ANOTHER SCHEDULING PASS ???
JRST MAIN ;YES,,GO CHECK AGAIN
SETZM S1 ;SLEEP TILL WE'RE NEEDED
PUSHJ P,I%SLP ;NO,,GO TO SLEEEEEEEEEEEPPPPP
JRST MAIN ;GO CHECK TO MESSAGE QUEUE
SUBTTL CHKFRK - ROUTINE TO PROCESS INFERIOR FORK TERMINATION
CHKFRK: SKIPN TRMFRK ;DID ANY FORK GO AWAY ???
JRST CHKF.4 ;NO,,GO CHECK FOR FORK INITIALIZATION
SETOM SCHEDL ;SCHEDULE ANOTHER PASS
SETZM TRMFRK ;ZERO FORK TERMINATION FLAG
MOVSI P1,-MAXRDR ;MAKE AN AOBJN AC
CHKF.1: SKIPN RDR,JOBPAG(P1) ;IS THIS STREAM ACTIVE ???
JRST CHKF.3 ;NO,,TRY THE NEXT ONE
SKIPE .RDSHT(RDR) ;DID THIS READER SHUTDOWN ???
JRST CHKF.2 ;YES,,SHUT IT DOWN
MOVE S1,.RDHND(RDR) ;GET THE PROCESS HANDLE
RFSTS ;GET THE FORK STATUS
ERJMP CHKF.2 ;IGNORE ANY ERRORS
TXZ S1,RF%FRZ ;CLEAR THE FROZEN FORK BIT
HLRZ S1,S1 ;MOVE LEFT TO RIGHT AND ZERO LEFT
CAIE S1,.RFHLT ;IS THIS FORK HALTED ???
CAIN S1,.RFFPT ;HERE TOO !
SKIPA ;YES TO EITHER,,CONTINUE ON
JRST CHKF.3 ;ELSE TRY NEXT FORK
HRROI S1,.RDSTP(RDR) ;POINT TO ERROR BUFFER
HRLOI S2,@.RDHND(RDR) ;ELSE GET FORK HANDLE,,-1
SKIPE .RDSTP(RDR) ;IS THERE ANY ERROR CODE ???
HRR S2,.RDSTP(RDR) ;YES,,GET FORK HANDLE,,ERROR CODE
MOVE T1,[-^D49,,0] ;GET -LENGTH,,0
ERSTR ;CONVERT ERROR TO A STRING
ERJMP .+2 ;IGNORE THIS ERROR
ERJMP .+1 ;AND THIS ONE
$WTO (< ^B/@JOBOBA(P1)/ Terminated >,<Reason: ^T/.RDSTP(RDR)/>,,<$WTFLG(WT.SJI)>)
CHKF.2: HRRZM P1,STREAM ;SAVE THE STREAM NUMBER
SKIPN 135 ;UNLESS WE ARE DEBUGGING
PUSHJ P,SHUTIT ;SHUT DOWN THE FORK
CHKF.3: AOBJN P1,CHKF.1 ;GO CHECK THE NEXT FORK
;Here to Check to see if any fork is finished initialization.
CHKF.4: SKIPN FRKINI ;ANY FORK END ITS INITIALIZATION ???
$RETT ;NO,,JUST RETURN
SETOM SCHEDL ;YES,,SCHEDULE ANOTHER PASS
SETZM FRKINI ;ZERO FORK TERMINATION FLAG
MOVSI P1,-MAXRDR ;MAKE AN AOBJN AC
CHKF.5: SKIPE RDR,JOBPAG(P1) ;IS THIS READER SETUP ???
SKIPN .RDINI(RDR) ;YES,,INITIALIZATION FLAG LIT ???
JRST CHKF.6 ;NO,,TRY NEXT
HRRZM P1,STREAM ;SAVE OUR STREAM NUMBER
SETZM .RDINI(RDR) ;CLEAR THE INITIALIZATION FLAG
MOVX S1,%RSUOK ;GET RESPONSE TO SETUP CODE (OK)
PUSHJ P,RSETUP ;SEND THE RESPONSE TO SETUP MESSAGE
CHKF.6: AOBJN P1,CHKF.5 ;GO CHECK THE NEXT RDR
$RETT ;RETURN WHEN DONE
SUBTTL RDINIT - ROUTINE TO INITIALIZE READER CONSTANTS
RDINIT: PUSHJ P,I%HOST ;GET OUR HOST NAME
MOVEM S1,CNTSTA ;SAVE THE SIXBIT NODE NAME
SKIPE 135 ;ARE WE DEBUGGING
SKIPN 116 ;AND ARE SYMBOLS DEFINED ???
JRST RDIN.1 ;NO TO EITHER,,SKIP THIS
HLRO S1,116 ;GET AOBJN LENGTH
MOVMS S1 ;GET ABSOLUTE VALUE
HRRZ S2,116 ;GET SYMBOL TABLE START ADDRESS
ADDI S1,-1(S2) ;CALC SYMBOL TABLE LENGTH
SKIPA ;SKIP OVER NORMAL CALC
RDIN.1: HLRZ S1,.JBSA## ;GET THE PROGRAM END ADDRESS
ADDI S1,777 ;ROUND IT OFF
ADR2PG S1 ;MAKE IT A PAGE NUMBER
MOVEM S1,RDRSIZ ;SAVE IT
$RETT ;RETURN
SUBTTL INPGET - ROUTINE TO SETUP THE READER FORK
INPGET: MOVE S1,STREAM ;GET THE STREAM NUMBER
MOVE S1,JOBOBA(S1) ;GET THE OBJECT BLOCK ADDRESS
SKIPN .RDREM(RDR) ;IS THIS A LOCAL READER ???
$TEXT (<-1,,.RDRFD(RDR)>,<PCDR^O/OBJ.UN(S1)/:^0>) ;YES,,GEN DEV NAME
SKIPGE .RDREM(RDR) ;OR IS IT A REMOTE READER ???
$TEXT (<-1,,.RDRFD(RDR)>,<^W/OBJ.ND(S1)/::PCDR^O/OBJ.UN(S1)/:^0>)
MOVX S1,<CR%CAP+CR%ACS> ;SUPERIOR CAPS AND AC'S
MOVEI S2,.RDREG(RDR) ;AC LOAD BUFFER
CFORK ;CREATE A SPOOLER
ERJMP FRKERR ;ON ERROR,,GO PROCESS IT
MOVEM S1,.RDHND(RDR) ;SAVE THE INFERIOR HANDLE
MOVSI S1,.FHSLF ;GET MY HANDLE
HRLZ S2,.RDHND(RDR) ;GET THE SPOOLER HANDLE
HRR T1,RDRSIZ ;GET THE LENGTH IN PAGES
HRLI T1,(PM%RWX!PM%CNT) ;COUNT+READ+EXECUTE
PMAP ;MAP THE PAGES
ERJMP PMPERR ;ON ERROR,,GO PROCESS IT
MOVE S1,RDR ;GET THE DATA BASE ADDRESS
ADR2PG S1 ;CONVERT IT TO A PAGE NUMBER
MOVE S2,S1 ;SAVE IT IN S2
HRLI S1,.FHSLF ;GET MY HANDLE
HRL S2,.RDHND(RDR) ;GET THE SPOOLER HANDLE
HRRI T1,DBSIZE ;GET THE PAGE COUNT
HRLI T1,(PM%RWX!PM%CNT) ;R,W,E + COUNT
PMAP ;MAP THE DATA BASE
ERJMP PMPERR ;ON ERROR,,GO PROCESS IT
MOVE S1,.RDHND(RDR) ;GET THE SPOOLER HANDLE
MOVEI S2,DOJOB ;GET THE START ADDRESS
SFORK ;START THE SPOOLER
ERJMP FRKERR ;ON ERROR,,PROCESS IT
MOVX S1,%RSUOK
$RETT ;AND RETURN
FRKERR: MOVE S1,STREAM ;GET THE STREAM NUMBER
$WTO (Cant create a Fork,,@JOBOBA(S1)) ;TELL THE OPERATOR
MOVX S1,%RSUDE ;GET THE ERROR CODE
$RETT ;AND RETURN
PMPERR: MOVE S1,STREAM ;GET THE STREAM NUMBER
$WTO (Cant PMAP Spooler Pages,,@JOBOBA(S1)) ;TELL THE OPERATOR
MOVX S1,%RSUDE ;GET THE ERROR CODE
$RETT ;AND RETURN
SUBTTL OACPAU - ROUTINE TO STOP A READER
OACPAU: MOVE S1,.RDHND(RDR) ;GET THE SPOOLER HANDLE
FFORK ;FREEZE THE FORK
ERJMP OACC.1 ;IF AN ERROR,,PROCESS IT
MOVE S1,STREAM ;GET THE STREAM NUMBER
$ACK (Stopped,,@JOBOBA(S1),.MSCOD(M)) ;TELL THE OPERATOR
MOVX S2,PSF%ST ;GET 'STOPPED' BIT
IORM S2,JOBSTW(S1) ;SET IT
PUSHJ P,UPDTST ;SEND A STATUS MESSAGE
$RETT ;AND RETURN
OACC.1: MOVE S1,STREAM ;GET THE STREAM NUMBER
$ACK (Cannot Be Stopped,,@JOBOBA(S1),.MSCOD(M)) ;TELL THE OPERATOR
$RETT ;AND RETURN
SUBTTL OACCON - ROUTINE TO CONTINUE A READER
OACCON: MOVE S1,.RDHND(RDR) ;GET THE SPOOLER HANDLE
RFORK ;RESTART THE SPOOLER
ERJMP OACC.2 ;IF AN ERROR,,GO PROCESS
MOVE S1,STREAM ;GET THE STREAM NUMBER
$ACK (Continued,,@JOBOBA(S1),.MSCOD(M)) ;TELL THE OPERATOR
MOVX S2,PSF%ST ;GET THE 'STOPPED' BIT
ANDCAM S2,JOBSTW(S1) ;CLEAR IT
MOVE S1,.RDHND(RDR) ;GET THE FORKS HANDLE
MOVX S2,<1B1> ;WANT CHANNEL 1
IIC ;TELL FORK TO SEND STATUS
$RETT ;AND RETURN
OACC.2: MOVE S1,STREAM ;GET THE STREAM NUMBER
$ACK (Cannot Be Continued,,@JOBOBA(S1),.MSCOD(M)) ;TELL THE OPERATOR
$RETT ;AND RETURN
SUBTTL OACCAN - ROUTINE TO CANCEL THE CURRENT JOB ON THE READER
OACCAN: MOVE S1,.RDHND(RDR) ;GET THE FORKS HANDLE
MOVX S2,<1B2> ;GET CHANNEL 2
IIC ;TELL THE FORK TO CANCEL THE JOB
$RETT ;AND RETURN
SUBTTL OACSHT - ROUTINE TO SHUTDOWN THE CARD READER
OACSHT: MOVE S1,.RDHND(RDR) ;GET THE FORKS HANDLE
MOVX S2,<1B3> ;GET CHANNEL 3
IIC ;TELL THE FORK TO SHUTDOWN
ERJMP .RETT ;ON AN ERROR,,RETURN OK
$RETF ;AND RETURN
SUBTTL INTERRUPT ROUTINES
LEVTAB: EXP LEV1PC ;INTRPT LEVEL 1 PC ADDRESS
EXP LEV2PC ;INTRPT LEVEL 2 PC ADDRESS
EXP LEV3PC ;INTRPT LEVEL 3 PC ADDRESS
CHNTAB: XWD 1,INTIPC ;IPCF INTERRUPT ON CHANNEL 0
XWD 1,INTFKI ;FORK INITIALIZATION END INTERRUPT
BLOCK ^D34 ;INFERIOR PROCESS TERM ON CHNL 19
;ALL OTHER CHANNELS 0
LEV1PC: BLOCK 1 ;LEVEL 1 INTERRUPT PC
LEV2PC: BLOCK 1 ;LEVEL 2 INTERRUPT PC
LEV3PC: BLOCK 1 ;LEVEL 3 INTERRUPT PC
INTINI: MOVE S1,[1,,ENDFRK] ;SET UP INFERIOR FORK TERM PARMS
MOVEM S1,CHNTAB+.ICIFT ; IN THE CHANNEL TABLE
MOVX S1,.FHSLF ;GET MY HANDLE
MOVX S2,1B0+1B1+1B19 ;GET CHNL 0 (IPCF)+CHNL 19 (FORK TERM)
AIC ;ACTIVATE CHANNEL 0 AND 1 AND 19
$RETT ;RETURN
INTIPC: $BGINT 1, ;INITIALIZE INTERRUPT LEVEL
PUSHJ P,C%INTR ;FLAG THE IPCF INTERRUPT
$DEBRK ;AND LEAVE INTERRUPT LEVEL
ENDFRK: $BGINT 1, ;INTIALIZE INTERRUPT LEVEL
SETOM TRMFRK ;INDICATE WE DID THIS
$DEBRK ;AND LEAVE INTERRUPT LEVEL
INTFKI: $BGINT 1, ;INITIALIZE INTERRUPT LEVEL
SETOM FRKINI ;FLAG THE INTERRUPT
$DEBRK ;AND LEAVE INTERRUPT LEVEL
SUBTTL INPREL - ROUTINE TO RELEASE A CARD READER
INPREL: MOVE S1,.RDHND(RDR) ;GET THE SPOOLER HANDLE
KFORK ;KILL THE FORK
ERJMP .+1 ;IGNORE ANY ERRORS
$RETT ;AND RETURN
SUBTTL SPOOLER - CARD READER SPOOLER FORK ROUTINE START ADDRESS
RDRIB: $BUILD IB.SZ ;
$SET (IB.PRG,,%%.MOD) ;PROGRAM 'CDRIVE'
$SET (IB.FLG,IP.STP,1) ;STOPCODES TO ORION
$SET (IB.PIB,,RDRPIB) ;SET UP PIB ADDRESS
$SET(IB.INT,,<LEVTBL,,CHNTBL>) ;SETUP INTERRUPT VECTOR
$EOB ;
RDRPIB: $BUILD PB.MNS ;
$SET (PB.HDR,PB.LEN,PB.MNS) ;
$EOB ;
DOJOB: MOVEI S1,IB.SZ ;GET THE IB SIZE
MOVEI S2,RDRIB ;GET THE IB ADDRESS
PUSHJ P,I%INIT ;GO MAP THE LIBRARY
SKIPE 135 ;ARE WE DEBUGGING ???
PUSHJ P,GETDDT ;YES,,GO LOAD DDT AND WAIT
MOVEI S1,.RDFD(RDR) ;GET THE FD ADDRESS
MOVEM S1,.RDFOB+FOB.FD(RDR) ;SAVE IT IN THE FOB
MOVE S1,.RDOBZ(RDR) ;GET THE OUTPUT BYTE SIZE
STORE S1,.RDFOB+FOB.CW(RDR),FB.BSZ ;SAVE IT IN THE FOB
MOVEI S1,1 ;GET A BIT
STORE S1,.RDFOB+FOB.CW(RDR),FB.NFO ;WANT 'NEW FILE ONLY' !!
MOVX S1,.FHSLF ;GET MY HANDLE
RPCAP ;GET MY CAPABILITIES
ERJMP INTERR ;STOP ON AN ERROR
MOVE T1,S2 ;WANT ALL AVAILABLE CAPABILITIES
MOVX S1,.FHSLF ;GET MY HANDLE
EPCAP ;ENABLE ALL CAPABILITIES
ERJMP INTERR ;STOP ON AN ERROR
PUSHJ P,OPENIT ;GO OPEN THE READER
MOVE S1,.RDSTR(RDR) ;GET THE STREAM NUMBER
$WTO (Started,,@JOBOBA(S1)) ;TELL THE OPERATOR
;SETUP THE UPDATE STATUS MESSAGE (ONCE ONLY)
MOVE S1,[STU.SZ,,.QOSTU] ;GET STATUS MSG LENGTH,,TYPE
MOVEM S1,.RDMSG+.MSTYP(RDR) ;SAVE IT
MOVE S1,.RDSTR(RDR) ;GET OUR STREAM NUMBER
HRLZ S1,JOBOBA(S1) ;GET OUR OBJECT BLOCK ADDRESS
HRRI S1,.RDMSG+STU.RB(RDR) ;GET THE DESTINATION ADDRESS
BLT S1,.RDMSG+STU.RB+OBJ.SZ-1(RDR) ;COPY THE OBJ BLK OVER
SETOM .RDSTS(RDR) ;LETS TRY IT FIRST CHANCE WE GET
MOVEI S1,2 ;GET A MAX ERROR COUNT OF 2
MOVEM S1,.RDECT(RDR) ;SAVE IT JUST IN CASE WE NEED IT
JRST MAINRT ;GO PROCESS
SUBTTL MAINRT - ROUTINE TO INPUT AND PROCESS CARDS
MAINRT: MOVE S1,.RDJFN(RDR) ;GET THE JFN
HRLZ S2,.RDIBZ(RDR) ;GET THE INPUT BYTE SIZE
LSH S2,6 ;POSITION IT
ADD S2,[POINT 0,.CARDS(RDR)] ;CREATE THE BYTE POINTER
MOVE T1,[EXP -CRDNBR] ;GET THE NUMBER OF CARDS TO READ
IMUL T1,.RDRCL(RDR) ;MULTIPLY BY RECORD LENGTH
PUSHJ P,$SIN ;GET A BATCH OF CARDS
JUMPT MAIN.1 ;WE WIN,,SO CONTINUE
MOVE P1,S2 ;SAVE THE OUTPUT BYTE POINTER
MOVE P2,T1 ;SAVE THE BYTE COUNT
PUSHJ P,$GTSTS ;GO SET THE READER STATUS
PUSHJ P,$GETER ;READ THE ERROR STATUS BITS
MOVE T1,P2 ;RESTORE THE NUMBER OF BYTES READ
CAXE S1,OPNX8 ;IS IT DEVICE OFFLINE ???
CAXN S1,IOX5 ; OR WAS IT AN I/O ERROR ???
JRST MAIN.1 ;YES,,GO PROCESS IT
CAXE S1,IOX4 ;WAS IT EOF ???
PJRST INTERR ;NO,,THEN A FATAL ERROR
TXO FLAG,EOF ;INDICATE AN EOF CONDITION OCCURED
PUSHJ P,RESDEV ;ON EOF,,GO CLOSE AND RE-OPEN THE RDR
MOVE S1,ENDIMG(AP) ;GET AN EOF BYTE
IDPB S1,P1 ;MAKE AN EOF CARD
MOVE T1,P2 ;GET THE NUMBER OF BYTES READ
ADD T1,.RDRCL(RDR) ;ADD 1 MORE CARD LENGTH
MAIN.1: MOVE S1,.RDRCL(RDR) ;GET THE RECORD LENGTH
IMULI S1,CRDNBR ;CALC # OF BYTES TO BE READ
ADD T1,S1 ;CALC # OF BYTES READ
IDIV T1,.RDRCL(RDR) ;CALC # OF CARDS READ
MOVEM T1,.RDNBR(RDR) ;SAVE IT
SKIPE T1 ;NO CARDS,,DONT PROCESS
PUSHJ P,READER ;GO PROCESS THE CARDS
SKIPG .RDREM(RDR) ;IS THIS A DN60 READER ???
PUSHJ P,CHKOFL ;NO,,GO CHECK FOR OFFLINE'NESS
MAIN.2: PUSHJ P,CHKSTS ;GO CHECK OUR STATUS
SETZM S1 ;SLEEP TILL WE'RE NEEDED
SKIPLE .RDREM(RDR) ;IS THIS A DN60 CDR ???
MOVEI S1,5 ;YES,,JUST SLEEP 5 SECONDS
SKIPE .RDOFL(RDR) ;IS THE READER OFFLINE ???
PUSHJ P,I%SLP ;YES,,JUST SLEEEEEEP
JRST MAINRT ;ELSE,,GO PROCESS SOME MORE CARDS
SUBTTL GENFIL - ROUTINE TO GENERATE A SPOOL FILENAME
GENFIL: MOVEI S1,.RDFD(RDR) ;GET THE FD ADDRESS
MOVEI S2,10 ;GET THE FD LENGTH
STORE S2,.FDLEN(S1),FD.LEN ;SAVE IT IN THE FD
AOS S2,FILENM ;BUMP HASH COUNT BY 1,,PUT IN S2
$TEXT (<-1,,.FDSTG(S1)>,<^T/SPL/RD^D4L0/S2,FILEMK/-^D3R0/FILEXT/>)
$RETT ;AND RETURN
RESDEV: SKIPLE .RDREM(RDR) ;IS THIS A DN60 CARD READER ???
$RETT ;YES,,JUST RETURN
MOVE S1,.RDJFN(RDR) ;GET THE JFN
TXO S1,CZ%ABT ;ABORT ANY INPUT PROCESSING
PUSHJ P,$CLOSF ;CLOSE THE READER DOWN
JUMPF OPNERR ;NO,,STOP ON AN ERROR
;FALL INTO READER OPEN CODE
OPENIT: MOVX S1,GJ%SHT+GJ%PHY ;SHORT JFN+PHYSICAL UNIT
HRROI S2,.RDRFD(RDR) ;GET THE DEVICE ADDRESS
PUSHJ P,$GTJFN ;GET A JFN
JUMPF OPNERR ;STOP ON AN ERROR
MOVEM S1,.RDJFN(RDR) ;SAVE THE JFN
MOVX S2,^D16B5+10B9+OF%RD+OF%HER+OF%OFL ;16 BIT BYTES+IMAGE MODE+
PUSHJ P,$OPENF ;OPEN THE READER
JUMPF OPNERR ;STOP ON AN ERROR
PUSHJ P,SETINT ;GO SETUP THE INTERRUPTS
PUSHJ P,$GTSTS ;GO GET THE READER STATUS
MOVE S1,.RDSTA(RDR) ;GET THE DEVICE STATUS BITS
TXNE S1,MO%FNX ;DOES THE DEVICE REALLY EXIST ???
JRST [MOVX S1,DIAGX8 ;NO,,GET 'DEVICE DOESN'T EXIST' CODE
MOVEM S1,.RDSTP(RDR) ;SAVE IT IN OUR DATA BASE
HALTF ] ;WE'RE DONE FOR !!!
TXNE FLAG,EOF ;HERE BECAUSE OF DEVICE EOF ???
$RETT ;YES,,JUST RETURN
SETOM .RDINI(RDR) ;FLAG END OF INITIALIZATION
MOVX S1,.FHSUP ;WANT SUPERIOR PROCESS
MOVX S2,<1B1> ;GET CHANNEL
IIC ;TELL SUPERIOR TO SEND RSP MSG TO QUASAR
ERJMP OPNERR ;CAN'T,,OH WELL !!!
$RETT ;OK,,RETURN
SPL: ASCIZ/PS:<SPOOL>/
SUBTTL CHKOFL - ROUTINE TO CHECK LOCAL/REMOTE OFFLINE STATUS
CHKOFL: SKIPN .RDOFL(RDR) ;ARE WE OFFLINE ???
$RETT ;NO,,JUST RETURN
MOVE S1,.RDSTR(RDR) ;GET OUR STREAM NUMBER
TXNE FLAG,JOBCD ;DO WE HAVE A JOB CARD ???
$WTO (Offline,,@JOBOBA(S1)) ;TELL THE OPERATOR ITS OFFLINE
SKIPE .RDREJ(RDR) ;ARE WE REJECTING CARDS ???
$WTOJ (< ^D/.RDREJ(RDR)/ Cards Flushed >,,@JOBOBA(S1)) ;YES,,TELL OPR
SETZM .RDREJ(RDR) ;ZERO THE REJECT COUNT
$RETT ;AND RETURN
SUBTTL CHKSTS - ROUTINE TO PROCESS THE DIFFERENT STATUS INTERRUPTS
CHKSTS: PUSHJ P,GETHSP ;GO READ THE HASP CONSOLE (IF NEEDED)
SKIPE .RDSTS(RDR) ;DO WE WANT TO SEND A STATUS UPDATE ??
PUSHJ P,SNDSTS ;YES,,DO IT
SKIPN .RDCAN(RDR) ;DO WE WANT TO CANCEL THIS GUY ???
JRST CHKS.1 ;NO,,CONTINUE ON
SETZM .RDCAN(RDR) ;CLEAR THE CANCEL FLAG
TXZ FLAG,JOBCD ;CLEAR THE JOBCARD FLAG
MOVE S1,.RDSTR(RDR) ;GET THE STREAM NUMBER
$WTOJ (Current Job Canceled,,@JOBOBA(S1)) ;TELL THE OPERATOR
CHKS.1: SKIPE .RDSHT(RDR) ;DO WE WANT TO SHUT DOWN
SKIPN .RDOFL(RDR) ;IF SO ARE WE OFFLINE ???
$RETT ;NO TO EITHER,,RETURN
TXNE FLAG,JOBCD ;ARE WE PROCESSING A JOB ???
$RETT ;YES,,RETURN
HALTF ;NO,,KILL THE FORK
SUBTTL GETDDT - ROUTINE TO LOAD DDT IF WE ARE DEBUGGING
GETDDT: MOVX S1,GJ%OLD+GJ%SHT ;OLD FILE+SHORT JFN
HRROI S2,[ASCIZ/SYS:SDDT.EXE/] ;WANT DDT IN HERE TOO
GTJFN ;GET DDT'S JFN
ERJMP INTERR ;CANT,,TOO BAD !!
HRLI S1,.FHSLF ;GET MY HANDLE
GET ;LOAD DDT
ERJMP INTERR ;CANT LOAD IT,,TOO BAD !!
MOVE S1,116 ;GET CONTENTS OF .JBSYM
HRRZ S2,770001 ;GET ADDRESS OF WHERE TO PUT IT
MOVEM S1,0(S2) ;POINT DDT AT MY SYMBOL TABLE
JRST 770000 ;AND ENTER DDT
GO: $RETT ;RETURN
SUBTTL SENDIT - ROUTINE TO SEND IPCF MESSAGES TO QUASAR
;CALL: S1/ THE MESSAGE ADDRESS
; S2/ THE MESSAGE LENGTH
;
;RET: TRUE ALWAYS
SNDOPR: TDZA TF ;ZAP ENTRY FLAG WORD AND SKIP
SENDIT: SETOM TF ;SET ENTRY FLAG WORD AND CONTINUE
MOVEM S1,.RDSAB+SAB.MS(RDR) ;SAVE THE MESSAGE ADDRESS
MOVEM S2,.RDSAB+SAB.LN(RDR) ;SAVE THE MESSAGE LENGTH
MOVX S1,SP.QSR ;GET QUASAR'S SPECIAL INDEX
SKIPN TF ;CHECK ENTRY FLAG; IS IT OPR ENTRY POINT
MOVX S1,SP.OPR ;YES,,GET ORIONS SPECIAL INDEX
TXO S1,SI.FLG ;SET SPECIAL INDEX FLAG
MOVEM S1,.RDSAB+SAB.SI(RDR) ;SAVE THE RECIEVERS ID
SETZM .RDSAB+SAB.PD(RDR) ;CLEAR THE PID WORD
MOVEI S1,PIB ;GET SUPERIORS PIB ADDRESS
MOVEM S1,.RDSAB+SAB.PB(RDR) ;SAVE IT FOR 'IN BEHALF OF' SEND
MOVEI S1,SAB.SZ ;GET THE SAB LENGTH
MOVEI S2,.RDSAB(RDR) ;GET THE SAB ADDRESS
PUSHJ P,C%SEND ;SEND IT TO QUASAR
JUMPT .RETT ;RETURN IF OK
PJRST INTERR ;ELSE END IT ALL
SUBTTL SNDSTS - ROUTINE TO SEND READER STATUS UPDATES TO QUASAR
SNDSTS: SETZM .RDSTS(RDR) ;CLEAR SEND STATUS FLAG
MOVX S1,%OFLNE ;DEFAULT TO OFFLINE
TXNN FLAG,JOBCD ;IF NO JOB,,THEN
MOVX S1,%IDLE ; DEFAULT TO IDLE
SKIPN .RDOFL(RDR) ;IF WE ARE READING
MOVX S1,%READN ; SET IT
STORE S1,.RDMSG+STU.CD(RDR) ;SAVE THE READER STATUS
MOVEI S1,.RDMSG(RDR) ;GET THE MESSAGE ADDRESS
MOVEI S2,STU.SZ ;GET THE MESSAGE LENGTH
PUSHJ P,SENDIT ;SEND IT TO QUASAR
$RETT ;AND RETURN
SUBTTL SETINT - ROUTINE TO SETUP PROCESS INTERRUPTS
;INTERRUPT DATA BASE
LEVTBL: EXP LVL1PC ;INTRPT LEVEL 1 PC ADDRESS
EXP LVL2PC ;INTRPT LEVEL 2 PC ADDRESS
EXP LVL3PC ;INTRPT LEVEL 3 PC ADDRESS
CHNTBL: XWD 1,CDRINT ;ONLINE/OFFLINE ON CHANNEL 0
XWD 1,STSINT ;UPDATE STATUS INTRPTS ON CHANL 1
XWD 1,CANINT ;CANCEL JOB INTRPTS ON CHANL 2
XWD 1,SHTINT ;SHUTDOWN READER INTRPTS ON CHANL 3
BLOCK ^D35 ;ALL OTHER CHANNELS 0
LVL1PC: BLOCK 1 ;LEVEL 1 INTRPT PC
LVL2PC: BLOCK 1 ;LEVEL 2 INTRPT PC
LVL3PC: BLOCK 1 ;LEVEL 3 INTRPT PC
SETINT: MOVX S1,.FHSLF ;GET THE PROCESS HANDLE
SETOM S2 ;DISABLE ALL 36 CHANNELS
DIC ;LETERRIP
ERJMP INTERR ;ON ERROR,,HALT
CIS ;CLEAR THE INTERRUPT SYSTEM
MOVX S1,.FHSLF ;GET MY PROCESS HANDLE
MOVE S2,[LEVTBL,,CHNTBL] ;GET PRTY LEVEL,,CHANNEL
SIR ;SETUP THE MONITOR INTRPT TABLE ADDRS
ERJMP INTERR ;ON ERROR,,HALT
MOVX S1,.FHSLF ;GET MY PROCESS HANDLE
EIR ;ENABLE THE INTERRUPT SYSTEM
ERJMP INTERR ;ON ERROR,,HALT
MOVE S1,.RDJFN(RDR) ;GET THE JFN
MOVX S2,.MOPSI ;FUNCTION: ADD TO INTRPT SYSTEM
MOVEI T1,T2 ;ARGUMENT BLOCK ADDRESS
MOVEI T2,3 ; "" "" LENGTH
MOVEI T3,0 ;INTERRUPTS ON CHANNEL 0
MOVX T4,MO%MSG ;NO MESSAGE
PUSHJ P,$MTOPR ;ADD TO THE INTERRUPT SYSTEM
JUMPF INTERR ;ON AN ERROR,,STOP
MOVX S1,.FHSLF ;GET MY PROCESS HANDLE
MOVX S2,1B0+1B1+1B2+1B3 ;INTERRUPT ON CHANNEL 0+1+2+3
AIC ;ACTIVATE THE INTERRUPT SYSTEM
ERJMP INTERR ;ON ERROR,,HALT
$RETT ;RETURN
INTERR:
OPNERR: MOVX S1,.FHSLF ;GET MY HANDLE
SETZM S2 ;CLEAR S2 (RESULT)
GETER ;GET THE LAST ERROR CODE
MOVEM S2,.RDSTP(RDR) ;SAVE THE ERROR CODE
HALTF ;END IT ALL
SUBTTL INTERRUPT ROUTINES
;READER ONLINE/OFFLINE INTERRUPT ROUTINE
CDRINT: $BGINT 1, ;INITIALIZE INTERRUPT LEVEL
SETOM .RDSTS(RDR) ;WANT A STATUS UPDATE MSG SENT
MOVE S1,.RDJFN(RDR) ;GET THE JFN
MOVX S2,.MORST ;READ DEVICE STATUS FUNCTION
MOVEI T1,T2 ;ARGUMENT BLOCK ADDRESS
MOVEI T2,2 ;ARGUMENT BLOCK LENGTH
SETZ T3, ;DEVICE STATUS
PUSHJ P,$MTOPR ;GET THE READER STATUS
MOVEM T3,.RDSTA(RDR) ;SAVE THE DEVICE STATUS BITS
SETZM .RDOFL(RDR) ;ASSUME WE ARE ON-LINE !!!
TXNE T3,MO%OL ;IS THE READER OFFLINE ???
SETOM .RDOFL(RDR) ;IF OFFLINE,,SAY SO.
SKIPE .RDREM(RDR) ;IF REMOTE,,
JRST CDRI.1 ; THEN SKIP THIS LOCAL STUFF
MOVEI S1,.RETT ;GET OFFLINE EXIT ADDRESS
SKIPE .RDIOA(RDR) ;WERE WE I/O ACTIVE ???
MOVEM S1,LVL1PC ;YES,,SAVE IT FOR DEBRK
CDRI.1: SETZM .RDIOA(RDR) ;CLEAR I/O ACTIVE
$DEBRK ;DISMISS THE INTERRUPT.
;UPDATE READER STATUS INTERRUPT ROUTINE
STSINT: $BGINT 1, ;INITIALIZE INTERRUPT LEVEL
SETOM .RDSTS(RDR) ;SAY WE WANT A STATUS UPDATE MSG SENT
$DEBRK ;LEAVE INTERRUPT LEVEL
;JOB CANCEL INTERRUPT ROUTINE
CANINT: $BGINT 1, ;INITIALIZE INTERRUPT LEVEL
SETOM .RDCAN(RDR) ;SAY WE WANT TO CANCEL THE CURRENT JOB
$DEBRK ;LEAVE INTERRUPT LEVEL
;CARD READER SHUTDOWN INTERRUPT ROUTINE
SHTINT: $BGINT 1, ;INITIALIZE INTERRUPT LEVEL
SETOM .RDSHT(RDR) ;SAY WE WANT TO SHUT DOWN
$DEBRK ;LEAVE INTERRUPT LEVEL
SUBTTL LOCAL/REMOTE I/O SUBROUTINES
$GTSTS: SKIPLE .RDREM(RDR) ;IS THIS A LOCAL OR DN200 CDR ???
$RETT ;NO, SO DN60, SO RETURN
MOVX S1,.FHSLF ;YES,,GET MY HANDLE
MOVX S2,<1B0> ;WANT CHANNEL 0
IIC ;FORCE INTERRUPT ON ONLINE/OFFLINE CHNL
ERJMP .+1 ;IGNORE ANY ERROR
$RETT ;AND RETURN
$GETER: SKIPE .RDREM(RDR) ;IS THIS A REMOTE READER ???
JRST [SKIPG .RDREM(RDR) ;YES,,IS THIS A DN200 READER ???
JRST GETE.2 ;YES,,MUST BE DN200
JRST GETE.6 ] ;NO,,MUST BE DN60
MOVX S1,.FHSLF ;GET MY HANDLE
GETER ;GET THE LAST ERROR CODE
HRRZ S1,S2 ;PUT IT INTO S1
$RETT ;AND RETURN
$SIN: SETOM .RDIOA(RDR) ;MARK I/O ACTIVE
SKIPE .RDREM(RDR) ;IS THIS A REMOTE READER ???
JRST [SKIPG .RDREM(RDR) ;YES,,IS IT THE DN200 READER ???
JRST SIN.2 ;YES,,GO PROCESS IT
JRST SIN.6 ] ;NO,,MUST BE DN60 READER
SKIPE .RDOFL(RDR) ;IS THE READER OFFLINE ???
JRST SIN.T ;YES,,JUST RETURN
SIN ;FINALLY READ THE DATA
ERJMP SIN.F ;RETURN FALSE ON AN ERROR
SIN.T: SETZM .RDIOA(RDR) ;CLEAR I/O ACTIVE
$RETT ;AND RETURN
SIN.F: SETZM .RDIOA(RDR) ;CLEAR I/O ACTIVE
$RETF ;AND RETURN
$OPENF: SKIPE .RDREM(RDR) ;IS THIS A REMOTE READER ???
JRST [SKIPG .RDREM(RDR) ;YES,,IS IT THE DN200 READER ???
JRST OPEN.2 ;YES,,GO PROCESS IT
JRST OPEN.6 ] ;NO,,MUST BE DN60 READER
OPENF ;OPEN THE CARD READER
ERJMP .RETF ;ON AN ERROR,,RETURN WITH ERROR
$RETT ;ELSE JUST RETURN
$MTOPR: SKIPE .RDREM(RDR) ;IS THIS A REMOTE READER ???
JRST [SKIPG .RDREM(RDR) ;YES,,IS IT THE DN200 READER ???
JRST MTOP.2 ;YES,,GO PROCESS IT
JRST .RETT ] ;NO,,MUST BE DN60 READER (NO MTOPR)
MTOPR ;LOCAL,,ISSUE MTOPR NORMALLY
ERJMP .RETF ;ON AN ERROR,,RETURN NO GOOD
$RETT ;RETURN OK
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
$GTJFN: SKIPE .RDREM(RDR) ;IS THIS A REMOTE READER ???
JRST [SKIPG .RDREM(RDR) ;YES,,IS IT THE DN200 READER ???
JRST GTJF.2 ;YES,,GO PROCESS IT
JRST GTJF.6 ] ;NO,,MUST BE DN60 READER (NO MTOPR)
GTJFN ;LOCAL,,ISSUE GTJFN NORMALLY
ERJMP .RETF ;NO GOOD,,SAY SO
$RETT ;ELSE RETURN OK
$CLOSF: SKIPE .RDREM(RDR) ;IS THIS A REMOTE READER ???
JRST [SKIPG .RDREM(RDR) ;YES,,IS IT THE DN200 READER ???
JRST CLOS.2 ;YES,,GO PROCESS IT
JRST CLOS.6 ] ;NO,,MUST BE DN60 READER (NO MTOPR)
CLOSF ;LOCAL,,ISSUE CLOSF NORMALLY
ERJMP .RETF ;NO GOOD,,SAY SO
$RETT ;ELSE RETURN OK
SUBTTL DN200 I/O SUPPORT ROUTINES
IFN FTRJE,<
GETE.2: MOVE S1,.RDJFN(RDR) ;GET THE JFN
MOVX S2,.MORST ;GET READ DEVICE STATUS FUNCTION
MOVEI T1,T2 ;GET ARG BLOCK ADDRESS
MOVEI T2,2 ;GET BLOCK LENGTH
SETZM T3 ;CLEAR ANSWER WORD
PUSHJ P,UMTOPR## ;ISSUE THE MTOPR
ERJMP INTERR ;NO GOOD,,FORGET IT
TXNE T3,MO%OL+MO%HEM+MO%SCK+MO%PCK+MO%RCK+MO%SER
MOVX S1,IOX5 ;ANY OF THE ABOVE,,SET I/O ERROR
TXNE T3,MO%EOF ;HARDWARE EOF ???
MOVX S1,IOX4 ;YES,,MAKE IT EOF
$RETT
SIN.2: SKIPE .RDOFL(RDR) ;IS THE READER OFFLINE ???
JRST SIN.T ;YES,,JUST RETURN
PUSHJ P,USIN## ;READ CARDS THROUGH NURD
ERJMP SIN.F ;RETURN FALSE ON AN ERROR
JRST SIN.T ;ELSE RETURN TRUE
OPEN.2: PUSHJ P,UOPENF## ;OPEN THE CARD READER THROUGH NURD
ERJMP .RETF ;CANT,,THATS AN ERROR
$RETT ;OK,,JUST RETURN
MTOP.2: PUSHJ P,UMTOPR## ;MAKE CALL VIA NURD
ERJMP .RETF ;NO GOOD,,SAY SO
$RETT ;ELSE RETURN OK
GTJF.2: PUSHJ P,UGTJFN## ;GET A JFN VIA NURD
ERJMP .RETF ;NO GOOD,,SAY SO
$RETT ;ELSE RETURN OK
CLOS.2: PUSHJ P,UCLOSF## ;CLOSE DOWN VIA NURD
ERJMP .RETF ;NO GOOD,,SAY SO
$RETT ;ELSE RETURN OK
>
IFE FTRJE,<
GETE.2:
SIN.2:
OPEN.2:
MTOP.2:
GTJF.2:
CLOS.2:
MOVX S1,DIAGX8 ;GET 'DEVICE DOES NOT EXIST'
MOVEM S1,.RDSTP(RDR) ;SAVE IT
MOVE S1,.RDSTR(RDR) ;GET OUR STREAM NUMBER
$WTO (DN200 Remote not Supported,,@JOBOBA(S1)) ;TELL OPERATOR
HALTF ;END IT ALL
>
SUBTTL DN60 I/O SUPPORT ROUTINES
IFN FTDN60,<
SIN.6: PUSHJ P,D60SIN## ;TRY TO READ SOME CARDS
JUMPT SIN.6C ;OK,,RETURN
CAIN S1,D6NBR ;WAS THE ERROR 'NON-BLOCKING RETURN' ?
JRST SIN.6C ;YES,,RETURN
CAIN S1,D6DOL ;IS THE ERROR 'DEVICE OFFLINE' ???
JRST SIN.6A ;YES,,GO PROCESS IT
CAIN S1,D6EOF ;IS THE ERROR 'END OF FILE' ???
JRST SIN.6B ;YES,,GO PROCESS IT
MOVE S2,.RDSTR(RDR) ;GET OUR STREAM NUMBER
$WTO ( DN60 I/O Error ,,@JOBOBA(S2)) ;TELL THE OPR
SOSG .RDECT(RDR) ;COUNT DOWN THE HARD ERRORS
JRST [SETOM .RDSHT(RDR) ;TOO MANY ERRORS,,LITE SHUTDOWN FLAG
$WTO( Too Many Device Errors ,,@JOBOBA(S2)) ;TELL OPR
HALTF ] ;AND SHUT US DOWN
SKIPA S1,[EXP IOX5] ;SKIP AND LOAD I/O ERROR CODE
SIN.6A: MOVX S1,OPNX8 ;LOAD 'DEVICE OFFLINE' ERROR CODE
SKIPA ;SKIP OVER EOF
SIN.6B: MOVX S1,IOX4 ;LOAD 'END OF FILE' ERROR CODE
MOVEM S1,.RDSTP(RDR) ;SAVE THE ERROR CODE FOR LATER
SKIPE .RDOFL(RDR) ;WERE WE OFFLINE BEFORE THIS CALL ???
$RETF ;YES,,JUST TAKE THE ERROR RETURN
SETOM .RDSTS(RDR) ;NO,,THEN SEND A STATUS MESSAGE
SETOM .RDOFL(RDR) ;WE CERTAINLY ARE OFFLINE NOW !!
PUSHJ P,CHKOFL ;PROCESS THE OFFLINE MESSAGE
$RETF ;TAKE THE ERROR RETURN
SIN.6C: SKIPE .RDOFL(RDR) ;WERE WE OFFLINE BEFORE THIS CALL ???
SETOM .RDSTS(RDR) ;YES,,THEN SEND A STATUS MESSAGE
SETZM .RDOFL(RDR) ;WE CERTAINLY ARE ONLINE NOW !!!
$RETT ;TAKE THE TRUE RETURN
GETE.6: MOVE S1,.RDSTP(RDR) ;GET THE LAST ERROR CODE
$RETT ;AND RETURN
GTJF.6: PUSHJ P,D60INI## ;INITIALIZE THE DN60 I/O PACKAGE
SETZM S1 ;NO JFN FOR DN60
$RETT ;RETURN OK
CLOS.6: MOVE S1,.RDJFN(RDR) ;GET JUST THE JFN
PUSHJ P,D60RLS## ;CLOSE DOWN VIA D60JSY
$RETT ;AND RETURN
;DN60 LINE CONDITIONING AND DEVICE OPENING ROUTINE
OPEN.6: MOVEI S1,.RDSUP(RDR) ;POINT TO OUR SETUP MESSAGE
PUSHJ P,D60CND## ;CONDITION THE FRONT END
MOVE S1,.RDSTR(RDR) ;GET OUR STREAM NUMBER
MOVE S1,JOBOBA(S1) ;AND GET OUT OBJECT BLOCK ADDRESS
JUMPT OPN.6A ;THE LINE CONDITIONING WON,,SKIP THIS
SETOM .RDSHT(RDR) ;INDICATE WE WERE SHUT DOWN
$WTO( Can't Condition Front End ,,0(S1)) ;TELL OPR
HALTF ;AND END IT HERE !!!
OPN.6A: MOVE S1,OBJ.UN(S1) ;GET OUR UNIT NUMBER
STORE S1,.RDOPB(RDR),OP$UNT ;SAVE THE UNIT NUMBER IN OPEN BLOCK
MOVX S1,.OPCDR ;WANT 'CDR' DEVICE
STORE S1,.RDOPB(RDR),OP$TYP ;SAVE THE DEVICE TYPE IN THE OPEN BLOCK
LOAD S1,.RDSUP+SUP.CN(RDR),CN$PRT ;GET THE PORT NUMBER
STORE S1,.RDOPB(RDR),OP$PRT ;SAVE IT IN THE OPEN BLOCK
LOAD S1,.RDSUP+SUP.CN(RDR),CN$LIN ;GET THE LINE NUMBER
STORE S1,.RDOPB(RDR),OP$LIN ;SAVE IT IN THE OPEN BLOCK
LOAD S1,.RDSUP+SUP.CN(RDR),CN$SIG ;GET THE LINE SIGNATURE
STORE S1,.RDOPB(RDR),OP$SIG ;SAVE IT IN THE OPEN BLOCK
MOVEI T1,^D60 ;GET A COUNT OF 60
OPN.6B: HRROI S1,-OP$SIZ ;GET THE NEGATIVE BLOCK LENGTH
MOVEI S2,.RDOPB(RDR) ;GET THE PARM BLOCK ADDRESS
PUSHJ P,D60OPN## ;OPEN THE READER
JUMPT OPN.6C ;THAT WINS,,CONTINUE ON
CAXE S1,D6DNU ;WAS THE ERROR 'DSR NOT UP' ???
$RETF ;NO,,TRASH THE REQUEST !!!
MOVEI S1,5 ;GET 5 SECONDS
PUSHJ P,I%SLP ;WAIT FOR DSR TO COME UP
SKIPE .RDSHT(RDR) ;HAVE WE BEEN SHUTDOWN ???
HALTF ;YES,,STOP
SOJGE T1,OPN.6B ;KEEP TRYING FOR 5 MINUTES
SETOM .RDSHT(RDR) ;INDICATE WE WERE SHUT DOWN
MOVE S1,.RDSTR(RDR) ;GET OUR STREAM NUMBER
$WTO ( Does Not Exist ,,@JOBOBA(S1)) ;TELL OPR
HALTF ;END IT ALL
OPN.6C: MOVEM S1,.RDJFN(RDR) ;SAVE THE CDR HANDLE
LOAD S1,.RDFLG(RDR),NT.TYP ;GET THE REMOTE TYPE
CAXE S1,DF.HSP ;IS IT HASP ???
$RETT ;NO,,JUST RETURN
HRLZI S1,.OPCIN ;YES,,GET OPR CONSOLE ID
STORE S1,.RDOPB(RDR),OP$DEV ;SAVE IT IN THE OPEN BLOCK
HRROI S1,-OP$SIZ ;GET THE NEGATIVE BLOCK LENGTH
MOVEI S2,.RDOPB(RDR) ;GET THE BLOCK ADDRESS
PUSHJ P,D60OPN## ;OPEN THE OPERATORS CONSOLE
JUMPF .RETF ;CANT,,THATS AN ERROR
MOVEM S1,.RDN60(RDR) ;SAVE THE OPR CONSOLE JFN
$RETT ;AND RETURN
;ROUTINE TO READ THE HASP OPERATORS CONSOLE
GETHSP: LOAD S1,.RDFLG(RDR),NT.TYP ;GET THE STATION TYPE
SKIPLE .RDREM(RDR) ;IS IT A DN60 TYPE REMOTE ???
CAXE S1,DF.HSP ;YES,,IS IT A HASP REMOTE ???
$RETT ;NOT DN60/NOT HASP,,RETURN NOW
MOVE S1,.RDN60(RDR) ;GET THE HASP CONSOLE JFN
MOVE S2,[POINT 7,.CARDS(RDR)] ;GET THE INPUT BUFFER BYTE POINTER
HRROI T1,-^D140 ;GET A LARGE BYTE COUNT
PUSHJ P,D60SIN## ;READ THE HASP OPERATORS CONSOLE
SKIPF ;IF THE READ FAILED
CAMN S2,[POINT 7,.CARDS(RDR)] ; OR NO DATA WAS READ
$RETT ; THEN JUST RETURN
MOVE S1,[POINT 7,.CARDS(RDR)] ;GET OUR INPUT BYTE POINTER BACK
PUSHJ P,OPRCMD ;GO PROCESS THE OPERATOR COMMAND
$RETT ;AND RETURN
>
IFE FTDN60,<
GETE.6:
SIN.6:
OPEN.6:
GTJF.6:
CLOS.6:
GETHSP:
MOVX S1,DIAGX8 ;GET 'DEVICE DOES NOT EXIST'
MOVEM S1,.RDSTP(RDR) ;SAVE IT
MOVE S1,.RDSTR(RDR) ;GET OUR STREAM NUMBER
$WTO (DN60 Type Remote not Supported,,@JOBOBA(S1)) ;TELL OPERATOR
HALTF ;END IT ALL
>
> ;END OF TOPS-20 CONDITIONAL CODE
SUBTTL READER - ROUTINE TO PROCESS THE INPUT CARDS.
READER: SKIPN .RDNBR(RDR) ;ARE THERE ANY CARDS THERE ???
JRST READ.4 ;NO,,JUST RETURN
PUSHJ P,.SAVE1 ;YES,,SAVE P1
HRLZ P1,.RDOBZ(RDR) ;GET THE CORRECT BYTE SIZE
LSH P1,6 ;POSITION SIZE FOR BYTE POINTER
ADD P1,[POINT 0,.CARDS(RDR)] ;COMBINE THE BYTE PTR & BYTE SIZE
MOVEM P1,.RDIPT(RDR) ;SAVE IT THE FIRST TIME THROUTH
READ.2: GETBYT S1,P1 ;GET A BYTE
HRRI S2,@P1 ;GET THE CARD STARTING ADDRESS
MOVEM S2,.RDCAD(RDR) ;SAVE IT FOR LATER
CAMN S1,$IMAGE(AP) ;IS IT A $ SIGN ???
JRST $CARD ;YES,,GO PROCESS IT
CAMN S1,ENDIMG(AP) ;IS IT AN EOF CARD ???
JRST ENDCRD ;YES,,GO PROCESS IT.
TXNN FLAG,JOBCD ;IS THERE A JOB SETUP ???
JRST REJECT ;NO,,REJECT THE CARD.
PUSHJ P,OUTCRD ;ELSE PUT OUT THE CARD.
READ.3: MOVE P1,.RDRCL(RDR) ;GET THE RECORD LENGTH IN BYTES
ADJBP P1,.RDIPT(RDR) ;POINT TO THE NEXT CARD
MOVEM P1,.RDIPT(RDR) ;SAVE THE POINTER FOR LATER
SOSLE .RDNBR(RDR) ;SUB 1 FROM CARD COUNT
JRST READ.2 ;MORE,,CONTINUE
READ.4: SETZM .RDNBR(RDR) ;ZERO THE NUMBER OF CARDS COUNTER
HRLZ S1,.RDOBZ(RDR) ;GET THE OUTPUT BYTE SIZE
LSH S1,6 ;POSITION IT
ADD S1,[POINT 0,.CARDS(RDR)] ;MAKE IT A BYTE POINTER
MOVEM S1,.RDOPT(RDR) ;AND SAVE IT
$RETT ;RETURN.
SUBTTL $CARD - ROUTINE TO PROCESS $ CARDS
$CARD: GETBYT S1,P1 ;GET A BYTE
CAME S1,JIMGUC(AP) ;IS IT A 'J' ??
CAMN S1,JIMGLC(AP) ;IS IT 'j' ???
JRST JOBCRD ;YES TO EITHER,,PROCESS JOB CARD.
CAME S1,EIMGUC(AP) ;IS IT A 'E' ???
CAMN S1,EIMGLC(AP) ;IS IT A 'e' ???
JRST EOJCRD ;YES TO EITHER,,PROCESS EOJ CARD.
CAMN S1,$IMAGE(AP) ;IS IT A COMMAND ??? ($$??)
JRST COMMAND ;YES,,GO PROCESS IT.
TXNN FLAG,JOBCD ;IS THERE A JOB SETUP ???
JRST REJECT ;NO,,REJECT IT.
PUSHJ P,OUTCRD ;ELSE WRITE IT OUT
JRST READ.3 ;AND CONTINUE
REJECT: TXZN FLAG,EOF ;REJECTING AN EOF GENERATED CARD ???
AOS .RDREJ(RDR) ;NO,,BUMP REJECT COUNT.
JRST READ.3 ;AND GO PROCESS IT.
SUBTTL JOBCRD - ROUTINE TO PROCESS A JOB CARD.
JOBCRD: GETBYT S1,P1 ;GET A BYTE.
CAME S1,OIMGUC(AP) ;IS IT A 'O' ???
CAMN S1,OIMGLC(AP) ;IS IT A 'o' ???
SKIPA ;YES,,KEEP ON GOING
JRST REJECT ;ELSE REJECT IT.
GETBYT S1,P1 ;GET THE NEXT BYTE.
CAME S1,BIMGUC(AP) ;IS IT A 'B' ???
CAMN S1,BIMGLC(AP) ;IS IT A 'b' ???
SKIPA ;YES,,KEEP ON GOING
JRST REJECT ;ELSE REJECT IT.
GETBYT S1,P1 ;GET THE NEXT BYTE.
CAME S1,BLANK(AP) ;IS IT A BLANK ???
JRST REJECT ;NO,,REJECT IT
AOS .RDJBC(RDR) ;BUMP JOB COUNT BY 1.
TXNE FLAG,JOBCD ;IS THE JOBCARD BIT ON ???
PUSHJ P,CREATE ;GO SEND CREATE MSG FOR THE LAST JOB.
TXO FLAG,JOBCD ;TURN ON THE JOB CARD BIT.
MOVEI S1,2 ;GET AN ERROR COUNT OF 2
MOVEM S1,.RDECT(RDR) ;SAVE IT FOR LATER
PUSHJ P,I%NOW ;GET THE TIME.
MOVEM S1,.RDTIM(RDR) ;SAVE AS JOB START TIME
MOVE S1,.RDSTR(RDR) ;GET THE STREAM NUMBER
SKIPE S2,.RDREJ(RDR) ;ANY REJECTED CARDS ???
$WTO (< ^D/S2/ Cards Flushed >,,@JOBOBA(S1)) ;YES,,TELL OPERATOR
SETZM .RDREJ(RDR) ;ZERO THE REJECT COUNT
PUSHJ P,GETFIL ;GO SETUP THE OUTPUT SPOOL FILE
PUSHJ P,OUTCRD ;PUT IT OUT
JRST READ.3 ;AND GO PROCESS THE NEXT CARD.
SUBTTL EOJCRD - ROUTINE TO PROCESS $EOJ CARDS.
EOJCRD: TXNN FLAG,JOBCD ;IS THERE A JOB SETUP ???
JRST REJECT ;NO,,REJECT THIS CARD.
GETBYT S1,P1 ;GET THE NEXT BYTE
CAME S1,OIMGUC(AP) ;IS IT A 'O' ???
CAMN S1,OIMGLC(AP) ;IS IT A 'o' ???
SKIPA ;YES,,KEEP ON GOING
JRST REJECT ;ELSE REJECT IT.
GETBYT S1,P1 ;GET THE NEXT BYTE.
CAME S1,JIMGUC(AP) ;IS IT A 'J' ???
CAMN S1,JIMGLC(AP) ;IS IT A 'j' ???
SKIPA ;YES,,KEEP ON GOING
JRST EODCRD ;ELSE CHECK FOR 'EOD'.
GETBYT S1,P1 ;GET THE NEXT BYTE
CAME S1,BLANK(AP) ;IS IT A BLANK ???
JRST REJECT ;NO,,REJECT IT
AOS .RDEOJ(RDR) ;BUMP END OF JOB COUNT BY 1
PUSHJ P,OUTCRD ;PUT IT OUT
PUSHJ P,CREATE ;SEND THE CREATE MSG OFF
JRST READ.3 ;AND CONTINUE PROCESSING
EODCRD: PUSHJ P,OUTCRD ;PUT IT OUT...
JRST READ.3 ;GO PROCESS THE NEXT CARD
SUBTTL ENDCRD - ROUTINE TO PROCESS END-OF-FILE CARDS
ENDCRD: AOS .RDEND(RDR) ;BUMP END CARD COUNT BY 1
TXNN FLAG,JOBCD ;IS THERE A JOB SETUP ???
JRST REJECT ;NO,,REJECT THIS CARD
PUSHJ P,CREATE ;GO SEND A CREATE MSG
JRST READ.3 ;AND GO GET THE NEXT CARD
SUBTTL COMMAND - ROUTINE TO PROCESS THE $$ COMMAND FOR OPR
COMMAND: TXNE FLAG,JOBCD ;ARE WE IN A JOB ???
JRST COMM.1 ;YES,,THEN JUST OUTPUT THE CARD
SKIPG .RDREM(RDR) ;IS THIS A DN60 REMOTE STATION ???
JRST REJECT ;NO,,REJECT THE CARD
MOVE S1,P1 ;GET THE CARD BYTE POINTER
PUSHJ P,OPRCMD ;GO PROCESS THE CARD
JRST READ.3 ;AND CONTINUE ON
COMM.1: PUSHJ P,OUTCRD ;OUTPUT THE CARD
JRST READ.3 ;AND CONTINUE ON
SUBTTL OPRCMD - ROUTINE TO GENERATE AN OPR COMMAND MESSAGE
;CALL: S1/ Byte Pointer to the Operator message terminated by a CRLF
;
;RET: True Always
OPRCMD: PUSHJ P,.SAVE2 ;SAVE P1 & P2 FOR A MINUTE
MOVE P1,S1 ;SAVE THE INPUT BYTE POINTER ALSO
PUSHJ P,M%GPAG ;GET A PAGE FOR THE MESSAGE
PUSH P,S1 ;SAVE THE PAGE ADDRESS
MOVE P2,S1 ;HERE ALSO
MOVX S1,.OMD60 ;GET THE MESSAGE TYPE
STORE S1,.MSTYP(P2),MS.TYP ;SAVE IT IN THE MESSAGE
MOVEI S1,3 ;GET THE BLOCK COUNT
MOVEM S1,.OARGC(P2) ;SAVE IT IN THE MESSAGE
MOVEI P2,.OHDRS(P2) ;GET THE FIRST BLOCK ADDRESS
MOVE S1,[2,,.ORNOD] ;GET THE FIRST BLOCK HEADER
MOVEM S1,ARG.HD(P2) ;SAVE IT IN THE MESSAGE
MOVE S1,.RDSTR(RDR) ;GET OUR STREAM NUMBER
MOVE S1,JOBOBA(S1) ;GET OUR OBJECT BLOCK ADDRESS
MOVE S1,OBJ.ND(S1) ;GET OUR NODE NAME IN SIXBIT
MOVEM S1,ARG.DA(P2) ;SAVE IT IN THE MESSAGE
ADDI P2,2 ;POINT TO THE NEXT BLOCK
MOVE S1,[3,,.ORD60] ;GET THE NEXT BLOCK HEADER
MOVEM S1,ARG.HD(P2) ;SAVE IT IN THE MESSAGE
LOAD S1,.RDSUP+SUP.CN(RDR),CN$PRT ;GET THE PORT NUMBER
HRLM S1,ARG.DA(P2) ;SAVE IT IN THE MSG DATA BLOCK
LOAD S1,.RDSUP+SUP.CN(RDR),CN$LIN ;GET THE LINE NUMBER
HRRM S1,ARG.DA(P2) ;SAVE IT IN THE MSG DATA BLOCK
LOAD S1,.RDFLG(RDR) ;GET THE FLAG BITS
MOVEM S1,ARG.DA+1(RDR) ;SAVE IT IN THE MSG DATA BLOCK
ADDI P2,3 ;POINT TO THE NEXT BLOCK
MOVX S1,.CMTXT ;GET THE BLOCK TYPE
MOVEM S1,ARG.HD(P2) ;SAVE IT IN THE MESSAGE
MOVE S1,[POINT 7,ARG.DA(P2)] ;GET THE OUTPUT BYTE POINTER
OPRC.1: ILDB S2,P1 ;GET A TEXT BYTE
IDPB S2,S1 ;SAVE IT IN THE MESSAGE
CAIE S2,12 ;IS IT THE LINE FEED ???
JRST OPRC.1 ;NO,,KEEP GOING TILL WE FIND ONE
MOVEI S1,@S1 ;GET THE ENDING ADDRESS
POP P,S2 ;RESTORE OUR STARTING ADDRESS
SUBI S1,-1(S2) ;CALC THE TOTAL MESSAGE LENGTH
STORE S1,.MSTYP(S2),MS.CNT ;SAVE THE MESSAGE LENGTH
SUBI S1,^D10 ;CALC THE LENGTH OF THE TEXT BLOCK
STORE S1,ARG.HD+^D10(S2),AR.LEN ;SAVE IT IN THE MESSAGE
LOAD S1,.MSTYP(S2),MS.CNT ;GET THE MESSAGE LENGTH IN S1
EXCH S1,S2 ;GET ADDRESS IN S1 AND LENGTH IN S2
PUSHJ P,SNDOPR ;SEND THE MESSAGE OFF
$RETT ;AND RETURN
SUBTTL GETFIL - ROUTINE TO CREATE AN OUTPUT SPOOL FILE
GETFIL: PUSHJ P,GENFIL ;GO GENERATE THE SPOOL FILENAME
MOVEI S1,2 ;GET FOB SIZE
MOVEI S2,.RDFOB(RDR) ;GET FOB ADDRESS
PUSHJ P,F%OOPN ;OPEN THE SPOOL FILE
JUMPT GETF.1 ;IF OK,,CONTINUE ON
CAIE S1,ERFAE$ ;IS THE ERROR 'FILE-ALREADY-EXISTS' ?
$STOP(COS,CANNOT OPEN SPOOL FILE) ;NO,,THEN ITS A FATAL ERROR
MOVE S1,FILENM ;GET THE FILE NAME HASH CODE
ANDI S1,FILEMK ;GET THE GOOD PART
CAIG S1,17500 ;IS IT LESS THEN 8000 (DECIMAL) ??
JRST GETFIL ;YES,,TRY THE NEXT FILE NAME
SETZM FILENM ;CREATE A NEW HASH CODE
AOS FILEXT ;AND A NEW EXTENSION
JRST GETF.1 ;AND TRY AGAIN
GETF.1: MOVEM S1,.RDIFN(RDR) ;SAVE THE IFN
$RETT ;AND RETURN
SUBTTL OUTCRD - ROUTINE TO OUTPUT A CARD.
OUTCRD: AOS .RDJBT(RDR) ;BUMP JOB CARD COUNT BY 1
SKIPLE .RDREM(RDR) ;IS IT LOCAL OR DN200 ???
JRST OUTD60 ;NO,,MUST BE DN60 !!!
MOVE S1,.RDIFN(RDR) ;GET THE SPOOL FILE IFN
HRL S2,.RDRCL(RDR) ;GET THE RECORD LENGTH
HRR S2,.RDCAD(RDR) ;GET THE CARD ADDRESS.
PUSHJ P,F%OBUF ;WRITE OUT THE CARD
JUMPT .RETT ;IF OK,,RETURN
$STOP(EWS,ERROR WRITING SPOOL FILE)
OUTD60: PUSHJ P,.SAVE2 ;SAVE P1 & P2 FOR A MINUTE
MOVE P1,.RDIPT(RDR) ;GET THE RECORD POINTER
MOVE P2,.RDRCL(RDR) ;GET THE RECORD LENGTH IN BYTES
OUTD.1: MOVE S1,.RDIFN(RDR) ;GET THE SPOOL FILE IFN
ILDB S2,P1 ;GET A BYTE
PUSHJ P,F%OBYT ;PUT IT OUT
JUMPF S..EWS ;CANT,,FORGET IT !!!
SOJG P2,OUTD.1 ;CONTINUE TILL DONE
$RETT ;AND RETURN
SUBTTL CREATE - ROUTINE TO GENERATE A CREATE MESSAGE FOR QUASAR
CREATE: MOVE S1,.RDIFN(RDR) ;GET THE FILE IFN
PUSHJ P,F%REL ;RELEASE THE IFN AND CLOSE THE FILE.
SKIPT ;IF OK,,CONTINUE
$STOP(CCS,CANNOT CLOSE SPOOL FILE) ;ELSE COMMIT SUICIDE
PUSHJ P,.SAVE1 ;SAVE P1 FOR A MINUTE
PUSHJ P,M%ACQP ;ACQUIRE PAGE FOR MESSAGE TO QUASAR
PG2ADR S1 ;CONVERT PAGE NUMBER TO ADDRESS
MOVEM S1,P1 ;SAVE IN MES (AC FOR EQ ENTRY)
MOVEI S1,<EQHSIZ+FPMSIZ+FDSIZE> ;SIZE OF FULL MESSAGE
STORE S1,.MSTYP(P1),MS.CNT ;SAVE IN HEADER FOR SIZE
MOVEI S1,.QOCRE ;CREATE INDICATOR TYPE
STORE S1,.MSTYP(P1),MS.TYP ;PLACE TYPE IN HEADER
MOVEI S1,%%.QSR ;QUASAR VERSION NUMBER
STORE S1,.EQLEN(P1),EQ.VRS ;SAVE VERSION NUMBER IN EQ
MOVEI S1,EQHSIZ ;EQ HEADER SIZE
STORE S1,.EQLEN(P1),EQ.LOH ;LENGTH OF HEADER FIELD
MOVX S1,<.OTBIN> ;BATCH INPUT QUEUE (SPRINT)
STORE S1,.EQROB+.ROBTY(P1) ;SAVE IN OBJECT TYPE
MOVE S1,CNTSTA ;GET THIS NODES ID
MOVEM S1,.EQROB+.ROBND(P1) ;SAVE NODE IN MESSAGE
CREA.1: MOVEI S1,1 ;NUMBER OF FILES IN REQUEST
STORE S1,.EQSPC(P1),EQ.NUM ;STORE IN EQ
MOVEI S1,FPMSIZ ;SIZE OF THE FP
STORE S1,<EQHSIZ+.FPLEN>(P1),FP.LEN ;FP HEADER SIZE
MOVSI S1,.RDFD(RDR) ;BEGIN OF FD (OLD FD)
HRRI S1,<EQHSIZ+FPMSIZ>(P1) ;DESTINATION ADDRESS
BLT S1,<EQHSIZ+FPMSIZ+FDSIZE-1>(P1) ;MOVE THE FD
MOVEI S2,EQHSIZ(P1) ;GET THE FP ADDRESS IN S2
MOVEI S1,.RDRCL(RDR) ;GET CARD SIZE OF DATA
STORE S1,.FPINF(S2),FP.RCL ;SAVE THE RECORD LENGTH
MOVEI S1,.FPFAI ;GET THE AUGMENTED IMAGE MODE BITS
SKIPLE .RDREM(RDR) ;UNLESS THIS IS A DN60 READER
MOVEI S1,.FPFSA ; THEN MAKE IT ASCII MODE
STORE S1,.FPINF(S2),FP.RCF ;SAVE THE RECORD FORMAT
MOVE S1,.RDJBT(RDR) ;CARD COUNT FOR JOB
STORE S1,.FPRCD(S2) ;SAVE THE NUMBER OF RECORDS
MOVEI S1,1 ;GET A ONE.....
STORE S1,.FPINF(S2),FP.SPL ;LITE THE SPOOLED FILE BIT
STORE S1,.FPINF(S2),FP.PCR ;SET PHYSICAL CARD READER BIT
STOLIM S1,.EQLIM(P1),CJOB ;ALSO 1 JOB PER FILE (FOR NOW)
MOVE S1,.RDTIM(RDR) ;GET START TIME OF JOB
STOLIM S1,.EQLIM(P1),CTIM ;SAVE START TIME OF JOB
MOVE S1,.RDSTR(RDR) ;GET THE STREAM NUMBER
MOVE S2,JOBOBA(S1) ;GET OUR OBJECT BLOCK ADDRESS
MOVE S2,OBJ.ND(S2) ;GET OUR NODE NAME
STOLIM S2,.EQLIM(P1),CNOD ;SAVE AS THE DESTINATION NODE
$WTO (< 1 Job: ^D/.RDJBT(RDR)/ Cards Spooled >,,@JOBOBA(S1))
AOS .RDIPC(RDR) ;COUNT OF MESSAGES SENT
TXZ FLAG,JOBCD ;TURN OFF THE JOB CARD BIT
SETZM .RDJBT(RDR) ;ZERO THE JOB CARD COUNT
MOVE S1,P1 ;PUT THE MSG ADDRESS INTO S1.
MOVEI S2,1000 ;PUT THE LENGTH IN S2.
PJRST SENDIT ;GO SEND IT OFF AND RETURN
END CDRIVE