Subversion Repositories Kolibri OS

Rev

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

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