;	PAGE ,132 ;
;	TITLE MSLPT - BIOS
	%warning 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 equ 0
	%include "msgroup.mac"	;DEFINE CODE SEGMENT
	%include "msextrn.mac"
	%include "msequ.mac"
	%include "msmacro.mac"
	%include "devsym.mac"
	%include "ioctl.mac"

	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	equ   10000000B		; NOT BUSY
ACKSTATUS	equ   01000000B		; ACKNOWLEDGE (FOR WHAT?)
NOPAPERSTATUS	equ   00100000B		; NO MORE PAPER
SELECTEDSTATUS	equ   00010000B		; THE PRINTER SAID IT WAS SELECTED
IOERRSTATUS	equ   00001000B		; SOME KINDA ERROR
RESERVED	equ   00000110B		; NOPS
TIMEOUTSTATUS	equ   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:DOSGROUP, es:nothing, ss:nothing
					; 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
PrnOp equ PRNOP	; NASM port label
	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:
Exit equ EXIT	; NASM port label
	jmp	Exit
Pmessg:
Err$Cnt equ ERR$CNT	; NASM port label
	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:DOSGROUP, es:nothing, ss:nothing
					; SET BY PRINTER DEVICE DRIVER ENTRY
	CALL	PRNSTAT			;DEVICE IN DX
PMESSG equ Pmessg	; NASM port label
	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:DOSGROUP, es:nothing, ss:nothing
					; 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
	push ds
	call biocode_get_ds_dosbiodata
 assume ds:DOSGROUP
	MOV	BL,[PRINTDEV]
	SHL	BX,1
	MOV	CX,[WAIT_COUNT + BX]	; WAIT COUNT TIMES TO COME READY
	pop ds
 assume ds:nothing
	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
 assume ds:DOSGROUP
	call biocode_get_ds_dosentry	; PTRSAV in DOSENTRY
 assume ds:DOSENTRYGROUP
	lds bx, [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:nothing
	POP	CX
PRN$BERR:
	POP	DS
 assume ds:DOSGROUP
	call biocode_get_ds_dosentry	; PTRSAV in DOSENTRY
 assume ds:DOSENTRYGROUP
	lds bx, [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:DOSGROUP, es:nothing, ss:nothing
					; SET BY PRINTER DEVICE DRIVER ENTRY
	call biocode_get_ds_dosentry
 assume ds:DOSENTRYGROUP
	LES	DI,[PTRSAV]
 assume es:nothing
	CMP	byte [ES:DI + MAJORFUNCTION],IOC_PC
	JE	PRNFUNC_OK
PRNFUNCERR:
	JMP	CMDERR

PRNFUNC_OK:
	MOV	AL,[ES:DI + MINORFUNCTION]
	LES	DI,[ES:DI + GENERICIOCTL_PACKET]
 assume es:nothing
	call biocode_get_ds_dosbiodata
 assume ds:DOSGROUP
	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
prn_exit:
	JMP	EXIT
PRN$GENIOCTL ENDP

 global prn_check_gen_ioctl
prn_check_gen_ioctl:
 assume ds:DOSGROUP, es:nothing, ss:nothing
	call biocode_get_ds_dosentry
 assume ds:DOSENTRYGROUP
	lds di, [PTRSAV]
 assume ds:nothing
	CMP byte [di + MAJORFUNCTION],IOC_PC
	jne PRNFUNCERR
	mov al, [di + MINORFUNCTION]
	cmp al, GET_RETRY_COUNT
	je prn_exit
	cmp al, SET_RETRY_COUNT
	je prn_exit
	jmp PRNFUNCERR

; (no prior section) ; CODE	ENDS
	END
