Subversion Repositories Kolibri OS

Rev

Rev 5079 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. format MS COFF
  9.  
  10. DEBUG           equ 1
  11.  
  12. include 'proc32.inc'
  13. include 'imports.inc'
  14.  
  15.  
  16.  
  17. API_VERSION       equ 0
  18. UART_VERSION      equ API_VERSION
  19.  
  20. PG_SW             equ 0x003
  21. page_tabs         equ 0xFDC00000     ;hack
  22.  
  23. OS_BASE           equ 0x80000000
  24. SLOT_BASE         equ (OS_BASE+0x0080000)
  25. TASK_COUNT        equ (OS_BASE+0x0003004)
  26. CURRENT_TASK      equ (OS_BASE+0x0003000)
  27.  
  28.  
  29. struc APPOBJ           ;common object header
  30. {
  31.    .magic       dd ?   ;
  32.    .destroy     dd ?   ;internal destructor
  33.    .fd          dd ?   ;next object in list
  34.    .bk          dd ?   ;prev object in list
  35.    .pid         dd ?   ;owner id
  36. };
  37.  
  38. virtual at 0
  39.   APPOBJ APPOBJ
  40. end virtual
  41.  
  42. struc IOCTL
  43. {  .handle      dd ?
  44.    .io_code     dd ?
  45.    .input       dd ?
  46.    .inp_size    dd ?
  47.    .output      dd ?
  48.    .out_size    dd ?
  49. }
  50.  
  51. virtual at 0
  52.   IOCTL IOCTL
  53. end virtual
  54.  
  55. DEBUG            equ   1
  56.  
  57. DRV_ENTRY        equ   1
  58. DRV_EXIT         equ  -1
  59.  
  60. THR_REG          equ  0;  x3f8   ;transtitter/reciever
  61. IER_REG          equ  1;  x3f9   ;interrupt enable
  62. IIR_REG          equ  2;  x3fA   ;interrupt info
  63. LCR_REG          equ  3;  x3FB   ;line control
  64. MCR_REG          equ  4;  x3FC   ;modem control
  65. LSR_REG          equ  5;  x3FD   ;line status
  66. MSR_REG          equ  6;  x3FE   ;modem status
  67.  
  68. LCR_5BIT         equ  0x00
  69. LCR_6BIT         equ  0x01
  70. LCR_7BIT         equ  0x02
  71. LCR_8BIT         equ  0x03
  72. LCR_STOP_1       equ  0x00
  73. LCR_STOP_2       equ  0x04
  74. LCR_PARITY       equ  0x08
  75. LCR_EVEN         equ  0x10
  76. LCR_STICK        equ  0x20
  77. LCR_BREAK        equ  0x40
  78. LCR_DLAB         equ  0x80
  79.  
  80. LSR_DR           equ  0x01     ;data ready
  81. LSR_OE           equ  0x02     ;overrun error
  82. LSR_PE           equ  0x04     ;parity error
  83. LSR_FE           equ  0x08     ;framing error
  84. LSR_BI           equ  0x10     ;break interrupt
  85. LSR_THRE         equ  0x20     ;transmitter holding empty
  86. LSR_TEMT         equ  0x40     ;transmitter empty
  87. LSR_FER          equ  0x80     ;FIFO error
  88.  
  89. FCR_EFIFO        equ  0x01     ;enable FIFO
  90. FCR_CRB          equ  0x02     ;clear reciever FIFO
  91. FCR_CXMIT        equ  0x04     ;clear transmitter FIFO
  92. FCR_RDY          equ  0x08     ;set RXRDY and TXRDY pins
  93. FCR_FIFO_1       equ  0x00     ;1  byte trigger
  94. FCR_FIFO_4       equ  0x40     ;4  bytes trigger
  95. FCR_FIFO_8       equ  0x80     ;8  bytes trigger
  96. FCR_FIFO_14      equ  0xC0     ;14 bytes trigger
  97.  
  98. IIR_INTR         equ  0x01     ;1= no interrupts
  99.  
  100. IER_RDAI         equ  0x01     ;reciever data interrupt
  101. IER_THRI         equ  0x02     ;transmitter empty interrupt
  102. IER_LSI          equ  0x04     ;line status interrupt
  103. IER_MSI          equ  0x08     ;modem status interrupt
  104.  
  105. MCR_DTR          equ  0x01     ;0-> DTR=1, 1-> DTR=0
  106. MCR_RTS          equ  0x02     ;0-> RTS=1, 1-> RTS=0
  107. MCR_OUT_1        equ  0x04     ;0-> OUT1=1, 1-> OUT1=0
  108. MCR_OUT_2        equ  0x08     ;0-> OUT2=1, 1-> OUT2=0;  enable intr
  109. MCR_LOOP         equ  0x10     ;lopback mode
  110.  
  111. MSR_DCTS         equ  0x01     ;delta clear to send
  112. MSR_DDSR         equ  0x02     ;delta data set redy
  113. MSR_TERI         equ  0x04     ;trailinh edge of ring
  114. MSR_DDCD         equ  0x08     ;delta carrier detect
  115.  
  116.  
  117. RATE_50          equ  0
  118. RATE_75          equ  1
  119. RATE_110         equ  2
  120. RATE_134         equ  3
  121. RATE_150         equ  4
  122. RATE_300         equ  5
  123. RATE_600         equ  6
  124. RATE_1200        equ  7
  125. RATE_1800        equ  8
  126. RATE_2000        equ  9
  127. RATE_2400        equ 10
  128. RATE_3600        equ 11
  129. RATE_4800        equ 12
  130. RATE_7200        equ 13
  131. RATE_9600        equ 14
  132. RATE_19200       equ 15
  133. RATE_38400       equ 16
  134. RATE_57600       equ 17
  135. RATE_115200      equ 18
  136.  
  137. COM_1            equ  1
  138. COM_2            equ  2
  139. COM_3            equ  3
  140. COM_4            equ  4
  141. COM_MAX          equ  2    ;only two port supported
  142.  
  143. COM_1_BASE       equ 0x3F8
  144. COM_2_BASE       equ 0x2F8
  145.  
  146. COM_1_IRQ        equ  4
  147. COM_2_IRQ        equ  3
  148.  
  149. UART_CLOSED      equ  0
  150. UART_TRANSMIT    equ  1
  151. UART_STOP        equ  2
  152.  
  153. struc UART
  154. {
  155.    .lock         dd ?
  156.    .base         dd ?
  157.    .lcr_reg      dd ?
  158.    .mcr_reg      dd ?
  159.    .rate         dd ?
  160.    .mode         dd ?
  161.    .state        dd ?
  162.  
  163.    .rcvr_buff    dd ?
  164.    .rcvr_rp      dd ?
  165.    .rcvr_wp      dd ?
  166.    .rcvr_count   dd ?
  167.    .rcvr_top     dd ?
  168.  
  169.    .xmit_buff    dd ?
  170.    .xmit_rp      dd ?
  171.    .xmit_wp      dd ?
  172.    .xmit_count   dd ?
  173.    .xmit_free    dd ?
  174.    .xmit_top     dd ?
  175. }
  176. virtual at 0
  177.   UART UART
  178. end virtual
  179.  
  180. UART_SIZE     equ 18*4
  181.  
  182. struc CONNECTION
  183. {
  184.    .magic       dd ?   ;'CNCT'
  185.    .destroy     dd ?   ;internal destructor
  186.    .fd          dd ?   ;next object in list
  187.    .bk          dd ?   ;prev object in list
  188.    .pid         dd ?   ;owner id
  189.  
  190.    .id          dd ?   ;reserved
  191.    .uart        dd ?   ;uart pointer
  192. }
  193.  
  194. virtual at 0
  195.   CONNECTION CONNECTION
  196. end virtual
  197.  
  198. CONNECTION_SIZE equ 7*4
  199.  
  200. public START
  201. public service_proc
  202. public version
  203.  
  204. section '.flat' code readable align 16
  205.  
  206. proc START stdcall, state:dword
  207.  
  208.         cmp     [state], 1
  209.         jne     .stop
  210.  
  211.         mov     eax, UART_SIZE
  212.         call    Kmalloc
  213.         test    eax, eax
  214.         jz      .fail
  215.  
  216.         mov     [com1], eax
  217.         mov     edi, eax
  218.         mov     ecx, UART_SIZE/4
  219.         xor     eax, eax
  220.         cld
  221.         rep stosd
  222.  
  223.         mov     eax, [com1]
  224.         mov     [eax+UART.base], COM_1_BASE
  225.  
  226.         stdcall AllocKernelSpace, 32768
  227.  
  228.         mov     edi, [com1]
  229.         mov     edx, eax
  230.  
  231.         mov     [edi+UART.rcvr_buff], eax
  232.         add     eax, 8192
  233.         mov     [edi+UART.rcvr_top], eax
  234.         add     eax, 8192
  235.         mov     [edi+UART.xmit_buff], eax
  236.         add     eax, 8192
  237.         mov     [edi+UART.xmit_top], eax
  238.  
  239.         call    AllocPage
  240.         test    eax, eax
  241.         jz      .fail
  242.  
  243.         shr     edx, 12
  244.         or      eax, PG_SW
  245.         mov     [page_tabs+edx*4], eax
  246.         mov     [page_tabs+edx*4+8], eax
  247.  
  248.         call    AllocPage
  249.         test    eax, eax
  250.         jz      .fail
  251.  
  252.         or      eax, PG_SW
  253.         mov     [page_tabs+edx*4+4], eax
  254.         mov     [page_tabs+edx*4+12], eax
  255.  
  256.         call    AllocPage
  257.         test    eax, eax
  258.         jz      .fail
  259.  
  260.         or      eax, PG_SW
  261.         mov     [page_tabs+edx*4+16], eax
  262.         mov     [page_tabs+edx*4+24], eax
  263.  
  264.         call    AllocPage
  265.         test    eax, eax
  266.         jz      .fail
  267.  
  268.         or      eax, PG_SW
  269.         mov     [page_tabs+edx*4+20], eax
  270.         mov     [page_tabs+edx*4+28], eax
  271.  
  272.         mov     eax, [edi+UART.rcvr_buff]
  273.         invlpg  [eax]
  274.         invlpg  [eax+0x1000]
  275.         invlpg  [eax+0x2000]
  276.         invlpg  [eax+0x3000]
  277.         invlpg  [eax+0x4000]
  278.         invlpg  [eax+0x5000]
  279.         invlpg  [eax+0x6000]
  280.         invlpg  [eax+0x7000]
  281.  
  282.         mov     eax, edi
  283.         call    uart_reset.internal   ;eax= uart
  284.  
  285.         stdcall AttachIntHandler, COM_1_IRQ, com_1_isr, dword 0
  286.         stdcall RegService, sz_uart_srv, service_proc
  287.         ret
  288. .fail:
  289. .stop:
  290.         xor     eax, eax
  291.         ret
  292. endp
  293.  
  294.  
  295. handle     equ  IOCTL.handle
  296. io_code    equ  IOCTL.io_code
  297. input      equ  IOCTL.input
  298. inp_size   equ  IOCTL.inp_size
  299. output     equ  IOCTL.output
  300. out_size   equ  IOCTL.out_size
  301.  
  302. SRV_GETVERSION  equ 0
  303. PORT_OPEN       equ 1
  304. PORT_CLOSE      equ 2
  305. PORT_RESET      equ 3
  306. PORT_SETMODE    equ 4
  307. PORT_GETMODE    equ 5
  308. PORT_SETMCR     equ 6
  309. PORT_GETMCR     equ 7
  310. PORT_READ       equ 8
  311. PORT_WRITE      equ 9
  312.  
  313. align 4
  314. proc service_proc stdcall, ioctl:dword
  315.  
  316.         mov     ebx, [ioctl]
  317.         mov     eax, [ebx+io_code]
  318.         cmp     eax, PORT_WRITE
  319.         ja      .fail
  320.  
  321.         cmp     eax, SRV_GETVERSION
  322.         jne     @F
  323.  
  324.         mov     eax, [ebx+output]
  325.         cmp     [ebx+out_size], 4
  326.         jne     .fail
  327.         mov     [eax], dword UART_VERSION
  328.         xor     eax, eax
  329.         ret
  330. @@:
  331.         cmp     eax, PORT_OPEN
  332.         jne     @F
  333.  
  334.         cmp     [ebx+out_size], 4
  335.         jne     .fail
  336.  
  337.         mov     ebx, [ebx+input]
  338.         mov     eax, [ebx]
  339.         call    uart_open
  340.         mov     ebx, [ioctl]
  341.         mov     ebx, [ebx+output]
  342.         mov     [ebx], ecx
  343.         ret
  344. @@:
  345.         mov     esi, [ebx+input]    ;input buffer
  346.         mov     edi, [ebx+output]
  347.         call    [uart_func+eax*4]
  348.         ret
  349. .fail:
  350.         or      eax, -1
  351.         ret
  352.  
  353. endp
  354.  
  355. restore   handle
  356. restore   io_code
  357. restore   input
  358. restore   inp_size
  359. restore   output
  360. restore   out_size
  361.  
  362.  
  363. ; param
  364. ;  esi=  input buffer
  365. ;        +0 connection
  366. ;
  367. ; retval
  368. ;  eax= error code
  369.  
  370. align 4
  371. uart_reset:
  372.         mov     eax, [esi]
  373.         cmp     [eax+APPOBJ.magic], 'CNCT'
  374.         jne     .fail
  375.  
  376.         cmp     [eax+APPOBJ.destroy], uart_close.destroy
  377.         jne     .fail
  378.  
  379.         mov     eax, [eax+CONNECTION.uart]
  380.         test    eax, eax
  381.         jz      .fail
  382.  
  383. ; set mode 2400 bod 8-bit
  384. ; disable DTR & RTS
  385. ; clear FIFO
  386. ; clear pending interrupts
  387. ;
  388. ; param
  389. ;  eax= uart
  390.  
  391. align 4
  392. .internal:
  393.         mov     esi, eax
  394.         mov     [eax+UART.state], UART_CLOSED
  395.         mov     edx, [eax+UART.base]
  396.         add     edx, MCR_REG
  397.         xor     eax, eax
  398.         out     dx, al       ;clear DTR & RTS
  399.  
  400.         mov     eax, esi
  401.         mov     ebx, RATE_2400
  402.         mov     ecx, LCR_8BIT+LCR_STOP_1
  403.         call    uart_set_mode.internal
  404.  
  405.         mov     edx, [esi+UART.base]
  406.         add     edx, IIR_REG
  407.         mov     eax, FCR_EFIFO+FCR_CRB+FCR_CXMIT+FCR_FIFO_14
  408.         out     dx, al
  409. .clear_RB:
  410.         mov     edx, [esi+UART.base]
  411.         add     edx, LSR_REG
  412.         in      al, dx
  413.         test    eax, LSR_DR
  414.         jz      @F
  415.  
  416.         mov     edx, [esi+UART.base]
  417.         in      al, dx
  418.         jmp     .clear_RB
  419. @@:
  420.         mov     edx, [esi+UART.base]
  421.         add     edx, IER_REG
  422.         mov     eax, IER_RDAI+IER_THRI+IER_LSI
  423.         out     dx, al
  424. .clear_IIR:
  425.         mov     edx, [esi+UART.base]
  426.         add     edx, IIR_REG
  427.         in      al, dx
  428.         test    al, IIR_INTR
  429.         jnz     .done
  430.  
  431.         shr     eax, 1
  432.         and     eax, 3
  433.         jnz     @F
  434.  
  435.         mov     edx, [esi+UART.base]
  436.         add     edx, MSR_REG
  437.         in      al, dx
  438.         jmp     .clear_IIR
  439. @@:
  440.         cmp     eax, 1
  441.         je      .clear_IIR
  442.  
  443.         cmp     eax, 2
  444.         jne     @F
  445.  
  446.         mov     edx, [esi+UART.base]
  447.         in      al, dx
  448.         jmp     .clear_IIR
  449. @@:
  450.         mov     edx, [esi+UART.base]
  451.         add     edx, LSR_REG
  452.         in      al, dx
  453.         jmp     .clear_IIR
  454. .done:
  455.         mov     edi, [esi+UART.rcvr_buff]
  456.         mov     ecx, 8192/4
  457.         xor     eax, eax
  458.  
  459.         mov     [esi+UART.rcvr_rp], edi
  460.         mov     [esi+UART.rcvr_wp], edi
  461.         mov     [esi+UART.rcvr_count], eax
  462.  
  463.         cld
  464.         rep stosd
  465.  
  466.         mov     edi, [esi+UART.xmit_buff]
  467.         mov     ecx, 8192/4
  468.  
  469.         mov     [esi+UART.xmit_rp], edi
  470.         mov     [esi+UART.xmit_wp], edi
  471.         mov     [esi+UART.xmit_count], eax
  472.         mov     [esi+UART.xmit_free], 8192
  473.  
  474.         rep stosd
  475.         ret                  ;eax= 0
  476. .fail:
  477.         or      eax, -1
  478.         ret
  479.  
  480. ; param
  481. ;  esi=  input buffer
  482. ;        +0 connection
  483. ;        +4 rate
  484. ;        +8 mode
  485. ;
  486. ; retval
  487. ;  eax= error code
  488.  
  489. align 4
  490. uart_set_mode:
  491.         mov     eax, [esi]
  492.         cmp     [eax+APPOBJ.magic], 'CNCT'
  493.         jne     .fail
  494.  
  495.         cmp     [eax+APPOBJ.destroy], uart_close.destroy
  496.         jne     .fail
  497.  
  498.         mov     eax, [eax+CONNECTION.uart]
  499.         test    eax, eax
  500.         jz      .fail
  501.  
  502.         mov     ebx, [esi+4]
  503.         mov     ecx, [esi+8]
  504.  
  505. ; param
  506. ;  eax= uart
  507. ;  ebx= baud rate
  508. ;  ecx= mode
  509.  
  510. align 4
  511. .internal:
  512.         cmp     ebx, RATE_115200
  513.         ja      .fail
  514.  
  515.         cmp     ecx, LCR_BREAK
  516.         jae     .fail
  517.  
  518.         mov     [eax+UART.rate], ebx
  519.         mov     [eax+UART.mode], ecx
  520.  
  521.         mov     esi, eax
  522.         mov     bx, [divisor+ebx*2]
  523.  
  524.         mov     edx, [esi+UART.base]
  525.         push    edx
  526.         add     edx, LCR_REG
  527.         in      al, dx
  528.         or      al, 0x80
  529.         out     dx, al
  530.  
  531.         pop     edx
  532.         mov     al, bl
  533.         out     dx, al
  534.  
  535.         inc     dx
  536.         mov     al, bh
  537.         out     dx, al
  538.  
  539.         add     edx, LCR_REG-1
  540.         mov     eax, ecx
  541.         out     dx, al
  542.         xor     eax, eax
  543.         ret
  544. .fail:
  545.         or      eax, -1
  546.         ret
  547.  
  548. ; param
  549. ;  esi=  input buffer
  550. ;        +0 connection
  551. ;        +4 modem control reg valie
  552. ;
  553. ; retval
  554. ;  eax= error code
  555.  
  556. align 4
  557. uart_set_mcr:
  558.  
  559.         mov     eax, [esi]
  560.         cmp     [eax+APPOBJ.magic], 'CNCT'
  561.         jne     .fail
  562.  
  563.         cmp     [eax+APPOBJ.destroy], uart_close.destroy
  564.         jne     .fail
  565.  
  566.         mov     eax, [eax+CONNECTION.uart]
  567.         test    eax, eax
  568.         jz      .fail
  569.  
  570.         mov     ebx, [esi+4]
  571.  
  572.         mov     [eax+UART.mcr_reg], ebx
  573.         mov     edx, [eax+UART.base]
  574.         add     edx, MCR_REG
  575.         mov     al, bl
  576.         out     dx, al
  577.         xor     eax, eax
  578.         ret
  579. .fail:
  580.         or      eax, -1
  581.         ret
  582.  
  583. ; param
  584. ;  eax= port
  585. ;
  586. ; retval
  587. ;  ecx= connection
  588. ;  eax= error code
  589.  
  590. align 4
  591. uart_open:
  592.         dec     eax
  593.         cmp     eax, COM_MAX
  594.         jae     .fail
  595.  
  596.         mov     esi, [com1+eax*4]            ;uart
  597.         push    esi
  598. .do_wait:
  599.         cmp     dword [esi+UART.lock], 0
  600.         je      .get_lock
  601.       ;     call change_task
  602.         jmp     .do_wait
  603. .get_lock:
  604.         mov     eax, 1
  605.         xchg    eax, [esi+UART.lock]
  606.         test    eax, eax
  607.         jnz     .do_wait
  608.  
  609.         mov     eax, esi                 ;uart
  610.         call    uart_reset.internal
  611.  
  612.         mov     ebx, [CURRENT_TASK]
  613.         shl     ebx, 5
  614.         mov     ebx, [CURRENT_TASK+ebx+4]
  615.         mov     eax, CONNECTION_SIZE
  616.         call    CreateObject
  617.         pop     esi                      ;uart
  618.         test    eax, eax
  619.         jz      .fail
  620.  
  621.         mov     [eax+APPOBJ.magic], 'CNCT'
  622.         mov     [eax+APPOBJ.destroy], uart_close.destroy
  623.         mov     [eax+CONNECTION.uart], esi
  624.         mov     ecx, eax
  625.         xor     eax, eax
  626.         ret
  627. .fail:
  628.         or      eax, -1
  629.         ret
  630. restore .uart
  631.  
  632. ; param
  633. ;  esi= input buffer
  634.  
  635. align 4
  636. uart_close:
  637.         mov     eax, [esi]
  638.         cmp     [eax+APPOBJ.magic], 'CNCT'
  639.         jne     .fail
  640.  
  641.         cmp     [eax+APPOBJ.destroy], uart_close.destroy
  642.         jne     .fail
  643. .destroy:
  644.         push    [eax+CONNECTION.uart]
  645.         call    DestroyObject   ;eax= object
  646.         pop     eax                     ;eax= uart
  647.         test    eax, eax
  648.         jz      .fail
  649.  
  650.         mov     [eax+UART.state], UART_CLOSED
  651.         mov     [eax+UART.lock], 0;release port
  652.         xor     eax, eax
  653.         ret
  654. .fail:
  655.         or      eax, -1
  656.         ret
  657.  
  658.  
  659. ; param
  660. ;  eax= uart
  661. ;  ebx= baud rate
  662.  
  663. align 4
  664. set_rate:
  665.         cmp     ebx, RATE_115200
  666.         ja      .fail
  667.  
  668.         mov     [eax+UART.rate], ebx
  669.         mov     bx, [divisor+ebx*2]
  670.  
  671.         mov     edx, [eax+UART.base]
  672.         add     edx, LCR_REG
  673.         in      al, dx
  674.         push    eax
  675.         or      al, 0x80
  676.         out     dx, al
  677.  
  678.         sub     edx, LCR_REG
  679.         mov     al, bl
  680.         out     dx, al
  681.  
  682.         inc     edx
  683.         mov     al, bh
  684.         out     dx, al
  685.  
  686.         pop     eax
  687.         add     edx, LCR_REG-1
  688.         out     dx, al
  689. .fail:
  690.         ret
  691.  
  692.  
  693. ; param
  694. ;   ebx= uart
  695.  
  696. align 4
  697. transmit:
  698.         push    esi
  699.         push    edi
  700.  
  701.         mov     edx, [ebx+UART.base]
  702.  
  703.         pushfd
  704.         cli
  705.  
  706.         mov     esi, [ebx+UART.xmit_rp]
  707.         mov     ecx, [ebx+UART.xmit_count]
  708.         test    ecx, ecx
  709.         je      .stop
  710.  
  711.         cmp     ecx, 16
  712.         jbe     @F
  713.         mov     ecx, 16
  714. @@:
  715.         sub     [ebx+UART.xmit_count], ecx
  716.         add     [ebx+UART.xmit_free], ecx
  717.         cld
  718. @@:
  719.         lodsb
  720.         out     dx, al
  721.         dec     ecx
  722.         jnz     @B
  723.  
  724.         cmp     esi, [ebx+UART.xmit_top]
  725.         jb      @F
  726.         sub     esi, 8192
  727. @@:
  728.         mov     [ebx+UART.xmit_rp], esi
  729.  
  730.         cmp     [ebx+UART.xmit_count], 0
  731.         je      .stop
  732.  
  733.         mov     [ebx+UART.state], UART_TRANSMIT
  734.         jmp     @F
  735. .stop:
  736.         mov     [ebx+UART.state], UART_STOP
  737. @@:
  738.         popfd
  739.         pop     edi
  740.         pop     esi
  741.         ret
  742.  
  743.  
  744. ; param
  745. ;  esi=  input buffer
  746. ;        +0 connection
  747. ;        +4 dst buffer
  748. ;        +8 dst size
  749. ;  edi=  output buffer
  750. ;        +0 bytes read
  751.  
  752. ; retval
  753. ;  eax= error code
  754.  
  755. align 4
  756. uart_read:
  757.         mov     eax, [esi]
  758.         cmp     [eax+APPOBJ.magic], 'CNCT'
  759.         jne     .fail
  760.  
  761.         cmp     [eax+APPOBJ.destroy], uart_close.destroy
  762.         jne     .fail
  763.  
  764.         mov     eax, [eax+CONNECTION.uart]
  765.         test    eax, eax
  766.         jz      .fail
  767.  
  768.         mov     ebx, [esi+8]   ;dst size
  769.         mov     ecx, [eax+UART.rcvr_count]
  770.         cmp     ecx, ebx
  771.         jbe     @F
  772.         mov     ecx, ebx
  773. @@:
  774.         mov     [edi], ecx     ;bytes read
  775.         test    ecx, ecx
  776.         jz      .done
  777.  
  778.         push    ecx
  779.  
  780.         mov     edi, [esi+4]   ;dst
  781.         mov     esi, [eax+UART.rcvr_rp]
  782.         cld
  783.         rep movsb
  784.         pop     ecx
  785.  
  786.         cmp     esi, [eax+UART.rcvr_top]
  787.         jb      @F
  788.         sub     esi, 8192
  789. @@:
  790.         mov     [eax+UART.rcvr_rp], esi
  791.         sub     [eax+UART.rcvr_count], ecx
  792. .done:
  793.         xor     eax, eax
  794.         ret
  795. .fail:
  796.         or      eax, -1
  797.         ret
  798.  
  799. ; param
  800. ;  esi=  input buffer
  801. ;        +0 connection
  802. ;        +4 src buffer
  803. ;        +8 src size
  804. ;
  805. ; retval
  806. ;  eax= error code
  807.  
  808. align 4
  809. uart_write:
  810.         mov     eax, [esi]
  811.         cmp     [eax+APPOBJ.magic], 'CNCT'
  812.         jne     .fail
  813.  
  814.         cmp     [eax+APPOBJ.destroy], uart_close.destroy
  815.         jne     .fail
  816.  
  817.         mov     eax, [eax+CONNECTION.uart]
  818.         test    eax, eax
  819.         jz      .fail
  820.  
  821.         mov     ebx, [esi+4]
  822.         mov     edx, [esi+8]
  823.  
  824. ; param
  825. ;  eax= uart
  826. ;  ebx= src
  827. ;  edx= count
  828.  
  829. align 4
  830. .internal:
  831.         mov     esi, ebx
  832.         mov     edi, [eax+UART.xmit_wp]
  833. .write:
  834.         test    edx, edx
  835.         jz      .fail
  836. .wait:
  837.         cmp     [eax+UART.xmit_free], 0
  838.         jne     .fill
  839.  
  840.         cmp     [eax+UART.state], UART_TRANSMIT
  841.         je      .wait
  842.  
  843.         mov     ebx, eax
  844.         push    edx
  845.         call    transmit
  846.         pop     edx
  847.         mov     eax, ebx
  848.         jmp     .write
  849. .fill:
  850.         mov     ecx, [eax+UART.xmit_free]
  851.         cmp     ecx, edx
  852.         jbe     @F
  853.         mov     ecx, edx
  854. @@:
  855.         push    ecx
  856.         cld
  857.         rep movsb
  858.         pop     ecx
  859.         sub     [eax+UART.xmit_free], ecx
  860.         add     [eax+UART.xmit_count], ecx
  861.         sub     edx, ecx
  862.         jnz     .wait
  863. .done:
  864.         cmp     edi, [eax+UART.xmit_top]
  865.         jb      @F
  866.         sub     edi, 8192
  867. @@:
  868.         mov     [eax+UART.xmit_wp], edi
  869.         cmp     [eax+UART.state], UART_TRANSMIT
  870.         je      @F
  871.         mov     ebx, eax
  872.         call    transmit
  873. @@:
  874.         xor     eax, eax
  875.         ret
  876. .fail:
  877.         or      eax, -1
  878.         ret
  879.  
  880.  
  881. align 4
  882. com_2_isr:
  883.         mov     ebx, [com2]
  884.         jmp     com_1_isr.get_info
  885. align 4
  886. com_1_isr:
  887.         mov     ebx, [com1]
  888. .get_info:
  889.         mov     edx, [ebx+UART.base]
  890.         add     edx, IIR_REG
  891.         in      al, dx
  892.  
  893.         test    al, IIR_INTR
  894.         jnz     .done
  895.  
  896.         shr     eax, 1
  897.         and     eax, 3
  898.  
  899.         call    [isr_action+eax*4]
  900.         jmp     .get_info
  901. .done:
  902.         ret
  903.  
  904. align 4
  905. isr_line:
  906.         mov     edx, [ebx+UART.base]
  907.         add     edx, LSR_REG
  908.         in      al, dx
  909.         ret
  910.  
  911. align 4
  912. isr_recieve:
  913.         mov     esi, [ebx+UART.base]
  914.         add     esi, LSR_REG
  915.         mov     edi, [ebx+UART.rcvr_wp]
  916.         xor     ecx, ecx
  917.         cld
  918. .read:
  919.         mov     edx, esi
  920.         in      al, dx
  921.         test    eax, LSR_DR
  922.         jz      .done
  923.  
  924.         mov     edx, [ebx+UART.base]
  925.         in      al, dx
  926.         stosb
  927.         inc     ecx
  928.         jmp     .read
  929. .done:
  930.         cmp     edi, [ebx+UART.rcvr_top]
  931.         jb      @F
  932.         sub     edi, 8192
  933. @@:
  934.         mov     [ebx+UART.rcvr_wp], edi
  935.         add     [ebx+UART.rcvr_count], ecx
  936.         ret
  937.  
  938. align 4
  939. isr_modem:
  940.         mov     edx, [ebx+UART.base]
  941.         add     edx, MSR_REG
  942.         in      al, dx
  943.         ret
  944.  
  945.  
  946. align 4
  947. divisor    dw 2304, 1536, 1047, 857, 768, 384
  948.            dw  192,   96,   64,  58,  48,  32
  949.            dw   24,   16,   12,   6,   3,   2, 1
  950.  
  951. align 4
  952. uart_func   dd 0                ;SRV_GETVERSION
  953.             dd 0                ;PORT_OPEN
  954.             dd uart_close       ;PORT_CLOSE
  955.             dd uart_reset       ;PORT_RESET
  956.             dd uart_set_mode    ;PORT_SETMODE
  957.             dd 0                ;PORT_GETMODE
  958.             dd uart_set_mcr     ;PORT_SETMODEM
  959.             dd 0                ;PORT_GETMODEM
  960.             dd uart_read        ;PORT_READ
  961.             dd uart_write       ;PORT_WRITE
  962.  
  963. isr_action  dd isr_modem
  964.             dd transmit
  965.             dd isr_recieve
  966.             dd isr_line
  967.  
  968. version     dd (5 shl 16) or (UART_VERSION and 0xFFFF)
  969.  
  970. sz_uart_srv db 'UART',0
  971.  
  972. align 4
  973.  
  974. com1        rd 1
  975. com2        rd 1
  976.  
  977.