.TITLE LPA.
/COPYRIGHT 1970, DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
/9-25-70	EDIT29
/J.M. WOLFBERG
/LPA.--IOPS LINE PRINTER HANDLER FOR LP15 LINE PRINTER
/	INTERFACE FOR DATA PRODUCTS 2310 AND 2410 LINE
/	PRINTERS AND THE MOHAWK 5000 PRINTER.
/CALLING SEQUENCE:
/	CAL + .DAT SLOT (9-17)
/	FUNCTION
/	N ARGS, WHERE N IS A FUNCTION OF "FUNCTION"
/	NORMAL RETURN
/BITS 12-13 OF .SCOM+4 INDICATE PRINTER.
/	00= UNDEFINED.
/	01= 80 COLUMNS.
/	10= 120 COLUMNS.
/	11= 132 COLUMNS.
/
/LOC 34=WORD COUNT (NEVER USED)
/LOC 35=CURRENT ADDRESS
/API CHANNEL 56
/
LPP1=706541			/PRINT 1 LINE.
LPPM=706521			/PRINT MULTI-LINES.
LPSF=706501			/SKIP IF DONE OR ERROR.
LPRS=706542+10			/CLEAR AC AND READ STATUS.
LPEI=706544			/ENABLE INTERRUPT.
LPDI=706561			/DISABLE INTERRUPT.
LPCD=706621			/CLEAR DONE FLAG.
LPCS=706641			/CLEAR STATUS & ERROR FLAG.
/
.SCOM=100
.MED=3
IDX=ISZ
	.GLOBL LPA.
LPA.	DAC	LPCALP		/SAVE CAL POINTER.
	DAC	LPARGP		/AND ARGUMENT POINTER.
	IDX	LPARGP		/POINTS TO WORD 2 - FUNCTION CODE.
	LAC*	LPARGP
	IDX	LPARGP		/POINTS TO WORD 3 - BUFFER ADDRESS.
	AND	(17777		/STRIP OFF UNIT NUMBER.
	TAD	(JMP LTABL-1	/DISPATCH TO PROCESS FUNCTION.
	DAC	.+1
	XX
LTABL	JMP	LPIN		/1 - .INIT
	SKP			/2 - .FSTAT,.RENAM,.DLETE - IGNORE
	JMP	LPER06		/3 - .SEEK - ERROR
	IDX	LPARGP		/4 - .ENTER - IGNORE
	JMP	LPNEXT		/5 - .CLEAR - IGNORE
	JMP	LPCLOS		/6 - .CLOSE
	JMP	LPNEXT		/7 - .MTAPE - IGNORE
	JMP	LPER06		/10 - .READ - ERROR.
	JMP	LPWRIT		/11 - .WRITE
	JMP	LPWAIT		/12 - .WAIT OR .WAITR
LPER06	LAW	6		/ILLEGAL HANDLER FUNCTION.
	JMP*	LIT4		/(.MED+1.
/
/LPA. INTERRUPT SERVICE
/
LPINT	JMP	LPPIC		/JMP FOR PI ENTRY.
	DAC	LPAC		/STORE AC FOR API ENTRY.
	LAC	LPFVSW-1	/(LAC LPAC
	DAC	LPFVSW		/LEAVE PIC ALONE ON EXIT.
	LAC	LPINT		/FOR API, CONTAINS PC,L,EM,MP.
	JMP	LPCOM
LPPIC	DAC	LPAC		/SAVE AC ON PI ENTRY.
	LAC	LITION		/(ION
	DAC	LPFVSW
	LAC*	LIT0		/GET PI,L,EM,MP.
LPCOM	DAC	LPOUT
/
/LPA. STATUS REGISTER
/	0 - ERROR*
/	1 - LP ALARM
/	2 - LINE OVER
/	3 - ILLEGAL HORIZONTAL TAB
/	4 - BUSY
/	5 - DONE*
/	* CAUSES PI OR API INTERRUPT
/
	LPRS			/READ AND
	LPCS			/CLEAR STATUS.
	DZM LPUND			/CLEAR I/O UNDERWAY SWITCH.
	SPA!RTL
	JMP LPERT		/ERROR CONDITION - SEE WHICH ONE.
CHKALL	LAC LPLFSW		/0 IF NO LF; + NON-0 IF LINE WAITING;
	DZM LPLFSW
	SZA
	JMP CHKMOD		/LINE WAITING.
CHKFF	LAC LPFFCT		/0 IF LPA JUST OUTPUT A FF.
	SZA
	JMP CHKRST		/NO LINE WAITING.
	LAW -73			/RESET FF COUNTER.
	DAC LPFFCT
CHKMOD	DAC INTERR
	LAC TWOLNE		/MULTILINE OPERATION?
	SZA!STL			/IOT ALREADY LPP1 BECAUSE JUST OUTPUT 1 LINE.
	JMP SETIOT		/RESET IOT FOR MULTILINE.
	JMP LPRINT		/OUTPUT WAITING LINE.
CHKRST	LAC HEADSW		/IF USER'S BUFFER WAS MODIFIED ON LAST
	SNA			/WRITE, MUST RESTORE IT TO ORIGINAL STATE.
	JMP LITION		/NO - NOT MODIFIED.
	LAC HEADER		/REPLACE USER'S HEADER WORD.
	DAC* LPHDRP
	LAC DATAWD		/REPLACE USER'S FIRST DATA WORD.
	DAC* LPDATP
	DZM HEADSW
LITION	ION			/ALLOW OTHER INTERRUPTS.
/
/INTERRUPT EXIT
/
LPEXIT	LAC	(JMP LPPIC	/RESTORE PIC INTERRUPT ENTRY.
	DAC	LPINT
	LAC	LPAC
LPFVSW	XX			/"ION" IF PI; "LAC LPAC" IF API.
	DBR
	XCT	.+1
	XCT	.+1
	JMP*	LPOUT		/0 IF PI; DTIN IF API.
/
/ERROR ROUTINE
/
LPERT	SZL!RAL
	JMP	LPIPS4		/BIT 1 = LP ALARM.
	SZL!CLL
	JMP	LPER37		/BIT 2 = LINE OVER.
	SPA
	SKP			/BIT 3 = ILLEGAL HORIZONTAL TAB.
	JMP LPRTY			/BIT 4 = BUSY: RETRY.
	STL
LPER37	LAC MULTSW		/PRINT ERRORS 37 AND 47 ONLY IF IN MULTI-LINE
	SMA			/MODE.
	JMP CHKALL		/IN SINGLE LINE MODE, IGNORE ERROR.
	LAW 47			/IOPS 47.  (ILLEGAL HORIZONTAL TAB)
	SNL
	LAW	37		/IOPS 37 (LINE OVER)
	JMP*	LIT4
LPIPS4	LAC	(LPRTY		/SET UP FOR IOPS4 RETURN.
	DAC*	(.MED
	LAC	LIT4
	JMP*	LIT4
LPRTY	LAC LPHEAD		/RETRY AFTER IOPS 4.
	JMP LPRNTA		/FIND CORRECT EXIT.
/
/.INIT
/
LPIN	IDX	LPARGP
/LPIN1 TO LPIN2-1 IS ONCE ONLY CODE AND IS USED
/FOR STORAGE AFTER THE INITIAL .INIT.
/LPOUT - HOLDS EXIT ADDRESS FOR INTERRUPT.
/LPAC - HOLDS AC ON INTERRUPT.
/MULTSW - NON-ZER0 (400000)=MULTI-LINE MODE, 0=SINGLE LINE MODE.
/LPHDRP - POINTER TO USER HEADER WORD.
/LPDATP - POINTER TO USER'S FIRST DATA WORD.
/LPHEAD - POINTER TO CURRENT OUTPUT BUFFER.
/LPMODE - 0=IOPS ASCII, 1=IMAGE.
/DATAWD - USER'S FIRST DATA WORD FOR POSSIBLE REPLACEMENT.
/HEADER - USER'S HEADER WORD FOR POSSIBLE REPLACEMENT.
/BUFSIZ - 70 FOR 132 COLMS;44 FOR 80 COLMS.
/LPFFCT - # LINES TO PRINT PER PAGE (57DECIMAL=-73).
/
LPIN1	CAL	56		/CHANNEL REGISTER.
LPOUT	16			/.SETUP
LPAC	LPSF
	LPINT
MULTSW	LAC	(JMP LPIN2	/JMP AROUND .SETUP CODE AFTER FIRST .INIT.
LPHDRP	DAC	LPIN1
LPDATP	LAC* (.SCOM+4		/GET BIT 12 OF .SCOM+4.
HEADER	AND SPACE			/BIT 12 = 0 IS 80 COLUMN PRINTER.
LPMODE	SNA			/BIT 12 = 1 IS 132 COLUMN PRINTER.
LPHEAD	JMP BUF44
BUFSIZ	LAC LIT70
LPFFCT	SKP
BUF44	LAC LIT44
DATAWD	DAC BUFSIZ		/RETURN CORRECT BUFFER SIZE TO USER.
LPIN2	LAC BUFSIZ		/36(10) FOR 80 COLS; 56(10) FOR 132 COLS.
	DAC* LPARGP		/RETURN TO USER.
	IDX LPARGP		/NOW POINTS TO RETURN.
	LAW	-73
	DAC	LPFFCT		/SET UP TO PRINT 57 (10) LINES PER PAGE.
	LAC* LPCALP		/BIT 6 OF FIRST WORD OF .INIT IS SET
	AND (4000		/TO INHIBIT FORM FEEDS EVERY 57 LINES.
	SZA
	JMP NOFF
	LAC (ISZ LPFFCT
	JMP NOFF1
NOFF	LAC LITNOP		/INHIBIT FF.
	DZM LPCLSW		/NO FF ON CLOSE EITHER.
NOFF1	DAC LPFF3
	DAC	LPFF2
PRNTFF	LAC (LPP1
	DAC LPIOT
	LAC FF
	DAC CTLCHR
	LAC	FFBUFP		/OUTPUT FF.  
	JMS LPSET
/
/NORMAL CAL EXIT
/
LPNEXT	DBR
	XCT	.+1
	XCT	.+1
	JMP*	LPARGP
/
/.WRITE
/
LPWRIT	JMS LPIOCK		/PRINTER BUSY?
	LAC*	LPARGP		/USER BUFFER ADDRESS.
	IDX LPARGP
	IDX LPARGP		/POINTS TO RETURN.
	DAC	LPHDRP
	LAC*	LPHDRP		/BIT 0=1 FOR MULTIPLE LINES;0 FOR SINGLE.
	DAC HEADER		/SAVE FOR POSSIBLE REPLACEMENT.
	AND LITMIN
	DAC MULTSW		/400000 IF MULTIPLE LINE MODE, 0 IF SINGLE.
	RAL
	LAC HEADER
	AND LIT1
	DAC LPMODE		/0=IOPS, 1=IMAGE ASCII.
	LAC	(LPP1
	SZL
SETIOT	LAC	(LPPM
	DAC	LPIOT
	SNL
	JMP LPCTRL		/IN SINGLE LINE MODE.
LPRINT	DZM TWOLNE
	LAC LPLFSW
	SZA
	JMP LFOUT
	LAC LPHDRP		/GO PRINT LINE.
LPRNTA	JMS LPSET
	LAC INTERR		/NON-0 IF OUTPUTTING LINE AFTER FF.
	SNA
	JMP LPNEXT		/EXIT VIA CAL EXIT.
	DZM INTERR
	JMP LPEXIT		/EXIT VIA INTERRUPT EXIT.
/
/OUTPUT LF BEFORE THE CURRENT LINE.
/
LFOUT	LAC (LPP1
	DAC LPIOT		/SET FOR SINGLE LINE MODE.
	LAC LF
	DAC CTLCHR
	LAC FFBUFP
	JMP LPRNTA
/
/IN SINGLE LINE MODE MUST CHECK FIRST CHARACTER FOR THE VERTICAL CONTROL
/CHARACTERS 12 (LF), 14 (FF), 20 (OVERPRINT) AND 21 (DOUBLE SPACE).
/
LPCTRL	LAC LPHDRP		/IN SINGLE LINE MODE MUST CHECK
	TAD LIT2		/FIRST DATA CHAR FOR VERTICAL CONTROL CHAR.
	DAC LPDATP
	LAC HEADER
	RAR			/LINK = 1 IF IN IMAGE MODE.
	LAC* LPDATP
	DAC DATAWD		/SAVE FOR POSSIBLE REPLACEMENT.
	SZL			/IF IN IMAGE MODE, CHARACTER ALREADY IN CORRECT BITS.
	JMP GOTCHR
	AND (774000		/ROTATE CHAR FROM BITS0-6 TO BITS11-17.
	RTL; RTL; RTL; RTL
GOTCHR	SAD DC1			/DC1? (DOUBLE SPACE) (CODE 21)
	JMP CTLDC1		/YES - PRINT 2 LINES.
	SAD FF			/FF? (CODE 14)
	JMP CTLFF		/YES: RESET FF CNT AND OUTPUT 2 LINES.
	SAD LF			/LINE FEED? (CODE 12)
	JMP CTLLF		/YES -  PRINT 2 LINES.
	SAD OVRPNT			/OVERPRINT? (AS OUTPUT BY F4 OTS) (CODE 20).
	JMP CTLOVR		/YES - REPLACE 1ST CHAR WITH 'CR' AND OUTPUT 2 LINES.
	LAC LIT1		/SET LF SWITCH TO + NON-0 VALUE SO WILL
	DAC LPLFSW		/OUTPUT LF BEFORE LINE.
	JMP LPFF
/
/HAVE FOUND A VERTICAL CONTROL CHARACTER.
/FF: RESET THE INTERNAL FF COUNT AND OUTPUT 2 LINES.
/LF: OUTPUT 2 LINES.
/DC1: SET SWITCH SO BUMP FF COUNT TWICE AND OUTPUT 2 LINES.
/OVERPRINT: REPLACE FIRST CHAR WITH A CR (WHICH EFFECTIVALLY DOES
/  NOTHING HERE) AND OUTPUT 2 LINES.
/
CTLFF	LAW -73
	DAC LPFFCT		/RESET FF COUNT.
	SKP
CTLDC1	DAC DBLESW		/SET TO COUNT 2 LINES.
CTLLF	LAC (LPPM
	DAC LPIOT		/RESET IOT FOR MULTILINE MODE.
	LAC HEADER		/MUST ALSO RESET HEADER FOR 2 LINES.
	AND LIT1
	XOR (402000
	DAC TWOLNE
	DAC HEADSW
	DAC* LPHDRP
LPFF	LAC DBLESW
	DZM DBLESW
	SZA
LPFF2	ISZ LPFFCT		/OR 'NOP'.
	SKP
	JMP FFOUT
LPFF3	ISZ LPFFCT
	JMP LPRINT
FFOUT	DZM LPLFSW		/NO NEED FOR BOTH FF AND LF.
	JMP PRNTFF
/
CTLOVR	LAC LPMODE		/MUST REPLACE 20 IN FIRST CHAR POSITION WITH
	SNA			/A CR.
	JMP LPOVR1
	LAC CR			/IMAGE MODE.
	JMP LPOVR2
LPOVR1	LAC DATAWD		/IOPS ASCII:
	AND (3777		/TAKE OUT FIRST 7 BIT CHAR AND
	XOR (064000		/PUT IN A CR.
LPOVR2	DAC* LPDATP
	JMP CTLLF
/
/
/.CLOSE
/
LPCLOS	JMS	LPIOCK		/CHECK I/O UNDERWAY.
	ISZ	LPCLSW		/777777 IN AC IF HAVEN'T BEEN THRU CLOSE CODE.
	JMP	LPCLDN		/DONE.
	LAC (LPP1
	DAC LPIOT
	LAC FF
	DAC CTLCHR
	LAC	FFBUFP		/OUTPUT FF.
	JMS LPSET
LPCALX	DBR
	XCT	.+1
	XCT	.+1
	JMP*	LPCALP		/HANG ON CAL.
LPCLSW	777777			/-1 = .CLOSE NOT DONE.
LPCLDN	LAW -1
	DAC	LPCLSW		/INITIALIZE .CLOSE INDICATOR
	JMP	LPNEXT		/EXIT.
/
/.WAIT OR .WAITR
/
LPWAIT	LAC*	LPCALP
	AND	(1000
	SNA			/BIT 8 = 1 FOR .WAITR
	JMP	LPWAT1		/.WAIT - GO HANG ON CAL.
	LAC	(700000		/LINK, ETC.
	AND	LPCALP
	DAC	LPCALP
	LAC*	LPARGP		/15-BIT BUSY ADDRESS.
	AND	(77777
	XOR	LPCALP
	DAC	LPCALP
	IDX	LPARGP
LPWAT1	JMS	LPIOCK		/CHECK I/O UNDERWAY.
	JMP* LPARGP		/OK - RETURN.
/
/CHECK FOR I/O UNDERWAY
/
LPIOCK	0
	LAC	LPUND		/0 = NO ACTIVITY.
	SNA
	JMP*	LPIOCK		/NO I/O UNDERWAY.
	JMP	LPCALX		/HANG ON CAL TIL NOT BUSY.
/
/ SETUP AND OUTPUT TO PRINTER.
/
LPSET	0
	DAC LPHEAD		/SAVE IN CASE OF IOPS 4.
	TAD LPCLDN		/(-1.
	DAC* LPCA35
	DAC LPUND		/SET I/O BUSY FLAG.
	ION
	LPEI			/ENABLE INTERRUPT.
LPIOT	LPP1			/LPP1 OR LPPM.
	JMP* LPSET
/
/CONSTANTS
/
LPCALP	0			/CAL ADDRESS.
LPARGP	0			/CAL ADDRESS - MODIFIED
HEADSW	0			/NON-ZERO = USER'S HEADER WORD HAS BEEN MODIFIED.
INTERR	0			/NON-0 IF OUTPUTTING LINE AFTER FF.
TWOLNE	0
LPLFSW	0			/LF SWITCH: NON-0 = LINE WAITING.
DC1	21			/SKIP 2 LINES (CODE OUTPUT BY OTS)
FF	14			/FORM FEED
CR	15
LF	12			/LINE FEED
OVRPNT	20			/CODE FOR OVERPRINT OUTPUT BY OTS
SPACE	40
LIT0	0
LIT1	1
LIT2	2
LIT4	4
LITNOP	740000
LITMIN	400000
LPCA35	35			/CURRENT ADDRESS
DBLESW	0			/SET FOR 2 LINE SPACE SO BUMP FF TWICE
LIT70	70
LIT44	44
FFBUF	2001
LPUND	0
CTLCHR	0			/.SIXBT CHAR: FF(14), OR LF(12).
FFBUFP	FFBUF
	.END