.MCALL .MODULE .MODULE CT,VERSION=09,COMMENT=,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. .SBTTL CONDITIONAL ASSEMBLY SUMMARY ;+ ;COND ; INIT (NDF) generate a test program ; NDF don't generate it ; DF generate it ; ; MUL (DF) generate multi-volume support ; NDF don't generate it ; DF generate it ; ; NEWVOL (DF) generate volume initialization code ; NDF don't generate it ; DF generate it ; ; RCHECK (NDF) generate read after write check code ; NDF don't generate it ; DF generate it ; ; DEBUG (NDF) generate debugging code ; (DF) if INIT defined ; NDF don't generate it ; DF generate it ; ; CT$VEC (260) vector ; ; CT$CSR (177500) CSR ; ; MMG$T std conditional ; TIM$IT std conditional (no code effects) ; ERL$G std conditional (no code effects) ;- ; THE RT11 CASSETTE HANDLER HANDLES HARDWARE AND SOFTWARE FUNCTIONS: ; HW FUNCTIONS ACCESS THE CASSETTE HW DIRECTLY; SW FUNCTIONS DO A ; SERIES OF HW OPERATIONS TO PERFORM SOME FILE SERVICING ROUTINE. ; THE HANDLER INITIALLY STARTS IN SW MODE IN WHICH IT WILL ACCEPT ONLY ; SW FUNCTIONS AND REWIND. SUBSEQUENT TO A REWIND IT WILL ACCEPT ; ANY FUNCTION UNTIL RECEIPT OF A SW FUNCTION WHICH WILL PUT IT ; IN SW MODE AGAIN. THE HANDLER INTERPRETS READS AND WRITES AC- ; CORDING TO THE CURRENT MODE. IN SW MODE A READ OR WRITE WITH A ; BLOCK NUMBER OF 0 WILL CAUSE A REWIND TO START OF FILE BEFORE EX- ; ECUTING THE FUNCTION. ; THE HANDLER RECEIVES THE FUNCTION CODE IN THE LOW BYTE OF THE ; 4TH WORD OF THE Q ELEMENT. A POSITIVE CODE INDICATES A HW FUNCTION; ; A NEGATIVE CODE A SW FUNCTION (SEE LIST OF CODES IN DISPATCH SECTION) ; A 0 CODE INDICATES A READ OR A WRITE DEPENDING ON THE SIGN OF THE WC, ; A POSITIVE WC INDICATING A READ. ; IN SW MODE THE HANDLER WILL REJECT A FUNCTION ILLEGAL IN THE CURRENT ; CONTEXT (E.G. A READ FOLLOWING AN ENTER) AND WILL NOTIFY THE CALLER ; BY SETTING THE SW ERROR BIT IN THE Q ELEMENT. ON AN UNRECOVERABLE HW ; ERROR IT WILL SET THE HW ERROR BIT IN THE Q ELEMENT. ; ASSEMBLY PARAMETERS ; ; PARAMETER FUNCTION ; --------- -------- ; RCHECK CHECK EVERY BLOCK WRITTEN ; ; NEWVOL INCLUDE VOLUME INITIALIZATION FUNCTION ; VOLUME INITIALIZED ON CODE 7 OR ON A ; DELETE WITH NULL FILE NAME. ; ; DEBUG PRODUCE ABSOLUTE CODE WHICH INCLUDES STANDALONE ; DEBUGGING CAPABILITY. .SBTTL GENERAL DESCRIPTION ; THE RT11 CASSETTE HANDLER FOR THE TA11 CONTAINS A DRIVER, ; FILE SERVICE ROUTINES, AND A DISPATCH ROUTINE. ; THE DISPATCH ROUTINE UNLOADS THE Q ELEMENT AND, DEPENDING ON THE SIGN ; OF THE FUNCTION CONTAINED THEREIN, EITHER CALLS THE DRIVER ; (NEGATIVE CODE) OR JUMPS TO THE FILE SERVICE ROUTINE. ; ON CODE 0 (READ OR WRITE DEPENDING ON SIGN OF WORD COUNT), ; IT DETERMINES WHERE TO GO BY THE CURRENT MODE, HW ; OR SW, AS MAINTAINED BY THE HANDLER. THE HANDLER ; STARTS IN SW MODE, ALLOWING ONLY SW FUNCTIONS AND REWIND. ; RECEIPT OF A REWIND OR NON-FILE LOOKUP ALLOWS HW FUNCTIONS ALSO. ; ANOTHER SW FUNCTION SETS SW MODE AGAIN. ; READS AND WRITES IN HW MODE READ OR WRITE ONE RECORD OF LENGTH ; DETERMINED BY THE WC. ; ; FILE SERVICE ROUTINE ; ; THE FILE SERVICE ROUTINE STARTS WITH A DISPATCH SECTION WHICH ; DETERMINES LEGALITY OF THE FUNCTION BY CHECKING A TABLE OF BYTES, ; ONE FOR EACH FUNCTION WITH EACH BIT REPRESENTING A UNIT. ; THE FUNCTIONS THEMSELVES UPDATE THIS TABLE WHEN THEY EXIT BY SETTING ; OR CLEARING BITS USING A WORD WHOSE HIGH AND LOW BYTES EACH HAVE ; A 1 BIT SET CORRESPONDING TO THE CURRENT UNIT. ; THE DISPATCH ROUTINE ALSO SETS A BIT FLAG FOR USE BY THE DRIVER ; INDICATING A SW FUNCTION, OR 'MACRO', IS CURRENTLY EXECUTING. ; ; SEEKS ; ; THE HEART OF THE FSR IS THE SEEK ROUTINE. ENTER, LOOKUP, AND DELETE ; ALL USE IT TO POSITION THE CASSETTE TO THE CORRECT FILE. ; SEEK CONVERTS THE RAD50 FILE NAME TO ASCII, STORING IT IN A SLOT ; PER THE CURRENT UNIT, THEN READS LABELS UNTIL IT FINDS A MATCHING ; NAME OR SENTINEL LABEL. ; ON A NUMBERED FUNCTION (ONE OF NON-0 BLOCK COUNT), IT SPACES TO THE ; N'TH FILE, REWINDING FIRST IF BLOCK < 0. ; OTHERWISE, IT ALWAYS DOES A REWIND FIRST. ; SEEK LEAVES THE TAPE POINTING TO THE FILE'S LABEL OR TO THE SENTINEL ; FILE. WHEN SEEK RETURNS, THE CALLING ROUTINES TEST FOR FILE FOUND ; AND ACT ACCORDINGLY. ; ENTER DELETES ANY FILE FOUND AND CONTINUES TO SEARCH, ; WRITING A LABEL WHEN NO FILE IS FOUND AND TAPE IS AT LEOT. ; LOOKUP CAUSES AN ERROR ON NOT FOUND OR, ON FOUND, SPACES PAST ; THE LABEL TO THE DATA. ; DELETE WRITES A DUMMY LABEL OVER THE LABEL WHICH THE SEEKHAS FOUND ; ; READ, WRITE, AND CLOSE ; ; BOTH READ AND WRITE PERFORM ENOUGH 128 BYTE OR LESS OPERATIONS TO ; SATISFY THE WC REQUESTED. ; READ WILL ZERO OUT THE REMAINDER OF THE USER'S INPUT BUFFER IF IT ; READS FILE GAP DURING THIS PROCESS. ; ALL TRANSFERS, EXCEPT TO BLOCK 0, JUST START FROM THE CURRENT TAPE ; POSITION; BLOCK 0 TRANSFERS REWIND TO START OF FILE BEFORE ; TRANSFERRING, DESTROYING THE FILE'S PREVIOUS CONTENTS ; IN THE CASE OF WRITE. ; A READ WITH 0 WORD COUNT AND NON-0 BLOCK COUNT INITITIATES ; A SEEK OF THE FILE POINTED TO BY THE READ'S CURRENT ADDRESS ; AND RETURNS TO THE CALLER WITH THE TAPE POSITIONED TO THE FILE SEEKED ; ; CLOSE JUST WRITES A SENTINEL FILE. ; ; HANDLING OF END OF VOLUME ; ; IF EOV OCCURS DURING A SEEK, A READ, OR A WRITE, THE HANDLER WILL ; ASK THE USER TO EITHER PUSH THE REWIND BUTTON INDICATING NO NEW VOLUME ; OR PHYSICALLY MOUNT A NEW VOLUME. ON NO NEW VOLUME, THE HANDLER ; RETURNS A SW ERROR. ON NEW VOLUME IT CONTINUES SEEKING OR IT ; READS/WRITES THE LAST BLOCK TRIED ON THE PREVIOUS VOLUME ; AFTER HAVING ENTERED OR LOOKUP'ED THE FILE OF THE NEXT SEQUENCE ; NUMBER ON THE NEW VOLUME. ; ; MULTI-VOLUME OPERATION ; ; WHEN EXECUTING A READ, WRITE, OR SEEK, IF THE HANDLER ENCOUNTERS EOT, ; IT PRINTS A MESSAGE REQUESTING THAT THE USER MOUNT A NEW VOLUME OR ; PUSH REWIND. ; IT THEN EXECUTES NEXTFILE FUNCTIONS IN A LOOP CHECKING THE ; OFFLINE AND EOT BITS AFTER EACH EXECUTION TO DETERMINE WHICH COURSE ; THE USER TOOK. ; ON A REWIND, IT RETURNS A SOFTWARE ERROR. ; ON A RE-MOUNT IT INFORMS THE INTERRUPTED ROUTINE. ; READS AND WRITES WILL OPEN A FILE OF NEXT HIGHER SEQUENCE NUMBER ; ON THE NEW VOLUME AND TRANSFER THE ENTIRE INTERRUPTED BLOCK. ; SEEKS WILL JUST CONTINUE SEEKING ON THE NEW VOLUME. ; ; SERVICE ROUTINES ; ; TO EXECUTE ALL HW FUNCTIONS, THE HANDLER CALLS THE ROUTINE 'SOFT' ; FOLLOWED BY THE FUNCTION CODE. ; SOFT SAVES THE PORTION OF THE STACK BELONGING TO THE HANDLER ; AND SOME REGISTERS, THEN INITIATES THE FUNCTION BY CALLING XCT, ; THUS, JSR R0,SOFT ; REWIND ; EXECUTES A REWIND. ; ; ; THE DRIVER ; ; THE DRIVER CONSISTS OF A FUNCTION INITIATION ROUTINE, XCT, ; AN INTERRUPT ROUTINE, CTINT, AND ERROR PROCESSING ROUTINES. ; XCT DETERMINES THE LEGALITY OF THE FUNCTION WITH RESPECT TO SW ; (E.G. HW FUNCTION ILLEGAL IN SW MODE) AND HW (E.G.READY). ; IT THEN SAVES THE CA AND WC (BYTE COUNT) IN TWO LOCATIONS ; (PSEUDO-REG.S) USED BY THE INTERRUPT ROUTINES AS COUNTERS AND ; INITIATES THE FUNCTION. ; ON HW FUNCTIONS, CA AND WC COME DIRECTLY FROM THE Q ELEMENT. ; SW ROUTINES AND RETRY CODE IN GENERAL LOAD THESE FOR THEIR OWN ; PURPOSES BEFORE CALLING THE DRIVER. HAVING INITIATED THE FUNCTION, ; XCT RETURNS TO THE CALLER VIA AN RTS PC. ; ; THE INTERRUPT ROUTINE HANDLES FUNCTION COMPLETIONS, TRANSFER ; REQUESTS AND ERRORS BY EITHER RETURNING TO THE MACRO OR USER PROGRAM ; THAT INITIATED THE REQUEST, TRANSFERRING ONE BYTE TO OR FROM THE DATA ; BUFFER OR ABORTING OR RETRYING. ; ; THE EXIT SEQUENCE SETS PROPER ERROR BITS AND, WHEN AN UNRECOVERABLE ; ERROR OCCURS IN SW MODE, ATTEMPTS TO SAVE THE FILE STRUCTURE: ; IT BACKFILES. THEN, ON AN ERROR DURING WRITE OR ENTER, WRITES LEOT. ; ; INTERRUPT LEVEL OPERATION ; ; THE CA HANDLER MUST, IN SOFTWARE MODE, RUN AT INTERRUPT LEVEL. ; THAT IS, IT MUST EXECUTE ONLY WHEN FIRST CALLED BY THE MONITOR ; OR AFTER AN INTERRUPT TO CASSETTE HAS OCCURRED. ; SINCE SW FUNCTIONS MUST ALL EXECUTE A SERIES OF HW OPERATIONS, ; THE HANDLER MUST RETURN TO THE MONITOR AFTER INITIATION OF EACH HW ; OPERATION AND DO SO WITH THE STACK AND REGISTERS LOOKING JUST AS ; THEY DID AT THE TIME OF THE CALL OR INTERRUPT. ; TO DO THIS, THE HANDLER, BEFORE RETURNING, SAVES IN MEMORY THE ; PORTION OF THE STACK IT HAS ADDED AND ALL REGISTERS IT WILL LATER ; NEED. WHEN AN INTERRUPT OCCURS, THE INTERRUPT ROUTINE RESTORES STACK ; AND REGISTERS AND RETURNS TO THE SW FUNCTION ROUTINE THAT ISSUED ; THE LAST HW REQUEST. ; THUS, SW OPERATION ALTERNATES BETWEEN A SAVE OF THE STACK AND RETURN ; AND A RESTORATION OF THE STACK AND EXECUTION OF HANDLER CODE. UPON ; COMPLETION OF THE LAST HW OPERATION FOR A SW FUNCTION, THE HANDLER ; EXITS TO THE Q MANAGER WITH THE LAST INTERRUPT AND 2 REGISTERS ON THE ; STACK. .SBTTL DEFINITIONS .MCALL .DRDEF,.PRINT,.DATE,.FORK .MCALL .ASSUME .ADDR .DRDEF CT,13,,0,177500,260,DMA=NO .IF EQ MMG$T ;If not XM .DRPTR .IFF .DRPTR FETCH = *NO* .ENDC ;EQ MMG$T .DREST CLASS=DVC.CT .DRSPF <-6> ;WRITE FILE GAP .DRSPF <-5> ;REWIND .DRSPF <-4> ;NEXT BLOCK .DRSPF <-3> ;NEXT FILE .DRSPF <-2> ;LAST BLOCK .DRSPF <-1> ;LAST FILE .IIF NDF RTE$M, RTE$M=0 .IIF NDF MMG$T, MMG$T=0 .IIF NDF ERL$G, ERL$G=0 .IIF NDF TIM$IT, TIM$IT=0 T5 = R5 ;ADDR OF TACS TACS = CT$CSR ERR = 100000 ;ERROR CRC = 40000 ;CRC ERROR BOTEOT = 20000 ;CLEAR LEADER WRL = 10000 ;WRITE LOCKED FGAP = 4000 ;FILE GAP ENCOUNTERED TIME = 2000 ;TIMING ERROR OFF = 1000 ;OFFLINE UNITNO = 400 ;UNIT NUMBER (0 OR 1) TREQ = 200 ;TRANSFER REQUEST INTEN = 100 ;INTERRUPT ENABLED READY = 40 ;READY FOR COMMAND ILBS = 20 ;INITIATE LAST BYTE SEQUENCE FUNC = 2 ;BASE OF FUNCTION BITS WGAP = 0 ;WRITE FILE GAP WRITE = 1 ;WRITE READ = 2 ;READ LSTFIL = 3 ;SPACE REVERSE FILE LSTBLK = 4 ;SPACE REVERSE BLOCK NXTFIL = 5 ;SPACE FORWARD FILE NXTBLK = 6 ;SPACE FORWARD BLOCK REWIND = 7 ;REWIND GO = 1 ;INITIATE FUNCTION TADB = TACS+2 ;DATA BUFFER CTDSIZ = 0 ;DEVICE SIZE CTSTS = 12013 ;DEVICE STATUS WORD. ; SOFTWARE FUNCTION CODES RW = 0 ;READ/WRITE CLOSE = 1 DELETE = 2 LOOKUP = 3 ENTER = 4 SJMON = 1 ;BIT TO TEST FOR SJ MONITOR HWERR = 1 ;HARDWARE ERROR BIT IN CSW EOVBIT = 40000 ;EOV ENCOUNTERED BIT IN CSW EOFBIT = 20000 ;EOF ENCOUNTERED BIT IN CSW MONLOW = 54 ;BASE ADDR. OF MONITOR OFFSET = 270 ;PTR TO Q MANAGER COMP ENTRY OFFBUF = 266 ;OFFSET TO USR BUFFER OFFSWW = 272 ;OFFSET TO SW ERROR WORD,SPUSR CONFIG = 300 ;OFFSET TO CONFIG WORD SYNCH = 324 ;OFFSET TO SYNCH ENTRY POINT ;SPUSR CODES. FILNFD = 1 ;FILE NOT FOUND/OR DEVICE FULL. ILLFUN = 2 ;ILLEGAL FUNCTION/OR DEVICE IN USE. PSW = -2 ;PROGRAM STATUS WORD PR6 = 300 ;PRIORITY 4 PR7 = 340 ASTRSK = 52 .SBTTL ENTRY AND DISPATCH ROUTINE ; CONDITIONAL DEFINITIONS RCHECK=0 ;ALWAYS ASSEMBLE WITH RAW AVAILABLE MUL=0 ;MULTI-VOLUME ALLOWED NEWVOL=0 ;VOLUME INIT ON NON-FILE DELETE ; RCHECK=0 ;READ AFTER WRITE CHECKING .IF DF,INIT DEBUG=0 NEWVOL=0 .ENDC .IF DF RCHECK .DRSET RAW,
,OPRAW,NO OPRAW: MOV (PC)+,R3 BNE .+NOTDUN-RAWOPT MOV R3,RAWOPT RETURN .ASSUME . LE 1000,MESSAGE=<;Set code too big> .ENDC ;DF RCHECK .IIF NDF DEBUG, .NLIST .IF DF,DEBUG .ENABL AMA .ASECT .=CT$VEC CTINT 0 .=1000 .ENDC .IIF NDF DEBUG, .LIST .SBTTL LOAD POINT, INITIATE REQUEST .IIF NDF DEBUG,.NLIST ;JD00 .IF DF DEBUG ; ;OUT .DRBEG FOR DEBUG .WORD CT$VEC ;CA INTERRUPT VECTOR ADDRESS .WORD CTINT-. ;OFFSET TO INTERRUPT ROUTINE .WORD PR6 ;PRIORITY CTLQE: .WORD 0 ;PTR TO LAST Q ENTRY CTCQE: .WORD QEL ;PTR TO CURRENT Q ENTRY, WORD 3 ;JD00 CSWDUM: .WORD 0 ;DUMMY CSW QCSW: .WORD CSWDUM ;PTR TO CSW QEL: QB: .WORD 0 ;BLOCK QF: .BYTE 0 ;FUNCTION QU: .BYTE 0 ;UNIT QCA: .WORD 0 ;ADDR QWC: .WORD 400 ;WC JSW: .WORD 0 ;X EXT=.+4 NAME: .RAD50 "FILEN EXT" .EVEN DATA=. TEST: ; NUVOL MOVB #7,QF+1 JSR PC,WAIT .IF DF INIT EMT 340+10 ;EXIT .ENDC DO: ; ENTER MOV #NAME,QCA ;ENTER MOV #0,QB MOVB #ENTER,QF JSR PC,WAIT ; WRITE MOV PC,R0 ADD #DATA-.,R0 MOV R0,QCA CLRB QF MOV #-1000,QWC JSR PC,WAIT ; CLOSE MOVB #CLOSE,QF JSR PC,WAIT ; ENTER (NON-REWIND) MOV #NAME,QCA ;ENTER MOV #1,QB MOVB #ENTER,QF JSR PC,WAIT ; WRITE MOV PC,R0 ADD #DATA-.,R0 MOV R0,QCA CLRB QF MOV #-40,QWC JSR PC,WAIT ; CLOSE MOVB #CLOSE,QF JSR PC,WAIT ; LOOKUP MOVB #LOOKUP,QF MOV #0,QB MOV #NAME,QCA JSR PC,WAIT ; READ MOV @#MONLOW,R0 MOV OFFBUF(R0),QCA CLRB QF MOV #400,QWC JSR PC,WAIT INC QB MOV #40,QWC JSR PC,WAIT MOV #400,QWC JSR PC,WAIT ; CLOSE MOVB #CLOSE,QF JSR PC,WAIT ; DELETE MOV #NAME,QCA MOV #0,QB MOVB #DELETE,QF JSR PC,WAIT NXTF: ADD #51,NAME+2 ;MAKE NEW FILE NAME BR DO ; REWIND MOVB #-5,QF JSR PC,WAIT ; WRITE MOV PC,R0 ADD #DATA-.,R0 MOV R0,QCA MOV #-400,QWC CLRB QF JSR PC,WAIT MOV #-400,QWC JSR PC,WAIT ; WRITE FILE GAP MOVB #-6,QF JSR PC,WAIT ; BACK BLOCK MOVB #-2,QF JSR PC,WAIT ; READ MOV @#MONLOW,R0 MOV OFFBUF(R0),QCA MOV #400,QWC CLRB QF JSR PC,WAIT ; BACK FILE MOVB #-1,QF JSR PC,WAIT ; FORWARD FILE MOVB #-3,QF JSR PC,WAIT HALT ; WAIT INITIATES THE ACTION THEN WAITS FOR COMPLETION WAIT: CLR (PC)+ ;CLEAR DONE FLAG WFLAG: .WORD 0 CLR @QCSW JSR PC,CT ;START FUNCTION WTLOOP: TST WFLAG ;THEN WAIT BEQ WTLOOP BIT #3,@QCSW BNE TMDK BIT #SWERR,@SWWPTR BNE TMDK RTS PC ;RETURN TO CALLER WHEN FLAG S TMDK: CLR @QCSW CLR @SWWPTR .PRINT #EM RTS PC EM: .ASCIZ "ERROR" QMAN: MOV SP,WFLAG ;SET FLAGG WHEN FUNCTION DONE MOV (SP)+,R0 MOV (SP)+,R3 RTI ;THEN RETURN TO WAIT LOOP ; SET DESIRED FUNCTION IN WF THEN START HERE START: JSR PC,WAIT HALT .ENDC ;.IF DF DEBUG .IIF NDF DEBUG, .LIST ;START OF HANDLER .DRBEG CT .ENABL LSB CT: SUB #10,SP ;PUSH 4 DUMMY REGISTERS MOV SP,(PC)+ ;SAVE STACK POINTER SPSAV: .WORD 0 ;(ORIGINAL STACK POINTER) MOV #TACS,T5 ;POINT R5 TO TACS (INT ROUTINE DOES SAME) MOV @#MONLOW,R0 MOV CONFIG(R0),CTSJ ;CONFIG WORD STORED ADD #OFFSWW,R0 ;POINT TO SW ERROR WORD MOV R0,(PC)+ ;AND SAVE PTR SWWPTR: .WORD 0 ;(PTR TO SW ERROR WORD) TST (PC)+ ;TEST DONE FLAG FIN: .WORD 0 ;(<0 MEANS LAST OP NOT COMPLETED) BGE 1$ ;IF LAST OP NOT COMPLETE JSR PC,DUNDEL ;INIT FLAG TABLE 1$: DEC FIN ;IN EITHER CASE SET FLAG <0 CLR IGNOFF ;SET FLAG TO CAUSE OFFLINE ERROR RETURN ;*************** ALL MMG$T STUFF ID JD00 *********** .IF NE MMG$T CLRB CTMVS ;CLEAR MULTI VOLUME SEEK FLAG. CLR RAWFLG ;CLEAR RAWFLW AND CTURW .ENDC MOV CTCQE,R0 ;GET PTR TO Q ELEMENT MOV -2(R0),(PC)+ ;SAVE PTR TO CSW CSWPTR: .WORD 0 ;(PTR TO CSW) MOV (R0)+,(PC)+ ;GET BLOCK BLOCK: .WORD 0 MOVB 1(R0),R1 ;GET AND ISOLATE JOB NUMBER ASR R1 ASR R1 ASR R1 BIC #177770,R1 MOV R1,SYNBLK+2 ;SAVE IN SYNCH BLOCK MOVB (R0)+,R1 ;GET FUNCTION CODE CLR R3 ;SET FOR UNIT 0 MOV #401,R2 ;SET UNIT MASKS MOVB (R0)+,(PC)+ ;GET UNIT UNIT: .WORD 0 ;(CURRENT UNIT) BIC #177770,UNIT ;UNIT IN LO 3 BITS BEQ 2$ ;BRANCH IF UNIT 0 CMP UNIT,#1 ;ONLY UNITS 0 AND 1 LEGAL BNE CTILLF ;UNIT IS > 1-REPORT ERROR ;JD00 ASL R2 ;SHIFT MASK LEFT BIS #UNITNO,R3 ;AND SET TO UNIT 1 2$: MOV R3,(T5) ;SET UNIT BIT .IF NE MMG$T MOV R2,UBITS ;SAME AS BELOW MOV (R0)+,CA NEG (R0) MOV (R0)+,WC TST (R0)+ ;SKIP Q.COMPLETION. MOV (R0),QPAR ;GET PAR BASE BR CGETC CA: .WORD 0 WC: .WORD 0 UBITS: .WORD 0 QPAR: .WORD 0 .IFF MOV R2,(PC)+ UBITS: .WORD 0 ;(2 BYTES WITH UNIT BIT SET IN EACH) MOV (R0)+,(PC)+ ;GET ADDRESS CA: .WORD 0 NEG (R0) ;MAKE WC NEGATIVE IN CASE SPACES MOV (R0)+,(PC)+ WC: .WORD 0 ;(WORD COUNT/LATER, BYTE COUNT) .ENDC .DSABL LSB .SBTTL FUNCTION DISPATCHER ; THE FOLLOWING CODE ALTERS THE FUNCTION CODE IN WORD 8 OF THE Q ELT ; FOR USE BY THE HANDLER. ; THE FUNCTION CODE COMES DOWN LIKE THIS: ; ; VALUE FUNCTION ; ----- -------- ; -6 WRITE FILE GAP ; -5 REWIND ; -4 NEXT BLOCK ; -3 NEXT FILE ; -2 LAST BLOCK ; -1 LAST FILE ;NOTE: if you add any SPFUN code (bloody unlikely!) also add them to .DRSPF ; 0 READ/WRITE ; 1 CLOSE ; 2 DELETE ; 3 LOOKUP ; 4 ENTER ; ; VALUES > 0 INDICATE A SOFTWARE FUNCTION. ; VALUES < 0 INDICATE A HARDWARE FUNCTION. ; ON CODE 0 (R/W), WC > 0 MEANS READ, WC < 0 MEANS WRITE. ; THE FOLLOWING CODE ALTERS ALL THE ABOVE VALUES. ; ON A SOFTWARE FUNCTION, IT JUST DIPATCHES TO THE SW SECTION. ; ON A HW FUNCTION, IT SUBTRACTS 2 FROM THE FUNCTION, MAKES IT POSITIVE ; AND GOES TO THE HW SECTION OF THE HANDLER. ; ON READ/WRITE (CODE 0), IT DETERMINES WHETHER TO DO A HW OR SW ; READ/WRITE BY LOOKING AT THE HW FLAG. ; ON A SW R/W IT SETS READ CODE=5, WRITE=6. ; ON A HW R/W IT SETS READ CODE=2, WRITE=1 .ENABL LSB CGETC: TST R1 ;EXAMINE FUNCTION CODE BMI 2$ ;NEGATIVE, GO DO HARDWARE FUNCTION BGT MACRO ;>0, GO DO SOFTWARE FUNCTION .IF NE MMG$T INCB CTURW ;SET READ/WRITE DATA TO USER MEMORY FLAG. .ENDC MOV WC,R0 ;READ OR WRITE. GET WORD COUNT BLE 1$ ;IF READ, LEAVE CODE 0 INC R1 ;CHANGE WRITE TO CODE 1 NEG R0 ;AND MAKE WC NEGATIVE 1$: ASL R0 ;*2 = BYTE COUNT MOV R0,(PC)+ ;SET TC TO SIZE OF TRANSFER TC: .WORD 0 ;(COUNT OF ACTUAL MEMORY XFRES TO DO) MOV R0,WC ;SAVE IN WC, TOO MOV R0,(PC)+ ;SAVE TOTAL NUMBER NUMBER OF BYTES REQUESTED ;JD00 CTTQCT: .WORD 0 ;TOTAL # OF BYTES REQUESTED. ;JD00 BITB R2,F.HW ;R2 HAS UBITS. ARE WE IN HW MODE? BEQ MACRW 2$: SUB #2,R1 ;CHANGE READ TO -2, WRITE TO -1 CLRB F.MACRO ;SET NON-MACRO MODE NEG R1 ;MAKE FUNCTION POSITIVE CMP R1,#10 ;IGNORE BAD FUNCTIONS BGT CTILLF ; ;JD00 JMP XCT ;WITH FUNC IN R1, GO XCT FUNCTION .DSABL LSB .SBTTL FILE SERVICE ROUTINES ; FILE SERVICE ROUTINES ; MACRO DISPATCHES TO THE PROPER SOFTWARE FUNCTION. .ENABL LSB MACRW: ADD #5,R1 ;FIX R1 FOR READ/WRITE MACRO: CMP R1,#MAXFUN ;IGNORE NON-EXISTANT FUNCTIONS BPL CTILLF ; ;JD00 MOV UBITS,R3 ;GET UNIT BIT .ADDR #FLGTAB,R0 ;SET FOR FLAG TEST BICB R3,(R0)+ ;DISALLOW HW FUNCTIONS BISB R3,@R0 ;SET MACRO MODE ADD R1,R0 ;INDEX INTO FLAGS BITB R3,@R0 ;BIT SET? BEQ CTILLF ;IF NOT SET, ABORT FUNCTION ;JD00 BICB R3,ENTFLG ;IF OK, SET ENTER IN PROGRESS FLAG ADD #MACROS-FLGTAB-1,R0 ;SET FOR DISPATCH ADD R1,R0 ;ADD FUNCTION AGAIN ADD @R0,R0 ;ADD OFFSET TO ROUTINE JSR PC,@R0 ;AND DISPATCH 1$: JMP RESP ;RETURN TO Q MANAGER ;SET SPUSR FOR THE FOLLOWING CTILLF: CMP R1,#1 ;IF WE'RE DOING A CLOSE ;DF ;002 BEQ 1$ ;THEN DON'T REPORT ERROR ;DF ;002 BIS #ILLFUN,@SWWPTR ;ILLEGAL FUNCTION OR DEVICE IN USE ;JD00;002 BR 1$ ; ;JD00 ;**-1 SWINIT: BIS #FILNFD,@SWWPTR ;FILE NOT FOUNF OR DEVICE FULL ;JD00 BR 1$ ;AND EXIT .DSABL LSB .SBTTL WRITE SERVICE ; WRITD PERFORMS WRITE SERVICE .ENABL LSB WRITD: MOV #-200,WC ;SET FOR 128. BYTE WRITE WRTBLK: .IF DF RCHECK MOV #3,(PC)+ ;COUNT THREE POSSIBLE RETRIES WTRY: .WORD 0 ;(COUNT OF WRITE RETRIES) WRTB: .ENDC MOV #-200,TC ;ALWAYS TRANSFER A FULL BLOCK JSR R0,SOFT ;DO THE WRITE .WORD WRITE .IF DF RCHECK BIT #BOTEOT,(T5) ;IF EOT REACHED, RAWOPT: BR NOTDUN ;DATA NOT ALL XFERRED SO DON'T CHECK .ASSUME . LE CTSTRT+1000,MESSAGE=<;Set code object not in block 1> JSR PC,BSP ;TO READ CHECK, BSP 1 BLOCK MOV CA,R2 ;SAVE ORIGINAL CA FOR POSSIBLE RETR .IF NE MMG$T INCB RAWFLG ;SET READ AFTER WRITE FLAG. .ENDC JSR PC,READU ;AND READ THE BLOCK USING PREV. TC MOV CA,R1 ;WHEN DONE, POINT TO INPUT BUFFER MOV R2,CA ;RESTORING CA TO ITS ORIG. CONTENTS MOV WC,R3 ;COUNT BYTES XFERRED .IF NE MMG$T MOV R4,-(SP) ;SAVE R4 MOV R2,TACA ;STORE BUFFER ADDRESS OFFSET OF MEMORY. .ADDR #TACA-4,R4 ;POINT R4 AT ADDRESS OF USER BUFFER JUST WRITTEN. 1$: JSR PC,@$GTBYT ;GET A BYTE FROM MEMORY. CMPB (SP)+,(R1)+ ;COMPARE IT WITH DATA IN HANDLER. .IFF 1$: CMPB (R1)+,(R2)+ ;THEN GO THRU BUFFER COMPARING .ENDC BNE 2$ ;DATA WRITTEN WITH READ INC R3 ;IF IT CHECKS, BLT 1$ .IF NE MMG$T CLRB RAWFLG ;CLEAR FLAG. MOV (SP)+,R4 ;RESTORE R4. .ENDC .ENDC NOTDUN: RTS PC ;GOOD WRITE, POSITION GOOD NOW 2$: .IF NE MMG$T MOV (SP)+,R4 ;RESTORE R4 .ENDC .IF DF RCHECK DEC WTRY ;IF NOT, DEC RETRY COUNT BGT WRTB ;AND TRY UP TO THREE TIMES JMP ERRHW ;IF STILL BAD, CALL IT HW ERROR .ENDC .DSABL LSB .SBTTL $LOOKUP, $ENTER ; $LOOKUP OPENS AN EXISTING FILE FOR INPUT. ; IT POSITIONS THE TAPE TO JUST BEFORE THE 1ST DATA BLOCK. .ENABL LSB $LOOKUP: .IF NE MMG$T JSR PC,GETFLN ;GET FILE NAME .ENDC TST @CA ;ON NON-FILE LOOKUP, BEQ 1$ ;GO REWIND JSR PC,SEEK ;ELSE, LOOK FOR FILE BR SWINIT ;IF NONE FOUND, RETURN ERROR LUKC: JSR PC,FSP ;ELSE, SPACE BEYOND LABEL TO DATA JSR PC,3$ ;SET FLAG TABLE AS FOR ENTER BICB R1,-(R0) ;BUT SWAP READ AND WRITE SETTINGS BISB R1,-(R0) RTS PC ;AND RETURN 1$: JSR R0,SOFT ;ON NON-FILE, REWIND .WORD REWIND BISB UBITS,F.HW ;SET HW MODE 2$: JSR PC,3$ ;SET FLAG TABLE AS FOR LOOKUP BIS R1,-(R0) ;BUT ALLOW BOTH READ AND WRITE RTS PC ; $ENTER OPENS A NEW FILE AT THE END OF THE TAPE BY WRITING ITS LABEL ; IT DELETES FILES OF THE SAME NAME THAT IT FINDS ALONG THE WAY. $ENTER: .IF NE MMG$T JSR PC,GETFLN ;GET FILE NAME. .ENDC TST @CA ;IF NON-FILE ENTER, BEQ 2$ ;GO DO NOTHING JSR PC,SEEK ;ELSE, LOOK FOR FILE OF SAME NAME ALREADY ON TAPE BR NFOUND ;IF NOT FOUND, ENTER THE NEW FILE OPEN: TST BLOCK ;IF FOUND RETURN BUT ON NUMBERED SEEK, BEQ NFOUND ;ENTER OVER FILE LEFT POINTING TO JSR PC,DELIT ;IF SAME NAME FOUND, DELETE IT JSR PC,CHKHDR ;AND CONTINUE TO SEEK LEOT BR NFOUND ;IF NONE FOUND, ENTER NEW FILE BR OPEN ;CONTINUE TO DELETE IF DUPLICATE FOUND AGAIN NFOUND: BIS UBITS,(PC)+ ;INIT ENTER FLAG AND SPARE FLAG .BYTE 0 ;(SPARE FLAG) ENTFLG: .BYTE 0 ;(=0 MEANS ENTER IN PROGRESS) JSR PC,LABEL ;THEN WRITE THE NEW LABEL WITH 0 COUNT 3$: .ADDR #F.CLOSE,R0 ;POINT TO BYTE TABLE MOV UBITS,R1 ;GET UNIT BITS IN HI AND LO BYTE BISB R1,(R0)+ ;ALLOW CLOSE ON THIS UNIT BICB R1,(R0)+ ;DISALLOW DELETE BIC R1,(R0)+ ;DISALLOW ENTER AND LOOKUP BICB R1,(R0)+ ;DISALLOW READ BISB R1,(R0)+ ;ALLOW WRITE MOV CTCQE,R2 ;CLEAR WORD 6 OF Q FOR MONITOR ;JD00 CLR Q$WCNT(R2) ;WORD COUNT 0 WILL RETURN 0 FILE SIZE ;JD00 RTS PC .DSABL LSB .SBTTL $NEWVOL, $DELETE, $CLOSE .ENABL LSB .IF DF NEWVOL ; $NEWVOL INITIALIZES THE VOLUME BY WRITING FILE GAP-SENTINEL FILE-FILE GAP $NEWVOL:JSR R0,SOFT ;REWIND AND CLEAR FILE COUNT .WORD REWIND BR 2$ ;GO WRITE SENTINEL FILE .ENDC ; $DELETE DELETES A FILE BY WRITING A DUMMY LABEL OVER ITS LABEL. .IF NE MMG$T SWINI2: JMP SWINIT ;SET ERROR AND RETURN. .ENDC $DELETE: .IF NE MMG$T JSR PC,GETFLN ;GET FILE NAME. .ENDC .IF DF,NEWVOL TST @CA ;IF NULL FILE NAME, BEQ $NEWVOL ;INITIALIZE VOLUME .ENDC JSR PC,SEEK ;FIND THE FILE .IF NE MMG$T BR SWINI2 .IFF SWINI2: BR SWINIT ;IF NONE FOUND, QUIT .ENDC DELIT: .ADDR #FILNAM,R2 ;POINT R2 TO FILE NAME IN LABEL MOVB #ASTRSK,(R2) ;MAKE FILENAME START WITH * CLRB SEQNO ;DELETED FILES HAVE 0 SEQ NO JSR PC,DELAB ;THEN WRITE THE LABEL W/O DATE, ETC. 1$: JSR R0,SOFT ;THEN SPACE TO END OF FILE .WORD NXTFIL BR DUNDEL ;THEN GO SET UP FLAG TABLE (SAMELY AS CLOSE) ; $CLOSE CLOSES A FILE. A CLOSE OF AN ENTER'ED FILE (INDICATED BY ; THE F.WRITE FLAG SET IN FLAG TABLE) WRITES SENTINEL LABEL. ; A CLOSE OF A LOOKUP SPACES FORWARD PAST THE END OF THE FILE. $CLOSE: BITB UBITS,F.WRITE ;IF WRITE NOT ALLOWED, BEQ 1$ ;GO CLOSE A LOOKUP BITB UBITS,F.READ ;IF BOTH READ AND WRITE ALLOWED, BNE DUNDEL ;NON-FILE CLOSE. GO SET TABLE 2$: JSR PC,WSENT ;WRITE SENTINEL FILE DUNDEL: .ADDR #F.CLOSE,R0 ;POINT TO BYTE TABLE MOV UBITS,R1 ;GET UNIT BITS BICB R1,(R0)+ ;DISALLOW CLOSE BISB R1,(R0)+ ;ALLOW DELETE BIS R1,(R0)+ ;ALLOW LOOKUP AND ENTER BIC R1,(R0)+ ;DISALLOW READ AND WRITE CLRB CTEOFF ;CLEAR EOF FLAG ;JD00 RTS PC .DSABL LSB .IF NE MMG$T ;GETFLN WILL GET THE FILE NAME POINTED ;TO BY THE Q AND STORE IT IN FILENM. GETFLN: .ADDR #CA-4,R4 ;POINT R4 AT CA ;JD00 MOV #6,R2 ;GET 6 BYTES OF FILE NAME .ADDR #FILENM,R1 ;POINT R1 AT BUF. TO STORE FILE NAME. MOV R1,R0 ;SAVE ADDRESS OF FILE NAME. 1$: JSR PC,@$GTBYT ;READ A BYTE OF FILE NAME. MOVB (SP)+,(R1)+ ;STORE IN BUF. DEC R2 BNE 1$ MOV R0,CA ;POINT CA AT FILE NAME. RTS PC ;JD00 .ENDC .SBTTL $READ ; $READ READS THE NEXT SEQUENTIAL BLOCKS FROM THE CASSETTE, READING ; ENOUGH BLOCKS TO SATISFY THE WORD COUNT BUT TRANSFERRING ONLY ; THE NUMBER OF WORDS SPECIFIED. ; ON END OF FILE, IT DISCONTINUES READING, SETS THE EOF BIT, AND CLEARS ; OUT WORDS IN THE USER'S BUFFER NOT READ. .ENABL LSB $READ: TSTB CTEOFF ;SET IF EOF WAS FOUND ON LAST READ ;JD00 BNE SWEOF ;YES,SET EOF AND RETURN. ;JD00 MOV WC,R4 ;GET WC BNE 1$ ;NOW IF, WC=0 TST BLOCK ;AND BLOCK NOT =0 BEQ 1$ ADD #2,CA ;PT. TO FILE NAME (NOT DEV) .IF NE MMG$T JSR PC,GETFLN ;GET THE FILE NAME. CLRB CTURW ;NOT I/O TO USER MEMORY. .ENDC JSR PC,SEEK ;AND DO A SEEK BY NUMBER OR NAME BR DUNDEL ;AND SET CLOSE FLAGS BR DUNDEL ;WHETHER FOUND OR NOT 1$: JSR PC,TSTBAK ;ELSE, REWIND TO START OF FILE ON BLOCK 0 2$: MOV #-200,WC ;SET FOR 128. BYTE READ MOV R4,TC ;SET TRANSFER COUNT TO REMAINING BYTES JSR PC,READB ;READ 128. BYTES BIT #FGAP,(T5) ;ON FILE GAP ENCOUNTERED, BEQ 4$ JSR PC,BSP ;BACK UP OVER LAST BLOCK MOV TACA,R2 ;GET COUNT OF WORDS NOT XFERRED CMP R4,CTTQCT ;TEST IF ANY DATA WAS READ. ;JD00 BEQ SWEOF ;NO,THEN SET EOF AND RETURN. ;JD00 .IF NE MMG$T 3$: MOV R4,-(SP) ;SAVE R4 .ADDR #TACA-4,R4 ;R4-> MAKE BELIEVE Q. CLR -(SP) JSR PC,@$PTBYT ;STORE ZERO IN MEMORY. MOV (SP)+,R4 ;RESTORE R4 .IFF 3$: CLRB (R2)+ ;AND CLEAR THESE OUT .ENDC INC R4 BNE 3$ INCB CTEOFF ;DATA WAS XFERED,AND EOF FOUNF ;JD00 JMP RESP ;SET FLAG TO SET EOF ON NEXT READ ;JD00 ;AND RETURN WITHOUT EOF SET. ;JD00 SWEOF: BIS #EOFBIT,@CSWPTR ;SET EOF BIT CLRB CTEOFF ;CLEAR EOF FLAG,WHEN EOF IS SET ;JD00 SWINI3: BR SWINI2 ;THEN SET ERROR BIT 4$: .IF DF MUL JSR PC,EOTCHK ;ELSE, CHECK FOR NEW VOLUME MOUNTED BEQ 5$ ;IF NOT, CONTINUE READING CLR BLOCK JSR PC,SEEKC ;ELSE, SEEK THE CURRENT FILE BR SWEOF ;IF NOT FOUND, EXIT WITH EOF ERROR JSR PC,LUKC ;ELSE, SPACE TO DATA PORTION MOV WCSAV,R4 MOV CASAV,CA .IF NE MMG$T CLRB CTMVS ;CLEAR MUTI VOLUME FLAG. .ENDC BR 2$ ;AND DO LAST READ AGAIN 5$: .ENDC ADD #200,R4 ;INCREASE COUNT BY AMOUNT XFERRED BCS RTSPC ;DONE. GO RETURN .IF NE MMG$T ADD #2,QPAR .IFF ADD #200,CA ;BUMP CURRENT ADDRESS .ENDC BR 2$ ;READ ANOTHER BLOCK. CTEOFF: .BYTE 0 ;EOF FLAG=1 TO SET EOF ON NEXT READ ;JD00 ;ELSE =0 CTMVS: .BYTE 0 ;=1 IF DOING SEEK OF FILE IN NEXT ;JD00 ;VOLUME,ELSE=0 .DSABL LSB .SBTTL $WRITE ; $WRITE WRITES ENOUGH 128. BYTE BLOCKS TO SATISFY THE WORD COUNT. ; ON BLOCK 0 IT REWINDS TO START OF FILE BEFORE WRITING. $WRITE: MOV WC,R4 ;GET WC JSR PC,TSTBAK ;REWIND ON BLOCK 0 1$: JSR PC,WRITD ;WRITE 128 BYTES .IF DF MUL JSR PC,EOTCHK ;CHECK FOR NEW VOLUME MOUNTED BEQ 4$ ;IF NOT, CONTINUE WRITING CLR BLOCK JSR PC,SEEKC ;ELSE, SEEK CURRENT FILE BR 2$ ;IF NOT FOUND, GO ENTER FILE JSR PC,OPEN ;ELSE, DELETE AND CONTINUE SEARCH BR 3$ ;WHICH WHEN DONE HAS ENTERED FILE 2$: JSR PC,NFOUND ;ENTER FILE 3$: MOV WCSAV,R4 MOV CASAV,CA .IF NE MMG$T CLRB CTMVS ;CLEAR MULTI VOLUME FLAG. .ENDC BR 1$ ;AND TRY THE WRITE AGAIN 4$: .ENDC ADD #200,R4 ;INCREASE COUNT BY AMOUNT XFERRED BCS RTSPC ;DONE, GO RETURN .IF NE MMG$T ADD #2,QPAR ;ADD 200 BYTES VIA ADDRESS BASE. .IFF ADD #200,CA ;BUMP CURRENT ADDRESS .ENDC BR 1$ .SBTTL READ SERVICE ROUTINE ; READ PERFORMS READ SERVICE. READU: .ADDR #LBLBUF,R0 ;GET ADDRESS OF LABEL BUFFER MOV R0,CA ;INTO CA READB: MOV #READ,R1 ;WE WERE CALLED. GET CODE TO DO BR SOFT1 ;AND LET SOFT RETURN FOR US ; TSTBAK TESTS FOR BLOCK 0 IN Q ELEMENT. IF SO IT EXECUTES A BSP TO ; START OF FILE. TSTBAK: TST BLOCK ;BLOCK 0? BNE RTSPC JSR R0,SOFT ;IF SO, BACKUP TO START OF FILE .WORD LSTFIL ; FALL THRU TO FORWARD SPACE OVER LABEL ; FSP SPACES TO THE NEXT BLOCK FSP: MOV #NXTBLK,R1 ;GET CODE BR SOFT1 ;GO DO IT ; WSENT WRITES A SENTINEL FILE AND FILE GAP, THEN LSTBLK'S WSENT: JSR R0,SOFT ;DO THE GAP .WORD WGAP JSR PC,NAMOFF ;POINT TO CURRENT NAME CLRB (R1) ;NULLIFY IT JSR PC,LABEL ;AND WRITE IT OUT ; BSP BACKSPACES 1 BLOCK BSP: MOV #LSTBLK,R1 ;GET THE CODE BR SOFT1 .SBTTL SOFT - INITIATE SOFTWARE FUNCTION ; SOFT INITIATES HW FUNCTIONS FOR MACROS. ; IT FIRST SAVES THE HANDLER'S PORTION OF THE STACK AND 3 REGISTERS ; IN A STORAGE AREA, THEN INITIATES THE FUNCTION. SOFT: MOV (R0)+,R1 ;GET ARGUMENT MOV R0,@SP ;SAVE RETURN ADDRESS, CLOBBER OLD R0 SOFT1: JSR R4,SAVSTK ;CALL TO DUMP STACK ;AND FALL THROUGH TO EXECUTE CODE IN R1 .SBTTL FUNCTION INITIATION ROUTINE ; XCT INITIATES THE FUNCTION. ; IT PICKS UP THE FUNCTION CODE FOLLOWING THE CALL AND SAVES IT. THEN, ; IF A MACRO CALLED, IT GOES TO (A) BELOW. ELSE, ON ANY HW FUNCTION IT ; RE-INITIALIZES THE SW FLAG TABLE AND CHECKS THE HW FLAG. IF IT FINDS ; THE HW FLAG ON, IT GOES TO (A) ELSE, IT ALLOWS ONLY A REWIND WHICH ; SETS THE HW FLAG AND GOES TO (A) ; (A) NOW IT CHECKS WHETHER THE HW WILL ALLOW ; THE FUNCTION. IF SO, IT SETS THE RETRY COUNT TO 3, CLEARS THE RETRY- ; IN-PROGRESS (BIP) FLAG, INITIATES THE FUNCTION AND RETURNS TO THE CALLER VIA AN RTS PC. ; IF NOT, IT SETS THE HW ERROR BIT AND RETURNS TO THE Q MANAGER. ; ALTERS R0, R1 AND R3. .ENABL LSB XCT: BIC #177770,R1 ;GET FUNCTION MOD 10 (OFFLIN COMES DOWN AS 10) MOV R1,CURFUN ;SAVE IT TSTB F.MACRO ;IF MACRO CALLING, BNE 2$ ;DO ANY FUNCTION BITB UBITS,F.HW ;IF CURRENTLY IN HW MODE, BNE 1$ ;DO ANY HW FUNCTION CMP R1,#REWIND ;ELSE, ALLOW ONLY REWIND BEQ 3$ ;OK ;JD00 JMP CTILLF ;NOT REWIND, ABORT WITH ERROR ;JD00 3$: BISB UBITS,F.HW ;TURN HW MODE ON 1$: MOV R1,-(SP) ;SAVE R1 JSR PC,DUNDEL ;ON ANY HW FUNCTION, RESET SW FLAG TABLE MOV (SP)+,R1 2$: MOV #3,(PC)+ ;SET RETRIES TO 3 RETRY: .WORD 0 ;(NUMBER OF RETRIES) ASL R1 ;ROTATE R1 FOR DISPATCH RERE: CLRB BIP ;CLEAR BSP IN PROGRESS FLAG .IF NE MMG$T MOV CA,TACA ;SAME AS BELOW. MOV WC,TABC MOV TC,TATC MOV QPAR,TAQP ;SAVE EXTENDED MEMORY BASE ADDRESS. MOV #512.,TAQPCT ;COUNT AT WHICH THE BASE ADDRESS IS UPDATED. .IFF MOV CA,(PC)+ ;SAVE ADDRESS IN PSEUDO HW REGISTER TACA: .WORD 0 ;(PSUED0-HW ADDRESS REGISTER MOV WC,(PC)+ ;ALSO BYTE COUNT TABC: .WORD 0 ;(PSEUDO HW BYTE COUNT) MOV TC,(PC)+ ;SET UP TRANSFER COUNT TATC: .WORD 0 ;(COUNT OF ACTUAL XFERS TO DO) .ENDC SETFUN: MOVB R1,(T5) ;SET FUNCTION CODE IN COMMAND REG. JSR R3,RESREG ;RESTORE REGISTERS FROM STACK BIS #INTEN+GO,@#TACS ;AND GO RTSPC: RTS PC ;THEN RETURN TO CALLER OF XCT .IF NE MMG$T TACA: .WORD 0 TABC: .WORD 0 TATC: .WORD 0 TAQP: .WORD 0 TAQPCT: .WORD 0 ;COUNT AFTER WHICH THE BASE ADDRESS IS UPDATED. .ENDC .DSABL LSB .IF DF MUL ;SYNCH ROUTINE IF MULTIPLE VOLUME SUPPORT .SBTTL SYNCH ROUTINE ; ENTER HERE TO CALL THE MONTIOR AS A COMPLETION ROUTINE ; TO SYNCHRONIZE WITH THE USER ; CALLING SEQUENCE: ; JSR PC,CTSYNCH ; BR SYRTN ;SYNCH ROUTINE (OBEYS RULES FOR ; ;COMPLETION ROUTINES) ; [RETURN] ;RETURN TO HANDLER HERE AT PR6 ; ;AFTER SYNCH ROUTINE IS DONE .ENABL LSB CTSYNCH:MOV @SP,1$ ;SET ADDRESS OF SYNCH ROUTINE ADD #2,@SP ;FIX RETURN ADDRESS BIT #SJMON,CTSJ ;IS IT SJ MONITOR? BEQ 10$ ;YES. IGNORE SYNCH JSR R4,SAVSTK ;SAVE THE INTERRUPT STACK ADD #SYNBLK-.,R4 ;POINT TO SYNCH BLOCK JSR R3,RESREG ;RESTORE OTHER REGISTERS CLR 12(R4) ;WILL NEVER FAIL JSR R5,@SYNCH(R5) ;CALL MONITOR .IF NE MMG$T BR CTABRJ .IFF BR CTABRT ;SYNCH ERROR ?!?! .ENDC JSR PC,@(PC)+ ;NOW AT SYNCH LEVEL, CALL ROUTINE 1$: .WORD 0 ; SYNCH ROUTINE DONE. NOW FAKE INTERRUPT TO REENTER HANDLER MOVB #PR6,@#PSW MOV @SP,-(SP) ;CONVERT CALL TO INTERRUPT CLR 2(SP) ;FROM PHONEY PRIORITY 0 BR CTINT ;AND FAKE AN INTERRUPT 10$: JSR PC,@1$ ;CALL THE SYNC ROUTINE RTS PC CTSJ: .WORD 0 .DSABL LSB .ENDC .IF NE MMG$T CTABRJ: JMP CTABRT .ENDC .SBTTL INTERRUPT ROUTINE ; CTINT HANDLES INTERRUPTS CAUSED BY FUNCTION COMPLETION, XFER REQUEST, ; AND ERROR. ; ON COMPLETION IT EITHER RETURNS TO THE MACRO CODE THAT ISSUED THE HW ; REQUEST OR TO THE Q MANAGER IF A USER ISSUED THE REQUEST ; ON COMPLETION OF A REVERSE BLOCK OPERATION PRIOR TO A ; RETRY OF A TRANSFER, IT RE-INITIATES THE READ OR WRITE. ; ON XFER REQUEST FLAG UP IT INCREMENTS THE PSEUDO BYTE COUNTER. ; ON OVERFLOW, IT INITIATES CRC SEQUENCE AND RTI'S. ; ON NO OVERFLOW IT LOADS OR UNLOADS THE DATA BUFFER, ; INCREMENTS THE PSEUDO CURRENT ADDRESS REG AND RTI'S ; IF THE TRANSFER COUNT REGISTER HAS OVERFLOWED ON A READ, ; IT DOES NOT XFER THE UNLOADED BYTE INTO MEMORY. ; ON AN ERROR IT EITHER: ; IGNORES THE ERROR (BOT, OFFLINE, OR FILE GAP IN SW MODE) ; EXITS (ERROR DURING REVERSE BLOCK RETRY OR WRITE LOCK OR BOT, ; OFFLINE OR FILE GAP IN HW MODE) ; OR INITIATES A REVERSE BLOCK FUNCTION (CRC, TIMING) .ENABL LSB ;INTERRUPT ENTRY POINT .IF NE MMG$T .DRAST CT,6,CTABRJ .IFF .DRAST CT,6,CTABRT .ENDC MOV R3,-(SP) ;SAVE REGS MOV R0,-(SP) MOV R1,-(SP) MOV R2,-(SP) MOV SP,SPSAV ;SAVE SP AT INTERRUPT TIME CTIN2: MOV #TACS,T5 ;PT R5 TO TACS TSTB (T5) ;IF NO XFER REQUEST PENDING, BPL 10$ ;GO TEST FOR ERROR INC TABC ;ELSE, INCREMENT BYTE COUNT PRIOR TO XFER BGT 3$ ;DONE WHEN IT GETS ABOVE 0 MOV TACA,R0 ;POINT R0 TO MEMORY ADDR .IF NE MMG$T MOV #TADB,R3 ;POINT R3 TO DATA BUFFER. .ENDC INC TATC ;INC TRANSFER COUNT .IF NE MMG$T BLE CDOXF ;BRANCH IF COUNT DOES'T OVERFLOW. .ADDR #CXFER,R0 ;POINT R0,TO DUMMY FOR XFER. BR CMRW ;DO I/O TO HANDLER. CXFER: .WORD 0 RAWFLG: .BYTE 0 ;READ AFTER WRITE FLAG ;=1 FOR RAW,ELSE=0 CTURW: .BYTE 0 ;=1 FOR A READ/WRITE TO MEMORY ;OTHERWISE 0 CDOXF: TSTB CTURW ;TEST FOR I/O TO MEMORY. BEQ CMRW ;NO,DO I/O TO HANDLER. TSTB CTMVS ;TEST IF DOING MUTI VOLUME SEEK. BNE CMRW ;YES,DO I/O TO HANDLER. TSTB RAWFLG ;TEST FOR RAW. BNE CMRW ;YES,DO I/O TO HANDLER. MOV R4,-(SP) ;SAVE R4 .ADDR #TACA-4,R4 ;POINT R4 AT MAKE BELIEVE Q. CMP CURFUN,#READ ;TEST FOR FUNCTION. BNE XCWRIT XCREAD: MOVB (R3),-(SP) ;READ VALUE FROM CASSETTE JSR PC,@$PTBYT ;STORE BYTE IN USER MEMORY. BR 5$ XCWRIT: JSR PC,@$GTBYT ;GET BYTE FROM USER MEMORY. MOVB (SP)+,(R3) ;WRITE IT TO CASSETTE. 5$: MOV (SP)+,R4 ;RESTORE R4 BR 6$ CMRW: CMP CURFUN,#READ ;TEST FOR READ OR WRITE. BNE 1$ MOVB (R3),(R0) ;READ DATA TO HANDLER. BR 2$ 1$: MOVB (R0),(R3) ;WRITE DATA FROM HANDLER. 2$: INC TACA ;POINT TO NEXT ADDRESS. 6$: DEC TAQPCT ;TEST TO UPDATE BASE ;ONLY HARDWARE I/O WILL NEED THIS ;ALL OTHER IS DONE IN 200 OCTAL BYTES ;OR LESS BNE 4$ ADD #8.,TAQP ;ADD TO BASE SUB #8.*32.*2,TACA ;AND SUBTRACT FROM OFFSET MOV #512.,TAQPCT ;RESET THE COUNT TO 256. WORDS. .IFF BLE 1$ ;IF COUNT OFLOWS, .ADDR #2$,R0 ;POINT R0 TO DUMMY FOR XFER 1$: MOV #TADB,R3 ;POINT R3 TO DATA BUFFER MOV #111013,2$ ;SET XFER DIRECTION TO OUTPUT ((0) TO (3)) CMP CURFUN,#READ ;BUT ON READ, BNE 2$ MOV (PC)+,(PC) ;REVERSE THE DIRECTION MOVB (R3),(R0) 2$: HALT ;(TRANSFER INSTRUCTION) INC TACA ;THEN POINT ADDRESS TO NEXT BYTE .ENDC BR 4$ ;AND RETURN FROM INTERRUPT 3$: BIS #ILBS,(T5) ;ON XFER DONE, SET ILBS FOR READ OR WRITE 4$: JSR R3,RESREG ;RESTORE REGISTERS FROM STACK RTS PC 10$: BIC #INTEN,(T5) ;DISABLE INTERRUPTS BIT #READY,(T5) ;READY BIT SET, BEQ ERRHW TST (T5) ;AND ERROR BIT SET BMI 20$ ;MEANS ERROR 11$: TSTB BIP ;ELSE, TEST BIP BNE 12$ ;IF SO, TRY ORIGINAL FUNCTION AGAIN TSTB F.MACRO ;ELSE, DID MACRO CALL? BEQ RESP ;IF NOT, EXIT THRU Q MANAGER JSR R4,RESSTK ;RESTORE STACK TO CONDITION BEFORE FUNCTION RTS PC ;RETURN TO ROUTINE THAT CALLED 'SOFT' 12$: MOVB CURFUN,R1 ;ON RETRY, RETRIEVE ORIG. FUNC. .IF NE MMG$T JMP RERE .IFF BR RERE ;RE-INITIATE FUNCTION WITH REGISTER LOAD .ENDC ; ERROR PROCESSING ROUTINE 20$: MOV (T5),R3 ;GET ERROR BITS BIT #BOTEOT,R3 ;AT END OF TAPE? BNE 22$ ;YES. ONLY ERROR IN HW MODE BIT #CRC+WRL+TIME,R3;IF NOT BOTEOT,OFF,OR FILE GAP BNE 21$ ;CAUSE AN ERROR 22$: BITB UBITS,F.HW ;ELSE, IF IN HW MODE, BNE 21$ ;CAUSE AN ERROR, TOO BIT #OFF+WRL,(T5) ;IF NOT AN OFFLINE OR WRITE LOCK ERROR, BEQ 11$ ;ALLOW IT IN SW MODE TST (PC)+ ;BUT DISALLOW OFFLINE ERROR IGNOFF: .WORD 0 ;(FLAG=0 PROCESS OFFLINE ERRS,=OFF IGNORE THEM) BNE 11$ ;UNLESS VOLCHK IN PROGRESS 21$: TSTB BIP ;ON OTHER ERRORS, DISALLOW ANY ERROR BNE ERRHW ;DURING LSTBLK RETRY OF READ DEC RETRY ;AND ALLOW ONLY 10. SUCH RETRIES BLE ERRHW BIT #OFF+WRL+BOTEOT+FGAP,R3 ;ON THESE ERRORS BNE ERRHW ;NO WAY TO SAVE FUNCTION, ABORT MOV R3,(PC)+ ;ON CRC ERROR DURING READ, SET FUNC AND FLAG CURFUN: .BYTE 0 ;(FUNCTION (READ) TO RETRY ON NEXT INT) BIP: .BYTE 0 ;(LSTBLK IN PROGRESS FLAG) MOV #LSTBLK*FUNC,R1 ;SET R3 FOR LSTBLK JMP SETFUN ;INITIATE THE FUNCTION AND RTI CTABRT: BIC #INTEN,@#TACS ;STOP IT BR CTHOME ;EXIT .DSABL LSB .SBTTL EXIT SEQUENCE ; EXIT SEQUENCE CODE .ENABL LSB ERRHW: BIS #HWERR,@CSWPTR ;SET ERROR BIT ON HW ERROR TSTB F.MACRO ;ON ERROR AFTER FUNCTION BEQ RESP ;EXIT TO Q MANAGER UNLESS MACRO CALLED BITB #FILNFD+ILLFUN,@SWWPTR ;HAS ERROR OCCURRED BEFORE? ;JD00 BNE 2$ ;THEN DON'T DO CLEANUP AGAIN BISB #FILNFD,@SWWPTR ;ELSE, SET SW ERROR BIT AND TRY TO SAVE TAPE ;JD00 ; CLEAN ATTEMPTS TO SAVE A TAPE'S FILE STRUCTURE WHEN A HW ERROR OCCURS. ;IF THE RROR OCCURED DURING A WRITE OR DURING AN ENTER, ;IT BACKS UP TO BEGINNING OF FILE AND WRITES LEOT OVER THE LABEL. CLEAN: BITB UBITS,F.WRITE ;IF WRITE'S ALLOWED BY FLAG TABLE BNE 1$ BITB UBITS,ENTFLG ;OR IF ENTER CURRENTLY EXECUTING BEQ RESP 1$: JSR R0,SOFT ;BACK UP TO LABEL .WORD LSTFIL JSR PC,WSENT ;GO WRITE LEOT AND FIX FLAG TABLE 2$: JSR PC,DUNDEL ;ON ALL ERRS, RESET FLAGS RESP: CLR FIN ;FLAG=0 MEANS OP DONE MOV SPSAV,SP ;RESTORE ORIG. SP JSR R3,RESREG ;RESTORE REGISTERS FROM STACK .IF NDF DEBUG ;CT EXIT TO MONITOR CTHOME: .DRFIN CT .IFF JMP QMAN ;RETURN TO SENDER .ENDC .DSABL LSB .SBTTL SEEK ; SEEK PERFORMS SEARCH SEQUENCE FOR ENTER, LOOKUP, AND DELETE ; ON A BLOCK ARG OF 0, IT REWINDS, THEN SEARCHES FOR THE NAMED FILE ; LEAVING THE TAPE POSITIONED IN FRONT OF THE FILE'S LABEL IF FOUND ; AND IN FRONT OF THE SENTINEL LABEL IF NOT FOUND. ; ON BLOCK N < 0 IT REWINDS THEN SPACES FORWARD TO THE NTH FILE ON THE ; TAPE OR TO THE FILE NAMED WHICHEVER OCCURS FIRST. ; ON BLOCK >0 IT PERFORMS AS FOR BLOCK<0, BUT DOES NOT DO A REWIND, ; MAKING THIS, IN EFFECT, A FORWARD FILE OPERATION. ; E.G., AN ENTER WITH AN ARGUMENT OF 2 WILL POSTION TO THE NEXT FILE ; AND OVERWRITE ITS LABEL. ; A LOOKUP WITH BLOCK=-1 WILL POSITION TO THE FIRST FILE ON THE TAPE. ; AN ARGUMENT GREATER THAN THE NUMBER OF FILES REMAINING ON TAPE ; WILL FIND THE END OF TAPE BEFORE DOING ANYTHING, ; AS WILL AN ARGUMENT OF 0 AND FILE NAME NOT FOUND. ; SEEK BUMPS RETURN ADDRESS IF FILE FOUND. ; CALLING SEQUENCE: ; JSR PC,SEEK ; BR NOTFOUND ; FOUND: .ENABL LSB SEEK: MOV CA,R2 ;GET POINTER TO FILE NAME ADD #6,R2 ;LAST WORD JSR PC,NAMOFF ;GET OFFSET INTO NAME STORAGE ADD #11,R1 ;POINT TO SEQ NUMBER CLRB (R1) ;AND SET IT TO 0 MOV #^B<0010010010000000>,R3 ;COUNT 3 RAD50 WORDS (9 CHARS) 1$: MOV -(R2),R0 ;GET RAD50 WORD INTO R0 2$: CLR R4 ;CLEAR REMAINDER MOV #16.,-(SP) ;COUNT 16 BITS 3$: ASL R0 ;SHIFT DIVIDEND-QUOTIENT REGISTER ROL R4 ;SHIFT REMAINDER CMP R4,#50 ;BIT ENUF TO SUBTRACT? BLO 4$ SUB #50,R4 ;IF SO, SUBTRACT DIVISOR INC R0 ;SET CORRESPONDING BIT IN QUOTIENT 4$: DEC (SP) ;ANY MORE BITS? BNE 3$ ;IF SO, CONTINUE DIVISION BIS (SP)+,R4 ;POP 0 OFF STACK, CONVERT R4 TO ASCII BEQ 5$ ;=0 MEANS SPACE CMP R4,#32 ;LETTER (1-32) ? BLE 6$ SUB #36,R4 ;DIGIT (36-47) ? BCC 7$ 5$: MOV #-40,R4 ;0,33,34,35 GIVE SPACE 6$: ADD #20,R4 ;CONVERT (1-32) TO (101-132) 7$: ADD #60,R4 ;CONVERT (36-47) TO (60-71) MOVB R4,-(R1) ;INSERT CHARS IN STORAGE ASL R3 ;ARE WE DONE THIS WORD? BCC 2$ ;NO BNE 1$ ;GO DO 3 WORDS TST BLOCK ;BLOCK <=0? BGT CHKHDR ;IF NOT, DON'T REWIND, JUST START SEARCHING NEG BLOCK ;ELSE, GET MAGNITUDE OF BLOCK SEEKC: JSR R0,SOFT ;AND DO A REWIND FIRST .WORD REWIND ; NO NEED TO SPACE PAST 1ST FILE GAP AT BOT CHKHDR: MOV #-32.,WC ;SET FOR 32 WBYTE READ MOV #-32.,TC ;SET XFER COUNT TO WC JSR PC,READU ;NOW READ THE LABEL .IF DF MUL JSR PC,EOTCHK ;CHECK FOR EOT BNE SEEKC ;IF SO AND NEW VOLUME, RE-START SEEK .ENDC JSR PC,NAMOFF ;ELSE, COMPARE NAME SOUGHT (R1) MOV CA,R0 ;WITH NAME FROM LABEL JUST READ TSTB (R0) ;NULL FILE NAME MEANS SENTINEL FILE BEQ 12$ ;INDICATING LEOT DEC BLOCK ;DEC BLOCK ARGUMENT BEQ 11$ ;IF IT = 0, CONSIDER THIS FOUND MOV #9.,R3 ;ELSE, TEST 9 CHARACTERS 10$: BICB #200,(R0) ;STRIP TO 7-BIT ASCII CMPB (R0)+,(R1)+ BNE 20$ ;IF NOT FOUND, KEEP LOOKING DEC R3 BGT 10$ ;IF FOUND, RETURN .IF DF MUL CMPB 3(R0),(R1) ;COMPARE SEQUENCE # TO CURRENT NUMBER BNE 20$ ;AND MAKE SURE IT MATCHES, TOO .ENDC 11$: ADD #2,(SP) ;ON FOUND, BUMP RETURN ADDR. 12$: JMP BSP ;NOW BACKSPACE OVER LABEL 20$: JSR R0,SOFT ;NOT FOUND, SPACE PAST THIS FILE .WORD NXTFIL BR CHKHDR ;AND CONTINUE SEEKING .DSABL LSB .SBTTL EOTCHK, VOLCHK .IF DF MUL ; EOTCHK TESTS FOR TAPE AT EOT. ; IF NOT, IT RETURNS WITH Z BIT SET. ; IF SO, IT ASKS THE USER FOR A NEW VOLUME. ; ON NO NEW VOLUME, IT EXITS SETTING THE EOF ERROR BIT. ; ON NEW VOLUME, IT SAVES WC AND CA, INCREASES THE CURRENT SEQ NUMBER ; AND RETURNS WITH Z BIT NOT SET. .ENABL LSB EOTCHK: JSR PC,VOLCHK ;ASK USER FOR NEW VOLUME BEQ 1$ ;IF NOT RETURN .IF NE MMG$T INCB CTMVS ;SET MULTI VOLUME SEEK FLAG. .ENDC CMP WC,#-32. ;DOING A SEEK? BEQ 2$ ;SEEK. RESTART OPERATION JSR PC,NAMOFF ;ELSE, POINT TO SEQ NUMBER ADD #11,R1 ;NUMBER IN NAME STORAGE INCB (R1) ;AND INCREASE IT MOV R4,(PC)+ ;THEN SAVE WC IN R4 WCSAV: .WORD 0 ;(WC AT TIME OF LAST TRANSFER) MOV CA,(PC)+ ;AS WELL AS CA CASAV: .WORD 0 ;(CA AT TIME OF LAST XFER) 2$: TST SP ;SET IT NON-ZERO 1$: RTS PC ;RETURN WITH Z BIT OFF (CA NON-0) .DSABL LSB ; VOLCHK TESTS FOR EOT AND RETURNS WITH Z BIT SET IF NOT. ; IF SO, A BAD XFER OCCURRED AT END OF TAPE. SO IT PRINTS ; "PUSH REWIND OR MOUNT NEW VOLUME". ; THEN WAITS FOR USER ACTION BY ISSUING NXTFIL'S IN A LOOP. ; ON OFFLINE UP THEN ONLINE IT RETURNS WITH Z BIT OFF. ; ON EOT NO LONGER SET, IT EXITS WITH A SW ERROR. .ENABL LSB VOLCHK: BIT #BOTEOT,(T5) ;AT EOT? BEQ 3$ ;IF NOT, RETURN WITH Z=1 DEC TABC ;BUT DID BYTE COUNT OFLOW ANYWAY? BEQ 3$ ;IF SO EOT OCCURRED IN GAP, ALL OK CLR (PC)+ ;ELSE, CLEAR OFFLINE FLAG OFLAG: .WORD 0 ;(>0 MEANS OFF THEN ON) JSR PC,CTSYNCH ;CALL SYNCHER TO PRINT MESSAGE BR 10$ ;SYNCH ROUTINE IS AT 10$ 1$: INC IGNOFF ;SET FLAG TO ALLOW OFFLINE ERR JSR R0,SOFT ;EXECUTE A NEXT BLOCK .WORD NXTBLK ;AND SEE WHAT HAPPENS BIT #OFF,(T5) ;OFFLINE? BEQ 2$ MOV #100001,OFLAG ;IF SO, SET FLAG TO NEAR OFLOW JSR PC,CTSYNCH ;SYNCH UP TO AVOID A HANG AT PR6 RTS PC ;BUT DON'T DO MUCH CLR IGNOFF ;PROCESS OFFLINE ERRS AGAIN BR 1$ ;AND LOOK AGAIN 2$: CLR IGNOFF ;PROCESS OFFLINE ERRS AGAIN TST OFLAG ;IF NOT, OFLAG<0 INDICATING OFF ONCE? BEQ 4$ DEC OFLAG ;IF SO, DEC THE FLAG BVC 1$ ;KEEP LOOKING UNLESS FLAG OVERFLOWS 3$: RTS PC ;INDICATING ON LONG ENUF, RETURN Z=0 4$: BIT #BOTEOT+OFF,(T5) ;IF NEVER OFF, TEST FOR REWIND PUSHED BNE 1$ ;IF NOT, KEEP LOOKING JSR R0,SOFT ;IF SO, REWIND FOR GOOD POSITION .WORD REWIND BICB UBITS,F.CLOSE ;DON"T WRITE SENTENEL AFTER REWIND ;DF;001 JMP SWEOF ;AND EXIT WITH SW ERROR ; THIS IS THE SYNCH ROUTINE TO PRINT THE MSG 10$: .ADDR #UNO,R0 ;POINT TO MESSAGE MOVB UNIT,@R0 ;SET UNIT NUMBER BISB #'0,@R0 TST -(R0) ;POINT TO MSG .PRINT ;PRINT IT RTS PC ;AND RETURN .NLIST BEX MSG: .ASCII "CT" UNO: .ASCIZ "0: PUSH REWIND OR MOUNT NEW VOLUME" .LIST BEX .EVEN .DSABL LSB .ENDC .SBTTL LABEL PROCESSOR ; LABEL WRITES THE FILE LABEL LABEL: JSR PC,NAMOFF ;GET FILE NAME STORAGE OFFSET INTO R1 .ADDR #FILNAM,R2 ;THEN PT TO NAME SLOT IN PROTOTYPE MOV #9.,R4 ;AND INSERT ALL 9 CHARACTERS 1$: MOVB (R1)+,(R2)+ DEC R4 BGT 1$ ADD #3,R2 ;POINT TO SEQUENCE NUMBER MOVB (R1)+,(R2)+ ;INSERT SEQUENCE NUMBER WHICH FOLLOWS NAME TSTB (R2)+ ;POINT TO DATE .DATE ;GET THE DATE IN RT11 FORMAT MOV R0,R1 ;THEN CONVERT IT TO 6 ASCII CHARACTERS ASL R1 ;RITE JUSTIFY DAY IN HI BYTE ASL R1 ASL R1 BIC #160377,R1 ;CLEAR UNUSED BITS JSR PC,ASC ;AND INSERT IT MOV R0,R1 ;GET MONTH IN HI BYTE BNE 2$ ;IS IT THERE? CLRB -2(R2) ;NO. NULL FIRST BYTE 2$: ASR R1 ASR R1 JSR PC,ASC ;AND INSERT IT MOV R0,R1 ;FINALLY, DO YEAR BIC #177740,R1 ;LEAVE YEAR BITS ADD #72.,R1 ;ADDING THE 72. THAT RT11 SUBTRACTS SWAB R1 ;MAKE SURE IT IS IN HIGH BYTE JSR PC,ASC ADD #FILNAM-GENNO,R2;POINT R2 TO START OF HEADER DELAB: MOV R2,CA ;SET ADDRESS TO THAT OF HEADER MOV #-32.,WC ;SET FOR 32 WORD BLOCK JMP WRTBLK ;AND WRITE THE LABEL ; ASC CONVERTS THE 5 BIT BINARY VALUE IN THE HIGH BYTE OF R1 ; INTO TWO DIGIT ASCII DECIMAL IN THE SLOT POINTED TO BY R2. ; ALTERS R1. PTS R2 TO NEXT BYTE. ASC: CLRB R1 ;GET VALUE INTO LOW BYTE 1$: ADD #173001,R1 ;SUBTRACT 10 FROM NUMBER, ADD 1 BPL 1$ ;LOOP UNTIL ALL 10'S ARE DONE ADD #"00+<10.*400-1>,R1 MOV R1,(R2)+ ;PUT IT IN RTS PC .SBTTL UTILITY ROUTINES ; SAVE HANDLER STACK ; CALLED BY JSR R4,SAVSTK SAVSTK: JSR R2,@PC ;SAVE R2, POINT TO INTERNAL STACK ADD #STAK-.,R2 MOV R2,STKPTR ;SAVE POINTER TO TOP OF STACK 1$: MOV (SP)+,(R2)+ ;MOVE A WORD CMP SPSAV,SP ;DONE? BHI 1$ ;NO MOV R2,(PC)+ ;SAVE DEPTH SPSAVE: 0 JMP @R4 ;RETURN ; RESTORE HANDLER STACK ; CALLED BY JSR R4,RESSTK ; ALSO RESTORES R2 AND R4 .ENABL LSB RESSTK: TST (SP)+ ;REMOVE CALLER'S R4 MOV SPSAVE,R2 ;POINT TO INTERNAL STACK 1$: MOV -(R2),-(SP) ;RESTORE SP STACK CMP (PC)+,R2 ;DONE? STKPTR: 0 BNE 1$ ;NO MOV (SP)+,R2 ;RESTORE R2 FROM STACK RTS R4 ;RESTORE R4 AND RETURN .DSABL LSB ; RESTORE R0-R3 FROM STACK BEFORE EXIT ; CALLED BY JSR R3,RESREG RESREG: TST (SP)+ ;REMOVE CALLER'S R3 MOV (SP)+,R2 MOV (SP)+,R1 MOV (SP)+,R0 MOV @#MONLOW,R5 ;WE USUALLY NEED THIS RTS R3 ; NAMOFF CALCULATES THE ADDRESS OF THE FILE NAME FOR THE CURRENT FILE ; AND RETURNS IT IN R1. ; ALTERS R3 AND R1 NAMOFF: MOV UNIT,R3 ;GET UNIT .ADDR #SNAME-12,R1 ;POINT TO STORAGE AREA 1$: ADD #12,R1 ;COUNT UP TO CURRENT UNIT DEC R3 BGE 1$ RTS PC .SBTTL DATA AREAS ; DISPATCH TABLE FOR SOFTWARE FUNCTIONS MACROS=.-2 ;FUNCTION VALUES START AT 2 10$: .WORD $CLOSE-. .WORD $DELETE-. .WORD $LOOKUP-. .WORD $ENTER-. .WORD $READ-. .WORD $WRITE-. .IF DF NEWVOL .WORD $NEWVOL-. .ENDC MAXFUN = <. - 10$> / 2 ; FLGTAB CONTAINS A FLAG FOR EACH SOFTWARE FUNCTION, FOR HARDWARE MODE, ; AND FOR MACROS. EACH BIT IN EACH FLAG CORRESPONDS TO A UNIT. ; THE FIRST TWO BYTES IN THE TABLE, F.HW AND F.MACRO, ; REFLECT THE CURRENT STATUS OF THE HANDLER: ; HW <> 0 MEANS HARDWARE MODE IN EFFECT ; HW = 0 MEANS SOFTWARE MODE IN EFFECT. ; IN HW MODE, ANY HW FUNCTION AND ANY OF THE SOFTWARE FUNCTIONS ; INITIALLY SET TO 1 IN THE TABLE CAN EXECUTE. ; EXECUTING ANY SOFTWARE FUNCTION CLEARS THIS BYTE. ; EXECUTING A REWIND FROM THE USER LEVEL SETS IT. ; WHENEVER A SOFTWARE FUNCTION EXECUTES IT SETS THE BYTE F.MACRO ; NON-0 TO INDICATE TO THE HARDWARE PORTION OF THE HANDLER THAT ; A SOFTWARE FUNCTION RATHER THAN A USER CALLED IT. ; THIS ALLOWS THE HARDWARE PORTION TO DECIDE WHETHER OR NOT TO EXECUTE. ; ; EACH OF THE LAST 6 BYTES CORRESPONDS TO ONE OF THE SOFTWARE FUNCTIONS ; BEFORE EXECUTING, EACH SOFTWARE FUNCTION TESTS ITS BYTE. ; IF NON-0, IT EXECUTES THE FUNCTION. OTHERWISE, IT ABORTS. ; ANY FUNCTION THAT EXECUTES SETS UP THIS TABLE TO REFLECT WHICH ; FUNCTIONS CAN AND CANNOT FOLLOW IT. ; FOR INSTANCE, AN ENTER WILL ALLOW ONLY A WRITE OR A CLOSE TO FOLLOW ; IT. THUS, IT WILL SET BOTH THESE BYTES AND CLEAR THE OTHER 4. FLGTAB: F.HW: .BYTE 0 ;HARDWARE INTITIALLY NOT ALLOWED F.MACRO:.BYTE 0 ;MACRO CURRENTLY EXECTUED BYTE F.CLOSE:.BYTE 0 ;CLOSE NOT ALLOWED AT START F.DELETE:.BYTE 377 ;DELETE ALLOWED AT START F.LOOKUP:.BYTE 377 ;LOOKUP ALLOWED F.ENTER:.BYTE 377 ;ENTER ALLOWED AT START F.READ: .BYTE 0 ;READ NOT ALLOWED F.WRITE:.BYTE 0 ;WRITE NOT ALLOWED .IF DF NEWVOL F.NEWVOL:.BYTE 377 ;ALWAYS ALLOW NEWVOL .ENDC .EVEN ; LABEL PROTOTYPE FILNAM: .ASCII / / ;9 CHARACTER FILE NAAME FILTYP: .BYTE 0 ;FILE TYPE LENGTH: .BYTE 0 ;256*1 .BYTE 200 ;128 BYTE RECORDS SEQNO: .BYTE 0 ;SEQUENCE NUMBER LEVEL: .BYTE 1 ;LEVEL 1 CASSETTE DATE: .ASCII / / ;DATE IN ASCII GENNO: .BYTE 0 ;GENERATION NUMBER ATTR: .BYTE 0 ;RECORD ATTRIBUTES UNUSED: .BYTE 0,0,0,0,0,0,0,0,0,0 ;UNUSED BYTES ;+++ .EVEN LBLBUF: .BLKB 32. ;SPACE FOR LABELS .IF DF RCHECK .BLKB 128.-32. ;HERE IT MUST BE BIG ENOUGH TO READ ALL .ENDC .IF NE MMG$T FILENM: .WORD 0,0,0 ;STORE FILE NAME FOR ENTER,LOOKUP ;AND DELETE HERE. .ENDC SNAME: .BLKB 12*2 ;STORAGE FOR 2 ASCII FILE NAMES SYNBLK: .WORD 0,0,0,0,0,0,0 ;BLOCK TO DO A SYNCH ; THE FOLLOWING STORAGE AREA CONTAINS ALL WORDS PUSHED ON THE STACK ; SINCE THE START OF THE HANDLER'S EXECUTION. STAK: .BLKW 12 .IIF NDF DEBUG, .NLIST .IF DF DEBUG .=.+100 ;ROOM FOR ODT'S STACK .ENDC .IIF NDF DEBUG, .LIST .IF DF INIT ;JD00 .END TEST .ENDC .DREND CT .END ;CHANGE TO .END TEST FOR DEBUG ;JD00