Subversion Repositories Kolibri OS

Rev

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