.MCALL .MODULE .MODULE QUEUE,VERSION=10,AUDIT=YES ; Copyright (c) 1998 by Mentec, Inc., Nashua, NH. ; All rights reserved ; ; This software is furnished under a license for use only on a ; single computer system and may be copied only 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 except for use on such ; system and to one who agrees to these license terms. Title ; to and ownership of the software shall at all times remain ; in Mentec, Inc. ; ; The information in this document is subject to change without ; notice and should not be construed as a commitment by Digital ; Equipment Corporation, or Mentec, Inc. ; ; Digital and Mentec assume no responsibility for the use or ; reliability of its software on equipment which is not supplied ; by Digital or Mentec, and listed in the Software Product ; Description. ; ; Edit Who Date Description of modification ; ---- --- ---- --------------------------- ; 001 WLD 19-MAR-1991 Fixed problem writing contents ; of LASTWD to output. When output ; device is mag tape, FSM rounds up ; any .WRITEx to 256. words. Calling ; the PRINT subroutine in QUEUE with a ; transfer length of one word causes ; the 510. bytes after LASTWD to be ; dumped to tape. ; ; 002 Tim 31-Mar-1997 Handle 4-digit dates on the ; Shoppa banner page. ;-- .SBTTL RT-11 DEVICE QUEUE .ENABL LC,GBL ; RT-11 DEVICE QUEUE SYSTEM - FOREGROUND I/O AND QUEUE MANAGEMENT PROGRAM ; ; VERSION: 5.0 ; ; AUTHOR: LES PARENT - JUNE, 1979 for RT-11 Version 4.0 ; ; V5 CHANGES: -Individual file output to file structured devices - LCP 12/80 ; -Optimized for MT (doesn't rewind) - LCP 12/80 ; -Fixed KILL bug - LCP 12/80 ; -Fixed R50ASC bug - LCP 12/80 ; -Protect input file while de-spooling - LCP 6/81 ; -Fixed /S,/R Bug - LCP 6/81 ; -Fixed # copies formatting bug - LCP 6/82 ; -Fixed unprotect input file bug - LCP 6/82 ; EDIT ; date author comment ; ; 03-SEP-82 C.A. - Add .SERR to allow queue of protected drive ; ; 21-DEC-82 C.A. - Check that the version of RT11 running is the ; desired one. ; ; 22-DEC-82 C.A. - Fix problem removing jobs from queue. ; ; 07-JAN-83 C.A. - Handle the case from queman of /H w/o a value. ; ; 13-JAN-83 C.A. - After error "Cannot open output device" the input ; channel must be purged. ; ; 21-FEB-83 C.A. - On routine QUACK: change order of CALL UPDATE and ; CALL QUEMSG to prevent problems on QUEMAN /A ; ; 22-AUG-84 G.T. - Ensure that only write-only devices get a CR ; appended at the end of a file. ; ; 08-Jun-89 R.H. - Replace .RENAME protection mechanism with ; new V5.5 .SFSTA request. ; ; 16-May-90 WFG - Fix SHOW QUEUE display problem (ACTION #5801) ; ; 01-Nov-1990 JFW - bracket error messages with ;+/;ERROR/.../;- .SBTTL QUEUE - MACRO SYSTEM DEFINITIONS .MCALL .ASSUME .ENTER .EXIT .CLOSE .CMKT .DATE .MCALL .DELETE .DSTATU .GTIM .GVAL .HERR .LOOKUP .MCALL .MRKT .MWAIT .PRINT .PURGE .QSET .RCVDC .MCALL .RENAME .READC .READ .READW .RSUM .SCCA .MCALL .SDAT .SERR .SFSTA .SPND .WAIT .WRITC .MCALL .WRITE .WRITW .SPFUN ...CMV .MACRO CHAR NAME,LIST ;**-1 .IRP X, .BYTE X*4.+1 . = . + 35. .ENDR . = .- <7*36.> + 1 .ENDM .SBTTL QUEUE - SOME REMARKS, OR "HOW THIS PROGRAM WORKS" ;SOME REMARKS ABOUT HOW THIS PROGRAM OPERATES... ;"QUEUE" is a foreground program which provides the ability to queue ;output to any RT-11 device. It can be run as the Foreground Job or ;as a System Job. ; ;QUEUE is intended to work in co-operation with a Background Job, ;specifically QUEMAN.SAV. ;QUEUE performs 2 major functions: ; ; 1. Accept Job Requests & maintain a FIFO queue on disk ; ; 2. Perform I/O transfers to specified output devices ; ;To accomplish this, QUEUE is organized into a Mainline program and ;several completion routines, so that these functions may execute ;"simultaneously". The Mainline code initializes itself and the queue ;disk file, opens a message channel to the BG (or other jobs) and ;suspends itself. Messages are directed to a completion routine which ;checks their validity and wakes up the mainline. The mainline processes ;the messages, which point to "Job Requests" and a list of "File Requests" ;located in the body of the sending job. These requests are processed ;by the mainline and enqueued in the workfile. If I/O is quiescent, ;it is started by the first Job Request, otherwise requests are merely ;enqueued and the mainline suspends itself again. ; ;I/O transfers are maintained by another completion routine until an ;End-of-File condition is reached on the input channel, whereupon the ;completion routine resumes the mainline. The mainline extracts the ;next File Request (if any) from the queue, starts the I/O transfer ;again and suspends. When the queue is exhausted, the mainline simply ;suspends waiting for Job Request Messages. ; ;QUEUE disables double control-c action in the Monitor and checks to ;see if a double control-c has been typed at the console after each ;I/O block transfer if I/O is in progress or every 5 seconds if the ;mainline is suspended (a third completion routine acts as the double ;control-c "watchdog" in this event, executing a .MRKT to itself every ;5 seconds). ; ;QUEUE can precede output files with "Banner Pages" which include the ;file name in B I G letters and a "trailer" specifying the Job Name, ;date & time stamps, file name and whether or not the input file is to ;be deleted after output. ; ;QUEUE is auto-restartable; that is if QUEUE is killed from the console ;or the system crashes for some other reason, running QUEUE again will ;cause it to restart output with the file it was processing at the time ;of the crash or program termination (this is true as long as the queue ;workfile is a PERMANENT entry and hasn't been opened with a .ENTER !). .SBTTL QUEUE - LOCAL DEFINITIONS VERSIO = 5 ;CURRENT VERSION OF RT11 ; JOB/FILE REQUEST BLOCK & QUEUE ELEMENT OFFSETS QNCOP =: 2 ;# OF COPIES (BYTE OFFSET) QNBAN =: 3 ;# OF BANNERS (BYTE OFFSET) QDEVIC =: 4 ;I/O DEVICE (RAD50) QLJBNM =: 6 ;LOGICAL JOB NAME (2 WDS OF RAD50) QFILNM =: 6 ;INPUT FILE NAME (" " " " ) QNFILZ =: 12 ;# OF INPUT FILES QBLINK =: 16 ;LINK TO PREVIOUS JOB REQUEST IN QUEUE ; REQUEST ACKNOWLEDGEMENT MESSAGE OFFSETS QMJBNM =: 2 ;LOGICAL JOB NAME (3 WDS ASCII) QMADDR =: 10 ;ADDRESS OF JOB/FILE REQUEST BLOCKS QMCCHN =: 10 ;QUEUE WORKFILE CHANNEL # QMCBLK =: 12 ;CONTROL BLOCK BLK # ; FLAG WORD BIT DEFINITIONS - JOB/FILE REQUEST FLG.DE =: 1 ;DELETE FILE AFTER OUTPUT FLG.CP =: 2 ;MAKE MULTIPLE COPIES FLG.HD =: 4 ;PRECEDE OUTPUT WITH BANNER PAGES FLG.JR =: 10 ;THIS IS A JOB REQUEST MESSAGE/BLOCK FLG.KL =: 100 ;REMOVE ("KILL") JOB/FILE FROM QUEUE FLG.SP =: 400 ;SET DEFAULT PARAMETERS FLG.SU =: 1000 ;SUSPEND OUTPUT AFTER CURRENT REQUEST FINISHES FLG.RS =: 2000 ;RESUME SUSPENDED OUTPUT/ RESTART OUTPUT FLG.AB =: 100000 ;ABORT QUEUE IMMEDIATELY !!! ; FLAG WORD BIT DEFINITIONS - NEGATIVE ACKNOWLEDGEMENT FLG.IR =: 100001 ;ILLEGAL JOB REQUEST FLG.QF =: 100002 ;NO ROOM IN QUEUE FOR REQUUEST FLG.NQ =: 100004 ;QUEUE BEING ABORTED FROM CONSOLE QLGLSW =: FLG.DE+FLG.CP+FLG.HD+FLG.JR ;LEGAL SWITS FOR A JOB ;THAT'S NOT 'QUEMAN' ; MISCELLANEOUS LF =: 12 ;CONTROL CHARACTERS FF =: 14 CR =: 15 SPACE =: 40 ;ASCII BUFSZ =: 256. ;SIZE OF I/O BUFFER OUTCH =: 1 ;OUTPUT CHANNEL # INPCH =: 2 ;INPUT CHANNEL # QBLKS =: 5 ;# OF BLOCKS IN QUEUE WORKFILE (DEFAULT) E.STAT =: 0 ;OFFSET TO STATUS WORD IN DIRECTORY ENTRY E.PROT =: 100000 ;FILE PROTECTION BIT E.DATE =: 14 ;OFFSET TO DATE WORD IN DIRECTORY ENTRY C.BIC =: 1 ; Code for BIC operation C.BIS =: 2 ; Code for BIS operation USRSWP =: 46 ;USR SWAP ADDRESS $ERRBY =: 52 ;ERROR BYTE $SYPTR =: 54 ;$RMON ADDRESS $SYSVE =: 276 ;BYTE CONTAINING SYSTEM VERSION NUMBER $CNFG1 =: 300 ;OFFSET OF 1ST CONFIG WORD CLK50$ =: 40 ;50 HZ CLOCK BIT IN $CNFG1 QUEUE$ =: 2000 ;FG QUEUE RUNNING BIT IN $CNFG1 $SYSGE =: 372 ;OFFSET OF SYSGEN OPTIONS WORD STASK$ =: 40000 ;SYSTEM JOB OPTION BIT IN SYSGEN WORD EOF$ =: 20000 ;EOF BIT IN CSW ; DSTATUS codes FILST$ =: 100000 ; Random-Access Device RONLY$ =: 40000 ; Device is READ_ONLY WONLY$ =: 20000 ; Device is WRITE_ONLY SPECL$ =: 10000 ; Special Directory Device HNDLR$ =: 4000 ; Abort/Exit bit 1 SPFUN$ =: 2000 ; Device handler does SPFUNS ABORT$ =: 1000 ; Abort/Exit bit 2 VARSZ$ =: 400 ; Variable Size Device LOOK.. =: 3 ; LOOKUP code for SPECL$ handlers SF.USR =: 354 ; ASYNC Lookup on magtape .SBTTL QUEUE - EMT ARGUMENT BLOCKS, FILE DESCRIPTORS, BUFFERS, ETC. .PSECT QDATA ;THIS DATA *MUST* BE OUTSIDE USR SWAP SPACE !!! .NLIST BEX QSIZE:: .WORD QBLKS ;# OF BLOCKS IN QUEUE WORK FILE **USER PATCHABLE** QRMSG: .WORD 0 ;JOB REQUEST MESSAGE BLOCK (WORD COUNT) QRMSG1: .BLKW 6 ;ACTUAL JOB REQ MESSAGE QAMSG: .WORD 0 ;REQUEST ACKNOWLEDGE MESSAGE BLOCK .NLCSI PART=NAME,TYPE=Z .WORD 0,0 QSYT$K: .WORD 0 ;SYSGEN OPTION MASK (NEED TO KNOW IF SYSTEM TASK;001 QSCCA: .WORD 0 ;^C^C STATUS WORD QTIME: .WORD 0,60.*5. ;^C WATCHDOG TIMEOUT (5 SEC) QELEM: .BLKW 10.*3 ;EXTRA RT-11 Q-ELEMENTS CAREA: .WORD 0,0 ;COMPLETION I/O EMT ARGUMENT BLOCK .WORD IOBUFF .WORD BUFSZ .WORD 0 MAREA: .BLKW 5 ;GENERAL MAINLINE EMTS QAREA: .WORD 0,0 ;QUEUE WORKFILE I/O EMTS .WORD QBUFF .WORD 256. .WORD 0 TAREA: .WORD 0 ;MRKT EMT ARGUMENT BLOCK .WORD QTIME .WORD QWATCH ;4TH WD = SEQ# = DON'T CARE! QJBLK: .RAD50 /MQ/ ;OPEN MESSAGE CHANNEL JOB BLOCK FOR SYT$K MONITORS .WORD 0,0,0 ;"NULL" LOGICAL JOB NAME QDBLK:: .RAD50 /SY/ ;QUEUE WORKFILE DESCRIPTOR BLOCK **PATCH** .RAD50 /QUFILE/ .RAD50 /WRK/ PSTAT: .WORD 0 ;File protection status JDBLK: .BLKW 8. ;JOB DESCRIPTOR (FOR OUTPUT .LOOKUP/.ENTER) ;REPLICA OF JOB REQUEST BLOCK FDBLK: .BLKW 4. ;FILE DESCRIPTOR (FOR INPUT .LOOKUP) IOERR: .BYTE 0,0 ;I/O ERROR BYTE (2ND BYTE RESERVED) IOBUFF: .BLKW BUFSZ ;I/O XFER BUFFER NFSBLK: .WORD 0,0,0,0 ; Non-file-structured LOOKUP block ASYBLK: .WORD 0,0,0 ; ASYNC SPFUN block .WORD LOOK.. .WORD -1 .WORD 0,0 ERRBLK: .WORD 0,0,0,0 .SBTTL QUEUE - COMPLETION ROUTINES .PSECT QCOMPL ;+ ; QMESSG - THIS COMPLETION ROUTINE EXECUTES WHENEVER A JOB REQUEST ; MESSAGE IS SENT TO QUEUE. AFTER VERIFYING THE MESSAGE ; IT AWAKENS THE MAINLINE CODE.: ;- QMESSG::TST QSCCA ;DOUBLE CTRL-C TYPED? BNE 10$ ;YES...JUST WAKE UP MAINLINE MOV #QRMSG1,R1 ;R1 => 1ST WORD OF MSG BIT #FLG.JR,(R1) ;JOB REQUEST FLAG ON? BEQ 9$ ;NO - ERROR CMP 2(R1),(PC)+ ;SEE IF MESSAGE IS FROM "QUEMAN" .WORD "QU BNE 5$ ;NO... CMP 4(R1),(PC)+ .WORD "EM BNE 5$ ;NO... CMP 6(R1),(PC)+ .WORD "AN BEQ 10$ ;YES ! 5$: BIT #^C,(R1) ;ANY ILLEGAL SWITS ON? BEQ 10$ ;NO 9$: MOV #-1,(R1) ;INDICATE ERROR 10$: .RSUM ;WAKE UP THE MAINLINE RETURN ;LEAVE... ;+ ; QWATCH - DOUBLE CTRL-C WATCHDOG...IN CASE MAINLINE IS SLEEPING ; AND I/O IS QUIESCENT, THIS ROUTINE WILL CHECK FOR ; CTRL-C ABORT FROM KEYBOARD EVERY 5 SECONDS. ;- QWATCH::TST QSCCA ;DOUBLE CTRL-C? BEQ QMKT ;NO... QCCAB: MOV @#$SYPTR,R0 ;YES! - TURN OFF BIC #QUEUE$,$CNFG1(R0) ;QUEUE RUNNING BIT IN MONITOR .RSUM ;WAKE UP MAINLINE RETURN ;THEN LEAVE COMPLETION CODE QMKT: .MRKT #TAREA ;SCHED US TO RUN AGAIN IN 5 SEC RETURN ;LEAVE... ;+ ; QUEIO - THIS IS THE I/O TRANSFER COMPLETION ROUTINE. ; I/O TRANSFER IS STARTED AND IS ; KEPT GOING UNTIL EOF, ERROR OR ^C^C ;- .ENABL LSB QUEIO:: TST QSCCA ;WAS DOUBLE CTRL-C TYPED? BNE 55$ ;YES - WAKE UP MAINLINE TSTB QSPND ;CHECK THE SUSPEND FLAG BMI 6$ ;/RESTART FILE (NOT REALLY SUSPENDED) .WAIT #OUTCH ;DID LAST WRITE FINISH OK? BCS 4$ ;NO! QBEGIO: .READC #CAREA,#INPCH,,,#2$,RDBLK ;QUEUE UP A READ BCS 5$ ;ERROR OR EOF...LET MAINLINE DECIDE RETURN ;LEAVE COMPLETION CODE ;002 2$: BIT #EOF$,R0 ;EOF ON N.S.F. DEVICE? ;002 BEQ 22$ ;NO, SKIP ;002 MOV FDBLK,R0 ;GET INPUT DEV SPEC ;002 BIC #37,R0 ;STRIP UNWANTED BITS... ;002 CMP #^RNL,R0 ;IS IT NL HANDLER? ;002 BNE 5$ ;NO, GO FINISH UP ;002 BR 6$ ;YES (YUCH!) - JUST LEAVE ;002 22$: .WAIT #INPCH ;DID LAST READ FINISH OK? ;002 BCS 5$ ;ERROR...GO CHECK IT OUT! ;**-1 TSTB QLP ;OUTPUT GOING TO LP? BNE 3$ ;NO...SKIP FORM-FEED CHECK TST RDBLK ;ARE WE DOING BLOCK 0? BNE 3$ ;NO...SKIP FORM-FEED CHECK CMPB IOBUFF,#FF ;IS 1ST CHAR A FF? BNE 3$ ;NO... ..DOFF::;NOP/NOP ; replace 2 words at ..DOFF with ; NOP/NOP to allow initial FF CLRB IOBUFF ;YES...DON'T GIVE 2 FF IN A ROW! 3$: INC RDBLK ;BUMP BLOCK # FOR NEXT READ .WRITC #CAREA,#OUTCH,,,#QUEIO,WRBLK ;QUEUE UP A WRITE INC WRBLK ;BUMP BLOCK #... BCC 6$ ;THAT'S IT FOR NOW 4$: MOVB #-1,IOERR ;INDICATE WRITE ERROR BR 55$ ;002 5$: MOVB @#$ERRBY,IOERR ;SET UP INLINE ERROR BYTE 55$: .RSUM ;WAKE UP MAINLINE 6$: RETURN ;LEAVE COMPL CODE .DSABL LSB .SBTTL QUEUE - CONTROL BLOCK, WORKFILE BUFFER, ETC. ;******** CONTROL BLOCK ********* QCBLK:: QWSIZ: .WORD QBLKS-1 ;SIZE (IN BLOCKS) OF THIS QUEUE QFREE: .WORD *32. ;# OF FREE ENTRIES IN QUEUE CQE: .WORD 0 ;CURRENT ENTRY IN QUEUE (BEING PRINTED) LQE: .WORD 0 ;LAST ENTRY IN QUEUE QIO: .BYTE 0 ;I/O IS QUEUED = 1 / QUEUE EMPTY = 0 QSPND: .BYTE 0 ;I/O IS SUSPENDED = 1 DELWF: .BYTE 0 ;DELETE WORKFILE ON PROGRAM TERMINATION = 1 QLP: .BYTE 0 ;IF OUTPUT DEVICE = LP, QLP = 0 QSPSV: .BYTE 0 ;SAVED SUSPEND STATUS QCOPY: .BYTE 1 ;DEFAULT # COPIES QBANR: .BYTE 0 ;DEFAULT # BANNER PAGES QDEL: .BYTE 0 ;ALWAYS DEFAULT TO DON'T DELETE! JCOPY: .BYTE 1 ;# COPIES FOR CURRENT JOB JBANR: .BYTE 0 ;# BANNER PAGES FOR CURRENT JOB JDEL: .BYTE 0 ;DELETE SWIT FOR JOB FCOPY: .BYTE 1 ;# COPIES FOR CURRENT FILE FBANR: .BYTE 0 ;# BANNER PAGES FOR CURRENT FILE FDEL: .BYTE 0 ;DELETE SWIT FOR FILE QRESV: .WORD 0 ;(RESERVED) ;001 RDBLK: .WORD 0 ;REL BLOCK OF CURRENT READ WRBLK: .WORD 0 ;REL BLOCK OF CURRENT WRITE QBLOK: .WORD 0 ;REL QUEUE BLOCK CURRENTLY IN MEMORY QJBSV: .BLKW 8. ;CURRENT JOB DESCRIPTOR (FOR RESTART) CQESV: .WORD 0 ;LAST QUEUE ELEMENT ID (FOR RESTART) QIDENT: .RAD50 /QUF/ ;QUFILE IDENTITY VERIFICATION WORD QIDOFF =: QIDENT-QCBLK ;OFFSET IN CONTROL BLOCK OF VALIDITY PATTERN ;*** END OF CONTROL BLOCK DATA - FOLLOWING DATA PADS OUT TO FULL BLOCK *** .PSECT QMAIN USRLOD = . ;SWAP USR STARTING HERE ;BUFFERS & POINTERS... QBUFF: .BLKW 256. ;QUEUE WORKFILE BUFFER LASTWD: .BYTE CR,0 ;CTRL CHAR TO FLUSH LP BUFFER... TOF: .BYTE FF,0 ;FORM FEED FOR 'LPRINT'... DVSPEC: .WORD 0 ;POINTER TO IN/OUT SPEC ..QDAS ==. ;**PATCH workfile device text** QUSPEC: .ASCIZ /SY:QUFILE.WRK/ ;QUEUE WORKFILE SPEC (ASCII) INSPEC: .BLKB 15. ;INPUT FILE SPEC (ASCII) OTSPEC: .BLKB 15. ;OUTPUT SPEC (ASCII) ; ****** ERROR MESSAGES ******* ;+ ;ERROR FOPEN: .NLCSI PART=PREFIX,TYPE=I .ASCIZ /F-Cannot open message channel/ QPROT: .NLCSI PART=PREFIX,TYPE=I .ASCII /F-Cannot delete protected file /<200> QDFUL: .NLCSI PART=PREFIX,TYPE=I .ASCII /F-No room for / .NLCSI PART=NAME,TYPE=I .ASCIZ / workfile on SY:/ FREAD: .NLCSI PART=PREFIX,TYPE=I .ASCII /F-Input error /<200> FWRIT: .NLCSI PART=PREFIX,TYPE=I .ASCII /F-Output error /<200> OFAIL: .NLCSI PART=PREFIX,TYPE=I .ASCII /E-Cannot open output device /<200> IFAIL: .NLCSI PART=PREFIX,TYPE=I .ASCII /E-Cannot open input device /<200> FNOFIL: .NLCSI PART=PREFIX,TYPE=I .ASCII /E-File not found /<200> FNOHND: .NLCSI PART=PREFIX,TYPE=I .ASCII /E-Handler not loaded /<200> WVERS: .NLCSI PART=PREFIX,TYPE=I .ASCII /F-Wrong version of RT11/<200> ;- .SBTTL QUEUE - BANNER TABLES, BUFFERS, ETC. ; BANNER TRAILER TEXT MONTBL: .ASCII /-Jan-Feb-Mar-Apr-May-Jun-Jul-Aug-Sep-Oct-Nov-Dec-/ ...CMV TYPE=V ALINE: .REPT 8. .ASCII /** RT-11 / ; characters 1-9 .BYTE ,,'.,, .ASCII / / ; 15th character .ENDR .ASCII /**/ ..NB1 == ALINE+<5*15.+3> ;LINE: .ASCII /***RT-11***RT-11***RT-11***RT-11***RT-11***RT-11***/ ; .ASCII /RT-11***RT-11***RT-11***/ ;..NB1:: ; .ASCII /RT-11***RT-11***RT-11***RT-11***RT-11***RT-11***/ .ASCIZ TRAILR: .ASCII /Job = / JOBNM: .ASCII / / .ASCII / Printed on / QDATE: .ASCII / / QAT: .ASCII /at / QTIM: .ASCII /00:00:00/ .ASCII / Copy / MCOPY: .ASCII / of / NCOPY: .ASCII / / ..NB2:: .ASCIZ / File = / DFILE: .ASCIZ / !!! FILE WILL BE DELETED !!!/ CRLFLF: .ASCIZ .EVEN ;BANNER BUFFERS & POINTERS... CCOPY: .BYTE 0 ;CURRENT COPY OF FILE BEING PRINTED CBANR: .BYTE 0 ; # BANNER PAGES LEFT TO PRINT BUFFR: .WORD IOBUFF ;POINTER TO I/O BUFFER BBUFF: .WORD 0 ;PTR TO NEXT WORD IN BANNER BUFFER LBUFF: .BLKB 132. ;BANNER LINE BUFFER CBUFF: .BLKB 16. ;ASCII BUFFER QTOD: .WORD 0,0 ;TIME-OF-DAY ; BANNER CHARACTER TABLE LINE: .WORD LINE1-'A,LINE2-'A,LINE3-'A,LINE4-'A,LINE5-'A,LINE6-'A .WORD LINE7-'A,0 LINE1: .BLKB 36. LINE2: .BLKB 36. LINE3: .BLKB 36. LINE4: .BLKB 36. LINE5: .BLKB 36. LINE6: .BLKB 36. LINE7: .BLKB 36. ENDTBL = . ;END OF TABLE .SBTTL QUEUE - BANNER CHARACTER DEFINITIONS/SIZE PATCH TABLE ; BANNER CHARACTER DEFINTIONS . = LINE1 CHAR A <16,21,21,37,21,21,21> CHAR B <36,21,21,36,21,21,36> CHAR C <16,21,20,20,20,21,16> CHAR D <36,21,21,21,21,21,36> CHAR E <37,20,20,36,20,20,37> CHAR F <37,20,20,36,20,20,20> CHAR G <16,21,20,27,21,21,16> CHAR H <21,21,21,37,21,21,21> CHAR I <16,04,04,04,04,04,16> CHAR J <01,01,01,01,01,21,16> CHAR K <21,22,24,30,24,22,21> CHAR L <20,20,20,20,20,20,37> CHAR M <21,33,25,25,21,21,21> CHAR N <21,31,31,25,23,23,21> CHAR O <16,21,21,21,21,21,16> CHAR P <36,21,21,36,20,20,20> CHAR Q <16,21,21,21,25,23,16> CHAR R <36,21,21,36,24,22,21> CHAR S <17,20,20,16,01,01,36> CHAR T <37,04,04,04,04,04,04> CHAR U <21,21,21,21,21,21,16> CHAR V <21,21,21,21,33,12,04> CHAR W <21,21,21,25,25,33,21> CHAR X <21,21,12,04,12,21,21> CHAR Y <21,21,21,16,04,04,04> CHAR Z <37,01,02,04,10,20,37> CHAR 0 <16,21,23,25,31,21,16> CHAR 1 <04,14,24,04,04,04,37> CHAR 2 <16,21,01,02,14,20,37> CHAR 3 <16,21,02,04,02,21,16> CHAR 4 <02,06,12,22,37,02,02> CHAR 5 <37,20,20,36,01,21,16> CHAR 6 <07,10,20,36,21,21,16> CHAR 7 <37,01,02,04,10,10,10> CHAR 8 <16,21,21,16,21,21,16> CHAR 9 <16,21,21,17,01,02,14> . = ENDTBL ;RESET PC TO END OF TABLE! .SBTTL QUEUE - MAINLINE ENTRY & DISPATCH ;+ ; PROGRAM ENTRY POINT & INITIALIZATION CODE ... ;- .ENABL LSB QUEUE:: .GVAL #MAREA,#$SYSVE ;Get system version CMPB #VERSIO,R0 ;IS IT THE CORRECT VERSION? BNE 30$ ;NO, BRANCH MOV #USRLOD,@#USRSWP ;GIVE USR A PLACE TO SWAP .SCCA #MAREA,#QSCCA ;INHIBIT DOUBLE CTRL-C KILLING US! .QSET #QELEM,#3 ;GET EXTRA Q-ELEMENTS 10$: MOV @#$SYPTR,R0 ;GET ADDR OF $RMON ADD #$CNFG1,R0 ;POINT TO $CNFG1 WORD BIS #QUEUE$,@R0 ;TELL MONITOR WE'RE RUNNING TST @R0 ;HAVE WE A CLOCK? BPL 20$ ;NO... MOV #60.,QCLK ;ASSUME 60 CYCLE CLOCK BIT #CLK50$,@R0 ;RIGHT? BEQ 20$ ;YEAH! MOV #50.,QCLK ;OOPS...WE'RE NOT! 20$: .GVAL #MAREA,#$SYSGE ;GET SYSGEN WORD BIC #^C,R0 ;CLEAR ALL BUT SYS JOB BIT MOV R0,QSYT$K ;PUT MASK IN OUR WORLD BEQ 40$ ;SKIP .LOOKUP IN NOT SYS JOB MONITOR .LOOKUP #MAREA,#16,#QJBLK ;OPEN A CHANNEL TO RECV MESSAGES ; BCC 40$ ;DONE! BCS LUMERR ;CAN'T DO IT (JMP DUE TO RANGE!) 40$: CALL RCVMSG ;QUEUE UP A READ/RCVD FOR INCOMING MSG CALL QOPEN ;OPEN THE WORKFILE TSTB QIO ;I/O IN PROCESS? BNE QREST ;YES...RESTART I/O CALL QWATCH ;NO...START CTRL-C WATCHDOG BR QWAIT2 ;THEN GO TO SLEEP 30$: BR PWVERS ;ERROR HELP JUMP ;+ ; RESTART QUEUE ... ;- QREST: MOV CQESV,CQE ;SET CQE TO PREVIOUS ONE MOV #QJBSV,R5 ;POINT TO LAST JOB REQ INCB QIO ;SET I/O IN PROGRESS DEC QFREE ;ADJUST FREE COUNT FOR RESTART TSTB QSPSV ;DO WE NEED TO RESTORE SPND STATUS? BEQ 50$ ;NO... MOVB QSPSV,QSPND ;YES...RESTORE SUSPEND STATUS CLRB QSPSV ;RESET FLAG 50$: JMP RESTRT ;RESTART I/O .DSABL LSB .SBTTL EXIT PROGRAM ;+ ; EXIT FROM QUEUE ... PERFORMS A "CONTROLLED" SHUTDOWN, RETAINING ; THE QUEUE WORKFILE IF REQUESTED ;- QEXIT: .PRINT ;ERROR MESSAGE ON CONSOLE QABORT: CALL CLOSE0 ;CLOSE CHANNELS 0-2 TSTB QIO ;Were we doing anything? ;V5 BEQ 1$ ;Nope...skip the "unprotect" ;V5 CALL UNPROT ;UNPROTECT INPUT FILE ON ERROR 1$: TSTB DELWF ;ARE WE TO RETAIN THE WORKFILE? BEQ Q.EXIT ;YES... .DELETE #MAREA,#OUTCH,#QDBLK ;DELETE IT (NO AUTO-RESTART!) BCC Q.EXIT ;DONE MASTER !!! CMPB @#$ERRBY,#3 ;OOPS - WAS IT PROTECTED? BNE Q.EXIT ;NO...DON'T WORRY ABOUT IT MOV #QUSPEC,DVSPEC ;DVSPEC = "SY:QUFILE.WRK" CALL FPROT ;TELL USER QUFILE IS PROTECTED! Q.EXIT: MOV @#$SYPTR,R0 ;R0 => $RMON BIC #QUEUE$,$CNFG1(R0) ;CLEAR QUEUE RUNNING BIT .EXIT ;TERMINATE QUEUE... .SBTTL QUEUE - PRINT I/O ERROR MESSAGES ... ;+ ; PRINT I/O ERROR MESSAGES HERE ... ;- ;+ ;ERROR LUMERR: MOV #FOPEN,R0 ;CAN'T OPEN MESSG CHANNEL ERROR BR QEXIT ;WE'RE DONE FOR!!! RDERR: .PRINT #FREAD ;INPUT ERROR MOV #INSPEC,R0 ;R0 => INPUT FILE SPEC BR QEXIT ;SKIP... WRERR: .PRINT #FWRIT ;OUTPUT ERROR MOV #OTSPEC,R0 ;R0 => OUTPUT SPEC BR QEXIT ;SKIP... ;002 ;002 PWVERS: MOV #WVERS,R0 ;GET ADDRESS OF MSG BR QEXIT ;GO PRINT IT FPROT: .PRINT #QPROT ;PRINT PROTECTED FILE MESSAGE ;**-1 .PRINT DVSPEC RETURN ;- .SBTTL SUSPEND/RESUME MAINLINE / SEND ACKNOWLEDGEMENT ;+ ; SUSPEND MAINLINE... ;- QWAIT:: TST QSCCA ;DID WE GET DOUBLE CTRL-C? BNE QABORT ;YES! WE DIE!!! CALL UPDCTL ;UPDATE CONTROL BLOCK ON DISK, QWAIT2: .SPND ;GO TO SLEEP... ;+ ; RESUME MAINLINE...WE'VE BEEN AWAKENED BY A COMPLETION ROUTINE ! ;- QWAKE:: CLR QAMSG ;CLEAR THE ACK FLAG WORD TST QRMSG1 ;WHO WOKE US UP? BGT JOBRQ ;WE GOT SOME MAIL ! BLT QNACK ;ERROR GETTING MAIL JMP CKEOF ;EOF ON INPUT FILE (JMP DUE TO RANGE) ;+ ; SEND ACKNOWLEDGEMENT MESSAGE... ;- .ENABL LSB QNACK: BIS #FLG.IR,QAMSG ;SET UP ILL JOB REQ FLAG QUACK:: CALL QUEMSG ;SEND ACK MSG & LOOK FOR MAIL CALL UPDATE ;UPDATE WORKFILE ON DISK TST QSCCA ;ABORT FLAG UP? BNE QABORT ;YES! ABORT!!! TSTB QSPND ;ARE WE SUSPENDED? BGT QWAIT2 ;YES...DON'T START ANY I/O BEQ 1$ ;NO... INCB QSPND ;YES, BUT ARE WE UNSUSPENDING? BEQ QREST ;NO...IT'S A RESTART CURRENT FILE CLRB QSPND ;YES, WE'RE UNSUSPENDING,... CALL UPDCTL ;UPDATE THE CONTROL BLOCK... BR 2$ ;Go check if we should start I/O ;V5 1$: TSTB QIO ;I/O IN PROGRESS? BNE QWAIT2 ;YES...JUST SLEEP 2$: CMP CQE,LQE ;NO...BUT SHOULD WE START SOME? BEQ QWAIT2 ;NOPE! JMP START ;START UP I/O!!! .DSABL LSB .SBTTL PROCESS JOB REQUEST ;+ ; PROCESS JOB REQUESTS - SWITCHES OTHER THAN COPIES, BANNER PAGES ; AND DELETE FILE ARE PROCESSED HERE PRIOR TO ACTING ON THE JOB ; REQUEST. ;- ;+ ; SET PARAMETERS, SUSPEND, RESTART/RESUME ... ;- .ENABL LSB JOBRQ:: TST QSCCA ;WERE WE DOUBLE CTRL-CED? BNE QNACK ;YES! FORGET THE REQUEST! MOV #QRMSG1,R3 ;JOB REQUEST...R3 => MESSAGE BLK MOV QMADDR(R3),R3 ;R3 => JOB REQ BLK BIT #FLG.AB,@R3 ;ABORT RIGHT NOW?? BEQ 1$ ;NO... MOV SP,QSCCA ;SET THE DBL CTRL-C SWIT BR QUACK ;ABANDON SHIP 1$: BIT #FLG.SP,@R3 ;SET PARAMETERS? BEQ 3$ ;NO... MOVB QNBAN(R3),QBANR ;GET DEFAULT # OF BANNER PAGES MOVB QNCOP(R3),DELWF ;AND WORKFILE DELETE/RETAIN FLAG BR QUACK ;DONE! 3$: BIT #FLG.SU,@R3 ;SUSPEND? BEQ 4$ ;NO MOVB #1,QSPND ;SET SUSPEND FLAG BR QUACK ;/S & /R ARE MUTUALLY EXCLUSIVE 4$: BIT #FLG.RS,@R3 ;/RESTART? BEQ 6$ ;NOPE... 5$: TSTB QSPND ;ARE WE SUSPENDED? BEQ 54$ ;NO... TSTB QIO ;YES...BUT ARE WE FINISHING CURRENT BEQ 53$ ;FILE? IF NOT, PROCEED CLRB QSPND ;IF WE ARE, JUST CLEAR SUSPEND FLAG BR QUACK ;THEN ACKNOWLEDGE... 53$: CMP CQE,LQE ;Anything queued? ;V5 BEQ QUACK ;No, ignore request ;V5 MOVB #-2,QSPND ;YES...FLAG WE'RE UNSUSPENDING BR QUACK ;ACKNOWLEDGE 54$: TSTB QIO ;I/O ACTIVE? BEQ QUACK ;NO...IGNORE REQUEST 55$: MOVB #-1,QSPND ;FLAG WE'RE RESTARTING FILE CALL CLOSE ;CLOSE I/O XFER CHANNELS (1 & 2) BR QUACK ;GO ACKNOWLEDGE ;+ ; KILL JOB ... ;- 6$: BIT #FLG.KL,@R3 ;KILL JOB/FILE? BEQ ENQUE ;NO...DONE WITH IMMEDIATE ACTION SWITS MOV @R3,R2 ;SAVE FLAGS WORD... ADD #QLJBNM,R3 ;THEN POINT TO LOGICAL JOB NAME MOV LQE,R4 ;R4 = LAST ENTRY IN QUEUE CALL GETCQE ;GO GET IT MOV QBLINK(R5),R4 ;GET ELEMENT WITH JOB REQ BLK 7$: CALL GETCQE ;GET THE JOB REQUEST BLOCK CMP @R3,QLJBNM(R5) ;IS THIS THE JOB TO BE KILLED? BNE 8$ CMP 2(R3),QLJBNM+2(R5) ;CHECK 2ND WORD BEQ 9$ 8$: CMP R4,QBLINK(R5) ;POINTS TO ITSELF? BEQ QUACK ;YES...NO SUCH JOB - BUT ACK ANYWAY MOV QBLINK(R5),R4 ;NO...POINT TO PRECEDING JOB BLOCK BR 7$ ;CONTINUE 9$: CMP R4,QBLINK(R5) ;CURRENT JOB? BEQ 10$ ;YES...TAKE SPECIAL ACTION BIT #FLG.KL,@R5 ;ALREADY DEAD? BNE 8$ ;YES...KEEP GOING, MAY BE ANOTHER BIS R2,@R5 ;NO..."KILL" THE JOB... QUACK2: BR QUACK ;AND SEND ACK MSG 10$: BIS R2,QJBSV ;SET KILL BIT IN SAVED JOB REQ BLK... MOVB QSPND,QSPSV ;SAVE SUSPEND STATUS... BR 55$ ;AND FAKE A RESTART ! .DSABL LSB .SBTTL INSERT REQUEST IN QUEUE WORKFILE ;+ ; INSERT REQUEST BLOCKS IN QUEUE ;- .ENABL LSB ENQUE:: MOV QNFILZ(R3),R2 ;GET # FILES IN REQUEST BMI QUACK2 ;NO FILES... ; BPL 1$ ;WE HAVE SOME... ; JMP QUACK ;NO FILES... 1$: CMP R2,QFREE ;HAVE WE ENOUGH ROOM? BLT 2$ ;YES BIS #FLG.QF,QAMSG ;SET ERROR BITS BR QUACK2 ;GIVE "NACK" MSG 2$: INC R2 ;INCLUDE JOB REQ BLK IN COUNT ! SUB R2,QFREE ;UPDATE FREE COUNT MOV R2,(PC)+ ;SAVE THE FILE COUNT FILCT: .WORD 0 ;WORKING FILE COUNT MOV LQE,R4 ;R4 = LAST ELEMENT USED CALL GETCQE ;R4 =>LAST ELEMENT USED MOV QBLINK(R5),R2 ;R2 = Q-ELEM OF PREVIOUS JOB REQ BLK CMP R4,CQE ;QUEUE CLOSED UP? BNE 10$ ;NO... TSTB QIO ;YES...IS I/O IN PROGRESS? BEQ 20$ ;NO...WE CAN USE THIS ELEMENT 10$: CALL GETNQE ;GET NEXT FREE "ELEMENT" 20$: MOV R4,R1 ;SAVE WHERE WE WILL PUT JOB REQ BLK 30$: MOV #6,R0 ;XFER BLK TO QUEUE - SET UP WD CNT 40$: MOV (R3)+,(R5)+ ;MOV A WORD... DEC R0 ;DONE? BNE 40$ ;NO...DO ANOTHER CLR (R5)+ ;Q-ELEM GETS 2 EXTRA WDS - 1ST RESERVD MOV R2,(R5) ;LAST WD = JOB REQ BLK POINTER MOV R1,R2 ;JOB REQ BLK => PREVIOUS JOB REQ BLK ;FILE REQ BLKS => THEIR JOB REQ BLK DEC FILCT ;MORE FILES? BEQ QUACK2 ;NO...SEND ACK MESSAGE ; BNE 60$ ;YES...CONTINUE ; JMP QUACK ;NO...SEND ACK MESSAGE ;60$: CALL GETNQE ;GET A FREE QUEUE ELEMENT MOV R4,LQE ;UPDATE LQE... BR 30$ ;GO QUEUE REQ BLOCK .DSABL LSB .SBTTL INITIATE I/O / EOF ON INPUT FILE ;+ ; INITIATE I/O ... PROCESS JOB REQUEST BLOCK FIRST ;- START:: INCB QIO ;INDICATE I/O IN PROGRESS .CMKT #MAREA,#0 ;CANCEL WATCHDOG... MOV CQE,R4 ;R4 = CURRENT Q ELEMENT CALL GETCQE ;GO GET IT (R5 => ELEMENT IN BUFFER) BR RESTRT QNXT: MOV CQE,R4 ;SET UP TO GET MOV R4,CQESV ;SAVE THIS ELEMENT FOR RESTART! CALL GETNQE ;THE NEXT ELEMENT MOV R4,CQE ;IT BECOMES THE "CURRENT ONE INC QFREE ;ADD Q-ELEMENT BACK TO FREE COUNT CALL UPDCTL ;UPDATE CTRL BLK ON DISK TSTB QSPND ;DID WE GET SUSPENDED? BEQ RESTRT ;NO...CONTINUE CLRB QIO ;SAY I/O IS OFF... CALL QWATCH ;RESTART WATCHDOG... JMP QWAIT ;THEN GO TO SLEEP RESTRT: CALL GETSW ;PICK UP ANY OPTIONS BIT #FLG.JR,@R5 ;JOB REQ BLK? BEQ FILRQ ;NO... CLR (PC)+ ;INITIALIZE DEAD JOB SWITCH KILSW: .WORD 0 BIT #FLG.KL,@R5 ;HAS JOB BEEN KILLED? BEQ 7$ ;NO... INC KILSW ;YES...SET DEAD JOB SWITCH BR QNXT ;TRAVERSE "DEAD" FILE REQ BLKS 7$: MOV R4,QBLINK(R5) ;SET LINKAGE TO POINT TO SELF .CLOSE #OUTCH ;CLOSE OUTPUT CHANNEL CALL SAVJOB ;SAVE JOB DESCRIPTOR ;V5+ MOV #JDBLK+QLJBNM,R2 ;R2 => LOGICAL JOB NAME MOV #JOBNM,R1 ;R1 => JOBNAME FIELD IN BANNER CALL CNVFNM ;SET IT UP IN ASCII MOVB #SPACE,@R1 ;BUT NOT IN ASCIZ!!! BR QNXT ;GO GET 1ST FILE REQ BLK... ;V5- ;+ ; PROCESS FILE REQUEST BLOCK ... ;- .ENABL LSB FILRQ: TST KILSW ;DEAD JOB? BNE QTST ;YES...IGNORE IT MOVB FCOPY,R0 ;R0 = # OF COPIES TO OUTPUT MOV #NCOPY,R1 ;R1 => WHERE IN BANNER TO PUT IT CALL CVT2 ;CONVERT TO ASCII CLRB CCOPY ;INITIALIZE CURRENT COPY BYTE MOV #FDBLK,R2 ;R2 => FILE DESCRIPTOR SAVE AREA MOV R2,R4 ;SAVE IT CMP (R5)+,(R5)+ ;ADJUST TO RAD50 FILE DESCRIPTOR .REPT 4 ;COPY FILE DESCRIPTOR OUT OF MOV (R5)+,(R2)+ ; TO SAVE AREAS WHERE .ENDR ; USR WON'T CLOBBER IT! MOV #INSPEC,DVSPEC ;SAVE IT FOR ERROR MESSAGE JSR R5,OPEN ;OPEN INPUT CHANNEL ;V5 INPCH BCS QTST ;OOPS! .CLOSE #OUTCH ;CLOSE OUTPUT CHANNEL MOV JDBLK+4,@R4 ;CHANGE TO OUTPUT DEV MOV #OTSPEC,DVSPEC ;=> OUTPUT DEVICE CLR WRBLK ;START WITH BLOCK 0 JSR R5,OPEN ;OPEN OUTPUT FILE OUTCH ; SAME AS INPUT! BCC QMOR1 ;First time, skip force of FF char. .PURGE #INPCH ;PURGE THE CHAN FOR FURTHER PROCE ;CA5 INC KILSW ;FAKE "KILL" TO GET NEXT JOB ;V5 QTST: CALL UNPROT ;UNPROTECT INPUT FILE ON ERROR CMP CQE,LQE ;ARE WE CAUGHT UP? BNE QNXT ;NO...GO GET SOME MORE WORK INC QFREE ;ADD LAST ELEMENT BACK TO FREE LIST CLRB QIO ;YES...INDICATE NOTHING GOING ON .CLOSE #OUTCH ;CLOSE OUTPUT CHANNEL CALL QWATCH ;START THE CTRL-C WATCHDOG... BR 13$ ;GO BACK TO SLEEP QMOR: CALL TOPFRM ;Print FF. QMOR1: TSTB FBANR ;PRINT BANNER PAGES? BLE 11$ ;NO CALL BANNER ;GO PRINT BANNER PAGES 11$: CLR RDBLK ;START WITH BLOCK 0... CALL QBEGIO ;START UP I/O XFER... 13$: JMP QWAIT ;THEN GO TO SLEEP RERR: JMP RDERR ;RELAY TO READ ERROR WERR: JMP WRERR ;RELAY TO WRITE ERROR .DSABL LSB .SBTTL EOF ON INPUT FILE ;+ ; EOF ON INPUT FILE ... CHECK IF MORE I/O TO DO ;- CKEOF:: TST QSCCA ;COMES HERE ON EOF-^C^C-I/O ERROR BEQ 1$ ;DBL CTRL-C? BRANCH IF NOT JMP QABORT ;YES...GET OUT, BUT GRACEFULLY 1$: TSTB IOERR ;WAS THERE AN ERROR? BGT RERR ;POSITIVE = READ ERROR BLT WERR ;NEGATIVE = WRITE ERROR CALL FLUSH ;YES...MAKE SURE EVERYTHING OUT! 2$: DECB FCOPY ;MORE COPIES TO PRINT? BGT QMOR ;YES... .CLOSE #INPCH ;CLOSE INPUT CHANNEL CALL UNPROT ;CHECK/UNPROTECT INPUT FILE TSTB FDEL ;DONE WITH FILE - DELETE IT? BEQ QTST ;NO...ON TO THE NEXT ONE .DELETE #MAREA,#INPCH,#FDBLK ;VANISH THE FILE BCC QTST ;OOPS...CAN'T !!! CALL FPROT ;TELL 'EM IT'S PROTECTED!!! BR QTST ;AND CONTINUE .SBTTL SAVE JOB & FILE DESCRIPTOR BLOCKS ;+ ; SAVEJOB - MOVES JOB REQUEST BLK TO SAVE AREA ;- SAVJOB::MOV #JDBLK,R2 ;R2 => JOB DESCRIPTOR BLOCK MOV #QJBSV,R4 ;R4 => RESTART SAVE AREA MOV #8.,R3 ;R3 = LENGTH OF JOB REQ ELEMENT 1$: MOV (R5),(R2)+ ;XFER TO JOB DESCRIPTOR BLOCK MOV (R5)+,(R4)+ ;AND TO RESTART SAVE AREA DEC R3 ;DONE? BNE 1$ ;NOT YET MOV #JDBLK+4,R4 ;R4 => JOB DESCRIPTOR 2$: RETURN ;RETURN TO CALLER .SBTTL PROTECT/UNPROTECT INPUT FILE ;+ ;V5+ ; PROT/UNPROT - PROTECTS/UNPROTECTS INPUT FILE FROM DELETION ;- .ENABL LSB PROTFI: MOV #C.BIS,(PC)+ ; Protect the input file CODE: .WORD 0 MOV FDBLK,(PC)+ ; Save the input device INDEVI: .WORD 0 BR 10$ ; Merge... UNPROT: TST PSTAT ;was file protected before? .ASSUME E.PROT EQ 100000 BMI 60$ ; if so, don't unprotect it. MOV #C.BIC,CODE MOV INDEVI,FDBLK ;Restore Rad50 input device spec 10$: .SERR ;Surpress MON-X-message ;CA5 .SFSTA #MAREA,#INPCH,#FDBLK,#E.PROT,USER,CODE BCC 30$ ;Branch if no error ;CA5+ ; The error code for "directory I/O error " is -3 CMPB #-3,@#$ERRBY ;Same? new code BEQ 20$ ;Yes, branch .HERR ;Clear intercept SEC ;Set carry RETURN ;Return 20$: .PURGE #INPCH ;Purge channel BR 40$ 30$: CMP CODE,#C.BIS ;Doing PROTECT? BEQ 50$ ; save status if so 40$: MOV #-1,R0 ; inhibit future unprotects 50$: MOV R0,PSTAT ;Save previous status .HERR ;Allow hard errors 60$: CLC ;Clear carry ;CA5- RETURN ;Return with C bit set/clear ;V5- .DSABL LSB .SBTTL GET CURRENT/NEXT QUEUE ELEMENT ;+ ; QUEUE MANAGEMENT SUBROUTINES - GETNQE / GETCQE ; ; THESE SUBROUTINES GET THE PROPER QUEUE BLOCK WHICH ; CONTAINS THE SPECIFIED "QUEUE ELEMENT" AND PASS ; BACK THE ADDRESS OF THE ELEMENT IN THE IN-MEMORY ; BUFFER. IF THE BLOCK IS NOT IN MEMORY, THE CURRENT ; BLOCK IS ROLLED OUT TO DISK AND THE REQUESTED BLOCK ; IS ROLLED IN. ; ; ENTRY: GETCQE - GET "CURRENT" QUEUE ELEMENT ; GETNQE - GET "NEXT" QUEUE ELEMENT ; ; INPUT: R4 = QUEUE ELEMENT "ID" ; EVEN BYTE = ELEMENT *WORD* OFFSET IN BLOCK (0-248.) ; ODD BYTE = QUEUE FILE BLOCK # ; ; OUTPUT: R5 = QUEUE BUFFER ADDRESS OF NEXT ELEMENT ; R4 = NEXT ELEMENT (IF CALLED AS 'GETNQE') ; = UNCHANGED IF CALLED AS 'GETCQE') ;- .ENABL LSB GETNQE::ADD #8.,R4 ;CALULATE NEXT QUEUE ELEMENT GETCQE::CLR R5 ;CLEAR R5 BISB R4,R5 ;R5 = WORD OFFSET... SWAB R4 ;GET BLOCK # IN LO BYTE MOVB R4,R4 ;GET RID OF UNWANTED BITS CMP CQE,LQE ;IS QUEUE CLOSED UP? BEQ 1$ ;YES CMP QWSIZ,R4 ;TIME TO WRAP QUEUE? BGT 1$ ;NO... CLR R4 ;YES... 1$: CMP QBLOK,R4 ;IS THE BLOCK IN MEMORY? BEQ 2$ ;YES .WRITW #QAREA,,#QBUFF,,QBLOK ;WRITE OUT OLD BLOCK BCS 3$ ;FATAL WRITE ERROR .READW #QAREA,,,,R4 ;READ IN NEW BLOCK BCS 4$ ;FATAL READ ERROR MOV R4,QBLOK ;UPDATE CURRENT Q BLOK 2$: SWAB R4 ;BLOCK # IN HI BYTE BIS R5,R4 ;CREATE NEW "QUEUE ELEMENT ID" ASL R5 ;WORDS TO BYTES FOR ADDRESSING! ADD #QBUFF,R5 ;R5 = ADDR OF ELEMENT IN BUFFER RETURN ;RETURN ;+ ;ERROR 3$: .PRINT #FWRIT ;WRITE ERROR BR 5$ ;MERGE... RQEXIT: 4$: .PRINT #FREAD ;READ ERROR 5$: MOV #QUSPEC,R0 ;POINT TO WORKFILE SPEC QEXIT1: JMP QEXIT ;QUEUE GO BOOM! ;- .DSABL LSB .SBTTL OPEN QUEUE WORKFILE ;+ ; QOPEN - "OPEN" THE QUEUE WORKFILE (QUFILE.TMP) ; IF THE WORKFILE ALREADY EXISTS THE CONTROL BLOCK ; AND THE CURRENT ELEMENT BLOCK ARE READ. IF ; THE FILE MUST BE CREATED THE CONTROL BLOCK AND ; THE CURRENT ELEMENT BLOCK (BLK 0) ARE INITIALIZED ;- QOPEN:: MOV #QDBLK,R4 ;R4 => WORKFILE DESCRIPTOR BLK .LOOKUP #MAREA,#0,R4 ;LOOKUP WORKFILE BCS 3$ ;NO DICE! DEC R0 ;QUEUE SIZE DOESN'T INCLUDE CTRL BLK MOV R0,R4 ;COPY TO R4 MOV #QBUFF,R2 ;SET UP TO READ CTRL BLK INTO Q-BUFFER MOV #QCBLK,R3 ;R3 => CONTROL BLOCK BUFFER 1$: .READW #QAREA,,R2,,R4 ;GET CONTROL BLOCK FROM EXISTING FILE BCS 2$ ;ERROR! CMP QIDOFF(R2),QDBLK+2 ;DID WE CREATE THIS WORKFILE? BNE 6$ ;NO... MOV #QIDOFF/2,R4 ;R4 = WORDS OF CTRL BLK DATA ;001 11$: MOV (R2)+,(R3)+ ;XFER IT TO WHERE IT BELONGS DEC R4 ;DONE YET? BNE 11$ ;NOPE...LOOP TILL DONE .READW #QAREA,,,,QBLOK ;NOW GET "CURRENT" ELEMENT BLK BCC 5$ ;OK... 2$: BR RQEXIT ;SAYONARA! 3$: .ENTER #MAREA,#0,R4,QSIZE ;CREATE A FRESH ONE BCC 4$ ;DONE! ;+ ;ERROR MOV #QDFUL,R0 ;ASSUME NO ROOM - POINT TO ERR MESSG BR QEXIT1 ;AND GO TO EXIT ROUTINE ;- 4$: CALL UPDATE ;"INITIALIZE" IT 5$: RETURN ;RETURN TO MAINLINE 6$: MOV R4,QWSIZ ;FIX SIZE OF QUEUE IN CTRL BLK .REPT 5 ;MULTIPLY # BLKS BY 32 ASL R4 ;TO GET # OF FREE Q "ELEMENTS" .ENDR ;(32 "ELEMENTS" / BLOCK) MOV R4,QFREE ;FIX # FREE ELEMENTS IN CTRL BLOCK CALL UPDCTL ;WRITE CTRL BLK TO "FOREIGN" FILE RETURN ;THEN RETURN .SBTTL OPEN I/O CHANNELS ;+ ;OPEN - "OPEN" CHANNELS FOR INPUT/OUTPUT ; ;ON ENTRY: R4 => INPUT/OUTPUT FILE DESCRIPTOR ; R5 => CHANNEL # ;- .ENABL LSB OPEN:: MOV (R5)+,R3 ;PICK UP CHAN# & POP TO RET ADDR MOV R5,-(SP) ;SAVE IT... MOV R4,R2 ;COPY R4 FOR CONVERSION RTNES MOV DVSPEC,R1 ;R1 => ASCII FILE SPEC OUTPUT AREA CALL CNVDEV ;CONVERT DEVICE TO ASCII .DSTAT #MAREA,R4 ;CHECK OUT DEVICE 10$: TST MAREA+4 ;HANDLER LOADED? ;002 BNE 20$ ;YES... ;**-1 ;+ ;ERROR .PRINT #FNOHND ;NO...T U R K E Y! BR 100$ ;PRINT ERROR MESSG! ;- 20$: CALL CNVFNM ;JOB/FILE NAME TO ASCII CMP #OUTCH,R3 ;IS IT OUTPUT? BNE 50$ ;NO... ; Open output file/device CLRB QLP ; INITIALIZE FLAG BIT #WONLY$,MAREA ; IS IT WRITE ONLY DEVICE? BNE 30$ ; BRANCH IF YES INCB QLP ; NO,SET FLAG <> FOR OUTPUT FLAG 30$: .ENTER #MAREA,R3,R4,#-1,#-1 ;AND OPEN WITH .ENTER ;V5 BCC 120$ ;OK... CMPB @#$ERRBY,#3 ;FILE EXISTS & PROTECTED? BNE 40$ ;NO...SOMETHING ELSE BAD ;+ ;ERROR .PRINT #QPROT ;INDICATE PROTECT ERROR BR 100$ ;THEN MERGE 40$: .PRINT #OFAIL ;INDICATE FATAL ERROR BR 100$ ;THEN MERGE ;- ; open input file 50$: CALL CNVEXT ;INPUT NEEDS EXT IN ASCII TOO! MOV MAREA,(PC)+ ;RT-11 File-structured device? ;V5+ INDVTP: .WORD 0 ; input device DSTAT word BPL 60$ ;Nope...don't try to prot file CALL PROTFI ;Protect input file... BCS 80$ ;OOPS! ;V5- 60$: CLR R5 ;seq no = 0 for rewind, if tape CMP @R4,LASDEV ;Same device as last time? BNE 70$ DEC R5 ;seq no = -1 >> don't rewind. 70$: MOV INDVTP,-(SP) BIC #^C,@SP CMP (SP)+,# ; Magtape? BNE 74$ MOV (R4)+,NFSBLK ; get device name for NFS lookup MOV #ASYBLK,R0 ; point to ASYNC SPFUN block MOV (R4)+,(R0)+ ; put filespec there MOV (R4)+,(R0)+ MOV (R4)+,(R0)+ MOV #NFSBLK,R4 ; point to NFS lookup block 74$: .LOOKUP #MAREA,R3,R4,R5 ;LOOKUP input file BCC 110$ ; branch on success 76$: TSTB @#$ERRBY ;FILE NOT FOUND? BEQ 85$ ; No. Failed for some other reason. TST INDVTP ; sequential input device? BMI 85$ ; No. no excuses TST R5 ; did we not rewind? BEQ 85$ ; Yes. File not found. CLR LASDEV ; Disavow knowledge of this device .PURGE R3 ; Release the channel, BR 60$ ; and reopen it with rewind. 80$: TSTB @#$ERRBY ;FILE NOT FOUND? BNE 90$ ;YES... ;+ ;ERROR 85$: .PRINT #IFAIL ;OTHERWISE CHANNEL IN USE!? BR 100$ 90$: .PRINT #FNOFIL ;FILE NOT FOUND! 100$: .PRINT DVSPEC ;PRINT DEV:FILESPEC ;- SEC ;CARRY SET = ERROR! BR 120$ 110$: MOV @R4,(PC)+ ;LOOKUP was a success. Save LASDEV: .WORD 0 ; the device name. TST 2(R4) ;was this an NFS Lookup? BNE 120$ ; skip if not. .SPFUN #MAREA,R3,#SF.USR,#ASYBLK,,#ERRBLK,#0 ; LOOKUP magtape file BCS 76$ 120$: MOV (SP)+,R5 ;RESTORE RETURN ADDR RTS R5 ;RETURN TO CALLER .DSABL LSB .SBTTL CLOSE I/O CHANNELS ;+ ;CLOSE - "CLOSE" I/O CHANNELS IN RANGE 0-2 ;- CLOSE:: .WAIT #INPCH ;WAIT FOR INPUT CHANNEL .CLOSE #INPCH ;CLOSE INPUT CHANNEL .WAIT #OUTCH ;WAIT FOR OUTPUT TO STOP .CLOSE #OUTCH ;THEN CLOSE IT TOO RTSPC: RETURN ;RETURN TO CALLER CLOSE0: CALL CLOSE ;CLOSE I/O CHANNELS .CLOSE #0 ;ALSO CLOSE WORKFILE RETURN ;RETURN TO CALLER .SBTTL QUEUE - *** UPDATE QUEUE WORKFILE IMAGE ON DISK *** ;+ ;UPDATE - UPDATES THE WORKFILE ON DISK ;- UPDATE:: .WRITW #QAREA,,#QBUFF,,QBLOK ;WRITE BACK Q BUFFER BCS UFAIL ;CAN'T! UPDCTL:: .WRITW #QAREA,,#QCBLK,,QWSIZ ;WRITE BACK CTRL BLOCK BCC RTSPC ;DONE...RETURN ;+ ;ERROR UFAIL: .PRINT #FWRIT ;OUTPUT ERROR MESSAGE MOV #QUSPEC,R0 ;FOR QUEUE WORKFILE... JMP QEXIT ;- .SBTTL CONVERT FILESPEC TO ASCII ;+ ;CNVDEV - CONVERT RAD50 DEVICE SPEC TO ASCII ;CNVFNM - CONVERT RAD50 FILENAME TO ASCII ;CNVEXT - CONVERT RAD50 EXTENSION TO ASCII ; INPUT: R2 => RAD50 / R1 => OUTPUT BUFFER ;- CNVDEV::MOV #3,R5 ;DEVICE IS UP TO 3 CHAR CALL R50ASC ;CONVERT TO ASCII CMPB #SPACE,-(R1) ;ONLY 2 LETTERS? BEQ 1$ ;YUP... TSTB (R1)+ ;NOPE... 1$: MOVB #':,(R1)+ ;PUT IN A COLON BR CNVRET ;RETURN... CNVFNM: MOV #6,R5 ;FILENAME = 6 CHAR CALL R50ASC ;CONVERT IT BR CNVRET ;RETURN TO CALLER CNVEXT: MOVB #'.,(R1)+ ;FOLLOW FILENAME WITH A PERIOD MOV #3,R5 ;EXTENSION = 3 CHAR CALL R50ASC ;CONVERT IT TOO CNVRET: CLRB @R1 ;MAKE ASCIZ!!! RETURN ;RETURN TO CALLER .SBTTL RT-11 DATE CONVERSION ;+ ;CNVDAT: - CONVERT RT-11 DATE TO DD-MMM-YY ; ; DATE FORMAT AS RETURNED IN R0 ;002 ; 15 14 13 10 9 5 4 0 ;002 ; +-------------------------------------+ ;002 ; ! AGE ! MONTH ! DAY ! YEAR-72. ! ;002 ; ! 0-3.! 1-12. ! 1-31. ! ! ;002 ; +-------------------------------------+ ;002 ;- ;DATARG: .WORD 1 ; 1 argument ; .WORD QDATE ; address of date string ;CNVDAT:: ; MOV #DATARG,R5 ; MOV #DATE,R0 ; CALLR CALL$F CNVDAT::MOV R0,R2 ;COPY R0 ROL R0 ;GET DAY BITS WHERE WE WANT THEM... ROL R0 ROL R0 SWAB R0 BIC #^C<37>,R0 ;GET RID OF UNWANTED BITS MOV #QDATE,R1 ;R1 = ADDR OF DATE LINE IN TRAILER CALL CVT2 ;CONVERT TO ASCII AND STUFF IN LINE MOV R2,R0 ;GET ORIGINAL WORD SWAB R0 ;GET MONTH BITS WHERE WE WANT THEM BIC #^C<74>,R0 ;CLEAR UNWANTED STUFF... ADD #MONTBL-4,R0 ;ADDRESS TABLE OF MONTHS MOV #5,R3 ;R3 = LOOP COUNT 1$: MOVB (R0)+,(R1)+ ;MOVE IN THE PROPER MONTH DEC R3 BNE 1$ MOV R2,R0 ;GET ORIGINAL WORD ONCE MORE BIC #^C<37>,R0 ;GET LOW 5 BITS OF YEAR SWAB R2 ;GET THE AGE BITS ;002 ROR R2 ; WHERE WE WANT THEM ;002 BIC #^C<140>,R2 ;ISOLATE THEM ;002 ADD R0,R2 ;NOW YEAR IN RANGE 0-127. ;002 ADD #72.,R2 ;ADD BACK THE 72 ;002 MOV #19.,R0 ;ASSUME 19XX ;002 CMP R2,#100. ;UNLESS YEAR .GE. 100 ;002 BLO 44$ ;ONLY IF YEAR WAS .GE. 100 ;002 INC R0 ;THEN IT IS 20XX ;002 SUB #100.,R2 ;AND HAVE TO GET LAST TWO DIGITS;002 44$: CALL CVT2 ;FIRST TWO DIGITS TO ASCII ;002 MOV R2,R0 ;NOW LAST TWO DIGITS ;002 CVT2:: ;CONVERT TO 2 DIGIT DECIMAL ASCII MOVB #SPACE,@R1 ;Initialize output field ;V5 MOVB @R1,1(R1) ; 2 digit's worth, please! ;V5 CMP R0,#10. ;SINGLE DIGIT # ? BLT CVT1 ;YES..DON'T ZERO FILL ! CVTZ2: SWAB R0 ;# IN HI BYTE 1$: ADD #173001,R0 ;DIV BY 10. W/ REPT SUBS BPL 1$ ;Q=Q-10, R=R+1 TILL V SET ADD #'0+<10.*400-1>,R0 ;CORRECT Q & R / ASCIIFY Q MOVB R0,(R1)+ ;XFER 1ST DIGIT TO LSTRNG SWAB R0 ;R TO LO BYTE CVT1: ADD #'0,R0 ;MAKE IT ASCII MOVB R0,(R1)+ ;XFER TO LSTRNG RETURN ;RETURN .SBTTL CONVERT TIME-OF-DAY TO ASCII ;+ ;CNVTIM - CONVERT CLOCK TICKS SINCE MIDNIGHT TO TIME-OF-DAY ;- ;TIMARG: .WORD 1 ; .WORD QTIM CNVTIM:: ; MOV #TIMARG,R5 ; MOV #TIME,R0 ; CALLR CALL$F MOV #QTIM,R1 ;GET ADDR OF FIELD IN BANNER MOV #QTOD,R2 ;R2 => TIME IN CLOCK TICKS MOV (R2)+,R3 ;HI ORDER IN R3... MOV @R2,R2 ;LO ORDER IN R2... JSR R4,DIVIDE ;DIVIDE OUT TICKS/SECOND QCLK: .WORD 0 ;CLOCK FREQ (ZERO IF NO CLOCK!) MOV #-1,R0 ;SET FLAG... MOV #3,R5 ;DIVIDE 3 MORE TIMES BY 60 1$: MOV R0,-(SP) ;SAVE REMAINDER/FLAG ;DIVIDES OUT AS SS,MM,HH !!! JSR R4,DIVIDE .WORD 60. DEC R5 ;DONE? BNE 1$ ;NOT YET 2$: CALL CVTZ2 ;CONVERT H/M/S TO ASCII MOV (SP)+,R0 ;GET NEXT VALUE/FLAG BMI 4$ ;WE'RE DONE! ; MOVB #':,(R1)+ ;PUT IN COLON... TSTB (R1)+ ; skip over colon BR 2$ ;...AND GO DO NEXT VALUE 4$: RETURN ;RETURN TO CALLER .SBTTL QUEUE - *** DOUBLE PRECISION DIVIDE *** ;+ ; DOUBLE PRECISION DIVIDE ROUTINE ;- DIVIDE::MOV R5,-(SP) ;SAVE R5... CLR R0 ;INITIALIZE REMAINDER MOV #31.,R5 ;32 BIT PRECISION 1$: ASL R2 ;DO IT... ROL R3 ROL R0 CMP R0,@R4 BLO 2$ SUB @R4,R0 INC R2 2$: DEC R5 BPL 1$ TST (R4)+ ;POP ARG TO GET RET ADDR MOV (SP)+,R5 ;RESTORE R5... RTS R4 .SBTTL RAD50 TO ASCII CONVERSION ;+ ; R50ASC - RAD50 TO ASCII CONVERSION ROUTINE - FROM RT-11 V4 ; - BUT HANDLES "*" & "%" ; INPUT: R2 => WORD TO CONVERT ; R5 = CHARACTER COUNT ; R1 => OUTPUT BUFFER ; ; *DESTROYS: R0,R5 ; ; R1 LEFT POINTING AT BYTE AFTER LAST CHARACTER CONVERTED ; R2 LEFT POINTING AT WORD AFTER LAST RAD50 INPUT ;- R50ASC::MOV R4,-(SP) ;SAVE R4 !!! MOV R3,-(SP) ;AND R3 1$: MOV #DIVTAB,R3 ;R3 => TABLE OF DIVISORS MOV (R2)+,R4 ;R4 = WORD TO CONVERT 2$: TST -(R3) ;BACKUP THROUGH TABLE - AT END? BEQ 1$ ;IF EQ - YES MOV #-1,R0 ;INIT QUOTIENT REG 3$: INC R0 ;DIVIDE BY POWER OF 50(8) SUB @R3,R4 ;USING REPETITIVE SUBTRACTS BCC 3$ ;UNTIL CARRY SET... ADD @R3,R4 ;RESTORE DIVIDEND TST R0 ;CHAR A BLANK? BEQ 5$ ;Branch if yes... ;V5+ CMP #35,R0 ;Have we an "*"? BNE 33$ ;Nope... ADD #15,R0 ;Yup...'ASCII-ize' BR 8$ ; then merge... ;V5- 33$: CMP #33,R0 ;$ , OR DIGIT? BLO 6$ ;PERIOD OR DIGIT BEQ 7$ ;DOLLAR SIGN 4$: ADD #40,R0 ;ELSE ALPHA OR ? 5$: ADD #16,R0 6$: ADD #11,R0 7$: ADD #11,R0 8$: MOVB R0,(R1)+ ;STORE CONVERTED CHARACTER DEC R5 ;ANY MORE TO DO? BNE 2$ ;YES CONTINUE MOV (SP)+,R3 ;RESTORE R3 MOV (SP)+,R4 ;RESTORE R4 RETURN ;RETURN TO CALLER .WORD 0 ;END OF TABLE FLAG .WORD 1 .WORD 50 .WORD 3100 DIVTAB: ;RAD50 DIVISION TABLE .SBTTL GET JOB & FILE SWITCHES ;+ ;GETSW - EXTRACT # COPIES, # BANNER PAGES, AND/OR WHETHER OR NOT ; TO DELETE THE FILE, FROM THE JOB/FILE REQUEST. IF THE ; OPTION ISN'T SPECIFIED, THE DEFAULT PARAMETERS ARE USED. ; IF THE NUMBER OF BANNER RETURNED IS -1 IT INDICATES THE ; USER DID NOT SPECIFY A NUMBER, THEREFORE 1 MUST BE PRINTED ; OR THE DEFAULT IF GREATER THAN ZERO. (C.A.) ;- GETSW:: MOV #JCOPY,R2 ;R2 => 1ST JOB PARAM MOV #FCOPY,R3 ;R3 => 1ST FILE PARAM BIT #FLG.JR,@R5 ;GUESSED RIGHT? BEQ 1$ ;YES! MOV R2,R3 ;R3 => 1ST JOB PARAM MOV #QCOPY,R2 ;R2 => 1ST DEFAULT QUEUE PARAM 1$: BIT #FLG.CP,@R5 ;MULTIPLE COPIES? BEQ 2$ ;NO... MOVB QNCOP(R5),(R3)+ ;YES...GET # FROM REQ BLK TSTB (R2)+ ;BUMP R2 TO STAY IN SYNCH BR 3$ ;CONTINUE 2$: MOVB (R2)+,(R3)+ ;USE DEFAULT VALUE 3$: BIT #FLG.HD,@R5 ;HOW ABOUT BANNER PAGES? BEQ 4$ ;NO... TSTB QNBAN(R5) ;MINUS ONE? ;V5+ BMI 10$ ;YES ,BRANCH ;V5+ MOVB QNBAN(R5),(R3)+ ;YES...GET # FROM REQ BLK TSTB (R2)+ ;BUMP R2 TO STAY IN SYNCH BR 5$ ;CONTINUE 10$: TSTB (R2) ;IS DEFAULT ZERO? ;V5+ BNE 4$ ;NO, BRANCH, USE DEFAULT ;V5+ MOVB #1,(R3)+ ;USE ONE ;V5+ TSTB (R2)+ ;GET IN SYNCH ;V5+ BR 5$ ;CONTINUE ;V5+ 4$: MOVB (R2)+,(R3)+ ;USE DEFAULT VALUE... 5$: BIT #FLG.DE,@R5 ;DELETE FILE AFTERWARDS? BEQ 7$ ;NO INCB @R3 ;YES...SO INDICATE RETURN ;WE'RE DONE 7$: MOVB @R2,@R3 ;USE THE DEFAULT RETURN ;RETURN .SBTTL SEND & RECEIVE MESSAGES ;+ ;QUEMSG/RCVMSG - SEND & RECEIVE MESSAGES TO & FROM JOBS ;- .ENABL LSB QUEMSG: TST QSYT$K ;ARE WE UNDER A SYS TASK MONITOR? BEQ 2$ ;NO... MOV QJBLK,QRMSG1 ;PUT MQ NAME IN 1ST WD OF MSG .WAIT #17 ;MAKE SURE CHANNEL'S FREE... .PURGE #17 ;CLEAR "MESSAGE" CHANNEL .LOOKUP #MAREA,#17,#QRMSG1 ;OPEN A CHANNEL FOR ACK MSG BCS 1$ ;ERROR ON LOOKUP...NO SUCH JOB .WRITE #MAREA,#17,#QAMSG,#6 ;SEND MSG TO JOB 1$: CLR QRMSG1 ;CLR 1ST WORD OF MSG BLOCK BR 5$ ;THEN MERGE... 2$: .MWAIT ;Make sure channel's free ;V5 .SDAT #MAREA,#QAMSG,#6 ;SEND MESSAGE TO BG JOB 3$: CLR QRMSG1 ;CLR 1ST WORD OF MSG... .RCVDC #MAREA,#QRMSG,#6,#QMESSG ;REGULAR F/B - TRY TO HANG A RECV BCC 6$ ;SUCCESS ! 4$: JMP LUMERR ;NO BG?? RCVMSG: TST QSYT$K ;SYS JOB MONITOR? BEQ 3$ ;NO...USE RCVDC 5$: .READC #MAREA,#16,#QRMSG,#6,#QMESSG ;"BREAKER, BREAKER 16" BCS 4$ ;BAD NEWS! 6$: RETURN ;RETURN TO CALLER .DSABL LSB .SBTTL BANNER - PRINT LEADING BANNER PAGES ;+ ; BANNER - PRINTS BANNER PAGES PRECEDING FILE... ; (THANKS TO A.B.C. & 'LPTSPL' FROM WHICH THIS WAS ; GLOMMED AND MODIFIED TO FIT OUR PURPOSES !) ;- BANNER: TSTB QCLK ;CLOCK ? ;002 BEQ 1$ ;NO... ;**-2 .GTIM #MAREA,#QTOD ;YES...GET THE TIME ;**-3 CALL CNVTIM ;TURN IT INTO SOMETHING USEFUL 1$: .DATE ;GET RT-11 DATE ;002 TST R0 ;IS THERE ONE? ;002 BEQ 2$ ;NO... ;002 CALL CNVDAT ;TURN IT INTO SOMETHING USEFUL ;002 2$: MOVB FBANR,CBANR ;CURRENT # BANNERS TO PRINT INCB CCOPY ;UPDATE WHICH COPY WE'RE PRINTING MOVB CCOPY,R0 ;PUT IT IN R0 MOV #MCOPY,R1 ;R1 => WHERE TO PUT ASCII-IZED # CALL CVT2 ;CONVERT TO ASCII PRINTB: MOV #256.,(PC)+ ;FULL BLOCK XFERS WDCNT: .WORD 0 ;TO START WITH... MOV #IOBUFF,BBUFF ;SET UP OUTPUT BUFFR PTR MOV #FDBLK+2,R2 ;R2 => FILENAME MOV #6.,R5 ;R5 = CHAR COUNT CALL PRBIG ;PRINT IN BIG LETTERS... MOV #FDBLK+6,R2 ;R2 => FILE EXTENSION MOV #3.,R5 ;R5 = CHAR COUNT CALL PRBIG ;PRINT BIG CALL PTRAIL ;PRINT "TRAILER" DECB CBANR ;MORE BANNERS? BNE PRINTB ;YUP... RETURN ;RETURN TO CALLER ;+ ; PRINT FILE NAME IN B I G LETTERS ;- .ENABL LSB PRBIG: MOV #CBUFF,R1 ;R1 => BUFFER CALL R50ASC ;CONVERT RAD50 TO ASCII CLRB @R1 ;MAKE IT ASCIZ... MOV #CBUFF,R5 ;R5 => ASCII NAME MOV #LINE,R0 ;R0 => CHARACTER TABLE 1$: MOV #LBUFF,R4 ;R4 => "LINE" BUFFER MOV (R0)+,R2 ;GET NEXT TABLE ENTRY BEQ 7$ ;DONE MOV R0,-(SP) ;SAVE CURRENT POSITION MOV R5,-(SP) ;AND NAME TO BE CONVERTED 2$: MOVB (R5)+,R1 ;GET NEXT CHAR BEQ 6$ ;DONE WITH LINE - PRINT IT MOV R2,R3 ;COPY TABLE POINTER ADD R1,R3 ;ADD IN CURRENT CHAR CMPB R1,#'A ;ALPHABETIC? BHIS 3$ ;YES...TABLE STARTS WITH "A" ADD #'A-'0+26.,R3 ;NO...POINT TO NUMBERS 3$: MOVB @R3,R3 ;PICKUP TABLE ENTRY ASLB R3 ;GET INTO POSITION... 4$: MOV #SPACE,R0 ;DEFAULT TO BLANK ASLB R3 ;DONE WITH THIS CHAR? BEQ 2$ ;YES BCC 5$ ;NO MOV R1,R0 ;ELSE PRINT CHAR 5$: MOVB R0,(R4)+ ;MAKE 3 COPIES MOVB R0,(R4)+ ..NB3:: MOVB R0,(R4)+ BR 4$ ;7 BYTES PER CHAR 6$: MOVB #CR,(R4)+ ;TERMINATE WITH CR MOVB #LF,(R4)+ ;LF CLRB (R4)+ ;AND A NULL JSR R4,LPRINT ;PRINT LINE 3 TIMES... LBUFF,LBUFF,LBUFF,0 MOV (SP)+,R5 ;RESTORE CHAR PTR MOV (SP)+,R0 ;AND TABLE PTR BR 1$ ;CONTINUE 7$: .REPT 4 ;SPACE DOWN 4 LINES MOVB #LF,(R4)+ .ENDR CLRB (R4)+ ;ASCIZ JSR R4,LPRINT ;"PRINT" IT... LBUFF,0 RETURN ;RETURN TO CALLER .DSABL LSB ;+ ; PRINT THE "TRAILER" ;- PTRAIL: JSR R4,LPRINT ;PRINT 2 LINES OF ALINE ;FANCY, RT-11 LOGO SEPARATORS ALINE TRAILR ;# COPIES & FILE NAME... INSPEC,0 TSTB FDEL ;ARE WE GOING TO DELETE FILE? BEQ 8$ ;NO... JSR R4,LPRINT ;YES...INCLUDE STATEMENT TO THAT DFILE,0 ;EFFECT 8$: JSR R4,LPRINT ;PRINT CRLFLF ;CR,LF,LF ... ALINE ;THE RT-11 LOGO SEPARATOR ... ALINE TOF,0 ;AND FINALLY A FF ; PRINT "SHORT" BUFFER CALL FPRINT ;Force small buffer to print. RETURN ;RETURN TO CALLER .SBTTL BANNER - PRINT BUFFER ;+ ;LPRINT - DOESN'T ACTUALLY DO PHYSICAL XFER UNTIL BUFFER FULL ;- LPRINT: MOV (R4)+,R1 ;GET BUFF ADDR & POP BEQ 4$ ;END OF LIST... MOV BBUFF,R0 ;R0 => CURRENT PLACE IN PUTPUT BUFFER 1$: CMP R0,#IOBUFF+512. ;BUFFER FULL? BLO 3$ ;NOT YET 11$: CALL PRINT ;OUTPUT THE BUFFER INC WRBLK ;BUMP BLK # MOV #IOBUFF,R0 ;SUCCESS - FRESH BUFFER 3$: MOVB (R1)+,(R0)+ ;XFER CHAR INTO BUFFER BNE 1$ ;WE'RE NOT DONE - DO ANOTHER TSTB -(R0) ;WE DON'T WANT THE NULL CHARACTER! MOV R0,BBUFF ;SAVE WHERE WE LEFT OFF TST QSCCA ;CONSOLE ABORT? BEQ LPRINT ;NO... JMP QABORT ;YES! - WE CAN'T GO ON!!! 4$: RTS R4 ;RETURN TO CALLER PRINT: .WRITW #MAREA,#OUTCH,BUFFR,WDCNT,WRBLK ;OUTPUT THE BLOCK BCC 2$ ;NO ERROR CMPB @#$ERRBY,#2 ;CHAN NOT OPEN? ;002 BEQ 2$ ;YES, IGNORE IT!! ;002 JMP WRERR ;OUTPUT ERROR! 2$: RETURN ;RETURN TO CALLER .PAGE .SBTTL FLUSH PRINT CR TO DUMP PRINTER BUFFER ; ; CALLING SEQUENCE: ; CALL FLUSH ; (RETURN) ; ; UPON RETURN, ; R0 DESTROYED ; R1 DESTROYED ; BBUFF ADR(IOBUFF) ; WDCNT 256. ; WRBLK INCREMENTED FLUSH: MOV #IOBUFF,BBUFF JSR R4,LPRINT ;Set CR into IOBUFF. LASTWD,0 CALL FPRINT ;Force IOBUFF to print. RETURN .PAGE .SBTTL PRINT TOP OF FORM ; ; CALLING SEQUENCE: ; CALL TOPFRM ; (RETURN) ; ; UPON RETURN, ; R0 DESTROYED ; R1 DESTROYED ; BBUFF ADR(IOBUFF) ; WDCNT 256. ; WRBLK INCREMENTED TOPFRM: MOV #IOBUFF,BBUFF JSR R4,LPRINT ;Set FF into IOBUFF. TOF,0 CALL FPRINT ;Force IOBUFF to print. RETURN .PAGE .SBTTL FPRINT - PAD IOBUFF WITH NULLs AND Print ; ; CALLING SEQUENCE: ; (BBUFF PTR(NEXT AVAILABLE POSITION IN IOBUFF)) ; CALL FPRINT ; (RETURN) ; ; UPON RETURN, ; R0 DESTROYED ; R1 DESTROYED ; BBUFF ADR(IOBUFF) ; WDCNT 256. ; WRBLK INCREMENTED FPRINT: MOV BBUFF,R0 ;Get working ptr to IOBUFF. MOV #IOBUFF+512.,R1 ;Calculate # characters in IOBUFF SUB R0,R1 ;remaining to be filled. BEQ 2$ ;BR if no filling required. 1$: CLRB (R0)+ ;Fill IOBUFF with NULLs. DEC R1 BNE 1$ 2$: MOV #256.,WDCNT ;Set to print all of IOBUFF. CALL PRINT ;Force IOBUFF to print. MOV #IOBUFF,BBUFF ;Reset working ptr to IOBUFF. INC WRBLK ;Increment # blocks printed. RETURN .PAGE .SBTTL QUEUE - *** PATCH AREA *** .REM % ; NO PATCH AREA .PSECT QPATCH QPACH:: .BLKW 64. ;PATCH SPACE % .END QUEUE