home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 September / Simtel20_Sept92.cdr / msdos / turbo_c / com_int.arc / INT3.ASM < prev    next >
Assembly Source File  |  1987-09-05  |  10KB  |  330 lines

  1. ;----------------------------------------------------------------------------
  2. ;    INT3.ASM        August 23,1987
  3. ;
  4. ; Data input/output via RS-232/2 (COM 2)
  5. ;      * initialization
  6. ;      * ISR
  7. ;----------------------------------------------------------------------------
  8. int3_TEXT    SEGMENT byte public 'CODE'
  9. int3_TEXT    ENDS
  10. _DATA        SEGMENT byte public 'DATA'
  11. _DATA        ENDS
  12. _BSS        SEGMENT byte public 'BSS'
  13. _BSS        ENDS
  14. ;
  15. DGROUP        GROUP    _DATA,_BSS
  16.  
  17.             ASSUME cs:int3_TEXT, ds:DGROUP, es:DGROUP
  18. ;
  19. ;----------------------------------------------------------------------------
  20. ;
  21. _DATA        SEGMENT byte public 'DATA'
  22. old_int3_CS    dw    0        ;old interrupt 4 CS
  23. old_int3_IP    dw    0        ;old interrupt 4 IP
  24. _DATA        ENDS
  25. ;
  26. ;----------------------------------------------------------------------------
  27. ;    PROGRAM EXTERNALS
  28. ;
  29.     extrn    _com2_input_queue:byte
  30.     extrn    _com2_in_queue_ptr:word
  31.  
  32.     extrn    _com2_rs232_error:word
  33.     extrn    _com2_port_status:word
  34.     extrn     _com2_interrupt_status:word
  35.  
  36.     extrn    _com2_out_queue_ptr:word
  37.     extrn    _com2_out_queue_out:word
  38.     extrn    _com2_output_queue:byte
  39. ;
  40. ;----------------------------------------------------------------------------
  41. ;    PROGRAM EQUATES
  42. ;
  43. BASE_ADR    EQU    02F8h        ;COM 2 port base address
  44. BUFSIZ        EQU    2048        ;size of data queues
  45. ;
  46. ; Don't enable the xmit interrupt unless there is something to xmit
  47. ;
  48. ;        1 ='s enable interrupt
  49. ;        0 ='s disable interrupt
  50. ;
  51. ;   Bits  7 to 4      ------    unused
  52. ;              3      ------    change in modem status register
  53. ;              2      ------    data reception error
  54. ;              1      ------    transmit register empty
  55. ;              0      ------    data received
  56. ;
  57. INT_CODE    EQU    1101B        ;receive, error and modem change
  58.                     ;interrupts are enabled here
  59.  
  60. RTS_ON        EQU    0bh        ;interrupts on, RTS on, DTR on
  61. RTS_OFF        EQU    09h        ;interrupts on, RTS off, DTR on
  62. ;
  63. ;----------------------------------------------------------------------------
  64. ;    Initialize the 8250 UART depending on parameter given as argument
  65. ;    and enable communication interrupts via INT 4 (primary com. port)
  66. ;
  67. ;   BIT    7   6   5          4    3         2                  1     0
  68. ;        { baud rate }      { parity } { stop bits }         { word length }
  69. ;    110 = 0   0   0   NONE = 0    0    1 =  0       7 bits =   1      0
  70. ;    150 = 0   0   1    or    1    0    2 =  1       8 bits =   1      1
  71. ;    300 = 0   1   0    ODD = 0    1
  72. ;    600 = 0   1   1   EVEN = 1    1
  73. ;   1200 = 1   0   0
  74. ;   2400 = 1   0   1
  75. ;   4800 = 1   1   0
  76. ;   9600 = 1   1   1
  77. ;
  78. ;----------------------------------------------------------------------------
  79. ;
  80. int3_TEXT    SEGMENT byte public 'CODE'
  81. ;
  82.     PUBLIC  _com2_set_interrupt
  83. _com2_set_interrupt    PROC    FAR
  84.     push    bp        ;save the registers used
  85.     mov    bp,sp        ;make a copy for variable access
  86.  
  87.     push    ax        ;save all registers used
  88.     push    bx
  89.     push    dx
  90.     push    ds
  91.     push    es
  92.  
  93.     mov    ah,35h        ;get vector function
  94.     mov    al,0bh        ;want INT 3 CS and IP vector
  95.     int    21h        ;execute DOS function call
  96.     mov    old_int3_CS,es    ;ES contains the CS for INT 3
  97.     mov    old_int3_IP,bx    ;BX contains the IP for INT 3
  98.  
  99.     mov    dx,offset INT3    ;point DS:DX to COM routine
  100.     mov    ax,seg    INT3    ;segment
  101.     mov    ds,ax        ;point DS
  102.     mov    al,0bh        ;INT 3 vector
  103.     mov    ah,25h        ;function to change vector
  104.     int    21h        ;execute DOS function call
  105.  
  106.     mov    ax,[bp+6]    ;grab baud rate and parms
  107.     mov    dx,1        ;0 = COM 1    1 = COM 2
  108.     int    14h        ;initialize RS232 port to given parameters
  109.                 ;(warning: COM interrupts are left disabled)
  110.  
  111.     mov    dx,BASE_ADR+4    ;modem control register (2fc)
  112.     mov    al,RTS_ON     ;INT's on(bit3), RTS on(bit1), DTR on(bit0)
  113.     out    dx,al
  114.  
  115.     mov    dx,BASE_ADR+1    ;interrupt enable register (2f9)
  116.     mov    al,INT_CODE    ;which interrupts to enable
  117.     out    dx,al        ;enable interrupts on 8250
  118.  
  119.     mov    dx,BASE_ADR    ;point at recieve buffer register(2f8)
  120.     in    al,dx        ;read any trash in buffer
  121.  
  122.     mov    dx,BASE_ADR+5    ;line status register(2fd)
  123.     in    al,dx        ;read any trash in status register
  124.  
  125.     mov    dx,BASE_ADR+6    ;modem status register (2fe)
  126.     in    al,dx        ;read any trash in status register
  127.  
  128.     in    al,21h        ;find out which interrupts are currently on
  129.     and    al,0f7h        ;enable bit 3 (INT 3 ='s SECONDARY COM. PORT)
  130.     out    21h,al        ;rewrite new interrupt flags
  131.  
  132.     pop    es        ;restore registers used
  133.     pop    ds
  134.     pop    dx
  135.     pop    bx
  136.     pop    ax
  137.     pop    bp
  138.     ret
  139. _com2_set_interrupt    ENDP
  140. ;
  141. ;----------------------------------------------------------------------------
  142. ;
  143. ;  This routine restores the interrupt vector which was modified by the
  144. ;    _set_interrupt routine so don't call this routine without 1st
  145. ;     calling the other routine.
  146. ;
  147.     PUBLIC  _com2_restore_interrupt
  148. _com2_restore_interrupt    PROC    FAR
  149.     push    ax        ;save all registers used
  150.     push    dx
  151.     push    ds
  152.  
  153.     mov    dx,old_int3_IP    ;point DS:DX to COM routine
  154.     mov    ax,old_int3_CS    ;segment
  155.     mov    ds,ax        ;point DS
  156.     mov    al,0bh        ;INT 3 vector
  157.     mov    ah,25h        ;function to change vector
  158.     int    21h        ;execute DOS function call
  159.  
  160.     in    al,21h        ;read current interrupt status
  161.     or    al,08h        ;disable bit 3 (INT 3)
  162.     out    21h,al        ;rewrite new interrupt status
  163.  
  164.     pop    ds        ;restore all registers used
  165.     pop    dx
  166.     pop    ax
  167.     ret
  168. _com2_restore_interrupt    ENDP
  169. ;
  170. ;----------------------------------------------------------------------------
  171. ; This is the interrupt routine that is executed with every
  172. ;   INT 3.
  173. ;
  174. ;  Options currenty implemented are:
  175. ;    1. receive interrupt
  176. ;    2. data reception error interrupt
  177. ;    3. transmit holding register empty interrupt
  178. ;    4. change in modem status register
  179. ;
  180. ;    Receive interrupt places characters in _input_queue at _in_queue_ptr
  181. ;        bytes into the queue.
  182. ;
  183. ;    Data reception error places the error int _rs232_error.
  184. ;
  185. ;    Transmit interrupt xmits characters in _output_queue at _out_queue_ptr
  186. ;        bytes into the queue.
  187. ;
  188. ;    Modem status register change stores its status in port_status
  189. ;
  190. ;----------------------------------------------------------------------------
  191. ;
  192.     public    INT3
  193.  
  194. INT3    PROC    FAR
  195.     push    ds        ;always save anything you use in an INT routine
  196.     push    di
  197.     push    dx
  198.     push    cx
  199.     push    ax
  200.  
  201.     mov    ax, SEG _DATA        ;make sure your pointing to the correct
  202.     mov    ds,ax            ; segment otherwise it's lockup city.
  203. ;----------------------------------------------------------------------------
  204. pending_interrupt:
  205.     mov    dx,BASE_ADR+2        ;interrupt ident. register (2fa)
  206.     in    al,dx            ;read whose requesting service
  207.  
  208.     mov    ah,00h            ;zero high byte
  209.     mov    _com2_interrupt_status,ax;store status
  210.  
  211.     cmp    al,00h            ;modem interrupt?
  212.     je    status_int        ;YES! jump
  213.  
  214.     cmp    al,02h            ;is it a transmit buf empty interrupt?
  215.     je    transmit_int        ;YES! jump
  216.  
  217.     cmp    al,04h            ;is it a recieve interrupt?
  218.     je    receive_int        ;YES! jump
  219.  
  220.     cmp    al,06h            ;is it reception error interrupt?
  221.     je    reception_error        ;YES! jump
  222.  
  223.     jmp    leave_interrupt        ;no more left.... so leave
  224. ;
  225. ;----------------------------------------------------------------------------
  226. ;    Modem status register change
  227. ;
  228. status_int:
  229.     mov    dx,BASE_ADR+6        ;modem status register (2fe)
  230.     in    al,dx
  231.  
  232.     mov    ah,00h            ;zero high byte
  233.     mov    _com2_port_status,ax    ;store status
  234.     jmp    leave_interrupt        ;go see if any interrupts pending
  235. ;
  236. ;----------------------------------------------------------------------------
  237. ; Receive buffer routine
  238. ;
  239. receive_int:
  240.     mov    dx,BASE_ADR        ;COM 1 recieve buffer (2f8)
  241.     in    al,dx            ;read the character in
  242.  
  243.     mov    dl,al            ;save character in another register for now
  244.  
  245.     mov    di,[_com2_in_queue_ptr]    ;grab input pointer
  246.  
  247.     mov    _com2_input_queue[di],dl;and place the char in the queue
  248.  
  249.     cmp    di,BUFSIZ        ;check for queue wrap
  250.     jge    reset_queue        ;reset if past end or equal
  251.  
  252.     inc    word ptr [_com2_in_queue_ptr] ;bump input pointer
  253.     jmp    leave_interrupt
  254. reset_queue:
  255.     mov    word ptr [_com2_in_queue_ptr],0 ;reset pointer to beginning
  256. ;----------------------------------------------------------------------------
  257. leave_interrupt:
  258.     mov    dx,BASE_ADR+2        ;interrupt ident. register (2fa)
  259.     in    al,dx            ;read whose request service
  260.  
  261.     and    al,01h            ;is there a pending interrupt?
  262.     jz    pending_interrupt    ;YES! jump
  263. ack_interrupt:
  264.     mov    al,20h            ;EOI code
  265.     out    20h,al            ;acknowledge END OF INTERRUPT
  266.  
  267.     pop    ax            ;put em back so the machine doesn't
  268.     pop    cx            ; DIE!
  269.     pop    dx
  270.     pop    di
  271.     pop    ds
  272.     iret                ;interrupt return
  273. ;
  274. ;----------------------------------------------------------------------------
  275. ; Reception error routine
  276. ;
  277. reception_error:
  278.     mov    dx,BASE_ADR+5        ;line status register (2fd)
  279.     in    al,dx            ; read which error occured
  280.  
  281.     mov    ah,00h            ;zero high byte
  282.     mov    _com2_rs232_error,ax    ;save error flags for someone else
  283.  
  284.     jmp    leave_interrupt        ;go look for pending interrupts
  285. ;
  286. ;----------------------------------------------------------------------------
  287. ; Transmit buffer empty routine
  288. ;
  289. transmit_int:
  290.  
  291.     mov    ax,[_com2_out_queue_ptr];grab input pointer
  292.     mov    di,[_com2_out_queue_out];grab output pointer
  293.  
  294.     cmp    ax,di            ;are the pointers equal?
  295.     jz    disable_xmit_int    ;YES! then disable interrupts
  296.  
  297.     mov    dx,BASE_ADR+6        ;point at modem status reg. (2fe)
  298.     mov    cx,200            ;give it 200 trys for CTS signal
  299.  
  300. wait_for_CTS:
  301.     in    al,dx            ;read port status
  302.     and    al,10h            ;test CTS line
  303.     loopnz    wait_for_CTS        ;
  304.  
  305.  
  306.     mov    al,_com2_output_queue[di];grab next char to output
  307.     mov    dx,BASE_ADR        ;output buffer port (2f8)
  308.     out    dx,al            ;send character out
  309.  
  310.     cmp    di,BUFSIZ        ;check for queue wrap
  311.     jge    out_queue_reset        ;reset if past end or equal
  312.  
  313.     inc    word ptr [_com2_out_queue_out] ;bump output pointer
  314.     jmp    leave_interrupt        ;and check for pending interrupts
  315. out_queue_reset:
  316.     mov    word ptr [_com2_out_queue_out],0 ;reset pointer to beginning
  317.     jmp    leave_interrupt        ;and check for pending interrupts
  318.  
  319. disable_xmit_int:
  320.     mov    dx,BASE_ADR+1        ;interrupt enable register (2f9)
  321.     in    al,dx            ;read current interrupt status
  322.     and    al,11111101B        ;turn off xmit interrupts (fdh)
  323.     out    dx,al            ;disable xmit interrupts on 8250
  324.     jmp    leave_interrupt        ; and check for pending interrupts
  325.  
  326. INT3    ENDP
  327. ;----------------------------------------------------------------------------
  328. int3_TEXT    ENDS
  329.     END
  330.