Subversion Repositories Kolibri OS

Rev

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

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