Subversion Repositories Kolibri OS

Rev

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

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