home *** CD-ROM | disk | FTP | other *** search
/ Software Collection (I) / TOOLS.iso / b04 / 15.img / COMM / IBMLPT.AS_ / IBMLPT.AS
Encoding:
Text File  |  1991-10-25  |  8.7 KB  |  413 lines

  1. page,132
  2. ;---------------------------Module-Header-------------------------------;
  3. ; Module Name: IBMLPT.ASM
  4. ;
  5. ; Copyright (c) Microsoft Corporation 1985-1990.  All Rights Reserved.
  6. ;
  7. ; General Description:
  8. ;
  9. ; History:
  10. ;
  11. ;-----------------------------------------------------------------------;
  12.  
  13. title    IBMLpt - IBM PC, PC-XT, PC-AT, PS/2 Parallel Communications Interface
  14.  
  15. .xlist
  16. include cmacros.inc
  17. include comdev.inc
  18. include ins8250.inc
  19. include ibmcom.inc
  20. .list
  21.  
  22. sBegin Code
  23. assumes cs,Code
  24. assumes ds,Data
  25.  
  26. externFP GetSystemMsecCount
  27.  
  28. externA __0040H
  29.  
  30. ;----------------------------Private-Routine----------------------------;
  31. ;
  32. ; DoLPT - Do Function To LPT port
  33. ;
  34. ; The given function (output or reset) is performed to the
  35. ; passed LPT port.
  36. ;
  37. ; Before a character is sent, a check is made to see if the device
  38. ; will be able to accept the character.  If it can, then the character
  39. ; will be sent.  If not, then an error will be returned.  If the
  40. ; printer is selected and busy and no error, then the code returned
  41. ; will be CE_TXFULL and the handshake bits will be set in HSFlag
  42. ; to simulate that a handshake was received.
  43. ;
  44. ; If the BIOS ROM code is examined, you will note that they wait for
  45. ; the busy character from the last charcater to be cleared before
  46. ; they strobe in the current character.  This can take a long time
  47. ; on the standard EPSON class printer (1 mSec to greater than
  48. ; 300 mSec if the last character actually caused printing).
  49. ;
  50. ; Because of this, several status read retrys will be made before
  51. ; declaring that the device is actually busy.  If only one status
  52. ; read is performed, the spooler will yeild, take a while to get
  53. ; back here, and things will be really slow.  What difference does
  54. ; it really make if we or the BIOS does the delay, at least we can
  55. ; break out of it at some point when it seems hopeless.
  56. ;
  57. ;   The OKIHACK: Okidata reports a 50 ns. 2.2 volt pulse on the paper
  58. ;   out signal on the trailing edge of the Busy signal.  If we see this
  59. ;   glitch then we report paper out.  So we try to get the status twice...
  60. ;   if it changes between the two tries we keep getting the status.
  61. ;   Silly hardware people.
  62. ;
  63. ; Entry:
  64. ;   AH    =  cid
  65. ;   AL    =  character to output
  66. ;   CH      =  Function request.    0 = Output, 1 = Initialize, 2 = Status
  67. ;   DS:SI -> DEB for the port
  68. ; Returns:
  69. ;   AX = 0 if no errors occured
  70. ; Error Returns:
  71. ;   AX = error code
  72. ; Registers Preserved:
  73. ;   SI,DI
  74. ; Registers Destroyed:
  75. ;   AX,BX,CX,DX,ES,FLAGS
  76. ; History:
  77. ;-----------------------------------------------------------------------;
  78.  
  79.    assumes ds,Data
  80.    assumes es,nothing
  81.  
  82.     public DoLPT
  83. DoLPT   proc   near
  84.  
  85.     mov    dx,Port[si]        ;Get port address
  86.  
  87. ;   DX = port address
  88. ;   CH = operation: 0 = write, 1 = init, 2 = status
  89. ;   AL = character
  90.  
  91.     or    ch, ch
  92.     jz    LPT_OutChar
  93.     cmp    ch, 1
  94.     jz    LPT_Reset
  95.     jmp    LPT_GetStatus
  96.     ret
  97.  
  98. LPT_Reset:
  99.  
  100.     inc    dx
  101.     inc    dx
  102.     mov    al, L_RESET
  103.     iodelay
  104.     out    dx, al
  105.  
  106.     push    dx
  107.  
  108.     cCall    GetSystemMsecCount
  109.     mov    bx, ax
  110.  
  111. LPT_ResetDelay:
  112.     push    bx
  113.     cCall    GetSystemMsecCount
  114.     pop    bx
  115.     sub    ax, bx
  116.     cmp    ax, 300         ; 1/3 sec as good as any
  117.     jbe    LPT_ResetDelay
  118.  
  119.     pop    dx
  120.  
  121.     mov    al, L_NORMAL
  122.     iodelay
  123.     iodelay
  124.     out    dx, al
  125.     dec    dx
  126.     dec    dx
  127.     jmp    LPT_GetStatus
  128.  
  129. LPT_OutChar:
  130.     push    ax            ; save character to be written
  131.  
  132.     ; first check to see if printer is ready for us
  133.     push    di
  134.  
  135.     push    dx
  136.     call    GetSystemMSecCount
  137.     mov    di, ax
  138.     pop    dx
  139.  
  140. LPT_WaitReady:
  141.  
  142.     inc    dx            ; point to status port
  143.     iodelay
  144.     in    al, dx            ; get status bits
  145.     and    al, L_BITS          ; mask unused ones
  146.     xor    al, L_BITS_INVERT     ; flip a couple
  147.     xchg    al, ah
  148.  
  149. ifndef NOOKIHACK
  150.     iodelay
  151.     in    al, dx
  152.  
  153.     dec    dx
  154.  
  155.     and    al, L_BITS
  156.     xor    al, L_BITS_INVERT
  157.     cmp    al, ah            ; did any bits change?
  158.     jnz    LPT_WaitReady
  159. else
  160.     dec    dx
  161. endif
  162.  
  163.  
  164.     test    ah, PS_PaperOut or PS_IOError
  165.     jnz    LPT_PrinterNotReady
  166.     test    ah, PS_Select
  167.     jz    LPT_PrinterNotReady
  168.     test    ah, PS_NotBusy
  169.     jnz    LPT_PrinterReady
  170.  
  171.     push    ax
  172.     push    dx
  173.     call    GetSystemMSecCount
  174.     pop    dx
  175.     pop    bx
  176.     sub    ax, di
  177.     cmp    ax, 300            ; 1/3 sec timeout
  178.  
  179.     jbe    LPT_WaitReady
  180.  
  181. ;       The device seems to be selected and powered up, but is just
  182. ;       busy (some printers seem to show selected but busy when they
  183. ;       are taken offline).  Show that the transmit queue is full and
  184. ;       that the hold handshakes are set.  This is so the windows
  185. ;    spooler will retry (and do yields so that other apps may run).
  186.  
  187.  
  188.     or    ComErr[si],CE_TXFULL    ;Show queue full
  189.     mov    ah,bh
  190.     or    ah, L_TIMEOUT
  191.  
  192. LPT_PrinterNotReady:
  193.  
  194.     pop    di
  195.     pop    cx            ; throw away character
  196.     jmp    short LPT_ReturnStatus
  197.  
  198. LPT_PrinterReady:
  199.     pop    di            ; get di back
  200.     pop    ax            ; get character back
  201.  
  202.     iodelay
  203.     out    dx, al            ; write character to port
  204.  
  205.     inc    dx            ; access status port
  206.  
  207. LPT_Strobe:
  208.     inc    dx            ; control port
  209.     mov    al, L_STROBE          ; set strobe high
  210.     iodelay
  211.     iodelay
  212.     iodelay
  213.     iodelay
  214.     out    dx, al            ;   ...
  215.  
  216.     mov    al, L_NORMAL          ;
  217.     iodelay
  218.     iodelay
  219.     iodelay
  220.     iodelay
  221.     out    dx, al            ; set strobe low
  222.  
  223.     sub    dx, 2            ; point back to port base
  224.  
  225.     ; FALL THRU
  226.  
  227. LPT_GetStatus:
  228.     inc    dx            ; point to status port
  229. LPT_GS1:
  230.     iodelay
  231.     iodelay
  232.     in    al, dx            ; get status bits
  233.     and    al, L_BITS          ; mask unused ones
  234.     xor    al, L_BITS_INVERT     ; flip a couple
  235.     mov    ah, al
  236.  
  237. ifndef NOOKIHACK
  238.     in    al, dx
  239.     and    al, L_BITS
  240.     xor    al, L_BITS_INVERT
  241.     cmp    al, ah
  242.     jnz    LPT_GS1     ; if they changed try again...
  243. endif
  244.  
  245. LPT_ReturnStatus:
  246.  
  247.     assumes ds,Data
  248.         and     ax,(PS_PaperOut+PS_Select+PS_IOError+PS_Timeout)*256
  249.         shr     ah,1
  250.         adc     ah,al                   ;Get back Timeout bit
  251.         xor     ah,HIGH CE_DNS          ;Invert selected bit
  252.    .errnz   LOW CE_DNS
  253.         or      by ComErr+1[si],ah      ;Save comm error
  254.         ret
  255.  
  256.    .errnz   CE_PTO-0200h
  257.    .errnz   CE_IOE-0400h
  258.    .errnz   CE_DNS-0800h
  259.    .errnz   CE_OOP-1000h
  260.  
  261. DoLPT40:
  262.     assumes ds,Data
  263.         or      ComErr[si],CE_TXFULL    ;Show queue full
  264.         ret
  265.  
  266. DoLPT   endp
  267. page
  268.  
  269.  
  270. CheckStatus proc    near
  271.     in    al, dx            ; get status bits
  272.     mov    ah, al
  273.     and    al, L_BITS          ; mask unused ones
  274.     xor    al, L_BITS_INVERT     ; flip a couple
  275.     xchg    al, ah
  276.  
  277. ifndef NOOKIHACK
  278.     iodelay
  279.     in    al, dx
  280.  
  281.     and    al, L_BITS
  282.     xor    al, L_BITS_INVERT
  283.     cmp    al, ah            ; did any bits change?
  284.     jnz    CheckStatus
  285. endif
  286.     test    ah, PS_PaperOut or PS_IOError
  287.     jz    @F
  288.     stc
  289.     ret
  290. @@:
  291.     test    ah, PS_Select
  292.     jnz    @F
  293.     stc
  294.     ret
  295. @@:
  296.     and    ah, PS_NotBusy
  297.     clc
  298.     ret
  299.  
  300. CheckStatus endp
  301.  
  302.  
  303. ;----------------------------Public Routine-----------------------------;
  304. ;
  305. ; StringToLPT - Send string To LPT Port
  306. ;
  307. ; Entry:
  308. ;   DS:SI -> DEB
  309. ;   ES:DI -> string to send
  310. ;   CX = # of bytes to send
  311. ; Returns:
  312. ;   AX = # of bytes actually sent
  313. ; Registers Destroyed:
  314. ;   AX,BX,CX,DX,ES,FLAGS
  315. ; History:
  316. ;-----------------------------------------------------------------------;
  317.  
  318. PUBLIC StringToLPT
  319. StringToLPT proc    near
  320.  
  321.     mov    dx, Port[si]        ; get port address
  322.     inc    dx            ; access status port
  323.  
  324.     push    cx            ; save count for later
  325.     push    ds
  326.     mov    bx, __0040H
  327.     mov    ds, bx
  328.  
  329.     cld
  330.  
  331.     call    CheckStatus        ; quick status check before slowness
  332.     jc    PrinterError
  333.     jz    PrinterBusy        ; if printer not ready for first char
  334.                     ;   then just return with CE_TXFULL
  335.  
  336. CharacterToLPT:
  337. ;;      mov      bh, 10          ; will wait 10 clock tics (~ 1/2 sec)
  338.     mov    bh, 3            ; will wait 3 clock tics (~ 1/6 sec)
  339. l1:
  340.     mov    bl, ds:[006Ch]        ; low byte of tic counter
  341. l2:
  342.     call    CheckStatus        ; quick status check before slowness
  343.     jc    PrinterError
  344.     jnz    LPT_PrinterRdy
  345.  
  346.     cmp    bl, ds:[006Ch]
  347.     jz    l2            ; tic count hasn't changed
  348.  
  349.     dec    bh
  350.     jz    PrinterBusy        ; out of tics, timeout
  351.     jmp    short l1
  352.  
  353. LPT_PrinterRdy:
  354.     mov    al, es:[di]
  355.     inc    di
  356.  
  357.     dec    dx            ; point to data port
  358.  
  359.     out    dx, al            ; write character to port
  360.  
  361.     add    dx, 2            ; access control port
  362.     mov    al, L_STROBE        ; set strobe high
  363.     out    dx, al            ;   ...
  364.  
  365.     mov    al, L_NORMAL        ;
  366.     iodelay
  367.     iodelay
  368.     out    dx, al            ; set strobe low
  369.  
  370.     dec    dx            ; point to status port for check
  371.  
  372.     loop    CharacterToLPT
  373.     pop    ds
  374.     jmp    short LPT_Exit
  375.  
  376. PrinterError:
  377.     pop    ds
  378.     jmp    short ReturnStatus
  379.  
  380. PrinterBusy:
  381.     pop    ds
  382.     or    ComErr[si],CE_TXFULL    ; set buffer full bit
  383.     or    al, L_TIMEOUT        ; show timeout bit
  384.  
  385. ReturnStatus:
  386.     and    ax,(PS_PaperOut+PS_Select+PS_IOError+PS_Timeout)
  387.     xchg    al, ah
  388.         shr     ah,1
  389.         adc     ah,al                   ;Get back Timeout bit
  390.     xor    ah,HIGH CE_DNS        ;Invert selected bit
  391.     .errnz    LOW CE_DNS
  392.     or    by ComErr+1[si],ah    ;Save comm error
  393.  
  394. LPT_Exit:
  395.     pop    ax            ; get total count
  396.     sub    ax, cx            ; subtract remaining unsent charts
  397.  
  398.     ret
  399.  
  400. StringToLPT endp
  401.  
  402.  
  403. IFDEF DEBUG        ;Publics for debugging
  404.     public  LPT_Reset
  405.     public  LPT_Outchar
  406.     public  LPT_Strobe
  407.     public  LPT_GetStatus
  408.     public  DoLPT40
  409. ENDIF
  410.  
  411. sEnd    code
  412. End
  413.