Subversion Repositories Kolibri OS

Rev

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

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