d .TITLE LPDRIVER - LP11/LS11/LV11 LINE PRINTER DRIVER .IDENT /X05/ , ; ; COPYRIGHT (C) 1977 X; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS 01754 ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE FOR USE ONLY ON A SINGLE ; COMPUTER SYSTEM AND MAY BE COPIED ONLY WITH THE INCLUSION OF THE ; ABOVE COPYRIGHT NOTICE. THIS SOFTWARE, OR ANY OTHER COPIES THEREOF, L; MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY OTHER PERSON ; EXCEPT FOR USE ON SUCH SYSTEM AND TO ONE WHO AGREES TO THESE LICENSE ; TERMS. TITLE TO AND OWNERSHIP OF THE SOFTWARE SHALL AT ALL TIMES x; REMAIN IN DEC. ; @; THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE ; AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT ; CORPORATION. l; ; DEC ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS 4; SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DEC. ; ; R. HEINEN 6-SEP-76 ` ; ; MODIFIED BY: ( ; ; D. N. CUTLER 20-AUG-77 ; T ; LP11/LS11/LV11 LINE PRINTER DRIVER ;  ; MACRO LIBRARY CALLS ;  .LIBRARY "LIB.MLB" H $IDBDEF ;DEFINE IDB OFFSETS $IODEF ;DEFINE I/O FUNCTION CODES  $IRPDEF ;DEFINE IRP OFFSETS t $LPDEF ;DEFINE LINE PRINTER CHARACTERISTICS  $MSGDEF ;DEFINE SYSTEM MESSAGE TYPES < $PCBDEF ;DEFINE PCB OFFSETS  $PRDEF ;DEFINE PROCESSOR REGISTERS  $SSDEF ;DEFINE SYSTEM STATUS VALUES h $UCBDEF ;DEFINE UCB OFFSETS  0; ; LOCAL SYMBOLS ; \; ARGUMENT LIST OFFSET DEFINITIONS ; $ P1=0 ;FIRST FUNCTION DEPENDENT PARAMETER P2=4 ;SECOND FUNCTION DEPENDENT PARAMETER PP3=8 ;THIRD FUNCTION DEPENDENT PARAMETER P4=12 ;FOURTH FUNCTION DEPENDEND PARAMETER P5=16 ;FIFTH FUNCTION DEPENDENT PARAMETER |P6=20 ;SIXTH FUNCTION DEPENDENT PARAMETER  D; ; CHARACTER CODE DEFINITIONS ; p C_CR=13 ;CARRIAGE RETURN 8C_FF=12 ;FORM FEED C_VT=11 ;VERTICLE TAB C_LF=10 ;LINE FEED dC_TAB=9 ;TABULATION  ,; ; FLAG REGISTER BIT DEFINITIONS ; X M_CRPEND=1 ;CARRIAGE RETURN PENDING V_CRPEND=0 ;  ; L; LP11/LS11/LV11 DEVICE REGISTER OFFSET DEFINITIONS ;  x $DEFINI LP  @$DEF LP_CSR .BLKW 1 ;CONTROL STATUS REGISTER $DEF LP_DBR .BLKW 1 ;DATA BUFFER REGISTER  l $DEFEND LP 4!; !; DEFINE DEVICE DEPENDENT UNIT CONTROL BLOCK OFFSETS !; `" " $DEFINI UCB (# #.=UCB$K_LENGTH ; # T$$DEF UCB$L_LP_MUTEX .BLKL 1 ;LINE PRINTER UCB MUTEX $$DEF UCB$B_LP_CURSOR .BLKB 1 ;CURRENT HORIZONAL POSITION %$DEF UCB$B_LP_LINCNT .BLKB 1 ;CURRENT LINE COUNT ON PAGE %$DEF UCB$B_LP_OFLCNT .BLKB 1 ;OFFLINE TIME COUNTER % .BLKB 1 ;SPARE UNUSED BYTE H& & $DEFEND UCB ' t'; '; LOCAL DATA <(; (; DRIVER DISPATCH TABLE ); h) ) .PSECT WIONONPAGED 0*LP$DDT:: ; * .LONG STARTIO ;START I/O OPERATION * .LONG 0 ;UNSOLICITED INTERRUPT \+ .LONG FUNCTABLE ;FUNCTION TABLE + .LONG IOC$CANCELIO ;CANCEL I/O $, .LONG 0,0 ;NO DIAGNOSTIC OR ERROR LOG INFORMATION , .PAGE , .SBTTL LP11/LS11/LV11 FUNCTION DECISION TABLE P-; -; LP11/LS11/LV11 FUNCTION DECISION TABLE .; |. .FUNCTABLE: ;FUNCTION DECISION TABLE D/ FUNCTAB , ;LEGAL FUNCTIONS / FUNCTAB , ;BUFFERED I/O FUNCTIONS 0 FUNCTAB LP_WRITE, ;WRITE FUNCTIONS p0 FUNCTAB LP_SETMODE, ;SET CHARACTERISTICS FUNCTIONS 0 .PAGE 81 .SBTTL SET CHARACTERISTICS AND SET MODE FUNCTION PROCESSING 1;+ 2; LP_SETMODE - SET CHARACTERISTICS AND SET MODE FUNCTION PROCESSING d2; 2; THIS ROUTINE IS CALLED FROM THE FUNCTION DECISION TABLE DISPATCHER TO PROCESS ,3; A SET MODE FUNCTION TO A LINE PRINTER. 3; 3; INPUTS: X4; 4; R0 = SCRATCH. 5; R1 = SCRATCH. 5; R2 = SCRATCH. 5; R3 = ADDRESS OF I/O REQUEST PACKET. L6; R4 = CURRENT PROCESS PCB ADDRESS. 6; R5 = ASSIGNED DEVICE UCB ADDRESS. 7; R6 = ADDRESS OF CCB. x7; R7 = I/O FUNCTION CODE. 7; R8 = FUNCTION DECISION TABLE DISPATCH ADDRESS. @8; R9 = SCRATCH. 8; R10 = SCRATCH. 9; R11 = SCRATCH. l9; AP = ADDRESS OF FIRST FUNCTION DEPENDENT PARAMETER. 9; 4:; OUTPUTS: :; :; THE SPECIFIED CHARACTERISTICS ARE MOVED INTO THE DEVICE UCB AND THE `;; I/O IS COMPLETED. ;;- (< < .PSECT Y$EXEPAGED PUSHL R3 ;SAVE PACKET ADDRESS > MOVAB UCB$L_LP_MUTEX(R5),R0 ;GET ADDRESS OF UCB MUTEX > JSB SCH$LOCKW ;LOCK UCB FOR WRITE ACCESS H? CMPL #IO$_SETMODE,R7 ;SET MODE FUNCTION? ? BEQL 10$ ;IF EQL YES @ MOVW (R1),UCB$B_DEVCLASS(R5) ;SET DEVICE CLASS AND TYPE t@10$: MOVW 2(R1),UCB$W_DEVBUFSIZ(R5) ;SET DEFAULT BUFFER SIZE @ MOVL 4(R1),UCB$L_DEVDEPEND(R5) ;SET DEVICE CHARACTERISTICS ;SAVE REGISTERS Q MOVL P1(AP),R8 ;GET STARTING ADDRESS OF USER BUFFER R MOVZWL P2(AP),R9 ;GET LENGTH OF USER BUFFER lR CMPL #IO$_WRITEPBLK,R7 ;WRITE PHYSICAL BLOCK? R BEQL 10$ ;IF EQL YES 4S MOVL P4(AP),IRP$B_CARCON(R3) ;INSERT CARRIAGE CONTROL INFORMATION S JSB TT$CARRIAGE ;TRANSLATE CARRIAGE CONTROL INFORMATION S MOVZBL IRP$B_CARCON(R3),R0 ;GET NUMBER OF PREFIX CONTROL BYTES `T MOVZBL IRP$B_CARCON+2(R3),R1 ;GET NUMBER OF SUFFIX CONTROL BYTES T ADDL R0,R1 ;CALCULATE NUMBER OF CARRIAGE CONTROL BYTES (U MOVAB 32(R1)[R11],R10 ;CALCULATE TOTAL NUMBER OF OVERHEAD BYTES U10$: TSTL R9 ;ANY BUFFER SPECIFIED? U BEQL 20$ ;IF EQL NO TV MOVQ R8,R0 ;RETRIEVE BUFFER PARAMETERS V JSB EXE$WRITECHK ;CHECK ACCESSIBILITY OF USER BUFFER W20$: MOVAB 12(R9)[R10],R1 ;CALCULATE LENGTH OF BUFFER REQUIRED W JSB EXE$BUFFRQUOTA ;CHECK IF PROCESS HAS SUFFICIENT QUOTA W BLBC R0,45$ ;IF LBC QUOTA CHECK FAILURE HX JSB EXE$ALLOCBUF ;ALLOCATE BUFFER FOR LINE PRINTER OUTPUT X BLBC R0,45$ ;IF LBC ALLOCATION FAILURE Y MOVL (SP),R3 ;RETRIEVE ADDRESS OF I/O PACKET tY MOVL R2,IRP$L_SVAPTE(R3) ;SAVE ADDRESS OF BUFFERED I/O PACKET Y SUBW R1,PCB$W_BYTCNT(R4) ;ADJUST BUFFERED I/O QUOTA ;RESTORE REGISTERS e JMP EXE$ABORTIO ; Xf50$: MOVW R9,IRP$L_MEDIA+2(R3) ;INSERT NUMBER OF BYTES TO PRINT f MOVC R9,(R8),(R2) ;MOVE CHARACTERS TO SYSTEM BUFFER g60$: POPR #^M ;RESTORE REGISTERS g PUSHL R3 ;SAVE ADDRESS OF I/O PACKET g MOVAB UCB$L_LP_MUTEX(R5),R0 ;GET ADDRESS OF UCB MUTEX Lh JSB SCH$UNLOCK ;UNLOCK UCB h POPL R3 ;RESTORE ADDRESS OF I/O PACKET i JMP EXE$QIODRVPKT ;QUEUE I/O PACKET TO DRIVER xi i; @j; SUBROUTINE TO INSERT CARRIAGE CONTROL IN BUFFER j; k lk70$: MOVZBL IRP$B_CARCON(R3),-(SP) ;GET NUMBER OF CHARACTERS TO OUTPUT k BEQL 100$ ;IF EQL NONE 4l MOVZBL IRP$B_CARCON+1(R3),R0 ;GET CHARACTER TO OUTPUT l BRB 85$ ; l80$: MOVZBL IRP$B_CARCON+2(R3),-(SP) ;GET NUMBER OF CHARACTERS TO OUTPUT `m BEQL 100$ ;IF EQL NONE m MOVZBL IRP$B_CARCON+3(R3),R0 ;GET CHARACTER TO OUTPUT (n85$: BNEQ 90$ ;IF NEQ CHARACTER SPECIFIED n MOVZBL #C_CR,R0 ;GET CARRIAGE RETURN n BSBB WRITE_BYTE ;WRITE BYTE IN SYSTEM BUFFER To MOVZBL #C_LF,R0 ;GET LINE FEED o90$: BSBB WRITE_BYTE ;WRITE BYTE IN SYSTEM BUFFER p SOBGTR (SP),90$ ;ANY MORE LEFT TO INSERT? p100$: TSTL (SP)+ ;REMOVE COUNT FROM STACK p RSB ; Hq .PAGE q .SBTTL WRITE BYTE INTO SYSTEM BUFFER r; tr; SUBROUTINE TO FORMAT AND FILL SYSTEM BUFFER WITH LINE PRINTER OUTPUT ONE BYTE r; AT A TIME. ;RESTORE REGISTERS  ADDW R10,PCB$W_BYTCNT(R4) ;ADJUST BYTE COUNT QUOTA x ADDL #32,R11 ;ADJUST COUNT OF OVERHEAD BYTES ܛ PUSHL R3 ;SAVE ADDRESS OF I/O PACKET @ MOVAB UCB$L_LP_MUTEX(R5),R0 ;GET ADDRESS OF UCB MUTEX JSB SCH$UNLOCK ;UNLOCK UCB  POPL R3 ;RESTORE ADDRESS OF I/O PACKET l BRW FORMAT ;TRY AGAIN Н .PAGE 4 .SBTTL LINE PRINTER DRIVER ;+ ; STARTIO - START I/O OPERATION ON LINE PRINTERS `; ğ; THIS ROUTINE IS ENTERED WHEN THE ASSOCIATED UNIT IS IDLE AND A PACKET (; IS AVAILABLE. ; ; INPUTS: T; ; R3 = ADDRESS OF I/O REQUEST PACKET. ; R5 = UCB ADDRESS FOR IDLE UNIT. ; ; OUTPUTS: H; ; NO EXPLICIT OUTPUTS - THE UNIT IS IN WAITING FOR INTERRPUT STATE ; OR THE I/O IS COMPLETE. t;- ؤ < .PSECT WIONONPAGED STARTIO:  MOVL UCB$L_IRP(R5),R3 ;RETRIEVE ADDRESS OF I/O PACKET h MOVW IRP$L_MEDIA+2(R3),UCB$W_BOFF(R5) ;SET NUMBER OF CHARACTERS TO PRINT ̦ MOVL UCB$L_SVAPTE(R5),R3 ;GET ADDRESS OF SYSTEM BUFFER 0 MOVAB 12(R3),R3 ;GET ADDRESS OF DATA AREA MOVL @UCB$L_CRB(R5),R4 ;GET ADDRESS OF CSR \; ; START NEXT OUTPUT SEQUENCE $; 10$: MOVW UCB$W_BOFF(R5),R1 ;GET NUMBER OF CHARACTERS REMAINING P MOVW #^X8080,R2 ;GET CONTROL REGISTER TEST MASK 20$: DECW R1 ;ANY MORE CHARACTERS TO OUTPUT?  BCS 80$ ;IF CS NO | BITW R2,LP_CSR(R4) ;PRINTER READY OR HAVE PAPER PROBLEM? BLEQ 30$ ;IF LEQ NOT READY OR PAPER PROBLEM D MOVB (R3)+,LP_DBR(R4) ;OUTPUT NEXT CHARACTER BRB 20$ ; p; ԭ; PRINTER IS NOT READY OR HAS PAPER PROBLEM 8; 30$: BNEQ 40$ ;IF NEQ PAPER PROBLEM d ADDW3 #1,R1,UCB$W_BOFF(R5) ;SAVE NUMBER OF CHARACTERS REMAINING ȯ DSBINT ;DISABLE INTERRUPTS , BISB #^X40,LP_CSR(R4) ;SET INTERRUPT ENABLE WFIKPCH 40$,#12 ;WAIT FOR INTERRUPT IOFORK ;CREATE A FORK PROCESS X BRB 10$ ; ; ; PRINTER HAS PAPER PROBLEM ; L 40$: CLRB UCB$B_LP_OFLCNT(R5) ;CLEAR OFFLINE COUNTER  ADDW3 #1,R1,UCB$W_BOFF(R5) ;SAVE NUMBER OF CHARACTERS REMAINING x50$: CLRW LP_CSR(R4) ;DISABLE PRINTER INTERRUPT ܴ SETIPL UCB$B_FIPL(R5) ;LOWER TO FORK LEVEL @ TSTW LP_CSR(R4) ;PRINTER STILL HAVE PAPER PROBLEM? BGEQ STARTIO ;IF GEQ NO  BBS #UCB$V_CANCEL,UCB$W_STS(R5),70$ ;IF SET, CANCEL I/O OPERATION l ACBB #15,#1,UCB$B_LP_OFLCNT(R5),60$ ;SKIP UNTIL TIMEOUT ж CLRB UCB$B_LP_OFLCNT(R5) ;RESET COUNTER 4 PUSHR #^M ;SAVE REGISTERS MOVZBL #MSG$_DEVOFFLIN,R4 ;SET UP MESSAGE TYPE MOVAB SYS$GL_OPRMBX,R3 ;ADDRESS TARGET MAILBOX ` BSBW EXE$SNDEVMSG ;SEND MESSAGE IGNORE ERROR ĸ POPR #^M ;RESTORE REGISTERS (60$: DSBINT ;DISABLE INTERRUPTS WFIKPCH 50$,#2 ;WAIT FOR AN INTERRUPT OR TIMEOUT 2 SEC IOFORK ;CREATE FOR PROCESS T BRB 50$ ; ; ; I/O OPERATION CANCELED ; H 70$: MOVZWL #SS$_ABORT,R0 ;SET OPERATION ABORTED STATUS  BRB 90$ ; t ؽ; <; I/O OPERATION SUCCESSFULLY COMPLETED ;  h80$: MOVZWL #SS$_NORMAL,R0 ;SET NORMAL COMPLETION STATUS ̿ CLRW UCB$W_BOFF(R5) ;CORRECT REMAINING CHARACTER COUNT 090$: MOVL UCB$L_IRP(R5),R3 ;RETRIEVE ADDRESS OF I/O PACKET MOVZWL IRP$L_MEDIA(R3),R1 ;GET NUMBER OF LINES PRINTED SUBW UCB$W_BOFF(R5),UCB$W_BCNT(R5) ;CALCULATE NUMBER OF CHARACTERS \ INSV UCB$W_BCNT(R5),#16,#16,R0 ;INSERT NUMBER OF CHARACTERS IN STATUS REQCOM ;COMPLETE I/O REQUEST $ .PAGE .SBTTL LP11/LS11/LV11 LINE PRINTER INTERRUPT DISPATCHER ;+ P; LP$INT - LP11/LS11/LV11 LINE PRINTER INTERRUPT DISPATCHER. ; ; THIS ROUTINE IS ENTERED VIA A JSB INSTRUCTION WHEN AN INTERRUPT OCCURS ON AN |; LP11/LS11/LV11 LINE PRINTER CONTROLLER. THE STATE OF THE STACK ON ENTRY IS: ; D; 00(SP) = ADDRESS OF IDB ADDRESS. ; 04(SP) = SAVED R3. ; 08(SP) = SAVED R4. p; 12(SP) = SAVED R5. ; 16(SP) = INTERRUPT PC. 8; 20(SP) = INTERRUPT PSL. ; ; INTERRUPT DISPATCHING OCCURS AS FOLLOWS: d; ; IF THE INTERRUPT IS EXPECTED, THEN THE DRIVER IS CALLED AT ITS INTERRUPT ,; WAIT ADDRESS. ELSE THE INTERRUPT IS DISMISSED. ;- XLP$INT:: ;ENTRY FROM DISPATCH MOVL @(SP)+,R3 ;GET ADDRESS OF IDB MOVQ IDB$L_CSR(R3),R4 ;GET CONTROLLER CSR AND OWNER UCB ADDRESS BBCC #UCB$V_INT,UCB$W_STS(R5),10$ ;IF CLR, INTERRUPT NOT EXPECTED CLRW (R4) ;DISABLE OUTPUT INTERRUPTS L MOVL UCB$L_FR3(R5),R3 ;RESTORE REMAINDER OF DRIVER CONTEXT JSB @UCB$L_FPC(R5) ;CALL DRIVER AT INTERRUPT WAIT ADDRESS 10$: POPR #^M ;RESTORE REGISTERS x REI ;RETURN .PAGE @ .SBTTL LINE PRINTER INTIAILIZATION ;+ ; LP$INITIAL - INITIALIZE THE PRINTER l; ; THIS ROUTINE IS CALLED AT SYSTEM STARTUP AND AFTER A POWER FAILURE. THE CSR 4; ADDRESS OF THE RESPECTIVE LP11/LS11/LV11 CONTROLLER IS READ TO INSURE ITS ; PRESENCE ON THE UBA. ; `; INPUTS: ; (; R4 = LINE PRINTER CONTROLLER CSR ADDRESS. ; R5 = IDB OF UNIT. ; T; OUTPUTS: ; ; ALL REGISTERS ARE PRESERVED. ;- HLP$INITIAL:: ;INITIALIZATION TSTW (R4) ;SYNCHRONIZE UBA ACCESS  RSB ; t .END