;<134-TENEX>LINEPR.MAC;65    23-JUN-75 22:00:41    EDIT BY ALLEN
; EXTERNED BUGCHK
;<134-TENEX>LINEPR.MAC;64    28-APR-75 12:41:08    EDIT BY CLEMENTS
;<134-TENEX>LINEPR.MAC;63    28-APR-75 11:39:30    EDIT BY CLEMENTS
;<134-TENEX>LINEPR.MAC;62    24-APR-75 14:20:03    EDIT BY CLEMENTS
;<134-TENEX>LINEPR.MAC;61    29-JAN-75 13:42:34    EDIT BY CLEMENTS
; MAKE ARG TO ASGJFR LARGER FOR SPOOLED OPEN IN CASE OF 39 CHAR NAME.
;<134-TENEX>LINEPR.MAC;60    21-JAN-75 13:55:09    EDIT BY CLEMENTS
; REMOVE MULTIPLE FORMFEEDS FROM LPTCLZ. LEAVE THIS UP TO
; SPOOLERS OR OPERATORS. SAVE TREES.
;<TENEX-132>LINEPR.MAC;59     5-JUN-74 11:24:25    EDIT BY CLEMENTS
; GET RID OF SOME MORE "EOL" CHARS, PUT IN CRLF'S
;<TENEX-132>LINEPR.MAC;58     2-MAY-74 14:43:22	EDIT BY TOMLINSON
; SWITCHED TO NEW ASCII CHARACTERS
;<TENEX-132>LINEPR.MAC;57    17-APR-74 23:25:35	EDIT BY TOMLINSON
;<TENEX-132>LINEPR.MAC;56    16-APR-74 13:01:52	EDIT BY ALLEN
;<TENEX-132>LINEPR.MAC;55     5-APR-74 11:24:43	EDIT BY TOMLINSON
; SWAP UPARROW WITH CARAT AND UNDERLINE WITH LEFTAROW
;<TENEX-132>LINEPR.MAC;54    21-DEC-73 12:02:22	EDIT BY ALLEN
; ELIMINATE CALL TO ARCSQ
;<TENEX-132>LINEPR.MAC;53    20-NOV-73 22:26:06	EDIT BY CLEMENTS
; CHANGES TO RUN EITHER LP10 OR BBN PRINTER.
; REMOVED FORCED ACCOUNT SETTING ON SPOOLED LPT
; PRIORITY SETTING CALL TO ADJUST QUEUE AFTER I/O WAIT
;<FILESYSTEM>LINEPR.MAC;49    25-AUG-72 17:52:09	EDIT BY TOMLINSON
;<FILESYSTEM>LINEPR.MAC;48    29-JUN-72 12:47:57	EDIT BY TOMLINSON
;<FILESYSTEM>LINEPR.MAC;47    29-JUN-72 10:14:01	EDIT BY TOMLINSON

	SEARCH	STENEX,PROLOG
IFDEF LPTN,<
	TITLE	LINEPRINTER
	SUBTTL	R.S.Tomlinson

;ASSEMBLES FOR LP10 (DEC) OR BBN (ONE-OF-A-KIND) LINEPRINTER
;DEPENDING ON FLAGS LP10F AND BBNPF

; Externally defined symbols

EXTERN	PBYTPO,PBYTSZ,BUGCHK
EXTERN	ASGJFR,RELFRE,FPTA,GDIRST,JOBDIR,MLKPG,MPP,MULKPG,UNLCKF
EXTERN	CPOPJ,SKPRET,LCKTST,BUGHLT,BUGNTE,MRETN,DISL,CAPENB
IFDEF LPTDVF,<
EXTERN	LPTCHR		; Return from line printer interrupt
EXTERN	LPTTIM		; Lpt check timer
EXTERN	DISLE		; Disms til arg .le. 0

; Entries to this part

INTERN	LPTSV,LPTRST	; Interrupt routine
INTERN	LPTCHK		; Check routine

; Parameters and fixed core locations

   IFN BBNPF,<
LPTCCW==167		; Line printer control word location
LPT=124>		; Line printer device
PI==4
IOS=6

LS(LPTINR)		; Return address in interrupt routine
LPSTKL==10		; Interrupt stack length
LS(LPSTK,LPSTKL)	; Stack for interrupt routine
LS(LPTSTS)		; Status word
LS(LPTOFC)		; Off-line count
LS(LPTRLP)		; Real core address for line printer
LS(LPTCNT)		; Buffer counter
LS(LPTPOS)		; Page position word
LS(LPTJOB)		; Job of last lpt opener
NRP(LPTBUF,1000)
>
LS(LPTLCK)		; Lock on opening lpt

IFDEF LPTDVF,<
FLG(ALTP,L,IOS,400000)
FLG(ALTI,L,IOS,200000)
FLG(OUERR,L,IOS,100000)	; Output error
FLG(OPN,L,IOS,040000)	; Line printer open
IFN BBNPF,<FLG(ESC,L,IOS,020000)> ; Escape character seen
FLG(CRSW,L,IOS,010000)	; Carret seen

   IFN LP10F,<		;LP10 DEFS
LS LPTCLS,1		;LPTCHK CLOCK SWITCH
LS LPTCCW,1		;BLKI/O PTR
LS LPTCKT,1		;INTERVAL FOR LPTTIM

FLG(FSTBUF,L,IOS,020000) ;FIRST BUFFER
FLG(LAST,L,IOS,004000)	;LAST WORD SENT

LPTBOT==10*LPTCHN+LPTCHN ;PRINTER HAS 2 PI ASSMTS
LPTCLR==1B25		;CONI/O BITS
LPTERR==1B27
LPTBSY==1B28
LPTDON==1B29
   >			;END OF LP10 DEFINITIONS
>

; Line printer dispatch table

SPLDTB::
LPTDTB::CPOPJ		; Set directory
	CPOPJ		; Name lookup
	CPOPJ		; Extension
	CPOPJ		; Version
	CPOPJ		; Protection insertion
	CPOPJ		; Account
	CPOPJ
	LPTOPN
	CPOPJ
	LPTSQO		; Output
	LPTCLZ
	CPOPJ		; Rename
	CPOPJ		; Delete
	CPOPJ		; Dump
	CPOPJ
	CPOPJ		; Mount
	CPOPJ		; Dismount
	CPOPJ		; Initialize directory
	CPOPJ		; Mtape
	CPOPJ		; Get status
	CPOPJ		; Set status


; Initialize line printer

	USE	RESPC

LPTINI::IFDEF LPTDVF,<
   IFN LP10F,<
	MOVSI A,(1B1)
	MOVEM A,LPTCKT>		;LPTTIM INTERVAL
	SETZM LPTSTS
	SETOM LPTCNT
	SETZM LPTPOS>
	SETOM LPTLCK
	POPJ P,

LPTRST:	IFDEF LPTDVF,<
	MOVE IOS,LPTSTS
	SKIPL LPTCNT
	JRST LPTSTR>
	POPJ P,

	USE	SWAPPC

; Open line printer

LPTOPN:	IFDEF LPTSPL,<
	HLRZ A,FILDDN(JFN)
	MOVE A,1(A)
	CAME A,[ASCII /LPT/]
IFDEF LPTDVF,<
	 JRST [	MOVEI B,600000
		MOVEI A,WHELX1
		TDNN B,CAPENB
		 POPJ P,
		JRST LP1OPN]>
IFNDEF LPTDVF,<
	 JRST LP1OPN>

	MOVEI A,400000
	PUSH P,CAPENB		; Save current capenb
	IORM A,CAPENB		; Give ourselves wheel status
LPTOPA:	MOVEI B,^D8+3+1		; 8 WORDS FOR NAME, 3 FOR PREFIX, 1 HDR
	PUSHJ P,ASGJFR		; Get some job storage
	 JRST LPTOPC		; Fail to spool
	PUSH P,A
	HRLI A,(<POINT 7,0,35>)
	HRROI B,[ASCIZ /<PRINTER>LPT./]
	SETZ C,
	SOUT
	MOVE B,JOBNO
	HRRZ B,JOBDIR(B)
	DIRST
	 BUG(HLT,<LPTOPN: DIRST OF LOGIN DIRECTORY FAILED>)

LPTOPD:	GTAD			; Use time of day as version
	ANDI A,177777
	XOR A,JFN		; Alter for differing jfn's
	HRLI A,(1B0!1B1!1B8!1B17)
	MOVE B,0(P)
	HRLI B,(<POINT 7,0,35>)
	GTJFN
	 JRST [	POP P,B
		MOVEI A,JSBFRE
		PUSHJ P,RELFRE
		JRST LPTOPC]
	POP P,B
	PUSH P,A
	MOVEI A,JSBFRE
	PUSHJ P,RELFRE
	MOVE A,0(P)
	MOVE B,[XWD 70000,100000]
	OPENF
	 JRST [	POP P,A
		RLJFN
		 JFCL
		JRST LPTOPC]
	NOINT
	PUSHJ P,UNLCKF
	POP P,A
	POP P,CAPENB
	MOVE B,JFN
	LSH B,-SJFN
	SWJFN
	RLJFN
	 JFCL
	MOVE A,MPP
	AOS (A)
	JRST MRETN

LPTOPC:	POP P,CAPENB
LP1OPN:	IFNDEF LPTDVF,<
	MOVEI A,OPNX9
	POPJ P,

LPTSQO:
LPTCLZ:	BUG(CHK,<LPT: LPTSQO OR LPTCLZ CALLED WHEN NO LPT EXISTS>)
	POPJ P,
>>		; Close of ifdef at lptopn and lp1opn

IFDEF LPTDVF,<		;DEVICE CODE - HERE TO END OF FILE
   IFN BBNPF,<	;BBN PRINTER OPEN
	LOCK(LPTLCK,<PUSHJ P,LCKTST>)
	MOVE IOS,LPTSTS
	CONSO LPT,20
	JRST [	UNLOCK LPTLCK
		MOVEI A,OPNX8
		POPJ P,]
	TEST(OE,OPN)
	JRST [	UNLOCK LPTLCK
		MOVEI A,OPNX9
		POPJ P,]	; Busy
	TLZ IOS,ALTP!ALTI!OUERR!ESC
	MOVEM IOS,LPTSTS
	SETOM LPTCNT		; Lpt idle
	MOVEI A,LPTBUF
	MOVES (A)
	PUSHJ P,FPTA		; Get ptn.pn for buffer
	PUSHJ P,MLKPG		; Lock the page
	LSH A,9			; Real page number to real address
	TLO A,-400*4		; 400 word count
	MOVEM A,LPTRLP		; Save
	MOVEI A,8
	DPB A,PBYTSZ		; 8 bit bytes
	MOVEI A,0
	DPB A,PBYTPO		; Position
	MOVEI A,LPTBUF-1
	HRRM A,FILBYT(JFN)	; Point to buffer
	MOVEI A,400*3
	MOVEM A,FILBYN(JFN)	; Character count
	TEST(Z,WNDF)
	SETZM LPTPOS		; Column zero, line 0
	UNLOCK LPTLCK
	MOVEI A,240
	PUSHJ P,LPTOUT
	MOVEI A,77
	PUSHJ P,LPTOUT
	MOVE A,JOBNO
	MOVEM A,LPTJOB
	HRRZ A,JOBDIR(A)	; Get login directory number
	CAIN A,1		; If system
	 JRST SKPRET		; No heading
	PUSHJ P,GDIRST		; Get name string location
	JRST LPTOP4
	UNLOCK DIRLCK		; No need to keep directory locked
	OKINT
	HRLI A,(<POINT 7,0,35>)	; Make it a byte pointer
	PUSH P,A		; Save on stack
	PUSH P,[^D10]		; Number of lines of ident
	MOVEI C,3		; Compute names per ident line
	AOS C
	ILDB B,A
	JUMPN B,.-2
	MOVEI B,^D75
	IDIV B,C
	PUSH P,B

LPTOP1:	PUSH P,0(P)		; Number of names per line
LPTOP2:	PUSH P,-3(P)		; Copy byte pointer to stack
LPTOP3:	ILDB A,(P)		; Get byte from string
	JUMPE A,LPTOP4		; End
	PUSHJ P,LPTSQO		; Print it
	JRST LPTOP3		; And loop thru all characters

LPTOP4:	MOVEI A,4
	MOVEM A,0(P)		; Smash spent byte pointer
	MOVEI A,40
	PUSHJ P,LPTSQO
	SOSLE 0(P)
	 JRST .-3
	SUB P,[XWD 1,1]
	SOSLE (P)		; Count names per line
	JRST LPTOP2		; Repeat
	SUB P,[XWD 1,1]		; Flush spent count
	MOVEI A,15
	PUSHJ P,LPTSQO		; End line with CR-LF
	MOVEI A,12
	PUSHJ P,LPTSQO		; ..
	SOSLE -1(P)		; Count lines of heading
	JRST LPTOP1		; Repeat for each line
	SUB P,[XWD 3,3]		; Flush byte pointer, line cnt, name cnt
	MOVEI A,14
	PUSHJ P,LPTSQO		; Output form feed
	JRST SKPRET
   >			;END OF BBNP OPEN

   IFN LP10F,<		;LP10 OPEN
	LOCK LPTLCK,<PUSHJ P,LCKTST>
	MOVE IOS,LPTSTS
	CONSZ LPT,LPTERR	;SKIP IF ON LINE
	JRST [	UNLOCK LPTLCK
		MOVEI A,OPNX8
		POPJ P,]	;FAIL
	TEST(OE,OPN)
	JRST [	UNLOCK LPTLCK
		MOVEI A,OPNX9
		POPJ P,]	;FAIL
	TLZ IOS,ALTP!ALTI!OUERR!LAST
	TLO IOS,FSTBUF
	MOVEM IOS,LPTSTS
	SETOM LPTCNT		; Lpt idle
	SETZM LPTCLS
	MOVEI A,LPTBUF
	MOVES (A)
	PUSHJ P,FPTA		; Get ptn.pn for buffer
	PUSHJ P,MLKPG		; Lock the page
	MOVE A,[XWD -400,LPTBUF]
	MOVEM A,LPTRLP		; Save
	MOVEI A,7
	DPB A,PBYTSZ		; 7 bit bytes
	MOVEI A,0
	DPB A,PBYTPO		; Position
	MOVEI A,LPTBUF-1
	HRRM A,FILBYT(JFN)	; Point to buffer
	MOVEI A,400*5
	MOVEM A,FILBYN(JFN)	; Character count
	TEST(Z,WNDF)
	SETZM LPTPOS		; Column zero, line 0
	UNLOCK LPTLCK
	MOVEI A,14	;FORM FEED
	PUSHJ P,LPTSQO
	MOVE A,JOBNO
	MOVEM A,LPTJOB
	HRRZ A,JOBDIR(A)	; Get login directory number
	CAIN A,1		;SYSTEM?
	JRST SKPRET		;YES, NO HEADING
	PUSHJ P,GDIRST		; Get name string location
	JRST LPTOP4
	UNLOCK DIRLCK		; No need to keep directory locked
	OKINT
	HRLI A,(<POINT 7,0,35>)	; Make it a byte pointer
	PUSH P,A		; Save on stack
	PUSH P,[^D10]		; Number of lines of ident
LPTOP1:	PUSH P,[^D8]		; Number of names per line
LPTOP2:	PUSH P,-2(P)		; Copy byte pointer to stack
LPTOP3:	ILDB A,(P)		; Get byte from string
	JUMPE A,LPTOP4		; End
	PUSHJ P,LPTSQO		; Print it
	JRST LPTOP3		; And loop thru all characters

LPTOP4:	POP P,A			; Flush spent byte pointer
	MOVEI A,11
	PUSHJ P,LPTSQO		; Follow name with tab
	SOSLE (P)		; Count names per line
	JRST LPTOP2		; Repeat
	POP P,A			; Flush spent count
	MOVEI A,15
	PUSHJ P,LPTSQO		; End line with CR-LF
	MOVEI A,12
	PUSHJ P,LPTSQO
	SOSLE (P)		; Count lines of heading
	JRST LPTOP1		; Repeat for each line
	POP P,A			; Flush spent count
	MOVEI A,14
	PUSHJ P,LPTSQO		; Output form feed
	POP P,A			; Flush saved byte pointer
	JRST SKPRET
   >			;END OF LP10 OPEN

; Close line printer

LPTCLZ:	MOVEI A,40
	PUSHJ P,LPTSQO
REPEAT 0,<			; IN THE INTEREST OF SAVING TREES
	MOVE A,LPTPOS
	MOVEI B,4		; End with form feeds to expel listing
	TRNE A,777777		; Unless not at top of form
	ADDI B,1		; THEN ONE MORE
>
REPEAT 1,<
	MOVEI B,1		; FORCE OUT CURRENT PAGE
>
	PUSH P,B
	MOVEI A,14
	PUSHJ P,LPTSQO
	SOSLE (P)
	JRST .-3
	POP P,A
   IFN BBNPF,<
	MOVEI A,240
LPTCL0:	PUSHJ P,LPTOUT
	MOVEI A,200>
   IFN LP10F,<
LPTCL0:	SETZ A,
	PUSHJ P,LPTSQO>
	TEST(NN,WNDF)		; Wndf is set when full
	JRST LPTCL0
	MOVEI 1,LPTCNT
	PUSHJ P,DISL		; Wait for line printer to stop
	MOVEI A,LPTBUF
	PUSHJ P,FPTA
	PUSHJ P,MULKPG
	MOVSI IOS,OPN
	ANDCAM IOS,LPTSTS
	JRST SKPRET

; Line printer sequential character output

   IFN BBNPF,<		;BBNP SEQ OUTPUT
LPTSQO:	ANDI A,177
	MOVSI IOS,ESC
	TDNE IOS,LPTSTS
	JRST [	IORI A,400	; Make it look like no special char
		ANDCAM IOS,LPTSTS
		JRST LPTNOR]
	CAIN A,177
	JRST [	MOVSI IOS,ESC
		IORM IOS,LPTSTS
		POPJ P,]
;	CAIN A,37		; Check for special characters
;	JRST LPTEOL
	JUMPE A,CPOPJ
	CAIL A,12
	CAIL A,25
	JRST LPTNOR
	CAIN A,15
	JRST [	MOVSI IOS,CRSW
		IORM IOS,LPTSTS
		HRRZS LPTPOS
		POPJ P,]
LPTFRM:	SUBI A,12
	IDIVI A,6
	EXCH A,B
	MOVE C,LPTFR1(B)
	MOVE B,LPTFR2(B)
	IMULI A,6
	ROTC B,6(A)
	ANDI B,77
	ANDI C,77
	CAIN C,60
	JRST [	MOVE A,B
		JRST LPTNOR]
	MOVSI A,CRSW
	ANDCAM A,LPTSTS		; Forget about preceding cr's
	HRRZ A,LPTPOS		; Get current line#
	PUSH P,A		; Save
	ADDI A,(B)		; Add skip for this format control
	PUSH P,B		; Save skip
	IDIV A,B		; Reduce to nearest lesser line#
	IMUL A,(P)
	POP P,B
	POP P,B			; Get back old line#
	SUBM A,B		; Get line feeds needed to simulate
	CAIL A,^D60
	TRNE C,40		; Are we to skip end ofpage?
	JRST LPTFRR		; No
	SETZ A,
	MOVEI C,20

LPTFRR:	PUSH P,B		; Save line feed count for simulation
	IDIVI A,^D66		; Reduce new line# mod linesperpage
	HRRM B,LPTPOS
	PUSH P,LPTPOS		; Save current column
	PUSH P,C		; Save format character and bits
	MOVEI A,240
	PUSHJ P,LPTOUT		; Terminate current line
	HRRZS LPTPOS
	POP P,A
	CAIE A,77
	TRZE A,20		; Simulate?
	JRST LPTFRZ
LPTFRQ:	SOSG -1(P)
	JRST LPTFRX
	MOVEI A,240
	PUSHJ P,LPTOUT
	JRST LPTFRQ

LPTFRX:	MOVEI A,40
LPTFRZ:	PUSHJ P,LPTOUT
	POP P,A
	SUB P,[XWD 1,1]
	HLRZS A
	JRST LPTSPC

; Format control tables
; Lptfr1 has the line space count for each format character in
; The range 12 - 24. for non-format characters in this
; Range, it contains the original character code
; Lptfr2 contains the format character to use plus bits as follows
; 40 -- spaces over end of page
; 20 -- not to be simulated with line feeds

LPTFR1:	BYTE (6)1,^D20,^D60,0,16,17,^D30,2,3,1,^D10
LPTFR2:	BYTE (6)37,5,20,77,60,60,6,2,3,40,4

;LPTEOL:	HRRZS LPTPOS
;	MOVEI A,12
;	JRST LPTFRM

LPTCR:	MOVEI A,15
	JRST LPTFRM

LPTNOR:	MOVSI IOS,CRSW
	TDNE IOS,LPTSTS
	JRST [	ANDCAM IOS,LPTSTS
		PUSH P,A
		PUSHJ P,LPTCR
		POP P,A
		JRST .+1]
	CAIE A,177		; IS THE CHARACTER NEW UPARO
	CAIN A,136		; OR NEW CARAT?
	 XORI A,41		; YES, SWAP THE TWO
	CAIE A,137		; IS IT NEW UNDERLINE
	CAIN A,37		; OR OLD UNDERLINE
	 XORI A,100		; YES, EXCHANGE THE TWO
	CAIN A,11
	JRST LPTTAB
LPTNO1:	PUSHJ P,LPTOUT
	MOVSI A,1
	ADDM A,LPTPOS
	POPJ P,

LPTTAB:	HLRZ A,LPTPOS		; Get current column
	ADDI A,10
	ANDCMI A,7
	HLRZ B,LPTPOS
	SUB A,B
LPTSPC:	SOJL A,CPOPJ
	PUSH P,A
	MOVEI A,40
	PUSHJ P,LPTNO1
	POP P,A
	JRST LPTSPC

; Put 8-bit character in buffer

LPTOUT:	MOVSI IOS,OUERR
	TDNE IOS,LPTSTS
	 TEST(O,ERRF)
	ANDCAB IOS,LPTSTS
	TEST(NE,WNDF)
	PUSHJ P,BUFWAT
	HRLZI B,201000
	IBP FILBYT(JFN)
	CAMGE B,FILBYT(JFN)	; Left 12 bits are not used
	HLLM B,FILBYT(JFN)	; Skip them
	DPB A,FILBYT(JFN)
	SOSLE FILBYN(JFN)
	POPJ P,
	MOVE IOS,LPTSTS
	AOSN LPTCNT
	PUSHJ P,LPTSTR
	MOVSI IOS,ALTP
	XORB IOS,LPTSTS
	MOVEI B,LPTBUF-1
	TEST(NN,ALTP)
	HRRM B,FILBYT(JFN)
	MOVEI B,400*3
	MOVEM B,FILBYN(JFN)
	TEST(O,WNDF)
	POPJ P,
   >		;END OF BBNP SEQ OUT

   IFN LP10F,<		;LP10 SEQ OUT
LPTSQO:	ANDI A,177
;	CAIN A,37	;CONVERT EOL
;	MOVEI A,12	;TO LF
	TEST(NE,WNDF)
	PUSHJ P,BUFWAT
	IDPB A,FILBYT(JFN)
	SOSLE FILBYN(JFN)
	POPJ P,
	AOSN LPTCNT	;IF COUNT WAS -1
	PUSHJ P,LPTSTR	;START LPT, OTHERWISE IT WAS GOING
	MOVSI IOS,ALTP
	XORB IOS,LPTSTS
	MOVEI B,LPTBUF-1
	TEST(NN,ALTP)
	HRRM B,FILBYT(JFN)
	MOVEI B,400*5
	MOVEM B,FILBYN(JFN)
	TEST(O,WNDF)
	POPJ P,
   >		;END OF LP10 SEQ OUT

BUFWAT:	PUSH P,1
	SKIPLE LPTCNT
	JRST [	MOVEI 1,LPTCNT		;WAIT FOR COUNT TO GO TO 0
		PUSHJ P,DISLE
		JRST .+1]
	TEST(Z,WNDF)
	POP P,1
	POPJ P,

; Line printer interrupt

	USE	RESPC

   IFN BBNPF,<		;BBNP INT SRV
LPTSV:	XWD LPTINR,.+1
	CONSO LPT,10
	JRST @LPTINR
	MOVEI A,LPTCHR
	MOVEM A,LPTINR
	MOVEM P,LPSTK
	MOVE P,[IOWD LPSTKL-1,LPSTK+1]
	PUSH P,IOS
	MOVE IOS,LPTSTS
	CONI LPT,A
	ANDI A,1600
	TRNE A,1600		; Error?
	JRST LPTER
LPTSV1:	CONO LPT,70(A)		; Reset everything
	TEST(C,ALTI)
	MOVEM IOS,LPTSTS
	SOSL LPTCNT
	PUSHJ P,LPTSTR		; More to do
LPTXIT:	MOVEM IOS,LPTSTS
	POP P,IOS
	POP P,P
	JRST @LPTINR

LPTER:	TRNE A,600		; Nxm or parity?
	JRST LPTBER		; Yes, bad error
	HRLOI A,377777
	MOVEM A,LPTTIM
	JRST LPTXIT

LPTBER:	BUG(NTE,<LINE PRINTER: NXM OR PARITY ERROR.>)
	JRST LPTSV1
   >		;END BBNP INT SRV

   IFN LP10F,<		;LP10 INT SRV
LPTSV:	XWD LPTINR,.+1
	CONSZ LPT,LPTDON+LPTERR
	CONSO LPT,77		;IS PRINTER RUNNING
	JRST @LPTINR		;NO, NOT MY INTERRUPT
	MOVEM P,LPSTK
	MOVE P,[IOWD LPSTKL-1,LPSTK+1]
	PUSH P,IOS
	MOVE IOS,LPTSTS
	CONSZ LPT,LPTERR
	JRST LPTER	;ERROR
	TEST (ZE,LAST)
	JRST LPTNXT	;NO MORE DATA IN THIS BUFFER
LPTOUT:	MOVE A,LPTCCW
	DATAO LPT,0(A)	;OUTPUT NEXT DATA WOR
	AOBJP A,LPTLST	;LAST WORD IN BUFFER
	MOVEM A,LPTCCW
LPTXIT:	POP P,IOS
	POP P,P
	JRST LPTCHR	;RETURN FROM INTERRUPT

;NOTE THAT LAST WORD OF BUFFER WAS TRANSMITTED

LPTLST:	TEST (O,LAST)	;SET LAST FLAG
	MOVEM IOS,LPTSTS
	JRST LPTXIT

;BUFFER COMPLETE, SEE IF MORE TO DO

LPTNXT:	TEST (C,ALTI)	;TOGGLE INTERRUPT BUFFERS
	MOVEM IOS,LPTSTS
	SOSL LPTCNT	;ANOTHER BUFFER READY?
	JRST [	PUSHJ P,LPTSET	;YES, SET IT UP
		JRST LPTOUT]
	CONO LPT,0
	JRST LPTXIT

LPTER:	CONO LPT,0	;SHUT OFF PRINTER
	SETOM LPTCLS
	MOVEI A,^D2000	;SHORT TIME BETWEEN
	MOVEM A,LPTCKT	;LPTCHK'S WHILE PRINTER IS OFF LINE
	MOVEM A,LPTTIM
	JRST LPTXIT

LPTSTR:	PUSHJ P,LPTSET
	TEST(ZN,FSTBUF)		;THIS FIRST BUFFER SINCE OPENING?
	JRST [	CONO LPT,LPTBOT	;NO, JUST POKE PNTR AGAIN
		DATAO LPT,[0]
		POPJ P,]
	MOVEM IOS,LPTSTS
	CONO LPT,LPTBOT+LPTCLR	;YES, CLEAR AND GIVE PI ASSMT, WILL INT
	POPJ P,

LPTSET:	PUSH P,A
	MOVE IOS,LPTSTS
	MOVE A,LPTRLP
	TEST(NE,ALTI)
	ADDI A,400
	MOVEM A,LPTCCW
	POP P,A
	POPJ P,
   >		;END OF LP10 INT SRV

   IFN BBNPF,<		;BBNP PERIODIC CHECK
LPTCHK:	MOVEI A,^D60000
	MOVEM A,LPTTIM
	SKIPE LPTSTS
	SKIPGE LPTCNT		; If doing nothing
	 POPJ P,		; Just return
	CONSO LPT,1B31		; If not on-line
	 JRST [	SOSLE LPTOFC
		POPJ P,
		MOVSI A,OUERR
		IORM A,LPTSTS
		SETOM LPTCNT
		CONO LPT,1070
		POPJ P,]
	BUG(NTE,<LINE PRINTER: HUNG!>)
	CONO LPT,1070
LPTSTR:	PUSH P,A
	MOVE A,LPTRLP
	TEST(NE,ALTI)
	ADDI A,400
	MOVEM A,LPTCCW
	MOVEI A,5		; Minutes of off-line status before err
	MOVEM A,LPTOFC
	MOVEI A,^D60000		; Time to print full buffer of lf's
	MOVEM A,LPTTIM		;  at 10 lines per second
	CONO LPT,1110+LPTCHN
	POP P,A
	POPJ P,
   >		;END OF BBNP CHK

   IFN LP10F,<		;LP10 PERIODIC CHECK
LPTCHK:	MOVE A,LPTCKT
	MOVEM A,LPTTIM		;RESET ALARM
	SKIPN LPTCLS		;CHECKING NEEDED?
	POPJ P,			;NO
	CONSZ LPT,LPTERR	;STILL OFF LINE?
	POPJ P,			;YES
	SETZM LPTCLS		;NO, RESTART IT
	MOVSI A,(1B1)
	MOVEM A,LPTCKT		;MAKE INTERVAL LARGE
	CONO LPT,LPTBOT		;REASSIGN PI
	DATAO LPT,[0]
	POPJ P,
   >		;END OF LP10 CHK
>				; END OF DEVICE CODE AT LPTOP1
>				; End of ifdef lptf on page 1
	END
