home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / dos_ency / 6 / comdvr.asm < prev    next >
Encoding:
Assembly Source File  |  1988-08-11  |  28.1 KB  |  901 lines

  1. Title   COMDVR  Driver for IBM COM Ports
  2. ;       Jim Kyle, 1987
  3. ;           Based on ideas from many sources......
  4. ;               including Mike Higgins, CLM March 1985;
  5. ;               public-domain INTBIOS program from BBS's;
  6. ;               COMBIOS.COM from CIS Programmers' SIG; and
  7. ;               ADVANCED MS-DOS by Ray Duncan.
  8. Subttl  MS-DOS Driver Definitions
  9.  
  10.         Comment *       This comments out the Dbg macro.....
  11. Dbg     Macro   Ltr1,Ltr2,Ltr3  ; used only to debug driver...
  12.         Local   Xxx
  13.         Push    Es              ; save all regs used
  14.         Push    Di
  15.         Push    Ax
  16.         Les     Di,Cs:Dbgptr    ; get pointer to CRT
  17.         Mov     Ax,Es:[di]
  18.         Mov     Al,Ltr1         ; move in letters
  19.         Stosw
  20.         Mov     Al,Ltr2
  21.         Stosw
  22.         Mov     Al,Ltr3
  23.         Stosw
  24.         Cmp     Di,1600         ; top 10 lines only
  25.         Jb      Xxx
  26.         Xor     Di,Di
  27. Xxx:    Mov     Word Ptr Cs:Dbgptr,Di
  28.         Pop     Ax
  29.         Pop     Di
  30.         Pop     Es
  31.         Endm
  32.         *                       ; asterisk ends commented-out region
  33. ;
  34. ;               Device Type Codes
  35. DevChr  Equ     8000h   ; this is a character device
  36. DevBlk  Equ     0000h   ; this is a block (disk) device
  37. DevIoc  Equ     4000h   ; this device accepts IOCTL requests
  38. DevNon  Equ     2000h   ; non-IBM disk driver (block only)
  39. DevOTB  Equ     2000h   ; MS-DOS 3.x out until busy supported (char)
  40. DevOCR  Equ     0800h   ; MS-DOS 3.x open/close/rm supported
  41. DevX32  Equ     0040h   ; MS-DOS 3.2 functions supported
  42. DevSpc  Equ     0010h   ; accepts special interrupt 29H
  43. DevClk  Equ     0008h   ; this is the CLOCK device
  44. DevNul  Equ     0004h   ; this is the NUL device
  45. DevSto  Equ     0002h   ; this is standard output 
  46. DevSti  Equ     0001h   ; this is standard input 
  47. ;
  48. ;               Error Status BITS
  49. StsErr  Equ     8000h   ; general error
  50. StsBsy  Equ     0200h   ; device busy
  51. StsDne  Equ     0100h   ; request completed
  52. ;
  53. ;               Error Reason values for lower-order bits
  54. ErrWp   Equ     0       ; write protect error
  55. ErrUu   Equ     1       ; unknown unit
  56. ErrDnr  Equ     2       ; drive not ready
  57. ErrUc   Equ     3       ; unknown command
  58. ErrCrc  Equ     4       ; cyclical redundancy check error
  59. ErrBsl  Equ     5       ; bad drive request structure length
  60. ErrSl   Equ     6       ; seek error
  61. ErrUm   Equ     7       ; unknown media
  62. ErrSnf  Equ     8       ; sector not found
  63. ErrPop  Equ     9       ; printer out of paper
  64. ErrWf   Equ     10      ; write fault
  65. ErrRf   Equ     11      ; read fault
  66. ErrGf   Equ     12      ; general failure
  67. ;
  68. ;       Structure of an I/O request packet header.
  69. ;
  70. Pack    Struc
  71. Len     Db      ?       ; length of record
  72. Prtno   Db      ?       ; unit code
  73. Code    Db      ?       ; command code
  74. Stat    Dw      ?       ; return status
  75. Dosq    Dd      ?       ; (unused MS-DOS queue link pointer)
  76. Devq    Dd      ?       ; (unused driver queue link pointer)
  77. Media   Db      ?       ; media code on read/write
  78. Xfer    Dw      ?       ; xfer address offset
  79. Xseg    Dw      ?       ; xfer address segment
  80. Count   Dw      ?       ; transfer byte count
  81. Sector  Dw      ?       ; starting sector value (block only)
  82. Pack    Ends
  83.  
  84. Subttl  IBM-PC Hardware Driver Definitions
  85. page
  86. ;
  87. ;               8259 data
  88. PIC_b   Equ     020h    ; port for EOI
  89. PIC_e   Equ     021h    ; port for Int enabling
  90. EOI     Equ     020h    ; EOI control word
  91. ;
  92. ;               8250 port offsets
  93. RxBuf   Equ     0F8h    ; base address
  94. Baud1   Equ     RxBuf+1 ; baud divisor high byte
  95. IntEn   Equ     RxBuf+1 ; interrupt enable register
  96. IntId   Equ     RxBuf+2 ; interrupt identification register
  97. Lctrl   Equ     RxBuf+3 ; line control register
  98. Mctrl   Equ     RxBuf+4 ; modem control register
  99. Lstat   Equ     RxBuf+5 ; line status register
  100. Mstat   Equ     RxBuf+6 ; modem status register
  101. ;
  102. ;               8250 LCR constants
  103. Dlab    Equ     10000000b ; divisor latch access bit
  104. SetBrk  Equ     01000000b ; send break control bit
  105. StkPar  Equ     00100000b ; stick parity control bit
  106. EvnPar  Equ     00010000b ; even parity bit
  107. GenPar  Equ     00001000b ; generate parity bit
  108. Xstop   Equ     00000100b ; extra stop bit
  109. Wd8     Equ     00000011b ; word length = 8
  110. Wd7     Equ     00000010b ; word length = 7
  111. Wd6     Equ     00000001b ; word length = 6
  112. ;
  113. ;               8250 LSR constants
  114. xsre    Equ     01000000b ; xmt SR empty
  115. xhre    Equ     00100000b ; xmt HR empty
  116. BrkRcv  Equ     00010000b ; break received
  117. FrmErr  Equ     00001000b ; framing error
  118. ParErr  Equ     00000100b ; parity error
  119. OveRun  Equ     00000010b ; overrun error
  120. rdta    Equ     00000001b ; received data ready
  121. AnyErr  Equ     BrkRcv+FrmErr+ParErr+OveRun
  122. ;
  123. ;               8250 MCR constants
  124. LpBk    Equ     00010000b ; UART out loops to in (test)
  125. Usr2    Equ     00001000b ; Gates 8250 interrupts
  126. Usr1    Equ     00000100b ; aux user1 output
  127. SetRTS  Equ     00000010b ; sets RTS output
  128. SetDTR  Equ     00000001b ; sets DTR output
  129. ;
  130. ;               8250 MSR constants
  131. CDlvl   Equ     10000000b ; carrier detect level
  132. RIlvl   Equ     01000000b ; ring indicator level
  133. DSRlvl  Equ     00100000b ; DSR level
  134. CTSlvl  Equ     00010000b ; CTS level
  135. CDchg   Equ     00001000b ; Carrier Detect change
  136. RIchg   Equ     00000100b ; Ring Indicator change
  137. DSRchg  Equ     00000010b ; DSR change
  138. CTSchg  Equ     00000001b ; CTS change
  139. ;
  140. ;               8250 IER constants
  141. S_Int   Equ     00001000b ; enable status interrupt
  142. E_Int   Equ     00000100b ; enable error interrupt
  143. X_Int   Equ     00000010b ; enable transmit interrupt
  144. R_Int   Equ     00000001b ; enable receive interrupt
  145. Allint  Equ     00001111b ; enable all interrupts
  146.  
  147. Subttl  Definitions for THIS Driver
  148. page
  149. ;
  150. ;               Bit definitions for the output status byte
  151. ;                      ( this driver only )
  152. LinIdl  Equ     0ffh    ; if all bits off, xmitter is idle
  153. LinXof  Equ     1       ; output is suspended by XOFF
  154. LinDSR  Equ     2       ; output is suspended until DSR comes on again
  155. LinCTS  Equ     4       ; output is suspended until CTS comes on again
  156. ;
  157. ;               Bit definitions for the input status byte
  158. ;                       ( this driver only )
  159. BadInp  Equ     1       ; input line errors have been detected
  160. LostDt  Equ     2       ; receiver buffer overflowed, data lost
  161. OffLin  Equ     4       ; device is off line now
  162. ;
  163. ;               Bit definitions for the special characteristics words
  164. ;                       ( this driver only )
  165. ;               InSpec controls how input from the UART is treated
  166. ;
  167. InEpc   Equ     0001h   ; errors translate to codes with parity bit on
  168. ;
  169. ;               OutSpec controls how output to the UART is treated
  170. ;
  171. OutDSR  Equ     0001h   ; DSR is used to throttle output data
  172. OutCTS  Equ     0002h   ; CTS is used to throttle output data
  173. OutXon  Equ     0004h   ; XON/XOFF is used to throttle output data
  174. OutCdf  Equ     0010h   ; carrier detect is off-line signal
  175. OutDrf  Equ     0020h   ; DSR is off-line signal
  176. ;
  177. Unit    Struc           ; each unit has a structure defining its state:
  178. Port    Dw      ?       ; I/O port address
  179. Vect    Dw      ?       ; interrupt vector offset (NOT interrupt number!)
  180. Isradr  Dw      ?       ; offset to interrupt service routine
  181. OtStat  Db      Wd8     ; default LCR bit settings during INIT,
  182.                         ; output status bits after
  183. InStat  Db      Usr2+SetRTS+SetDTR   ; MCR bit settings during INIT,
  184.                         ; input status bits after
  185. InSpec  Dw      InEpc   ; special mode bits for INPUT
  186. OutSpec Dw      OutXon  ; special mode bits for OUTPUT
  187. Baud    Dw      96      ; current baud rate divisor value (1200 b)
  188. Ifirst  Dw      0       ; offset of first character in input buffer
  189. Iavail  Dw      0       ; offset of next available byte
  190. Ibuf    Dw      ?       ; pointer to input buffer
  191. Ofirst  Dw      0       ; offset of first character in output buffer
  192. Oavail  Dw      0       ; offset of next avail byte in output buffer
  193. Obuf    Dw      ?       ; pointer to output buffer
  194. Unit    Ends
  195.  
  196. ;
  197. ;       Beginning of driver code and data
  198. ;
  199. Driver  Segment
  200.         Assume  Cs:driver, ds:driver, es:driver
  201.         Org     0               ; drivers start at 0
  202.  
  203.         Dw      Async2,-1       ; pointer to next device
  204.         Dw      DevChr + DevIoc ; character device with IOCTL
  205.         Dw      Strtegy         ; offset of Strategy routine
  206.         Dw      Request1        ; offset of interrupt entry point 1
  207.         Db      'ASY1    '      ; device 1 name
  208. Async2:
  209.         Dw      -1,-1           ; pointer to next device: MS-DOS fills in
  210.         Dw      DevChr + DevIoc ; character device with IOCTL
  211.         Dw      Strtegy         ; offset of Strategy routine
  212.         Dw      Request2        ; offset of interrupt entry point 2
  213.         Db      'ASY2    '      ; device 2 name
  214.  
  215. ;dbgptr dd      0b0000000h
  216. ;
  217. ;         Following is the storage area for the request packet pointer
  218. ;
  219. PackHd  Dd      0
  220. ;
  221. ;         baud rate conversion table
  222. Asy_baudt Dw           50,2304          ; first value is desired baud rate
  223.           Dw           75,1536          ; second is divisor register value
  224.           Dw          110,1047
  225.           Dw          134, 857
  226.           Dw          150, 786
  227.           Dw          300, 384
  228.           Dw          600, 192
  229.           Dw         1200,  96
  230.           Dw         1800,  64
  231.           Dw         2000,  58
  232.           Dw         2400,  48
  233.           Dw         3600,  32
  234.           Dw         4800,  24
  235.           Dw         7200,  16
  236.           Dw         9600,  12
  237.  
  238. ; table of structures
  239. ;       ASY1 defaults to the COM1 port, INT 0CH vector, XON,
  240. ;       no parity, 8 databits, 1 stop bit, and 1200 baud
  241. Asy_tab1:
  242.         Unit    <3f8h,30h,asy1isr,,,,,,,,in1buf,,,out1buf>
  243.  
  244. ;       ASY2 defaults to the COM2 port, INT 0BH vector, XON,
  245. ;       no parity, 8 databits, 1 stop bit, and 1200 baud
  246. Asy_tab2:
  247.         Unit    <2f8h,2ch,asy2isr,,,,,,,,in2buf,,,out2buf>
  248.  
  249. Bufsiz  Equ     256        ; input buffer size
  250. Bufmsk  =       Bufsiz-1   ; mask for calculating offsets modulo bufsiz
  251. In1buf  Db      Bufsiz DUP (?)
  252. Out1buf Db      Bufsiz DUP (?)
  253. In2buf  Db      Bufsiz DUP (?)
  254. Out2buf Db      Bufsiz DUP (?)
  255. ;
  256. ;               Following is a table of offsets to all the driver functions
  257.  
  258. Asy_funcs:
  259.         Dw      Init            ;  0 initialize driver
  260.         Dw      Mchek           ;  1 media check (block only)
  261.         Dw      BldBPB          ;  2 build BPB (block only)
  262.         Dw      Ioctlin         ;  3 IOCTL read
  263.         Dw      Read            ;  4 read
  264.         Dw      Ndread          ;  5 nondestructive read
  265.         Dw      Rxstat          ;  6 input status
  266.         Dw      Inflush         ;  7 flush input buffer
  267.         Dw      Write           ;  8 write
  268.         Dw      Write           ;  9 write with verify
  269.         Dw      Txstat          ; 10 output status
  270.         Dw      Txflush         ; 11 flush output buffer
  271.         Dw      Ioctlout        ; 12 IOCTL write
  272. ; Following are not used in this driver.....
  273.         Dw      Zexit           ; 13 open (3.x only, not used)
  274.         Dw      Zexit           ; 14 close (3.x only, not used)
  275.         Dw      Zexit           ; 15 rem med (3.x only, not used)
  276.         Dw      Zexit           ; 16 out until bsy (3.x only, not used)
  277.         Dw      Zexit           ; 17
  278.         Dw      Zexit           ; 18
  279.         Dw      Zexit           ; 19 generic IOCTL request (3.2 only)
  280.         Dw      Zexit           ; 20
  281.         Dw      Zexit           ; 21
  282.         Dw      Zexit           ; 22
  283.         Dw      Zexit           ; 23 get logical drive map (3.2 only)
  284.         Dw      Zexit           ; 24 set logical drive map (3.2 only)
  285.  
  286. Subttl  Driver Code
  287. Page
  288. ;
  289. ;       The Strategy routine itself:
  290. ;
  291. Strtegy Proc    Far
  292. ;       dbg     'S','R',' '
  293.         Mov     Word Ptr CS:PackHd,BX   ; store the offset
  294.         Mov     Word Ptr CS:PackHd+2,ES ; store the segment
  295.         Ret
  296. Strtegy Endp
  297. ;
  298. Request1:                       ; async1 has been requested
  299.         Push    Si              ; save SI
  300.         Lea     Si,Asy_tab1     ; get the device unit table address
  301.         Jmp     Short   Gen_request
  302.  
  303. Request2:                       ; async2 has been requested
  304.         Push    Si              ; save SI
  305.         Lea     Si,Asy_tab2     ; get unit table two's address
  306.  
  307. Gen_request:
  308. ;       dbg     'R','R',' '
  309.         Pushf                   ; save all regs
  310.         Cld
  311.         Push    Ax
  312.         Push    Bx
  313.         Push    Cx
  314.         Push    Dx
  315.         Push    Di
  316.         Push    Bp
  317.         Push    Ds
  318.         Push    Es
  319.         Push    Cs              ; set DS = CS
  320.         Pop     Ds
  321.         Les     Bx,PackHd       ; get packet pointer
  322.         Lea     Di,Asy_funcs    ; point DI to jump table
  323.         Mov     Al,es:code[bx]  ; command code
  324.         Cbw
  325.         Add     Ax,Ax           ; double to word
  326.         Add     Di,ax
  327.         Jmp     [di]            ; go do it
  328. ;
  329. ;       Exit from driver request
  330. ;
  331. ExitP   Proc    Far
  332. Bsyexit:
  333.         Mov     Ax,StsBsy
  334.         Jmp     Short   Exit
  335.  
  336. Mchek:
  337. BldBPB:
  338. Zexit:  Xor     Ax,Ax
  339. Exit:   Les     Bx,PackHd       ; get packet pointer
  340.         Or      Ax,StsDne
  341.         Mov     Es:Stat[Bx],Ax  ; set return status
  342.         Pop     Es              ; restore registers
  343.         Pop     Ds
  344.         Pop     Bp
  345.         Pop     Di
  346.         Pop     Dx
  347.         Pop     Cx
  348.         Pop     Bx
  349.         Pop     Ax
  350.         Popf
  351.         Pop     Si
  352.         Ret
  353. ExitP   Endp
  354.  
  355. Subttl  Driver Service Routines
  356. Page
  357.  
  358. ;       Read data from device
  359.  
  360. Read:
  361. ;       dbg     'R','d',' '
  362.         Mov     Cx,Es:Count[bx] ; get requested nbr
  363.         Mov     Di,Es:Xfer[bx]  ; get target pointer
  364.         Mov     Dx,Es:Xseg[bx]
  365.         Push    Bx              ; save for count fixup
  366.         Push    Es
  367.         Mov     Es,Dx
  368.         Test    InStat[si],BadInp Or LostDt
  369.         Je      No_lerr         ; no error so far...
  370.         Add     Sp,4            ; error, flush SP
  371.         And     InStat[si],Not ( BadInp Or LostDt )
  372.         Mov     Ax,ErrRf        ; error, report it
  373.         Jmp     Exit
  374. No_lerr:
  375.         Call    Get_in          ; go for one
  376.         Or      Ah,Ah
  377.         Jnz     Got_all         ; none to get now
  378.         Stosb                   ; store it
  379.         Loop    No_lerr         ; go for more
  380. Got_all:
  381.         Pop     Es
  382.         Pop     Bx
  383.         Sub     Di,Es:Xfer[bx]  ; calc number stored
  384.         Mov     Es:Count[bx],Di ; return as count
  385.         Jmp     Zexit
  386.  
  387. ;       Nondestructive read from device
  388.  
  389. Ndread:
  390.         Mov     Di,ifirst[si]
  391.         Cmp     Di,iavail[si]
  392.         Jne     Ndget
  393.         Jmp     Bsyexit         ; buffer empty
  394. Ndget:
  395.         Push    Bx
  396.         Mov     Bx,ibuf[si]
  397.         Mov     Al,[bx+di]
  398.         Pop     Bx
  399.         Mov     Es:media[bx],al ; return char
  400.         Jmp     Zexit
  401.  
  402. ;       Input status request
  403.  
  404. Rxstat:
  405.         Mov     Di,ifirst[si]
  406.         Cmp     Di,iavail[si]
  407.         Jne     Rxful
  408.         Jmp     Bsyexit         ; buffer empty
  409. Rxful:
  410.         Jmp     Zexit           ; have data
  411.  
  412. ;       Input flush request
  413.  
  414. Inflush:
  415.         Mov     Ax,iavail[si]
  416.         Mov     Ifirst[si],ax
  417.         Jmp     Zexit
  418.  
  419. ;       Output data to device
  420.  
  421. Write:
  422. ;       dbg     'W','r',' '
  423.         Mov     Cx,es:count[bx]
  424.         Mov     Di,es:xfer[bx]
  425.         Mov     Ax,es:xseg[bx]
  426.         Mov     Es,ax
  427. Wlup:
  428.         Mov     Al,es:[di]      ; get the byte
  429.         Inc     Di
  430. Wwait:
  431.         Call    Put_out         ; put away
  432.         Cmp     Ah,0
  433.         Jne     Wwait           ; wait for room!
  434.         Call    Start_output    ; get it going
  435.         Loop    Wlup
  436.  
  437.         Jmp     Zexit
  438.  
  439. ;       Output status request
  440.  
  441. Txstat:
  442.         Mov     Ax,ofirst[si]
  443.         Dec     Ax
  444.         And     Ax,bufmsk
  445.         Cmp     Ax,oavail[si]
  446.         Jne     Txroom
  447.         Jmp     Bsyexit         ; buffer full
  448. Txroom:
  449.         Jmp     Zexit           ; room exists
  450.  
  451. ;       IOCTL read request, return line parameters
  452.  
  453. Ioctlin:
  454.         Mov     Cx,es:count[bx]
  455.         Mov     Di,es:xfer[bx]
  456.         Mov     Dx,es:xseg[bx]
  457.         Mov     Es,dx
  458.         Cmp     Cx,10
  459.         Je      Doiocin
  460.         Mov     Ax,errbsl
  461.         Jmp     Exit
  462. Doiocin:
  463.         Mov     Dx,port[si]     ; base port
  464.         Mov     Dl,Lctrl        ; line status
  465.         Mov     Cx,4            ; LCR, MCR, LSR, MSR
  466. Getport:
  467.         In      Al,dx
  468.         Stos    Byte Ptr [DI]
  469.         Inc     Dx
  470.         Loop    Getport
  471.  
  472.         Mov     Ax,InSpec[si]   ; spec in flags
  473.         Stos    Word Ptr [DI]
  474.         Mov     Ax,OutSpec[si]  ; out flags
  475.         Stos    Word Ptr [DI]
  476.         Mov     Ax,baud[si]     ; baud rate
  477.         Mov     Bx,di
  478.         Mov     Di,offset Asy_baudt+2
  479.         Mov     Cx,15
  480. Baudcin:
  481.         Cmp     [di],ax
  482.         Je      Yesinb
  483.         Add     Di,4
  484.         Loop    Baudcin
  485. Yesinb:
  486.         Mov     Ax,-2[di]
  487.         Mov     Di,bx
  488.         Stos    Word Ptr [DI]
  489.         Jmp     Zexit
  490.  
  491. ;       Flush output buffer request
  492.  
  493. Txflush:
  494.         Mov     Ax,oavail[si]
  495.         Mov     Ofirst[si],ax
  496.         Jmp     Zexit
  497.  
  498. ;       IOCTL request: change line parameters for this driver
  499.  
  500. Ioctlout:
  501.         Mov     Cx,es:count[bx]
  502.         Mov     Di,es:xfer[bx]
  503.         Mov     Dx,es:xseg[bx]
  504.         Mov     Es,dx
  505.         Cmp     Cx,10
  506.         Je      Doiocout
  507.         Mov     Ax,errbsl
  508.         Jmp     Exit
  509.  
  510. Doiocout:
  511.         Mov     Dx,port[si]     ; base port
  512.         Mov     Dl,Lctrl        ; line ctrl
  513.         Mov     Al,es:[di]
  514.         Inc     Di
  515.         Or      Al,Dlab         ; set baud
  516.         Out     Dx,al
  517.         Clc
  518.         Jnc     $+2
  519.         Inc     Dx              ; mdm ctrl
  520.         Mov     Al,es:[di]
  521.         Or      Al,Usr2         ; Int Gate
  522.         Out     Dx,al
  523.         Add     Di,3            ; skip LSR,MSR
  524.         Mov     Ax,es:[di]
  525.         Add     Di,2
  526.         Mov     InSpec[si],ax
  527.         Mov     Ax,es:[di]
  528.         Add     Di,2
  529.         Mov     OutSpec[si],ax
  530.         Mov     Ax,es:[di]      ; set baud
  531.         Mov     Bx,di
  532.         Mov     Di,offset Asy_baudt
  533.         Mov     Cx,15
  534. Baudcout:
  535.         Cmp     [di],ax
  536.         Je      Yesoutb
  537.         Add     Di,4
  538.         Loop    Baudcout
  539.  
  540.         Mov     Dl,Lctrl        ; line ctrl
  541.         In      Al,dx           ; get LCR data
  542.         And     Al,not Dlab     ; strip
  543.         Clc
  544.         Jnc     $+2
  545.         Out     Dx,al           ; put back
  546.         Mov     Ax,ErrUm        ; "unknown media"
  547.         Jmp     Exit
  548.  
  549. Yesoutb:
  550.         Mov     Ax,2[di]        ; get divisor
  551.         Mov     Baud[si],ax     ; save to report later
  552.         Mov     Dx,port[si]     ; set divisor
  553.         Out     Dx,al
  554.         Clc
  555.         Jnc     $+2
  556.         Inc     Dx
  557.         Mov     Al,ah
  558.         Out     Dx,al
  559.         Clc
  560.         Jnc     $+2
  561.         Mov     Dl,Lctrl        ; line ctrl
  562.         In      Al,dx           ; get LCR data
  563.         And     Al,not Dlab     ; strip
  564.         Clc
  565.         Jnc     $+2
  566.         Out     Dx,al           ; put back
  567.         Jmp     Zexit
  568.  
  569. Subttl  Ring Buffer Routines
  570. Page
  571.  
  572. Put_out Proc    Near    ; puts AL into output ring buffer
  573.         Push    Cx
  574.         Push    Di
  575.         Pushf
  576.         Cli
  577.         Mov     Cx,oavail[si]   ; put ptr
  578.         Mov     Di,cx
  579.         Inc     Cx              ; bump
  580.         And     Cx,bufmsk
  581.         Cmp     Cx,ofirst[si]   ; overflow?
  582.         Je      Poerr           ; yes, don't
  583.         Add     Di,obuf[si]     ; no
  584.         Mov     [di],al         ; put in buffer
  585.         Mov     Oavail[si],cx
  586. ;       dbg     'p','o',' '
  587.         Mov     Ah,0
  588.         Jmp     Short   Poret
  589. Poerr:
  590.         Mov     Ah,-1
  591. Poret:
  592.         Popf
  593.         Pop     Di
  594.         Pop     Cx
  595.         Ret
  596. Put_out Endp
  597.  
  598. Get_out Proc    Near    ; gets next character from output ring buffer
  599.         Push    Cx
  600.         Push    Di
  601.         Pushf
  602.         Cli
  603.         Mov     Di,ofirst[si]   ; get ptr
  604.         Cmp     Di,oavail[si]   ; put ptr
  605.         Jne     Ngoerr
  606.         Mov     Ah,-1           ; empty
  607.         Jmp     Short   Goret
  608. Ngoerr:
  609. ;       dbg     'g','o',' '
  610.         Mov     Cx,di
  611.         Add     Di,obuf[si]
  612.         Mov     Al,[di]         ; get char
  613.         Mov     Ah,0
  614.         Inc     Cx              ; bump ptr
  615.         And     Cx,bufmsk       ; wrap
  616.         Mov     Ofirst[si],cx
  617. Goret:
  618.         Popf
  619.         Pop     Di
  620.         Pop     Cx
  621.         Ret
  622. Get_out Endp
  623.  
  624. Put_in  Proc    Near    ; puts the char from AL into input ring buffer
  625.         Push    Cx
  626.         Push    Di
  627.         Pushf
  628.         Cli
  629.         Mov     Di,iavail[si]
  630.         Mov     Cx,di
  631.         Inc     Cx
  632.         And     Cx,bufmsk
  633.         Cmp     Cx,ifirst[si]
  634.         Jne     Npierr
  635.         Mov     Ah,-1
  636.         Jmp     Short   Piret
  637. Npierr:
  638.         Add     Di,ibuf[si]
  639.         Mov     [di],al
  640.         Mov     Iavail[si],cx
  641. ;       dbg     'p','i',' '
  642.         Mov     Ah,0
  643. Piret:
  644.         Popf
  645.         Pop     Di
  646.         Pop     Cx
  647.         Ret
  648. Put_in  Endp
  649.  
  650. Get_in  Proc    Near    ; gets one from input ring buffer into AL
  651.         Push    Cx
  652.         Push    Di
  653.         Pushf
  654.         Cli
  655.         Mov     Di,ifirst[si]
  656.         Cmp     Di,iavail[si]
  657.         Je      Gierr
  658.         Mov     Cx,di
  659.         Add     Di,ibuf[si]
  660.         Mov     Al,[di]
  661.         Mov     Ah,0
  662. ;       dbg     'g','i',' '
  663.         Inc     Cx
  664.         And     Cx,bufmsk
  665.         Mov     Ifirst[si],cx
  666.         Jmp     Short   Giret
  667. Gierr:
  668.         Mov     Ah,-1
  669. Giret:
  670.         Popf
  671.         Pop     Di
  672.         Pop     Cx
  673.         Ret
  674. Get_in  Endp
  675.  
  676. Subttl  Interrupt Dispatcher Routine
  677. Page
  678.  
  679. Asy1isr:
  680.         Sti
  681.         Push    Si
  682.         Lea     Si,asy_tab1
  683.         Jmp     Short   Int_serve
  684.  
  685. Asy2isr:
  686.         Sti
  687.         Push    Si
  688.         Lea     Si,asy_tab2
  689.  
  690. Int_serve:
  691.         Push    Ax              ; save all regs
  692.         Push    Bx
  693.         Push    Cx
  694.         Push    Dx
  695.         Push    Di
  696.         Push    Ds
  697.         Push    Cs              ; set DS = CS
  698.         Pop     Ds
  699. Int_exit:
  700. ;       dbg     'I','x',' '
  701.         Mov     Dx,Port[si]     ; base address
  702.         Mov     Dl,IntId        ; check Int ID
  703.         In      Al,Dx
  704.         Cmp     Al,00h          ; dispatch filter
  705.         Je      Int_modem
  706.         Jmp     Int_mo_no
  707. Int_modem:
  708. ;       dbg     'M','S',' '
  709.         Mov     Dl,Mstat
  710.         In      Al,dx           ; read MSR content
  711.         Test    Al,CDlvl        ; carrier present?
  712.         Jnz     Msdsr           ; yes, test for DSR
  713.         Test    OutSpec[si],OutCdf      ; no, is CD off line?
  714.         Jz      Msdsr
  715.         Or      InStat[si],OffLin
  716. Msdsr:
  717.         Test    Al,DSRlvl       ; DSR present?
  718.         Jnz     Dsron           ; yes, handle it
  719.         Test    OutSpec[si],OutDSR      ; no, is DSR throttle?
  720.         Jz      Dsroff
  721.         Or      OtStat[si],LinDSR       ; yes, throttle down
  722. Dsroff:
  723.         Test    OutSpec[si],OutDrf      ; is DSR off line?
  724.         Jz      Mscts
  725.         Or      InStat[si],OffLin       ; yes, set flag
  726.         Jmp     Short   Mscts
  727. Dsron:
  728.         Test    OtStat[si],LinDSR       ; throttled for DSR?
  729.         Jz      Mscts
  730.         Xor     OtStat[si],LinDSR       ; yes, clear it out
  731.         Call    Start_output
  732. Mscts:
  733.         Test    Al,CTSlvl       ; CTS present?
  734.         Jnz     Ctson           ; yes, handle it
  735.         Test    OutSpec[si],OutCTS      ; no, is CTS throttle?
  736.         Jz      Int_exit2
  737.         Or      OtStat[si],LinCTS       ; yes, shut it down
  738.         Jmp     Short   Int_exit2
  739. Ctson:
  740.         Test    OtStat[si],LinCTS       ; throttled for CTS?
  741.         Jz      Int_exit2
  742.         Xor     OtStat[si],LinCTS       ; yes, clear it out
  743.         Jmp     Short   Int_exit1
  744. Int_mo_no:
  745.         Cmp     Al,02h
  746.         Jne     Int_tx_no
  747. Int_txmit:
  748. ;       dbg     'T','x',' '
  749. Int_exit1:
  750.         Call    Start_output    ; try to send another
  751. Int_exit2:
  752.         Jmp     Int_exit
  753. Int_tx_no:
  754.         Cmp     Al,04h
  755.         Jne     Int_rec_no
  756. Int_receive:
  757. ;       dbg     'R','x',' '
  758.         Mov     Dx,port[si]
  759.         In      Al,dx           ; take char from 8250
  760.         Test    OutSpec[si],OutXon  ; is XON/XOFF enabled?
  761.         Jz      Stuff_in        ; no
  762.         Cmp     Al,'S' And 01FH ; yes, is this XOFF?
  763.         Jne     Isq             ; no, check for XON
  764.         Or      OtStat[si],LinXof ; yes, disable output
  765.         Jmp     Int_exit2       ; don't store this one
  766. Isq:
  767.         Cmp     Al,'Q' And 01FH ; is this XON?
  768.         Jne     Stuff_in        ; no, save it
  769.         Test    OtStat[si],LinXof ; yes, waiting?
  770.         Jz      Int_exit2       ; no, ignore it
  771.         Xor     OtStat[si],LinXof ; yes, clear the XOFF bit
  772.         Jmp     Int_exit1       ; and try to resume xmit
  773. Int_rec_no:
  774.         Cmp     Al,06h
  775.         Jne     Int_done
  776. Int_rxstat:
  777. ;       dbg     'E','R',' '
  778.         Mov     Dl,Lstat
  779.         In      Al,dx
  780.         Test    InSpec[si],InEpc ; return them as codes?
  781.         Jz      Nocode          ; no, just set error alarm
  782.         And     Al,AnyErr       ; yes, mask off all but error bits
  783.         Or      Al,080h
  784. Stuff_in:
  785.         Call    Put_in          ; put input char in buffer
  786.         Cmp     Ah,0            ; did it fit?
  787.         Je      Int_exit3       ; yes, all OK
  788.         Or      InStat[si],LostDt  ; no, set DataLost bit
  789. Int_exit3:
  790.         Jmp     Int_exit
  791. Nocode:
  792.         Or      InStat[si],BadInp
  793.         Jmp     Int_exit3
  794. Int_done:
  795.         Clc
  796.         Jnc     $+2
  797.         Mov     Al,EOI          ; all done now
  798.         Out     PIC_b,Al
  799.         Pop     Ds              ; restore regs
  800.         Pop     Di
  801.         Pop     Dx
  802.         Pop     Cx
  803.         Pop     Bx
  804.         Pop     Ax
  805.         Pop     Si
  806.         Iret
  807.  
  808. Start_output    Proc    Near
  809.         Test    OtStat[si],LinIdl ; Blocked?
  810.         Jnz     Dont_start      ; yes, no output
  811.         Mov     Dx,port[si]     ; no, check UART
  812.         Mov     Dl,Lstat
  813.         In      Al,Dx
  814.         Test    Al,xhre         ; empty?
  815.         Jz      Dont_start      ; no
  816.         Call    Get_out         ; yes, anything waiting?
  817.         Or      Ah,Ah
  818.         Jnz     Dont_start      ; no
  819.         Mov     Dl,RxBuf        ; yes, send it out
  820.         Out     Dx,al
  821. ;       dbg     's','o',' '
  822. Dont_start:
  823.         ret
  824. Start_output    Endp
  825.  
  826. Subttl  Initialization Request Routine
  827. Page
  828.  
  829. Init:   Lea     Di,$            ; release rest...
  830.         Mov     Es:Xfer[bx],Di
  831.         Mov     Es:Xseg[bx],Cs
  832.  
  833.         Mov     Dx,Port[si]     ; base port
  834.         Mov     Dl,Lctrl
  835.         Mov     Al,Dlab         ; enable divisor
  836.         Out     Dx,Al
  837.         Clc
  838.         Jnc     $+2
  839.         Mov     Dl,RxBuf
  840.         Mov     Ax,Baud[si]     ; set baud
  841.         Out     Dx,Al
  842.         Clc
  843.         Jnc     $+2
  844.         Inc     Dx
  845.         Mov     Al,Ah
  846.         Out     Dx,Al
  847.         Clc
  848.         Jnc     $+2
  849.  
  850.         Mov     Dl,Lctrl        ; set LCR
  851.         Mov     Al,OtStat[si]   ; from table
  852.         Out     Dx,Al
  853.         Mov     OtStat[si],0    ; clear status
  854.         Clc
  855.         Jnc     $+2
  856.         Mov     Dl,IntEn        ; IER
  857.         Mov     Al,AllInt       ; enable ints in 8250
  858.         Out     Dx,Al
  859.         Clc
  860.         Jnc     $+2
  861.         Mov     Dl,Mctrl        ; set MCR
  862.         Mov     Al,InStat[si]   ; from table
  863.         Out     Dx,Al
  864.         Mov     InStat[si],0    ; clear status
  865.  
  866. ClRgs:  Mov     Dl,Lstat        ; clear LSR
  867.         In      Al,Dx
  868.         Mov     Dl,RxBuf        ; clear RX reg
  869.         In      Al,Dx
  870.         Mov     Dl,Mstat        ; clear MSR
  871.         In      Al,Dx
  872.         Mov     Dl,IntId        ; IID reg
  873.         In      Al,Dx
  874.         In      Al,Dx
  875.         Test    Al,1            ; int pending?
  876.         Jz      ClRgs           ; yes, repeat
  877.  
  878.         Cli
  879.         Xor     Ax,Ax           ; set int vec
  880.         Mov     Es,Ax
  881.         Mov     Di,Vect[si]
  882.         Mov     Ax,IsrAdr[si]   ; from table
  883.         Stosw
  884.         Mov     Es:[di],cs
  885.  
  886.         In      Al,PIC_e        ; get 8259
  887.         And     Al,0E7h         ; com1/2 mask
  888.         Clc
  889.         Jnb     $+2
  890.         Out     PIC_e,Al
  891.         Sti
  892.  
  893.         Mov     Al,EOI          ; now send EOI just in case
  894.         Out     PIC_b,Al
  895.  
  896. ;       dbg     'D','I',' '     ; driver installed
  897.         Jmp     Zexit
  898.  
  899. Driver  Ends
  900.         End
  901.