Subversion Repositories Kolibri OS

Rev

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

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