Subversion Repositories Kolibri OS

Rev

Rev 593 | 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. ;;  I8255X.INC                                                     ;;
  8. ;;                                                                 ;;
  9. ;;  Ethernet driver for Menuet OS                                  ;;
  10. ;;                                                                 ;;
  11. ;;  Version 0.3  11 August 2003                                    ;;
  12. ;;                                                                 ;;
  13. ;;  This driver is based on the eepro100 driver from               ;;
  14. ;;  the etherboot 5.0.6 project. The copyright statement is        ;;
  15. ;;                                                                 ;;
  16. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  17. ;;             Version 2, June 1991                                ;;
  18. ;;                                                                 ;;
  19. ;;  remaining parts Copyright 2002 Mike Hibbett,                   ;;
  20. ;;   mikeh@oceanfree.net                                           ;;
  21. ;;                                                                 ;;
  22. ;;  See file COPYING for details                                   ;;
  23. ;;                                                                 ;;
  24. ;;                                                                 ;;
  25. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  26.  
  27. $Revision: 782 $
  28.  
  29.  
  30. ;********************************************************************
  31. ;   Interface
  32. ;      I8255x_reset
  33. ;      I8255x_probe
  34. ;      I8255x_poll
  35. ;      I8255x_transmit
  36. ;
  37. ;      These functions are referenced in ethernet.inc
  38. ;
  39. ;********************************************************************
  40.  
  41.  
  42. rxfd_status             equ  eth_data_start
  43. rxfd_command            equ  eth_data_start + 2
  44. rxfd_link               equ  eth_data_start + 4
  45. rxfd_rx_buf_addr        equ  eth_data_start + 8
  46. rxfd_count              equ  eth_data_start + 12
  47. rxfd_size               equ  eth_data_start + 14
  48. rxfd_packet             equ  eth_data_start + 16
  49.  
  50.  
  51.  
  52. uglobal
  53. eeprom_data:  times 16  dd 0
  54.  
  55. align 4
  56.  
  57. lstats:
  58. tx_good_frames: dd 0
  59. tx_coll16_errs:  dd 0
  60. tx_late_colls: dd 0
  61. tx_underruns: dd 0
  62. tx_lost_carrier: dd 0
  63. tx_deferred: dd 0
  64. tx_one_colls: dd 0
  65. tx_multi_colls: dd 0
  66. tx_total_colls: dd 0
  67. rx_good_frames: dd 0
  68. rx_crc_errs: dd 0
  69. rx_align_errs: dd 0
  70. rx_resource_errs: dd 0
  71. rx_overrun_errs: dd 0
  72. rx_colls_errs: dd 0
  73. rx_runt_errs: dd 0
  74. done_marker: dd 0
  75.  
  76. align 4
  77.  
  78. confcmd:
  79. confcmd_status:         dw    0
  80. confcmd_command:        dw    0
  81. confcmd_link:           dd    0
  82. endg
  83.  
  84. iglobal
  85. confcmd_data:           db    22, 0x08, 0, 0, 0, 0x80, 0x32, 0x03, 1
  86.                         db    0, 0x2e, 0, 0x60, 0, 0xf2, 0x48, 0, 0x40, 0xf2
  87.                         db    0x80, 0x3f, 0x05
  88. endg
  89.  
  90. uglobal
  91. align 4
  92.  
  93. txfd:
  94. txfd_status:            dw   0
  95. txfd_command:           dw   0
  96. txfd_link:              dd   0
  97. txfd_tx_desc_addr:      dd   0
  98. txfd_count:             dd   0
  99. txfd_tx_buf_addr0:      dd   0
  100. txfd_tx_buf_size0:      dd   0
  101. txfd_tx_buf_addr1:      dd   0
  102. txfd_tx_buf_size1:      dd   0
  103.  
  104. align 4
  105.  
  106. hdr:
  107. hdr_dst_addr:           times 6 db 0
  108. hdr_src_addr:           times 6 db 0
  109. hdr_type:               dw   0
  110. endg
  111.  
  112.  
  113. ;***************************************************************************
  114. ;   Function
  115. ;      wait_for_cmd_done
  116. ;
  117. ;   Description
  118. ;       waits for the hardware to complete a command
  119. ;       port address in edx
  120. ;
  121. ;       al destroyed
  122. ;***************************************************************************
  123. wait_for_cmd_done:
  124.    in       al, dx
  125.    cmp      al, 0
  126.    jne      wait_for_cmd_done
  127.    ret
  128.  
  129.  
  130.  
  131. ;***************************************************************************
  132. ;   Function
  133. ;      mdio_read
  134. ;
  135. ;   Description
  136. ;       This probably reads a register in the "physical media interface chip"
  137. ;         Phy_id in ebx
  138. ;         location in ecx
  139. ;
  140. ;       Data returned in eax
  141. ;
  142. ;***************************************************************************
  143. mdio_read:
  144.    mov      edx, [io_addr]
  145.    add      edx, 16         ; SCBCtrlMDI
  146.  
  147.    mov      eax, 0x08000000
  148.    shl      ecx, 16
  149.    or       eax, ecx
  150.    shl      ebx, 21
  151.    or       eax, ebx
  152.  
  153.    out      dx, eax
  154.  
  155. mrlp:
  156.    call     delay_us
  157.    in       eax, dx
  158.    mov      ecx, eax
  159.    and      ecx, 0x10000000
  160.    jz       mrlp
  161.  
  162.    and      eax, 0xffff
  163.    ret
  164.  
  165.  
  166.  
  167. ;***************************************************************************
  168. ;   Function
  169. ;      mdio_write
  170. ;
  171. ;   Description
  172. ;       This probably writes a register in the "physical media interface chip"
  173. ;         Phy_id in ebx
  174. ;         location in ecx
  175. ;         data in edx
  176. ;       Data returned in eax
  177. ;
  178. ;***************************************************************************
  179. mdio_write:
  180.    mov      eax, 0x04000000
  181.    shl      ecx, 16
  182.    or       eax, ecx
  183.    shl      ebx, 21
  184.    or       eax, ebx
  185.    or       eax, edx
  186.  
  187.    mov      edx, [io_addr]
  188.    add      edx, 16         ; SCBCtrlMDI
  189.    out      dx, eax
  190.  
  191. mwlp:
  192.    call     delay_us
  193.    in       eax, dx
  194.    mov      ecx, eax
  195.    and      ecx, 0x10000000
  196.    jz       mwlp
  197.  
  198.    and      eax, 0xffff
  199.    ret
  200.  
  201.  
  202.  
  203. ;/***********************************************************************/
  204. ;/*                       I82557 related defines                        */
  205. ;/***********************************************************************/
  206.  
  207. ; Serial EEPROM section.
  208. ;   A "bit" grungy, but we work our way through bit-by-bit :->.
  209. ;  EEPROM_Ctrl bits.
  210. EE_SHIFT_CLK    equ   0x01    ; EEPROM shift clock.
  211. EE_CS           equ   0x02    ; EEPROM chip select.
  212. EE_DATA_WRITE   equ   0x04    ; EEPROM chip data in.
  213. EE_DATA_READ    equ   0x08    ; EEPROM chip data out.
  214. EE_WRITE_0      equ   0x4802
  215. EE_WRITE_1      equ   0x4806
  216. EE_ENB          equ   0x4802
  217.  
  218.  
  219. ; The EEPROM commands include the alway-set leading bit.
  220. EE_READ_CMD     equ   6
  221.  
  222. ; The SCB accepts the following controls for the Tx and Rx units:
  223. CU_START       equ   0x0010
  224. CU_RESUME      equ   0x0020
  225. CU_STATSADDR   equ   0x0040
  226. CU_SHOWSTATS   equ   0x0050   ; Dump statistics counters.
  227. CU_CMD_BASE    equ   0x0060   ; Base address to add to add CU commands.
  228. CU_DUMPSTATS   equ   0x0070   ; Dump then reset stats counters.
  229.  
  230. RX_START       equ   0x0001
  231. RX_RESUME      equ   0x0002
  232. RX_ABORT       equ   0x0004
  233. RX_ADDR_LOAD   equ   0x0006
  234. RX_RESUMENR    equ   0x0007
  235. INT_MASK       equ   0x0100
  236. DRVR_INT       equ   0x0200   ; Driver generated interrupt.
  237.  
  238.  
  239. ;***************************************************************************
  240. ;   Function
  241. ;      do_eeprom_cmd
  242. ;
  243. ;   Description
  244. ;       writes a cmd to the ethernet cards eeprom, by bit bashing
  245. ;       cmd in ebx
  246. ;       cmd length in ecx
  247. ;       return in eax
  248. ;***************************************************************************
  249. do_eeprom_cmd:
  250.    mov      edx, [io_addr]    ; We only require the value in dx
  251.    add      dx, 14            ; the value SCBeeprom
  252.  
  253.    mov      ax, EE_ENB
  254.    out      dx, ax
  255.    call     delay_us
  256.  
  257.    mov      ax, 0x4803        ; EE_ENB | EE_SHIFT_CLK
  258.    out      dx, ax
  259.    call     delay_us
  260.  
  261.     ; dx holds ee_addr
  262.     ; ecx holds count
  263.     ; eax holds cmd
  264.    xor      edi, edi          ; this will be the receive data
  265.  
  266. dec_001:
  267.    mov      esi, 1
  268.  
  269.    dec      ecx
  270.    shl      esi, cl
  271.    inc      ecx
  272.    and      esi, ebx
  273.    mov      eax, EE_WRITE_0   ; I am assuming this doesnt affect the flags..
  274.    cmp      esi,0
  275.    jz       dec_002
  276.    mov      eax, EE_WRITE_1
  277.  
  278. dec_002:
  279.    out      dx, ax
  280.    call     delay_us
  281.  
  282.    or       ax, EE_SHIFT_CLK
  283.    out      dx, ax
  284.    call     delay_us
  285.  
  286.    shl      edi,1
  287.  
  288.    in       ax, dx
  289.    and      ax, EE_DATA_READ
  290.    cmp      ax,0
  291.    jz       dec_003
  292.    inc      edi
  293.  
  294. dec_003:
  295.    loop     dec_001
  296.  
  297.    mov      ax, EE_ENB
  298.    out      dx, ax
  299.    call     delay_us
  300.  
  301.    mov      ax, 0x4800
  302.    out      dx, ax
  303.    call     delay_us
  304.  
  305.    mov      eax, edi
  306.  
  307.    ret
  308.  
  309.  
  310. ;***************************************************************************
  311. ;   Function
  312. ;      I8255x_probe
  313. ;   Description
  314. ;      Searches for an ethernet card, enables it and clears the rx buffer
  315. ;      If a card was found, it enables the ethernet -> TCPIP link
  316. ;
  317. ;***************************************************************************
  318. I8255x_probe:
  319.    DEBUGF 1," K : Probing i8255x device \n"
  320.    mov      eax, [io_addr]
  321.  
  322.    mov      ebx, [pci_bus]
  323.    mov      ecx, [pci_dev]
  324.    mov      edx, 0x04      ; PCI_COMMAND
  325.    call     pcibios_read_config_word
  326.  
  327.    or       ax, 0x05
  328.    mov      ebx, [pci_bus]
  329.    mov      ecx, [pci_dev]
  330.    mov      edx, 0x04      ; PCI_COMMAND
  331.    call     pcibios_write_config_word
  332.  
  333.    mov      ebx, 0x6000000
  334.    mov      ecx, 27
  335.    call     do_eeprom_cmd
  336.    and      eax, 0xffe0000
  337.    cmp      eax, 0xffe0000
  338.    je       bige
  339.  
  340.    mov      ebx, 0x1800000
  341.    mov      ecx, 0x40
  342.    jmp      doread
  343.  
  344. bige:
  345.    mov      ebx, 0x6000000
  346.    mov      ecx, 0x100
  347.  
  348. doread:
  349.    ; do-eeprom-cmd will destroy all registers
  350.    ; we have eesize in ecx
  351.    ; read_cmd in ebx
  352.  
  353.    ; Ignore full eeprom - just load the mac address
  354.    mov      ecx, 0
  355.  
  356. drlp:
  357.    push     ecx      ; save count
  358.    push     ebx
  359.    mov      eax, ecx
  360.    shl      eax, 16
  361.    or       ebx, eax
  362.    mov      ecx, 27
  363.    call     do_eeprom_cmd
  364.  
  365.    pop      ebx
  366.    pop      ecx
  367.  
  368.    mov      edx, ecx
  369.    shl      edx, 2
  370.    mov      esi, eeprom_data
  371.    add      esi, edx
  372.    mov      [esi], eax
  373.  
  374.    inc      ecx
  375.    cmp      ecx, 16
  376.    jne      drlp
  377.  
  378.    ; OK, we have the MAC address.
  379.    ; Now reset the card
  380.  
  381.    mov      edx, [io_addr]
  382.    add      dx, 8         ; SCBPort
  383.    xor      eax, eax      ; The reset cmd == 0
  384.    out      dx, eax
  385.  
  386.    mov      esi, 10
  387.    call     delay_ms      ; Give the card time to warm up.
  388.  
  389.    mov      eax, lstats
  390.    mov      edx, [io_addr]
  391.    add      edx, 4            ; SCBPointer
  392.    out      dx, eax
  393.  
  394.    mov      eax, 0x0140         ; INT_MASK | CU_STATSADDR
  395.    mov      edx, [io_addr]
  396.    add      edx, 2            ; SCBCmd
  397.    out      dx, ax
  398.  
  399.    call     wait_for_cmd_done
  400.  
  401.    mov      eax, 0
  402.    mov      edx, [io_addr]
  403.    add      edx, 4            ; SCBPointer
  404.    out      dx, eax
  405.  
  406.    mov      eax, 0x0106         ; INT_MASK | RX_ADDR_LOAD
  407.    mov      edx, [io_addr]
  408.    add      edx, 2            ; SCBCmd
  409.    out      dx, ax
  410.  
  411.    call     wait_for_cmd_done
  412.  
  413.    ; build rxrd structure
  414.    mov      ax, 0x0001
  415.    mov      [rxfd_status], ax
  416.    mov      ax, 0x0000
  417.    mov      [rxfd_command], ax
  418.  
  419.    mov      eax, rxfd_status
  420.    sub      eax, OS_BASE
  421.    mov      [rxfd_link], eax
  422.  
  423.    mov      eax, Ether_buffer
  424.    sub      eax, OS_BASE
  425.    mov      [rxfd_rx_buf_addr], eax
  426.  
  427.    mov      ax, 0
  428.    mov      [rxfd_count], ax
  429.  
  430.    mov      ax, 1528
  431.    mov      [rxfd_size], ax
  432.  
  433.    mov      edx, [io_addr]
  434.    add      edx, 4           ; SCBPointer
  435.  
  436.    mov      eax, rxfd_status
  437.    sub      eax, OS_BASE
  438.    out      dx, eax
  439.  
  440.    mov      edx, [io_addr]
  441.    add      edx, 2           ; SCBCmd
  442.  
  443.    mov      ax, 0x0101         ; INT_MASK | RX_START
  444.    out      dx, ax
  445.  
  446.    call     wait_for_cmd_done
  447.  
  448.    ; start the reciver
  449.  
  450.    mov      ax, 0
  451.    mov      [rxfd_status], ax
  452.  
  453.    mov      ax, 0xc000
  454.    mov      [rxfd_command], ax
  455.  
  456.    mov      edx, [io_addr]
  457.    add      edx, 4           ; SCBPointer
  458.  
  459.    mov      eax, rxfd_status
  460.    sub      eax, OS_BASE
  461.    out      dx, eax
  462.  
  463.    mov      edx, [io_addr]
  464.    add      edx, 2           ; SCBCmd
  465.  
  466.    mov      ax, 0x0101         ; INT_MASK | RX_START
  467.    out      dx, ax
  468.  
  469.    ; Init TX Stuff
  470.  
  471.    mov      edx, [io_addr]
  472.    add      edx, 4           ; SCBPointer
  473.  
  474.    mov      eax, 0
  475.    out      dx, eax
  476.  
  477.    mov      edx, [io_addr]
  478.    add      edx, 2           ; SCBCmd
  479.  
  480.    mov      ax, 0x0160         ; INT_MASK | CU_CMD_BASE
  481.    out      dx, ax
  482.  
  483.    call     wait_for_cmd_done
  484.  
  485.    ; Set TX Base address
  486.  
  487.    ; First, set up confcmd values
  488.  
  489.    mov      ax, 2
  490.    mov      [confcmd_command], ax
  491.    mov      eax, txfd
  492.    sub      eax, OS_BASE
  493.    mov      [confcmd_link], eax
  494.  
  495.    mov      ax, 1
  496.    mov      [txfd_command], ax         ; CmdIASetup
  497.  
  498.    mov      ax, 0
  499.    mov      [txfd_status], ax
  500.  
  501.    mov      eax, confcmd
  502.    sub      eax, OS_BASE
  503.    mov      [txfd_link], eax
  504.  
  505.  
  506.  
  507.    ; ETH_ALEN is 6 bytes
  508.  
  509.    mov      esi, eeprom_data
  510.    mov      edi, node_addr
  511.    mov      ecx, 3
  512. drp000:
  513.    mov      eax, [esi]
  514.    mov      [edi], al
  515.    shr      eax, 8
  516.    inc      edi
  517.    mov      [edi], al
  518.    inc      edi
  519.    add      esi, 4
  520.    loop     drp000
  521.  
  522.    ; Hard code your MAC address into node_addr at this point,
  523.    ; If you cannot read the MAC address from the eeprom in the previous step.
  524.    ; You also have to write the mac address into txfd_tx_desc_addr, rather
  525.    ; than taking data from eeprom_data
  526.  
  527.    mov      esi, eeprom_data
  528.    mov      edi, txfd_tx_desc_addr
  529.    mov      ecx, 3
  530. drp001:
  531.    mov      eax, [esi]
  532.    mov      [edi], al
  533.    shr      eax, 8
  534.    inc      edi
  535.    mov      [edi], al
  536.    inc      edi
  537.    add      esi, 4
  538.    loop     drp001
  539.  
  540.  
  541.    mov      esi, eeprom_data + (6 * 4)
  542.    mov      eax, [esi]
  543.    shr      eax, 8
  544.    and      eax, 0x3f
  545.    cmp      eax, 4            ; DP83840
  546.    je       drp002
  547.    cmp      eax, 10            ; DP83840A
  548.    je       drp002
  549.    jmp      drp003
  550.  
  551. drp002:
  552.    mov      ebx, [esi]
  553.    and      ebx, 0x1f
  554.    push     ebx
  555.    mov      ecx, 23
  556.    call     mdio_read
  557.    pop      ebx
  558.    or       eax, 0x0422
  559.    mov      ecx, 23
  560.    mov      edx, eax
  561.    call     mdio_write
  562.  
  563. drp003:
  564.    mov      ax, 0x4002         ; Cmdsuspend | CmdConfigure
  565.    mov      [confcmd_command], ax
  566.    mov      ax, 0
  567.    mov      [confcmd_status], ax
  568.    mov      eax, txfd
  569.    mov      [confcmd_link], eax
  570.    mov      ebx, confcmd_data
  571.    mov      al, 0x88         ; fifo of 8 each
  572.    mov      [ebx + 1], al
  573.    mov      al, 0
  574.    mov      [ebx + 4], al
  575.    mov      al, 0x80
  576.    mov      [ebx + 5], al
  577.    mov      al, 0x48
  578.    mov      [ebx + 15], al
  579.    mov      al, 0x80
  580.    mov      [ebx + 19], al
  581.    mov      al, 0x05
  582.    mov      [ebx + 21], al
  583.  
  584.    mov      eax, txfd
  585.    sub      eax, OS_BASE
  586.    mov      edx, [io_addr]
  587.    add      edx, 4            ; SCBPointer
  588.    out      dx, eax
  589.  
  590.    mov      eax, 0x0110         ; INT_MASK | CU_START
  591.    mov      edx, [io_addr]
  592.    add      edx, 2            ; SCBCmd
  593.    out      dx, ax
  594.  
  595.    call     wait_for_cmd_done
  596. jmp skip
  597.  
  598.    ; wait for thing to start
  599. drp004:
  600.    mov      ax, [txfd_status]
  601.    cmp      ax, 0
  602.    je       drp004
  603.  
  604. skip:
  605.    ; Indicate that we have successfully reset the card
  606.    mov      eax, [pci_data]
  607.    mov      [eth_status], eax
  608.  
  609. I8255x_exit:
  610.    ret
  611.  
  612.  
  613.  
  614. ;***************************************************************************
  615. ;   Function
  616. ;      I8255x_reset
  617. ;   Description
  618. ;      Place the chip (ie, the ethernet card) into a virgin state
  619. ;      No inputs
  620. ;      All registers destroyed
  621. ;
  622. ;***************************************************************************
  623. I8255x_reset:
  624.    ret
  625.  
  626.  
  627.  
  628. ;***************************************************************************
  629. ; Function
  630. ;    I8255x_poll
  631. ;
  632. ; Description
  633. ;    Polls the ethernet card for a received packet
  634. ;    Received data, if any, ends up in Ether_buffer
  635. ;
  636. ;***************************************************************************
  637. I8255x_poll:
  638.    mov      ax, 0      ; assume no data
  639.    mov      [eth_rx_data_len], ax
  640.  
  641.    mov      ax, [rxfd_status]
  642.    cmp      ax, 0
  643.    je       i8p_exit
  644.  
  645.    mov      ax, 0
  646.    mov      [rxfd_status], ax
  647.  
  648.    mov      ax, 0xc000
  649.    mov      [rxfd_command], ax
  650.  
  651.    mov      edx, [io_addr]
  652.    add      edx, 4           ; SCBPointer
  653.  
  654.    mov      eax, rxfd_status
  655.    sub      eax, OS_BASE
  656.    out      dx, eax
  657.  
  658.    mov      edx, [io_addr]
  659.    add      edx, 2           ; SCBCmd
  660.  
  661.    mov      ax, 0x0101         ; INT_MASK | RX_START
  662.    out      dx, ax
  663.  
  664.    call     wait_for_cmd_done
  665.  
  666.    mov      esi, rxfd_packet
  667.    mov      edi, Ether_buffer
  668.    mov      ecx, 1518
  669.    cld
  670.    rep      movsb
  671.  
  672.    mov      ax, [rxfd_count]
  673.    and      ax, 0x3fff
  674.    mov      [eth_rx_data_len], ax
  675.  
  676. i8p_exit:
  677.    ret
  678.  
  679.  
  680.  
  681. ;***************************************************************************
  682. ;   Function
  683. ;      I8255x_transmit
  684. ;
  685. ;   Description
  686. ;       Transmits a packet of data via the ethernet card
  687. ;          Pointer to 48 bit destination address in edi
  688. ;         Type of packet in bx
  689. ;         size of packet in ecx
  690. ;         pointer to packet data in esi
  691. ;
  692. ;***************************************************************************
  693. I8255x_transmit:
  694.  
  695.    mov      [hdr_type], bx
  696.  
  697.    mov      eax, [edi]
  698.    mov      [hdr_dst_addr], eax
  699.    mov      ax, [edi+4]
  700.    mov      [hdr_dst_addr+4], ax
  701.  
  702.    mov      eax, [node_addr]
  703.    mov      [hdr_src_addr], eax
  704.    mov      ax, [node_addr+4]
  705.    mov      [hdr_src_addr+4], ax
  706.  
  707.    mov      edx, [io_addr]
  708.    in       ax, dx
  709.    and      ax, 0xfc00
  710.    out      dx, ax
  711.  
  712.    xor      ax, ax
  713.    mov      [txfd_status], ax
  714.    mov      ax, 0x400C            ; Cmdsuspend | CmdTx | CmdTxFlex
  715.    mov      [txfd_command], ax
  716.    mov      eax, txfd
  717.    mov      [txfd_link], eax
  718.    mov      eax, 0x02208000
  719.    mov      [txfd_count], eax
  720.    mov      eax, txfd_tx_buf_addr0
  721.    sub      eax, OS_BASE
  722.    mov      [txfd_tx_desc_addr], eax
  723.    mov      eax, hdr
  724.    sub      eax, OS_BASE
  725.    mov      [txfd_tx_buf_addr0], eax
  726.    mov      eax, 14   ; sizeof hdr
  727.    mov      [txfd_tx_buf_size0], eax
  728.  
  729.    ; Copy the buffer address and size in
  730.    mov      eax, esi
  731.    sub      eax, OS_BASE
  732.    mov      [txfd_tx_buf_addr1], eax
  733.    mov      eax, ecx
  734.    mov      [txfd_tx_buf_size1], eax
  735.  
  736.    mov      eax, txfd
  737.    sub      eax, OS_BASE
  738.    mov      edx, [io_addr]
  739.    add      edx, 4            ; SCBPointer
  740.    out      dx, eax
  741.  
  742.    mov      ax, 0x0110         ; INT_MASK | CU_START
  743.    mov      edx, [io_addr]
  744.    add      edx, 2            ; SCBCmd
  745.    out      dx, ax
  746.  
  747.    call     wait_for_cmd_done
  748.  
  749.    mov      edx, [io_addr]
  750.    in       ax, dx
  751.  
  752. I8t_001:
  753.    mov      ax, [txfd_status]
  754.    cmp      ax, 0
  755.    je       I8t_001
  756.  
  757.    mov      edx, [io_addr]
  758.    in       ax, dx
  759.  
  760.    ret