home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / asmutil / stdlib.zip / SER1.ASM < prev    next >
Assembly Source File  |  1990-08-12  |  18KB  |  788 lines

  1. stdlib        segment    para public 'slcode'
  2.         assume    cs:stdlib
  3. ;
  4. ;
  5. ; Routines to handle COM1 data transmission.
  6. ;
  7. ; COM1 refers to HARDWARE COM1 port which is located beginning at port
  8. ; address 3f8h and causes INT 0Ch.
  9. ;
  10. ;
  11. ; Released to the public domain.
  12. ; Created by Randall Hyde.
  13. ; Date: 8/11/90
  14. ;
  15. ;
  16. ; Useful equates:
  17. ;
  18. BIOSvars    =    40h
  19. Com1Adrs    =    0
  20. Com2Adrs    =    2
  21. ;
  22. BufSize        =    256            ;# of bytes in buffer.
  23. ;
  24. ;
  25. ; Serial port equates:
  26. ;
  27. Com1Port    =    3F8h
  28. Com1IER        =    3F9h
  29. Com1IIR        =    3FAh
  30. Com1LCR        =    3FBh
  31. Com1MCR        =    3FCh
  32. Com1LSR        =    3FDh
  33. Com1MSR        =    3FEh
  34. ;
  35. ;
  36. ; Register assignments:
  37. ;
  38. ; Interupt enable register (IER):
  39. ;
  40. ;        If one:
  41. ; bit 0-    Enables received data available interrupt.
  42. ; bit 1-    Enables transmitter holding register empty interrupt.
  43. ; bit 2-    Enables receiver line status interrupt.
  44. ; bit 3-    Enables the modem status interrupt.
  45. ; bits 4-7-    Always set to zero.
  46. ;
  47. ; Interrupt ID Register (IIR):
  48. ;
  49. ; bit 0-    No interrupt is pending (interrupt pending if zero).
  50. ; bits 1,2-    Binary value denoting source of interrupt:
  51. ;            00-Modem status
  52. ;            01-Transmitter Hold Register Empty
  53. ;            10-Received Data Available
  54. ;            11-Receiver line status
  55. ; bits 3-7    Always zero.
  56. ;
  57. ;
  58. ; Line Control Register (LCR):
  59. ;
  60. ; bits 0,1-    Word length (00=5, 01=6, 10=7, 11=8 bits).
  61. ; bit 2-    Stop bits (0=1, 1=2 stop bits [1-1/2 if 5 data bits]).
  62. ; bit 3-    Parity enabled if one.
  63. ; bit 4-    0 for odd parity, 1 for even parity (assuming bit 3 = 1).
  64. ; bit 5-    1 for stuck parity.
  65. ; bit 6-    1=force break.
  66. ; bit 7-    1=Divisor latch access bit.  0=rcv/xmit access bit.
  67. ;
  68. ; Modem Control Register (MCR):
  69. ;
  70. ; bit 0-    Data Terminal Ready (DTR)
  71. ; bit 1-    Request to send (RTS)
  72. ; bit 2-    OUT 1
  73. ; bit 3-    OUT 2
  74. ; bit 4-    Loop back control.
  75. ; bits 5-7-    Always zero.
  76. ;
  77. ; Line Status Register (LSR):
  78. ;
  79. ; bit 0-    Data Ready
  80. ; bit 1-    Overrun error
  81. ; bit 2-    Parity error
  82. ; bit 3-    Framing error
  83. ; bit 4-    Break Interrupt
  84. ; bit 5-    Transmitter holding register is empty.
  85. ; bit 6-    Transmit shift register is empty.
  86. ; bit 7-    Always zero.
  87. ;
  88. ; Modem Status Register (MSR):
  89. ;
  90. ; bit 0-    Delta CTS
  91. ; bit 1-    Delta DSR
  92. ; bit 2-    Trailing edge ring indicator
  93. ; bit 3-    Delta carrier detect
  94. ; bit 4-    Clear to send
  95. ; bit 5-    Data Set Ready
  96. ; bit 6-    Ring indicator
  97. ; bit 7-    Data carrier detect
  98. ;
  99.  
  100. ;
  101. ; sl_Com1Baud: Set the COM1 port baud rate
  102. ; AX = baud rate (110, 150, 300, 600, 1200, 2400, 4800, 9600, 19200)
  103. ;
  104.         public    sl_Com1Baud
  105. sl_Com1Baud    proc    far
  106.         push    ax
  107.         push    dx
  108.         cmp    ax, 9600
  109.         ja    Set19200
  110.         je    Set9600
  111.         cmp    ax, 2400
  112.         ja    Set4800
  113.         je    Set2400
  114.         cmp    ax, 600
  115.         ja    Set1200
  116.         je    Set600
  117.         cmp    ax, 150
  118.         ja    Set300
  119.         je    Set150
  120.         mov    ax, 1047        ;Default to 110 baud
  121.         jmp    short SetPort
  122. ;
  123. Set150:        mov    ax, 768
  124.         jmp    short SetPort
  125. ;
  126. Set300:        mov    ax, 384
  127.         jmp    short SetPort
  128. ;
  129. Set600:        mov    ax, 192
  130.         jmp    short SetPort
  131. ;
  132. Set1200:    mov    ax, 96
  133.         jmp    short SetPort
  134. ;
  135. Set2400:    mov    ax, 48
  136.         jmp    short SetPort
  137. ;
  138. Set4800:    mov    ax, 24
  139.         jmp    short SetPort
  140. ;
  141. Set9600:    mov    ax, 12
  142.         jmp    short SetPort
  143. ;
  144. Set19200:    mov    ax, 6
  145. SetPort:    mov    dx, ax            ;Save baud value.
  146.         call    far ptr sl_GetLCRCom1
  147.         push    ax            ;Save old divisor bit value.
  148.         or    al, 80h            ;Set divisor select bit.
  149.         call    far ptr sl_SetLCRCom1
  150.         mov    ax, dx            ;Get baud rate divisor value.
  151.         mov    dx, Com1Port
  152.         out    dx, al
  153.         inc     dx
  154.         mov    al, ah
  155.         out    dx, al
  156.         mov    dx, Com1LCR
  157.         pop    ax
  158.         call    far ptr sl_SetLCRCom1    ;Restore divisor bit value.
  159.         pop    dx
  160.         pop    ax
  161.         ret
  162. sl_Com1Baud    endp
  163. ;
  164. ;
  165. ; sl_Com1Stop:
  166. ; Set the number of stop bits.
  167. ;
  168. ; AL=1 for one stop bit, 2 for two stop bits.
  169. ;
  170.         public    sl_com1Stop
  171. sl_com1Stop    proc    far
  172.         push    ax
  173.         push    dx
  174.         dec    ax
  175.         shl    ax, 1            ;position into bit #2
  176.         shl    ax, 1
  177.         mov    ah, al
  178.         mov    dx, Com1LCR
  179.         in    al, dx
  180.         and     al, 11111011b        ;Mask out Stop Bits bit
  181.         or    al, ah            ;Mask in new # of stop bits.
  182.         out    dx, al
  183.         pop    dx
  184.         pop    ax
  185.         ret
  186. sl_com1Stop    endp
  187. ;
  188. ;
  189. ; sl_com1size: Sets word size on the com1 port.
  190. ; AX = 5, 6, 7, or 8 which is the number of bits to set.
  191. ;
  192.         public    sl_com1size
  193. sl_com1size    proc    far
  194.         push    ax
  195.         push    dx
  196.         sub    al, 5
  197.         cmp    al, 3
  198.         jbe    Okay
  199.         mov    al, 3            ;Default to eight bits.
  200. Okay:        mov    ah, al
  201.         mov    dx, com1LCR
  202.         in    al, dx
  203.         and    al, 11111100b        ;Mask out old word size
  204.         or    al, ah            ;Mask in new word size
  205.         out    dx, al
  206.         pop    dx
  207.         pop    ax
  208.         ret
  209. sl_com1size    endp
  210. ;
  211. ;
  212. ; sl_com1parity: Turns parity on/off, selects even/odd parity, or stuck parity.
  213. ; ax contains the following:
  214. ;
  215. ; bit 0-    1 to enable parity, 0 to disable.
  216. ; bit 1-    0 for odd parity, 1 for even (only valid if bit 0 is 1).
  217. ; bit 2-    Stuck parity bit.  If 1 and bit 0 is 1, then the parity bit
  218. ;        is always set to the inverse of bit 1.
  219. ;
  220.         public    sl_com1parity
  221. sl_com1parity    proc    far
  222.         push    ax
  223.         push    dx
  224. ;
  225.         shl    ax, 1
  226.         shl    ax, 1
  227.         shl    ax, 1
  228.         and    ax, 00111000b        ;Mask out other data.
  229.         mov    ah, al
  230.         mov    dx, com1LCR
  231.         in    al, dx
  232.         and    al, 11000111b
  233.         or    al, ah
  234.         out    dx, al
  235.         pop    dx
  236.         pop    ax
  237.         ret
  238. sl_com1parity    endp
  239. ;
  240. ;
  241. ;****************************************************************************
  242. ;
  243. ; Polled I/O:
  244. ;
  245. ;
  246. ; sl_ReadCom1-    Reads a character from COM1 and returns that character in
  247. ;        the AL register.  Synchronous call, meaning it will not
  248. ;        return until a character is available.
  249. ;
  250.         public    sl_ReadCom1
  251. sl_ReadCom1    proc    far
  252.         push    dx
  253.         call    far ptr sl_GetLCRCom1
  254.         push    ax            ;Save divisor latch access bit.
  255.         and    al, 7fh            ;Select normal port.
  256.         call    far ptr sl_SetLCRCom1
  257.         mov    dx, com1LSR
  258. WaitForChar:    call    far ptr sl_GetLSRCom1
  259.         test    al, 1            ;Data Available?
  260.         jz    WaitForChar
  261.         mov    dx, com1Port
  262.         in    al, dx
  263.         mov    dl, al            ;Save character
  264.         pop    ax            ;Restore divisor access bit.
  265.         call    far ptr sl_SetLCRCom1
  266.         mov    al, dl            ;Restore output character.
  267.         pop    dx
  268.         ret
  269. sl_ReadCom1    endp
  270. ;
  271. ;
  272. ;
  273. ; sl_WriteCom1-    Writes the character in AL to the com1 port.
  274. ;
  275.         public    sl_WriteCom1
  276. sl_WriteCom1    proc    far
  277.         push    dx
  278.         push    ax
  279.         mov    dl, al            ;Save character to output
  280.         call    far ptr sl_GetLCRCom1
  281.         push    ax            ;Save divisor latch access bit.
  282.         and    al, 7fh            ;Select normal port.
  283.         call    far ptr sl_SetLCRCom1
  284. WaitForXmtr:    call    far ptr sl_GetLSRCom1
  285.         test    al, 00100000b        ;Xmtr buffer empty?
  286.         jz    WaitForXmtr
  287.         mov    al, dl            ;Get output character.
  288.         mov    dx, Com1Port
  289.         out    dx, al
  290.         pop    ax            ;Restore divisor access bit.
  291.         call    far ptr sl_SetLCRCom1
  292.         pop    ax
  293.         pop    dx
  294.         ret
  295. sl_WriteCom1    endp
  296. ;
  297. ;
  298. ;
  299. ; sl_TstInpCom1-Returns AL=0 if a character is not available at the com1 port.
  300. ;        Returns AL=1 if a character is available.
  301. ;
  302.         public    sl_TstInpCom1
  303. sl_TstInpCom1    proc    far
  304.         push    dx
  305.         mov    dx, com1LSR
  306.         in    al, dx
  307.         and     al, 1
  308.         pop    dx
  309.         ret
  310. sl_TstInpCom1    endp
  311. ;
  312. ;
  313. ; sl_TstOutCom1-Returns AL=1 when it's okay to send another character to
  314. ;        the transmitter.  Returns zero if the transmitter is full.
  315. ;
  316.         public    sl_TstOutCom1
  317. sl_TstOutCom1    proc    far
  318.         push    dx
  319.         mov    dx, com1LSR
  320.         in    al, dx
  321.         test    al, 00100000b
  322.         mov    al, 0
  323.         jz    toc1
  324.         inc    ax
  325. toc1:        pop    dx
  326.         ret
  327. sl_TstOutCom1    endp
  328. ;
  329. ;
  330. ; sl_GetLSRCom1-Returns the LSR in al:
  331. ;
  332. ; AL:
  333. ;    bit 0-    Data Ready
  334. ;    bit 1-    Overrun error
  335. ;    bit 2-    Parity error
  336. ;    bit 3-    Framing error
  337. ;    bit 4-    Break interrupt
  338. ;    bit 5-    Xmtr holding register is empty.
  339. ;    bit 6-    Xmtr shift register is empty.
  340. ;    bit 7-    Always zero.
  341. ;
  342.         public    sl_GetLSRCom1
  343. sl_GetLSRCom1    proc    far
  344.         push    dx
  345.         mov    dx, com1LSR
  346.         in    al, dx
  347.         pop    dx
  348.         ret
  349. sl_GetLSRCom1    endp
  350. ;
  351. ;
  352. ; sl_GetMSRCom1-Returns the modem status register in AL
  353. ;
  354. ; AL:
  355. ;    bit 0-    Delta clear to send
  356. ;    bit 1-    Delta data set ready
  357. ;    bit 2-    Trailing edge ring indicator
  358. ;    bit 3-    Delta data carrier detect
  359. ;    bit 4-    Clear to send (CTS)
  360. ;    bit 5-    Data set ready (DSR)
  361. ;    bit 6-    Ring indicator (RI)
  362. ;    bit 7-    Data carrier detect (DCD)
  363. ;
  364.         public    sl_GetMSRCom1
  365. sl_GetMSRCom1    proc    far
  366.         push    dx
  367.         mov    dx, com1MSR
  368.         in    al, dx
  369.         pop    dx
  370.         ret
  371. sl_GetMSRCom1    endp
  372. ;
  373. ;
  374. ; sl_SetMCRCom1-Writes the data in AL to the modem control register.
  375. ; sl_GetMCRCom1-Reads the data from the modem control register into AL.
  376. ;
  377. ; AL:
  378. ;    bit 0-    Data terminal ready (DTR)
  379. ;    bit 1-    Request to send (RTS)
  380. ;    bit 2-    Out 1
  381. ;    bit 3-    Out 2
  382. ;    bit 4-    Loop
  383. ;    bits 5-7 (must be zero)
  384. ;
  385.         public    sl_SetMCRCom1
  386. sl_SetMCRCom1    proc    far
  387.         push    dx
  388.         mov    dx, com1MCR
  389.         out    dx, al
  390.         pop    dx
  391.         ret
  392. sl_SetMCRCom1    endp
  393. ;
  394.         public    sl_GetMCRCom1
  395. sl_GetMCRCom1    proc    far
  396.         push    dx
  397.         mov    dx, com1MCR
  398.         in    al, dx
  399.         pop    dx
  400.         ret
  401. sl_GetMCRCom1    endp
  402. ;
  403. ;
  404. ;
  405. ; sl_GetLCRCom1- Reads the value from the line control register into AL.
  406. ; sl_SetLCRCom1- Writes the value in AL to the line control register.
  407. ;
  408. ; AL:
  409. ;    bits 0,1-    Word length selection
  410. ;    bit 2-        Number of stop bits
  411. ;    bit 3-        Parity Enable
  412. ;    bit 4-        Even parity select
  413. ;    bit 5-        Stuck parity
  414. ;    bit 6-        Set Break
  415. ;    bit 7-        Divisor latch access bit
  416. ;
  417.         public    sl_GetLCRCom1
  418. sl_GetLCRCom1    proc    far
  419.         push    dx
  420.         mov    dx, com1LCR
  421.         in    al, dx
  422.         pop    dx
  423.         ret
  424. sl_GetLCRCom1    endp
  425. ;
  426.         public    sl_SetLCRCom1
  427. sl_SetLCRCom1    proc    far
  428.         push    dx
  429.         mov    dx, com1LCR
  430.         out    dx, al
  431.         pop    dx
  432.         ret
  433. sl_SetLCRCom1    endp
  434. ;
  435. ;
  436. ; sl_GetIIRCom1-Reads the interrupt indentification register and returns its
  437. ;        value in AL.
  438. ;
  439. ; AL:
  440. ;    bit 0-        0 if interrupt pending, 1 if no interrupt.
  441. ;    bits 1,2-    Interrupt ID (highest priority).
  442. ;    bits 3-7-    Always zero.
  443. ;
  444. ; Interrupt ID
  445. ; bit 2  1    Source                Reset by
  446. ;     ----    -----------------------------    ------------------------------
  447. ;     0  0    CTS, DSR, RI            Reading the MSR
  448. ;     0  1    Xmtr holding register empty    Reading IIR or writing to xmtr
  449. ;     1  0    Receiver data available        Reading rcvr buffer
  450. ;     1  1    Overrun, parity, framing, or    Reading the LSR.
  451. ;        break
  452. ;
  453. ;
  454.         public    sl_GetIIRCom1
  455. sl_GetIIRCom1    proc    far
  456.         push    dx
  457.         mov    dx, com1IIR
  458.         in    al, dx
  459.         pop    dx
  460.         ret
  461. sl_GetIIRCom1    endp
  462. ;
  463. ;
  464. ; sl_GetIERCom1-Reads the IER and returns it in AL.
  465. ; sl_SetIERCom1-Stores the value in AL into the IER.
  466. ;
  467. ; AL:
  468. ;    bit 0-    Enable data available interrupt.
  469. ;    bit 1-    Enable xmtr holding register empty interrupt.
  470. ;    bit 2-    Enable receive line status interrupt.
  471. ;    bit 3-    Enable modem status interrupt
  472. ;    bits 4-7  Always zero.
  473. ;
  474.         public    sl_GetIERCom1
  475. sl_GetIERCom1    proc    far
  476.         push    dx
  477.         call    sl_GetLCRCom1
  478.         push    ax            ;Save divisor access bit.
  479.         and    al, 7fh            ;Address the IER.
  480.         call    sl_SetLCRCom1
  481.         mov    dx, com1IER
  482.         in    al, dx
  483.         mov    dl, al            ;Save for now
  484.         pop    ax
  485.         call    sl_SetLCRCom1        ;Restore divisor latch
  486.         mov    al, dl            ;Restore IER value
  487.         pop    dx
  488.         ret
  489. sl_GetIERCom1    endp
  490. ;
  491. ;
  492.         public    sl_SetIERCom1
  493. sl_SetIERCom1    proc    far
  494.         push    dx
  495.         push    ax
  496.         mov    ah, al            ;Save value to output
  497.         call    sl_GetLCRCom1        ;Get and save divsor access
  498.         push    ax            ;bit.
  499.         and    al, 7fh            ;Address the IER.
  500.         call    sl_SetLCRCom1
  501.         mov    al, ah
  502.         mov    dx, com1IER
  503.         out    dx, al
  504.         pop    ax            ;Restore divisor latch bit.
  505.         call    sl_SetLCRCom1
  506.         pop    ax
  507.         pop    dx
  508.         ret
  509. sl_SetIERCom1    endp
  510. ;
  511. ;
  512. ;****************************************************************************
  513. ;
  514. ; Interrupt-driven Serial I/O
  515. ;
  516. int0Cofs    equ    es:[30h]
  517. int0Cseg    equ    es:[32h]
  518. int0cVec    dd    ?        ;Holds old int 0ch vector.
  519. InHead        dw    InpBuf
  520. InTail        dw    InpBuf
  521. InpBuf        db    Bufsize dup (?)
  522. InpBufEnd    equ    this byte
  523. ;
  524. OutHead        dw    OutBuf
  525. OutTail        dw    OutBuf
  526. OutBuf        db    BufSize dup (?)
  527. OutBufEnd    equ    this byte
  528. ;
  529. i8259a        db    0        ;8259a interrupt enable register.
  530. TestBuffer    db    0        ;1 means we are transmitting out of
  531. ;                    ; the transmit buffer.  0 means the
  532. ;                    ; transmitter register is empty and
  533. ;                    ; we can store data directly to it.
  534. ;
  535. ;
  536. ; sl_InitCom1Int-    Initializes the hardware to use interrupt-driven I/O
  537. ;            for COM1:
  538. ;
  539.         public    sl_InitCom1Int
  540. sl_InitCom1Int    proc    far
  541.         pushf            ;Save interrupt disable flag.
  542.         push    es
  543.         push    ax
  544.         push    dx
  545. ;
  546. ; Turn off the interrupts while we're screwing around here.
  547. ;
  548.         cli
  549. ;
  550. ; Save old interrupt vector.
  551. ;
  552.         xor    ax, ax        ;Point at interrupt vectors
  553.         mov    es, ax
  554.         mov    ax, Int0Cofs    ;Get ofs int 0ch vector.
  555.         mov    word ptr cs:int0cVec, ax
  556.         mov    ax, Int0Cseg    ;Get seg int 0ch vector.
  557.         mov    word ptr cs:int0cVec+2, ax
  558. ;
  559. ; Point int 0ch vector at our interrupt service routine:
  560. ;
  561.         mov    ax, cs
  562.         mov    Int0Cseg, ax
  563.         mov    ax, offset Com1IntISR
  564.         mov    Int0Cofs, ax
  565. ;
  566. ; Clear any pending interrupts:
  567. ;
  568.         call    far ptr sl_GetLSRCom1    ;Clear Receiver line status
  569.         call    far ptr sl_GetMSRCom1    ;Clear CTS/DSR/RI Interrupts
  570.         call    far ptr sl_GetIIRCom1    ;Clear xmtr empty interrupt
  571.         mov    dx, Com1Port
  572.         in    al, dx            ;Clear data available intr.
  573. ;
  574. ; Clear divisor latch access bit.  WHILE OPERATING IN INTERRUPT MODE, THE
  575. ; DIVISOR ACCESS LATCH BIT MUST ALWAYS BE ZERO.  If for some horrible reason
  576. ; you need to change the baud rate in the middle of a transmission (or while
  577. ; the interrupts are enabled) clear the interrupt flag, do your dirty work,
  578. ; clear the divisor latch bit, and finally restore interrupts.
  579. ;
  580.         call    far ptr sl_getLCRCom1
  581.         and    al, 7fh
  582.         call    far ptr sl_SetLCRCom1
  583. ;
  584. ;
  585. ; Enable the receiver and transmitter interrupts
  586. ;
  587.         mov    al, 3        ;Enable rcv/xmit interrupts
  588.         call    far ptr sl_SetIERCom1
  589. ;
  590. ; Must set the OUT2 line for interrupts to work.
  591. ; Also sets DTR and RTS active.
  592. ;
  593.         mov    al, 00001011b
  594.         call    far ptr sl_SetMCRCom1
  595. ;
  596. ; Activate the COM1 (int 0ch) bit in the 8259A interrupt controller chip.
  597. ;
  598.         in    al, 21h
  599.         mov    cs:i8259a, al    ;Save interrupt enable bit.
  600.         and    al, 0efh    ;Bit 4=IRQ 4 = INT 0Ch
  601.         out    21h, al
  602. ;
  603.         pop    dx
  604.         pop    ax
  605.         pop    es
  606.         popf            ;Restore interrupt disable flag.
  607.         ret
  608. sl_InitCom1Int    endp
  609. ;
  610. ;
  611. ; sl_IntsOffCom1- Disconnects the interrupt system and shuts off interrupt
  612. ;          activity at the COM1: port.
  613. ;
  614. ;    Warning!  This routine assumes that interrupts are currently active
  615. ;          due to a call to sl_InitCom1Int.  If you call this guy
  616. ;          w/o first calling sl_InitCom1Int you will probably crash
  617. ;          the system.  Furthermore, this routine makes the (rather
  618. ;          presumptuous) assumption that no one else has patched into
  619. ;          the INT 0Ch vector since SL_InitCom1Int was called.
  620. ;
  621.         public    sl_IntsOffCom1
  622. sl_IntsOffCom1    proc    far
  623.         pushf
  624.         push    es
  625.         push    dx
  626.         push    ax
  627. ;
  628.         cli            ;Don't allow interrupts while messing
  629.         xor    ax, ax        ; with the interrupt vectors.
  630.         mov    es, ax        ;Point at interrupt vectors.
  631. ;
  632. ; First, turn off the interrupt source:
  633. ;
  634.         call    far ptr sl_GetMCRCom1
  635.         and    al, 3            ;Mask out OUT 2 bit (masks ints)
  636.         call    far ptr sl_SetMCRCom1
  637. ;
  638.         in    al, 21h            ;Get 8259a ier
  639.         and    al, 0efh        ;Clear IRQ 4 bit.
  640.         mov    ah, cs:i8259a        ;Get our saved value
  641.         and    ah, 1000b        ;Mask out com1: bit (IRQ 4).
  642.         or    al, ah            ;Put bit back in.
  643.         out    21h, al
  644. ;
  645. ; Restore the interrupt vector:
  646. ;
  647.         mov    ax, word ptr cs:Int0cVec
  648.         mov    Int0Cofs, ax
  649.         mov    ax, word ptr cs:Int0cVec+2
  650.         mov    Int0Cseg, ax
  651. ;
  652.         pop    ax
  653.         pop    dx
  654.         pop    es
  655.         popf
  656.         ret
  657. sl_IntsOffCom1    endp
  658. ;
  659. ;----------------------------------------------------------------------------
  660. ;
  661. ; Com1IntISR- Interrupt service routine for COM1:
  662. ;
  663. Com1IntISR    proc    far
  664.         push    ax
  665.         push    bx
  666.         push    dx
  667. TryAnother:    mov    dx, Com1IIR
  668.         in    al, dx            ;Get id
  669.         test    al, 1            ;Any interrupts left?
  670.         jnz     IntRtn
  671.         test    al, 100b
  672.         jnz    ReadCom1
  673.         test    al, 10b
  674.         jnz    WriteCom1
  675. ;
  676. ; Bogus interrupt?
  677. ;
  678.         call    sl_GetLSRCom1        ;Clear receiver line status
  679.         call    sl_GetMSRCom1        ;Clear modem status.
  680.         jmp    TryAnother
  681. ;
  682. IntRtn:        mov    al, 20h            ;Acknowledge interrupt to the
  683.         out    20h, al            ; 8259A interrupt controller.
  684.         pop    dx
  685.         pop    bx
  686.         pop    ax
  687.         iret
  688. ;
  689. ; Handle incoming data here:
  690. ; (Warning: This is a critical region.  Interrupts MUST BE OFF while executing
  691. ;  this code.  By default, interrupts are off in an ISR.  DO NOT TURN THEM ON
  692. ;  if you modify this code).
  693. ;
  694. ReadCom1:    mov    dx, Com1Port
  695.         in    al, dx            ;Get the input char
  696.         mov    bx, cs:InHead
  697.         mov    cs:[bx], al
  698.         inc    bx
  699.         cmp    bx, offset InpBufEnd
  700.         jb    NoInpWrap
  701.         mov    bx, offset InpBuf
  702. NoInpWrap:    cmp    bx, cs:InTail
  703.         je    TryAnother
  704.         mov    cs:InHead, bx
  705.         jmp    TryAnother
  706. ;
  707. ;
  708. ; Handle outgoing data here (This is also a critical region):
  709. ;
  710. WriteCom1:      mov    bx, cs:OutTail
  711.         cmp    bx, cs:OutHead
  712.         jne    OutputChar
  713. ;
  714. ; If head and tail are equal, simply set the TestBuffer variable to zero
  715. ; and quit.  If they are not equal, then there is data in the buffer and
  716. ; we should output the next character.
  717. ;
  718.         mov    cs:TestBuffer, 0
  719.         jmp    TryAnother
  720. ;
  721. ; The buffer pointers are not equal, output the next character down here.
  722. ;
  723. OutputChar:     mov    al, cs:[bx]
  724.         mov    dx, Com1Port
  725.         out    dx, al
  726.         inc    bx
  727.         cmp    bx, offset OutBufEnd
  728.         jb      NoOutWrap
  729.         mov    bx, offset OutBuf
  730. NoOutWrap:    mov    cs:OutTail, bx
  731.         jmp    TryAnother
  732. Com1IntISR    endp
  733. ;
  734. ;
  735. ;----------------------------------------------------------------------------
  736. ;
  737. ; Routines to read/write characters in serial buffers.
  738. ;
  739.         public    sl_InCom1
  740. sl_InCom1    proc    far
  741.         pushf                ;Save interrupt flag
  742.         push    bx
  743.         sti                ;Make sure interrupts are on.
  744. TstInLoop:    mov    bx, cs:InTail
  745.         cmp    bx, cs:InHead
  746.         je    TstInLoop
  747.         mov    al, cs:[bx]        ;Get next char.
  748.         cli                ;Turn off ints while adjusting
  749.         inc    bx            ; buffer pointers.
  750.         cmp    bx, offset InpBufEnd
  751.         jne    NoWrap2
  752.         mov    bx, offset InpBuf
  753. NoWrap2:    mov    cs:InTail, bx
  754.         pop    bx
  755.         popf                ;Restore interrupt flag.
  756.         ret
  757. sl_InCom1    endp
  758. ;
  759. ;
  760.         public    sl_OutCom1
  761. sl_OutCom1    proc    far
  762.         pushf
  763.         cli                ;No interrupts now!
  764.         cmp    cs:TestBuffer, 0    ;Write directly to serial chip?
  765.         jnz    BufferItUp
  766.         call    far ptr sl_WriteCom1    ;Output to port
  767.         mov    cs:TestBuffer, 1    ;Must buffer up next char.
  768.         popf
  769.         ret
  770. ;
  771. BufferItUp:    push    bx
  772.         mov    bx, cs:OutHead
  773.         mov    cs:[bx], al
  774.         inc    bx
  775.         cmp    bx, offset OutBufEnd
  776.         jne    NoWrap3
  777.         mov    bx, offset OutBuf
  778. NoWrap3:    cmp    bx, cs:OutTail
  779.         je    NoSetTail
  780.         mov    cs:OutTail, bx
  781. NoSetTail:    pop    bx
  782.         popf
  783.         ret
  784. sl_OutCom1    endp
  785. ;
  786. stdlib        ends
  787.         end
  788.