PAGE ,132 ; TITLE MSLPT - BIOS %OUT ...MSLPT.ASM ;============================================================================== ;REVISION HISTORY: ;AN000 - New for DOS Version 4.00 - J.K. ;AC000 - Changed for DOS Version 4.00 - J.K. ;AN00x - PTM number for DOS Version 4.00 - J.K. ;============================================================================== ;AN001 - P156 KBMLPT device driver's retry logic. 8/18/87 J.K. ;============================================================================== itest=0 INCLUDE MSGROUP.INC ;DEFINE CODE SEGMENT INCLUDE MSEQU.INC INCLUDE MSMACRO.INC INCLUDE DEVSYM.INC INCLUDE IOCTL.INC EXTRN BUS$EXIT:NEAR ;MSBIO1 EXTRN ERR$CNT:NEAR ;MSBIO1 EXTRN CMDERR:NEAR ;MSBIO1 EXTRN GETDX:NEAR ;MSBIO1 EXTRN EXIT:NEAR ;MSBIO1 EXTRN ERR$EXIT:NEAR ;MSBIO1 ;DATA EXTRN PTRSAV:DWORD ;MSBIO1 EXTRN TIMDEV:WORD ;MSCLOCK EXTRN LPT2DEV:WORD ;MSBIO2 EXTRN WAIT_COUNT:WORD ;MSDATA EXTRN PRINTDEV:BYTE ;MSDATA ; IBM ROM STATUS BITS (I DON'T TRUST THEM, NEITHER SHOULD YOU) NOTBUSYSTATUS = 10000000B ; NOT BUSY ACKSTATUS = 01000000B ; ACKNOWLEDGE (FOR WHAT?) NOPAPERSTATUS = 00100000B ; NO MORE PAPER SELECTEDSTATUS = 00010000B ; THE PRINTER SAID IT WAS SELECTED IOERRSTATUS = 00001000B ; SOME KINDA ERROR RESERVED = 00000110B ; NOPS TIMEOUTSTATUS = 00000001B ; TIME OUT. ; WARNING!!! THE IBM ROM DOES NOT RETURN JUST ONE BIT. IT RETURNS A ; WHOLE SLEW OF BITS, ONLY ONE OF WHICH IS CORRECT. ;---------------------------------------------------------- ;J.K. AN001; PRN$WRIT will retry only if error code is TIMEOUT. ; WRITE TO PRINTER DEVICE ; CX HAS COUNT OF BYTES ; ES:DI POINT TO DESTINATION ; AUXNUM HAS PRINTER NUMBER PUBLIC PRN$WRIT PRN$WRIT PROC NEAR ASSUME DS:CODE ; SET BY PRINTER DEVICE DRIVER ENTRY jcxz Prn$Done ;No char to output Prn$Loop: mov bx, 2 ;Initialize retry count Prn$Out: ;SB34LPT000**************************************************************** ;SB Print the character at ES:[DI] ;SB Call the function PrnOP to do this ;SB The character to be printed goes in AL and the function code ;SB for 'Output character' goes in AH ;SB Check for error in printing. ;SB If there is no error go to print the next character. ;SB If there is an error indicated see if it is due to TIMEOUT. If the ;SB error is not TIMEOUT then we can do nothing about it. Just go to ;SB print the next character. If it is due to timeout we can execute ;SB the code to retry the print which follows this piece of code ;SB LOCS: 6 mov al,es:[di] ; assume AX disposible since enter xor ah,ah ; via int 21h call PrnOp ; print to printer jz Prn$Con ; no error - continue test ah,TIMEOUTSTATUS jz Prn$Con ; NOT time out - continue ;SB34LPT000**************************************************************** dec bx ;Retry until count is exhausted. jnz Prn$Out ;Retry it. jmp short Pmessg ;Return with error. ; ; next character ; Prn$Con: inc di ;point to next char and continue loop Prn$Loop Prn$Done: jmp Exit Pmessg: jmp Err$Cnt PRN$WRIT endp ; JCXZ EXVEC3 ; NO CHARS TO OUTPUT.. ;PRN$LOOP: ; MOV BX,2 ; INITIALIZE RETRY FLAG ;PRN$OUT: ; MOV AL,ES:[DI] ; GET CHAR INTO AL ; INC DI ; POINT TO NEXT CHAR ; XOR AH,AH ; AH=0 => OUTPUT CHAR IN DL ; CALL PRNOP ; TO INDICATE PRINT CHAR IN AL ; JNZ PRRETRY ; LOOP PRN$LOOP ;EXVEC3: ; JMP EXIT ;PRRETRY: ; DEC DI ; UNDO THE INC ABOVE... ; DEC BX ; JNZ PRN$OUT ;PMESSG: ; JMP ERR$CNT ;RETURN WITH THE ERROR ;PRN$WRIT ENDP ;-------------------------------------------------------- ; PRINTER STATUS ROUTINE PUBLIC PRN$STAT PRN$STAT PROC NEAR ASSUME DS:CODE ; SET BY PRINTER DEVICE DRIVER ENTRY CALL PRNSTAT ;DEVICE IN DX JNZ PMESSG ; OTHER ERRORS WERE FOUND ;J.K. The next three lines are commented out, since it is a dead code. ; MOV AL,9 ; AGAIN, ASSUME OUT OF PAPER... ; TEST AH,NOPAPERSTATUS ; JNZ PMESSG TEST AH,NOTBUSYSTATUS jnz Prn$Done ;No error. Exit JMP BUS$EXIT PRN$STAT ENDP ; TAKE THE APPROPRIATE PRINTER AND DO THE OPERATION. TRIAGE THE STATUS ; RETURNED IN AH INTO SOME MEANINGFUL ERROR. PRNSTAT PROC NEAR ;SB33037********************************************************************** mov AH, 2 ; set command for get status ;SB ;3.30* PRNOP: ;SB ;3.30* call GETDX ; determine which printer ;SB ;3.30* int 17h ; call ROM-BIOS printer routine ;SB;3.30* ;SB33037********************************************************************** ; EXAMINE THE STATUS BITS TO SEE IF AN ERROR OCCURRED. UNFORTUNATELY, SEVERAL ; OF THE BITS ARE SET SO WE HAVE TO PICK AND CHOOSE. WE MUST BE EXTREMELY ; CAREFUL ABOUT BREAKING BASIC. TEST AH,IOERRSTATUS ; I/O ERROR? JZ CHECKNOTREADY ; NO, TRY NOT READY ; AT THIS POINT, WE KNOW WE HAVE AN ERROR. THE CONVERSE IS NOT TRUE. MOV AL,9 ; FIRST, ASSUME OUT OF PAPER TEST AH,NOPAPERSTATUS ; OUT OF PAPER SET? JNZ RET1 ; YES, ERROR IS SET INC AL ; INDICATE I/O ERROR RET1: ; WE HAVE TRIAGED NOW FOR OUT OF PAPER AND IO ERR (IGNORING TIME-OUT) RET ; RETURN WITH ERROR ; THE BITS SAID NO ERROR. UNFORTUNATELY, THERE MAY BE OTHER THINGS AT WORK ; HERE. CHECKNOTREADY: MOV AL,2 ; ASSUME NOT-READY TEST AH,TIMEOUTSTATUS ; IS TIME-OUT SET? ; IF NZ THEN ERROR, ELSE OK??? PRNOP2: RET PRNSTAT ENDP ; OUTPUT UNTIL BUSY. THIS ENTRY POINT IS USED EXCLUSIVELY BY THE PRINT ; SPOOLERS. UNDER NO CURCUMSTANCES SHOULD THE DEVICE DRIVER BLOCK WAITING FOR ; THE DEVICE TO BECOME READY. ; INPUTS: CX HAS COUNT OF BYTES TO OUTPUT. ; ES:DI POINTS TO SOURCE BUFFER ; OUTPUTS: SET THE NUMBER OF BYTES TRANSFERRED APPROPRIATELY PUBLIC PRN$TILBUSY PRN$TILBUSY PROC NEAR ASSUME DS:CODE ; SET BY PRINTER DEVICE DRIVER ENTRY PUSH DS PUSH ES POP DS ; NOW ES AND DS BOTH POINT TO SOURCE BUFFER ASSUME DS:NOTHING MOV SI,DI ; EVERYTHING IS SET FOR LODSB PRN$TILBLOOP: PUSH CX PUSH BX XOR BX,BX MOV BL,CS:[PRINTDEV] SHL BX,1 MOV CX,CS:WAIT_COUNT[BX] ; WAIT COUNT TIMES TO COME READY POP BX PRN$GETSTAT: CALL PRNSTAT ; GET STATUS JNZ PRN$BPERR ; ERROR TEST AH,10000000B ; READY YET? LOOPZ PRN$GETSTAT ; NO, GO FOR MORE POP CX ; GET ORIGINAL COUNT JZ PRN$BERR ; STILL NOT READY => DONE LODSB XOR AH,AH CALL PRNOP JNZ PRN$BERR ; ERROR LOOP PRN$TILBLOOP ; GO FOR MORE PRN$B: POP DS LDS BX,CS:[PTRSAV] ASSUME DS:NOTHING SUB WORD PTR [BX].COUNT,CX ;# OF SUCCESSFUL I/O'S JMP EXIT PRN$TILBUSY ENDP PRN$BPERR PROC NEAR ASSUME DS:CODE POP CX PRN$BERR: POP DS LDS BX,CS:[PTRSAV] ASSUME DS:NOTHING SUB WORD PTR [BX].COUNT,CX ;# OF SUCCESSFUL I/O'S JMP ERR$EXIT PRN$BPERR ENDP ; ; MANIPULATES THE VALUE IN WAIT_COUNT DEPENDING ON THE VALUE PASSED IN THE ; GENERIC IOCTL PACKET. ; IT EITHER SETS OR RETURNS THE CURRENT VALUE FOR THE RETRY COUNT FOR THE ; DEVICE. ; PUBLIC PRN$GENIOCTL PRN$GENIOCTL PROC NEAR ASSUME DS:CODE ; SET BY PRINTER DEVICE DRIVER ENTRY LES DI,[PTRSAV] CMP ES:[DI].MAJORFUNCTION,IOC_PC JE PRNFUNC_OK PRNFUNCERR: JMP CMDERR PRNFUNC_OK: MOV AL,ES:[DI].MINORFUNCTION LES DI,ES:[DI].GENERICIOCTL_PACKET XOR BX,BX MOV BL,[PRINTDEV] ; GET INDEX INTO RETRY COUNTS SHL BX,1 MOV CX,WAIT_COUNT[BX] ; PULL OUT RETRY COUNT FOR DEVICE CMP AL,GET_RETRY_COUNT JZ PRNGETCOUNT CMP AL,SET_RETRY_COUNT JNZ PRNFUNCERR MOV CX,ES:[DI].RC_COUNT PRNGETCOUNT: MOV WAIT_COUNT[BX],CX ; PLACE "NEW" RETRY COUNT MOV ES:[DI].RC_COUNT,CX ; RETURN CURRENT RETRY COUNT JMP EXIT PRN$GENIOCTL ENDP CODE ENDS END