Subversion Repositories Kolibri OS

Rev

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