ߋtv ?B-NO BOOT ON VOLUME @w p@w wP׭ ׭ w f& fwW#w v   @ @wP  @& 7 "  BLOCK@   IS BAD   -̂@ &   # p@ zw 7 P7 R & B g wD ѕ  Rì     s   p x] \Z 1  d s  -2&w* rrXkQ.kQ .`TkQ .L0 kQ .kQX .kQ .%kQ4 .}kQ .= kQ! .kQ .d@^kQ.FWkQ.FWkQ .FWkQ .FWkQ . kQ . kQ .MkQ .fkQ .fkQ .     c.%v(c.%v(c.%v(c.%v(c.%v(c.%v(c.%v(c.%v(c.   (rXz:c.bT  (   )]  +'jL^c+f  ,M0kQ ,"cw  {Qcw C-Krcw C-3cw  -}}  -Q$:  -jLp  -  -oQ  -cw #.cw  #. Ncw #.'jL^c.+2 ;POINTS TO START BLOCK OF CHANNEL 17 HDERR$ = 1 ;BITS IN CSW WORD 0 INDX$M = 76 ;MASK FOR DEVICE INDEX RENAM$ = 100 DWRIT$ = 200 DBLOK$ = 400 DBLK$M = 17400 ;MASK FOR DIR. BLOCK # DBLK$N = 160377 ;COMPLEMETARY MASK EOF$ = 20000 ACTIV$ = 100000 C.SBLK = 2 ;OFFSETS INTO CHANNEL C.LENG = 4 C.USED = 6 C.DEVQ = 10 $SYSCH: BSS 5 ;INTERNAL CHANNEL USED ONLY FOR $SYS CALLS BLKEY: .WORD 0 ;DIRECTORY BLOCK # IN CORE CHKEY: .WORD 0 ;DEVICE WHOSE DIRECTORY IS IN CORE $DATE: .WORD 0 ;DATE WORD DFLG: .WORD 0 ;DIRECTORY OP. IN PROGRESS FLAG $USRLC: .WORD USRBUF ;*** BOOT *** WHERE DIRECTORY BUFFER IS QCOMP: .WORD COMPLT ;*** BOOT *** HANDLERS GO HERE TO FINISH UP SPUSR: .WORD 0 ;USED TO REPORT SPECIAL USR ERRORS SYUNIT: .WORD 0 ;UNIT OF RUNNING SYSTEM DEVICE SYSVER: .BYTE 2 ;THIS IS VERSION 2B SYSUPD: .BYTE 3 ;VERSION RELEASE NUMBER (A=1,B=2,ETC.) ;DV23 CONFIG: .WORD FBMON$+CLK50 ;SYSTEM CONFIGURATION WORD SCROLL: .WORD 0 ;LINK WORD FOR GTON SCROLLER TTKS: .WORD TKS ; -> KEYBOARD STATUS REGISTER TTKB: .WORD TKB ; -> KEYBOARD BUFFER TTPS: .WORD TPS ; -> TTY OUTPUT STATUS TTPB: .WORD TPB ; -> TTY OUTPUT BUFFER MAXBLK: .WORD -1 ;LARGEST OUTPUT FILE OPENABLE (INITIALLY UNLIMITED) E16LST: .WORD LST16-$RMON ;OFFSET TO EMT 16 LIST CNTXT: .WORD BKGND ; -> RUNNING JOB'S IMPURE AREA JOBNUM: .WORD 0 ;ACTIVE JOB'S NUMBER SYNCH: .WORD $SYNCH ;SYNCH ENTRY POINT (FIXED OFFSET) LOWMAP: ;MAP OF PROTECTED WORDS IN LOW CORE ; NOTE THAT THE BOOTSTRAP PROTECTS THE SYSTEM HANDLER ; BYTES ARE READ LEFT TO RIGHT. E.G., THE FOURTH BYTE 11110000 ; PROTECTS THE RANGE 60-76, AND SPECIFICALLY 60,62,64, AND 66. .RADIX 2 .BYTE 11111111,00111100,00001111,11110000 ; 0 - 076 .BYTE 11000011,00000000,00000000,00000000 ;100 - 176 .BYTE 00111111,11000000,00110011,00110000 ;200 - 276 .BYTE 00000000,00000000,00000000,00000000 ;300 - 376 .BYTE 00000000,00000000,00000000,00000000 ;400 - 476 .RADIX 8. MAPSIZ = <. - LOWMAP> / 2 ;SIZE OF PROTECT MAP IN WORDS MAPOFF = LOWMAP - $RMON USRLOC: .WORD USRBUF ;WHERE USR REALLY IS NOW GTVECT: .WORD 320 ;LOCATION OF GT40 VECTORS (USUALLY 320) ERRCNT: .WORD 0 ;ERROR COUNT RETURN FROM CUSPS $MTPS: RTI ;STACK TO PS ;DV15 $MFPS: BR GETPSW ;BR TO ROUTINE TO RETURN PS IN SP ;DV15 USRLVL: .BYTE 0 ;DEPTH OF USR CALLS USROWN: .BYTE 377 ;OWNER OF USR (377 => FREE) USRSWP: .WORD 0 ;FLAG SAYING WHETHER THE USR SWAPS $SWPBL: .WORD 0 ;START OF SWAP AREA EXLIST: .WORD 0 ;IOB USED TO WRITE OUT USER ON EXIT .WORD - .WORD 0 $KMLOC: .WORD KMON ;*** BOOT *** .WORD USRLEN+KMLEN .WORD 0 KMLOC: .WORD KMON ;LOCATION OF KMON $TIME: BSS 2 ;DOUBLE PRECISION TIMER SYINDX: .WORD 0 ;SYSTEM DEVICE INDEX NUMBER SYINDO = SYINDX - $RMON ;COMPUTE OFFSET FOR BOOTSTRAP CORPTR: .WORD 0 ;FREE CORE POINTER .WORD CORPTR ;*** BOOT *** IMPLOC: .WORD $IMPUR+MXJNUM+2 ;***BOOT*** PTR TO IMPURE AREA PTRS ;DV16 KMONIN: .WORD 1 ;0 => USER RUNNING; ELSE KMON RUNNING ;DV16 ; ROUTINE TO RETURN CONTENTS OF PS TO CALLER IN STACK. THE PS ; REFERENCE IS MODIFIED BY BOOT TO A MFPS INSTRUCTION IF THE PROCESSOR ; IS AN LSI11. GETPSW: MOV (SP),-(SP) ;COPY RETURN ADDRESS ;DV15 MOV @#PS,2(SP) ;PUT PS CONTENTS IN SP ;DV15 RTS PC ;RETURN TO CALLER ;DV15 $OWNER: BSS 2*$SLOT ;DEVICE OWNERSHIP TABLE $UNAM1: BSS $SLOT ;ASSIGNED NAME TABLE - PERMANENT NAMES DKASSG = . - $RMON .RAD50 /DK0/ SYASSG = . - $RMON .RAD50 /SY0/ ; KEEP THESE LINES IN ORDER $UNAM2: BSS $SLOT ;ASSIGNED NAME TABLE - USER NAMES .RAD50 /DK / .RAD50 /SY / $PNAME: BSS $SLOT ;PERMANENT NAME TABLE ; END OF ORDERED SECTION $STAT: BSS $SLOT .WORD 0 ;******DUMMY FOR MSG ENTRY******* .WORD 0 ;THIS HAS TO BE HERE FOR MSG. CHAN. FILST$ = 100000 ;1=> DEVICE IS FILE STRUCTURED RONLY$ = 40000 ;1=> DEVICE IS READ ONLY WONLY$ = 20000 ;1=> DEVICE IS WRITE ONLY SPECL$ = 10000 ;1=> DEVICE IS NON-RT11 STRUCTURE [MT,CT] HNDLR$ = 4000 ;1=> TAKE ABORT ENTRY ON EVERY JOB ABORT ;DV16 SPFUN$ = 2000 ;1=> DEVICE HNDLR ACCEPTS .SPFUN ;DV17 $ENTRY: BSS $SLOT .WORD -1 ;STOPPER $PNAMO = $PNAME - $ENTRY ;COMPUTE OFFSET FOR BOOTSTRAP MSGENT: JBLQE ;ENTRY TO MSG PROCESSOR $DVREC: BSS $SLOT ;DEVICE HANDLER RECORD # (FOR .FETCH) CCB: BSS 10 ;RESIDENT CCB FOR KMON SWIIOB: .WORD 0,USRLEN,0 ;IOB FOR SWAP INTO MEMORY SWOIOB: .WORD 0,-USRLEN,0 ;IOB FOR WRITING USER TO SWAP BLOCKS KMBLK: BSS 3 ;IOB FOR FINAL READ OF USER FOR R OR RUN ; ; THE FOLLOWING TABLE CONTAINS THE HIGH LIMIT (HIGHEST SETTOP + 2) ; AND LOW LIMIT FOR EACH JOB IN THE SYSTEM. ; NOTE THAT THE HIGH LIMIT FOR THE BG IS ALSO THE LOWEST LOADED ; HANDLER OR FG JOB, I.E. SYSLOW $JBLIM: SYSLOW: BLIMIT: .WORD $RMON,0 ;*** BOOT *** ENTIRE AREA FLIMIT: .WORD 0,0 ;NO FG JOB .SBTTL DEVICE TABLES ;********************************************************************** ; ; THE FOLLOWING MACRO IS USED TO MAKE ENTRIES IN ALL ; THE DEVICE-RELATED TABLES, BOTH IN THE USR AND THE RMON. ; THE 4 MACRO ARGUMENTS ARE HANDLER NAME, # OF BLOCKS ON DEVICE, ; STATUS (FOR $STAT), AND ENTRY POINT (GLOBAL NAME). ; .MACRO DEVICE NAME,SIZ,STAT,ENTRY . = $HSIZE + HNUM .IF IDN NAME,DK .WORD SYSIZE .IFF .WORD NAME'SIZE .ENDC . = $DVSIZE + HNUM .WORD SIZ . = $PNAME + HNUM .RAD50 /NAME/ . = $STAT + HNUM .WORD STAT .IF NB ENTRY . = $ENTRY + HNUM .WORD ENTRY .ENDC HNUM = HNUM + 2 .ENDM DEVICE HNUM = 0 ;START OF WITH 0 DEVICE INDEX ... = . ;KEEP OUR PLACE ; NAME SIZE STATUS ENTRY ; ---- ---- ------ ----- DEVICE TT 0 4 TTLQE DEVICE DS 1024. 16+FILST$ DSSYS DEVICE RK 11300 0+FILST$ RKSYS DEVICE RF 2000 12+FILST$ RFSYS DEVICE PR 0 7+RONLY$ DEVICE PP 0 10+WONLY$ DEVICE MT 0 11+SPECL$+SPFUN$ DEVICE LP 0 3+WONLY$ DEVICE DT 1102 1+FILST$ DTSYS DEVICE CT 0 13+SPECL$+SPFUN$ DEVICE MM 0 20+SPECL$+SPFUN$ BA.NUM = HNUM DEVICE BA 0 4 DEVICE DP 40000. 21+FILST$ DPSYS DEVICE DX 494. 22+FILST$+SPFUN$ DXSYS .IIF NDF BANDW, .NLIST .IF DF BANDW DEVICE AM 200 15+FILST$ .ENDC .IIF NDF BANDW, .LIST . = ... ;BACK TO WHERE WE WERE .SBTTL DESCRIPTION OF MONITOR DATA BASE ; "MERELY CORROBORATIVE DETAIL, INTENDED TO GIVE ARTISTIC ; VERISIMILITUDE TO AN OTHERWISE BALD AND UNCONVINCING ; NARRATIVE." - W.S. GILBERT, THE MIKADO ;********************************************************************** ; CHANNEL STATUS TABLE---$CSW ; THIS TABLE CONTAINS 16 ENTRIES OF 5 WORDS EACH ; DESCRIBING THE I/O CHANNELS. THE FORMAT IS: ; ; OFFSET BIT(S) MEANING ; ------ ------ ----------------------------------------------- ; 0 0 1 => HARD ERROR OCCURED ON DEVICE ; 1-5 DEVICE INDEX IN TABLES ; 6 1 => RENAME OPERATION IN PROGRESS ; 7 1 => CLOSE REQUIRES DIRECTORY REWRITE ; 8-12 DIRECTORY BLOCK # OF FILE ; 13 1 => EOF FOUND ON CHANNEL ; 15 1 => CHANNEL ACTIVE ; 2 START BLOCK OF FILE ; 4 LENGTH OF FILE (HOLE) ALLOCATED ; 6 ACTUAL DATA LENGTH (HIGHEST BLK WRITTEN) ; 10 0-7 NUMBER OF REQUESTS PENDING ON THIS CHANNEL ; 8-15 PHYSICAL UNIT NUMBER ; ;********************************************************************** ; ; BLKEY AND CHKEY ARE USED TO INDICATE WHICH DIRECTORY IS IN CORE ; AND WHAT DEVICE THAT DIRECTORY IS ATTACHED TO. ; BLKEY IS THE NUMBER OF THE DIRECTORY SEGMENT NOW IN CORE ; SEGMENTS ARE NUMBERED 1-32. THEY ARE 2 PHYSICAL BLOCKS EACH. ; ; CHKEY DESCRIBES THE DEVICE TO WHICH THE DIRECTORY IS ATTACHED. ; THE EVEN BYTE CONTAINS THE DEVICE INDEX, IDENTIFYING THE DEVICE TYPE, ; AND THE ODD BYTE CONTAINS THE UNIT NUMBER OF THE DEVICE ; ;********************************************************************** ; PERMANENT NAME TABLE $PNAME ; THIS TABLE HOLDS THE RAD50 REPRESENTATION OF THE DEVICE NAMES. ; THEY ARE LOADED BY THE DEVICE MACRO (SEE BELOW). THE TABLE ; IS CONSTRUCTED IN REVERSE ALPHABETICAL ORDER BECAUSE OF ; THE ALGORITHM USED TO DETERMINE UNIT NUMBERS ; ;********************************************************************** ; ; USER NAME TABLES: $UNAM1 AND $UNAM2. ; THESE TABLES ARE USED TO HOLD THE DEVICE NAMES DEFINED VIA ; THE ASSIGN COMMAND. THE USER SPECIFIES 2 NAMES IN THE ASSIGN: ; .ASSIGN NAM1 NAM2 ; NAM1 IS THE SYSTEM PERMANENT NAME, AND NAM2 IS HIS SUPPLIED NAME. ; $UNAM2 CONTAINS THE USER'S NAME, AND AT THE CORRESPONDING ; LOCATION IN $UNAM1 IS THE SYSTEM NAME WHICH IS EQUATED TO IT. ; ;********************************************************************** ; ; $STAT CONTAINS INFORMATION ABOUT THE DEVICE TYPES AND THE STRUCTURE ; OF THE DEVICES IN THE SYSTEM. THE 2 BYTES IN EACH ENTRY ARE: ; EVEN BYTE: CONTAINS AN NUMBER WHICH IS UNIQUE TO THAT DEVICE: ; 0 = RK05 ; 1 = DECTAPE ; 2 = CASSETTE ; 3 = LINE PRINTER ; 4 = TTY (ASR 33,35) ; 5 = LA30 ; 6 = VT05 ; 7 = HI SPEED READER ; 10= HI SPEED PUNCH ; 11= TM11/TU10/TS03 MAGTAPE ; 12= RF11 DISK ; 13= TA11 CASSETTE ; 14= CR11 CARD READER ; 15= RESERVED ; 16= RJS03/RJS04 FIXED HEAD DISK ; 17= RESERVED ; 20= TJU16 MAGTAPE ; 21= RP11/RPR02/RP03 DISK ; 22= RX11/RX01 FLOPPY DISK ; ; THE ODD BYTE CONTAINS INFORMATION ON THE STRUCTURE OF THE DEVICE: ; BIT 15 1 => FILE STRUCTURED DEVICE ; 0 => NON FILE STRUCTURED ; BIT 14 1 => READ ONLY DEVICE (PTR) ; BIT 13 1 => WRITE ONLY DEVICE (LPT) ; BIT 12 1 => SPECIAL FILE DEVICE (CASSETTE) ; BIT 11 1 => TAKE ABORT ENTRY ON EVERY JOB ABORT ;DV16 ; BIT 10 1 => HANDLER ACCEPTS .SPFUN ;DV17 ; ;********************************************************************** ; ; $ENTRY TABLE ; WHEN A DEVICE HANDLER IS IN CORE, THE $ENTRY WORD FOR THE ; DEVICE POINTS TO THE HANDLER (LAST Q-ELEMENT WORD). ; A ZERO WORD MEANS THE HANDLER IS NOT IN CORE. .SBTTL IMPURE AREA OFFSET DEFINITONS .MACRO DSECT N ..TEMP = N .ENDM DSECT .MACRO DS NAME,SIZE,UNIT .IF NB NAME .LIST NAME = ..TEMP .NLIST .ENDC .IF B SIZE ..TEMP = ..TEMP + 2 .IFF .IF NB UNIT ..TEMP = ..TEMP + SIZE .IFF ..TEMP = ..TEMP + <2*SIZE> .ENDC .ENDC .ENDM DS ; FOLLOWING ARE OFFSET DEFINITIONS INTO THE IMPURE AREA: ; NUMBERS AT RIGHT INDICATE WORDS WHICH MUST STAY TOGETHER DSECT 0 ;START OFFSETS FROM 0 DS I.JSTA ;1 PTR TO $JSTAT ENTRY DS I.QHDR ;1 I/O QUEUE HEADER DS I.CMPE ;1 COMPLETION QUEUE LAST ELEMENT DS I.CMPL ;1 COMPLETION QUEUE HEAD DS I.CHWT ;1 POINTER TO CHANNEL DURING I/O WAIT DS I.PCHW ;1 SAVED I.CHWT DURING COMPLETION DS I.PERR ;1 SAVED ERRBYT DURING COMPLETION DS I.PTTI ;PREVIOUS TTY INPUT CHAR DS I.TTLC ;TTY LINE COUNT DS I.TID ;POINTER TO JOB ID AREA DS I.JNUM ;JOB NUMBER DS I.CNUM ;2 NUMBER OF CHANNELS DEFINED DS I.CSW ;2 POINTER TO CHANNEL AREA DS I.IOCT ;NUMBER OF OUTSTANDING I/O OPERATIONS DS I.SCTR ;SUSPEND COUNTER (<0 => SUSPENDED) DS I.SPLS ;3 POINTER TO SPECIAL DEV. ADDR LIST DS I.TRAP ;3 ADDRESS OF TRAP TO 4/10 ROUTINE DS I.FPP ;3 ADDRESS OF FPP EXCEPTION ROUTINE DS I.SWAP,2 ;3 POINTER TO EXTRA SWAP STUFF DS I.SP ;3 SAVED STACK POINTER DS I.BITM,MAPSIZ ;3 BIT MAP FOR PROTECTION DS I.IRNG ;4 INPUT RING LOW LIMIT DS I.IPUT ;4 INPUT 'PUT' POINTER FOR INTERRUPTS DS I.ICTR ;4 INPUT CHARACTER COUNT DS I.IGET ;4 INPUT 'GET' POINTER FOR .TTYIN EMT DS I.ITOP ;4 INPUT RING BUFFER HIGH LIMIT DS ,TTYIN BYTES ;4 INPUT RING DS I.OPUT ;5 OUTPUT 'PUT' POINTER FOR .TTYOUT EMT DS I.OCTR ;5 OUTPUT CHARACTER COUNT DS I.OGET ;5 OUTPUT 'GET' POINTER FOR INTERRUPTS DS I.OTOP ;5 OUTPUT RING BUFFER HIGH LIMIT DS ,TTYOUT BYTES ;5 OUTPUT RING DS I.QUE,8. ;THE INITIAL QUEUE ELEMENT DS I.MSG,2 ;INTERNAL MESSAGE CHANNEL DS I.SERR,3 ;USE WD 3 AS HARD/SOFT ERR FLAG DS I.JID,4 ;JOB TTY PROMPT STRING ;DV16 DS I.NAME,4 ;RAD50 NAME/EXT OF JOB RUNNING ;DV16 DS I.TERM,1 ;TERMINAL STATUS WORD ;DV25 IMPSIZ = ..TEMP .SBTTL BACKGROUND IMPURE AREA ; THE IMPURE AREA FOR THE BACKGROUND IS: ; BKGND: .WORD 0 ;JSTATE BKGND1: .WORD BAVAIL ;*** BOOT *** QUEUE HEADER .WORD 0,0,0,0,0 ;COMPL TAIL, HDR, CHWT, PCHW, PERR .WORD 0 ;PREVIOUS CHARACTER .WORD 0 ;LINE COUNT BKGND2: .WORD BKGID ;*** BOOT *** JOB ID AREA .WORD 0 ;B IS ALWAYS JOB #0 .WORD 16. ;16 CHANNELS IN BACKGROUND BKGND3: .WORD $CSW ;*** BOOT *** CHANNEL STATUS AREA .WORD 0 ;IO COUNT .WORD 0 ;SUSPEND COUNTER .WORD 0 ;ADDRESS OF SPECIAL LIST .WORD 0 ;TRAP TO 4/10 HANDLER .WORD 0 ;FPP EXCEPTION ADDRESS .WORD 0,0 ;EXTRA STUFF TO CONTEXT SWAP .WORD 0 ;STACK POINTER BSS MAPSIZ ;BIT MAP TTIBUF: .WORD IBUFR ;*** BOOT *** LOW LIMIT .WORD IBUFR ;*** BOOT *** INT POINTER .WORD 0 ;COUNT .WORD IBUFR ;*** BOOT *** EMT POINTER .WORD IBUFR+ TTYIN ;*** BOOT *** HIGH LIMIT IBUFR: .BLKB TTYIN ;INPUT RING BUFFER TTOBUF: .WORD OBUFR ;*** BOOT *** EMT PTR FOR OUTPUT RING .WORD 0 ;CHAR. COUNT .WORD OBUFR ;*** BOOT *** INTERRUPT POINTER .WORD OBUFR+ TTYOUT ;*** BOOT *** UPPER BUFFER LIMIT OBUFR: .BLKB TTYOUT ;RING OUTPUT BUFFER BAVAIL: .BLKW 8. ;INITIAL QUEUE ELEMENT .WORD ACTIV$+ ;MESSAGE CHANNEL .WORD 0,0,0,0 ;3RD WORD IS .SERR FLIP/FLOP BKGID: .ASCIZ "B>" ;JOB ID BLOCK FOR BACKGROUND .EVEN BNAME: .WORD 0,0,0,0 ;NAME OF PROGRAM RUNNING IN B/G ;DV16 ;.RAD50 DEV:FILNAM.EXT ;DV16 .WORD 0 ;TERMINAL STATUS WORD ;DV25 .IF NE <. - BKGND> - IMPSIZ .ERROR ;BACKGROUND IMPURE AREA IMPROPERLY DEFINED .ENDC .SBTTL MORE IMPURE AREA, QUEUE HEADS ; TABLE OF IMPURE AREA POINTERS ; .WORD -1 ;STOPPER FOR SEARCHES $IMPUR: BCNTXT: BKGND ;BACKGROUND FCNTXT: 0 ;FOREGROUND MXJNUM = . - $IMPUR - 2 ;MAXIMUM LEGAL JOB # ; ;************************************************************ ; ; THE FIRST WORD IN THE IMPURE AREA IS THE JOB STATE. IT CONTAINS ; INFORMATION ON THE CURRENT STATE OF THE SYSTEM. ; BIT DEFINITIONS ARE: CMPLT$ = 100000 ;JOB IS IN COMPLETION ROUTINE TTIWT$ = 40000 ;WAITING FOR TTY INPUT TTOWT$ = 20000 ;WAITING FOR ROOM IN BUFFER ;TTSPC$ = 10000 ;THIS BIT IS IN THE SAME PLACE AS IN JSW ;DV25 CHNWT$ = 4000 ;WAITING FOR CHANNEL TO COMPLETE SPND$ = 2000 ;SUSPENDED (SUSPEND COUNT > 0) NORUN$ = 1000 ;JOB IS NOT LOADED (CLEARED ONLY BY KMON) EXIT$ = 400 ;WAITING FOR ALL I/O TO STOP CPEND$ = 200 ;COMPLETION ROUTINE IS PENDING KSPND$ = 100 ;JOB SUSPENDED FROM KMON ABORT$ = 40 ;JOB REQUIRES ABORT USRWT$ = 20 ;JOB IS WAITING FOR THE USR USRRN$ = 10 ;USR IS RUNNING FOR JOB CSIRN$ = 4 ;CSI IS RUNNING FOR JOB BATRN$ = 2 ;BATCH IS RUNNING, DO NOT ADDRESS CHECK! ; ; BLOCK$ IS THE SET OF BITS WHICH CAN BLOCK A JOB FROM RUNNING ; BLOCK$ = TTIWT$ ! TTOWT$ ! CHNWT$ ! SPND$ ! NORUN$ ! EXIT$ ! KSPND$ ! USRWT$ .SBTTL QUEUE ELEMENT FORMATS ;************************************************************ ; ; FOLLOWING IS THE FORMAT FOR THE IO QUEUE ELEMENT, AND ; FOR THE QUEUE HEADER AREA. EACH JOB ACTIVE WILL HAVE IT'S ; OWN QUEUE HEADER AND ELEMENTS.THE QUEUE ELEMENT LOOKS LIKE: ; ; OFFSET MEANING ; ------ ---------------------------------------------- ; 0 POINTER TO NEXT ELEMENT ; 2 POINTER TO CSW AREA ; 4 BLOCK NUMBER FOR TRANSFER ; 6 SPECIAL CODES FOR MAGTAPE & CASSETTE ; 7 UNIT #(3 BITS), JOB # ; 10 BUFFER ADDRESS ; 12 WORD COUNT ; 14 COMPLETION FUNCTION (0=WAIT, 1=NOTHING, N=COMPLETION) ; DSECT 0 ;START OFFSETS AT 0 DS ,1 ;LINK WORD DS Q.CSW ;POINTER TO CHANNEL DS Q.BLKN ;BLOCK NUMBER DS Q.FUNC,1 BYTE ;SPECIAL FUNCTION CODE (LOW BYTE) DS Q.JNUM,0 BYTES ;JOB NUMBER (*8) DS Q.UNIT,1 BYTE ;UNIT # (IN HIGH BYTE) DS Q.BUFF ;BUFFER ADDRESS DS Q.WCNT ;WORD COUNT DS Q.COMP ;COMPLETION FUNCTION QESIZE = ..TEMP ;SIZE OF Q ELT. ; ;************************************************************ ; ; FOLLOWING IS THE FORMAT OF AN ELEMENT ON THE TIMER QUEUE: ; DSECT 0 DS C.HOT ;HIGH ORDER EXPIRATION TIME DS C.LOT ;LOW " " " DS C.LINK ;LINK TO NEXT ELEMENT DS C.JNUM ;JOB NUMBER OF OWNER DS C.SEQ ;OWNER'S SEQUENCE NUMBER DS ,1 DS C.COMP ;COMPLETION ADDRESS .SBTTL EMT DISPATCH TABLE ; THIS IS A LIST OF THE FUNCTIONS AVAILABLE AS EMT SERVICES. ; THE FUNCTIONS ARE DIVIDED INTO 2 GROUPS, EMT 375 FUNCTIONS, ; WHICH TAKE MORE THAN A CODE & CHANNEL, AND EMT 374 FUNCTIONS ; WHICH TAKE ONLY CODE AND POSSIBLY CHANNEL NUMBER. ; THE EMT DISPATCHER WILL ADDRESS CHECK THE R0 ARGUMENT ; AND/OR THE FIRST R1 ARGUMENT IF ASKED POLITELY. ; THE FOLLOWING MACRO DEFINES THE DISPATCH TABLE .MACRO EMTDEF ENTRY,R0CHK,R1CHK,ABBR .IF NB ABBR ..'ABBR = ..TEMP .ENDC ..TEMP = ..TEMP + 1 .IF NB R0CHK .WORD +R1CHK*2+R0CHK .IFF .WORD *2 .ENDC .ENDM EMTDEF ..TEMP = 0 NO = 0 YES = 1 EMTLST: 10$: ; NAME R0? R1? CODE ; ------ ---- --- --- EMTDEF D$LETE YES NO ; 0 DELETE EMTDEF L$OOK YES NO ; 1 LOOKUP EMTDEF E$NTER YES NO ; 2 ENTER EMTDEF S$TRAP YES NO ; 3 SET TRAP TO 4 & 10 EMTDEF R$NAME YES NO ; 4 RENAME EMTDEF S$AVST YES NO ; 5 SAVESTATUS EMTDEF R$OPEN YES NO ; 6 REOPEN EMTDEF C$LOSE NO NO ; 7 CLOSE EMTDEF R$EAD NO YES ; 10 READ EMTDEF W$RITE NO YES ; 11 WRITE EMTDEF W$AIT NO NO ; 12 WAIT EMTDEF C$PYCH NO NO ; 13 COPY OTHER JOB'S CHANNEL EMTDEF D$VICE YES NO ; 14 SET SPECIAL DEVICES EMTDEF C$DFN YES NO ; 15 DEFINE CHANNELS EMTDEF EMT16 NO NO ; 16 GROUP 16 EMTS EMTDEF EMT17 NO NO ; 17 INTERNAL ERROR EMTDEF G$TJB YES NO ; 20 GET JOB PARAMETERS EMTDEF G$TIM YES NO GTIM ; 21 GET TIME OF DAY EMTDEF M$RKT YES YES MRKT ; 22 MARK TIME EMTDEF C$MKT NO YES CMKT ; 23 CANCEL MARK TIME EMTDEF T$WAIT YES NO TWAI ; 24 TIMED WAIT EMTDEF S$DAT NO YES ; 25 SEND DATA EMTDEF R$CVD NO YES ; 26 RECEIVE DATA EMTDEF C$STAT YES NO ; 27 CHANNEL STATUS EMTDEF S$FPP NO NO ; 30 SET FPP EXCEPTION EMTDEF P$ROTE NO NO ; 31 PROTECT VECTORS EMTDEF S$PFUN NO YES ; 32 SPECIAL DEVICE FUNCTIONS EMTDEF S$SWAP YES NO ; 33 SET EXTRA SWAP ADDRESSES EMTDEF S$TRAP YES NO ; 34 SET TRAP TO 4 AND 10 E375MX = <. - 10$> / 2 11$: EMTDEF W$AIT ; 0 WAIT EMTDEF S$SPND ; 1 SUSPEND THIS JOB EMTDEF R$SUME ; 2 RESUME THIS JOB EMTDEF P$URGE ; 3 PURGE CHANNEL EMTDEF S$ERR ; 4 SET SOFT ERRORS EMTDEF H$ERR ; 5 SET HARD ERRORS EMTDEF C$LOSE ; 6 CLOSE (374 STYLE) EMTDEF T$LOCK ; 7 TEST & LOCK USR EMTDEF C$HAIN ;10 CHAIN EMTDEF M$WAIT ;11 MESSAGE WAIT E374MX = <. - 11$> / 2 EMTMAX = <. - 10$> / 2 .SBTTL ERROR PROCESSOR ; "THE FAULT, DEAR BRUTUS, IS NOT IN OUR STARS, ; BUT IN OURSELVES" - SHAKESPEARE, JULIUS CAESAR ; EMT 376 IS USED TO REPORT MONITOR ERRORS. ; IF THE ERROR IS UNCONDITIONALLY FATAL OR THE USER HAS ; NOT ASKED FOR CONTROL ON ERRORS, IT PRINTS A MESSAGE AND ; ABORTS THE JOB. ; OTHERWISE, IT REPORTS A NON-FATAL ERROR CODE ; "AND OFTENTIMES, EXCUSING OF A FAULT ; DOTH MAKE THE FAULT WORSE BY THE EXCUSE." - SHAKESPEARE, JOHN IV ; THIS MACRO DEFINES AN ERROR MESSAGE .MACRO ERRMSG CODE,TEXT .NLIST .ASCII TEXT<200> CODE'.E = ..TEMP ..TEMP = ..TEMP + 1 .LIST .ENDM ERRMSG ..TEMP = 0 FPPERR: BIT #HWFPU$,CONFIG ;WE GOTTA FPU? BEQ 1$ CMP (SP)+,(SP)+ ;YUP. DISCARD THE STST DATA 1$: MOV (SP)+,R4 ;GETTA ADDRESS MOV #FPP.E,R3 ;GETTA ERROR CODE BR ERRCOM ;PUTTA MESSAGE .ENABL LSB ; "EXTREME REMEDIES ARE VERY APPROPRIATE FOR EXTREME DISEASES." ; - HIPPOCRATES, "APHORISMS" 12$: RESET ;TERRIBLY FATAL ERROR HALT BR .-2 ;AND NO WAY OUT ; "THE DEATH OF GOD LEFT THE ANGELS IN A STRANGE POSITION." ; - BARTHELME, "ON ANGELS" TRAP4: TRAP10: ROL @#ERRBYT ;PRESERVE CONDITION IN R3(MI=>10) TST INTLVL ;TRAP FROM THE SYSTEM? BPL 12$ ;OUCH CMP #400,SP ;STACK OVERFLOW? BHIS 14$ ;YES, IGNORE USER INTERCEPT SPL 0 ;NO. SAFE TO COME DOWN MOV R5,-(SP) ;SAVE R5 MOV CNTXT,R5 ;POINT TO CURRENT IMPURE AREA MOV I.TRAP(R5),-(SP) ;GET USER INTERCEPT ADDRESS BEQ 13$ ;NONE, I'D RATHER DO IT MYSELF CLR I.TRAP(R5) ;STOP RECURSIVE PROBLEMS MOV (SP)+,R5 ;GET INTERCEPT ADDRESS IN R5 ASR @#ERRBYT ;GET INDICATION OF TRAP TO 4 OR 10 RTS R5 ;GO TO USER 13$: CMP (SP)+,(SP)+ ;PURGE THE 0 14$: MOV (SP)+,R4 ;SAVE OFFENDING PC MOV @#USERSP,SP ;RESET STACK BEQ 12$ ;OUCH AGAIN. NO STACK SPL 0 ;GOOD. DOWN TO PR0 ASR @#ERRBYT ;RESTORE CONDITION MOV #TR04.E,R3 ;GET MSG NUMBER ADC R3 ;MAKE IT TRAP TO 10 IF IT WAS BR 3$ ;MERGE WITH ERRORS 1$: COM R3 ;FATAL CODE TO POSITIVE 2$: MOV -(R2),R4 ;GET OFFENDING PC MOV R2,SP ;UPGRADE STACK ERRCOM: 3$: .HRESET ;STOP THE WORLD. IT'S TIME TO GET OFF .RCTRLO JSR R0,5$ ;POINT R0 TO MESSAGES, ENTER LOOP .ASCII "?M-"<200> ERRMSG USRX,<"ILL USR"> ERRMSG NODV,<"NO DEV"> ERRMSG DIRI,<"DIR IO ERR"> ERRMSG FETC,<"BAD FETCH"> ERRMSG OVLY,<"OVLY ERR"> ERRMSG DOVR,<"DIR OVFLO"> ERRMSG ADDR,<"ILL ADDR"> ERRMSG CHAN,<"ILL CHAN"> ERRMSG EMT,<"ILL EMT"> ERRMSG TR04,<"TRAP TO 4"> ERRMSG TR10,<"TRAP TO 10"> ERRMSG FPP,<"FP TRAP"> .EVEN 4$: TSTB (R0)+ ;ADVANCE POINTER BPL 4$ ;NOT DONE SKIPPING YET DEC R3 ;THIS THE MESSAGE? BPL 4$ 5$: .PRINT ;PRINT A THING TST R3 ;DONE PRINTING? BPL 4$ ;NO .TTYOUT #40 ;PRINT BLANK MOVB #30,R0 ;PRINT THE NUMBER IN R4 SEC 6$: ROL R4 ROLB R0 .TTYOUT MOV #206,R0 SEVEN$: ASL R4 BEQ EIGHT$ ROLB R0 BCS SEVEN$ BR 6$ EIGHT$: ADDR MZEROB,R0 ;POINT TO NULL BYTE CMPB JOBNUM,USROWN ;DO WE OWN THE USR? BNE NINE$ ;NO TST DFLG ;ABORT DURING CRITICAL PLACE BEQ NINE$ ;NO ADD #MDIRUN-MZEROB,R0 ;GIVE MESSAGE CLR DFLG ;AVOID A CRASH NINE$: .PRINT JMP UABORT ;KILL HIM E376: MOV SAVE+2(SP),R1 ;R1 -> DEPTH AND ERROR CODE MOVB (R1)+,R2 ;R2 = DEPTH OF USER PS ADD SP,R2 ;R2 -> USER PS ADD #ERRPS,R2 MOVB (R1)+,R3 ;R3 = ERROR CODE BMI 1$ ;<0 IS ALWAYS FATAL MOV CNTXT,R5 ;POINT TO IMPURE AREA TST I.SERR(R5) ;NOT FATAL. DOES HE WANT SOFT ERRORS? BEQ 2$ ;NO COM R3 ;YES. MAKE A NEGATIVE CODE MOVB R3,@#ERRBYT ;PUT IT IN BIS #1,@R2 ;PUT CARRY ON IN HIS PS MOV R1,SAVE+2(SP) ;SKIP MONITOR OVER ERRORS CLR R2 BR EMTOUT MDIRUN: .ASCII "?M-DIR UNSAFE" MZEROB: .BYTE 0 .EVEN .DSABL LSB .SBTTL CONSOLE TTY CONFIGURATION DATA ; THE CONSOLE TELETYPE IS SHARED AMONG THE ACTIVE JOBS IN THE SYSTEM. ; EACH JOB HAS RING BUFFERS FOR INPUT AND OUTPUT IN ITS IMPURE AREA, ; ALONG WITH BUFFER POINTERS, CHARACTER COUNTS, ETC. ; THE FOLLOWING BYTES CONTROL PRINTING OF SPECIAL CHARACTERS ; (TABS, FILLS, ETC.). THEY MUST BE KEPT IN ORDER TTWIDT: .BYTE 72. ;WIDTH OF CARRIAGE .BYTE CR FILCHR: .BYTE 0 ;CHARACTER USED TO FILL FILCTR: .BYTE 0 ;NUMBER OF FILLS OUTCHR: .BYTE 0 ;CHARACTER TO PRINT LINPOS: .BYTE 0 ;POSITION ON CARRIAGE ; THE FOLLOWING WORD CONFIGURES THE TTY HANDLER FOR VARIOUS OPTIONS ; IT IS PLACED HERE SO IT CAN BE ACCESSED KNOWING LOCATION 30. VT05$ = 100000 ;VT05 MODE (RUBOUT = BS SPACE BS) PAGE$ = 200 ;^S AND ^Q HOLD TTY OUTPUT FBTTY$ = 10 ;^B AND ^F SWITCH CONTEXT FORM$ = 4 ;HARDWARE FORM FEED (DO NOT SIMULATE) CRLF$ = 2 ;GIVE CRLF WHEN REACHING TTWIDTH HWTAB$ = 1 ;HARDWARE TAB (DO NOT SIMULATE) TTCNFG: .WORD PAGE$+CRLF$+FBTTY$ .SBTTL EMT PROCESSOR ; "WHAT'S IT GOING TO BE THEN, EH?" - A. BURGESS, "CLOCKWORK ORANGE" ; THIS DISPATCHER MUST RESIDE BEFORE ANY EMT ROUTINE EMTPRO: BIC #1,2(SP) ;CLEAR C BIT MOV R1,-(SP) ;SAVE ALL REGS MOV R2,-(SP) MOV R3,-(SP) MOV R4,-(SP) MOV R5,-(SP) MOV R0,-(SP) CLR R2 ;FOR CALLING THE USR MOV SAVE+2(SP),R5 ;R5 -> WORD AFTER THE EMT MOV -(R5),R4 ;R4 = EMT INSTRUCTION MOV SP,R1 ;POINT R1 TO ARGS ON STACK CMPB R4,#374 ;IS IT NEW FORMAT? BHIS NEWEMT ;YES. ADD #SAVE+6,R1 ;POINT R1 TO ARGS MOV R4,R5 ;COPY IT BIC #-20,R4 ;ISOLATE CHANNEL NUMBER BIC #177417,R5 ASR R5 ASR R5 ASR R5 BR EMTCOM ;MERGE WITH COMMON CODE NEWEMT: BNE 1$ ;EMT 375 OR 376 ADD #E375MX*400,R0 ;INDEX TO END OF LIST BR 3$ ;AND LINK WITH COMMON CODE 1$: CMPB R4,#376 ;IS IT 376 OR 377? BHI EMTOUT ;EMT 377 IS IGNORED BEQ E376 ;376 IS FATAL ERROR CODE JSR R5,CHKSP ;CHECK LIST ADDRESS FOR VALIDITY BR ERRARG ;SOFT ADDRESS CHECK MOV R0,R1 MOV (R1)+,R0 ;PUT CODE AND CHANNEL INTO R0 MOV (R1)+,@SP ;NORMAL R0 ARG TO R0 MOV #100000,R2 ;R1 NOW POINTS TO ARG LIST. 3$: CLR R4 ;R4 WILL HOLD CHANNEL DATA BISB R0,R4 BEQ 4$ ;CHANNEL # IS 0. MOV CNTXT,R5 ;COMPARE CHAN SPECFIED W/ # DECLARED CMPB R4,I.CNUM(R5) BHIS CHANER ;CHANNEL IS TOO GREAT 4$: MOV R0,R5 ;FUNCTION GOES TO R5 CLRB R5 SWAB R5 CMPB #EMTMAX,R5 ;IS IT A LEGAL ONE? BLOS TOOBIG ;NO ASL R5 ;*2 FOR INDEXING MOV @SP,R0 ;R0 ARG BACK TO R0 EMTCOM: ADD PC,R5 ;GET EMT ROUTINE OFFSET MOV EMTLST-.(R5),R5 ; INTO R5 ROR R5 ;SHIFT RIGHT ONE BCC 1$ ;DO NOT CHECK R0 ARG JSR R5,CHKSP ;CHECK R0 ARG BR ERRARG ;BADDIE 1$: ASR R5 ;CHECK R1 ARG? BCC 2$ ;NAH MOV @R1,-(SP) ;GET R1 ARG JSR R5,CHKSP ;YAH BR ERRARH TST (SP)+ ;PRUNE 2$: ASL R5 ;FIX OFFSET MOV R5,-(SP) ; AND SAVE IT MOV CNTXT,R5 ;GENERAL POINTER TO IMPURE AREA ASL R4 ;MULTIPLY # CHANNELS BY 2 MOV R4,R3 ;NOW POINT R3 TO CORRECT CSW AREA ASL R3 ASL R3 ADD R4,R3 ;(10. BYTES PER CHANNEL) ADD I.CSW(R5),R3 ;ADD POINTER TO START OF CHANNEL AREA CLRB @#ERRBYT ;TURN OFF ERROR BYTE INDICATOR ADD (SP)+,PC ;JUMP TO ROUTINE EMTCAL: ;USED IN DISPATCH TABLE TOOBIG: MONERR EMT ;GIVE MAYBE FATAL ERROR BR EMTOUT ERRARH: TST (SP)+ ;PURGE A WORD FIRST ERRARG: MONERR ADDR ;ILLEGAL ADDRESS IN R0 BR EMTOUT CHANER: MONERR CHAN ;ILLEGAL CHANNEL NUMBER EMTOUT: JMP EMTDON .SBTTL MARK TIME ENQUEUE ; MARK TIME SETS UP A NODE IN THE TIMER QUEUE FOR THE USER ; IT REQUIRES A TIME INTERVAL (IN CLOCK TICKS) AND A ; COMPLETION ROUTINE ADDRESS. ; MARKTM ACTUALLY DOES THE WORK. IT MUST BE CALLED FROM BASE ; EMT LEVEL, AS .MRKT AND .TWAIT DO. IT GIVES ERROR 0 IF NO ; QUEUE ELEMENTS ARE AVAILABLE MARKTM: TST (R5)+ ;POINT TO AVAIL HEADER SPL 7 ;GET ELEMENT AT PRIO 7 ;DV15 MOV @R5,R3 ;* GET ELEMENT BEQ 4$ ;* NONE THERE, ERROR. MOV @R3,@R5 ;* LINK AVAIL QUEUE FORWARD SPL 0 ;* BACK TO PRIO 0 ;DV15 MOV (R0)+,(R3)+ ;MOVE IN HIGH ORDER TIME MOV (R0)+,(R3)+ ; AND LOW ORDER TIME ADD #C.COMP-C.LINK,R3 ;MOVE IN STUFF IN REVERSE MOV (R1)+,@R3 ;COMPLETION ADDRESS CLR -(R3) ;CLEAR FOR NO CHANNEL OFFSET MOV (R1)+,-(R3) ;IDENTIFYING NUMBER MOV JOBNUM,-(R3) ;JOB NUMBER TST -(R3) ;MOVE TO LINK WORD ENSYS 3$ ;ENTER SYSTEM STATE, RETURN TO 3$ ADD PSCLOK,-(R3) ;CHANGE TIME TO SYSTEM RELATIVE ADC -(R3) MOV (R3)+,R0 ;R0 = HIGH ORDER TIME ADDR LKQUE,R2 ;R2 -> Q. HEADER 1$: MOV R2,R1 ;R1 -> PREVIOUS LINK WORD MOV @R1,R2 ;R2 -> NEXT ELEMENT TO CONSIDER BEQ 2$ ;PUT IT AT END OF QUEUE MOV (R2)+,R4 ;GET TIME OF EXPIRATION OF THIS ELT MOV (R2)+,R5 CMP R0,R4 ;COMPARE HIGH ORDER TIMES BHI 1$ ;NOT YET BLO 2$ ;YES, DEFINITELY CMP @R3,R5 ;EQUAL. COMPARE LOW ORDER TIMES. BHIS 1$ ;NOT YET 2$: TST -(R3) ;ADVANCE R3 TO START OF ELT MOV @R1,C.LINK(R3) ;PUT OTHER LINK INTO US MOV R3,@R1 ;POINT OTHER GUY AT US 3$: RTS PC ;GET OUT OF SYSTEM STATE 4$: CLRB @R2 ;* TO PRIO. 0 TST (SP)+ ;PURGE JSR BR EMTER0 ;GIVE AN ERROR .SBTTL CHAN. DEF, TWAIT, SUSPEND, RESUME, MARK TIME .SBTTL SET: DEVICE, ^C, FPP .ENABL LSB C$DFN: ADD #I.CNUM,R5 ;POINT TO CHANNEL COUNT ;DV1 MOV 2(R5),R2 ;R2 -> OLD CHANNEL AREA ;DV1 CMPB @R1,@R5 ;NEW COUNT <= OLD COUNT? ;DV1 BLOS EMTER0 ;YEP, ERROR JSR PC,QUIESCE ;WAIT FOR QUIETNESS CLR R3 ;CLEAR CHANNEL COUNTER 1$: MOV #5,R4 ;5 WORDS / CHANNEL CMPB @R5,R3 ;OLD COUNT >= CHANNEL WE ARE WORKING ON BHI 3$ ;YES, SO COPY IT 2$: CLR (R0)+ ;NO, CLEAR IT DEC R4 ;5 WORDS BNE 2$ BR 4$ 3$: MOV (R2)+,(R0)+ ;COPY THE CHANNEL DEC R4 BNE 3$ 4$: INCB R3 ;BUMP NUMBER OF WORKING CHANNEL CMPB @R1,R3 ;NEW COUNT >= THIS CHANNEL? BHI 1$ ;YES, KEEP GOING MOV @R1,(R5)+ ;SET NEW COUNT BR 10$ ;GO SET NEW POINTER ; "BUT WE LIKE SENTRIES ARE OBLIGED TO STAND ; IN STARLESS NIGHTS, AND WAIT TH' APPOINTED HOUR" ; - DRYDEN, "DON SEBASTIAN" FUDGE2: .WORD RESUM ;*** BOOT *** POINTER TO CMPLTION T$WAIT: MOV (PC)+,R1 ;POINT TO COMPLETION ROUTINE FUDGE1: .WORD FUDGE2 ;*** BOOT *** PTR TO ROUTINE PTR JSR PC,MARKTM ;DO A MARK TIME FOR THE INTERVAL ;AND SUSPEND THE GUY S$SPND: MOV CNTXT,R1 ;COPY IMPURE POINTER DEC I.SCTR(R1) ;SUSPEND HIM BPL RTILK0 ;NOT SUSPENDED YET. LEAVE TST @R1 ;IS HE IN COMPLETION ROUTINE ? BMI RTILK0 ;YES. HE CAN'T BE SUSPENDED HERE JSR R4,$SYSWT ;NO. WAIT FOR SUSPEND COUNT .WORD SPND$ ; TO GO ABOVE 0 MOV I.SCTR(R1),R0 ;; GET COUNT ASL R0 ;; IF < 0, STILL BLOCKED JSR PC,@(SP)+ ;; BACK TO $SYSWT BR RTILK0 ;DONE RESUM: MOV CNTXT,R0 ;COMPLETION TYPE RESUME INC I.SCTR(R0) RTS PC R$SUME: INC I.SCTR(R5) ;RESUME HIM (NOTE THAT WE ARE BR RTILK0 ; IN A COMPL ROUTINE AND RUNNING, ; SO WE NEED NOT CHANGE DISPATCHABILITY) M$RKT: JSR PC,MARKTM ;CALL MARK TIME BR RTILK0 ;EXIT EMT WHEN DONE S$SWAP: TST (R5)+ ;I.SWAP = I.FPP + 2 TST @R0 ;R0 -> LIST, IS IT NULL? BNE 5$ ;NO CLR @SP ;YES. NULLIFY POINTER 5$: TST @SP ;IS POINTER NULL? BEQ 8$ ;YES. SET IT UP 6$: MOV (R0)+,-(SP) ;CHECK A POINTER CMP #500,@SP ;IS POINTER A VECTOR? BHI 7$ ;YES, IT WON'T BE IN HIS AREA CMP #160000,@SP ;WELL, IS IT IN THE I/O PAGE? BLOS 7$ ;YES, ALLOW THAT, TOO JSR R5,CHKSP ;NO. IT MUST BE IN HIS AREA CLR @SP ;SIGNAL ERROR 7$: ASR (SP)+ ;ERROR OR ODD ADDRESS? BLOS EMTER0 ;YES TST @R0 ;END OF LIST? BNE 6$ ;NO S$FPP: CMP #1,R0 ;SET FPP SWITCH BUT NO TRAP? BHIS 8$ ;YES JSR R5,CHKSP ;NO, CHECK INTERRUPT ADDRESS BR EMTER0 ;INVALID ADDRESS 8$: TST (R5)+ ;I.FPP = I.TRAP + 2 S$TRAP: TST (R5)+ ;I.TRAP = I.SPLS + 2 D$VICE: ADD #I.SPLS,R5 ;POINT TO WORD TO BE FILLED 10$: MOV @SP,@R5 ;YES. PLUG WORD IN IMPURE AREA RTILK0: BR EMTRTI ;AND EXIT .DSABL LSB .SBTTL TTYIN & TTYOUT T$TIN: MOV R5,R2 ;COPY TO CALL IGET MOV R5,R1 ;WE NEED COPIES LATER ON. ADD #I.TTLC,R1 ;R1 -> LINE COUNT JSR PC,TTRSET ;COPY SPECIAL-MODE BIT, ETC. TST @R1 ;IS COUNT=0? BNE 4$ ;NO, WE CAN GIVE HIM STUFF BIT #TCBIT$,@#JSW ;DOES HE REALLY WANT C-BIT RETURN? BNE EMTER0 ;YES JSR R4,$SYSWT ;NO, ENTER SYSTEM WAIT STATE .WORD TTIWT$ ; WITH PROPER BLOCKING BIT CMP @R1,#1 ;; DO WE HAVE A CHARACTER YET? JSR PC,@(SP)+ ;; TELL CALLER IF WE ARE GOOD 4$: JSR PC,IGET ;GET A CHARACTER FROM THE RING BEQ 5$ ;IT WAS ^C MOV R4,@SP ;GIVE IT TO HIM IN R0 BR EMTRTI ;AND LEAVE 5$: MOV R4,R0 ;MAKE R0 NON 0 GOEXIT: MOV #..EXIT,R4 ;EXIT VIA TABLE IN CASE OF BATCH JMP EMT16 ;DISPATCH AN EXIT ; EMT 16(1) - TTYOUT ; THIS EMT PUTS A CHARACTER INTO THE OUTPUT RING BUFFER. T$TOUT: MOV R0,R4 JSR R0,TTOUT ;OUTPUT THE CHARACTER, WAIT IF NEED BE .WORD TCBIT$ ;BIT TO TEST FOR CARRY OR NAY BCC EMTRTI ;GOT IT OUT (OR TCBIT WAS OFF) EMTER0: EMTERR+0 ;SET C BIT IN STATUS BR EMTRTI ;SAY GOODBYE .SBTTL RETURN FROM EMT ; COME HERE TO RETURN FROM AN EMT WHICH TOOK ARGUMENTS ON THE STACK ; IF IT IS AN OLD STYLE EMT, WE POP OFF THE ARGS EMTDON: ASL R2 ;CONVERT WORD COUNT TO BYTES BEQ EMTRTI ;NONE TO POP MOV SAVE+2(SP),R3 ;POINT TO THE EMT THAT CALLED US CMPB #374,-2(R3) ;IS IT NEW STYLE? BLOS EMTRTI ;YES. NO POP MOV SP,R3 ;NO. POINT R3 ABOVE REGS, PC, PS ADD #OLDPS+2,R3 ADD R3,R2 ;POINT R2 ABOVE WHERE IT SHOULD GO 1$: MOV -(R3),-(R2) ;MOVE A WORD CMP R3,SP ;DONE YET? BHI 1$ ;NO MOV R2,SP ;YES. RESET STACK POINTER ; COME HERE IF THERE IS NO POPPING TO BE DONE EMTRTI: MOV (SP)+,R0 ;RESTORE ALL REGS MOV (SP)+,R5 MOV (SP)+,R4 MOV (SP)+,R3 MOV (SP)+,R2 MOV (SP)+,R1 RTI ;BACK TO THE USER .SBTTL SET TOP, CANCEL ^O, PRINT BLOCK ; EMT 16(12) - SET TOP OF CORE ; ATTEMPT TO MAKE THE GIVEN ADDRESS THE JOB'S NEW HIGH CORE LIMIT. ; IF THE NUMBER IS VALID, AND THE JOB IS THE BACKGROUND, ; IT IS DETERMINED WHETHER OR NOT USR SWAPPING WILL BE REQUIRED. S$ETOP: MOV JOBNUM,R2 ;POINT TO LIMIT TABLES ASL R2 ADDR $JBLIM+2,R2,ADD ;R2 -> LOW LIMIT CMP R0,@R2 ;REQUEST : LOW LIMIT BHIS 10$ ;OK. MOV @R2,R0 ;NO, RESET TO LOW LIMIT 10$: CMP R0,-(R2) ;REQUEST : HIGH LIMIT BLO 1$ ;OK MOV @R2,R0 ;NO, RESET TO HIGH LIMIT 11$: TST -(R0) 1$: TST JOBNUM ;IS THIS THE BACKGROUND? BNE 3$ ;NO. THEN IT'S EASY. JSR PC,ENQUSR ;OWN THE USR TO CHANGE SWAPABILITY CLR USRSWP ;GUESS AT NO USR SWAPPING CMP R0,$KMLOC ;KILLING KMON? BLO 29$ ;NO, OBVIOUSLY NOT USR, EITHER CLR KMLOC ;YES. KMON NON-RESIDENT CMP R0,$USRLC ;KILLING USR? BLO 29$ ;NO BIT #USR$,CONFIG ;ARE WE FORBIDDEN TO SWAP THE USR? BEQ 2$ ;NO, DO IT MOV $USRLC,R0 ;YES. POINT TO THE USR BR 11$ ;AND DECREMENT BY 2 2$: CLR USRLOC ; IT IS NON-RESIDENT MOV SP,USRSWP ;SET THE USR-IS-SWAPPING FLAG 29$: TSTB USRLVL ;DID HE OWN THE USR BEFORE THAT ENQ? BNE 3$ ;YES, RETAIN POSSESSION JSR PC,DEQUSR ;DISOWN USR 3$: MOV R0,@SP ;RETURN R0=TOP MOV R0,@#USERTOP ;AND LOCATION 50 BR EMTRTI ; EMT 16(13) - CANCEL CONTROL O R$CTLO: CLRB I.OCTR+1(R5) ;CLEAR FLAG BYTE JSR PC,TTRSET ;COPY SPECIAL-MODE FLAG BR EMTRTI ; EMT 16(9) - STRING PRINT .ENABL LSB P$RINT: MOVB #LF,OUTCHR ;FORCE CONSOLE CONTEXT SWITCH BR 2$ 1$: ADDR 3$,R0 ;POINT TO CRLF 2$: MOVB (R0)+,R4 ;CHARACTER TO R4 BEQ 1$ ;0 => PUT IN CRLF CMP R4,#177600 ;200 ENDS IT ALL BEQ EMTRTI ;(OTHER NEGATIVES ARE OK) JSR R0,TTOUT ;PUT OUT THE CHARACTER .WORD 0 ;WAIT EVEN IF TCBIT$ IS ON BR 2$ ;TRY AGAIN ON RETURN 3$: .BYTE CR,LF,200,0 ;CR LF TERMINATOR .EVEN .DSABL LSB .SBTTL LOCK / UNLOCK USR, INTERNAL ERROR EMT, SET SOFT / HARD EXIT ; EMT 16(6) - LOCK USR IN CORE ; IF A USER WANTS TO HAVE THE USR IN CORE FOR A SERIES OF ; I/O TYPE OPERATIONS, HE CAN LOCK IT INTO CORE WITH THE ; LOCK EMT. ; ENTERING AT TLOCK SETS THE CARRY IF THE USR IS NOT FREE, ; RATHER THAN WAITING FOR IT AND CLAIMING IT. T$LOCK: ENSYS 2$ ;ENTER SYSTEM STATE CMPB #377,USROWN ;IS THE USR FREE? BNE 1$ ;NO, EXIT SYSTEM STATE MOVB JOBNUM,USROWN ;YES. CLAIM IT 1$: RTS PC ;BACK TO USER 2$: CMPB JOBNUM,USROWN ;DO WE OWN IT NOW? BNE EMTER0 ;NO. GIVE HIM A CARRY L$OCK: JSR PC,CALUSR ;READ MONITOR IN BR EMTRTI ; EMT 16(7) - RELEASE USR FROM CORE ; AFTER A LOCK, THIS EMT RELEASES THE USR. ; IT ALSO IS THE ENTRY POINT FOR USR RETURN. .ENABL LSB U$NLOK: CMPB USROWN,JOBNUM ;DO WE OWN THE USR? BNE EMTRTI ;NO, WE HAVE NO RIGHT TO UNLOCK IT TSTB USRLVL ;WE OWN IT. DID WE LOCK IT? BEQ 1$ ;NO, IT'S NOT CALLED MONOUT: BIC #USRRN$,@CNTXT ;TURN ON ADDRESS CHECKING AGAIN DECB USRLVL ;UP A LEVEL BNE EMTDON ;USR CALLED SELF. LEAVE IT IN CORE 1$: JSR PC,RIDUSR ;OUT OF USR. GET RID OF IT JMP EMTDON ;AND EXIT .DSABL LSB ; EMT 17--USED FOR INTERNAL PURPOSES ONLY. SHOULD NOT BE ; CALLED BY THE USER. MOVES AN ERROR CODE INTO LOCATION ; SET ASIDE FOR THE CODE, AND TURNS THE C BIT ON IN THE ; OFFENDING EMT'S STATUS. EMT17: ASR R4 ;NEED NUMBER BETWEEN 0-17 MOVB R4,@#ERRBYT BIS #1,ERRPS(SP) BR EMTRTI ;************************************************** ; SERR AND HERR GOVERN THE REPORTING OF FATAL MONITOR ERRORS. ; .SERR INDICATES THAT NO FATAL ERRORS ARE TO BE REPORTED. ; .HERR INDICATES THAT HARD ERRORS ARE TO BE REPORTED. ;************************************************** S$ERR: INC R2 ;R2 WAS 0 FROM EMTPRO H$ERR: MOVB R2,I.SERR(R5) ;PUT THE VALUE INTO FLAG RTILK1: BR EMTRTI .SBTTL SOFT RESET ; EMT 16(10) - SOFT RESET ; SOFT RESET CLEARS ALL CHANNELS (EXCEPT 17 IF OVERLAYING IS ON) ; IT THEN FALLS INTO QRESET, WHICH RESETS THE I/O QUEUE TO ; ONE ELEMENT. ; FOR THE BACKGROUND, ANY NON-LOADED HANDLERS ARE PURGED S$RSET: JSR PC,REVERT ;QUIESCE IO, REVERT CHANNELS, ;RESET QUEUE, RELEASE HANDLERS MOV I.CSW(R3),R1 ;POINT TO CHANNELS MOV #16.*5,R0 ;ORIGINAL 16 CHANNELS, 5 WDS EACH BIT #OVLY$,@#JSW ;OVERLAID? BEQ 1$ ;NYET SUB #5,R0 ;DA, REDUCING COUNT 1$: CLR (R1)+ ;ZAP DEC R0 ;REZAP? BNE 1$ ;ZIP BR RTILK1 ;ZOOP ; THE FOLLOWING SUBROUTINE WAITS FOR ALL I/O TO STOP QUIESCE:MOV CNTXT,R3 ;GET IMPURE POINTER JSR R4,$SYSWT ;WAIT FOR I/O TO COMPLETE .WORD EXIT$ MOV I.IOCT(R3),-(SP) ;SET C IF NON-0 NEG (SP)+ JSR PC,@(SP)+ ;RETURN RTS PC .SBTTL CLOSE, PURGE, EMT 16, USR CALLS ; CLOSE EMT ; IF NO DIRECTORY OPERATION IS REQUIRED, THE CHANNEL IS DISSOCIATED, ; AND WE ARE DONE. IF DIRECTORY WORK IS REQUIRED, THE USR IS CALLED. C$LOSE: BIT #RENAM$+DWRIT$,@R3 ;DIRECTORY REWRITE NEEDED? BNE C$LOS2 ;YES. CALL USR P$URGE: CLR (R3)+ ;DISSOCIATE CHANNEL BR RTILK1 ;EXIT EMT16: TST (R4)+ ;R4 HAS SUB CODE TO DO ADD PC,R4 ADD (R4),PC LST16: 10$: T$TIN -10$ T$TOUT-10$ D$STAT-10$ ;DEVICE STATUS F$ETCH-10$ ;FETCH/RELEASE C$SIGN-10$ ;GENERAL MODE CSI C$SISP-10$ ;SPECIAL MODE CSI L$OCK -10$ ;LOCK USR U$NLOK-10$ ;RELEASE USR ..EXIT = . - 10$ E$XIT -10$ ;EXIT PROGRAM P$RINT-10$ ;STRING PRINT S$RSET-10$ ;SOFT RESET Q$SET -10$ ;SET IO QUEUE S$ETOP-10$ ;SET TOP OF CORE R$CTLO-10$ ;RESET ^O BIT EMTRTI-10$ H$RSET-10$ ;HARD RESET .ENABL LSB C$SIGN: TST (PC)+ ;CLEAR THE CARRY C$SISP: SEC ;SET THE CARRY BIS #CSIRN$,@R5 ;SAY THAT THE CSI IS RUNNING BIC R4,R4 ;CLEAR R4 ROR R4 ;PUT GENERAL/SPECIAL FLAG IN SIGN BIT MOV #..CSI,R2 ;CSI CALL IS NUMBER 10. TST @R1 ;IS INPUT STRING FROM THE TTY? BNE EMTUSR ;NYET. GO DOING THINGS INCB R4 ;IF WE DON'T OWN USR YET, WE WILL ;ENTER IT AT A DEPTH OF CALL OF 1 CMPB USROWN,JOBNUM ;WELL, OWN WE IT? BNE 1$ ;NOOOO INCB USRLVL ;YES. THE CSI CALL IS ANOTHER LEVEL CSIERR: CLRB R4 ;PICK UP LEVEL IN LOW BYTE OF R4 BISB USRLVL,R4 JSR PC,RIDUSR ;THROW IT AWAY WHILE WE COLLECT A LINE 1$: MOV CNTXT,R1 ;R1 -> IMPURE AREA ;DV25 BIC #TTSPC$,I.TERM(R1) ;DON'T GATHER STRING IN SPEC. MODE ;DV25 MOV $ENTRY+BA.NUM,R0 ;IS BATCH RESIDENT BEQ 11$ ;NO, WE MUST WAIT! TST 6(R0) ;YES. IS IT ACTIVE? BEQ 11$ ;NO, GOTTA WAIT TST JOBNUM ;BATCH IN AND ACTIVE. IS WE DA BG? BEQ 12$ ;YES, AVOID THE WAIT 11$: .TTYOUT #'* ;PRINT THE PROMPT JSR R4,$SYSWT ;WAIT FOR A LINE ;DV25 .WORD TTIWT$ TST I.TTLC(R1) ;GOT LINE YET? BNE 2$ ;YES, LEAVE C=0 SEC ;NO, SET CARRY 2$: JSR PC,@(SP)+ ;RETURN TO WAITER 12$: MOV #..CSI,R2 ;CSI INDEX JSR PC,CALUSR ;GET THE USR IN CORE AND OURS MOVB R4,USRLVL ;RESTORE (OR SET) PROPER DEPTH CLRB R4 ;R4 = SPECIAL/GENERAL FLAG BIS #CSIRN$,@CNTXT ;FLAG CSI IS RUNNING ;DV7 BR 10$ ;WELL, GO DO IT! ; FOLLOWING IS A TABLE OF CALLS INTO THE USR. R2 IS ; USED AS AN INDEX TO THE PROPER FUNCTION ONCE CONTROL ; HAS PASSED INTO THE USR. D$STAT: INC R2 ;DEVICE STATUS R$NAME: INC R2 ;RENAME L$OOK: INC R2 ;LOOKUP E$NTER: INC R2 ;ENTER C$LOS2: INC R2 ;CLOSE F$ETCH: INC R2 ;FETCH/RELEASE D$LETE: INC R2 ;DELETE Q$SET: ;SET IO QUEUE EMTUSR: JSR PC,CALUSR ;GRAB THE USR 10$: BIS #USRRN$,@CNTXT ;SAY THAT THE USR IS IN CONTROL JMP @USRLOC .DSABL LSB .SBTTL EXIT ; "YOU WILL SOFTLY AND SUDDENLY VANISH AWAY ; AND NEVER BE MET WITH AGAIN." - LEWIS CARROLL ; "THE HUNTING OF THE SNARK" ; EXIT CAUSES THE EXECUTING PROGRAM TO RETURN TO THE MONITOR. ; EXIT FIRST RELEASES THE USR AND WAITS FOR ALL USER I/O TO COMPLETE. ; IF THE FG IS EXITING, IT IS LINKED INTO THE FREE SPACE LIST. ; IF THE BG JOB IS EXITING, IT IS SWAPPED OUT IF NECESSARY ; AND THE KMON AND USR ARE READ INTO THEIR STANDARD PLACE. .ENABL LSB C$HAIN: BIS #CHAIN$,@#JSW ;CHAIN SIMPLY SETS CHAIN BIT MOV SP,R0 ;AVOID HARD EXIT BR 15$ ERRXIT: .PRINT ;PRINT THE MESSAGE CLR R0 ;INDICATE HARD EXIT E$XIT: BIC #CHAIN$,@#JSW ;INDICATE NO CHAINING 15$: MOV R0,-(SP) ;PRESERVE HARD/SOFT FLAG MOV JOBNUM,R2 ;GET OUR JOB NUMBER CMPB USROWN,R2 ;DO WE OWN THE USR? BNE 1$ ;NO CLR BLKEY JSR PC,RIDUSR ;GET RID OF USR 1$: TST @CNTXT ;TRYING EXIT FROM COMPLETION? BMI UABTLK ;THAT'S NAUGHTY ENSYS 16$ JMP CMKALL ;CANCEL ALL OUTSTANDING MARK TIMES 16$: JSR PC,REVERT ;WAIT FOR ALL I/O TO STOP ADD #I.SPLS,R3 ;POINT TO IMPURE GOODIES MOV @R3,R1 ;POINT TO SPECIAL LIST TO KILL ON EXIT BEQ 4$ ;NOTHING CLR @R3 ;TURN IT OFF JUST IN CASE IT TRAPS BR 3$ ;ENTER LOOP 2$: MOV (R1)+,@R2 ;JAM A WORD 3$: MOV (R1)+,R2 ;GET A POINTER BNE 2$ 4$: MOV (R3)+,(R3)+ ;CLEAR TRAP INTERCEPT (JAM ADDR NOW 0) CLR (R3)+ ;CLEAR FPP INTERCEPT CLR (R3)+ ;CLEAR SPECIAL SWAPS CMP (R3)+,(R3)+ ;SKIP OVER SWAP2, SAVED SP ADDR LOWMAP,R5 ;POINT TO BIT MAP MOV #MAPSIZ,R2 ;CLEAR ALL MAP WORDS 5$: BIC @R3,(R5)+ ;CLEAR PERM. MAP CLR (R3)+ ;AND JOB MAP DEC R2 ;LOOP BNE 5$ TST JOBNUM ;ARE WE EXITING FROM THE FG? BNE 50$ ;YES. NO KMON, NO NOTHING. MOV SP,(PC)+ ;FLAG B/G ABORT IN PROGRESS EXTFLG: .WORD 0 ADD #SPTR->,R5 ;SWITCH TO MONITOR STACK MOV (SP)+,-(R5) ;PUT PASSED R0 ONTO NEW STACK MOV R5,SP MOV $KMLOC,R2 ;POINT TO PERM ADDRESS FOR KMON TST KMLOC ;IS KEYBOARD IN CORE? BNE 11$ ;YES, JUST GO TO IT JSR PC,ENQUSR ;WE MUST OWN THE USR FOR THIS ADD #USRSWP-,R5 ;POINT TO SWAP DATA CLR (R5)+ ;USR DOES NOT SWAP MOV (R5)+,R0 ;GET START OF SWAP AREA MOV R2,@R5 ;SET POINTER TO KMON BIC #777,@R5 ;ROUND IT DOWN TO SWAP OUT MOV (R5)+,@R5 ;COMPUTE AMOUNT TO WRITE OUT SUB @#USERTOP,@R5 ;IT'S A NEGATIVE NUMBER BHI 6$ ;KMON ROUNDED > HIS TOP, DON'T WRITE ROR @R5 ;MAKE IT A WORD COUNT DEC @R5 ;TOP WAS OFF BY 2 TST -(R5) ;FIX R5 JSR PC,$SYS ;AND SWAP THE GUY OUT BCS SWPERR ;ERROR, GO ABORT THE JOB TST (R5)+ ;FIX R5 SO 6$ ENTERED SAME WAY 6$: CMP (R5)+,(R5)+ ;ADVANCE POINTER TO SWAP-IN IOB ADD #SWAPSZ,R0 ;AND POINT TO BLOCK WITH KMON CMP -(R2),-(R2) ;BACK UP SO WE CALL LOCATE FIRST JSR PC,$SYS ;READ IN THE KMON/USR BCC 11$ ;AOK READ, GO ENTER AT MEXIT JSR R0,9$ ;OOPS, THAT'S REALLY BAD. SAVE R0 .ASCIZ /?M-SYS ERR/ ;PRINT THIS MESSAGE .EVEN 9$: .PRINT ;DO THE PRINT MOV (SP)+,R0 ;RESTORE BLOCK NUMBER 10$: JSR PC,$SYS ;AND KEEP TRYING DESPERATELY BCS 10$ ;UNTIL IT SUCCEEDS 11$: JMP MEXIT2-KMON(R2) ;ENTER THE KMON 50$: MOV CNTXT,R0 ;FLUSH OUTPUT BUFFER 51$: TSTB I.OCTR(R0) ;DONE? BNE 51$ ;LOOP BIS #NORUN$,@CNTXT ;DO NOT LET HIM RUN AGAIN ADDR TTIUSR,R4 ;THROW AWAY THE TTY JSR PC,CTRL.B ;BY GIVING IT TO THE BG JMP USWAPO ;SAY GOODNIGHT, DICK. .DSABL LSB SWPERR: .HRESET ;STOP EVERYTHING CLR @#USERTOP ;DON'T TRY TO WRITE THE GUY OUT JSR R0,ERRXIT ;PRINT ERROR AND EXIT .ASCIZ /?M-SWAP ERR/ .EVEN UABTLK: JMP UABORT ;GO TO ABORTER .SBTTL SWAP USR ROUTINE ; CALUSR---- ; THIS ROUTINE LOADS THE USR INTO CORE. ; THE USER PROGRAM IS SWAPPED OUT IF NECESSARY. .ENABL LSB CALUSR: JSR PC,ENQUSR ;OWN THE USR BEFORE USING IT INCB USRLVL ;BUMP USAGE COUNT TST USRLOC ;MONITOR IN CORE? BNE 4$ MOV $USRLC,-(SP) ;IF NOT FLOATING, IT GOES HERE TST USRSWP ;FLOAT? BEQ 3$ ;NO, READ IN A GOOD PERM COPY MOV @#UFLOAT,@SP ;ADDRESS OF FLOATING USR BEQ 1$ ;DOESN'T FLOAT. SEE IF RESIDENT. JSR R5,CHKSP ;CHECK LOW LIMIT BR 90$ ;ERROR ADD #USRSIZE-2,@SP ;CHECK TOP LIMIT JSR R5,CHKSP ;CHECK HIGH LIMIT BR 90$ SUB #USRSIZE-2,@SP ;FIX ADDRESS BR 2$ ;OK, CONTINUE 1$: TST JOBNUM ;ONLY BG CAN SWAP IN STANDARD PLACE BNE 90$ ;AND THIS ISN'T HE MOV $USRLC,@SP ;AH. SWAP IT THERE 2$: MOV (PC)+,R5 ;POINT TO IOB FOR SYSTEM WRITE SWOPTR: .WORD SWOIOB ;*** BOOT *** MOV @SP,@R5 ;PUT IN ADDRESS OF BUFFER JSR PC,$SYSSW ;DO I/O TO SWAP BLOCKS BCS SWPERR ;SWAP ERROR 3$: MOV (PC)+,R5 ;POINT TO IOB FOR SYSTEM READ SWIPTR: .WORD SWIIOB ;*** BOOT *** MOV (PC)+,R0 ;GET BLOCK NUMBER OF USR $MONBL: .WORD 0 ;*** BOOT *** MOV @SP,@R5 ;PUT IN ADDRESS OF AREA JSR PC,$SYS ;DO THE I/O BCS SWPERR ;OOPS, GOT AN ERROR MOV (SP)+,USRLOC ;WE NOW HAVE A GOOD USR COPY IN CORE 4$: RTS PC ;RETURN WITH USR IN CORE 90$: CMP (SP)+,(SP)+ ;PRUNE MONERR USRX,,FATAL ;ATTEMPT TO SWAP USR INTO ILLEGAL AREA ; "WELL, IT'S BLAST-OFF TIME FOR GALACTO-CITY." - PERRY RHODAN RDOVLY: CLR KMONIN ;KMON DEAD AS SOON AS READ STARTS JSR PC,$SYS ;THE KMON SET UP KMBLK FOR FINAL READ BCS SWPERR ;BAD SAVE FILE, GIVE '?M-SWAP ERR' ENTRPG: MOV @#USERSP,SP ;NEW STACK POINTER CLR KMONIN ;USER IS RUNNING ;DV16 CLRB USRLVL ;GET RID OF THE USR MOV R2,-(SP) ;SET TO RETURN TO THE USER START ADDRESS BR DEQUSR ;AND RELEASE THE USR WITH NO SWAPPING .DSABL LSB .SBTTL ENQ / DEQ ON USR ; THE FOLLOWING SUBROUTINE OBTAINS EXCLUSIVE USE OF THE USR ; FOR THE RUNNING JOB. IT IS CALLED FROM USER STATE WITH A JSR PC,ENQUSR ; AND MAY SWITCH INTO SYSTEM STATE IF IT HAS TO WAIT. ; IN ANY CASE, IT INCREMENTS THE USR LEVEL OF CALL ENQUSR: CMPB JOBNUM,USROWN ;DO WE OWN IT ALREADY? BEQ 1$ ;YEP ENSYS ENQUSR ;NO, ENTER SYSTEM STATE TO GET IT CMPB USROWN,#377 ;IS IT FREE? BNE 2$ ;NO, DELAY UNTIL IT IS OURS MOVB JOBNUM,USROWN ;YES. STAKE OUR CLAIM 1$: RTS PC ;GET OUT OF SYSTEM STATE 2$: JMP DLYUSR ;JUMP TO DELAY CODE ; SWAP USR OUT IF NECESSARY, THEN FREE IT RIDUSR: BIC #USRRN$+CSIRN$,@CNTXT CLRB USRLVL ;INSURE 0 LEVEL BIT #ABORT$,@CNTXT ;WAS ABORT REQUESTED DURING DIRECTORY OP? BNE UABTLK ;YEP. TST USRSWP ;IS THE USR SWAPPING? BEQ DEQUSR ;NO. DON'T SWAP. CLR BLKEY ;KILLS DIRECTORY IN CORE MOV SWIPTR,R5 ;POINT TO IOB FOR SYSTEM READ MOV SWOIOB,@R5 ;READ INTO SAME PLACE WE LAST WROTE USER BEQ 1$ ;NO READ DONE! JSR PC,$SYSSW ;DO I/O TO SWAP BLOCKS BCS SWPERR ;SWAPPING ERROR! CLR SWOIOB ;INDICATE NO USER IS OUT THERE 1$: CLR USRLOC ;USR NO LONGER IN CORE ; THIS ROUTINE RELEASES USE OF THE USR. ; IT DECREMENTS USR LEVEL, AND IF ZERO, RELEASES EXCLUSIVE USE ; OF IT AND GIVES IT TO ANY OTHER GUY WHO WANTS IT DEQUSR: CMPB JOBNUM,USROWN ;DO WE OWN THE USR? BNE 2$ ;NO, IGNORE ATTEMPTS TO DISOWN IT ENSYS 2$ ;GOTTA GIVE IT AWAY MOVB #377,USROWN ;MARK IT NOT IN USE MOV IMPLOC,R4 ;POINT TO IMPURE POINTERS ;DV16 1$: MOV -(R4),R5 ;GET AN IMPURE POINTER BEQ 1$ ;JOB NOT ACTIVE INC R5 ;END OF TABLE? BEQ 2$ ;YES. IT IS FREE BITB #USRWT$,-(R5) ;IS HE WAITING FOR THE USR? BEQ 1$ ;NO JSR R4,UNBLOK ;YES. LET A GUY RUN .WORD USRWT$ MOVB I.JNUM(R5),USROWN ;AND GIVE IT TO HIM 2$: RTS PC .SBTTL RESIDENT TELETYPE HANDLER .ENABL LSB TTCMPL+2-. ;OFFSET TO ABORT ENTRY 0 ;HANDLER HOLD FLAG TTLQE: 0 ;POINTER TO LAST Q ELEMENT TTCQE: 0 ;CURRENT Q ELEMENT MOV TTCQE,R3 ;R3 -> CQE MOV (R3)+,R4 ;R4 = BLOCK # MOV (R3)+,R1 ;R1 HAS JOB NUMBER SWAB R1 ;PUT IT IN PLACE ASR R1 ASR R1 ASR R1 BIC #177761,R1 ;ISOLATE NUMBER ADD PC,R1 ;POINT TO IMPURE AREA (PIC) MOV $IMPUR-.(R1),R2 ASL 2(R3) ;WORD COUNT -> BYTE COUNT BEQ TTCMPL ;0 => DONE SEEK BCS 5$ ;<0 => WRITE MOV R2,(PC)+ ;READ. SAVE IMPURE OF INPUT USER TTHIUS: 0 TST R4 ;IS THIS BLOCK 0? BNE TTHIN ;NO MOVB #'^,R4 ;YES. PUT A PROMPT IN HIS BUFFER JSR PC,TTOPT2 ; TTHIN IS ENTERED WHEN THE HANDLER IS FIRST CALLED, AND AGAIN ; EACH TIME THE RESIDENT SERVICE DETECTS A LINE DELIMITER. ; IT ATTEMPTS TO GET AS MANY LINES AS POSSIBLE OUT OF THE RING BUFFER TTHIN: MOV TTCQE,R3 ;R3 -> Q ELEMENT CMP (R3)+,(R3)+ ;ADVNACE TO BUFFER POINTER 1$: MOV TTHIUS,R2 ;R2 -> IMPURE AREA TST I.TTLC(R2) ;MAN GOTTUM LINE? BEQ 6$ ;NO JSR PC,IGET ;YES. GETTUM CHARACTER BEQ $RQABT ;^C ABORTS CMPB #'Z-100,R4 ;END OF FILE MARKER? BEQ 3$ ;YES MOVB R4,@(R3)+ ;PUT BYTE IN BUFFER DEC @R3 ;DECREMENT BYTE COUNTER BEQ 35$ ;EMPTY, GO COMPLETE IO INC -(R3) ;BUMP BUFFER POINTER BR 1$ ;LOOP 2$: INC -(R3) ;BUMP BUFFER POINTER 3$: CLRB @(R3)+ ;CLEAR AN UNFULFILLED BYTE DEC @R3 ;COUNT DOWN BNE 2$ ;KEEP GOING BIS #EOF$,@Q.CSW-Q.WCNT(R3) ;SET END OF FILE 35$: MOV R5,R3 ;PRESERVE R5 JSR PC,TTCMPL ;CALL COMPLETION MOV R3,R5 ;RESTORE R5 MOV R0,R4 ;PUT CHAR TO ECHO IN R4 6$: RTS PC ;RETURN TO TT OR MONITOR TTCMPL: CLR TTHIUS ;STOP USING THE TT: CLR TTHOUS ADDR TTCQE,R4 ;POINT TO CQE JMP COMPLT ;EXIT VIA COMPLETION 5$: MOV (R3)+,-(SP) ;REVERSE BUFFER POINTER AND BYTE COUNT MOV @R3,-(R3) ; SO THAT IT RESEMBLES THE MONITOR'S NEG (R3)+ ; RING POINTERS (AND CONVERT TO REAL MOV (SP)+,@R3 MOV R2,TTHOUS ;SAY WE ARE USING IT BR TTOENB ;TURN ON TTY IF NOT ALREADY ON .DSABL LSB ; GET A CHARACTER FROM A USER'S INPUT RING BUFFER ; ENTER WITH R2 -> IMPURE AREA, EXIT WITH CHARACTER IN R4 ; CONDITION CODES READ ZERO IF ^C READ IGET: ADD #I.IGET,R2 ;MOVE UP TO GET POINTER INC @R2 ;BUMP POINTER CMP (R2)+,@R2 ;TIME TO WRAP? BNE 1$ SUB #TTYIN,-2(R2) ;WRAP THE BUFFER 1$: MOVB @-(R2),R4 ;GET THE CHARACTER DEC -(R2) ;DECREASE THE COUNT JSR PC,EOLTST ;END OF LINE (^C, ^Z, LF) BNE 2$ DEC I.TTLC-I.ICTR(R2) ;DECREMENT # OF LINES LEFT CMPB #'C-100,R4 ;SET ZERO IF CTRL C 2$: RTS PC TTRSET: MOV @#JSW,R3 ;JSW IN R3 ;DV25 BIC #127777,R3 ;CLEAR ALL BUT TTSPC$ & TTLC$ ;DV25 BIT #TTSPC$,R3 ;IS SPECIAL BIT ON IN JSW? ;DV25 BEQ 1$ ;NO SPECIAL MODE ADD #I.ICTR-I.TTLC,R1 ;R1 -> CHAR COUNT FOR SPECIAL 1$: MOV R3,I.TERM(R5) ;SAVE TERMINAL STATUS OF JOB ;DV25 RTS PC ; PUT A CHARACTER OUT TO THE TT, WAITING IF NECESSARY TTOUT1: JSR R4,$SYSWT ;WAIT FOR ROOM IN OUTPUT BUFFER .WORD TTOWT$ CMPB #TTYOUT-1,@R2 ;SET CARRY IF STILL NO ROOM JSR PC,@(SP)+ ;COROUTINE RETURN TTOUT: MOV CNTXT,R2 ;POINT TO IMPURE AREA JSR PC,TTOPT2 ;CALL ROUTINE TO PUT IT OUT BCC 1$ ;GOT IT, RETURN BIT @R0,@#JSW ;NO ROOM. DOES HE WANT C-BIT? BEQ TTOUT1 ;TCBIT OFF, OR DOING .PRINT 1$: BIT (R0)+,R1 ;POP R0 WITHOUT CHANGING CARRY RTS R0 ;RETURN TO CALLER .SBTTL TTY INPUT INTERRUPT .ENABL LSB CTRL.C: JSR R5,ECHO0C ;TYPE A ^C AND CR/LF .BYTE CR,LF CMP R0,I.PTTI(R5) ;IS IT SECOND ^C? BNE TTINC3 ;NO. IGNORE IT FOR NOW. TST I.JNUM(R5) ;TYPED TO B/G? BNE 20$ ;BR IF NOT TST EXTFLG ;EXIT IN PROGRESS? BNE TTINC3 ;YES,SKIP THIS MOV $ENTRY+BA.NUM,R3 ;BA.SYS RESIDENT? BEQ 20$ ;BR IF NOT CLR 6(R3) ;STOP BATCH IF ACTIVE 20$: ; YES. ASK FOR AN ABORT WHEN WE ARE ABOUT TO RETURN FROM LEVEL 0 ; THE FOLLOWING ROUTINE REQUESTS THAT A USER BE ABORTED ; IT IS CALLED FROM SYSTEM STATE WITH R5 -> USER'S IMPURE AREA ; $RQABT: BIS #100000,INTACT ;SET 'ABORT PENDING' FLAG BIS #ABORT$,@R5 ;TURN ON ABORT REQUEST IN USER'S JSTAT RTS PC ;RETURN CTRL.Q: CLR XEDOFF ;ALLOW THE TYPER TO TYPE TSTB TTCNFG ;ARE WE SUPPOSED TO IGNORE THIS? BMI 2$ ;YES, GO DO OUR THING JSR PC,TTIDSP ;NO, GO PROCESS THE CHARACTER 2$: CLR @TTPS BR TTOENB ;INTERRUPT IT IF IDLE CTRL.B: MOV BCNTXT,R0 1$: MOV R0,@R4 ;SET NEW TTIUSR CMP -(R4),R0 ;IS NEW GUY ALSO TTOUSR? BEQ 3$ MOV R0,@R4 ;NO, GIVE HIM TELETYPE MOV I.TID(R0),-(R4) ;PRINT ID CHANGE TTOENB: MOV #IENABL,@TTPS 3$: RTS PC CTRL.F: MOV FCNTXT,R0 ;POINT TO FG IMPURE AREA BEQ 4$ ;NO FG! BIT #NORUN$,@R0 ;BE HE DEAD? BEQ 1$ ;NAY, HE LIVETH 4$: JSR R5,ECHO ;SMITE HIM WHO TYPETH ^F .BYTE 'F,'? ECHOCL: JSR R5,ECHO ;PUT OUT CR/LF .BYTE CR,LF RTS PC TTIINT: JSR R5,$INTEN ;* DO INTERRUPT COMMON ENTRY .WORD ^C&PR7 ; (LEVEL 4) JSR R3,SAVE30 ;SAVE REGS 3-0 MOV @TTKB,R0 ;CHARACTER TO R0 ;*** FOLLOWING LINE MODIFIED BY GT ON TO INTERCEPT INTERRUPTS *** SCLNK2: BIC #177600,R0 ;CLEAR PARITY BEQ 3$ ;EXIT ON NULLS. ADDR LIST,R2 ;POINT TO SPECIALS LIST MOV R2,R4 ;COPY POINTER FOR ^F, ^B MOV -(R4),R5 ;R4 -> TTIUSR (= R5) MOV R5,R1 ;COPY IMPURE PTR ADD #I.ICTR,R1 ;R1 -> INPUT RING COUNT BIT #TTLC$,I.TERM(R5) ;CONVERT TO UPPER CASE LEGAL? ;DV25 BNE 10$ ;NO, CONVERSION IS DISABLED. CMP R0,#'A+40 ;IF LOWER CASE, CONVERT BLT 10$ ;TO UPPER CASE CMP R0,#'Z+40 BGT 10$ BIC #40,R0 ;UPPER CASE CONVERSION. 10$: .DSABL LSB .ENABL LSB 2$: MOVB (R2)+,R3 ;OFFSET TO R3 BEQ TTINCC ;DONE SPECIALS IF ZERO ASLB R3 ;MAKE IT A WORD. DONE GENERALS? BEQ TTIDSP ;YES CMPB (R2)+,R0 ;A MATCH? BNE 2$ ADD R3,PC ;DO A NON-STANDARD JUMP TTIBASE: ;THIS IS USED TO BASE THE SPECIAL LIST .35$: CLR @R5 ;CLEAR PREVIOUS INPUT CHAR BR ECHOCL ;ECHO CR/LF CTRL.S: MOVB TTCNFG,XEDOFF ;SET X-ED OFF SWITCH BMI 4$ ;IF ENABLED, IT'S ON, SO RETURN TTIDSP: BIT #TTSPC$,I.TERM(R5) ;IS IT IN SPECIAL MODE? ;DV25 BEQ 2$ ;NO, FINISH PROCESSING FOR USER BR TTINC3 ;YES ALT: MOV #ESCAPE,R0 ;USE 33 CODE AS STANDARD TTINCC: CMP I.PTTI(R5),#RUBOUT ;WAS PREVIOUS A RUBOUT? BNE TTINC3 TST TTCNFG ;CONSOLE IS VT05? BMI TTINC3 ;YES, NO \ JSR R5,ECHO ;YES. TYPE \ FIRST .BYTE '\,0 TTINC3: CMP @R1,#TTYIN ;WILL IT FIT IN BUFF? BGE 25$ ;NO. MOV R0,R4 ;COPY CHAR. FOR ECHOING INC @R1 ;BUMP COUNT INC -(R1) ;BUMP INPUT POINTER CMP @R1,6(R1) ;TIME TO WRAP? BNE 6$ SUB #TTYIN,@R1 ;CYCLE THE BUFFER. 6$: MOVB R0,@(R1)+ ;PUT CHARACTER INTO BUFFER. JSR PC,EOLTST ;END OF LINE TEST BNE 7$ ;NOT EOL. INC I.TTLC(R5) ;BUMP LINE COUNT CMP TTHIUS,R5 ;IS HE USING THE TT: HANDLER FOR INPUT? BNE 7$ ;NO JSR PC,TTHIN ;YES, CALL THE HANDLER 7$: MOV R0,I.PTTI(R5) ;SAVE PREVIOUS CHAR. JSR R4,UNBLOK ; WE UNBLOCK HIM .WORD TTIWT$ BIT #TTSPC$,I.TERM(R5) ;DON'T ECHO IN SPECIAL MODE ;DV25 BNE 10$ JSR PC,TTOPT3 ;ECHO THE CHARACTER ; NOTICE THAT SINCE WE IGNORE THE CARRY, IF IT WON'T FIT IT ; WON'T ECHO 10$: ADD #LF-CR,R0 ;IS CHAR A CR? CMP #LF,R0 ;IF YES, PUT IN A LINE FEED BEQ TTINC3 4$: RTS PC CTRL.O: ADD #I.OCTR-I.ICTR,R1 ;R1 -> OUTPUT COUNT. CLRB (R1)+ ;CLEAR THE COUNT MOVB @R1,-(SP) ;GET FORMER ^O CONDITION CLRB (R1)+ ;TURN IT OFF TEMPORARILY MOV (R1),-4(R1) ;SET BUFFER PTRS. EQUAL. JSR R5,ECHO0C ;ECHO ^O CR LF .BYTE CR,LF COM @SP ;FLIP THE FLOP MOVB (SP)+,-(R1) ;AND SET IT UP BEQ 20$ ;TURNING IT ON IS EASY JSR R4,UNBLOK ;TURNING OFF TTY OUTPUT MEANS .WORD TTOWT$ ; INFINITE ROOM IN BUFFER 20$: RTS PC ;RETURN FROM INTERRUPT 25$: MOV #BELL,R4 ;DING HIM FOR OVERFLOW MOV R0,I.PTTI(R5) ;BUT BE WARY OF ^C ^C BR TTOPT4 ;GO DING .DSABL LSB .ENABL LSB CTRL.U: JSR PC,ECHOR0 ;ECHO ^U RUB: ADD #I.PTTI,R5 ;R5 -> PREVIOUS INPUT CHAR 30$: TST @R1 ;ANY CHARS TO DELETE? BEQ .35$ ;NO. MOVB @-(R1),R4 ;CHARACTER TO R4 JSR PC,EOLTST ;LINE TERMINATOR? BEQ .35$ ;NO. CMP @R1,-2(R1) ;NEED TO WRAP AROUND BACKWARDS? BNE 31$ ;NO ADD #TTYIN,@R1 ;YES. BUMP TO TOP OF BUFFER 31$: DEC (R1)+ ;BACK UP POINTER DEC @R1 ;DECREASE CHARACTER COUNT CMPB #'U-100,R0 ;ARE WE DOING ^U? BEQ 30$ ;YES. TRY ANOTHER RUBOUT TST TTCNFG ;NO, IT'S A RUBOUT. VT05? BPL 32$ ;NO, NORMAL ECHO JSR R5,ECHO ;YES, ECHO BS,SPACE,BS .BYTE BS,40 MOV #BS,R4 ;LAST ECHO BR TTOPT4 ;PUT IT OUT AND SAY BYE 32$: MOV R4,-(SP) ;SAVE CHAR BEING RUBBED CMP @R5,R0 ;WAS LAST A RUBOUT? BEQ 33$ ;YES MOV R0,@R5 ;REPLACE PREVIOUS CHARACTER TYPED JSR R5,ECHO ;NO, TYPE THE LEADING \ .BYTE '\,0 33$: MOV (SP)+,R0 ;RESTORE THE MOV R0,R4 ; CHARACTER TO DELETE BR TTOPT3 ;OUTPUT THE CHARACTER, EXIT .DSABL LSB .MACRO INLST LOC,CHAR .BYTE /2,CHAR .ENDM INLST ; TTOID POINTS TO A JOB ID AREA WHEN ONE IS BEING PRINTED. ; THE JOB ID IS "B>" FOR BACKGROUND, SIMILAR FOR FG. ; TTIUSR/TTOUSR POINT TO THE IMPURE AREAS OF THE JOBS CURRENTLY ; CONTROLLING THE TTY INPUT AND OUTPUT, RESPECTIVELY. TTOID: .WORD 0 ;POINTS TO ID WHEN ID PRINT IN PROGRESS TTOUSR: .WORD BKGND ;*** BOOT *** INITIALLY POINT TO BACKGROUND TTIUSR: .WORD BKGND ;*** BOOT *** LIST: INLST CTRL.C,'C-100 INLST CTRL.O,'O-100 INLST CTRL.S,'S-100 INLST CTRL.Q,'Q-100 LISTFB: INLST CTRL.F,'F-100 INLST CTRL.B,'B-100 .BYTE 200 ;END OF GENERAL LIST INLST CTRL.U,'U-100 INLST ALT,175 INLST ALT,176 INLST RUB,RUBOUT .BYTE 0 .EVEN .SBTTL TTY OUTPUT SUBROUTINES ; NOTE THAT THIS ROUTINE RETURNS CONDITION IN C BIT ; IT DOES NOT SWAP THE USER, SINCE IT MAY BE CALLED FROM INTERRUPT LEVEL .ENABL LSB ECHOR0: MOV #'^,R4 ;PUT OUT AN ^ JSR PC,TTOPT3 ;PUT OUT THE ^ MOV R0,R4 ;GET THE CONTROL CHAR BIS #100,R4 ;MAKE IT VISIBLE, FALL INTO PRINTER TTOPT3: CMP #'C-100,R4 ;REFUSE TO ECHO ^C BEQ 3$ CMP #ESCAPE,R4 ;SPECIAL INPUT ECHO OF ESCAPE BNE 10$ MOV #'$,R4 ;WHICH IS $ 10$: CMP #40,R4 ;IS IT PRINTABLE? BLOS TTOPT4 ;YES CMP #15,R4 ;SPECIAL RANGE? BLO ECHOR0 ;ECHO AS ^(R0) CMP #11,R4 ;OTHER END OF RANGE BHI ECHOR0 TTOPT4: MOV TTIUSR,R2 ;PUT CHARACTERS INTO INPUT OWNERS BUFF TTOPT2: ADD #I.OCTR,R2 ;POINT TO OUTPUT COUNT TST @R2 ;< 0 MEANS CONTROL O BMI 3$ ;YES. ACT LIKE SUCCESS BIC #177600,R4 ;EXTRANEOUS BITS OUT CMP #TTYOUT-1,@R2 ;WILL THIS FIT? BLO 3$ ;NO, RETURN CARRY SET (EVIL) MOVB R4,@-(R2) ;INSERT CHARACTER INTO RING INC @R2 ;BUMP THE POINTER CMP 6(R2),@R2 ;TIME TO WRAP AROUND? BHI 1$ SUB #TTYOUT,@R2 ;NOTE THAT THIS CLEARS THE CARRY 1$: INC 2(R2) ;BUMP COUNT JMP TTOENB ;ENABLE OUTPUT INTERRUPTS ECHO0C: JSR PC,ECHOR0 ;FIRST ECHO ^ [R0] ECHO: MOVB (R5)+,R4 ;ECHO 1 OR 2 BYTES JSR PC,TTOPT4 MOVB (R5)+,R4 BEQ 2$ ;ONLY ONE JSR PC,TTOPT4 ;PRINT THE OTHER 2$: RTS R5 EOLTST: CMPB #LF,R4 ;IS IT A LINE FEED? BEQ 3$ CMPB #'Z-100,R4 BEQ 3$ CMPB #'C-100,R4 ;IS IT ^C 3$: RTS PC .DSABL LSB .SBTTL TTY OUTPUT INTERRUPT .ENABL LSB OFILL: DEC NFILLS CLR @TTPB ;PUT OUT A NULL RTS PC TTOINT: JSR R5,$INTEN ;* DO USUAL INTERRUPT ENTRY .WORD ^C&PR7 ; CHECK FOR FILLERS SPECIFIED IN SYSCOM LOC. 56 TST (PC)+ ;FILLING? NFILLS: 0 BNE OFILL ;YEP TSTB (PC)+ ;XOFF GIVEN? XEDOFF: 0 BMI 9$ ;YEP ; CHECK FOR TAB TO SPACE CONVERSION FOON: ADDR FILCTR,R4 ;CHECK FOR TAB OR FREE CRLF INCB @R4 ;COUNT FILLS BMI 8$ ;STILL FILLING. PUT IT OUT CLRB (R4)+ ;FIX CTR, POP R4 MOV TTOID,R5 ;PRINTING AN ID? BEQ 3$ ;NO 1$: MOVB (R5)+,(R4)+ ;YES. SET CHAR OF ID BNE 2$ ;GOT ONE CLR R5 ;END OF ID 2$: MOV R5,TTOID ;SAVE NEW TTOID BNE 8$ ;PUT OUT CHARACTER DEC R4 ;FIX R4 3$: MOV TTOUSR,R5 ;GET USER'S IMPURE PTR CMPB @R4,#LF ;TIME TO ARBITRATE? BNE 5$ ;NO MOV IMPLOC,R4 ;YES, POINT TO JOB TABLES ;DV16 4$: MOV -(R4),R5 ;GET PTR BEQ 4$ ;NO SUCH JOB CMP #-1,R5 ;END OF TABLE? BEQ .20$ ;YES. NOBODY WANTS TO TALK BIT #NORUN$,@R5 ;DEAD MEN SPEAK NOT BNE 4$ CMP (PC)+,R5 ;IS HE USING THE TT: FOR OUTPUT? TTHOUS: 0 ;IMPURE AREA PTR FOR OUTPUT USER BEQ 45$ ;YES, ERGO HE CAN SPEAK TSTB I.OCTR(R5) ;A JOB. DOES HE HAVE OUTPUT? BEQ 4$ ;SILENT 45$: ADDR OUTCHR,R4 ;YES. FIX R4 POINTER CMP TTOUSR,R5 ;SAME GUY? BEQ 5$ ;YES. DO NOT PRINT ID MOV R5,TTOUSR ;NO, CHANGE USERS MOV I.TID(R5),R5 ;GET ID POINTER BR 1$ ;PRINT THE ID 5$: CMP TTHOUS,R5 ;IF HE IS USING THE HANDLER BEQ TTHOUT ; DO SPECIAL STUFF JSR R4,UNBLOK ;UNBLOCK THE LUCKY GUY .WORD TTOWT$ ADD #I.OTOP,R5 ;POINT TO RING POINTERS CMP @R5,-(R5) ;TIME TO WRAP? BNE 6$ ;NO SUB #TTYOUT,@R5 ;YES 6$: TSTB -2(R5) ;ANYTHING TO PRINT? BEQ .20$ ;NO MOVB @(R5)+,@R4 ;GET BYTE TO PRINT .65$: BICB #200,@R4 ;7 BIT ASCII CMPB (R4)+,#40 ;PRINTABLE? BLO .10$ ;MAYBE NOT INCB @R4 ;YES. BUMP LINE POSITION BIT #CRLF$,TTCNFG ;DOES HE WANT FREE CRLF'S? BEQ OBUMP ;NO, TYPE IT CMPB @R4,TTWIDTH ;OVER TT LINE WIDTH? BLOS OBUMP ;NOT YET CLRB @R4 ;YES. GIVE CR/LF. CLEAR LINPOS DEC R4 MOV #177000+LF,-(R4) ;1 FILL OF LF BR 8$ ;DO NOT CYCLE POINTERS OCKCR: CMPB (R4)+,#CR ;IS SPECIAL A CR? BNE OBUMP ;NO CLRB @R4 ;YES. CLEAR LINE POSITION OBUMP: INC -(R5) ;BUMP OUTPUT RING PTR DEC -(R5) ;COUNT DOWN CHARACTERS 8$: MOVB -(R4),@TTPB ;PRINT CMPB @R4,@#TTFILL ;NEED FILLERS? BNE 9$ ;NO MOVB @#TTNFIL,NFILLS ;YES. SET EM UP 9$: RTS PC ;RETURN FROM INTERRUPT .DSABL LSB TTHOCM: JSR PC,TTCMPL ;CALL COMPLETION FUNCTION FOR TT: OUTPUT BR FOON ;AND TRY THE INTERRUPT AGAIN .ENABL LSB .10$: CMPB -(R4),#TAB ;A TAB? BEQ 11$ ;YES CMPB (R4)+,#BS ;NO. A BACKSPACE? BEQ 14$ ;YES CMPB -(R4),#FF ;IS IT A FORM FEED? BNE OCKCR ;NO, GO CHECK FOR CR BIT #FORM$,TTCNFG ;DOES HE HAVE HARDWARE FORM? BNE 13$ ;YES, DO NOT SIMULATE MOV #174000+LF,-(R4) ;SIMULATE EIGHT FORM FEEDS BR 13$ ;FIX R4 11$: BIT #HWTAB$,TTCNFG ;HARDWARE TABS? BNE 12$ ;YES MOV @R4,-(R4) ;MOVE LINPOS TO FILLCTR CLRB @R4 ;BLANKS BIS #174000+40,@R4 ;SET TO FILL WITH BLANKS 12$: ADD #8.*400,LINPOS-1 ;FIX UP LINE POSITION BIC #7*400,LINPOS-1 13$: INC R4 ; BUMP POINTER BR OBUMP ;PUT IT OUT 14$: TST TTCNFG ;VT05 MODE ON? BPL OBUMP ;NO DECB @R4 ;YES. BACK UP BR OBUMP .20$: CLR @TTPS ;NO OUTPUT. TURN OFF TTY RTS PC TTHOUT: TST I.OCTR(R5) ;IF HE HIT ^O BMI TTHOCM ;COMPLETE VERY QUICKLY MOV TTCQE,R5 ;POINT TO Q ELEMENT ADD #Q.BUFF-Q.BLKN,R5 ;POINT TO BYTE COUNT TTHOU1: TST (R5)+ ;OUTPUT COMPLETE? BEQ TTHOCM ;YEAH MOVB @(R5)+,@R4 ;GET A BYTE BNE .65$ ;PRINT NON NULLS INC -(R5) ;BUMP BYTE POINTER DEC -(R5) ;DROP CHAR COUNTER BR TTHOU1 ;LOOP .DSABL LSB .SBTTL SPECIAL FUNCTIONS, RCVD, READ ; SPECIAL FUNCTION CALLS LOOK LIKE READ EMT'S, BUT THE 3RD ; WORD OF THE ARG LIST IS IN THE FORM .BYTE 377,CODE ; WHERE CODE IS THE FUNCTION TO BE DONE. WORD 4 CONTAINS THE ACTUAL ; COMPLETION FUNCTION S$PFUN: MOV @R3,R2 ;GET CSW STATUS WORD BIC #177701,R2 ;ISOLATE DEVICE INDEX ADD PC,R2 ;PIC CODE IS FUN BIT $STAT-.(R2),#SPFUN$ ;IS THIS A SPECIAL DEVICE? ;DV17 BEQ RWXT ;YUP. IGNORE THE STRANGE CALL CMP (R1)+,(R1)+ ;ADVANCE R1 TST @R1 ;DID HE SHIP US A POSITIVE CODE? BPL RWXTE0 ;YUP. SHIP HIM BACK AN ERROR 0 MOVB #377,@R1 ;MAKE SURE THE 377 IS THERE MOV 2(R1),R2 ;R2 = COMPLETION FUNCTION JSR R4,TSWSPC ;DO COMMON STUFF BR SPREAD ;BRANCH TO SPECIAL READ ENTRY ; "I'M QUITE ILLITERATE, BUT I READ A LOT." ; - J.D. SALINGER, "THE CATCHER IN THE RYE" .ENABL LSB ; RCVD POINTS R3 TO THE PSEUDO MESSAGE CHANNEL IN THE IMPURE AREA, ; AND FALLS INTO THE NORMAL READ CODE. IF THE OTHER JOB ISN'T PRESENT, ; ERROR 0 IS GENERATED AS IF FROM A READ REQUEST. R$CVD: JSR PC,OTHRJB ;GET POINTER TO OTHER JOB BEQ 5$ ;IT DOESN'T EXIST MOV R5,R3 ADD #I.MSG,R3 R$EAD: MOV 4(R1),R2 ;R2 = COMPLETION FUNCTION JSR R4,TSWCNT ;DO SOME CHECKING NOP ;NON-FILE OR DIRECTORY. IGNORE FACT NOP ;IGNORE IF READ WAS SHORTENED SPREAD: MOV R4,@SP ;SET WORD COUNT FOR R0 1$: TST -(R1) ;FIX PTR TO ARG LIST BIT #HDERR$,@R3 ;HARD ERROR? BNE 6$ BIT #EOF$,@R3 ;END OF MEDIUM? BNE 4$ MOV R1,R5 ;POINT R5 TO ARG LIST MOV (R3),R2 ;ISOLATE ENTRY VALUE OF HANDLER BIC #177701,R2 ADD PC,R2 ;IN A PIC MANNER, MOV $ENTRY-.(R2),R2 ;POINT TO ENTRY POINT BEQ 2$ ;NO HANDLER! ZOUNDS, MAN! ADD C.SBLK(R3),R0 ;MAKE BLOCK ABSOLUTE. MOV C.DEVQ(R3),R1 ;UNIT # TO R1 CLRB R1 JSR PC,QMANGR ;QUEUE AN ENTRY BIT #HDERR$,(R3) ;HARDWARE GOOF? BNE 6$ RWXT: MOV #3,R2 ;3 ARGUMENTS TO CLEAN UP JMP EMTDON 2$: MONERR NODV ;NO DEVICE HANDLER BR RWXT 3$: TST (SP)+ ;PURGE STACK 4$: BIC #EOF$,(R3) ;CLEAR EOF BIT RWXTE0: 5$: EMTERR+0 BR RWXT 6$: BIC #HDERR$,(R3) ;CLEAR ERROR BIT EMTERR+1 BR RWXT 7$: TST (SP)+ 8$: EMTERR+2 BR RWXT .SBTTL SDAT, WRITE ; SDAT IS SIMILAR TO WRITE. R3 IS POINTED TO THE OTHER JOB'S ; CHANNEL AND THEN A WRITE IS EXECUTED ON THE MESSAGE ; PSEUDO CHANNEL. IF THE OTHER JOB IS NOT IN CORE, ; THE ERROR 0 RETURN IS TAKEN. S$DAT: JSR PC,OTHRJB BEQ 5$ ;NO RECEIVER PRESENT MOV R5,R3 ;R5 RETURNS POINTING TO THE ADD #I.MSG,R3 ;OTHER'S IMPURE AREA ; "THEIR MANNER OF WRITING IS VERY PECULIAR, BEING NEITHER FROM THE ; LEFT TO THE RIGHT, LIKE THE EUROPEANS; NOR FROM THE RIGHT TO THE ; LEFT, LIKE THE ARABIANS; FROM UP TO DOWN, LIKE THE CHINESE; NOR ; FROM DOWN TO UP, LIKE THE CASCAGIANS" ; - J. SWIFT, "GULLIVER'S TRAVELS" W$RITE: MOV 4(R1),R2 ;R2 = COMPLETION FUNCTION JSR R4,TSWCNT BR NFWRIT ;NON FILE OR DIRECTORY OP. EMTERR+0 ;GIVE ERROR IF SHORTENED, BUT DO IT CMP R5,C.USED(R3) ;CHECK FOR GOING OVER HIGHEST WRITTEN BLOS NFWRIT BIT #DWRIT$,@R3 ;ENTERED ? BEQ NFWRIT ;NO MOV R5,C.USED(R3) NFWRIT: MOV R4,@SP ;WORD COUNT FOR R0 NEG R4 ;MAKE IT A WRITE BR 1$ ;DO COMMON STUFF .SBTTL READ/WRITE COMMON ROUTINE ; "'SO IT DOES!' SAID POOH. 'IT GOES IN!' ; 'SO IT DOES!' SAID PIGLET. 'AND IT COMES OUT!' ; 'DOESN'T IT?' SAID EEYORE. ; -A.A. MILNE, "WINNIE THE POOH" ; TSWCNT DOES VALIDITY CHECKING FOR THE READ/WRITE EMTS. ; THE NUMBER OF CHANNELS IS CHECKED, AS WELL AS THE ; BUFFER TRANSFER ADDRESSES. R1 IS A POINTER TO THE ; ARGUMENTS FOR THE OPERATION. R3 IS THE CHANNEL AREA ; POINTER. IF THE STARTING BLOCK OF A CHANNEL ; IS 0, THE OPERATION IS EITHER NON-FILE STRUCTURED, OR ; A DIRECTORY OPERATION. IN EITHER CASE, THE OPERATION IS ; ALLOWED TO PROGRESS. TSWCNT: MOV (R1)+,@SP ;BUFFER ADDRESS TO OLD R4 ;(EMT DISPATCHER ALREADY CHECKED THIS) MOV (R1)+,-(SP) ;COMPUTE LAST WORD OF XFER BEQ 85$ ;DON'T MESS UP SEEK DEC @SP ;(NOT FIRST WORD AFTER IT) ASL @SP ;(WORD COUNT!) 85$: ADD (SP)+,@SP JSR R5,CHKSP ;VALIDITY OF END ADDRESS BR TSERR TSWSPC: CMP R2,#1 ;DOING COMPLETION IO? BLOS 9$ MOV R2,@SP ;YES. CHECK ADD. OF ROUTINE JSR R5,CHKSP BR TSERR ;BAD ADDRESS 9$: MOV -(R1),R5 ;WORD COUNT TO R5 MOV R5,@SP ;RETURN W.C. IN R4 MOV @R3,R2 ;GET DEVICE INDEX IN R2 BPL 7$ ;GT MEANS CHANNEL CLOSED! BIC #177701,R2 ;ISOLATE INDEX ADD PC,R2 ;PICLY, TST $STAT-.(R2) ; SEE IF FILE STRUCTURED DEVICE BPL TSWOUT ;NO. LET XFER GO. BIC #EOF$,@R3 ;CLEAR EOF BIT FOR FILE DEV. TST C.SBLK(R3) ;START BLOCK 0? BEQ TSWOUT ;YES. PROBABLE DIRECTORY OP. CMP (R4)+,(R4)+ ;BUMP TO LEGAL RETURN. MOV C.LENG(R3),R2 ;GET # OF BLOCKS IN FILE CMP R0,R2 ;IS R0 LEGAL BLOCK? BHIS 3$ ;NO. GIVE EOF ERROR. ADD #377,R5 ;CHANGE WORDS TO BLOCKS CLRB R5 SWAB R5 ADD R0,R5 ;WILL XFER REACH EOF? SUB R5,R2 BPL TSWOUT ;NO. IT ALL FITS. ADD R2,R5 MOV R5,(SP) ;GIVE BACK WHAT WE READ SUB R0,(SP) SWAB (SP) TST -(R4) ;BACK OFF TO SHORTENED RETURN TSWOUT: RTS R4 TSERR: TST (SP)+ MONERR ADDR ;GIVE ERROR BR RWXT ;AND ABORT OPERATION .DSABL LSB .SBTTL SAVESTATUS ,REOPEN, WAIT, MWAIT, CSTATUS, GTJB S$AVST: TST @R3 ;IS THIS CHANNEL OPEN? BPL 1$ ;NO. SAVE 'NOT OPEN' STATUS TSTB @R3 ;WAS AN 'ENTER'DONE? BMI E5ER1 ;YES. NO SAVESTATUS PERMITTED 1$: MOV @R3,(R0)+ ;CHANNEL STAT. WORD CLR (R3)+ ;DEACTIVATE CHANNEL. .REPT 4 ;FILL IN REMAINING DATA MOV (R3)+,(R0)+ .ENDR XCLOSE: JMP EMTRTI R$OPEN: TST @R3 ;CHANNEL CAN'T BE IN USE BMI E5ER0 ;AMAZING! REOPEN IS INVERSE OF SAVE! .REPT 5 ;REPLACE THE WORDS MOV (R0)+,(R3)+ .ENDR BR XCLOSE E5ER0: EMTERR+0 BR XCLOSE ; EMT12--WAIT ON I/O. THIS EMT RETURNS AN ERROR IF THE ; CHANNEL IS NOT ACTIVE, GIVING A WAY TO CHECK TO SEE IF ; A CHANNEL IS CURRENTLY IN USE. M$WAIT: MOV R5,R3 ;POINT TO MESSAGE CHANNEL ADD #I.MSG,R3 W$AIT: TST @R3 ;CHANNEL ACTIVE? BPL E5ER0 ;>0=> NO JSR PC,CHWAIT ;YES, SWAP OUT & WAIT BIT #HDERR$,@R3 ;WAS THERE AN ERROR? BEQ XCLOSE ;NO. RETURN TO USER BIC #HDERR$,@R3 ;YES. CLEAR HARD ERROR BIT E5ER1: EMTERR+1 BR XCLOSE ; GET JOB PARAMETERS OF RUNNING JOB ; RETURNS JOB NUMBER, HIGH LIMIT, LOW LIMIT G$TJB: MOV JOBNUM,R1 ;GET JOB NUMBER MOV R1,(R0)+ ;GIVE IT HIM ASL R1 ;DOUBLE FOR TABLE REFERENCE ADDR $JBLIM,R1,ADD ;POINT TO LIMIT TABLE MOV (R1)+,(R0)+ MOV (R1)+,(R0)+ MOV I.CSW(R5),(R0)+ ;START OF CHANNEL AREA BR XCLOSE ; CHANNEL STATUS ; RETURNS CSW, START BLOCK OF FILE, LENGTH, HIGHEST BLOCK WRITTEN, ; UNIT #, RAD50 OF ASSOCIATED DEVICE C$STAT: MOV @R3,R4 ;GET DEVICE INDEX BIC #^C<76>,R4 MOV (R3)+,(R0)+ ;CSW BPL E5ER0 ;ERROR, CHANNEL INACTIVE MOV (R3)+,(R0)+ MOV (R3)+,(R0)+ MOV (R3)+,(R0)+ MOV @R3,@R0 ;UNIT NUMBER CLRB @R0 SWAB (R0)+ ADD PC,R4 ;GET PIC DEVICE NAME MOV $PNAME-.(R4),(R0)+ BR XCLOSE .SBTTL ADDRESS CHECK, GET OTHER JOB NUMBER ;********************************************************************** ; CHKSP CHECKS THE ADDRESS ON THE STACK FOR VALIDITY ; THE CALLING SEQUENCE IS: ; TOP OF STACK = ADDR TO BE CHECKED ; JSR R5,CHKSP ; ERROR RETURN ; NORMAL RETURN ; THE ERROR RETURN IS TAKEN IF THE ADDRESS IS OUT OF BOUNDS OR ODD CHKSP: MOV R2,-(SP) ;PRESERVE R2 MOV 4(SP),-(SP) ;PUT ARG CLOSER. BEQ 1$ ;LET ADDRESS 0 ALONE BIT #USRRN$+CSIRN$+BATRN$+CMPLT$,@CNTXT ;IS USR RUNNING? BGT 1$ ;YES BIT #1,(SP) ;IS IT ODD? BNE 2$ MOV JOBNUM,R2 ;CHECK IT AGAINST LIMITS BNE 10$ ;NOT BG, CANNOT BE KMON TST KMONIN ;KMON DOING IT? BNE 1$ ;YES, ASSUME IT'S SMARTER THAN US 10$: ASL R2 ;$JBLIM IS 2 WORDS/ENTRY ADDR $JBLIM,R2,ADD ;R2 TO LIMIT CMP (SP),(R2)+ ;ABOVE UPPER LIMIT? BHIS 2$ CMP (SP),(R2) ;BELOW LOW LIMIT? BLO 2$ 1$: TST (R5)+ ;ADVANCE TO NON-ERROR RETURN 2$: TST (SP)+ ;REMOVE STACK THING MOV (SP)+,R2 ;RESTORE R2 RTS R5 ;********************************************************************** ; OTHRJB MUST BE CHANGED WHEN RT11 EXPANDS TO MORE THAN 2 JOBS ; IT ENABLES US TO GET THE IMPURE POINTER TO ; THE ONLY OTHER JOB THAT CAN BE IN THE SYSTEM. ; THE CALL IS: ; JSR R5,OTHRJB ; ERROR RETURN ;NO OTHER JOB AROUND ; NORMAL RETURN ; ON RETURN, R2 POINTS TO THE IMPURE AREA OF THE JOB. OTHRJB: MOV JOBNUM,R2 ;GET CURRENT JOB # NEG R2 ;OTHER JOB IS 4-THISJOB ADD PC,R2 ;GET OTHER IMPURE POINTER MOV $IMPUR+2-.(R2),R2 RTS PC ;RETURN ZERO CONDITION IF NO JOB .SBTTL SAVE 3-0 SAVE30: MOV R2,-(SP) ;SAVE REGS 3 - 0. CALLED BY JSR R3,SAVE30 MOV R1,-(SP) MOV R0,-(SP) JSR PC,@R3 ;CALL CALLER MOV (SP)+,R0 ;RESSTORE REGS MOV (SP)+,R1 MOV (SP)+,R2 MOV (SP)+,R3 RTS PC .SBTTL MESSAGE HANDLER ;************************************************** ; THIS IS THE MESSAGE HANDLER FOR RT11. IT IS ; SET UP TO LOOK LIKE A DEVICE HANDLER, AS THAT IS ; INDEED THE NEATEST WAY TO SEND MESSAGES IN ; THE SYSTEM. THE BASIC OPERATION IS AS FOLLOWS: ; ON ENTRY, IF THERE IS NO MATCHING OPERATION ; WAITING FOR THIS ENTRY, THE CURRENT OP IS ; STORED IN THE INTERNAL Q OF WAITING REQUESTS. ; IF A MATCHING OPERATION IS FOUND, THE MESSAGE TRANSFER ; IS MADE, AND THE Q ELEMENTS USED ARE FREED FOR ; USE AGAIN. .ENABL LSB .WORD 0,0 JBLQE: .WORD 0 ;LAST ENTRY IN QUEUE JBCQE: .WORD 0 ;CURRENT Q ENTRY MOV JBCQE,R3 ;PICK UP CURRENT ENTRY TST (R3)+ ;POINT TO UNIT # MOV (R3)+,R4 ;UNIT # INTO R4 TST (R3)+ ;POINT TO WORD COUNT SWAB R4 ASR R4 ;SHIFT TO GET JOB # ASR R4 ASR R4 BIC #177761,R4 ;ISOLATE JOB NUMBER MOV R4,-(R3) ;SAVE IN UNUSED SLOT IN Q ELEM. TST @R3 ;BUT CHANGE QUEUES ON A WRITE BPL 1$ NEG R4 ;CHANGE 2 TO 0, 0 TO 2 ADD #2,R4 1$: ADDR JBQ,R4,ADD ;POINT R4 TO INTERNAL LIST HEADERS MOV @R4,R0 ;POINTER TO WAITING ELEMENT TO R0 BEQ 25$ ;NONE THERE. STORE ONE MOV @R0,R1 ;WHAT IS WAITING OPERATION? BPL 15$ ; >0 => RCVD WAITING. WE NEED A ;SDAT TO COMPLETE. CHECK FOR ONE. MOV @R3,R1 ;SDAT WAITING. IS THIS RCVD? BMI 20$ ;NO. ANOTHER SDAT. BEQ 10$ ;DON'T MESS WITH SEEKS! MOV -(R3),R2 ;R1=WD COUNT. R2=ADD TO READ TO MOV @R0,@R2 ;AMOUNT SENT IN SDAT MOV -(R0),R0 ;R0=BUFF TO WRITE FROM ;R2=BUFF TO READ TO ;R1=WORD COUNT TO XFER 3$: NEG (R2)+ ;RETURN AMOUNT SENT IN FIRST ;WORD OF THE BUFFER OF RECEIVER 5$: MOV (R0)+,(R2)+ DEC R1 BNE 5$ MOV @R4,R0 ;REMOVE ELEMENT FROM OUR LIST SUB #12,R0 ;POINT R0 TO START OF Q ELT TO FREE MOV @R0,@R4 ;ADVANCE INTERNAL QUEUE CLR (R0)+ ;CLEAR LINK IN ELEMENT SO WE DON'T REENTER TST (R0)+ ;NOW R0 -> 3RD WORD OF ELT (NORMAL CQE) ADDR JBCQE,R4 ;FREE THE SAVED ONE FIRST MOV (R4),-(SP) MOV R0,(R4) CLR -4(R0) ;AND CLEAR THIS LINK WORD (SHOULD BE 0) JSR PC,COMPLT ;THIS FREES THE ENTRY MOV (SP)+,JBCQE ;NOW FREE THE CURRENT ONE 10$: ADDR JBCQE,R4 JMP COMPLT ;FREE THIS ELEMENT 15$: BEQ 10$ ;0 WORDS TO TRANSFER TST @R3 ;RCVD WAITING. THIS A SDAT? BPL 20$ ;ANOTHER RCVD. STORE IT MOV -(R0),R2 ;RECEIVER'S BUFFER MOV @R3,@R2 ;RETURN THE AMOUNT SENT MOV -(R3),R0 ;SENDER'S BUFFER BR 3$ ;DO COMMON STUFF 19$: MOV R1,R0 ;LOOK AT NEXT ELEMENT 20$: SUB #12,R0 ;BACK UP TO REAL LINK WORD MOV @R0,R1 ;LINK FORWARD TO END OF QUEUE BNE 19$ ;KEEP GOING MOV R3,@R0 ;END. LINK LAST ELEMENT TO US ;TO THE WAITING WORD COUNT 22$: CLR -12(R3) ;ZERO LAST LINK WORD CLR JBLQE CLR JBCQE JBRTS: RTS PC ;1/2 DONE. WAIT FOR A CONNECTION 25$: MOV R3,@R4 ;STORE THE FIRST ELEMENT BR 22$ ; THIS ROUTINE IS CALLED FROM IORSET. IT FLUSHES ALL ; QUEUE ELEMENTS THAT MAY BE SITTING IN THE MESSAGE ; PROCESSORS INTERNAL QUEUE. JBABRT: MOV CNTXT,R0 ;R0 -> IMPURE AREA JSR R3,24$ ;SAVE R3, POINT TO JBQ JBQ: .WORD 0,0,-1 ;THIRD WORD IS STOPPER 24$: MOV R3,R1 ;R1 -> LAST LINK MOV (R3)+,R2 ;R2 -> FIRST ELEM BEQ 24$ ;BR IF IT EXISTS CMP R2,#-1 ;END OF TABLE? BNE 26$ ;NO, SEARCH THE QUEUE TST (SP)+ ;ELSE WE'RE DONE. RTS PC 26$: SUB #12,R2 ;ADJUST R2 -> TOP OF ELEM. CMP Q.BLKN(R2),JOBNUM ;ORIGINATED BY ABORTED JOB? BNE 27$ ;BR IF NOT CORRECT JOB # DEC I.IOCT(R0) ;DECREMENT PENDING I/O COUNT MOV @R2,@R1 ;AND LINK AROUND IT BEQ 24$ ;BR IF END OF THIS Q MOV @R2,R2 ;R2 -> NEXT ELEMENT BR 26$ 27$: MOV R2,R1 ;CHECK NEXT ELEM MOV @R2,R2 ;R2 -> NEXT ELEM, R1 -> PREV. BEQ 24$ ;BR IF END OF Q BR 26$ .DSABL LSB .SBTTL SYSTEM I/O HANDLER ; ALL IO REQUESTS FOR A PARTICULAR DEVICE ARE PUT INTO A QUEUE, ; AND THE INDIVIDUAL DEVICE DRIVERS TAKE THEIR JOBS FROM THAT QUEUE ; THE ENTRY POINT FOR MONITOR IO REQUESTS IS $SYS. ; THIS ENTRY SAVES ALL REGISTERS, AND CALLS THE Q MANAGER $SYSSW: MOV $SWPBL,R0 ;ENTER HERE TO DO I/O TO SWAP BLOCKS $SYS: JSR R3,SAVE30 ;SAVE REGISTERS ADD #$SYSCH-.,R3 ;POINT TO SYSTEM CHANNEL MOV R4,-(SP) MOV R5,-(SP) MOV SYUNIT,R1 ;UNIT # OF SYS. MOV (PC)+,R2 ;LAST Q ENTRY FOR SYS SYENTR: .WORD 0 SYENTO = SYENTR - $RMON ;COMPUTE OFFSET FOR BOOTSTRAP MOV 2(R5),R4 ;WORD COUNT IN R4 JSR PC,QMANGR ;Q A REQUEST MOV (SP)+,R5 ;RESTORE REGS MOV (SP)+,R4 ROR $SYSCH ;SEE IF ERROR IS ON RTS PC .SBTTL QUEUE MANAGER ; THE Q MANAGER IS ENTERED WHEN AN IO REQUEST IS TO BE PUT IN ; THE Q. ; CALLING SEQUENCE: ; JSR PC,QMANGR ; REGISTERS: ; 0 BLOCK # TO READ/WRITE ; 1 UNIT NUMBER IN LOW BITS OF ODD BYTE ; 2 POINTS TO 4TH WORD OF HANDLER ; 3 POINTER TO CHANNEL STATUS WORD ; 4 WORD COUNT ; 5 POINTER TO ARGUMENT LIST .ENABL LSB QMANGR: MOV R4,-(SP) ;SAVE REGS MOV R1,-(SP) MOV CNTXT,R1 ;POINT TO IMPURE AREA TST (R1)+ ;R1 -> HEAD OF AVAIL QUEUE QGTELT: SPL 7 ;GET Q ELT AT PRIORITY 7 MOV @R1,R4 ;* POINT TO AN ELEMENT BEQ QFULL ;* NO ELEMENTS THERE MOV @R4,@R1 ;* ADVANCE QUEUE SPL 0 ;* AND REENABLE INTERRUPTS INC I.IOCT-2(R1) ;INCREMENT # OF REQUESTS CLR (R4)+ ;CLEAR LINK WORD MOV R3,(R4)+ ;FILL IN PTR TO CSW INCB 10(R3) ;BUMP CHANNEL REQUEST COUNTER MOV R0,(R4)+ ;BLOCK # MOV (SP)+,@R4 ;UNIT # CLRB @R4 ;CLEAN OUT LOW BYTE MOV JOBNUM,R0 ;GET JOB # SWAB R0 ;PUT IT IN THE RIGHT BITS ASL R0 ASL R0 ASL R0 BIS R0,(R4)+ ;OR IN THE JOB NUMBER MOV (R5)+,(R4)+ ;BUFFER ADDRESS MOV (SP)+,(R4)+ ;WORD COUNT TST (R5)+ ;(SKIP R5 OVER W.C.) MOV (R5)+,@R4 ;COMPLETION CMPB @R4,#377 ;SPECIAL FUNCTION FOR MT/CT? BNE 1$ ;NO MOVB 1(R4),Q.FUNC-Q.COMP(R4) ;YES, PUT IN FUNCTION BYTE MOV (R5)+,@R4 ;AND PUT IN REAL COMPLETION FUNCTION 1$: ADD #Q.BLKN-Q.COMP,R4 ;FIX R4 TO POINT TO PROPER WORD MOV R3,-(SP) ;SAVE CSW POINTER ENSYS 10$ ;ENTER SYSTEM STATE MOV R2,R1 ;COPY HANDLER POINTER BIS #100000,-(R1) ;HOLD THE HANDLER TST (R2)+ ;IS LQE = 0? BNE 2$ ;NO, THE HANDLER IS ACTIVE CLR (R1)+ ;YES. UNHOLD THE HANDLER MOV R4,(R1)+ ;SET LQE MOV R4,(R1)+ ;SET CQE JMP @R1 ;GO TO HANDLER, IT RETURNS FOR US 2$: MOV @R2,R5 ;R5 -> NEXT ELEMENT 3$: MOV R5,R2 ;COPY POINTER CMP -(R2),-(R2) ;BACK UP R2 TO LINK WORD MOV @R2,R5 ;R5 -> NEXT ELEMENT BEQ 4$ ;END OF Q. PUT IT HERE CMP 2(R5),R0 ;ELT. JOB # : THIS JOB # ;DV8 BHIS 3$ ;ELT >= THIS, KEEP CHAINING 4$: MOV R5,-4(R4) ;LINK WORD TO THIS ELEMENT MOV R4,@R2 ;LINK PREV ELEMENT TO THIS ONE ASL @R1 ;DID HANDLER COMPLETE WHILE HELD? BPL 20$ ;NO, SAY GOODBYE CLR (R1)+ ;UNHOLD HANDLER TST (R1)+ ;ADVANCE R1 -> HANDLER CQE WORD BR CMPLT2 ;ENTER COMPLETION, WHICH RETURNS 10$: MOV (SP)+,R3 ;BACK IN USER STATE. RETRIEVE CSW PTR TST -(R5) ;WAIT FOR COMPLETION? BNE 20$ ;NO, RETURN CHWAIT: MOV CNTXT,R1 ;WE MUST WAIT. POINT TO IMPURE AREA MOV R3,I.CHWT(R1) ;SAVE POINTER TO CHANNEL BEING AWAITED JSR R4,$SYSWT ;ENTER SYSTEM STATE & WAIT .WORD CHNWT$ ;WITH THIS BLOCKING BIT MOVB 10(R3),R2 ;; COROUTINE DETERMINES IF BLOCKED NEGB R2 ;; SET CARRY IF <>0, ELSE CLEAR IT JSR PC,@(SP)+ ;; COROUTINE RETURN 20$: RTS PC QFULL: SPL 0 ;* NO ROOM. BACK TO LEVEL 0 USWAPO: ENSYS QGTELT ;ENTER SYSTEM STATE FOR WAITING MOV JOBNUM,R5 ;GET GUY'S JOB NUMBER (NOTE R5 SCR) BEQ 11$ ;THERE IS NO JOB # -2 TST -(R5) ;START SCHEDULING BELOW HIM! 11$: JMP $RQSIG ;ENTER SCHEDULE REQUEST AT SIG-EVENT ;NOTE THAT HE WILL RETURN TO THE ;LEVEL 0 INTERRUPT EXIT FOR US .DSABL LSB .SBTTL QUEUE COMPLETION ; WHEN A DEVICE TRANSFER COMPLETES, THE HANDLER TRANSFERS TO ; COMPLT, TO START A NEW REQUEST ; IF A COMPLETION ROUTINE IS ASSOCIATED WITH THE REQUEST, ; IT IS PLACED ON THE USER'S COMPLETION QUEUE AND, IF HE IS ; CURRENTLY AT NON-COMPLETION LEVEL, A TASK SWITCH FOR HIM IS ; REQUESTED. ; THE I/O COUNT FOR THE CHANNEL IS DECREMENTED, AND IF THE ; USER IS WAITING FOR THAT CHANNEL, HE IS UNBLOCKED FROM THE WAIT ; ENTER WITH R5 AND R4 ON STACK. R4 POINTS TO THE LOCATION ; IN THE HANDLER WHICH POINTS TO THE CURRENT Q ENTRY BEING ; PROCESSED. .ENABL LSB COMPLT: ASR -4(R4) ;IS HANDLER BEING HELD? BMI 7$ ;YES. FLAG IS ON, JUST RETURN JSR R3,SAVE30 ;NO. SAVE REGS 3-0 MOV R4,R1 ;R1 -> HANDLER CQE CMPLT2: MOV @R1,R4 ;R4 -> Q ELEMENT MOV -(R4),R3 ;R3 -> CHANNEL MOVB Q.JNUM-Q.CSW(R4),R5 ;GET JOB NUMBER OF OWNER ASR R5 ;EXTRACT JOB NUMBER ASR R5 ASR R5 BIC #177761,R5 ADD PC,R5 ;R5 -> HIS IMPURE AREA MOV $IMPUR-.(R5),R5 ; (PIC, OF COURSE) DECB 10(R3) ;DECREASE PENDING REQUESTS ON CHANNEL BNE 1$ ;IS CHANNEL FREE? CMP R3,I.CHWT(R5) ;IS HE WAITING FOR THIS ONE? BNE 1$ ;NO JSR R4,UNBLOK ;YES. UNBLOCK HIM IF NEED BE .WORD CHNWT$ 1$: DEC I.IOCT(R5) ;DECREASE # OF OUTSTANDING REQUESTS BNE 2$ ;NOT 0 JSR R4,UNBLOK ;NONE LEFT. LET HIM RUN IF WAITING FOR .WORD EXIT$ ; ALL I/O TO COMPLETE 2$: MOV -(R4),(R1)+ ;LINK DEVICE Q FORWARD (NOTE - NOT RUNNING) BEQ 3$ ;NOTHING LEFT ON DEVICE MOV R1,-(SP) ;SET ADDRESS TO CALL HANDLER BR 4$ ;MERGE 3$: MOV -(R1),-(R1) ;CLEAR OUT LQE FLAG 4$: CMP Q.COMP(R4),#1 ;COMPLETION? BLOS AQLINK ;NO, GO LINK INTO AVAIL QUEUE MOV @R3,Q.BUFF(R4) ;SAVE CHANNEL STATUS IN BUFFER PTR SUB I.CSW(R5),R3 ;MAKE R3 A CHANNEL OFFSET MOV R3,Q.WCNT(R4) ;SAVE CHANNEL OFFSET IN WORD COUNT WORD TST (R5)+ ;ADVANCE POINTER MOV R5,R2 ;SAVE R5 MOV I.JNUM-2(R5),R5 ;GET JOB NUMBER JSR PC,$RQTSW ;ASK THAT HE BE ELIGIBLE MOV R2,R5 ;RESTORE R5 BIS #CPEND$,-(R2) ;INDICATE COMPLETION PENDING CQLINK: TST (R5)+ ;ADVANCE R5 TO COMPLETION LAST ELT. CLR @R4 ;CLEAR LINK WORD IN ELEMENT JSR PC,GETPSW ;PS TO STACK ;DV15 SPL 7 ;UP ... MOV (R5)+,R0 ;* R0 -> LAST ELEMENT IN COMPL. Q BNE 5$ ;* (IF THERE IS ONE) MOV R5,R0 ;* SET R0 TO PLUG CQE = LQE 5$: MOV R4,@R0 ;* POINT LAST ELEMENT AT THIS ONE 6$: MOV R4,-(R5) ;* MAKE THIS THE LAST ELEMENT JSR PC,$MTPS ;* BACK TO PRIORITY N ;DV15 7$: RTS PC ;RETURN FROM INTERRUPT, MAYBE TO HANDLER AQLINK: TST (R5)+ ;BUMP R5 TO AVAIL QUEUE JSR PC,GETPSW ;PS TO STACK ;DV15 SPL 7 ;UPPPPP MOV (R5)+,@R4 ;* THIS ELEMENT'S LINK -> FORMER AVAIL BR 6$ ;* GO POINT AVAIL TO US $SYNCH: TST Q.COMP(R4) ;IS THIS NODE IN USE? BNE 20$ ;YES, ERROR HIM CMP (R5)+,(SP)+ ;POP TO GOOD RETURN, PRUNE STACK MOV R5,Q.COMP(R4) ;SAVE SYNCH ADDRESS IN NODE MOV #-1,Q.WCNT(R4) ;PLUG TO AVOID LINKING TO AVAIL Q LATER MOV 2(R4),R5 ;GET JOB NUMBER IN R5 BIT #177775,R5 ;IS IT 0 OR 2? BNE 7$ ;NO, JUST EXIT QUIETLY JSR PC,$RQTSW ;YES. REQUEST A TASK SWITCH FOR THE GUY ADD PC,R5 ;IN A PIC-Y WAY MOV $IMPUR-.(R5),R5 ;POINT TO NEW IMPURE AREA BEQ 7$ ;NO SUCH JOB. BOOT BIT #NORUN$,@R5 ;IS JOB DEAD? BNE 7$ ;YES, BAD BIS #CPEND$,@R5 ;NO. A COMPLETION ROUTINE IS HERE ADD #I.CMPL,R5 ;POINT TO HEAD OF QUEUE JSR PC,GETPSW ;PS TO STACK ;DV15 SPL 7 ;UPWARDS MOV (R5)+,@R4 ;PUT TOP C ELEMENT IN THIS LINK BNE 6$ ;TOP ELT EXISTS. MAKE THIS THE TOP MOV R4,-(R5) ;C. QUEUE EMPTY. MAKE THIS THE TOP BR 6$ ;AND GO MAKE IT THE LQE, TOO. 20$: RTS R5 ;RETURN IF SYNCH NODE IN USE. .DSABL LSB .SBTTL GET TIME OF DAY, CANCEL MARK TIME ; "PERFECTION IN A CLOCK DOES NOT CONSIST IN BEING FAST, ; BUT IN BEING ON TIME." - VAUVENARGUES, "REFLEXIONS" ; GET TIME OF DAY .ENABL LSB G$TIM: ENSYS EMTRTI 11$: ADDR $TIME+2,R1 ;R1 -> TIME ADDITIVE MOV PSCLKH,(R0)+ ;MOVE IN HIGH PSEUDO TIME MOV PSCLOK,@R0 ;MOVE IN LOW ORDER TIME ADD @R1,@R0 ;ADD IN THING TO MAKE IT TIME OF DAY ADC -(R0) ;PROPAGANDA CARRY ADD -(R1),@R0 ;AND SO ON ... CMP (R0)+,(PC)+ ;CHECK FOR MIDNIGHT TURNOVER GTM.HI: .WORD 117 ;INITIALLY ASSUME 60 CYCLE BLO 6$ ;NOT YET BHI 12$ ;EGAD, 2 DAYS GONE BY CMP @R0,#15000 ;MIDNIGHT YET? BLO 6$ ;NO 12$: SUB GTM.HI,(R1)+ ;ADJUST TIME WORDS SUB (PC)+,@R1 GTM.LO: .WORD 15000 SBC -(R1) ADD #40,$DATE ;FIX TODAY TST -(R0) ;ADJUST HIS POINTER BR 11$ ;TRY AGAIN ; CANCEL MARK TIME: TAKES AN IDENTIFYING NUMBER AND CANCELS ; THE FIRST MARK TIME ELEMENT FOR THAT JOB WHICH HAS THAT NUMBER. ; IF A TWO WORD AREA IS ALSO GIVEN, THE AMOUNT OF TIME REMAINING ; IS RETURNED IN THAT AREA C$MKT: ENSYS EMTRTI ;DO IT IN SYS STATE TO STOP CLOCK MOV #177377,SYSLIM ;SET SYSTEM ID LIMIT ;DV16 CMARKT: ADDR LKQUE+2,R4 ;POINT TO QUEUE HEADER 1$: MOV R4,R3 ;R3 -> PREV LINK WORD + 2 2$: MOV -(R3),R4 ;R4 -> NEXT ELEMENT BEQ 5$ ;END OF QUEUE ADD #C.JNUM,R4 ;POINT TO JOB NUMBER WORD CMP JOBNUM,@R4 ;IS ELEMENT FOR THIS JOB? BNE 1$ ;NO, SKIP IT TST R0 ;ARE WE CANCELING EVERYTHING? ;DV16 BNE 3$ ;NO ;DV16 CMP 2(R4),(PC)+ ;YES, THIS ONE A SYSTEM ELEM.? ;DV16 SYSLIM: .WORD 177777 ;HIGHEST ID TO CANCEL ;DV16 BLOS 20$ ;NO, DELETE IT ;DV16 ;NOTE: SINCE R0 = 0, CMP BELOW FAILS AND BRANCH GOES TO 1$ ;DV16 3$: CMP R0,2(R4) ;NO. IS THIS THE RIGHT IDENTIFIER? ;DV16 BNE 1$ ;NO. TRY AGAIN 20$: MOV -(R4),(R3)+ ;PUT OUR LINK INTO PREV. LINK WORD ;DV16 MOV -(R4),R2 ;R2 = LOW ORDER EXPIRATION TIME TST -(R4) ;POINT TO HIGH ORDER TOX TST R0 ;CANCELING ALL? BEQ 4$ ;YES. NO RETURN STUFF MOV @R1,R5 ;R5 -> AREA TO PUT ANSWER BEQ 4$ ;NONE. SUB PSCLOK,R2 ;CONVERT TOX TO TIME REMAINING MOV @R4,@R5 ;MOVE IN HIGH ORDER TIME REMAINING SBC (R5)+ MOV R2,@R5 ;MOVE IN LOW ORDER 4$: MOV CNTXT,R5 ;POINT TO IMPURE AREA JSR PC,AQLINK ;PLACE ELEMENT ON HIS AVAIL QUEUE TST R0 ;CANCELING ALL? BEQ 2$ ;YES, KEEP TRUCKING RTS PC ;NO. WE SUCCEEDED 5$: TST R0 ;RAN OFF END. CANCELING ALL? BEQ 6$ ;YES, THAT IS SUCCESS SYSER0: MOV TASKSP,R0 ;NO. WE COULDN'T FIND ONE WITH THAT ID. INC <1+6+4>*2(R0) ;SET C ABOVE PC+6 REGS+FAKE INTERRUPT 6$: RTS PC ;BACK! .DSABL LSB .SBTTL PROTECT VECTORS, COPY OTHER JOB'S CHANNEL .ENABL LSB P$ROTE: CMP #500,R0 ;ADDRESS MUST BE <500 AND =0 MOD 4 BLOS 2$ ;NO, GIVE ERROR 1 ASR R0 ;GET WORD PAIR INDEX BCS 2$ ;ADDRESS NOT =0 MOD 4 ASR R0 BCS 2$ ;ADDRESS NOT =0 MOD 4 MOV R0,R1 ;GET SHIFT COUNT BIC #177774,R1 ;0-3 MOV #3*400,R2 ;MASK IN R2 1$: ASR R2 ;SHIFT MASK ASR R2 DEC R1 ;RIGHT YET? BPL 1$ ASR R0 ;CONVERT TO BYTE NUMBER ASR R0 ADD R0,R5 ;OFFSET THE IMPURE PTR MOV R5,R3 ;COPY POINTER ADDR LOWMAP,R0,ADD ;POINT TO PERM MAP BYTE ENSYS EMTRTI BITB R2,@R0 ;ARE THOSE LOCATIONS ALREADY PROTECTED? BNE SYSER0 ;YES, GIVE ERROR 0 BISB R2,@R0 ;NO, PROTECT THEM BISB R2,I.BITM(R3) RTS PC ;GET OUT OF SYSTEM STATE 2$: EMTERR+1 ;GIVE ERROR 1 JMP EMTRTI ;GET OUT OF EMT C$PYCH: TST @R3 ;IS THIS JOB'S CHANNEL ACTIVE? BMI 2$ ;YES. GIVE ERROR 1 ENSYS EMTRTI JSR PC,OTHRJB ;GET POINTER TO OTHER JOB'S IMPURE BEQ SYSER0 ;NO SUCH JOB. ERROR 0 BIC #177400,R0 ;ISOLATE OTHER GUY'S CHANNEL NO. CMPB I.CNUM(R2),R0 ;DOES OTHER JOB HAVE ENOUGH CHANNELS? BLOS SYSER0 ;NAY MOV R0,R1 ASL R0 ;CHANNEL * 2 ASL R0 ;* 4 ADD R1,R0 ;* 5 ASL R0 ;* 10. ADD I.CSW(R2),R0 ;POINT TO THE CHANNEL MOV (R0)+,R1 ;SAVE FIRST WORD BPL SYSER0 ;ERROR, CHANNEL NOT ACTIVE MOV R1,@R3 ;COPY CSW BIC #DWRIT$+RENAM$,(R3)+ ;WE NO GOTTA REWRITE ON CLOSE MOV (R0)+,(R3)+ ;START BLOCK MOV (R0)+,(R3)+ ;HOLE SIZE MOV (R0)+,(R3)+ ;DATA SIZE TSTB R1 ;WAS THIS FILE ENTERED? BPL 3$ ;IF 0, LOOKED UP MOV -(R3),-(R3) ;CHANGE HOLE SIZE TO MAX SIZE USED BIC (R3)+,(R3)+ ;FIX R3, AND IT'S LIKE A LOOKUP! 3$: MOV (R0)+,@R3 ;UNIT # CLRB @R3 ;CLEAR I/O COUNT BYTE ;DV21 RTS PC .DSABL LSB .SBTTL FLOATING POINT INTERRUPT FPPINT: MOV #100000,(PC)+ ;SET FLAG SAYING INTERRUPT FPPFLG: 0 CMPB 2(SP),#PR7 ;DID WE INTERRUPT THE SYSTEM? BHIS EXRTI ;YES. OUT FAST MOVB 2(SP),1$ ;NO. GO DOWN APPROPRIATELY COMB 1$ JSR R5,$INTEN ;ENTER SYSTEM STATE 1$: 0 RTS PC ;AND PROCESS ERROR LATER .SBTTL CLOCK INTERRUPT HANDLER ; "THE TIME IS OUT OF JOINT; O CURSED SPITE, ; THAT EVER I WAS BORN TO SET IT RIGHT." - SHAKESPEARE ; "HAMLET" ; "TEMPORA LABUNTUR" - OVID .ENABL LSB LKINT: INC (PC)+ ;* BUMP CLOCK TICKER TIKCTR: 0 INC INTLVL ;* DID WE INTERRUPT THE USER? BGT EXINT ;* NO. GET OUT FAST AT LEVEL 7 MOV R5,-(SP) ;* PUSH R5 ONTO HIS STACK MOV SP,R5 ;* SAVE THE SP MOV RMONSP,SP ;* SWITCH TO MONITOR STACK SPL 0 ;* AND DOWN TO LEVEL 0 FAST MOV R4,-(R5) ;NOW CALMLY SAVE HIS R4 MOV R5,TASKSP ;AND HIS STACK POINTER MOV TIKCTR,R5 ;GET NUMBER OF ELAPSED TICKS TIMER: SUB R5,TIKCTR ;FIX UP NUMBER OF TICKS ; (WE MAY HAVE TICKED BETWEEN MOV & SUB) ADD R5,(PC)+ ;UPDATE SYSTEM PSEUDO-CLOCK PSCLOK: 0 1$: MOV (PC)+,R4 ;POINT TO CLOCK QUEUE LKQUE: 0 BCS 4$ ;DIFFERENT ROUTINE IF PSCLOCK OVERFLOW BEQ EXUSER ;OUT IF QUEUE EMPTY TST (R4)+ ;IS HIGH ORDER EXP. TIME = 0? BNE EXUSER ;NO. IT CANNOT EXPIRE CMP PSCLOK,(R4)+ ;IS PSEUDO CLOCK < EXP. TIME? BLO EXUSER ;NO. NOT EXPIRED 2$: ROR -(SP) ;SAVE CARRY MOV (R4)+,LKQUE ;LINK QUEUE FORWARD MOV @R4,R5 ;R5 = JOB NUMBER JSR PC,$RQTSW ;ASK FOR A SWITCH FOR HIM ADD PC,R5 MOV $IMPUR-.(R5),R5 ;POINT TO HIS IMPURE AREA BIS #CPEND$,(R5)+ ;SET COMPLETION PENDING SUB #C.JNUM,R4 ;POINT TO BEGINNING OF ELEMENT MOV R0,-(SP) ;SAVE R0 JSR PC,CQLINK ;LINK IT ONTO COMPLETION Q MOV (SP)+,R0 ROL (SP)+ ;RESTORE CARRY BR 1$ ;START WITH TOP OF Q AGAIN 3$: SUB #1,(R4)+ ;NORMALIZE Q ELEMENT, SET C IF EXPIRED BIT (R4)+,R0 ;ADVANCE POINTER OVER LOW TIME BCS 2$ ;IF CARRY ON, EXPIRED. GO DISPATCH MOV @R4,R4 ;ELSE LINK TO NEXT ELEMENT 4$: BNE 3$ ;IF ANY INC (PC)+ ;BUMP HIGH ORDER PSEUDO CLOCK PSCLKH: 0 CLC ;DONE NORMALIZING QUEUE BR 1$ ;LOOK FOR EXPIRED ELEMENTS .DSABL LSB .SBTTL COMMON INTERRUPT ENTRY AND EXIT ; "LIFE IS MADE UP OF INTERRUPTIONS." - W.S. GILBERT, "PATIENCE" ; "FOR SLEEP, HEALTH, AND WEALTH TO BE TRULY ENJOYED, THEY MUST ; BE INTERRUPTED." - J.P. RICHTER, "FLOWER, FRUIT, AND THORN PIECES" ; EVERY HANDLER AND EVERY INTERRUPT-LEVEL ROUTINE MUST CALL THE ; COMMON ENTRY CODE AT $INTEN. ; IF A HANDLER ASKS FOR A TASK SWITCH, THIS SWITCH WILL BE DEFERRED ; UNTIL WE ARE ABOUT TO RETURN TO THE USER. THIS KEEPS THE STACK FROM ; GETTING MESSED UP. FURTHERMORE, ALL INTERRUPT LEVEL CODE RUNS ; ON THE SYSTEM STACK. ; THE CALL IS OF THE FORM: ; MOV @#SYSPTR,-(SP) ; JSR R5,@(SP)+ (OR JSR R5,$INTEN INTERNALLY) ; (HANDLERS ARE GIVEN A POINTER TO $INTEN WHEN FETCHED) ; .WORD ^C&340 .ENABL LSB ; THE MONITOR CALLS $ENSYS TO ENTER SYSTEM STATE TO MANIPULATE ; THE TIMER QUEUE OR TO CHANGE CONTEXT, ETC. ; THE CALL IS: ; JSR R5,$ENSYS ; .WORD
-. ; .WORD PR7 ; THE ROUTINE FOLLOWING THE CALL IS EXECUTED IN SYSTEM STATE. ; IT MUST RETURN VIA AN RTS PC. $ENSYS: MOV R5,-(SP) ;SAVE USER RETURN ADDRESS ADD (R5)+,@SP ;FUDGE IT TO RETURN WHERE HE WANTS MOV 2(SP),-(SP) ;SAVE REAL R5 JSR PC,GETPSW ;GET THE PS ;DV15 MOV (SP)+,4(SP) ;SAVE PS IN PLACE ;DV15 SPL 7 ;ENTER HERE TO SWITCH INTO SYSTEM STATE $INTEN: MOV R4,-(SP) ;* SAVE R4 INC (PC)+ ;* BUMP LEVEL POINTER INTLVL: .WORD -1 BGT 1$ ;* GO IF ALREADY SWITCHED STACKS MOV SP,(PC)+ ;* SAVE USER'S STACK PTR TASKSP: 0 MOV (PC)+,SP ;* SWITCH TO SYSTEM STATE RMONSP: RMSTAK ;* *** BOOT *** ; THE FOLLOWING TWO INSTRUCTIONS ARE MODIFIED BY THE BOOT IF THE ; PROCESSOR IS FOUND TO BE AN LSI11. THE INSTRUCTION SEQUENCE BECOMES: ; ; MFPS R4 ; BIC (R5)+,R4 ; MTPS R4 ; 1$: MOV R4,-(SP) ;PRESERVE R4 ;DV15 MOV #PS,R4 ;R4 -> PS ;DV15 BIC (R5)+,@R4 ;* DOWN TO HANDLER PRIORITY ;DV15 MOV (SP)+,R4 ;RESTORE R4 (FOR $ENSYS ENTRY) ;DV15 JSR PC,@R5 ;CALL HANDLER BACK (HE WILL RTS BACK) ; AND NOW, WE PROCESS A RETURN FROM INTERRUPT LEVEL TST INTLVL ;TO WHERE ARE WE ABOUT TO RETURN? BNE RTICMN ;EXIT FROM SYSTEM IS EASY EXUSER: MOV TIKCTR,R5 ;ANY TIME GONE BY? BNE TIMER ;YES. PROCESS TIMER QUEUE ASL FPPFLG ;HATH HE A PENDANT FPP INTERRUPT? BCS 3$ ;YES. FORCE TO HIM AN INTERRUPT 2$: SPL 7 ;TO THE USER! MOV (PC)+,R4 ;* IS THERE ANY ACTION TO DO? INTACT: 0 BNE EXSWAP ;* YES. GO DO IT MOV TASKSP,SP ;* NO. SWITCH TO HIS STACK RTICMN: MOV (SP)+,R4 ;* RESTORE REGS MOV (SP)+,R5 EXINT: DEC INTLVL ;* FIX LEVEL EXRTI: RTI ;* AND RETURN TO HIM 3$: MOV TASKSP,R4 ;PUT AN FPP INTERRUPT ON HIS STACK MOV (R4)+,-(SP) ;SAVE HIS OLD R4/R5 MOV (R4)+,-(SP) BIT #HWFPU$,CONFIG ;DOES THE HARDWARE HAVE AN FPU? BEQ 4$ ;NO STST -(R4) ;YES. SAVE STATUS 4$: CLR -(R4) ;FAKE PS MOV CNTXT,R5 ;POINT TO USER'S IMPURE MOV I.FPP(R5),-(R4) ;SET TO RETURN TO HIS FPU ROUTINE CMP #1,@R4 ;GOT HE ANY? BLO 5$ ;YAH ADDR FPPERR,@R4 ;NO, USE OURS 5$: MOV #1,I.FPP(R5) ;AVOID RECURSION MOV (SP)+,-(R4) ;RESTORE HIS R4/R5 MOV (SP)+,-(R4) MOV R4,TASKSP ;RESET SP BR 2$ .DSABL LSB .SBTTL EXIT TO USER ; "IT IS ALWAYS THOSE WHO ARE READY WHO SUFFER IN DELAYS." ; - DANTE, "THE DIVINE COMEDY" ; HERE WE ARE ABOUT TO EXIT TO THE USER ; WE MUST SEE IF A TASK SWITCH HAS BEEN REQUESTED, OR IF AN ABORT ; IS IN PROGRESS. .ENABL LSB EXSWAP: BMI ABORT ;* DO AN ABORT CLR INTACT ;* DO A TASK SWITCH. CLEAR ACTION FLAG SPL 0 ;* ANY NEW REQUESTS ARE CAUGHT LATER INC R4 ;ADD 2 TO START SEARCH ASLB R4 ;MAKE IT A TRUE JOB NUMBER MOV R4,JOBNUM ;KEEP IT ; NOTE: A RACE CONDITION CANNOT DEVELOP HERE, SINCE AN ASYNCHRONOUS ; REQUEST FOR A SWITCH TO JOB 'JOBNUM' OR HIGHER WILL BE HONORED, ; AND ANY ASYNCHRONOUS REQUEST FOR JOBNUM-2 OR LOWER NEED NOT BE ; FORMALLY HONORED, SINCE WE WILL EXAMINE THAT JOB IN THE LOOP NOW. ; WE KEEP JOBNUM AS HIGH AS POSSIBLE AT ALL TIMES SO THAT SPURIOUS ; REQUESTS FOR A SWITCH TO A LOW PRIORITY JOB WILL NOT CAUSE A PASS ; THROUGH THE SCHEDULING LOOP. ADDR $IMPUR,R4,ADD ;POINT TO $IMPUR TABLE ENTRY 3$: SUB #2,JOBNUM ;WE ARE ABOUT TO EXAMINE THE NEXT JOB BMI 10$ ;NOTHING RUNNABLE! MOV -(R4),R5 ;GET POINTER TO IMPURE AREA BEQ 3$ ;JOB DOES NOT EXIST BIT #BLOCK$,@R5 ;ANY BLOCKING BITS ON? BEQ 4$ ;NO! WE CAN GO TO HIM! TST @R5 ;YES. IS HE BLOCKED IN COMPLETION? BMI 3$ ;YES, HE IS REALLY BLOCKED TSTB @R5 ;NO. DOES HE HAVE COMPLETION PENDING? BPL 3$ ;NO. BIT #KSPND$!NORUN$,@R5 ;DOES THE KMON HAVE HIM SUSPENDED? BNE 3$ ;YES. EVEN COMPLETION CANNOT RUN. 4$: JSR PC,CNTXSW ;NO, DO THE CONTEXT SWITCH! BR EXUSER ;AND TRY TO EXIT AGAIN ; "A SOURCE OF INNOCENT MERRIMENT!" ; - W.S. GILBERT, "MIKADO" ; "DID NOTHING IN PARTICULAR, AND DID IT VERY WELL" ; - W.S. GILBERT, "IOLANTHE" ; "TO BE IDLE IS THE ULTIMATE PURPOSE OF THE BUSY" ; - SAMUEL JOHNSON, "THE IDLER" 10$: DEC (PC)+ ;THE RT-11 LIGHTS ROUTINE! 20$: 1 BNE 14$ ;NOT TOO OFTEN ADD #512.,20$ ;RESET COUNT, CLEAR CARRY 16$: ROL 13$ ;JUGGLE THE LIGHTS BNE 11$ ;NOT CLEAR YET COM 13$ ;TURN ON LIGHTS, SET CARRY 11$: BCC 12$ ;NOTHING FELL OFF, KEEP MOVING ADD #100,16$ ;REVERSE DIRECTION BIC #200,16$ ;ROL/ROR FLIP ;12$: MOV (PC)+,@(PC)+ ;PUT IN LIGHTS(FOR 11/45) 12$: BR 14$ ;SKIP FOR OTHER MACHINES 13$: .WORD 0,SR 14$: MOVB #MXJNUM/2+200,INTACT ;DO A COMPLETE SCAN EXUSLK: BR EXUSER ;BACK INTO LOOKFOR LOOP .DSABL LSB .SBTTL ABORT USERS ; "BEHOLD THE LORD HIGH EXECUTIONER! ; A PERSONAGE OF NOBLE RANK AND TITLE - ; A DIGNIFIED AND POTENT OFFICER, ; WHOSE FUNCTIONS ARE PARTICULARLY VITAL." ; - W.S. GILBERT, "THE MIKADO" ; THE FOLLOWING ENTRY POINT IS USED TO ABORT A RUNNING JOB ; IT SWITCHES TO SYSTEM STATE, SETS THE ABORT BIT FOR THE USER, ; AND FALLS INTO THE ABORT CODE. UABORT: JSR R5,$ENSYS ;GET INTO SYSTEM STATE .WORD 0 .WORD PR7 ;AT PRIORITY 0 BIS #ABORT$,@CNTXT ;AND REQUEST THE ABORT ; THIS ROUTINE ABORTS ALL USER TASKS WHICH ARE WAITING TO BE ABORTED ; IT PURGES ALL I/O, STOPS ANY RUNNING I/O, CLEANS UP THE IMPURE ; AREA SO THAT THE GUY IS RUNNABLE, AND FORCES HIM TO RETURN TO ; $EXIT. ABORT: SPL 0 ;* DOWN TO PRIO 0 1$: JSR PC,SWAPME ;WE MUST CONSIDER CURRENT USER LATER CLRB INTACT+1 ;TURN OFF 'ABORT REQ' FLAG MOV IMPLOC,R4 ;POINT TO TABLE OF IMPURE PTRS ;DV16 2$: MOV -(R4),R5 ;GET AN IMPURE POINTER BEQ 2$ ;JOB NOT EXTANT CMP R5,#-1 ;END OF TABLE? BEQ EXUSLK ;YES. DONE WITH ABORT BIT #ABORT$,@R5 ;IS IT HE? BEQ 2$ ;NO TSTB DFLG ;IS JOB DOING DIRECTORY OPERATION? BEQ 3$ ;NO CMPB USROWN,I.JNUM(R5) ;IF SO, IS THIS THE JOB? BEQ 2$ ;YES, CATCH HIM LATER 3$: JSR PC,CNTXSW ;SWITCH TO ABORT CONTEXT JSR PC,IORSET ;RESET ANY ACTIVE IO MOV TASKSP,R5 ;POINT TO TASK'S STACK CMP (R5)+,(R5)+ ;SKIP OVER SAVED REGS ADDR GOEXIT,@R5 ;R0 -> EXIT ROUTINE MOV CNTXT,R5 ;CLEAN UP IMPURE AREA: CLR @R5 ;WIPE OUT SPECIAL JSTATUS CLR I.TTLC(R5) ;NO TYPE-AHEAD CLR I.SCTR(R5) ;CLEAR SUSPEND COUNT MOV I.IPUT(R5),I.IGET(R5) ;EQUALIZE INPUT BUFFER POINTERS CLR I.ICTR(R5) ;NO INPUT WAITS BIC #CHAIN$!TTSPC$!TCBIT$!TTLC$,@#JSW ;CLEAN UP SPECIAL STATUS MOV SP,R0 ;DO NOT HARD-RESET HIM IN KMON BR 1$ ;CONSIDER ABORTED GUY IN SWAP .SBTTL CHANGE CURRENT CONTEXT ; "IT IS BEST NOT TO SWAP HORSES WHILE CROSSING THE RIVER." ; - A. LINCOLN ; THIS ROUTINE IS ENTERED AT SYSTEM STATE LEVEL 0 TO CHANGE THE ; CONTEXT OF THE USER LEVEL ROUTINE. ; IT CLEVERLY AVOIDS WORK IF WE ARE ASKED TO SWITCH TO THE CURRENT GUY. ; IT WILL ALSO KLUDGE UP HIS STACK FOR COMPLETION ROUTINES IF THERE ; ARE ANY PENDING ; ENTRY: R5 -> IMPURE AREA OF NEW GUY ; EXIT: R4 = TASKSP .ENABL LSB CNTXSW: MOV TASKSP,R4 ;POINT TO CURRENT TASK'S STACK CMP CNTXT,R5 ;IS IT THE SAME JOB? BEQ 7$ ;YES, SKIP ALL THE SAVING STUFF MOV R3,-(R4) ;SAVE REGS ON HIS STACK MOV R2,-(R4) MOV R1,-(R4) MOV R0,-(R4) MOV #34,R0 ;SAVE LOW CORE STUFF 5$: MOV (R0)+,-(R4) CMP R0,#54 BLO 5$ MOV CNTXT,R1 ;GET OLD CONTEXT ADD #I.FPP,R1 ;POINT TO SPECIAL SWAP LIST TST (R1)+ ;WANNA SWAP FPU? BEQ 51$ ;NO BIT #HWFPU$,CONFIG ;GOT FPU TO SWAP? BEQ 51$ STFPS -(R4) ;STORE ALL FPU GORP SETD STD R0,-(R4) STD R1,-(R4) STD R2,-(R4) STD R3,-(R4) LDD R4,R0 STD R0,-(R4) LDD R5,R0 STD R0,-(R4) 51$: MOV (R1)+,R2 ;ANYTHING ELSE TO GO? BEQ 53$ ;NO 52$: MOV @(R2)+,-(R4) ;SWAP STUFF TST @R2 ;UNTIL NO MORE BNE 52$ 53$: MOV R2,(R1)+ ;SAVE TOP OF EXTRA STUFF MOV R4,(R1)+ ;SAVE OLD STACK PTR MOV R5,CNTXT ;SAVE CONTEXT OF NEW JOB ADD #I.SP,R5 ;POINT TO SAVED SP MOV @R5,R4 ;GET NEW USER STACK MOV -(R5),R2 ;GET TOP OF EXTRA SAVED TST -(R5) ;IS THE LIST DEFINED? BEQ 55$ ;NO 54$: MOV (R4)+,@-(R2) ;YES. RESTORE IT CMP @R5,R2 ;END OF LIST? BNE 54$ ;NO 55$: TST -(R5) ;FPU TO SWAP? BEQ 6$ ;NO BIT #HWFPU$,CONFIG ;GOT ONE? BEQ 6$ SETD LDD (R4)+,R0 STD R0,R5 LDD (R4)+,R0 STD R0,R4 LDD (R4)+,R3 LDD (R4)+,R2 LDD (R4)+,R1 LDD (R4)+,R0 LDFPS (R4)+ 6$: MOV (R4)+,-(R0) ;RESTORE LOW CORE CMP R0,#34 BHI 6$ MOV (R4)+,R0 ;RESTORE REGS MOV (R4)+,R1 MOV (R4)+,R2 MOV (R4)+,R3 MOV R4,TASKSP ;SAVE POINTER TO USER STACK 7$: MOV CNTXT,R5 ;RESTORE R5 MOV I.JNUM(R5),JOBNUM ;SET UP JOB NUMBER TST @R5 ;HE'S IN. IS HE DOING COMPLETION? BMI 8$ ;YES. JUST RETURN TSTB @R5 ;NO. SHOULD WE PUT HIM THERE? BPL 8$ ;NO. MOV (R4)+,-(SP) ;YES! KLUDGE UP HIS STACK WITH A FAKE MOV (R4)+,-(SP) ; INTERRUPT BIC #&^C,@R5 ;UNBLOCK HIM COMPLETELY BIS #CMPLT$,@R5 ;AND SAY HE IS IN COMPLETION ROUTINE ADD #I.CHWT,R5 ;SKIP OVER QUEUE HEADS MOV (R5)+,(R5)+ ;SAVE CHANNEL BEING WAITED FOR MOV @#ERRBYT,(R5)+ ;SAVE IMPORTANT STUFF LIKE ERROR BYTE CLR -(R4) ;A FAKE PS! MOV (PC)+,-(R4) ;GIVE HIM A PLACE TO WHICH TO RETURN .$CRTN: $CRTNE ;*** BOOT *** MOV (SP)+,-(R4) ;RESTORE HIS R4 & R5 MOV (SP)+,-(R4) MOV R4,TASKSP ;SAVE THIS 8$: RTS PC ;DONE SWAPPING CONTEXT. R5 = TASKSP .DSABL LSB .SBTTL HARD AND SOFT RESET ; HARD RESET GOES HERE. IT STOPS ANY ACTIVE IO, THEN DOES A SOFT RESET H$RSET: ENSYS S$RSET ;SOFT RESET WHEN DONE IORSET: JSR R3,SAVE30 ;SAVE REGS 3-0 ADDR $ENTRY,R2 ;POINT TO HANDLER ENTRY TABLE 1$: MOV (R2)+,R3 ;GET HANDLER ADDRESS BEQ 1$ ;NOT RESIDENT CMP R3,#-1 ;END OF TABLE? BEQ 10$ ;YES MOV -(R2),R0 ;ALSO POINT R0 AT HANDLER (NOTE! CARRY SET) ROR -(R0) ;SET HANDLER HOLD FLAG TST (R3)+ ;ADVANCE TO CQE POINTER BIT #HNDLR$,<$STAT-$ENTRY>(R2) ;FORCE ABORT ENTRY? ;DV16 BEQ 3$ ;NO, ONLY IF CQE PRESENT ;DV16 MOV @R3,R4 ;R4 -> CQE PTR ;DV16 BR 4$ ;JUMP INTO ENTRY CODE ;DV16 3$: JSR R1,8$ ;GET JOB NUMBER. IS IT OURS? ;DV16 4$: MOV -(R0),R1 ;YES. R1 = OFFSET TO INT. ENTRY ;DV16 ADD R0,R1 ;R1 -> INTERRUPT ENTRY MOV R4,-(SP) ;HE MIGHT DESTROY R4 MOV JOBNUM,R4 ;ENTER WITH R4 = JOB # ;DV16 JSR PC,-(R1) ;CALL ABORT ENTRY IN HANDLER MOV (SP)+,R4 BEQ 9$ ;GO ON IF NO CQE EXISTS ;DV16 6$: MOV R4,R3 ;R3 -> PREVIOUS ELEMENT 7$: JSR R1,8$ ;ISOLATE JOB NUMBER. IS IT OURS? MOV @R4,@R3 ;DISCARD ELEMENT (Q. RESET LATER) BR 7$ ;TRY AGAIN 8$: TST (SP)+ ;THROW AWAY BAD R1 MOV @R3,R4 ;R4 -> NEXT ELEMENT BEQ 9$ ;DONE. GO TO NEXT ELEMENT CMP -(R4),-(R4) ;BACK UP TO LINK WORD MOVB Q.JNUM(R4),-(SP) ;GET JOB NUMBER ASR @SP ;ISOLATE IT ASR @SP ASR @SP BIC #177761,@SP CMP (SP)+,JOBNUM ;IS IT OURS? BNE 6$ ;IF NOT, CONTINUE (ENTER) LOOP JMP @R1 ;IF SO, PROCESS AS HEAD OR OTHERWISE 9$: MOV (R2)+,R4 ;R4 -> HANDLER AGAIN ASL -(R4) ;TEST COMPLETION, RESET HOLD FLAG BPL 1$ ;TOP ELEMENT DID NOT COMPLETE CLR (R4)+ ;TOP ELEMENT COMPLETED. TURN OFF FLAG TST (R4)+ ;POINT TO CQE WD IN HANDLER JSR PC,COMPLT ;CALL QUEUE COMPLETION FOR TOP ELEMENT BR 1$ ;TRY ANOTHER DEVICE 10$: JSR PC,JBABRT ;GET RID OF HANGING MESSAGES CMKALL: MOV #-1,SYSLIM ;CANCEL ALL MARK TIMES ;DV16 CLR R0 ;FLAG CANCEL ALL ;DV16 JMP CMARKT .SBTTL REVERT TO ORIGINAL CHANNELS, QRESET & PURGE HANDLERS ; THESE ROUTINES RUN IN USER STATE REVERT: JSR PC,JBABRT ;CANCEL ANY MESSAGES FOR THIS JOB JSR PC,QUIESCE ;WAIT FOR I/O TO STOP ADDR $CSW,R1 ;POINT TO BG'S CHANNELS TST JOBNUM ;IS THIS THE BG? BEQ 1$ ;YUPPIE MOV R3,R1 ;NOPE, POINT TO FG IMPURE AREA ADD #I.SERR+16,R1 ;ADVANCE TO CHANNELS 1$: MOV #16.,I.CNUM(R3) ;HE NOW GOT ONLY 16 CHANNELS MOV R1,I.CSW(R3) ;AND THEY SITTIN' IN THE USUAL PLACE MOV R3,R5 ;QRESET WANTS IMPURE POINTER IN R5 QRESET: CLR I.SCTR(R5) ;RESET SUSPENSION, TOO TST (R5)+ ;ADVANCE TO AVAIL HEADER MOV R5,@R5 ;RESET TO POINT TO ADD #I.QUE-2,@R5 ; THE ONE ELEMENT CLR @(R5)+ ;WHOSE LINK WORD WE CLEAR CLR (R5)+ ;ZAP COMPLETION Q CLR (R5)+ TST JOBNUM ;IF WE ARE FG BNE 3$ ; WE ARE DONE ADDR $ENTRY,R2 ;ELSE PURGE NON-RESIDENT HANDLERS MOV #$SLOT,R1 1$: CMP @R2,SYSLOW ;IS THIS RESIDENT? BHIS 2$ ;YES. LEAVE IT ALONE CLR @R2 ;NO, CLOBBER IT 2$: TST (R2)+ DEC R1 ;COUNT DOWN BNE 1$ 3$: BIS #100,@TTKS ;MAKE SURE TTY IS RUNNIN' RTS PC ;GO BACK TO CALLER .SBTTL DEQUEUE A COMPLETION ROUTINE; EXIT FROM COMPLETION RTN ; "SO SHE WENT INTO THE GARDEN TO CUT A CABBAGE LEAF TO MAKE AN APPLE ; PIE; AND, AT THE SAME TIME, A GREAT SHE-BEAR COMING UP THE STREET ; POPS ITS HEAD INTO THE SHOP - "WHAT! NO SOAP!" SO HE DIED, ; AND SHE VERY IMPRUDENTLY MARRIED THE BARBER." ; - SAMUEL FOOTE ; THE FOLLOWING CODE EXITS FROM A USER'S COMPLETION ROUTINE ; AND ENTERS ANOTHER ONE, IF PENDING. ; IF NOTHING IS PENDING, WE RETURN TO MAIN CODE OURSELVES $CRTNE: MOV R1,-(SP) ;USER COMES HERE TO START COMPLETION MOV R0,-(SP) ;SAVE REGS 1$: MOV CNTXT,R1 ;POINT TO OUR IMPURE AREA ADD #I.PERR,R1 ;POINT TO STUFF TO RESTORE MOV @R1,@#ERRBYT ;RESTORE ERROR WORD MOV -(R1),-(R1) ;RESTORE CHANNEL WAIT SPL 7 ;LOCK OUT OTHERS MOV -(R1),R0 ;* GET A COMPLETION ROUTINE BNE 2$ ;* NONE, GO BACK TO MAIN LEVEL BIC #CMPLT$+CPEND$,I.JSTA-I.CMPL(R1) ;* TURN OFF FLAGS MOV (SP)+,R0 ;* MOV (SP)+,R1 ;* RESTORE REGS RTI ;* BACK TO USER'S MAIN ROUTINE 2$: MOV @R0,@R1 ;* LINK COMPL FORWARD CMP -(R1),R0 ;* END OF QUEUE? BNE 3$ ;* NO CLR @R1 ;* YEP. CLEAR LQE 3$: SPL 0 ;* DON'T SPEND TOO MUCH TIME AT 7 CMP #-1,Q.WCNT(R0) ;IS THIS A SYNCH ELEMENT? BEQ 35$ ;YUPPER SPL 7 ;NO, LINK INTO AVAIL AT PRIO 7 MOV -(R1),@R0 ;* PUT AVAIL PTR INTO ELEMENT MOV R0,@R1 ;* POINT AVAIL TO THIS ELEMENT SPL 0 ;* SAFE TO COME DOWN NOW 35$: ADD #Q.COMP,R0 ;POINT TO EXTRAS MOV @R0,-(SP) ;SAVE PLACE TO CALL CLR @R0 ;THIS NODE IS NOW FREE CLR R1 ;ACCUMULATE CHANNEL # IN R1 TST -(R0) ;POINT TO COUNT. IF <= 0 BLE 5$ ;USE 0 4$: INC R1 SUB #10.,@R0 ;CHEAPO DIVIDE BY 10. (= CHANNEL SIZE) BGT 4$ 5$: MOV -(R0),R0 ;R0 = CSW OR ID NUMBER JSR PC,@(SP)+ ;CALL YE ROUTINE BR 1$ ;AND AROUND AGAIN .SBTTL BLOCK A TASK ; "THERE'S A LONG, LONG NIGHT OF WAITING ; UNTIL MY DREAMS ALL COME TRUE." ; - STODDARD KING, "THERE'S A LONG, LONG TRAIL" ; "NOW THE SERPENT WAS MORE SUBTIL THAN ANY BEAST OF THE FIELD" ; - GENESIS 3:1 ; THE FOLLOWING ROUTINE IS USED IN THE MONITOR EMT PROCESSOR WHEN ; A USER HAS TO WAIT FOR A SPECIFIC CONDITION. IT SETS THE BLOCKING ; BIT FOR THE CONDITION, AND SWITCHES THE USER OUT. ; WHEN THE USER IS AGAIN RUNNABLE, THIS ROUTINE IS ENTERED AGAIN ; AND IT DETERMINES WHETHER THE CONDITION STILL WARRANTS BLOCKING ; (SPURIOUS UNBLOCKING CAN BE CAUSED BY COMPLETION ROUTINES). ; IF RUNNABLE, IT RETURNS TO THE CALLER (SOMEWHERE IN THE MONITOR). ; IF NOT, IT RE-ENABLES THE BLOCKING BIT AND GOES AWAY AGAIN. ; THE CALLING SEQUENCE IS: ; JSR R4,$SYSWT ; .WORD BLOCKBIT ; ROUTINE TO DETERMINE WHETHER ROUTINE SHOULD STAY BLOCKED: ; ROUTINE MUST SET CARRY IF BLOCKED, CLEAR IT IF RUNNABLE ; IT MAY ASSUME THAT IT HAS REGISTERS R0-R3 UNCHANGED ; JSR PC,@(SP)+ ;CALL TO RETURN CONDITION TO $SYSWT ; RETURN HERE IN USER STATE WHEN FINALLY UNBLOCKED $SYSWT: JSR PC,2(R4) ;STILL BLOCKED? (CALL IN USER MODE) BCS 1$ ;YES MOV (SP)+,R4 ;NO! GET RETURN ADDRESS RTS R4 ;AND RETURN TO UNBLOCKED CODE 1$: TST (SP)+ ;PURGE RETURN ADDRESS ENSYS $SYSWT BIS (R4)+,@CNTXT ;TURN ON BLOCKING BIT IN JSTAT JSR PC,@R4 ;NOW, SEE IF HE WAS UNBLOCKED A MOMENT AGO INC (SP)+ ;WE NEVER WANT TO RETURN NOW! BCS SWAPME ;IF HE WAS UNBLOCKED BEFORE THAT BIS BIC -(R4),@CNTXT ; UNBLOCK HIM AGAIN RTS PC ;AND RETURN FROM FAKE INTERRUPT WITHOUT ; REQUESTING A TASK SWITCH .SBTTL REQUEST TASK SWITCH, UNBLOCK A TASK ; "IF IT BE NOW, 'TIS NOT TO COME; IF IT BE NOT TO COME, IT WILL ; BE NOW; IF IT BE NOT NOW, YET IT WILL COME; THE READINESS IS ALL." ; - SHAKESPEARE, "HAMLET" ; SWAPME AND $RQTSW ARE USED FROM MONITOR LEVEL ROUTINES TO REQUEST ; A SCAN OF THE DISPATCH TABLE, STARTING AT THE JOB WHOSE NUMBER IS ; IS R5. SWAPME USES THE NUMBER OF THE CURRENT JOB. .ENABL LSB DLYUSR: BIS #USRWT$,@CNTXT ;DELAY FOR USR. SET BLOCK BIT SWAPME: MOV CNTXT,R5 ;GET CURRENT JOB NUMBER MOV I.JNUM(R5),R5 $RQTSW: CMP R5,JOBNUM ;WANT LOWER PRIORITY THAN CURRENT JOB? BLO 1$ ;YES, THAT'S POINTLESS $RQSIG: SEC ;TURN ON STRANGE BIT RORB R5 ; IN INTACT JSR PC,GETPSW ;SAVE PRIO TO COME DOWN TO ;DV15 SPL 7 ;COMPARE AND SET MUST BE TOGETHER CMPB R5,INTACT ;* HIGHER THAN LATEST REQUEST? BLOS 2$ ;* NO MOVB R5,INTACT ;* YES, SET IT 2$: JSR PC,$MTPS ;* DOWN TO PROPER LEVEL ;DV15 ASLB R5 ;FIX R5 1$: RTS PC .DSABL LSB ; THIS ROUTINE CAUSES A USER TO BE UNBLOCKED FROM A CONDITION ; IF HE IS CURRENTLY BLOCKED BY IT. IN ADDITION, IF THERE IS A ; CHANGE IN STATUS, A RESCHEDULE IS REQUESTED ; CALLING SEQUENCE: ; R5 -> JOB IMPURE AREA ; JSR R4,UNBLOK ; .WORD BLOCKBIT UNBLOK: BIT (R4)+,@R5 ;IS BLOCKING BIT ON IN JSTAT ? BEQ 1$ ;NO, DO NOT SWITCH BIC -2(R4),@R5 ;YES, UNBLOCK THE TASK MOV R5,-(SP) ;SAVE IMPURE POINTER MOV I.JNUM(R5),R5 ;GET JOB NUMBER JSR PC,$RQTSW ;TIME FOR A CHANGE MOV (SP)+,R5 ;REPOINT TO IMPURE AREA 1$: RTS R4 ;BACK TO HIM .SBTTL FILL COMPUTATIONS, HANDLER SPACE . = . + 74 SPTR = . . = . + 100 RMSTAK = . RMONSZ = . + MAXSYH - $RMON + 777 / 1000 ;RMON LENGTH IN BLOCKS RMSIZE = RMONSZ * 1000 ;RMON LENGTH IN BYTES RMLEN = RMONSZ * 400 ;RMON LENGTH IN WORDS RT11SZ = KMONSZ + USRSZ + RMONSZ ;NUMBER OF BLOCKS IN ALL RT-11 RTSIZE = RT11SZ * 1000 ;SIZE OF RT-11 IN BYTES RTLEN = RT11SZ * 400 ;SIZE OF RT-11 IN WORDS FILLER= RT11SZ*1000-<.-KMON+MAXSYH> ;AMOUNT TO FILL TO PLACE THE ;KMON OVERLAYS ON A BLOCK .CSECT SYSHND ; SYSTEM HANDLER FITS IN THIS CSECT . = . + MAXSYH + FILLER .IIF DF NLRMON, .LIST .TITLE CR.SYS ; RT-11 CARD READER (CR11) HANDLER ; ; DEC-11-OCRHA-E ; ; ECP, ABC, RRB ; MARCH 1975 ; ; COPYRIGHT (C) 1974, 1975 ; ; DIGITAL EQUIPMENT CORPORATION ; MAYNARD, MASSACHUSETTS 01754 ; ; 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 DIGITAL. ; ; THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO ; CHANGE WITHOUT NOTICE AND SHOULD NOT BE CONSTRUED ; AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION. ; ; DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE ; OR RELIABILITY OF ITS SOFTWARE ON EQUIPMENT ; WHICH IS NOT SUPPLIED BY DIGITAL. .SBTTL MISCELLANEOUS EQUATES R0=%0 R1=%1 R2=%2 R3=%3 R4=%4 R5=%5 SP=%6 PC=%7 ; CARD READER CONTROL CRVECT=230 ;INTERRUPT VECTOR CRST=177160 ;CARD READER STATUS REGISTER CRB1=177162 ;DATA BUFFER 1 CRB2=177164 ;DATA BUFFER 2 ; CONSTANTS FOR MONITOR COMMUNICATIONS HDERR=1 ;HARD ERROR MONLOW=54 ;BASE ADDRESS OF MONITOR OFFSET=270 ;OFFSET TO HANDLER RETURN PS=177776 ;PROGRAM STATUS WORD PR7=340 ;PRIORITY 7 PR6=300 ;PRIORITY 6 ; ASCII CONSTANTS CR=15 ;CARRIAGE RETURN LF=12 ;LINE FEED SPACE=40 ;SPACE EOF=41 ;END OF FILE ; CARD READER CONTROL AND STATUS BITS READ=1 ;READ EJECT=2 ;EJECT CARD INTEB=100 ;INTERRUPT ENABLE COLD=200 ;COLUMN DONE READY=400 ;READY BUSY=1000 ;BUSY ONLIN=2000 ;ONLINE DATLAT=4000 ;DATA LATE MOTIN=10000 ;MOTION CHECK(CM11 ONLY) HOPCK=20000 ;HOPPER CHECK(CM11 ONLY) CARDN=40000 ;CARD DONE ERR=100000 ;ERROR .SBTTL CONFIGURATION SECTION ; THE FOLLOWING CODE IS EXECUTED WHEN A "SET CR" CONSOLE COMMAND IS ; GIVEN. .ASECT .=400 ;CONFIGURATION AREA ; SET CR [NO] CRLF ; APPEND/DO NOT APPEND CARRIAGE RETURN/LINE FEED TO EACH CARD IMAGE BR .+LXCRLF-XCRLF .RAD50 /CRLF/ .WORD /2+100000 ; SET CR [NO] TRIM ; TRIM/DO NOT TRIM TRAILING BLANKS FROM CARD IMAGES BR .+LXTRIM-XTRIM .RAD50 /TRIM/ .WORD /2+100000 ; SET CR [NO] HANG ; HANG/RETURN HARD ERROR IF READER NOT READY AT START OF TRANSFER BNE .+LERROR-XHANG .RAD50 /HANG/ .WORD /2+100000 ; SET CR CODE [=] 026 [029] ; SET TRANSLATION TO 026 [029] MODE .WORD 026. .RAD50 /CODE/ .WORD /2+40000 ; SET CR [NO] IMAGE ; TRANSMIT EACH COLUMN AS 12 BITS (ONE WORD/COLUMN) .WORD NOIMAG-IMBASE .RAD50 /IMAGE/ .WORD /2+100000 .WORD 0 ;END-OF-OPTIONS FLAG .SBTTL CONFIGURATION SUBROUTINES CRLF: MOV (PC)+,R3 ;NOP IF POSITIVE NOP MOV R3,XCRLF ;ENTRY POINT FOR NO RTS PC TRIM: MOV (PC)+,R3 ;NOP IF POSITIVE NOP MOV R3,XTRIM ;ENTRY POINT FOR NO RTS PC HANG: MOV (PC)+,R3 ;NOP IF POSITIVE NOP MOV R3,XHANG ;ENTRY POINT FOR NO RTS PC CODE: MOV PC,R1 ;R1 -> CONVERSION TABLE FOR 026 ADD #SET026-.,R1 SUB R3,R0 ;026 REQUESTED? BMI CODEXT ;NOPE - ERROR (NOTE THAT C IS SET!) BEQ SETCOD ;YES, IT'S 026 - GO DO IT ADD #SET029-SET026,R1 ;R1 -> CONVERSION TABLE FOR 029 CMP #3,R0 ;WAS IT 029? BEQ SETCOD ;YES SEC ;ELSE AN ERROR - INDICATE SUCH CODEXT: RTS PC ;AND RETURN TO KMON SETCOD: MOV PC,R3 ;R3 -> CHARACTER TABLE ADD #CHRTBL-.,R3 SCODE: CLR R0 ;PICK UP NEXT OFFSET TO BE MODIFIED BISB (R1)+,R0 ; FROM APPROPRIATE TABLE BEQ CODEXT ;ALL DONE (NOTE: C IS CLEAR) ADD R3,R0 ;POINT TO BYTE TO MODIFY MOVB (R1)+,@R0 ;AND PLUG IN NEW VALUE BR SCODE ;CONTINUE IMAGE: ADD #YAIMAG-NOIMAG,R3 ;POINT TO "YES" TABLE ADD PC,R3 ;ENTRY FOR "NO" IMBASE: MOV (R3)+,XIM1 ;AND PATCH HANDLER MOV (R3)+,XIM2 MOV (R3)+,XIM2+2 MOV (R3)+,XIM3+2 RTS PC NOIMAG: BEQ .+NXTCHR-XIM1 MOVB CHRTBL-XIM2(R5),@(PC)+ .WORD 1 YAIMAG: BR .+NXTCHR-XIM1 MOV @#CRB1,@(PC)+ .WORD 2 .SBTTL 026, 029 CONVERSION TABLES ; 026 CONVERSION TABLE ; MODIFIES CHARACTER TABLE TO ACCEPT 026 KEYPUNCH CODES SET026: .BYTE 012,137 ;BACK ARROW (8-2) .BYTE 013,075 ;EQUAL (8-3) .BYTE 015,136 ;UP ARROW (8-5) .BYTE 016,047 ;APOSTROPHE (8-6) .BYTE 017,134 ;BACKSLASH (8-7) .BYTE 052,073 ;SEMICOLON (0-8-2) .BYTE 054,050 ;LEFT PAREN (0-8-4) .BYTE 055,042 ;QUOTES (0-8-5) .BYTE 056,043 ;LB. SIGN (0-8-6) .BYTE 057,045 ;PERCENT (0-8-7) .BYTE 112,072 ;COLON (11-8-2) .BYTE 115,133 ;L BRACKET (11-8-5) .BYTE 116,076 ;GREATER THAN (11-8-6) .BYTE 117,046 ;AMPERSAND (11-8-7) .BYTE 200,053 ;PLUS (12) .BYTE 212,077 ;QUESTION (12-8-2) .BYTE 214,051 ;RIGHT PAREN (12-8-4) .BYTE 215,135 ;R BRACKET (12-8-5) .BYTE 216,074 ;LESS THAN (12-8-6) .WORD 0 ;** END OF TABLE ** ; 029 CONVERSION TABLE ; MODIFIES CHARACTER TABLE TO ACCEPT 029 KEYPUNCH CODES SET029: .BYTE 012,072 ;COLON (8-2) .BYTE 013,043 ;LB. SIGN (8-3) .BYTE 015,047 ;APOSTROPHE (8-5) .BYTE 016,075 ;EQUAL (8-6) .BYTE 017,042 ;QUOTES (8-7) .BYTE 052,134 ;BACKSLASH (0-8-2) .BYTE 054,045 ;PERCENT (0-8-4) .BYTE 055,137 ;BACK ARROW (0-8-5) .BYTE 056,076 ;GREATER THAN (0-8-6) .BYTE 057,077 ;QUESTION (0-8-7) .BYTE 112,135 ;R BRACKET (11-8-2) .BYTE 115,051 ;RIGHT PAREN (11-8-5) .BYTE 116,073 ;SEMICOLON (11-8-6) .BYTE 117,136 ;UP ARROW (11-8-7) .BYTE 200,046 ;AMPERSAND (12) .BYTE 212,133 ;L BRACKET (12-8-2) .BYTE 214,074 ;LESS THAN (12-8-4) .BYTE 215,050 ;LEFT PAREN (12-8-5) .BYTE 216,053 ;PLUS (12-8-6) .WORD 0 ;** END OF TABLE ** .IIF GE -1000, .ERROR ;TABLE NOT IN BLOCK 1 .SBTTL HANDLER PROPER .CSECT CR11 ; LOAD POINT LOADPT: .WORD CRVECT ;INTERRUPT VECTOR .WORD CRINT-. ;OFFSET TO INTERRUPT SERVICE .WORD PR7 ;PS CRLQE: .WORD 0 ;LAST QUEUE ENTRY CRCQE: .WORD 0 ;CURRENT QUEUE ENTRY ; ENTRY POINT CRHAND: MOV CRCQE,R5 ;POINT TO Q ELEMENT MOV CHRPTR,R4 ;POINT INTO CARD IMAGE ASL 6(R5) ;CONVERT WORD COUNT TO BYTE COUNT BLOS LERROR ;NULL REQUEST OR WRITE IS LOGIC ERR BIT #READY+BUSY,@#CRST ;IS READER READY? XHANG: NOP ;* PATCH HERE TO ISSUE HARD ERROR TST (R5)+ ;BLOCK 0 REQUEST ? BEQ READR ;YES, GO INITIATE REQUEST TST (R5)+ ;NO, POINT TO BUFFER PTRS BR CONT ;GO SEE IF ANY STUFF IS LEFT IN OLD CARD BR ABORT ;ABORT ; INTERRUPT ENTRY POINT CRINT: JSR R5,@$INPTR ;ENTER SYSTEM STATE .WORD ^C&PR7 DEC COLCNT ;COUNT DOWN INTERRUPTS THIS CARD MOV @#CRST,R5 ;GET STATUS BMI ERROR ;WHOOPS -- ERROR TSTB R5 ;CHECK FOR COLUMN DONE BPL CARD ;BRANCH IF NOT COLUMN DONE MOV @#CRB2,R5 ;GET COMPRESSED CHAR BEQ INCOLT ;IT'S BLANK MOV @#CRB1,-(SP) ;GET EXPANDED CHAR CMP CHRPTR,BUFPTR ;FIRST COLUMN? BNE TSTPUN ;NOPE MOV @SP,CHAR12 ;ELSE SAVE FOR EOF CHECK TSTPUN: BIC #177003,@SP ;CHECK ONLY ROWS 1-7 MOV @SP,-(SP) ;CHECK FOR INVALID PUNCHES NEG @SP ;BY CHECKING FOR 2 OR MORE PUNCHES BIC (SP)+,(SP)+ ;IN COLUMNS 1-7 XIM1: BEQ NXTCHR ;IT'S OKAY MOV #377,R5 ;ELSE FORCE TRANSLATION INTO 134 NXTCHR: MOV CHRPTR,(PC)+ ;REMEMBER POSITION OF NON-BLANK ENDPTR: .WORD 0 INCOLT: ADD PC,R5 ;MAKE A PIC POINTER TO TRANS TABLE XIM2: MOVB CHRTBL-.(R5),@(PC)+ ;PUT TRANSLATED CHAR IN LINE CHRPTR: .WORD 0 XIM3: ADD #1,CHRPTR ;PUSH BUFFER POINTER BY 1 OR 2 INTRET: BIS #INTEB,@#CRST ;ENABLE ONLINE INTR IF NECESSARY RTS PC ; CARD DONE OR ERROR CARD: BIT #CARDN,R5 ;CARD DONE? BEQ ERR1 ;NOPE -- SPURIOUS INTERRUPT - IGNORE MOV (PC)+,R4 ;R4 -> CHRBUF BUFPTR: .WORD 0 ;POINTER TO CHRBUF MOV CRCQE,R5 ;POINT TO Q ELEMENT CMP (R5)+,(R5)+ ;PUSH OVER BUFFER POINTER CMP #7417,(PC)+ ;END OF FILE? CHAR12: .WORD 0 ;12-BIT FOR FIRST CARD COL. BEQ ENDFIL ;YES MOV R1,-(SP) ;SAVE R1 MOV CHRPTR,R1 ;POINT TO PAST END OF 80 CHARS XTRIM: NOP ;* PATCH HERE TO SUPPRESS TRIMMING MOV ENDPTR,R1 ;DA, GIVE IT TO HIM INC R1 LXTRIM: XCRLF: NOP ;* PATCH HERE TO SUPPRESS CR/LF MOVB #CR,(R1)+ ;JA, GIVE IT HIM MOVB #LF,(R1)+ LXCRLF: MOV R1,ENDPTR ;THIS IS NOW THE END MOV (SP)+,R1 ;RESTORE R1 BR CONT ;ENTER FILLING LOOP FILBUF: MOVB (R4)+,@(R5)+ ;PUT A BYTE IN HIS BUFFER DEC @R5 ;IS HE FULL ? BEQ RETMON ;YEP INC -(R5) ;PUSH BUFFER POINTER CONT: CMP ENDPTR,R4 ;END OF OUR CARD ? BHI FILBUF ;NOT YET ERR1: BIT #READY+BUSY,@#CRST ;OKAY TO INIT READ? BNE INTRET ;NOPE - GO HANG UNTIL READY READR: MOV PC,R4 ;POINT TO CHRBUF ADD #CHRBUF-.,R4 MOV R4,CHRPTR ;START FILLING FROM NEW CARD MOV R4,ENDPTR ;WHICH IS AS YET EMPTY MOV R4,BUFPTR ;ESTABLISH BUFFER POINTER CLR CHAR12 ;CLEAR EOF FLAG MOV #80.,(PC)+ ;SET COLUMN COUNT COLCNT: .WORD 0 ;COUNT OF COLUMNS REMAINING IN CARD MOV #READ+INTEB,@#CRST ;START A CARD GOIN' RTS PC ;BYE ; VARIOUS ERRORS LERROR: MOV CRCQE,R5 ;POINT TO QUEUE ELEMENT BIS #HDERR,@-(R5) ;YOU CAN'T WRITE ON A READER BR ABORT ERROR: BIT #DATLAT,R5 ;DATA LATE IS ONLY NOT CURABLE BNE LERROR ;ISSUE HARD ERROR IF SO TST COLCNT ;DONE WITH DATA COLUMNS? BPL ERR1 ;NOPE -- MUST BE PICK CHECK, ETC., ; START A NEW READ TO CORRECT CONDITION. BR CARD ;ELSE ASSUME CARD DONE ; END OF FILE CARD FOUND ENDFIL: MOV (R5)+,R4 ;POINT INTO HIS BUFFER CLRBUF: CLRB (R4)+ ;CLEAR IT ALL DEC @R5 BNE CLRBUF BIS #20000,@-10(R5) ;SET EOF BIT IN CHANNEL ABORT: CLR ENDPTR ;FORCE A READ NEXT TIME ; RETURN TO MONITOR (REQUEST DONE, EOF, OR ERROR) RETMON: MOV R4,CHRPTR ;SAVE POSITION IN CARD CLR @#CRST ;NO INTERRUPTS MOV PC,R4 ;THE USUAL MONITOR RETURN ADD #CRCQE-.,R4 MOV @#MONLOW,R5 JMP @OFFSET(R5) .SBTTL CHARACTER TABLE ; THE FOLLOWING MACRO TAKES AS ARGUMENTS THE ASCII TRANSLATION ; DESIRED AND THE LIST OF PUNCH COMBINATIONS FOR THAT CHARACTER. .MACRO C $LIST T=0 .IRP X,<$LIST> .IF NE X'. .IF LE X'.-7 T=T+X'. .IFF U=10 .REPT X'.-8. U=U+U .ENDR T=T+U .ENDC .IFF T=T+40 .ENDC .ENDR .=CHRTBL+T .BYTE $CHAR $CHAR = $CHAR + 1 .ENDM C ; THE FOLLOWING TABLE TRANSLATES 029 KEYPUNCH CODES TO ASCII. CHRTBL: .REPT 256. .BYTE 134 ;DEC STANDARD ERROR CHARACTER .ENDR .=CHRTBL $CHAR = 0 ;START AT OCTAL 000 C <12,0,9,8,1> ;NULL C <12,9,1> ;CTRL-A C <12,9,2> ;CTRL-B C <12,9,3> ;CTRL-C C <9,7> ;CTRL-D C <0,9,8,5> ;CTRL-E C <0,9,8,6> ;CTRL-F C <0,9,8,7> ;CTRL-G C <11,9,6> ;CTRL-H C <12,9,5> ;CTRL-I C <0,9,5> ;CTRL-J C <12,9,8,3> ;CTRL-K C <12,9,8,4> ;CTRL-L C <12,9,8,5> ;CTRL-M C <12,9,8,6> ;CTRL-N C <12,9,8,7> ;CTRL-O C <12,11,9,8,1> ;CTRL-P C <11,9,1> ;CTRL-Q C <11,9,2> ;CTRL-R C <11,9,3> ;CTRL-S C <9,8,4> ;CTRL-T C <9,8,5> ;CTRL-U C <9,2> ;CTRL-V C <0,9,6> ;CTRL-W C <11,9,8> ;CTRL-X C <11,9,8,1> ;CTRL-Y C <9,8,7> ;CTRL-Z C <0,9,7> ;ALTMODE (ESCAPE) C <11,9,8,4> ;CTRL-\ C <11,9,8,5> ;CTRL-] C <11,9,8,6> ;CTRL-^ C <11,9,8,7> ;CTRL-_ C <> ;SPACE C <12,8,7> ;! C <8,7> ;" C <8,3> ;# C <11,8,3> ;$ C <0,8,4> ;% C <12> ;& C <8,5> ;' C <12,8,5> ;( C <11,8,5> ;) C <11,8,4> ;* C <12,8,6> ;+ C <0,8,3> ;, C <11> ;- C <12,8,3> ;. C <0,1> ;/ C <0> ;0 C <1> ;1 C <2> ;2 C <3> ;3 C <4> ;4 C <5> ;5 C <6> ;6 C <7> ;7 C <8> ;8 C <9> ;9 C <8,2> ;: C <11,8,6> ;; C <12,8,4> ;< C <8,6> ;= C <0,8,6> ;> C <0,8,7> ;? C <8,4> ;@ C <12,1> ;A C <12,2> ;B C <12,3> ;C C <12,4> ;D C <12,5> ;E C <12,6> ;F C <12,7> ;G C <12,8> ;H C <12,9> ;I C <11,1> ;J C <11,2> ;K C <11,3> ;L C <11,4> ;M C <11,5> ;N C <11,6> ;O C <11,7> ;P C <11,8> ;Q C <11,9> ;R C <0,2> ;S C <0,3> ;T C <0,4> ;U C <0,5> ;V C <0,6> ;W C <0,7> ;X C <0,8> ;Y C <0,9> ;Z C <12,8,2> ;[ C <0,8,2> ;\ C <11,8,2> ;] C <11,8,7> ;^ C <0,8,5> ;_ C <8,1> ;ACCENT GRAVE C <12,0,1> ;LC A C <12,0,2> ;LC B C <12,0,3> ;LC C C <12,0,4> ;LC D C <12,0,5> ;LC E C <12,0,6> ;LC F C <12,0,7> ;LC G C <12,0,8> ;LC H C <12,0,9> ;LC I C <12,11,1> ;LC J C <12,11,2> ;LC K C <12,11,3> ;LC L C <12,11,4> ;LC M C <12,11,5> ;LC N C <12,11,6> ;LC O C <12,11,7> ;LC P C <12,11,8> ;LC Q C <12,11,9> ;LC R C <11,0,2> ;LC S C <11,0,3> ;LC T C <11,0,4> ;LC U C <11,0,5> ;LC V C <11,0,6> ;LC W C <11,0,7> ;LC X C <11,0,8> ;LC Y C <11,0,9> ;LC Z C <12,0> ;OPEN BRACE C <12,11> ;VERTICAL BAR C <11,0> ;CLOSE BAR C <11,0,1> ;TILDE C <12,9,7> ;DEL . = CHRTBL + 256. CHRBUF: .BLKW 81. $INPTR: .WORD 0 ;PLUGGED TO POINT TO COMMON ENTRY CRSIZE=.-LOADPT .END .NLIST TTM ; LISTC=0 .IF NDF,LISTC .NLIST CND .ENDC .IF NDF,TM11 .IF NDF,TM02 TM11=0 ;ASSEMBLE FOR TM11 .ENDC .ENDC .IF DF,TM11 .TITLE TM11 V01-17 .ENDC .IF NDF,TM11 .TITLE TM02 HANDLER UNDER RT11 .ENDC ;RT11 MAGTAPE HANDLER .IF DF,TM11 ; DEC-11-ORMHA-E .ENDC .IF NDF,TM11 ; DEC-11-ORJSA-E .ENDC ; ; COPYRIGHT (C) 1975 ; ; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. ; ; 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 DEC. ; ; THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO ; CHANGE WITHOUT NOTICE AND SHOULD NOT BE CONSTRUED ; AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION. ; ; DEC ASSUMES NO RESPONSIBILITY FOR THE USE ; OR RELIABILITY OF ITS SOFTWARE ON EQUIPMENT ; WHICH IS NOT SUPPLIED BY DEC. ; ;AUTHOR: BOB FRIEDENTHAL ;DATE: 1-OCT-74 ; ;REVISED BY: B.C. ;DATE: 22-JAN-75 ; (CHANGES NOTED BY ';###') ;REVISED BY: J.D./R.B./B.C. ;DATE: 29-AUG-75 ; (CHANGES NOTED BY ';+++') ;THE RT11 MAGTAPE HANDLER HANDLES 2 KINDS OF FUNCTIONS, HARDWARE AND SOFTWARE. ;HW FUNCTIONS ACCESS THE MAGTAPE 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 HI BYTE OF THE ;8TH 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. ;THE HANDLER EXITS THROUGH THE Q MANAGER WITH THE FINAL INTERRUPT ;OR PSEUDO INTERRUPT ON THE STACK. ;ASSEMBLY PARAMETERS ; PARAMETER RESULT ; TM11/TM02 TM11 DEFINED(DEFAULT): TM11 VERSION ; TM02 DEFINED & TM11 NOT DEFINED: TM02 VERSION ; NEWVOL INCLUDE VOLUME INITIALIZATION FUNCTION ; VOLUME INITIALIZED ON CODE 7 OR ON A ; DELETE WITH NULL FILE NAME. ; VOL1 INCLUDE COMPLETE VOL1 LABEL RATHER THAN ONL ITS ; ID ("VOL1"). (ADDS 38 WORDS) ; DEBUG PRODUCE ABSOLUTE CODE WHICH INCLUDES STANDALONE ; DEBUGGING CAPABILITY. ; INIT CODE WHEN RUN STANDALONE WILL INITIALIZE THE ; VOLUME ON UNIT 0 AND EXIT. ; ASCDAT CODE WILL ENTER ASCII DATE IN LABELS. ; FCNT CODE TO COUNT FILES AND PUT PROPER FILE ;### ; SEQUENCE NUMBER IN HEADER LABELS. ;### ;CURRENTLY DEFINED CONDITIONALS NEWVOL=0 ;VOLUME INIT VOL1=0 ;FULL VOLUM LABEL ; DEBUG=0 ; INIT=0 ASCDAT=0 .SBTTL GENERAL DESCRIPTION ;THE RT11 MAGTAPE HANDLER FOR THE TM11 AND TM02 CONTAINS A DRIVER, FILE SERVICE ;ROUTINES, AND A DISPATCH ROUTINE. THE DISPATCH ROUTINE CHANGES THE ;SUBROUTINE CALL ON THE STACK INTO A PSEUDO-INTERRUPT, ;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 ALLOWS HW FUNCTIONS, AS WELL. 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 ALSO 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, ;WHEN EXITING, UPDATE THIS TABLE BY SETTING OR CLEARING BITS USING A WORD ;WHOSE HIGH AND LOW BYTES EACH HAVE 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 ROUITINE. ENTER, LOOKUP, AND DELETE ;ALL USE IT TO POSITION THE MAGTAPE TO THE CORRECT FILE. BASICALLY, IT ;CONVERTS THE RAD50 FILE NAME TO ASCII, STORING IT IN A SLOT PER THE CURRENT UNIT, ;THEN READS HDR1'S UNTIL IT FINDS A MATCHING NAME OR READS EOF WHEN TRYING TO ;READ A HDR1. ON A POSITIVE NUMBERED FUNCTION IT STARTS SEARCHING FROM THE CURRENT ;TAPE POSITION; OTHERWISE, IT DOES A REWIND AND CHECKS FOR PROPER VOLUME LABEL ;FIRST. IT ALWAYS LEAVES THE TAPE POINTING TO THE FILE'S HDR1 OR ;BETWEEN THE LEOT MARKS SO THAT SPACING FORWARD A FILE MERELY INVOLVES ;SPACING FORWARD 3 TAPE MARKS (ACCOMPLISHED BY DOING A FORWARD SPACE WITH ;THE WC REGISTER SET TO 0 EACH TIME). WHEN SEEK RETURNS, THE CALLING ;ROUTINES TEST FOR FILE FOUND AND ACT ACCORDINGLY. ENTER ;DELETES ANY FILE FOUND AND CONTINUES TO SEARCH, WRITING A HDR1* WHEN ;NO FILE IS FOUND AND TAPE IS AT LEOT. LOOKUP CAUSES AN ERROR ON NOT FOUND OR, ;ON FOUND, SPACES PAST THE HDR1* TO THE DATA. AND DELETE WRITES A DUMMY ;HDR1* OVER THE HDR1 THAT THE SEEK RETURNS POINTING TO. THIS OPERATION ;DOES NOT DESTORY THE FILE ONLY THE FIRST RECORD OF THE ;FILE WHICH GETS ERASED. SINCE THE HANDLER DOES NOT ALLOW NULL FILES, ;THE *EOF1* SEQUENCE NECESSARY FOR PROPER TAPE POSITIONING REMAINS ;INTACT. ; ;READ, WRITE, AND CLOSE ; ;BOTH READ AND WRITE PERFORM ENOUGH 256 WORD OR LESS OPERATIONS TO FILL THE WC ;REQUESTED. READ WILL ZERO OUT THE REMAINDER OF THE USER'S INPUT ;BUFFER IF IT READS EOF DURING THIS PROCESS. ALL WRITES, EXCEPT TO BLOCK ;0, JUST WRITE FROM THE CURRENT TAPE POSITION; BLOCK 0 WRITES REWIND TO ;START OF FILE BEFORE WRITING, DESTROYING THE FILE'S PREVIOUS CONTENTS. ;READ ALLOWS ACCESS TO ANY BLOCK IN THE FILE, FORWARD OR BACKWARD SPACING ;AS NECESSARY BEFORE STARTING THE READ. READ KNOWS THE CURRENT BLOCK ;NUMBER BECAUSE THE FSR KEEPS TRACK OF BLOCKS READ AND WRITTEN, EACH ;ENTER OR LOOKUP CLEARING THE COUNT FOR THE CURRENT UNIT; EACH READ OR WRITE ;UPDATING IT. .IFNDF FCNT ;### THE FOLLOWING FEATURE WAS DELETED FOR RT-11 V2B B.C. ;### .ENDC ;FCNT ; THE SYSTEM ALSO KEEPS TRACK OF THE NUMBER OF THE CURRENT ;FILE, SETTING THIS TO 0 (THE NULL FILE AT THE START OF THE VOLUME BEING ;FILE 0) ON ALL REWINDS, INCREMENTING IT ON ANY OPERATION THAT SPACES ;PAST A FILE, INCLUDING CLOSE. .IFNDF FCNT ;### END OF DELETED FEATURE B.C. ;### .ENDC ;FCNT ;### FOR RT-11 V2B, THE MT FILE LABELS (HDR1) WERE CHANGED TO ;### IGNORE A '.' IN POSITION 7 OF THE FILE ID, FOR ;### COMPATIBILITY WITH RSX. ALSO, WE NOW WRITE A '.' ;### BETWEEN FILENAME AND EXT ON MT LABELS. WHEN LOOKING FOR A ;### VOLUME OR FILE LABEL, WE ONLY TRY TO READ 80. BYTES, SINCE ;### RSX AND ANSII ONLY WRITE 80. BYTE LABEL. THIS STILL ALLOWS ;### US TO READ A 512. BYTE LABEL. WE STILL ONLY WRITE 512. BYTE ;### LABELS. B.C. ; CLOSE, WHICH WRITES THE EOF1** SEQUENCE ;ALSO MAKES USE OF THE BLOCK COUNT WHICH IT MUST INSERT, CONVERTED TO ;ASCII DECIMAL DIGITS, INTO THE EOF1 LABEL. ; ;SERVICE ROUTINES ; ;THE FSR MAKES CONTINUAL USE OF A SUBROUTINE WHICH RETURNS A VALUE ;TO WHICH THE CALLER NEED ONLY ADD A TABLE POINTER MINUS THE PC IN ;THE SUBROUTINE TO GET AN INDEX INTO THE TABLE CORRESPONDING TO THE ;NUMBER OF THE CURRENT UNIT. THUS, JSR PC,UNOFF ; CLR TABLE-PZ(R2) ;CLEARS THE CORRECT TABLE ENTRY. ; ;TO EXECUTE ALL HW FUNCTIONS, THE HANDLER CALLS A SINGLE ROUTINE FOLLOWED BY THE ;FUNCTION CODE. THIS ROUTINE, SOFT, SAVES THE PORTION OF THE STACK BELONGING TO ;THE HANDLER AND SOME REGISTERS, THEN INITIATES THE FUNCTION BY DROPPING THRU TO XCT, ;WHICH RETURNS TO THE MONITOR VIA AN RTS PC. ;THUS, JSR PC,SOFT ; REWIND ;EXECUTES A REWIND. ; ; ;THE DRIVER ; ;THE DRIVER CONSISTS OF A FUNCTION INITIATION ROUTINE, XCT, AN INTERRUPT ROUTINE, MTINT, ;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. ;NO REWIND NEEDED IF AT BOT). THEN IT INITIATES THE FUNCTION BY LOADING THE ;WC REGISTER WITH THE VALUE IN WC AND THE CURRENT ADDRESS REGISTER WITH ;THE VALUE IN CA. ON HW FUNCTIONS, CA AND WC COME DIRECTLY FROM THE Q ;ELEMENT. BUT SW ROUTINES AND RETRY CODE IN GENERAL LOAD THESE FOR THEIR OWN ;PURPOSES BEFORE CALLING THE DRIVER. HAVING INITIATED THE FUNCTION, XCT ;RESTORES REGISTERS SAVED ON THE PREVIOUS INTERRUPT OR HANDLER ;ENTRY AND RETURNS TO THE INTERRUPTED ROUTINE. ; ;THE INTERRUPT ROUTINE IS FAIRLY COMPLEX AS IT MUST PROCESS SUCCESS AND ;FAILURE IN BOTH HW AND SW MODES. ON SUCESSFUL COMPLETION OF ;A SOFTWARE REQUESTED FUNCTION IT RESTORES THE STACK AND REGISTERS TO THEIR ;APPEARANCE UPON ENTRY TO ROUTINE SOFT, THEN DOES AN RTS PC WHICH RETURNS ;TO THE SW ROUTINE THAT HAD CALLED SOFT. ON A SUCCESSFUL HW MODE ;FUNCTION, MTINT DISPATCHES TO THE HW EXIT SEQUENCE. ON AN ERROR IN EITHER ;HW OR SW MODES, IT EITHER DISPATCHES TO THE PROPER ERROR EXIT SEQUENCE IF ;IT CANNOT RECOVER, RETRIES THE FUNCTION, OR, ON A READ OR WRITE, .IF DF,TM11 ;ISSUES A BACKSPACE 1 RECORD AND RETRIES THE FUNCTION ON THE NEXT INTERRUPT. .ENDC .IF NDF,TM11 ;BACKSPACES 3 RECORDS OR TO BOT, THEN FORWARD SPACES TO THE START OF THE ;BAD RECORD THEN RETRIES THE FUNCTION. .ENDC ;RETRY OF THE FUNCTION INVOLVES EITHER JUST SETTING THE GO BIT IN THE ;COMMAND REGISTER OR RESETTING WC AND CA REGISTERS AND SETTING THE GO ;BIT. ; ;THE EXIT SEQUENCE SETS PROPER ERROR BITS AND, WHEN AN UNRECOVERABLE ERROR OCCURS ;IN SW MODE, ATTEMPTS TO SAVE THE FILE STRUCTURE: ;ON ERROR DURING ENTER IT WRITES LEOT OVER THE BAD HDR1. ;ON ERROR DURING WRITE, IT SPACES PAST THE OFFENDING RECORD AND CLOSES THE ;FILE. ;ON ERROR DURING A CLOSE OF AN ENTER, IT ENDS THE DATA WITH A TRIPLE TAPE ;MARK. ;ON ERROR DURING LOOKUP OR READ, IT REWINDS. ;IF AN ERROR OCCURS DURING THE RECOVERY PROCESS, IT EXITS. ;ON ANY ERROR, IT SETS THE HW ERROR BIT IN THE CSW. ; ;INTERRUPT LEVEL OPERATION ; ;THE MT 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 MAGTAPE 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 ,PRIOR TO ISSUING AN RTS PC (RTI), SAVES 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 VIA AN RTS PC. ;THUS, SW OPERATION ALTERNATES BETWEEN A SAVE OF THE STACK AND AN RTI 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. .SBTTL DEFINITIONS R0=%0 R1=%1 R2=%2 R3=%3 R4=%4 R5=%5 R6=%6 R7=%7 SP=%6 PC=%7 PSW=-2 ;PROGRAM STATUS WORD PR5=240 PR7=340 .IF DF,TM11 ;TM11 CODE MTS=172520 ;STATUS REGISTER MTC=MTS+2 ;COMMAND REGISTER MTBRC=MTC+2 ;BYTE RECORD COUNTER MTCMA=MTBRC+2 ;CURRENT MEMORY ADDRESS MTD=MTCMA+2 ;DATA BUFFER MTRD=MTD+2 ;TM11 READ LINES MTVEC=224 ;ADDRESS OF MT INTERRUPT VECTOR ;MTC BIT DEFINITIONS DENSE=20000 ;BASE OF DENSITY BITS PWRCLR=10000 ;POWER CLEAR PEVN=4000 ;PARITY:=0 MEANS ODD UNITNO=400 ;BASE OF UNIT BITS INTEN=100 ;INTERRUPT ENBALE EXMEM=20 ;BASE OF EXTENDED MEMORY BITS FUNC=2 ;BASE OF FUNCTION BITS GO=1 ;START BIT ;DENSITIES FOR MTC DENSITY BITS B200=0 B556=20000 B800A=40000 ;800 BPI, 7-TRACK B800B=60000 ;800 BPI, 9-TRACK AND 7-TRACK DUMP ;FUNCTIONS FOR MTC FUNCTION BITS OFFLIN=0 ;UNIT OFFLINE READ=1 WRITE=2 WEOF=3 ;WRITE EOF FORWSP=4 ;FORWARD SPACE ONE RECORD BACKSP=5 ;BACKWARD SPACE WRITEX=6 ;WRITE EXTENDED REWIND=7 ;MTS BITS ILC=100000 ;ILLEGAL COMMAND EOF=40000 ;EOF ENCOUNTERED CRE=20000 ;CRC ERROR PAE=10000 ;PARITY ERROR BGL=4000 ;BUS GRANT LATE EOT=2000 ;EOT READ:=1 READ FORWARD,=0 READ BACKWARD RLE=1000 ;READ RECORD TOO LONG BTE=400 ;BAD TAPE NXM=200 ;NON-EXISTANT MEMORY REFERENCE SELR=100 ;=1 MEANS SELECTED UNIT OK BOT=40 ;BEGINNING OF TAPE JUST READ CH7=20 ;=1 MEANS 7 CHANNEL SDWN=10 ;=1 MEANS SLOWING DOWN WRL=4 ;WRITE PROTECTED RWS=2 ;DOING REWIND NOW TUR=1 ;READY ;MTRD GPSDN=10000 ;GAP SHUT DOWN .ENDC .IF NDF,TM11 ;TM02 DEFINITIONS ;TM02 REGISTER DEFINITIONS AND BIT DEFINITIONS RHCS1=172440 ;CONTROL AND STATUS SC=100000 ;SPECIAL CONDTION TRE=40000 ;TRANSFER ERROR MCPE=20000 ;PARITY ERROR ON MASSBUS DVA=4000 ;DRIVE AVAILABLE PSEL=2000 ;PORT SELECT A16=400 ;ADDRESS EXTENSION BITS (2) RDY=200 ;READY INTEN=100 ;INTERRUPT ENABLED FUNC=2 ;FUNCTION CODE MTNOP=0 ;NOP MTOFF=1 MTREW=3 MTCLR=4 ;DRIVE CLEAR MTEOF=13 ;WRITE END OF FILE MTEXT=12 ;ERASE MTFSP=14 ;FORWARD SPACE MTBSP=15 ;BACKSPACE MTWCHK=24 ;WRITE CHECK FORWARD MTCHKR=27 ;WRITE CHECK REVERSE MTWRT=30 ;WRITE MTREAD=34 ;READ FORWARD MTRDR=37 ;READ REVERSE GO=1 ;GO RHWC=RHCS1+2 ;WORD COUNT RHBA=RHWC+2 ;BUS ADDRESS RHFC=RHBA+2 ;FRAME COUNT RHCS2=RHFC+2 ;RH11 STATUS AND CONTROL DLT=100000 ;DATA LATE WCE=40000 ;WRITE CHEK ERROR(ONELY ON WRITE CHECK) UPE=20000 ;UNIBUS PARITY ERROR NED=10000 ;NON-EXISTANT DRIVE(OR DRIVE POWERED DOWN) NEM=4000 ;NON-EXISTANT MEMORY PGE=2000 ;PROGRAM ERROR MXF=1000 ;MISSED TRANSFER MDPE=400 ;MASSBUS PARITY ERROR OR=200 ;OUTPUT READY IR=100 ;INPUT READY CLEAR=40 ;CONTROLLWER CLEAR PAI=20 ;PARITY TEST (=0 MEANS ODD PARITY) BAI=10 ;BUFFER INCREMENT INHIBIT U=1 ;UNIT SELECT RHDS=RHCS2+2 ;DRIVE STATUS ATA=100000 ;ATENTION ACTIVE ERR=40000 ;ERROR SUMMARY(OR OF RHER BITS): COMMAND NOT ACCEPTED ;WHEN SET PIP=20000 ;POSITIONING IN PORGRESS(REWIND OR SPACE) MOL=10000 ;MEDIUM ON-LINE WRL=4000 ;WRITE LOCKED (WHEN =1) EOT=2000 ;EOT ENCOUNTERED DURING FORWARD TAPE MOTION (=1) ;=0 DURING REVERSE MOTION DPR=400 ;DRIVE PRESENT DRY=200 ;DRIVE READY SSC=100 ;SLAVE STATUS CHANGE PES=40 ;PHASE ENCODED STATUS (=0 MEANS NRZ,=1 MEANS PE) SDWN=20 ;SLOWING DOWN IDB=10 ;IDENTIFICATION BURST EOF=4 ;EOF DETECTED BOT=2 ;BEGINNING OF TAPE (=1 WHILE DETECTED) SLA=1 ;SLAVE ATTENTION (WHEN REWIND DONE, POWER FAIL RWS=0 ;REWIND STATUS NON-EXISTANT IN TM02 ;ONLINE, OFFLINE) RHER=RHDS+2 ;ERROR STATUS CORCRC=100000 ;CORRECTABLE DATA ERROR/ CRC ERROR UNS=40000 ;UNSAFE OPI=20000 ;OPERATION INCOMPLETE DTE=10000 ;DRIVE TIMING ERROR NEF=4000 ;NON-EXECUTABLE FUNCTION CSIFM=2000 ;CORRECTABLE SKEW/ILLIGAL FILE MARK FCE=1000 ;FRAME COUNT ERROR (NOT =0 AT END OF WRITE OR SPACE) BTE=400 ;BAD TAPE PEFLRC=200 ;PE FORMAT ERROR/LRC INCORRECT INCVPE=100 ;VERTICAL PARITY ERROR FPAR=40 ;FORMATTER PARITY ERROR FMT=20 ;FORMAT ERROR PAR=10 ;MASSBUS PARITY ERROR RMR=4 ;REGISTER MODIFICATION REFUSED(ATTEMPT TO LOAD ILR=2 ;ILLEGAL REGISTER ILF=1 ;ILLEGAL FUNCTION RHAS=RHER+2 ;ATTENTION SUMMARY RHDB=RHAS+4 ;DATE BUFFER RHMR=RHDB+2 ;MAINTENANCE RHDT=172466 ;DRIVE TYPE NSA=100000 ;NOT SECTOR ADDRESSED (ON) TAP=40000 ;TAPE (ON) MOH=20000 ;MOVING HEAD (OFF) CH7=10000 ;7 CHANNEL IF ON DRQ=4000 ;DRIVE REQUEST REQUIRED (OFF) SPR=2000 ;SLAVE PRESENT DT=1 ;DRIVE TYPE NUMBER (11(8)) RHSN=172470 ;SERIAL NUMBER RHTC=172472 ;TAPE CONTROL ACL=100000 ;ACCELERATION (SLAVE NOT READING OR WRITING) FCS=40000 ;FRAME COUNT LOADED TCW=20000 ;TAPE CONTROL WRITE(SET WHEN RHTC WRITTEN) EAODTE=10000 ;ENABLE ABORT ON DATA TRANSFER ERROR IFCE=4000 ;INHIBIT FCE ON SHORT RECORD DENSE=400 ;BASE OF DENSITY BITS B200=0 ;VARIOUS DENSITIES IN BPI B556=1 B800A=2 B800B=3 B1600=4 FORMAT=20 ;BASE OF FORMAT BITS F10COR=0 ;PDP-10 CORE DUMP F10.7=1 ;PDP-10 7-TRACK F10ASC=2 ;PDP-10 ASCII F10CO7=3 ;PDP-10 7-TRACK CORE DUMP F8.9=6 ;PDP-8 9-TRACK F8.7=7 ;PDP-8 7-TRACK F11.9=14 ;PDP-11 9-TRACK (OR 7-TRACK) F11.7=15 ;PDP-11 CORE DUMP(7-TRACK) F15=16 ;PDP-15 SLAVE=1 ;BASE OF UNIT BITS RHCH=172460 ;CHARACTER CHECK MTVEC=224 ;VECTOR ADDRESS ;CODE FOR FUNCTIONS AS SENT BY MONITOR OFFLIN=0 READ=1 WRITE=2 WEOF=3 FORWSP=4 BACKSP=5 WRITEX=6 REWIND=7 .ENDC ;SOFTWARE FUNCTION CODES RW=0 ;READ/WRITE CLOSE=1 DELETE=2 LOOKUP=3 ENTER=4 HWERR=1 ;HARDWARE ERROR BIT IN CSW SWERR=1 ;SW ERROR BIT IN CSW EOFBIT=20000 ;EOF ENCOUNTERED BIT IN CSW MONLOW=54 ;BASE ADDR. OF MONITOR BLKEY=256 ;OFFSET TO DIR SEG # IN USR BFR ;(MST CLR THIS BEFORE USING USR BFR) OFFSET=270 ;PTR TO Q MANAGER COMP ENTRY OFFDAT=262 ;OFFSET TO DATE OFFBUF=352 ;OFFSET TO USR BUFFER OFFSWW=272 ;OFFSET TO SW ERROR WORD .SBTTL ENTRY AND DISPATCH ROUTINE .IF DF,INIT DEBUG=0 NEWVOL=0 VOL1=0 .ENDC .IF DF,DEBUG .ENABL AMA .ASECT .=224 MTINT 0 .=1000 .ENDC ;LOAD POINT .WORD MTVEC ;MT INTERRUPT VECTOR ADDRESS .WORD MTINT-. ;OFFSET TO INTERRUPT ROUTINE .WORD PR5 ;PRIORITY MTLQE: .WORD 0 ;PTR TO LAST Q ENTRY .IF DF,DEBUG MTCQE: .WORD QEL ;PTR TO CURRENT Q ENTRY, WORD 3 .ENDC .IF NDF,DEBUG MTCQE: .WORD 0 ;PTR TO CURRENT Q ENTRY, WORD 3 .ENDC .IF DF,DEBUG QCSW: .WORD 776 ;PTR TO CSW QEL: QB: .WORD 0 ;BLOCK QF: .BYTE 0 ;FUNCTION QU: .BYTE 3 ;UNIT QCA: .WORD 0 ;ADDR QWC: 400 ;WC JSW: .WORD 0 ;X EXT=.+4 NAME: .RAD50 "FILEN EXT" .EVEN DATA=. TEST: ;NUVOL MOVB #7,QF 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 ;LOOKUP MOVB #LOOKUP,QF MOV #0,QB MOV #NAME,QCA JSR PC,WAIT ;READ MOV @#MONLOW,R0 MOV OFFBUF(R0),QCA CLRB QF MOV #1000,QWC JSR PC,WAIT INC QB ;GO BACK AND READ BLOCK 1 JSR PC,WAIT MOV #10,QB ;TRY TO READ NON-EXISTANT BLOCK JSR PC,WAIT ;CLOSE MOVB #CLOSE,QF JSR PC,WAIT ;DELETE MOV #NAME,QCA MOV #0,QB MOVB #DELETE,QF JSR PC,WAIT NEXTF: 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 ;WRITEX MOVB #-4,QF MOV PC,R0 ADD #DATA-.,R0 MOV R0,QCA MOV #-400,QWC JSR PC,WAIT ;BACKSPACE 2 MOV #2,QWC MOVB #-2,QF JSR PC,WAIT ;READ MOV @#MONLOW,R0 MOV OFFBUF(R0),QCA MOV #400,QWC CLRB QF JSR PC,WAIT ;FORWARD SPACE 1 MOV #1,QWC MOVB #-2,QF JSR PC,WAIT ;WEOF MOVB #-1,QF JSR PC,WAIT ;OFFLINE MOVB #-6,QF JSR PC,WAIT HALT ;WAIT INITIATES THE ACTION THEN WAITS FOR COMPLETION WAIT: INC (PC)+ ;SET DONE FLAG WFLAG: .WORD 0 CLR @QCSW JSR PC,MT ;START FUNCTION WLOOP: TST WFLAG ;THEN WAIT BNE WLOOP BIT #3,@QCSW BNE TMDK BIT #3,@SWWPTR BNE TMDK RTS PC ;RETURN TO CALLER WHEN FLAG S TMDK: CLR @SWWPTR CLR @QCSW RTS PC QMAN: CLR WFLAG ;CLEAR FLAG WHEN FUNCTION DONE RTS PC ;THEN RETURN TO WAIT LOOP ;SET DESIRED FUNCTION IN WF THEN START HERE START: JSR PC,WAIT HALT .ENDC MT: SUB #12,SP ;PUSH 5 DUMMY REGISTERS (ALL BUT R5) MOV SP,(PC)+ ;SAVE STACK POINTER SPSAV: .WORD 0 ;(ORIGINAL STACK POINTER) MOV @#MONLOW,R0 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 FOR LAST OP DONE .IF DF,TM11 FIN: .WORD 0 ;(=0 MEANS LAST OP DONE) BGE DUN .ENDC .IF NDF,TM11 FIN: .WORD -1 ;(=0 MEANS LAST OP COMPLETED) BGE DUN JSR PC,DRVCLR ;ENTERING HANDLER OR IF FUNC NOT DONE, ;CLEAR ALL .ENDC JSR PC,DUNDEL ;IF NOT, INIT FLAG TABLE DUN: DEC FIN ;EITHER WAY, SET FLAG<0 FOR DURATION MOV MTCQE,R0 ;GET PTR TO Q ELEMENT MOV -(R0),(PC)+ ;SAVE PTR TO CSW CSWPTR: .WORD 0 ;(PTR TO CSW) TST (R0)+ ;POINT R0 BACK TO WORD 3 MOV (R0)+,(PC)+ ;GET BLOCK BLOCK: .WORD 0 MOV (R0)+,R1 ;GET UNIT NUMBER BIC #^C3400,R1 .IF DF,TM11 MOV R1,R3 ;SAVE THE UNIT, BIS (PC)+,R1 ;SET PARITY/DENSITY BITS ;TABLE OF PARDEN PATCHES FOR VARIOUS PARITIES, DENSITITES AND TRACKS: ; DENSITY TRACK SETTING (+4000 FOR EVEN PARITY) ; 200 BPI 7 000000 ; 556 BPI 7 020000 ; 800 BPI 7 040000 ; DUMP MODE 7 060000 ; 800 BPI 9 060000 ; PARDEN: .WORD 60000 ;(PARITY/DENSITY,800BPI) MOV R1,@#MTC ;AND SET BITS IN MTC SWAB R3 ;GET UNIT INTO LO BYTE .ENDC .IF NDF,TM11 SWAB R1 ;GET UNIT INTO LO BYTE MOV R1,R3 ;AND COPY INTO R3 .ENDC MOV R3,(PC)+ ;SAVE UNIT UNIT: .WORD 0 ;(CURRENT UNIT) MOV #401,R2 ULOOP: DEC R3 ;SET BITS IN 2 BYTES BLT DUNU ;CORRESPONDING TO NUMBER OF UNIT ASL R2 BR ULOOP DUNU: MOV R2,(PC)+ UBITS: .WORD 0 ;(2 BYTES WITH UNIT BIT SET IN EACH) .IF NDF,TM11 SETMOD: JSR PC,UNOFF ;GET UNIT OFFSET MOV UNIMOD-PZ(R2),-(SP) ;AND PICK UP MODE OF THIS UNIT BIS #F11.9*FORMAT,(SP) ;SET 9-TRACK FORMAT BIT #CH7,@#RHDT ;THEN IF 7-TRACK SLAVE, BEQ CH9 BIS (PC)+,(SP) ;SET 7-TRACK FORMAT INSTEAD F11.7*FORMAT ;(7-TRACK DUMP MODE) CH9: BIS R1,(SP) ;SET THE UNIT BITS MOV (SP)+,@#RHTC ;AND MOVE THE WHOLE THING INTO THE REGISTER .ENDC MOV (R0)+,(PC)+ ;GET ADDRESS CA: .WORD 0 NEG (R0) ;MAKE WC NEGATIVE IN CASE SPACES .IF DF,TM11 MOV (R0)+,(PC)+ ;GET WC: .WORD 0 ;(WORD COUNT/LATER, BYTE COUNT) .ENDC .IF NDF,TM11 MOV (R0)+,R2 ;GET WORD COUNT MOV R2,(PC)+ ;AND SAVE IT FC: .WORD 0 ;(FRAME COUNT FOR READS, WRITES, SPACING) .ENDC ;THE FOLLOWING CODE ALTERS THE FUNCTION CODE IN WORD 8 OF THE Q ELEMENT ;FOR USE BY THE HANDLER. ;THE FUNCTION CODE COMES DOWN LIKE THIS: ; ; VALUE FUNCTION ; 0 READ/WRITE ; 1 CLOSE ; 2 DELETE ; 3 LOOKUP ; 4 ENTER .IF DF,NEWVOL ; 7 NEWVOL .ENDC ; -1 WRITE EOF ; -2 FORWARD SPACE ; -3 BACKWARD SPACE ; -4 WRITE EXTENDED GAP ; -5 REWIND ; -6 OFFLINE ; ;VALUES >0, THUS, 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=6, WRITE=7. ;ON A HW R/W IT SETS READ CODE=1, WRITE=2 MOVB -6(R0),R1 ;GET FUNCTION CODE BEQ FUN0 ;IF 0, READ OR WRITE BGT TSTFUN ;IF GREATER, SOFTWARE FUNCTION SUB #2,R1 ;IF LESS, HW FUNCT: SUB 2 BR TSTFUN .IF DF,TM11 FUN0: INC R1 ;PREPARE FOR CODE CONVERSION TST WC ;GET SIGN OF WC BLE WCGT ;WC NEG NOW MEANS CAME DOWN POS: READ INC R1 ;ELSE INC CODE NEG WC ;AND MAKE WC NEG FOR TRANSFERS WCGT: ASL WC ;MAKE WC BYTE COUNT .ENDC .IF NDF,TM11 FUN0: INC R1 ;PREPARE FOR FUNCTION CONSTRUCTION TST R2 ;GET SIGN OF WC BLE WCGT ;WC NEG MEANS WRITE INC R1 ;ELSE, INC CODE NEG R2 ;AND MAKE WC NEGATIVE WCGT: JSR PC,WCFC ;AND PUT IT IN WC AND FC .ENDC BITB UBITS,HW ;IF HW READ OR WRITE, BNE HWON ;GO NEGATE THE FUNCTION CODE ADD #4,R1 ;ELSE ADD 4 TO IT FOR DISPATCH TABLE BR TSTFUN HWON: NEG R1 TSTFUN: BGT MACRO ;FUNCTION CODE > 0 MEANS SOFTWARE FUNCTION CLRB MAC ;SET NON-MACRO MODE NEG R1 ;MAKE FUNCTION POSITIVE CMP R1,#10 ;IGNORE BAD FUNCTIONS BGT SWINIT JMP XCT ;NOW EXECUTE FUNCTION AND RTI .IF NDF,TM11 ;MODTAB CONTAINS THE FORMAT SETTINGS AVAILABLE ON THE TM02 MODTAB: .BYTE B200*DENSE/400 ;MODE 1 .BYTE B556*DENSE/400 ;2 .BYTE B800A*DENSE/400 ;3 .BYTE B800B*DENSE/400 ;4 .BYTE B1600*DENSE/400 ;5 (PE MODE ONLY) .EVEN ;UNIMOD CONTAINS THE CURRENT MODE FOR EACH SLAVE. ;THIS TABLE MAY BE PATCHED TO ALTER THE DEFAULT MODE OR ALTERED BY THE PROGRAM ;USING A NON-FILE STRUCTURED LOOKUP WITH MODE NUMBER AS THE ;BLOCK ARGUMENT. ; DENSITY CONTENTS OF MODE WORD ; 200 BPI 0 ; 556 BPI 400 ; 800 BPI 1000 ; 800 BPI 1400 ; 16000 BPI 2000 ;NO SLAVE MAY HAVE ITS MODE CHANGED EXCEPT AT BOT. UNIMOD: .WORD B800A*DENSE ;DEFAULT 800 BPI .WORD B800A*DENSE .WORD B800A*DENSE .WORD B800A*DENSE .WORD B800A*DENSE .WORD B800A*DENSE .WORD B800A*DENSE .WORD B800A*DENSE .ENDC .SBTTL FILE SERVICE ROUTINES ;FILE SERVICE ROUTINES ;MACRO DISPATCHES TO THE PROPER SOFTWARE FUNCTION. MACRO: .IF NDF,NEWVOL CMP R1,#7 ;IGNORE NON-EXISTANT FUNCTIONS .ENDC .IF DF,NEWVOL CMP R1,#10 .ENDC BPL SWINIT .IF DF,TM11 CMP PARDEN,#60000 ;IF NOT IN DUMP MODE OR 9-TRACK, BNE SWINIT ;DISALLOW SW MODE .ENDC MOV UBITS,R3 ;GET UNIT BIT MOV PC,R0 ;SET FOR FLAG TEST ADD #FLGTAB-.,R0 BICB R3,(R0)+ ;DISALLOW HW FUNCTIONS BISB R3,(R0) ;SET MACRO MODE ADD R1,R0 ;INDEX INTO FLAGS BITB R3,(R0) ;BIT SET? BNE OK ;IF NOT SET, ABORT FUNCTION SWINIT: BIS #SWERR,@SWWPTR ;SET SW ERROR BIT IN CSW BR DIDIT ;AND EXIT OK: 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 DIDIT: JMP RESP ;RETURN TO Q MANAGER MACROS=.-2 ;FUNCTION VALUES START AT 2 CLOZE-. DLEET-. LUKUP-. ENTUR-. REDE-. RIGHT-. .IF DF,NEWVOL NUVOL-. .ENDC ;FLGTAB CONTAINS A FLAG FOR EACH SOFTWARE FUNCTION AND A FLAG FOR ;HARDWARE MODE AND FOR MACROS. EACH BIT IN EACH FLAG CORRESPONDS ;TO A UNIT. ;THE TABLE WORKS LIKE THIS: ;THE FIRST TWO BYTES IN THE TABLE, HW AND MAC, REFLECT THE CURRENT ;STATUS OF THE HANDLER. HW NON-0 MEANS HARDWARE MODE IN EFFECT; HW=0 ;MEANS SOFTWARE MODE IN EFFECT. IN HARDWARE MODE, ANY HARDWARE FUNCTION ;CAN EXECUTE 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 MAC 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 ;EACH SOFTWARE FUNCTION BEFORE EXECUTING 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=. HW: .BYTE 0 ;HARDWARE INTITIALLY NOT ALLOWED MAC: .BYTE 0 ;MACRO CURRENTLY EXECTUED BYTE CLO: .BYTE 0 ;CLOSE NOT ALLOWED AT START DEL: .BYTE 377 ;DELETE ALLOWED AT START LOOK: .BYTE 377 ;LOOKUP ALLOWED ENT: .BYTE 377 ;ENTER ALLOWED AT START REED: .BYTE 0 ;READ NOT ALLOWED WRYT: .BYTE 0 ;WRITE NOT ALLOWED .IF DF,NEWVOL NEW: ;ALWAYS ALLOW NUVOL (NEXT INSTR.=377) .ENDC ;LUKUP OPENS AN EXISTING FILE FOR INPUT. ;IT POSITIONS THE TAPE TO JUST BEFORE THE 1ST DATA BLOCK. LUKUP: TST @CA ;ON NON-FILE LOOKUP, BEQ NONFIL ;GO REWIND JSR PC,SEEK ;LOOK FOR FILE SWINV: BR SWINIT ;IF NONE FOUND, RETURN ERROR LUKC: JSR PC,FSPN ;ELSE, SPACE BEYOND TAPE MARK TO DATA ENDNON: JSR PC,ENTDUN ;SET FLAG TABLE AS FOR ENTER BICB R1,-(R0) ;BUT SWAP READ AND WRITE SETTINGS BISB R1,-(R0) RTS PC ;AND RETURN NONFIL: JSR PC,REWCLR ;ON NON-FILE, REWIND BISB UBITS,HW ;SET HW MODE .IF NDF,TM11 MOV BLOCK,R1 ;GET BLOCK ARG BLE NOMOD ;IF IT'S NON-0, CMP R1,#5 ;AND <=5 BGT NOMOD ADD PC,R1 ;OFFSET ADD #MODTAB-1-.,R1 ;INTO TABLE OF AVAILABLE MODES JSR PC,UNOFF ;THEN GET AN OFFSET INTO MODES PER UNIT INC R2 ;HI BYTE MOVB (R1),UNIMOD-PZ(R2) ;AND SET THE MODE FOR CURRENT UNIT NOMOD: .ENDC NONF: JSR PC,ENTDUN ;SET FLAG TABLE AS FOR LOOKUP BIS R1,-(R0) ;BUT ALLOW BOTH READ AND WRITE RTS PC ;ENTUR OPENS A NEW FILE AT THE END OF THE TAPE BY WRITING HDR1*. ;IT DELETES FILES OF THE SAME NAME THAT IT FINDS ALONG THE WAY. ENTUR: TST @CA ;IF NON-FILE ENTER BEQ NONF ;GO DO NOTHING JSR PC,SEEK ;LOOK FOR FILE OF SAME NAME ALREADY ON TAPE BR NFOUND ;IF NOT FOUND, ENTER THE NEW FILE OPEN: TST BLOCK ;IF FOUND NUMBERED FILE, BEQ NFOUND ;DO THE ENTER OVER IT JSR PC,DELIT ;IF SAME NAME FOUND, DELETE IT JSR PC,CHKHDR ;AND CONTINUE TO SEEK LEOT BR NFOUND BR OPEN ;CONTINUE TO DELETE IF DUPLICATE FOUND AGAIN NFOUND: .IF DF,TM11 BIT #EOT,@#MTS .ENDC .IF NDF,TM11 BIT #EOT,@#RHDS ;IF AT EOT, .ENDC BEQ XXXXXX JMP HWINIT ;DISALLOW ENTER XXXXXX: BIS UBITS,(PC)+ ;INIT ENTER FLAG AND SPARE FLAG EOFS: .BYTE 0 ;(SPARE FLAG) ENTFLG: .BYTE 0 ;(BIT=1 MEANS ENTER IN PROGRESS) JSR PC,WTHDR1 ;THEN WRITE THE NEW HEADER WITH 0 COUNT JSR PC,TSTEOT ;IF EOT PASSED, JMP NULCL3 ;ABORT THIS FILE ENTDUN: JSR PC,CLRWRT ;CLEAR WRITE COUNT FOR CURRENT UNIT MOV PC,R0 ADD #CLO-.,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 RTS PC ;TSTEOT TESTS FOR TAPE AT EOT TSTEOT: .IF DF,TM11 BIT #EOT,@#MTS ;IF TAPE AT EOT, .ENDC .IF NDF,TM11 BIT #EOT,@#RHDS ;IF TAPE AT EOT, .ENDC BEQ NOEOT STEOT: JSR PC,BSPN ;BACKSPACE .IF DF,TM11 BIT #EOT,@#MTS ;IF TAPE AT EOT, .ENDC .IF NDF,TM11 BIT #EOT,@#RHDS ;IF TAPE AT EOT, .ENDC BNE STEOT RTS PC NOEOT: ADD #4,(SP) ;ADD 4 TO EITHER RETURN ADDRESS RTS PC ;SEEK PERFORMS SEARCH SEQUENCE FOR ENTER, LOOKUP, AND DELETE ;IF THE BLOCK ARG FOR EITHER IS <=0 IT WILL PRECEDE THE SEARCH WITH A REWIND AND ;A TEST OF THE VOLUME LABEL ON THE TAPE. OTHERWISE, IT WILL JUST START ;SEARCHING FROM THE CURRENT TAPE POSITION WHICH WILL ALWAYS POINT TO SOME ;HDR1 LABEL. FOR BLOCK N, N NON-0, IT WILL SPACE FORWARD N FILES ;OR UNITL IT FINDS A MATCHING NAME, WHICHEVER COMES FIRST. ;THUS, AN ENTER WITH AN ARGUMENT OF 1 WILL POSITION TO THE CURRENT FILE AND OVERWRITE IT. ;A LOOKUP WITH AN ARGUMENT OF -2 WILL REWIND THEN ;SPACE FORWARD ONE FILE. AN ARGUMENT ;GREATER IN MAGNITUDE 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 ADDR. IF FILE FOUND, SO CALLED WITH: ; JSR PC,SEEK ; BR NOTFOUND ; FOUND: ; ;IF FOUND, TAPE POSITIONED BEFORE HDR1 LABEL; ;IF NOT FOUND, BETWEEN FINAL TAPE MARKS. SEEK: MOV CA,R2 ;PT TO RAD50 NAME ADD #6,R2 ;LAST WORD JSR PC,NAMOFF ;GET OFFSET INTO NAME STORAGE ADD #11,R1 ;POINT TO LAST CHAR IN NAME MOV #3,R3 ;COUNT 3 RAD50 WORDS (9 CHARS) GET50: MOV -(R2),R0 ;GET RAD50 WORD INTO R0 MOV #3,(PC)+ ;COUNT 3 CHARS PER WORD CCNT: .WORD 0 CNVLUP: CLR R4 ;CLEAR REMAINDER MOV #20,-(SP) ;COUNT 16 BITS DIVLUP: ASL R0 ;SHIFT DIVIDEND-QUOTIENT REGISTER ROL R4 ;SHIFT REMAINDER CMP R4,#50 ;BIT ENUF TO SUBTRACT? BLO NOFIT SUB #50,R4 ;IF SO, SUBTRACT DIVISOR INC R0 ;SET CORRESPONDING BIT IN QUOTIENT NOFIT: DEC (SP) ;ANY MORE BITS? BNE DIVLUP ;IF SO, CONTINUE DIVISION TST (SP)+ ;WHEN DONE, FIX STACK TST R4 ;AND CONVERT R4 TO ASCII BEQ PSPACE ;=0 MEANS SPACE CMP R4,#32 ;LETTER (1-32) ? BLE LETTER SUB #36,R4 ;DIGIT (36-47) ? BCC DIGIT PSPACE: MOV #-40,R4 ;0,33,34,35 GIVE SPACE LETTER: ADD #20,R4 ;CONVERT (1-32) TO (101-132) DIGIT: ADD #60,R4 ;CONVERT (36-47) TO (60-71) MOVB R4,-(R1) ;INSERT CHARS IN STORAGE DEC CCNT ;DO 3 CHARS BGT CNVLUP DEC R3 ;IF DONE, DO NEXT WORD, IF ANY BGT GET50 TST BLOCK ;BLOCK 0? BGT CHKHDR ;IF GREATER, DON'T REWIND, JUST START SEARCHING NEG BLOCK ;ELSE, GET MAGNITUDE OF BLOCK SEEKC: JSR PC,REWCLR ;AND DO A REWIND FIRST JSR PC,READU ;READ VOLUME LABEL MOV CA,R0 ;GET PTR TO FIRST TWO WORDS JUST READ CMP (R0)+,#"VO ;AND MAKE SURE THEY CONTAIN 'VOL1' ;### NOVOL: BNE SWINV2 CMP (R0)+,#"L1 ;### BEQ CHKHDR SWINV2: JMP SWINV CHKHDR: JSR PC,READU ;NOW READ THE HDR1 .IF DF,TM11 BIT #EOF,@#MTS ;IF TAPE MARK READ, LEOT REACHED .ENDC .IF NDF,TM11 BIT #EOF,@#RHDS ;IF TAPE MARK READ, LEOT REACHED .ENDC BNE LEOT ;SO GO RETURN CMP @CA,#"HD ;WAS BLOCK READ A HDR1? ;+++ BNE CHKHDR ;NO-TRY NEXT ;+++ DEC BLOCK ;DEC BLOCK ARGUMENT BEQ FOUND ;IF =0, RETURN AS FILE FOUND JSR PC,NAMOFF ;ELSE, COMPARE NAME SOUGHT (R1) MOV CA,R0 ;WITH NAME FROM HDR1 JUST READ ADD #HDRNAM-HDR,R0 MOV #9.,R3 ;TOTAL OF 9 CHARACTERS CMPLOP: CMPB (R0)+,(R1)+ ;COMPARE CHARACTERS ;### BNE DOTSP ;IF NOT EQUAL, CHK DOT IN NAME ;### DEC R3 BGT CMPLOP ;IF FOUND, RETURN FOUND: ADD #2,(SP) ;ON FOUND, BUMP RETURN ADDR. LEOT: MOV #-1,R0 ;IF LEOT REACHED, SPACE BACK ONE JMP BSP ; JSR PC,BSP ;### ; RTS PC ;### SEEKIT: JSR PC,NXTFIL ;ELSE, SPACE PAST 3 TAPE MARKS BR CHKHDR ;AND CONTINUE SEEKING ; ;DOTSP-- FOR RSX COMPATIBILITY, FILENAMES LIKE 'ABC.DAT' ON MAGTAPE ;ARE CORRECTLY MATCHED TO NAMES LIKE 'ABC DAT' PASSED TO THE ;HANDLER. DOTSP DOES THIS EQUIVALENCING IN THE CMPLOP OF FILENAMES ; DOTSP: CMPB -(R0),#'. ;NXT CHAR A DOT? ;### BNE SEEKIT ;IF NE-NO-KEEP LOOKING ;### CMPB (R0)+,-(R1) ;YES-ADJUST POINTERS ;### CMP R3,#3 ;IS DOT IN COL 7 OF STRING? ;### BEQ CMPLOP ;IF EQ-YES-JUST IGNORE IT ;### CMPB (R1)+,#' ;NO-BUT DOT MATCHES BLANK IN FILNAM;### BNE SEEKIT ;IF NE-NOT SPACE-KEEP LOOKING ;### DEC R0 ;SPACE-KEEP COMPARING W/ DOT ;### BR CMPLOP ; ;### ;NAMOFF CALCULATES THE ADDRESS OF THE FILE NAME FOR THE CURRENT UNIT AND ;RETURNS IT IN R1. ;ALTERS R1 AND R4. NAMOFF: MOV UNIT,R4 ;GET UNIT MOV PC,R1 ADD #SNAME-11-.,R1 ;POINT TO STORAGE AREA ROOM: ADD #11,R1 ;THEN COUNT UP TO CURRENT UNIT DEC R4 ;WHILE INCREASING POINTER BGE ROOM RTS PC SNAME: .BLKB 11*10 ;STORAGE FOR 8 ASCII FILE NAMES ;REWCLR REWINDS AND CLEARS THE FILE COUNT FOR CURRENT UNIT BY FALLING INTO CLRFIL ;### ;### IF FILES NOT BEING COUNTED, JUST REWIND AND RTN. REWCLR: .IFDF FCNT JSR PC,SOFT ;### REWIND ;### ;CLRFIL CLEARS THE COUNT OF FILES PASSED, I.E. THE CURRENT FILE POSITION CLRFIL: JSR PC,UNOFF ;OFFSET FOR CURRENT UNIT MOV #1,FILCNT-PZ(R2) ;AND SET ITS COUNT TO 1ST FILE ;### RTS PC .IFF JSR PC,SOFTNR ;REWIND ;### REWIND .IFT FILCNT: .WORD 1 ;### .WORD 1 ;### .WORD 1 ;### .WORD 1 ;### .WORD 1 ;### .WORD 1 ;### .WORD 1 ;### .WORD 1 ;### .ENDC ;FCNT ;DLEET DELETES A FILE BY WRITING A NEW HDR1 OVER ITS HDR1. ;THEN IT WRITES AN EOF BEFORE OR OVER THE 1ST DATA RECORD OF THE FILE. ;(ALL FILES HAVE AT LEAST ONE RECORD.) DLEET: .IF DF,NEWVOL TST @CA ;TEST FOR NULL FILE NAME BEQ NUVOL ;WHICH MEANS INITIALIZE VOLUME .ENDC JSR PC,SEEK ;FIND THE FILE BR SWINV2 ;IF NONE FOUND AND BLOCK NOT 0, QUIT RUBOUT=377 ;DELETED FILES START WITH RUBOUT DELIT: MOVB #RUBOUT,HDRNAM ;ELSE, WRITE HDR1 WITH BAD FILE NAME MOV PC,R0 ADD #HDR1-.,R0 ;LABEL PROTO-TYPE CORRECTLY, JSR PC,WRTHDR ;AND WRITE DUMMY HEADER OVER HDR1 LABEL JSR PC,BSPN ;BACKSPACE TO BEG OF FILE (TM11 WILL NOT ;ALLOW YOU TO FSPACE AFTER WRITE) JSR PC,NXTFIL ;THEN SPACE TO END OF FILE BR DUNDEL ;THEN GO SET UP FLAG TABLE (SAMELY AS CLOSE) ENDCLO: JSR PC,NXT2 ;SPACE TO END OF FILE BR DUNDEL ;THEN GO SETUP FLAG TABLE (SAMELY AS CLOSE) .IF DF,NEWVOL ;NUVOL INTIALIZES A TAPE WITH 'VOL1 **' ;### NUVOL: JSR PC,REWCLR ;REWIND TAPE ; MOV PC,R0 ;### ; ADD #VOL-.,R0 ;POINT TO VOLUME LABEL ;### ; MOV R0,CA ;### JSR PC,BFADR ;ADDRESS OF USR BUFFER ;### 1$: MOV #" ,-(R2) ;SET BFR TO SPACES ;### CMP R2,R0 ;AT BEGIN OF BFR YET? ;### BNE 1$ ;IF NE-NO ;### MOVB #'1,79.(R0) ;ANSI STANDARD LEVEL ;### MOV #"VO,(R0)+ ;CREATE VOLUME LABEL ;### MOV #"L1,(R0)+ ; ;### MOV #"RT,(R0)+ ; VOL ID ;### MOV #"11,(R0)+ ; ;### MOV #"01,(R0)+ ; ;### ADD #27.,R0 ;POINT TO VOL OWNER (C.P. 38.) ;### MOVB #'D,(R0)+ ; OWNER ID ;### MOV #"D%,(R0)+ ; (DD%% FOR RSX) ;### MOVB #'%,(R0)+ ; ;### JSR PC,WRTLAB ;WRITE IT ; JSR PC,NAMOFF ;POINT TO NAME SLOT FOR THIS UNIT ;### ; MOVB #RUBOUT,(R1) ;AND DUMMY IT UP ;### ; JSR PC,WTHDR1 ;THEN WRITE THE DUMMY HDR1 ;### ; JSR PC,CLRWRT ;CLEAR WRITE COUNT ;### CLR BLKCTR-PZ(R2) ;CLEAR WRITE COUNT ;### JSR PC,WRTEOF ;WRITE FIRST TAPE MARK ;### BR DUNFIL ;WRITE SECOND T.M.,FINISH UP ;### .ENDC ;NXTFIL SPACES FORWARD 3 TAPE MARKS LEAVING THE TAPE POSITIONED TO ;THE START OF NEXT FILE HDR1 SEQUENCE NXTFIL: JSR PC,FSPN ;SPACE FORWARD 3 EOF'S NXT2: .IFDF FCNT JSR PC,FSPN .IFF JSR PC,(PC) ;!!!!!!CAREFUL!!!!!!!!!!! ;### .ENDC ;FCNT NXT1: JSR PC,FSPN INCFIL: JSR PC,UNOFF ;GET OFFSET FOR THIS UNIT .IFDF FCNT INC FILCNT-PZ(R2) ;AND INC ITS FILE COUNT ;### .ENDC ;FCNT RTS PC ;CLOZE CLOSES A FILE. A CLOSE OF AN ENTER'ED FILE (INDICATED BY ;THE WRYT FLAG SET IN FLAG TABLE) WRITES AN EOF1 LABEL FOLLOWED BY AN EOF. ;A CLOSE OF A LOOKUP SPACES FORWARD PAST THE END OF THE FILE. ;IT MUST SPACE FORWARD 2 EOF'S TO DO THIS UNLESS THE LAST READ ;READ AN EOF (INDICATED BY REED FLAG CLEARED IN FLAG TABLE) ;IN WHICH CASE IT MUST SPACE FORWARD 1 EOF. CLOZE: BITB UBITS,WRYT ;IF WRITE NOT ALLOWED, BEQ ENDCLO ;GO CLOSE A LOOKUP BITB UBITS,REED ;IF BOTH READ AND WRITE ALLOWED BNE DUNDEL ;DO NON-FILE CLOSE ENTCLO: BIS UBITS,EOFS ;SET FLAG TO SAY CLOSE IN PROGRESS ; JSR PC,UNOFF ;GET UNIT OFFSET ;+++ ; TST BLKCTR-PZ(R2) ;AND IF NO WRITES TO THIS UNIT, NULL FILE ;+++ ; BEQ NULL ;GO DELETE IT ;+++ CLOZ1: JSR PC,WRTEOF ;ELSE, WRITE TAPE MARK AFTER DATA JSR PC,WTEOF1 ;THEN EOF1 WITH CORRECT BLOCK CNT JSR PC,INCFIL ;COUNT THIS FILE DUNFIL: JSR PC,WRTEOF ;THEN DOUBLE TAPE MARK (LEOT) JSR PC,BSPN ;LEAVE POINTING BETWEEN FINAL MARKS DUNDEL: MOV PC,R0 ADD #CLO-.,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 RTS PC NULL: ; TST FILCNT-PZ(R2) ;ALLOW NULL FILE 0 ;### ; BEQ CLOZ1 ;GO CLOSE IT ;### NULCLO: JSR PC,BSPN ;TO ABORT OTHER FILES, SPACE TO HDR1 NULCL2: JSR PC,BSPN .IF NDF TM02 ;+++ BIT #BOT,@#MTS ;AT BOT? ;+++ .IFF ;+++ BIT #BOT,@#RHDS ;AT BOT? ;+++ .ENDC ;TM02 ;+++ BEQ NULCL3 ;IF EQ-NO ;+++ MOV #-1,R0 ;YES-SPACE OVER VOL1 LABEL ;+++ JSR PC,FSP ;+++ JSR PC,WRTEOF ;AND WRITE FIRST TAPE MARK ;+++ BR DUNFV ;GO WRITE SECND T.M. AND CLN UP ;+++ NULCL3: JSR PC,FSPN ;NOT BOT-SPACE PAST TAPE MARK ;+++ DUNFV: JSR PC,DUNFIL ;THEN END TAPE AND SET FLAGS HWEX: JMP HWINIT ;AND SET ERROR ;REDE DOES RANDOM READS OF THE CURRENT FILE. ;IF IT RECEIVES A BLOCK ARGUMENT EQUAL TO THE CURRENT BLOCK COUNT, ;IT JUST READS THE BLOCK. ON A LARGER BLOCK, IT SPACES FORWARD ;AND DOES THE READ (IF IT ENCOUNTERS EOF IT BACKSPACES AND CORRECTLY ;SETS THE WRITE COUNT). ON A SMALLER BLOCK IT BACKSPACES, THEN DOES THE ;READ. IF EOF OCCURS DURING THE READ, REDE WILL ZERO OUT THE REMAINDER ;OF THE INPUT BUFFER. ON READ WITH WC=0, REDE INPUT ONE ENTIRE RECORD ONLY AND ;DOES NOT CLEAR THE INPUT BUFFER. REDE: MOV WC,R4 ;SAVE WC BEQ READIT ;ON WC=0, DO READ FROM CURRENT POSITION MOV BLOCK,R0 ;R0=BLOCK-BLKCTR JSR PC,UNOFF ;GET UNIT OFFSET ADD #BLKCTR-PZ,R2 ;AND SAVE ADDRESS OF BLOCK COUNT SUB (R2),R0 ;USE IT FIRST TO DO SUBTRACTION BEQ READIT ;IF BLOCK=BLKCTR, DO THE READ MOV BLOCK,(R2) ;ELSE, SET BLKCTR=BLOCK TST R0 BLT BAKBLK ;IF BLOCK WAS < BLKCTR, GO BACKSPACE NEG R0 ;ELSE, FORWARD SPACE BLOCK-BLKCTR JSR PC,FSP .IF DF,TM11 BIT #EOF,@#MTS ;IF NO EOF ENCOUNTERED, .ENDC .IF NDF,TM11 BIT #EOF,@#RHDS ;IF NOEOF ENCOUNTERED, .ENDC BEQ READIT ;GO START READING .IF DF,TM11 ADD @#MTBRC,(R2) ;ELSE, BLKCTR=BLOCK+MTBRC-1 .ENDC .IF NDF,TM11 ADD @#RHFC,(R2) ;ELSE, BLKCTR=BLOCK+FC-1 .ENDC DEC BLKCTR BADRD: BIS #EOFBIT,@CSWPTR ;SET EOF BIT IN CSW JSR PC,BSPN ;BACKSPACE OVER EOF MOV CA,R2 ;NOW GET CURRENT ADDRESS CLRLUP: CLRB (R2)+ ;AND CLEAR OUT WORDS NOT TRANSFERRED INC R4 BLT CLRLUP JMP SWINIT ;THEN EXIT BAKBLK: JSR PC,BSP ;BACK SPACE BLOCK-BLKCTR READIT: MOV R4,WC ;SET WC TO REMAINDER (TOO BIG DOESN'T HURT) JSR PC,READB1 ;AND READ .IF DF,TM11 BIT #EOF,@#MTS ;ON EOF ENCOUNTERED, INSTEAD .ENDC .IF NDF,TM11 BIT #EOF,@#RHDS ;ON EOF ENCOUNTERED, INSTEAD .ENDC BNE BADRD ;GO SET ERROR BIT JSR PC,INCBLK ;ELSE, INCREMENT BLOCK COUNT JSR PC,TSTMOR ;AND TEST FOR MORE BLOCKS TO READ BR READIT ;IF SO, READ ON ;RIGHT WRITES A RECORD FROM THE ADDR. SPECIFIED BY ;THE CURRENT ADDR. WORD IN THE Q ELEMENT RIGHT: MOV WC,R4 ;SAVE WC ;TEST FOR BLOCK 0 REWIND ;TESTS FOR BLOCK 0 IN Q ELEMENT. ;### ;IF SO IT POSITIONS TAPE TO THE ;### ;FIRST RECORD OF THE FILE. ;### TSTBAK: TST BLOCK ;BLOCK 0? ;### BNE NOTZER ;NOT ZERO ;### JSR PC,BSPN ;IF 0, BACKSPACE ALOT ;### JSR PC,FSPN ;THEN FORWARD BEYOND MARK ;### JSR PC,CLRWRT ;CLR CNT OF RECORDS WRITTEN ;### NOTZER: BLT NULCLO ;ON BLOCK <0 ABORT THIS FILE DORITE: JSR PC,WRITD ;ELSE, DO THE WRITE JSR PC,TSTEOT ;IF AT EOT, JMP NULCL2 ;ABORT THIS FILE JSR PC,TSTMOR ;TEST FOR MORE WRITES TO DO BR DORITE ;SUBR RETURNS IF SO ;TSTMOR TESTS WHETHER ORIG. WC (IN R4) COMPLETELY SPENT. IF SO, IT RETURNS ;TO EXIT SEQUENCE. IF NOT, IT INCREMENTS THE CA AND THE WC (R4), THEN ;RETURNS TO CALLER FOR ANOTHER I/O OPERTION. TSTMOR: DEC R4 ;DEC WC IN CASE CAME DOWN = 0 .IF DF,TM11 ADD #513.,R4 ;INCREASE ORIG. WC BY 512. .ENDC .IF NDF,TM11 ADD #257.,R4 ;INCREASE WC BY 1 BLOCK .ENDC BCS POPOFF ;IF STILL <0, DO ANOTHER OPERATION DOMOR: ADD #512.,CA ;BEFORE OPERATION, ALTER CA RTS PC POPOFF: TST (SP)+ ;TO EXIT, POP OFF LAST JSR RTS PC ;AND RETURN TO DISPATCH CODE ;WRITD PERFORMS WRITE SERVICE. WRITD: .IF DF,TM11 WRTLAB: MOV #-1000,WC ;SET BYTE COUNT TO 512 .ENDC .IF NDF,TM11 WRTLAB: MOV #-400,R2 ;SET WORD COUNT TO 256 JSR PC,WCFC ;SET WC AND FC .ENDC JSR PC,SOFT ;THEN WRITE IT WRITE INCBLK: JSR PC,UNOFF ;OFFSET FOR CURRENT UNIT INC BLKCTR-PZ(R2) ;AND INCREMENT WRITE COUNT FOR THAT UNIT RTS PC ;THEN GO GET NEW CA BLKCTR: .BLKW 10 ;COUNT OF RECORDS WRITTEN FOR 8 UNITS ; ; GET ADR OF USR BUFR INTO R0, END OF BFR INTO R2 ; BFADR: MOV @#MONLOW,R0 ;BASE OF RMON INTO R0 CLR BLKEY(R0) ;CLR DIR SEG # IN CORE ;### MOV OFFBUF(R0),R0 ;SWAP ADDR OF USR FROM MONITOR MOV R0,R2 ;END OF BUFR ADDR TO R2 ;### SUB #512.,R0 ;THE USR BUFFER STARTS TWO BLOCKS BELOW USR MOV R0,CA ;POINT CA TO USR BUFFER RTS PC ;### ;READB PERFORMS READ SERVICE. READU: JSR PC,BFADR ;GET BFR ADR, SET CA ;### READB: .IF DF,TM11 MOV #-80.,WC ;SET WC TO 80. ;### .ENDC .IF NDF,TM11 MOV #-40.,R2 ;SET WORD COUNT ;### JSR PC,WCFC ;SET WC, FC, AND CA .ENDC READB1: JSR PC,SOFTNR ;### READ .IF NDF,TM11 ;WCFC SETS UP THE WC REG. WITH THE WORD COUNT SENT DOWN IN R2 BY THE CALLING ;ROUTINE. IT THEN CALCULATES THE FRAME COUNT BY MULTIPLYING BY 2 FOR ;9-TRACK FORMAT AND BY 4 FOR 7-TRACK. WCFC: MOV R2,(PC)+ ;SET WORD COUNT TO VALUE IN ARG. WC: .WORD 0 ;(WORD COUNT FOR XFER OPERATIONS) ASL R2 ;*2 FOR 9-TRACK MODE BIT #CH7,@#RHDT ;IF 7-TRACK SLAVE, BEQ TNINE ASL R2 ;*2 AGAIN TNINE: MOV R2,FC ;PUT THIS INTO FRAME COUNT RTS PC .ENDC ;FSPN SPACES FORWARD TO NEXT TAPE MARK FSPN: CLR R0 ;SET WC FOR VERY BIG SPACE FORWARD ;FSP SPACES FORWARD R2 RECORDS. FSP: .IF DF,TM11 MOV R0,WC ;GET AMT TO SPACE .ENDC .IF NDF,TM11 MOV R0,FC ;GET AMT TO SPACE .ENDC JSR PC,SOFTNR ;AND SPACE FORWARD TILL IT ABORTS ;### FORWSP ;HAVING REACHED A TAPE MARK ;BSPN SPACES BACK PAST THE LAST TAPE MARK BSPN: CLR R0 ;BSP SPACES BACK R2 RECORDS BSP: .IF DF,TM11 MOV R0,WC ;GET AMT TO SPACE .ENDC .IF NDF,TM11 MOV R0,FC .ENDC JSR PC,SOFTNR ;### BACKSP ;WTHDR1 WRITES HDR1 WTHDR1: CLR R3 ;SET BLOCK COUNT TO 0 .IFDF FCNT MOV #HDR1-FILSEQ,-(SP) ;MOVE ADDR OF HDR1 TO STACK ;### BR WRTHD2 ;PUT NAME AND BLKCNT INTO HDR AND WRITE ;### .IFF JSR PC,NAMBLK ;AND INSERT IT AND NAME IN LABEL ADD #HDR1-BLKCNT-1,R0 ;POINT TO 'HDR1' BR WRTHDR ;AND GO WRITE LABEL .ENDC ;FCNT ;WTEOF1 WRITES AND EOF1 LABEL AND * WTEOF1: JSR PC,UNOFF ;OFFSET FOR CURRENT UNIT MOV BLKCTR-PZ(R2),R3 ;AND GET COUNT OF BLOCKS WRITTEN .IFDF FCNT MOV #EOF1-FILSEQ,-(SP) ;MOV ADDR OF 'EOF1'TO STACK ;### WRTHD2: JSR PC,NAMBLK ;INSERT COUNT AND NAM INTO LABEL ;### ADD (SP)+,R0 ;ADDR OF HDR IDENTIFIER TO R0 ;### .IFF JSR PC,NAMBLK ;INSERT COUNT AND NAME INTO LABEL ADD #EOF1-BLKCNT-1,R0 ;POINT TO 'EOF1' .ENDC ;FCNT WRTHDR: MOV PC,R2 ;### ADD #HDR-.,R2 ;### MOV R2,CA ;SET ADDRESS TO THAT OF HEADER ;### MOV (R0)+,(R2)+ ;INSERT EITHER "HDR1" OR "EOF1" ;### MOV (R0)+,(R2) ;### .IF DF,ASCDAT ;USE BLANKS FOR DATE UNLESS ANSI STANDARD ;THE FOLLOWING SECTION OF CODE CONVERTS THE DATE FROM RT-11 FORMAT TO ;JULIAN DATE IN ASCII,AND STUFFS THE DATE INTO THE HEADER PRIOR TO WRITING IT MOV @#54,R2 MOV OFFDAT(R2),R2 ;DATE INTO R2 MOV R2,R1 ;COPY DATE INTO R1 ASR R1 ;MOVE MO RIGHT ONE BIC #140777,R1 ;LEAVE MO BITS SWAB R1 ;MONTH*2 IN R1 MOV PC,R4 ADD #MONTAB-.,R4 ;R4 POINTS TO MONTAB ADD R1,R4 MOV (R4),R3 ;R3=NO OF DAYS TO FIRST OF THIS MONTH CMP R1,#4 ;IS MO= JAN OR FEB? BLE 1$ ;YES-THEN FEB 29 CAN'T BE HERE YET MOV R2,R1 ;DATE TO R1 ROR R1 ROR R1 BCS 1$ BMI 1$ ;IF BOTH BITS 0 AND 1 OF DATE=0,THEN LEAP YEAR INC R3 ;AND THERE IS EXTRA DAY AROUND 1$: MOV R2,R1 ;DATE INTO R1 ASR R1 ASR R1 ASR R1 ASR R1 ASR R1 ;DAYS INTO BITS 0-4 BIC #177740,R1 ;LEAVE DATE THIS MO IN R1 ADD R1,R3 ;TOTAL # OF DAYS THIS YEAR IN R3 BIC #177740,R2 ;LEAVE YEAR IN R2 BEQ 2$ ;IF YR=0,MEANS NO YEAR,NOT 1972 ADD #110,R2 ;YEAR +1972 IN R2 2$: MOV PC,R0 ADD #CDATE+1-.,R0 ;R0 POINTS TO DATE STRING .IFDF FCNT MOV #5,R1 ;SET COUNT FOR MAKTEN ;### .ENDC ;FCNT JSR PC,MAKTEN ;CONVERT DAY TO 3 ASCII CHARS IN HEADER MOV R2,R3 ;YEAR INTO R3 SUB #3,R4 ;BACK PTR BY 3 OVER JUST COMPLTED DAY DIGITS JSR PC,RLOOP ;CONVERT YEAR TO TWO ASCII CHARS IN HEADER .ENDC JSR PC,WRTLAB ;AND WRITE THE HEADER WRTEOF: JSR PC,SOFTNR ;FOLLOWED BY EOF ;### WEOF ; ; CLEAR COUNT OF RECORDS WRITTEN ;### ; CLRWRT: JSR PC,UNOFF ;OFFSET FOR CURRENT UNIT CLR BLKCTR-PZ(R2) ;CLEAR COUNT OF RECORDS WRITTEN NOT0: RTS PC ;MONTAB CONTAINS 12 ENTRIES ONE FOR EACH MONTH EACH CONTAINING THE TOTAL ;NUMBER OF DAYS IN A NON-LEAP YEAR UP TILL THE START OF THAT MONTH. JAN=0 ;0 DAYS UP TO JANUARY FEB=JAN+31. MAR=FEB+28. APR=MAR+31. MAY=APR+30. JUN=MAY+31. JUL=JUN+30. AUG=JUL+31. SEP=AUG+31. OCT=SEP+30. NOV=OCT+31. NOEL=NOV+30. MONTAB: 0 ;IF NO DATE SPECIFIED,MO=0 JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV NOEL ;NAMBLK INSERTS THE FILE NAME FOR THE CURRENT UNIT AND THE BLOCK ;COUNT CONTAINED IN R1 INTO THE LABEL PROTOTYPE ;ALTERS R0,R1, AND R4. NAMBLK: JSR PC,NAMOFF ;GET FILE NAME STORAGE OFFSET INTO R1 MOV PC,R0 ADD #HDRNAM-.,R0 ;THEN PT TO NAME SLOT IN PROTOTYPE MOV #11,R4 ;AND INSERT ALL 9 CHARACTERS CLOOP: MOVB (R1)+,(R0)+ CMP R4,#4 ;DONE MOVING IFLENAME ;### BNE 1$ ;IF NE-NO ;### MOVB #'.,(R0)+ ;YES-PUT A DOT AFTER IT ;### 1$: DEC R4 ;### BGT CLOOP ADD #BLKCNT-HDRNAM-12+1,R0 ;THEN POINT TO BLOCK COUNT ;### .IFDF FCNT MOV #5,R1 ;SET R1 FOR MAKTEN ;### JSR PC,MAKTEN ;CNVT IT ;### ADD #FILSEQ-BLKCNT-1,R0 ;POINT TO FILSEQ IN HEADER ;### JSR PC,UNOFF ;### MOV FILCNT-PZ(R2),R3 ;GET FILE COUNT ;### MOV #4,R1 ;SET COUNT FOR MAKTEN ;### .ENDC ;FCNT ;AND FALL THROUGH TO MAKTEN ;MAKTEN CONVERTS A BINARY WORD INTO ITS ASCII DECIMAL EQUIVALENT. ;IT DOES THIS BY COUNTING UP TO THE VALUE OF THE WORD IN DECIMAL. ;THUS, EACH COUNT INCREASES THE ASCII VALUE OF THE LOWEST SIGNIFICANT ;DIGIT, OVERFLOWS INCREASING THE COUNT IN THE NEXT HIGHER SIGNIFICANT ;DIGIT AND CLEARING THE DIGIT THAT OVERFLOWED. ;CALLED WITH BINARY VALUE IN R3, LOCATION TO PUT 6 CHARACTER DECIMAL ;VALUE IN R0. ;ALTERS R1, R3, AND R4. ;IF FCNT IS DEFINED, MAKTEN REQIRES THAT R1 BE SET UP ;### MAKTEN: MOV R0,R4 ;1ST ZERO OUT THE COUNT .IFNDF FCNT MOV #5,R1 ;INITIALIZE 5 CHARS TO 0 .ENDC ;FCNT 1$: MOVB #60,(R4)+ ;INIT CHAR DEC R1 ;DONE? BGT 1$ ;NO ; DEC R4 ;POINT IT TO LAST DIGIT ;### RLOOP: MOV R4,R1 ;GET POINTER TO RIGHTMOST DIGIT DEC R3 ;COUNT DOWN BLT NOT0 ;WHEN LESS THAN 0, RETURN TENLOP: INCB -(R1) ;INCREMENT CURRENT DIGIT ;### CMPB (R1),#72 ;OVERFLOW? BLT RLOOP ;NO, KEEP COUNTING MOVB #60,(R1) ;YES, CLEAR THIS DIGIT ; DEC R1 ;POINT TO NEXT DIGIT (ONE BYTE EARLIER) BR TENLOP ;AND GO INCREMENT IT HDR1: .ASCII "HDR1" ;HDR1 LABEL EOF1: .ASCII "EOF1" ;EOF1 LABEL ;HDR1 CONTAINS THE PROTOTYPE HDR1 OR EOF1, 80 BYTES LONG HDR: .ASCII "HDR1" ;LABEL NAME HDRNAM: .ASCII " " ;FILE NAME, 17 CHARACTERS BLANK=HDRNAM+10. ;POINT TO STRING OF SPACES FILSET: .ASCII "RT1101" ;FILE SET, -AGREES WITH VOL ID ;### FILSEC: .ASCII "0001" ;FILE SECTION ;### FILSEQ: .ASCII "0001" ;FILE SEQUENCE NUMBER ;### FILGEN: .ASCII "0001" ;GENRATION NUMBER ;### FILVER: .ASCII "00" ;VERSION NUMBER CDATE: .ASCII " 00000" ;DATE: SPACE +YEAR*1000+DAY XDATE: .ASCII " 00000" ;EXPIRATION DATE ACCESS: .ASCII " " ;ACCESSIBILITY BLKCNT: .ASCII "00000" ;BLOCK COUNT (1ST 5 CHARACTERS OF IT) BLKDIG: .ASCII "0" ;LAST CHAR OF BLOCK COUNT SYSTEM: .ASCII "RT11 " ;SYSTEM ID SPACES: .ASCII " " ;7 SPACES ENDS IT ; VOL: .ASCII "VOL1" .IF DF,NEWVOL .IF DF,VOL1 ;USE COMPLETE VOL1 ONLY IF VOL1 DEFINED ;VOLUME LABEL PROTOTYPE ; VOLID: .ASCII " " ;VOLUME ID ; VOLACC: .ASCII " " ;ACCESSIBILITY ; .ASCII " " ;BLANKS ; VOLOWN: .ASCII "DD%% " ;OWNER ID ; .ASCII " " ;BLANKS ; VOLVER: .ASCII "1" ;ANSI VERSION NUMBER ;### .EVEN .ENDC .ENDC ;UNOFF RETURNS IN R2 A WORD OFFSET BASED ON THE CURRENT UNIT. UNOFF: MOV UNIT,R2 ;GET UNIT ASL R2 ;*2 FOR WORD OFFSET ADD PC,R2 ;AND ALLOW PIC PZ: RTS PC ;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. ;NOTE-SOFTNR IS AN ALTERNATIVE TO SOFT. THE FOLLOWING TWO ;SETS OF CODE DO THE SAME THING: ; ; JSR PC,SOFT JSR PC,SOFTNR ; (FUNC) (FUNC) ; RTS PC ; SOFTNR: MOV @(SP)+,R1 ;GET ARG.-POP RETN OFF STACK ;### BR SFT1 ;GO ON LIKE SOFT ;### SOFT: MOV @(SP),R1 ;GET ARGUMENT ADD #2,(SP) ;BUMP RETURN SFT1: MOV PC,R0 ;POINT R0 TO STACK STORAGE AREA ;### ADD #STAK-.,R0 SPLOP: MOV (SP)+,(R0)+ ;AND SAVE STACK CMP SP,SPSAV ;UP TO THE MONITOR JSR OR THE INTERRUPT BMI SPLOP MOV R2,(R0)+ ;ALSO SAVE NEEDED REGISTERS MOV R4,(R0)+ MOV R0,(PC)+ ;THEN SAVE POINTER TO LAST REG. SAVED R0SAV: .WORD 0 ;(PTR TO TOP OF STACK STORAGE) ;FALL THRU TO XCT THE FUNCTION 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 DISPATCHES TO A ROUTINE TO CHECK WHETHER THE HW WILL ALLOW ;THE FUNCTION. .IF DF,TM11 ;IF SO, IT SETS THE RETRY COUNT TO 10, CLEARS THE RETRY- ;IN-PROGRESS (BIP) FLAG, INITIATES THE FUNCTION AND RETURNS TO THE INTERRUPTED ROUTINE. .ENDC .IF NDF,TM11 ;IF SO, IT CLEARS RETRY COUNT AND RETRY IN PROGRESS FLAG (RIP), INITIATES ;THE FUNCTION, AND RETURNS TO THE INTERRUPTED ROUTINE. .ENDC ;IF NOT, IT SETS THE HW ERROR BIT AND RETURNS TO THE Q MANAGER. ;ALTERS R0, R1 AND R3. XCT: BIC #177770,R1 ;MOD 10 (OFFLIN COMES DOWN AS 10) MOV R1,CURFUN ;AND SAVE IT TSTB MAC ;IF MACRO CALLING, BNE DOIT ;DO ANY FUNCTION BITB UBITS,HW ;IF CURRENTLY IN HW MODE, BNE DOHW ;DO ANY HW FUNCTION CMP R1,#REWIND ;ELSE, ALLOW ONLY REWIND BEQ DOREW JMP SWINIT ;IF NOT, ABORT WITH SW ERROR DOREW: .IFDF FCNT JSR PC,CLRFIL ;CLEAR FILE COUNT ;### .ENDC ;FCNT BISB UBITS,HW ;TURN HW MODE ON DOHW: MOV R1,-(SP) ;SAVE R1 AROUND SUBR JSR PC,DUNDEL ;ON ANY HW FUNCTION, RESET SW FLAG TABLE MOV (SP)+,R1 .IF DF,TM11 DOIT: MOV #12,(PC)+ ;SET RETRIES TO 10 .ENDC .IF NDF,TM11 DOIT: CLR (PC)+ ;CLEAR RETRY COUNTER .ENDC RETRY: .WORD 0 ;(NUMBER OF RETRIES) .IF DF,TM11 MOV #MTS,R3 ;POINT TO MTS ASL R1 ;ASL FOR DISPATCH AND FOR REGISTER LOAD MOV R1,R0 .ENDC .IF NDF,TM11 MOV #RHDS,R3 ;POINT R3 TO RHDS REGISTER MOV R1,R0 ASL R0 ;ASL FOR DISPATCH .ENDC ADD PC,R0 ADD #CHKSUB-.,R0 ;INDEX FUNCTION INTO TABLE OF ADD (R0),PC ;ADD OFFSET TO ROUTINE CHKSUB: OFFCHK-CHKSUB RDCHK-CHKSUB WRTCHK-CHKSUB EOFCHK-CHKSUB FSPCHK-CHKSUB BSPCHK-CHKSUB EXTCHK-CHKSUB REWCHK-CHKSUB WRTCHK:EOFCHK:EXTCHK: JSR PC,WENABL ;CHECK FOR WRITE ENABLE RDCHK:FSPCHK: JSR PC,NOTEOT ;MAKE SURE NOT AT END OF TAPE OFFCHK: JSR PC,READY ;MAKE SURE UNIT READY ; BR RETURN ;IF OK,BACK TO INSTR AFTER CALL ;### ;ERROR TESTING ROUTINES RETURN HERE IF FUNCTION OK TO EXECUTE. RETURN: .IF NDF,TM11 RERE: CLRB RIP ;CLEAR RETRY FLAG MOV CA,@#RHBA ;SET CURRENT ADDRESS MOV WC,@#RHWC ;SET WORD COUNT MOV FC,@#RHFC ;AND FRAME COUNT SETFUN: ADD PC,R1 ;POINT TO TABLE OF FUNCTION CODES ADD #FUNCOD-.,R1 MOVB (R1),R1 ;GET FUNCTION CODE SETF1: MOV R1,(PC)+ ;SAVE FUNCTION CODE CS1: .WORD 0 ;(LAST FUNCTION EXECUTED) SETGO: MOV (SP)+,R4 ;RESTORE REG.S MOV (SP)+,R2 MOV (SP)+,R1 MOV (SP)+,R0 MOV (SP)+,R3 MOV CS1,@#RHCS1 ;NOW INITIATE THE FUNCTION DONE: RTS PC ;THEN RETURN TO CALLER ;FUNCOD CONTAINS THE TM02 FUNCTION CODES CORRESPONDING TO THE ;CODE NUMBERS RECOGNIZED BY THE HANDLER FOR EACH FUNCTION. FUNCOD: .BYTE MTOFF*FUNC+INTEN+GO ;INTEN AND GO SET IN EACH CODE .BYTE MTREAD*FUNC+INTEN+GO .BYTE MTWRT*FUNC+INTEN+GO .BYTE MTEOF*FUNC+INTEN+GO .BYTE MTFSP*FUNC+INTEN+GO .BYTE MTBSP*FUNC+INTEN+GO .BYTE MTEXT*FUNC+INTEN+GO .BYTE MTREW*FUNC+INTEN+GO .EVEN .ENDC .IF DF,TM11 RERE: CLRB BIP ;CLEAR BSP IN PROGRESS FLAG MOV CA,@#MTCMA ;SET UP CURRENT ADDRESS MOV WC,@#MTBRC ;AND BYTE RECORD COUNT SETFUN: MOVB R1,@#MTC ;SET FUNCTION CODE SETGO: MOV (SP)+,R4 ;RESTORE REG.S MOV (SP)+,R2 MOV (SP)+,R1 MOV (SP)+,R0 MOV (SP)+,R3 BIS #INTEN+GO,@#MTC ;AND GO DONE: RTS PC ;THEN RETURN TO CALLER .ENDC ;ROUTINES TO TEST WHETHER FUNCTION OK TO EXECUTE BSPCHK:REWCHK: JSR PC,NOTBOT ;MAKE SURE NOT AT BOT BR OFFCHK ;NOTEOT CHECKS FOR END OF TAPE NOTEOT: BIT #EOT,(R3) ;TEST EOT BIT BEQ EOTOK BIS #SWERR,@SWWPTR ;IF SET, SET SW ERROR BIT, BUT ALLOW EOTOK: RTS PC ;WENABL TEST FOR UNIT WRITE ENABLED WENABL: BIT #WRL,(R3) ;TEST WRITE ENABLED BIT .IF DF TM02 BNE HWINV ;IF WRITE LOCKED, ABORT .IFF BNE HWINIT ;IF WRITE LOCKED ABORT .ENDC BOTOFF: RTS PC .IF DF,TM11 ;READY TESTS FOR SELR & (TUR.OR.RWS.OR.SDWN.OR.GPSDN) ;IF NOT, IT ABORTS THE FUNCTION. READY: BIT #SELR,(R3) ;CHECK UNIT SELECTED HWINV: BEQ HWINIT ;IF NOT, ABORT 1$: BIT #TUR+RWS+SDWN,(R3) ;CHECK READY BITS BNE OKGO ;IF ANY SET, COOL BIT #GPSDN,@#MTRD ;ELSE, GPSDN LAST CHANCE BEQ 1$ ;IF NOT READY, ABORT OKGO: RTS PC .ENDC .IF NDF,TM11 HWINV:HWINI: JMP HWINIT ;READY TESTS FOR RDY & (DRY.OR.PIP.OR.SDWN) ;IF NOT, IT ABORTS THE FUNCTION READY: BIT #RDY,@#RHCS1 ;TEST FOR RH11 READY BEQ HWINI ;IF NOT, ABORT BIT #DRY+PIP+SDWN,(R3) ;IF SO, READY? BEQ HWINI ;IF NOT, ERROR OKGO: RTS PC ;IF SO, ALL COOL .ENDC .SBTTL INTERRUPT ROUTINE ; ABORT SERVICE-TURNS OFF INTERRUPTS AND RETURNS MTABRT: .IF DF,TM11 BIC #INTEN,@#MTC ;STOP INTERRUPTS .ENDC .IF NDF,TM11 BIC #INTEN,@#RHCS1 ;STOP INTERRUPTS .ENDC JSR PC,DUNDEL ;SET FLAGS JMP QXIT2 ;AND BACK TO Q MGR BR MTABRT ;ABORT ENTRY POINT ;MTINT HANDLES MT INTERRUPTS CAUSED BY COMPLETION OF A FUNCTION OR AN ERROR ;DURING THE FUNCTION. ;ON SUCCESSFUL COMPLETION (NO ERROR BITS SET EXCEPT, POSSIBLY, EOF OR RLE), ;IT EITHER RESTORES THE STACK AND REGISTERS AND RETURNS TO THE ;SW FUNCTION THAT CALLED 'SOFT' OR, ;FOR HW MODE FUNCTIONS, EXITS TO THE Q MANAGER. .IF DF,TM11 ;ON ALL HW ERRORS IT SETS THE HW ERROR BIT IN THE CSW. ON BTE, ;NXM, OR ILC IT JUST GOES TO THE EXIT SEQUENCE. ON ALL OTHER ;ERRORS (CRE, PAE, BGL) IT PERFORMS RECOVERY. ON OFFLINE, ;READ, OR WEOF IT IGNORES THE ERROR ASSUMING THE FUNCTION ;COMPLETED. ON READ, WRITE, AND WRITEX IT PERFORMS A BACKSPACE ;BEFORE RETRY ONLY IF IT FINDS MTBRC INCREMENTED. AND ON BSP AND FSP ;IT ONLY SETS THE GO BIT AND ONLY IF MTBRC DOES NOT =0, IGNORING THE ;ERROR OTHERWISE, THEN RTI'S. .ENDC .IF NDF,TM11 ;IF IT FINDS SPECIAL CONDITION SET IN RHCS1 IT TESTS FOR AN ERROR IN ;THE RH11 OR TM02. IF IT FINDS ONE IT DECIDES WHETHER OR NOT IT IS ;A REAL ERROR. IF NOT (E.G. FCE ON SPACE OPERATION) IT REVERTS TO ;THE NORMAL INTERRUPT PROCESSING. IF SO, IT DECIDES WHETHER OR NOT ;IT CAN RECOVER THE ERROR. IF NOT, IT EXITS TO THE CLEANUP ROUTINE. ;IF SO, IT DECIDES WHETHER TAPE MOVEMENT OCCURRED. IF NOT, IT ;RETRIES THE FUNCTION BY RE-LOADING THE RHWC, RHBA, RHFC, ;AND RHCS1 AND RETURNS TO THE INTERRUPTED ROUTINE. IF SO, ;IT BACKSPACES 3 RECORDS OR TO BOT, FORWARD SPACES TO THE BAD RECORD, ;ON WRITE FUNCTIONS ERASES AS MANY TIMES AS WRITE ERROR HAS OCCURRED, ;THEN RETRIES THE BAD FUNCTION. ;IT WILL RETRY UP TO 10 TIMES BEFORE ABORTING WITH A HW ERROR. ;THIS DESCRIPTION OF ITS LOGICAL FUNCTIONING DOES NOT CORRESPOND EXACTLY ;TO THE ACTUAL SEQUENCE OF TESTS IT CARRIES OUT. .ENDC MTINT: .IF NDF,DEBUG MOV @#54,-(SP) ;ARRANGE TO GO TO $INTEN JSR R5,@(SP)+ .WORD ^C&PR7 ;PRIORITY 5 .ENDC .IF DF,DEBUG MOV (SP)+,(SP) ;IN DEBUG MODE, CHANGE INT TO JSR .ENDC MOV R3,-(SP) ;SAVE 2 REG.S MOV R0,-(SP) MOV R1,-(SP) ;AND 3 MORE MOV R2,-(SP) MOV R4,-(SP) MOV SP,SPSAV ;SAVE SP AT INTERRUPT TIME .IF DF,TM11 BIC #INTEN,@#MTC ;DISABLE INTERRUPTS BMI MTERR ;AND GO PROCESS ANY ERROR NOERR: TSTB BIP ;ELSE, TEST BIP BNE TRYIT ;IF SO, TRY ORIGINAL FUNCTION AGAIN .ENDC .IF NDF,TM11 BIT #SC,@#RHCS1 ;SPECIAL CONDITION MEANS POSSIBLE ERROR BNE MTERR ;GOPROCESS IT NOERR: TSTB RIP ;IF NO RETRY IN PROGRESS, BEQ RTSPC ;FUNCTION COMPLETE, RETURN INCB I ;IF A RETRY, INC COUNTER TSTB RIP ;IF RIP FLAG <0, BLT REWRIT ;GOCONTINUE WRITE RETRY TSTB I ;IF I NON-0 INDICATING SPACING NOT DONE, BNE SPACE ;CONTINUE SPACING TSTW: CMPB CURFUN,#WRITE ;ELSE, IF LAST FUNC A WRITE BEQ ERAGO ;START ERASE SEQUENCE TRYIT: MOVB (PC)+,R1 ;ELSE, RE-INITIATEBAD FUNC CURFUN: .WORD 0 ;(CODE FOR CURRENT FUNCTION) TRYITT: BR RERE ;BY BRANCHING TO INITIATION SEQUENCE REWRIT: CMPB I,RETRY ;ON WRITE RETRY, IF BAD RECORDS LEFT, BLT ERASE ;GO ERASE ANOTHER ONE OF THEM BR TRYIT ;ELSE, RETRY THE WRITE ERAGO: COM RIP ;TO START ERASEING, SET FLAG <0 ERASE: MOVB #MTEXT*FUNC+INTEN+GO,R1 ;PUT ERASE CODE IN R1 BR DOSP ;AT THIS POINT, CODE HAS DETERMINED I, THE SPACING COUNTER, NON-0 ;00 MEANS SPACING IN PROGRESS ;<0 MEANS ERASING IN PROGRESS) BNE ERROR ;FORGET IT CLR (PC)+ ;IF NOT, CLEAR COUNTER I: .WORD 0 ;(COUNTER FOR REPOSITIONING) INC RIP ;SAY RETRY IN PROGRESS BR DOBSP ;AND INITIATE FIRST BSP ;DRVCLR DOES A DRIVE CLEAR. DRVCLR: MOV #MTCLR*FUNC+GO,@#RHCS1 ;DRIVE CLEAR MOV @#RHAS,@#RHAS ;CLEAR ATTENTION SUMMARY BIS #40000,@#RHCS1 ;CLEAR TRE RTS PC .ENDC .SBTTL EXIT SEQUENCE ;EXIT SEQUENCE CODE HWINIT: BIS #HWERR,@CSWPTR ;ON CAN'T INTITIATE HW FUNCTION RESPV2: BR RESPE ;JUST SET ERROR BIT AND EXIT TO Q MANAGER ERROR: BIS #HWERR,@CSWPTR ;ON ERROR AFTER FUNCTION, SET HW ERROR BIT TSTB MAC QEXITV: BEQ QEXIT ;EXIT TO Q MANAGER UNLESS MACRO CALLED BITB #SWERR,@SWWPTR ;HAS ERROR OCCURRED BEFORE? BNE RESPE ;THEN DON'T DO CLEANUP AGAIN BISB #SWERR,@SWWPTR ;ELSE, SET SW ERROR BIT AND TRY TO SAVE TAPE ;CLEAN ATTEMPTS TO SAVE A TAPE'S FILE STRUCTURE WHEN A HW ERROR OCCURS. ;ON ERROR DURING ENTER, IT WRITES LEOT. ;ON ERROR DURING WRITE, IT SPACES BACK TO THE PREVIOUS TAPE MARK, SPACES ;FORWARD OVER THE OFFENDING RECORD USING THE RECORD COUNT, AND ;THEN CLOSES THE FILE. ;ON ERROR DURING CLOSE OF AN ENTER, IT WRITES A TRIPLE TAPE MARK TO END ;THE FILE AND THE TAPE. ;ON ERROR DURING LOOKUP OR READ, IT REWINDS TO RESTORE KNOWN TAPE ;POSITION. CLEAN: JSR PC,BSPN ;SPACE BACK OVER LAST EOF JSR PC,FSPN ;THEN FORWARD OVER IT BITB UBITS,WRYT BNE DOCL BITB UBITS,ENTFLG ;THEN IF ENTER IN PROGRESS, BEQ REWIT WE: JSR PC,WRTEOF ;WRITE AN EOF, ENDING THE TAPE JSR PC,BSPN ;AND EXIT POSITIONED BETWEEN DOUBLE MARKS BR RESPE REWIT: JSR PC,REWCLR ;ON INPUT FUNCTIONS, REWIND TAPE BR RESPE ;AND GO RESET FLAG TABLE DOCL: BITB UBITS,ENTFLG ;IF WRITES ALLOWED AND FLAG SET, BEQ WR JSR PC,WRTEOF ;CLOSE OF ENTER IN PROGRESS, WRITE 2 MARKS BR WE WR: JSR PC,UNOFF ;IF WRITE IN PROGRESS, MOV BLKCTR-PZ(R2),R0 ;GET COUNT OF RECORDS WRITTEN THUS FAR NEG R0 ;NEGATE IT FOR SPACING JSR PC,FSP ;AND SPACE FORWARD OVER ALL GOOD RECORDS JSR PC,ENTCLO ;THEN WRITE EOF1 LABEL ENDING FILE RESPE: JSR PC,DUNDEL ;ON ALL ERRORS, RESET FLAG TABLE 2$: RESP: MOV SPSAV,SP ;RESTORE ORIG. SP QEXIT: CLR FIN ;ON EXIT, CLEAR DONE FLAG MOV (SP)+,R4 ;RESTORE REG.S MOV (SP)+,R2 MOV (SP)+,R1 MOV (SP)+,R0 ;R4 AND R5 WERE SAVED AT $INTEN MOV (SP)+,R3 QXIT2: .IF NDF,DEBUG MOV PC,R4 ADD #MTCQE-.,R4 MOV @#MONLOW,R5 JMP @OFFSET(R5) .ENDC .IF DF,DEBUG JMP QMAN ;RETURN TO SENDER .ENDC ;THE FOLLOWING STORAGE AREA CONTAINS ALL WORDS PUSHED ON THE STACK SINCE THE START OF ;THE HANDLER'S EXECUTION. STAK=. .=.+14 .IF DF,DEBUG .=.+100 ;ROOM FOR ODT'S STACK .ENDC .IF NDF,INIT .END .IF DF,INIT .END TEST .ENDC TM02=0 .TITLE TA11 HANDLER V02-01 ; RT11 CASSETTE HANDLER ; ; DEC-11-OCAHA-E ; ; COPYRIGHT (C) 1974,1975 ; ; DIGITAL EQUIPMENT CORPORATION ; MAYNARD, MASSACHUSETTS 01754 ; ; 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 DIGITAL. ; ; THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO ; CHANGE WITHOUT NOTICE AND SHOULD NOT BE CONSTRUED ; AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION. ; ; DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE ; OR RELIABILITY OF ITS SOFTWARE ON EQUIPMENT ; WHICH IS NOT SUPPLIED BY DIGITAL. ; ; AUTHORS: BF/ABC/EF ; ; DATE: 17-SEP-74 .LIST TTM .IF NDF LISTC .ENDC COM=0 ;ALWAYS LIST COMMENTS .IF DF COM ; 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. .ENDC .IF DF COM .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. .ENDC .SBTTL DEFINITIONS .MCALL .PRINT, .DATE ; THIS MACRO COMPUTES AN ADDRESS FOR PIC CODE .MACRO ADDR LOC,R MOV PC,R ADD #LOC-.,R .ENDM ADDR R0 = %0 R1 = %1 R2 = %2 R3 = %3 R4 = %4 R5 = %5 R6 = %6 R7 = %7 T5 = R5 ;ADDR OF TACS SP = %6 PC = %7 TACS = 177500 ;COMMAND AND STATUS REGISTER 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 = 177502 ;DATA BUFFER CAVEC = 260 ;INTERRUPT VECTOR ; 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 SWERR = 1 ;SW 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 CONFIG = 300 ;OFFSET TO CONFIG WORD SYNCH = 324 ;OFFSET TO SYNCH ENTRY POINT 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 .ASECT .=400 BR .+NOTDUN-RAWOPT ;CODE FOR "SET RAW" OPTION .RAD50 /RAW / .WORD /2+100000 0 OPRAW: MOV (PC)+,R3 BNE .+NOTDUN-RAWOPT MOV R3,RAWOPT RTS PC .CSECT .ENDC .IIF NDF DEBUG, .NLIST .IF DF,DEBUG .ENABL AMA .ASECT .=CAVEC CTINT 0 .=1000 .ENDC .IIF NDF DEBUG, .LIST .SBTTL LOAD POINT, INITIATE REQUEST .WORD CAVEC ;CA INTERRUPT VECTOR ADDRESS .WORD CTINT-. ;OFFSET TO INTERRUPT ROUTINE .WORD PR6 ;PRIORITY CALQE: .WORD 0 ;PTR TO LAST Q ENTRY .IIF NDF DEBUG, .NLIST .IF DF DEBUG CACQE: .WORD QEL ;PTR TO CURRENT Q ENTRY, WORD 3 .ENDC .IIF NDF DEBUG, .LIST .IF NDF DEBUG CACQE: .WORD 0 ;PTR TO CURRENT Q ENTRY, WORD 3 .ENDC .IIF NDF DEBUG, .NLIST .IF DF DEBUG 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 .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 MOV CACQE,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 @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 SWINIT ;UNIT IS > 1-REPORT ERROR ASL R2 ;SHIFT MASK LEFT BIS #UNITNO,R3 ;AND SET TO UNIT 1 2$: MOV R3,(T5) ;SET UNIT BIT 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) .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 ; 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 TST R1 ;EXAMINE FUNCTION CODE BMI 2$ ;NEGATIVE, GO DO HARDWARE FUNCTION BGT MACRO ;>0, GO DO SOFTWARE FUNCTION 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 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 SWINIT 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 SWINIT 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 SWINIT ;IF NOT SET, ABORT FUNCTION 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 SWINIT: BIS #SWERR,@SWWPTR ;SETTING SW ERROR BIT IN CSW 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 JSR PC,BSP ;TO READ CHECK, BSP 1 BLOCK MOV CA,R2 ;SAVE ORIGINAL CA FOR POSSIBLE RETR 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 1$: CMPB (R1)+,(R2)+ ;THEN GO THRU BUFFER COMPARING BNE 2$ ;DATA WRITTEN WITH READ INC R3 ;IF IT CHECKS, BLT 1$ .ENDC NOTDUN: RTS PC ;GOOD WRITE, POSITION GOOD NOW .IF DF RCHECK 2$: 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: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: 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 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. $DELETE:.IF DF,NEWVOL TST @CA ;IF NULL FILE NAME, BEQ $NEWVOL ;INITIALIZE VOLUME .ENDC JSR PC,SEEK ;FIND THE FILE SWINI2: BR SWINIT ;IF NONE FOUND, QUIT 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 RTS PC .DSABL LSB .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: 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) 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 3$: CLRB (R2)+ ;AND CLEAR THESE OUT INC R4 BNE 3$ SWEOF: BIS #EOFBIT,@CSWPTR ;SET EOF BIT 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 BR 2$ ;AND DO LAST READ AGAIN 5$: .ENDC ADD #200,R4 ;INCREASE COUNT BY AMOUNT XFERRED BCS RTSPC ;DONE. GO RETURN ADD #200,CA ;BUMP CURRENT ADDRESS BR 2$ ;READ ANOTHER BLOCK .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 BR 1$ ;AND TRY THE WRITE AGAIN 4$: .ENDC ADD #200,R4 ;INCREASE COUNT BY AMOUNT XFERRED BCS RTSPC ;DONE, GO RETURN ADD #200,CA ;BUMP CURRENT ADDRESS 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 BNE SWINI3 ;NOT REWIND, GO ABORT W/ ERROR 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 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) 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 .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 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 BR CTABRT ;SYNCH ERROR ?!?! 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 .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 BR CTABRT ;ABORT ENTRY POINT CTINT: MOV @#MONLOW,-(SP) ;ARRANGE TO GO TO $INTEN JSR R5,@(SP)+ .WORD ^C&PR7 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 INC TATC ;INC TRANSFER COUNT 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 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. BR RERE ;RE-INITIATE FUNCTION WITH REGISTER LOAD ; 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 #SWERR,@SWWPTR ;HAS ERROR OCCURRED BEFORE? BNE 2$ ;THEN DON'T DO CLEANUP AGAIN BISB #SWERR,@SWWPTR ;ELSE, SET SW ERROR BIT AND TRY TO SAVE TAPE ; 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 CTHOME: ADDR CACQE,R4 MOV @#MONLOW,R5 JMP @OFFSET(R5) .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 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 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 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 NDF INIT CTEND: .END .IFF .END TEST .ENDC .TITLE RJS03/RJS04 HANDLER 02-01 ; RT-11 RJS03/RJS04 FIXED HEAD DISK HANDLER ; ; DEC-11-ORJSA-E ; ; ABC, RRB, JEG, HJ ; SEPT 1975 ; ; COPYRIGHT (C) 1974,1975 ; ; DIGITAL EQUIPMENT CORPORATION ; MAYNARD, MASSACHUSETTS 01754 ; ; 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 DIGITAL. ; ; THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO ; CHANGE WITHOUT NOTICE AND SHOULD NOT BE CONSTRUED ; AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION. ; ; DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE ; OR RELIABILITY OF ITS SOFTWARE ON EQUIPMENT ; WHICH IS NOT SUPPLIED BY DIGITAL. ; REGISTER SYMBOLS: R0=%0 R1=%1 R2=%2 R3=%3 R4=%4 R5=%5 SP=%6 PC=%7 ; SYSTEM EQUATES: PR5= 240 PR7= 340 SYSPTR= 54 OFFSET= 270 ; GLOBALS FOR USE AS SYSTEM DEVICE: .GLOBL DSINT, DPSYS,RCSYS,DXSYS .GLOBL RKSYS, RFSYS, DTSYS, DSSYS, $INPTR, $INTEN ; RS SYSTEM DEFINITIONAL EQUATES: DXSYS= 0 DPSYS= 0 DTSYS= 0 RFSYS= 0 RKSYS= 0 RCSYS= 0 ; RS CONTROL & STATUS REGISTERS, ETC. .IF NDF MBUSSC RSVEC= 204 ;VECTOR ADRS RSCS1= 172040 ;CONTROL & STATUS 1 RSCS2= 172050 ;CONTROL & STATUS 2 RSER= 172054 ;ERROR SUMMARY RSDT= 172066 ;DRIVE TYPE .ENDC RSCNT= 8. ;RETRY COUNT .IF DF MBUSSC RSVEC= 150 ;VECTOR ADRS RSCS1= 176300 ;CONTROL AND STATUS 1 RSCS2= 176310 ;CONTROL AND STATUS 2 RSER= 176314 ;ERROR SUMMARY RSDT= 176326 ;DRIVE TYPE .ENDC .CSECT SYSHND START: .WORD RSVEC ;VECTOR .WORD DSINT-. ;OFFSET TO INTERRUPT SERVICE .WORD PR7 DSSYS: RSLQE: .WORD 0 RSCQE: .WORD 0 ;CURRENT QUEUE ELEMENT POINTER ; ENTRY POINT MOV R3,-(SP) ;SAVE R3 MOV #RSCNT,(PC)+ ;SET RETRY COUNT RSTRY: .WORD 0 RSINIT: MOV RSCQE,R3 ;R3 -> CURRENT QUEUE ELEMENT MOV (R3)+,R4 ;R4 = BLOCK # MOV (R3)+,-(SP) ;GET UNIT # SWAB @SP ;AND ISOLATE IT BIC #177770,@SP MOV #RSCS2,R5 ;R5 -> CONTROL & STATUS REG 2 MOV #40,@R5 ;CONTROLLER CLEAR MOV (SP)+,@R5 ;SET UNIT # MOV #1,(PC)+ ;ASSUME RS04 RSTYPE: .WORD 0 ;1 IS RS04, 3 IS RS03 BIT #2,@#RSDT ;CHECK DRIVE TYPE BNE RS1 ;BRANCH IF RS04 MOV #3,RSTYPE ;SET TYPE TO RS03 ASL R4 ;RS03, ACCOUNT FOR 64 WORD SECTORS BCS RSERR RS1: CMP #2048.,R4 ;VALID BLOCK #? BLOS RSERR ;NOPE ASL R4 ;CONVERT TO SECTOR AND TRACK ADRS MOV R4,-(R5) ;ELSE SET BLOCK # MOV (R3)+,-(R5) ;SET BUFFER ADRS MOV @R3,R3 ;GET WORD COUNT INTO R3 MOV R3,(PC)+ ;SAVE READ/WRITE FLAG FOR LATER RSRWF: .WORD 0 ;READ/WRITE FLAG RSFIX: MOV #161,R4 ;ASSUME WRITE OPERATION MOV R3,-(R5) ;SET WORD COUNT BEQ RSHOME ;SEEK HOME RSRD: BMI RS2 ;IT WAS A WRITE NEG @R5 ;ELSE FIX WORD COUNT MOV #171,R4 ;AND SET READ CODE RS2: MOV R4,-(R5) ;START THE TRANSFER MOV (SP)+,R3 ;AND GO AWAY RTS PC ; THE ABOVE RTS INSTRUCTION SERVES AS THE ABORT ENTRY ; SINCE THIS IS A FAST DEVICE ABORT CONSISTS OF ; LETTING IT FINISH NORMALLY. ; INTERRUPT SERVICE DSINT: JSR R5,@$INPTR ;ENTER SYSTEM STATE .WORD ^C&PR7 MOV R3,-(SP) ;SAVE R3 FOR GOODNESS BIT #60000,@#RSCS1 ;ANY ERRORS? BNE 1$ ;BRANCH IF EROOR TST RSRWF ;ARE WE DOING A READ OR WRITE? BPL RSHOME ;BRANCH IF READ, ALL DONE MOV #RSCS2,R5 ;POINT R5 TO CONTROL REG 2 BIT RSTYPE,-(R5) ;ARE WE AT END OF 256 WORD BLOCK? BEQ RSHOME ;BRANCH IF SO ; FORCE ZERO FILL OF REMAINDER OF BLOCK MOV PC,R4 ;CREATE PIC REFERENCE TO A 0 ADD #RSZERO-.,R4 ;R4 -> A 0 MOV R4,-(R5) ;SET BUS ADDRESS MOV #-1,R3 ;SET WORD COUNT AND WRITE INDICATOR BR RSFIX ;START WRITE 1$: BIT #47007,@#RSER ;HARD ERRORS? BNE RSERR ;YUP - NO CHANCE BIT #14000,@#RSCS2 ;MAYBE, CONTINUE CHECK BNE RSERR ;YUP - KILL DEC RSTRY ;ELSE RETRY BGT RSINIT ;IF DESIRED RSERR: MOV RSCQE,R4 ;R4 -> CURRENT QUEUE ELEMENT BIS #1,@-(R4) ;INDICATE HARD ERROR MOV #40,@#RSCS2 ;ISSUE CONTROLLER CLEAR RSHOME: MOV (SP)+,R3 ;RESTORE R3 MOV PC,R4 ;AND GO HOME TO MAMA ADD #RSCQE-.,R4 MOV @#SYSPTR,R5 JMP @OFFSET(R5) RSZERO: .WORD 0 ;USED FOR ZERO FILL AT END OF BLOCK $INPTR: .WORD $INTEN ;PLUGGED TO POINT TO COMMON ENTRY RSSIZE= .-START .END .TITLE CREF V01-04 ;RT-11 CROSS-REFERENCE PROGRAM ; ;DEC-11-ORCFA-E ; ;RICH BILLIG ; ;JULY;JULY 1973 / MARCH 1975 ; ;COPYRIGHT (C) 1974, 1975 ; ;DIGITAL EQUIPMENT CORPORATION ;MAYNARD, MASSACHUSETTS 01754 ; ; 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 DIGITAL. ; ; THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO ; CHANGE WITHOUT NOTICE AND SHOULD NOT BE CONSTRUED ; AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION. ; ; DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE ; OR RELIABILITY OF ITS SOFTWARE ON EQUIPMENT ; WHICH IS NOT SUPPLIED BY DIGITAL. .SBTTL MISCELLANEOUS EQUATES R0 = %0 R1 = %1 R2 = %2 R3 = %3 R4 = %4 R5 = %5 SP = %6 PC = %7 .MCALL .EXIT, .FETCH, .PRINT, .QSET, .RCTRL, .SETTO ENTSIZ = 12. ; LENGTH (BYTES) OF A SORT ITEM ERRADR = 52 ; MONITOR ERROR CODE BYTE ADDRESS TAB = 11 CR = 15 LF = 12 FF = 14 SPACE = 40 FDFLT = 7 ; DEFAULT NUMBER OF OUTPUT FIELDS USRADR = 46 ; MONITOR USR ADDRESS WORD USRLOD = START ; WHERE TO LOAD USR JSW = 44 ; JOB STATUS WORD ADDRESS REFLAG = 020000 ; REENTERABLE FLAG BIT IN JSW SPSTRT = 42 ; INITIAL STACK POINTER WORD ADDR MONLOW = 54 ; RMON LOW ADDRESS SRTSIZ = 7 ; # OF BYTES IN SORT KEY CHAIN = 400 ;CHAIN BIT IN JSW HIGHAD = 50 ;HIGH LIMIT (AFTER SETTOP) .MACRO ERROR STRING JSR R0,ERROR .ASCIZ /?'STRING'?/ .EVEN .ENDM .SBTTL CHAIN INTERFACE SPECIFICATION .REPT 0 ;FOR CLEANLINESS AND BEAUTY RT-11 CREF IS DESIGNED TO BE CHAINED TO BY OTHER SYSTEM PROGRAMS. IT WILL APPEND A CROSS-REFERENCE TABLE TO THE LISTING FILE PRODUCED BY ITS CALLER. THE SPECIFICATIONS PASSED IN THE CHAIN COMMUNICATIONS AREA (BETWEEN 500 AND 776 ABSOLUTE) ARE AS FOLLOWS: LOCATION CONTENTS -------- -------- 500 .RAD50 /SY / 502 .RAD50 /CRE/ THE CHAIN FILE SPECIFICATION 504 .RAD50 /F / WHICH INVOKES CREF. 506 .RAD50 /SAV/ 510 RT-11 CHANNEL NUMBER OF LISTING (OUTPUT) FILE. 512 RAD50 NAME OF OUTPUT DEVICE 514 HIGHEST OUTPUT BLOCK # WRITTEN + 1 516 RT-11 CHANNEL NUMBER OF INPUT (CREF FILE). 520 RAD50 NAME OF INPUT DEVICE 522 HIGHEST INPUT BLOCK # WRITTEN + 1 524 LISTING FORMAT (0 = 80-COL., -1 = 132-COL.) 526 .RAD50 /DEV/ 530 .RAD50 /FIL/ PROGRAM TO CHAIN BACK TO. 532 .RAD50 /NAM/ IF ZERO, THEN CREF WILL CLOSE 534 .RAD50 /EXT/ THE LISTING FILE AND EXIT 536-??? ASCIZ STRING TO BE USED AS TITLE LINE (NO PAGE #) CREF ACCEPTS AS INPUT A FILE WHICH CONSISTS OF 12. BYTE ENTRIES, ONE FOR EACH REFERENCE TO A SYMBOL. THE FORMAT OF AN ENTRY IS: OFFSET VALUE ------ ----- 0 SECTION DESCRIPTOR (1-BYTE) HIGH-ORDER 3 BITS = SECTION # (CONTROLS ORDER OF SECTS) LOW-ORDER 5 BITS = ALPHA CHAR TO USE AS SECTION NAME (STRIPPED TO 5 BITS) 1-6 ASCII NAME OF SYMBOL 7-10 PAGE NUMBER (BINARY), -1 IF NO PAGE NUMBER IS USED 11-12 LINE NUMBER (BINARY) 13 1-CHARACTER IDENTIFIER TO PRINT NEXT TO THIS REFERENCE. (TYPICALLY USED TO IDENTIFY A DESTRUCTIVE REFERENCE, OR A DEFINITIONAL REFERENCE). .ENDR .SBTTL INITIALIZATION CODE START: BIT #CHAIN,@#JSW ;WERE WE CHAINED TO? BNE 1$ ;YES CLR RETSPC ;PREVENT CHAIN-BACK ERROR ;ONLY ALLOW CHAIN 1$: MOV #510,R2 ;COPY CHAIN PARAMETERS MOV #LSTCHN,R3 ;INTO OUR AREA MOV #11.,R0 2$: MOV (R2)+,(R3)+ DEC R0 BNE 2$ 3$: MOVB (R2)+,(R3)+ ;COPY TITLE LINE SUPPLIED BNE 3$ MOV @#MONLOW,R1 ;FIND LOW ADRS OF MONITOR TST -(R1) .SETTOP R1 ;AND FORCE USR SWAPPING MOV @#HIGHAD,R1 ;GET ALLOCATED HIGH LIMIT IN R1 MOV #CRFHGH,R2 ;R2 -> NEXT AVAILABLE LOC AFTER CREF .FETCH R2,#LSTDEV ;LOAD THE LISTING DEVICE HANDLER BCS 4$ ; DEVICE NOT FOUND MOV R0,R2 ;COPY NEW HIGH ADRS .FETCH R2,#CRFDEV ;LOAD THE CREF FILE DEVICE HANDLER BCC 5$ ; IF OKAY 4$: ERROR ;ELSE ERROR - DEVICE NOT FOUND 5$: MOV R0,R2 ;R2 = HIGH ADRS OF HANDLER AREA MOV LSTSIZ,OUTBLK ;SET OUTPUT FILE INITIAL BLOCK # TST LSTFMT ;132-COLUMN MODE? BEQ ALLOC ;NOPE MOV #14.,WIDTH ;ELSE SET # OF OUTPUT FIELDS MOV #14.,NUMFLD .SBTTL STORAGE ALLOCATION & EXEC ALLOC: MOV R2,SRTBUF ;INITIALIZE BUFFER ADDRESSES MOV R2,F1BUF MOV R2,F2BUF MOV R2,F3BUF SUB R2,R1 ;COMPUTE AVAILABLE SPACE ; COMPUTE # OF 3-BLOCK SECTIONS AVAILABLE (=SECT) CLR R4 ;SECT=0 MOV R1,R0 ;COPY AVAILABLE SPACE 7$: SUB #3*512.,R0 BLO 8$ ;R4 = R0/(3*512.) INC R4 BR 7$ ; COMPUTE # OF 3-BLOCK SECTIONS SORTED PER PASS 8$: SUB #2,R4 ;R4 = SECT - 2 ; GET LENGTH OF INPUT FILE (=N) IN BLOCKS MOV CRFSIZ,R5 ;GET SIZE AS PASSED DEC R5 ; COMPUTE NUMBER OF SORT PASSES MOV R4,-(SP) ;R4 = # OF BLOCKS PER SORT LOAD ASL R4 ADD (SP)+,R4 MOV R4,SECT3 ;COPY INTO SECT CLR R0 ;SORT PASSES = 0 11$: INC R0 ;SORT PASSES + 1 SUB R4,R5 ;R0 = N/(3*SECT) BPL 11$ CMP R0,#1 ;OPTIMIZE FOR ONE-PASS CASE BGT 14$ COM INCORE ;SET FLAG IF CREF FILE FITS IN CORE 14$: MOV R0,SRTPAS ;SAVE FOR POSTERITY MOV R0,MRGPAS CLR R5 ;COMPUTE START BLOCK # FOR FIRST 12$: DEC R0 ; MERGE PASS BEQ 13$ ADD R4,R5 BR 12$ 13$: MOV R5,F1BLK ; SORT EXEC SWAB R4 ;TO 256.*(3*SECT) MOV R4,SRTWC ;SET WORD COUNT .QSET #QAREA,#1 ;ADD A QUEUE ELEMENT FOR LISTING I/O EXEC: MOV #SRTCMD,R5 ;READ IN A CORE LOAD JSR PC,READ MOV R0,ENDF1 ;SET END-OF-BUFFER ADRS FOR LISTING CLR -(SP) ;QUICKSORT STOP FLAG MOV R0,-(SP) ;SET NEW STOP ADDR MOV SRTBUF,-(SP) ;SET START ADDR MOV #ENTSIZ,R0 ;SET UP PARAMETER 1$: JMP QUICKS ;GO SORT THE CORE LOAD DONSRT: TST INCORE ;DOES ENTIRE FILE FIT IN CORE? BMI 2$ ;IF YES, THEN GO LIST MOV #SRTCMD,R5 ;WRITE THE CORE LOAD BACK OUT JSR PC,WRITE DEC SRTPAS ;ANY MORE SORT PASSES NEEDED? BEQ 2$ ;NOPE - GO CHECK MERGE ADD SECT3,SRTBLK ;ELSE UPDATE BLOCK NUMBER BR EXEC ;AND GO SORT NEXT CORE LOAD ; MERGE EXEC 2$: MOV SECT3,R5 ;GET # OF BLKS MERGED PER PASS SWAB R5 ;CHANGE TO WORD COUNT MOV R5,F1WC ;AND STORE IT ASL R5 ;GET BYTE COUNT ADD R5,F2BUF ;SET F2 BUFFER ADDRESS ADD R5,F3BUF ;AND F3 BUFFER ADDRESS ADD #3*512.,F3BUF MOV F3BUF,ENDF3 ;AND END-OF-F3-BUFFER ADDRESS ADD #3*512.,ENDF3 3$: DEC MRGPAS ;ANY MERGE PASSES REMAIN? BEQ LIST ;NOPE - GO FORMAT LISTING MOV #3*256.,F2WC ;### A.C. FIX TO CREF MOV #F1BLK,R5 ;GET INPUT BLOCK ADDR SUB SECT3,@R5 ;GET NEXT SECTION TO MERGE MOV @R5,R4 ;PICK UP F1 BLOCK # MOV R4,F3BLK ;SET OUTPUT START BLOCK ADD SECT3,R4 ;GET F2 START BLOCK MOV R4,F2BLK TST -(R5) ;POINT AT THE COMMAND WORD JSR PC,READ ;READ F1 JSR PC,READ ;AND F2 ADD #ENTSIZ,R0 ;BUMP END F2 ADDR MOV R0,ENDF2 ;AND SET F2 END MOV #3*256.,F3WC ;RESET OUTPUT WORD COUNT JSR PC,MERGE ;DO THE MERGE PASS BR 3$ ;AND CONTINUE LIST: JMP FORMAT ;GO FORMAT LISTING .SBTTL IMPURE AREA, CHAIN PARAMETERS SRTCMD: .WORD 0 ;SORT COMMAND & CHANNEL SRTBLK: .WORD 0 ;SORT BLOCK NUMBER SRTBUF: .WORD 0 ;SORT BUFFER ADDRESS SRTWC: .WORD 0 ;SORT WORD COUNT SRTMOD: .WORD 0 ;SORT MODE (WAIT MODE) F1CMD: .WORD 0 ;MERGE INPUT #1 COMMAND & CHANNEL F1BLK: .WORD 0 ;MERGE INPUT #1 BLOCK NUMBER F1BUF: .WORD 0 ;MERGE INPUT #1 BUFFER ADDRESS F1WC: .WORD 0 ;MERGE INPUT #1 WORD COUNT F1MOD: .WORD 0 ;MERGE INPUT #1 MODE (WAIT MODE) F2CMD: .WORD 0 ;MERGE INPUT #2 COMMAND & CHANNEL F2BLK: .WORD 0 ;MERGE INPUT #2 BLOCK NUMBER F2BUF: .WORD 0 ;MERGE INPUT #2 BUFFER ADDRESS F2WC: .WORD 3*256. ;MERGE INPUT #2 WORD COUNT F2MOD: .WORD 0 ;MERGE INPUT #2 MODE (WAIT MODE) F3CMD: .WORD 0 ;MERGE OUTPUT COMMAND & CHANNEL F3BLK: .WORD 0 ;MERGE OUTPUT BLOCK NUMBER F3BUF: .WORD 0 ;MERGE OUTPUT BUFFER ADDRESS F3WC: .WORD 3*256. ;MERGE OUTPUT WORD COUNT F3MOD: .WORD 0 ;MERGE OUTPUT MODE (WAIT MODE) SRTPAS: .WORD 0 ;# OF SORT PASSES REQUIRED MRGPAS: .WORD 0 ;# OF MERGE PASSES REQUIRED SECT3: .WORD 0 ;# OF BLOCKS SORTED PER PASS INCORE: .WORD 0 ;IF MINUS, ALL OF INPUT FITS IN CORE LSTCHN: .BLKW ;LISTING (OUTPUT) CHANNEL LSTDEV: .BLKW ; DEVICE LSTSIZ: .BLKW ; SIZE + 1 CRFCHN: .BLKW ;CREF (INPUT) CHANNEL CRFDEV: .BLKW ; DEVICE CRFSIZ: .BLKW ; SIZE + 1 LSTFMT: .BLKW ;LISTING FORMAT (0=80COL, -1=132COL) RETSPC: .WORD 0,0,0,0 ;RETURN CHAIN FILE SPECIFICATION TITLE: .BLKB 80. ;TITLE PASSED BY CALLER SBTTL: .ASCIZ /CROSS REFERENCE TABLE (CREF V01-04 )/ PAGEST: .ASCII / PAGE / ;PAGE NUMBER HEADER CRFTYP: .ASCIZ / -/ ;SECTION TYPE HEADER TTLBUF: .REPT 134. ;HEADER LINE BUFFER .BYTE 40 ;INITIALIZED TO BLANKS .ENDR .EVEN .SBTTL MORE IMPURE AREA INTFLG: .WORD 0 ;QUICKSORT FLAG SRTFLG: .WORD 0 ;BUBBLE SORT FLAG NUMFLD: .WORD FDFLT ;NUMBER OF OUTPUT FIELDS WIDTH: .WORD FDFLT ;AND MEMORY OF ABOVE CURNAM: .BYTE 0,0,0,0,0,0 ;CURRENT SYMBOL NAME CRFTP: .WORD 0 ;CURRENT SECTION TYPE LINLFT: .WORD 1 ;# OF LINES LEFT ON THIS PAGE PAGNUM: .WORD 0 ;OUTPUT PAGE NUMBER LSTSPC: .WORD 11*400 ;LISTING OUTPUT COMMAND & CHANNEL OUTBLK: .WORD 0 ;LISTING OUTPUT BLOCK NUMBER CURBUF: .WORD 0 ;LISTING OUTPUT BUFFER POINTER .WORD 256. ;LISTING OUTPUT WORD COUNT .WORD 1 ;ASYNCHRONOUS WRITE NXTBUF: .WORD 0 ;ADRS OF NEXT OUTPUT BUFFER OUTCNT: .WORD 513. ;# OF CHARS REMAINING IN CURRENT BUF OUTPTR: .WORD 0 ;CURRENT LISTING BUFFER POINTER .WORD 0 ;DIVISION TABLE FOR CVTASC .WORD 1 .WORD 10. DIG3: .WORD 100. .WORD 1000. DIG5: .WORD 10000. ENDF1: .WORD 0 ;END OF MERGE INPUT #1 BUFFER ENDF2: .WORD 0 ;END OF MERGE INPUT #2 BUFFER ENDF3: .WORD 0 ;END OF MERGE OUTPUT BUFFER .SBTTL EXIT, ERROR PROCESSING ; ERRORS INDICATED ELSEWHERE BY THE "ERROR" MACRO ARE PROCESSED ; BY A JSR R0,ERROR, FOLLOWED BY THE ASCIZ STRING TO PRINT. ERROR: .RCTRLO ;RESET ANY CONTROL-O EFFECT .PRINT ;PRINT THE ERROR MESSAGE ON THE TTY ; THE FOLLOWING CODE IS EXECUTED AFTER AN ERROR, OR ON NORMAL EXIT ; FROM CREF. EXIT: MOV #6*400,R0 ;GET A CLOSE EMT ADD LSTCHN,R0 ;FOR THE APPROPRIATE CHANNEL EMT 374 ;AND CLOSE THE OUTPUT FILE MOV #3*400,R0 ;GET PURGE EMT ADD CRFCHN,R0 ;FOR THE TEMP FILE EMT 374 ;AND GET RID OF IT MOV #RETSPC,R1 ;POINT AT RETURN CHAIN SPEC MOV #500,R0 ;PREPARE TO RETURN THE CHAIN MOV (R1)+,(R0)+ ;MOVE THE DEVICE NAME BEQ RTEXIT ;NO ONE TO CHAIN BACK TO - JUST EXIT MOV (R1)+,(R0)+ ;ELSE COPY REMAINDER OF SPEC MOV (R1)+,(R0)+ MOV (R1)+,(R0)+ MOV #10*400,R0 ;GET A CHAIN EMT CODE EMT 374 ;AND LEAVE RTEXIT: .EXIT ;ELSE EXIT TO RT-11 .SBTTL READ/WRITE ROUTINES (INPUT FILE) BLKNO= 2 ;INDEX TO BLOCK NUMBER OF REQUEST BUFAD= 4 ;INDEX TO BUFFER ADDRESS WDCNT= 6 ;INDEX TO WORD COUNT READ: CMP BLKNO(R5),CRFSIZ ;END-OF-FILE? BHIS 5$ ;YES MOVB WDCNT+1(R5),R0 ;GET WORD COUNT AS BLOCKS ADD BLKNO(R5),R0 ;AND ADD IN THE START BLOCK CMP CRFSIZ,R0 ;BEYOND END-OF-FILE? BHIS 1$ ;NOPE SUB CRFSIZ,R0 ;ELSE CORRECT SWAB R0 SUB R0,WDCNT(R5) ;AND MODIFY WORD COUNT 1$: MOV CRFCHN,@R5 ;SET CHANNEL FOR READ BIS #10*400,@R5 ;AND INDICATE READ OPERATION MOV R5,R0 ;POINT R0 AT PARAMETER LIST EMT 375 ;AND INITIATE READ BCS IOERR ; WHOOPS - ERROR MOV WDCNT(R5),-(SP) ;FIND LAST THREE-BLOCK SEGMENT CLR R0 2$: ADD #3*400,R0 ;INCREASE BY 3 BLOCKS CMP @SP,R0 ;HAVE WE OVERRUN ACTUAL WORD COUNT? BHI 2$ ;NOPE SUB #3*400,R0 ;ELSE BACK OFF BY 3 BLOCKS ASL R0 ;MAKE BYTE COUNT ASL @SP ;DITTO FOR STACK ADD BUFAD(R5),R0 ;POINT TO BEGINNING OF LAST 3-BLOCK BUF ADD BUFAD(R5),@SP ;AND SET END-OF-BUFFER ADRS 3$: TST @R0 ;IS THIS THE LAST ENTRY? BEQ 4$ ;YES ADD #ENTSIZ,R0 ;ELSE MOVE FORWARD BY ONE CMP @SP,R0 ;END OF BUFFER? BHI 3$ ;NOPE 4$: TST (SP)+ ;DISCARD END POINTER SUB #ENTSIZ,R0 ;BACK OFF TO LAST VALID ENTRY ADD #12,R5 ;POINT TO NEXT SET OF BLOCKS RTS PC ;AND RETURN TO CALLER 5$: ADD #12,R5 ;ADVANCE TO NEXT SET OF BLOCKS SEZ ;INDICATE END-OF-FILE RTS PC ;AND RETURN TO CALLER WRITE: MOV CRFCHN,@R5 ;SET OUTPUT CHANNEL BIS #11*400,@R5 ;INDICATE WRITE FUNCTION MOV R5,R0 ;POINT TO PARAMETER LIST EMT 375 BCC 1$ ; BRANCH IF NO ERRORS TSTB @#ERRADR ; WAS IT WRITE PAST EOF ? BNE IOERR ; NOPE - GIVE MESSAGE SUB #256.,2(R5) ; ALTER WORD COUNT BR WRITE ; AND TRY AGAIN 1$: RTS PC ; RETURN TO CALLER IOERR: ERROR .SBTTL QUICKSORT ROUTINE ; THIS ROUTINE SORTS A CORELOAD OF CREF DATA ; AT ENTRY, THE ROUTINE EXPECTS THE FOLLOWING PARMS: ; ; R0 = ENTSIZ (THE NUMBER OF BYTES IN A SORT ENTRY) ; @SP = ADDRESS OF FIRST ITEM TO BE SORTED ; 2(SP) = ADDRESS OF LAST ITEM TO BE SORTED ; 4(SP) = 0 (USED AS END-OF-STACK FLAG) ; ; CALLING SEQUENCE: JMP QUICKS QUICKS: MOV @SP,R1 ;LEFT POINTER BEQ DONE ;IF ZERO, THEN WE'RE DONE MOV 2(SP),R2 ;RIGHT POINTER CLR INTFLG ;RESET WHICH-PTR-TO-MOVE FLAG MOV R2,R3 ;CHECK NUMBER OF ITEMS SUB R1,R3 ;GET # OF ITEMS - 1 (*ENTSIZ) BEQ QPOP2 ;ONLY ONE - IT'S SORTED ALREADY CMP #ENTSIZ*10.,R3 ;11 OR FEWER ITEMS ? BLO 2$ ;NOPE - CONTINUE QUICKSORT MOV R1,R4 ;ELSE SET UP FOR TWO-BUBBLE MOV R1,R5 ; SORT ADD R0,R5 BR SORT ;AND DO IT 2$: MOV R0,R3 ;SET LOOP COUNT MOV R1,R4 ;COPY LEFT PTR MOV R2,R5 ;AND RIGHT PTR 3$: CMPB (R4)+,(R5)+ ;COMPARE PAIR OF ENTRIES BHI 8$ ;IF HIGH, MUST INTERCHANGE BLO 10$ ;IF LOW, OKAY DEC R3 ;LOOP UNTIL DONE WITH ENTRY BNE 3$ 10$: TST INTFLG ;SHOULD WE MOVE LEFT OR RIGHT PTR? BNE 5$ ;INC LEFT POINTER 4$: SUB R0,R2 ;DEC RIGHT POINTER BR 6$ ;GO SEE IF DONE WITH THIS PASS 5$: ADD R0,R1 ;BUMP LEFT PTR BY ONE ENTRY 6$: CMP R1,R2 ;DONE WITH THIS PASS? BLO 2$ ;NOPE - CONTINUE MOV 2(SP),R3 ;PICK UP FORMER RIGHT PTR MOV @SP,R2 ; AND FORMER LEFT POINTER MOV R1,R4 ;COPY THE ADDRESS WE STOPPED AT MOV R3,R5 ;AND THE FORMER RIGHT POINTER SUB R2,R4 ;SIZE OF LEFT PARTITION SUB R1,R5 ;SIZE OF RIGHT PARTION + ENTSIZ CMP R4,R5 ;WHICH PARTITION IS LARGER ? BHI 7$ ;THE LEFT ONE IS . . . ; ELSE THE RIGHT PARTITION IS THE LARGER. WE WISH TO STACK ; THE LARGER TO MINIMIZE STACK SIZE AT RUNTIME. MOV R1,@SP ;STORE NEW LEFT PTR ADD R0,@SP ;AND ADD IN ENTSIZ TST R4 ;IS THE LEFT PART NULL? BEQ QUICKS ;YUP - JUST DO THE RIGHT SUB R0,R1 ;GET NEW STOP ADDR MOV R1,-(SP) ;AND STACK IT MOV R2,-(SP) ;ALSO STACK LEFT PTR BR QUICKS ;START SORTING LEFT PARTITION 7$: MOV R1,R2 ;GET STOP ADDRESS SUB R0,R2 ;BACK UP AN ENTRY MOV R2,2(SP) ;AND SET RIGHT PTR ON STACK TST R5 ;IS RIGHT PART NULL? BEQ QUICKS ;YUP - JUST DO THE LEFT MOV R3,-(SP) ;PUT NEW RIGHT PTR ON STACK ADD R0,R1 ;AND NEW LEFT POINTER MOV R1,-(SP) ;STACK IT BR QUICKS ;GO SORT ; EXCHANGE TWO ENTRIES JUST COMPARED. 8$: CMPB -(R4),-(R5) ;RESET POINTERS FOR EXCHANGE 9$: MOVB @R4,R0 ;EXCHANGE ONE BYTE OF EACH MOVB @R5,(R4)+ MOVB R0,(R5)+ DEC R3 ;LOOP UNTIL ALL BYTES SWITCHED BNE 9$ MOV #ENTSIZ,R0 ;RESET R0 VALUE COM INTFLG ;SWITCH POINTER MOVEMENT BEQ 4$ ; AND UPDATE POINTERS BR 5$ DONE: JMP DONSRT ;RETURN TO CALLER QPOP2: CMP (SP)+,(SP)+ ;POP POINTERS BR QUICKS ;AND CONTINUE .SBTTL LOWER-LEVEL SORT ROUTINE ; ROUTINE IS CALLED FROM QUICKSORT TO HANDLE PARTITIONS ; OF A SMALL NUMBER OF ITEMS (TO MINIMIZE SIZE OF STACK) ; ; AT ENTRY, THE REGISTER ALLOCATION IS: ; R0 = ENTSIZ ; R1 = ADDRESS OF FIRST ITEM TO BE SORTED ; R2 = ADDRESS OF LAST ITEM TO BE SORTED ; R4 = ADDRESS OF FIRST ITEM (=R1) ; R5 = ADDRESS OF SECOND ITEM SORT: CLR SRTFLG ;CLEAR BACKUP FLAG 1$: CMP R4,R2 ;DONE YET? BHIS QPOP2 ;YUP - RETURN TO QUICKSORT MOV R0,R3 ;ELSE SET LOOP COUNT 2$: CMPB (R4)+,(R5)+ ;COMPARE NEXT TWO ENTRIES BNE 3$ DEC R3 BNE 2$ BR 4$ ;IF THEY WERE EQUAL, BRANCH 3$: CMPB -(R4),-(R5) ;BACKUP POINTERS BHI 5$ ;BRANCH IF WE MUST EXCHANGE ADD R3,R4 ;ELSE UPDATE TO NEXT ITEM ADD R3,R5 4$: TST SRTFLG ;WERE WE GOING BACKWARDS? BEQ 1$ ;NOPE - JUST CONTINUE MOV SRTFLG,R4 ;ELSE PICK UP START ADDR MOV R4,R5 ;SET UP SECOND POINTER ADD R0,R5 ;PUSH UP ONE ITEM BR SORT ;AND CONTINUE 5$: MOVB @R4,R0 ;EXCHANGE DISORDERED ITEMS MOVB @R5,(R4)+ MOVB R0,(R5)+ DEC R3 BNE 5$ TST SRTFLG ;BACKING UP ALREADY? BNE 6$ ;YUP - SKIP POINTER SETUP MOV R4,SRTFLG ;ELSE NOTE WHERE TO RESTART 6$: MOV #ENTSIZ*2,R0 ;PREPARE TO BACK UP ONE ENTRY SUB R0,R4 SUB R0,R5 ASR R0 ;R0 = ENTSIZ CMP R5,R1 ;BACK TO THE BEGINNING? BHI 1$ ;NOPE - KEEP BACKING UP BR 4$ ;YES - RESET BACKUP AND CONTINUE .SBTTL LISTING OUTPUT FORMAT ROUTINE ; READ A SORTED CORE LOAD (IN DEFERENCE TO DECTAPE-ONLY ; SYSTEMS) AND WRITE THE LISTING OUTPUT. FORMAT: MOV F3BUF,R5 ;GET A CONVENIENT PLACE FOR LINE BUFFER MOV R5,R2 ;SET BUFFER POINTER MOV #140.,R1 ;SET LOOP COUNT 1$: MOVB #SPACE,(R2)+ ;BLANK OUT LINE BUFFER DEC R1 BNE 1$ MOV R5,R2 ;RESTORE POINTER MOV F2BUF,R5 ;PLACE FOR FIRST OUTPUT BUFFER MOV R5,CURBUF ;INDICATE SUCH MOV R5,OUTPTR ;AND INITIALIZE OUTPUT POINTER ADD #512.,R5 ;POINT AT SECOND OUTPUT BUFFER MOV R5,NXTBUF ;AND STORE ITS ADDRESS TST INCORE ;IS FILE IN CORE ALREADY? BMI NEXT1 ;YES - DON'T READ NEXT: TST INCORE ;IF ENTIRE FILE FITS, BMI ALLDON ;THEN WE MUST BE DONE ALREADY MOV #F1CMD,R5 ;POINT AT INPUT FILE DATA JSR PC,READ ;READ A CORELOAD BEQ ALLDON ;EOF - ALL DONE MOV R0,ENDF1 NEXT1: MOV F1BUF,R1 ;INIT INPUT POINTER ADD SECT3,F1BLK ;UPDATE INPUT BLOCK NUMBER NEWITM: CMP ENDF1,R1 ;END OF BUFFER ? BLO NEXT ;YES - GET A NEW ONE CMPB CRFTP,(R1)+ ;STILL THE SAME TYPE ? BEQ 1$ ;YES - SKIP TSTB -(R1) ;THE VERY END (OF THE FILE) ? BEQ ALLDON ;YES - GO CLOSE UP SHOP CLR PAGNUM ;ELSE RESET THE PAGE NUMBER MOVB (R1)+,R0 ;GET THE NEW TYPE MOVB R0,CRFTP ;SAVE FOR COMPARE BIC #177740,R0 ;ISOLATE LETTER SPEC ADD #100,R0 ;MAKE IT ASCII MOVB R0,CRFTYP ;AND INSTALL IT IN HEADER LINE JSR PC,ENDPAG ;PRINT THE HEADER AND SUCH 1$: MOV #6,R0 ;SET LOOP COUNTER MOV #CURNAM,R5 ;POINT AT CURRENT SYMBOL NAME 2$: CMPB (R1)+,(R5)+ ;CHECK FOR A NEW SYMBOL NAME BNE 4$ ;FOUND A DIFFERENCE - JUMP DEC R0 ;ELSE CHECK NEXT BYTE BNE 2$ ;IF THERE IS ONE 3$: DEC NUMFLD ;SEE IF ANY SPACE LEFT ON LINE BNE 9$ ;YES - GO INSERT NEXT REFERENCE JSR PC,ENDLIN ;ELSE END THIS LINE ADD #6,R2 ;NO SYMBOL NAME 9$: MOV R2,-(SP) ;SAVE CURRENT LINE POINTER INC R2 ;LEAVE ONE BLANK MOVB (R1)+,R0 ;GET PAGE NUMBER SWAB R0 CLRB R0 BISB (R1)+,R0 MOVB (R1)+,-(SP) ;PUT LINE NUMBER ON STACK SWAB @SP MOVB (R1)+,@SP CMP #-1,R0 ;IS PAGE NUMBER -1? BEQ 6$ ;YES - HE ONLY WANTS LINE NUMBERS JSR R1,CVTASC ;ELSE CONVERT PAGE NUMBER .WORD DIG3,1 MOVB #'-,(R2)+ ;INSERT DELIMITER MOV (SP)+,R0 ;GET LINE NUMBER JSR R1,CVTASC ;AND CONVERT IT .WORD DIG3,0 BR 7$ 6$: ADD #2,R2 ;LEAVE 2 BLANKS MOV (SP)+,R0 ;GET LINE NUMBER JSR R1,CVTASC ;AND CONVERT IT .WORD DIG5,1 7$: MOVB (R1)+,(R2)+ ;INSTALL FLAG BYTE MOV (SP)+,R2 ;RESTORE LINE POINTER ADD #9.,R2 ;AND ADVANCE TO NEXT FIELD BR NEWITM ;AND GO RECORD NEXT 4$: CMPB -(R1),-(R5) ;RESET POINTERS FOR EXCHANGE 5$: MOVB (R1)+,(R5)+ ;MOVE NEW NAME INTO CURRENT NAME DEC R0 ;DONE MOVING NAME ? BNE 5$ ;NOPE - KEEP ON MOVIN' JSR PC,ENDLIN ;GET A NEW LINE MOV #CURNAM,R3 ;ADDR OF STORED SYMBOL NAME MOV (R3)+,(R2)+ ;MOVE NAME TO OUTPUT LINE MOV (R3)+,(R2)+ MOV (R3)+,(R2)+ BR 9$ ;HANDLE FIRST REF TO NEW NAME ALLDON: JSR PC,ENDLIN ;DUMP LINE BUFFER MOV OUTPTR,R2 ;GET CURRENT OUTPUT BUFFER POINTER 8$: CLRB (R2)+ ;AND CLEAR REMAINDER DEC OUTCNT ; FOR LP HANDLER BNE 8$ JSR PC,WRITBF ;DUMP THE LAST BUFFER MOV LSTCHN,R0 ;WAIT FOR THE WRITE TO END EMT 374 BCS INERR ;PRINT MESSAGE JMP EXIT ;AND EXIT INERR: ERROR .SBTTL END-OF-LINE ROUTINE ; THE FOLLOWING ROUTINE IS USED TO FLUSH THE CURRENT CONTENTS ; OF THE LINE BUFFER TO THE OUTPUT. A CARRIAGE RETURN/LINE FEED ; IS APPENDED TO THE LINE, AND THE LINE BUFFER IS BLANK-FILLED ; BEFORE RETURNING. R2 IS UPDATED TO POINT TO THE BEGINNING OF ; THE LINE BUFFER. ENDLIN: MOVB #CR,(R2)+ ;MOVE IN CARRIAGE RETURN - MOVB #LF,(R2)+ ; AND LINE FEED MOV R2,-(SP) ;SAVE R2 DEC LINLFT ;ASSURE ENOUGH ROOM ON PAGE BPL 1$ ;YES - THERE IS JSR PC,ENDPG1 ;ELSE GET A NEW PAGE 1$: MOV OUTPTR,R2 ;GET CURRENT POSITION IN BUFFER MOV F3BUF,R0 ;AND A POINTER TO THE LINE BUFFER MOV WIDTH,NUMFLD ;RESET NUMBER OF OUTPUT FLDS 2$: DEC OUTCNT ;IS BUFFER FULL YET ? BEQ 3$ ;YES - GO GET A NEW ONE MOVB @R0,(R2)+ ;MOVE LINE BUFFER TO OUTPUT BUFFER MOVB #SPACE,(R0)+ ;AND CLEAR LINE BUFFER CMP @SP,R0 ;MOVED ALL OF LINE YET ? BNE 2$ ;NO - KEEP GOING MOV R2,OUTPTR ;UPDATE BUFFER POINTER MOV F3BUF,R2 ;RESET LINE POINTER TST (SP)+ ;CLEAN UP STACK RTS PC ;AND RETURN 3$: MOV R0,-(SP) ;SAVE LINE POINTER JSR PC,WRITBF ;GET A NEW BUFFER MOV (SP)+,R0 ;RESTORE POINTER BR 2$ ;AND CONTINUE WHERE WE LEFT OFF .SBTTL END-OF-PAGE ROUTINE ; THIS ROUTINE TERMINATES THE CURRENT PAGE AND STARTS A NEW ; PAGE, WITH THE APPROPRIATE HEADER LINE. ENDPAG: INC LINLFT ;ASSURE AT LEAST ONE LINE JSR PC,ENDLIN ;CLOSE OUT THE CURRENT LINE ENDPG1: MOV #60.,LINLFT ;RESET # LINES LEFT THIS PAGE MOV F3BUF,-(SP) ;SAVE LINE BUFFER ADRS MOV #TTLBUF,R2 ;GET HEADER LINE BUFFER ADRS MOV R2,F3BUF ;AND USE IT TEMPORARILY MOV #TITLE,R0 ;GET ADDR OF HEADER FOR LISTING 1$: MOVB (R0)+,(R2)+ ;MOVE HEADER TO LINE BUF BNE 1$ DEC R2 ;CLOBBER NULL MOV #PAGEST,R0 ;GET PAGE NUMBER STRING 3$: MOVB (R0)+,(R2)+ ;AND MOVE IT INTO THE LINE BUFFER BNE 3$ DEC R2 ;CLOBBER THE NULL INC PAGNUM ;ADD ONE FOR NEW PAGE MOV PAGNUM,R0 ;GET CURRENT PAGE NUMBER TO CONVERT JSR R1,CVTASC ;AND MAKE IT DECIMAL .WORD DIG3,0 JSR PC,ENDLIN ;PRINT THE LINE MOV #SBTTL,R0 ;PREPARE TO PRINT SBTTL LINE 4$: MOVB (R0)+,(R2)+ ;MOVE IT INTO THE LINE BUFFER BNE 4$ DEC R2 ;CLOBBER THE NULL JSR PC,ENDLIN ;AND PRINT IT JSR PC,ENDLIN ;AND A BLANK CMP #1,PAGNUM ;IS THIS THE FIRST PAGE OF SECTION? BEQ 2$ ;YUP - JUST RETURN JSR PC,ENDLIN ;ELSE SKIP ANOTHER LINE 2$: MOV (SP)+,R2 ;RESTORE LINE BUFFER ADRS MOV R2,F3BUF ;AND BUFFER POINTER RTS PC ;AND RETURN .SBTTL LISTING WRITE, CONVERT-TO-ASCII ROUTINES WRITBF: MOV LSTCHN,R0 ;WAIT FOR THE PREVIOUS WRITE TO END EMT 374 MOV #LSTSPC,R0 ;AND START THE NEXT MOVB LSTCHN,@R0 EMT 375 BCS 1$ ;ERROR INC OUTBLK ;SET NEW BLOCK NUMBER FOR NEXT MOV #513.,OUTCNT ;RESET BYTES REMAINING IN BUFFER MOV NXTBUF,R2 ;GET THE NEXT BUFFER ADDR MOV CURBUF,NXTBUF ;SET NEXT BUFFER ADDR MOV R2,CURBUF ;AND SET CURRENT BUFFER RTS PC ;RETURN TO CALLER 1$: ERROR ; CONVERT THE UNSIGNED NUMBER IN R0 TO ASCII AT (R2)+. ; CALLING SEQUENCE: ; JSR R1,CVTASC ; .WORD ; .WORD <0 IF LEFT-JUSTIFY, 1 IF BLANK PAD> CVTASC: MOV (R1)+,R5 ;GET DIVISION TABLE POINTER CLR R3 ;CLEAR LEADING ZEROES FLAG 1$: MOV #-1,R4 ;INITIALIZE DIGIT ACCUMULATOR MOVB #SPACE,@R2 ;BLANK FILL 2$: INC R4 ;DIVIDE BY POWER OF TEN SUB @R5,R0 BCC 2$ ADD @R5,R0 ;CORRECT NUMBER TST -(R5) ;DONE? BEQ 3$ ;YES - GO PUT OUT LAST DIGIT ADD @R1,R2 ;INC IF BLANK FILL, ELSE NOP ADD R4,R3 ;LEADING ZERO? BEQ 1$ ;YES SUB @R1,R2 ;REMOVE AFFECT OF ABOVE ADD #'0,R4 ;MAKE ASCII MOVB R4,(R2)+ ;AND INSTALL IT BR 1$ ;CONTINUE WITH NEXT DIGIT 3$: ADD #'0,R4 ;MAKE LAST DIGIT ASCII MOVB R4,(R2)+ ;AND PUT IT IN BUFFER TST (R1)+ ;SKIP FLAG RTS R1 ;AND RETURN TO CALLER .SBTTL MERGE ROUTINE MERGE: MOV #ENTSIZ,R4 ;SET LOOP COUNT MOV F1BUF,R1 ;GET F1 BUFFER ADDR MOV F2BUF,R2 ;GET F2 BUFFER ADDR MOV F3BUF,R3 ;GET F3 BUFFER ADDR MOV #3*256.,F2WC ;ASSURE F2 READS 3 BLOCKS 1$: MOV R4,R0 ;SET LOOP COUNT 2$: MOVB @R1,(R3)+ ;MOVE A WORD TO OUTPUT BUFFER CMPB (R1)+,(R2)+ ;DID WE MOVE THE CORRECT ENTRY? BLO 3$ BHI 6$ DEC R0 ;EQUAL SO FAR, SO GO BACK BNE 2$ ;IF ANY WORDS LEFT SUB R4,R2 ;MOVE F2 POINTER BACK ONE ENTRY BR 5$ ;AND CHECK FOR END OF F1 3$: SUB R4,R2 ;BACK OFF F2 BY AN ENTRY DEC R0 ;AND INDICATE BYTE USED BEQ 5$ ;IT WAS THE LAST OF THE RECORD 4$: MOVB (R1)+,(R3)+ ;MOVE F1 TO F3 INC R2 ;ADVANCE F2 POINTER DEC R0 ;MOVE ONE ENTRY BNE 4$ 5$: CMP F2BUF,R1 ;END OF CURRENT F1 BUFFER ? BNE 8$ ;NOPE - CONTINUE BR 9$ ;YES - GO COPY F2 TO OUTPUT 6$: CMPB -(R2),-(R3) ;LAST BYTE MOVED WAS INCORRECT SUB R4,R1 ;MOVE F1 POINTER BACK ONE ENTRY 7$: MOVB (R2)+,(R3)+ ;MOVE F2 TO F3 INC R1 ;ADVANCE F1 POINTER DEC R0 ;FOR AS MANY WORDS AS LEFT BNE 7$ DEC R1 ;OFF BY A BYTE CMP ENDF2,R2 ;END OF F2 BUFFER ? BNE 8$ ;NOPE JSR PC,17$ ;ELSE CHECK E-O-F BEQ 12$ ;YES - GO COPY F1 8$: JSR PC,CHECK3 ;CHECK OUTPUT BUFFER BR 1$ ;AND CONTINUE MERGE 9$: JSR PC,CHECK3 ;CHECK ON OUTPUT BUFFER MOV R4,R0 ;SET LOOP COUNTER ASR R0 ;GET WORD COUNT 10$: MOV (R2)+,(R3)+ ;DONE WITH F1 - MOVE F2 TO OUTPUT DEC R0 ;MOVE ONE ENTRY AT A TIME BNE 10$ CMP ENDF2,R2 ;END OF F2 BUFFER ? BNE 9$ ;NOPE JSR PC,17$ ;ELSE CHECK E-O-F BEQ 16$ ;YES - WE'RE DONE BR 9$ ;AND CONTINUE 12$: JSR PC,CHECK3 ;CHECK FOR END OF OUTPUT BUFFER MOV R4,R0 ;SET LOOP COUNT ASR R0 ;GET WORD COUNT 13$: MOV (R1)+,(R3)+ ;MOVE F1 TO OUTPUT DEC R0 ;A WORD AT A TIME BNE 13$ CMP F2BUF,R1 ;END OF F1 BUFFER BNE 12$ ;AND CONTINUE 16$: CLR @R3 ;NOW, WE ARE DONE BR WRITE3 ;WRITE LAST AND RETURN TO CALLER 17$: MOV #F2BLK,R5 ;SET UP FOR READ ADD #3,@R5 TST -(R5) JSR PC,READ ;TRY A READ BEQ 18$ ;BRANCH ON E-O-F MOV F2BUF,R2 ;ELSE RESET BUFFER POINTER ADD #ENTSIZ,R0 ;POINT BEYOND LAST ENTRY MOV R0,ENDF2 ;RESET F2 END ADDR 18$: RTS PC ;RETURN TO CALLER CHECK3: CMP ENDF3,R3 ;END OF F3 BUFFER ? BNE W3END ;NOPE - DON'T WRITE WRITE3: MOV #F3CMD,R5 ;WRITE OUTPUT FILE JSR PC,WRITE ADD #3,F3BLK ;UPDATE BLOCK NUMBER MOV F3BUF,R3 ;RESET BUFFER POINTER W3END: RTS PC ;RETURN TO CALLER .SBTTL STORAGE ALLOCATION EQUATES .=4096.+START ;ALLOW 2K FOR USR SWAPPING QAREA: .BLKW 7 ;EXTRA QUEUE ELEMENT CRFHGH = . ;HIGH LIMIT .END START NOUSER=1 NOSTAT=1 NONAME=1 NOLPEN=1 NOTAG=1 .TITLE VTBASE V02-07 ; ; VTBASE ; ; THE ROOT SECTION OF THE VT11 DISPLAY FILE HANDLER ; ; DEC-11-OVTHA-E ; ; COPYRIGHT (C) 1974,1975 ; ; DIGITAL EQUIPMENT CORPORATION ; MAYNARD, MASSACHUSETTS 01754 ; ; 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 DIGITAL. ; ; THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO ; CHANGE WITHOUT NOTICE AND SHOULD NOT BE CONSTRUED ; AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION. ; DIGITAL ASSUMES NO RESPONSIBILITY FOR ANY ERRORS THAT ; MAY APPEAR IN THIS DOCUMENT ; ; DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE ; OR RELIABILITY OF ITS SOFTWARE ON EQUIPMENT ; WHICH IS NOT SUPPLIED BY DIGITAL. ; ; MARCH 74 ; ; D. VELTEN ; ; VERSION 02 ; ; EDIT 7 ; .SBTTL DEFINITIONS AND CONDITIONS ; THE DISPLAY FILE HANDLER IS CONDITIONALIZED SO THAT IT ; MAY BE EASILY ADAPTED TO A VARIETY OF APPLICATIONS. IF NO ; CONDITIONS ARE SPECIFIED, THE HANDLER WILL HAVE THESE ; CHARACTERISTICS: ; - DISPLAY STOP AND LIGHT PEN INTERRUPT HANDLERS ; - SUBPICTURE STACK DEPTH OF 10 ; - NAME REGISTER STACK DEPTH OF 10 ; - MAXIMUM OF 2 USER MAIN DISPLAY FILES ; - RT11 SCROLLER LINK-UP CAPABILITY ; - TRACKING OBJECT ; - BASIC/GT-FORTRAN/GT FILE COMPATIBILITY ; - SUBROUTINE CALL SEQUENCE WILL BE: ; DJSR ; RETURN ADDR. ; SUBR. ADDR. ; TAG ; ; TO ALTER THE HANDLER DEFAULT STRUCTURE: ; ; DEFINE: RESULT: ; ; NOLINK CREATES STAND ALONE SYSTEM W/O SCROLL ; LINK. CALL .SCROL IS UNDEFINED. ; ; NOTRAK NO TRACK OBJECT. IMPLIED WHEN NOTAG OR ; NOLPEN ARE DEFINED. ; ; NOTAG NO BASIC/GT TAG STRUCTURE. CALLS .BLANK, ; .RESTR,.TRACK ARE UNDEFINED. CALL SEQ. IS: ; DJSR ; ADDR. OF SUBR. ; ; NOLPEN NO LIGHT PEN SUPPORT, .LPEN UNDEFINED ; ; NOSTAT NO STATUS DATA SUPPORT, .STAT UNDEFINED. ; ; NOUSER A SINGLE USER DISPLAY FILE MAY BE ; INSERTED AT A TIME. ; ; NONAME NO NAME REGISTER STACK ; ; NORT11 RT11 MONITOR DEPENDENCIES ARE REMOVED. ; NOLINK IS IMPLIED AND .SCROL IS UNDEFINED. ; TO ALTER HANDLER DEFAULT PARAMETERS: ; ; DEFINE: DEFAULT(OCTAL): MEANING: ; ; SCRPOS 1750 SCROLL TOP Y POSITION ; ; STKSIZ 12 SUBPICTURE STACK DEPTH ; ; USERNM 2 MAX. # USER MAIN FILES ; THAT CAN BE CALLED BY HANDLR ; ; THE FOLLOWING ARE DISPLACEMENTS OF PARAMETERS WITHIN THE ; SCROLL LOGIC LOCATED ABOVE THE RMON FROM THE BEGINNING OF ; THE SCROLL LOGIC. THEY MUST BE REDEFINED IF THEIR POSITION ; CHANGES. ; ; TAG: DEFAULT USE ; ; SCLINK 6 SCROLL LINK SEGMENT ; ; SCMAX 4 MAX. LINE COUNT ; ; DISP 300 DISPL. FROM RMON (LOC. 54) ; TO CONFIG WD. ; ; THE VT11 HAS FLOATING VECTORS. IF THE VT11 IS INSTALLED AT ; A VECTOR OR DEVICE ADDRESS OTHER THAN DEFAULT, THESE ; PARAMETERS SHOULD BE REDEFINED: ; ; DEFINE: DEFAULT: MEANING: ; ; FVEC 320 DISPLAY STOP INT. TRAP ADDR. ; ; DPC 172000 FIRST DEVICE ADDR. (DISPLAY ; PROGRAM COUNTER). .SBTTL GLOBALS AND ASSIGNMENTS R0=%0 R1=%1 R2=%2 R3=%3 R4=%4 R5=%5 SP=%6 PC=%7 PR4=200 ;PRIORITY 4 DJSR=173400 ;DISPLAY SUBROUTINE CALL DRET=173400 ;DISPLAY SUBROUTINE RETURN DSTAT=173420 ;DISPLAY STATUS REQUEST DHALT=173500 ;DISPLAY HALT AND RETURN STATUS DNAME=173520 ;SET NAME REGISTER DNOP=164000 ;DISPLAY NOP DJMP=160000 CHAR=100000 ;CHARACTER MODE INT4=3000 ;INTENSITY 4 INT5=3200 ;5 INT6=3400 ;6 DSR=2 ;DISPL TO DSR XSR=4 ;DISPL. TO XSR YSR=6 ;DISPL. TO YSR .IIF NDF USERNM,USERNM=2 ;NUMBER OF USER CALLS PERMITTED .IIF NDF FVEC,FVEC=320 ;VT11 FLOATING VECTOR .IIF NDF DPC,DPC=172000 ;VT11 DEV. ADDR. .IIF NDF STKSIZ,STKSIZ=12 ;DEPTH OF SUBPIC STACK .IIF NDF SCRPOS,SCRPOS=1750 ;SCROLL TOP POSITION .IIF NDF SCTC,SCTC=12 ;DISPL TO ADDR OF CTRL/C ROUTINE $FVEC=FVEC .CSECT $GTB .IF DF NORT11 NOLINK=1 .IFF .GLOBL $PDV1,$PEXIT .ENDC .GLOBL $DPC,$DSVEC,$TACKE,$TACKP .GLOBL $SOINT,$VSTIN,$NR,$LSRA .GLOBL $STOPF,$DFILE,$DSINT,$VSTP .GLOBL STKSIZ,SCRPOS,$FVEC,$LPINT .GLOBL $DFILE,$CTRAK,$NULL,$CUSER .IF DF NOUSER USERNM=1 ;SINGLE USER FILE .ENDC .IF NDF NONAME .GLOBL $NRBUF .ENDC .IF DF NOTAG!NOLPEN NOTRAK=1 .ENDC .IF NDF NOLPEN .GLOBL $LPBUF,$TACKP .ENDC .IF NDF NOTRAK .GLOBL $XSTOR,$YSTOR,$XT,$YT,$TRAKC .ENDC .IF NDF NOSTAT .GLOBL $TATBF .ENDC .IF NDF NOLINK .GLOBL $LINKF,$LCDIS,$LINK,$LCNT .GLOBL $BYPAS,$BLANK,$YS .ENDC NO$X=0 .IF DF NOLPEN .IF DF NOSTAT NO$X=1 .ENDC .ENDC .SBTTL DISPLAY STOP INTERRUPT HANDLER ; THE DISPLAY STOP INTERRUPT IS USED TO IMPLEMENT SEVERAL ; FEATURES OF THE DEVICE SUPPORT PACKAGE--SUBROUTINE ; CALLS, SUBROUTINE RETURN, SUBPICTURE TAGGING, EXTERNAL STOPS, ; AND NAME REGISTER TAGGING. THE WORD FOLLOWING THE DSTOP IS ; USED AS AN ARGUMENT: ; 0 SUBROUTINE RETURN ; 1-77777 NAME REGISTER TAG ; 1000 UP SUBROUTINE CALL ; IF RT11 VERSION 2 IS THE MONITOR IN USE, ALL INTERRUPT ; HANDLERS MUST MAKE A CALL TO A SETUP SERVICE IN RMON. ; THIS SERVICE RAISES THE PRIORITY OF THIS ROUTINE TO THE ; REQUESTED LEVEL AND SAVES R4 AND R5 ON THE STACK. RETURN ; IS VIA A RTS PC RATHER THAN A RTI. $DSINT: .IF DF NORT11 MOV R4,-(SP) ;SAVE REGISTERS MOV R5,-(SP) .IFF MOV @#54,-(SP) ;PUSH RMON ADDR ON STK JSR R5,@(SP)+ ;CALL RT11 INT SETUP .WORD 140 ;GO TO SYSTEM STATE AT PR4 .ENDC TST (PC)+ ;STOP FLAG SET? $STOPF: .WORD 0 ;STOP FLAG BEQ 1$ ;NO, GO ON CLR $STOPF ;YES, EXIT WITH DISPLAY STOPPED BR EXIT 1$: MOV @$DPC,R4 ;GET THE DISPLAY PC .IF NDF NOSTAT CMP #DSTAT,-2(R4) ;WHICH STOP DID IT? BHI DSTOPC ;SUBROUTINE SERVICE BEQ DSTATS ;STATUS REQUEST CMP #DHALT,-2(R4) ;NONE OF ABOVE, WAS IT BEQ DSTOPM ;DISPLAY HALT REQUEST? .IFF CMP #DNAME,-2(R4) ;IS IT A DNAME? BNE DSTOPC ;NO,ASSUME SUBR CALL .ENDC ; ASSUME NAME REGISTER SERVICE REQUEST MOV (R4)+,(PC)+ ;SAVE ARGUMENT IN NAME REG. $NR: .WORD 0 ;NAME REGISTER MOV R4,@$DPC ;RESUME DISPLAY BR EXIT ; THE DJSR CODE IS EITHER A SUBROUTINE CALL OR A RETURN, ; DEPENDING ON THE ARGUMENT OF THE CALL .ENABL LSB DSTOPC: MOV (PC)+,R5 ;R5 -> TAG STACK $TACKP: .WORD $TACKE ;SUBPICTURE STACK POINTER .IF NDF NOTAG TST (R4) ;ARG. ZERO? .IFF TST (R4)+ .ENDC BNE 2$ ;NO, NEW SUBR CALL ; YES, EITHER A SUBROUTINE RETURN OR THE BOTTOM OF ROOT FILE CMP #$TACKE,R5 ;STACK EMPTY? BNE 1$ ;NO, USER RETURN MOV #$DFILE,@$DPC ;RESUME THE DISPLAY BR EXIT ;AT TOP OF ROOT FILE 1$: MOV (R5)+,R4 ;ADDR. OF RETURN ADDR. .IF NDF NOTAG MOV (R4),@$DPC ;START THE DPU .IFF MOV R4,@$DPC .ENDC MOV R5,$TACKP ;SAVE TAG STACK PTR .IF NDF NONAME MOV (PC)+,R5 ;R5 -> NAME STACK $TACKN: .WORD $TAKNE ;NAME REG. STACK POINTER MOV (R5)+,$NR ;RESTORE NR VALUE MOV R5,$TACKN ;SAVE NR STACK .ENDC BR EXIT 2$: CMP #STACK,R5 ;STACK OVERFLOW? BHIS 3$ ;YES! MOV R4,-(R5) ;STACK ADDR OF RET ADD(DSTOP+2) MOV R5,$TACKP ;SAVE TAG STK PTR .IF NDF NONAME MOV $TACKN,R5 ;R5 -> N STACK MOV $NR,-(R5) ;AND SAVE NR MOV R5,$TACKN ;SAVE N STK PTR .ENDC 3$: .DSABL LSB .IF NDF NOTAG MOV 2(R4),@$DPC .IFF MOV -2(R4),@$DPC .ENDC BR EXIT .IF NDF NOSTAT DSTOPM: INC $STOPF ;SET STOP FLAG FOR LATER DSTATS: TST (PC)+ ;BUFFER POINTER SET UP? $TATBF: .WORD 0 ;ADDR. OF USER STATUS BUFR BEQ REXIT ;NO, JUST EXIT MOV #DNOP,-2(R4) ;DNOP THE REQUEST MOV @$TACKP,R4 ;GET CURRENT SUBPIC. MOV 4(R4),R4 ;PUT ITS TAG IN R4 MOV $TATBF,R5 ;POINT TO USER STATUS BUFR JSR PC,$XSTAT ;TRANSFER DATA .ENDC REXIT: INC @(PC)+ ;RESUME THE DISPLAY $DPC: .WORD DPC ;POINTER TO DISPLAY PC EXIT: .IF DF NORT11 MOV (SP)+,R5 MOV (SP)+,R4 RTI .IFF RTS PC .ENDC .IF NDF NOLINK $LINKF: .WORD 0 ;LINK FLAG(=0 NO LINK) $LCDIS: .WORD -1 ;LINE COUNT DISPLAC. FROM 54 $LCNT: .WORD 0 ;RMON LINE CNT SAVED BY LNKRT .ENDC $DSVEC: .WORD FVEC ;POINTER TO GT40/44 INT VECTOR STACK: .BLKW STKSIZ ;SUBPICTURE STACK $TACKE=. .IF NDF NONAME .BLKW STKSIZ ;NAME REGISTER STACK $TAKNE=. .ENDC .SBTTL DISPLAY FILE FOR VT11 DRIVER ; ROOT DISPLAY FILE FOR THE VT11 SUPPORT PACKAGE. ; THE DEVICE DRIVER PORTION OF THE VT11 SUPPORT PACKAGE ; MAINTAINS CONTROL OVER THE VT11 BY USING ITS OWN ; DISPLAY FILE AS THE ROOT FILE. ALL USER FILES ARE CALLED ; AS SUBPICTURES TO THE ROOT FILE. THIS FILE ALSO CONTAINS ; THE TRACKING OBJECT AND THE LINK TO THE SCROLLER, IF THERE ; IS ONE. ; MACRO TO GENERATE CALLS TO A NULL USER DISPLAY FILE .MACRO PCALL .IF NDF NOTAG DJMP .+4 .IFF DJSR .ENDC $NULL .ENDM ; DISPLAY FILE STARTS WITH LINK TO SCROLLER. THE ABSOLUTE POINT ; OVERIDES THE START POSITION IN THE SCROLLER. IT IS SET ; INITIALLY TO THE TOP OF THE SCREEN. THE LINK TO THE SCROLLER ; IS NOT MADE UNTIL A CALL TO SCROLL LINK IS MADE. $DFILE: .WORD 110000 ;LONGV TO SLOW 'ER DOWN FOR F/B .WORD 1777,0 .WORD 21777,0 .IF NDF NOLINK 117124 ;APNT!INT4!TYPE0!LPOFF 0 ;X POS. -- START OF SCROLL $YS: .WORD SCRPOS ;Y POS. $BLANK: CHAR!INT5 ;USED TO BLANK TEXT SCROLL DJMP ;LINK TO SCROLL, BUT $LINK: .WORD .+2 ;NOT INITIALLY DJMP ;BY-PASS ALL USER CALLS $BYPAS: $CTRAK ;FOR SIMULATED EXTERN. STOP .ENDC ; FILE NEXT CONTAINS A CALL TO THE TRACK OBJECT, WHICH ; IS INITIALLY BYPASSED UNTIL A CALL TO TRACK. .IF NDF NOTRAK $CTRAK: DJMP ;REPLACE WITH DJSR .+6 ;TO CALL TRACK OBJECT. TRACK ;ADDRESS OF TRACK SUBP. -1 ;SPECIAL SUBP. TAG FOR TRACK .IFF $CTRAK: .ENDC ; AFTER THE CALL TO THE TRACK OBJECT, ISSUE SOME INSTRUCTIONS ; TO NORMALIZE THE DISPLAY. .WORD 117124 ;APNT!INT4!TYPE0!LPOFF .WORD 0,0 ;(X,Y)=(0,0) $LSRA: .WORD 170240 ;LSR A:LP INTENSIFY!NORMAL FONT!NOSYNC .WORD 174101 ;LSRB: GRAPH INCR = 1 $CUSER: .REPT USERNM PCALL .ENDR $NULL: DRET ;END OF ROOT FILE .WORD 0 ; THIS IS THE TRACK OBJECT SUBPICTURE CALLED FROM THE ROOT FILE. .IF NDF NOTRAK TRACK: .WORD 170200 ;LSR A .WORD 117524 ;APNT!INT6!LINE0 $XT: .WORD 0 ;X POS. OF OBJECT $YT: .WORD 0 ;Y POS. .WORD 104100 ;SHORTVEC!LPOFF .WORD 57600 .WORD 37677 .WORD 40177 .WORD 40177 .WORD 37677 .WORD 57600 .WORD 17600 ; TURN ON LP INTERRUPTS FOR REST OF TRACK FIGURE .WORD 104140 ;LPON .WORD 77677 .WORD 77777 .WORD 57777 .WORD 57677 .WORD 65600 .WORD 72050 .WORD 72150 .WORD 52150 .WORD 52050 .WORD 72050 DRET .WORD 0 .ENDC .IF NDF NOLPEN .SBTTL LIGHT PEN INTERRUPT HANDLER ; THIS ROUTINE SERVICES THE LIGHT PEN INTERRUPTS FROM THE VT11. ; IF THE HIT WAS ON THE TRACKING OBJECT, THE ROUTINE MOVES THE ; OBJECT TO THE NEW POSITION AFTER SMOOTHING THE DATA AND ; RETURNING IT TO THE USER AREA(UNSCALED). IF THE HIT WAS ON A ; SUBPICTURE THE HANDLER RETURNS STATUS DATA TO ABUFFER IN THE ; USER AREA WHOSE ADDRESS WAS PREVIOUSLY SET UP BY A CALL TO THE ; .LPEN MACRO. IT FIRST CHECKS THE FLAG TO SEE IF DATA PREVIOUSLY ; HAS BEEN PROCESSED (I.E. BUFFER FLAG IS CLEAR). THEN IT ; TRANSFERS THE DATA AND SETS THE FLAG. .ENABL LSB $LPINT: .IF DF NORT11 MOV R4,-(SP) MOV R5,-(SP) .IFF MOV @#54,-(SP) ;PUSH RMON ADDR ON STK JSR R5,@(SP)+ ;CALL RT11 INT SERVICE .WORD 140 ;LEVEL 4 .ENDC MOV @$TACKP,R5 ;POINT TO CURRENT SUBP. MOV 4(R5),R4 ;PUT TAG IN R4. .IF NDF NOTRAK CMP #-1,R4 ;IS IT -1? BEQ LPTRAK ;TAG= -1 IS TRACK OBJECT .ENDC MOV (PC)+,R5 ;GET USER BUFR ADDR. $LPBUF: .WORD 0 ;ADDR. OF USER STATUS BUFFER BEQ REXIT ;NONE IF ZERO JSR PC,$XSTAT ;TRANSFER STATUS TO USER .IF NDF NONAME MOV (PC)+,R5 ;R5 -> USER NAME BUFFER $NRBUF: .WORD 0 ;ADDR OF USER NAME STACK BUFFER BEQ REXIT ;EXIT IF NONE JSR PC,$NRXFR ;GO TRANSFER DATA .ENDC 1$: BR REXIT .IF NDF NOTRAK LPTRAK: MOV $DPC,R5 ;POINT TO DISPLAY PC BIT #40,DSR(R5) ;EDGE VIOLATION? BNE REXIT ;YES,JUST EXIT MOV XSR(R5),R4 ;GET X STATUS REG. AND BIC #176000,R4 ;MASK OFF X POSITION. SUB $XT,R4 ;XNEW-XOLD ASR R4 ;DIV. BY 2 ASR R4 ;DIV. BY 2 ADD R4,$XT ;X=OLD+(NEW-OLD)/4 MOV $XT,@$XSTOR ;PASS TO USER LPYTST: MOV YSR(R5),R4 ;GET Y STATUS BIC #176000,R4 ;MASK OFF Y POSITION SUB $YT,R4 ;YNEW-YOLD ASR R4 ;DIV. BY 2 ASR R4 ;DIV. BY 2 ADD R4,$YT ;Y=OLD+(NEW-OLD)/4 MOV $YT,@$YSTOR ;PASS TO USER MOV (PC)+,R5 ;COMPLETION ROUTINE SET UP? $TRAKC: .WORD 0 ;ADDR. OF USERS TRACK COMPL ROUT. BEQ 1$ ;NO, JUST EXIT JSR PC,@R5 ;YES, CALL IT AS A SUBR. BR 1$ ;GO EXIT .ENDC .DSABL LSB .ENDC .IF NDF NOTRAK $XSTOR: .WORD 0 ;ADDR. OF USER X TRACK COORDINATE $YSTOR: .WORD 0 ;ADDR. OF USER Y TRACK COORDINATE .ENDC .IF DF NOLPEN $LPINT: JSR PC,$VSTIN RTI .ENDC .IF EQ NO$X .SBTTL DATA TRANSFER SUBROUTINE ($XSTAT) ; SUBROUTINE TO TRANSFER STATUS DATA TO A USER BUFFER AREA ; WHOSE ADDRESS WAS PREVIOUSLY SET UP BY A CALL TO A STATUS ; MACRO. ADDR. OF BUFFER IS EXPECTED IN R5 AND A SUBPICTURE ; TAG,IF ANY, IN R4. R4 AND R5 ARE ALTERED. $XSTAT: TST (R5) ;USER FLAG CLEAR? BNE XEXIT ;NO, JUST EXIT INC (R5)+ ;YES, SET THE FLAG MOV $NR,(R5)+ ;XFR NAME REG. TAG MOV R4,(R5)+ ;XFR SUBPICTURE TAG MOV $DPC,R4 ;PUT DPC ADDR IN R4 MOV (R4)+,(R5)+ ;XFR DPC MOV (R4)+,(R5)+ ;XFR DSR MOV (R4)+,(R5)+ ;XFR XSR MOV (R4),(R5) ;XFR YSR XEXIT: RTS PC .ENDC .IF NDF NONAME .SBTTL NAME STACK TRANSFER SUBROUTINE ; THIS SUBROUTINE TRANSFERS THE NAME REGISTER STACK DEPTH ; AND CONTENTS TO A BUFFER SUPPLIED BY THE USER AND ; SPECIFIED WITH THE .NAME CALL. THE FIRST BYTE OF THE BUFFER ; WILL CONTAIN THE DEPTH, THE SECOND BYTE WILL BE SET NEGATIVE ; TO FLAG THE TRANSFER. THE BUFFER SIZE SHOULD BE STACK SIZE ; PLUS ONE. ONLY THE NUMBER OF WORDS INDICATED BY THE STACK DEPTH ; ARE ACTUALLLY TRANSFERRED, I.E. THE REST OF THE BUFFER IS ; NOT CLEARED. TO INDICATE THE BUFFER IS READY FOR ANOTHER ; TRANSFER, THE FIRST WORD SHOULD BE CLEARED. THE USER CAN THEN LOOP ; ON A TST OF THE FIRST WORD. $NRXFR: TST @R5 ;USER FLAG CLEARED? BNE 2$ ;NO, JUST EXIT MOV R3,-(SP) MOV #$TAKNE,R4 ;R4=TOP OF STACK MOV R4,R3 SUB $TACKN,R3 ;R3=STACK DEPTH ASR R3 ;CONVERT TO WORDS MOVB R3,(R5)+ ;STORE IN BUFFER COMB (R5)+ ;SET HI BYTE NEGATIVE 1$: MOV -(R4),(R5)+ ;TRANSFER NAME STACK DEC R3 ;TO USER BUFFER BNE 1$ ;DONE? MOV (SP)+,R3 2$: RTS PC .ENDC .SBTTL SHIFT OUT/TIME OUT INTERRUPT HANDLER ; SHIFT OUT/TIME OUT INTERRUPT ROUTINE. HANDLES THESE INTERRUPTS ; IN THE ABSENCE OF A HANDLER IN THE SCROLLER LOGIC. SIMPLY RESTARTS ; THE DISPLAY. ; THIS HANDLER IS NEEDED IF NO LINK IS MADE TO THE SCROLLER. ; IT IS NECESSARY FOR SYSTEMS NOT USING THE SCROLL ; SUPPORT OR FOR SYSTEMS OTHER THAN RT11. $SOINT: JSR PC,$VSTIN ;INIT STACK AND START DPU RTI .SBTTL STACK INITIALIZATION SUBROUTINE ; CLEARS STACK AND STARTS DPU AT TOP. $VSTIN: MOV #$TACKE,$TACKP ;RESET STACK POINTER .IF NDF NONAME MOV #$TAKNE,$TACKN ;ALSO N STACK .ENDC MOV #$DFILE,@$DPC ;START THE DISPLAY RTS PC ; $VSTP -- UTILITY SUBROUTINE TO STOP THE DISPLAY PROCESSOR. ; IT IS ONLY USED INTERNALLY TO STOP THE DPU WHEN CRITICAL ; CHANGES ARE BEING MADE IN THE DISPLAY FILE. THE DPU ; IS ACTUALLY STOPPED FOR A USER .STOP REQUEST ONLY WHEN ; NOLINK HAS BEEN DEFINED AND THERE IS NO POSSIBILITY OF ; A LINK EXISTING WITH A MONITOR. $VSTP: MOV R2,-(SP) MOV $DPC,R2 ;POINT TO DISPLAY PC TST (R2)+ ;WAS DPU EVER STARTED? BEQ 2$ ;NO, JUST EXIT TST (R2) ;IF SO, IS IT STOPPED? BMI 2$ ;YES, SO EXIT INC $STOPF ;NO, REQUEST A STOP 1$: TST $STOPF ;WAIT TIL DONE BNE 1$ 2$: MOV (SP)+,R2 RTS PC .IF NDF NORT11 .SBTTL SPECIAL DEVICE TABLE ; THIS TABLE IS USED BY THE RT11 FOREGROUND/BACKGROUND ; MONITOR TO ZAP THE DISPLAY WHEN THE USER PROGRAM EXITS. ; THIS IS NECESSARY BECAUSE F/B DOES NOT USE HARD RESETS. ; THE SPECIAL EXIT PERFORMS THE FUNCTION OF THE CTRL/C IN ; THE S/U MONITOR TO ENSURE THE VT11 IS ZAPPED ONLY WHEN THE ; CTRL/C IS TYPED TO THE JOB USING THE DISPLAY. OTHERWISE WE ; MIGHT HAVE AN IRATE FOREGROUND USER! $PDV1: .WORD $FVEC,$PEXIT,0 ; THIS SPECIAL EXIT ROUTINE GOES TO SYSTEM STATE, THEN DETERMINES ; IF THERE IS A SCROLLER IN CORE. IF NOT, A SIMPLE EXIT WITH THE ; VT11 DEAD IS SUFFICIENT, ELSE WE HAVE TO CALL THE CTRL/C CODE ; IN THE SCROLLER LOGIC TO DE-LINK, ETC. $PEXIT: MOV @#54,-(SP) ;GO TO SYSTEM STATE JSR R5,@(SP)+ .WORD 140 ;AT LEVEL 4 MOV @#54,R4 ;POINT TO RMON MOV 302(R4),R5 ;F/B, SEE IF SCROLLER IN CORE BEQ 1$ ;NO, SUFFICIENT TO EXIT JMP @SCTC(R5) ;GO TO CTRL/C ROUTINE IN SCROLLER 1$: RTS PC .ENDC .END .NLIST .TITLE VTMAC ; ; VTMAC ; ; LIBRARY OF MACRO CALLS AND MNEMONIC DEFINITIONS ; FOR THE VT11 DEVICE SUPPORT PACKAGE ; ; DEC-11-OVTMA-E ; ; 24 OCTOBER 73 ; ; COPYRIGHT (C) 1974,1975 ; ; DIGITAL EQUIPMENT CORPORATION ; MAYNARD, MASSACHUSETTS 01754 ; ; 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 DIGITAL. ; ; THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO ; CHANGE WITHOUT NOTICE AND SHOULD NOT BE CONSTRUED ; AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION. ; ; DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE ; OR RELIABILITY OF ITS SOFTWARE ON EQUIPMENT ; WHICH IS NOT SUPPLIED BY DIGITAL. ; ; VTMAC IS A LIBRARY OF MACRO CALLS WHICH PROVIDE SUPPORT ; OF THE VT11 DISPLAY PROCESSOR. THE MACROS PRODUCE CALLS ; TO THE VT11 DEVICE SUPPORT PACKAGE, USING GLOBAL REFER- ; ENCES. ; MACRO TO GENERATE A MACRO WITH ZERO ARGUMENTS. ; .MACRO MAC0 NAME,CALL .MACRO NAME .GLOBL CALL JSR %^O7,CALL .ENDM .ENDM ; ; MACRO TO GENERATE A MACRO WITH ONE ARGUMENT ; .MACRO MAC1 NAME,CALL .MACRO NAME ARG .IF NB,ARG MOV ARG,%^O0 .ENDC .GLOBL CALL JSR %^O7,CALL .ENDM .ENDM ; ; MACRO TO GENERATE A MACRO WITH TWO OPTIONAL ARGUMENTS ; .MACRO MAC2 NAME,CALL .MACRO NAME ARG1,ARG2 .GLOBL CALL .IF NB,ARG1 MOV ARG1,%^O0 .ENDC .IF NB,ARG2 MOV ARG2,-(%^O6) .IFF CLR -(%^O6) .NARG T .IF EQ,T CLR %^O0 .ENDC .ENDC JSR %^O7,CALL .ENDM .ENDM ; ; MACRO LIBRARY FOR VT11: ; MAC0 <.CLEAR>,<$VINIT> MAC0 <.STOP>,<$VSTOP> MAC0 <.START>,<$VSTRT> MAC1 <.INSRT>,<$VNSRT> MAC1 <.REMOV>,<$VRMOV> MAC1 <.BLANK>,<$VBLNK> MAC1 <.RESTR>,<$VRSTR> MAC1 <.STAT>,<$VSTPM> MAC1 <.LPEN>,<$VLPEN> MAC1 <.SCROL>,<$VSCRL> MAC2 <.TRACK>,<$VTRAK> MAC0 <.LNKRT>,<$VRTLK> MAC0 <.UNLNK>,<$VUNLK> ; MNEMONIC DEFINITIONS FOR THE VT11 DISPLAY PROCESSOR ; DJMP=160000 ;DISPLAY JUMP DNOP=164000 ;DISPLAY NOP DJSR=173400 ;DISPLAY SUBROUTINE CALL DRET=173400 ;DISPLAY SUBROUTINE RETURN DNAME=173520 ;SET NAME REGISTER DSTAT=173420 ;RETURN STATUS DATA DHALT=173500 ;STOP DISPLAY AND RETURN STATUS DATA ; CHAR=100000 ;CHARACTER MODE SHORTV=104000 ;SHORT VECTOR MODE LONGV=110000 ;LONG VECTOR MODE POINT=114000 ;POINT MODE GRAPHX=120000 ;GRAPH X MODE GRAPHY=124000 ;GRAPH Y MODE RELATV=130000 ;RELATIVE VECTOR MODE ; INT0=2000 ;INTENSITY 0 INT1=2200 INT2=2400 INT3=2600 INT4=3000 INT5=3200 INT6=3400 INT7=3600 ; LPOFF=100 ;LIGHT PEN OFF LPON=140 ;LIGHT PEN ON BLKOFF=20 ;BLINK OFF BLKON=30 ;BLINK ON LINE0=4 ;SOLID LINE LINE1=5 ;LONG DASH LINE2=6 ;SHORT DASH LINE3=7 ;DOT DASH ; STATSA=170000 ;LOAD STATUS REG A LPLITE=200 ;INTENSIFY ON LPEN HIT LPDARK=300 ;DON'T INTENSIFY ITAL0=40 ;ITALICS OFF ITAL1=60 ;ITALICS ON SYNC=4 ;POWER LINE SYNC ; STATSB=174000 ;LOAD STATUS REG B INCR=100 ;GRAPH PLOT INCREMENT INTX=40000 ;INTENSIFY VECTOR OR POINT MAXX=1777 ;MAXIMUM X INCR. - LONGV MAXY=1377 ;MAXIMUM Y INCR. - LONGV MINUSX=20000 ;NEGATIVE X INCREMENT MINUSY=20000 ;NEGATIVE Y INCREMENT MAXSX=17600 ;MAXIMUM X INCR. - SHORTV MAXSY=77 ;MAXIMUM Y INCR. - SHORTV MISVX=20000 ;NEGATIVE X INCR. - SHORTV MISVY=100 ;NEGATIVE Y INCR. - SHORTV .LIST ;PCIOCH.MAC V02-02 .NLIST ; COPYRIGHT (C) 1974,1975 ; ; DIGITAL EQUIPMENT CORPORATION ; MAYNARD, MASSACHUSETTS 01754 ; ; 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 DIGITAL. ; ; THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO ; CHANGE WITHOUT NOTICE AND SHOULD NOT BE CONSTRUED ; AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION. ; ; DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE ; OR RELIABILITY OF ITS SOFTWARE ON EQUIPMENT ; WHICH IS NOT SUPPLIED BY DIGITAL. ; .LIST .SBTTL MCIOCH - I/O CHANNEL ASSIGNMENTS .MACRO GENCHN ZCHAN,ZBUF,ZBLK,ZRTCHN,ZTYPE SETCHN SRC, SRC, SRC, 3, 0 SETCHN TMP, TMP, TMP, 0, 0 .IF NDF XSML SETCHN SML, SML SML, 16, 0 .ENDC .ENDM TMPCNT= 0 .MACRO SETCHN ZCHAN,ZBUF,ZBLK,ZRTCHN,ZTYPE .LIST ZCHAN'CHN= TMPCNT .NLIST TMPCNT= TMPCNT+2 .ENDM GENCHN MAXCHN= TMPCNT ;JUST TO PRESERVE THE COUNT .IRP X, .GLOBL $'X .MACRO $'X CHAN MOV #CHAN'CHN,R0 CALL $'X .ENDM $'X .ENDM