;<134-TENEX>LINEPR.MAC;6     1-Jul-77 16:00:28    EDIT BY LYNCH
;<134-TENEX>LINEPR.MAC;5    17-Jun-77 09:09:55    EDIT BY LYNCH
; FIXED TO RUN WITHOUT PHYSICAL DEVICE ONLINE ANYMORE.
;<134-TENEX>LINEPR.MAC;4    17-FEB-76 11:40:20    EDIT BY UNTULIS
;ADDED EXTERNS
;<133-TENEX>LINEPR.MAC;11    12-DEC-75 13:46:55    EDIT BY UNTULIS
;DISABLE DEFAULT ACCOUNT FOR LPT. FILES
;<133-TENEX>LINEPR.MAC;10    17-JUN-75 14:10:24    EDIT BY UNTULIS
;<133-TENEX>LINEPR.MAC;9    17-JUN-75 13:45:06    EDIT BY UNTULIS
;<133-TENEX>LINEPR.MAC;8    15-JUN-75 22:33:35    EDIT BY UNTULIS
;<133-TENEX>LINEPR.MAC;10     6-MAR-75 09:16:14    EDIT BY UNTULIS
;<133-TENEX>LINEPR.MAC;9     2-MAR-75 15:22:33    EDIT BY UNTULIS
;<133-TENEX>LINEPR.MAC;5    28-FEB-75 09:43:31    EDIT BY UNTULIS
;ADD CODE FOR PAGE OUTPUT TO PRINTER
;<133-TENEX>LINEPR.MAC;3    13-FEB-75 19:53:36    EDIT BY LYNCH
; MADE PRINTER BUFFER WHOLE PAGE INSTEAD OF HALF PAGE.
;<BARRETT>LINEPR.AIC;1    27-DEC-73 15:18:27	EDIT BY LYNCH
;<TENEX-MON>LINEPR.AIC;4    19-DEC-73 14:19:47	EDIT BY LYNCH
;<TENEX-MON>LINEPR.AIC;3    12-NOV-73 23:49:58	EDIT BY KREMERS
;FIXED SO PRINTR CAN RUN AS AUTO JOB
;<SRIMON131>LINEPR.MAC;6     8-AUG-73  5:45:07	EDIT BY KREMERS
;<SRIMON131>LINEPR.MAC;5     8-AUG-73  5:33:38	EDIT BY KREMERS
;<SRIMON131>LINEPR.MAC;4     8-AUG-73  5:25:50	EDIT BY KREMERS
;<SRIMON131>LINEPR.MAC;3     8-AUG-73  5:09:12	EDIT BY KREMERS

	SEARCH PROLOG,STENEX
	TITLE LINEPR
IFDEF LPTN,<
;	LAST ALTERED BY		P.H.LIPMAN	8 MAY 72	10:17AM

;ORIGINAL SRI-AIC 1.29 LINEPR.FAI MODIFIED TO WORK WITH 1.31

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

; Entries to this part

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

; Parameters and fixed core locations

LPT=124			; Line printer device
LPTWID==^D132		; NO. OF CHARS ON A PRINTER LINE
PI==4
IOS=6
HDBLNK==4		; NO. OF BLANKS AFTER EACH HEADER NAME
LPTCLR==1B25		; CLEAR PRINTER
LPTBSY==1B28		; BUSY BIT
LPTDON==1B29		; DONE BIT
LPTERR==1B27		; LINE PRINTER OFF LINE
LPTBOT==10*LPTCHN+LPTCHN	; BOTH INTERRUPTS FOR LPT
LPTFF==1	;NUMBER OF FORMFEEDS OUTPUT TO LP1 WHEN CLOSED.

LS(LPTINR)		; Return address in interrupt routine
LPSTKL==10		; Interrupt stack length
LS(LPSTK,LPSTKL)	; Stack for interrupt routine
LS(LPTSTS)		; Status word
LS(LPTRLP)		; Real core address for line printer
LS(LPTCNT)		; Buffer counter
LS(LPTJOB)		; Job of last lpt opener
LS(LPTCLS)		; SWITCH TO TURN ON CLOCK STUFF
LS(LPTCCW)		; WORD FOR INTERRUPT ROUTINE TO DO "BLKO"
LS(LPTCKT)		; AMOUNT OF TIME TO WAIT BETWEEN CALLS TO LPTCHK
NRP(LPTBUF,2000)
>
LS(LPTLCK)		; Lock on opening lpt

IFDEF LPTDVF,<
FLG(ALTP,L,IOS,400000)	; 0 IF FILLING FIRST BUFFER, 1 IF FILLING SECOND
FLG(ALTI,L,IOS,200000)
FLG(OUERR,L,IOS,100000)	; OUTPUT ERROR
FLG(OPN,L,IOS,040000)	;LINE PRINTER OPEN
FLG(FSTBF,L,IOS,020000)	; FIRST BUFFER OF FILE ISSUE RESET
FLG(LAST,L,IOS,010000)	; LAST WORD SENT
>

; Line printer dispatch table

USE RESPC

SPOOLP:	1		; .GT. 0 IF SPOOLING

USE SWAPPC

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
IFDEF LPTDVF,<
	LPTDMP		; DUMP ENTIRE PAGE TO PRINTER
>
IFNDEF LPTDVF,<
	CPOPJ
>
	CPOPJ		; Mount
	CPOPJ		; Dismount
	CPOPJ		; Initialize directory
	CPOPJ		; Mtape
	CPOPJ		; Get status
	CPOPJ		; Set status


; Initialize line printer

USE RESPC

LPTINI:
	IFDEF LPTDVF,<
	SETZM LPTSTS
	SETOM LPTCNT>
	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)
	SKIPE SPOOLP		; IF NOT SPOOLING
	CAME A,[ASCII /LPT/]	; OR IF LP1
	JRST LP1OPN		; THEN DON'T SPOOL

	MOVEI A,400000
	PUSH P,CAPENB		; Save current capenb
	IORM A,CAPENB		; Give ourselves wheel status
LPTOPA:	MOVEI B,8
	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>)
;	HRROI B,[ASCIZ /;ASYSTEM/]
;	SOUT		DISABLE TO ALLOW SPOOLER TO CHARGE USER
;			FOR PRINT TIME


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>)
>>		; Close of ifdef at lptopn and lp1opn

; Open line printer

IFDEF LPTDVF,<
	LOCK LPTLCK,<PUSHJ P,LCKTST>
	MOVE IOS,LPTSTS
	CONSZ LPT,LPTERR	;SKIP IF ON LINE
	JRST LPTBS1	;CALL IT BUSY, EVEN THOUGH OFF LINE
	TEST(OE,OPN)
	JRST LPTBS1	;BUSY
	LDB A,PBYTSZ	;USER SPECIFIED BYTE SIZE
	CAIE A,7	;MUST BE 7 FOR LPT
	JRST [	UNLOCK LPTLCK
		MOVEI A,SFBSX2
		POPJ P,	]
	TLZ IOS,ALTP!ALTI!OUERR!LAST
	TEST(O,FSTBF)
	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
	MOVEI A,LPTBUF+1000	; POINT TO ALTERNATE BUFFER PAGE
	MOVES (A)		; TOUCH IT
	PUSHJ P,FPTA
	PUSHJ P,MLKPG
	MOVE A,[XWD -1000,LPTBUF]
	MOVEM A,LPTRLP		; Save
	MOVEI A,0
	DPB A,PBYTPO		; Position
	MOVEI A,LPTBUF-1
	HRRM A,FILBYT(JFN)	; Point to buffer
	MOVEI A,1000*5
	MOVEM A,FILBYN(JFN)	; Character count
	TEST(Z,WNDF)
	UNLOCK LPTLCK
	MOVE A,JOBNO
	HRRZ A,JOBDIR(A)	;IS THIS <SYSTEM> (I.E. LINE PRINTER AUTO JOB) ?
	CAIE 1,1		;DIRNUM FOR <SYSTEM> IS AND ALWAYS WILL BE 1
	JRST LPTHDR		;NO, PRINT HEADER
	JRST SKPRET		;AND RETURN SUCCESSFULLY


LPTBS1:	UNLOCK LPTLCK
LPTBS2:	MOVEI A,OPNX9
	POPJ P,		;NO SKIP RETURN

LPTHDR:	MOVE A,JOBNO
	HRRZ A,JOBDIR(A)	; Get login directory number
	PUSHJ P,GDIRST		; Get name string location
	JRST [	JSR BUGCHK	;BAD DIRECTORY NO.
		POPJ P,	]
	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
	MOVEI C,HDBLNK-1	;4 BLANKS AT END OF EACH NAME
	AOS C
	ILDB B,A
	JUMPN B,.-2		;COUNT CHARS IN NAME
	MOVEI A,LPTWID		;WIDTH OF PRINTER IN CHARS
	IDIV A,C		;NO. OF NAMES THAT WILL FIT
	PUSH P,A		;SAVE ON STACK
	PUSH P,[^D10]		; Number of lines of ident
LPTHD1:	PUSH P,-1(P)		; Number of names per line
LPTHD2:	PUSH P,-3(P)		; Copy byte pointer to stack
LPTHD3:	ILDB A,(P)		; Get byte from string
	JUMPE A,LPTHD4		; End
	PUSHJ P,@BOUTD(DEV)		; Print it
	JRST LPTHD3		; And loop thru all characters

LPTHD4:	MOVEI A,HDBLNK
	MOVEM A,(P)	;CLOBBER SPENT BYTE PTR
LPTHD5:	MOVEI A," "
	PUSHJ P,@BOUTD(DEV)
	SOSLE (P)
	JRST LPTHD5
	POP P,A		;FLUSH CLOBBERED SPENT BYTE PTR
	SOSLE (P)		; Count names per line
	JRST LPTHD2		; Repeat
	POP P,A			; Flush spent count
	MOVEI A,37
	PUSHJ P,@BOUTD(DEV)		; End line with eol
	SOSLE (P)		; Count lines of heading
	JRST LPTHD1		; Repeat for each line
	POP P,A			; Flush spent count
	POP P,A			;FLUSH SAVED NAME COUNT
	POP P,A			; Flush saved byte pointer
	MOVEI A,14
	PUSHJ P,@BOUTD(DEV)
	JRST SKPRET

; Close line printer

LPTCLZ:	IFN LPTFF,<MOVEI B,LPTFF	;END WITH LPTFF NUMBER OF LINEFEEDS
	PUSH P,B
	MOVEI A,14
	PUSHJ P,LPTSQO
	SOSLE (P)
	JRST .-3
	POP P,A>
LPTCL0:	SETZ A,
	PUSHJ P,LPTSQO	;FILL BUFFER WITH NULLS
	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
	MOVEI A,LPTBUF+1000	; ALSO RELEASE SECOND PAGE
	PUSHJ P,FPTA
	PUSHJ P,MULKPG
	MOVSI IOS,OPN
	ANDCAM IOS,LPTSTS
	JRST SKPRET
;	DUMP ONE PAGE TO PRINTER
;	ASSUMPTIONS
;	1)FIRST DATA CHARACTER ON PAGE BOUNDRY
;	2)CHARACTER COUNT APPEARS IN WORD BEFORE FIRST DATA WORD
;		AC2= IOWD -1001,CHARACTER COUNT WORD ADDRESS
LPTDMP:
	UMOVE	A,2		;GET COMMAND LIST ADDRESS
	UMOVE	B,0(A)		;GET ADDRESS OF BYTE COUNT
	UMOVE	C,0(B)		;GET BYTE COUNT
	HRRI	D,1(B)		;ADDRESS OF DATA
	HRLI	D,440700
OUTLP:
	XCTBU[ILDB	A,D]	;GET BYTE INTO A
	PUSHJ	P,LPTSQ1	;OUTPUT BYTE
	SOJG	C,OUTLP
	POPJ	P,

; SEQUENTIAL OUTPUT ROUTINE

LPTSQO:	ANDI A,177
LPTSQ1:	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,1000*5
	MOVEM B,FILBYN(JFN)
	TEST(O,WNDF)
	POPJ P,

BUFWAT:	PUSH P,1
	MOVEI 1,LPTCNT
	SKIPLE (1)	;IF LPTCNT ^D1, THEN BOTH BUFFERS FULL
	PUSHJ P,DISLE	;WAIT FOR BUFFER
	TEST(Z,WNDF)
	POP P,1
	POPJ P,


USE RESPC

; Line printer interrupt

LPTSV:	XWD LPTINR,.+1
	CONSO LPT,LPTDON+LPTERR
	JRST @LPTINR
	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 LPTCON
	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


LPTCHK:	MOVE A,LPTCKT
	MOVEM A,LPTTIM
	SKIPN LPTCLS
	POPJ P,
;NEED TO TRY AND RESTART PRINTER, SEE IF ERROR STILL SET
	CONSZ LPT,LPTERR
	POPJ P,	;STILL NOT READY
	SETZM LPTCLS
	MOVSI A,(1B1)	;RESET INTERVAL BETWEEN
	MOVEM A,LPTCKT	;LPTCHK'S TO VERY LARGE TIME
	JRST LPTST1	;START IT UP AGAIN
LPTSET:	PUSH P,A
	MOVE IOS,LPTSTS
	MOVE A,LPTRLP
	TEST(NE,ALTI)
	ADDI A,1000
	MOVEM A,LPTCCW
	POP P,A
	POPJ P,

LPTSTR:	PUSHJ P,LPTSET	;RETURNS WITH IOS SET UP
	TEST (ZN,FSTBF)	;SKIP IF THIS IS FIRST BUFFER OUT
			;SINCE OPENING
	JRST LPTST1
	MOVEM IOS,LPTSTS	;NO INTERRUPTS COULD INTERFERE
	CONO LPT,LPTBOT+LPTCLR	;ISSUE CLEAR AS WELL, WILL INTERRUPT
				;WHEN READY
	POPJ P,
LPTST1:	CONO LPT,LPTBOT
	DATAO LPT,[0]
	POPJ P,

LPTCON:	PUSHJ P,LPTSET
	JRST LPTOUT
>				;END OF IFDEF JUST BELOW LP1OPN

USE	SWAPPC

	END	>

