Subversion Repositories Kolibri OS

Rev

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

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