.SBTTL COPYRIGHT .TITLE PIREX.154 ; ;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 PRO- ;VIDED 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 DOCUMENT IS SUBJECT TO CHANGE ;WITHOUT NOTICE AND SHOULD NOT BE CONSTRUED AS A COM- ;MITMENT BY DIGITAL EQUIPMENT CORPORATION. ; ;DEC ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY ;OF ITS SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DEC. ; ; P I R E X ; ; A MULTI-PROGRAMMING PERIPHERAL EXECUTIVE FOR THE UNICHANNEL-15 ; ; ; .SBTTL LEGEND ; EDIT=154. ; ; EDIT #075 SR FIRST TRY AT PLOTTER DRIVER ; EDIT #081 SK TEMPORARY TASK FIX IN SD.DISCON ; EDIT #082 SK QUEUE REQ TO REAL TASK WHEN SPOOLER ; HALTED + TEMPORARY TASK BUG FIX ON CTL 'C' ; EDIT #083 SR EXPERIMENTAL CHANGE FOR LP ?BUG? ; EDIT #086 SR+KB INSTALL LV11 TASK ; FOR VERSATEK PRINTER/PLOTTER ; EDIT #087 SR FIX VERSATEK TASK NUMBER ERRORS FROM 086 ; EDIT #090 SR FIX LV STACK SIZE.MAKE LP OK FOR IMAGE MODE. ; EDIT #091 SR #090 MISSED, TRY AGAIN ; EDIT #092 SR CD ERROR CODES. PL REST OF ASCII SET. ; EDIT #093 SR BRING BACK LV, FIX % IN PLOTTER. ; EDIT #094 SR TAKE OUT LEVEL 6 CLOCK REF. IN LP. ; EDIT #095 SK 19-NOV-73 FIX CTL'C' IN ST TASK WITH RESET ; + PERMIT SOFTWARE INT. FACILITY FOR EACH TASK ; + REMOVE $CL COND. + GENERAL COMMENT FIXUP ; 096 SK 5-DEC-73 HANDLE DEVICE CONTROL REG. SETUP IN ; INITIALIZATION ROUTINE, REMOVE RESET INSTT ; FROM ST TASK, REPLACE CLR @-6( ) + ; GENERAL FIXUP TO EDIT #095 ; 097 SR 12/18/73 CD; MAKE COLUMN COUNT CHECK. ; XY; OFF LINE FROM PDP-11 SWITCHES. ; RK; PRIORITY OF RETRY. ; 098 SK 1/2/74 LP: - 4 ; ST,SD: REMOVE LEVEL CHANGE IF SPOOLING ; MASREQ: REMOVE TEST FOR ST TASK ACTIVE ; 099 SK 1/31/74 ST: FIX SINGLE TASK STOP I/O FOR RSX ; 100 SCR 4/5/74 ST: GIVE CD A WINDOW AT LVL 5 ; CD: REMOVE IOPS75 ENTIRELY, REPLACE IOPS4 ; LV: CHANGE EXIT TO .TRAN ; 101 SCR 4/9/74 CD REWRITE INTERRUPT SECTION ; 102 SCR 4/10/74 FIX 101 ; 103 SCR 4/12/74 ADD CD-2=0 LOGIC;LV OFF BY 1. ; 104 SCR 5/20/74 CHANGE LV STATUS AND DATA REG.'S ; 114 SCR 7/10/74 INSTALL XY311 SUPPORT ; 115 SCR 7/11/74 1.MAKE XY DRIVER MATCH EXACTLY. ; 2.ATTEMPT CD ERROR HANDLING FIX ; 116 BLR 7/15/74 FIX SPOL CNTRL C BUG ; 117 RKH 22-JUL-74 REMOVED DEBUG HALTS ; FOR OUT OF RANGE DISK REFS ; 118 EIK 6-AUG-74 FIX BUG TO ALLOW FULL LIST ; 119 SK 12-NOV-74 ADD LP HALT ON CLOSE FEATURE ; 120 BLR 13-NOV-74 ADD MOVE DIRECTIVE ; ADD MEMSIZ TO CORE STAT DIRECTIVE ; REMOVE STOP ON SOFT ERROR FORM RK TASK ; 121 SK 15-NOV-74 PLOTTER EOF SPOOLING WAIT FEATURE ; 122 BR 8-DEC-74 SPOOLER DISK UNIT # ADDED ; 123 SCR 10-DEC-74 TRIAL CD PWER OFF-ON FIX; SPEED ; LOOP FOR PL; REMAKE LV FROM LP. ; 124 SCR 11-DEC-74 EXTEND $NOSW;MINOR CD FIX ; 125 BLR 16-DEC-74 CLEAN UP MOVE DIRECTIVE ; 126 BLR 6-JAN-75 STOP ON SOFT DISK ERROR REMOVED ; 127 BLR 6-JAN-75 PRIORITY 5 WINDOW IN ERROR REPT. DIR ADDED ; 132 SCR 8-JAN-75 MADE FROM 127, ANOTHER TRY AT IOPS45 ; 133 SCR 31-JAN-75 PL:FIX RETRY CONTROL BYTE FOREOF STOP ; 134 BLR 24-MAR-75 CLEAN UP SLOW CODE ; 135 BLR 25-MAR-75 FIX LP HALT EOF BUG ; 136 BLR 26-APR-75 EXTEND RK TRANSFERS TO 128K ; 137 SCR 5-MAY-75 FIX XY EOF LOGIC;REM @# ; 138 SCR 5-MAY-75 LOST INSTR. IN #137 ; 139 BLR 6-JUN-75 RESCHED AFTER SEXIT 0 ADDED ; 140 RCHM 10-JUN-75 PREPARE PIREX FOR THE ACCEPTANCE OF THE ; HURLEY PROTOCOL COMMUNICATIONS OPTION. ; 141 RCHM 20-JUN-75 REMOVE ILLINT HACK SO NEW DEVICES CAN BE ; INSTALLED MORE EASILY ; 142 BLR 20-JUL-75 CHECK FOR OFLINE RK BEING SPOOLED ; 143 BLR 22-JUL-75 CHANGE SPOOLER ABORT ERROR TO #26 ; 144 BLR 4-AUG-75 CLEAN UP XVM BYTE INTERFACE PROBLEM ; 145 BLR 18-AUG-75 CLEAN UP SOFTWARE DIR'CTVE BUG ; 146 BLR 18-AUG-75 ADD UNSUPPORTED POWER-FAIL ROUTINE ; 147 BLR 19-AUG-75 CHANGE WAY DISCONNECT FREE'S MEMORY ; 148 BLR 21-AUG-75 GIVE ERROR FOR TCB SENT FROM >28K ; 149 SCR 9/9/75 ALTERNATE XY CHAR SPACE($SPACE=0) ; 150 BLR 9/26/75 ILLEGAL BLOCK FIX ; 151 BLR 9/28/75 ADD STATUS REGS. TO EDIT 150 ; 152 SCR 10/3/75 LP: EOF IN HDR, NOT A 6414 DATA ; 153 RCHM 11/03/75 PUT IN DEC CONFIGURATION DEFAULTS ; FOR SECOND DL-11. ; 154 BLR 11/09/75 CHANGED COND. ASM FOR SPKILL .SBTTL CONDITIONAL ASSEMBLY PARAMETERS ; .LIST ME .LIST TOC .ENABL ABS ; ; ; THIS SOURCE IS CONDITIONALISED TO PRODUCE DIFFERENT VERSIONS. ; BY DEFINING A CONDITIONAL A TASK IS ASSEMBLED INTO THE PIREX VERSION ; THE FOLLOWING IS A LIST OF THE PARAMETERS: ; EAE FOR EAE OPTION (UNSUPPORTED)*** ; $RK FOR RK15/RK05 DISK CARTRIDGE TASK ; $DT FOR DT11 DECTAPE TASK (UNSUPPORTED)*** ; $LP FOR LP11/LS11 LINE PRINTER TASK ; $CD FOR CR11 CARD READER TASK ; $PL FOR XY11 PLOTTER TASK ; $LV FOR LV11 VERSATEK PRINTER/PLOTTER TASK (UNSUPPORTED)*** ; $PL311 FOR XY311 INTERFACE TO CALCOMP 936 PLOTTER ; $UNITS FOR XY311: STEP SIZE ; DEFINED .05 MM. ; NOT DEFINED .002 INCHES ; $NOSW DEFINE TO DISABLE ALL CONSOLE SWITCH INTERACTIONS ; $HP FOR HURLEY PROTOCOL (HP) COMMUNICATIONS OPTION. THE HP COMMUNICATIONS ; OPTION UTILIZES A DL-11 AND A KG-11 TO COMMUNICATE WITH A DECSYSTEM-10. ; AS SUPPLIED BY DIGITAL THE HP MODULE ASSUMES THE USE OF A DL-11 OTHER ; THAN THE CONSOLE AND THE FIRST KG-11. IN ADDITION, FOR PROPER ; OPERATION OF THE HP MODULE, THE DL-11 USED MUST BE MODIFIED TO INTERRUPT ; AT API LEVEL 6. ; DL.UN A PARAMETER REQUIRED BY THE COMMUNICATIONS PACKAGE. THIS REPRESENTS THE ; TOTAL NUMBER OF DL-11 UNITS INSTALLED ON THE PDP-11. THIS NUMBER INCLUDES ; THE CONSOLE DL-11. ; DL.NT WHERE "N" IS AN OCTAL NUMBER SUCH THAT 0<=N<=17. THIS PARAMETER IS ; SET TO INDICATE WHICH TASK IS TO UTILIZE THE DL-11. FOR EXAMPLE, ; DL.1T=14 IMPLIES THAT DL-11 UNIT #1 (THE SECOND DL-11) IS TO BE USED ; BY TASK NUMBER 14. ; THE EXACT PARAMETERS ARE: ; ; $RK=100000 ; $LP=40000 ; $CD=20000 ; $PL=10000 ; $DT=0 ; $LV=0 ; EAESTK=3 FOR EAE ELSE EAESTK=0 ; $PL311=0 IN ADDITION TO $PL=10000 ; $UNITS=0 IN ADDITION TO $PL311=0 AND $PL=10000 ; $NOSW=0 ; $HP=0 ; DL.UN= (SEE ABOVE) ; DL.?T= (SEE ABOVE) ; ; ; ; DEVTYP=0 .IFDF $HP ;(RCHM-140) HP OPTION SPECIFIED? .IFNDF DL.UN ;(RCHM-140) YES, IS A NUMBER OF DL-11'S SPECIFIED? .ERROR ;DL.UN NOT SPECIFIED AND HURLEY PROTOCOL OPTION SELECTED. .ENDC ;(RCHM-140) .ENDC ;(RCHM-140) .IFDF $RK DEVTYP=DEVTYP!$RK .ENDC .IFDF $LP DEVTYP=DEVTYP!$LP .ENDC .IFDF $CD DEVTYP=DEVTYP!$CD .ENDC .IFDF $PL DEVTYP=DEVTYP!$PL .ENDC ; ; .SBTTLE SYMBOLIC EQUATES ; R0=%0 ;GENERAL PURPOSE REGISTERS R1=%1 R2=%2 R3=%3 R4=%4 R5=%5 SP=%6 PC=%7 PS=-2 ;PROCESSOR STATUS WORD SW=177570 ;SWITCH REGISTER AC=177302 ;EAE REGISTERS MQ=177304 SC=177310 RETURN=207 ;RETURN = RTS PC ; CLSTS=177546 ; LINE FREQ. CLOCK CONTROL REG. TCBP=167764 ;TASK CONTROL BLOCK POINTER REGISTER TCBP18=167774 ;TASK CONTROL BLOCK POINTER BITS 16 AND 17 TCBINT=167760 ;TASK CONTROL BLOCK INTERRUPT ENABLE REGISTER STKSZE=14+EAESTK ; STACK SIZE TO SAVE R0-R5 + EAE REGS. POLSIZ=18. ;POOL SIZE SET AT 18+2=20 NODES APIREG=167762 ;API TRAP VECTORS FOR LEVELS 2 AND 3 ; (LEVELS 0 AND 1 ARE AT APIREG+10). APIDNE=167774 ;API DONE FLAGS ; TCN=2 ;TASK CODE NUMBER TEV=4 ;TASK EVENT VARIABLE ; STCOD=52324 ;'EST': ST TASK MNEMONIC SDCOD=52304 ;'ESD': SD TASK MNEMONIC RKCOD=41325 ;'DKU': RK TASK MNEMONIC DTCOD=42425 ;'DTU': DT TASK MNEMONIC LPCOD=142025 ;'LPU': LP TASK MNEMONIC CDCOD=30425 ;'CDU': CD TASK MNEMONIC PLCOD=72225 ;'GRU': PL TASK MNEMONIC SPCOD=52320 ;'ESP': SP TASK MNEMONIC LVCOD=142625 ;'LVU': LV TASK MNEMONIC ; ; SPTCOD=7 ;SPOOLER TASK CODE ; ; ; ATL NODE EQUATES ; A.SP=4 ;SP REGISTER USED WHEN NOT RUNNING A.TS=06 ;TASK STATUS A.TP=07 ;TASK PRIORITY LEVEL WAITST=2 ; WAIT STATUS EXITST=4 ; EXIT STAUS ; EAESTK=0 ;DEFAULT EAE STACK SPACE IS NULL (ZERO) .IIF DF EAE,EAESTK=6 ;DEFINE EAE STACK SPACE IF EAE IS ; DEFINED. ; .SBTTL MACRO DEFINITIONS ; ; RESERVE BLOCK OF ZEROED MEMORY ; ; .MACRO .BLOCK N .NLIST .REPT N .WORD 0 .ENDR .LIST .ENDM ; ; DEFINE A TASK LISTHEAD ; .MACRO LISTHEAD TK TK'.LH: .WORD . .WORD .-2 .ENDM ; ; CALL SUBROUTINE ; .MACRO CALL ROUTINE JSR PC,ROUTINE .ENDM ; ; PUSH ARGUMENTS ON STACK ; .MACRO PUSH CEL1,CEL2,CEL3,CEL4,CEL5,CEL6 .NLIST .NARG N .LIST MOV CEL1,-(SP) .NLIST .IFGT N-1 .LIST MOV CEL2,-(SP) .NLIST .IFGT N-2 .LIST MOV CEL3,-(SP) .NLIST .IFGT N-3 .LIST MOV CEL4,-(SP) .NLIST .IFGT N-4 .LIST MOV CEL5,-(SP) .NLIST .IFGT N-5 .LIST MOV CEL6,-(SP) .NLIST .ENDC .ENDC .ENDC .ENDC .ENDC .LIST .ENDM ; ; POP ARGUMENTS FROM STACK ; .MACRO POP CEL1,CEL2,CEL3,CEL4,CEL5,CEL6 .NLIST .NARG N .LIST MOV (SP)+,CEL1 .NLIST .IFGT N-1 .LIST MOV (SP)+,CEL2 .NLIST .IFGT N-2 .LIST MOV (SP)+,CEL3 .NLIST .IFGT N-3 .LIST MOV (SP)+,CEL4 .NLIST .IFGT N-4 .LIST MOV (SP)+,CEL5 .NLIST .IFGT N-5 .LIST MOV (SP)+,CEL6 .NLIST .ENDC .ENDC .ENDC .ENDC .ENDC .LIST .ENDM ; ; INHIBIT INTERRUPTS ; .MACRO .INH PUSH PS BIS #340,PS .ENDM ; ; ENABLE INTERRUPTS ; .MACRO .ENA POP PS .ENDM ; ; EXIT FROM TASK IN STATE "S" ; .MACRO SEXIT S IOT .BYTE 0,S .ENDM ; ; ISSUE A TASK REQUEST ; .MACRO IREQ TCBP MOV TCBP,R5 MOV #100000,R4 IOT .BYTE 1,0 .ENDM ; .SBTTL TRAP VECTORS .=0 ;(RCHM-141) SET INITIAL PC TO 0 .BLOCK 1000 ;(RCHM-141) INITIALIZE FIRST 1000 WORDS TO 0. ; ;DO NOT CHANGE THE LOCATION OR ORDER OF THE FOLLOWING REGISTERS UPTILL ;THE LINE MARKED *******END NO CHANGE****** ; ; THE FOLLOWING ARE PDP-11 TRAP VECTORS. ; .=0 JMP START ;(00) LOCATION ZERO IS A RESTART LOCATION NODEV ;(04) BUS ERRORS HALT .+2 ;(10) RESERVED INSTRUCTION HALT .+2 ;(14) TRACE TRAP HALT IOTPRO ;(20) IOT TRAP 7*40 PWRFAL ;(24) POWER FAIL (LVL 07) 7*40 .+2 ;(30) EMT TRAP HALT .+2 ;(34) TRAP TRAP HALT ; ; THE FOLLOWING LOCATIONS ARE USED BY PIREX TO STORE MISCELLANEOUS ; INFORMATION. ; MEMSIZ: 0 ;(40) LOCAL MEMORY SIZE OF THE PDP-11 EDIT ;(42) CURRENT EDIT NUMBER LCLAST: LASTLC ;(44) LAST LOCATION USED BY PIREX (BR-147) DUMMY: 0 ;(46) DUMMY CONTROL REGISTER ; .SBTTL SYSTEM INTERRUPT VECTORS ; ; ; THE FOLLOWING ARE THE DEVICE INTERRUPT VECTORS - PAIRS, CONSISTING ; OF INTERRUPT ROUTINE ADDRESS & PRIORITY LEVEL - . ; THE PRIORITY LEVEL OF "ALL" DEVICES SHOULD BE LVL-7 "ONLY". ; THIS IS TO PERMIT PIREX TO DO A CONTEXT SWITCH BEFORE PROCESSING THE ; INTERRUPT. ; ; .IFDF $HP ;(RCHM-141) HURLEY DEFINED? .IFDF DL.0T ;(RCHM-141) USING THE CONSOLE DL? .=60 ;(RCHM-141) START CONSOLE VECTORS AT 60. DL.0R ;(RCHM-141) TRANSFER VECTOR TO READ ROUTINE. 000340 ;(RCHM-141) AT LEVEL 7. DL.0S ;(RCHM-141) TRANSFER VECTOR TO SEND ROUTINE. 000340 ;(RCHM-141) AT LEVEL 7. .ENDC ;(RCHM-141) .ENDC ;(RCHM-141) ; .=100 ;(RCHM-141) CLOCK VECTORS AT 100. CLINT ;(100) $CL INTERRUPT VECTOR 340 ; .IFDF $PL .=120 ;(RCHM-141) PLOTTER VECTORS AT 120. PLINT ;(120) PL INTERRUPT VECTOR(LVL 4) 340 .ENDC ; .IFDF $LV .=170 ;(RCHM-141) LV VECTORS AT 170. LVINT 340 .ENDC ; .IFDF $LP .=200 ;(RCHM-141) LP VECTORS AT 200 LPINT ;(200) LP INTERRUPT VECTOR (LVL 04) 340 .ENDC ; .IFDF $DT .=214 ;(RCHM=141) DT VECTORS AT 214. DTINT ;(214) DT INTERRUPT VECTOR (LVL 07) 340 .ENDC .IFDF $RK .=220 ;(RCHM-141) RK VECTORS AT 220. DKINT ;(220) RK INTERRUPT VECTOR (LVL 05) 340 .ENDC ; .IFDF $CD .=230 ;(RCHM-141) CD VECTORS AT 230. CDINT ;(230) CD INTERRUPT VECTOR (LVL 6) 340 .ENDC ; .IFDF $HP ;(RCHM-153) STICK IN THE DEFAULT ASSIGNMENTS .IFDF DL.1T ;(RCHM-153) SO THAT CERTAIN PEOPLE WILL .=300 DL.1R ;(RCHM-153) WILL NOT HAVE ANY PROBLEMS 000340 ;(RCHM-153) INSTALLING THIS OPTION. DL.1S ;(RCHM-153) 000340 ;(RCHM-153) .ENDC ;(RCHM-153) .ENDC ;(RCHM-153) ; .=310 ;(RCHM-141) PDP-15 INTERRUP VECTOR LINK THROUGH 310. MASREQ ;(310) LEVEL 7 INTERRUPT VECTOR (LVL 07) 340 ; .SBTTL SYSTEM STACK AND REGISTERS .=1000 ; SSTACK: ;START OF SYSTEM STACK SYS.SP: 1000 ;SYSTEM STACK POINTER ; ; SYSTEM REGISTERS BEGIN HERE ; SEND11 ;INT. RETURN ADD. (ON 11) ON END OF I/O CURTSK: 000000 ; CURRENT TASK RUNNING POL.LH ; ADDRESS OF POOL LISTHEAD LISTHD ; ADDRESS OF TASK LISTHEADS R.SAVE ; ENTRY POINT TO REGISTER SAVE R.REST ; ENTRY POINT TO REGISTER RESTORE AS.E1 ; ENTRY POINT TO ATL RESCAN MOVEN ; ENTRY POINT TO NODE MOVER DEQU ; ENTRY POINT TO DEQUEUE SEND15 ; ENTRY POINT TO SEND INTERRUPT EMPTY ; ENTRY POINT TO EMPTY A DEQUE ATLNP ; ATL NODE POINTER TABLE RATLN ; ENTRY POINT TO RETURN ATL NODE SPOLSW ;SPOOLER SWITCHES ADDRESS RTURN ;REUTURN INST. ADD. FOR PIC CODE NBRTEV: NTEV ; CURRENT NBR OF TASKS PWRDWN: RTURN ; ENTRY POINT TO PWR FAIL DOWN PWRUP: RTURN ; ENTRY POINT TO PWR FAIL UP SPOLSW: 0 ;SPOOLER SWITCHES DEVST ;DEVICE ERROR STATUS TABLE CLTABL ;TABLE, A TIME-ADDR PAIR FOR EACH TASK DEQU1 ; ENTRY TO -SET TASK IN WAIT STATE- ROUTINE CEXIT ; ENTRY TO -SET TASK IN RUN STATE- ROUTINE TEVADD ; TABLE OF TASK START ADDRESSES DEVARE: .WORD DEVTYP DEVSPL: .WORD 0 ;DEVICES SPOOL:ED SWITCH CTLCNT: .WORD 0 ;PDP-15 CTL C RUNNING COUNTER (BR-116) SPUNIT: .WORD 0 ;SPOOLER DISK UNIT NR. (BR-122) ; ; ;********END NO CHANGE********** ; .SBTTL SYSTEM TABLES ; ; TASK START ADDRESS TABLE ; ; EACH TASK HAS A 2 CHAR. MNEMONIC 'XX' WHICH IS ALSO THE LABEL ; OF THE FIRST EXECUTABLE INST. IN THE TASK. VIZ.. ; XX: MOV ..... ; ; EVERY TASK IN PIREX HAS A TASK CODE 'X'. X CAN TAKE A VALUE ; UPTO A MAXIMUM OF 177 OCTAL. BY DEFAULT ALL TASKS ARE SPOOLED ; TASKS. TO CREATE AN UNSPOOLED TASK ADD '200' TO THE TASK CODE. ; VIZ.. '200+X' ; ; TEVADD: .WORD ST ;STOP TASKS (TASK CODE = 200) .WORD SD ;SOFTWARE DIRECTIVES (TASK CODE = 201) .IFDF $RK .WORD DK ;RK05 (TASK CODE = 202) .ENDC .IFNDF $RK .WORD 0 .ENDC .IFDF $DT .WORD DT ;DT11 (TASK CODE = 203) .ENDC .IFNDF $DT .WORD 0 .ENDC .IFDF $LP .WORD LP ;LP11 (TASK CODE = 4) .ENDC .IFNDF $LP .WORD 0 .ENDC .IFDF $CD .WORD CD ;CR11 (TASK CODE = 5) .ENDC .IFNDF $CD .WORD 0 .ENDC .IFDF $PL .WORD PL ;XY PLOTTER(TASK CODE=6) .ENDC .IFNDF $PL .WORD 0 .ENDC .WORD 0 ;SPOOLER (TASK CODE = 207) .IFDF $LV .WORD LV ;LV PRINTER/PLOTTER CODE 210 .ENDC .IFNDF $LV .WORD 0 .ENDC .IFDF $HP ;(RCHM-140) HURLEY PROTOCOL COMMUNICATIONS OPTION (211) .WORD HP.ENT ;(RCHM-140) POINTER TO INTERFACE TASK ENTRY POINT. .IFF ;(RCHM-140) .WORD 0 ;(RCHM-140) HP COMMUNICATIONS OPTION NOT SELECTED. .ENDC ;(RCHM-140) ; INSERT PERMANENT TASKS BEFORE THIS LINE ONLY!!!!!! NTEV=.-TEVADD/2 ;NUMBER OF TASKS ; INSERT TEMPORARY TASKS AFTER THIS LINE ONLY!!! .WORD 0 ;SPARE TASK(TASK CODE=212) .WORD 0 ;SPARE TASK(TASK CODE=213) .WORD 0 ;SPARE TASK(TASK CODE=214) ; INSERT TEMPORARY TASKS BEFORE THIS LINE ONLY!!! (BR-147) NTSK=.-TEVADD/2 ;NUMBER OF TOTAL TASKS (BR-147) ; ; TASK SCHEDULING PRIORITY LEVEL TABLE ; .BYTE 7*40 ;LEVEL 7 - CL :-1 LEVEL: .BYTE 7*40 ;LEVEL 7 - ST :0 .BYTE 7*40 ;LEVEL 7 - SD :1 .BYTE 5*40 ;LEVEL 5 - DK :2 .BYTE 6*40 ;LEVEL 6 - DT :3 .BYTE 4*40 ;LEVEL 4 - LP :4 .BYTE 6*40 ;LEVEL 6 - CD :5 .BYTE 5*40 ;LEVEL 5 - PL :6 .BYTE 0*40 ;LEVEL 0 - SP :7 .BYTE 4*40 ;LEVEL 4 - LV :10 .BYTE 6*40 ;(RCHM-140) LEVEL 6 - HP :11 .BYTE 0,0,0 .EVEN ; ; THE TK.END TABLE IS USED TO CONTROL ALLOCATION OF MEMORY TO TEMP. TASKS ; VIA THE CONNECT AND DISCONNECT DIRECTIVES. THE CONNECT DIR. CAUSES ; THE TASK'S LAST LOC+1 TO BE ENTERED INTO THE TK.END ENTRY CORRESPONDING ; TO THE TASK'S 'TASK-CODE-NUMBER'. EACH DISCONNECT CAUSES THE ; THE ENTRY FOR THAT TASK TO BE CLEARED. THE TK.END TABLE IS THE SCANNED ; TO FIND THE HIGHEST MEMORY ADR. WHICH THEN BECOMES THE NEXT AVAILABLE ; LOC. (LCLAST).THIS ROUTINE ASSURES THAT ANY HOLES LEFT BY TASKS ; DISCONNECTING IN A DIFFERENT ORDER THAN THEY CONNECTED, WILL BE ; RECOVERED - EVENTUALY. ; ; NOTE: THE RESIDENT PERM. SECTION OF PIREX HAS AN ENTRY ; IN TK.END+0 (ST: ENTRY). THIS WAS DONE BECAUSE ANY OTHER ; ENTRIES WOULD BE REDUNDANT AND TO ALLOW USERS TO DELETE ; PIREX TASKS AND USE THEIR ENTRIES FOR TEMP. TASKS. ; ; NOTE2: UNDER THE FOLLOWING CONDITIONS THE NEXT FREE LOC. POINTER ; 'LCLAST' IS RESET TO THE END OF PIREX+1 (LASTLC): ; INITIALIZATION ; RESTART FROM 0 ; POWERFAIL RECOVERY ; TK.END: .REPT NTSK ;NUMBER OF ENTRIES=NUMBER OF TASKS (BR-147) .WORD 0 ;INITIALIZED TO 0 (BR-147) .ENDR ;END OF TABLE (BR-147) T.END=. ;ADR. OF END OF TABLE (BR-147) ; ; TASK ATL NODE POINTERS ARE STORED IN THIS TABLE WHEN TASK IS ACTIVE ; EACH TASK HAS A ONE WORD ENTRY IN THE TABLE WHICH IS '0' IF TASK ; IS INACTIVE ; CLKNOD ;CL -1 ATLNP: 0 ;ST 0 0 ;SD 1 0 ;RK 2 0 ;DT 3 0 ;LP 4 0 ;CD 5 0 ;PL 6 SPLNP: 0 ;SP 7 (BR-145) 0 ;LV 10 0 ;(RCHM-140) HP 11 0 ; 12 0 ; 13 0 ;(RCHM-140) 14 ; ; THE FOLLOWING IS A TABLE OF TRANSFER VECTORS TO HANDLE COMPLETION ; OF I/O INT.(FUNCTION CODE IN TCB = 2) ; SEND11: 0 ;ST 0 0 ;SD 1 0 ;RK 2 0 ;DT 3 0 ;LP 4 0 ;CD 5 0 ;PL 6 0 ;SP 7 0 ;LV 10 0 ;(RCHM-140) HP 11 0 ; 12 0 ; 13 0 ;(RCHM-140) 14 ; ; TASK STATUS CODED AS FOLLOWS IS STORED IN THIS TABLE ; ; WORD 1: TASK MNEMONIC IN SIXBIT/RAD50 ; WORD 2: SPARE ; WORD 3: ERROR CODE(XXXX) ; SPOOLER ERROR CODE(HIGH BYTE) ; TASK ERROR CODE(LOW BYTE) ; DEVST=. ST.EST=. STCOD .WORD 0,0 ;ST STATUS SD.EST=. SDCOD .WORD 0,0 ;SD STATUS RK.EST=. RKCOD .WORD 0,0 ;RK STATUS DT.EST=. DTCOD .WORD 0,0 ;DT STATUS LP.EST=. LPCOD .WORD 0,0 ;LP STATUS CD.EST=. CDCOD .WORD 0,0 ;CD STATUS PL.EST=. PLCOD .WORD 0,0 ;PL STATUS SP.EST=. SPCOD .WORD 0,0 ;SP STATUS LV.EST=. LVCOD .WORD 0,0 ;LV STATUS HP.EST=. ;(RCHM-140) .WORD 0,0,0 ;(RCHM-140) HP STATUS (UNUSED AT PRESENT). T1.EST=. .WORD 0,0,0 ;SPARE 1 T2.EST=. .WORD 0,0,0 ;SPARE 2 T3.EST=. .WORD 0,0,0 ;SPARE 3 NDEVST=.-DEVST/3 ; ; ; ; ; IF CLOCK DEFINED A TABLE FOR ONE TIMING REQUEST FROM EACH TASK. ; TWO WORDS: FIRST IS TIME TO GO, PAIR IS DISABLED WITH 0 TIME; ; SECOND WORD IS ADDR FOR JSR PC,XXX .THIS IS CALLED AT ; CLOCK INTERRUPT LEVEL (6). THE USER MUST OF COURSE DO ; A RTS PC. TIME IS IN TICKS, I.E. 1/60 SEC. ; A TASK MAY CANCELL A TIMING REQUEST BY CLEARING THE TIME WORD. ; TO MAKE A REQUEST, PUT THE ADDR OF SUBROUTINE TO BE CALLED ; WHEN TIME COMES DUE IN ADDR WORD. PUT THE DELAY TIME IN TICKS ; IN THE TIME WORD, IN THAT SEQUENCE. ; ; CLTABL=. ST.CL=. .WORD 0,0 SD.CL=. .WORD 0,0 DK.CL=. .WORD 0,0 DT.CL=. .WORD 0,0 LP.CL=. .WORD 0,0 CD.CL=. .WORD 0,0 PL.CL=. .WORD 0,0 SP.CL=. .WORD 0,0 LV.CL=. .WORD 0,0 HP.CL=. ;(RCHM-140) HP CLOSK INTERVAL ENTRY. .WORD 0,0 ;(RCHM-140) T1.CL=. .WORD 0,0 T2.CL=. .WORD 0,0 T3.CL=. .WORD 0,0 CLEND=. ; ; ; ; EACH TASK HAS A LINKED LIST OF NODES, EACH NODE CONTANING THE ; TCBP OF A REQUEST. THE LIST IS CALLED THE "TASK REQUEST LIST" ; (TRL). ; THE FOLLOWING ARE THE TASK LISTHEADS(POINTERS) ; ; LISTHD: LISTHEAD ST ;ST = STOP TASKS LISTHEAD SD ;SD = SOFTWARE DIRECTIVES LISTHEAD DK ;DK = RK05 DISK LISTHEAD DT ;DT = DECTAPE LISTHEAD LP ;LP = LINE PRINTER LISTHEAD CD ;CD = CARD READER LISTHEAD PL ;PL = XY PLOTTER LISTHEAD SP ;SP = SPOOLER LISTHEAD LV ;LV = LV PLOTTER/PRINTER LISTHEAD HP ;(RCHM-140) HP = HURLEY PROTOCOL COMMUNICATIONS OPTION. LISTHEAD T1 ;SPARE TASK LISTHEAD T2 ;SPARE TASK LISTHEAD T3 ;SPARE TASK ; ; PIREX MAINTAINS INFORMATION(VIZ.. STACK POINTER,PRIORITY ; LEVEL, TASK CODE, TASK STATUS) OF ACTIVE TASKS IN A LINKED ; LIST CALLED THE "ACTIVE TASK LIST"(ATL). THE FOLLOWING IS THE ; ATL LISTHEAD WITH ITS PERMANENT ENTRIES(CLKNOD+NULNOD) ; ; ATL.LH: .WORD CLKNOD ;CLOCK & NUL JOB ARE ALWAYS ACTIVE .WORD NULNOD ; ; CLOCK ATL NODE ; CLKNOD: .WORD NULNOD ;POINTS TO NUL JOB NODE .WORD ATL.LH ;POINTS TO ATL LIST HEAD .WORD CLINT-EAESTK ;STACK POINTER .WORD 167762 ;LVL 7 + '-1' TASK CODE + WAIT STATE ; ; NUL JOB ATL NODE ; NULNOD: .WORD ATL.LH ;INITIALLY POINTS TO ATL LIST .WORD CLKNOD ;POINTS TO CLOCK NODE .WORD NULPC ;NUL JOB'S STACK POINTER (BR-134) .WORD 0 ;TASK IS ALWAYS RUNNABLE AT MAIN- ; STREAM LEVEL. ; .SBTTL POOL OF EMPTY NODES ; ; THE FOLLOWING IS A POOL OF EMPTY NODES. THE POOL EXISTS IN A ; LINKED LIST FORM. ; ; POL.LH: .WORD .+4 .WORD POLEND ; .WORD .+10 .WORD POL.LH .BLOCK 2 ; .REPT POLSIZ ; .WORD .+10 .WORD .-12 .BLOCK 2 .ENDR ; .WORD POL.LH .WORD .-12 .BLOCK 2 ; POLEND=.-10 ; .SBTTL SYSTEM REGISTER SAVE/RESTORE ROUTINES ; ; THIS ROUTINE SAVES SYSTEM REG.'S R0-R5 &EAE (IFDEFINED) AND SAVES ; TASK SP IN ATL NODE AND DOES A CONTEXT SWITCH TO INT. PRC. TASK ; ; CALLING SEQUENCE: JSR R0,R.SAVE ; TASKCODE/-2 ; ...... INSTRUCTION TO BE EXECUTED ; ON RETURN ; REGS. USED: R0-R3 ; R.SAVE: CMP #NULNOD,CURTSK ;TEST FOR NUL TASK (BR-134) BEQ 2$ ;BRANCH IF NULTASK (BR-134) PUSH R1,R2,R3,R4,R5 ;SAVE R0-R5 (R0 SAVED ON CALL) .IFDF EAE PUSH AC,MQ,SC ;SAVE EAE REGISTERS ALSO .ENDC MOV CURTSK,R2 ;SAVE CURRENT TASK SP MOV SP,A.SP(R2) 2$: MOV (R0)+,R1 ;GET CALLING TASK CODE (BR-134) CMP #-2,R1 ;SKIP SWITCH STACK? BEQ 1$ MOV R1,R3 ;SAVE TASK CODE IN R3 ASL R1 ;CONVERT TO WORD OFFSET MOV ATLNP(R1),R2 ;SWITCH STACK MOV R2,CURTSK ;SET CURTSK MOV A.SP(R2),SP ;SP BIC #17,A.TS(R2) ;SET STATUS TO RUN MOVB LEVEL(R3),PS ;SET PRIRITY 1$: MOV R0,PC ;RETURN TO CALLER ; ; THIS ROUTINE RESTORES EAE REGS.(IF DEFINED) & SYSTEM REGISTERS ; R0-R5. ; ; REGS. USED: NONE ; R.REST: CMP #NULNOD,CURTSK ;TEST FOR RESTORE OF NULTASK(BR-134) BEQ 2$ ;BRANCH IF NULTSK (BR-134) TST (SP)+ ;FORGET CALL R0 .IFDF EAE POP SC,MQ,AC ;RESTORE THE EAE REGISTERS .ENDC POP R5,R4,R3,R2,R1 ;RESTORE R1-R5 2$: RTS R0 ;R0 RESTORED ON EXIT (BR-134) ; .SBTTL POWER FAIL HANDLER ; ; THIS ROUTINE CURRENTLY HANDLES POWER FAILURE. ; *******IT IS UNSUPPORTED******* ; IT CLEARS ALL INTS. AND CALLS THE INITIALIZATION ROUTINE ; WHEN POWER IS BROUGHT UP. ; NO ATTEMPT IS MADE TO CONTINUE PREVIOUS WORK. ; INDEED THE SPOOLER IS KILLED ON EVERY POWER-UP AND MUST ; BE RESTARTED. ; PWRFAL: MOV #RSTART,@#24 ;RESTART ADDRESS DURING POWER UP HALT ;HALT DURING POWER DOWN ; ; ;ENTER HERE ON AUTO RECOVERY OF POWER FAIL ; RSTART: MOV #PWRFAL,@#24 ;RESTORE POWER FAIL ADR AT VECTOR (BR-146) RESET ;CLEAR ALL REG,I/O ETC. (BR-146) JMP START ;GO TO PIREX INIT. ROUTINE (BR-146) ; .SBTTL NUL TASK ; ; THIS IS THE NUL TASK WHICH RUNS WHEN ALL OTHER TASKS CANNOT. ; THE TASK IS ALWAYS RUNNNABLE ; IT CONSISTS OF 2 INSTRUCTIONS. THE"WAIT" INSTRUCTION IS USED TO ; INCREASE UNIBUS THROUGHPUT. ; .BLOCK EAESTK*2+14. NULPC: .WORD NULJOB ;PC SETUP FOR START OF NULJOB (BR-134) .WORD 0 ;PS SETUP ....... .WORD DUMMY .WORD 0 .WORD 0 NULJOB: WAIT BR NULJOB ; .SBTTL INTER-TASK REQUEST COMMUNICATION HANDLER ; ; THIS IS THE INTER-TASK REQUEST COMMUNICATION HANDLER. REQUESTS ; ARE ISSUED BY PASSING THE ADDRESS/POINTER OF/TO A BLOCK OF INFORMATION ; (CALLED THE "TASK CONTROL BLOCK"-TCB-). WHEN REQUESTS ARE ISSUED FROM ; THE PDP-15 THE READING OF THE TCB REGISTER SETS THE "DONE" FLAG IN THE PDP-15. ; WHEN PIREX RECEIVES A REQUEST FROM THE PDP-15 IT FIRST SAVES THE ; GENERAL PURPOSE REGISTERS, READS IN AN 18 BIT TCBP AND THEN ; RELOCATES THE TCBP TO A PDP-11 ADDRESS. ; WHEN REQUESTS ARE ISSUED FROM THE PDP-11 THE TCBP IS ALREADY PRESENT IN ; R4(2 MSB'S) & R5(16 LSB'S). A CHECK IS THEN MADE ; TO DETERMINE IF THE TASK IN REFERENCE IS BUSY. IF BUSY, THE ; REQUEST IS QUEUED TO THE TASK REFERENCED. IF NOT, THE REQUEST ; IS ENTERED INTO THE TASK IDLE SWITCH AND AN ATL SCAN IS MADE STARTING ; FROM THE TOP OF THE LIST, TO RUN THE HIGHEST PRIORITY TASK. ; ; WHEN THE PIREX COMPLETELY FINISHES A REQUEST FOR THE PDP-15, IT SIGNALS ; THE PDP-15 OF THIS FACT BY ISSUING AN API INTERRUPT IF REQUESTED AT A LEVEL ; CORRESPONDING TO THAT WHICH WAS SPECIFIED IN THE ACTIVE LEVELS ; TABLE. A SOFTWARE INTERRUPT ON THE PDP-11 IS ISSUED IF ; THE REQUEST IS MADE BY A TASK RUNNING ON THE PDP-11 IF REQUESTED IN THE TCB. ; IN EITHER CASE THE REQUEST EVENT VARIABLE(REV) IN THE TCB IS SET ; TO THE APPROPRIATE VALUE ON COMPLETION OF THE REQUEST. IF MORE REQUESTS EXIST ; IN THE TASKS DEQUES AT THE COMPLETION OF A PREVIOUS REQUEST, THE NEXT ; ENTRY IS REMOVED AND PROCESSED. THIS CONTINUES UNTIL THE ENTIRE DEQUE ; IS EMPTY AT WHICH TIME THE TASK GOES INTO AN WAIT STATE(IF IT IS A PERMANENET TASK) ; OR EXIT STATE(IF IT IS A TEMPORARAY TASK). ; ; ; THIS ROUTINE IS ENTERED AT "MASREQ" WHEN A REQUEST IS ISSUED BY THE ; PDP-15 AND AT "CALLTK" WHEN REQUEST IS ISSUED BY A TASK RUNNING ON THE ; PDP-11 THRO' THE IREQ MACRO. ; ; REGS. USED: ALL ; MASREQ: JSR R0,R.SAVE ;SAVE REGISTERS -2 ;SKIP SWITCH STACK MOV SYS.SP,SP ;NOTE: UPPER 2 BITS OF MOV TCBP18,R4 ; TCB ARE SAVED BUT NOT USED HERE. BIC #177774,R4 ; IF 11 HAS AN MX11, THESE EXTEND ; BITS WILL HAVE TO BE ACCOUNTED FOR. MOV TCBP,R5 ;GET THE TCBP FROM THE 15. READING ; THE TCBP REGISTER AUTOMATICALLY ; SETS THE "DONE" FLAG FOR THE 15. ADD MEMSIZ,R5 ;ADJUST TCBP TO REFLECT THE 11'S ADC R4 ; REAL ADDRESS. TST R4 ;WAS TCB SENT FROM COMMON MEMORY? (BR-148) BNE HI.TCB ;BRANCH IF TCB NOT IN COMMON MEMORY (BR-148) CMP #160000,R5 ;28K IS THE LIMIT (BR-148) BLO HI.TCB ;BRANCH IF TCB NOT IN COMMON MEMORY (BR-148) CALTSK: TSTB TCN(R5) ;SPOOLED TASK? BMI CALLTK BIT #140000,SPOLSW ;YES. SPOOLER ENABLES? BEQ CALLTK MOV #SPTCOD,R1 ;YES. CALL SPOOLER BR CALTK0 HI.TCB: MOV #602,SD.EST+4 ;SET ERROR IN POLLER TABLE,SINCE TCB ;EVENT VARIABLE IS OUT OF RANGE (BR-148) JMP AS.E1 ;RESCAN ATL FOR NEXT TASK (BR-148) CALLTK: MOVB TCN(R5),R1 ;GET TASK CODE NUMBER FROM TCB BIC #177600,R1 ;CLEAR SPOOLED/UNSPOOLED BIT CMPB NBRTEV,R1 ;LEGAL TASK CODE? (BR-134) BLT LVL703 ;NO: RETURN WITH ERROR CODE IN CALLERS (BR-134) CALTK0: MOV R1,R2 ; TCB (EVENT VARIABLE). ASL R1 MOV TEVADD(R1),R3 ;GET STARTING ADDRESS OF TASK BEQ LVL703 ;NO TASK CONNECTED TO THIS SLOT TST -(R3) ;IS THE TASK IN REFERENCE TO THIS BNE LVL701 ; REQUEST CURRENTLY BUSY? MOV R5,(R3) ;USE TCBP TO SET TASK'S IDLE/BUSY MOV R4,-(R3) ; SWITCH. CLR TEV(R5) ;CLEAR TASK EVENT VARIABLE IN ; THE TCB. MOV ATLNP(R1),R1 ;GET ATL NODE ADDRESS IF PRESENT BEQ 1$ ; ALLOCATED FOR THIS TASK. MOV R1,R0 ;FOUND ONE, SET STATUS TO RUNNABLE BR 4$ ; AND RESCAN THE ATL. 1$: MOV #ATL.LH,R0 ;SCAN THE ATL FOR A POSITION FOR 3$: MOV @R0,R1 ; THIS NEW NODE ENTRY. CMPB A.TP(R1),LEVEL(R2) BLO 2$ ;FOUND ONE, BACK UP ONE AND LINK A ; NODE FROM THE POOL TO IT. CMP #NULNOD,R1 ;END OF ATL? BEQ 2$ ;YES: LINK BEFORE NUL TASK NODE MOV R1,R0 ;LINK TO NEXT NODE BR 3$ 2$: CMP #POL.LH,POL.LH ;ANY NODES LEFT IN THE POOL? BEQ LVL705 ;NO: TELL CALLER AND EXIT MOV R0,R1 ;USE PREVIOUS NODE TO LINK TO MOV POL.LH,R0 ;MOVE NODE FROM THE POOL NOW ASL R2 ;CONVERT TASK CODE TO WORD OFFSET MOV R0,ATLNP(R2) ;SAVE ATL NODE ADDRESS IN ATLNP TABLE ASR R2 ;GET BACK TASK CODE CALL MOVEN 4$: SUB #4,R3 ;R3-4 (BR-134) PUSH R2 ;SAVE TASK CODE # MOVB LEVEL(R2),(R3) ; SET PS IN TASK'S STACK AREA. PUSH R3 ;SAVE TASK STARTING ADDRESS(PC) IN STACK ADD #10,(SP) ; AREA. POP -(R3) SUB #STKSZE,R3 ;NOW EXTABLISH THE STACK MOV R3,A.SP(R0) ASL R2 ;SAVE TASK CODE # IN ATL ASL R2 ASL R2 ASL R2 MOV R2,A.TS(R0) ; ..... AND AT THE SAME TIME, BICB #340,A.TP(R0) ;SET PRIORITY LVL OF TASK IN ATL POP R2 ;GET TASK CODE BISB LEVEL(R2),A.TP(R0) BR AS.E1 ; SET TASK STATUS TO RUNNABLE. ; LVL701: ASL R1 ;LINK A NODE FROM POOL TO TASK'S DEQUE TST (R1)+ ;(POINTS TO BACKWARD POINTER OF LISTHEAD) MOV LISTHD(R1),R1 CMP #POL.LH,POL.LH ;ANY POOL NODES LEFT? BEQ LVL705 ;NO: TELL USER MOV POL.LH,R0 ;GET A NODE FROM THE POOL MOV R5,6(R0) ;SAVE TCBP IN NODE MOV R4,4(R0) CALL MOVEN ;MOVE NODE CLR TEV(R5) ;CLEAR TASK EVENT VARIABLE IN TCB. BR AS.E1 ;RESCAN THE ATL LVL705: MOV #-777,R1 ;TELL USER HE'S OUT OF POOL BR LVL704 ; AND RESCAN THE ATL. ; LVL703: MOV #-200,R1 ;ILLEGAL TASK SPECIFIED, RETURN LVL704: MOV R5,R0 CALL SEND15 BR AS.E1 ;RESCAN ATL NOW ; .SBTTL SCAN OF ACTIVE TASK LIST ; ; THE ACTIVE TASK LIST (ATL) IS A PRIORITY ORDERED LIST ; (LINKED NODES) OF TASKS TO BE PROCESSED. ; ; THE SYSTEM IS DRIVEN BY SCANNING THE ATL FROM THE TOP (HIGHEST ; PRIORITY). A TASK IS CAPABLE OF EXECUTION ONLY IF ITS ; STATUS IS ZERO. ALL OTHER CODES RESULTS IN SPECIAL ; HANDLING. ; ; THERE ARE THREE ENTRY POINTS TO THE ATL SCAN ROUTINE ; ; AS.E1 -- TO SCAN THE ATL DOWNWARD FROM THE TOP. ; ; AS.SCN-- TO SCAN THE ATL DOWNWARD STARTING FROM THE NEXT NODE ; POINTED TO BY R0. ; ; AS.E2 -- TO SCAN THE ATL DOWNWARD STARTING AT THE NODE POINTED ; TO BY R0. ; ; CONTROL IS ALWAYS TRANSFERRED TO THE SCANNER WITH THE ; CURRENT TASKS PS, PC, AND THE GENERAL PURPOSE REGISTERS ; PUSHED ON THE STACK. ; ; REGS. USED: R0,R1,R2 ; AS.E1: ;SCAN FROM TOP OF ATL MOV #ATL.LH,R0 ;SET R0 TO THE FIRST ATL NODE ; ; SCAN LOOP -- AFTER PROCESSING AN ATL ENTRY, CONTROL IS ; TRANSFERRED EITHER: (1) TO 'AS.SCN' TO PROCESS THE NEXT ATL NODE, ; OR (2) TO 'AS.TE' TO TERMINATE THE ATL SCAN (A RUNNABLE TASK HAS BEEN ; FOUND). ; ; CONTROL IS TRANSFERRED HERE FROM AN ATL SCAN SERVICE ROUTINE ; (SPECIAL HANDLING ROUTINE) WITH THE STACK AND R0 UNCHANGED FROM ; THE DISPATCH TO THAT SERVICE ROUTINE. ; AS.SCN: MOV @R0,R0 ;ADVANCE R0 TO THE NEXT ATL NODE AS.E2: MOVB A.TS(R0),R1 ; AND DISPATCH PER ACTIVE TASK STATUS, BIC #177760,R1 ; WITH R0=ATL NODE ADDR AND R1=STATUS. JMP @AS.E3(R1) AS.E3: ;DISPATCH ADDRESS TABLE AS.TE ;(00) TASK IS RUNNABLE AS.SCN ;(02) TASK IS IN A WAIT STATE AS.STP ;(04) TASK MUST BE STOPPED AND CLEANED UP ; ; TERMINATE THE ATL SCAN. A RUNNABLE TASK HAS BEEN FOUND ; AS.TE: MOV SP,SYS.SP ;SAVE SYSTEM STACK POINTER MOV R0,CURTSK ;ESTABLISH NEW CURRENT TASK MOV A.SP(R0),SP ;RESTORE THIS TASK'S REGISTERS CMP #NULNOD,R0 ;IS THIS THE NULL TASK (BR-134) BEQ 2$ ;YES BRANCH (BR-134) .IFDF EAE POP SC,MQ,AC ;EAE REGS .ENDC POP R5,R4,R3,R2,R1,R0 2$: RTI ;RETURN CONTROL TO INTERRUPTED TASK (BR-134) ; ; STOP TASK NOW BY REMOVING HIS NODE FROM THE ATL & ZEROING ENTRY IN ATLNP TABLE ; AS.STP: MOV #POL.LH,R1 ;RETURN NODE TO POOL CLR 4(R0) ;ZERO ENTRY BEFORE RETURNING MOV 6(R0),R2 ;GET TASK CODE ASR R2 ;CONVERT TO WORD OFFSET ASR R2 ASR R2 BIC #177601,R2 ;CLEAR JUNK CLR ATLNP(R2) ;CLEAR ATL NODE ENTRY IN SYSTEM TABLE CLR 6(R0) ASR R2 ;GET TASK CODE CMPB NBRTEV,R2 ;TEMPORARY TASK (BR-134) BNE 1$ DEC NBRTEV 1$: MOV @R0,R2 ;SAVE LINK TO NEXT NODE CALL MOVEN MOV R2,R0 ;NOW LOOK AT NEXT NODE BR AS.E2 ; ; .SBTTL IOT PROCESSOR ; ; PROCESSES THE FOLLOWING MACRO REQUESTS: ; SEXIT S - EXIT FROM TASK IN STATE "S" ; MACRO EXPANSION: ; IOT ; .BYTE 0,S ; IREQ TCBP - ISSUE A TASK REQUEST ; MACRO EXPANSION: ; MOV TCBP,R5 ; MOV #100000,R4 ; IOT ; .BYTE 1,0 ; ; THIS ROUTINE IS ENTERED WHEN AN IOT IS EXECUTED. ; ; REGS. USED: R0,R1,R2 ; IOTPRO: JSR R0,R.SAVE ;SAVE CURRENT TASK'S REGISTERS ON HIS -2 ;SKIP SWITCH STACK MOV @14(SP),R1 ;GET FUN. & ARG. MOV CURTSK,R0 ;GET ATL NODE ADDRESS MOV R1,R2 ;SPLIT UP FUNCTION AND ARGUMENT ASL R1 SWAB R2 BIC #177400,R1 BIC #177400,R2 JMP @1$(R1) ;CALL APPROPRIATE ROUTINE ; 1$: ;DISPATCH TABLE ADDRESS IOTS ;(00) SET TASK IN STATE "S" SLAREQ ;(01) ISSUE TASK REQUEST ; ; EXIT FROM TASK IN STATE "S" ; IOTS: BIC #17,A.TS(R0) ;CLEAR OUT OLD REQUEST BIS R2,A.TS(R0) ;SET NEW REQUEST MOV SP,A.SP(R0) ;SAVE IN ATL NODE MOV SYS.SP,SP ;SWITCH TO SYSTEM STACK TST R2 ;WAS STATE REQUESTED 0 ? (BR-139) BEQ 1$ ;YES BRANCH (BR-139) ADD #20,A.SP(R0) ;INCREMENT STACKS (BR-139) JMP @AS.E3(R2) ;PROCESS REQUEST NOW 1$: JMP AS.E1 ;RESCHEDULE FROM TOP (BR-139) ; ; ISSUE TASK REQUEST ; SLAREQ: ADD #2,14(SP) ;BUMP PC ON STACK TO RET. ADD. MOV SYS.SP,SP ;SWITCH TO SYSTEM STACK JMP CALLTK ;ISSUE REQUEST ; .SBTTL MOVE A NODE ; ; SUBROUTINE TO MOVE A NODE FROM ONE DEQUE TO ANOTHER DEQUE. ; ; CALLING SEQUENCE: ; NODE ADDRESS IN R0 ; INHIBIT INTERRUPTS ; ADDRESS OF WHERE NODE WILL END UP IN R1 ; CALL MOVEN ; ENABLE INTERRUPTS ; ; REGS. USED: R0,R1 ; MOVEN: PUSH R1 ;SAVE R1 TEMP MOV (R0),R1 ;DELETE NODE FROM SOURCE DEQUE MOV R1,@2(R0) MOV 2(R0),2(R1) POP R1 ;RESTORE R1 PUSH (R1) ;INSERT NODE IN DESTINATION DEQUE ADD #2,(SP) MOV (R1),(R0) MOV R1,2(R0) MOV R0,(R1) MOV R0,@(SP)+ RTURN: RETURN ;RETURN TO CALLER ; ; .SBTTL RETURN ATL NODE TO POOL ; ; THIS ROUTINE RETURNS THE ATL NODE(IF PRESENT) TO THE POOL & ZEROS ; THE ATL NODE POINTER ENTRY IN "ATLNP" TABLE. ; THE TASK CODE IS SPECIFIED IN R2. ROUTINE MUST BE CALLLED ; AT LEVEL 7. ; ; CALLING SEQUENCE: ; MOV #TASCOD,R2 ; INHIBIT INT. ; CALL RATLN ; .... ;RETURN ; ; REGS. USED: R0,R1 ; RATLN: ASL R2 ;CONVERT TASK CODE TO WORD OFFSET MOV ATLNP(R2),R1 ;LOOK FOR ATL NODE BEQ 1$ ;NO ENTRY IN ATL CLR ATLNP(R2) ;RESET ENTRY MOV R1,R0 ;NOW RETURN NODE TO POOL MOV #POL.LH,R1 CLR 4(R0) ;ZERO ENTRY BEFORE RETURNING CLR 6(R0) CALL MOVEN 1$: RETURN ;RETURN TO CALLER ; .SBTTL DEQUEUE A NODE FROM TASK'S DEQUE ; ; ROUTINE TO TEST IF TASK HAS MORE ENTRIES IN HIS TRL. IF ; SO, THE ENTRY IS PROCESSED IMMEDIATELY, OTHERWISE HE ; REMAINS IDLE AND EXITS ALLOWING LOWER PRIORITY TASKS TO BE RUN. ; ROUTINE MUST BE CALLED AT LEVEL 7. ; ; CALLING SEQUENCES: ; ADDRESS OF TASK LISTHEAD IN R1 ; ADDRESS OF TASK IN R3 ; JMP DEQU ;ROUTINE ""MUST"" BE CALLED WITH ; ; TASK'S IDLE/BUSY SWITCH ; ; CLEARED. ; ; REGS. USED: R0,R1 ; DEQU: CMP (R1),R1 ;DOES A NODE EXIST IN THE TASK'S DEQUE? (BR-134) BEQ DEQU1 ;NO: EXIT IMMEDIATELY MOV (R1),R0 ;GET ADDRESS OF NODE MOV 4(R0),-4(R3) ;SET BUSY IDLE SWITCH OF TASK MOV 6(R0),-2(R3) MOV #POL.LH,R1 ;RETURN NODE TO POOL CLR 4(R0) ;ZERO ENTRY BEFORE RETURNING TO POOL CLR 6(R0) CALL MOVEN MOV CURTSK,R0 ;SET TASK STATUS IN ATL NODE TO RUN MOV A.TS(R0),R1 ;SET PRIORITY SWAB R1 MOV R1,PS JMP @R3 ;EXIT TO TASK ; ; NO NODES IN TRL ; ; CALLING SEQUENCE: ; JMP DEQU1 ; ; REGS. USED: R0 ; DEQU1: BIS #340,PS ;RAISE TO LVL 7 MOV CURTSK,R0 ;SAVE TASK SP MOV SP,A.SP(R0) BIC #17,A.TS(R0) ;SET STATUS TO WAIT BIS #WAITST,A.TS(R0) MOV SYS.SP,SP ;SWITCH TO SYSTEM STACK JMP AS.E1 ;SCHEDULE NEXT TASK ; .SBTTL SEND COMPLETION OF I/O INTERRUPT TO CALLER ; ; ; ROUTINE TO SEND COMPLETION OF I/O INTERRUPT TO THE CALLER. CALL TO ; THIS ROUTINE MUST BE DONE AT LEVEL 7. IF FUNCTION CODE (BIT 0) ; IN TCB IS = 1, API INTERRUPT TO PDP-15 IS NOT ISSUED. IF EQUAL TO ; ZERO IT IS ISSUED. IF FUNCTION CODE IS = 2, A SOFTWARE INTERRUPT IS ISSUED TO THE ; CALLER. VIZ.. CALL @SEND11(TASK CODE*2). ; THE REV IN TCB IS ALWAYS SET TO THE VALUE IN R1 IRRESPECTIVE OF THE FUNCTION CODE ; BEFORE ISSUING THE INTERRUPT. ; ; CALLING SEQUENCE: ; ADDRESS OF TCB IN R0 ; EVENT VARIABLE IN R1 ; CALL SEND15 ; REGISTERS USED: R2 THRU R5 ; SEND15: BIT #400,2(R0) ;FUNCTION CODE BIT 0 = 1? BNE 3$ ;YES: IGNORE SENDING INTERRUPT MOVB (R0),R2 ;GET API TRAP LEVEL SPECIFIED BY TCB CMP #3,R2 ;LEVEL MUST BE 0, 1, 2, OR 3 (BR-134) BLT 4$ ;ILLEGAL LEVEL GIVEN, TELL USER OF ; ERROR. (BR-134) 5$: MOV #APIREG,R3 ;BUILD THE CORRECT API LEVEL VECTOR MOV #APIDNE,R4 ; AND "DONE" FLAG TEST VECTOR. MOV #100,R5 BIT #2,R2 ;API LEVELS 2 AND 3 TEST BNE 1$ ASL R5 ;API LEVELS 0 AND 1 BIS #10,R3 1$: BIT #1,R2 ;API LEVELS 1 AND 3 TEST BEQ 2$ CMPB (R3)+,(R4)+ ;API LEVELS 1 AND 3 USES ODD BYTES ; (R3=R3+1, R4=R4+1). 2$: BITB (R4),R5 ;WAIT FOR RECEIPT OF PREVIOUS INTERRUPT (BR-134) BEQ 2$ ; REQUESTS BY THE PDP15. PUSH (R0) ;OK, NOW SEND INTERRUPT TO THE SWAB (SP) ; 15 AT THE CORRECT API LEVEL. MOV R1,TEV(R0) ;SET TASK'S EVENT VARIABLE IN ; CALLERS TCB. MOVB (SP),(R3) TST (SP)+ ;POP STACK RETURN ;RETURN TO CALLER 3$: MOV R1,TEV(R0) ;SET TASK'S EVENT VARIABLE IN BIT #1000,2(R0) ;RETURN @SEND11? BEQ 6$ MOVB 2(R0),R1 ;GET TASK CODE BIC #177600,R1 MOVB LEVEL(R1),R2 ;LOWER TO DEVICE LEVEL COMB R2 BICB R2,PS ;SET PS MOVB (R0),R1 ;GET CALLER TASK CODE BICB #177600,R1 ;CLEAR JUNK ASL R1 ;CONVERT TASK CODE TO WORD OFFSET CALL @SEND11(R1) ;YES. ; CALLERS TCB. 6$: RETURN ;NO ; 4$: MOV #-300,TEV(R0) ;ILLEGAL LEVEL. TELL USER OF ERROR MOV #3,R2 ;RETURN AT LEVEL 3 BR 5$ ; .SBTTL EMPTY A TASKS DEQUE ; ; THIS ROUTINE WILL EMPTY A TASKS DEQUE BY RETURNING ALL UNUSED ; NODES BELONGING TO THE 15 TO THE SYSTEM POOL. ; ; CALLING SEQUENCE: ; ROUTINE MUST BE CALLED AT PROTECTED LEVEL (LVL 7) ; ADDRESS OF TASK'S LISTHEAD IN R2 ; CALL EMPTY ; REGISTERS USED: R0, R1, R2 AND R3 ; EMPTY: PUSH R2 ;SAVE R2 TEMPORARILY MOV R2,R3 2$: CMP (R2),R3 ;ANY NODES IN THIS TASK'S DEQUE (BR-134) BEQ 1$ ;ALL EMPTY MOV (R2),R0 ;RETURN THIS NODE TO THE POOL ONLY IF TST 4(R0) ; IT WAS INSERTED BY A 15 REQUEST. BMI 3$ ;NO: SKIP PAST THIS NODE MOV #POL.LH,R1 CLR 4(R0) ;ZERO NODE ENTRY BEFORE RETURNING CLR 6(R0) CALL MOVEN MOV (SP),R2 ;RESTORE R2 CMP 2(R2),R3 ;ARE WE PAST THE BOTTOM NODE OF ; THE DEQUE? BNE 2$ ;NO: TRY FOR ANOTHER NODE 1$: POP R2 ;RESTORE R2 AND STACK RETURN ;RETURN 3$: MOV R0,R2 ;LINK TO NEXT NODE BR 2$ ;LOOK AT NEXT NODE ; .SBTTL INITIALIZATION ; ; THIS ROUTINE INITIALLY STARTS THE SYSTEM GOING BY ARMING THE TCB ; REGISTER AND SCHEDULING THE NUL TASK. ; START: RESET ;RESET THE HARDWARE MOV APIDNE,R0 ;DETERMINE LOCAL MEMORY SIZE BIC #170377,R0 ; OF THE 11. ASL R0 ASL R0 ASL R0 ASL R0 ASL R0 MOV R0,MEMSIZ MOV #1000,SP ;SETUP THE SYSTEM STACK POINTER BIS #340,PS ;PROTECT WHILE SETTING UP THE SYSTEM ; SETUP DEVICE CONTROL REGISTERS BASED ON EXISTING HARDWARE IN SYSTEM MOV NBRTEV,R3 ;GET NUMBER OF TASKS IN PIREX CLR R1 NXTSK: TST (R1)+ ;BUMP INDEX MOV TEVADD(R1),R2 ;GET TASK START ADDRESS BEQ NXTASK ;SKIP SETUP IF TASK NOT ASSEMBLED CLR @-6(R2) ;TASK PRESENT. CHECK IF HARDWARE EXISTS NXTASK: DEC R3 BNE NXTSK ;DONE? MOV #6,@#4 ;YES. RESET TRAP VECTOR MOV #CLTABL,R0 ;GET ADR. OF CLOCK TABLE (BR-146) 1$: CLR (R0)+ ;CLEAR CLOCK TABLE ENTRY (BR-146) CMP #CLEND,R0 ;ARE WE DONE ? (BR-146) BNE 1$ ;REPEAT IF NOT DONE (BR-146) MOV #LASTLC,LCLAST ;SET UP INITIAL NEXT FREE LOC. (BR-147) MOV #LASTLC,TK.END ;DO SAME FOR TK.END TABLE (BR-147) MOV #TK.END+2,R0 ;START TO CLEAR TK.END TABLE AFTER (BR-147) ;FIRST ENTRY (BR-147) 2$: CLR (R0)+ ;CLEAR TK.END ENTRY (BR-147) CMP #T.END,R0 ;DONE ? (BR-147) BNE 2$ ;BRANCH IF NOT DONE (BR-147) MOV #LASTLC,R0 ;DUMMY ATL NODE ADDRESS FOR STARTUP MOV R0,CURTSK ;ESTABLISH IT AS THE CURRENT TASK BIS #100,TCBINT ;ARM THE TCB INTERRUPT FROM THE 15 ; ; START CLOCK ; MOV #100,CLSTS TST SPLNP ;IS SPOOLER CONNECTED ? (BR-146) BEQ 3$ ;BRANCH IF NO SPOOLER (BR-146) CALL SPKILL ;SPOOLER CONNECTED - KILL IT (BR-146) 3$: MOV #ST.TCB,R5 ;STOP ALL I/O REQUESTS AND CLEAR (BR-146) CLR R4 ;OUT ALL DEQUES AND QUEUES (BR-146) JMP CALLTK ;NOW START UP THE NUL JOB ; NODEV: CLR TEVADD(R1) ;CLEAR TASK FROM TABLE BR NXTASK ;TEST IF DONE ; ; ST TASK CONTROL BLOCK TO STOP ALL TASKS AND I/O CURRENTLY UNDERWAY. ; ST.TCB: .WORD 0,200,0 ; .SBTTL LINE CLOCK INTERRUPT SERVICE ; ; A CLOCK TICK INTERRUPT HANDLER ; CLSTS=177546 ; .BLOCK 8.+EAESTK*3 ;CLOCK STACK ; CLINT: JSR R0,R.SAVE ;SAVE REGISTERS INCASE WE CALL ANYONE -1 ;CLOCK TASK CODE CLR CLSTS ;DISABLE CLOCK INT CLR CLTMP ;USE AS 'DID ANYONE TIME-OUT' FLAG MOV #CLTABL-4,R0 ;SET UP POINTER TO TABLE 1$: ADD #4,R0 ;BUMP TO NEXT ENTRY (BR-134) CMP R0,#CLEND ;DONE YET BEQ 4$ ;YES IF EQUAL TST (R0) ;TIME ENTRY OF THIS PAIR 0?? BEQ 1$ ;IF ZERO, THIS PAIR DISABLED, CHECK NEXT DEC (R0) ;NOT ZERO, DO COUNTDOWN ; ; WARNING, IF BETWEEN TST AND DEC, SOMEONE AT LEVEL SEVEN ZEROED ; A PREVIOUSLY NON-ZERO ENTRY, WE WILL LOSE, SETTING IN MOTITION ; A 2^16 TICK TIME REQUEST. ; BNE 1$ ;UNLESS !BECAME! 0, ALL WE DO NOW MOV R0,CLTMP ;SAVE REG #0, OUR POINTER JSR PC,@2(R0) ;CALL INTERRUPT LEVEL SERVICE ROUTINE MOV CLTMP,R0 ;RESTORE REG #0 ; ; CALLED ROUTINE CAN ASSUME REGISTERS HAVE BEEN SAVED, AND ; R0 POINTS TO TIME COUNTER FOR HIS SLOT IN CLOCK TABLE!! ; RETURN BY DOING A RTS PC. NOTE YOU ARE CALLED AT LEVEL 6. DO ; BR 1$ ;GO CHECK NEXT ENTRY ; 4$: MOV #100,CLSTS ;ENABLE CLOCK INT JMP DEQU1 ;SCHEDULE NEXT TASK ; CLTMP: 0 ; ; .SBTTL STOP ONE OR ALL TASKS .EVEN ; ; THIS TASK IS USED TO STOP TASKS AND/OR I/O CURRENTLY UNDERWAY FOR ; ALL TASKS OR FOR A PARTICULAR TASK. IT DOES SO BY RESETTING THE SYSTEM OR DEVICE ; CONTROLLERS(IF NECESSARY), CLEARING TASK DEQUES, AND ZEROING TASKS ; REGISTERS. ; .BLOCK 8.+EAESTK*3 .WORD DUMMY ;DUMMY REGISTER .WORD 0 ;TCB POINTER (EXTENDED 2 BITS) .WORD 0 ; (LOWER 16 BITS) ; THIS WORD IS USED AS THE IDLE/BUSY ; SWITCH FOR THE TASK. ; ST: ; MOV ST-2,R0 MOVB 3(R0),R2 ;STOP ALL TASKS? BIC #177600,R2 ;TEMPORARILY REMOVE SIGN BIT BNE 2$ ;NO: JUST CLEAR THE SPECIFIED TASK INC CTLCNT ;INC CTL C RUNNING COUNTER (BR-116) MOV #2,R5 ;ZERO ALL IDLE/BUSY REGISTERS (TCBP'S) CLR -(SP) 1$: INC (SP) ;DO NEXT TASK MOV TEVADD(R5),R4 ;RETURN ALL NODES BEQ 11$ ; IN THE TASKS DEQUES THAT TSTB 3(R0) ; BELONG TO THE 15 ONLY. BMI 7$ TST -4(R4) ;(NOTE: PREVIOUS TSTB WAS USED TO BMI 3$ ; CLEAR ALL REQUESTS INCLUDING 11'S) 7$: CLR -4(R4) ;RESET TASK BUSY/IDLE SWITCH CLR -2(R4) CLR @-6(R4) ;SHUT DOWN DEVICE MOV (SP),R2 MOV R2,R3 ;GET WORD OFFSET IN R3 ASL R3 MOV ATLNP(R3),R1 ;GET ATL NODE ADDRESS IF PRESENT ; & SET HIS STATUS TO "STOP" BEQ 11$ ;NO ATL NODE WAS FOUND BIC #17,A.TS(R1) ;SET TASK STATUS TO "STOP" MOV #EXITST,R3 ; OR "WAIT" DEPENDING ON CMPB #NTEV,R2 ; WHETHER THEY ARE PERMANENT (BR-134) BLE 9$ ; ONES OR NOT. (BR-134) ASR R3 9$: BIS R3,A.TS(R1) 3$: MOV R5,R2 ASL R2 ADD #LISTHD,R2 PUSH R0 ;SAVE R0 TEMP CALL EMPTY ;(EMPTY TASKS DEQUE) POP R0 ;RESTORE R0 11$: BIC #100,PS ;OPEN WINDOW FOR CD LVL 6 INTERRUPT ; ;ONCE EACH ITERATION AT THIS 'SAFE' PLACE TST (R5)+ ;DO NEXT TASK PUSH NBRTEV ASL (SP) BIS #100,PS ;CLOSE WINDOW , RETURN TO 7 CMP (SP)+,R5 ;ALL DONE ? (BR-134) BGE 1$ ;NO: CONTINUE (BR-134) TST (SP)+ ;CLEAN UP STACK BR 13$ ;TELL 15 THAT REQUEST IS COMPLETE ; 2$: MOV R2,R5 ;SAVE TASK CODE ASL R2 ;GET ADDRESS OF TASK IN MOV TEVADD(R2),R4 ; REFERENCE. BEQ 12$ TSTB 3(R0) ;IF NEG., REMOVE ALL ENTRIES BMI 8$ TST -4(R4) ;IGNORE TCBP IN TASKS BUSY SWITCH BMI 4$ ; IF IT WASN'T A FROM A 15 REQUEST. 8$: CLR -4(R4) ;ZERO THE IDLE/BUSY REGISTER FOR THIS CLR -2(R4) ; TASK ONLY IF IT'S A REQUEST THAT ; CAME FROM THE PDP15. CLR @-6(R4) ;NOW DISABLE THE TASK MOV ATLNP(R2),R1 ;IF ATL NODE PRESENT SET STATUS TO STOP BEQ 4$ ;NO ATL NODE EXISTS FOR THIS TASK BIC #17,A.TS(R1) ;SET TASK STATUS TO "STOP" MOV #EXITST,R3 ; OR "WAIT" DEPENDING ON CMPB #NTEV,R5 ; WHETHER THEY ARE PERMANENT (BR-134) BLE 10$ ; ONES OR NOT. (BR-134) ASR R3 10$: BIS R3,A.TS(R1) 4$: ASL R2 ;EMPTY TASKS DEQUE ADD #LISTHD,R2 CALL EMPTY 13$: MOV #1,R1 ;TELL CALLER ALL OK 5$: BIS #340,PS ;INHIBIT INTERRUPTS MOV ST-2,R0 ;RESTORE R0 (TCBP) CLR ST-2 ;CLEAR OUT THIS TCBP (I.E. "ST" DRIVER") CLR ST-4 MOV R1,TEV(R0) ;TELL 15 THAT REQUEST IS COMPLETE MOV #ST.LH,R1 ;TEST FOR ANY PENDING REQUESTS (BR-145) CMP (R1),R1 ;ANY PENDING ? (BR-145) BNE 14$ ;BRANCH IF ANY PENDING REQ. (BR-145) SEXIT EXITST ;RETURN ATL NODE TO POOL AND ; EXIT BACK TO THE ATL SCANNER. 12$: MOV #-600,R1 ;TELL CALLER ATL NODE MISSING BR 5$ 14$: MOV #ST,R3 ;SET UP RETURN TO ST: FOR DEQU (BR-145) JMP DEQU ;EXIT - WITH RETURN IF ANY MORE REQUESTS (BR-145) ; .SBTTL SOFTWARE DIRECTIVE PROCESSING .EVEN ; ; THIS TASK CARRIES OUT FUNCTIONS CALLED "DIRECTIVES". ; THE FOLLOWING DIRECTIVES ARE CURRENTLY SUPPORTED. ; ; FUNCTION CODE DIRECTIVE ; ; 00 DISCONNECT TASK FROM PIREX & REMOVE ATL ; 01 CONNECT TASK TO PIREX & RUN TASK ; 02 REPORT CORE STATUS IN LOCAL MEMORY TO CALLER ; 03 REPORT ERROR STATUS OF TASKS ; .BLOCK 8.+EAESTK*4 .WORD DUMMY ;DUMMY CONTROL REG SINCE SOFTWARE ; ROUTINES DO NOT NEED HARDWARE ; SHUT DOWNS. .WORD 0 ;TCB POINTER (EXTENDED BITS) .WORD 0 ;TCB POINTER (LOWER 16 BITS). THIS ; WORD IS USED AS THE IDLE/BUSY ; SWITCH FOR THE SD TASK. SD: MOV SD-2,R0 ;TCBP MOVB 7(R0),R1 ;GET FUNCTION CODE FROM TCB CMP NBRFCT,R1 ;FUNCTION OUT OF RANGE? (BR-134) BGT 1$ ;NO (BR-134) MOV #-400,R1 ;RETURN ILLEGAL FUNCTION CODE IN TCB CALL SEND15 SEXIT EXITST ;EXIT AND RETURN ATL NODE TO POOL ; 1$: MOVB 6(R0),R2 ;GET TASK CODE ASL R1 JMP @DIRDSP(R1) ;DISPATCH TO APPROPRIATE ROUTINE ; ; DIRECTIVE DISPATCH TABLE ; DIRDSP: DISCON ;DISCONNECT DIRECTIVE CONNEC ;CONNECT DIRECTIVE COREPT ;CORE STATUS REPORT DIRECTIVE ERREPT ;ERROR REPORT DIRECTIVE; SPLSTS ;SPOOLER STATUS (BR-120) MOVEIT ;MOVE INFO DIRECTIVE (BR-120) NBRFCT: .-DIRDSP/2 ; ; CONNECT DIRECTIVE ; CONNEC: CMP NBRTEV,R2 ;USE NEW TASK CODE # FOR UPPER (BR-134) BGE 1$ ; LIMIT IF ITS LARGER. (BR-134) MOV R2,NBRTEV 1$: MOV R2,R4 ;SAVE IN R4 ASL R2 ;CONVERT TASK CODE TO WORD OFFSET MOV 14(R0),R1 ;GET START ADDRESS TST 10(R0) ;11'S REQUEST? BMI 2$ ASL R1 ;CONVERT TO BYTE ADDRESS ADD MEMSIZ,R1 ;ADD 11'S LOCAL MEMSIZE BR 3$ 2$: ADD 16(R0),LCLAST ;UPDATE LAST LOCATION (BR-147) MOV LCLAST,TK.END(R2) ;SET 'NEXT-FREE-LOC.' IN TK.END TABLE (BR-147) 3$: MOV R1,TEVADD(R2) ;SET TASK FA IN SYSTEM TABLE MOV #LISTHD,R3 ;NOW INITIALIZE THE LISTHEAD ADD R2,R3 ADD R2,R3 MOV R3,(R3) ;FORWARD POINTER MOV R3,2(R3) ;BACKWARD POINTER MOVB 20(R0),LEVEL(R4);ESTABLISH TASK RUN PRIORITY MOV TEVADD(R2),R2 ;NOW UNBUSY THE TASK CLR -4(R2) CLR -2(R2) MOV #1,R1 ;TELL CALLER ALL OK CONN3: MOV SD-2,R0 ;SET UP R0 WITH TCBP (BR-145) CALL SEND15 ;TELL CALLER THAT HIS REQUEST HAS BEEN (BR-145) ;COMPLETED (BR-145) BIC #100,PS ;ALLOW PENDING PRIORITY 6,7 INTER. (BR-145) NOP ;GIVING A TWO INSTRUCTION WINDOW (BR-145) BIS #100,PS ;THEN LOCK-OUT INTS. AGAIN (BR-145) CLR SD-2 ;ALLOW NEXT TCB (BR-145) CLR SD-4 ;DITTO (BR-145) MOV #SD,R3 ;SETUP RETURN FROM DEQU IF ANY PENDING TCB'S (BR-145) MOV #SD.LH,R1 ;TELL DEQU WHERE TRL IS (BR-145) JMP DEQU ;GET ANY PENDING TCB'S (BR-145) ; ; DISCONNECT DIRECTIVE ; DISCON: CMPB NBRTEV,R2 ;TEMPORARY TASK? (BR-134) BNE 1$ DEC NBRTEV ;YES. UPDATE HIGHEST TASK CODE # 1$: BIS #340,PS ;RAISE TO LVL 7 MOV R2,R3 ;SAVE TASK CODE ASL R3 ;CONVERT TASK CODE TO WORD OFFSET MOV ATLNP(R3),R1 ;GET ATL NODE ADDRESS BEQ 4$ ;REPORT IF ATL NODE MISSING CALL RATLN ;RETURN ATL NODE CLR TEVADD(R3) ;DISCONNECT TASK MOV R3,R4 ;SAVE TASK-CODE*2 (BR-147) ASL R3 ;SETUP FOR EMPTY MOV R3,R2 ADD #LISTHD,R2 ;SETUP FOR EMPTY CALL EMPTY ;CLEAR DEQUE MOV SD-2,R0 ;SAVE TCBP TST 10(R0) ;11'S REQUEST? BPL 2$ CLR TK.END(R4) ;CLEAR THIS TASK'S MEMORY REQUIREMENT (BR-147) CLR R4 ;SET MAX 'NEXT-FREE-LOC.' TO ZERO (BR-147) MOV #TK.END,R1 ;POINT TO FIRST ENTRY IN TK.END TABLE (BR-147) 5$: CMP (R1)+,R4 ;DOES R4 CONTAIN THE HIGHEST LOC. (BR-147) BLE 6$ ;BRANCH IF SO (BR-147) MOV -2(R1),R4 ;NO - UPDATE R4 (BR-147) 6$: CMP #T.END,R1 ;ARE WE DONE? (BR-147) BNE 5$ ;NO - TRY NEXT ENTRY (BR-147) TST R4 ;YES - DOES R4 CONTAIL VALID LOC. (BR-147) ;IF VALUE IS 0 - LOC. IS NOT VALID (BR-147) BEQ 7$ ;NO - FATAL ERROR -TELL USER (BR-147) MOV LCLAST,R1 ;SAVE OLD 'NEXT-FREE-LOC.' (BR-147) MOV R4,LCLAST ;UPDATE 'NEXT-FREE-LOC.' WITH R4 (BR-147) CMP R1,R4 ;DID WE DELETE A HOLE IN MIDDLE? (BR-147) ;NOTE: THIS IS BEING DONE TO MAINTAIN ;COMPATABILITY WITH OLDER PIREX SYSTEMS. ;A HOLE IN MIDDLE WILL NOW BE RECOVERED WHEN ;HIGER (IN MEMORY) TASKS ARE DISCONNECTED. BEQ 3$ ;BRANCH IF HOLE IN MIDDLE (BR-147) 2$: MOV #1,R1 ;TELL CALLER ALL OK BR CONN3 ;UNBUSY SD TASK & EXIT 3$: MOV #2,R1 ;NO. TELL CALLER THAT HOLE IS CREATED BR CONN3 4$: MOV #-600,R1 ;TELL CALLER ATL NODE MISSING BR CONN3 7$: MOV #-601,R1 ;TELL CALLER - SERIOUS MEMORY PROBLEM (BR-147) MOV #601,SD.EST+4 ;TELL USER VIA POLLER OF PROBLEM ;THIS IS DONE SO THAT USER PROGRAM NEED ;NOT DETECT THIS ERROR . COMPATABILITY ;WITH PREVIOUS (PRE VER 148) PIREX SYSTEMS IS ;MAINTAINED. ALSO THIS ERROR IS SO SERIOUS ;THAT THE OPERATOR SHOULD ALWAYS BE TOLD. ;NOTE THAT LCLAST IS NOT RESET WHEN THIS ;ERROR IS DETECTED,BUT REMAINS SET AT IT'S OLD ;VALUE ,THIS PRESERVES OCCUPIED MEMORY. (BR-148) JMP CONN3 ;AND EXIT (BR-147) ; ; ; TASK ERROR STATUS REPORT DIRECTIVE ; ERREPT: BIC #100,PS ;##127##KICK DOWN TO LVL 5 FOR CD MOV R0,R1 ;POINT R1 TO MESAG WORD ADD #10,R1 MOV #NTEV+2*3,R2 ;SET # OF ENTRYS MOV #DEVST,R3 1$: MOV (R3)+,(R1)+ ;COPY TABLE DEC R2 BNE 1$ BIC #100,PS ;##127## AGAIN IN CASE RECHEDULED MOV #NTEV+2,R2 ;RESET TABLE ENTRIES MOV #DEVST,R3 2$: ADD #4,R3 ;BUMP TO ERROR WORD (BR-134) CLR (R3)+ DEC R2 BNE 2$ BIS #340,PS ;##127##AND BACK TO 7 FOR REMAINDER MOV #1,R1 JMP CONN3 ;AND EXIT (BR-147) ; ; ;CORE REPORT STATUS DIRECTIVE ; COREPT: MOV MEMSIZ,R2 ;GET SIZE OF LOCAL MEMORY SUB MEMSIZ+4,R2 ;DEDUCT LAST LOCATION ASR R2 ;CONVERT TO WORD BPL 1$ MOV #-500,R1 ;NO FREE CORE!! JMP CONN3 ;AND EXIT (BR-147) 1$: MOV R2,16(R0) ;SET FREE CORE SIZE IN TCB MOV MEMSIZ+4,12(R0) ;SET LAST LOCATION IN TCB MOV MEMSIZ,10(R0) ;SET LOCAL MEMORY SIZE (BR-120) MOVB NBRTEV,6(R0) ;SET CURRENT HIGHEST TASK CODE # IN TCB MOV 6(R0),6(R0) ;THIS CLEARS THE PARITY BITS IN COMMON MEMORY ;AFTER THE ABOVE XVM BYTE OPERATION (BR-143) MOV #1,R1 ;TELL CALLER ALL OK JMP CONN3 ;AND EXIT (BR-147) ; ; ; SPOOLER STATUS DIR. ; ; SPLSTS: MOV SPOLSW,10(R0) ;SET UP SPOOL STATUS MOV DEVARE,12(R0) MOV DEVSPL,14(R0) MOV SPUNIT,16(R0) ;MOVE SPOOLER DISK UNIT NR. (BR-122) MOV #1,R1 ;RETURN STATUS OK JMP CONN3 ;AND RETURN TO CALLER ; ; ; PIREX MOVE DIRECTIVE ; ; MOVEIT: MOV 10(R0),R1 ;GET FROM LOCATION (BR-125) MOV 12(R0),R2 ;GET TO LOCATION (BR-125) MOV 14(R0),R3 ;GET NUMBER OF WORDS TO MOVE (BR-125) CMP R1,R2 ;WHICH IS GREATER ? (BR-120) BLO 1$ ;BRANCH IF FROM LESS THAN TO (BR-120) 4$: MOV (R1)+,(R2)+ ;MOVE DATA BOTTOM UP (BR-120) DEC R3 ;KEEP COUNT OF HOW MANY MOVES (BR-120) BNE 4$ ;DONE YET? (BR-120) BR 2$ ;YES (BR-120) 1$: INC R1 ;SET UP FOR -(RX) CONSTRUCT (BR-120) INC R1 ;DITTO (BR-120) INC R2 ;DITTO (BR-120) INC R2 ;DITTO (BR-120) 5$: MOV -(R1),-(R1) ;MOVE DATA FORM TOP DOWN (BR-120) DEC R3 ;KEEP COUNT OF HOW MANY MOVES (BR-120) BNE 5$ ;DONE YET? (BR-120) 2$: MOV #1,R1 ;YES - SAY SO (BR-120) JMP CONN3 ;AND RETURN TO CALLER (BR-120) ; ; .NLIST .IFDF $RK .LIST .SBTTL DISK DRIVER FOR RK11/15 .EVEN ; RKDS=177400 RKER=177402 RKCS=177404 RKWC=177406 RKBA=177410 RKDA=177412 RKWC15=14 RKUNFC=16 RKCS15=20 RKER15=22 RKDS15=24 ; ; CALL TO ROUTINE HAS ADDRESS OF TCB IN HANDLER BUSY (IDLE) REGISTER ; .BLOCK 8.+EAESTK*4 .WORD RKCS ;ADDRESS OF RKCS CONTROL STATUS REGISTER ; USED TO RESET DEVICE ON STOP I/O ; REQUESTS. .WORD 0 ;TCB POINTER (EXTEND BITS) .WORD 0 ;TCB POINTER (LOWER 16 BITS) THIS ; WORD IS USED AS THE IDLE SWITCH ; FOR THE DEVICE DRIVER. DK: MOV #400,DKREPT ;CLEAR RETRY INDICATOR DKRTRY: CLR DK.CL ;STOP TIMED WAKEUP (BR-142) MOV DK-2,R0 ;SETUP R0 TO POINT TO TCB MOV RKUNFC(R0),R1 ;GET UNIT IN R1(13-15) SWAB R1 BIC #177770,R1 ASR R1 ;LEFT-JUSTIFY UNIT ROR R1 ROR R1 ROR R1 ;UNIT NOW AS DESIRED ADD #6,R0 ;POINTER TCB+BLOCK MOV (R0)+,R2 TST R2 ;IS BLOCK WITHIN BOUNDS (BR-134) BMI 5$ ;NEGATIVE BLOCK NUMBERS ILLEGAL CMP #4872.,R2 ;TEST UPPER BOUND (BR-134) BHI 2$ ;YES BRANCH (BR-134) ; ROUTINE TO PROCESS ERROR. 5$: MOV DK-2,R0 ;SETUP TCB TO REFLECT ERROR BEQ DKXT ;IGNORE IF ITS ALREADY BEEN STOPPED BY ;A STOP I/O REQUEST. MOV #RKDS,R5 ;POINTER TO RK REGISTER SET (BR-151) MOV (R5)+,RKDS15(R0) ;MOVE RKDS INTO TCB (BR-151) MOV (R5)+,RKER15(R0) ;MOVE RKER INTO TCB (BR-151) BIS #140,RKER15(R0) ;SET ILLEGAL BLOCK ERROR (BR-151) MOV (R5),RKCS15(R0) ;MOVE RKCS INTO TCB (BR-151) BIS #100000,RKCS15(R0) ;SET GLOBAL ERROR (BR-151) BR DKXIT ;EXIT NOW ;CALCULATE CYLINDER ADDRESS 3$: ADD #40,R1 ;+1 TO CYLINDER ADDRESS 2$: SUB #24.,R2 BGE 3$ ADD #24.,R2 ;RESET OVERFLOW CMP #12.,R2 ;IF >=12. CAUSE A SURFACE INCREM. (BR-134) BGT 4$ ADD #4,R2 4$: ADD R2,R1 MOV #RKDA,R4 7$: TSTB -6(R4) ;CONTROL READY? BPL 7$ MOV R1,@R4 ;YES. SET UP DISK ADDRESS MOV (R0)+,R2 ;SETUP MEMORY ADDRESS (M.S.) MOV (R0)+,R3 ;SETUP MEMORY ADDRESS (L.S.) BIC #77774,R2 ;CLEAR JUNK AND DO NOT RELOC ADR WHEN PDP11 (BR-136) BMI 6$ ;BRANCH IF PDP11 REQ (BR-136) 1$: ASL R3 ;RELOCATE ADDRESS (WORD TO BYTE) ROL R2 ADD MEMSIZ,R3 ;(+ 11'S OWN LOCAL MEMORY) ADC R2 6$: ASL R2 ;SHIFT TO POSITION IN CONTROL WORD (BR-136) ASL R2 ASL R2 ASL R2 MOV R3,-(R4) ;MEMORY ADDRESS (L.S.) MOV (R0)+,-(R4) ;SET UP WORD COUNT BIT #4,-6(R0) ;TEST FOR EXTRA 64K TRANSFER (BR-136) BEQ 10$ ;NOT NEEDED - BRANCH (BR-136) CLR (R4) ;NEEDED - CAUSE INITIAL 64K TRANSFER (BR-136) 10$: MOV (R0)+,R1 ;PUT IN THE FUNCTION (BR-136) BIS #101,R1 ;SET I.D.E. , GO (BR-120) BIC #177460,R1 ;CLEAR GARBAGE (BR-126) BIS R2,R1 ;ADD IN EXTENDED MEMORY BITS MOV R1,-(R4) ;NO. SEND FUNCTION TO CONTROL SEXIT WAITST ;ENTER A WAIT STATE AND RESCAN ; THE ATL NOW. ; ; INTERRUPT PROCESSOR ; DKINT: JSR R0,R.SAVE ;SAVE REGISTERS 2 ;TASK CODE MOV DK-2,R0 ;GET THE TCBP BEQ DKXT ;IGNORE IF ITS ALREADY BEEN STOPPED BY ; A STOP I/O REQUEST. MOV #RKDS,R5 MOV (R5)+,R1 ;SAVE THE RKDS, RKER, AND RKCS IN TCB MOV R1,RKDS15(R0) MOV (R5)+,R2 MOV R2,RKER15(R0) MOV @R5,R4 MOV R4,RKCS15(R0) BMI DKERP ;BRANCH ON ERROR BIT #10,R4 ;WAS LAST FUNCTION A DRIVE RESET? BNE DKER00 ;YES: BRANCH DKXIT: MOV DK-2,R0 ;POINT TO TCB START (BR-136) BIT #4,10(R0) ;WAS 64KW TRANSFER JUST DONE ? (BR-136) BEQ 1$ ;NO - BRANCH TO NORMAL EXIT (BR-136) ADD #400,6(R0) ;INCREMENT THE STARTING DISK ADR. (BR-136) BIC #4,10(R0) ;CLEAR EXTRA 64K FLAG AND TEST FOR PDP11 REQUEST (BR-136) BPL 2$ ;NO - BRANCH (BR-136) ADD #2,10(R0) ;YES - ADD 128KB TO STARTING MEM ADR (BR-136) BIC #4,10(R0) ;CLEAR POSSIBLE OVERFLOW (BR-136) JMP DK ;DO SECOND TCB [WC-64KW] (BR-136) 2$: INC 10(R0) ;ADD 64KW TO STARTING MEM ADR (BR-136) BIC #4,10(R0) ;CLEAR POSSIBLE OVERFLOW (BR-136) JMP DK ;DO SECOND TCB [WC-64KW] (BR-136) 1$: BIS #340,PS ;INHIBIT INTERRUPTS (BR-136) MOV #1,R1 ;SEND AN API INTERRUPT TO THE 15 NOW CALL SEND15 ; TELLING HIM THAT HIS REQUEST HAS ; BEEN PROCESSED. DKXT: BIS #340,PS ;INHIBIT INTERRUPTS CLR DK-2 ;CLEAR BUSY (IDLE) FLAG CLR DK-4 MOV #DK.LH,R1 ;POINT TO RK TRL (BR-145) CMP (R1),R1 ;ARE THERE ANY REQUESTS PENDING (BR-145) BNE DKXT1 ;YES - GO GET THEM (BR-145) TST SPOLSW ;ARE WE SPOOLING (BR-142) BPL DKXT1 ;NO - DO NOTHING (BR-142) MOV #RKCHK,DK.CL+2 ;MOVE TIMER WAKEUP ADR. TO CLK TABLE (BR-142) MOV #170,DK.CL ;ASK FOR WAKEUP IN 2 SECONDS TO TEST (BR-142) ;IF DISK IS ENABLED (BR-142) DKXT1: MOV #DK,R3 ;DEQUEUE ANOTHER REQUEST IF ANY EXISTS JMP DEQU RKCHK: TST DK-2 ;IS DISK ACTIVE (BR-142) BNE 3$ ;BRANCH IF ACTIVE - DISABLE CLOCK WAKEUP (BR-142) TST SPOLSW ;IS THE SPOOLER STILL ACTIVE (BR-142) BPL 3$ ;BRANCH IF NOT ACTIVE - STOP WAKEUPS (BR-142) TSTB RKCS ;TEST TO SEE IF CONTROLER IS BUSY (BR-142) BPL 2$ ;BRANCH IF BUSY - RETRY LATER (BR-142) MOV SPUNIT,R2 ;GET UNIT # OF RK BEING SPOOLED TO (BR-142) ROR R2 ;SHIFT INTO POSITION FOR LOAD INTO RKDA (BR-142) ROR R2 ;"" (BR-142) ROR R2 ;"" (BR-142) ROR R2 ;"" (BR-142) MOV R2,RKDA ;SELECT UNIT "SPUNIT" (BR-142) TSTB RKDS ;IS SPUNIT ENABLED (BR-142) BPL 1$ ;BRANCH IF NOT ENABLED (BR-142) 2$: MOV #170,(R0) ;ASK FOR ANOTHER WAKEUP (BR-142) 3$: RTS PC ;RETURN TO CLOCK ROUTINE (BR-142) 1$: MOVB #26,SP.EST+4 ;TELL USER SPOOLER DISCONNECTED (BR-143) CALL SPKILL ;DISCONNECT AND ABORT SPOOLER (BR-145) RTS PC ;RETURN TO CLOCK ROUTINE (BR-145) .NLIST .ENDC .LIST .SBTTL SPOOLER ABORT ROUTINE .EVEN SPKILL: ;SPOOLER ABORT ROUTINE (BR-145) MOV SPUNIT,SP.EST+2 ;TELL USER WHICH UNIT WAS SPOOLING (BR-143) IREQ #KILLSP ;DISCONNECT SPOOLER (BR-142) RTS PC ;RETURN TO CALLER (BR-145) KILLSP: .WORD 0 ;TCB TO TELL SPOOLER TO GO AWAY (BR-142) ;NO RETURN VIA SEND11 WANTED (BR-142) .WORD 607 ;SPOOLER STOP CODE (BR-142) .WORD 0 ;(BR-142) .WORD 4 ;(BR-142) ; .NLIST .IFDF $RK .LIST .SBTTL DISK ERROR PROCESSOR .EVEN ; ; ERROR PROCESSOR ; DKERP: ASL R4 ;HARD ERROR? BMI DKHER ;YES: BRANCH DKER00: ROL (PC)+ ;TRIED 8 TIMES? DKREPT: .WORD 0 BCC DKER25 ;IF NOT, TRY AGAIN BR DKXIT ;EXIT AND SHOW ERROR TO THE 15 ; ; HARD ERROR ; DKHER: MOV #1,@R5 ;CLEAR THE CONTROL DKHR00: TSTB @R5 ;DONE YET? BPL DKHR00 ;NO - LOOP BIT #1000,R1 ;IS IT SEEK INCOMPLETE? BEQ DKHR05 ;NO - BRANCH MOV R1,6(R5) ;REPLACE DRIVE # MOV #115,@R5 ;SET UP FOR DRIVE RESET BR DKXIT ;TAKE INTERIM EXIT DKHR05: BIT #11400,R2 ;CAN WE POSSIBLY GO ON? BNE DKER00 ;YES - BRANCH BR DKXIT ;NO: SHOW ERROR TO THE 15 ; DKER25: BIS #340,PS ;INHIBIT INTERRUPTS MOV #4,R3 ;SEE IF THERE'S AN ATL NODE MOV ATLNP(R3),R1 BEQ DKXT ;NO ATL NODE, FORGET RE-TRYING THEN MOV #DK,R2 ;SETUP FOR CEXIT MOV #DKRTRY,-12(R2) ASR R3 ;GET RK TASK CODE MOVB LEVEL(R3),-10(R2) ; .NLIST .ENDC ; .LIST ; CALLING SEQUENCE: ATL NODE ADDRESS IN R1 ; TASK START ADDRESS IN R2 ; JMP CEXIT ; ; REGS.USED: R2 CEXIT: BIS #340,PS ; INHIBIT INT. BIC #17,A.TS(R1) ;DECLARE TASK RUNNABLE ADD #-26,R2 MOV R2,A.SP(R1) ;SET SP MOV SYS.SP,SP ;SWITCH TO SYSTEM STACK JMP AS.E1 ;SCHEDULE NEXT TASK ; .NLIST .IFDF $LP .LIST .SBTTL LINE PRINTER DRIVER FOR LP11/15 .EVEN ; LPCSR=177514 LPBUF=177516 LPSA=6 LPIOT=12 LPSTAT=14 LPEST=LP.EST+4 ;ADDR IN PIREX ERROR TABLE FOR NOT READY LPUNN=LP.EST+2 ;ADDR FOR UNIT # (FOR NOW 0) LPTCOD=4 ;LINE PRINTER TASK CODE LPEOF=6414 ;EOF CODE(DATA) FOR SPOOLING ; ; ; ; ; MAKE THE PDP-15 DO ALL THE WORK. THE PDP-11 SIMPLY GET S A COUNT ; OF CHARACTERS TO PRINT OUT. WE TREAT THE CONTROL CHARACTERS ; 12,15, AND 14 ONLY. A MINUS CHARACTER IS CONVERTED INTO MINUS ; THAT NUMBER OF SPACES. NOTE ALL REAL ASCII CHAR'S HAVE A ZERO LEADING BIT! ; EACH LINE HAS AN IMPLIED CARRIAGE RETURN THAT IS ADDED BY THE DRIVER ; RATHER THAN SENT BY THE PDP-15 ; ; NOTE, IF HEADER WORD OF BUFFER HAS 400 BIT SET, IT IS ; IMAGE MODE, AND WE NIETHER BUT ON LF OR CR!! ; ; ; CALL TO ROUTINE HAS ADDRESS OF TCB IN HANDLER BUSY (IDLE) REGISTER ; .BLOCK 8.+EAESTK*4 .WORD LPCSR ;ADDRESS OF LPCSR CONTROL STATUS ; REGISTER USED TO RESET DEVICE ; ON STOP I/O OPERATIONS. .WORD 0 ;TCB POINTER (EXTENDED BITS) .WORD 0 ;TCB POINTER (LOWER 16 BITS). THIS ; WORD IS USED AS THE IDLE/BUSY ; SWITCH FOR THE DEVICE DRIVER. ; LP: CLR LP.CL ;CLEAR OUT ANY PENDING TIMER REQUESTS FOR US. MOV LP-2,R0 ;SETUP R0 TO POINT TO TCB CLR LPSTAT(R0) ;CLEAR STATUS FLAG IN TCB MOV LPSA+2(R0),R1 ;GET BUFFER START ADDRESS TST LPSA(R0) ;DON'T RELOCATE ADDRESS IF BIT 15 BMI 1$ ; IS ON. ASL R1 ;RELOCATE ADDRESS (WORD TO BYTE POINTER) ADD MEMSIZ,R1 ;(+ 11'S OWN LOCAL MEMORY) 1$: MOV (R1)+,R2 ;(SCR-152)FULL HEADR WORD MOVB #15,LPEOL ;DEFAULT, ASCII, HERE IS MOV #5000,(R1)+ ;(SCR-152)DEFAULT PRECEED WITH LF CLRB LPERWT ;RESET ERROR WAIT SWITCH .IFNDF $NOSW ;##124##IF $NOSW, DISABLE ALL SWITCH INTERACT BIT #140000,SPOLSW ;SPOOLER ENABLED & RUNNNG BEQ 6$ ;GO TO DISABLE HALT AT EOF (BR-135) TST R2 ;(SCR-152)EOF IF TOP BIT ON BMI 5$ ;(SCR-152)GOT AN EOF TSTB LPEFWT ;WAS LAST RECORD AN EOF ? (BR-135) BEQ 2$ ;NO - BRANCH TO NORMAL CODE (BR-135) CLRB LPEFWT ;YES - CLEAR SWITCH FOR NEXT USE (BR-135) BIT #2,SW ;IS SWITCH 2 UP ON 11 CONSOLE ? (BR-135) BEQ 2$ ;NO - RESUME NORMAL CODE (BR-135) MOV #LPECHK,LP.CL+2 ;YES - SET UP CLOCK (BR-135) MOV #170,LP.CL ;TWO SECOND RETRY (BR-135) SEXIT WAITST ;EXIT TO SYSTEM 5$: INCB LPEFWT ;SET EOF FLAG FOR NEXT TCB (BR-135) BR 2$ ;RESUME NORMAL CODE (BR-135) 6$: CLRB LPEFWT ;CLEAR FLAG - IN CASE SPOOLER JUST TURNED OFF (BR-135) .ENDC 2$: BIT #400,R2 ;(SCR-152)BIT SET IF IMAGE MODE BEQ 3$ ;NOT IMAGE, CHECK FORMS CONTROL CLRB LPEOL ;IMAGE, DON'T FORCE CR AFTER MESSAGE BR 4$ ;ALLOW ALL FORMS CONTROL 3$: CMPB #14,(R1) ;FIRST CHAR FORM FEED? BEQ 4$ ;YES, DON'T ADD LINE FEED TO LINE CMPB #15,(R1) ;FIRST CHAR CARRIAGE RETURN BEQ 4$ ;YES, DON'T ADD LINE FEED TO LINE DEC R1 ;MOVE POINTER BACK TO LINE FEED INC R2 ;COUNT ADDITION OF LF TO BUFFER 4$: BIC #177400,R2 ;(SCR-152)CLEAR MODE BYTE FROM COUNT MOV R2,LPBTCT ;SAVE COUNT MOV R1,LPBUFF ;SAVE POINTER CLRB LPTAB TSTB LPBUF ;HISTORY SAYS THIS HERE BIS #100,LPCSR ;ENABLE INTERRUPTS TO LP GOING SEXIT WAITST ;EXIT IN A WAIT STATE AND RESCAN ; THE ATL NOW. ; ; ; LP INTERRUPT ENTRANCE ; LPINT: BIC #100,LPCSR ;DISABLE LP INTERRUPT JSR R0,R.SAVE ;SAVE REGISTERS 4 ;TASK CODE MOV LP-2,R0 ;GET TCB POINTER BEQ LPXT ;IGNORE IF ITS ALREADY BEEN STOPPED BY ; A STOP I/O REQUEST. TST LPCSR ;CHECK FOR ERROR BMI LPERR ;YES CLR LP.CL ;CLEAR OUT ANY PENDING TIMER REQUEST FOR US. LPLOP: TSTB LPCSR ;IS PRINTER CURRENTLY GOING? BPL LPSTIL ;YES: FORGET CHAR FOR NOW TSTB LPTAB ;IN TAB EXPANSION TO SPACES? BMI 4$ ;YES DEC LPBTCT ;DECR CHAR COUNT BMI 5$ ;WENT TO -1, MAKE CR TO FINISH LINE TSTB @LPBUFF ;MINUS BYTE IS TAB EXPANSION COUNT BMI 6$ ;IS ONE, GO SET UP MOVB @LPBUFF,LPBUF ;STICK CHAR INTO LINE PRINTER BUFFER INC LPBUFF ;MOVE POINTER TO NEXT CHAR BR LPLOP ;GO DO NEXT ; 6$: MOVB @LPBUFF,LPTAB ;SET UP TAB COUNT (MINUS, A LA 15) INC LPBUFF 4$: INCB LPTAB ;COUNT A SPACE FOR THIS TAB MOVB #40,LPBUF ;SPACE TO LINE PRINTER BR LPLOP ;GO DO NEXT 5$: TSTB LPEOL ;IMAGE OR ASCII BEQ 7$ ;IMAGE, DON'T FORCE MOVB LPEOL,LPBUF ;ASCII, HERE IS 7$: INC LPSTAT(R0) ;SET REV TO GOOD COMPLETION BR LPXIT ; LPSTIL: BIS #100,LPCSR ;ENABLE INTERRUPT ON LP BR LPXIT1 ;RESTORE R0-R5 AND RETURN ; LPERR: INCB LPERWT ;SET ERROR WAIT SW. MOVB #4,LPEST ;ERROR CODE 1,NOT READY TO TABLE LPERR1: MOV #LPCHK,LP.CL+2 ;ADDR. FOR TIMER REQ. MOV #170,LP.CL ;2 SECS. IN TICKS(OCTAL) LPXIT1: JMP DEQU1 ;SCHEDULE NEXT TASK ; LPXIT: CLRB LPEST ;INDICATE SUCCESSFULL OPERATION BIS #340,PS ;INHIBIT INTERRUPTS CLR LPCSR ;SHUT DOWN DEVICE MOV #1,R1 ;TELL CALLER DONE MOV LP-2,R0 ;GET TCBP CALL SEND15 ;TELL CALLER DONE LPXT: BIS #340,PS ;INHIBIT INTERRUPTS CLR LP-2 ;CLEAR BUSY(IDLE) FLAG CLR LP-4 MOV #LP,R3 ;DEQUEUE ANOTHER REQUEST IF ANY MOV #LP.LH,R1 ; IN THIS DRIVERS DEQUE. JMP DEQU ; ; ; ; SUBROUTINE TO FIELD CLOCK COUNT-DOWN ; ; LPECHK: TST LP-2 ;HAVE WE BEEN DISABLED ? (BR-135) BEQ LPCX ;YES - RETURN TO CLOCK - NO RETRY (BR-135) BIT #2,SW ;NO - IS SWITCH 2 STILL UP ? (BR-135) BNE LPCXIT ;YES - SET UP CLOCK RETRY (BR-135) BR LPCLK ;NO - SET UP RETRY OF TCB (BR-135) LPCHK: TST LP-2 ;HAVE WE BEEN DISABLED BEQ LPCX ;IF YES, EXIT, LEAVING CLOCK DISABLED (BR-135) TST LPCSR ;DOES ERROR STILL EXIST ? (BR-135) BMI LPCXIT ;YES - SET UP CLOCK RETRY (BR-135) LPCLK: MOV #LPTCOD*2,R2 ;SCAN ATL FOR OUR NODE (BR-135) MOV ATLNP(R2),R1 MOV #LP,LP-12 ;RESTART AT BEGINNING OF REQ. BIC #17,A.TS(R1) ;R1 POINTS TO OUR NODE, MAKE RUNNABLE MOV #LP-26,A.SP(R1) ;SET UP STACK POINTER ASR R2 ;MAKE BYTE ADDRESSING MOVB LEVEL(R2),LP-10 ;SET UP PS RTS PC ;RETURN TO CLOCK (BR-135) LPCXIT: MOV #170,(R0) ;R0 POINTS TO TIMER ENTRY LPCX: RTS PC ;RETURNS TO CLOCK ; LPBUFF: .WORD 0 ;BUFFER POINTER LPBTCT: .WORD 0 ;BYTE COUNT LPTAB: .WORD 0 ;TAB LOCATION LPEOL: .BYTE 0 ;0 IF IMAGE, 15 IF ASCII LPERWT: .BYTE 0 ;MAKE EVEN LPEFWT: .BYTE 0 ;EOF WAS LAST RECORD FLAG (BR-135) .EVEN ;MAKE EVEN (BR-135) ; .NLIST .ENDC ; .IFDF $CD .LIST .SBTTL CR11 CARD READER DRIVER .EVEN ; CDS=177160 ;STATUS AND CONTROL REGISTER CDB1=177162 ;READ CARD COLUMN IN BINARY CDB2=177164 ;READ IN COMPRESSED COLUMN ; CDEST=CD.EST+4 ;ADDR OF DRIVER ERROR STATUS BYTE CDUNN=CD.EST+2 ;ADDR OF UNIT # (FOR NOW ONLY 0) CDBUF=10 ;TCB OFFSET EQUALITY FOR BUFFER ADDR. CDUNI=12 ;TCB OFFSET FOR UNIT # (NOT PRESENTLYUSED) CDTCOD=5 ;OUR TASK NUMBER UNDER PIREX CDCOLC=80. ;COLOUMN COUNT CDCOLD=CDCOLC+CDCOLC ;BYTES PER80 FULL BINARY COL.'S ; ; ERROR CODES PLACED IN CDEST IN TABLE IN PIREX ; NOTE, ERRORS 12&74 ARE 'HARD' ERRORS, ERROR 4 IS 'SOFT' ; ; 0 OPERATION COMPLETED OK ; 74 COLUMN DONE INTERRUPT BFORE PREVIOUS ONE SERVICED ; 12 READ CHECK (COVERS A VARIETY OF SINS) ; 72 ILLEGAL PUNCH COMBINATION ; 4 READER OFF LINE (NOT RETURNED IF SPOOLING) A NUMBER OF CAUSES.. ; 75 HARDWARE IS BUSY, BUT DRIVER IS NOT.(NOW DONE AS IOPS4) ; 76 HARD ERROR !BETWEEN CARDS! , TROUBLE! ; 45 MORE THAN 80 COLUMNS FOUND ON CARD ; 3 ILLEGAL INTERRUPT, OR UNEXPECTED READER-TO-ON-LINE ; .BLOCK 8.+EAESTK*4 ;STACK (WE'RE AT LEVEL 6) .WORD CDS ;FOR PIREX, ADDR CONTROL REGISTER .WORD 0 ;HIGH ORDER PART TCB ADDR. .WORD 0 ;LOW ORDER; SERVES AS IDLE/BUSY ; CD: MOV CD-2,R0 ;TCB ADDR CLRB CDEWT ;CLEAR WAIT FOR ERROR BYTE MOV CDBUF(R0),R1 ;CALLER'S BUFFER ADDR. MOV #CDS,R2 ;ADDR. OF CONTROL REGISTER TST CD-4 ;PDP15 OR PDP 11 REQUEST? BMI 1$ ;BRANCH IF PDP11 ASL R1 ;PDP15 ADDR. *2 WORDS TO BYTES ADD MEMSIZ,R1 ;ADD OUR MEMORY SIZE TO OFFSET ADDR. 1$: MOV #CDCOLC,(R1)+ ;BYTE COUNT IN FIRST WORD OF 2 WORD ; ;HEADER. MOVE POINTER UP 2 BYTES ; ; !!HOOK!! ; FOR BLANK COMPRESSION, LEAVE OUT PLACEMENT OF 120 ; CLR (R1)+ ;CLEAR CHECKSUM WORD. POINT TO FIRST DATA MOV R1,CDBUFI ;SAVE INITIAL POINTER FOR RETRY MOV R1,CDBUFP ;ALL READY TO PLACE DATA IN BUFFER MOV #CDBUFX,CDBUFQ ;LOAD POINTR FOR COLUMN BINARY BUFFER CLRB CDUNN ;THIS PRESENT DRIVER HAS ONLY UNIT #0 CLR (R2)+ ;##132##CLR STATUS, REAL ERRORS STAY UP MOV (R2),R5 ;##132##READ A COLUMN TO CLR COLUMN REDY BIT #135400,-(R2) ;##123##UNIT IN ERROR (NEW BIT PATTERN) BNE 2$ ;TREAT AT 2 MOV #101,(R2) ;SEEMS OK, READ A CARD BR 4$ 2$: INCB CDEWT ;HANG UNTIL READER GOES ON LINE. ; ;WE GET AN INTERRUPT IN THAT CASE. MOV #76,R3 ;DEFAULT ERROR CODE FOR HARD ERROR BIT #14000,(R2) ;CHECK HARD ERROR BITS BNE 3$ ;GOT ONE, GO PUT ERROR CODE OF 76 ; ; HERE USED TO BE IOPS75 HANDLING, TREAT AS IOPS4! ; MOV #4,R3 ;ERROR CODE OF 4 FOR NOT READY TST SPOLSW ;SPOOLING ON? BPL 3$ ;NO, LEAVE FOUR CODE NOT READY CLR R3 ;YES, NOT READY IS NOT ERROR 3$: MOVB R3,CDEST ;PLACE ERROR STATUS MOV #100,(R2) ;ENABLE INTERRUPTS AND WAIT 4$: SEXIT WAITST ; ; ; REWRITE INTERRUPT HANDLER TO OPERATE ENTIRELY AT LEVEL7 ; DURING THE CARD, BECAUSE SYSTEM OVERHEAD DESTROYS LEVEL6. ; RUNNING AT LEVEL6 LEADS TO LOSS OF CARD COLUMNS WHILE SPOOLING. ; AT END OF CARD, LOWER TO LEVEL6 (EVEN LOWER BETTER??) TO DO ; COLUMN VALIDITY CHECKING AND CHECKSUMMING. THIS APPRAOCH ; REQUIRES A 120 WORD BUFFER FOR THE COLUMN BINIARY, AS IT ; MUST BE SAVED UNTIL THE END OF THE CARD. COMPRESSED COLUMN ; WILL BE PLACED INTO THE USER'S BUFFER AT INTERRUPT LEVEL. ; IF THE CARD TURNS OUT TO BE OK, THIS STORED DATA IS OK. ; ; INTERRUPT CODE (EXCEPT END OF CARD) SAVES AND RESTORES R0 ; USING THAT REGISTER !!ONLY!! ; CDINT: TST CD-2 ;DID WE GET TURNED OFF BEQ 70$ ;IF SO GO FINISH UP PUSH R0 ;SAVE R0 ON STACK (ONLY REG. USE ; ;UNLESS END OF CARD) MOV CDS,R0 ;##123##TRIAL FIX FOR IOPS45 TSTB CDEWT ;WAITING FOR ERROR RECOVERY??? BNE 30$ ;TO 30 IF YES BIT #2000,R0 ;##123##TRIAL FOR IOPS45 BNE 76$ ;##123##GOT ONLINE WHEN NOT WANTED!! TST R0 ;##123##SET UP FOR ERROR TEST BMI 50$ ;IF MINUS, ERROR, GO TREAT TSTB R0 ;CHECK COLUMN DONE BIT (7) BMI 40$ ;GOT A COLUMN ASL R0 ;CARD DONE BIT TO AC15 BMI 20$ ;CARD DONE BR 76$ ;NONE OF ABOVE!?!?!? JUST EXIT ; ; ERROR HANDLING ; 50$: CMP CDBUFQ,#CDBUFX+CDCOLD ;IF ALREADY 80 CC, IGNORE ERR., BEQ 21$ ;IS SUPPLY ERROR ON LAST CARD IN HOPPER BIC #173777,R0 ;CLEAR XCPT TIMING ERROR ADD #174012,R0 ;12 HARD ERROR BYTE. BMI 60$ ;BRANCH ON HARD ERROR, BYTE SET UP MOV #74,R0 ;MISSED COLUMN BYTE 62$: MOV #102,CDS ;EJECT REST OF CARD ON MISSED COUMN 60$: MOVB R0,CDEST ;COME TO 60$ ERROR BYTE IN R0.SET IN TABLE MOVB R0,CDEWT ;SET WAITING FOR ERROR BYTE. 76$: MOV #100,CDS ;##124##REARRANGE; CLEAR OUT STATUS REG MOV CDB1,R0 ;##132##CLEAR COLUMN DONE BIT BR 75$ ;##124##REARRANGE; GO EXIT ; ; GET A COLUMN ; 40$: MOV CDBUFQ,R0 ;FULL BINARY COLUMN POINTER CMP #CDBUFX+CDCOLD,R0 ;ALREADY 80? (BR-134) BLE 49$ ;YES ERROR (BR-134) MOV CDB1,(R0)+ ;TO BUFFFER MOV R0,CDBUFQ ;SAVE POINTER MOVB CDB2,@CDBUFP ;COMPRESSED COLUMN FOR BUFFER INC CDBUFP ;MOVE UP POINTER 75$: POP R0 ;RESTORE R0 RTI ;EXIT ; 49$: MOV #45,R0 ;ERROR CODE FOR TOO MANY CC. BR 62$ ;EJECT CARD, REGISTER ERROR ; ; 70$: CLR CDS ;STOP DEVICE CLRB CDEWT ;WE'RE NO LONGER WAITING JSR R0,R.SAVE ;SAVE REG'S TO JOIN SYSTEM CDTCOD ;OUR TASK CODE BR 28$ ;SYSTEM EXIT CODE ; ; WAITING FOR ERROR TO BE FIXED CODE ; 30$: BIT #2000,R0 ;##123##TO ON LINE INTERRUPT?? BEQ 76$ ;##123##NO JUST IGNORE CLR CDS ;##123##MAKE ANY REAL ERRORS REAPPEAR BIT #135400,CDS ;##124##DEVICE STILL!! IN ERROR??? BNE 76$ ;##123##YES, JUST KEEP WAITING ; ; WHEN READER GOES TO ON LINE, AN INTERRRUPT IS GIVEN. WE ASSUME ; THE OPERATOR HAS FIXED THE PROBLEM, AND RETRY THE CARD ; 77$: CLRB CDEST ;CLEAR ERROR BYTE IN TABLE (IF STILLSET)(BR-112) CLRB CDEWT ;CLEAR OUR WAITING FOR ERROR BYTE MOV CDBUFI,CDBUFP ;RESET COMPRESSED COLUMN BUFFER POINTER MOV #CDBUFX,CDBUFQ ;RESET FULL BINARY BUFFER POINTER MOV #101,CDS ;READ A CARD BR 75$ ;EXIT FROM INTERRRUPT ; ; END OF CARD PROCESSING ; 20$: MOVB #74,R0 ;ERROR BYTE FOR MISSED COLUMN CMP CDBUFQ,#CDBUFX+CDCOLD ;BETTER HAVE 80 BNE 60$ ;NO , GO REGISTER COMPLAINT 21$: POP R0 ;NOW WE GO TO SAVE ALL REGISTERS ; ; CODE SNARFERS WATCH IT, R.SAVE EXPECTS R0 POINTING TO CALL+2 ; JSR R0,R.SAVE ;THIS SAVES R0, DON'T SAVE TWICE CDTCOD ;OUR TASK CODE ; ; WE NOW COME DOWN TO LEVEL 6 , CURTESY OF R.SAVE ; MOV #CDBUFX,R5 ;GO THRU COLUMN BINARY BUFFER MOV (R5),R0 ;TO ENSURE LEGAL PUNCHES BIC #170777,R0 ;TEST 1,EOF CARD IF 12,11,0 ALLIN COL. 1 CMP #7000,R0 ;EOF CARD IF EQUAL BEQ 26$ ;CARD OK, CLOSE OUT DEVICE ; ; !!HOOK!! ; ; FOR SPOOLER UPGRADE, TEST FOR ALT-ALT END OF DECK CARD HERE ; AND PLACE -2 IN TOP BYTE OF BUFFER (CDBUFI-3). ; SIMILARLY, THE EOF CARD ABOVE SHOULD PLACE A -1 IN THE SAME ; BYTE, SO THAT THE SPOOLER DOESN'T HAVE TO WORRY ABOUT ; DEVICE PECULAIRITIES!!!!!!!! ; 24$: MOV (R5)+,R0 ;MAIN VERIFICATION LOOP, NEXT COL. MOV R0,R3 ;ANOTHER COPY BIC #170777,R3 ;CHECK IF MORE THAN 1 OF 12,11,0 MOV R3,R1 ;TWO COPIES OF 12,11,0 NEG R1 ;ONLY COMMON BIT ON IS LOWEST OF 12,11,0 BIC R1,R3 ;CLEAR IT! IF MORE THAN 1, R3 LEFT NON0! BNE 29$ ;IF NON0, AN ILLEGAL PUNCH, GO TO ERROR BIT #776,R0 ;ANY 1-8 PUNCHES? BEQ 25$ ;NO, CARD MUST BE LEGAL BIT #1,R0 ;A NINE PUNCH WITH 1-8? (SHOULD ROR,HACKERS) BNE 29$ ;THAT'S ILLEGAL, ERROR OUT CMP #4402,R0 ;IS SPECIFICALLY 12-1-8 ALT MODE BEQ 25$ ;YES OK MOV #402,R1 ;1-8 PUNHES TO R1 BIC R0,R1 ;1 AND 8 ILLEGAL, SEE IF BOTH THERE BEQ 29$ ;IF BOTH CLEARED, AN ERROR BIC #177003,R0 ;KEEP 1-7, TO SEE IF MORE THAN 1 OF THEM MOV R0,R3 ; A COPY NEG R3 ;ONLY COMMON BIT IS LOWEST OF 1-7 BIC R3,R0 ;SO R0 MUST BE CLEARED IF OK BNE 29$ ;MISSED, GO ERROR 25$: CMP #CDBUFX+CDCOLD,R5 ;DONE BGE 24$ ;NOPE 26$: CLR CDS ;CLEAR OUT DEVICE ; ; !!HOOK!! ; ; AT THIS POINT, COLUMN COMPRESSION SHOULD BE DONE ; GO THRU THE USER BUFFER, ALL CONSECUTIVE BLANKS ARE REMOVED ; AND REPLACED BY ONE BYTE, WHICH IS MINUS THE COUNT OF BLANKS ; INCLUDING -1 FOR ONE BLANK. BLANKS AT THE END OF THE CARD ARE ; IGNORED. THE RESULTING COUNT OF BYTES IS PLACED IN THE ; BUFFER HEADER (CDBUFP-4) COUNT IS A BYTE WIDE! ; CLRB CDEST ;SAY OK OPERATION MOV CDBUFI,R5 ;POINT TO START OF DATA MOV R5,R1 ;RUNNING POINTER MOV -4(R5),R4 ;CHECKSUM INCLUDES HEADER MOVB R4,R3 ;MAKE CONTROL COUNT ADD R1,R3 ;GOT CONTROL COUNT 22$: ADD (R1)+,R4 ;ADD INTO CHECKSUM CMP R1,R3 ;DONE? BLT 22$ ;NO IF R1 MOT UP TO R3 MOV R4,-2(R5) ;PLACE CHECKSUM IN HEADER+2 ; ; SYSTEM CALLS, USE AS IS! ; BIS #340,PS ;LOCK OUT INTERRUPTS MOV #1,R1 ;SEND EVENT VARIABLE TO PDP-15 OK! MOV CD-2,R0 ;AND TCB ADDR FOR SEND15 CALL SEND15 28$: BIS #340,PS ;LOCK OUT INTERRUPTS CLR CD-4 ;CLEAR OUT OUR BUSY/IDLE FLAG CLR CD-2 MOV #CD,R3 ;RESCHEDULE OURSELVES IF NECESSARY MOV #CD.LH,R1 JMP DEQU ; ; EXTRA BUNCH OF CODE FOR ILLEGAL PUNCH ERROR ; 29$: MOVB #72,CDEST ;PLACE ILLEGAL PUNCH IN TABLE MOV #100,CDS ;CLEAR DEVICE EXCPT INTERRUPTS MOVB #72,CDEWT ;SAVE WE'RE WAITING FOR ERROR JMP DEQU1 ;RELEASE INTERRUPT ; ;WE'VE CALLED R.SAVE,SO EXIT THRU SYSTEM ; ;EXIT, DEQU1 RESTORES, SCANS ATL, RTI'S. ; ; ; STORAGE ; CDBUFP: .WORD 0 ;POINTER TO BYTE BUFFER CDBUFI: .WORD 0 ;POINT TO BEGINNING OF BYTE BUFFER CDBUFQ: .WORD 0 ;POINT TO FULL BINARY COLUMN BUFFER CDBUFX: .BLOCK 120 ;SAVE FULL COLUMN BINARY CDEWT: .BYTE 0 ;ERROR FLAG. NON0 IF WAITING FOR ERROR FIX CDXX: .BYTE 0 ;EXTRA BYTE TO COME OUT EVEN ; .NLIST .ENDC ; .IFDF $PL .LIST .SBTTL XY11 DRIVER/XY311 DRIVER CONDITIONAL ASSY PARAMETERS .EVEN ; XYCS=172554 ;PLOTTER STATUS REG XYDB=172556 ;PLOTTER DATA BUFFER PLSA=6 ;BUFFER ADDR OFFSET IN TCB PLEST=PL.EST+4 ;POINTER TO ERROR TABLE LOCATION PLUNN=PL.EST+2 ;UNIT NUMBER (NOT NOW USED) ; ; CONDITIONAL ASSEMBLY FOR CHARACTER POSITION. ; ; CHARACTERS ARE 'DRAWN' INSIDE A LOGICAL BOX HAVING 11 HORIZONTAL ; AND 11 VERTICAL POSITIONS. THE CHARACTER TABLE IS SET UP TO ; DEFAULT THAT THE CHARACTER IS CENTERED IN THE BOX ALONG THE ; X-AXIS. (THE BOX INCLUDES THE INTERCHARACTER SPACING.) IT MIGHT ; BE DESIRABLE TO MAKE THE CHARACTER EITHER RIGHT OR LEFT JUSTIFIED ; IN THE BOX. TO DO SO DEFINE $RIGHT=0 OR $LEFT=0. ; ; DEFAULT SETUP ; .IFNDF $SPACE ;##149## ONLY WITHOUT EXPERIMNT .IFNDF $RIGHT .IFNDF $LEFT STEPIN=12 ;INITIALIZE POSITION (X) FOR FIRST CHAR STEPOU=0 ;POSITION PEN AFTER LAST CHAR .ENDC .ENDC ; ; RIGHT ; .IFDF $RIGHT STEPIN=11 STEPOU=1 .ENDC ; ; LEFT ; .IFDF $LEFT STEPIN=13 STEPOU=-1 .ENDC CHRWID=12 ;##149##EQUATE FOR WIDTH .ENDC ;##149## ; .IFDF $SPACE ;##149## GREATER INTERCHAR SPACE .IFNDF $RIGHT ;##149## .IFNDF $LEFT ;##149## STEPIN=14 ;##149## STEPOU=0 ;##149## .ENDC ;##149## .ENDC ;##149## .IFDF $RIGHT ;##149## STEPIN=13 ;##149## STEPOU=1 ;##149## .ENDC ;##149## .IFDF $LEFT ;##149## STEPIN=15 ;##149## STEPOU=-1 ;##149## .ENDC ;##149## CHRWID=14 ;##149## CHARACTER WIDTH .ENDC ;##149## ; ; ; ; THE CALCOMP PLTTER DOES NOT HAVE AN OFFLINE SWITCH. THIS ; LEADS TO DIFFICULTY IN STOPPING THE PLOTTER TO ; REFIL PEN, TAKE OFF PLOTS ETC. BIT 2 SWITCH OF THE PDP-11 ; CONSOLE SWITCHES IS TO BE USED AS THE OFFLINE ; SWITCH FOR THE CALCOMP. IF YOU DO !!NOT!! WISH THIS FEATURE ; DEFINE $NOSW=0. ; NOTE, FOR $PL311, THIS IS AUTOMATICALLY DISABLED, DON'T DEFINE!! ; ; ; CONDITIONAL ASSEMBLY FOR XY11 OR XY311 PLOTTER INTERFACE ; ; $PL311 IF DEFINED WILL GENERATE THE CONTROL BYTES REQUIRED ; FOR CALCOMP'S 936.IF UNDEFINED,THE CONTROL BYTES FOR CALCOMP'S ; 500 SERIES ARE GENERATED.IF $PL311 IS DEFINED THEN THE ; UNITS FOR THE PLOTTER STEP SIZE SHOULD BE ; SPECIFIED.$UNITS DEFINED GENERATES A METRIC PLOTTER,UNDEFINED ; GIVES ONE IN INCHES. ; ; ; .IFDF $PL311 .RADIX 10 .IFDF $UNITS PENDIS=1520/5 ;PEN DISPL.=1.52 CM./0.05 MM. .ENDC .IFNDF $UNITS PENDIS=600/2 ;PEN DISPL.=0.6 INCHES/0.002 INCHES .ENDC .RADIX 8 PY=0 ;+Y PYPX=1 ;+Y,+X PX=2 ; +X NYPX=3 ;-Y,+X NY=4 ;-Y NYNX=5 ;-Y,-X NX=6 ; -X PYNX=7 ;+Y,-X ESFM=10 ;ENTER SPECIAL FUNCTION MODE PENUP=11 ;PEN UP PENPUL=11 ;PEN SELECT PULSE PENDWN=12 ;PEN DOWN PENNOP=13 ;NO OPERATION ;14,15 ARE NOT CURRENTLY USED LSFM=16 ;LEAVE SPECIAL FUNCTION MODE ;17 IS NOT USED .ENDC .IFNDF $PL311 PENUP=40 ;XY11 CODE PENDWN=20 .ENDC ; ; ; ; .SBTTL XY11 DRIVER/XY311 DRIVER ; ; ; ; THE LOWEST LEVEL SUBROUTINE 'PLOT' ISSUES DATA TO PLOTTER ; DATA BUFFER, RELEASES CONTROL, AND IS WAKEN UP BY INTERRUPT. ; THIS IS ALL WELL AND GOOD, BUT IT LEADS TO SAVE AND RESTORE ; QUESTIONS ABOUT REGISTERS AND STACK. ; ; THEREFORE, SINCE THIS THING HAS TO COME UP IN A SUPER HURRY, ; SUBROUTINE CALLS ARE MADE BY SIMULATING PDP-15 JMS, THE RETURN ; ADDRESSS IS STORED IN CORE. SIMILARLY, NO REGISTERS ARE ; ASSUMED TO LIVE THRU A CALL TO A LOWER LEVEL SUBROUTINE. ; ; LEVEL 3, THE LOWEST LEVEL, CALLED BY LEVEL 2 ; ; THE ONLY ROUTINE IS 'PLOT' ISSUES HARDWARE REQUESTS TO XY ; ; LEVEL 2, CAKLLED BY LEVEL 1 ; ; ROUTINE 'APPR' DOES LINE APPROXIMATION ; ROUTINE 'PEN' DOES PEN UP AND DOWN MOVEMENTS ; ; LEVEL 1.5, CALLS LEVEL 3 AND THEN CALLS LEVEL 1 TO RETURN TO PDP-15 ; ; ROUTINE 'SELPEN' SELECTS THE PEN NUMBER WHICH IS TO BE ACTIVE ; CALLS 'PLOT' TO ISSUE CONTOL BYTES TO XY311 ; CALLS 'LINE' TO POSITION NEW PEN OVER CURRENT COORDINATE(ORDINATE) ; ; LEVEL 1 ; ; ROUTINE 'LINE' DOES LINES AND POSITIONING ; CALLS 'PEN' AND 'APPR' ; ROUTINE 'CHAR' DOES CHARACTERS ; CALLS 'PEN' AND 'APPR' ; ROUTINE 'CLOS' PICKS UP THE PEN IRREGARDLESS OF PRESENT ; CALLS 'PEN' ; ROUTINE 'INIT' LIFTS PEN, AND OBTAINS CHARACTER DECRIPTION ; CALLS 'PEN' ; ; BUFFER FORMAT (MODELED AFTER LP TO SPEED SPOOLER CODING) ; ; WORD 1 MODE,,BYTE COUNT ; WORD 2 CHECKSUM (NOT PRESENTLY IMPLEMENTED) ; WORD 3-N DATA ; ; MODE VALUES ; ; 1 LINE DATA ; 2 CHARACTER DATA, ASCII CHAR'S TWO PER WORD. ; 3 INIT; LIFT PEN, SET UP CHAR DATA ; 4 PEN SELECT #1,2 OR 3 IF XY311 INSTALLED ; -1 END OF FILE, MAINLY FOR SPOOLER, PICK UP PEN ; ; NOTE SPOOLER IGNORES HIGH HALF OF FIRST WORD. ; ; ; .BLOCK 8.+EAESTK*4 ;(115 SCR)BRING STACK UP TO DATE .WORD XYCS ;POINTER TO STATUS REG. .WORD 0 ;2 WORDS FOR TCB .WORD 0 ;LOW ONE ALSO IDLE/BUSY 0=IDLE ; ; PL: CLRB XYXIT ;FLAG NON-INTERRUPT EXIT! MOV PL-2,R0 ;TCB POINTER MOV PLSA+2(R0),R1 ;BUFFER POINTER TST PLSA(R0) ;PDP-11 OR PDP-15 REQUEST BMI 1$ ;DON'T RELOCATE FOR PDP-11 REQ ASL R1 ;WORD ADDR TO BYTE ADD MEMSIZ,R1 ;PLUS OFFSET FOR PDP-11 MEMORY 1$: CLR XYCNT ;CLEAR OUT HIGH HALF MOVB (R1)+,XYCNT ;BYTE COUNT FOR LOOP CONTROL MOVB (R1)+,R2 ;WHICH MODE FOR BUFFER ADD #2,R1 ;POINT R1 TO DATA (BR-134) .IFNDF $NOSW ;##124##IF $NOSW, DISABLE ALL SWTICH INTERACT BIT #140000,SPOLSW ;SPOOLING? BEQ 2$ BICB #10,MASK ;##137##CLEAR OEF WAIT BIT BISB PLERWT,MASK ;##137##SET IF LAST TCB A CLOSE .ENDC 2$: CLRB PLERWT ;##137##CLEAR CLOSE FLAG MOV R1,XYPNT ;SAVE POINTER DEC R2 ;CHECK FOR ALINE BEQ LINE ;IT IS DEC R2 ;CHECK FOR CHARACTER STRING BEQ CHAR ;YES DEC R2 ;CHECK FOR INIT BEQ INIT ;YUP, IF NOT IT, FALL THRU TO CLOS .IFDF $PL311 DEC R2 ;CHECK FOR PEN # SELECTION BNE CLOS ;IF NON ZERO CLOSE JMP SELPEN ;MODE 4,SELECT A PEN CLOS: CLR R0 ;PLUS R0 SAYS PEN UP .IFNDF $NOSW MOVB #10,PLERWT ;##137##SET CLOSE FLAG FOR NEXT TCB .ENDC MOV #CLOS1,PEN ;SET RETURN FOR JMP PEN+2 ;JMS CLOS1: MOV #1,@XYPNT ;FORCE SELECTION OF PEN #1 JMP SELPEN ;RETURNS VIA LINE TO CLOSRT ; ; .ENDC .IFNDF $PL311 CLOS: CLR R0 ;PLUS R0 SAYS PEN UP(R1 NON-0 ; ;ALREADY TO FORCE ACTION) .IFNDF $NOSW MOVB #10,PLERWT ;##137##SET CLOSE FLAG FOR NEXT TCB .ENDC MOV #CLOSRT,PEN ;JMS PEN JMP PEN+2 .ENDC CLOSRT: BIS #340,PS ;TO LEVEL 7 WHILE WE CLOSE OUT MOV PL-2,R0 ;TCB ADR REQUIRED IN R0 MOV #1,R1 ;FOLLOWING IS VERY TRICKY CALL SEND15 PLHMM: BIS #340,PS ;REJOIN HERE ON PHANTOM TURN OFF CLR PL-2 CLR PL-4 MOV #PL,R3 MOV #PL.LH,R1 JMP DEQU ;GONE (WARNING, THIS ASSUMES WE ; ;ARE EXITING FROM AN INTRRUPT, AND ; ;MUST SOMETIME DO AN RTI ; ;************************************************************* ; LEVEL 1 CODE ;************************************************************** ; ; LINE: ASR XYCNT ;DIVIDE BY FOUR BYTE COUNT ASR XYCNT ;SO WORD PAIR COUNT LINLOO: MOV @XYPNT,R0 ;DO ANY PEN ACTION NEEDED ; ;UP-DOWN XOR'ED IN TOP BIT OF DX ADD #40000,R0 ;MAKE PLUS FOR UP, MINUS FOR DOWN CLR R1 ;R1=0 SAYS NO ACTION IF PEN ALREADY OK MOV #LINRT1,PEN ;JMS PEN JMP PEN+2 LINRT1: MOV XYPNT,R2 ;BRING POINTER TO GET DY AND DX MOV (R2)+,R0 ;DX ADD UPDWN,R0 ;CORRECT DATA VALUE FOR XOR'ED PEN!! MOV (R2)+,R1 ;DY MOV R2,XYPNT ;SAVE UPDATED POINTER MOV #LINRT2,APPR ;JMS APPROX JMP APPR+2 LINRT2: DEC XYCNT ;DONE YET BGT LINLOO ;NO BR CLOSRT ;IN COMMON WITH CLOSE RETURN TO PDP15 ; ; ; ; ; ; SOME LOCAL STORAGE ; XYPNT: .WORD 0 ;POINTER TO DATA COMING TO US XYCNT: .WORD 0 ;COUNT OF DATA ITEMS XYXIT: .BYTE 0 ;0 IF 'CAL' EXIT, NON0 IF INTERRUPT EXIT STROKC: .BYTE 0 ;STROK COUNT FOR CHAR'S STROKP: .WORD 0 ;POINTER TO STROKE BYTE ; ; DATA TO DECRIBE SIZE OF UNIT CHARACTER. WE HAVE STORED CHAR'S ; ON AN 11X11 GRID. MUST DESCRIBE DX AND DY OF GRID UNIT IN X ; DIRECTION, AND DX AND DY OF GRID UNIT IN Y DIRECTION. THE PDP-15 ; CALCULATES THESE, AND SENDS WITH 'INIT' CALL. EACH QUANTITY ; MUST BE DOUBLE PRECISION TO PREVENT US LOSING TRACK OF THE ; PEN POSITION. THE ORDER OF THESE VARIABLES MUST MATCH ; THAT IN THE PDP-15! ; ; XDXH: .WORD 2 ;HIGH HALF XDXL: .WORD 0 ;LOW HALF OF DX FOR X GRID UNIT STEP YDYH: .WORD 2 ;Y GRID, Y DIRECTION, HIGH HALF YDYL: .WORD 0 ;LOW HALF XDYH: .WORD 0 ;HIGH HALF XDYL: .WORD 0 ;DY FOR X GRID, NEEDED IF CHAR'S TIPPED YDXH: .WORD 0 YDXL: .WORD 0 ; XLOCH: .WORD 0 ;CHAR'S, HIGH HALF X DISPLACEMENT XLOCL: .WORD 100000 ;OF TOTAL STRING.LOW HALF YLOCH: .WORD 0 ;SAME FOR Y YLOCL: .WORD 100000 ; XSTEP: .WORD 0 ;INTEGER GRID UNIT STEP X,Y YSTEP: .WORD 0 ;WE ARE NOW AT ; INIT: MOV #XDXH,R2 ;POINTER TO PLACE 8 WORDS MOV #10,R3 ;COUNT FOR LOOP CONTROL 1$: MOV (R1)+,(R2)+ ;MOVE FROM CALLER BUFFER TO OUR STORE DEC R3 ;CONTRO COUNT BGT 1$ ;IF STILL >0, KEEP GOING ; ; NOW FORCE THE PEN UP ; CLR R0 ;THIS SAYS UP, R1 NON0 TO FORCE .IFDF $PL311 TST (R1) ;ARE WE A REAL INIT, OR JUST A SET CHAR? BEQ CLOSRT ;0 JUST A SET CHAR, DON'T CHANGE PEN MOV #INITR1,PEN ;RETURN ADR FOR JMP PEN+2 ;JMS INITR1: MOV #1,@XYPNT ;FORCE SELECTION OF PEN #1 AT INIT JMP SELPEN ;RETURNS VIA LINE TO CLOSRT .ENDC .IFNDF $PL311 MOV #INITR,PEN ;JMS PEN, HERE IS OUR RETURN JMP PEN+2 ;GO THERE INITR: BR CLOSRT ;THAT'S ALL, GO TO COMMON FINISH UP .ENDC ; ; ONCE PER CHARACTER STRING CODE ; CHAR: CLR XLOCH ;HIGH HALF OF X LOC REL TO START CLR YLOCH ;AND Y;OF THE STRING MOV #100000,XLOCL ;THIS IS TO HELP UP ROUND RIGHT MOV #100000,YLOCL ;AND Y; WHEN MAKING DX AND DY MOV #CHARR3,APPR ;WE OWN APPROX. LEAVE OUR RETURN ADDR. CLR YSTEP ;ACCUMULATED Y STEPS PRIOR TO 'THIS' CHAR MOV #STEPIN,XSTEP ;POSITION CHARACTERS CENTER,RIGHT,OR LEFT ; ;'FALSE' POSITION GENERATED IS CANCLLD ; ;AT EXIT. 12 FOR CENTER IS CANCELLED AT ; ;LOCATION CHARL1 IN LOOP. ; ; NOW LOOP PER EACH CHAR ; CHARL1: CLR R0 ;RAISE THE PEN (ONLY IF NEEDED) CLR R1 ;R1=0 SAY CONDITIONAL RAISE MOV #CHARR1,PEN ;JMS PEN, HERE IS REUTNR ADDR. JMP PEN+2 ;GO CHARR1: SUB #CHRWID,XSTEP ;##149##!!TOUGH!!WE ARE NOW IN THE NEXT CHAR ; ;SO THE IN CHAR GRID MEMORY HAS TO BE ; ;MOVED BY THE INTERCHARACTER SPACING. ; MOVB @XYPNT,R0 ;GET CHARACTER FOR TABLE LOOK UP ON STROKE INC XYPNT ;MOVE POINTER TO NEXT SUB #40,R0 ;NRMALIZE 40-137 RANGE TO 0-77 MOVB TABPNT(R0),R4 ;RELATIVE POINTER TO THIS CHAR MOVB TABPNT+1(R0),R5 ;AND RELATIVE POINTER TO NEXT CHAR ; ; WHILE WE ARE HERE. THE RELATIVE POINTERS ARE: ; ADDR OF FIRST STROKE OF CHAR MINUS TABLE BEGINNING ADDR ; MINUS 8 TIMES (THE CHARACTER VALUE MINUS 40 (OCTAL)) ; ; ALL THIS JAZZ IS SO THAT WE CAN STORE THE ADDR. IN ONE BYTE. ; SUB R4,R5 ;DIFFERENCE IN POINTERS IS CONTROL ADD #10,R5 ;COUNT FOR # OF STROKES PER CHAR. BNE 1$ ;SKIP IF REAL CHAR (I.E. SOME STROKES) JMP CHARR4 ;NOPE, GO END OF LOOP 1$: MOVB R5,STROKC ;SAVE STROKE CONTROL COUNT ASL R0 ;R0*8 TO CALCULATE REAL STROKE ADDR. ASL R0 ;FROM RELATIVE POINTER ASL R0 ADD R0,R4 ;RELATIVE+8*(CHAR-32) ADD #TABCHR,R4 ;+ADDR OF TOP OF TABLE MOV R4,STROKP ;WE NEED REG'S, SAVE POINTER BR CHARR2 ;WATCH IT! TOP OF LOOP ALWAYS TRIES TO ; ;PUT THE PEN DOWN. FOR THE FIRST STROKE ; ;THE PEN IS ALWAYS UP, SO WE WILL ENTER ; ;THE LOOP A LITTLE FURTHER DOWN, SINCE ; ;THE PEN IS NOW KNOWN TO BE UP ; ; ; PER STROKE LOOP ; CHARL2: MOV UPDWN,R0 ;GET STATE OF PEN MOVB @STROKP,R1 ;CHECK FOR SPECIAL STROKE -1 ; ;WHICH IS A PEN CONTROL STROKE CMP #-1,R1 ;-1 SAYS PUT PEN UP FOR NEXT STROKE BNE 1$ ;NOT IT, GO DO OTHER WORK INC STROKP ;GOT A -1, MOVE POINTER+COUNT DECB STROKC ;TO A REAL MOVE CONTROLLER BR 2$ ;GO GET IN THE PEN CHANGING ACTION 1$: TST R0 ;REGULAR CHECK; IS PEN UP? BMI CHARR2 ;ON MINUS NO; GO JOIN LOOP 2$: COM R0 ;BOTH GUYS WANT ONE THING, INVERT PEN! MOV #CHARR2,PEN ;JMS PEN, HERE IS OUR RETURN JMP PEN+2 ; ; COMPUTE GRID STEP CONTROL FROM STROKE BYTE ; CHARR2: MOVB @STROKP,R1 ;GET THE STROKE BYTE INC STROKP ;MOVE POINTER TO NEXT MOV R1,R0 ;MAKE A COPY FOR X CHANGE ASR R0 ;X IS IN HIGH 4 BITS OF BYTE ASR R0 ;SO RIGHT JUSTIFY ASR R0 ASR R0 BIC #177760,R0 ;STRIP GARBAGE FROM BOTH CO-ORD. BIC #177760,R1 MOV R0,R4 ;KEEP A COPY, SINCE WE NEED DX,DY MOV R1,R5 ;COMPUTED FROM XSTEP, YSTEP SUB XSTEP,R4 ;DX IN GRID STEPS SUB YSTEP,R5 ;DY IN GRID STEPS MOV R0,XSTEP ;SAVE PRESENT FOR NEXT TIME AROUND MOV R1,YSTEP ; ; NOW BRING UP THE RUNNING TOTALS OF WHERE ARE WE ; MOV XLOCH,R0 ;HIGH HALVES MOV YLOCH,R1 MOV XLOCL,R2 ;LOW HALVES MOV YLOCL,R3 ; ;NOW HERE IS DOUBLE PRECISION GRID CALCULATION ; TST R4 ;+,0,-? BEQ 10$ ;0, NO CHANGE OF X GRID BMI 4$ ;-,SUBTRACK GRID UNIT STEPS FROM TOTALS 1$: ADD XDXL,R2 ;+, ADD IN GRID UNIT STEPS, LOW 1/2 X ADC R0 ;IF CARRY, ADD TO HIGH HALF ADD XDXH,R0 ;AND HIGH HALF FOR UNIT STEP ADD XDYL,R3 ;Y DIRECTION OF UNIT X STEP ADC R1 ;CARRY TO HIGH HALF ADD XDYH,R1 ;HIGH HALF DEC R4 ;DECREMENT CONTROL COUNT BGT 1$ ; IF >0, NOT DONE YET BR 10$ ;GO DO Y UNIT STEPS 4$: SUB XDXL,R2 ;SUBTRACT SINCE MINUS X UNIT STEPS SBC R0 SUB XDXH,R0 SUB XDYL,R3 SBC R1 SUB XDYH,R1 INC R4 BLT 4$ ; ; Y UNIT STEP ; 10$: TST R5 ;+,0,-? BEQ 20$ ;0, NO Y STEPS TO DO BMI 14$ ;-, SUBTRACT 11$: ADD YDXL,R2 ;+, ADD X COMPONENT Y STEP TO TATOL ADC R0 ;CARRY TO HIGH HALF ADD YDXH,R0 ;HIGH HALF X COMPONENT ADD YDYL,R3 ;Y COMPONENT Y STEP ADC R1 ADD YDYH,R1 ;Y COMPONENT Y STEP, HIGH HALF DEC R5 ;COUNT DOWN ON UNIT STEPS BGT 11$ ;NOT DONE YET BR 20$ ;DONE 14$: SUB YDXL,R2 ;-,JUST SUBTRACT INSTEAD OF ADD SBC R0 SUB YDXH,R0 SUB YDYL,R3 SBC R1 SUB YDYH,R1 INC R5 BLT 14$ ; ; WHEW, HAVE UPDATED POSITION, NOW SAVE, AND CALCULATE DX,DY ; 20$: MOV R2,XLOCL ;SAVE LOW HALVES MOV R3,YLOCL MOV R0,R2 ;SAVE COPY OF HIGH, SINCE WE SUBTRACT MOV R1,R3 ;ON THE OTHER COPY SUB XLOCH,R0 ;THIS IS DX FOR APPROXIMATOR SUB YLOCH,R1 ;AND DY MOV R2,XLOCH ;SAVE PRESENT VALUE FOR NEXT TIME MOV R3,YLOCH JMP APPR+2 ;CALL LINE APPROIMATOR ; CHARR3: DECB STROKC ;ANY MORE STROKES PER CHAR BGT CHARL2 ;YES, GO DO CHARR4: DEC XYCNT ;AND MORE CHARACTERS BGT 1$ ;DEFINITELY YES, GO TO CHARL1 BLT 2$ ;DEFINITELY NO, GO FINISH ; ; ;SORT OF, WE INVENT A CHARACTER ; ;SO THE THE PEN IS FORCED TO THE LOWER ; ;RIGHT OF THE LAST CHARACTER ; ;140 IS THE CHARACTER; IT HAS ONE STROKE ; ;TO 0,0!! MOV #MAGIC,XYPNT ;MOVE POINTER TO 140 TO INPUT CHAR GETTER ADD #STEPOU,XSTEP ;CANCELL LEFT-RIGHT FUDGE AT BEGINNING ; ;OF CHARCTER STRING 1$: JMP CHARL1 ;AND GO DO IT. SORRY ABOUT THAT. 2$: JMP CLOSRT ;CLOSE UP OPERATION ; .IFDF $PL311 ; ;************************************************************** ; LEVEL 1.5 CODE ;************************************************************** ; ; ; SELPEN ROUTINE ; ; USED TO ACTIVATE THE PEN NUMBER CONTAINED IN THE ; FIRST DATA WORD OF THE TCB ; ; LOCAL STORAGE ; CURPEN: .WORD 1 ;THE NUMBER OF THE CURRENTLY ACTIVE PEN PENCT: .WORD 0 ;LOOPN CONTROL FOR CONTROL BYTES PEN SELCT. ;NOW FOLLOWS A TABLE OF 5 STEP VALUES ONE OF THESE MUST BE ISSUED EACH TIME ;A PEN SELECTION IS MADE TO KEEP THE ACRIVE PEN OVER THE CURRENT COORDINATE. .WORD -2*PENDIS .WORD -1*PENDIS STEPS: .WORD +0*PENDIS .WORD +1*PENDIS .WORD +2*PENDIS ; ; SELPEN: CLR R0 ;MOVE UP PEN CLR R1 ;ONLY IF NOT ALREADY UP MOV #SELP1,PEN ;JMS TO PEN JMP PEN+2 SELP1: MOV XYPNT,R3 ;TCB ADDRESS OF THE PEN NUMBER ; ;PERFORM A RANGE TEST ON PEN #; ; IS # < OR = 3? ; IS # > OR = 1? ; SUB #3,(R3) ;TOO LARGE? BGT 1$ ;BRANCH IF # IS >3,WE WILL FORCE #=1 ADD #2,(R3) ;TOO SMALL? BGE 2$ ;BRANCH IF # IS>0,IT'S OK 1$: CLR (R3) ;PREPARE FOR #1 FORCE 2$: ADD #1,(R3) ;RESET TO ORIGINAL OR AC- ; ;CEPTABLE VALUE MOV CURPEN,R2 ;PEN NUMBER UNTIL NOW MOV (R3),CURPEN ;UPDATE CURRENT PEN NUMBER ; ; NOW BUILD AN XY INCREMENT BUFFER TO ENSURE THAT SELECTED PEN ; STAYS ON STATION ; SUB (R3),R2 ;PEN NUMBER "DISPLACEMENT" ASL R2 ;USE AS AN ADDRESS INDEX CLR (R3)+ ;SET # OF IX=0 AND FLAG FOR PEN UP MOV STEPS(R2),(R3) ;INSERT # OF IY INCREMENTS REQUIRED MOV #4,XYCNT ;BYTE COUNT FOR ONE XY PAIR ; ; MAKE THE SELECTED PEN ACTIVE BY CALLS TO PLOT ; MOV CURPEN,PENCT ;PEN NUMBER GIVES NUMBER OF LOOPS MOV #ESFM,R0 ;ENTER SPECIAL FN MODE MOV #SLPN1,PLOT JMP PLOT+2 SLPN1: MOV #PENPUL,R0 ;PEN PULSE IS NEXT CTL BYTE MOV #SLPN2,PLOT JMP PLOT+2 SLPN2: DEC PENCT ;1,2 OR 3 PULSES ONLY TO BE SENT BNE SLPN1 ;PULSE AGAIN MOV #LSFM,R0 ;PEN IS NOW SELECTED,LEAVE SPECIAL FN MODE MOV #SLPN3,PLOT JMP PLOT+2 ; ; SELECTED PEN IS NOW ACTIVE AND MUST BE POSITIONED. ; AT ADR INDEXED BY TCB DATA (XYPNT) TO DO THIS. ; EXIT FROM "LINE" WILL BE TO PDP-15 ; SLPN3: JMP LINE ; ; .ENDC ; ; ; ;************************************************************** ; LEVEL 2 CODE ;************************************************************** ; ; ; ; ; ; ; PEN SUBROUTINE ; ; CALLING SEQUENCE ARGUMENTS ; ; PEN MUST CONTAIN RETURN ADDR FOR JMP INDIRECT ; R0 IS + FOR PEN UP AND - FOR PEN DOWN ; R1 IS NON0 IF PEN ACTION ALWAYS TO TAKE PLACE ; R1 IS 0 IF PEN MOVED ONLY WHEN NEEDED ; ; LOCAL STORAGE ; UPDWN: .WORD 0 ;0 WHEN PEN NOW UP, 100000 WHEN DOWN ; PEN: .WORD 0 ;PLACE ADDR HERE TST R1 ;CONDITIONAL MOVE? BNE 1$ ;GO TO 1$ ON NO ADD UPDWN,R0 ;IS REQUEST SAME AS IT ALREADY IS BPL PENRET ;YES, JUST EXIT ADD UPDWN,R0 ;RESTORE R0 TO ORIGINAL 1$: BIC #77777,R0 ;KEEP ONLY SIGN BIT MOV R0,UPDWN ;SAVE THAT AS STATUS ADD #PENUP,R0 ;DEFAULT ON R0=0, UP CODE FOR XY BPL 2$ ;IF POSITIVE, ALLL SET MOV #PENDWN,R0 ;DOWN CODE 2$: MOV #PENRET,PLOT ;JMS PLOT, BYTE IN R0 JMP PLOT+2 PENRET: JMP @PEN ;RETURN TO CALLER ; ; ; LINE APPROXIMATION ROUTINE ; ; DOES ALL X AND Y MOVEMENTS, BUT NO PEN MOVEMENT ; ; CALL WITH RETURN ADDR IN APPR ; CALL WITH DX IN R0 ; CALL WITH DY IN R1 ; ; ; DX AND DY IN INTEGER PLOTTER UNITS. ; LOCAL STORAGE ; TOTAL: .WORD 0 ;'AC' FOR APPROXIMATION CALCULATION COUNT: .WORD -1 ;CONTROL COUNT OF NUMBER OF STEPS ; ;##123##ALSO USED AS DOING LINE SWITCH, SO IT ; ;##123##MUST REMAIN - FOR NON-LINES PLUS: .WORD 0 ;ADD IN ON DIAGONAL MOVE MINUS: .WORD 0 ;AND ADD ON ORTHOGONAL MINUSD: .BYTE 0 ;PLOTTER CONTROL BYTE PLUSD: .BYTE 0 ;PLOTTER CONTROL BYTE ; ; APPR: .WORD 0 MOV #APPRET,PLOT ;RETURN FROM PLOT FOR WHOLE LOOP .IFNDF $PL311 MOV #5,R5 ;DEFAULT DIAGONAL LINE +X,+Y TST R1 ;IS DY POSITIVE BPL 1$ ;IF SO NO ACTION NEG R1 ;MAKE POSITIVE ADD #4,R5 ;MAKE CONTROL BYTE -Y 1$: TST R0 ;IS DX POSITIVE BPL 2$ ; YUP, ALREADY OK NEG R0 ;NOW POSITIVE INC R5 ;CONTROL BYTE REMEMBER -X 2$: MOV R5,R4 ;ANOTHER COPY CONTRO BYTE CMP R0,R1 ;X OR Y BIGGER BMI 3$ MOV R0,COUNT ;X BIGGER, IT GIVES STEP COUNT BIC #14,R4 ;ORTHOGONAL CONTROL BYTE .ENDC .IFDF $PL311 MOV R0,R2 ;SAVE SIGN OF DX MOV R1,R3 ;SAVE SIGN OF DY MOV #PYPX,R5 ;DEFAULT DIAG. +X,+Y CTL BYTE TST R1 ;DY +VE? BPL 1$ ;IF SO,NO ACTION NEG R1 ;MAKE +VE MOV #NYPX,R5 ;MAKE CTL BYTE +X,-Y TST R0 ;DX +VE? BPL 2$ ;IF SO,NO ACTION NEG R0 ;MAKE +VE MOV #NYNX,R5 ;MAKE CTL BYTE-X,-Y 2$: CMP R0,R1 ;X OR Y BIGGEST? BMI 3$ ;BRANCH IF Y MOV R0,COUNT ;X DETERMINES STEP COUNT MOV #PX,R4 ;ASSUME ORTHOG.CTL BYTE IS +X TST R2 ;IS DX +VE? BPL 5$ ;IF SO NO ACTION MOV #NX,R4 ;CTL BYTE FOR -VE DX .ENDC 5$: ASL R0 ;*2 FOR LOOP APPROX ASL R1 MOV R1,MINUS SUB R1,R0 NEG R0 MOV R0,PLUS BR 4$ ;REJOIN OTHER LINE .IFNDF $PL311 3$: MOV R1,COUNT ;Y BIGGER, STEP COUNT BIC #3,R4 ;ORTHOG CONTROL Y DIRECTION .ENDC .IFDF $PL311 1$: TST R0 ;DX IS +VE ASSUMED BPL 2$ ;IF SO NO ACTION NEG R0 ;MAKE DX +VE MOV #PYNX,R5 ;MAKE CTL BYTE -X,+Y BR 2$ ;NOW CHECK FOR ORTHOG. STEPS ; ; ; 3$: MOV R1,COUNT ;Y IS BIGGER,GIVES STEP COUNT MOV #PY,R4 ;ASSUME A +DY CTL BYTE(KEEP INST FMT SAME TST R3 ;IS DY +VE? BPL 6$ ;IF SO NO CHANGE MOV #NY,R4 ;MAKE CTL BYTE -Y .ENDC 6$: ASL R0 ASL R1 MOV R0,MINUS SUB R0,R1 NEG R1 MOV R1,PLUS 4$: MOVB R5,PLUSD ;SAVE DIAG CONTROL BYTE MOVB R4,MINUSD ;ORTHOG ADD R1,R0 ;OBTAIN STARTING TOTAL ASR R0 MOV R0,TOTAL ; ; APPROXIMATIONS LOOP ; APPRET: DEC COUNT ;ANY MORE STEPS TO DO BMI 2$ ;THIS ALSO PICKS UP ZERO LENGTHLINE TST TOTAL ;MINUS OR PLUS BMI 1$ ;'ADD' OR 'SUBTRACT' DEPENDING ADD PLUS,TOTAL MOVB PLUSD,R0 ;CONTROL BYTE JMP PLOT+2 ;ADDR ALREADY IN PLOT, GO DO IT 1$: ADD MINUS,TOTAL MOVB MINUSD,R0 JMP PLOT+2 2$: JMP @APPR ;DONE, RETURN TO CALLER ; ;************************************************************** ; LEVEL 3 CODE ;************************************************************** ; ; PLOT ROUTINE, DO ACTUAL HARDWARE PUSH, WAIT FOR INTRRUPT ; ; CALLING SEQUENCE, PLACE RETURN ADDR IN PLOT ; PLACE BYTE FOR XY IN R0 ; BYTE XYXIT IS ZERO FOR 'CAL' EXIT, NON0 FOR INTERRUPT EXIT ; ; LOCAL STORAGE ; ; PLOT: .WORD 0 .IFNDF $NOSW ;##138## REARRANGE CONDITIONALS BITB MASK,SW ;##137##TEST FOR OFFLINE,EOF WAIT BNE PLCHK1 ;##123## .ENDC ;##123## .IFDF $PL311 BIT #40,XYCS ;PL311 HAS REAL OFF LINE, USE THAT!! BNE PLCHK1 ;##123## .ENDC PLOTGO: MOVB R0,XYDB ;CONTROL BYTE TO DEVICE BISB #100,XYCS ;ENABLE INTERRUPTS PLEXIT: TSTB XYXIT ;FIGURE OUT WHICH KIND OF EXIT BLE 1$ ;BRANCH ON WAIT OR CLOCK RETURN JMP DEQU1 ;RESTORE REG.'S AND RTI 1$: BNE 2$ ;BRANCH ON CLOCK RETURN SEXIT WAITST ;WAIT FOR FIRST INTERRUPT 2$: RTS PC ;CLOCK CALLED HERE AS SUBROUTINE ; ; ; COME BACK FROM INTERRUPT ; ; PLINT: DEC COUNT ;##123##SPEED LOOP FOR LINES BMI PLINT1 ;##123##ISN'T A LINE, OR LINE DONE .IFDF $PL311 ;##123## OFF LINE TEST BIT #40,XYCS ;##123## PL311 CHECK STATUS REG. BNE PLINT1 ;##123##OFF LINE;ALL FUNNIES REJOIN .ENDC ;##123##MAIN LOOP, GET RESORTED LATER .IFNDF $PL311 ;##123##REGULAR PLOTTER USES CONSOLE .IFNDF $NOSW ;##123##SWITCHES UNLESS DEFINED OUT BIT #4,SW ;##123##BIT IS SAME AS IN SPOOLER STATUS BNE PLINT1 ;##123##WORD .ENDC ;##123## .ENDC ;##123## TST PL-2 ;##123## DID WE GET TURNED OFF BEQ PLINT1 ;##123##YUP TST TOTAL ;##123##DO LINE APPROX BPL 1$ ;##124##MAKE ORTHOGONAL TAKE SHORTED PATH ADD MINUS,TOTAL ;##123## MOVB MINUSD,XYDB ;##123## RTI ;##123## 1$: ADD PLUS,TOTAL ;##124##CHANGE SHORTEST PATH TO ORTHOG MOVB PLUSD,XYDB ;##124## RTI ;##124## ; PLINT1: INC COUNT ;##123##CANCELL PREVIOUS DEC!!!! JSR R0,R.SAVE ;SAVE REGISTERS 6 ;TASK CODE BIC #100,XYCS ;TURN OFF INTERRUPTS MOVB #100,XYXIT ;INTERRUPT EXIT FLAG TST PL-2 ;DID WE GET TURNED OFF BNE 1$ ;NOPE JMP PLHMM ;CLEAN UP BUT DON'T SEND TO PDP-15 1$: JMP @PLOT ;RETURN TO LEVEL 2 CALLER ; ; ; SUBROUTINE TO RECEIVE CLOCK COUNTDOWN ; PLCHK: MOVB PLSAVB,R0 ;PLOTTER CONTROL BYTE IF NEEDED MOVB #377,XYXIT ;SAY WE HAVE TO EXIT TO CLOCK TST PL-2 ;DID DRIVER GET TURNER OFF BEQ PLEXIT ;YES, JUST GO AWAY .IFNDF $NOSW ;##124## BITB MASK,SW ;##137##BOTH SWITCHES OK?? BNE PLCHK1 ;##124## .ENDC ;##124## .IFDF $PL311 BIT #40,XYCS ;CHECK STATUS REG FOR READY BNE PLCHK1 ;##124## .ENDC BEQ PLOTGO PLCHK1: MOVB R0,PLSAVB ;SAVE PLTTER BYTE MOV #PLCHK,PL.CL+2 ;SET UP ADDR FOR CLOCK REQ. MOV #170,PL.CL ;AND TIME, THAT'S IT BR PLEXIT ;AND DO APPROPRIATE EXIT PLSAVB: .BYTE 0 ;SAVE PLOTTER BYTE HERE PLERWT: .BYTE 0 ;EOF SPOOL WAIT SW.SET TO 10 BY CLOSE .IFDF $PL311 MASK: .BYTE 0 ;##137##DEFAULT, NO CONSOLE FOR 311 .ENDC .IFNDF $PL311 MASK: .BYTE 4 ;##137##DEFAULT, OFF LINE FOR XY11 .ENDC ; ; ; ; THE FOLLOWING IS A TABLE OF BYTES TO DESCRIBE THE STARTING ; ADDRESSES OF THE STROKES WHICH MAKE UP THE CHARACTERS ; IN ORDER TO FIT THESE ADDRESSES INTO SINGLE BYTES, THESE BYTES HAVE ; THE FORM [ADDRESS-TOP OF STROKE TABLE ADDRESS-8*(CHAR-BLANK)] ; CHAR-BLANK IS THE DIFFERENCE IN THE ASCII CHARACTER VALUES BETWEEN ; THE CHARACTER IN QUESTION AND BLANK. I.E. FOR A 'B', IT WOULD ; BE 42 OCTAL. THE VALUE OF 8 IS EASY TO MULTIPLY BY, AND TURNS ; OUT TO BE ROUGHLY THE AVERAGE NUMBER OF STROKES PER CHARACTER. ; ; FURTHERMORE, THE DIFFERENCE IN ADJACENT TABLE ENTRIES+8 GIVES ; A CONTROL COUNT FOR # OF STROKES PER CHARACTER. ; ; NOTE, THE PDP-15 RESTRICTS THE CHARACTER RANGE SENT TO 40-137. ; TABPNT: .BYTE KCTBLA-TABCHR .BYTE KCTEXC-TABCHR-10 .BYTE KCTDQO-TABCHR-20 .BYTE KCTPOU-TABCHR-30 .BYTE KCTDOL-TABCHR-40 .BYTE KCTPCT-TABCHR-50 .BYTE KCTAMP-TABCHR-60 .BYTE KCTSQO-TABCHR-70 .BYTE KCTOPR-TABCHR-100 .BYTE KCTCPR-TABCHR-110 .BYTE KCTAST-TABCHR-120 .BYTE KCTPLU-TABCHR-130 .BYTE KCTCOM-TABCHR-140 .BYTE KCTMIN-TABCHR-150 .BYTE KCTPER-TABCHR-160 .BYTE KCTSLA-TABCHR-170 .BYTE KCT0-TABCHR-200 .BYTE KCT1-TABCHR-210 .BYTE KCT2-TABCHR-220 .BYTE KCT3-TABCHR-230 .BYTE KCT4-TABCHR-240 .BYTE KCT5-TABCHR-250 .BYTE KCT6-TABCHR-260 .BYTE KCT7-TABCHR-270 .BYTE KCT8-TABCHR-300 .BYTE KCT9-TABCHR-310 .BYTE KCTCOL-TABCHR-320 .BYTE KCTSEM-TABCHR-330 .BYTE KCTOAN-TABCHR-340 .BYTE KCTEQU-TABCHR-350 .BYTE KCTCAN-TABCHR-360 .BYTE KCTQES-TABCHR-370 .BYTE KCTATS-TABCHR-400 .BYTE KCTA-TABCHR-410 .BYTE KCTB-TABCHR-420 .BYTE KCTC-TABCHR-430 .BYTE KCTD-TABCHR-440 .BYTE KCTE-TABCHR-450 .BYTE KCTF-TABCHR-460 .BYTE KCTG-TABCHR-470 .BYTE KCTH-TABCHR-500 .BYTE KCTI-TABCHR-510 .BYTE KCTJ-TABCHR-520 .BYTE KCTK-TABCHR-530 .BYTE KCTL-TABCHR-540 .BYTE KCTM-TABCHR-550 .BYTE KCTN-TABCHR-560 .BYTE KCTO-TABCHR-570 .BYTE KCTP-TABCHR-600 .BYTE KCTQ-TABCHR-610 .BYTE KCTR-TABCHR-620 .BYTE KCTS-TABCHR-630 .BYTE KCTT-TABCHR-640 .BYTE KCTU-TABCHR-650 .BYTE KCTV-TABCHR-660 .BYTE KCTW-TABCHR-670 .BYTE KCTX-TABCHR-700 .BYTE KCTY-TABCHR-710 .BYTE KCTZ-TABCHR-720 .BYTE KCTOSQ-TABCHR-730 .BYTE KCTBSL-TABCHR-740 .BYTE KCTCSQ-TABCHR-750 .BYTE KCTUAR-TABCHR-760 .BYTE KCTBAR-TABCHR-770 .BYTE KCTEOT-TABCHR-1000 .BYTE KCTEOF-TABCHR-1010 ;CONTROL FOR 140 FLUSH OUT BYTE ; ; CHARACTER TABLE ; ; CHARACTERS ARE DECRIBED AS ABSOLUTE CO-ORDINATE POINTS ON ; AN 11X11 GRID. A BYTE DESCRIBES AN X-Y CO-ORDINATE PAIR. ; THE FORMAT IS 16*X+Y. NUMBERS ARE INDECIMAL FOR VIEWING ; CONVENIENCE. IT IS ASSUMED THAT THE MOVE TO GET TO THE ; FIRST CO-ORDINATE PAIR IS UNINTENSIFIED. OTHERWISE ; THE PEN WILL STAY DOWN THRU THE CHARACTER. EXCEPTION, THE ; BYTE -1 SAYS MOVE THE PEN UP FOR NEXT STROKE ONLY. ; LOGIC IN TOP OF LOOP PUTS PEN DOWN UNLESS OTHERWISE NOTIFIED. ; AT THE END OF THE CHARACTER THE PEN (IN CONCEPT) IS MOVED TO LOWER ; RIGHT CORNER OF THE 'BOX' CONTAINING THE CHAR. IN ; PRACTICE THAT MOVE IS ADDED TO THE UNINTENSIFIED STROKE ; LEADING OFF THE NEXT CHAR. ; ; Y VALUES RANGE 0-10, I.E. THE WHOLE BOX. X VALUES RANGE FROM 1-9; ; THIS GIVES THE INTERCHARACTER SPACING ALONG X-AXIS. CNETERING ; OF THE CHARACTER IN TE BOX IS DISCUSSED AT THE TOP OF THE PLOTTER SECTION. ; CHRACTER STROKES MAY BE CHANGED OR REMOVED ENTIRELY. NOTE THAT ; IF THERE ARE NO STROKES FOR A CHARACTER (SEE BLANK (KCTBLA)), A BALNK ; CHARACTER WILL BE PRODUCED. IT MIGHT PROVE CONVENIENT TO ; DO THIS IF CORE WAS TIGHT, AND SOME OF THE ASCII SET WAS NOT TO ; BE USED. IT IS NOT NECESSARY TO CHANGE TABPNT TABLE WHEN CHANGING ; CHARACTER STROKES. YOU MUST, HOWEVER, LEAVE IN ALL THE LABELS! ; ; .RADIX 10 ; TABCHR: ;TOP OF TABLE ADDRESS FOR TABPNT ; KCTBLA: ;BLANK KCTEXC: .BYTE 16*4+0 ;! .BYTE 16*6+0 .BYTE 16*6+2 .BYTE 16*4+2 .BYTE 16*4+0 .BYTE -1 ;LIFT PEN .BYTE 16*5+3 .BYTE 16*4+6 .BYTE 16*4+10 .BYTE 16*6+10 .BYTE 16*6+6 .BYTE 16*5+3 KCTDQO: .BYTE 16*3+7 ;" .BYTE 16*3+8 .BYTE 16*2+8 .BYTE 16*2+10 .BYTE 16*4+10 .BYTE 16*4+8 .BYTE 16*3+7 .BYTE -1 .BYTE 16*7+7 .BYTE 16*7+8 .BYTE 16*6+8 .BYTE 16*6+10 .BYTE 16*8+10 .BYTE 16*8+8 .BYTE 16*7+7 KCTPOU: .BYTE 16*1+4 ;# .BYTE 16*4+4 .BYTE 16*4+0 .BYTE 16*4+4 .BYTE 16*6+4 .BYTE 16*6+0 .BYTE 16*6+4 .BYTE 16*9+4 .BYTE 16*6+4 .BYTE 16*6+6 .BYTE 16*9+6 .BYTE 16*6+6 .BYTE 16*6+10 .BYTE 16*6+6 .BYTE 16*4+6 .BYTE 16*4+10 .BYTE 16*4+6 .BYTE 16*1+6 .BYTE 16*4+6 .BYTE 16*4+4 KCTDOL: .BYTE 16*2+2 ;$ .BYTE 16*3+1 .BYTE 16*7+1 .BYTE 16*8+2 .BYTE 16*8+4 .BYTE 16*7+5 .BYTE 16*3+5 .BYTE 16*2+6 .BYTE 16*2+8 .BYTE 16*3+9 .BYTE 16*5+9 .BYTE 16*7+9 .BYTE 16*8+8 .BYTE 16*7+9 .BYTE 16*5+9 .BYTE 16*5+10 .BYTE 16*5+0 KCTPCT: .BYTE 16*1+1 ;% .BYTE 16*9+9 .BYTE -1 .BYTE 16*3+9 .BYTE 16*1+9 .BYTE 16*1+7 .BYTE 16*3+7 .BYTE 16*3+9 .BYTE -1 .BYTE 16*7+3 .BYTE 16*9+3 .BYTE 16*9+1 .BYTE 16*7+1 .BYTE 16*7+3 KCTAMP: .BYTE 16*9+1 ;& .BYTE 16*3+7 .BYTE 16*3+9 .BYTE 16*4+10 .BYTE 16*5+10 .BYTE 16*6+9 .BYTE 16*6+7 .BYTE 16*5+6 .BYTE 16*3+6 .BYTE 16*1+4 .BYTE 16*1+1 .BYTE 16*2+0 .BYTE 16*6+0 .BYTE 16*9+3 KCTSQO: .BYTE 16*5+7 ;' .BYTE 16*5+8 .BYTE 16*4+8 .BYTE 16*4+10 .BYTE 16*6+10 .BYTE 16*6+8 .BYTE 16*5+7 KCTOPR: .BYTE 16*7+10 ;( .BYTE 16*5+8 .BYTE 16*5+2 .BYTE 16*7+0 KCTCPR: .BYTE 16*3+0 ;) .BYTE 16*5+2 .BYTE 16*5+8 .BYTE 16*3+10 KCTAST: .BYTE 16*3+3 ;* .BYTE 16*5+5 .BYTE 16*7+7 .BYTE 16*5+5 .BYTE 16*3+7 .BYTE 16*5+5 .BYTE 16*7+3 .BYTE 16*5+5 .BYTE 16*2+5 .BYTE 16*5+5 .BYTE 16*8+5 KCTPLU: .BYTE 16*2+5 ;+ .BYTE 16*8+5 .BYTE 16*5+5 .BYTE 16*5+8 .BYTE 16*5+5 .BYTE 16*5+2 KCTCOM: .BYTE 16*5+0 ;, .BYTE 16*5+1 .BYTE 16*4+1 .BYTE 16*4+3 .BYTE 16*6+3 .BYTE 16*6+1 .BYTE 16*5+0 KCTMIN: .BYTE 16*2+5 ;- .BYTE 16*8+5 KCTPER: .BYTE 16*4+1 ;. .BYTE 16*6+1 .BYTE 16*6+3 .BYTE 16*4+3 .BYTE 16*4+1 KCTSLA: .BYTE 16*1+1 ;/ .BYTE 16*9+9 KCT0: .BYTE 16*2+1 ;0 .BYTE 16*1+3 .BYTE 16*1+7 .BYTE 16*2+9 .BYTE 16*4+10 .BYTE 16*6+10 .BYTE 16*8+9 .BYTE 16*9+7 .BYTE 16*9+3 .BYTE 16*8+1 .BYTE 16*6+0 .BYTE 16*4+0 .BYTE 16*2+1 KCT1: .BYTE 16*2+7 ;1 .BYTE 16*5+10 .BYTE 16*5+0 .BYTE 16*1+0 .BYTE 16*5+0 .BYTE 16*9+0 KCT2: .BYTE 16*1+9 ;2 .BYTE 16*2+10 .BYTE 16*8+10 .BYTE 16*9+9 .BYTE 16*9+6 .BYTE 16*8+5 .BYTE 16*2+5 .BYTE 16*1+4 .BYTE 16*1+0 .BYTE 16*9+0 KCT3: .BYTE 16*1+9 ;3 .BYTE 16*2+10 .BYTE 16*8+10 .BYTE 16*9+9 .BYTE 16*9+6 .BYTE 16*8+5 .BYTE 16*3+5 .BYTE 16*8+5 .BYTE 16*9+4 .BYTE 16*9+1 .BYTE 16*8+0 .BYTE 16*2+0 .BYTE 16*1+1 KCT4: .BYTE 16*9+3 ;4 .BYTE 16*1+3 .BYTE 16*8+10 .BYTE 16*8+0 KCT5: .BYTE 16*1+1 ;5 .BYTE 16*2+0 .BYTE 16*8+0 .BYTE 16*9+1 .BYTE 16*9+5 .BYTE 16*8+6 .BYTE 16*1+6 .BYTE 16*1+10 .BYTE 16*9+10 KCT6: .BYTE 16*1+4 ;6 .BYTE 16*2+5 .BYTE 16*8+5 .BYTE 16*9+4 .BYTE 16*9+1 .BYTE 16*8+0 .BYTE 16*2+0 .BYTE 16*1+1 .BYTE 16*1+4 .BYTE 16*1+9 .BYTE 16*2+10 .BYTE 16*8+10 .BYTE 16*9+9 KCT7: .BYTE 16*1+10 ;7 .BYTE 16*9+10 .BYTE 16*1+0 KCT8: .BYTE 16*2+0 ;8 .BYTE 16*1+1 .BYTE 16*1+4 .BYTE 16*2+5 .BYTE 16*8+5 .BYTE 16*2+5 .BYTE 16*1+6 .BYTE 16*1+9 .BYTE 16*2+10 .BYTE 16*8+10 .BYTE 16*9+9 .BYTE 16*9+6 .BYTE 16*8+5 .BYTE 16*9+4 .BYTE 16*9+1 .BYTE 16*8+0 .BYTE 16*2+0 KCT9: .BYTE 16*1+1 ;9 .BYTE 16*2+0 .BYTE 16*8+0 .BYTE 16*9+1 .BYTE 16*9+6 .BYTE 16*9+9 .BYTE 16*8+10 .BYTE 16*2+10 .BYTE 16*1+9 .BYTE 16*1+6 .BYTE 16*2+5 .BYTE 16*8+5 .BYTE 16*9+6 KCTCOL: .BYTE 16*4+6 ;: .BYTE 16*4+8 .BYTE 16*6+8 .BYTE 16*6+6 .BYTE 16*4+6 .BYTE -1 .BYTE 16*6+4 .BYTE 16*6+2 .BYTE 16*4+2 .BYTE 16*4+4 .BYTE 16*6+4 KCTSEM: .BYTE 16*4+6 ;; .BYTE 16*4+8 .BYTE 16*6+8 .BYTE 16*6+6 .BYTE 16*4+6 .BYTE -1 .BYTE 16*6+4 .BYTE 16*6+2 .BYTE 16*5+1 .BYTE 16*5+2 .BYTE 16*4+2 .BYTE 16*4+4 .BYTE 16*6+4 KCTOAN: .BYTE 16*7+10 ;< .BYTE 16*2+5 .BYTE 16*7+0 KCTEQU: .BYTE 16*2+3 ;= .BYTE 16*8+3 .BYTE -1 .BYTE 16*2+7 .BYTE 16*8+7 KCTCAN: .BYTE 16*3+10 ;> .BYTE 16*8+5 .BYTE 16*3+0 KCTQES: .BYTE 16*2+9 ;? .BYTE 16*3+10 .BYTE 16*7+10 .BYTE 16*8+9 .BYTE 16*8+7 .BYTE 16*7+6 .BYTE 16*6+6 .BYTE 16*5+5 .BYTE 16*5+3 .BYTE -1 .BYTE 16*6+2 .BYTE 16*6+0 .BYTE 16*4+0 .BYTE 16*4+2 .BYTE 16*6+2 KCTATS: .BYTE 16*4+1 ;@ .BYTE 16*2+3 .BYTE 16*2+7 .BYTE 16*4+9 .BYTE 16*6+9 .BYTE 16*8+7 .BYTE 16*8+3 .BYTE 16*7+2 .BYTE 16*6+3 .BYTE 16*5+3 .BYTE 16*4+4 .BYTE 16*4+6 .BYTE 16*5+7 .BYTE 16*6+7 .BYTE 16*6+3 KCTA: .BYTE 16*1+0 ;A .BYTE 16*3+5 .BYTE 16*5+10 .BYTE 16*7+5 .BYTE 16*3+5 .BYTE 16*7+5 .BYTE 16*9+0 KCTB: .BYTE 16*1+0 ;B .BYTE 16*1+5 .BYTE 16*1+10 .BYTE 16*8+10 .BYTE 16*9+9 .BYTE 16*9+6 .BYTE 16*8+5 .BYTE 16*1+5 .BYTE 16*8+5 .BYTE 16*9+4 .BYTE 16*9+1 .BYTE 16*8+0 .BYTE 16*1+0 KCTC: .BYTE 16*9+9 ;C .BYTE 16*8+10 .BYTE 16*2+10 .BYTE 16*1+9 .BYTE 16*1+1 .BYTE 16*2+0 .BYTE 16*8+0 .BYTE 16*9+1 KCTD: .BYTE 16*1+0 ;D .BYTE 16*1+10 .BYTE 16*8+10 .BYTE 16*9+9 .BYTE 16*9+1 .BYTE 16*8+0 .BYTE 16*1+0 KCTE: .BYTE 16*9+10 ;E .BYTE 16*1+10 .BYTE 16*1+5 .BYTE 16*6+5 .BYTE 16*1+5 .BYTE 16*1+0 .BYTE 16*9+0 KCTF: .BYTE 16*1+0 ;F .BYTE 16*1+5 .BYTE 16*6+5 .BYTE 16*1+5 .BYTE 16*1+10 .BYTE 16*9+10 KCTG: .BYTE 16*9+9 ;G .BYTE 16*8+10 .BYTE 16*2+10 .BYTE 16*1+9 .BYTE 16*1+1 .BYTE 16*2+0 .BYTE 16*8+0 .BYTE 16*9+1 .BYTE 16*9+5 .BYTE 16*6+5 KCTH: .BYTE 16*1+0 ;H .BYTE 16*1+5 .BYTE 16*1+10 .BYTE 16*1+5 .BYTE 16*9+5 .BYTE 16*9+10 .BYTE 16*9+5 .BYTE 16*9+0 KCTI: .BYTE 16*2+0 ;I .BYTE 16*5+0 .BYTE 16*8+0 .BYTE 16*5+0 .BYTE 16*5+10 .BYTE 16*2+10 .BYTE 16*5+10 .BYTE 16*8+10 KCTJ: .BYTE 16*1+2 ;J .BYTE 16*1+1 .BYTE 16*2+0 .BYTE 16*8+0 .BYTE 16*9+1 .BYTE 16*9+10 KCTK: .BYTE 16*1+0 ;K .BYTE 16*1+4 .BYTE 16*1+10 .BYTE 16*1+4 .BYTE 16*4+7 .BYTE 16*7+10 .BYTE 16*4+7 .BYTE 16*9+0 KCTL: .BYTE 16*1+10 ;L .BYTE 16*1+0 .BYTE 16*9+0 KCTM: .BYTE 16*1+0 ;M .BYTE 16*1+10 .BYTE 16*5+0 .BYTE 16*9+10 .BYTE 16*9+0 KCTN: .BYTE 16*1+0 ;N .BYTE 16*1+10 .BYTE 16*9+0 .BYTE 16*9+10 KCTO: .BYTE 16*1+1 ;O .BYTE 16*1+9 .BYTE 16*2+10 .BYTE 16*8+10 .BYTE 16*9+9 .BYTE 16*9+1 .BYTE 16*8+0 .BYTE 16*2+0 .BYTE 16*1+1 KCTP: .BYTE 16*1+0 ;P .BYTE 16*1+5 .BYTE 16*1+10 .BYTE 16*8+10 .BYTE 16*9+9 .BYTE 16*9+6 .BYTE 16*8+5 .BYTE 16*1+5 KCTQ: .BYTE 16*7+2 ;Q .BYTE 16*8+1 .BYTE 16*9+3 .BYTE 16*9+7 .BYTE 16*8+9 .BYTE 16*6+10 .BYTE 16*4+10 .BYTE 16*2+9 .BYTE 16*1+7 .BYTE 16*1+3 .BYTE 16*2+1 .BYTE 16*4+0 .BYTE 16*6+0 .BYTE 16*8+1 .BYTE 16*9+0 KCTR: .BYTE 16*1+0 ;R .BYTE 16*1+5 .BYTE 16*1+10 .BYTE 16*8+10 .BYTE 16*9+9 .BYTE 16*9+6 .BYTE 16*8+5 .BYTE 16*4+5 .BYTE 16*1+5 .BYTE 16*4+5 .BYTE 16*9+0 KCTS: .BYTE 16*1+1 ;S .BYTE 16*2+0 .BYTE 16*8+0 .BYTE 16*9+1 .BYTE 16*9+4 .BYTE 16*8+5 .BYTE 16*2+5 .BYTE 16*1+6 .BYTE 16*1+9 .BYTE 16*2+10 .BYTE 16*8+10 .BYTE 16*9+9 KCTT: .BYTE 16*5+0 ;T .BYTE 16*5+10 .BYTE 16*1+10 .BYTE 16*5+10 .BYTE 16*9+10 KCTU: .BYTE 16*1+10 ;U .BYTE 16*1+1 .BYTE 16*2+0 .BYTE 16*8+0 .BYTE 16*9+1 .BYTE 16*9+10 KCTV: .BYTE 16*1+10 ;V .BYTE 16*5+0 .BYTE 16*9+10 KCTW: .BYTE 16*1+10 ;W .BYTE 16*3+0 .BYTE 16*5+10 .BYTE 16*7+0 .BYTE 16*9+10 KCTX: .BYTE 16*1+0 ;X .BYTE 16*5+5 .BYTE 16*9+10 .BYTE 16*5+5 .BYTE 16*1+10 .BYTE 16*5+5 .BYTE 16*9+0 KCTY: .BYTE 16*1+10 ;Y .BYTE 16*5+5 .BYTE 16*9+10 .BYTE 16*5+5 .BYTE 16*5+0 KCTZ: .BYTE 16*1+10 ;Z .BYTE 16*9+10 .BYTE 16*1+0 .BYTE 16*9+0 KCTOSQ: .BYTE 16*7+10 ;[ .BYTE 16*5+10 .BYTE 16*5+0 .BYTE 16*7+0 KCTBSL: .BYTE 16*1+9 ;\ .BYTE 16*9+1 KCTCSQ: .BYTE 16*3+10 ;] .BYTE 16*5+10 .BYTE 16*5+0 .BYTE 16*3+0 KCTUAR: .BYTE 16*3+8 ;^ .BYTE 16*5+10 .BYTE 16*7+8 .BYTE 16*5+10 .BYTE 16*5+0 KCTBAR: .BYTE 16*3+3 ;_ .BYTE 16*1+5 .BYTE 16*3+7 .BYTE 16*1+5 .BYTE 16*9+5 KCTEOT: .RADIX 8 .BYTE 0 ;140 FORCE MOVE TO RIGHT OF LAST CHAR ; KCTEOF: ;ADDR FOR CONTROL CALCULATE ON 140 ; MAGIC: .BYTE 140 ;THE 140 TO FEED IN, SINCE DOESN'T COME ; ;FROM THE PDP-15 ; .NLIST .ENDC ; .IFDF $LV .LIST .SBTTL LINE PRINTER/PLOTTER DRIVER FOR LV11/15 .EVEN ; LVCSR=164000 LVBUF=164002 LVSA=6 LVIOT=12 LVSTAT=14 LVEOF=6414 LVEST=LV.EST+4 ;ADDR IN PIREX ERROR TABLE FOR NOT READY LVUNN=LV.EST+2 ;ADDR FOR UNIT # (FOR NOW 0) LVTCOD=10 ;VERSATEK TASK CODE ; ; ; ; ; MAKE THE PDP-15 DO ALL THE WORK. THE PDP-11 SIMPLY GET S A COUNT ; OF CHARACTERS TO PRINT OUT. WE TREAT THE CONTROL CHARACTERS ; 12,15, AND 14 ONLY. A MINUS CHARACTER IS CONVERTED INTO MINUS ; THAT NUMBER OF SPACES. NOTE ALL REAL ASCII CHAR'S HAVE A ZERO LEADING BIT! ; EACH LINE HAS AN IMPLIED CARRIAGE RETURN THAT IS ADDED BY THE DRIVER ; RATHER THAN SENT BY THE PDP-15 ; ; NOTE, IF HEADER WORD OF BUFFER HAS 400 BIT SET, IT IS ; IMAGE MODE, AND WE NIETHER BUT ON LF OR CR!! ; ; ; CALL TO ROUTINE HAS ADDRESS OF TCB IN HANDLER BUSY (IDLE) REGISTER ; .BLOCK 8.+EAESTK*4 .WORD LVCSR ;ADDRESS OF LVCSR CONTROL STATUS ; REGISTER USED TO RESET DEVICE ; ON STOP I/O OPERATIONS. .WORD 0 ;TCB POINTER (EXTENDED BITS) .WORD 0 ;TCB POINTER (LOWER 16 BITS). THIS ; WORD IS USED AS THE IDLE/BUSY ; SWITCH FOR THE DEVICE DRIVER. ; LV: CLR LV.CL ;CLEAR OUT ANY PENDING TIMER REQUESTS FOR US. MOV LV-2,R0 ;SETUP R0 TO POINT TO TCB CLR LVSTAT(R0) ;CLEAR STATUS FLAG IN TCB CLR LVPLT ;CLEAR PLOT MODE FLAG MOV LVSA+2(R0),R1 ;GET BUFFER START ADDRESS TST LVSA(R0) ;DON'T RELOCATE ADDRESS IF BIT 15 BMI 1$ ; IS ON. ASL R1 ;RELOCATE ADDRESS (WORD TO BYTE POINTER) ADD MEMSIZ,R1 ;(+ 11'S OWN LOCAL MEMORY) MOV 16(R0),R2 ;GET TRAN WORD COUNT BMI 6$ 1$: MOVB (R1)+,R2 BIC #177400,R2 ;CLEAR OUT TOP OF REGISTER MOVB #15,LVEOL ;DEFAULT, ASCII, HERE IS CMPB (R1)+,(R1)+ ;R1=R1+2 MOVB #12,(R1)+ ;DEFAULT, PRECEED LINE WITH LINE FEED CLRB LVERWT ;RESET ERROR WAIT SWITCH .IFNDF $NOSW ;##124## BIT #140000,SPOLSW ;SPOOLER ENABLED & RUNNNG BEQ 2$ CMP #LVEOF,(R1) ;EOF RECORD? BNE 2$ BIT #40,SW ;CONSOLE SW. BIT '2' UP? ;INDICATES WAIT AFTER NEXT EOF RECORD BEQ 2$ MOV #40,LVMASK ;SETUP TIMER MASK MOV #SW,LVADDR ;SETUP TIMER ADRESS INCB LVERWT ;SET ERROR WAIT SW. .ENDC 2$: BITB #1,-3(R1) ;400 BIT SET IN HEADER IF IMAGE BEQ 3$ ;NOT IMAGE, CHECK FORMS CONTROL CLRB LVEOL ;IMAGE, DON'T FORCE CR AFTER MESSAGE BR 4$ ;ALLOW ALL FORMS CONTROL 3$: CMPB #14,(R1) ;FIRST CHAR FORM FEED? BEQ 4$ ;YES, DON'T ADD LINE FEED TO LINE CMPB #15,(R1) ;FIRST CHAR CARRIAGE RETURN BEQ 4$ ;YES, DON'T ADD LINE FEED TO LINE DEC R1 ;MOVE POINTER BACK TO LINE FEED INC R2 ;COUNT ADDITION OF LF TO BUFFER 4$: MOV R2,LVBTCT ;SAVE COUNT MOV R1,LVBUFF ;SAVE POINTER CLRB LVTAB TSTB LVBUF ;HISTORY SAYS THIS HERE BIS #100,LVCSR ;ENABLE INTERRUPTS TO LV GOING 5$: SEXIT WAITST ;EXIT IN A WAIT STATE AND RESCAN ; ; THE ATL NOW. ; 6$: CLR 16(R0) ;DON'T KNOW WHY!??? ASL R2 ;WORD COUNT TO BYTE COUNT MOV #101,LVCSR ;SET UP FOR PLOT MODE TSTB LVCSR ;READY? BPL 8$ ;NO, SET UP TO WAIT FOR READY INTTRPT MOVB (R1)+,LVBUF ;PLACE ON CHAR NOW, REST AFTER INTR. 7$: MOV R1,LVBUFF ;SAVE BUFFER POINTER MOV R2,LVPLT ;WATCH IT, SAVE -COUNT-1 !! BR 5$ 8$: DEC R2 ;-1 FOR -COUNT-1 BR 7$ ;REJOIN ; ; ; LV INTERRUPT ENTRANCE ; LVINT: BIC #100,LVCSR ;DISABLE LV INTERRUPT JSR R0,R.SAVE ;SAVE REGISTERS LVTCOD ;TASK CODE MOV LV-2,R0 ;GET TCB POINTER BEQ LVXT ;IGNORE IF ITS ALREADY BEEN STOPPED BY ; A STOP I/O REQUEST. TST LVCSR ;CHECK FOR ERROR BMI LVERR ;YES CLR LV.CL ;CLEAR OUT ANY PENDING TIMER REQUEST FOR US. MOV LVPLT,R2 ;CHECK FOR PLOT MODE BMI LVPIC ;YUP,GO DO IT LVLOP: TSTB LVCSR ;IS PRINTER CURRENTLY GOING? BPL LVSTIL ;YES: FORGET CHAR FOR NOW TSTB LVTAB ;IN TAB EXPANSION TO SPACES? BMI 4$ ;YES DEC LVBTCT ;DECR CHAR COUNT BMI 5$ ;WENT TO -1, MAKE CR TO FINISH LINE TSTB @LVBUFF ;MINUS BYTE IS TAB EXPANSION COUNT BMI 6$ ;IS ONE, GO SET UP MOVB @LVBUFF,LVBUF ;STICK CHAR INTO LINE PRINTER BUFFER INC LVBUFF ;MOVE POINTER TO NEXT CHAR BR LVLOP ;GO DO NEXT ; 6$: MOVB @LVBUFF,LVTAB ;SET UP TAB COUNT (MINUS, A LA 15) INC LVBUFF 4$: INCB LVTAB ;COUNT A SPACE FOR THIS TAB MOVB #40,LVBUF ;SPACE TO LINE PRINTER BR LVLOP ;GO DO NEXT 5$: TSTB LVEOL ;IMAGE OR ASCII BEQ 7$ ;IMAGE, DON'T FORCE MOVB LVEOL,LVBUF ;ASCII, HERE IS 7$: INC LVSTAT(R0) ;SET REV TO GOOD COMPLETION BR LVXIT ; LVSTIL: BIS #100,LVCSR ;ENABLE INTERRUPT ON LV BR LVXIT1 ;RESTORE R0-R5 AND RETURN ; LVERR: INCB LVERWT ;SET ERROR WAIT SW. MOVB #4,LVEST ;ERROR CODE 1,NOT READY TO TABLE MOV #100000,LVMASK ;SET TIMER MASK MOV #LVCSR,LVADDR ;SET TIMER ADDRESS LVERR1: MOV #LVCHK,LV.CL+2 ;ADDR. FOR TIMER REQ. MOV #170,LV.CL ;2 SECS. IN TICKS(OCTAL) LVXIT1: JMP DEQU1 ;SCHEDULE NEXT TASK ; LVXIT: CLRB LVEST ;INDICATE SUCCESSFULL OPERATION TSTB LVERWT ;ERROR WAIT? BNE LVERR1 BIS #340,PS ;NO. INHIBIT INT. CLR LVCSR ;SHUT LV INT. ENABLE MOV #1,R1 ;TELL CALLER DONE MOV LV-2,R0 ;GET TCBP CALL SEND15 ;TELL CALLER DONE LVXT: BIS #340,PS ;INHIBIT INTERRUPTS CLR LV-2 ;CLEAR BUSY(IDLE) FLAG CLR LV-4 MOV #LV,R3 ;DEQUEUE ANOTHER REQUEST IF ANY MOV #LV.LH,R1 ; IN THIS DRIVERS DEQUE. JMP DEQU ; LVPIC: INC R2 ;CHECK IF WE FINISHED LAST TIME BEQ LVXIT ;YES, JUSTEXIT MOV LVBUFF,R1 ;SET UP FETCH POINTER MOV #LVCSR,R3 ;FOR QUICKER ACCESS TO STATUS MOV #LVBUF,R4 ;AND DATA REG'S MOV #101,(R3) 1$: TSTB (R3) ;CAN TAKE A BYTE BPL 2$ ;NOPE, GET OUT FOR NOW MOVB (R1)+,(R4) ;DATA TO DEVICE INC R2 ;LOOP CONTROL BMI 1$ ;MORE 2$: DEC R2 ;MAKE -1 WAITING FOR COMPLETION INTR. MOV R2,LVPLT MOV R1,LVBUFF BR LVXIT1 ; ; ; SUBROUTINE TO FIELD CLOCK COUNT-DOWN ; ; LVCHK: TST LV-2 ;HAVE WE BEEN DISABLED BEQ 10$ ;IF YES, EXIT, LEAVING CLOCK DISABLED BIT LVMASK,@LVADDR ;ERROR STILL EXISTS? BNE 7$ CLRB LVERWT ;NO. PROCESS REQ. MOV #LVTCOD*2,R2 ;SCAN ATL FOR OUR NODE MOV ATLNP(R2),R1 MOV #LV,LV-12 ;RESTART AT BEGINNING OF REQ. BIC #17,A.TS(R1) ;R1 POINTS TO OUR NODE, MAKE RUNNABLE MOV #LV-26,A.SP(R1) ;SET UP STACK POINTER ASR R2 ;MAKE BYTE ADDRESSING MOVB LEVEL(R2),LV-10 ;SET UP PS BR 10$ 7$: MOV #170,(R0) ;R0 POINTS TO TIMER ENTRY 10$: RTS PC ;RETURNS TO CLOCK ; LVBUFF: .WORD 0 ;BUFFER POINTER LVPLT: .WORD 0 ;PLOT MODE BYTE COUNT AND SWITCH LVBTCT: .WORD 0 ;BYTE COUNT LVTAB: .WORD 0 ;TAB LOCATION LVEOL: .BYTE 0 ;0 IF IMAGE, 15 IF ASCII LVERWT: .BYTE 0 ;MAKE EVEN LVMASK: .WORD 0 ;MASK FOR TIMER LVADDR: .WORD 0 ;POINTER TO TIMER ERROR CHECK ; .NLIST .ENDC ; ; .IFDF $DT .LIST .SBTTL DECTAPE DRIVER FOR DT11/15 .EVEN ; DTCST=177340 ;CONTROL & STATUS REGISTER DTCCM=177342 ;COMMAND REGISTER DTCWC=177344 ;WORD COUNT .. DTCBA=177346 ;BUS ADDRESS .. DTCDT=177350 ;DATA .. ; ; TCB INDEX VARIABLES DF=2 EV=4 BN=6 SA1=10 SA2=12 WC=14 FN=16 SA=20 RP1=22 RP2=24 RP3=26 ; ; THIS IS A DECTAPE DRIVER ON THE PDP 11 FOR THE STANDARD ; DEVICE HANDLERS ON THE PDP 15 ; ; CALLER SETS UP THE BUSY(IDLE) SWITCH(DT-2) TO POINT TO TCB ; .BLOCK 8.+EAESTK*2 .WORD DTCCM .WORD 0 .WORD 0 DT: MOV #10,DT.RTC ;INITIALIZE RETRY COUNT L10=.-4 DTRST1: MOV DT-2,R0 ;SETUP R0 TO POINT TO TCB MOV #DTCWC,R1 ;GET ADDRESS OF WC REG. MOV WC(R0),(R1) ;SET UP WC PUSH SA2(R0) ;...STARTING ADDRESS MOV SA1(R0),R2 ;DON'T RELOCATE ADDRESS IF BMI 1$ ; BIT 15 IS ON. ASL (SP) ROL R2 ADD MEMSIZ,(SP) ADC R2 1$: POP 2(R1) MOV BN(R0),DT.BRQ ;SAVE BLOCK # FOR LATER DTRST2: CLRB DTINT ;SET INT. SW TO SEARCH MOV DT.BRQ,DT.BCK ;SET BLOCK CONTROL FOR SEARCH MOV #100,R3 ;USED IN NEXT SEQUENCE MOV R3,DT.TAC ;SET TURN AROUND COUNT PUSH FN(R0) ;GET UNIT,DIR. & FUN. BIC #7517,(SP) ;CLEAR POSSIBLE GARBAGE TSTB R2 ;XBA ON? BEQ 1$ ;NO, SKIP XBA COMMAND REG. SET UP BIC #177774,R2 ;REMOVE GARBAGE BITS ASL R2 ;SHIFT LEFT(4) TO PROPER POS. ASL R2 ASL R2 ASL R2 BIS R2,(SP) ;SET UP XBA BITS IN COMMAND REG. 1$: MOVB (SP),DT.FRQ ;SAVE FUN. FOR LATER MOVB #102,(SP) ;RESET FUN. TO SEARCH ASL R3 ;(NOW CONTAINS 200) BIT (SP),#4000 ;TRAVEL FWD.? BNE 2$ INC R3 ;IF SO, R3 NOW =201 & SO... 2$: MOVB R3,DT.SSW ;MAKING BPL OR BMI AS REQD. POP -(R1) ;SET DT COMMAND REG. SEXIT WAITST ;EXIT IN A WAIT STATE AND RESCAN ; THE ATL NOW. ; ; ; INTERRUPT SERVICE- SEARCH COMPLETE? ; DT.SIP: TST @#DTCCM ;CHK. FOR ERROR BMI DT.SER ;IF ERROR, FIND WHAT ERROR CMP @#DTCDT,DT.BRQ ;CHK. IF BLOCK FOUND BEQ DT.BFD ;YES, CHK. DIR. OF ROT. BMI DT.SXT ;NO, GET TO BLOCK THIS WAY? DT.SSW=.-1 ;(BPL IF BKWD.) DT.TA1: BICB #40,PS ;LOWER PRIORITY TO LVL 6 ASRB #0 ;HOW MANY TURNS DT.TAC=.-2 BCS DT.BER ;IF 6, CAN'T FIND BLOCK? PUSH #4000 ;OTHERWISE MUST TURN AROUND PUSH #2 ;ASSUME TRAVEL NOW FWD. RORB DT.SSW ;CHK. DIR. BCS DT.TA2 ;IF FWD., OMIT NEXT 2 INST. NEG 2(SP) ;BKWD., REVERSE ALL NEG (SP) DT.TA2: SUB (SP)+,DT.BRQ ;ALLOW 2 BLOCKS FOR TURN AROUND ADD (SP)+,@#DTCCM ;DISABLE DELAY INHIBIT ROLB DT.SSW ;RESET DIR. SW(C BIT REVERSES) DT.SXT: .INH ;INHIBIT INTERRUPTS WHILE LOOKING TST DT-2 ; AT TCBP FOR THIS REQUEST SINCE BEQ DT.SX1 ; IT COULD CHANGE ON US IN THE ; MIDDLE. INCB @#DTCCM ;CONTINUE SEARCH DT.SX1: .ENA ;REENABLE INTERRUPTS JMP DEQU1 ;BLOCK FOUND- CHK. TRAVEL DIR. ; DT.BFD: CMP #0,#0 ;TRAVEL AS BEFORE? DT.BRQ=.-4 DT.BCK=.-2 BNE DT.TA1 ;NO, MUST TURN AROUND INCB DTINT ;RESET INT. SW FOR TFR. MOVB #0,@#DTCCM DT.FRQ=.-4 JMP DEQU1 ; ; INTERRUPT SERVICE- TRANSFER COMPLETE? ; DTINT: BR .+2 ;INTERRUPT SW .... BR DT.SIP ;FOR SEARCH COMES HERE JSR R0,R.SAVE ;SAVE REGS. 3 ;TASK CODE BICB #40,PS ;LOWER TO LVL 6 MOV #DTCCM,R1 ;GET COMMAND REG. ADDRESS TST (R1) ;ERROR CAUSE INT.? BMI DT.TER ;IF YES, CHK. WHY? MOV #1,EVAR ;NO, INDICATE IN EV DTNXIT: MOVB L10,(R1) ;STOP TAPE DTXIT: MOV DT-2,R0 ;GET TCB ADDRESS IN R0 BEQ DTXT ;IGNORE IF ITS ALREADY BEEN STOPPED BY ; A STOP I/O REQUEST. MOV DTCCM,RP1(R0) ;RETURN INFO. TO 15 ...... MOV DTCWC,RP2(R0) ; ...... MOV DTCBA,RP3(R0) ; ...... MOV DTCST,SA(R0) ; ...... BIS #340,PS ;INHIBIT INTERRUPTS MOV EVAR,R1 ;LOAD R1 WITH EV CALL SEND15 ; ....& TELL 15 CURRENT REQ. COMPLETE DTXT: BIS #340,PS ;INHIBIT INTERRUPTS CLR DT-2 ;CLEAR BUSY SW CLR DT-4 MOV #DT,R3 ;SET UP FOR DEQUEUE MOV #DT.LH,R1 JMP DEQU ;CLEAN LIST & CHK. ANY MORE REQ. DTINXT: JMP DEQU1 ; ; SEARCH ERROR- DETERMINE CAUSE? ; DT.SER: TST @#DTCST ;IN END ZONE? BMI DT.TA1 ;IF YES, TURN AROUND BICB #40,PS ;LOWER TO LVL 6 MOV #-1,EVAR ;SET EV TO SEARCH ERROR BR DTNXIT ;CALL 15, CLEAN UP & EXIT ; ; BLOCK NOT FOUND ON SEARCH ; DT.BER: MOV #-2,EVAR ;REFLECT IN EV BR DTNXIT ;CALL 15, CLEAN UP & EXIT ; ; TRANSFER ERROR ; DT.TER: BIT #14000,-(R1) ;ILO/SELE ERROR? BNE DT.ER1 ;IF SO, REFLECT IN EV & EXIT BIT #100400,(R1)+ ;ENDZ/NEX ? BNE DT.FER ;IF SO, REFLECT IN EV & EXIT BIT #20000,-(R1) ;MTE ? BNE DT.ER2 ;IF SO,REFLECT IN EV & EXIT MOV DT-2,R0 ;GET TCB ADDRESS IN R0 BEQ DTXT ;IGNORE IF ITS ALREADY BEEN STOPPED BY ; A STOP I/O REQUEST. ; ; RECOVERABLE ERRORS- TIMING/PARITY ; ASL #0 ;TRIED 8 TIMES ? DT.RTC=.-2 BCC DT.RXT ;IF NOT, RETRY MOV #-5,EVAR ;YES, REFLECT IN EV MOVB L10,(R1)+ ;STOP TAPE IN CASE ...... MOV 1(R1),R2 ;ELSE GET WC IN TCB .... BEQ DTXIT ;IF SO, THATS IT! SUB WC(R0),R2 ;ELSE GET WC IN TCB SWAB R2 ; .....& # OF BLOCKS DONE BITB L10,(R1)+ ;CHK. PRESENT TRAVEL DIR. BEQ 1$ NEG R2 1$: ADD R2,DT.BRQ ;MODIFY SEARCH START BLOCK # MOV L10,DT.RTC ; ....RESET RETRY COUNT TST (R1)+ ;BUMP R1 TO POINT DTCWC MOV #DTRST2,R3 ;GO SET UP & RESTART BR DTRTRY ; .....& TAKE INTERIM EXIT ; ; FATAL ERROR- END ZONE/NEXM ; DT.FER: MOV #-4,EVAR ;REFLECT IN EV BR DTNXIT ; ....TELL 15,RESET ALL, EXIT ; ; PARITY/TIMING ERROR- TRY AGAIN ; DT.RXT: MOV #DTRST1,R3 ;RESTART OPERATION DTRTRY: BIS #340,PS ;INHIBIT INTERRUPTS MOV #6,R2 ;FIND ATL NODE MOV ATLNP(R2),R1 BEQ DTXIT ;FORGET RETRYING IF NO ATL NODE EXISTS MOV R3,DT-12 ;NEW PC MOV #6*40,DT-10 ;NEW PS JMP CEXIT ;NOW RETRY IT ; ; OPERATOR ERROR ; DT.ER1: MOV #-3,EVAR ;REFLECT IN EV BR DTNXIT ;CALL 15, CLEAN UP & EXIT ; ; MARK TRACK ERROR ; DT.ER2: MOV #-6,EVAR ;REFLECT IN EV BR DTNXIT ;CALL 15, CLEAN UP & EXIT ; EVAR: .WORD 0 ; .NLIST .ENDC ; LASTLC: ;LAST LOCATION USED BY PIREX ; .END START