Subversion Repositories Kolibri OS

Rev

Rev 1159 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2007. 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.