Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

412 lines
8.3 KiB

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