1
0
mirror of https://github.com/PDP-10/stacken.git synced 2026-03-01 17:26:38 +00:00
Files
Lars Brinkhoff 6e18f5ebef Extract files from tape images.
Some tapes could not be extracted.
2021-01-29 10:47:33 +01:00

1079 lines
38 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
TITLE LP2SER - LINE PRINTER SERVICE FOR LP20 CONTROLLER ON 2020 - V034
SUBTTL D. DETROY/DBD 21-JUNE-88
SEARCH F,S,DEVPRM
$RELOC
$HIGH
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION
;1978,1979,1980,1982,1984,1986,1988.
;ALL RIGHTS RESERVED.
.CPYRT<1978,1988>
XP VLP2SR,034 ;DEFINE GLOBAL VERSION NUMBER FOR LOADER MAP
LP2SER: ENTRY LP2SER
SUBTTL LP20 REGISTER DEFINITIONS
; OFFSETS INTO THE EXTERNAL PAGE REGISTERS
LPCSRA==0 ;CONTROL AND STATUS REGISTER A
LPCSRB==2 ;CONTROL AND STATUS REGISTER B
LPBSAD==4 ;BUS ADDRESS REGISTER (CURRENT ADDRESS)
LPBCTR==6 ;BYTE COUNT REGISTER (2'S COMPLEMENT)
LPPCTR==10 ;PAGE COUNTER
LPRAMD==12 ;RAM DATA REGISTER
LPCBUF==14 ;(BYTE) CHARACTER BUFFER REGISTER
LPCCTR==15 ;(BYTE) COLUMN COUNT REGISTER
LPTDAT==16 ;(BYTE) PRINTER DATA REGISTER
LPCKSM==17 ;(BYTE) CHECKSUM REGISTER
;WORD BIT DEFINITIONS IN LPCSRA
LPWDON==000200 ;LP DONE
LPWIEN==000100 ;LP INTERRUPT ENABLE
LPWA17==40 ;B17 OF PDP-11 ADDRESS (EXTENDED)
LPWA16==20 ;B16
LPWDVU==000010 ;LOAD DAVFU
LPWTM==000004 ;TEST MODE
LPWPEN==000002 ;PARITY ENABLE
LPWGO==000001 ;GO
LPWERR==<200>B<35-8> ;ERROR (COMPOSITE)
LPWPZR==<100>B<35-8> ;PAGE COUNTER REACHED 0
LPWCI==<40>B<35-8> ;UNDEFINED CHARACTER INTERRUPT
LPWDR==<20>B<35-8> ;DAVFU READY
LPWOL==<10>B<35-8> ;ON LINE
LPWDH==<4>B<35-8> ;DELIMITER HOLD
LPWRSE==<2>B<35-8> ;RESET ERROR
LPWINT==<1>B<35-8> ;LP INITIALIZE
;BYTE BIT DEFINITIONS IN LPCSRA
LP1DON==000200 ;LP DONE
LP1IEN==000100 ;LP INTERRUPT ENABLE
LP1A17==40 ;B17 OF PDP-11 ADDRESS (EXTENDED)
LP1A16==20 ;B16
LP1DVU==000010 ;LOAD DAVFU
LP1TM==000004 ;TEST MODE
LP1PEN==000002 ;PARITY ENABLE
LP1GO==000001 ;GO
;BYTE BIT DEFINITIONS IN LPCSRA+1 (-11 LPCSRA BITS 15,14,13,12,11,10,9,8)
LP1ERR==200 ;ERROR (COMPOSITE)
LP1PZR==100 ;PAGE COUNTER REACHED 0
LP1CI==40 ;UNDEFINED CHARACTER INTERRUPT
LP1DR==20 ;DAVFU READY
LP1OL==10 ;ON LINE
LP1DH==4 ;DELIMITER HOLD
LP1RSE==2 ;RESET ERROR
LP1INT==1 ;LP INITIALIZE
;WORD LPCSRB BIT DEFINITIONS
LPWOFL==000200 ;OFF LINE
LPWDVN==000100 ;DAVFU NOT READY
LPWPER==000040 ;LINE PRINTER PARITY ERROR
LPWMPE==000020 ;MEMORY PARITY ERROR
LPWRPE==000010 ;RAM PARITY ERROR
LPWSYE==000004 ;MASTER SYNC ERROR
LPWDME==000002 ;DEMAND TIME-OUT ERROR
LPWGOE==000001 ;GO ERROR
LPWVDT==200B<35-8> ;VALID DATA
LPWPNR==40B<35-8> ;PRINTER NOT READY
LPWDPB==20B<35-8> ;LINE PRINTER DATA PARITY BIT
LPWOVF==10B<35-8> ;OPTICAL VFU
;BYTE LPCSRB BIT DEFINITIONS
LP1OFL==000200 ;OFF LINE
LP1DVN==000100 ;DAVFU NOT READY
LP1PER==000040 ;LINE PRINTER PARITY ERROR
LP1MPE==000020 ;MEMORY PARITY ERROR
LP1RPE==000010 ;RAM PARITY ERROR
LP1SYE==000004 ;MASTER SYNC ERROR
LP1DME==000002 ;DEMAND TIME-OUT ERROR
LP1GOE==000001 ;GO ERROR
;BYTE LPCSRB+1 BIT DEFS
LP1VDT==200 ;VALID DATA
LP1PNR==40 ;PRINTER NOT READY
LP1DPE==20 ;LINE PRINTER DATA PARITY ERROR
LP1OVF==10 ;OPTICAL VFU
SUBTTL LPT SPECIFIC DDB DEFINITIONS
;GENERAL BITS IN LH OF DEVIOS
IOSMON==400000 ;DEVICE IS DOING IO FROM THE MONITOR
; USED BY MAPIO ROUTINE
;DEVICE DEPENDENT BITS IN LH OF DEVIOS
LPTSYN==Z(1B11) ;CRFF AFTER CLOSE HAS BEEN SENT
LPTEND==Z(1B10) ;CLOSE UUO HAS BEEN DONE
LPTVFU==Z(1B9) ;VFU NEEDS RELOADING
LPTOPB==Z(1B8) ;POSSIBLE PARTIAL BUFFER ALREADY OUTPUT
LPTRAM==Z(1B7) ;RAM NEEDS RELOADING
LPTARW==Z(1B6) ;DOING UP-ARROW TRANSLATION
;DEVICE DEPENDENT BITS IN RH OF DEVIOS
LPTNFF==100 ;SUPPRESS FREE FORM FEEDS
;MISCELLANEY
MAXLBZ==:^D253 ;MAX WORD SIZE OF USER'S LPT BUFFERS
;(LPTSPL USES THIS NUMBER)
SUBTTL LP20 SYSERR DATA BLOCK DEFINITIONS
;WORDS ARE IN EACH LINEPRINTER DDB FOR DAEMON ERROR REPORTING.
.HCNAM==0 ;DEVICE NAME
.HCTYP==1 ;CONTROLLER/DEVICE TYPE
HC.CTL==77B5 ;CONTROLLER TYPE BYTE
.CTILL==0 ;ILLEGAL
.CTB10==1 ;BA10
.CTLP1==2 ;LP100
.CTLP2==3 ;LP20
.CTCD2==4 ;CD20
HC.DEV==77B11 ;DEVICE TYPE BYTE
.DEILL==0 ;ILLEGAL
.DELPT==1 ;LPT
.DECDR==2 ;CDR
.DECDP==3 ;CDP
.DEPLT==4 ;PLT
HC.RTY==777777B35 ;RETRY COUNT FIELD
.RTNON==1B17 ;NON-ECOVERABLE FLAG
.HCUID==2 ;PPN OF USER
.HCPGM==3 ;PROGRAM NAME
.HCSBP==4 ;SUB-BLOCK POINTER
; (XWD .HCL25-.HCSBP,,.HCL20)
.HCL20==5 ;UBA STATUS REGISTER
.HCL21==6 ;UBA MAP SLOT
.HCL22==7 ;LPCSRA,,LPCSRB
.HCL23==10 ;LPBSAD,,LPBCTR
.HCL24==11 ;LPPCTR,,LPRAMD
.HCL25==12 ;LPCBUF,,LPTDAT
.HCSIZ==13 ;SIZE OF BLOCK
SUBTTL AUTOCONFIGURE
;DRIVER CHARARCTERISTICS
; LP2 = LPTCNF
; LPT = DEVICE TYPE (LINE PRINTER)
; 7 = MAXIMUM DEVICES IN SYSTEM
; 0 = KONTROLLER TYPE
; 0 = MAXIMUM DRIVES PER KONTROLLER
; 0 = HIGHEST DRIVE NUMBER ON KONTROLLER
; MDSEC0 = SECTION FOR KDB/UDB
; MDSEC0 = SECTION FOR DDB
DRVCHR (LP2,LPT,7,0,0,0,MDSEC0,MDSEC0,<DR.GCC!DR.NET>)
.ORG DEVLSD
LPTDAP:!BLOCK 1 ;PLACE TO BUILD AOBJN POINTER TO LPTDAE
LPTDAE:!BLOCK .HCSIZ ;SYSERR BLOCK
LPTSTS:!BLOCK 1 ;MORE DEVICE STATUS
LPTRSV:!BLOCK 1 ;SAVE AREA DURING UP-ARROW TRANSLATION
LPTWSV:!BLOCK 1 ;...
LPTUDC:!BLOCK 1 ;UNDEFINED CHAR INTERRUPT DATA SAVED
LPTPAG:!BLOCK 1 ;PAGE COUNTER WORD
LPTVEC:!BLOCK 1 ;ADDRESS OF VECTOR INTERRUPT CODE
LPTBAS:!BLOCK 1 ;LP20 BASE DEVICE ADDRESS
LPTFNC:!BLOCK 1 ;CURRENT FUNCTION BITS SAVED HERE
LPTBYT:!BLOCK 1 ;OUTPUT BYTE COUNT STORED HERE
LPTCDB:!BLOCK 1 ;ADDRESS OF CHANNEL DATA BLOCK
LPTPTR:!BLOCK 1 ;IOWD POINTER TO DATA BUFFER
LPTBUF:!BLOCK <<MAXLBZ*5>/4>+1 ;ENOUGH ROOM FOR LPTSPL 7 TO 8 BIT BYTE CONVERSION
LPTBFZ==.-LPTBUF ;SIZE OF THE LPT BUFFER
LPTFRM:!BLOCK 1 ;FORMS TYPE NAME (SIXBIT)
LP2LEN:! ;LENGTH OF LPT DDB
.ORG
LP2DDB: DDBBEG (LPT,LP2LEN)
SETWRD (DEVCHR,<6*HUNGST+DVLPTL,,LPTSIZ##>) ;DEVCHR
SETWRD (DEVSER,<MCSEC0+LPTDSP>) ;DEVSER
SETWRD (DEVMOD,<DVOUT!DVLPT,,<1_A+1_AL+1_I>>) ;DEVMOD
SETWRD (DEVTYP,<<.TYLPT*.TYEST>!.SPLPT!DEPLEN,,0>) ;DEVTYP
SETWRD (DEVCPU,<LPTCHN##>) ;DEVCPU
SETWRD (LPTDAP,<-.HCSIZ,,LPTDAE>) ;LPTDAP
DDBEND
;CONSO SKIP CHAIN CODE (AUTCON WILL FILL IN THE BLANKS)
LP2ICD: PHASE 0
EXP 0 ;(00) OLD PC FLAGS
EXP 0 ;(01) OLD PC
EXP IC.UOU ;(02) NEW PC FLAGS
EXP .+1 ;(03) NEW PC
JSR PIERR## ;(04) SAVE ACS AND SETUP PDL
DMOVE T1,0 ;(05) GET INTERRUPT FLAGS AND PC
DMOVEM T1,-1 ;(06) SAVE IN TRADITIONAL PLACE FOR XJEN CH'N
SKIPA F,.+1 ;(07) SET UP DDB ADDRESS
EXP 0 ;(10) DDB ADDRESS
XJRST .+1 ;(11) CALL INTERRUPT HANDLER
EXP 0 ;(12) INTERRUPT HANDLER ADDRESS
DEPHASE
LP2ICL==.-LP2ICD ;LENGTH OF CONSO SKIP CHAIN CODE
EQUATE (LOCAL,0,<LP2CKT,LP2KDB,LP2KLN,LP2UDB,LP2ULN>)
EQUATE (LOCAL,0,<LP2ULB,LP2ULP>)
LP2DSP: DRVDSP (LP2,LPTCHN##,LP2DDB,LP2LEN,URDDIA##)
;DEFAULT MONGEN'ED DEVICE TABLE
DEFMDT: MDKS10 (7,LP11IV,LP11CA,0,0,<MD.KON>)
MDTERM
;BITS FOR MDT ENTIRES ARE ALLOCATED HERE
LPT.UC==:1 ;UPPER-CASE ONLY PRINTER
LP2CFG: XMOVEI T1,LP2MDT## ;MONGEN'ED DEVICE TABLE
XMOVEI T2,DEFMDT ;DEFAULT TABLE
MOVNI T3,1 ;NO MASSBUS UNIT OR DRIVE INFORMATION
MOVEI T4,MD.KON ;MATCH ON KONTROLLER DEFINITION
PUSHJ P,AUTMDT## ;SCAN THE TABLES
JRST CPOPJ1## ;NO MATCHES
PUSH P,T1 ;PRESERVE MDT DATA
MOVEI T1,LPTBAS ;WORD CONTAINING AN I/O INSTRUCTION
PUSHJ P,AUTFND## ;SEE IF THERE'S ALREADY A DDB
JRST LP2CF1 ;JUST MAKE SURE THE NUMBERS ARE OK
PUSHJ P,AUTADN## ;ALLOCATE A DEVICE NUMBER
HRLI T1,'LPT' ;INCLUDE GENERIC DEVICE NAME
SETZ T2, ;LOCAL DEVICE
PUSHJ P,AUTDDB## ;CREATE A DDB
JRST TPOPJ## ;NO CORE
ADDM F,LPTDAP(F) ;FIX UP DAEMON ERROR POINTER
LP2CF1: LDB T1,[POINT 21,.CPDVC##,35] ;GET UNIBUS ADDRESS
MOVEM T1,LPTBAS(F) ;SAVE IN DDB
MOVSI T1,CP.LP2 ;GET CHANNEL TYPE BITS
PUSHJ P,AUTCHN## ;ALLOCATE CHANNEL DATA BLOCK
JRST LP2CF2 ;NO CORE
MOVE T1,.CPCHA## ;GET CHANNEL DATA BLOCK ADDRESS
MOVEM T1,LPTCDB(F) ;SALT IT AWAY
HLRZ T1,LPTBAS(F) ;GET UNIBUS ADAPTER NUMBER
MOVEI T2,2 ;NUMBER OF MAPPING REGISTERS NEEDED
PUSHJ P,AUTAMR## ;ALLOCATE MAPPING REGISTERS
JRST TPOPJ## ;SORRY
MOVE T4,LPTCDB(F) ;GET CHANNEL DATA BLOCK ADDRESS BACK
MOVEM T1,CHNIMR(T4) ;STORE THE DATA AWAY
MOVEM T2,CHNMRC(T4)
MOVEM T3,CHNIEA(T4)
SKIPE LPTVEC(F) ;BEEN HERE BEFORE?
JRST LP2CF4 ;THEN DON'T MESS WITH INTERRUPT CODE
MOVE T1,F ;DATA BLOCK ADDRESS
XMOVEI T2,LP2INT ;INTERRUPT SERVICE
PUSHJ P,AUTICD## ;GENERATE INTERRUPT ROUTINES
LP2CF2: SKIPA T2,F ;NO CORE
JRST LP2CF3 ;ONWARD
MOVEI T1,LP2LEN ;GET DDB LENGTH
PUSHJ P,AUTKIL## ;DELETE THE DDB
PUSHJ P,AUTDDN## ;DEALLOCATE DEVICE NUMBER
JRST TPOPJ## ;PHASE STACK AND RETURN
LP2CF3: MOVEM T2,LPTVEC(F) ;SAVE IN CASE ANYONE IS INTERESTED
PUSHJ P,AUTVII## ;COMPUTE VECTOR INSTRUCTION ADDRESS
MOVE T2,LPTVEC(F) ;GET VECTOR ROUTINE ADDRESS
HRLI T2,(XPCW) ;INTERRUPT INSTRUCTION
MOVEM T2,(T1) ;SAVE IN VECTOR TABLE
MOVE T1,DEVNAM(F) ;GET DEVICE NAME
MOVEM T1,LPTDAE+.HCNAM(F) ;SET IT UP
MOVE T1,[XWD .HCL25-.HCSBP,.HCL20] ;GET SUB-BLOCK POINTER
MOVEM T1,LPTDAE+.HCSBP(F) ;SET IT UP
LP2CF4: POP P,T1 ;RESTORE MDT DATA
MOVSI T2,DVLPTL ;LOWERCASE LPT
TRNE T1,LPT.UC ;IF AN UPPER-CASE ONLY PRINTER,
ANDCAM T2,DEVCHR(F) ;CLEAR IT FOR LPTTYP
POPJ P, ;ALL DONE
SUBTTL LPT SERVICE DISPATCH TABLE
;LINE PRINTER SERVICE DISPATCH TABLE
JRST LPTONL ;S IF LPT IS ON LINE NOW
JRST LPTDVP ;DEVOP. UUO
JRST REGSIZ## ;GET BUFFER SIZE FROM DDB
JRST LP2INI ;INITIALIZE
JRST LPTHNG ;HUNG DEVICE ERROR
LPTDSP: JRST LPTREL ;RELEASE
JRST LPTCLS ;CLOSE
JRST LPTOUT ;OUTPUT
JRST ILLINP## ;INPUT
SUBTTL SYSTEM START-UP DEVICE INITIALIZATION
;LP2INI IS CALLED AT SYSTEM INITIALIZATION TIME FROM
;IOGO IN SYSINI WITH THE DDB ADDRESS IN F
;NOTE: THE LP2INI CODE FORCES IOGO IN SYSINI TO INVOKE
; LP2INI FOR EACH LINE PRINTER ON THE SYSTEM RATHER
; THAN FOR THE NORMAL CASE WHERE IT INVOKES THE
; INITIALIZATION CODE ONCE FOR EACH DISPATCH TABLE.
;
; THEREFORE, THE CORRECT OPERATION OF THE LP2INI CODE
; IS DEPENDENT UPON THE IOGO CODE WHICH SHOULD BE:
;
; PUSHJ P,DINI(P3)
; HRRZM P3,SAVITM
LP2INI: CAIN F,LP2DDB ;PROTOTYPE?
JRST CPOPJ1## ;YES, SKIP SO IOGO CALLS INI ROUTINE AGAIN
MOVSI T4,DVOFLN ;OFF-LINE BIT
ANDCAM T4,DEVCHR(F) ;ASSUME LPT IS ON-LINE
PUSHJ P,LPTONL ;IS IT REALLY?
IORM T4,DEVCHR(F) ;NO--SET OFF-LINE BIT
TLO S,LPTRAM+LPTVFU ;MARK RAM AND VFU FOR LOADING
PUSHJ P,LPTREL ;GO THRU RELEASE CODE
PJRST CPOPJ1## ;SKIP RETURN TO FORCE CALL FOR EACH LPT
SUBTTL OUT/OUTPUT UUO
LPTOUT: TLO S,IO ;INDICATE OUTPUT
PUSHJ P,LPTOFL ;IF OFF-LINE, GET IT FIXED
TLZE S,LPTRAM ;RAM NEED DEFAULT RELOADING?
PUSHJ P,RESRAM ;YES--GO DO IT
TLNN S,LPTVFU ;VFU NEED DEFAULT RELOADING?
JRST LPTOU1 ;NO--GO ON
PUSHJ P,LPTSTV ;YES--SETUP FOR VFU LOAD
JRST LPTGO ; AND GO DO IT
LPTOU1: TRNE S,LPTNFF ;SUPPRESS FORM FEED?
TLZA S,IOBEG ;YES--CLEAR IOBEG AND OUTPUT BUFFER
TLNN S,IOBEG ;NO--1ST OUTPUT?
JRST LPTOU2 ;NO--JUST DO NEXT USER BUFFER
PUSHJ P,LPTSTI ;YES--SETUP INITIAL OUTPUT BUFFER
JRST LPTGO ; AND GO DO IT
LPTOU2: PUSHJ P,LPTSET ;SET UP USER'S OUTPUT BUFFER
PJRST STOIOS## ;ERROR IN BUFFER, RETURN
;HERE TO START THE PRINTER GOING
LPTGO: MOVE T1,LPTBAS(F) ;GET BASE ADDRESS OF IO REGISTERS
MOVEI T2,7777 ;12 BITS IN THE BYTE COUNTER
TION T2,LPBCTR(T1) ;IS THERE REALLY SOMETHING TO PRINT?
JRST LPTSTP ;NO--JUST SHUT DOWN I/O
MOVEI T2,LPWRSE ;ERROR RESET BIT
BSIO T2,LPCSRA(T1) ;ENSURE LPWERR IS CLEAR
RDIO T2,LPBCTR(T1) ;COPY BYTE COUNTER TO ITSELF TO
WRIO T2,LPBCTR(T1) ; CLEAR DONE FROM LPWRSE ABOVE
RDIO T3,LPCSRA(T1) ;PICK UP CSRA
HRLM T3,LPTSTS(F) ;SAVE HERE FOR ANALYZING GO ERRORS
RDIO T3,LPCSRB(T1) ;PICK UP CSRB
HRRM T3,LPTSTS(F) ;SAVE HERE FOR ANALYZING GO ERRORS
TRO S,IOACT ;SET IOACT
MOVEM S,DEVIOS##(F)
MOVE T1,LPTBAS(F) ;GET BASE ADDRESS OF IO REGISTERS
MOVEI T2,LP1IEN+LP1PEN ;INTERRUPT ENABLE AND PARITY ENABLE BITS
BSIOB T2,LPCSRA(T1) ;SET THEM
MOVEI T2,LP1GO ;GO BIT
BSIOB T2,LPCSRA(T1) ;START THE PRINTER
PJRST SETHNG## ;SET HUNG TIMER AND RETURN
;HERE DURING OUTPUT UUO TO SEE IF DEVICE EXISTS
LPTOFL: PUSHJ P,LPTONL ;SEE IF LPT IS ON-LINE
SKIPA ;IT'S NOT, TELL THE USER
POPJ P, ;IT IS, JUST RETURN
MOVEM S,DEVIOS(F) ;YES, SAVE S (LPTRBL OFF)
MOVSI T4,DEPADV ;WANT BUFFER LEFT ALONE
IORM T4,DEVADV(F) ;
MOVSI T4,DVOFLN ;MARK LPT OFF LINE
IORM T4,DEVCHR(F)
PUSHJ P,HNGSTP## ;HALT JOB & PRINT REMINDER
MOVSI T4,DEPADV ;LOAD "DONT ADV BUFFERS"
ANDCAM T4,DEVADV(F) ;AND CLEAR IT IN THE DDB
JRST LPTOFL ;BACK HERE ON CONT, TRY AGAIN
SUBTTL CLOSE UUO - RELEASE UUO
;CLOSE UUO - WHEN A CLOSE UUO IS EXECUTED (OR CLOSE COMMAND)
; LPTCLS IS CALLED. LPTCLS RESETS SOME STATUS FLAGS AND
; LIGHTS LPTEND SO THE FINAL CRFF CAN BE SETUP NEXT TIME
; LPTOUT IS CALLED. LPTCLS RETURNS BY BRANCHING TO "OUT"
; SO THE LAST PARTIAL BUFFER IS OUTPUT.
LPTCLS: TLO S,LPTEND ;SET "CLOSE DONE"
TLZ S,LPTSYN ;MAKE SURE THIS CLEAR
MOVEM S,DEVIOS(F) ;STORE S
JRST OUT## ;AND CALL OUT FOR LAST BUFFER
;RELEASE UUO - WHEN A "RESET" IS DONE ON THE LPT, LPTREL IS
; CALLED. THE LINEPRINTER IS "TURNED-OFF" (SEE LPTSTP)
; THE PAGE COUNTER IS TURNED OFF AND THE DDB IS CLEANED UP.
LPTREL: MOVE T1,LPTBAS(F) ;GET BASE ADDRESS OF I/O REGISTERS
PUSHJ P,UBGOOD## ;IS LP20 ALIVE ON THE UNIBUS?
JRST LPTRE1 ;NO--DON'T TRY TO ACCESS IT
MOVEI T2,LPWINT ;INITIALIZE BIT
WRIO T2,LPCSRA(T1) ;CLEAR PRINTER
PUSHJ P,LPTTYP ;SETUP LINEPRINTER TYPE
LPTRE1: MOVSI T2,DEPADV ;GET "DONT ADV BUFFER" BIT
ANDCAM T2,DEVADV(F) ;TURN IT OFF
TLZ S,LPTOPB!LPTARW!LPTSYN ;CLEAR THESE OUT
SETOM LPTPAG(F) ;TURN OFF PAGE COUNTER
PJRST LPTSTP ;CLEAR PRINTER + IOACT, SAVE S AND RETURN
LPTHNG==LPTREL ;HUNG DEVICE IS SAME AS RELEASE
SUBTTL GENERAL INTERRUPT ROUTINE
;ENTER HERE ON ALL INTERRUPTS
LP2INT: PUSHJ P,IOSET## ;SETUP ACS R AND S
LDB J,PJOBN## ;SET UP J WITH JOB NUMBER
MOVE T1,LPTBAS(F) ;GET BASE ADDRESS OF I/O REGISTERS
RDIO T2,LPCSRA(T1) ;PICK UP CSRA
RDIO T3,LPCSRB(T1) ;PICK UP CSRB
HRLM T2,DEVSTS(F) ;SAVE STATUS AT INTERRUPT
HRRM T3,DEVSTS(F) ;...
TRNN T2,LPWDON ;SKIP IF DONE IS UP
JRST LPTERR ;ELSE HANDLE ERROR INTERRUPT
TLZE S,LPTARW ;WAS THIS AN UP-ARROW TRANSLATION?
JRST ARWFIN ;YES--GO RESUME NORMAL PATH
SKIPE T2,LPTFNC(F) ;WERE WE LOADING THE RAM/VFU?
JRST CHKVFU ;YES--GO CHECK IF DEFAULT LOAD
TLZE S,IOBEG ;NO BUFFER ADVANCE ON 1ST OUTPUT
JRST LPTNX1 ;YES, SETUP NEXT BUFFER AND RETURN
TLZE S,LPTEND ;CLOSE DONE?
JRST LPTNX2 ;YES, OUTPUT CRFF
TLZN S,LPTSYN ;WAS CRFF JUST OUTPUT?
PUSHJ P,ADVBFE## ;NO, ADVANCE TO NEXT BUFFER
PJRST LPTSTP ;CANT ADVANCE, BUFFER UNAVAIL
PUSHJ P,SETIOD## ;ARRANGE FOR JOB TO RUN AGAIN
LPTNX1: PUSHJ P,LPTSET ;SET UP NEW BUFFER POINTER
PJRST LPTSTP ;ERROR IN BUFFER, SHUT DOWN IO
PJRST LPTGO ;GO START IT UP
LPTNX2: TRNE S,LPTNFF ;SUPPRESS FORM FEEDS?
PJRST LPTSTP ;YES--GO SHUT DOWN IO
TLO S,LPTSYN ;NO--MARK CRFF SENT SO DON'T ADVANCE BUFFERS
PUSHJ P,LPTSTI ;SET OUTPUT FOR CRFF
PJRST LPTGO ;GO START IT UP
;HERE TO CHECK IF THE VFU WAS BEING LOADED BY MONITOR
; AND NOT BY USER (DEVOP.); IF SO, OUTPUT UUO MUST BE CONTINUED
CHKVFU: CAIN T2,LPWDVU ;WERE WE LOADING THE VFU?
TLZN S,LPTVFU ;YES--WAS IT BY MONITOR, NOT USER?
PJRST LPTSTP ;NO--NOTHING ELSE TO DO NOW
PJRST LPTOU1 ;YES--CONTINUE THE OUTPUT UUO
SUBTTL ERROR INTERRUPT ROUTINES -- DISPATCH
LPTERR: TRNE T3,LPWDVN ;VFU ERROR?
JRST LPTVFE ;YES HANDLE VFU ERROR
TRNE T2,LPWPZR ;PAGE-ZERO?
JRST LPTPZR ;YES, HANDLE ZERO PAGE COUNTER
TRNE T2,LPWCI ;UNDEFINED CHARACTER?
JRST LPTUCI ;YES, HANDLE IT
TRNE T3,LPWPER ;LINE PRINTER PARITY?
JRST LPTPAR ;YES, HANDLE PARITY ERROR
TRNE T3,LPWRPE ;RAM PARITY ERROR?
JRST LPTRPE ;YES, HANDLE IT
TRNE T3,LPWSYE!LPWDME!LPWMPE ;ANY HARD ERRORS?
JRST LPTHRD ;YES, HANDLE IT
TRNE T3,LPWOFL ;OFF-LINE?
JRST LPTNOL ;YES, HANDLE IT
TRNE T3,LPWGOE ;GO ERROR?
JRST LPTGOE ;YES, HANDLE IT
;HERE IF ON-LINE OR ERROR RESET INTERRUPT
MOVSI T1,DVOFLN ;OFF-LINE BIT
TDNN T1,DEVCHR(F) ;WAS THE LPT OFF-LINE?
POPJ P, ;NO--ERROR CLEARING, JUST DISMISS
ANDCAM T1,DEVCHR(F) ;YES--CLEAR OFF-LINE BIT
PUSHJ P,PSIONL## ;TELL USER LPT IS NOW ON-LINE
POPJ P, ;DISMISS
SUBTTL ERROR INTERRUPT ROUTINES -- HANDLERS
;HERE ON PAGE-COUNTER ZERO INTERRUPT
LPTPZR: MOVE T2,LPTPAG(F) ;GET THE PAGE COUNTER
MOVEI T1,IOPLE% ;LOAD THE ERROR CODE
JUMPE T2,LPTPZ2 ;IT'S EMPTY, TELL USER
PUSHJ P,LPTSPC ;ELSE, SET IT
PJRST LPTGO ;GO RESTART PRINTER, IF NECESSARY
LPTPZ2: TLO S,LPTOPB ;SET PARTIAL BUFFER PENDING
PJRST LPTIOE ;GIVE USER ERROR AND RETURN
;HERE ON LINE-PRINTER PARITY ERROR
LPTPAR: PUSHJ P,LPTSYR ;DO SYSERR REPORTING
MOVEI T1,IOPAR% ;LOAD PARITY ERROR
PJRST LPTIOE ;GIVE USER ERROR AND RETURN
;HERE ON LINE-PRINTER VFU ERROR
LPTVFE: PUSHJ P,LPTSYR ;TELL SYSERR
PUSHJ P,LPTNOL
TLO S,LPTVFU ;MARK VFU FOR RELOADING IF USER DOESN'T
MOVEI T1,IOVFE% ;VFU ERROR
PJRST LPTIOE ;GIVE USER ERROR AND RETURN
;HERE WHEN LINE PRINTER IS OFF-LINE
LPTNOL: MOVSI T1,DVOFLN ;MARK LPT OFF-LINE
IORM T1,DEVCHR(F) ;FOR ON-LINE INTERRUPT
TLO S,LPTOPB ;INDICATE POSSIBLE PARTIAL BUFFER
PJRST DEVERR## ;CAUSE UUOCON TO RETRY ON UUO LEVEL
;HERE ON RAM PARITY ERROR
LPTRPE: PUSHJ P,LPTSYR ;DO SYSERR REPORTING
TLO S,LPTRAM ;MARK RAM FOR RELOADING IF USER DOESN'T
MOVEI T1,IORPE% ;LOAD RAM PARITY ERROR
PJRST LPTIOE ;GIVE IT TO USER
;HERE ON "HARD" ERRORS
LPTHRD: PUSHJ P,LPTSYR ;DO SYSERR REPORTING
MOVE U,LPTCDB(F) ;GET CHAN DATA BLOCK
MOVEI T1,UNBTMO!UNBBME
BSIO T1,@CHNUBA(U) ;CLEAR ANY UBA ERRORS
MOVEI T1,IODER% ;LOAD ERROR CODE
PJRST LPTIOE ;GIVE IT TO USER
;HERE ON A GO ERROR
LPTGOE: HRRZ T1,LPTSTS(F) ;GET CSRB BEFORE LAST "GO"
TRNE T1,LPWOFL ;DID THE LPT DROP OFF-LINE?
PJRST LPTGO ;YES--JUST GO RESTART IT
PUSHJ P,LPTSYR ;NO--DO SYSERR REPORTING
STOPCD CPOPJ##,JOB,ULE ;++UNEXPECTED LP20 ERROR
;HERE ON UNDEFINED CHARACTER
LPTUCI: RDIOB T3,LPRAMD(T1) ;GET RAM DATA FOR THIS CHARACTER
CAIE T3,"^" ;IS THIS FOR UP-ARROW TRANSLATION?
JRST LPTUC1 ;NO--HANDLE AS REAL ERROR
TLO S,LPTARW ;FLAG DOING UP-ARROW MODE
RDIO T3,LPBSAD(T1) ;READ CURRENT BUS ADDRESS
TRZ T2,777717 ;ISOLATE HIGH-ORDER ADDRESS BITS IN CSRA
LSH T2,14 ;SHIFT TO BITS 19-20 (16-17 OF -11)
IORI T3,(T2) ;FORM COMPLETE 18-BIT ADDRESS
HRLM T3,LPTRSV(F) ; AND SAVE IT
RDIO T2,LPBCTR(T1) ;READ CURRENT BYTE COUNTER
HRRM T2,LPTRSV(F) ; AND SAVE IT
MOVEI T2,LPTBUF(F) ;ADDRESS OF FIRST WORD IN LPT BUFFER
MOVE T3,(T2) ;GET CONTENTS
MOVEM T3,LPTWSV(F) ; AND SAVE IT
MOVEI T3,"^" ;GET AN UP-ARROW
DPB T3,[POINT 8,(T2),17] ;PUT WHERE IT WILL BE PRINTED FROM
RDIOB T3,LPCBUF(T1) ;GET THE CONTROL CHARACTER
TRO T3,100 ;MAKE IT A PRINTING CHARACTER
ANDI T3,177 ;GET RID OF ANY GARBAGE BITS
DPB T3,[POINT 10,(T2),9] ;PUT IN BUFFER & CLEAR BITS 0-1
MOVNI T2,2 ;NEGATIVE NUMBER OF CHARS TO PRINT
MOVE P3,LPTCDB(F) ;POINT TO THE CDB TO GET INITIAL ADDR
PUSHJ P,REGSE2 ;SET LP20 REGISTERS
PJRST LPTGO ;PRINT THE TWO CHARACTERS
LPTUC1: RDIO T2,LPRAMD(T1) ;GET RAM DATA
HRLM T2,LPTUDC(F) ; AND SAVE HERE (FOR POSSIBLE DEVOP.)
RDIO T2,LPCBUF(T1) ;GET CHAR BUFFER DATA
HRRM T2,LPTUDC(F) ; AND SAVE HERE
MOVEI T1,IOUNC% ;LOAD ERROR CODE
PJRST LPTIOE ;GIVE USER ERROR AND RETURN
;HERE WHEN WE FINISHED AN UP-ARROW TRANSLATION TO CONTINUE NORMAL PRINTING
ARWFIN: MOVE T2,LPTWSV(F) ;GET SAVED BUFFER WORD
MOVEM T2,LPTBUF(F) ; AND RESTORE IT
HRRZ T2,LPTRSV(F) ;GET SAVED BYTE COUNTER
WRIO T2,LPBCTR(T1) ; AND RESTORE IT
HLRZ T2,LPTRSV(F) ;GET SAVED BUS ADDRESS
PUSHJ P,REGSE3 ; AND RESTORE IT
PJRST LPTGO ;CONTINUE PRINTER
SUBTTL SETUP NEXT BUFFER ROUTINES
;HERE FOR NEXT REGULAR BUFFER (OR LAST PARTIAL)
;SKIP RETURN IF NO ERRORS
LPTSET: MOVE T1,LPTBAS(F) ;GET BASE ADDRESS OF I/O REGISTERS
TLZN S,LPTOPB ;POSSIBLE PARTIAL BUFFER PENDING?
JRST LPTSE1 ;NO--GO AHEAD
MOVEI T3,7777 ;12 BITS IN THE BYTE COUNTER
TIOE T3,LPBCTR(T1) ;IS THERE SOMETHING LEFT?
PJRST CPOPJ1## ;YES--RETURN TO COMPLETE PARTIAL
LPTSE1: MOVEI T2,@DEVOAD(F) ;GET USER ADDR. OF CURRENT BUFFER
MOVN T3,1(T2) ;GET NEG WORD COUNT FROM BUFFER HEADER
JUMPE T3,LPTSTN ;ZERO LENGTH? SEND NULLS TO GET DONE INTERRUPT
HRLI T2,(T3) ;FORM IOWD IN T2
AOS T2 ;BUMP T2 FOR IOWD; DO THIS BUFFER
MOVN T3,T3 ;POSITIVE WORD COUNT
CAIG T3,MAXLBZ ;EXCEEDING MAX BUFFER SIZE POSSIBLE?
JRST LPTSE2 ;NO--PROCEED
TRO S,IOBKTL ;YES--SET BLOCK TOO LARGE
POPJ P, ;GIVE NON-SKIP RETURN
LPTSE2: AOS (P) ;SET FOR SKIP RETURN
IMULI T3,5 ;CONVERT WDS TO BYTES (5 7-BIT BYTES/WD)
MOVEM T3,LPTBYT(F) ;SAVE IT HERE
LPTSE3: SETZM LPTFNC(F) ;SET FOR REGULAR PRINT FUNCTION
PJRST REGSET ;GO SET IT UP
;HERE TO SETUP NEXT OUTPUT AS <NUL><NUL>
LPTSTN: AOS (P) ;SET FOR SKIP RETURN
SKIPA T2,[LPNULL-1] ;MAKE IOWD TO NULLS, FALL INTO LPTSTI
;HERE TO SETUP NEXT OUTPUT AS <CR><FF>
LPTSTI: HRRI T2,LPCRFF-1 ;MAKE IOWD TO CRFF
HRLI T2,-1 ;PUT IN WORD COUNT
MOVEI T3,2 ;BYTE COUNT
MOVEM T3,LPTBYT(F) ;SAVE IT
TLO S,IOSMON ;INDICATE MONITOR IO TO MAPIO
PJRST LPTSE3 ;GO SET IT UP
LPNULL: BYTE (7)0,0 ;<NUL><NUL>
LPCRFF: BYTE (7)15,14 ;<CR><FF>
;HERE TO SETUP NEXT OUTPUT AS THE DEFAULT VFU LOAD
LPTSTV: HRRI T2,VFUBUF-1 ;MAKE IOWD TO DATA
HRLI T2,-VFUBFZ ;PUT IN WORD COUNT
MOVE T3,VFUBUF+VFUBFZ-1 ;GET BYTE COUNT
MOVEM T3,LPTBYT(F) ;SAVE IN DDB
MOVEI T3,LPWDVU ;VFU LOAD FUNCTION BITS
MOVEM T3,LPTFNC(F) ;SAVE IN DDB
TLO S,IOSMON ;INDICATE MONITOR IO TO MAPIO
PJRST REGSET ;GO SET IT UP
SUBTTL SETUP REAL BUFFER AND LP20 REGISTERS ROUTINE
; HERE WITH IOWD IN T2 TO SETUP "REAL" OUTPUT BUFFER AND THEN
; SET THE LP20 REGISTERS.
REGSET: MOVEM T2,LPTPTR(F) ;LPTPTR GETS IOWD TO BUFFER
HRRZI T3,1(T2) ;SOURCE BUFFER ADDRESS TO RH(T3)
HRLI T3,(<POINT 7,0>);FORM BYTE POINTER TO IT
MOVE T4,LPTBYT(F) ;BYTE COUNT TO T4
MOVE U,LPTFNC(F) ;FUNCTION BITS
CAIN U,LPWDVU+LPWTM ;ARE WE LOADING THE RAM?
JRST REGSE1 ;YES--CONTINUE
MOVEI T2,LPTBUF(F) ;NO--"REAL" OUTPUT BUFFER ADDRESS TO T2
CAIN U,LPWDVU ;ARE WE LOADING THE VFU?
PUSHJ P,SHUFLR ;YES--REPACK DATA AND SKIP RETURN
PUSHJ P,SHUFL ;NO--REPACK DATA AND RETURN
HRRI T2,LPTBUF-1(F) ;BUFFER ADDRESS-1 TO T2
HRLI T2,-LPTBFZ ;FORM COMPLETE IOWD FOR MAPIO
TLO S,IOSMON ;INDICATE MONITOR IO TO MAPIO
REGSE1: SETZB P1,P4 ;FIRST CALL,NO FRAME COUNT
MOVE P3,LPTCDB(F) ;GET POINTER TO CHANNEL DATA BLOCK
PUSHJ P,MAPIO## ;SET UP UNIBUS ADAPTOR REGISTERS
JRST LPTSTP ;SHOULDN'T HAPPEN
TLZ S,IOSMON ;CLEAR MONITOR IO BIT
MOVN T2,LPTBYT(F) ;GET NEGATIVE BYTE COUNT
REGSE2: WRIO T2,LPBCTR(T1) ;SET IN BYTE COUNT REGISTER
MOVE T2,CHNIEA(P3) ;GET -11 STYLE ADDRESS
REGSE3: WRIO T2,LPBSAD(T1) ;SET IN BUS ADDRESS REGISTER
LSH T2,-14 ;ISOLATE TWO HIGH ORDER BITS OF ADDRESS
TRZ T2,777717 ; IN PROPER POSITION FOR LPCSRA
IOR T2,LPTFNC(F) ;PUT IN THE FUNCTION BITS
WRIOB T2,LPCSRA(T1) ;SET THEM
POPJ P, ; AND RETURN
SUBTTL DEVOP UUO INTERFACE -- DISPATCH
;HERE ON DISPATCH FROM UUOCON
; F=DDB
; T1=FUNCTION
LPTDVP: MOVSI T2,-LPTDVL ;GET TABLE LENGTH SETUP AOBJN PTR
LPTDV1: HLRZ T3,LPTDVT(T2) ;GET THE FUNCTION CODE
HRRZ T4,LPTDVT(T2) ;GET THE DISPATCH ADDRESS
CAMN T1,T3 ;DO CODES MATCH?
JRST (T4) ;YES, DISPATCH
AOBJN T2,LPTDV1 ;NO, LOOP
PJRST ECOD2## ;NO MATCH, GIVE AN ERROR
LPTDVT: XWD 11,DVLRAM ;LOAD RAM
XWD 12,DVLVFU ;LOAD VFU
XWD 1000,DVPC ;READ PAGE COUNTER
XWD 2000,DVPC ;SET PAGE COUNTER
XWD 1004,DVDCS ;READ DEVICE STATUS
XWD 1005,DVFRMR ;READ FORMS TYPE NAME
XWD 2005,DVFRMS ;SET FORMS TYPE NAME
LPTDVL==.-LPTDVT ;DISPATCH TABLE LENGTH
SUBTTL DEVOP UUO INTERFACE -- HANDLERS
;HERE TO LOAD RAM OR VFU WITH DATA FROM USER
DVLRAM: PUSHJ P,LPTOFL ;IF OFF-LINE, GET IT FIXED
MOVEI T3,LPWDVU+LPWTM ;FUNCTION BITS FOR RAM LOAD
TLZ S,LPTRAM ;CLEAR DEFAULT LOAD BIT
SETZ P2,0 ;RAM FLAG
JRST DVLVF0 ;CONTINUE
DVLVFU: PUSHJ P,LPTOFL ;IF OFF-LINE, GET IT FIXED
MOVEI T3,LPWDVU ;FUNCTION BITS FOR VFU LOAD
TLZ S,LPTVFU ;CLEAR DEFAULT LOAD BIT
MOVEI P2,1 ;VFU FLAG
DVLVF0: MOVEM S,DEVIOS(F) ;UPDATE DDB COPY
PUSHJ P,WAIT1## ;MAKE SURE ANY IO HAS STOPPED
PUSHJ P,GETWR1## ;GET RAM/VFU BYTE COUNT ARGUMENT
PJRST ECOD3## ;ERROR
JUMPLE T1,ECOD3## ;ERROR IF .LE. ZERO
MOVEM T1,LPTBYT(F) ;SAVE BYTE COUNT HERE
ADDI T1,3(P2) ;FUDGE REMAINDER
IDIVI T1,4(P2) ;MAKE T1 A WORD COUNT
CAILE T1,^D128 ;WITHIN RANGE?
PJRST ECOD3## ;NO--ERROR
PUSH P,T1 ;SAVE IT
MOVN T2,T1 ;NEGATIVE WORD COUNT
HRLZS T2 ;FORM LH OF IOWD
PUSHJ P,GETWR1## ;GET ADDRESS OF RAM/VFU DATA
PJRST RTM1## ;COULDN'T--GIVE ADDRESS ERROR
HRRI T2,-1(T1) ;FORM COMPLETE IOWD
MOVEM T2,LPTPTR(F) ;SAVE HERE
MOVEM T3,LPTFNC(F) ;PUT FUNCTION BITS HERE
CAIE T3,LPWDVU ;IS THIS A VFU LOAD?
JRST DVLRA1 ;NO--JUST GO ON
HRRZI T3,1(T2) ;USER VIRT ADDRESS HERE
MOVE T1,0(P) ;WORD COUNT HERE
PUSHJ P,GTEVBF## ;GO MAP THIS INTO EVM
STOPCD TPOPJ1,JOB,NEM, ;++NO EXEC VIRTUAL MEMORY
MOVEM T1,0(P) ;SAVE EVM USAGE WORD
MOVE T2,LPTPTR(F) ;GET IOWD
HRRI T2,-1(T3) ;UPDATE WITH EXEC ADDRESS
DVLRA1: MOVE T1,LPTBAS(F) ;GET BASE ADDRESS OF I/O REGISTERS
PUSHJ P,REGSET ;GO SET UP LP20
MOVEI T1,LPWDVU ;VFU LOAD FUNCTION BITS
CAME T1,LPTFNC(F) ;LOADING THE VFU?
JRST DVLRA2 ;NO--PROCEED
MOVE T2,0(P) ;GET EVM USAGE WORD
LDB T1,[POINT 9,T2,35] ;NO. OF PAGES
PUSHJ P,GIVEVM## ;RETURN THE STUFF
DVLRA2: PUSHJ P,LPTGO ;START UP THE IO
PJRST TPOPJ1## ;GIVE A GOOD RETURN
;HERE TO READ OR SET THE PAGE COUNTER
DVPC: MOVE T3,DEVHCW(F) ;GET CHARACTERISTICS
TLNN T3,(HC.PGC) ;DEVICE HAVE PAGE COUNTER?
PJRST ECOD11## ;NO, ERROR
TRNE T1,1000 ;READ?
JRST DVPC1 ;YES
PUSHJ P,GETWR1## ;NO, SET T1=PAGE ARG
PJRST RTM1## ;ERROR
SETOM LPTPAG(F) ;ASSUME -1
JUMPE T1,CPOPJ1## ;RETURN
MOVEM T1,LPTPAG(F) ;STORE NEW PAGE COUNTER WORD
PUSHJ P,LPTSPC ;SET PAGE COUNTER
JRST CPOPJ1##
DVPC1: SKIPGE LPTPAG(F) ;ATTEMPT TO READ WHEN
PJRST ECOD10## ; NOT SET
MOVE T1,LPTBAS(F) ;GET BASE ADDRESS OF I/O REGISTERS
RDIO T1,LPPCTR(T1) ;GET PAGE COUNTER
ANDI T1,7777 ;ONLY THESE BITS
ADD T1,LPTPAG(F) ;ADD IN REMAINING AMOUNT
PJRST STOTC1## ;RETURN WITH PAGE COUNT IN T1
;HERE TO READ LPT STATUS
DVDCS: MOVEI T1,0 ;INITIALIZE
MOVE T2,LPTBAS(F) ;GET BASE ADDRESS OF I/O REGISTERS
RDIO T2,LPCSRB(T2) ;GET SECOND STATUS REGISTER
TRNE T2,LPWOFL ;OFF-LINE?
TLO T1,(DV.OFL) ;YES
TRNE T2,LPWDVN ;DAVFU ERROR?
TRO T1,DV.VFE ;YES
PJRST STOTC1## ;STORE STATUS/GOOD RETURN
;HERE TO READ OR SET THE FORMS TYPE NAME
DVFRMR: MOVE T1,LPTFRM(F) ;GET FORMS NAME
JRST STOTC1## ;GIVE IT TO THE USER
DVFRMS: PUSHJ P,GETWR1## ;FETCH USER'S ARGUMENT
JRST RTM1## ;ADDRESS CHECK ERROR
MOVEM T1,LPTFRM(F) ;SAVE IT FOR POSTERITY
JRST CPOPJ1## ;SUCCESS RETURN
SUBTTL VARIOUS UTILITY ROUTINES
;SUBROUTINE TO SET THE HARDWARE PAGE COUNTER
; IF SOFTWARE PAGE COUNTER WORD (SPCW) IS .EQ. 0, JUST RETURN
; ELSE SET HARDWARE PAGE COUNTER TO MAX(SPCW,7777) I IF THE
; SPCW IS NOT-NEGATIVE, DECREMENT IT BY THE AMOUNT SET.
LPTSPC: SKIPN LPTPAG(F) ;IS THERE ANYTHING TO SET?
POPJ P, ;NO, JUST RETURN
SKIPL U,LPTPAG(F) ;GET THE SPCW
CAILE U,7777 ;WITHIN RANGE OF HARDWARE?
MOVEI U,7777 ;NO, PUT WITHIN RANGE
MOVE T1,LPTBAS(F) ;GET BASE ADDRESS OF I/O REGISTERS
WRIO U,LPPCTR(T1) ;SET THE PAGE COUNTER
MOVNS U ;NEGATE THE AC
SKIPL LPTPAG(F) ;DONT DECREMENT IF NOT SET
ADDM U,LPTPAG(F) ;DECREMENT THE SPCW
POPJ P, ;AND RETURN
;SUBROUTINE TO SEE IF THE LPT IS ON LINE
LPTONL: MOVE T1,LPTBAS(F) ;GET BASE ADDRESS OF I/O REGISTERS
PUSHJ P,UBGOOD## ;IS LP20 ALIVE ON THE UNIBUS?
POPJ P, ;NO--RETURN OFF-LINE
RDIO T2,LPCSRB(T1) ;YES--GET SECOND STATUS REGISTER
TRNN T2,LPWOFL ;IS PRINTER OFF-LINE?
AOS (P) ;NO--IT'S ON-LINE, SO SKIP RETURN
POPJ P, ;EITHER ON-LINE OR OFF
;HERE TO STOP THE LPT AND START THE USER.
LPTSTP: MOVE T1,LPTBAS(F) ;GET BASE ADDRESS OF IO REGISTERS
PUSHJ P,UBGOOD## ;IS LP20 ALIVE ON THE UNIBUS?
JRST LPTST1 ;NO--DON'T TRY TO ACCESS IT
MOVEI T2,LP1IEN ;INTERRUPT ENABLE BIT
BCIOB T2,LPCSRA(T1) ;TURN'EM OFF
LPTST1: PUSHJ P,SETIOD## ;CLEAR IOW, REQUE IF NEEDED
PUSHJ P,CLRACT## ;CLEAR IOACT, UPDATE S
PJRST RTEVMO## ;RETURN ANY EVM
;HERE TO GIVE THE USER AN I/O ERROR AND DISMISS THE INTERRUPT.
; ERROR CODE IN T1.
LPTIOE: DPB T1,PDVESE## ;STORE THE ERROR CODE
TRO S,740000 ;SET ALL ERRORS
PJRST LPTSTP ;GO SHUTDOWN IO AND START USER
;HERE TO DO DAEMON ERROR REPORTING FOR SYSERR
LPTSYR: MOVE U,LPTCDB(F) ;GET CHAN DATA BLOCK
RDIO T2,@CHNUBA(U) ;READ UBA STATUS REGISTER
MOVEM T2,LPTDAE+.HCL20(F) ;SAVE IT
MOVE T1,LPTBAS(F)
RDIO T3,LPCSRA(T1) ;GET CSRA
LSH T3,-4 ;POSITION 2 BIT ADDRESS EXTENSION
RDIO T2,LPBSAD(T1) ;GET ENDING BUS ADDRESS
DPB T3,[POINT 2,T2,19] ; AND PUT IN HIGH ORDER BITS
IDIVI T2,UBAMUL ;COMPUTE MAP REGISTER OFFSET
ADDI T2,UBAEXP ;ADD IN THE BASE ADDRESS
HLL T2,CHNUBA(U) ;PUT IN PROPER UBA NUMBER
RDIO T3,(T2) ;READ OUT MAP SLOT OF LAST WORD XFER'ED
MOVEM T3,LPTDAE+.HCL21(F) ;SAVE IT
RDIO U,LPCSRA(T1) ;GET FIRST STATUS REGISTER
RDIO T2,LPCSRB(T1) ;GET SECOND STATUS REGISTER
HRLI T2,(U) ;PUT IN LH(T2)
MOVEM T2,LPTDAE+.HCL22(F) ;SAVE IT
RDIO U,LPBSAD(T1) ;GET BUS ADDRESS REGISTER
RDIO T2,LPBCTR(T1) ;GET BYTE COUNTER
HRLI T2,(U) ;PUT IN LH(T2)
MOVEM T2,LPTDAE+.HCL23(F) ;SAVE IT
RDIO U,LPPCTR(T1) ;GET PAGE COUNTER
RDIO T2,LPRAMD(T1) ;GET RAM DATA
HRLI T2,(U) ;PUT IN LH(T2)
MOVEM T2,LPTDAE+.HCL24(F) ;SAVE IT
RDIO U,LPCBUF(T1) ;GET CHAR BUFFER AND COL COUNT
RDIO T2,LPTDAT(T1) ;GET PRINTER DATA AND CHECKSUM
HRLI T2,(U) ;PUT IN LH(T2)
MOVEM T2,LPTDAE+.HCL25(F) ;SAVE IT
MOVE T2,JBTPPN##(J) ;PICK UP PPN
MOVEM T2,LPTDAE+.HCUID(F) ;SAVE IT
MOVE T2,JBTPRG##(J) ;PICK UP PROGRAM NAME
MOVEM T2,LPTDAE+.HCPGM(F) ;SAVE IT
MOVEI T1,.ERHCC ;LOAD SYSERR TYPE
HRLI T1,LPTDAP(F) ;POINTER TO AOBJN POINTER
PJRST DAEERR## ;CALL DAEMON
;HERE TO SETUP HARDWARE CHARACTERISTICS WORD AND DETERMINE CONTROLLER TYPE
LPTTYP: MOVSI T3,DVLPTL ;GET LOWER CASE PRINTER BIT
TDNN T3,DEVCHR(F) ;A LOWER CASE PRINTER?
TDZA T3,T3 ;NO, UPPER CASE
MOVSI T3,(HC.LCP) ;YES, NOTE THAT
TLNN T3,(HC.LCP) ;A LOWER CASE PRINTER?
TDZA T2,T2 ;NO, UPPER CASE
MOVEI T2,.HCC95 ;YES, THEN FLAG AS 96-CHAR SET ALSO
DPB T2,[POINT 3,T3,8] ;STORE IN HARDWARE CHARACTERISTICS
MOVEI T2,LPWOVF ;OPTICAL VFU BIT
SETZ T4, ;ASSUME WE HAVE AN OPTICAL UNIT
TION T2,LPCSRB(T1) ;DO WE?
MOVEI T4,.HCVTD ;NO, MUST BE DAVFU
DPB T4,[POINT 3,T3,5] ;STORE THAT
CAIE T4,.HCVTD ;DID WE DECIDE IT WAS A LOADABLE VFU?
TLZ S,LPTVFU ;NO, CLEAR THE FLAG REQUESTING VFU LOAD
TLO T3,(HC.PGC) ;LP20 HAS A HARDWARE PAGE COUNTER
MOVEI T2,.CTLP2 ;INDICATE LP20
DPB T2,[POINT 3,T3,11] ;STORE THAT
TLO T3,(<.HCULP>B14) ;LP05 CLASS PRINTER
HLLM T3,DEVHCW(F) ;STORE HARDWARE CHARACTERISTICS
DPB T2,[POINT 6,LPTDAE+.HCTYP(F),5] ;AND CONTROLLER TYPE
MOVEI T2,.DELPT ;INDICATE LPT DEVICE
DPB T2,[POINT 6,LPTDAE+.HCTYP(F),11] ;STORE IT
POPJ P, ;RETURN
;ROUTINE TO CLEAR AND THEN SET THE RAM FOR STANDARD SETTINGS
RESRAM: MOVE T1,LPTBAS(F) ;GET BASE ADDRESS OF IO REGISTERS
MOVEI T2,377 ;MAXIMUM RAM ADDRESS
SETZ T3, ;A ZERO
RESRA1: WRIOB T2,LPCBUF(T1) ;SET THIS RAM ADDRESS
WRIO T3,LPRAMD(T1) ;ZERO THIS RAM ENTRY
SOJGE T2,RESRA1 ;GO THRU THE WHOLE RAM
MOVEI T2,RAMTSZ-1 ;SIZE OF RAMTAB MINUS 1
RESRA2: HLRZ T3,RAMTAB(T2) ;GET RAM CHAR (=RAM ADDRESS)
WRIOB T3,LPCBUF(T1) ;SET THIS RAM ADDRESS
HRRZ T3,RAMTAB(T2) ;GET CORRESPONDING RAM BITS TO LOAD
WRIO T3,LPRAMD(T1) ;LOAD THEM
SOJGE T2,RESRA2 ;BACK FOR ANOTHER
MOVSI T2,DVLPTL ;A LOWER CASE PRINTER?
TDNE T2,DEVCHR(F)
POPJ P, ;YES--RETURN
MOVEI T2,36 ;NO--NUMBER OF LOWER CASE CODES
RESRA3: MOVEI T3,140(T2) ;THE LOWER CASE CHARACTER CODE
WRIOB T3,LPCBUF(T1) ;SET THIS RAM ADDRESS
MOVEI T3,1000-40(T3) ;TRANS BIT + UPPER CASE CODE
WRIO T3,LPRAMD(T1) ;SET IN RAM
SOJGE T2,RESRA3 ;BACK FOR ANOTHER
POPJ P, ;RETURN
RAMTAB: XWD 12,1407 ;LF,,CHANNEL 8
XWD 13,1406 ;VT,,CHANNEL 7
XWD 14,1400 ;FF,,CHANNEL 1
XWD 20,1401 ;DLE,,CHANNEL 2
XWD 21,1402 ;DC1,,CHANNEL 3
XWD 22,1403 ;DC2,,CHANNEL 4
XWD 23,1404 ;DC3,,CHANNEL 5
XWD 24,1405 ;DC4,,CHANNEL 6
RAMTSZ==.-RAMTAB ;SIZE OF RAMTAB
;ROUTINE TO CHANGE CONTIGUOUS BYTES IN -10 FORMAT TO SHUFFLED BYTES
;IN -11 FORMAT. CALL:
; T2/ ADDRESS TO RECEIVE SHUFFLED BYTES
; T3/ BYTE POINTER TO CONTIGUOUS BYTES
; T4/ NUMBER OF BYTES TO DO
SHUFL: PUSHJ P,SAVE2## ;NEED A COUPLE OF THESE REGISTERS
SHUFL1: SOJL T4,CPOPJ## ;DONE, SO QUIT
ILDB P1,T3 ;GET FIRST BYTE
SOJL T4,SHUFL3 ;DONE AFTER FIRST BYTE
ILDB P2,T3 ;GET NEXT CHARACTER
LSH P2,^D8 ;SHIFT INTO POSITION
IOR P2,P1 ;PUT CHARACTERS TOGETHER
HRLZM P2,(T2) ;STORE CHARACTERS
SOJL T4,CPOPJ## ;DONE
ILDB P1,T3 ;GET ANOTHER CHARACTER
SOJL T4,SHUFL4 ;DONE
ILDB P2,T3 ;GET LAST CHARACTER
LSH P2,^D8 ;PUT INTO POSITION
IOR P2,P1 ;PUT CHARACTERS TOGETHER
HRRM P2,(T2) ;STORE CHARACTERS
AOJA T2,SHUFL1 ;NEXT WORD
SHUFL3: HRLZM P1,(T2) ;STORE CHARACTER
POPJ P, ;RETURN
SHUFL4: HRRM P1,(T2) ;STORE CHARACTER
POPJ P, ;RETURN
;ROUTINE TO CHANGE CONTIGUOUS BYTES IN -10 FORMAT TO SHUFFLED BYTES
;IN -11 FORMAT. ALSO CONVERT BA10/LP100 START/STOP CODES TO LP20 STYLE.
;CALL:
; T2/ ADDRESS TO RECEIVE SHUFFLED BYTES
; T3/ BYTE POINTER TO CONTIGUOUS BYTES
; T4/ NUMBER OF BYTES TO DO
;GIVES A SKIP RETURN ALWAYS (FOR CONVENIENCE OF HOW IT WAS CALLED)
SHUFLR: PUSHJ P,SAVE3## ;NEED A COUPLE OF THESE REGISTERS
SETO P3, ;SET FLAG INDICATING FIRST BYTE
SHUFR1: SOJL T4,CPOPJ1## ;DONE, SO QUIT
ILDB P1,T3 ;GET FIRST BYTE
PUSHJ P,CHKSTR ;DO START CODE CONVERSION IF NEEDED
PUSHJ P,CHKST1 ;DO STOP CODE CONVERSION
SOJL T4,SHUFR3 ;DONE AFTER FIRST BYTE
ILDB P2,T3 ;GET NEXT CHARACTER
PUSHJ P,CHKST2 ;DO STOP CODE CONVERSION
LSH P2,^D8 ;SHIFT INTO POSITION
IOR P2,P1 ;PUT CHARACTERS TOGETHER
HRLZM P2,(T2) ;STORE CHARACTERS
SOJL T4,CPOPJ1## ;DONE
ILDB P1,T3 ;GET ANOTHER CHARACTER
PUSHJ P,CHKST1 ;DO STOP CODE CONVERSION
SOJL T4,SHUFR4 ;DONE
ILDB P2,T3 ;GET LAST CHARACTER
PUSHJ P,CHKST2 ;DO STOP CODE CONVERSION
LSH P2,^D8 ;PUT INTO POSITION
IOR P2,P1 ;PUT CHARACTERS TOGETHER
HRRM P2,(T2) ;STORE CHARACTERS
AOJA T2,SHUFR1 ;NEXT WORD
SHUFR3: HRLZM P1,(T2) ;STORE CHARACTER
PJRST CPOPJ1## ;RETURN
SHUFR4: HRRM P1,(T2) ;STORE CHARACTER
PJRST CPOPJ1## ;RETURN
;HERE TO DO START CODE CONVERSION
CHKSTR: SKIPN P3 ;IS THIS THE FIRST BYTE?
POPJ P, ;NO--RETURN
CAIN P1,25 ;STANDARD START CODE?
MOVEI P1,356 ;YES--LP20 VERSION
CAIN P1,26 ;6 LPI?
MOVEI P1,354 ;YES--LP20 VERSION
CAIN P1,27 ;8 LPI?
MOVEI P1,355 ;YES--LP20 VERSION
SETZ P3, ;CLEAR FIRST BYTE FLAG
POPJ P, ;RETURN
;HERE TO CONVERT STOP CODE IN P1
CHKST1: CAIN P1,126 ;IS IT THE STOP CODE?
MOVEI P1,357 ;YES--LP20 VERSION
POPJ P, ;RETURN
;HERE TO CONVERT STOP CODE IN P2
CHKST2: CAIN P2,126 ;IS IT THE STOP CODE?
MOVEI P2,357 ;YES--LP20 VERSION
POPJ P, ;RETURN
SUBTTL MACROS FOR GENERATING DEFAULT VFU DATA
; THE FOLLOWING MACROS ARE USED TO GENERATE VFUBUF, WHICH CONTAINS
; THE DEFAULT VFU DATA TO BE LOADED. THE DEFAULT DATA IN COMBINATION WITH
; THE DEFAULT RAM DATA LOADED BY THE RESRAM ROUTINE WILL MAKE
; THE LP20 AND ITS PRINTER OPERATE SIMILIARLY TO A BA10/LP100 STYLE SYSTEM.
DEFINE MOD(A,B),<A-<<A/B>*B>> ;TAKE A MODULO B
; MACRO OUTBYT - USED TO GENERATE A STREAM OF 7-BIT BYTES. CALLED EACH TIME
; A BYTE NEEDS OUTPUTING. ASSEMBLES 5 7-BIT BYTES AND THEN OUTPUTS A
; EXP PSEUDO-OP.
DEFINE OUTBYT(B),<
..BC==..BC+1 ;;INCREMENT THE BYTE COUNT
..BP==..BP+7 ;;BUMP THE POSITION POINTER BY BYTE SIZE
B==<B&177>_<^D35-..BP> ;;MAKE SURE ONLY 7 BITS WIDE AND THEN
;;SHIFT TO PROPER POSITION IN CURRENT WORD
..B==..B!B ;;PUT BYTE INTO ACCUMULATOR
IFE ..BP-^D34,< ;;IF WE'RE AT THE LAST BYTE IN CURRENT WORD
..BP==-1 ;;RESET POSITION POINTER TO BEGINNING
EXP ..B ;;ASSEMBLE THE WORD
..B=0 ;;CLEAR OUT THE ACCUMULATOR
>;END IFE
>;END DEFINE
; MACRO LASBYT - MUST BE CALLED AFTER ANY USAGE OF OUTBYT MACRO TO ENSURE
; THAT THE LAST BYTE(S) GET OUTPUT.
DEFINE LASBYT,<
IFN ..B,< ;;IF THERE IS SOMETHING LEFT IN THE ACCUMUALTOR
EXP ..B ;; ASSEMBLE IT
>;END IFN
EXP ..BC ;;ASSEMBLE BYTE COUNT AS LAST WORD
>;END DEFINE
; MACRO VFUBIT - CALLED TO OUTPUT TWO BYTES OF DATA FOR A PARTICULAR
; LINE NUMBER IN THE VFU. GENERATES CHANNEL BIT SETTINGS FOR
; A STANDARD VFU TAPE.
DEFINE VFUBIT(LINE),<
..BT==0 ;;ZERO THE BIT ACCUMULATOR
;;DO 1ST BYTE - CHANNELS 1-6
IFE LINE,<..BT==..BT!1> ;;LINE 0 GETS CHANNEL 1 (TOP OF FORM)
IFE MOD(LINE,36),<..BT==..BT!2> ;;EVERY 30 LINES GETS CHANNEL 2
IFE MOD(LINE,2),<..BT==..BT!4> ;;EVEN NUMBERED LINES GET CHANNEL 3
IFE MOD(LINE,3),<..BT==..BT!10> ;;EVERY 3RD LINE GETS CHANNEL 4
IFE MOD(LINE,12),<..BT==..BT!40>;;EVERY TEN LINES GETS CHANNEL 6
IFLE LINE-^D59,<..BT==..BT!20> ;;ALL LINES GET CHANNEL 5
IFGE LINE-^D60,<..BT==20> ;;LINES 60-65 GET ONLY CHANNEL 5
OUTBYT(..BT) ;;OUTPUT THIS BYTE
;;DO 2ND BYTE - CHANNELS 7-12
..BT==0 ;;ZERO THE BIT ACCUMULATOR
IFE MOD(LINE,24),<..BT==..BT!1> ;;EVERY 20 LINES GET CHANNEL 7
IFLE LINE-^D59,<..BT==..BT!2> ;;LINES 0-59 GET CHANNEL 8
IFE LINE-^D59,<..BT==..BT!40> ;;LINE 59 GETS CHANNEL 12
IFGE LINE-^D60,<..BT==0> ;;LINES 60-65 GET NOTHING
OUTBYT(..BT) ;;OUTPUT THIS BYTE
>;END DEFINE
SUBTTL DEFAULT VFU DATA BUFFER
..BP==-1 ;INITIALIZE POSITION FOR FIRST BYTE
..B==0 ;INITIALIZE BYTE ACCUMULATOR
..BC==0 ;INITIALIZE BYTE COUNT
..L==0 ;INITIALIZE LINE COUNTER
STARTC==25 ;DEFINE START CODE
STOPC==126 ;DEFINE STOP CODE
VFUBUF:
SALL
OUTBYT(STARTC) ;OUTPUT THE START CODE
REPEAT ^D66,< ;66 LINES/PAGE
VFUBIT(..L) ;DO BYTES FOR THIS LINE
..L==..L+1 ;BUMP LINE COUNTER
>;END REPEAT
OUTBYT(STOPC) ;OUTPUT THE STOP COODE
LASBYT ;FINISH UP
XALL
VFUBFZ==.-VFUBUF ;SIZE OF DATA BUFFER
$LIT
END