Google
 

Trailing-Edge - PDP-10 Archives - tops20v41_monitor_sources - monitor-sources/lpksdv.mac
There are 20 other files named lpksdv.mac in the archive. Click here to see a list.
;<4-1-FIELD-IMAGE.MONITOR>LPKSDV.MAC.2, 25-Feb-82 20:29:39, EDIT BY DONAHUE
;UPDATE COPYRIGHT DATE
; UPD ID= 402, FARK:<4-WORKING-SOURCES.MONITOR>LPKSDV.MAC.2,  15-Feb-81 17:36:54 by ZIMA
;Edit 1832 - move 1824 to a device dependent routine.
; UPD ID= 271, SNARK:<4.MONITOR>LPKSDV.MAC.92,  18-Feb-80 15:24:34 by SANICHARA
;Fix for error status 0
;<4.MONITOR>LPKSDV.MAC.91,  3-Jan-80 08:09:29, EDIT BY R.ACE
;UPDATE COPYRIGHT DATE
;<4.MONITOR>LPKSDV.MAC.90,  7-Nov-79 09:27:47, EDIT BY OSMAN
;tco 4.2465 - Don't print garbage on KS printer when system coming up
;<4.MONITOR>LPKSDV.MAC.89, 17-Oct-79 09:30:57, EDIT BY OSMAN
;tco 4.2529 - Don't start printer if it's already printing (LPWGO)
;<4.MONITOR>LPKSDV.MAC.88,  1-Oct-79 17:08:00, EDIT BY OSMAN
;tco 4.2504 - Don't restart printer in LPINT if LPWGO is set (it's printing!)
;<OSMAN.MON>LPKSDV.MAC.1, 10-Sep-79 15:41:50, EDIT BY OSMAN
;TCO 4.2412 - Move definition of BUGHLTs, BUGCHKs, and BUGINFs to BUGS.MAC
;TCO 4.2240 - DO ERROR RESET WHEN DONE LOADING RAM OR VFU
;<4.MONITOR>LPKSDV.MAC.85, 20-Apr-79 15:00:48, EDIT BY OSMAN
;DON'T GENERATE ERROR IF PAGE COUNTER REACHES 0
;<4.MONITOR>LPKSDV.MAC.84, 19-Apr-79 10:16:27, EDIT BY OSMAN
;tco 4.2235 - handle GO ERR like any other error (don't restart printer)
;<4.MONITOR>LPKSDV.MAC.83,  2-Apr-79 09:17:11, EDIT BY OSMAN
;more 4.2186 - Don't error reset in CLRERR if merely page counter reached 0
;<4.MONITOR>LPKSDV.MAC.82,  4-Mar-79 18:21:45, EDIT BY KONEN
;UPDATE COPYRIGHT FOR RELEASE 4
;<4.MONITOR>LPKSDV.MAC.81,  9-Feb-79 09:41:00, EDIT BY OSMAN
;tco 4.2186 - set .DVFFE when setting .DVFHE
;<4.UTILITIES>LPKSDV.MAC.1,  5-Jan-79 14:19:30, EDIT BY OSMAN
;more 4.2142, copy page counter to itself if user doesn't care
;<4.MONITOR>LPKSDV.MAC.78,  2-Jan-79 15:09:13, EDIT BY OSMAN
;tco 4.2142 - check for page-counter-zeroed at CLRERR
;<4.MONITOR>LPKSDV.MAC.77, 27-Sep-78 11:20:11, Edit by MCLEAN
;FIX FOR LP07 VFU NOT READY
;<4.MONITOR>LPKSDV.MAC.76, 27-Sep-78 11:19:43, Edit by MCLEAN

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1976,1977,1978,1979,1980,1981,1982 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.

; DEVICE DEPENDENT CODE FOR THE LINE PRINTER
; (LP20  SERVICE) SPECIFIC CODE.

;DEFSTRS NEEDED WITHIN

DEFSTR (LPXBTS,L11A,19,2)	;PDP-11 TWO EXTENDED ADDRESSING BITS

; LINE PRINTER DEVICE DISPATCH TABLE

FELPVT:	IFIW!FESFLO		;SEND FLUSH
	IFIW!FESLOP		;PAGE COUNTER
	IFIW!FESACK		;ACK
	IFIW!FESDTA		;SEND DATA
	IFIW!FESEOF		;EOF
	IFIW!FESNDS		;STRING DATA
	IFIW!OURTLS		;SEND STATUS
	IFIW!LP20RS		;RESTART
	IFIW!LP20IN		;INITALIZE
	IFIW!LP20IE		;CHECK INTERRUPT ENABLE
;**;[1832] Add one line at FELPVT: +10L	JGZ	15-FEB-81
	IFIW!LP20OP		;[1832] DEVICE OPEN
   IFN <.-FELPMX>-FELPVT,<PRINTX %%INVALID DEVICE DEPENDENT TABLE SIZE>

;TABLE OF -11 HARDWARE ADDRESSES OF THE LINEPRINTER CONTROLLER REGISTERS
;LCRTAB+N SHOWS THE ADDRESS FOR THE DATA BASE FOR LINEPRINTER N.

LCRTAB:	LP11CA

;PARALLEL TABLE OF -11 INTERRUPT VECTOR ADDRESSES.  THAT IS, THE
;CONTENTS OF LPVTAB+N IS THE -11 ADDRESS WHICH WOULD CONTAIN THE
;ADDRESS OF THE INTERRUPT ROUTINE FOR LINEPRINTER N, IF WE WERE
;AN -11.

LPVTAB:	LP11IV

;TABLE OF ADDRESSES OF INTERRUPT ROUTINES, ONE FOR EVERY LINEPRINTER.

LPINTB:	LP0INT
;INITIALIZATION ROUTINE.

LP20IN:	MOVEI U,LPTN
LP20I1:	SOJL U,R		;RETURN IF ALL LP'S INITIALIZED
	SKIPE PROFLG		;IF PROFLG DON'T INITALIZE
	CALL L2INI		;INITIALIZE A LINE PRINTER
	JRST LP20I1		;LOOP FOR ALL LP'S
	RET			;DONE

;ROUTINE TO INITIALIZE A LINE PRINTER.  IT EXPECTS U TO CONTAIN 0
;THROUGH N-1 WHERE THERE ARE N LINE PRINTERS ON THE SYSTEM.

L2INI:	MOVE A,LCRTAB(U)	;GET ADDRESS ON UNIBUS FOR THIS LP
	SETZRO LPXBIT,(U)	;ASSUME NONE
	CALL UBGOOD		;CHECK FOR EXISTANCE
	RET			;RETURN NO DEVICE
	SETONE LPXBIT,(U)	;SET DEVICE EXISTS
	MOVE A,U		;SEE WHICH LINE PRINTER WE'RE DOING
	LSH A,2			;MULTIPLY BY FOUR BECAUSE XPCW NEEDS FOUR WORDS
	ADDI A,LPXPTB		;POINT XPCW AT CORRECT PLACE
	SETZM 2(A)		;CLEAR FLAGS OUT OF WHERE XPCW WILL POINT TO
	MOVE B,LPINTB(U)	;GET INTERRUPT ROUTINE ADDRESS FOR THIS LP
	MOVEM B,3(A)		;STORE IT FOR XPCW TO TRANSFER TO ON INTERRUPT
	HRLI A,(XPCW)		;MAKE THE XPCW INSTRUCTION
	MOVE B,SMTEPT+LPTUBN	;GET ADDRESS OF XPCW TABLE
	MOVE C,LPVTAB(U)	;GET -11 ADDRESS THAT HOLDS LP INTERRUPT ROUTINE ADDRESS
	LSH C,-2		;DIVIDE BY 4 TO GET OFFSET INTO XPCW TABLE
	ADD B,C			;GET ADDRESS WHERE XPCW SHOULD GO
	MOVEM A,(B)		;STORE THE XPCW
	MOVEI A,LPTUBN		;UNIBUS ADAPTOR NUMBER
	MOVEI B,1		;WE NEED ONE -11 PAGE
	CALL ALUBWA		;GET IT
	BUG(NLWA)
	MOVEM A,LPWINA(U)	;SAVE ADDRESS OF UBA
	MOVEM B,L11A(U)		;REMEMBER -11 ADDRESS WE GOT
LP20RS:	CALL GETLPA		;GET ADDRESS OF THIS LINEPRINTER'S BUFFER
	MOVE C,A
	MOVE B,L11A(U)		;GET BUFFER ADDRESS
	LSH C,-9		;MAKE PAGE NUMBER
	TXO C,UNBD18+UNBVBT	;DISABLE 18-BIT TRANSFERS, SAY VALID TRANSFER
	WRIO C,@LPWINA(U)	;ASSOCIATE -10 PAGE WITH FAKE -11 PAGE
	CALL LPTRUE		;MAKE SURE PRINTER EXISTS
	 RET			;DON'T REFERENCE NONEXISTENT HARDWARE!
	move B,LCRTAB(U)	;GET BASE ADDRESS FOR REGISTERS
	MOVX A,LP1RSE+LP1INT	;SET ERROR RESET AND INITIALIZE
	WRIOB A,LPCSRA+1(B)
	MOVX A,LP1IEN		;INTERRUPT ENABLE BIT
	WRIOB A,LPCSRA(B)	;MAKE SURE INTERRUPTS ARE ENABLED
	RET


;**;[1832] Add several lines at LP20RS: +16L	JGZ	15-FEB-81
;DEVICE DEPENDENT OPEN FUNCTIONS.  CALL WITH U SETUP.
;SETS LINE ALLOCATION BASED ON BYTE SIZE OF OPEN.

LP20OP: LOAD B,LPBSZ,(U)	;[1832] GET BYTE SIZE FROM OPENF
	MOVX A,NLPBF*5		;[1832] ASSUME 7-BIT BYTES BY DEFAULT
	CAIN B,^D8		;[1832] IS IT 8-BIT BYTES?
	MOVX A,NLPBF*4		;[1832]  YES, USE LOWER BYTE ALLOCATION
	STOR A,LPTMX,(U)	;[1832] SET BYTE ALLOCATION FOR DEVICE
	RET			;[1832] AND DONE


;ROUTINE TO CALL WITH U SET UP, WHICH SKIPS IFF LINEPRINTER EXISTS,
;AS DETERMINED DURING SYSTEM STARTUP

LPTRUE:	LOAD A,LPXBIT,(U)	;GET EXISTENCE BIT FOR THIS LP
	JUMPE A,R		;NON-SKIP IF NONX LINEPRINTER
	RETSKP			;SKIP IF EXISTENT PRINTER

;LINEPRINTER INTERRUPT ROUTINES.  

LP0INT:	MOVEM P,LPACS+P		;SAVE CALLER'S P
	MOVEI P,LPACS		;SAVE ACS
	BLT P,LPACS+16
	MOVE P,[XWD -LPSLEN,LPSTAK-1]	;GET STACK POINTER FOR LP INTERRUPT ROUTINE
	MOVEI U,0		;IDENTIFY WHICH PRINTER INTERRUPTED
;	JRST LPINT		;JOIN COMMON INTERRUPT ROUTINE

;COMMON INTERRUPT ROUTINE FOR LINEPRINTERS.  IT ASSUMES U CONTAINS UNIT
;OF LINEPRINTER THAT INTERRUPTED, THAT P IS SET UP, AND THAT THE ACS
;FROM BEFORE THE INTERRUPT ARE SAVED

LPINT:	LOAD A,LPTCC,(U)	;GET CHARACTER COUNT
	JUMPE A,LPINTA
	SETZRO LPTCC,(U)	;ZERO INTERRUPT CHARACTER COUNT
	MOVE B,U		;GET UNIT NUMBER FOR LPTINT
	CALL LPTINT		;NOTIFY INTERRUPT ROUTINE
LPINTA:	MOVE A,U		;GET UNIT NUMBER
	LSH A,2			;GET OFFSET INTO XPCW DATA TABLE
	ADD A,[XJEN LPXPTB]	;MAKE APPROPRIATE XJEN INSTRUCTION FOR DISMISSING INTERRUPT
	MOVEM A,LPXJEN		;REMEMBER THE INSTRUCTION FOR LATER
	MOVE Q2,LCRTAB(U)	;GET -11 ADDRESS OF THIS LP'S REGISTERS
	MOVX A,LPWCI+LPWDON	;CHARACTER INTERRUPT + DONE FLAG
	TIOE A,LPCSRA(Q2)	;SKIP IF NOT DONE OR CHARACTER INTERRUPT
	JRST PDJCOL		;PRINTER DIDN'T JUST COME ONLINE IF 
				;DONE IS SET OR THERE'S AN UNDEFINED CHARACTER INTERRUPT
	MOVX A,7777		;BYTE COUNTER IS 12 BITS WIDE
	MOVX B,LP1OFL+LP1DVN+LP1PER+LP1MPE+LP1RPE+LP1SYE	;CAN'T USE LP1ERR
				;BECAUSE IT STICKS AFTER ERROR IS REMEDIED
	TIOEB B,LPCSRB(Q2)	; WAS THERE SORT OF ERROR?
	JRST NOCINT		;YES, GO LOG IT
	MOVX C,LPWGO		;GET GO BIT (DESIGNATES THAT PRINTER IS RUNNING)
	TIOE C,LPCSRA(Q2)	;IS PRINTER STILL RUNNING?
	JRST LPXIT		;Yes, so quietly dismiss interrupt without doing
		;anything.  Getting here means an interrupt happened while the
		;printer is still printing.  I never thought this could happen
		;but it mysteriously started happening around 9/28/79.
	TIOE A,LPBCTR(Q2)	;SKIP IF BYTE COUNT IS 0
	JRST [	MOVEI T2,3		;NO ERROR AND BYTE COUNT NON-0,
		TIONB T2,T2(Q2)		; GO RESTART PRINTER
		JRST LPGO		;DO NOT RESTART IF DME OR GO ERR
		CALL CLRER1
		JRST LPXIT]
PDJCOL:	LOAD A,ARROWF,(U)	;SEE IF DOING CTRL CHAR
	JUMPN A,FINCTL		;YES, PREPARE TO GO BACK TO ORIG BUFF
	MOVX A,LPWCI		;BIT WE WANT TO TEST
	TIOE A,LPCSRA(Q2)	;DID WE JUST GET A CHARACTER INTERRUPT?
	JRST LPCINT		;YES, GO HANDLE IT
NOCINT:	CALL OURTLS		;GET STATUS OF THIS LINEPRINTER
	MOVX A,LP1DON		;SEE IF LINEPRINTER DONE PRINTING
	MOVE B,U		;LPTINT EXPECTS UNIT NUMBER IN B
	TIOEB A,LPCSRA(Q2)	;TEST DONE FLAG
	JRST [	SETZRO LPTFE,(U) ;ZERO COUNT OF CHARACTERS
		LOAD A,LPTLOR,(U)	;GET BIT SAYING WHETHER RAM OR VFU WAS BEING LOADED
		CAIE A,0	;WAS IT?
		CALL CLRER1	;YES, SO DO ERROR RESET
		SETZRO LPTLOR,(U)	;RAM OR VFU NO LONGER BEING LOADED
		JE LPTBL,(U),LPXIT
		SETZRO LPTBL,(U)
		MOVEI 1,0	;FAKE INTERRUPT RESTART
		CALL LPTINT
		JRST LPXIT]
;	JRST LPXIT		;DISMISS INTERRUPT

;LINEPRINTER INTERRUPT EXIT ROUTINE.  RESTORES AC'S AS BEFORE INTERRUPT
;AND DISMISSES INTERRUPT...

LPXIT:	MOVSI 17,LPACS		;MAKE BLT POINTER
	BLT 17,17		;RESTORE AC'S
	XCT LPXJEN		;RETURN TO CALLER


;GET HERE ON CHARACTER INTERRUPT

LPCINT:	RDIOB A,LPRAMD(Q2)	;GET RAM DATA FOR THIS INTERRUPT
	CAIE A,"^"		;IS THIS INTERRUPT FOR A CONTROL CHARACTER 
				;DESIRING TO BE MADE "UPARROW-CHARACTER"
	JRST NOCINT		;NO, HANDLE THIS CONDITION AS ANY OTHER ERROR
	RDIO A,LPBCTR(Q2)	;GET BYTE COUNTER SO FAR FOR THIS PRINTER
	STOR A,SAVBCT,(U)	;REMEMBER IT FOR LATER TO CONTINUE PRINTER
	RDIO A,LPBSAD(Q2)	;GET BUS ADDRESS
	STOR A,SAVBUS,(U)	;REMEMBER IT TOO
	MOVE A,L11A(U)		;GET -11 ADDRESS OF LPT DATA BUFFER
	WRIO A,LPBSAD(Q2)	;TELL LP20 WHERE DATA IS
	MOVEI A,1
	STOR A,ARROWF,(U)	;MARK THAT WE'RE DOING ARROWS
				;GET THE UP-ARROW FOR THE CONTROL CHAR
	CALL GETLPA		;GET BUFFER ADDRESS
	MOVEI B,"^"		;WHAT YOU MEAN "WE", KIMO SABE?
	DPB B,[POINT 8,(A),17]	;PUT THE ^ IN THE BUFFER
	LDB C,[POINT 8,(A),9]	;GET CHARACTER THAT HASN'T BEEN PRINTED YET
	STOR C,SAVCHR,(U)	;SAVE IT BECAUSE WE NEED THE BUFFER SPACE
	RDIOB B,LPCBUF(Q2)	;GET CONTROL CHARACTER
	TRO B,100		;MAKE IT A PRINTING CHARACTER
	ANDI B,177		;AND OFF GARBAGE BITS
	DPB B,[POINT 10,(A),9]	;MAKE ^ CHARACTER IN BUFFER & CLR B0/B1
	MOVNI A,2		;GET NEG OF # OF CHARS
	WRIO A,LPBCTR(Q2)	;SET UP BYTE COUNT TO 2
LPGO1:	CALL SETGOA
	JRST LPXIT		;DON'T SEND STATUS FOR EACH CONTROL CHARACTER

LPGO:	CALL SETGOA		;START THE LP
	CALL OURTLS		;ALWAYS REPORT STATUS AFTER RESTARTING PRINTER
	JRST LPXIT		;WAIT FOR TWO CHARS TO PRINT

;GET HERE TO FINISH INTERRUPTED BUFFER

FINCTL:	MOVEI A,0
	STOR A,ARROWF,(U)	;SAY NOT DOING CTRL CHAR
	LOAD A,SAVBCT,(U)
	JUMPE A,NOCINT		;QUIT IF THIS WAS THE LAST CHARACTER
	WRIO A,LPBCTR(Q2)	;RESTORE ORIG BYTE COUNTER
	LOAD A,SAVBUS,(U)
	WRIO A,LPBSAD(Q2)	;RESTORE ORIG BUS ADDRESS
	CALL GETLPA		;GET BUFFER ADDRESS
	LOAD B,SAVCHR,(U)	;GET SAVED BUFFER CHARACTER
	DPB B,[POINT 8,(A),9]	;RESTORE BUFFER CHARACTER
	JRST LPGO1		;START PRINTER AGAIN
; ROUTINE TO SEND A FLUSH 
;THIS CAUSES LINEPRINTER TO IMMEDIATELY STOP PRINTING

FESFLO:	CALL LPTRUE		;MAKE SURE PRINTER EXISTS
	 RET			;DOESN'T!
	MOVE B,LCRTAB(U)	;GET REGISTER FOR THIS LP
	MOVEI A,LPWINT+LP1IEN	;SET INTERRUPT ENABLE
	WRIO A,(B)		;AND STOP DEVICE WITH LOCAL INIT
	MOVEI A,LP1IEN+LP1GO	;SET IENERRUPT ENABLE
	WRIO A,(B)
	SETZRO LPTFE,(U)	;ZERO COUNT OF BYTES IN FE
	RET			;RETURN
;SET page counter
;SKIPS IFF SUCCESFUL

FESLOP:	CALL LPTRUE		;DOES LINEPRINTER EXIST?
	 RET			;NO, GIVE FAILURE RETURN
	LOAD A,PGCTR,(U)	;GET VALUE TO BE SET
	MOVE B,LCRTAB(U)	;GET BASE REGISTER
	WRIO A,LPPCTR(B)	;SET THE PAGE COUNTER
	RETSKP			;DONE

; ROUTINE TO SEND AN ACK
;THIS IS CALLED TO GET THE PRINTER ROLLING AGAIN AFTER IT HAS
;STOPPED DUE TO SOME ERROR.

FESACK:	CALL LPTRUE		;MAKE SURE PRINTER EXISTS
	 RET			;DOESN'T
	MOVE B,LCRTAB(U)	;GET REGISTER FOR THIS LP
	RDIO A,LPPCTR(B)
	WRIO A,LPPCTR(B)	;SET PAGE COUNTER IN CASE THERE WAS A PAGE COUNTER INTERRUPT
	RDIO A,LPBCTR(B)	;SEE HOW MANY CHARACTERS LEFT IN BUFFER
	TXNE A,7777		;ANY CHARACTERS LEFT TO PRINT?
	CALL SETGO		;YES, SET THE GO FLAG
	RET			;RETURN
;ROUTINE TO LOAD VFU OR RAM DATA.  ACCEPTS:
;	B/	FUNCTION-CODE,,0	;.DFLVF => LOAD VFU
;					;.DFLTR => LOAD TRANSLATION RAM
;	D/	NUMBER OF 8-BIT BYTES


FESDTA:	STKVAR <LVFU,N8BB>
	SETOM LVFU		;FIRST ASSUME LOADING VFU
	CAMN B,[.DFLTR,,0]	;LOADING RAM??
	SETZM LVFU		;YES, SO NOT LOADING VFU!
	MOVEM D,N8BB		;REMEMBER NUMBER OF 8-BIT BYTES
	CALL LPTRUE
	 RET			;JUST RETURN IF PRINTER DOESN'T EXIST
	MOVE D,LCRTAB(U)	;GET BASE REGISTER FOR THIS LP
	RDIO A,LPCSRA(D)	;GET GO BIT
	TXNE A,LPWGO		;IS PRINTER ALREADY PRINTING?
	RET			;YES, SO RETURN RATHER THAN MINGLE.
				;NOTE:  I SUSPECT THAT ON THE KL, THE SNDEOF
				;ROUTINE CAUSES THE FRONT END TO WAIT UNTIL ALL
				;ACTIVITY HAS STOPPED.  THE KS'S SNDEOF ROUTINE
				;SHOULD SOMEHOW WAIT TOO (BY USING LPTDIS?).
				;HOWEVER, UNTIL IT IS TAUGHT TO, THIS LPWGO
				;CHECK PREVENTS TRAFFIC JAMS. --E.O. 10/17/79
	CALL GETLPA		;GET BUFFER ADDRESS FOR THIS LINEPRINTER
	MOVE B,LPTRLP(U)	;FIGURE OUT WHERE DATA TO BE LOADED IS
	OPSTR <SKIPN>,ALTP,(U)
	ADDI B,NLPBF
	HRLI B,(<POINT 16,0>)	;EACH BYTE IS 8+8 BITS
	MOVE C,N8BB		;LOAD UP NUMBER OF BYTES TO DIGEST
	CALL CHANGE		;REARRANGE DATA THE WAY IT WOULD BE IN AN -11
	MOVE B,U		;LODDON ROUTINE EXPECTS UNIT NUMBER IN B
	CALL LODDON		;TELL WORLD WE'VE RECEIVED THE DATA
	MOVE A,L11A(U)		;GET LPT BUFFER ADDRESS
	WRIO A,LPBSAD(D)	;TELL PRINTER WHERE DATA IS
	MOVN A,N8BB		;GET NEGATIVE OF NUMBER OF BYTES
	WRIO A,LPBCTR(D)	;TELL PRINTER HOW MUCH DATA WE'RE SENDING
	SETONE LPTLOR,(U)	;REMEMBER THAT WE'RE DOING RAM/VFU LOAD
	MOVX B,LP1PEN+LP1DVU+LP1IEN+LP1GO	;PARITY ENABLE, LOAD VFU, INTERRUPT ENABLE
	SKIPN LVFU		;SKIP IF REALLY LOADING VFU
	MOVX B,LP1PEN+LP1TM+LP1DVU+LP1IEN+LP1GO	;PARITY, TEST MODE, LOAD DVU, INTERRUPT ENABLE
	CALL SETGOB		;START THE PRINTER
	RET			;DONE
FESEOF:	CALL OURTLS		;WHEN EOF REQUESTED, ASK FOR STATUS
	RET			;RETURN

;ROUTINE TO SEND DATA TO THE LINE PRINTER TO BE PRINTED.
;PASS IT COUNT IN F OF NUMBER OF BYTES
;THIS ROUTINE SKIPS IFF SUCCESSFUL

FESNDS:	STOR F,LPTCC,(U)	;SAVE COUNT OF CHARACTERS
	CALL LPTRUE
	 RET			;FAILURE RETURN IF PRINTER DOESN'T EXIST
	MOVE D,LCRTAB(U)	;GET -11 BASE ADDRESS FOR HARDWARE LP REGISTERS
	RDIO A,LPCSRA(D)	;GET GO BIT
	TXNE A,LPWGO		;IS PRINTER ALREADY PRINTING?
	RET			;YES, SO FAIL RATHER THAN MINGLE.
				;NOTE:  I SUSPECT THAT ON THE KL, THE SNDEOF
				;ROUTINE CAUSES THE FRONT END TO WAIT UNTIL ALL
				;ACTIVITY HAS STOPPED.  THE KS'S SNDEOF ROUTINE
				;SHOULD SOMEHOW WAIT TOO (BY USING LPTDIS?).
				;HOWEVER, UNTIL IT IS TAUGHT TO, THIS LPWGO
				;CHECK PREVENTS TRAFFIC JAMS. --E.O. 10/17/79
	CALL GETLPA		;GET BUFFER ADDRESS FOR THIS PRINTER
	MOVE B,LPTCCW(U)	;GET POINTER TO DATA BEING SENT
	LOAD C,LPTCC,(U)	;GET NUMBER OF CHARACTERS BEING SENT
	CALL SHUFFL		;PUT BYTES IN -11 FORMAT
	MOVE D,LCRTAB(U)	;GET -11 BASE ADDRESS FOR HARDWARE LP REGISTERS
	MOVE A,L11A(U)		;GET -11 ADDRESS OF LPT DATA BUFFER
	WRIO A,LPBSAD(D)	;TELL LP20 WHERE DATA IS
	LOAD A,LPTCC,(U)	;GET NUMBER OF BYTES BEING SENT
	MOVNS A			;NEGATE IT
	WRIO A,LPBCTR(D)	;TELL LP20 HOW MANY
	CALL SETGO		;START THE PRINTER
	LOAD A,LPTCC,(U)	;SET NUMBER OF CHARACTERS SENT
	RETSKP			;ALL DONE

;ROUTINE TO START THE PRINTER.

SETGO:	MOVX B,LP1IEN+LP1GO	;INTERRUPT ENABLE + GO
SETGOB:	LOAD A,LPXBTS,(U)	;GET PDP-11 EXTENDED ADDRESS BITS
	STOR A,LP1A17+LP1A16,B	;SET HIGH ORDER ADDRESS BITS IN WORD BEING WRITTEN TO PRINTER
	MOVE A,LCRTAB(U)	;GET REGISTER ADDRESS FOR THIS PRINTER
	WRIOB B,LPCSRA(A)	;START THE PRINTER
	RET

SETGOA:	CALL CLRERR		;CLEAR ALL ERRORS
	MOVX B,LP1IEN+LP1GO	;SET GO
	MOVE A,LCRTAB(U)	;GET DEVICE ADDRESS
	BSIOB B,LPCSRA(A)	;START DEVICE
	RET			;RETURN

;ROUTINE TO CALL BEFORE SENDING DATA TO PRINTER.  IT DOES THE
;APPROPRIATE ERROR CLEARING.

CLRERR:	MOVX A,LPWERR		;GET BIT BEING TESTED
	MOVE D,LCRTAB(U)	;GET REGISTER FOR THIS PRINTER
	TIOE A,LPCSRA(D)	;SKIP IF NOT ERROR
	CALL CLRER1		;DO ERROR RESET
	LOAD C,PGENB,(U)	;SEE IF USER WANTS PRINTER TO KEEP TRACK OF PAGE COUNT
	JUMPN C,R		;DONE IF SO
	MOVX A,LPWPZR
	MOVX B,LPWRSE+LP1IEN	;GET BIT BEING SET
	TION A,LPCSRA(D)	;PAGE COUNTER EXCEEDED?
	RET			;NO, NOTHING MORE TO DO
	RDIO B,LPPCTR(D)	;READ CURRENT PAGE COUNTER
	WRIO B,LPPCTR(D)	;COPY PAGE COUNTER TO ITSELF TO CLEAR COUNTER EXCEEDED ERROR
	RET			;DONE

;ROUTINE TO ACTUALLY DO THE ERROR RESET.

CLRER1:	MOVX B,LPWRSE+LP1IEN	;GET BIT BEING SET
	MOVE D,LCRTAB(U)	;GET BASE ADDRESS FOR THIS LP
	WRIO B,LPCSRA(D)	;THERE'S AN ERROR, SO CLEAR IT
	RDIO A,LPBCTR(D)	;COPY BYTE COUNTER TO ITSELF
	WRIO A,LPBCTR(D)	;SINCE ERROR RESET SETS DONE (WHICH WOULD CAUSE PREMATURE INTERRUPT)
	RET

;ROUTINE TO RETURN LINEPRINTER BUFFER ADDRESS IN A FOR LINEPRINTER
;UNIT NUMBER IN U.

GETLPA:	MOVE A,U		;SEE WHICH LINEPRINTER WE'RE GETTING BUFFER FOR
	IMULI A,NLPBF		;MAKE CORRECT OFFSET INTO BUFFER SPACE
	ADDI A,LPBUF		;ADD BASE ADDRESS TO MAKE CORRECT WORD ADDRESS
	RET			;DONE

;WHEN SENDING RAM OR VFU DATA TO PRINTER, IT IS INITIALLY PACKED
;IN PDP-10 WORDS IN THE FORMAT BYTE(16)WORD,WORD,WORD...
;THE LP20 WANTS IT IN THE FORMAT BYTE(2)0(16)WORD(2)0(16)WORD...
;THE FOLLOWING ROUTINE CREATES THE SECOND FORMAT GIVEN THE FIRST.
;ACCEPTS:
;	A/	ADDRESS TO RECIEVE SHUFFLED BYTES
;	B/	ILDB POINTER TO CONTIGUOUS BYTES
;	C/	NUMBER OF BYTES TO DO

CHANGE:	SAVEAC <Q2>		;SAVE AN AC
	HRLI A,(<POINT 18,0>)	;MAKE BYTE POINTER TO HALFWORDS
	ASH C,-1		;DIVIDE BYTES BY 2 TO GET NUMBER OF -11 WORDS
	JUMPE C,R		;RETURN IF NONE
CHAN1:	ILDB Q2,B		;GET SOME DATA
	IDPB Q2,A		;STORE IT
	SOJG C,CHAN1		;LOOP
	RET			;RETURN

;ROUTINE TO CHANGE CONTIGUOUS BYTES IN -10 FORMAT TO SHUFFLED BYTES
;IN -11 FORMAT.
;ACCEPTS:
;	A/	ADDRESS TO RECIEVE SHUFFLED BYTES
;	B/	ILDB POINTER TO CONTIGUOUS BYTES
;	C/	NUMBER OF BYTES TO DO
;RETURNS:	+1

SHUFFL:	PUSH P,Q2		;SAVE A REGISTER
SHUF1:	SOJL C,SHUF2		;DONE QUIT
	ILDB Q2,B		;GET FIRST CHARACTER
	SOJL C,SHUF3		;DONE AFTER 1 CHARACTER
	ILDB D,B		;GET NEXT CHARACTER
	LSH D,^D8		;SHIFT INTO POSITION
	IOR D,Q2		;BUT CHARACTERS TOGETHER
	HRLZM D,(A)		;STORE CHARACTERS
	SOJL C,SHUF2		;QUIT
	ILDB Q2,B		;GET ANOTHER CHARACTER
	SOJL C,SHUF4		;QUIT
	ILDB D,B		;GET LAST CHARACTER
	LSH D,^D8		;PUT INTO POSITION
	IOR D,Q2		;PUT TOGETHER
	HRRM D,(A)		;STORE CHARACTER
	AOJA A,SHUF1		;NEXT WORD

SHUF2:	POP P,Q2		;RESTORE REGISTER
	RET			;RETURN

SHUF3:	HRLZM Q2,(A)		;STORE CHARACTER
	JRST SHUF2		;QUIT

SHUF4:	HRRM Q2,(A)		;STORE CHARACTER
	JRST SHUF2


;AS ASCII /ABCDE/ TO THE NEW FORM BYTE(1)0,0(7)B,A(1)0,0(7)D,C(1)0,0(7)E
;THIS IS DONE BECAUSE FOR DMA DEVICES (DIRECT MEMORY ACCESS) THAT
;THINK THEY'RE LOOKING AT AN -11 AND NOT A -10, SO WE MUST SHUFFLE THE
;DATA SO THEY DON'T FIND OUT THE TRUTH.
;ROUTINE TO ASK FOR THE LPT STATUS


;ROUTINE TO GET LPT STATUS.  ON THE KL, THE -11 SUPPLIED THE STATUS
;TO THE -10 AS PACKED BYTES, WHICH THE LPTTLS ROUTINE UNPACKS.  WE'LL
;CALL LPTTLS TOO, BUT WE'LL FIRST PACK THE BYTES SO THAT LPTTLS WON'T
;KNOW THAT WE'RE NOT AN -11 SENDING THE DATA.

NSIZE==26		;NUMBER OF 8-BIT BYTES IN DEVICE DEPENTENT STATUS
;
; THE STATUS BLOCK IS IN THE FOLLOWING FORMAT:
;
; PDP11 WORD NUMBERS
;
; WORD  0	STATUS WORD 0 (DV.XXX)
; WORD  1	STATUS WORD 1 (DD.XXX)
; WORD  2	(HIGH 8 BITS) # BYTES OF DEVICE DEPENDENT INFO
;		(LOW BYTE) # BYTES OF DEVICE REGISTERS (ALWAYS 20)
; WORD  3	(LOW BYTE) ACCUMULATED CHECKSUM (HIGH BYTE)RETRY COUNT (NOT ALL IMPL)
; LP20 DEVICE REGISTERS
; WORD 4	LPCSRA
; WORD 5	LPCSRB
; WORD 6	LPBSAD
; WORD 7	LPBCTR
; WORD 10	LPPCTR
; WORD 11	LPRAMD
; WORD 12	LPCBUF/LPCCTR
; WORD 13	LPTDAT/LPCKSM




OURTLS:	SAVEPQ			;SAVE REGISTERS
	HRRZ A,U		;GET UNIT NUMBER
	IMULI A,LPERSZ		;POINT TO CORRECT BLOCK
	ADD A,[POINT 8,LPERBF]	;POINT TO BUFFER
	MOVE P6,A		;SAVE BUFFER POINTER
	MOVE P5,A
	MOVEI B,0		;SET "DEVICE HUNG" AND "ERROR FROM -11" BITS TO 0
	IDPB B,P5		;STORE THOSE BITS
	MOVEI Q2,0		;START WITH 0'S FOR SECOND BYTE
	CALL LPTRUE		;MAKE SURE PRINTER EXISTS
	TXO Q2,.DVFNX+.DVFOL	;NO, SET BIT THAT SAYS SO, 
				;ALSO OFF LINE, OP INTERVENTION REQUIRED
	MOVE B,Q2
	MOVE D,LCRTAB(U)	;GET REGISTER BASE ADDRESS
	SETZB Q3,P3		;FIRST ASSUME THE REGISTERS ARE 0
	TXNE B,.DVFNX		;PRINTER EXIST?
	JRST OURTL1		;NO, SO DON'T REFERENCE HARDWARE!
	RDIO Q3,LPCSRA(D)	;GET STANDARD STATUS BITS
	RDIO P3,LPCSRB(D)	;SPECIAL BITS
OURTL1:	TXNN Q3,LPWOL		;IS PRINTER ON-LINE?
	TXO B,.DVFOL		;NO, OFF, SO SAY SO
	TXNE P3,LP1PER+LP1MPE+LP1RPE+LP1SYE	;PARITY ERROR, MEMORY PARITY ERROR, RAM PARITY ERROR, MASTER SYNC ERROR 
	TXOA B,.DVFHE!.DVFFE	;HARD ERROR ON ANY OF THESE CONDITIONS
		;NOTE:  THE KL FRONT END DOESN'T SET IT'S CORRESPONDING .DVFFE
		;UNTIL A RETRY COUNT OF 10 RUNS OUT.  HENCE SOMEONE MAY WANT
		;TO IMPLEMENT THE RETRY FEATURE ON THE KS IF PROBLEMS ARISE.
	TXNE Q2,.DVFNX		;CHECK FOR END OF FILE IF NO ERRORAND EXISTS
	JRST NOTEOF		;EOF NOT POSSIBLE IF THERE'S AN ERROR
	MOVEI A,7777		;CHECK FOR COUNTER 0
	TION A,LPBCTR(D)	;IS COUNTER 0? (ALL CHARACTERS BEEN PRINTED?)
	TXO B,.DVFEF		;YES, SET EOF BIT
NOTEOF:	IDPB B,P5		;STORE VALUE OF REST OF STANDARD STATUS BITS
	MOVEI B,0		;FIRST WORD OF LPT STATUS IS ALL 0
	IDPB B,P5
	TXNE Q3,LPWPZR		;DID PAGE COUNTER REACH 0?
	TXO B,MO%LPC		;YES
	TXNE Q3,LPWCI		;UNDEFINED CHARACTER INTERRUPT?
	TXO B,MO%LCI		;YES
	TXNE P3,LPWDVN		;IS VFU ALRIGHT?
	JRST [	TXNE Q3,LPERR	;NOT AN ERROR IF ERROR NOT SET
		TXO B,MO%LVF		;NO
		JRST .+1]
	TXNE P3,LPWOVF		;DO WE HAVE AN OPTICAL VFU?
	TXO B,MO%LVU		;YES
	TXNE P3,LPWRPE		;WAS THERE A RAM PARITY ERROR?
	TXO B,MO%RPE		;YES
	IDPB B,P5		;STORE LPT STATUS BYTE
	MOVEI B,2		;NUMBER OF DEVICE-DEPENDENT INFO
	IDPB B,P5
	MOVEI B,20		;NUMBER OF DEVICE REGISTER BYTES
	IDPB B,P5
	TXNE Q2,.DVFNX		;CHECK FOR EXISTANT DEVICE
	JRST LPNEXA		;DON'T READ REGISTERS
	MOVEI A,0		;NO RETRY
	IDPB A,P5
	RDIOB A,LPCKSM(D)	;GET CHECKSUM
	IDPB A,P5		;STORE CHECKSUM
	IBP P5			;MUST GET TO NEXT WORD HERE
	HRLI P5,(<POINT 16,0>)	;SET UP FOR DEVICE REGISTERS
	MOVEI A,10		;NUMBER OF REGISTERS TO DUMP
LPDVDL:	RDIO B,(D)		;READ A REGISTER
	IDPB B,P5		;STORE IN BUFFER
	ADDI D,2		;LOOK AT NEXT REGISTER
	SOJG A,LPDVDL		;DO UNTIL ALL DONE
	TXNN Q2,.DVFHE		;CHECK FOR HARDERR
	JRST LPNEXD		;NO SYSERR REQUIRED
	MOVEI A,NSIZE+FE%LEN	;GET LENGTH OF BUFFER NEEDED
	MOVEI B,NSIZE+FE%SIZ
	CALL ALCSEB		;ALLOCATE BA BUFFER
	JRST LPNEXD		;NO BUFFER FORGET IT
	SETZM FE%DTE+SEBDAT(A)	;SET NO DTE
	MOVEI B,.FELPT		;GET THE DEVICE CODE
	HRLI B,0(U)		;SET THE UNIT NUMBER
	MOVEM B,FE%DEV+SEBDAT(A)
	MOVNI D,NSIZE		;GET THE SIZE
	HRLM D,FE%PTR+SEBDAT(A)	;SAVE COUNT OF WORDS
	MOVEI C,NSIZE		;GET SIZE
	MOVE D,P6		;GET POINTER TO BUFFER
	MOVE B,[POINT 8,FE%INF+SEBDAT(A)] ;POINTER TO DEVICE DATA
	MOVEM C,FE%BYT+SEBDAT(A)
SYELP:	ILDB P5,D		;GET BUFFER CHARACTERS
	IDPB P5,B		;STORE CHARACTERS
	SOJG C,SYELP
	MOVE B,[-2,,[
			SEBPTR 0,SBTEVC,SEC%FE
			SEBPTR 0,SBTFNA,LPTSER]]
	MOVE Q2,A		;SAVE POINTER TO ERROR BUFFER
	CALL SEBCPY
	JFCL			;FORGET IT IF ERROR
	MOVE A,Q2		;RESTORE BUFFER POINTER
	CALL QUESEB		;QUEUE ERROR
LPNEXD:	CALL CLRERR		;CLEAR ERRORS
LPNEXA:	MOVE B,U		;LPTTLS EXPECTS UNIT IN B
	MOVE D,P6		;POINTER TO BEGINNING OF BUFFER IN D
	MOVEI C,NSIZE		;NUMBER OF BYTES IN C
	CALLRET LPTTLS		;GO MULL OVER STATUS AND RETURN
;
; ROUTINE TO CHECK FOR INTERRUPT ENABLE ON THE LP20
;
LP20IE:	CALL LPTRUE		;CHECK TO SEE IF LINEPRINTER EXISTS
	RET			;NOPE -- JUST RETURN
	MOVEI A,LP1IEN		;GET INTERRUPT ENABLE FLAG
	TIOE A,@LCRTAB(U)	;CHECK TO SEE IF IT IS SET
	RET			;YES -- ALL OK
	BUG(LP2IEN,<<U,D>>)
	BSIO A,@LCRTAB(U)	;SET INTERRUPT ENABLE AND HOPE
	RET			;RETURN




;ROUTINE CALLED BY SYSER RO DETERMINE OWING PROCESS AND
;COMPLETE THE SYSERR BLOCK
;
;

LPTSER:	SETZ B			;SET UNIT (ONLY 1 FOR NOW)
	JE LPOPN,(B),[		;OPENED?
		MOVNI C,-1	;SAY UNASSIGNED
		JRST LPFKS]	;STORE IT
	LOAD B,LPFRK,(B)	;GET ID OF OWNER
	HLRZ C,FKJOB(B)		;FIND FORK
	HRLI C,0(B)		;UNIT
	MOVE B,JOBDIR(C)	;DIRECTORY
	HRLI B,USRLH		;SET UP USER NUMBER
	MOVEM B,FE%DIR+SEBDAT(A) ;STORE DIR NUMBER
	MOVE B,JOBPNM(C)	;GET NAME
	MOVEM B,FE%NAM+SEBDAT(A)
LPFKS:	MOVEM C,FE%FJB+SEBDAT(A)
	MOVEI B,FE%INF		;START OF ERROR WORDS
	HRRM B,FE%PTR+SEBDAT(A)
	SETZM FE%ID+SEBDAT(A)
	RET			;RESTURN


	TNXEND
	END