Subversion Repositories Kolibri OS

Rev

Rev 431 | 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. $Revision: 593 $
  9.  
  10.  
  11. ;; Copyright (c) 2004, Endre Kozma <endre.kozma@axelero.hu>
  12. ;; All rights reserved.
  13. ;;
  14. ;; Redistribution  and  use  in  source  and  binary  forms, with or without
  15. ;; modification, are permitted provided  that  the following  conditions are
  16. ;; met:
  17. ;;
  18. ;; 1. Redistributions of source code must retain the above  copyright notice,
  19. ;;    this list of conditions and the following disclaimer.
  20. ;;
  21. ;; 2. Redistributions  in  binary form  must  reproduce  the above copyright
  22. ;;    notice, this  list of conditions  and the  following disclaimer in the
  23. ;;    documentation and/or other  materials  provided with  the distribution.
  24. ;;
  25. ;; 3. The name of the author may not be used to  endorse or promote products
  26. ;;    derived from this software without  specific prior  written permission.
  27. ;;
  28. ;; THIS SOFTWARE IS  PROVIDED  BY  THE  AUTHOR  ``AS IS'' AND ANY EXPRESS OR
  29. ;; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30. ;; OF  MERCHANTABILITY AND FITNESS  FOR A PARTICULAR  PURPOSE ARE DISCLAIMED.
  31. ;; IN  NO  EVENT  SHALL  THE  AUTHOR  BE  LIABLE  FOR  ANY  DIRECT, INDIRECT,
  32. ;; INCIDENTAL, SPECIAL, EXEMPLARY, OR  CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  33. ;; NOT LIMITED TO, PROCUREMENT OF  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  34. ;; DATA, OR  PROFITS; OR  BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON ANY
  35. ;; THEORY OF  LIABILITY, WHETHER IN  CONTRACT,  STRICT  LIABILITY,  OR  TORT
  36. ;; (INCLUDING NEGLIGENCE OR OTHERWISE)  ARISING IN ANY WAY OUT OF THE USE OF
  37. ;; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38.  
  39. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  40. ;;                                                                         ;;
  41. ;;  3C59X.INC                                                              ;;
  42. ;;                                                                         ;;
  43. ;;  Ethernet driver for Menuet OS                                          ;;
  44. ;;                                                                         ;;
  45. ;;  Driver for 3Com fast etherlink 3c59x and                               ;;
  46. ;;         etherlink XL 3c900 and 3c905 cards                              ;;
  47. ;;  References:                                                            ;;
  48. ;;    www.3Com.com - data sheets                                           ;;
  49. ;;    DP83840A.pdf - ethernet physical layer                               ;;
  50. ;;    3c59x.c - linux driver                                               ;;
  51. ;;    ethernet driver template by Mike Hibbett                             ;;
  52. ;;                                                                         ;;
  53. ;;  Credits                                                                ;;
  54. ;;   Mike Hibbett,                                                         ;;
  55. ;;         who kindly supplied me with a 3Com905C-TX-M card                ;;
  56. ;;                                                                         ;;
  57. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  58. ;;  History
  59. ;;  =======
  60. ;;  $Log: 3C59X.INC,v $
  61. ;;  Revision 1.3  2004/07/11 12:21:12  kozma
  62. ;;  Support of vortex chips (3c59x) added.
  63. ;;  Support of 3c920 and 3c982 added.
  64. ;;  Corrections.
  65. ;;
  66. ;;  Revision 1.2  2004/06/12 19:40:20  kozma
  67. ;;  Function e3c59x_set_available_media added in order to set
  68. ;;  the default media in case auto detection finds no valid link.
  69. ;;  Incorrect mii check removed (3c900 Cyclone works now).
  70. ;;  Cleanups.
  71. ;;
  72. ;;  Revision 1.1  2004/06/12 18:27:15  kozma
  73. ;;  Initial revision
  74. ;;
  75. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  76.  
  77. ; comment the next line out if you don't want debug info printed
  78. ; on the debug board. This option adds a lot of bytes to the driver
  79. ; so it's worth to comment it out.
  80. ;        E3C59X_DEBUG    equ 1
  81.  
  82. ; forcing full duplex mode makes sense at some cards and link types
  83.         E3C59X_FORCE_FD equ 1
  84.  
  85. macro virt_to_dma reg
  86. {
  87. if defined E3C59X_LINUX
  88.         sub     reg, [virt_addr]
  89.         add     reg, [dma_addr]
  90. end if
  91. }
  92.  
  93. macro dma_to_virt reg
  94. {
  95. if defined E3C59X_LINUX
  96.         sub     reg, [dma_addr]
  97.         add     reg, [virt_addr]
  98. end if
  99. }
  100.  
  101. macro zero_to_virt reg
  102. {
  103. if defined E3C59X_LINUX
  104.         add     reg, [virt_addr]
  105. end if
  106. }
  107.  
  108. macro virt_to_zero reg
  109. {
  110. if defined E3C59X_LINUX
  111.         sub     reg, [virt_addr]
  112. end if
  113. }
  114.  
  115. macro zero_to_dma reg
  116. {
  117. if defined E3C59X_LINUX
  118.         add     reg, [dma_addr]
  119. end if
  120. }
  121.  
  122. macro dma_to_zero reg
  123. {
  124. if defined E3C59X_LINUX
  125.         sub     reg, [dma_addr]
  126. end if
  127. }
  128.  
  129. macro strtbl name, [string]
  130. {
  131. common
  132.         label name dword
  133. forward
  134.         local label
  135.         dd label
  136. forward
  137.         label db string, 0
  138. }
  139.  
  140. ; Ethernet frame symbols
  141.         ETH_ALEN                       equ 6
  142.         ETH_HLEN                       equ (2*ETH_ALEN+2)
  143.         ETH_ZLEN                       equ 60 ; 60 + 4bytes auto payload for
  144.                                               ; mininmum 64bytes frame length
  145. ; PCI programming
  146.         PCI_REG_COMMAND                equ 0x4 ; command register
  147.         PCI_REG_STATUS                 equ 0x6 ; status register
  148.         PCI_REG_LATENCY                equ 0xd ; latency timer register
  149.         PCI_REG_CAP_PTR                equ 0x34 ; capabilities pointer
  150.         PCI_REG_CAPABILITY_ID          equ 0x0 ; capapility ID in pm register block
  151.         PCI_REG_PM_STATUS              equ 0x4 ; power management status register
  152.         PCI_REG_PM_CTRL                equ 0x4 ; power management control register
  153.         PCI_BIT_PIO                    equ 0 ; bit0: io space control
  154.         PCI_BIT_MMIO                   equ 1 ; bit1: memory space control
  155.         PCI_BIT_MASTER                 equ 2 ; bit2: device acts as a PCI master
  156. ; Registers
  157.         E3C59X_REG_POWER_MGMT_CTRL     equ 0x7c
  158.         E3C59X_REG_UP_LIST_PTR         equ 0x38
  159.         E3C59X_REG_UP_PKT_STATUS       equ 0x30
  160.         E3C59X_REG_TX_FREE_THRESH      equ 0x2f
  161.         E3C59X_REG_DN_LIST_PTR         equ 0x24
  162.         E3C59X_REG_DMA_CTRL            equ 0x20
  163.         E3C59X_REG_TX_STATUS           equ 0x1b
  164.         E3C59X_REG_RX_STATUS           equ 0x18
  165.         E3C59X_REG_TX_DATA             equ 0x10
  166. ; Common window registers
  167.         E3C59X_REG_INT_STATUS          equ 0xe
  168.         E3C59X_REG_COMMAND             equ 0xe
  169. ; Register window 7
  170.         E3C59X_REG_MASTER_STATUS       equ 0xc
  171.         E3C59X_REG_POWER_MGMT_EVENT    equ 0xc
  172.         E3C59X_REG_MASTER_LEN          equ 0x6
  173.         E3C59X_REG_VLAN_ETHER_TYPE     equ 0x4
  174.         E3C59X_REG_VLAN_MASK           equ 0x0
  175.         E3C59X_REG_MASTER_ADDRESS      equ 0x0
  176. ; Register window 6
  177.         E3C59X_REG_BYTES_XMITTED_OK    equ 0xc
  178.         E3C59X_REG_BYTES_RCVD_OK       equ 0xa
  179.         E3C59X_REG_UPPER_FRAMES_OK     equ 0x9
  180.         E3C59X_REG_FRAMES_DEFERRED     equ 0x8
  181.         E3C59X_REG_FRAMES_RCVD_OK      equ 0x7
  182.         E3C59X_REG_FRAMES_XMITTED_OK   equ 0x6
  183.         E3C59X_REG_RX_OVERRUNS         equ 0x5
  184.         E3C59X_REG_LATE_COLLISIONS     equ 0x4
  185.         E3C59X_REG_SINGLE_COLLISIONS   equ 0x3
  186.         E3C59X_REG_MULTIPLE_COLLISIONS equ 0x2
  187.         E3C59X_REG_SQE_ERRORS          equ 0x1
  188.         E3C59X_REG_CARRIER_LOST        equ 0x0
  189. ; Register window 5
  190.         E3C59X_REG_INDICATION_ENABLE   equ 0xc
  191.         E3C59X_REG_INTERRUPT_ENABLE    equ 0xa
  192.         E3C59X_REG_TX_RECLAIM_THRESH   equ 0x9
  193.         E3C59X_REG_RX_FILTER           equ 0x8
  194.         E3C59X_REG_RX_EARLY_THRESH     equ 0x6
  195.         E3C59X_REG_TX_START_THRESH     equ 0x0
  196. ; Register window 4
  197.         E3C59X_REG_UPPER_BYTES_OK      equ 0xe
  198.         E3C59X_REG_BAD_SSD             equ 0xc
  199.         E3C59X_REG_MEDIA_STATUS        equ 0xa
  200.         E3C59X_REG_PHYSICAL_MGMT       equ 0x8
  201.         E3C59X_REG_NETWORK_DIAGNOSTIC  equ 0x6
  202.         E3C59X_REG_FIFO_DIAGNOSTIC     equ 0x4
  203.         E3C59X_REG_VCO_DIAGNOSTIC      equ 0x2 ; may not supported
  204. ; Bits in register window 4
  205.         E3C59X_BIT_AUTOSELECT          equ 24
  206. ; Register window 3
  207.         E3C59X_REG_TX_FREE             equ 0xc
  208.         E3C59X_REG_RX_FREE             equ 0xa
  209.         E3C59X_REG_MEDIA_OPTIONS       equ 0x8
  210.         E3C59X_REG_MAC_CONTROL         equ 0x6
  211.         E3C59X_REG_MAX_PKT_SIZE        equ 0x4
  212.         E3C59X_REG_INTERNAL_CONFIG     equ 0x0
  213. ; Register window 2
  214.         E3C59X_REG_RESET_OPTIONS       equ 0xc
  215.         E3C59X_REG_STATION_MASK_HI     equ 0xa
  216.         E3C59X_REG_STATION_MASK_MID    equ 0x8
  217.         E3C59X_REG_STATION_MASK_LO     equ 0x6
  218.         E3C59X_REG_STATION_ADDRESS_HI  equ 0x4
  219.         E3C59X_REG_STATION_ADDRESS_MID equ 0x2
  220.         E3C59X_REG_STATION_ADDRESS_LO  equ 0x0
  221. ; Register window 1
  222.         E3C59X_REG_TRIGGER_BITS        equ 0xc
  223.         E3C59X_REG_SOS_BITS            equ 0xa
  224.         E3C59X_REG_WAKE_ON_TIMER       equ 0x8
  225.         E3C59X_REG_SMB_RXBYTES         equ 0x7
  226.         E3C59X_REG_SMB_DIAG            equ 0x5
  227.         E3C59X_REG_SMB_ARB             equ 0x4
  228.         E3C59X_REG_SMB_STATUS          equ 0x2
  229.         E3C59X_REG_SMB_ADDRESS         equ 0x1
  230.         E3C59X_REG_SMB_FIFO_DATA       equ 0x0
  231. ; Register window 0
  232.         E3C59X_REG_EEPROM_DATA         equ 0xc
  233.         E3C59X_REG_EEPROM_COMMAND      equ 0xa
  234.         E3C59X_REG_BIOS_ROM_DATA       equ 0x8
  235.         E3C59X_REG_BIOS_ROM_ADDR       equ 0x4
  236. ; Physical management bits
  237.         E3C59X_BIT_MGMT_DIR            equ 2 ; drive with the data written in mgmtData
  238.         E3C59X_BIT_MGMT_DATA           equ 1 ; MII management data bit
  239.         E3C59X_BIT_MGMT_CLK            equ 0 ; MII management clock
  240. ; MII commands
  241.         E3C59X_MII_CMD_MASK            equ (1111b shl 10)
  242.         E3C59X_MII_CMD_READ            equ (0110b shl 10)
  243.         E3C59X_MII_CMD_WRITE           equ (0101b shl 10)
  244. ; MII registers
  245.         E3C59X_REG_MII_BMCR            equ 0 ; basic mode control register
  246.         E3C59X_REG_MII_BMSR            equ 1 ; basic mode status register
  247.         E3C59X_REG_MII_ANAR            equ 4 ; auto negotiation advertisement register
  248.         E3C59X_REG_MII_ANLPAR          equ 5 ; auto negotiation link partner ability register
  249.         E3C59X_REG_MII_ANER            equ 6 ; auto negotiation expansion register
  250. ; MII bits
  251.         E3C59X_BIT_MII_AUTONEG_COMPLETE     equ 5 ; auto-negotiation complete
  252.         E3C59X_BIT_MII_PREAMBLE_SUPPRESSION equ 6
  253. ; eeprom bits and commands
  254.         E3C59X_EEPROM_CMD_READ         equ 0x80
  255.         E3C59X_EEPROM_BIT_BUSY         equ 15
  256. ; eeprom registers
  257.         E3C59X_EEPROM_REG_OEM_NODE_ADDR equ 0xa
  258.         E3C59X_EEPROM_REG_CAPABILITIES  equ 0x10
  259. ; Commands for command register
  260.         E3C59X_SELECT_REGISTER_WINDOW  equ (1 shl 11)
  261.  
  262.         IS_VORTEX                      equ 0x1
  263.         IS_BOOMERANG                   equ 0x2
  264.         IS_CYCLONE                     equ 0x4
  265.         IS_TORNADO                     equ 0x8
  266.         EEPROM_8BIT                    equ 0x10
  267.         HAS_PWR_CTRL                   equ 0x20
  268.         HAS_MII                        equ 0x40
  269.         HAS_NWAY                       equ 0x80
  270.         HAS_CB_FNS                     equ 0x100
  271.         INVERT_MII_PWR                 equ 0x200
  272.         INVERT_LED_PWR                 equ 0x400
  273.         MAX_COLLISION_RESET            equ 0x800
  274.         EEPROM_OFFSET                  equ 0x1000
  275.         HAS_HWCKSM                     equ 0x2000
  276.         EXTRA_PREAMBLE                 equ 0x4000
  277.  
  278. iglobal
  279.         align 4
  280. e3c59x_hw_versions:
  281.         dw 0x5900, IS_VORTEX ; 3c590 Vortex 10Mbps
  282.         dw 0x5920, IS_VORTEX ; 3c592 EISA 10Mbps Demon/Vortex
  283.         dw 0x5970, IS_VORTEX ; 3c597 EISA Fast Demon/Vortex
  284.         dw 0x5950, IS_VORTEX ; 3c595 Vortex 100baseTx
  285.         dw 0x5951, IS_VORTEX ; 3c595 Vortex 100baseT4
  286.         dw 0x5952, IS_VORTEX ; 3c595 Vortex 100base-MII
  287.         dw 0x9000, IS_BOOMERANG ; 3c900 Boomerang 10baseT
  288.         dw 0x9001, IS_BOOMERANG ; 3c900 Boomerang 10Mbps Combo
  289.         dw 0x9004, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c900 Cyclone 10Mbps TPO
  290.         dw 0x9005, IS_CYCLONE or HAS_HWCKSM ; 3c900 Cyclone 10Mbps Combo
  291.         dw 0x9006, IS_CYCLONE or HAS_HWCKSM ; 3c900 Cyclone 10Mbps TPC
  292.         dw 0x900A, IS_CYCLONE or HAS_HWCKSM ; 3c900B-FL Cyclone 10base-FL
  293.         dw 0x9050, IS_BOOMERANG or HAS_MII ; 3c905 Boomerang 100baseTx
  294.         dw 0x9051, IS_BOOMERANG or HAS_MII ; 3c905 Boomerang 100baseT4
  295.         dw 0x9055, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE ; 3c905B Cyclone 100baseTx
  296.         dw 0x9058, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c905B Cyclone 10/100/BNC
  297.         dw 0x905A, IS_CYCLONE or HAS_HWCKSM ; 3c905B-FX Cyclone 100baseFx
  298.         dw 0x9200, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c905C Tornado
  299.         dw 0x9800, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c980 Cyclone
  300.         dw 0x9805, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c982 Dual Port Server Cyclone
  301.         dw 0x7646, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3cSOHO100-TX Hurricane
  302.         dw 0x5055, IS_CYCLONE or EEPROM_8BIT or HAS_HWCKSM ; 3c555 Laptop Hurricane
  303.         dw 0x6055, IS_TORNADO or HAS_NWAY or EEPROM_8BIT or HAS_CB_FNS \
  304.                               or INVERT_MII_PWR or HAS_HWCKSM ; 3c556 Laptop Tornado
  305.         dw 0x6056, IS_TORNADO or HAS_NWAY or EEPROM_OFFSET or HAS_CB_FNS \
  306.                               or INVERT_MII_PWR or HAS_HWCKSM ; 3c556B Laptop Hurricane
  307.         dw 0x5b57, IS_BOOMERANG or HAS_MII or EEPROM_8BIT ; 3c575 [Megahertz] 10/100 LAN CardBus
  308.         dw 0x5057, IS_BOOMERANG or HAS_MII or EEPROM_8BIT ; 3c575 Boomerang CardBus
  309.         dw 0x5157, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT \
  310.                               or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFE575BT Cyclone CardBus
  311.         dw 0x5257, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \
  312.                               or MAX_COLLISION_RESET or HAS_HWCKSM ; 3CCFE575CT Tornado CardBus
  313.         dw 0x6560, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \
  314.                               or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFE656 Cyclone CardBus
  315.         dw 0x6562, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \
  316.                               or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFEM656B Cyclone+Winmodem CardBus
  317.         dw 0x6564, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \
  318.                               or MAX_COLLISION_RESET or HAS_HWCKSM ; 3CXFEM656C Tornado+Winmodem CardBus
  319.         dw 0x4500, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c450 HomePNA Tornado
  320.         dw 0x9201, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c920 Tornado
  321.         dw 0x1201, IS_TORNADO or HAS_HWCKSM or HAS_NWAY ; 3c982 Hydra Dual Port A
  322.         dw 0x1202, IS_TORNADO or HAS_HWCKSM or HAS_NWAY ; 3c982 Hydra Dual Port B
  323.         dw 0x9056, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE ; 3c905B-T4
  324.         dw 0x9210, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c920B-EMB-WNM Tornado
  325. E3C59X_HW_VERSIONS_SIZE= $-e3c59x_hw_versions
  326. endg
  327.  
  328. ; RX/TX buffers sizes
  329.         E3C59X_MAX_ETH_PKT_SIZE      equ 1536 ; max packet size
  330.         E3C59X_NUM_RX_DESC           equ 4 ; a power of 2 number
  331.         E3C59X_NUM_TX_DESC           equ 4 ; a power of 2 number
  332.         E3C59X_RX_BUFFER_SIZE        equ (E3C59X_MAX_ETH_FRAME_SIZE*E3C59X_NUM_RX_DESC)
  333.         E3C59X_TX_BUFFER_SIZE        equ (E3C59X_MAX_ETH_FRAME_SIZE*E3C59X_NUM_TX_DESC)
  334. ; Download Packet Descriptor
  335.         E3C59X_DPD_DN_NEXT_PTR       equ 0
  336.         E3C59X_DPD_FRAME_START_HDR   equ 4
  337.         E3C59X_DPD_DN_FRAG_ADDR      equ 8 ; for packet data
  338.         E3C59X_DPD_DN_FRAG_LEN       equ 12 ; for packet data
  339.         E3C59X_DPD_SIZE              equ 16 ; a power of 2 number
  340. ; Upload Packet Descriptor
  341.         E3C59X_UPD_UP_NEXT_PTR       equ 0
  342.         E3C59X_UPD_PKT_STATUS        equ 4
  343.         E3C59X_UPD_UP_FRAG_ADDR      equ 8 ; for packet data
  344.         E3C59X_UPD_UP_FRAG_LEN       equ 12 ; for packet data
  345.         E3C59X_UPD_SIZE              equ 16
  346.  
  347. ; RX/TX buffers
  348. if defined E3C59X_LINUX
  349.         E3C59X_MAX_ETH_FRAME_SIZE = 160 ; size of ethernet frame + bytes alignment
  350.         e3c59x_rx_buff = 0
  351. else
  352.         E3C59X_MAX_ETH_FRAME_SIZE = 1520 ; size of ethernet frame + bytes alignment
  353.         e3c59x_rx_buff = eth_data_start
  354. end if
  355.  
  356.         e3c59x_tx_buff = e3c59x_rx_buff+E3C59X_RX_BUFFER_SIZE
  357.         e3c59x_dpd_buff = e3c59x_tx_buff+E3C59X_TX_BUFFER_SIZE
  358.         e3c59x_upd_buff = e3c59x_dpd_buff+(E3C59X_DPD_SIZE*E3C59X_NUM_TX_DESC)
  359.  
  360. uglobal
  361. e3c59x_curr_upd: dd 0
  362. e3c59x_prev_dpd: dd 0
  363. e3c59x_prev_tx_frame: dd 0
  364. e3c59x_transmit_function: dd 0
  365. e3c59x_receive_function: dd 0
  366. endg
  367.  
  368. iglobal
  369. e3c59x_ver_id: db 17
  370. endg
  371. uglobal
  372. e3c59x_full_bus_master: db 0
  373. e3c59x_has_hwcksm:  db 0
  374. e3c59x_preamble: db 0
  375. e3c59x_dn_list_ptr_cleared: db 0
  376. e3c59x_self_directed_packet: rb 6
  377. endg
  378.  
  379. if defined E3C59X_DEBUG
  380. e3c59x_hw_type_str: db "Detected hardware type  : ", 0
  381. e3c59x_device_str: db  "Device ID               : 0x"
  382. e3c59x_device_id_str: db "ffff", 13, 10, 0
  383. e3c59x_vendor_str: db  "Vendor ID               : 0x"
  384. e3c59x_vendor_id_str: db "ffff", 13, 10, 0
  385. e3c59x_io_info_str: db "IO address              : 0x"
  386. e3c59x_io_addr_str: db "ffff", 13, 10, 0
  387. e3c59x_mac_info_str: db "MAC address             : "
  388. e3c59x_mac_addr_str: db "ff:ff:ff:ff:ff:ff", 13, 10, 0
  389. e3c59x_boomerang_str: db " (boomerang)", 13, 10, 0
  390. e3c59x_vortex_str: db " (vortex)", 13, 10, 0
  391. e3c59x_link_type_str: db "Established link type   : ", 0
  392. e3c59x_new_line_str: db 13, 10, 0
  393. e3c59x_link_type: dd 0
  394.  
  395. e3c59x_charset: db '0123456789abcdef'
  396.  
  397. strtbl e3c59x_link_str, \
  398.         "No valid link type detected", \
  399.         "10BASE-T half duplex", \
  400.         "10BASE-T full-duplex", \
  401.         "100BASE-TX half duplex", \
  402.         "100BASE-TX full duplex", \
  403.         "100BASE-T4", \
  404.         "100BASE-FX", \
  405.         "10Mbps AUI", \
  406.         "10Mbps COAX (BNC)", \
  407.         "miiDevice - not supported"
  408.  
  409. strtbl e3c59x_hw_str, \
  410.         "3c590 Vortex 10Mbps", \
  411.         "3c592 EISA 10Mbps Demon/Vortex", \
  412.         "3c597 EISA Fast Demon/Vortex", \
  413.         "3c595 Vortex 100baseTx", \
  414.         "3c595 Vortex 100baseT4", \
  415.         "3c595 Vortex 100base-MII", \
  416.         "3c900 Boomerang 10baseT", \
  417.         "3c900 Boomerang 10Mbps Combo", \
  418.         "3c900 Cyclone 10Mbps TPO", \
  419.         "3c900 Cyclone 10Mbps Combo", \
  420.         "3c900 Cyclone 10Mbps TPC", \
  421.         "3c900B-FL Cyclone 10base-FL", \
  422.         "3c905 Boomerang 100baseTx", \
  423.         "3c905 Boomerang 100baseT4", \
  424.         "3c905B Cyclone 100baseTx", \
  425.         "3c905B Cyclone 10/100/BNC", \
  426.         "3c905B-FX Cyclone 100baseFx", \
  427.         "3c905C Tornado", \
  428.         "3c980 Cyclone", \
  429.         "3c982 Dual Port Server Cyclone", \
  430.         "3cSOHO100-TX Hurricane", \
  431.         "3c555 Laptop Hurricane", \
  432.         "3c556 Laptop Tornado", \
  433.         "3c556B Laptop Hurricane", \
  434.         "3c575 [Megahertz] 10/100 LAN CardBus", \
  435.         "3c575 Boomerang CardBus", \
  436.         "3CCFE575BT Cyclone CardBus", \
  437.         "3CCFE575CT Tornado CardBus", \
  438.         "3CCFE656 Cyclone CardBus", \
  439.         "3CCFEM656B Cyclone+Winmodem CardBus", \
  440.         "3CXFEM656C Tornado+Winmodem CardBus", \
  441.         "3c450 HomePNA Tornado", \
  442.         "3c920 Tornado", \
  443.         "3c982 Hydra Dual Port A", \
  444.         "3c982 Hydra Dual Port B", \
  445.         "3c905B-T4", \
  446.         "3c920B-EMB-WNM Tornado"
  447.  
  448. end if ; defined E3C59X_DEBUG
  449.  
  450. ;***************************************************************************
  451. ;   Function
  452. ;      e3c59x_debug
  453. ;   Description
  454. ;      prints debug info to the debug board
  455. ;   Parameters
  456. ;      ebp - io_addr
  457. ;   Return value
  458. ;   Destroyed registers
  459. ;      eax, ebx, ecx, edx, edi, esi
  460. ;
  461. ;***************************************************************************
  462. if defined E3C59X_DEBUG
  463.         align 4
  464. e3c59x_debug:
  465.         pushad
  466. ; print device type
  467.         mov     esi, e3c59x_hw_type_str
  468.         call    sys_msg_board_str
  469.         movzx   ecx, byte [e3c59x_ver_id]
  470.         mov     esi, [e3c59x_hw_str+ecx*4]
  471.         call    sys_msg_board_str
  472.         mov     esi, e3c59x_boomerang_str
  473.         cmp     dword [e3c59x_transmit_function], e3c59x_boomerang_transmit
  474.         jz      .boomerang
  475.         mov     esi, e3c59x_vortex_str
  476. .boomerang:
  477.         call    sys_msg_board_str
  478. ; print device/vendor
  479.         mov     ax, [pci_data+2]
  480.         mov     cl, 2
  481.         mov     ebx, e3c59x_device_id_str
  482.         call    e3c59x_print_hex
  483.         mov     esi, e3c59x_device_str
  484.         call    sys_msg_board_str
  485.         mov     ax, [pci_data]
  486.         mov     cl, 2
  487.         mov     ebx, e3c59x_vendor_id_str
  488.         call    e3c59x_print_hex
  489.         mov     esi, e3c59x_vendor_str
  490.         call    sys_msg_board_str
  491. ; print io address
  492.         mov     ax, [io_addr]
  493.         mov     ebx, e3c59x_io_addr_str
  494.         mov     cl, 2
  495.         call    e3c59x_print_hex
  496.         mov     esi, e3c59x_io_info_str
  497.         call    sys_msg_board_str
  498. ; print MAC address
  499.         mov     ebx, e3c59x_mac_addr_str
  500.         xor     ecx, ecx
  501. .mac_loop:
  502.         push    ecx
  503.         mov     al, [node_addr+ecx]
  504.         mov     cl, 1
  505.         call    e3c59x_print_hex
  506.         inc     ebx
  507.         pop     ecx
  508.         inc     cl
  509.         cmp     cl, 6
  510.         jne     .mac_loop
  511.         mov     esi, e3c59x_mac_info_str
  512.         call    sys_msg_board_str
  513. ; print link type
  514.         mov     esi, e3c59x_link_type_str
  515.         call    sys_msg_board_str
  516.         xor     eax, eax
  517.         bsr     ax, word [e3c59x_link_type]
  518.         jz      @f
  519.         sub     ax, 4
  520. @@:
  521.         mov     esi, [e3c59x_link_str+eax*4]
  522.         call    sys_msg_board_str
  523.         mov     esi, e3c59x_new_line_str
  524.         call    sys_msg_board_str
  525.         popad
  526.         ret
  527.  
  528. ;***************************************************************************
  529. ;   Function
  530. ;      e3c59x_print_hex
  531. ;   Description
  532. ;      prints a hexadecimal value
  533. ;   Parameters
  534. ;      eax - value to be printed out
  535. ;      ebx - where to print
  536. ;       cl - value size (1, 2, 4)
  537. ;   Return value
  538. ;      ebx - end address after the print
  539. ;   Destroyed registers
  540. ;      eax, ebx
  541. ;
  542. ;***************************************************************************
  543.         align 4
  544. e3c59x_print_hex:
  545.         cmp     cl, 1
  546.         je      .print_byte
  547.         cmp     cl, 2
  548.         jz      .print_word
  549. .print_dword:
  550.         push    eax
  551.         bswap   eax
  552.         xchg    ah, al
  553.         call    .print_word
  554.         pop     eax
  555. .print_word:
  556.         push    eax
  557.         xchg    ah, al
  558.         call    .print_byte
  559.         pop     eax
  560. .print_byte:
  561.         movzx   eax, al
  562.         push    eax
  563.         and     al, 0xf0
  564.         shr     al, 4
  565.         mov     al, byte [eax+e3c59x_charset]
  566.         mov     [ebx], al
  567.         inc     ebx
  568.         pop     eax
  569.         and     al, 0x0f
  570.         mov     al, byte [eax+e3c59x_charset]
  571.         mov     [ebx], al
  572.         inc     ebx
  573.         ret
  574. end if ; defined E3C59X_DEBUG
  575.  
  576. ;***************************************************************************
  577. ;   Function
  578. ;      e3c59x_try_link_detect
  579. ;   Description
  580. ;      e3c59x_try_link_detect checks if link exists
  581. ;   Parameters
  582. ;      ebp - io_addr
  583. ;   Return value
  584. ;      al - 0 ; no link detected
  585. ;      al - 1 ; link detected
  586. ;   Destroyed registers
  587. ;      eax, ebx, ecx, edx, edi, esi
  588. ;
  589. ;***************************************************************************
  590.         align 4
  591. e3c59x_try_link_detect:
  592. ; download self-directed packet
  593.         mov     edi, node_addr
  594.         mov     bx, 0x0608 ; packet type
  595.         mov     esi, e3c59x_self_directed_packet
  596.         mov     ecx, 6 ; 6 + 6 + 2 + 6 = 20 bytes
  597.         call    dword [e3c59x_transmit_function]
  598. ; switch to register window 5
  599.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  600.         mov     ax, E3C59X_SELECT_REGISTER_WINDOW+5
  601.         out     dx, ax
  602. ; program RxFilter for promiscuous operation
  603.         mov     ax, (10000b shl 11)
  604.         lea     edx, [ebp+E3C59X_REG_RX_FILTER]
  605.         in      al, dx
  606.         or      al, 1111b
  607.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  608.         out     dx, ax
  609. ; switch to register window 4
  610.         mov     ax, E3C59X_SELECT_REGISTER_WINDOW+4
  611.         out     dx, ax
  612. ; check loop
  613.         xor     ebx, ebx
  614.         mov     ecx, 0xffff ; 65535 tries
  615. .loop:
  616.         push    ecx ebx
  617.         call    dword [e3c59x_receive_function]
  618.         pop     ebx ecx
  619.         test    al, al
  620.         jnz     .finish
  621. .no_packet_received:
  622. ; switch to register window 4
  623.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  624.         mov     ax, E3C59X_SELECT_REGISTER_WINDOW+4
  625.         out     dx, ax
  626. ; read linkbeatdetect
  627.         lea     edx, [ebp+E3C59X_REG_MEDIA_STATUS]
  628.         in      ax, dx
  629.         test    ah, 1000b ; test linkBeatDetect
  630.         jnz     .link_detected
  631.         xor     al, al
  632.         jmp     .finish
  633. .link_detected:
  634. ; test carrierSense
  635.         test    al, 100000b
  636.         jz      .no_carrier_sense
  637.         inc     ebx
  638. .no_carrier_sense:
  639.         dec     ecx
  640.         jns     .loop
  641. ; assume the link is good if 0 < ebx < 25 %
  642.         test    ebx, ebx
  643.         setnz   al
  644.         jz      .finish
  645.         cmp     ebx, 16384 ; 25%
  646.         setb    al
  647. .finish:
  648. if defined E3C59X_DEBUG
  649.         test    al, al
  650.         jz      @f
  651.         or      byte [e3c59x_link_type+1], 100b
  652. @@:
  653. end if ; defined E3C59X_DEBUG
  654.         ret
  655.  
  656. ;***************************************************************************
  657. ;   Function
  658. ;      e3c59x_try_phy
  659. ;   Description
  660. ;      e3c59x_try_phy checks the auto-negotiation function
  661. ;      in the PHY at PHY index. It can also be extended to
  662. ;      include link detection for non-IEEE 802.3u
  663. ;      auto-negotiation devices, for instance the BCM5000.
  664. ;   Parameters
  665. ;       ah - PHY index
  666. ;      ebp - io_addr
  667. ;   Return value
  668. ;      al - 0 link is auto-negotiated
  669. ;      al - 1 no link is auto-negotiated
  670. ;   Destroyed registers
  671. ;       eax, ebx, ecx, edx, esi
  672. ;
  673. ;***************************************************************************
  674.         align 4
  675. e3c59x_try_phy:
  676.         mov     al, E3C59X_REG_MII_BMCR
  677.         push    eax
  678.         call    e3c59x_mdio_read ; returns with window #4
  679.         or      ah, 0x80 ; software reset
  680.         mov     ebx, eax
  681.         pop     eax
  682.         push    eax
  683.         call    e3c59x_mdio_write ; returns with window #4
  684. ; wait for reset to complete
  685.         mov     esi, 2000 ; 2000ms = 2s
  686.         call    delay_ms
  687.         pop     eax
  688.         push    eax
  689.         call    e3c59x_mdio_read ; returns with window #4
  690.         test    ah, 0x80
  691.         jnz     .fail_finish
  692.         pop     eax
  693.         push    eax
  694. ; wait for a while after reset
  695.         mov     esi, 20 ; 20ms
  696.         call    delay_ms
  697.         pop     eax
  698.         push    eax
  699.         mov     al, E3C59X_REG_MII_BMSR
  700.         call    e3c59x_mdio_read ; returns with window #4
  701.         test    al, 1 ; extended capability supported?
  702.         jz      .no_ext_cap
  703. ; auto-neg capable?
  704.         test    al, 1000b
  705.         jz      .fail_finish ; not auto-negotiation capable
  706. ; auto-neg complete?
  707.         test    al, 100000b
  708.         jnz     .auto_neg_ok
  709. ; restart auto-negotiation
  710.         pop     eax
  711.         push    eax
  712.         mov     al, E3C59X_REG_MII_ANAR
  713.         push    eax
  714.         call    e3c59x_mdio_read ; returns with window #4
  715.         or      ax, (1111b shl 5) ; advertise only 10base-T and 100base-TX
  716.         mov     ebx, eax
  717.         pop     eax
  718.         call    e3c59x_mdio_write ; returns with window #4
  719.         pop     eax
  720.         push    eax
  721.         call    e3c59x_mdio_read ; returns with window #4
  722.         mov     ebx, eax
  723.         or      bh, 10010b ; restart auto-negotiation
  724.         pop     eax
  725.         push    eax
  726.         call    e3c59x_mdio_write ; returns with window #4
  727.         mov     esi, 4000 ; 4000ms = 4 seconds
  728.         call    delay_ms
  729.         pop     eax
  730.         push    eax
  731.         mov     al, E3C59X_REG_MII_BMSR
  732.         call    e3c59x_mdio_read ; returns with window #4
  733.         test    al, 100000b ; auto-neg complete?
  734.         jnz     .auto_neg_ok
  735.         jmp     .fail_finish
  736. .auto_neg_ok:
  737. ; compare advertisement and link partner ability registers
  738.         pop     eax
  739.         push    eax
  740.         mov     al, E3C59X_REG_MII_ANAR
  741.         call    e3c59x_mdio_read ; returns with window #4
  742.         xchg    eax, [esp]
  743.         mov     al, E3C59X_REG_MII_ANLPAR
  744.         call    e3c59x_mdio_read ; returns with window #4
  745.         pop     ebx
  746.         and     eax, ebx
  747.         and     eax, 1111100000b
  748.         push    eax
  749. if defined E3C59X_DEBUG
  750.         mov     word [e3c59x_link_type], ax
  751. end if ; defined E3C59X_DEBUG
  752. ; switch to register window 3
  753.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  754.         mov     ax, E3C59X_SELECT_REGISTER_WINDOW+3
  755.         out     dx, ax
  756. ; set full-duplex mode
  757.         lea     edx, [ebp+E3C59X_REG_MAC_CONTROL]
  758.         in      ax, dx
  759.         and     ax, not 0x120 ; clear full duplex and flow control
  760.         pop     ebx
  761.         test    ebx, (1010b shl 5) ; check for full-duplex
  762.         jz      .half_duplex
  763.         or      ax, 0x120 ; set full duplex and flow control
  764. .half_duplex:
  765.         out     dx, ax
  766.         mov     al, 1
  767.         ret
  768. .no_ext_cap:
  769. ; not yet implemented BCM5000
  770. .fail_finish:
  771.         pop     eax
  772.         xor     al, al
  773.         ret
  774.  
  775. ;***************************************************************************
  776. ;   Function
  777. ;      e3c59x_try_mii
  778. ;   Description
  779. ;      e3c59x_try_MII checks the on-chip auto-negotiation logic
  780. ;      or an off-chip MII PHY, depending upon what is set in
  781. ;      xcvrSelect by the caller.
  782. ;      It exits when it finds the first device with a good link.
  783. ;   Parameters
  784. ;      ebp - io_addr
  785. ;   Return value
  786. ;      al - 0
  787. ;      al - 1
  788. ;   Destroyed registers
  789. ;      eax, ebx, ecx, edx, esi
  790. ;
  791. ;***************************************************************************
  792.         align 4
  793. e3c59x_try_mii:
  794. ; switch to register window 3
  795.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  796.         mov     ax, E3C59X_SELECT_REGISTER_WINDOW+3
  797.         out     dx, ax
  798.         lea     edx, [ebp+E3C59X_REG_INTERNAL_CONFIG]
  799.         in      eax, dx
  800.         and     eax, (1111b shl 20)
  801.         cmp     eax, (1000b shl 20) ; is auto-negotiation set?
  802.         jne     .mii_device
  803. ; auto-negotiation is set
  804. ; switch to register window 4
  805.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  806.         mov     ax, E3C59X_SELECT_REGISTER_WINDOW+4
  807.         out     dx, ax
  808. ; PHY==24 is the on-chip auto-negotiation logic
  809. ; it supports only 10base-T and 100base-TX
  810.         mov     ah, 24
  811.         call    e3c59x_try_phy
  812.         test    al, al
  813.         jz      .fail_finish
  814.         mov     cl, 24
  815.         jmp     .check_preamble
  816. .mii_device:
  817.         cmp     eax, (0110b shl 20)
  818.         jne     .fail_finish
  819.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  820.         mov     ax, E3C59X_SELECT_REGISTER_WINDOW+4
  821.         out     dx, ax
  822.         lea     edx, [ebp+E3C59X_REG_PHYSICAL_MGMT]
  823.         in      ax, dx
  824.         and     al, (1 shl E3C59X_BIT_MGMT_DIR) or (1 shl E3C59X_BIT_MGMT_DATA)
  825.         cmp     al, (1 shl E3C59X_BIT_MGMT_DATA)
  826.         je      .serch_for_phy
  827.         xor     al, al
  828.         ret
  829. .serch_for_phy:
  830. ; search for PHY
  831.         mov     cl, 31
  832. .search_phy_loop:
  833.         cmp     cl, 24
  834.         je      .next_phy
  835.         mov     ah, cl ; ah = phy
  836.         mov     al, E3C59X_REG_MII_BMCR ; al = Basic Mode Status Register
  837.         push    ecx
  838.         call    e3c59x_mdio_read
  839.         pop     ecx
  840.         test    ax, ax
  841.         jz      .next_phy
  842.         cmp     ax, 0xffff
  843.         je      .next_phy
  844.         mov     ah, cl ; ah = phy
  845.         push    ecx
  846.         call    e3c59x_try_phy
  847.         pop     ecx
  848.         test    al, al
  849.         jnz     .check_preamble
  850. .next_phy:
  851.         dec     cl
  852.         jns     .search_phy_loop
  853. .fail_finish:
  854.         xor     al, al
  855.         ret
  856. ; epilog
  857. .check_preamble:
  858.         push    eax ; eax contains the return value of e3c59x_try_phy
  859. ; check hard coded preamble forcing
  860.         movzx   eax, byte [e3c59x_ver_id]
  861.         test    word [eax*4+e3c59x_hw_versions+2], EXTRA_PREAMBLE
  862.         setnz   [e3c59x_preamble] ; force preamble
  863.         jnz     .finish
  864. ; check mii for preamble suppression
  865.         mov     ah, cl
  866.         mov     al, E3C59X_REG_MII_BMSR
  867.         call    e3c59x_mdio_read
  868.         test    al, 1000000b ; preamble suppression?
  869.         setz    [e3c59x_preamble] ; no
  870. .finish:
  871.         pop     eax
  872.         ret
  873.  
  874. ;***************************************************************************
  875. ;   Function
  876. ;      e3c59x_test_packet
  877. ;   Description
  878. ;      e3c59x_try_loopback try a loopback packet for 10BASE2 or AUI port
  879. ;   Parameters
  880. ;      ebp - io_addr
  881. ;   Return value
  882. ;      al - 0
  883. ;      al - 1
  884. ;   Destroyed registers
  885. ;      eax, ebx, ecx, edx, edi, esi
  886. ;
  887. ;***************************************************************************
  888.         align 4
  889. e3c59x_test_packet:
  890. ; switch to register window 3
  891.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  892.         mov     ax, E3C59X_SELECT_REGISTER_WINDOW+3
  893.         out     dx, ax
  894. ; set fullDuplexEnable in MacControl register
  895.         lea     edx, [ebp+E3C59X_REG_MAC_CONTROL]
  896.         in      ax, dx
  897.         or      ax, 0x120
  898.         out     dx, ax
  899. ; switch to register window 5
  900.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  901.         mov     ax, E3C59X_SELECT_REGISTER_WINDOW+5
  902.         out     dx, ax
  903. ; set RxFilter to enable individual address matches
  904.         mov     ax, (10000b shl 11)
  905.         lea     edx, [ebp+E3C59X_REG_RX_FILTER]
  906.         in      al, dx
  907.         or      al, 1
  908.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  909.         out     dx, ax
  910. ; issue RxEnable and TxEnable
  911.         call    e3c59x_rx_reset
  912.         call    e3c59x_tx_reset
  913. ; download a self-directed test packet
  914.         mov     edi, node_addr
  915.         mov     bx, 0x0608 ; packet type
  916.         mov     esi, e3c59x_self_directed_packet
  917.         mov     ecx, 6 ; 6 + 6 + 2 + 6 = 20 bytes
  918.         call    dword [e3c59x_transmit_function]
  919. ; wait for 2s
  920.         mov     esi, 2000 ; 2000ms = 2s
  921.         call    delay_ms
  922. ; check if self-directed packet is received
  923.         call    dword [e3c59x_receive_function]
  924.         test    al, al
  925.         jnz     .finish
  926. ; switch to register window 3
  927.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  928.         mov     ax, E3C59X_SELECT_REGISTER_WINDOW+3
  929.         out     dx, ax
  930. ; clear fullDuplexEnable in MacControl register
  931.         lea     edx, [ebp+E3C59X_REG_MAC_CONTROL]
  932.         in      ax, dx
  933.         and     ax, not 0x120
  934.         out     dx, ax
  935.         xor     al, al
  936. .finish:
  937.         ret
  938.  
  939. ;***************************************************************************
  940. ;   Function
  941. ;      e3c59x_try_loopback
  942. ;   Description
  943. ;      tries a loopback packet for 10BASE2 or AUI port
  944. ;   Parameters
  945. ;      al -  0: 10Mbps AUI connector
  946. ;            1: 10BASE-2
  947. ;      ebp - io_addr
  948. ;   Return value
  949. ;      al - 0
  950. ;      al - 1
  951. ;   Destroyed registers
  952. ;      eax, ebx, ecx, edx, edi, esi
  953. ;
  954. ;***************************************************************************
  955.         align 4
  956. e3c59x_try_loopback:
  957.         push    eax
  958. ; switch to register window 3
  959.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  960.         mov     ax, E3C59X_SELECT_REGISTER_WINDOW+3
  961.         out     dx, ax
  962.         pop     eax
  963.         push    eax
  964. if defined E3C59X_DEBUG
  965.         mov     bl, al
  966.         inc     bl
  967.         shl     bl, 3
  968.         or      byte [e3c59x_link_type+1], bl
  969. end if ; defined E3C59X_DEBUG
  970.         test    al, al ; aui or coax?
  971.         jz      .complete_loopback
  972. ; enable 100BASE-2 DC-DC converter
  973.         mov     ax, (10b shl 11) ; EnableDcConverter
  974.         out     dx, ax
  975. .complete_loopback:
  976.         mov     cl, 2 ; give a port 3 chances to complete a loopback
  977. .next_try:
  978.         push    ecx
  979.         call    e3c59x_test_packet
  980.         pop     ecx
  981.         test    al, al
  982.         jnz     .finish
  983.         dec     cl
  984.         jns     .next_try
  985. .finish:
  986.         xchg    eax, [esp]
  987.         test    al, al
  988.         jz      .aui_finish
  989. ; issue DisableDcConverter command
  990.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  991.         mov     ax, (10111b shl 11)
  992.         out     dx, ax
  993. .aui_finish:
  994.         pop     eax ; al contains the result of operation
  995. if defined E3C59X_DEBUG
  996.         test    al, al
  997.         jnz     @f
  998.         and     byte [e3c59x_link_type+1], not 11000b
  999. @@:
  1000. end if ; defined E3C59X_DEBUG
  1001.         ret
  1002.  
  1003. ;***************************************************************************
  1004. ;   Function
  1005. ;      e3c59x_set_available_media
  1006. ;   Description
  1007. ;      sets the first available media
  1008. ;   Parameters
  1009. ;      ebp - io_addr
  1010. ;   Return value
  1011. ;      al - 0
  1012. ;      al - 1
  1013. ;   Destroyed registers
  1014. ;      eax, edx
  1015. ;
  1016. ;***************************************************************************
  1017.         align 4
  1018. e3c59x_set_available_media:
  1019. ; switch to register window 3
  1020.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  1021.         mov     ax, E3C59X_SELECT_REGISTER_WINDOW+3
  1022.         out     dx, ax
  1023.         lea     edx, [ebp+E3C59X_REG_INTERNAL_CONFIG]
  1024.         in      eax, dx
  1025.         push    eax
  1026.         lea     edx, [ebp+E3C59X_REG_MEDIA_OPTIONS]
  1027.         in      ax, dx
  1028.         test    al, 10b
  1029.         jz      @f
  1030. ; baseTXAvailable
  1031.         pop     eax
  1032.         and     eax, not (1111b shl 20)
  1033.         or      eax, (100b shl 20)
  1034. if defined E3C59X_DEBUG & defined E3C59X_FORCE_FD
  1035.         mov     word [e3c59x_link_type], (1 shl 8)
  1036. else if defined E3C59X_DEBUG
  1037.         mov     word [e3c59x_link_type], (1 shl 7)
  1038. end if
  1039.         jmp     .set_media
  1040. @@:
  1041.         test    al, 100b
  1042.         jz      @f
  1043. ; baseFXAvailable
  1044.         pop     eax
  1045.         and     eax, not (1111b shl 20)
  1046.         or      eax, (101b shl 20)
  1047. if defined E3C59X_DEBUG
  1048.         mov     word [e3c59x_link_type], (1 shl 10)
  1049. end if
  1050.         jmp     .set_media
  1051. @@:
  1052.         test    al, 1000000b
  1053.         jz      @f
  1054. ; miiDevice
  1055.         pop     eax
  1056.         and     eax, not (1111b shl 20)
  1057.         or      eax, (0110b shl 20)
  1058. if defined E3C59X_DEBUG
  1059.         mov     word [e3c59x_link_type], (1 shl 13)
  1060. end if
  1061.         jmp     .set_media
  1062. @@:
  1063.         test    al, 1000b
  1064.         jz      @f
  1065. .set_default:
  1066. ; 10bTAvailable
  1067.         pop     eax
  1068.         and     eax, not (1111b shl 20)
  1069. if defined E3C59X_DEBUG & defined E3C59X_FORCE_FD
  1070.         mov     word [e3c59x_link_type], (1 shl 6)
  1071. else if defined E3C59X_DEBUG
  1072.         mov     word [e3c59x_link_type], (1 shl 5)
  1073. end if ; E3C59X_FORCE_FD
  1074.         jmp     .set_media
  1075. @@:
  1076.         test    al, 10000b
  1077.         jz      @f
  1078. ; coaxAvailable
  1079.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  1080.         mov     ax, (10b shl 11) ; EnableDcConverter
  1081.         out     dx, ax
  1082.         pop     eax
  1083.         and     eax, not (1111b shl 20)
  1084.         or      eax, (11b shl 20)
  1085. if defined E3C59X_DEBUG
  1086.         mov     word [e3c59x_link_type], (1 shl 12)
  1087. end if ; defined E3C59X_DEBUG
  1088.         jmp     .set_media
  1089. @@:
  1090.         test    al, 10000b
  1091.         jz      .set_default
  1092. ; auiAvailable
  1093.         pop     eax
  1094.         and     eax, not (1111b shl 20)
  1095.         or      eax, (1 shl 20)
  1096. if defined E3C59X_DEBUG
  1097.         mov     word [e3c59x_link_type], (1 shl 11)
  1098. end if ; defined E3C59X_DEBUG
  1099. .set_media:
  1100.         lea     edx, [ebp+E3C59X_REG_INTERNAL_CONFIG]
  1101.         out     dx, eax
  1102. if defined E3C59X_FORCE_FD
  1103. ; set fullDuplexEnable in MacControl register
  1104.         lea     edx, [ebp+E3C59X_REG_MAC_CONTROL]
  1105.         in      ax, dx
  1106.         or      ax, 0x120
  1107.         out     dx, ax
  1108. end if ; E3C59X_FORCE_FD
  1109.         mov     al, 1
  1110.         ret
  1111.  
  1112. ;***************************************************************************
  1113. ;   Function
  1114. ;      e3c59x_set_active_port
  1115. ;   Description
  1116. ;      It selects the media port (transceiver) to be used
  1117. ;   Parameters:
  1118. ;      ebp - io_addr
  1119. ;   Return value:
  1120. ;   Destroyed registers
  1121. ;      eax, ebx, ecx, edx, edi, esi
  1122. ;
  1123. ;***************************************************************************
  1124.         align 4
  1125. e3c59x_set_active_port:
  1126. ; switch to register window 3
  1127.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  1128.         mov     ax, E3C59X_SELECT_REGISTER_WINDOW+3
  1129.         out     dx, ax
  1130.         lea     edx, [ebp+E3C59X_REG_INTERNAL_CONFIG]
  1131.         in      eax, dx
  1132.         test    eax, (1 shl 24) ; check if autoselect enable
  1133.         jz      .set_first_available_media
  1134. ; check 100BASE-TX and 10BASE-T
  1135.         lea     edx, [ebp+E3C59X_REG_MEDIA_OPTIONS]
  1136.         in      ax, dx
  1137.         test    al, 1010b ; check whether 100BASE-TX or 10BASE-T available
  1138.         jz      .mii_device ; they are not available
  1139. ; set auto-negotiation
  1140.         lea     edx, [ebp+E3C59X_REG_INTERNAL_CONFIG]
  1141.         in      eax, dx
  1142.         and     eax, not (1111b shl 20)
  1143.         or      eax, (1000b shl 20)
  1144.         out     dx, eax
  1145.         call    e3c59x_try_mii
  1146.         test    al, al
  1147.         jz      .mii_device
  1148.         ret
  1149. .mii_device:
  1150. ; switch to register window 3
  1151.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  1152.         mov     ax, E3C59X_SELECT_REGISTER_WINDOW+3
  1153.         out     dx, ax
  1154. ; check for off-chip mii device
  1155.         lea     edx, [ebp+E3C59X_REG_MEDIA_OPTIONS]
  1156.         in      ax, dx
  1157.         test    al, 1000000b ; check miiDevice
  1158.         jz      .base_fx
  1159.         lea     edx, [ebp+E3C59X_REG_INTERNAL_CONFIG]
  1160.         in      eax, dx
  1161.         and     eax, not (1111b shl 20)
  1162.         or      eax, (0110b shl 20) ; set MIIDevice
  1163.         out     dx, eax
  1164.         call    e3c59x_try_mii
  1165.         test    al, al
  1166.         jz      .base_fx
  1167.         ret
  1168. .base_fx:
  1169. ; switch to register window 3
  1170.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  1171.         mov     ax, E3C59X_SELECT_REGISTER_WINDOW+3
  1172.         out     dx, ax
  1173. ; check for 100BASE-FX
  1174.         lea     edx, [ebp+E3C59X_REG_MEDIA_OPTIONS]
  1175.         in      ax, dx ; read media option register
  1176.         test    al, 100b ; check 100BASE-FX
  1177.         jz      .aui_enable
  1178.         lea     edx, [ebp+E3C59X_REG_INTERNAL_CONFIG]
  1179.         in      eax, dx
  1180.         and     eax, not (1111b shl 20)
  1181.         or      eax, (0101b shl 20) ; set 100base-FX
  1182.         out     dx, eax
  1183.         call    e3c59x_try_link_detect
  1184.         test    al, al
  1185.         jz      .aui_enable
  1186.         ret
  1187. .aui_enable:
  1188. ; switch to register window 3
  1189.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  1190.         mov     ax, E3C59X_SELECT_REGISTER_WINDOW+3
  1191.         out     dx, ax
  1192. ; check for 10Mbps AUI connector
  1193.         lea     edx, [ebp+E3C59X_REG_MEDIA_OPTIONS]
  1194.         in      ax, dx ; read media option register
  1195.         test    al, 100000b ; check 10Mbps AUI connector
  1196.         jz      .coax_available
  1197.         lea     edx, [ebp+E3C59X_REG_INTERNAL_CONFIG]
  1198.         in      eax, dx
  1199.         and     eax, not (1111b shl 20)
  1200.         or      eax, (0001b shl 20) ; set 10Mbps AUI connector
  1201.         out     dx, eax
  1202.         xor     al, al ; try 10Mbps AUI connector
  1203.         call    e3c59x_try_loopback
  1204.         test    al, al
  1205.         jz      .coax_available
  1206.         ret
  1207. .coax_available:
  1208. ; switch to register window 3
  1209.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  1210.         mov     ax, E3C59X_SELECT_REGISTER_WINDOW+3
  1211.         out     dx, ax
  1212. ; check for coaxial 10BASE-2 port
  1213.         lea     edx, [ebp+E3C59X_REG_MEDIA_OPTIONS]
  1214.         in      ax, dx ; read media option register
  1215.         test    al, 10000b ; check 10BASE-2
  1216.         jz      .set_first_available_media
  1217.         lea     edx, [ebp+E3C59X_REG_INTERNAL_CONFIG]
  1218.         in      eax, dx
  1219.         and     eax, not (1111b shl 20)
  1220.         or      eax, (0011b shl 20) ; set 10BASE-2
  1221.         out     dx, eax
  1222.         mov     al, 1
  1223.         call    e3c59x_try_loopback
  1224.         test    al, al
  1225.         jz      .set_first_available_media
  1226.         ret
  1227. .set_first_available_media:
  1228.         jmp    e3c59x_set_available_media
  1229.  
  1230. ;***************************************************************************
  1231. ;   Function
  1232. ;      e3c59x_wake_up
  1233. ;   Description
  1234. ;      set the power state to D0
  1235. ;   Destroyed registers
  1236. ;      eax, ebx, ecx, edx, edi, esi
  1237. ;
  1238. ;***************************************************************************
  1239.         align 4
  1240. e3c59x_wake_up:
  1241. ; wake up - we directly do it by programming PCI
  1242. ; check if the device is power management capable
  1243.         mov     al, 2
  1244.         mov     ah, [pci_bus]
  1245.         mov     bl, PCI_REG_STATUS
  1246.         mov     bh, [pci_dev]
  1247.         push    eax ebx
  1248.         call    pci_read_reg
  1249.         test    al, 10000b ; is there "new capabilities" linked list?
  1250.         pop     ebx eax
  1251.         jz      .device_awake
  1252. ; search for power management register
  1253.         mov     al, 1
  1254.         mov     bl, PCI_REG_CAP_PTR
  1255.         push    eax ebx
  1256.         call    pci_read_reg
  1257.         mov     cl, al
  1258.         cmp     cl, 0x3f
  1259.         pop     ebx eax
  1260.         jbe     .device_awake
  1261. ; traverse the list
  1262.         mov     al, 2
  1263. .pm_loop:
  1264.         mov     bl, cl
  1265.         push    eax ebx
  1266.         call    pci_read_reg
  1267.         cmp     al, 1
  1268.         je      .set_pm_state
  1269.         test    ah, ah
  1270.         mov     cl, ah
  1271.         pop     ebx eax
  1272.         jnz     .pm_loop
  1273.         jmp     .device_awake
  1274. ; waku up the device if necessary
  1275. .set_pm_state:
  1276.         pop     ebx eax
  1277.         add     bl, PCI_REG_PM_CTRL
  1278.         push    eax ebx
  1279.         call    pci_read_reg
  1280.         mov     cx, ax
  1281.         test    cl, 3
  1282.         pop     ebx eax
  1283.         jz      .device_awake
  1284.         and     cl, not 11b ; set state to D0
  1285.         call    pci_write_reg
  1286. .device_awake:
  1287.         ret
  1288.  
  1289. ;***************************************************************************
  1290. ;   Function
  1291. ;      e3c59x_probe
  1292. ;   Description
  1293. ;      Searches for an ethernet card, enables it and clears the rx buffer
  1294. ;      If a card was found, it enables the ethernet -> TCPIP link
  1295. ;   Destroyed registers
  1296. ;      eax, ebx, ecx, edx, edi, esi
  1297. ;
  1298. ;***************************************************************************
  1299.         align 4
  1300. e3c59x_probe:
  1301.         movzx   ebp, word [io_addr]
  1302.         mov     al, 2
  1303.         mov     ah, [pci_bus]
  1304.         mov     bh, [pci_dev]
  1305.         mov     bl, PCI_REG_COMMAND
  1306.         push    ebp eax ebx
  1307.         call    pci_read_reg
  1308.         mov     cx, ax
  1309.         or      cl, (1 shl PCI_BIT_MASTER) or (1 shl PCI_BIT_PIO)
  1310.         and     cl, not (1 shl PCI_BIT_MMIO)
  1311.         pop     ebx eax
  1312.         call    pci_write_reg
  1313. ; wake up the card
  1314.         call    e3c59x_wake_up
  1315.         pop     ebp
  1316. ; get chip version
  1317.         mov     ax, [pci_data+2]
  1318.         mov     ecx, E3C59X_HW_VERSIONS_SIZE/4-1
  1319. .chip_ver_loop:
  1320.         cmp     ax, [e3c59x_hw_versions+ecx*4]
  1321.         jz      .chip_ver_found
  1322.         dec     ecx
  1323.         jns     .chip_ver_loop
  1324.         xor     ecx, ecx
  1325. .chip_ver_found:
  1326.         mov     [e3c59x_ver_id], cl
  1327.         test    word [e3c59x_hw_versions+2+ecx*4], HAS_HWCKSM
  1328.         setnz   [e3c59x_has_hwcksm]
  1329. ; set pci latency for vortex cards
  1330.         test    word [e3c59x_hw_versions+2+ecx*4], IS_VORTEX
  1331.         jz      .not_vortex
  1332.         mov     cx, 11111000b ; 248 = max latency
  1333.         mov     al, 1
  1334.         mov     ah, [pci_bus]
  1335.         mov     bl, PCI_REG_LATENCY
  1336.         mov     bh, [pci_dev]
  1337.         call    pci_write_reg
  1338. .not_vortex:
  1339. ; set RX/TX functions
  1340.         mov     ax, E3C59X_EEPROM_REG_CAPABILITIES
  1341.         call    e3c59x_read_eeprom
  1342.         test    al, 100000b ; full bus master?
  1343.         setnz   [e3c59x_full_bus_master]
  1344.         jnz     .boomerang_func
  1345.         mov     dword [e3c59x_transmit_function], e3c59x_vortex_transmit
  1346.         mov     dword [e3c59x_receive_function], e3c59x_vortex_poll
  1347.         jmp     @f
  1348. .boomerang_func: ; full bus master, so use boomerang functions
  1349.         mov     dword [e3c59x_transmit_function], e3c59x_boomerang_transmit
  1350.         mov     dword [e3c59x_receive_function], e3c59x_boomerang_poll
  1351. @@:
  1352. ; read MAC from eeprom
  1353.         mov     ecx, 2
  1354. .mac_loop:
  1355.         lea     ax, [E3C59X_EEPROM_REG_OEM_NODE_ADDR+ecx]
  1356.         call    e3c59x_read_eeprom
  1357.         xchg    ah, al ; htons
  1358.         mov     [node_addr+ecx*2], ax
  1359.         dec     ecx
  1360.         jns     .mac_loop
  1361.         test    byte [e3c59x_full_bus_master], 0xff
  1362.         jz      .set_preamble
  1363. ; switch to register window 2
  1364.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  1365.         mov     ax, E3C59X_SELECT_REGISTER_WINDOW+2
  1366.         out     dx, ax
  1367. ; activate xcvr by setting some magic bits
  1368.         lea     edx, [ebp+E3C59X_REG_RESET_OPTIONS]
  1369.         in      ax, dx
  1370.         and     ax, not 0x4010
  1371.         movzx   ebx, byte [e3c59x_ver_id]
  1372.         test    word [ebx*4+e3c59x_hw_versions+2], INVERT_LED_PWR
  1373.         jz      @f
  1374.         or      al, 0x10
  1375. @@:
  1376.         test    word [ebx*4+e3c59x_hw_versions+2], INVERT_MII_PWR
  1377.         jz      @f
  1378.         or      ah, 0x40
  1379. @@:
  1380.         out     dx, ax
  1381. .set_preamble:
  1382. ; use preamble as default
  1383.         mov     byte [e3c59x_preamble], 1 ; enable preamble
  1384.  
  1385. ;***************************************************************************
  1386. ;   Function
  1387. ;      e3c59x_reset
  1388. ;   Description
  1389. ;      Place the chip (ie, the ethernet card) into a virgin state
  1390. ;   Destroyed registers
  1391. ;      eax, ebx, ecx, edx, edi, esi
  1392. ;
  1393. ;***************************************************************************
  1394. e3c59x_reset:
  1395. ; issue global reset
  1396.         call    e3c59x_global_reset
  1397. ; disable interrupts
  1398.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  1399.         mov     ax, (1110b shl 11)
  1400.         out     dx, ax
  1401. ; enable Statistics
  1402.         mov     ax, (10101b shl 11)
  1403.         out     dx, ax
  1404. ; set indication
  1405.         mov     ax, (1111b shl 11) or 0x6c6
  1406.         out     dx, ax
  1407. ; acknowledge (clear) every interrupt indicator
  1408.         mov     ax, (1101b shl 11) or 0x661
  1409.         out     dx, ax
  1410. ; switch to register window 2
  1411.         mov     ax, E3C59X_SELECT_REGISTER_WINDOW+2
  1412.         out     dx, ax
  1413. ; write MAC addres back into the station address registers
  1414.         lea     edx, [ebp+E3C59X_REG_STATION_ADDRESS_LO]
  1415.         mov     esi, node_addr
  1416.         cld
  1417.         outsw
  1418.         add     edx, 2
  1419.         outsw
  1420.         add     edx, 2
  1421.         outsw
  1422.         add     edx, 2
  1423. ; clear station mask
  1424.         xor     eax, eax
  1425.         out     dx, ax
  1426.         add     edx, 2
  1427.         out     dx, ax
  1428.         add     edx, 2
  1429.         out     dx, ax
  1430. ; switch to register window 6
  1431.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  1432.         mov     ax, E3C59X_SELECT_REGISTER_WINDOW+6
  1433.         out     dx, ax
  1434. ; clear all statistics by reading
  1435.         lea     edx, [ebp+E3C59X_REG_CARRIER_LOST]
  1436.         mov     cl, 9
  1437. .stat_clearing_loop:
  1438.         in      al, dx
  1439.         inc     edx
  1440.         dec     cl
  1441.         jns     .stat_clearing_loop
  1442.         in      ax, dx
  1443.         add     dx, 2
  1444.         in      ax, dx
  1445. ; switch to register window 4
  1446.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  1447.         mov     ax, E3C59X_SELECT_REGISTER_WINDOW+4
  1448.         out     dx, ax
  1449. ; clear BadSSD
  1450.         lea     edx, [ebp+E3C59X_REG_BAD_SSD]
  1451.         in      al, dx
  1452. ; clear extra statistics bit in NetworkDiagnostic
  1453.         lea     edx, [ebp+E3C59X_REG_NETWORK_DIAGNOSTIC]
  1454.         in      ax, dx
  1455.         or      ax,  0x0040
  1456.         out     dx, ax
  1457. ; SetRxEarlyThreshold
  1458.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  1459.         mov     ax, (10001b shl 11)+(E3C59X_MAX_ETH_PKT_SIZE shr 2)
  1460.         out     dx, ax
  1461.         test    byte [e3c59x_full_bus_master], 0xff
  1462.         jz      .skip_boomerang_setting
  1463. ; set upRxEarlyEnable
  1464.         lea     edx, [ebp+E3C59X_REG_DMA_CTRL]
  1465.         in      eax, dx
  1466.         or      eax, 0x20
  1467.         out     dx, eax
  1468. ; TxFreeThreshold
  1469.         lea     edx, [ebp+E3C59X_REG_TX_FREE_THRESH]
  1470.         mov     al, (E3C59X_MAX_ETH_PKT_SIZE / 256)
  1471.         out     dx, al
  1472. ; program DnListPtr
  1473.         lea     edx, [ebp+E3C59X_REG_DN_LIST_PTR]
  1474.         xor     eax, eax
  1475.         out     dx, eax
  1476. .skip_boomerang_setting:
  1477. ; initialization
  1478.         call    e3c59x_rx_reset
  1479.         call    e3c59x_tx_reset
  1480.         call    e3c59x_set_active_port
  1481.         call    e3c59x_rx_reset
  1482.         call    e3c59x_tx_reset
  1483. ; switch to register window 5
  1484.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  1485.         mov     ax, E3C59X_SELECT_REGISTER_WINDOW+5
  1486.         out     dx, ax
  1487. ; program RxFilter for promiscuous operation
  1488.         mov     ax, (10000b shl 11)
  1489.         lea     edx, [ebp+E3C59X_REG_RX_FILTER]
  1490.         in      al, dx
  1491.         or      al, 1111b
  1492.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  1493.         out     dx, ax
  1494. ; switch to register window 4
  1495.         mov     ax, E3C59X_SELECT_REGISTER_WINDOW+4
  1496.         out     dx, ax
  1497. ; wait for linkDetect
  1498.         lea     edx, [ebp+E3C59X_REG_MEDIA_STATUS]
  1499.         mov     cl, 20 ; wait for max 2s
  1500.         mov     esi, 100 ; 100ms
  1501. .link_detect_loop:
  1502.         call    delay_ms
  1503.         in      ax, dx
  1504.         test    ah, 1000b ; linkDetect
  1505.         jnz     @f
  1506.         dec     cl
  1507.         jnz     .link_detect_loop
  1508. @@:
  1509. ; Indicate that we have successfully reset the card
  1510.         mov     eax, [pci_data]
  1511.         mov     [eth_status], eax
  1512. if defined E3C59X_DEBUG
  1513.         call    e3c59x_debug
  1514. end if ; defined E3C59X_DEBUG
  1515.         ret
  1516.  
  1517. ;***************************************************************************
  1518. ;   Function
  1519. ;      e3c59x_global_reset
  1520. ;   Description
  1521. ;      resets the device
  1522. ;   Parameters:
  1523. ;      ebp - io_addr
  1524. ;   Return value:
  1525. ;   Destroyed registers
  1526. ;      ax, ecx, edx, esi
  1527. ;
  1528. ;***************************************************************************
  1529.         align 4
  1530. e3c59x_global_reset:
  1531. ; GlobalReset
  1532.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  1533.         xor     eax, eax
  1534. ;       or      al, 0x14
  1535.         out     dx, ax
  1536. ; wait for GlobalReset to complete
  1537.         mov     ecx, 64000
  1538. .global_reset_loop:
  1539.         in      ax, dx
  1540.         test    ah, 10000b ; check CmdInProgress
  1541.         jz      .finish
  1542.         dec     ecx
  1543.         jnz     .global_reset_loop
  1544. .finish:
  1545. ; wait for 2 seconds for NIC to boot
  1546.         mov     esi, 2000 ; 2000ms = 2s
  1547.         push    ebp
  1548.         call    delay_ms
  1549.         pop     ebp
  1550.         ret
  1551.  
  1552. ;***************************************************************************
  1553. ;   Function
  1554. ;      e3c59x_tx_reset
  1555. ;   Description
  1556. ;      resets and enables transmitter engine
  1557. ;   Parameters:
  1558. ;      ebp - io_addr
  1559. ;   Return value:
  1560. ;   Destroyed registers
  1561. ;      ax, ecx, edx
  1562. ;
  1563. ;***************************************************************************
  1564.         align 4
  1565. e3c59x_tx_reset:
  1566. ; TxReset
  1567.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  1568.         mov     ax, (01011b shl 11)
  1569.         out     dx, ax
  1570. ; wait for TxReset to complete
  1571.         mov     ecx, 2000
  1572. .tx_reset_loop:
  1573.         in      ax, dx
  1574.         test    ah, 10000b ; check CmdInProgress
  1575.         jz      .tx_enable
  1576.         dec     ecx
  1577.         jns     .tx_reset_loop
  1578.         test    byte [e3c59x_full_bus_master], 0xff
  1579.         jz      .tx_enable
  1580. ; init last_dpd
  1581.         mov     dword [e3c59x_prev_dpd], e3c59x_dpd_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_DPD_SIZE
  1582.         mov     dword [e3c59x_prev_tx_frame], e3c59x_tx_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_MAX_ETH_FRAME_SIZE
  1583. .tx_enable:
  1584.         mov     ax, (01001b shl 11) ; TxEnable
  1585.         out     dx, ax
  1586.         ret
  1587.  
  1588. ;***************************************************************************
  1589. ;   Function
  1590. ;      e3c59x_rx_reset
  1591. ;   Description
  1592. ;      resets and enables receiver engine
  1593. ;   Parameters:
  1594. ;      ebp - io_addr
  1595. ;   Return value:
  1596. ;   Destroyed registers
  1597. ;      eax, ebx, ecx, edx, edi, esi
  1598. ;
  1599. ;***************************************************************************
  1600.         align 4
  1601. e3c59x_rx_reset:
  1602.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  1603.         mov     ax, (0101b shl 11) or 0x4 ; RxReset
  1604.         out     dx, ax
  1605. ; wait for RxReset to complete
  1606.         mov     ecx, 200000
  1607. .rx_reset_loop:
  1608.         in      ax, dx
  1609.         test    ah, 10000b ; check CmdInProgress
  1610.         jz      .setup_upd
  1611.         dec     ecx
  1612.         jns     .rx_reset_loop
  1613. .setup_upd:
  1614. ; check if full bus mastering
  1615.         test    byte [e3c59x_full_bus_master], 0xff
  1616.         jz      .rx_enable
  1617. ; create upd ring
  1618.         mov     eax, e3c59x_upd_buff
  1619.         zero_to_virt eax
  1620.         mov     [e3c59x_curr_upd], eax
  1621.         mov     esi, eax
  1622.         virt_to_dma esi
  1623.         mov     edi, e3c59x_rx_buff
  1624.         zero_to_dma edi
  1625.         mov     ebx, e3c59x_upd_buff+(E3C59X_NUM_RX_DESC-1)*E3C59X_UPD_SIZE
  1626.         zero_to_virt ebx
  1627.         mov     cl, E3C59X_NUM_RX_DESC-1
  1628. .upd_loop:
  1629.         mov     [ebx+E3C59X_UPD_UP_NEXT_PTR], esi
  1630.         and     dword [eax+E3C59X_UPD_PKT_STATUS], 0
  1631.         mov     [eax+E3C59X_UPD_UP_FRAG_ADDR], edi
  1632.         mov     dword [eax+E3C59X_UPD_UP_FRAG_LEN], E3C59X_MAX_ETH_FRAME_SIZE or (1 shl 31)
  1633.         add     edi, E3C59X_MAX_ETH_FRAME_SIZE
  1634.         add     esi, E3C59X_UPD_SIZE
  1635.         mov     ebx, eax
  1636.         add     eax, E3C59X_UPD_SIZE
  1637.         dec     cl
  1638.         jns     .upd_loop
  1639.         mov     eax, e3c59x_upd_buff
  1640.         zero_to_dma eax
  1641.         lea     edx, [ebp+E3C59X_REG_UP_LIST_PTR]
  1642.         out     dx, eax ; write E3C59X_REG_UP_LIST_PTR
  1643.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  1644. .rx_enable:
  1645.         mov     ax, (00100b shl 11) ; RxEnable
  1646.         out     dx, ax
  1647.         ret
  1648.  
  1649. ;***************************************************************************
  1650. ;   Function
  1651. ;      e3c59x_write_eeprom
  1652. ;   Description
  1653. ;      reads eeprom
  1654. ;      Note : the caller must switch to the register window 0
  1655. ;             before calling this function
  1656. ;   Parameters:
  1657. ;      ax - register to be read (only the first 63 words can be read)
  1658. ;      cx - value to be read into the register
  1659. ;   Return value:
  1660. ;      ax - word read
  1661. ;   Destroyed registers
  1662. ;      ax, ebx, edx
  1663. ;
  1664. ;***************************************************************************
  1665. ;       align 4
  1666. ;e3c59x_write_eeprom:
  1667. ;       mov     edx, [io_addr]
  1668. ;       add     edx, E3C59X_REG_EEPROM_COMMAND
  1669. ;       cmp     ah, 11b
  1670. ;       ja      .finish ; address may have a value of maximal 1023
  1671. ;       shl     ax, 2
  1672. ;       shr     al, 2
  1673. ;       push    eax
  1674. ;; wait for busy
  1675. ;       mov     ebx, 0xffff
  1676. ;@@:
  1677. ;       in      ax, dx
  1678. ;       test    ah, 0x80
  1679. ;       jz      .write_enable
  1680. ;       dec     ebx
  1681. ;       jns     @r
  1682. ;; write enable
  1683. ;.write_enable:
  1684. ;       xor     eax, eax
  1685. ;       mov     eax, (11b shl 4)
  1686. ;       out     dx, ax
  1687. ;; wait for busy
  1688. ;       mov     ebx, 0xffff
  1689. ;@@:
  1690. ;       in      ax, dx
  1691. ;       test    ah, 0x80
  1692. ;       jz      .erase_loop
  1693. ;       dec     ebx
  1694. ;       jns     @r
  1695. ;.erase_loop:
  1696. ;       pop     eax
  1697. ;       push    eax
  1698. ;       or      ax, (11b shl 6) ; erase register
  1699. ;       out     dx, ax
  1700. ;       mov     ebx, 0xffff
  1701. ;@@:
  1702. ;       in      ax, dx
  1703. ;       test    ah, 0x80
  1704. ;       jz      .write_reg
  1705. ;       dec     ebx
  1706. ;       jns     @r
  1707. ;.write_reg:
  1708. ;       add     edx, E3C59X_REG_EEPROM_DATA-E3C59X_REG_EEPROM_COMMAND
  1709. ;       mov     eax, ecx
  1710. ;       out     dx, ax
  1711. ;; write enable
  1712. ;       add     edx, E3C59X_REG_EEPROM_COMMAND-E3C59X_REG_EEPROM_DATA
  1713. ;       xor     eax, eax
  1714. ;       mov     eax, (11b shl 4)
  1715. ;       out     dx, ax
  1716. ; wait for busy
  1717. ;       mov     ebx, 0xffff
  1718. ;@@:
  1719. ;       in      ax, dx
  1720. ;       test    ah, 0x80
  1721. ;       jz      .issue_write_reg
  1722. ;       dec     ebx
  1723. ;       jns     @r
  1724. ;.issue_write_reg:
  1725. ;       pop     eax
  1726. ;       or      ax, 01b shl 6
  1727. ;       out     dx, ax
  1728. ;.finish:
  1729. ;       ret
  1730. ;***************************************************************************
  1731. ;   Function
  1732. ;      e3c59x_read_eeprom
  1733. ;   Description
  1734. ;      reads eeprom
  1735. ;   Parameters:
  1736. ;       ax - register to be read (only the first 63 words can be read)
  1737. ;      ebp - io_addr
  1738. ;   Return value:
  1739. ;      ax - word read
  1740. ;   Destroyed registers
  1741. ;      ax, ebx, edx, ebp
  1742. ;
  1743. ;***************************************************************************
  1744.         align 4
  1745. e3c59x_read_eeprom:
  1746.         push    eax
  1747. ; switch to register window 0
  1748.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  1749.         mov     ax, E3C59X_SELECT_REGISTER_WINDOW+0
  1750.         out     dx, ax
  1751.         pop     eax
  1752.         and     ax, 111111b ; take only the first 6 bits into account
  1753.         movzx   ebx, byte [e3c59x_ver_id]
  1754.         test    word [ebx*4+e3c59x_hw_versions+2], EEPROM_8BIT
  1755.         jz      @f
  1756.         add     ax, 0x230 ; hardware constant
  1757.         jmp     .read
  1758. @@:
  1759.         add     ax, E3C59X_EEPROM_CMD_READ
  1760.         test    word [ebx*4+e3c59x_hw_versions+2], EEPROM_OFFSET
  1761.         jz      .read
  1762.         add     ax, 0x30
  1763. .read:
  1764.         lea     edx, [ebp+E3C59X_REG_EEPROM_COMMAND]
  1765.         out     dx, ax
  1766.         mov     ebx, 0xffff ; duration of about 162 us ;-)
  1767. .wait_for_reading:
  1768.         in      ax, dx
  1769.         test    ah, 0x80 ; check bit eepromBusy
  1770.         jz      .read_data
  1771.         dec     ebx
  1772.         jns     .wait_for_reading
  1773. .read_data:
  1774.         lea     edx, [ebp+E3C59X_REG_EEPROM_DATA]
  1775.         in      ax, dx
  1776.         ret
  1777.  
  1778. ;***************************************************************************
  1779. ;   Function
  1780. ;      e3c59x_mdio_sync
  1781. ;   Description
  1782. ;      initial synchronization
  1783. ;   Parameters
  1784. ;      ebp - io_addr
  1785. ;   Return value
  1786. ;   Destroyed registers
  1787. ;      ax, edx, cl
  1788. ;
  1789. ;***************************************************************************
  1790.         align 4
  1791. e3c59x_mdio_sync:
  1792. ; switch to register window 4
  1793.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  1794.         mov     ax, E3C59X_SELECT_REGISTER_WINDOW+4
  1795.         out     dx, ax
  1796.         cmp     byte [e3c59x_preamble], 0
  1797.         je      .no_preamble
  1798. ; send 32 logic ones
  1799.         lea     edx, [ebp+E3C59X_REG_PHYSICAL_MGMT]
  1800.         mov     cl, 31
  1801. .loop:
  1802.         mov     ax, (1 shl E3C59X_BIT_MGMT_DATA) or (1 shl E3C59X_BIT_MGMT_DIR)
  1803.         out     dx, ax
  1804.         in      ax, dx ; delay
  1805.         mov     ax, (1 shl E3C59X_BIT_MGMT_DATA) \
  1806.                     or (1 shl E3C59X_BIT_MGMT_DIR) \
  1807.                     or (1 shl E3C59X_BIT_MGMT_CLK)
  1808.         out     dx, ax
  1809.         in      ax, dx ; delay
  1810.         dec     cl
  1811.         jns     .loop
  1812. .no_preamble:
  1813.         ret
  1814.  
  1815. ;***************************************************************************
  1816. ;   Function
  1817. ;      e3c59x_mdio_read
  1818. ;   Description
  1819. ;      read MII register
  1820. ;      see page 16 in D83840A.pdf
  1821. ;   Parameters
  1822. ;       ah - PHY addr
  1823. ;       al - register addr
  1824. ;      ebp - io_addr
  1825. ;   Return value
  1826. ;      ax - register read
  1827. ;   Destroyed registers
  1828. ;      eax, ebx, cx, edx
  1829. ;
  1830. ;***************************************************************************
  1831.         align 4
  1832. e3c59x_mdio_read:
  1833.         push    eax
  1834.         call    e3c59x_mdio_sync ; returns with window #4
  1835.         pop     eax
  1836.         lea     edx, [ebp+E3C59X_REG_PHYSICAL_MGMT]
  1837.         shl     al, 3
  1838.         shr     ax, 3
  1839.         and     ax, not E3C59X_MII_CMD_MASK
  1840.         or      ax, E3C59X_MII_CMD_READ
  1841.         mov     ebx, eax
  1842.         xor     ecx, ecx
  1843.         mov     cl, 13
  1844. .cmd_loop:
  1845.         mov     ax, (1 shl E3C59X_BIT_MGMT_DIR) ; write mii
  1846.         bt      ebx, ecx
  1847.         jnc     .zero_bit
  1848.         or      al, (1 shl E3C59X_BIT_MGMT_DATA)
  1849. .zero_bit:
  1850.         out     dx, ax
  1851.         push    eax
  1852.         in      ax, dx ; delay
  1853.         pop     eax
  1854.         or      al, (1 shl E3C59X_BIT_MGMT_CLK) ; write
  1855.         out     dx, ax
  1856.         in      ax, dx ; delay
  1857.         dec     cl
  1858.         jns     .cmd_loop
  1859. ; read data (18 bits with the two transition bits)
  1860.         mov     cl, 17
  1861.         xor     ebx, ebx
  1862. .read_loop:
  1863.         shl     ebx, 1
  1864.         xor     eax, eax ; read comand
  1865.         out     dx, ax
  1866.         in      ax, dx ; delay
  1867.         in      ax, dx
  1868.         test    al, (1 shl E3C59X_BIT_MGMT_DATA)
  1869.         jz      .dont_set
  1870.         inc     ebx
  1871. .dont_set:
  1872.         mov     ax, (1 shl E3C59X_BIT_MGMT_CLK)
  1873.         out     dx, ax
  1874.         in      ax, dx ; delay
  1875.         dec     cl
  1876.         jns     .read_loop
  1877.         mov     eax, ebx
  1878.         ret
  1879.  
  1880. ;***************************************************************************
  1881. ;   Function
  1882. ;      e3c59x_mdio_write
  1883. ;   Description
  1884. ;      write MII register
  1885. ;      see page 16 in D83840A.pdf
  1886. ;   Parameters
  1887. ;       ah - PHY addr
  1888. ;       al - register addr
  1889. ;       bx - word to be written
  1890. ;      ebp - io_addr
  1891. ;   Return value
  1892. ;      ax - register read
  1893. ;   Destroyed registers
  1894. ;      eax, ebx, cx, edx
  1895. ;
  1896. ;***************************************************************************
  1897.         align 4
  1898. e3c59x_mdio_write:
  1899.         push    eax
  1900.         call    e3c59x_mdio_sync
  1901.         pop     eax
  1902.         lea     edx, [ebp+E3C59X_REG_PHYSICAL_MGMT]
  1903.         shl     al, 3
  1904.         shr     ax, 3
  1905.         and     ax, not E3C59X_MII_CMD_MASK
  1906.         or      ax, E3C59X_MII_CMD_WRITE
  1907.         shl     eax, 2
  1908.         or      eax, 10b ; transition bits
  1909.         shl     eax, 16
  1910.         mov     ax, bx
  1911.         mov     ebx, eax
  1912.         mov     ecx, 31
  1913. .cmd_loop:
  1914.         mov     ax, (1 shl E3C59X_BIT_MGMT_DIR) ; write mii
  1915.         bt      ebx, ecx
  1916.         jnc     .zero_bit
  1917.         or      al, (1 shl E3C59X_BIT_MGMT_DATA)
  1918. .zero_bit:
  1919.         out     dx, ax
  1920.         push    eax
  1921.         in      ax, dx ; delay
  1922.         pop     eax
  1923.         or      al, (1 shl E3C59X_BIT_MGMT_CLK) ; write
  1924.         out     dx, ax
  1925.         in      ax, dx ; delay
  1926.         dec     ecx
  1927.         jns     .cmd_loop
  1928.         ret
  1929.  
  1930. ;***************************************************************************
  1931. ;   Function
  1932. ;      e3c59x_transmit
  1933. ;   Description
  1934. ;      Transmits a packet of data via the ethernet card
  1935. ;         edi - Pointer to 48 bit destination address
  1936. ;          bx - Type of packet
  1937. ;         ecx - size of packet
  1938. ;         esi - pointer to packet data
  1939. ;         ebp - io_addr
  1940. ;   Destroyed registers
  1941. ;      eax, ecx, edx, ebp
  1942. ;
  1943. ;***************************************************************************
  1944.         align 4
  1945. e3c59x_transmit:
  1946.         jmp     dword [e3c59x_transmit_function]
  1947.  
  1948. ;***************************************************************************
  1949. ;   Function
  1950. ;      e3c59x_check_tx_status
  1951. ;   Description
  1952. ;      Checks TxStatus queue.
  1953. ;   Return value
  1954. ;      al - 0 no error was found
  1955. ;      al - 1 error was found TxReset is needed
  1956. ;   Destroyed registers
  1957. ;      eax, ecx, edx, ebp
  1958. ;
  1959. ;***************************************************************************
  1960. e3c59x_check_tx_status:
  1961.         movzx   ebp, word [io_addr] ; to be implemented in ETHERNET.INC
  1962. ; clear TxStatus queue
  1963.         lea     edx, [ebp+E3C59X_REG_TX_STATUS]
  1964.         mov     cl, 31 ; max number of queue entries
  1965. .tx_status_loop:
  1966.         in      al, dx
  1967.         test    al, al
  1968.         jz      .finish ; no error
  1969.         test    al, 0x3f
  1970.         jnz     .finish ; error
  1971. .no_error_found:
  1972. ; clear current TxStatus entry which advances the next one
  1973.         xor     al, al
  1974.         out     dx, al
  1975.         dec     cl
  1976.         jns     .tx_status_loop
  1977. .finish:
  1978.         ret
  1979.  
  1980. ;***************************************************************************
  1981. ;   Function
  1982. ;      e3c59x_vortex_transmit
  1983. ;   Description
  1984. ;      Transmits a packet of data via the ethernet card
  1985. ;         edi - Pointer to 48 bit destination address
  1986. ;          bx - Type of packet
  1987. ;         ecx - size of packet
  1988. ;         esi - pointer to packet data
  1989. ;         ebp - io_addr
  1990. ;   Destroyed registers
  1991. ;      eax, edx, ecx, edi, esi, ebp
  1992. ;
  1993. ;***************************************************************************
  1994.         align 4
  1995. e3c59x_vortex_transmit:
  1996.         push    ecx
  1997.         call    e3c59x_check_tx_status
  1998.         pop     ecx
  1999.         test    al, al
  2000.         jz      .no_error_found
  2001.         jmp     e3c59x_tx_reset
  2002. .no_error_found:
  2003. ; switch to register window 7
  2004.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  2005.         mov     ax, E3C59X_SELECT_REGISTER_WINDOW+7
  2006.         out     dx, ax
  2007. ; check for master operation in progress
  2008.         lea     edx, [ebp+E3C59X_REG_MASTER_STATUS]
  2009.         in      ax, dx
  2010.         test    ah, 0x80
  2011.         jnz     .finish ; no DMA for sending
  2012. ; dword boundary correction
  2013.         cmp     ecx, E3C59X_MAX_ETH_FRAME_SIZE
  2014.         ja      .finish ; packet is too long
  2015. ; write Frame Start Header
  2016.         mov     eax, ecx
  2017. ; add header length and extend the complete length to dword boundary
  2018.         add     eax, ETH_HLEN+3
  2019.         and     eax, not 3
  2020.         lea     edx, [ebp+E3C59X_REG_TX_DATA]
  2021.         out     dx, eax
  2022. ; prepare the complete frame
  2023.         push    esi
  2024.         mov     esi, edi
  2025.         mov     edi, e3c59x_tx_buff
  2026.         zero_to_virt edi
  2027.         cld
  2028. ; copy destination address
  2029.         movsd
  2030.         movsw
  2031. ; copy source address
  2032.         mov     esi, node_addr
  2033.         movsd
  2034.         movsw
  2035. ; copy packet type
  2036.         mov     [edi], bx
  2037.         add     edi, 2
  2038. ; copy packet data
  2039.         pop     esi
  2040.         push    ecx
  2041.         shr     ecx, 2
  2042.         rep     movsd
  2043.         pop     ecx
  2044.         and     ecx, 3
  2045.         rep     movsb
  2046.         mov     ecx, eax
  2047. ; program frame address to be sent
  2048.         lea     edx, [ebp+E3C59X_REG_MASTER_ADDRESS]
  2049.         mov     eax, e3c59x_tx_buff
  2050.         zero_to_dma eax
  2051.         out     dx, eax
  2052. ; program frame length
  2053.         lea     edx, [ebp+E3C59X_REG_MASTER_LEN]
  2054.         mov     eax, ecx
  2055.         out     dx, ax
  2056. ; start DMA Down
  2057.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  2058.         mov     ax, (10100b shl 11) + 1 ; StartDMADown
  2059.         out     dx, ax
  2060. .finish:
  2061.         ret
  2062.  
  2063. ;***************************************************************************
  2064. ;   Function
  2065. ;      e3c59x_boomerang_transmit
  2066. ;   Description
  2067. ;      Transmits a packet of data via the ethernet card
  2068. ;         edi - Pointer to 48 bit destination address
  2069. ;          bx - Type of packet
  2070. ;         ecx - size of packet
  2071. ;         esi - pointer to packet data
  2072. ;         ebp - io_addr
  2073. ;   Destroyed registers
  2074. ;      eax, ebx, ecx, edx, esi, edi, ebp
  2075. ;
  2076. ;***************************************************************************
  2077.         align 4
  2078. e3c59x_boomerang_transmit:
  2079.         push    ecx
  2080.         call    e3c59x_check_tx_status
  2081.         pop     ecx
  2082.         test    al, al
  2083.         jz      .no_error_found
  2084.         jmp     e3c59x_tx_reset
  2085. .no_error_found:
  2086.         cmp     ecx, E3C59X_MAX_ETH_FRAME_SIZE
  2087.         ja      .finish ; packet is too long
  2088. ; calculate descriptor address
  2089.         mov     eax, [e3c59x_prev_dpd]
  2090.         cmp     eax, e3c59x_dpd_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_DPD_SIZE
  2091.         jb      @f
  2092. ; wrap around
  2093.         mov     eax, e3c59x_dpd_buff-E3C59X_DPD_SIZE
  2094. @@:
  2095.         add     eax, E3C59X_DPD_SIZE
  2096.         zero_to_virt eax
  2097.         push    eax
  2098. ; check DnListPtr
  2099.         lea     edx, [ebp+E3C59X_REG_DN_LIST_PTR]
  2100.         in      eax, dx
  2101. ; mark if Dn_List_Ptr is cleared
  2102.         test    eax, eax
  2103.         setz    [e3c59x_dn_list_ptr_cleared]
  2104. ; finish if no more free descriptor is available - FIXME!
  2105.         cmp     eax, [esp]
  2106.         pop     eax
  2107.         jz      .finish
  2108.         push    eax esi
  2109.         mov     esi, edi
  2110. ; calculate tx_buffer address
  2111.         mov     edi, [e3c59x_prev_tx_frame]
  2112.         cmp     edi, e3c59x_tx_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_MAX_ETH_FRAME_SIZE
  2113.         jb      @f
  2114. ; wrap around
  2115.         mov     edi, e3c59x_tx_buff-E3C59X_MAX_ETH_FRAME_SIZE
  2116. @@:
  2117.         add     edi, E3C59X_MAX_ETH_FRAME_SIZE
  2118.         zero_to_virt edi
  2119.         mov     eax, edi
  2120.         cld
  2121. ; copy destination address
  2122.         movsd
  2123.         movsw
  2124. ; copy source address
  2125.         mov     esi, node_addr
  2126.         movsd
  2127.         movsw
  2128. ; copy packet type
  2129.         mov     [edi], bx
  2130.         add     edi, 2
  2131. ; copy packet data
  2132.         pop     esi
  2133.         push    ecx
  2134.         shr     ecx, 2
  2135.         rep     movsd
  2136.         pop     ecx
  2137.         push    ecx
  2138.         and     ecx, 3
  2139.         rep     movsb
  2140. ; padding, do we really need it?
  2141.         pop     ecx
  2142.         add     ecx, ETH_HLEN
  2143.         cmp     ecx, ETH_ZLEN
  2144.         jae     @f
  2145.         mov     ecx, ETH_ZLEN
  2146. @@:
  2147. ; calculate
  2148.         mov     ebx, ecx
  2149.         test    byte [e3c59x_has_hwcksm], 0xff
  2150.         jz      @f
  2151.         or      ebx, (1 shl 26) ; set AddTcpChecksum
  2152. @@:
  2153.         or      ebx, 0x8000 ; transmission complete notification
  2154.         or      ecx, 0x80000000 ; last fragment
  2155. ; program DPD
  2156.         mov     edi, eax
  2157.         pop     eax
  2158.         and     dword [eax+E3C59X_DPD_DN_NEXT_PTR], 0
  2159.         mov     dword [eax+E3C59X_DPD_FRAME_START_HDR], ebx
  2160.         virt_to_dma edi
  2161.         mov     dword [eax+E3C59X_DPD_DN_FRAG_ADDR], edi
  2162.         mov     [eax+E3C59X_DPD_DN_FRAG_LEN], ecx
  2163. ; calculate physical address
  2164.         virt_to_dma eax
  2165.         push    eax
  2166.         cmp     byte [e3c59x_dn_list_ptr_cleared], 0
  2167.         jz      .add_to_list
  2168. ; write Dn_List_Ptr
  2169.         out     dx, eax
  2170.         jmp     .finish
  2171. .add_to_list:
  2172. ; DnStall
  2173.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  2174.         mov     ax, ((110b shl 11)+2)
  2175.         out     dx, ax
  2176. ; wait for DnStall to complete
  2177.         mov     ecx, 6000
  2178. .wait_for_stall:
  2179.         in      ax, dx ; read E3C59X_REG_INT_STATUS
  2180.         test    ah, 10000b
  2181.         jz      .dnstall_ok
  2182.         dec     ecx
  2183.         jnz     .wait_for_stall
  2184. .dnstall_ok:
  2185.         pop     eax
  2186.         push    eax
  2187.         mov     ebx, [e3c59x_prev_dpd]
  2188.         zero_to_virt ebx
  2189.         mov     [ebx], eax
  2190.         lea     edx, [ebp+E3C59X_REG_DN_LIST_PTR]
  2191.         in      eax, dx
  2192.         test    eax, eax
  2193.         jnz     .dnunstall
  2194. ; if Dn_List_Ptr has been cleared fill it up
  2195.         pop     eax
  2196.         push    eax
  2197.         out     dx, eax
  2198. .dnunstall:
  2199. ; DnUnStall
  2200.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  2201.         mov     ax, ((110b shl 11)+3)
  2202.         out     dx, ax
  2203. .finish:
  2204.         pop     eax
  2205.         dma_to_zero eax
  2206.         mov     [e3c59x_prev_dpd], eax
  2207.         dma_to_zero edi
  2208.         mov     [e3c59x_prev_tx_frame], edi
  2209.         ret
  2210.  
  2211. ;***************************************************************************
  2212. ; Function
  2213. ;    e3c59x_poll
  2214. ; Description
  2215. ;    Polls the ethernet card for a received packet
  2216. ;    Received data, if any, ends up in Ether_buffer
  2217. ; Destroyed registers
  2218. ;    eax, ebx, edx, ecx, edi, esi, ebp
  2219. ;
  2220. ;***************************************************************************
  2221.         align 4
  2222. e3c59x_poll:
  2223.         jmp     dword [e3c59x_receive_function]
  2224.  
  2225. ;***************************************************************************
  2226. ; Function
  2227. ;    e3c59x_vortex_poll
  2228. ; Description
  2229. ;    Polls the ethernet card for a received packet
  2230. ;    Received data, if any, ends up in Ether_buffer
  2231. ; Parameters
  2232. ;    ebp - io_addr
  2233. ; Return value
  2234. ;    al - 0 ; no packet received
  2235. ;    al - 1 ; packet received
  2236. ; Destroyed registers
  2237. ;    eax, ebx, edx, ecx, edi, esi, ebp
  2238. ;
  2239. ;***************************************************************************
  2240.         align 4
  2241. e3c59x_vortex_poll:
  2242.         and     word [eth_rx_data_len], 0 ; assume no packet received
  2243.         movzx   ebp, word [io_addr] ; to be implemented in ETHERNET.INC
  2244. .rx_status_loop:
  2245. ; examine RxStatus
  2246.         lea     edx, [ebp+E3C59X_REG_RX_STATUS]
  2247.         in      ax, dx
  2248.         test    ax, ax
  2249.         jz      .finish
  2250.         test    ah, 0x80 ; rxIncomplete
  2251.         jz      .check_error
  2252.         jmp     .finish
  2253. .check_error:
  2254.         test    ah, 0x40
  2255.         jz      .check_length
  2256. ; discard the top frame received advancing the next one
  2257.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  2258.         mov     ax, (01000b shl 11)
  2259.         out     dx, ax
  2260.         jmp     .rx_status_loop
  2261. .check_length:
  2262.         and     eax, 0x1fff
  2263.         cmp     eax, E3C59X_MAX_ETH_PKT_SIZE
  2264.         ja      .discard_frame ; frame is too long discard it
  2265. .check_dma:
  2266.         push    eax
  2267. ; switch to register window 7
  2268.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  2269.         mov     ax, E3C59X_SELECT_REGISTER_WINDOW+7
  2270.         out     dx, ax
  2271. ; check for master operation in progress
  2272.         lea     edx, [ebp+E3C59X_REG_MASTER_STATUS]
  2273.         in      ax, dx
  2274.         test    ah, 0x80
  2275.         jz      .read_frame ; no DMA for receiving
  2276.         pop     eax
  2277.         jmp     .finish
  2278. .read_frame:
  2279. ; program buffer address to read in
  2280.         lea     edx, [ebp+E3C59X_REG_MASTER_ADDRESS]
  2281. if defined E3C59X_LINUX
  2282.         mov     eax, e3c59x_rx_buff
  2283.         zero_to_dma eax
  2284. else
  2285.         mov     eax, Ether_buffer
  2286. end if
  2287.         out     dx, eax
  2288. ; program frame length
  2289.         lea     edx, [ebp+E3C59X_REG_MASTER_LEN]
  2290.         mov     ax, 1560
  2291.         out     dx, ax
  2292. ; start DMA Up
  2293.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  2294.         mov     ax, (10100b shl 11) ; StartDMAUp
  2295.         out     dx, ax
  2296. ; check for master operation in progress
  2297. .dma_loop:
  2298.         lea     edx, [ebp+E3C59X_REG_MASTER_STATUS]
  2299.         in      ax, dx
  2300.         test    ah, 0x80
  2301.         jnz     .dma_loop
  2302. ; registrate the received packet length
  2303.         pop     eax
  2304.         mov     word [eth_rx_data_len], ax
  2305. ; discard the top frame received
  2306. .discard_frame:
  2307.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  2308.         mov     ax, (01000b shl 11)
  2309.         out     dx, ax
  2310. .finish:
  2311. ; set return value
  2312.         cmp     word [eth_rx_data_len], 0
  2313.         setne   al
  2314.         ret
  2315.  
  2316. ;***************************************************************************
  2317. ; Function
  2318. ;    e3c59x_boomerang_poll
  2319. ; Description
  2320. ;    Polls the ethernet card for a received packet
  2321. ;    Received data, if any, ends up in Ether_buffer
  2322. ; Parameters
  2323. ;    ebp - io_addr
  2324. ; Return value
  2325. ;    al - 0 ; no packet received
  2326. ;    al - 1 ; packet received
  2327. ; Destroyed registers
  2328. ;    eax, edx, ecx, edi, esi, ebp
  2329. ;
  2330. ;***************************************************************************
  2331.         align 4
  2332. e3c59x_boomerang_poll:
  2333.         and     word [eth_rx_data_len], 0 ; assume no packet received
  2334.         movzx   ebp, word [io_addr] ; to be implemented in ETHERNET.INC
  2335. ; check if packet is uploaded
  2336.         mov     eax, [e3c59x_curr_upd]
  2337.         test    byte [eax+E3C59X_UPD_PKT_STATUS+1], 0x80 ; upPktComplete
  2338.         jnz     .check_error
  2339.         jmp     .finish
  2340. ; packet is uploaded check for any error
  2341. .check_error:
  2342.         test    byte [eax+E3C59X_UPD_PKT_STATUS+1], 0x40 ; upError
  2343.         jz      .copy_packet_length
  2344.         and     dword [eax+E3C59X_UPD_PKT_STATUS], 0
  2345.         jmp     .finish
  2346. .copy_packet_length:
  2347.         mov     ecx, [eax+E3C59X_UPD_PKT_STATUS]
  2348.         and     ecx, 0x1fff
  2349.         cmp     ecx, E3C59X_MAX_ETH_PKT_SIZE
  2350.         jbe     .copy_packet
  2351.         and     dword [eax+E3C59X_UPD_PKT_STATUS], 0
  2352.         jmp     .finish
  2353. .copy_packet:
  2354.         push    ecx
  2355.         mov     word [eth_rx_data_len], cx
  2356.         mov     esi, [eax+E3C59X_UPD_UP_FRAG_ADDR]
  2357.         dma_to_virt esi
  2358.         mov     edi, Ether_buffer
  2359.         shr     ecx, 2 ; first copy dword-wise
  2360.         cld
  2361.         rep     movsd ; copy the dwords
  2362.         pop     ecx
  2363.         and     ecx, 3
  2364.         rep     movsb ; copy the rest bytes
  2365.         mov     eax, [e3c59x_curr_upd]
  2366.         and     dword [eax+E3C59X_UPD_PKT_STATUS], 0
  2367.         virt_to_zero eax
  2368.         cmp     eax, e3c59x_upd_buff+(E3C59X_NUM_RX_DESC-1)*E3C59X_UPD_SIZE
  2369.         jb      .no_wrap
  2370. ; wrap around
  2371.         mov     eax, e3c59x_upd_buff-E3C59X_UPD_SIZE
  2372. .no_wrap:
  2373.         add     eax, E3C59X_UPD_SIZE
  2374.         zero_to_virt eax
  2375.         mov     [e3c59x_curr_upd], eax
  2376. .finish:
  2377. ; check if the NIC is in the upStall state
  2378.         lea     edx, [ebp+E3C59X_REG_UP_PKT_STATUS]
  2379.         in      eax, dx
  2380.         test    ah, 0x20 ; UpStalled
  2381.         jz     .noUpUnStall
  2382. ; issue upUnStall command
  2383.         lea     edx, [ebp+E3C59X_REG_COMMAND]
  2384.         mov     ax, ((110b shl 11)+1) ; upUnStall
  2385.         out     dx, ax
  2386. .noUpUnStall:
  2387. ; set return value
  2388.         cmp     word [eth_rx_data_len], 0
  2389.         setnz   al
  2390.         ret
  2391.