home *** CD-ROM | disk | FTP | other *** search
- page,132
- ;---------------------------Module-Header-------------------------------;
- ; Module Name: IBMLPT.ASM
- ;
- ; Copyright (c) Microsoft Corporation 1985-1990. All Rights Reserved.
- ;
- ; General Description:
- ;
- ; History:
- ;
- ;-----------------------------------------------------------------------;
-
- title IBMLpt - IBM PC, PC-XT, PC-AT, PS/2 Parallel Communications Interface
-
- .xlist
- include cmacros.inc
- include comdev.inc
- include ins8250.inc
- include ibmcom.inc
- .list
-
- sBegin Code
- assumes cs,Code
- assumes ds,Data
-
- externFP GetSystemMsecCount
-
- externA __0040H
-
- ;----------------------------Private-Routine----------------------------;
- ;
- ; DoLPT - Do Function To LPT port
- ;
- ; The given function (output or reset) is performed to the
- ; passed LPT port.
- ;
- ; Before a character is sent, a check is made to see if the device
- ; will be able to accept the character. If it can, then the character
- ; will be sent. If not, then an error will be returned. If the
- ; printer is selected and busy and no error, then the code returned
- ; will be CE_TXFULL and the handshake bits will be set in HSFlag
- ; to simulate that a handshake was received.
- ;
- ; If the BIOS ROM code is examined, you will note that they wait for
- ; the busy character from the last charcater to be cleared before
- ; they strobe in the current character. This can take a long time
- ; on the standard EPSON class printer (1 mSec to greater than
- ; 300 mSec if the last character actually caused printing).
- ;
- ; Because of this, several status read retrys will be made before
- ; declaring that the device is actually busy. If only one status
- ; read is performed, the spooler will yeild, take a while to get
- ; back here, and things will be really slow. What difference does
- ; it really make if we or the BIOS does the delay, at least we can
- ; break out of it at some point when it seems hopeless.
- ;
- ; The OKIHACK: Okidata reports a 50 ns. 2.2 volt pulse on the paper
- ; out signal on the trailing edge of the Busy signal. If we see this
- ; glitch then we report paper out. So we try to get the status twice...
- ; if it changes between the two tries we keep getting the status.
- ; Silly hardware people.
- ;
- ; Entry:
- ; AH = cid
- ; AL = character to output
- ; CH = Function request. 0 = Output, 1 = Initialize, 2 = Status
- ; DS:SI -> DEB for the port
- ; Returns:
- ; AX = 0 if no errors occured
- ; Error Returns:
- ; AX = error code
- ; Registers Preserved:
- ; SI,DI
- ; Registers Destroyed:
- ; AX,BX,CX,DX,ES,FLAGS
- ; History:
- ;-----------------------------------------------------------------------;
-
- assumes ds,Data
- assumes es,nothing
-
- public DoLPT
- DoLPT proc near
-
- mov dx,Port[si] ;Get port address
-
- ; DX = port address
- ; CH = operation: 0 = write, 1 = init, 2 = status
- ; AL = character
-
- or ch, ch
- jz LPT_OutChar
- cmp ch, 1
- jz LPT_Reset
- jmp LPT_GetStatus
- ret
-
- LPT_Reset:
-
- inc dx
- inc dx
- mov al, L_RESET
- iodelay
- out dx, al
-
- push dx
-
- cCall GetSystemMsecCount
- mov bx, ax
-
- LPT_ResetDelay:
- push bx
- cCall GetSystemMsecCount
- pop bx
- sub ax, bx
- cmp ax, 300 ; 1/3 sec as good as any
- jbe LPT_ResetDelay
-
- pop dx
-
- mov al, L_NORMAL
- iodelay
- iodelay
- out dx, al
- dec dx
- dec dx
- jmp LPT_GetStatus
-
- LPT_OutChar:
- push ax ; save character to be written
-
- ; first check to see if printer is ready for us
- push di
-
- push dx
- call GetSystemMSecCount
- mov di, ax
- pop dx
-
- LPT_WaitReady:
-
- inc dx ; point to status port
- iodelay
- in al, dx ; get status bits
- and al, L_BITS ; mask unused ones
- xor al, L_BITS_INVERT ; flip a couple
- xchg al, ah
-
- ifndef NOOKIHACK
- iodelay
- in al, dx
-
- dec dx
-
- and al, L_BITS
- xor al, L_BITS_INVERT
- cmp al, ah ; did any bits change?
- jnz LPT_WaitReady
- else
- dec dx
- endif
-
-
- test ah, PS_PaperOut or PS_IOError
- jnz LPT_PrinterNotReady
- test ah, PS_Select
- jz LPT_PrinterNotReady
- test ah, PS_NotBusy
- jnz LPT_PrinterReady
-
- push ax
- push dx
- call GetSystemMSecCount
- pop dx
- pop bx
- sub ax, di
- cmp ax, 300 ; 1/3 sec timeout
-
- jbe LPT_WaitReady
-
- ; The device seems to be selected and powered up, but is just
- ; busy (some printers seem to show selected but busy when they
- ; are taken offline). Show that the transmit queue is full and
- ; that the hold handshakes are set. This is so the windows
- ; spooler will retry (and do yields so that other apps may run).
-
-
- or ComErr[si],CE_TXFULL ;Show queue full
- mov ah,bh
- or ah, L_TIMEOUT
-
- LPT_PrinterNotReady:
-
- pop di
- pop cx ; throw away character
- jmp short LPT_ReturnStatus
-
- LPT_PrinterReady:
- pop di ; get di back
- pop ax ; get character back
-
- iodelay
- out dx, al ; write character to port
-
- inc dx ; access status port
-
- LPT_Strobe:
- inc dx ; control port
- mov al, L_STROBE ; set strobe high
- iodelay
- iodelay
- iodelay
- iodelay
- out dx, al ; ...
-
- mov al, L_NORMAL ;
- iodelay
- iodelay
- iodelay
- iodelay
- out dx, al ; set strobe low
-
- sub dx, 2 ; point back to port base
-
- ; FALL THRU
-
- LPT_GetStatus:
- inc dx ; point to status port
- LPT_GS1:
- iodelay
- iodelay
- in al, dx ; get status bits
- and al, L_BITS ; mask unused ones
- xor al, L_BITS_INVERT ; flip a couple
- mov ah, al
-
- ifndef NOOKIHACK
- in al, dx
- and al, L_BITS
- xor al, L_BITS_INVERT
- cmp al, ah
- jnz LPT_GS1 ; if they changed try again...
- endif
-
- LPT_ReturnStatus:
-
- assumes ds,Data
- and ax,(PS_PaperOut+PS_Select+PS_IOError+PS_Timeout)*256
- shr ah,1
- adc ah,al ;Get back Timeout bit
- xor ah,HIGH CE_DNS ;Invert selected bit
- .errnz LOW CE_DNS
- or by ComErr+1[si],ah ;Save comm error
- ret
-
- .errnz CE_PTO-0200h
- .errnz CE_IOE-0400h
- .errnz CE_DNS-0800h
- .errnz CE_OOP-1000h
-
- DoLPT40:
- assumes ds,Data
- or ComErr[si],CE_TXFULL ;Show queue full
- ret
-
- DoLPT endp
- page
-
-
- CheckStatus proc near
- in al, dx ; get status bits
- mov ah, al
- and al, L_BITS ; mask unused ones
- xor al, L_BITS_INVERT ; flip a couple
- xchg al, ah
-
- ifndef NOOKIHACK
- iodelay
- in al, dx
-
- and al, L_BITS
- xor al, L_BITS_INVERT
- cmp al, ah ; did any bits change?
- jnz CheckStatus
- endif
- test ah, PS_PaperOut or PS_IOError
- jz @F
- stc
- ret
- @@:
- test ah, PS_Select
- jnz @F
- stc
- ret
- @@:
- and ah, PS_NotBusy
- clc
- ret
-
- CheckStatus endp
-
-
- ;----------------------------Public Routine-----------------------------;
- ;
- ; StringToLPT - Send string To LPT Port
- ;
- ; Entry:
- ; DS:SI -> DEB
- ; ES:DI -> string to send
- ; CX = # of bytes to send
- ; Returns:
- ; AX = # of bytes actually sent
- ; Registers Destroyed:
- ; AX,BX,CX,DX,ES,FLAGS
- ; History:
- ;-----------------------------------------------------------------------;
-
- PUBLIC StringToLPT
- StringToLPT proc near
-
- mov dx, Port[si] ; get port address
- inc dx ; access status port
-
- push cx ; save count for later
- push ds
- mov bx, __0040H
- mov ds, bx
-
- cld
-
- call CheckStatus ; quick status check before slowness
- jc PrinterError
- jz PrinterBusy ; if printer not ready for first char
- ; then just return with CE_TXFULL
-
- CharacterToLPT:
- ;; mov bh, 10 ; will wait 10 clock tics (~ 1/2 sec)
- mov bh, 3 ; will wait 3 clock tics (~ 1/6 sec)
- l1:
- mov bl, ds:[006Ch] ; low byte of tic counter
- l2:
- call CheckStatus ; quick status check before slowness
- jc PrinterError
- jnz LPT_PrinterRdy
-
- cmp bl, ds:[006Ch]
- jz l2 ; tic count hasn't changed
-
- dec bh
- jz PrinterBusy ; out of tics, timeout
- jmp short l1
-
- LPT_PrinterRdy:
- mov al, es:[di]
- inc di
-
- dec dx ; point to data port
-
- out dx, al ; write character to port
-
- add dx, 2 ; access control port
- mov al, L_STROBE ; set strobe high
- out dx, al ; ...
-
- mov al, L_NORMAL ;
- iodelay
- iodelay
- out dx, al ; set strobe low
-
- dec dx ; point to status port for check
-
- loop CharacterToLPT
- pop ds
- jmp short LPT_Exit
-
- PrinterError:
- pop ds
- jmp short ReturnStatus
-
- PrinterBusy:
- pop ds
- or ComErr[si],CE_TXFULL ; set buffer full bit
- or al, L_TIMEOUT ; show timeout bit
-
- ReturnStatus:
- and ax,(PS_PaperOut+PS_Select+PS_IOError+PS_Timeout)
- xchg al, ah
- shr ah,1
- adc ah,al ;Get back Timeout bit
- xor ah,HIGH CE_DNS ;Invert selected bit
- .errnz LOW CE_DNS
- or by ComErr+1[si],ah ;Save comm error
-
- LPT_Exit:
- pop ax ; get total count
- sub ax, cx ; subtract remaining unsent charts
-
- ret
-
- StringToLPT endp
-
-
- IFDEF DEBUG ;Publics for debugging
- public LPT_Reset
- public LPT_Outchar
- public LPT_Strobe
- public LPT_GetStatus
- public DoLPT40
- ENDIF
-
- sEnd code
- End
-