Subversion Repositories Kolibri OS

Rev

Rev 413 | 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_rp      dd ?
  129.    .rcvr_wp      dd ?
  130.    .rcvr_cnt     dd ?
  131.  
  132.    .xmit_buff    dd ?
  133.    .xmit_rp      dd ?
  134.    .xmit_wp      dd ?
  135.    .xmit_count   dd ?
  136.    .xmit_free    dd ?
  137.    .xmit_top     dd ?
  138. }
  139. virtual at 0
  140.   UART UART
  141. end virtual
  142.  
  143. UART_SIZE     equ 16*4
  144.  
  145. struc CONNECTION
  146. {
  147.    .magic       dd ?   ;'CNCT'
  148.    .destroy     dd ?   ;internal destructor
  149.    .fd          dd ?   ;next object in list
  150.    .bk          dd ?   ;prev object in list
  151.    .pid         dd ?   ;owner id
  152.  
  153.    .id          dd ?   ;reserved
  154.    .uart        dd ?   ;uart pointer
  155. }
  156.  
  157. virtual at 0
  158.   CONNECTION CONNECTION
  159. end virtual
  160.  
  161. CONNECTION_SIZE equ 7*4
  162.  
  163. UART_VERSION  equ 0x12345678        ;debug
  164.  
  165. init_uart_service:
  166.            mov eax, UART_SIZE
  167.            call malloc
  168.            test eax, eax
  169.            jz .fail
  170.  
  171.            mov [com1], eax
  172.            mov edi, eax
  173.            mov ecx, UART_SIZE/4
  174.            xor eax, eax
  175.            cld
  176.            rep stosd
  177.  
  178.            mov eax, [com1]
  179.            mov [eax+UART.base], COM_1_BASE
  180.  
  181.            stdcall alloc_kernel_space, 16384
  182.  
  183.            mov edi, [com1]
  184.            mov edx, eax
  185.            mov [edi+UART.xmit_buff], eax
  186.            add eax, 8192
  187.            mov [edi+UART.xmit_top], eax
  188.  
  189.            call alloc_page
  190.            test eax, eax
  191.            jz .fail
  192.  
  193.            shr edx, 12
  194.            or eax, PG_SW
  195.            mov [page_tabs+edx*4], eax
  196.            mov [page_tabs+edx*4+8], eax
  197.  
  198.            call alloc_page
  199.            test eax, eax
  200.            jz .fail
  201.  
  202.            or eax, PG_SW
  203.            mov [page_tabs+edx*4+4], eax
  204.            mov [page_tabs+edx*4+12], eax
  205.  
  206.            mov eax, [edi+UART.xmit_buff]
  207.            invlpg [eax]
  208.            invlpg [eax+0x1000]
  209.            invlpg [eax+0x2000]
  210.            invlpg [eax+0x3000]
  211.  
  212.            mov eax, edi
  213.            call uart_reset.internal   ;eax= uart
  214.  
  215.            stdcall attach_int_handler, COM_1_IRQ, com_1_isr
  216.            stdcall reg_service, sz_uart_srv, uart_proc
  217.            ret
  218. .fail:
  219.            xor eax, eax
  220.            ret
  221.  
  222. handle     equ  IOCTL.handle
  223. io_code    equ  IOCTL.io_code
  224. input      equ  IOCTL.input
  225. inp_size   equ  IOCTL.inp_size
  226. output     equ  IOCTL.output
  227. out_size   equ  IOCTL.out_size
  228.  
  229. SRV_GETVERSION  equ 0
  230. PORT_OPEN       equ 1
  231. PORT_CLOSE      equ 2
  232. PORT_RESET      equ 3
  233. PORT_SETMODE    equ 4
  234. PORT_GETMODE    equ 5
  235. PORT_SETMCR     equ 6
  236. PORT_GETMCR     equ 7
  237. PORT_READ       equ 8
  238. PORT_WRITE      equ 9
  239.  
  240. align 4
  241. proc uart_proc stdcall, ioctl:dword
  242.  
  243.            mov ebx, [ioctl]
  244.            mov eax, [ebx+io_code]
  245.            cmp eax, PORT_WRITE
  246.            ja .fail
  247.  
  248.            cmp eax, SRV_GETVERSION
  249.            jne @F
  250.  
  251.            mov eax, [ebx+output]
  252.            mov [eax], dword UART_VERSION
  253.            xor eax, eax
  254.            ret
  255. @@:
  256.            cmp eax, PORT_OPEN
  257.            jne @F
  258.  
  259.            mov ebx, [ebx+input]
  260.            mov eax, [ebx]
  261.            call uart_open
  262.            mov ebx, [ioctl]
  263.            mov ebx, [ebx+output]
  264.            mov [ebx], ecx
  265.            ret
  266. @@:
  267.            mov esi, [ebx+input]     ;input buffer
  268.            mov edi, [ebx+output]
  269.            call [uart_func+eax*4]
  270.            ret
  271. .fail:
  272.            or eax, -1
  273.            ret
  274.  
  275. endp
  276.  
  277. restore   handle
  278. restore   io_code
  279. restore   input
  280. restore   inp_size
  281. restore   output
  282. restore   out_size
  283.  
  284.  
  285. ; param
  286. ;  esi=  input buffer
  287. ;        +0 connection
  288. ;
  289. ; retval
  290. ;  eax= error code
  291.  
  292. align 4
  293. uart_reset:
  294.            mov eax, [esi]
  295.            cmp [eax+APPOBJ.magic], 'CNCT'
  296.            jne .fail
  297.  
  298.            cmp [eax+APPOBJ.destroy], uart_close.destroy
  299.            jne .fail
  300.  
  301.            mov eax, [eax+CONNECTION.uart]
  302.            test eax, eax
  303.            jz .fail
  304.  
  305. ; set mode 2400 bod 8-bit
  306. ; disable DTR & RTS
  307. ; clear FIFO
  308. ; clear pending interrupts
  309. ;
  310. ; param
  311. ;  eax= uart
  312.  
  313. align 4
  314. .internal:
  315.            mov esi, eax
  316.            mov [eax+UART.state], UART_CLOSED
  317.            mov edx, [eax+UART.base]
  318.            add edx, MCR_REG
  319.            xor eax, eax
  320.            out dx, al        ;clear DTR & RTS
  321.  
  322.            mov eax, esi
  323.            mov ebx, RATE_2400
  324.            mov ecx, LCR_8BIT+LCR_STOP_1
  325.            call uart_set_mode.internal
  326.  
  327.            mov edx, [esi+UART.base]
  328.            add edx, IIR_REG
  329.            mov eax,FCR_EFIFO+FCR_CRB+FCR_CXMIT+FCR_FIFO_14
  330.            out dx, al
  331. .clear_RB:
  332.            mov edx, [esi+UART.base]
  333.            add edx, LSR_REG
  334.            in al, dx
  335.            test eax, LSR_DR
  336.            jz @F
  337.  
  338.            mov edx, [esi+UART.base]
  339.            in al, dx
  340.            jmp .clear_RB
  341. @@:
  342.            mov edx, [esi+UART.base]
  343.            add edx, IER_REG
  344.            mov eax,IER_RDAI+IER_THRI+IER_LSI
  345.            out dx, al
  346. .clear_IIR:
  347.            mov edx, [esi+UART.base]
  348.            add edx, IIR_REG
  349.            in al, dx
  350.            test al, IIR_INTR
  351.            jnz .done
  352.  
  353.            shr eax, 1
  354.            and eax, 3
  355.            jnz @F
  356.  
  357.            mov edx, [esi+UART.base]
  358.            add edx, MSR_REG
  359.            in al, dx
  360.            jmp .clear_IIR
  361. @@:
  362.            cmp eax, 1
  363.            je .clear_IIR
  364.  
  365.            cmp eax, 2
  366.            jne @F
  367.  
  368.            mov edx, [esi+UART.base]
  369.            in al, dx
  370.            jmp .clear_IIR
  371. @@:
  372.            mov edx, [esi+UART.base]
  373.            add edx, LSR_REG
  374.            in al, dx
  375.            jmp .clear_IIR
  376. .done:
  377.            mov edi, [esi+UART.xmit_buff]
  378.            mov ecx, 8192/4
  379.            xor eax, eax
  380.  
  381.            mov [esi+UART.xmit_rp], edi
  382.            mov [esi+UART.xmit_wp], edi
  383.            mov [esi+UART.xmit_count], eax
  384.            mov [esi+UART.xmit_free], 8192
  385.  
  386.            cld
  387.            rep stosd
  388.  
  389.  
  390. ;           mov [esi+UART.rcvr_rp], eax
  391. ;           mov [esi+UART.rcvr_wp], eax
  392. ;           mov [esi+UART.rcvr_cnt], eax
  393.  
  394.            ret
  395. .fail:
  396.            or eax, -1
  397.            ret
  398.  
  399. ; param
  400. ;  esi=  input buffer
  401. ;        +0 connection
  402. ;        +4 rate
  403. ;        +8 mode
  404. ;
  405. ; retval
  406. ;  eax= error code
  407.  
  408. align 4
  409. uart_set_mode:
  410.            mov eax, [esi]
  411.            cmp [eax+APPOBJ.magic], 'CNCT'
  412.            jne .fail
  413.  
  414.            cmp [eax+APPOBJ.destroy], uart_close.destroy
  415.            jne .fail
  416.  
  417.            mov eax, [eax+CONNECTION.uart]
  418.            test eax, eax
  419.            jz .fail
  420.  
  421.            mov ebx, [esi+4]
  422.            mov ecx, [esi+8]
  423.  
  424. ; param
  425. ;  eax= uart
  426. ;  ebx= baud rate
  427. ;  ecx= mode
  428.  
  429. align 4
  430. .internal:
  431.            cmp ebx, RATE_115200
  432.            ja .fail
  433.  
  434.            cmp ecx, LCR_BREAK
  435.            jae .fail
  436.  
  437.            mov [eax+UART.rate], ebx
  438.            mov [eax+UART.mode], ecx
  439.  
  440.            mov esi, eax
  441.            mov bx, [divisor+ebx*2]
  442.  
  443.            mov edx, [esi+UART.base]
  444.            push edx
  445.            add edx, LCR_REG
  446.            in al, dx
  447.            or al, 0x80
  448.            out dx, al
  449.  
  450.            pop edx
  451.            mov al, bl
  452.            out dx, al
  453.  
  454.            inc dx
  455.            mov al, bh
  456.            out dx, al
  457.  
  458.            add edx, LCR_REG-1
  459.            mov eax, ecx
  460.            out dx, al
  461.            xor eax, eax
  462.            ret
  463. .fail:
  464.            or eax, -1
  465.            ret
  466.  
  467. ; param
  468. ;  esi=  input buffer
  469. ;        +0 connection
  470. ;        +4 modem control reg valie
  471. ;
  472. ; retval
  473. ;  eax= error code
  474.  
  475. align 4
  476. uart_set_mcr:
  477.  
  478.            mov eax, [esi]
  479.            cmp [eax+APPOBJ.magic], 'CNCT'
  480.            jne .fail
  481.  
  482.            cmp [eax+APPOBJ.destroy], uart_close.destroy
  483.            jne .fail
  484.  
  485.            mov eax, [eax+CONNECTION.uart]
  486.            test eax, eax
  487.            jz .fail
  488.  
  489.            mov ebx, [esi+4]
  490.  
  491.            mov [eax+UART.mcr_reg], ebx
  492.            mov edx, [eax+UART.base]
  493.            add edx, MCR_REG
  494.            mov al, bl
  495.            out dx, al
  496.            xor eax, eax
  497.            ret
  498. .fail:
  499.            or eax, -1
  500.            ret
  501.  
  502. ; param
  503. ;  eax= port
  504. ;
  505. ; retval
  506. ;  ecx= connection
  507. ;  eax= error code
  508.  
  509. align 4
  510. uart_open:
  511.            dec eax
  512.            cmp eax, COM_MAX
  513.            jae .fail
  514.  
  515.            mov esi, [com1+eax*4]             ;uart
  516.            push esi
  517. .do_wait:
  518.            cmp dword [esi+UART.lock],0
  519.            je .get_lock
  520.            call change_task
  521.            jmp .do_wait
  522. .get_lock:
  523.            mov eax, 1
  524.            xchg eax, [esi+UART.lock]
  525.            test eax, eax
  526.            jnz .do_wait
  527.  
  528.            mov eax, esi                  ;uart
  529.            call uart_reset.internal
  530.  
  531.            mov ebx, [CURRENT_TASK]
  532.            shl ebx, 5
  533.            mov ebx, [CURRENT_TASK+ebx+4]
  534.            mov eax, CONNECTION_SIZE
  535.            call create_kernel_object
  536.            pop esi                       ;uart
  537.            test eax, eax
  538.            jz .fail
  539.  
  540.            mov [eax+APPOBJ.magic], 'CNCT'
  541.            mov [eax+APPOBJ.destroy], uart_close.destroy
  542.            mov [eax+CONNECTION.uart], esi
  543.            mov ecx, eax
  544.            xor eax, eax
  545.            ret
  546. .fail:
  547.            or eax, -1
  548.            ret
  549. restore .uart
  550.  
  551. ; param
  552. ;  esi= input buffer
  553.  
  554. align 4
  555. uart_close:
  556.            mov eax, [esi]
  557.            cmp [eax+APPOBJ.magic], 'CNCT'
  558.            jne .fail
  559.  
  560.            cmp [eax+APPOBJ.destroy], uart_close.destroy
  561.            jne .fail
  562. .destroy:
  563.            push [eax+CONNECTION.uart]
  564.            call destroy_kernel_object   ;eax= object
  565.            pop eax                      ;eax= uart
  566.            test eax, eax
  567.            jz .fail
  568.  
  569.            mov [eax+UART.state], UART_CLOSED
  570.            mov [eax+UART.lock], 0 ;release port
  571.            xor eax, eax
  572.            ret
  573. .fail:
  574.            or eax, -1
  575.            ret
  576.  
  577.  
  578. ; param
  579. ;  eax= uart
  580. ;  ebx= baud rate
  581.  
  582. align 4
  583. set_rate:
  584.            cmp ebx, RATE_115200
  585.            ja .fail
  586.  
  587.            mov [eax+UART.rate], ebx
  588.            mov bx, [divisor+ebx*2]
  589.  
  590.            mov edx, [eax+UART.base]
  591.            add edx, LCR_REG
  592.            in al, dx
  593.            push eax
  594.            or al, 0x80
  595.            out dx, al
  596.  
  597.            sub edx, LCR_REG
  598.            mov al, bl
  599.            out dx, al
  600.  
  601.            inc edx
  602.            mov al, bh
  603.            out dx, al
  604.  
  605.            pop eax
  606.            add edx, LCR_REG-1
  607.            out dx, al
  608. .fail:
  609.            ret
  610.  
  611.  
  612. ; param
  613. ;   ebx= uart
  614.  
  615. align 4
  616. transmit:
  617.            push esi
  618.            push edi
  619.  
  620.            mov edx, [ebx+UART.base]
  621.  
  622.            pushfd
  623.            cli
  624.  
  625.            mov esi, [ebx+UART.xmit_rp]
  626.            mov ecx, [ebx+UART.xmit_count]
  627.            test ecx, ecx
  628.            je .stop
  629.  
  630.            cmp ecx, 16
  631.            jbe @F
  632.            mov ecx, 16
  633. @@:
  634.            sub [ebx+UART.xmit_count], ecx
  635.            add [ebx+UART.xmit_free], ecx
  636.            cld
  637. @@:
  638.            lodsb
  639.            out dx, al
  640.            dec ecx
  641.            jnz @B
  642.  
  643.            cmp esi,[ebx+UART.xmit_top]
  644.            jb @F
  645.            sub esi, 8192
  646. @@:
  647.            mov [ebx+UART.xmit_rp], esi
  648.  
  649.            cmp [ebx+UART.xmit_count], 0
  650.            je .stop
  651.  
  652.            mov [ebx+UART.state], UART_TRANSMIT
  653.            jmp @F
  654. .stop:
  655.            mov [ebx+UART.state], UART_STOP
  656. @@:
  657.            popfd
  658.            pop edi
  659.            pop esi
  660.            ret
  661.  
  662.  
  663. ; param
  664. ;  esi=  input buffer
  665. ;        +0 connection
  666. ;        +4 dst buffer
  667. ;        +8 dst size
  668. ;  edi=  output buffer
  669. ;        +0 bytes read
  670.  
  671. ; retval
  672. ;  eax= error code
  673.  
  674. align 4
  675. uart_read:
  676.            mov eax, [esi]
  677.            cmp [eax+APPOBJ.magic], 'CNCT'
  678.            jne .fail
  679.  
  680.            cmp [eax+APPOBJ.destroy], uart_close.destroy
  681.            jne .fail
  682.  
  683.            mov eax, [eax+CONNECTION.uart]
  684.            test eax, eax
  685.            jz .fail
  686.  
  687.            mov ebx, [esi+8]    ;dst size
  688.            mov ecx, [eax+UART.rcvr_cnt]
  689.            cmp ecx, ebx
  690.            jbe @F
  691.            mov ecx, ebx
  692. @@:
  693.            mov [edi], ecx      ;bytes read
  694.            test ecx, ecx
  695.            jz .done
  696.  
  697.            sub [eax+UART.rcvr_cnt], ecx
  698.  
  699.            push eax
  700.            mov edi, [esi+4]    ;dst
  701.        ;    lea esi, [eax+RCVR_OFFSET]
  702.            mov ebx, [eax+UART.rcvr_rp]
  703.            cld
  704. @@:
  705.            and ebx, 127
  706.            mov al, [esi+ebx]
  707.            stosb
  708.            inc ebx
  709.            dec ecx
  710.            jnz @B
  711.  
  712.            pop eax
  713.            mov [eax+UART.rcvr_rp], ebx
  714. .done:
  715.            xor eax, eax
  716.            rep
  717. .fail:
  718.            or eax, -1
  719.            ret
  720.  
  721. ; param
  722. ;  esi=  input buffer
  723. ;        +0 connection
  724. ;        +4 src buffer
  725. ;        +8 src size
  726. ;
  727. ; retval
  728. ;  eax= error code
  729.  
  730. align 4
  731. uart_write:
  732.            mov eax, [esi]
  733.            cmp [eax+APPOBJ.magic], 'CNCT'
  734.            jne .fail
  735.  
  736.            cmp [eax+APPOBJ.destroy], uart_close.destroy
  737.            jne .fail
  738.  
  739.            mov eax, [eax+CONNECTION.uart]
  740.            test eax, eax
  741.            jz .fail
  742.  
  743.            mov ebx, [esi+4]
  744.            mov edx, [esi+8]
  745.  
  746. ; param
  747. ;  eax= uart
  748. ;  ebx= src
  749. ;  edx= count
  750.  
  751. align 4
  752. .internal:
  753.            mov esi, ebx
  754.            mov edi, [eax+UART.xmit_wp]
  755. .write:
  756.            test edx, edx
  757.            jz .fail
  758. .wait:
  759.            cmp [eax+UART.xmit_free], 0
  760.            jne .fill
  761.  
  762.            cmp [eax+UART.state], UART_TRANSMIT
  763.            je .wait
  764.  
  765.            mov ebx, eax
  766.            push edx
  767.            call transmit
  768.            pop edx
  769.            mov eax, ebx
  770.            jmp .write
  771. .fill:
  772.            mov ecx, [eax+UART.xmit_free]
  773.            cmp ecx, edx
  774.            jbe @F
  775.            mov ecx, edx
  776. @@:
  777.            push ecx
  778.            cld
  779.            rep movsb
  780.            pop ecx
  781.            sub [eax+UART.xmit_free], ecx
  782.            add [eax+UART.xmit_count], ecx
  783.            sub edx, ecx
  784.            jnz .wait
  785. .done:
  786.            cmp edi, [eax+UART.xmit_top]
  787.            jb @F
  788.            sub edi, 8192
  789. @@:
  790.            mov [eax+UART.xmit_wp], edi
  791.            cmp [eax+UART.state], UART_TRANSMIT
  792.            je @F
  793.            mov ebx, eax
  794.            call transmit
  795. @@:
  796.            xor eax, eax
  797.            ret
  798. .fail:
  799.            or eax, -1
  800.            ret
  801.  
  802.  
  803. align 4
  804. com_2_isr:
  805.            mov ebx, [com2]
  806.            jmp com_1_isr.get_info
  807. align 4
  808. com_1_isr:
  809.            mov ebx, [com1]
  810. .get_info:
  811.            mov edx, [ebx+UART.base]
  812.            add edx, IIR_REG
  813.            in  al, dx
  814.  
  815.            test al, IIR_INTR
  816.            jnz .done
  817.  
  818.            shr eax, 1
  819.            and eax, 3
  820.  
  821.            call [isr_action+eax*4]
  822.            jmp .get_info
  823. .done:
  824.            ret
  825.  
  826. align 4
  827. isr_line:
  828.            mov edx, [ebx+UART.base]
  829.            add edx, LSR_REG
  830.            in al, dx
  831.            ret
  832.  
  833. align 4
  834. isr_recieve:
  835.            mov edx, [ebx+UART.base]
  836.            in al, dx
  837.            ret
  838.  
  839. align 4
  840. isr_modem:
  841.            mov edx, [ebx+UART.base]
  842.            add edx, MSR_REG
  843.            in al, dx
  844.            ret
  845.  
  846.  
  847. align 4
  848. com1        dd 0
  849. com2        dd 0
  850.  
  851. align 4
  852. uart_func   dd 0                ;SRV_GETVERSION
  853.             dd 0                ;PORT_OPEN
  854.             dd uart_close       ;PORT_CLOSE
  855.             dd uart_reset       ;PORT_RESET
  856.             dd uart_set_mode    ;PORT_SETMODE
  857.             dd 0                ;PORT_GETMODE
  858.             dd uart_set_mcr     ;PORT_SETMODEM
  859.             dd 0                ;PORT_GETMODEM
  860.             dd uart_read        ;PORT_READ
  861.             dd uart_write       ;PORT_WRITE
  862.  
  863. isr_action  dd isr_modem
  864.             dd transmit
  865.             dd isr_recieve
  866.             dd isr_line
  867.  
  868. ;version      dd 0x00040000
  869.  
  870. divisor     dw 2304, 1536, 1047, 857, 768, 384
  871.             dw  192,   96,   64,  58,  48,  32
  872.             dw   24,   16,   12,   6,   3,   2, 1
  873.  
  874.  
  875.  
  876. sz_uart_srv db 'UART',0
  877.  
  878.  
  879.  
  880.