Google
 

Trailing-Edge - PDP-10 Archives - BB-JR93N-BB_1990 - 10,7/galaxy/lptspl/lptser.mac
There are 16 other files named lptser.mac in the archive. Click here to see a list.
TITLE	LPTSER - LINE PRINTER SERVICE ROUTINE FOR MULTIPLE LINE PRINTERS - V531
SUBTTL	T. N. MCMANUS /TNM/CHW/RCC/LSS   TS 25-OCTOBER-88

	SEARCH	F,S,DEVPRM
	$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 
;1973,1974,1975,1976,1977,1978,1979,1980,1982,1984,1986,1988.
;ALL RIGHTS RESERVED.

.CPYRT<1973,1988>


XP VLPTSR,531		;DEFINE GLOBAL VERSION NUMBER FOR LOADER MAP

LPTSER::ENTRY	LPTSER
SUBTTL	CONI/CONO DEFINITIONS

;LINE PRINTER CONI BITS AND MASKS FOR LP100 AND BA10

	CI.VFU==3B1			;VFU TYPE
	   VFUPT==0			;OPTICAL
	   VFUDA==1			;DIRECT ACCESS
	   VFUNO==2			;NONE
	CI.FEN==1B2			;FEATURES ENABLED
	CI.ENV==1B3			;EVEN PARITY
	CI.CTR==7777B17			;PAGE COUNTER
	CI.INT==1B18			;INTERRUPT IF CI.FEN
	CI.NRY==1B19			;LPT NOT READY
	CI.PZR==1B20			;PAGE COUNTER ZERO
	CI.PAR==1B21			;LPT PARITY ERROR
	CI.VFE==1B22			;VFU ERROR
	CI.NLD==1B23			;VFU LOAD INHIBIT
	CI.CHR==3B25			;CHARACTER SET (BA10 ALSO)
	   CHR64==0			;64 CHARACTERS
	   CHR96==1			;96 CHARACTERS
	   CHR128==2			;128 CHARACTERS
	   CHRVAR==3			;VARIABLE (NOT BA10)
	CI.LOV==1B26			;LINE OVERFLOW (646 ONLY)
	CI.OFL==1B27			;OFF-LINE (BA10 ALSO)
	CI.BSY==1B28			;BUSY (BA10 ALSO)
	CI.DON==1B29			;DONE (BA10 ALSO)
	CI.PIB==7B32			;ERROR INTERRUPT CHN (BA10 ALSO)
	CI.PIA==7B35			;DONE INTERRUPT CHN (BA10 ALSO)

;LINE PRINTER CONO BITS AND MASKS FOR LP100 AND BA10

	CO.CIN==1B18			;CLEAR INTERRUPT
	CO.FEN==1B20			;FEATURES ENABLED
	CO.CPE==1B21			;CLEAR PARITY ERROR
	CO.SEP==1B22			;SEND EVEN PARITY
	CO.NLD==1B23			;INHIBIT VFU LOAD
	CO.PRI==1B25			;PRINTER INIT (BA10 ALSO)
	CO.LSV==1B26			;LOAD STANDARD VFU
	CO.SPC==1B27			;NEXT DATAO SETS PAGE COUNTER
	CO.SBY==1B28			;SET BUSY (BA10 ALSO)
	CO.SDN==1B29			;SET DONE (BA10 ALSO)
	CO.PIB==7B32			;ERROR INTERRUPT CHN (BA10 ALSO)
	CO.PIA==7B35			;DONE INTERRUPT CHAN (BA10 ALSO)

;SPECIAL CONI/CONO COMBOS

	CI%SKP==CI.INT+CI.LOV+CI.OFL+CI.DON  ;CONSO SKIP CHAIN MASK
	CI%SKF==CI.INT			     ;CONSO MASK WHEN LPT IF OFF
	CI%SKE==CI%SKP-CI.DON		     ;CONSO/Z SKIP IF ERROR
	CO%OFF==CO.CIN+CO.FEN+CO.CPE	     ;CONO TO TURN LPT OFF
	CO%ON==CO%OFF+CO.SDN		     ;CONO TO TURN LPT ON
SUBTTL	SYMBOL DEFINITIONS

;DEVICE DEPENDENT BITS IN LH OF DEVIOS
	LPTSYN==Z(1B11)			;CRFF AFTER CLOSE HAS BEEN SENT
	LPTEND==Z(1B10)			;CLOSE UUO HAS BEEN DONE
	LPTRBL==Z(1B9)			;LPT TROUBLE DETECTED AT INTERRUPT LEVEL
	LPTOPB==Z(1B8)			;PARTIAL BUFFER ALREADY OUTPUT

;DEVICE DEPENDENT BITS IN RH OF DEVIOS
	LPTNFF==100			;SUPPRESS FREE FORM FEEDS
SUBTTL	LPT ERROR REPORTING

;EIGHT WORDS ARE IN EACH LINEPRINTER DDB FOR DAEMON ERROR REPORTING.

;;         !=======================================================!
;; LPTDAP: !          AOBJN POINTER TO DAEMON ERROR BLOCK          !
;;         !=======================================================!
;;	
;;	
;;	
;;         !=======================================================!
;; LPTDAE: !                  SIXBIT DEVICE NAME                   !
;;         !-------------------------------------------------------!
;;         !CTR TYPE!DEV TYPE!      !N !        RETRY COUNT        !
;;         !-------------------------------------------------------!
;;         !                          PPN                          !
;;         !-------------------------------------------------------!
;;         !                     PROGRAM NAME                      !
;;         !-------------------------------------------------------!
;;         !   # WORDS IN SUB-BLOCK    !     SUB-BLOCK OFFSET      !
;;         !-------------------------------------------------------!
;;         !                  CONI WORD AT ERROR                   !
;;         !-------------------------------------------------------!
;;         !              LAST DATA WORD SENT TO LPT               !
;;         !=======================================================!


	.LENAM==0		;SIXBIT DEVICE NAME
	.LETYP==1		;CONTROLLER/DEVICE TYPE
	  LE.CTR==77B5		;CONTROLLER TYPE
	    .LECIL==.HCTUK	;ILLEGAL
	    .LECBX==.HCTBX	;BA-10
	    .LECLC==.HCTLC	;LP-100
	  LE.DTP==77B11		;DEVICE TYPE
	    .LEDLP==1		;LPT
	  LE.NRC==1B17		;NON-RECOVERABLE ERROR
	  LE.RTY==777777B35	;RETRY COUNT
	.LEPPN==2		;PPN
	.LEPGM==3		;PROGRAM NAME
	.LEPTR==4		;NUMBER WORDS FOLLOWING,,OFFSET TO FIRST
	.LECNI==5		;CONI AT ERROR
	.LEDAT==6		;LAST DATA WORD SENT TO LPT

	.LESIZ==7		;SIZE OF THE BLOCK
SUBTTL	AUTOCONFIGURE


;DRIVER CHARARCTERISTICS
;	LPT	= LPTCNF
;	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	(LPT,LPT,7,0,0,0,MDSEC0,MDSEC0,<DR.GCC!DR.NET>)

	 .ORG	DEVLEN

LPTCHF:! BLOCK	1		;PI CHANNEL FLAGS
LPTCSO:! BLOCK	1		;ADDRESS OF INTERRUPT CODE
LPTSVE:! BLOCK	1		;ADDRESS OF ALTERNATE ENTRY TO INTERRUPT CODE
LPTRET:! BLOCK	1		;ADDRESS OF ALTERNATE EXIT FROM INTERRUPT
LPTPAG:! BLOCK	1		;PAGE COUNTER
LPTPTR:! BLOCK	1		;BLKO POINTER
LPTDAP:! BLOCK	1		;AOBJN POINTER TO ERROR BLOCK
LPTDAE:! BLOCK	7		;DAEMON ERROR BLOCK
LPTIOB:!			;START OF I/O INSTRUCTIONS
LPTCNI:! BLOCK	1		;CONI
LPTCNO:! BLOCK	1		;CONO
LPTDTO:! BLOCK	1		;DATAO
LPTBKO:! BLOCK	1		;BLKO
LPTSTS:! BLOCK	1		;DEVICE STATUS WORD CONI
LPTDNO:! BLOCK	1		;CONSZ SKIP IF ERROR
LPTDNZ:! BLOCK	1		;CONSO SKIP IF ERROR
LPTCSZ:! BLOCK	1		;CONSO FOR LINE CONTROL
LPTIOE:!			;END OF I/O INSTRUCTIONS
LPTFRM:! BLOCK	1		;FORMS TYPE NAME (SIXBIT)
LPTLEN:!			;LENGTH OF LPT DDB

	 .ORG


	$LOW
LPTDDB:	DDBBEG	(LPT,LPTLEN)
	SETWRD	(DEVCHR,<6*HUNGST+DVLPTL,,LPTSIZ##>) ;DEVCHR
	SETWRD	(DEVSER,<MCSEC0+LPTDSP>)	;DEVSER
	SETWRD	(DEVMOD,<DVOUT!DVLPT,,<1_A+1_AL+1_I>>) ;DEVMOD
	SETWRD	(DEVTYP,<<.TYLPT*.TYEST>!.SPLPT!DEPLEN,,0>) ;DEVTYP
	SETWRD	(DEVCPU,<LPTCHN##>)		;DEVCPU
	SETWRD	(LPTCHF,<<LPTCHN##*10>+LPTCHN##>) ;PI CHANNEL FLAGS (ERR+INT)
	SETWRD	(LPTDNO,<CONSZ 000,CI%SKE>)	;SKIP IF ERROR
	SETWRD	(LPTDNZ,<CONSO 000,CI%SKE>)	;SKIP IF ERROR
	SETWRD	(LPTCSZ,<CONSZ 000,(U)>)	;LINE CONTROL
	SETWRD	(LPTCNI,<CONI 000,U>)		;CONI
	SETWRD	(LPTCNO,<CONO  000,(U)>)	;CONO
	SETWRD	(LPTDTO,<DATAO 000,(U)>)	;DATAO
	SETWRD	(LPTBKO,<BLKO  000,LPTPTR>)	;BLKO
	SETWRD	(LPTSTS,<CONI 000,DEVSTS>)	;DEVICE STATUS WORD CONI
	DDBEND
	$HIGH


;CONSO SKIP CHAIN CODE (AUTCON WILL FILL IN THE BLANKS)
LPTICD:	PHASE	0
	CONSO	000,0			;(00) SKIP IF INTERRUPT FOR THIS LPT
	JRST	.-1			;(01) GO TO NEXT SKIP CHAIN ELEMENT
	MOVEM	F,LPTSAV		;(02) SAVE AC F
	SKIPA	F,.+1			;(03) SET UP DDB ADDRESS
	EXP	0			;(04) DDB ADDRESS
	XJRST	.+1			;(05) CALL INTERRUPT HANDLER
	EXP	0			;(06) INTERRUPT HANDLER ADDRESS
LPTINX:!MOVE	F,LPTSAV		;(07) RESTORE AC F
	JSR	PIERR##			;(10) SAVE ACS AND SETUP PDL
	SKIPA	F,.+1			;(11) SET UP DDB ADDRESS
	EXP	0			;(12) DDB ADDRESS
	XJRST	.+1			;(13) CALL INTERRUPT HANDLER
LPTICN:!EXP	0			;(14) INTERRUPT HANDLER ADDRESS
LPTEXT:!MOVE	F,LPTSAV		;(15) RESTORE AC F
	XJEN	-1			;(16) DONE
LPTSAV:!EXP	-1			;(17) STORAGE FOR AC F
	DEPHASE
LPTICL==.-LPTICD			;LENGTH OF CONSO SKIP CHAIN CODE

EQUATE	(LOCAL,0,<LPTCKT,LPTKDB,LPTKLN,LPTUDB,LPTULN>)
EQUATE	(LOCAL,0,<LPTULB,LPTULP>)

LPXDSP:	DRVDSP	(LPT,LPTCHN##,LPTDDB,LPTLEN,URDDIA##)

;DEFAULT MONGEN'ED DEVICE TABLE
DEFMDT:	MDKL10	(7,124,0,0,<MD.KON>)	;DEVICE CODE 124
	MDKL10	(7,234,0,0,<MD.KON>)	;DEVICE CODE 234
	MDKL10	(7,230,0,0,<MD.KON>)	;DEVICE CODE 230
	MDTERM

;BITS FOR MDT ENTRIES ARE ASSIGNED HERE
	LPT.UC==:1		;UPPER-CASE ONLY PRINTER
LPTCFG:	XMOVEI	T1,LPTMDT##	;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
	PUSH	P,T1		;SAVE MDT DATA
	MOVEI	T1,LPTIOB	;WORD CONTAINING AN I/O INSTRUCTION
	PUSHJ	P,AUTFND##	;SEE IF THERE'S ALREADY A DDB
	  JRST	LPTCF1		;JUST MAKE SURE THE NUMBERS ARE OK
	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	[POP	P,T1	;NO CORE
		 PJRST	AUTDDN##] ;DEALLOCATE DEVICE NUMBER
LPTCF1:	MOVSI	T1,-<LPTIOE-LPTIOB> ;-LENGTH
	XMOVEI	T2,LPTIOB(F)	;STARTING ADDRESS
	HRRZ	T3,.CPDVC##	;DEVICE CODE
	PUSHJ	P,AUTDVC##	;FILL IN DEVICE CODES
	SKIPE	LPTCSO(F)	;BEEN HERE BEFORE?
	JRST	LPTCF3		;THEN DON'T MESS WITH THE SKIP CHAIN
	ADDM	F,LPTSTS(F)	;RELOCATE CONI TO LOAD UP DEVSTS
	ADDM	F,LPTBKO(F)	;RELOCATE BLKO INSTRUCTION
	MOVE	T1,F		;DATA BLOCK ADDRESS
	XMOVEI	T2,LPTINT	;INTERRUPT SERVICE
	PUSHJ	P,AUTICD##	;GENERATE INTERRUPT ROUTINES
	  SKIPA	T2,F		;NO CORE
	JRST	LPTCF2		;ONWARD
	MOVEI	T1,LPTLEN	;DDB ADDRESS
	PUSHJ	P,AUTKIL##	;DELETE THE DDB
	PUSHJ	P,AUTDDN##	;DEALLOCATE DEVICE NUMBER
	JRST	TPOPJ##		;PHASE STACK AND RETURN
LPTCF2:	MOVEM	T1,LPTCSO(F)	;SAVE ADDRESS
	MOVEI	T2,LPTNXT	;ALTERNATE INTERRUPT ENTRY POINT
	HRRM	T2,LPTICN(T1)	;SET UP DISPATCH
	MOVEI	T2,LPTINX(T1)	;ALTERNATE INTERRUPT ENTRY ADDRESS
	MOVEM	T2,LPTSVE(F)	;SAVE
	MOVEI	T2,LPTEXT(T1)	;ALTERNATE INTERRUPT EXIT ADDRESS
	MOVEM	T2,LPTRET(F)	;SAVE
	MOVEI	T2,LPTCHN##	;PI CHANNEL
	PUSHJ	P,AUTCSO##	;LINK INTO CONSO SKIP CHAIN
LPTCF3:	POP	P,T4		;RESTORE MDT DATA
	MOVSI	T1,DVLPTL	;LOWERCASE LPT BIT
	TRNE	T4,LPT.UC	;IF THIS IS AN UPPER-CASE ONLY PRINTER,
	ANDCAM	T1,DEVCHR(F)	;CLEAR IT FOR LPTTYP
;ADD FUTURE MDT VALUE TESTS HERE
	POPJ	P,		;ALL DONE
;LINE PRINTER SERVICE DISPATCH TABLE

	JRST	LPTONL		;SEE IF LPT IS ON LINE NOW
	JRST	LPTDVP		;DEVOP. UUO
	JRST	REGSIZ##	;GET BUFFER SIZE FROM DDB
	JRST	LPTINI		;INITIALIZE
	JRST	LPTHNG		;HUNG DEVICE ERROR
LPTDSP:	JRST	LPTREL		;RELEASE
	JRST	LPTCLS		;CLOSE
	JRST	LPTOUT		;OUTPUT
	JRST	ILLINP##	;INPUT
SUBTTL	MONITOR-LOAD DEVICE INITIALIZATION

;LPTINI IS CALLED AT SYSTEM INITIALIZATION TIME FROM
;	IOGO IN SYSINI WITH THE DDB ADDRESS IN F

	;	1.  CLEAR THE SPECIFIED LINE PRINTER
	;	2.  DEASSIGN BOTH THE ERROR AND DONE INTERRUPT
	;	     CHANNELS FOR THAT LINE PRINTER
	;	3.  CLEAR THE SKIP CHAIN INTERRUPT MASK FLAGS
	;	     FOR THAT LINE PRINTER

	;NOTE:  THE LPTINI CODE FORCES IOGO IN SYSINI TO INVOKE
	;       LPTINI FOR EACH LINE PRINTER 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 THE LPTINI CODE
	;       IS DEPENDANT UPON THE IOGO CODE WHICH SHOULD BE:
	;		PUSHJ P,DINI(P3)
	;		HRRZM P3,SAVITM

LPTINI:	CAIN	F,LPTDDB	;PROTOTYPE DDB?
	JRST	CPOPJ1##	;IOGO WILL CALL US AGAIN
	PUSHJ	P,LPTREL	;GO THRU RELEASE CODE
	MOVSI	T1,-.LESIZ	;LOAD LENGTH OF ERROR BLOCK
	HRRI	T1,LPTDAE(F)	;MAKE AN AOBJN POINTER
	MOVEM	T1,LPTDAP(F)	;AND STORE IT
	MOVE	T1,DEVNAM(F)	;GET DEVICE NAME
	MOVEM	T1,LPTDAE+.LENAM(F) ;SAVE TIME AT INTERRUPT LEVEL
	MOVEI	T1,.LEDLP	;DEVICE TYPE IS LPT
	DPB	T1,[POINT 6,LPTDAE+.LETYP(F),11] ;STORE IN TYPE WORD
	MOVE	T1,[.LESIZ-.LEPTR-1,,.LECNI] ;GET SUB-BLOCK POINTER
	MOVEM	T1,LPTDAE+.LEPTR(F) ;SAVE IN POINTER WORD
	PJRST	CPOPJ1##	;SKIP RETURN TO FORCE CALL FOR EACH LPT
SUBTTL	OUT/OUTPUT UUO

LPTOUT:	TLO	S,IO		;NO, INDICATE OUTPUT
	PUSHJ	P,LPTOFL	;IF TROUBLE, GET IT FIXED
	XCT	LPTCNI(F)	;DO A CONI
	ANDI	U,CI.NLD	;GET STATE OF NO LOAD BIT
	IOR	U,LPTCHF(F)	;GET CHANNEL ASSIGNMENT FROM DDB
	TRO	U,CO%ON		;SET LPT "ON"
	TRNE	S,LPTNFF	;SUPPRESS FORM FEED?
	TLZA	S,IOBEG		;YES, CLEAR IOBEG AND OUTPUT FIRST BUFFER
	TLNN	S,IOBEG		;1ST OUTPUT?
	JRST	LPTGO		;NO, CONTINUE ON NORMALLY

;HERE IF THIS IS THE FIRST OUTPUT AFTER INIT
	PUSHJ	P,LPTSTI	;SETUP INITIAL BLKO POINTER
	CAIA

;HERE TO START THE PRINTER GOING
LPTGO:	PUSHJ	P,LPTSET	;SET UP BLKO POINTER
	PUSHJ	P,SETACT##	;SET IOACT, STORE S, SET HNG CNT
	HLL	U,LPTCHF(F)	;GET SKIP CHAIN MASK FLAGS
	PIOFF			;TURN OFF PI TO PREVENT IMM. INT.
	XCT	LPTCNO(F)	;SEND CONDITIONS OUT TO LPT
	HLRM	U,@LPTCSO(F)	;SAVE SKIP CHAIN MASK FLAGS
	XCT	LPTCSZ(F)	;FIND OUT IF DEVICE EXISTS
	JRST	ONPOPD##	;DEVICE RECEIVED CONO, OK
	PION			;REENABLE ALL INTERRUPTS
	PUSHJ	P,CLRACT##	;DEVICE NON-EXISTANT OR OFF, CLEAR IOACT
	PUSHJ	P,LPTSTP	;DON'T LEAVE THE CONSO MASK SETUP
	PUSHJ	P,LPTOF1	;CLEAR HUNG COUNTER AND PRINT A MESSAGE
	JRST	LPTOUT		;TRY AGAIN WHEN WE GET BACK


;HERE DURING OUTPUT UUO TO SEE IF DEVICE EXISTS
LPTOFL:	PUSHJ	P,LPTONL	;SEE IF LPT IS ON-LINE
	  SKIPA			;IT'S NOT, TELL THE USER
	POPJ	P,		;IT IS, JUST RETURN
LPTOF1:	MOVEM	S,DEVIOS(F)	;YES, SAVE S (LPTRBL OFF)
	MOVSI	T4,DEPADV	;WANT BUFFER LEFT ALONE
	IORM	T4,DEVADV(F)	;
	MOVSI	T4,DVOFLN	;MARK LPT OFF LINE
	IORM	T4,DEVCHR(F)
	PUSHJ	P,HNGSTP##	;HALT JOB & PRINT REMINDER
	MOVSI	T4,DEPADV	;LOAD "DONT ADV BUFFERS"
	ANDCAM	T4,DEVADV(F)	;AND CLEAR IT IN THE DDB
	JRST	LPTOFL		;BACK HERE ON CONT, TRY AGAIN
SUBTTL	CLOSE UUO - RELEASE UUO

;CLOSE UUO  -  WHEN A CLOSE UUO IS EXECUTED (OR CLOSE COMMAND)
;	LPTCLS IS CALLED.  LPTCLS RESETS SOME STATUS FLAGS AND
;	LIGHTS LPTEND SO THE FINAL CRFF CAN BE SETUP NEXT TIME
;	LPTOUT IS CALLED.  LPTCLS RETURNS BY BRANCHING TO "OUT"
;	SO THE LAST PARTIAL BUFFER IS OUTPUT.

LPTCLS:	TLO	S,LPTEND	;SET "CLOSE DONE"
	TLZ	S,LPTOPB+LPTSYN	;CLEAR TROUBLE BITS
	MOVEM	S,DEVIOS(F)	;STORE S
	JRST	OUT##		;AND CALL OUT FOR LAST BUFFER



;RELEASE UUO  -  WHEN A "RESET" IS DONE ON THE LPT, LPTREL IS
;	CALLED.  THE LINEPRINTER IS "TURNED-OFF" (SEE LPTOFF)
;	THE PAGE COUNTER IS TURNED OFF AND THE DDB IS CLEANED UP.

LPTREL:	PUSHJ	P,LPTTYP	;SETUP LINEPRINTER TYPE
	CAIE	T2,.LECLC	;AN LP100?
	JRST	LPTRE1		;NO, BA10
	MOVEI	U,CO%OFF+CO.NLD	;TURN OFF THE LPT AND DISABLE LOADING THE VFU
	MOVEI	T1,CI%SKP-CI.OFL ;CONSO MASK
	HRLI	T1,CI%SKF	;SKIP ON ERRORS
	JRST	LPTRE2		;GO DO THE INITIALIZATION
LPTRE1:	MOVEI	U,CO.PRI	;ZAP THE PRINTER
	MOVEI	T1,CI%SKP	;CONSO MASK
	HRLI	T1,CI%SKE	;SKIP ON ERRORS
LPTRE2:	XCT	LPTCNO(F)	;TURN THE LPT OFF
	HRLM	T1,LPTCHF(F)	;STORE THE CONSO MASK
	HLRM	T1,LPTDNZ(F)	;SKIP ON ERRORS
	HLRM	T1,LPTDNO(F)	;SKIP ON DONE
	HLLZS	@LPTCSO(F)	;AND TAKE IT OFF CONSO CHAIN
	MOVSI	T1,DEPADV	;GET "DONT ADV BUFFER" BIT
	ANDCAM	T1,DEVADV(F)	;TURN IT OFF
	TLZ	S,LPTOPB	;CLEAR THE TROUBLE BITS
	SETOM	LPTPAG(F)	;TURN OFF PAGE COUNTER
	TRZ	S,IOACT		;CLEAR ACTIVE I/O
	PJRST	STOIOS##	;SAVE S AND RETURN


	LPTHNG==LPTREL			;HUNG DEVICE IS SAME AS RELEASE
SUBTTL	INTERRUPT ENTRY & DATA INTERRUPT ROUTINE

;ENTER HERE ON ALL INTERRUPTS
LPTINT:	XCT	LPTSTS(F)	;STORE CONI STATUS IN DDB
	HRL	F,DEVIOS(F)	;GET RH FLAGS
	TLNN	F,IOACT		;JOB DOING I/O
	XJRST	LPTSVE(F)	;NO, RANDOM DONE INTERRUPT
	XCT	LPTDNZ(F)	;SKIP IF DONE FLAG IS OFF
	SKIPL	LPTPTR(F)	;BLKO COUNT TO 0 ON LAST INT?
	XJRST	LPTSVE(F)	;YES, SAVE AC'S, RETURNS AT LPTNXT
	XCT	LPTBKO(F)	;NO, SEND NEXT WORD FOR PRINTING
	  XJRST	LPTRET(F)	;LAST WORD SENT BUT INT PENDING
	XJRST	LPTRET(F)	;GO RESTORE F AND RETURN

;LAST BLKO POINTER RAN OUT.  NEED TO ADVANCE BUFFER-RING AND SETUP BLKO
LPTNXT:	PUSHJ	P,IOSET##	;SETUP ACS R AND S
	XCT	LPTDNO(F)	;SKIP IF DONE IS UP
	JRST	LPTERR		;ELSE HANDLE ERROR INTERRUPT
	TRNN	S,IOACT		;RANDOM DONE INT?
	JRST	LPTSTP		;YES, STOP PRINTER
	TLZE	S,IOBEG		;NO BUFFER ADVANCE ON 1ST OUTPUT
	JRST	LPTNX1		;YES, SETUP NEXT BLKO AND RETURN
	TLZE	S,LPTEND	;CLOSE DONE?
	JRST	LPTNX2		;YES, OUTPUT CRFF
	TLZN	S,LPTSYN	;WAS CRFF JUST OUTPUT?
	PUSHJ	P,ADVBFE##	;NO, ADVANCE TO NEXT BUFFER
	  PJRST	LPTSTP		;CANT ADVANCE, BUFFER UNAVAIL
	PUSHJ	P,SETIOD##	;ARRANGE FOR JOB TO RUN AGAIN
LPTNX1:	PUSHJ	P,LPTSET	;SET UP NEW BLKO POINTER
	PJRST	STOIOS##	;SAVE S, SET HUNG COUNT, AND JEN
LPTNX2:	PUSHJ	P,RTNEVM##
	TLO	S,LPTSYN	;REMEMBER CRFF SENT SO DON'T ADVANCE BUFFERS
	PUSHJ	P,LPTSTI	;SET BLKO POINTER FOR CRFF
	JRST	STOIOS##	;STORE S AND JEN
SUBTTL	ERROR INTERRUPT ROUTINE

LPTERR:	XCT	LPTCNI(F)	;DO A CONI TO READ LPT STATUS
	TRNE	U,CI.PZR	;PAGE-ZERO?
	JRST	LPTPZR		;YES, HANDLE ZERO PAGE COUNTER
	TRNE	U,CI.VFE	;VFU ERROR?
	JRST	LPTVFE		;YES HANDLE VFU ERROR
	TRNE	U,CI.PAR	;LINE-PRINTER PARITY?
	JRST	LPTPAR		;YES, HANDLE PARITY ERROR
	TRNE	U,CI.LOV	;LINE OVERFLOW (PDP6 PRINTER)
	JRST	LPTLOV		;YES, DO IT
	TRNE	U,CI.OFL+CI.NRY	;OFF-LINE?
	JRST	LPTNOL		;YES, HANDLE IT

;HERE IF ON-LINE OR VFU ERROR CLEARED
	MOVSI	T1,DVOFLN	;OFF-LINE BIT
	TDNN	T1,DEVCHR(F)	;IS THE LPT OFF-LINE?
	JRST	LPTRTI		;NO, MUST HAVE BEEN VFU ERROR CLEARING
	ANDCAM	T1,DEVCHR(F)	;CLEAR OFF-LINE BIT
	PUSHJ	P,PSIONL##	;TELL USER LPT IS NOW ON-LINE

	JRST	LPTRTI		;CLEAR INTERRUPT AND DISMISS

;HERE ON PAGE-COUNTER ZERO INTERRUPT ON LP100
LPTPZR:	MOVE	T2,LPTPAG(F)	;GET THE PAGE COUNTER
	MOVEI	T1,IOPLE%	;LOAD THE ERROR CODE
	PJUMPE	T2,LPTOER	;EMPTY, GIVE I/O ERROR
	PUSHJ	P,LPTSPC	;ELSE, SET IT
	JRST	LPTRTI		;CLEAR CONDITION AND RETURN
;HERE ON LINE-PRINTER PARITY ERROR ON LP100
LPTPAR:	PUSHJ	P,LPTSYR	;DO SYSERR REPORTING
	MOVEI	T1,IOPAR%	;LOAD PARITY ERROR
	PJRST	LPTOER		;GIVE USER ERROR AND RETURN

;HERE ON LINE-PRINTER VFU ERROR ON LP100
LPTVFE:	TRNN	U,CI.NLD	;LOADING THE VFU?
	JRST	LPTRTI		;YES, IGNORE VFU ERROR
	PUSHJ	P,LPTSYR	;TELL SYSERR
	PUSHJ	P,LPTNOL
	MOVEI	T1,IOVFE%	;VFU ERROR
	JRST	LPTOER		;TELL THE USER ABOUT IT

;HERE TO HANDLE LINE-OVERFLOW INTERRUPT ON PDP6 PRINTER
LPTLOV:	MOVN	U,[EXP 1000001]	;DECREMENT BLKO POINTER
	ADDM	U,LPTPTR(F)	;BACKUP THE POINTER
	MOVEI	U,[EXP 15B6+12B13]	;LOAD A CRLF
	XCT	LPTDTO(F)	;AND PRINT IT
	POPJ	P,		;RETURN

;HERE WHEN LINE PRINTER IS OFF-LINE
LPTNOL:	TRNN	S,IOACT		;OFF-LINE WHILE PRINTING
	JRST	LPTSTP		;NO, CATCH IT LATER
	MOVSI	T1,DVOFLN	;MARK LPT OFF-LINE
	IORM	T1,DEVCHR(F)	;FOR ON-LINE INTERRUPT
	TLO	S,LPTOPB	;INDICATE TROUBLE NOTICED ON INTERRUPT
	PUSHJ	P,LPTSTP	;TURN OFF LPT, CLEAR IOACT
	JRST	DEVERR##	;CAUSE UUOCON TO RETRY ON UUO LEVEL
SUBTTL	SETUP NEXT BLKO POINTER

LPTSET:	MOVEI	T1,@DEVOAD(F)	;GET ABS. ADDR. OF CURRENT BUFFER
	MOVN	T2,1(T1)	;GET NEGATIVE WORD COUNT
	HRL	T1,T2		;COMBINE NEG. WORD COUNT AND ADDR.
	TLZN	S,LPTOPB	;TROUBLE ON LAST IO?
	AOJA	T1,LPTS1	;NO
	SKIPL	T2,LPTPTR(F)	;YES PARTIAL BUFFER LEFT?
	JRST	[TLNE S,IOBEG!LPTSYN ;NO, TROUBLE ON FREE FORM FEED
		 AOJA T1,LPTS1	;YES, PROCEED WITH USERS BUFFER
		 PUSHJ P,ADVBFE## ;GET NEXT SINCE WE REALLY FINSHED LAST ONE
		   JRST LPTSTP	;WAS THE LAST, SHUT DOWN THE PRINTER
		 JRST LPTSET]	;SET UP FOR NEW BUFFER
	HRRI	T2,-1		;YES.  SET RH(T2) FOR SUB
	SUB	T2,T1		;LH(T2)=NO OF WORDS ALREADY OUT
	HLRS	T2
	ADD	T1,T2		;UPDATE POINTER BY NO OF WORDS DONE
	ADDI	T1,1		;+1 FOR IOWD TO FORM
LPTS1:	MOVEM	T1,LPTPTR(F)	; LPTPTR:= -(WORD COUNT),(BUFF. ADDR. +1)
	POPJ	P,		; AND RETURN


;HERE TO SETUP BLKO POINTER FOR CRFF ON OPEN AND CLOSE
;	SETS BLKO POINTER FOR CRFF UNLESS THE USER HAS REQUESTED
;	SUPPRESSION.  SETS LPTDAB SINCE NEXT BLKO WILL NOT PROCESS
;	"CURRENT" BUFFER.

LPTSTI:	SETZM	LPTPTR(F)	;CLEAR THE POINTER
	HRROI	T1,LPCRFF-1	;MAKE BLKO POINTER TO CRFF
	TRNN	S,LPTNFF	;DOES HE WANT THEM?
	MOVEM	T1,LPTPTR(F)	;YES, GIVE THEM TO HIM
	POPJ	P,		;AND RETURN

LPCRFF:	BYTE	(7)	15,14,0	;<CR><FF>
SUBTTL	DEVOP UUO INTERFACE

;HERE ON DISPATCH FROM UUOCON
;	F=DDB
;	T1=FUNCTION

LPTDVP:	MOVSI	T2,-LPTDVL	;GET TABLE LENGTH SETUP AOBJN PTR
LPTDV1:	HLRZ	T3,LPTDVT(T2)	;GET THE FUNCTION CODE
	HRRZ	T4,LPTDVT(T2)	;GET THE DISPATCH ADDRESS
	CAMN	T1,T3		;DO CODES MATCH?
	JRST	(T4)		;YES, DISPATCH
	AOBJN	T2,LPTDV1	;NO, LOOP
	PJRST	ECOD2##		;NO MATCH, GIVE AN ERROR

LPTDVT:	XWD	1,DVLLV		;LOAD HARDWARE VFU
	XWD	2,DVENV		;ENABLE PROGRAM VFU LOAD
	XWD	3,DVDEV		;DISABLE PROGRAM VFU LOAD
	XWD	1000,DVPC	;READ PAGE COUNTER
	XWD	2000,DVPC	;SET PAGE COUNTER
	XWD	1004,DVDCS	;READ DEVICE STATUS
	XWD	1005,DVFRMR	;READ FORMS TYPE
	XWD	2005,DVFRMS	;SET FORMS TYPE
	LPTDVL==.-LPTDVT		;DISPATCH TABLE LENGTH

;ROUTINE TO LOAD STANDARD HARDWARE VFU
DVLLV:	PUSHJ	P,LPTSCO	;SETUP FOR CONO
	TRO	U,CO.LSV	;SET
	JRST	DVLLV1		;ENTER COMMON CODE

;DISABLE PROGRAM LOADING OF VFU
DVDEV:	PUSHJ	P,LPTSCO
	TRO	U,CO.NLD
	JRST	DVLLV1

;ENABLE FOR PROGRAM LOADING OF VFU
DVENV:	PUSHJ	P,LPTSCO
	TRZ	U,CO.NLD	;SET
DVLLV1:	LDB	T2,[POINT 2,U,1] ;GET VFU TYPE
	CAIE	T2,VFUDA
	PJRST	ECOD5##
	XCT	LPTCNO(F)	;OK
	PJRST	CPOPJ1##	;SKIP RETURN
;HERE TO READ OR SET THE PAGE COUNTER
DVPC:	MOVE	T3,DEVHCW(F)	;GET CHARACTERISTICS
	TLNN	T3,(HC.PGC)	;DEVICE HAVE PAGE COUNTER?
	  PJRST	ECOD11##	;NO, ERROR
	TRNE	T1,1000		;READ?
	  JRST	DVPC1		;YES
	PUSHJ	P,GETWR1##	;NO, SET T1=PAGE ARG
	  PJRST	RTM1##		;ERROR
	SETOM	LPTPAG(F)	;ASSUME -1
	JUMPE	T1,CPOPJ1##	;RETURN
	MOVEM	T1,LPTPAG(F)	;STORE NEW PAGE COUNTER WORD
	PUSHJ	P,LPTSPC	;SET PAGE COUNTER
	JRST	CPOPJ1##

DVPC1:	SKIPGE	LPTPAG(F)	;ATTEMPT TO READ WHEN
	PJRST	ECOD10##	; NOT SET
	XCT	LPTCNI(F)	;GET STATUS
	LDB	T1,[POINT 12,U,17] ;ISOLATE PAGE COUNTER
	ADD	T1,LPTPAG(F)	;ADD IN REMAINING AMOUNT
	PJRST	STOTC1##	;RETURN WITH PAGE COUNT IN T1


;HERE TO READ LPT STATUS
DVDCS:	MOVEI	T1,0		;INITIALIZE
	PUSHJ	P,LPTONL	;READ STATUS/CHECK OFFLINE
	  TLO	T1,(DV.OFL)	;OFF LINE
	TRNE	U,CI.VFE	;VFU ERROR?
	TRO	T1,DV.VFE	;YES
	TRNN	U,CI.NLD	;CAN PROGRAM LOAD THE VFU?
	TRO	T1,DV.VLE	;YES
	PJRST	STOTC1##	;STORE STATUS/GOOD RETURN

;HERE TO READ/SET FORMS TYPE NAME
DVFRMR:	MOVE	T1,LPTFRM(F)	;GET FORMS NAME
	JRST	STOTC1##	;RETURN IT TO THE USER

DVFRMS:	PUSHJ	P,GETWR1##	;FETCH USER'S ARGUMENT
	  JRST	RTM1##		;ADDRESS CHECK ERROR
	MOVEM	T1,LPTFRM(F)	;SET IT
	JRST	CPOPJ1##	;RETURN SUCCESS
SUBTTL	VARIOUS UTILITY ROUTINES

;SUBROUTINE TO SET THE HARDWARE PAGE COUNTER
;	IF SOFTWARE PAGE COUNTER WORD (SPCW) IS .EQ. 0, JUST RETURN
;	ELSE SET HARDWARE PAGE COUNTER TO MAX(SPCW,7777) I IF THE
;	SPCW IS NOT-NEGATIVE, DECREMENT IT BY THE AMOUNT SET.

LPTSPC:	SKIPN	LPTPAG(F)	;IS THERE ANYTHING TO SET?
	POPJ	P,		;NO, JUST RETURN
	PUSHJ	P,LPTSCO	;SETUP FOR CONO
	TRO	U,CO.SPC	;SET THE FLAG
	XCT	LPTCNO(F)	;DO THE CONO
	SKIPL	U,LPTPAG(F)	;GET THE SPCW
	CAILE	U,7777		;WITHIN RANGE OF HARDWARE?
	MOVEI	U,7777		;NO, PUT WITHIN RANGE
	XCT	LPTDTO(F)	;SET THE PAGE COUNTER
	MOVNS	U		;NEGATE THE AC
	SKIPL	LPTPAG(F)	;DONT DECREMENT IF NOT SET
	ADDM	U,LPTPAG(F)	;DECREMENT THE SPCW
	POPJ	P,		;AND RETURN

;SUBROUTINE TO SETUP TO DO A CONO
;	DOES A CONI, PRESERVES BUSY, DONE, PIA, PIB, FEATURES ENABLE,
;	AND VFU-NOLOAD.  RETURNS WORD IN U.

LPTSCO:	XCT	LPTCNI(F)	;DO THE CONI
	TRZ	U,-1-CI.BSY-CI.DON-CI.NLD-CI.PIA-CI.PIB
	IORI	U,CO.FEN	;PRESERVE FEA-EN AND NOLOAD
	POPJ	P,		;AND RETURN
;SUBROUTINE TO SEE IF THE LPT IS ON LINE
LPTONL:	XCT	LPTCNI(F)	;GET THE CONI WORD
	JUMPE	U,[PIOFF	;NO CONI BITS, TURN OFF PI
		   MOVEI U,1	;"FAKE" PI CHANNEL
		   XCT LPTCNO(F) ;GIVE IT ONE (1)
		   XCT LPTCSZ(F) ;SEE IF SOMETHING TOOK IT
		   AOS (P)	;ITS THERE AND ON-LINE
		   SETZ U,	;CLEAR PI ASSIGNMENT
		   XCT LPTCNO(F) ;ZAP
		   JRST ONPOPD##] ;RESTORE PI SYS AND RETURN
	TRNE	U,CI.NRY!CI.OFL!CI.BSY	;IS IT OFF-LINE?
	POPJ	P,
	TLNE	U,(CI.FEN)
	TRNE	U,CI.NLD
	TRNN	U,CI.VFE
	AOS	(P)		;SKIP IF NOT "OFF"
	POPJ	P,		;EITHER OFF-LINE OR OFF

;HERE TO GIVE THE USER AN I/O ERROR AND DISMISS THE INTERRUPT
;	ERROR CODE IN T1.
LPTOER:	DPB	T1,PDVESE##	;STORE THE ERROR CODE
	PUSHJ	P,RTNEVM##	;RETURN ANY EVM
	TRO	S,740000	;SET ALL ERROR FLAGS IN S
				;FALL INTO DISMISS ROUTINE

;HERE TO STOP THE LPT AND START THE USER.
LPTSTP:	PUSHJ	P,LPTSCO	;SETUP TO DO CONO
	TLNN	U,(CI.FEN)	;DID FEATURES ENABLED SET?
	JRST	LPTOFF		;NO, OLD LPT
	HRLI	U,CI%SKP-CI.OFL	;CONSO MASK FOR PRINT WHEN OFF
	TRO	U,CO%OFF	;SET TO TURN LPT OFF
	TRZA	U,CI.DON+CI.NRY+CI.CHR
LPTOFF:	MOVEI	U,0		;CONO LPT, 0, NO CONSO MASK
	XCT	LPTCNO(F)	;TURN LPT OFF
	HLRM	U,@LPTCSO(F)	;SET CONSO MASK
	TRZE	S,IOACT		;CLEAR IOACT
	PUSHJ	P,SETIOD##	;START UP THE USER
	PJRST	STOIOS##	;STORE S AND RETURN
;HERE TO CLEAR ALL INTERRUPT CONDITIONS AND DISMISS THE INTERRUPT
LPTRTI:	PUSHJ	P,LPTSCO	;SETUP THE CONO WORD
	TRO	U,CO%OFF	;CLEAR THE CONDITIONS
	XCT	LPTCNO(F)	;DO THE CONO
	PJRST	STOIOS##	;STORE S AND RETURN

;HERE TO DO DAEMON ERROR REPORTING FOR SYSERR
LPTSYR:	LDB	J,PJOBN##	;GET JOB NUMBER FROM DDB
	MOVE	T1,JBTPPN##(J)	;GET PPN OF USER
	MOVEM	T1,LPTDAE+.LEPPN(F) ;SAVE IN ERROR REPORTING BLOCK
	MOVE	T1,JBTNAM##(J)	;GET NAME OF RUNNING JOB
	MOVEM	T1,LPTDAE+.LEPGM(F) ;SAVE IN ERROR REPORTING BLOCK
	XCT	LPTCNI(F)	;GET THE CONI
	MOVEM	U,LPTDAE+.LECNI(F)	;SAVE IT
	HRRZ	T1,LPTPTR(F)	;GET BLKO POINTER
	MOVE	T1,(T1)		;GET THE DATA WORD
	MOVEM	T1,LPTDAE+.LEDAT(F) ;SAVE IT
	MOVEI	T1,.ERHCC	;LOAD SYSERR TYPE
	HRLI	T1,LPTDAP(F)	;POINTER TO AOBJN POINTER
	PJRST	DAEERR##	;CALL DAEMON

;HERE TO SETUP HARDWARE CHARACTERISTICS WORD AND DETERMINE CONTROLLER TYPE
LPTTYP:	PUSHJ	P,LPTSCO	;SETUP UP CONO WORD
	XCT	LPTCNO(F)	;DO THE CONO
	XCT	LPTCNI(F)	;DO A CONI
	SETZ	T1,		;ASSUME UPPER CASE PRINTER
	LDB	T2,[POINTR (U,CI.CHR)] ;GET CHARACTER SET TYPE
	MOVSI	T3,DVLPTL	;GET LOWER CASE PRINTER BIT
	TLNE	U,(CI.FEN)	;FEATURES ENABLED (LPT100)?
	CAIG	T2,CHR64	;AND AN LOWER CASE PRINTER?
	TDNE	T3,DEVCHR(F)	;A LOWER CASE PRINTER?
	MOVSI	T1,(HC.LCP)	;YES, NOTE THAT
	DPB	T2,[POINTR (T1,HC.CST)] ;STORE CHARACTER SET TYPE
	LDB	T2,[POINTR (U,CI.VFU)] ;VFU TYPE
	DPB	T2,[POINTR (T1,HC.VFT)] ;BA10/LP100 CODES MATCH HC.VFT CODES
	ANDCAM	T3,DEVCHR(F)	;ASSUME AN UPPER CASE PRINTER
	TLNE	T1,(HC.LCP)	;LOWER CASE PRINTER?
	IORM	T3,DEVCHR(F)	;PROPAGATE BIT FOR UUOCON
	MOVEI	T2,.HCTBX	;ASSUME A BA10
	TLNN	U,(CI.FEN)	;LP100?
	JRST	LPTTY1		;BA10
	TLO	T1,(HC.PGC)	;LP100 HAS A HARDWARE PAGE COUNTER
	MOVEI	T2,.HCTLC	;INDICATE LP100
LPTTY1:	TLO	T1,(<.HCULP>B14) ;LP05 CLASS PRINTER
	HLLM	T1,DEVHCW(F)	;STORE HARDWARE CHARACTERISTICS
	DPB	T2,[POINT 3,DEVHCW(F),11] ;STORE CONTROLLER TYPE IN DEVHCW
	DPB	T2,[POINT 6,LPTDAE+.LETYP(F),5] ;AND CONTROLLER TYPE
	POPJ	P,		;RETURN
	$LIT
	END