;
; File:
;                          printer.asm
; Description:
;                      Printer device driver
;
;                       Copyright (c) 1998
;                       Pasquale J. Villani
;                       All Rights Reserved
;
; This file is part of DOS-C.
;
; DOS-C is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License
; as published by the Free Software Foundation; either version
; 2, or (at your option) any later version.
;
; DOS-C is distributed in the hope that it will be useful, but
; WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
; the GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public
; License along with DOS-C; see the file COPYING.  If not,
; write to the Free Software Foundation, 675 Mass Ave,
; Cambridge, MA 02139, USA.
;
; $Header$
;

                %include "io.inc"

		%define PRT_TIMEOUT    01h
		%define PRT_IOERROR    08h
		%define PRT_SELECTED   10h
		%define PRT_OUTOFPAPER 20h
		%define PRT_ACK	       40h
		%define PRT_NOTBUSY    80h

		%define PRT_WRITECHAR  00h
		%define PRT_INITPORT   01h
		%define PRT_GETSTATUS  02h

segment	_IO_FIXED_DATA

                global  LptTable
LptTable        db      18h
                dw      _IOExit
                dw      _IOExit
                dw      _IOExit
                dw      _IOCommandError
                dw      _IOSuccess
                dw      _IODone
                dw      _IOExit
                dw      _IOExit
                dw      PrtWrite
                dw      PrtWrite
                dw      PrtOutStat
                dw      _IOExit
                dw      _IOExit
                dw      _IOExit
                dw      _IOExit
                dw      _IOExit
                dw      PrtOutBsy
                dw      _IOExit
                dw      _IOExit
                dw      PrtGenIoctl
                dw      _IOExit
                dw      _IOExit
                dw      _IOExit
                dw      _IOCommandError
                dw      _IOCommandError


segment	_IO_TEXT
                global  uPrtNo
uPrtNo          db      0
uPrtQuantum     dw      50h
                dw      50h, 50h
                db      50h, 00h

PrtWrite:
                jcxz    PrtWr3                  ; Exit if nothing to write

PrtCharLoop:                                    ; next character loop
		 
                mov     bx, 2			; number of retries
PrtRetryTwice:
                mov     ah, PRT_GETSTATUS       ; get status, ah=2
                call    PrtIOCall               ;
                jnz     PrtWr4

		mov     al,[es:di]

                mov     ah, PRT_WRITECHAR       ; print character, ah=0
                call    PrtIOCall               ; (0800)

                jnz     PrtWr4                  ; NZ = error, retry

                inc     di
                loop    PrtCharLoop             ; next character
PrtWr3:
                jmp     _IOExit
PrtWr4:						; repeat
                dec     bx
                jnz     PrtRetryTwice
PrtWr5:
                jmp     _IOErrCnt



PrtOutStat:
                call    GetPrtStat
                jnz     PrtWr5
                mov     al, E_PAPER
                test    ah, PRT_OUTOFPAPER
                jnz     PrtWr5
                test    ah, PRT_NOTBUSY
                jnz     PrtWr3
                jmp     _IODone



GetPrtStat:
                mov     ah,PRT_GETSTATUS

PrtIOCall:
                call    GetUnitNum
                int     17h             ; print char al, get status ah

                mov     al, ah          ; if (stat & 0x30) == 0x30 return 10;
                and     al, PRT_SELECTED|PRT_OUTOFPAPER
                cmp     al, PRT_SELECTED|PRT_OUTOFPAPER
		mov     al, E_WRITE
                je      ret_error_code

                test    ah, PRT_OUTOFPAPER|PRT_IOERROR|PRT_TIMEOUT          ; 29h
                mov     al, E_NOTRDY
		jz      ret_error_code

                test    ah, PRT_OUTOFPAPER	; 20h 
                mov     al, E_WRITE
                jz      ret_error_code		; not out of paper -> E_WRITE

ret_error_code_9:
                mov     al, E_PAPER  

ret_error_code:
                cmp     al, E_NOTRDY            ; 2 = no error
                retn



PrtOutBsy:
                push    ds
                push    es
                pop     ds
                mov     si,di
PrtOtBsy1:
                push    cx
                push    bx
                xor     bx,bx
                mov     bl,[cs:uPrtNo]
                shl     bx,1
                mov     cx,[cs:uPrtQuantum+bx]
                pop     bx
PrtOtBsy2:
                call    GetPrtStat
                jnz     PrtOtBsy3
                test    ah, PRT_NOTBUSY
                loopz   PrtOtBsy2
                pop     cx
                jz      PrtOtBsy4
                lodsb
                xor     ah,ah
                call    PrtIOCall
                jnz     PrtOtBsy4
                loop    PrtOtBsy1
                pop     ds
                lds     bx,[cs:_ReqPktPtr]
                sub     [bx+12h],cx
                jmp     _IOExit
PrtOtBsy3:
                pop     cx
PrtOtBsy4:
                pop     ds
                lds     bx,[cs:_ReqPktPtr]
                sub     [bx+12h],cx
                jmp     _IOErrorExit



PrtGenIoctl:
                les     di,[cs:_ReqPktPtr]
                cmp     byte [es:di+0Dh],5
                je      PrtGnIoctl2
PrtGnIoctl1:
                jmp     _IOCommandError
PrtGnIoctl2:
                mov     al,[es:di+0Eh]
                les     di,[es:di+13h]
                xor     bx,bx
                mov     bl,[cs:uPrtNo]
                shl     bx,1
                mov     cx,[cs:uPrtQuantum+bx]
                cmp     al,65h
                je      PrtGnIoctl3
                cmp     al,45h
                jne     PrtGnIoctl1
                mov     cx,[es:di]
PrtGnIoctl3:
                mov     [cs:uPrtQuantum+bx],cx
                mov     [es:di],cx
                jmp     _IOExit



;
; some comments to last changes (TE, 23/09/01)
;
; original implementation didn't print at all  - on my machine,LPT2
;
; maybe this one is not much better either,
; but should print a little bit
;
; the status bits = AH
; 
;               1                       0
; 80 - BUSY  not busy               busy
; 40 - ACK   transfer finished      not yet finished
; 20 - PAP   no paper available     paper OK
; 10 - ONOF  printer online         not online
; 08 - ERR   some error             no error
; 01 - TIM   some error when transfer   OK
;
; some states
; 30 - there is no printer at all
; c8 - there is a printer without power
; 10 - printer with power, but not initialized
; 90 - this one is fine
;
; you must not simply print without asking for status
; as the BIOS has a LARGE timeout before aborting
;
