Trailing-Edge
-
PDP-10 Archives
-
bb-jr93h-bb
-
7,6/ap021/dlpser.x21
There are 3 other files named dlpser.x21 in the archive. Click here to see a list.
TITLE DLPSER - LINEPRINTER SERVICE FOR MULTIPLE RSX-20F LINEPRINTERS - V041
SUBTTL A. WILSON 25-OCT-88
SEARCH F,S,DEVPRM,DTEPRM
$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
; 1977,1978,1979,1980,1982,1984,1986,1988.
;ALL RIGHTS RESERVED.
.CPYRT<1977,1988>
XP VDLPSR,041 ;DEFINE GLOBAL VERSION NUMBER FOR LOADER MAP
PRMMIN==063 ;DTEPRM MUST BE AT LEAST THIS RECENT
IFL VDTPRM-PRMMIN,<PRINTX ?PLEASE USE LATEST VERSION OF DTEPRM
PASS2
END>
DLPSER::ENTRY DLPSER
SUBTTL SYMBOL DEFINITIONS
;DEVICE DEPENDENT BITS IN LH OF DEVIOS
DLPSYN==Z(1B11) ;CRFF AFTER CLOSE HAS BEEN SENT
DLPEND==Z(1B10) ;CLOSE UUO HAS BEEN DONE
DLPOPB==Z(1B9) ;PARTIAL BUFFER ALREADY OUTPUT
;DEVICE DEPENDENT BITS IN RH OF DEVIOS
DLPNFF==100 ;SUPPRESS FREE CRFF
;LPT SPECIFIC STATUS BITS FROM RSX-20F
DL.PGZ==1B35 ;PAGE COUNTER PASSED ZERO
DL.RCI==1B34 ;CHARACTER INTERRUPT (FROM RAM)
DL.VFE==1B33 ;VFU ERROR--PAPER REALIGNMENT REQUIRED
DL.LER==1B32 ;ERROR FINDING/READING VFU/RAM FILE
DL.OVF==1B31 ;PRINTER HAS OPTICAL (NOT DA) VFU
DL.RPE==1B30 ;RAM PARITY ERROR--RELOAD REQUIRED
SUBTTL AUTOCONFIGURE
;DRIVER CHARARCTERISTICS
; DLP = DLPCNF
; LPT = 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 (DLP,LPT,7,0,0,0,MDSEC0,MDSEC0,<DR.GCC!DR.NET>)
.ORG DEVLEN
DLPDUX:! BLOCK 1 ;UNIT # ON FRONT-END,,DTE INDEX
DLPCDN:! BLOCK 1 ;CPU,,DTE NUMBERS
DLPMLA:! BLOCK 1 ;MAXIMUM LINE ALLOCATION
DLPRLA:! BLOCK 1 ;REMAINING LINE ALLOCATION
DLPSNT:! BLOCK 1 ;NUMBER OF WORDS ALREADY SENT
DLPFRM:! BLOCK 1 ;FORMS TYPE NAME (SIXBIT)
DLPLEN:! ;LENGTH OF DTE PRINTER DDB
.ORG
$LOW
DLPDDB: DDBBEG (DLP,DLPLEN)
SETWRD (DEVCHR,<6*HUNGST+DVLPTL,,LPTSIZ##>) ;DEVCHR
SETWRD (DEVSER,<MCSEC0+RLPDSP>) ;DEVSER
SETWRD (DEVMOD,<DVOUT!DVLPT,,<1_A+1_AL+1_BYTMOD+1_I>>) ;DEVMOD
SETWRD (DEVTYP,<<.TYLPT*.TYEST>!.SPLPT!DEPLEN,,0>) ;DEVTYP
DDBEND
$HIGH
EQUATE (LOCAL,0,<DLPCKT,DLPICD,DLPICL,DLPINT,DLPKDB,DLPKLN,DLPUDB,DLPULN>)
EQUATE (LOCAL,0,<DLPULB,DLPULP>)
DLPDSX: DRVDSP (DLP,0,DLPDDB,DLPLEN,URDDIA##)
;DEFAULT MONGEN'ED DEVICE TABLE
DEFMDT: MDKL10 (7,200,0,0,<MD.KON>) ;DEVICE CODE 200
MDKL10 (7,204,0,0,<MD.KON>) ;DEVICE CODE 204
MDKL10 (7,210,0,0,<MD.KON>) ;DEVICE CODE 210
MDKL10 (7,214,0,0,<MD.KON>) ;DEVICE CODE 214
MDTERM
;BITS FOR MDT ENTRIES ARE ASSIGNED HERE
LPT.UC==:1 ;UPPER-CASE ONLY PRINTER
DLPCFG: XMOVEI T1,DLPMDT## ;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
MOVE T1,.CPCPN## ;OUR CPU NUMBER
HRRZ F,DTEMAS##(T1) ;FETCH MASTER DTE
LDB T1,[POINT 7,ETDCNI(F),9] ;GET DTE NUMBER
HRRZ T2,.CPDVC## ;AND DEVICE BEING CONFIGURED
CAIE T1,(T2) ;DOING THE MASTER DTE?
JRST CPOPJ1## ;NO
MOVSI T1,(ED.PPC) ;BIT TO TEST
TDNE T1,ETDSTS(F) ;PRIMARY PROTOCOL RUNNING?
PJRST DLPRDS ;YES--CAN REQUEST DEVICE STATUS DIRECTLY
XMOVEI T1,DLPRDS ;ROUTINE TO REQUEST DEVICE STATUS
MOVEI T2,1 ;WAIT FOR PRIMARY PROTOCOL TO START
PUSHJ P,AUTCLK## ;QUEUE UP A CLOCK REQUEST
JRST CPOPJ1## ;MAYBE OTHER DTE-BASED DEVICES EXIST
;HERE WHILE PRIMARY PROTOCOL IS RUNNING TO REQUEST DEVICE STATUS
DLPRDS: PUSHJ P,SAVE4## ;SAVE SOME ACS
MOVE T1,.CPCPN## ;OUR CPU NUMBER
HRRZ F,DTEMAS##(T1) ;FETCH MASTER DTE
LOAD. P1,ED.DTN,(F) ;GET MASTER DTE NUMBER
HRL P1,.CPCPN## ;INCLUDE OUR CPU NUMBER
MOVE P2,[.EMLPT,,.EMRDS] ;FE DEVICE CODE,,FUNCTION CODE
TDZA P3,P3 ;START WITH UNIT ZERO
DLPRD1: HLLZS P3 ;READ STATUS TAKES UNIT,,0
MOVE P4,[POINT 8,P3,9] ;BYTE POINTER TO UNIT NUMBER
SETZ S, ;NO POST ADDRESS
S0PSHJ DTEQUE## ;QUEUE UP REQUEST FOR DEVICE STATUS
JFCL ;SHOULDN'T FAIL
AOBJN P3,.+1 ;ADVANCE UNIT NUMBER
TLNN P3,-1-DLPMAX##+1 ;OVERFLOW?
JRST DLPRD1 ;LOOP BACK FOR MORE
JRST CPOPJ1## ;MAYBE OTHER DTE-BASED DEVICES EXIST
;HERE WHILE PROCESSING A DEVICE STATUS MESSAGE FOR A PREVIOUSLY
;UNKNOWN DTE-BASED DEVICE TO ACTUALLY BUILD THE DTE DEVICE DATA BASE
;P1 - P4 SETUP WITH DEVICE STATUS MESSAGE POINTERS
DLPDTS: SE1ENT ;ENTER SECTION ONE
PUSHJ P,AUTLOK## ;INTERLOCK THE DATA BASE
JRST [PUSHJ P,DLPRDS ;BUSY & INTERRUPT LEVEL--TRY AGAIN LATER
JFCL ;WILL MOST LIKELY SKIP
POPJ P,] ;CALL THIS A FAILURE
PUSH P,F ;SAVE DDB ADDRESS OR ZERO
MOVE T1,.CPCPN## ;OUR CPU NUMBER
HRRZ F,DTEMAS##(T1) ;AND THE MASTER ETD FOR THIS CPU
LDB T1,[POINT 7,ETDCNI(F),9] ;DEVICE CODE
XMOVEI T2,DLPDSX ;DRIVER DISPATCH
SETZ T3, ;NO CHANNEL
PUSHJ P,AUTSET## ;SET UP AUTCON CALLS
POP P,F ;GET FLAG BACK
JUMPN F,DLPDT1 ;JUMP IF A KNOWN DEVICE
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 [PUSHJ P,AUTULK## ;NO CORE
PJRST AUTDDN##] ;DEALLOCATE DEVICE NUMBER
DLPDT1: MOVEM P1,DLPCDN(F) ;SAVE CPU,,DTE NUMBER
HLLM P3,DLPDUX(F) ;SAVE FE UNIT (LINE) NUMBER
HRRM P1,DLPDUX(F) ;SAVE DTE NUMBER (HISTORICAL)
XMOVEI T1,DLPMDT## ;POINT TO MONGEN'ED DEVICE TABLE
XMOVEI T2,DEFMDT ;GET DEVICE CODES FROM THE DEFAULT TABLE
HLLO T3,P3 ;USE FE UNIT FOR UNIT NUMBER
SETZ T4, ;IGNORE FLAGS
PUSHJ P,AUTMDT## ;SEE IF WE HAVE DATA
JRST DLPDT2 ;THERE IS NONE
MOVSI T2,DVLPTL ;GET LOWER-CASE PRINTER BIT
TRNE T1,LPT.UC ;IF UPPER-CASE ONLY PRINTER
ANDCAM T2,DEVCHR(F) ;THEN CLEAR THE LOWER-CASE BIT
;ADD FUTURE MDT VALUE TESTS HERE
DLPDT2: PUSHJ P,AUTULK## ;RELEASE INTERLOCK
JRST CPOPJ1## ;RETURN
SUBTTL DISPATCH TABLES
;UUOCON DISPATCH TABLE FOR RSX-20F LINEPRINTER(S)
JRST DLPONL ;SEE IF LPT ON-LINE NOW
JRST DLPDVP ;DEVOP. UUO
JRST REGSIZ## ;GET BUFFER SIZE FROM DDB
JRST DLPINI ;INITIALIZATION
JRST DLPHNG ;HUNG DEVICE ERROR
RLPDSP::JRST DLPREL ;RELEASE
JRST DLPCLS ;CLOSE
JRST DLPOUT ;OUT/OUTPUT
JRST ILLINP## ;IN/INPUT
;DTESER DISPATCH TABLE FOR LPT
IFIW CPOPJ## ;(-1) LOST TO-10 INDIRECT MESSAGE
DLPDSP::DTEFNC ;(??) GENERATE DUMMY TABLE ENTRIES
DTEFNC (HDS,DLPTKS) ;(07) TAKE DEVICE STATUS
DTEFNC (ACK,DLPACK) ;(17) ACK
DTEFNC (HLA,DLPHLA) ;(23) LINE ALLOCATIONS
DTEFNC (AKA,DLPAAL) ;(25) ACK ALL
SUBTTL MONITOR-LOAD DEVICE INITIALIZATION
;DLPINI IS CALLED AT SYSTEM INITIALIZATION TIME FROM IOGO IN SYSINI WITH
; THE DDB ADDRESS IN F. DLPINI FORCES IOGO TO INVOKE DLPINI FOR EACH RSX-20F
; LINEPRINTER 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 DLPINI IS DEPENDENT ON THE IOGO CODE WHICH SHOULD BE:
;
; PUSHJ P,DINI(P3)
; HRRZM P3,SAVITM
DLPINI: PUSHJ P,DLPREL ;GO THROUGH RELEASE CODE
PJRST CPOPJ1## ;SKIP RETURN TO FORCE CALL FOR EACH LPT
SUBTTL OUT/OUTPUT UUO
;HERE FROM UUOCON ON OUT OR OUTPUT UUO
DLPOUT: TLO S,IO ;INDICATE OUTPUT
PUSHJ P,DLPOFL ;IF TROUBLE, GET IT FIXED
TLZE S,IOBEG ;FIRST OUTPUT?
PUSHJ P,DLPSFF ;YES, SEE ABOUT SENDING FREE CRFF
JFCL
TLZE S,DLPOPB ;PARTIAL BUFFER ALREADY OUTPUT?
DLPOU0: JRST [SKIPLE DEVCTR(F) ;YES, BUT WERE WE DONE WITH IT
JRST DLPOU1 ;NO, MORE TO PRINT
PUSHJ P,ADVBFE## ;GET NEXT BUFFER HERE
PJRST DLPSTP ;NO MORE, SHUT DOWN PRINTER
JRST .+1] ;RETURN INLINE FOR NEW BUFFER
MOVE T1,DEVOAD(F) ;PICK UP BUFFER ADDRESS
HRRZ T1,1(T1) ;PICK UP WORD COUNT
MOVEM T1,DEVCTR(F) ;SET DEVCTR UP WITH WORD COUNT
SETZM DLPSNT(F) ;NO DATA FROM THIS BUFFER YET
JUMPE T1,DLPOU0 ;GET NEXT IF NO DATA
DLPOU1: PUSHJ P,DLPSND ;START DATA TRANSFER
PJRST SETACT## ;SET IOACT, STORE S, SET HUNG COUNT, RETURN
;HERE DURING OUTPUT UUO TO SEE IF LPT ON-LINE
;ARGS: F/DDB ADDRESS
; S/DEVIOS WORD FROM DDB
;CALL: PUSHJ P,DLPOFL
; RETURN HERE WHEN ON-LINE (BOTHERING USER IF NECESSARY TO GET IT ON-LINE)
DLPOFL: PUSHJ P,DLPONL ;SEE IF LPT ON-LINE
JRST DLPOF1 ;IT'S NOT--TELL THE USER
POPJ P, ;IT IS--RETURN
DLPOF1: MOVEM S,DEVIOS(F) ;SAVE S
MOVSI T1,DEPADV
IORM T1,DEVADV(F) ;LEAVE BUFFERS ALONE
MOVSI T1,DVOFLN
IORM T1,DEVCHR(F) ;MARK DDB OFF-LINE
PUSHJ P,HNGSTP## ;HALT JOB AND COMPLAIN
MOVSI T1,DEPADV
ANDCAM T1,DEVADV(F) ;CLEAR BIT ON RETRY
JRST DLPOFL ;TRY AGAIN
;ROUTINE TO SEE IF LPT ON-LINE
;ARGS: F/DDB ADDRESS
;CALL: PUSHJ P,DLPONL
; RETURN HERE IF OFF-LINE
; RETURN HERE IF ON-LINE
DLPONL: MOVEI T1,EM.OFL+EM.NXD ;GET RSX-20F OFF-LINE BITS
TDNN T1,DEVSTS(F) ;OFF-LINE?
AOS (P) ;NO--SKIP RETURN FOR ON-LINE
POPJ P, ;YES--NON-SKIP RETURN
;HERE TO SEND INITIAL/FINAL CRFF IF NECESSARY
;ARGS: F/DDB ADDRESS
; S/DEVIOS WORD FROM DDB
;CALL: PUSHJ P,DLPSFF
; RETURN HERE IF CRFF NOT SENT
; RETURN HERE IF SENT
DLPSFF: TRNE S,DLPNFF ;NEED TO SEND CRFF?
POPJ P, ;NO--NON-SKIP RETURN
PUSHJ P,SAVE4## ;SAVE P1-P4
MOVE P4,[POINT 7,LPCRFF] ;POINT TO CRFF
MOVEI T1,1 ;ONLY 1 WORD
PUSHJ P,DLPSOU ;SEND THIS STRING
PJRST CPOPJ1## ;SKIP RETURN
LPCRFF: BYTE (7) 15,14,0 ;CR,FF,0
SUBTTL CLOSE AND RELEASE UUO'S
;HERE FROM UUOCON ON CLOSE UUO
DLPCLS: TLO S,DLPEND ;SET "CLOSE DONE"
TLZ S,DLPOPB+DLPSYN ;CLEAR TROUBLE AND SYNC BITS
MOVEM S,DEVIOS(F) ;STORE S
JRST OUT## ;TAKE CARE OF LAST BUFFER
;HERE FROM UUOCON ON RELEASE UUO
;SET UP SOME REASONABLE DEFAULTS FOR LP20-BASED LPT'S
;VARIABLE RAM, LP20/LP05, DAVFU
DLPHCW==INSVL.(.HCT20,HC.TYP)!INSVL.(.HCVTD,HC.VFT)!
INSVL.(.HCCVR,HC.CST)!INSVL.(.HCULP,HC.TYU)
DLPHNG: ;HUNG DEVICE IS SAME AS RELEASE
DLPREL: MOVSI T1,(DLPHCW) ;GET INITIAL HCW WORD
MOVSI T2,DVLPTL ;LPT LOWERCASE BIT
TDNE T2,DEVCHR(F) ;IF SET,
TLO T1,(HC.LCP) ;THEN PROPAGATE TO HCW BITS
MOVSI T2,DL.OVF ;BIT FOR OPTICAL VFU
TDNE T2,DEVSTS(F) ;DID -20F SET IT?
TLC T1,(INSVL.(.HCVTD^!.HCVTO,HC.VFT)) ;YES--CHANGE TO OPTICAL
HLLM T1,DEVHCW(F) ;SET FOR PRYING EYES
MOVSI T1,DEPADV ;GET "DON'T ADVANCE BUFFER" BIT
ANDCAM T1,DEVADV(F) ;TURN IT OFF IN DDB
TLZ S,DLPOPB ;CLEAR PARTIAL BUFFER BIT
PJRST DLPSTP ;CLEAR ACTIVE I/O
SUBTTL ACK MESSAGE ("OUTPUT DONE") PROCESSING
;HERE FROM DTESER ON ACK FOR LPT
DLPACK: SUBI P3,2 ;ACCOUNT FOR TWO BYTES/ARGUMENT
JUMPL P3,CPOPJ## ;RETURN WHEN ARGUMENT COUNT EXHAUSTED
ILDB T3,P4 ;GET UNIT NUMBER
IBP P4 ;MOVE PAST UNUSED BYTE
PUSHJ P,FNDDLP ;FIND CORRECT DLP DDB
PUSHJ P,DLPDON ;TREAT THIS AS DONE INTERRUPT
JRST DLPACK ;LOOP FOR MORE ARGUMENTS
;HERE FROM DTESER ON ACK ALL FOR LPT
DLPAAL: SKIPE F,DDBTAB##+.TYLPT ;POINT TO FIRST LPT IN SYSTEM
DLPAA1: HLRZ F,DEVSER(F) ;LINK TO NEXT
JUMPE F,CPOPJ## ;RETURN IF RUN OUT OF DDBS
LDB T1,PDVTYP## ;GET DEVICE TYPE
CAIE T1,.TYLPT ;CHECKED ALL LPTS?
POPJ P, ;ALL DONE
HRRZ T1,DEVSER(F) ;GET DISPATCH
CAIE T1,RLPDSP ;OWNED BY US?
JRST DLPAA1 ;TRY ANOTHER
CAMN P1,DLPCDN(F) ;CPU#,,DTE# MATCH?
PUSHJ P,DLPDON ;YES--TREAT THIS AS DONE INTERRUPT
JRST DLPAA1 ;GO CHECK OUT THE NEXT LPT
SUBTTL HERE ARE LINE ALLOCATIONS PROCESSING
;HERE FROM DTESER ON HERE ARE LINE ALLOCATIONS FOR LPT
DLPHLA: SUBI P3,2 ;ACCOUNT FOR TWO BYTES/ARGUMENT
JUMPL P3,CPOPJ## ;RETURN WHEN ARGUMENT COUNT EXHAUSTED
ILDB T2,P4 ;GET ALLOCATION
ILDB T3,P4 ;GET LINE NUMBER
PUSHJ P,FNDDLP ;FIND SPECIFIED DDB
MOVEM T2,DLPMLA(F) ;SAVE LINE ALLOCATION
JRST DLPHLA ;LOOP FOR MORE
SUBTTL OUTPUT DONE PROCESSING
;HERE IF RSX-20F ACKNOWLEDGED AN ACTIVE LINEPRINTER
;ARGS: F/DDB ADDRESS
; S/LPT STATUS WORD (DDB DEVIOS)
;CALL: PUSHJ P,DLPDON
; RETURN HERE
DLPDON: PUSHJ P,IOSET## ;SET UP THE REST OF THE REGS
MOVE T1,DLPMLA(F) ;PICK UP MAX ALLOCATION
MOVEM T1,DLPRLA(F) ;THIS IS CURRENT ALLOCATION
TRNN S,IOACT ;OUTPUT ACTIVE?
POPJ P, ;NO, RETURN
SKIPLE DEVCTR(F) ;OUTPUT REMAINING FROM PREVIOUS BUFFER?
JRST DLPDN1 ;YES--WORK ON THAT BUFFER SOME MORE
TLZE S,DLPEND ;CLOSE DONE?
JRST DLPDN2 ;YES--SEE ABOUT FINAL CRFF
TLZN S,DLPSYN ;NO--CRFF JUST OUTPUT?
DLPDN0: PUSHJ P,ADVBFE## ;NO--ADVANCE TO NEXT BUFFER
PJRST DLPSTP ;CAN'T--SHUT DOWN LPT
PUSHJ P,SETIOD## ;ARRANGE FOR JOB TO RUN AGAIN
MOVE T1,DEVOAD(F) ;PICK UP BUFFER ADDRESS
HRRZ T1,1(T1) ;PICK UP WORD COUNT
MOVEM T1,DEVCTR(F) ;SET DEVCTR UP WITH WORD COUNT
SETZM DLPSNT(F) ;NO, THIS BUFFER IS DONE
JUMPE T1,DLPDN0 ;IGNORE EMPTY BUFFERS
DLPDN1: PUSHJ P,DLPSND ;START UP NEXT OUTPUT
PJRST STOIOS## ;SAVE S, SET HUNG COUNT, RETURN
DLPDN2: PUSHJ P,DLPSFF ;SEE ABOUT SENDING CRFF
PJRST DLPSTP ;NOT SENT--SHUT DOWN LPT
TLO S,DLPSYN ;REMEMBER CRFF SENT SO DON'T ADVANCE BUFFERS
PJRST STOIOS## ;SAVE S, SET HUNG COUNT, RETURN
;HERE TO STOP LPT AND START USER
DLPSTP: TRZ S,IOACT ;CLEAR IOACT
MOVEM S,DEVIOS(F) ;SAVE DEVIOS
PUSHJ P,SETIOD## ;START UP THE USER
PJRST RTEVMO## ;RETURN ANY EVM
SUBTTL SEND LPT DATA TO FRONT-END
;HERE TO SEND OUTPUT DATA TO RSX-20F LPT FROM USER BUFFER
;ARGS: F/DDB ADDRESS
;CALL: PUSHJ P,DLPSND
; RETURN HERE
DLPSND: PUSHJ P,SAVE4## ;SAVE P1-P4
MOVE P4,DEVPTR(F) ;PICK UP DATA ADDRESS
ADDI P4,2 ;POINT TO FIRST DATA WORD
ADD P4,DLPSNT(F) ;OFFSET POINTER TO REMAINING DATA
HRLI P4,440700 ;ASSUME 7 BIT BYTES
LDB T1,PIOMOD## ;PICK UP I/O MODE
CAIN T1,BYTMOD ;REALLY BYTE MODE?
HRLI P4,441000 ;YES, 8 BIT BYTES
HRRZ T1,DEVCTR(F) ;PICK UP REMAINING WORD COUNT
PUSHJ P,DLPSOU ;SEND THIS STRING
ADDM T1,DLPSNT(F) ;ACCUMULATE WORD COUNT
MOVNS T1 ;NEED NEGATIVE OF COUNT
ADDM T1,DEVCTR(F) ;DECREMENT REMAINING COUNT
POPJ P, ;DONE
;HERE TO SEND STRING OUTPUT DATA TO RSX-20F LPT
;ARGS: F/DDB ADDRESS
; T1/WORD COUNT
; P4/BYTE POINTER
;CALL: PUSHJ P,DLPSOU
; RETURN HERE WITH WORDS SENT IN T1
DLPSOU: LDB T3,[POINT 6,P4,11] ;PICK UP BYTE SIZE
MOVEI T2,44 ;36 BITS/WORD
IDIVI T2,(T3) ;NOW GOT BYTES/WORD
MOVE T3,DLPRLA(F) ;PICK UP REMAINING ALLOCATION
IDIVI T3,(T2) ;CONVERT TO WORDS
CAMLE T1,T3 ;SMALLER THAN STRING LENGTH?
MOVE T1,T3 ;YES, USE ALLOCATION
JUMPLE T1,CPOPJ## ;RETURN IF NO ALLOCATION LEFT
MOVE P3,DLPDUX(F) ;P3 IS UNIT #,,DLP DTE INDEX
MOVE P1,DLPCDN(F) ;P1 IS CPU#,,DTE#
MOVE P2,[.EMLPT,,EM.IND+.EMSTR] ;OUTPUT INDIRECT STRING TO LPT
IMULI T2,(T1) ;GET STRING LENGTH IN BYTES
HRR P3,T2 ;PUT INTO ARG LIST
MOVNS T2 ;NEGATE
ADDM T2,DLPRLA(F) ;UPDATE REMAINING ALLOCATION
PUSH P,S ;SAVE S
PUSH P,T1 ;SAVE WORD COUNT
MOVEI S,0 ;NO POST ADDRESS
PUSHJ P,DTEQUE## ;QUEUE THE REQUEST
JFCL ;FAILED--WAIT FOR HUNG TIME-OUT OR ACK ALL
POP P,T1 ;RESTORE WORD COUNT
POP P,S ;RESTORE S
POPJ P, ;DONE
SUBTTL TAKE DEVICE STATUS FROM FRONT-END
;HERE FROM DTESER TO TAKE LPT STATUS FROM FRONT-END (DTESER ALREADY RECEIVED IT)
DLPTKS: PUSHJ P,SETRGS ;SET UP NECESSARY ACS
PJRST EATMSG## ;COULDN'T--IGNORE THIS MESSAGE
ILDB T1,P4 ;GET FIRST STATUS (GENERAL) BYTE
ILDB T2,P4 ;GET SECOND (LPT) BYTE
HRL T1,T2 ;PUT THEM TOGETHER
MOVEM T1,DEVSTS(F) ;SAVE COMBINED STATUS BITS
MOVEI T2,.HCVTO ;CODE FOR OPTICAL VFU
TLNE T1,DL.OVF ;IS IT OPTICAL TYPE
DPB T2,[POINT 3,DEVHCW(F),5] ;YES, SAVE IN CHARACTERISTICS WORD
MOVEI T2,IOPAR% ;CODE FOR RAM ERROR
TLNE T1,DL.RCI+DL.RPE ;ANY RAM PROBLEMS?
JRST DLPIOE ;YES
MOVEI T2,IOVFE% ;NO, CODE FOR VFU PROBLEM
TLNE T1,DL.VFE ;VFU PROBLEM?
JRST DLPIOE ;YES
MOVEI T2,IODER% ;CODE FOR DEVICE ERROR
TRNN T1,EM.FER ;FATAL ERROR (ALL RETRIES FAILED)
JRST DLPTK2 ;NO, GO CHECK FOR OFFLINE
DLPIOE: DPB T2,PDVESE## ;STORE THE CODE
TRO S,740000 ;SET ALL ERROR FLAGS IN S
TRO T1,EM.OFL ;DECLARE PRINTER OFF-LINE
PUSH P,S ;SAVE STATUS
PUSH P,T1 ;SAVE STATUS FOR A MOMENT
PUSHJ P,[PUSHJ P,SAVE4 ;SAVE SOME REGS
HRRI P2,.EMFLO ;FLUSH ANY REMAINING OUTPUT
HRRI P3,0 ;NO DATA
SETZB P4,S ;NO POST ROUTINE
PJRST DTEQUE##] ;SEND MESSAGE TO CFE
JFCL ;IGNORE FAILURE
POP P,T1 ;GET BACK STATUS
POP P,S ;RESTORE S
;HERE TO DEAL WITH OFF-LINE OR ON-LINE
DLPTK2: MOVE T2,DEVCHR(F) ;PICK UP OLD STATUS
MOVSI T3,DVOFLN ;OFF-LINE BIT
TRNE T1,EM.OFL!EM.NXD ;DEVICE THERE?
JRST DLPTK3 ;NO
ANDCAM T3,DEVCHR(F) ;ASSUME ON-LINE
TLNE T2,DVOFLN ;WAS IT OFF-LINE?
PUSHJ P,PSIONL## ;YES, TELL USER IT IS BACK AGAIN
PJRST EATMSG## ;DONE WITH THIS MESSAGE
DLPTK3: MOVEM S,DEVIOS(F) ;MAKE SURE ERROR BITS ARE SAVED
TRNN S,IOACT ;PRINTER ACTIVE NOW?
PJRST EATMSG## ;NO, DONE WITH THIS MESSAGE
IORM T3,DEVCHR(F) ;NOTE DEVICE OFF-LINE
TLNN T1,DL.RCI+DL.RPE+DL.VFE ;ANY ERRORS IN LPT?
TLO S,DLPOPB ;NO, INDICATE MINOR TROUBLE NOTICED
PUSHJ P,DLPSTP ;STOP LPT AND START USER
PUSHJ P,DEVERR## ;CAUSE UUOCON TO RETRY ON UUO LEVEL
PJRST EATMSG## ;DONE
SUBTTL DEVOP. UUO INTERFACE
;HERE FROM UUOCON ON DEVOP. UUO
;ARGS: F/DDB ADDRESS
; T1/FUNCTION
;CALL: PUSHJ P,DLPDVP
; RETURN HERE ON ERROR OR INVALID FUNCTION
; RETURN HERE ON SUCCESS, T1 CONTAINING ANY ARGUMENT RETURNED
DLPDVP: MOVSI T2,-DLPDVL ;MAKE AOBJN POINTER WITH TABLE LENGTH
DLPDV1: HLRZ T3,DLPDVT(T2) ;GET THE FUNCTION CODE
HRRZ T4,DLPDVT(T2) ;GET DISPATCH ADDRESS
CAMN T1,T3 ;CODES MATCH?
JRST (T4) ;YES--DISPATCH
AOBJN T2,DLPDV1 ;NO--TRY NEXT ONE
PJRST ECOD2## ;NO MATCH--ERROR
DLPDVT: 11,,DVPRAM ;LOAD LPT RAM
12,,DVPVFU ;LOAD LPT VFU
1004,,DVPSTS ;READ DEVICE STATUS
1005,,DVPFTR ;READ FORMS TYPE
2005,,DVPFTS ;SET FORMS TYPE
DLPDVL==.-DLPDVT ;DISPATCH TABLE LENGTH
;HERE TO READ LPT STATUS
DVPSTS: MOVEI T1,0 ;ZERO INITIAL STATUS
MOVE T2,DEVSTS(F) ;GET STATUS BITS SENT FROM FRONT-END
TRNE T2,EM.OFL+EM.NXD ;OFF-LINE?
TLO T1,(DV.OFL) ;YES
TLNE T2,DL.VFE ;VFU ERROR?
TRO T1,DV.VFE ;YES
PJRST STOTC1## ;STORE STATUS, SKIP RETURN
;HERE TO READ/SET FORMS TYPE NAME
DVPFTR: MOVE T1,DLPFRM(F) ;GET FORMS NAME
JRST STOTC1## ;RETURN IT TO THE USER
DVPFTS: PUSHJ P,GETWR1## ;FETCH USER'S ARGUMENT
JRST RTM1## ;ADDRESS CHECK ERROR
MOVEM T1,DLPFRM(F) ;SET FOR POSTERITY
JRST CPOPJ1## ;SUCCESS RETURN
;ROUTINE TO LOAD LPT RAM/VFU
;ARGS: F/DDB ADDRESS
; M/USER ARGUMENT AREA ADDRESS
;CALL: SAVE P1-P4
; PUSHJ P,DVPXXX WHERE XXX IS RAM OR VFU
; RETURN HERE IF UNSUCCESSFUL
; RETURN HERE IF SUCCESSFUL
DVPRAM: TDZA P2,P2 ;REMEMBER LOADING RAM
DVPVFU: MOVEI P2,1 ;REMEMBER LOADING VFU
PUSHJ P,DLPOFL ;MUST BE ON-LINE
PUSHJ P,GETWR1## ;GET RAM/VFU BYTE-COUNT ARG FROM USER
PJRST ECOD3## ;ERROR
JUMPLE T1,ECOD3## ;ERROR IF BYTE COUNT NOT GREATER THAN ZERO
MOVE P3,T1 ;REMEMBER BYTE COUNT
ADDI T1,3(P2) ;FUDGE REMAINDER
IDIVI T1,4(P2) ;MAKE T1 A WORD-COUNT
CAILE T1,^D128 ;WITHIN REASON?
PJRST ECOD3## ;NO--OUT-OF-RANGE ERROR
MOVN P1,T1 ;YES--GET -WC
HRLZS P1 ;MAKE LH OF AOBJN POINTER
PUSHJ P,GETWR1## ;GET ADDRESS OF RAM/VFU DATA BLOCK
PJRST RTM1## ;COULDN'T--GIVE ADDRESS-ERROR RETURN
HRRI M,-1(T1) ;PREPARE FOR CALL TO GETWR1
MOVEI T2,^D160 ;WORDS OF MONITOR FREE CORE
PUSHJ P,GETWDS## ;ALLOCATE CORE
PJRST ECOD3## ;NOT REALLY OUT OF RANGE, BUT ...
MOVE P4,T1 ;REMEMBER ADDRESS OF FREE CORE
HRR P1,T1 ;FINISH BUILDING AOBJN POINTER
JUMPN P2,DVPVF1 ;GO GET VFU DATA
DVPMOV: PUSHJ P,GETWR1## ;GET WORD FROM USER
PJRST [PUSHJ P,DVPGIV ;ERROR--GIVE BACK FREE CORE
PJRST RTM1##] ;GIVE ADDRESS-ERROR RETURN
MOVEM T1,(P1) ;SAVE WORD IN OUR BUFFER AREA
AOBJN P1,DVPMOV ;LOOP IF MORE DATA TO MOVE
HRLI P4,(POINT 18,) ;P4 IS BYTE POINTER
MOVE P2,[.EMLPT,,EM.16B+EM.IND+.EMLDR] ;FUNCTION WORD
PUSH P,P3 ;SET UP THE BYTE COUNT
JRST DVPCMN ;GO TO COMMON PART
DVPVF1: HRLI P1,(POINT 8,0) ;MAKE OUTPUT BYTE POINTER
MOVE P2,P3 ;PICK UP BYTE COUNT
PUSHJ P,DVPVB1 ;GET A VFU BYTE
CAIN T2,25 ;STANDARD START CODE?
MOVEI T2,356 ;YES
CAIN T2,26 ;6 LPT?
MOVEI T2,354 ;YES
CAIN T2,27 ;8 LPT?
MOVEI T2,355 ;YES
SKIPA ;ALREADY HAVE FIRST BYTE
DVPVF2: PUSHJ P,DVPVFB ;GET ANOTHER BYTE
PUSH P,T2 ;BYTES NEED TO SWAP
SOJG P2,DVPVF3 ;COUNT IT
SETZ T2, ;PUT A ZERO BYTE FOR LAST
JRST DVPVF4 ;GO STORE IT
DVPVF3: PUSHJ P,DVPVFB ;GET NEXT BYTE
CAIN T2,126 ;STOP CODE?
MOVEI T2,357 ;YES
DVPVF4: IDPB T2,P1 ;PUT BYTE INTO OUTPUT
POP P,T2 ;GET SWAPPED BYTE
IDPB T2,P1 ;PUT IT INTO OUTPUT ALSO
SOJG P2,DVPVF2 ;LOOP THRU WHOLE VFU
HRLI P4,(POINT 16,) ;SET UP BYTE POINTER FOR DTESER
MOVE P2,[.EMLPT,,EM.16B+EM.IND+.EMLDV] ;SET UP FUNCTION WORD
PUSH P,P3 ;SAVE ON STACK NOW
DVPCMN: MOVE P3,DLPDUX(F) ;P3 IS UNIT #,,DLP DTE INDEX
MOVE P1,DLPCDN(F) ;GET CPU#,,DTE#
PUSH P,S ;SAVE S
HRRZ S,P4 ;SET S TO BUFFER ADDR
DVPPRT: MOVEI T1,300 ;DO MAX OF 300 BYTE TRANSFERS
CAML T1,-1(P) ;FEWER BYTES REMAINING?
MOVE T1,-1(P) ;YEP, USE SMALLER NUMBER
HRR P3,T1 ;PUT COUNT INTO MESSAGE
MOVNS T1 ;CALCULATE REMAINING DATA
ADDM T1,-1(P)
SKIPG -1(P) ;LAST MESSAGE?
HRLI S,DVPGIV ;YES, GIVE BACK CORE ON THIS ONE
PUSHJ P,DTEQUE## ;YES--QUEUE THE REQUEST
PJRST DLPERR ;ERROR--SAY DEVICE OFF-LINE
ADDI P4,300/4 ;POINT TO NEXT PART OF STRING
SKIPE -1(P) ;DONE?
JRST DVPPRT ;NO, GO DO THE NEXT PART
PUSHJ P,DLPEOF ;SEND EOF TO TERMINATE LOAD FUNCTION
PJRST DLPER1 ;ERROR--SAY DEVICE OFF-LINE
POP P,S ;RESTORE S
POP P,(P) ;THROW AWAY COUNT
PJRST CPOPJ1## ;SKIP RETURN
DVPVFB: TLNE T3,760000 ;MORE DATA STILL IN WORD?
JRST DVPVB2 ;YES, GO GET IT
DVPVB1: PUSHJ P,GETWR1## ;NO, GET NEXT WORD
PJRST [POP P,(P) ;POP OFF RETURN
PUSHJ P,DVPGIV ;GIVE BACK CORE
PJRST RTM1##] ;GIVE ADDRESS-ERROR RETURN
MOVE T3,[POINT 7,T1] ;RESET BYTE POINTER
DVPVB2: ILDB T2,T3 ;GET A BYTE
POPJ P, ;RETURN
DLPERR: PUSHJ P,DVPGIV ;GIVE BACK FREE CORE
DLPER1: POP P,S ;RESTORE S
POP P,(P) ;THROW AWAY COUNT
PJRST ECOD7## ;SAY DEVICE OFF-LINE
;ROUTINE TO GIVE BACK MONITOR FREE CORE
;ARGS: RH(S)/ADDRESS OF FREE CORE AREA
;CALL: PUSHJ P,DVPGIV
; RETURN HERE
DVPGIV: MOVEI T1,^D160 ;RETURN THE WORDS WE USED
HRRZ T2,S ;GET ADDRESS OF CORE AREA
PJRST GIVWDS## ;GIVE IT BACK
;ROUTINE TO SET EOF STATUS FOR FRONT-END LPT
;ARGS: F/DDB ADDRESS
;CALL: SAVE P1-P4,S
; PUSHJ P,DLPEOF
; RETURN HERE IF UNSUCCESSFUL
; RETURN HERE IF EOF SENT SUCCESSFULLY
DLPEOF: MOVE P3,DLPDUX(F) ;P3 IS UNIT #,,DLP DTE INDEX
MOVE P1,DLPCDN(F) ;GET CPU#,,DTE#
MOVE P2,[.EMLPT,,EM.16B+EM.IND+.EMHDS] ;SET DEVICE STATUS FOR LPT
HRRI P3,2 ;TWO 8-BIT BYTES OF STATUS
MOVE P4,[POINT 16,[BYTE (16) EM.EOF]]
MOVEI S,0 ;NO POST ROUTINE OR VALUE TO SAVE
PUSHJ P,DTEQUE## ;QUEUE THE REQUEST
POPJ P, ;ERROR--NON-SKIP RETURN
PJRST CPOPJ1## ;SUCCESS--SKIP RETURN
SUBTTL GENERAL SUBROUTINES
;INTERRUPT REGISTER SETUP
;CALL WITH:
; P1=CPU #,,DTE #
; P3=LINE,,DATA COUNT
; P4=BYTE POINTER TO MESSAGE
SETRGS: MOVE T1,P4 ;COPY BYTE POINTER
ILDB T1,T1 ;GET GENERAL STATUS BYTE
TRNE T1,EM.NXD ;NON-EXISTANT DEVICE?
POPJ P, ;THEN WE CERTAINLY DON'T KNOW ABOUT IT
MOVE F,DDBTAB##+.TYLPT ;POINT TO PROTOTYPE DDB
SETRG1: HLRZ F,DEVSER(F) ;LINK TO NEXT
JUMPE F,SETRG2 ;GO CONFIGURE IF END OF CHAIN
LDB T1,PDVTYP## ;GET DEVICE TYPE
CAIE T1,.TYLPT ;STILL LOOKING AT RIGHT TYPE?
JRST SETRG2 ;NO--MUST CONFIGURE
HRRZ T1,DEVSER(F) ;GET DISPATCH
CAIN T1,RLPDSP ;OWNED BY US?
CAME P1,DLPCDN(F) ;AND CPU,,DTE NUMBERS MATCH?
JRST SETRG1 ;TRY NEXT DDB
HLRZ T1,DLPDUX(F) ;GET FE UNIT (LINE) NUMBER
HLRZ T2,P3 ;AND THE ONE FROM THE MESSAGE
CAIE T1,(T2) ;MATCH?
JRST SETRG1 ;TRY ANOTHER
AOS (P) ;GIVE SKIP RETURN
PJRST IOSET## ;GET THE REST OF THE AC'S
SETRG2: SETZ F, ;UNKNOWN DEVICE
PUSHJ P,DLPDTS ;AUTOCONFIGURE A LINE PRINTER
POPJ P, ;FAILED
AOS (P) ;GIVE SKIP RETURN
PJRST IOSET## ;GET THE REST OF THE AC'S
FNDDLP: MOVE F,DDBTAB##+.TYLPT ;POINT TO PROTOTYPE DDB
FNDDL1: HLRZ F,DEVSER(F) ;LINK TO NEXT
JUMPE F,CPOPJ1## ;NO LPTS??
LDB T1,PDVTYP## ;GET DEVICE TYPE
CAIE T1,.TYLPT ;STILL LOOKING AT RIGHT TYPE?
JRST CPOPJ1## ;GIVE UP
HRRZ T1,DEVSER(F) ;GET DISPATCH
CAIN T1,RLPDSP ;OWNED BY US?
CAME P1,DLPCDN(F) ;AND CPU,,DTE NUMBERS MATCH?
JRST FNDDL1 ;TRY NEXT DDB
HLRZ T1,DLPDUX(F) ;GET FE UNIT (LINE) NUMBER
CAIE T1,(T3) ;MATCH?
JRST FNDDL1 ;TRY ANOTHER
POPJ P, ;RETURN WITH DDB IN AC 'F'
SUBTTL END
END