Subversion Repositories Kolibri OS

Rev

Rev 1481 | Blame | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  9. ;;
  10. ;;  Ethernet Driver for KolibriOS
  11. ;;
  12. ;;  3c59x.asm
  13. ;;  Ported to KolibriOS net-branch by hidnplayr (28/05/10)
  14. ;;
  15. ;;  Thanks to: scrap metal recyclers, whom provide me with loads of hardware
  16. ;;             diamond: who makes me understand KolibriOS
  17. ;;
  18. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  19.  
  20. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  21. ;;                                                                         ;;
  22. ;;  3C59X.INC                                                              ;;
  23. ;;                                                                         ;;
  24. ;;  Ethernet driver for Menuet OS                                          ;;
  25. ;;                                                                         ;;
  26. ;;  Driver for 3Com fast etherlink 3c59x and                               ;;
  27. ;;         etherlink XL 3c900 and 3c905 cards                              ;;
  28. ;;  References:                                                            ;;
  29. ;;    www.3Com.com - data sheets                                           ;;
  30. ;;    DP83840A.pdf - ethernet physical layer                               ;;
  31. ;;    3c59x.c - linux driver                                               ;;
  32. ;;    ethernet driver template by Mike Hibbett                             ;;
  33. ;;                                                                         ;;
  34. ;;  Credits                                                                ;;
  35. ;;   Mike Hibbett,                                                         ;;
  36. ;;         who kindly supplied me with a 3Com905C-TX-M card                ;;
  37. ;;                                                                         ;;
  38. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  39. ;;
  40. ;; Copyright (c) 2004, Endre Kozma <endre.kozma@axelero.hu>
  41. ;; All rights reserved.
  42. ;;
  43. ;; Redistribution  and  use  in  source  and  binary  forms, with or without
  44. ;; modification, are permitted provided  that  the following  conditions are
  45. ;; met:
  46. ;;
  47. ;; 1. Redistributions of source code must retain the above  copyright notice,
  48. ;;    this list of conditions and the following disclaimer.
  49. ;;
  50. ;; 2. Redistributions  in  binary form  must  reproduce  the above copyright
  51. ;;    notice, this  list of conditions  and the  following disclaimer in the
  52. ;;    documentation and/or other  materials  provided with  the distribution.
  53. ;;
  54. ;; 3. The name of the author may not be used to  endorse or promote products
  55. ;;    derived from this software without  specific prior  written permission.
  56. ;;
  57. ;; THIS SOFTWARE IS  PROVIDED  BY  THE  AUTHOR  ``AS IS'' AND ANY EXPRESS OR
  58. ;; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  59. ;; OF  MERCHANTABILITY AND FITNESS  FOR A PARTICULAR  PURPOSE ARE DISCLAIMED.
  60. ;; IN  NO  EVENT  SHALL  THE  AUTHOR  BE  LIABLE  FOR  ANY  DIRECT, INDIRECT,
  61. ;; INCIDENTAL, SPECIAL, EXEMPLARY, OR  CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  62. ;; NOT LIMITED TO, PROCUREMENT OF  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  63. ;; DATA, OR  PROFITS; OR  BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON ANY
  64. ;; THEORY OF  LIABILITY, WHETHER IN  CONTRACT,  STRICT  LIABILITY,  OR  TORT
  65. ;; (INCLUDING NEGLIGENCE OR OTHERWISE)  ARISING IN ANY WAY OUT OF THE USE OF
  66. ;; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  67. ;;
  68. ;;  History
  69. ;;  =======
  70. ;;  $Log: 3C59X.INC,v $
  71. ;;  Revision 1.3  2004/07/11 12:21:12  kozma
  72. ;;  Support of vortex chips (3c59x) added.
  73. ;;  Support of 3c920 and 3c982 added.
  74. ;;  Corrections.
  75. ;;
  76. ;;  Revision 1.2  2004/06/12 19:40:20  kozma
  77. ;;  Function e3c59x_set_available_media added in order to set
  78. ;;  the default media in case auto detection finds no valid link.
  79. ;;  Incorrect mii check removed (3c900 Cyclone works now).
  80. ;;  Cleanups.
  81. ;;
  82. ;;  Revision 1.1  2004/06/12 18:27:15  kozma
  83. ;;  Initial revision
  84. ;;
  85. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  86.  
  87.  
  88. PROMISCIOUS equ 1
  89.  
  90.  
  91. format MS COFF
  92.  
  93.         API_VERSION             equ 0x01000100
  94.  
  95.         DEBUG                   equ 1
  96.         __DEBUG__               equ 1
  97.         __DEBUG_LEVEL__         equ 1
  98.  
  99. include 'proc32.inc'
  100. include 'imports.inc'
  101. include 'fdo.inc'
  102. include 'netdrv.inc'
  103.  
  104.  
  105. OS_BASE         equ 0
  106. new_app_base    equ 0x60400000
  107. PROC_BASE       equ OS_BASE+0x0080000
  108.  
  109. public START
  110. public service_proc
  111. public version
  112.  
  113.  
  114. virtual at ebx
  115.  
  116.         device:
  117.  
  118.         ETH_DEVICE
  119.  
  120.       .rx_buffer        dd ?
  121.       .tx_buffer        dd ?
  122.       .dpd_buffer       dd ?
  123.       .upd_buffer       dd ?
  124.       .curr_upd         dd ?
  125.       .prev_dpd         dd ?
  126.  
  127.       .io_addr          dd ?
  128.       .pci_bus          db ?
  129.       .pci_dev          db ?
  130.       .irq_line         db ?
  131.  
  132.       .prev_tx_frame            dd ?
  133.       .ver_id                   db ?
  134.       .full_bus_master          db ?
  135.       .has_hwcksm               db ?
  136.       .preamble                 db ?
  137.       .dn_list_ptr_cleared      db ?
  138.       .self_directed_packet     rb 20
  139.  
  140.       .size = $ - device
  141.  
  142. end virtual
  143.  
  144.  
  145. struc DPD {     ; Download Packet Descriptor
  146.  
  147.       .next_ptr         dd ?
  148.       .frame_start_hdr  dd ?
  149.       .frag_addr        dd ?    ; for packet data
  150.       .frag_len         dd ?    ; for packet data
  151.       .realaddr         dd ?
  152.       .size             = 32
  153. }
  154.  
  155. virtual at 0
  156.   dpd DPD
  157. end virtual
  158.  
  159.  
  160. struc UPD {     ; Upload Packet Descriptor
  161.  
  162.       .next_ptr         dd ?
  163.       .pkt_status       dd ?
  164.       .frag_addr        dd ?
  165.       .frag_len         dd ?    ; for packet data
  166.       .realaddr         dd ?
  167.       .size             = 32
  168.  
  169. }
  170.  
  171. virtual at 0
  172.   upd UPD
  173. end virtual
  174.  
  175.  
  176.         MAX_DEVICES             equ 16
  177.         FORCE_FD                equ 0  ; forcing full duplex mode makes sense at some cards and link types
  178.  
  179.  
  180. ; Ethernet frame symbols
  181.         ETH_ALEN                equ 6
  182.         ETH_HLEN                equ (2*ETH_ALEN+2)
  183.         ETH_ZLEN                equ 60 ; 60 + 4bytes auto payload for
  184.                                               ; mininmum 64bytes frame length
  185.  
  186. ; Registers
  187.         REG_POWER_MGMT_CTRL     equ 0x7c
  188.         REG_UP_LIST_PTR         equ 0x38
  189.         REG_UP_PKT_STATUS       equ 0x30
  190.         REG_TX_FREE_THRESH      equ 0x2f
  191.         REG_DN_LIST_PTR         equ 0x24
  192.         REG_DMA_CTRL            equ 0x20
  193.         REG_TX_STATUS           equ 0x1b
  194.         REG_RX_STATUS           equ 0x18
  195.         REG_TX_DATA             equ 0x10
  196. ; Common window registers
  197.         REG_INT_STATUS          equ 0xe
  198.         REG_COMMAND             equ 0xe
  199. ; Register window 7
  200.         REG_MASTER_STATUS       equ 0xc
  201.         REG_POWER_MGMT_EVENT    equ 0xc
  202.         REG_MASTER_LEN          equ 0x6
  203.         REG_VLAN_ETHER_TYPE     equ 0x4
  204.         REG_VLAN_MASK           equ 0x0
  205.         REG_MASTER_ADDRESS      equ 0x0
  206. ; Register window 6
  207.         REG_BYTES_XMITTED_OK    equ 0xc
  208.         REG_BYTES_RCVD_OK       equ 0xa
  209.         REG_UPPER_FRAMES_OK     equ 0x9
  210.         REG_FRAMES_DEFERRED     equ 0x8
  211.         REG_FRAMES_RCVD_OK      equ 0x7
  212.         REG_FRAMES_XMITTED_OK   equ 0x6
  213.         REG_RX_OVERRUNS         equ 0x5
  214.         REG_LATE_COLLISIONS     equ 0x4
  215.         REG_SINGLE_COLLISIONS   equ 0x3
  216.         REG_MULTIPLE_COLLISIONS equ 0x2
  217.         REG_SQE_ERRORS          equ 0x1
  218.         REG_CARRIER_LOST        equ 0x0
  219. ; Register window 5
  220.         REG_INDICATION_ENABLE   equ 0xc
  221.         REG_INTERRUPT_ENABLE    equ 0xa
  222.         REG_TX_RECLAIM_THRESH   equ 0x9
  223.         REG_RX_FILTER           equ 0x8
  224.         REG_RX_EARLY_THRESH     equ 0x6
  225.         REG_TX_START_THRESH     equ 0x0
  226. ; Register window 4
  227.         REG_UPPER_BYTES_OK      equ 0xe
  228.         REG_BAD_SSD             equ 0xc
  229.         REG_MEDIA_STATUS        equ 0xa
  230.         REG_PHYSICAL_MGMT       equ 0x8
  231.         REG_NETWORK_DIAGNOSTIC  equ 0x6
  232.         REG_FIFO_DIAGNOSTIC     equ 0x4
  233.         REG_VCO_DIAGNOSTIC      equ 0x2 ; may not supported
  234. ; Bits in register window 4
  235.         BIT_AUTOSELECT          equ 24
  236. ; Register window 3
  237.         REG_TX_FREE             equ 0xc
  238.         REG_RX_FREE             equ 0xa
  239.         REG_MEDIA_OPTIONS       equ 0x8
  240.         REG_MAC_CONTROL         equ 0x6
  241.         REG_MAX_PKT_SIZE        equ 0x4
  242.         REG_INTERNAL_CONFIG     equ 0x0
  243. ; Register window 2
  244.         REG_RESET_OPTIONS       equ 0xc
  245.         REG_STATION_MASK_HI     equ 0xa
  246.         REG_STATION_MASK_MID    equ 0x8
  247.         REG_STATION_MASK_LO     equ 0x6
  248.         REG_STATION_ADDRESS_HI  equ 0x4
  249.         REG_STATION_ADDRESS_MID equ 0x2
  250.         REG_STATION_ADDRESS_LO  equ 0x0
  251. ; Register window 1
  252.         REG_TRIGGER_BITS        equ 0xc
  253.         REG_SOS_BITS            equ 0xa
  254.         REG_WAKE_ON_TIMER       equ 0x8
  255.         REG_SMB_RXBYTES         equ 0x7
  256.         REG_SMB_DIAG            equ 0x5
  257.         REG_SMB_ARB             equ 0x4
  258.         REG_SMB_STATUS          equ 0x2
  259.         REG_SMB_ADDRESS         equ 0x1
  260.         REG_SMB_FIFO_DATA       equ 0x0
  261. ; Register window 0
  262.         REG_EEPROM_DATA         equ 0xc
  263.         REG_EEPROM_COMMAND      equ 0xa
  264.         REG_BIOS_ROM_DATA       equ 0x8
  265.         REG_BIOS_ROM_ADDR       equ 0x4
  266. ; Physical management bits
  267.         BIT_MGMT_DIR            equ 2 ; drive with the data written in mgmtData
  268.         BIT_MGMT_DATA           equ 1 ; MII management data bit
  269.         BIT_MGMT_CLK            equ 0 ; MII management clock
  270. ; MII commands
  271.         MII_CMD_MASK            equ (1111b shl 10)
  272.         MII_CMD_READ            equ (0110b shl 10)
  273.         MII_CMD_WRITE           equ (0101b shl 10)
  274. ; MII registers
  275.         REG_MII_BMCR            equ 0 ; basic mode control register
  276.         REG_MII_BMSR            equ 1 ; basic mode status register
  277.         REG_MII_ANAR            equ 4 ; auto negotiation advertisement register
  278.         REG_MII_ANLPAR          equ 5 ; auto negotiation link partner ability register
  279.         REG_MII_ANER            equ 6 ; auto negotiation expansion register
  280. ; MII bits
  281.         BIT_MII_AUTONEG_COMPLETE     equ 5 ; auto-negotiation complete
  282.         BIT_MII_PREAMBLE_SUPPRESSION equ 6
  283. ; eeprom bits and commands
  284.         EEPROM_CMD_READ         equ 0x80
  285.         EEPROM_BIT_BUSY         equ 15
  286. ; eeprom registers
  287.         EEPROM_REG_OEM_NODE_ADDR equ 0xa
  288.         EEPROM_REG_CAPABILITIES  equ 0x10
  289. ; Commands for command register
  290.         SELECT_REGISTER_WINDOW  equ (1 shl 11)
  291.  
  292.         IS_VORTEX               equ 0x1
  293.         IS_BOOMERANG            equ 0x2
  294.         IS_CYCLONE              equ 0x4
  295.         IS_TORNADO              equ 0x8
  296.         EEPROM_8BIT             equ 0x10
  297.         HAS_PWR_CTRL            equ 0x20
  298.         HAS_MII                 equ 0x40
  299.         HAS_NWAY                equ 0x80
  300.         HAS_CB_FNS              equ 0x100
  301.         INVERT_MII_PWR          equ 0x200
  302.         INVERT_LED_PWR          equ 0x400
  303.         MAX_COLLISION_RESET     equ 0x800
  304.         EEPROM_OFFSET           equ 0x1000
  305.         HAS_HWCKSM              equ 0x2000
  306.         EXTRA_PREAMBLE          equ 0x4000
  307.  
  308. ; Status
  309.  
  310.         IntLatch                equ 0x0001
  311.         HostError               equ 0x0002
  312.         TxComplete              equ 0x0004
  313.         TxAvailable             equ 0x0008
  314.         RxComplete              equ 0x0010
  315.         RxEarly                 equ 0x0020
  316.         IntReq                  equ 0x0040
  317.         StatsFull               equ 0x0080
  318.         DMADone                 equ 0x0100 ; 1 shl 8
  319.         DownComplete            equ 0x0200 ; 1 shl 9
  320.         UpComplete              equ 0x0400 ; 1 shl 10
  321.         DMAInProgress           equ 0x0800 ; 1 shl 11  (DMA controller is still busy)
  322.         CmdInProgress           equ 0x1000 ; 1 shl 12  (EL3_CMD is still busy)
  323.  
  324.         S_5_INTS                equ HostError + RxEarly + UpComplete + DownComplete ; + RxComplete + TxComplete + TxAvailable
  325.  
  326.  
  327.  
  328. ; Commands
  329.  
  330.         TotalReset              equ 0 shl 11
  331.         SelectWindow            equ 1 shl 11
  332.         StartCoax               equ 2 shl 11
  333.         RxDisable               equ 3 shl 11
  334.         RxEnable                equ 4 shl 11
  335.         RxReset                 equ 5 shl 11
  336.         UpStall                 equ 6 shl 11
  337.         UpUnstall               equ (6 shl 11)+1
  338.         DownStall               equ (6 shl 11)+2
  339.         DownUnstall             equ (6 shl 11)+3
  340.         RxDiscard               equ 8 shl 11
  341.         TxEnable                equ 9 shl 11
  342.         TxDisable               equ 10 shl 11
  343.         TxReset                 equ 11 shl 11
  344.         FakeIntr                equ 12 shl 11
  345.         AckIntr                 equ 13 shl 11
  346.         SetIntrEnb              equ 14 shl 11
  347.         SetStatusEnb            equ 15 shl 11
  348.         SetRxFilter             equ 16 shl 11
  349.         SetRxThreshold          equ 17 shl 11
  350.         SetTxThreshold          equ 18 shl 11
  351.         SetTxStart              equ 19 shl 11
  352.         StartDMAUp              equ 20 shl 11
  353.         StartDMADown            equ (20 shl 11)+1
  354.         StatsEnable             equ 21 shl 11
  355.         StatsDisable            equ 22 shl 11
  356.         StopCoax                equ 23 shl 11
  357.         SetFilterBit            equ 25 shl 11}
  358.  
  359.  
  360. ; Rx mode bits
  361.  
  362.         RxStation               equ 1
  363.         RxMulticast             equ 2
  364.         RxBroadcast             equ 4
  365.         RxProm                  equ 8
  366.  
  367.  
  368. ; RX/TX buffers sizes
  369.  
  370.         MAX_ETH_PKT_SIZE        equ 1536   ; max packet size
  371.         NUM_RX_DESC             equ 4      ; a power of 2 number
  372.         NUM_TX_DESC             equ 4      ; a power of 2 number
  373.         RX_BUFFER_SIZE          equ (MAX_ETH_FRAME_SIZE*NUM_RX_DESC)
  374.         TX_BUFFER_SIZE          equ (MAX_ETH_FRAME_SIZE*NUM_TX_DESC)
  375.         MAX_ETH_FRAME_SIZE      equ 1520        ; size of ethernet frame + bytes alignment
  376.  
  377.  
  378.  
  379.  
  380.  
  381. section '.flat' code readable align 16
  382.  
  383. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  384. ;;                        ;;
  385. ;; proc START             ;;
  386. ;;                        ;;
  387. ;; (standard driver proc) ;;
  388. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  389.  
  390. align 4
  391. proc START stdcall, state:dword
  392.  
  393.         cmp [state], 1
  394.         jne .exit
  395.  
  396.   .entry:
  397.  
  398.         DEBUGF 1,"Loading 3com network driver\n"
  399.         stdcall RegService, my_service, service_proc
  400.         ret
  401.  
  402.   .fail:
  403.   .exit:
  404.         xor eax, eax
  405.         ret
  406.  
  407. endp
  408.  
  409.  
  410.  
  411.  
  412.  
  413. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  414. ;;                        ;;
  415. ;; proc SERVICE_PROC      ;;
  416. ;;                        ;;
  417. ;; (standard driver proc) ;;
  418. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  419.  
  420. align 4
  421. proc service_proc stdcall, ioctl:dword
  422.  
  423.         mov     edx, [ioctl]
  424.         mov     eax, [IOCTL.io_code]
  425.  
  426. ;------------------------------------------------------
  427.  
  428.         cmp     eax, 0 ;SRV_GETVERSION
  429.         jne     @F
  430.  
  431.         cmp     [IOCTL.out_size], 4
  432.         jl      .fail
  433.         mov     eax, [IOCTL.output]
  434.         mov     [eax], dword API_VERSION
  435.  
  436.         xor     eax, eax
  437.         ret
  438.  
  439. ;------------------------------------------------------
  440.   @@:
  441.         cmp     eax, 1 ;SRV_HOOK
  442.         jne     .fail
  443.  
  444.         cmp     [IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
  445.         jl      .fail
  446.  
  447.         mov     eax, [IOCTL.input]
  448.         cmp     byte [eax], 1                           ; 1 means device number and bus number (pci) are given
  449.         jne     .fail                                   ; other types of this hardware dont exist
  450.  
  451. ; check if the device is already listed
  452.  
  453.         mov     ecx, [VORTEX_DEVICES]
  454.         test    ecx, ecx
  455.         jz      .maybeboomerang
  456.  
  457.         mov     esi, VORTEX_LIST
  458.         mov     eax, [IOCTL.input]                      ; get the pci bus and device numbers
  459.         mov     ax , [eax+1]                            ;
  460.   .nextdevice:
  461.         mov     ebx, [esi]
  462.         cmp     ax , word [device.pci_bus]              ; compare with pci and device num in device list (notice the usage of word instead of byte)
  463.         je      .find_devicenum                         ; Device is already loaded, let's find it's device number
  464.         add     esi, 4
  465.         loop    .nextdevice
  466.  
  467.  
  468.   .maybeboomerang:
  469.         mov     ecx, [BOOMERANG_DEVICES]
  470.         test    ecx, ecx
  471.         jz      .firstdevice
  472.  
  473.         mov     esi, BOOMERANG_LIST
  474.         mov     eax, [IOCTL.input]                      ; get the pci bus and device numbers
  475.         mov     ax , [eax+1]                            ;
  476.   .nextdevice2:
  477.         mov     ebx, [esi]
  478.         cmp     ax , word [device.pci_bus]              ; compare with pci and device num in device list (notice the usage of word instead of byte)
  479.         je      .find_devicenum                         ; Device is already loaded, let's find it's device number
  480.         add     esi, 4
  481.         loop    .nextdevice2
  482.  
  483.  
  484. ; This device doesnt have its own eth_device structure yet, lets create one
  485.   .firstdevice:
  486.         mov     ecx, [BOOMERANG_DEVICES]
  487.         add     ecx, [VORTEX_DEVICES]
  488.         cmp     ecx, MAX_DEVICES                        ; First check if the driver can handle one more card
  489.         jge     .fail
  490.  
  491.         push    edx
  492.         stdcall KernelAlloc, dword device.size          ; Allocate the buffer for eth_device structure
  493.         pop     edx
  494.         test    eax, eax
  495.         jz      .fail
  496.         mov     ebx, eax                                ; ebx is always used as a pointer to the structure (in driver, but also in kernel code)
  497.  
  498. ; Fill in the direct call addresses into the struct
  499.  
  500.         mov     [device.reset], reset
  501.         mov     [device.transmit], null_op
  502.         mov     [device.get_MAC], read_mac
  503.         mov     [device.set_MAC], write_mac
  504.         mov     [device.unload], null_op
  505.         mov     [device.name], my_service
  506.  
  507. ; save the pci bus and device numbers
  508.  
  509.         mov     eax, [IOCTL.input]
  510.         mov     cl , [eax+1]
  511.         mov     [device.pci_bus], cl
  512.         mov     cl , [eax+2]
  513.         mov     [device.pci_dev], cl
  514.  
  515. ; Now, it's time to find the base io addres of the PCI device
  516.  
  517.         find_io [device.pci_bus], [device.pci_dev], [device.io_addr]
  518.  
  519. ; We've found the io address, find IRQ now
  520.  
  521.         find_irq [device.pci_bus], [device.pci_dev], [device.irq_line]
  522.  
  523.         DEBUGF  1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
  524.         [device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:4
  525.  
  526.         allocate_and_clear [device.tx_buffer], (MAX_ETH_FRAME_SIZE*NUM_TX_DESC), .err
  527.         allocate_and_clear [device.rx_buffer], (MAX_ETH_FRAME_SIZE*NUM_RX_DESC), .err
  528.         allocate_and_clear [device.dpd_buffer], (dpd.size*NUM_TX_DESC), .err
  529.         allocate_and_clear [device.upd_buffer], (dpd.size*NUM_RX_DESC), .err
  530.  
  531. ; Ok, the eth_device structure is ready, let's probe the device
  532.         call    probe                                                   ; this function will output in eax
  533.         test    eax, eax
  534.         jnz     .err                                                    ; If an error occured, exit
  535.  
  536.  
  537.         movzx   ecx, [device.ver_id]
  538.         test    word [hw_versions+2+ecx*4], IS_VORTEX
  539.         jz      .not_vortex
  540.  
  541.  
  542.         mov     eax, [VORTEX_DEVICES]                                          ; Add the device structure to our device list
  543.         mov     [VORTEX_LIST+4*eax], ebx                                ; (IRQ handler uses this list to find device)
  544.         inc     [VORTEX_DEVICES]                                               ;
  545.  
  546.   .register:
  547.  
  548.         call    EthRegDev
  549.  
  550.         cmp     eax, -1
  551.         je      .destroy
  552.  
  553.         call    start
  554.  
  555.         ret
  556.  
  557.   .not_vortex:
  558.  
  559.         mov     eax, [BOOMERANG_DEVICES]                                          ; Add the device structure to our device list
  560.         mov     [BOOMERANG_LIST+4*eax], ebx                                ; (IRQ handler uses this list to find device)
  561.         inc     [BOOMERANG_DEVICES]
  562.  
  563.         call    .register
  564.  
  565. ; If the device was already loaded, find the device number and return it in eax
  566.  
  567.   .find_devicenum:
  568.         DEBUGF  1,"Trying to find device number of already registered device\n"
  569.         call    EthStruc2Dev                                            ; This kernel procedure converts a pointer to device struct in ebx
  570.                                                                         ; into a device number in edi
  571.         mov     eax, edi                                                ; Application wants it in eax instead
  572.         DEBUGF  1,"Kernel says: %u\n", eax
  573.         ret
  574.  
  575. ; If an error occured, remove all allocated data and exit (returning -1 in eax)
  576.  
  577.   .destroy:
  578.         ; todo: reset device into virgin state
  579.  
  580.   .err:
  581.         stdcall KernelFree, [device.rx_buffer]
  582.         stdcall KernelFree, [device.tx_buffer]
  583.         stdcall KernelFree, ebx
  584.  
  585.  
  586.   .fail:
  587.         or      eax, -1
  588.         ret
  589.  
  590. ;------------------------------------------------------
  591. endp
  592.  
  593.  
  594. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  595. ;;                                                                        ;;
  596. ;;        Actual Hardware dependent code starts here                      ;;
  597. ;;                                                                        ;;
  598. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  599.  
  600.  
  601.  
  602.  
  603.  
  604. ;***************************************************************************
  605. ;   Function
  606. ;      probe
  607. ;   Description
  608. ;      Searches for an ethernet card, enables it and clears the rx buffer
  609. ;   Destroyed registers
  610. ;      eax, ebx, ecx, edx, edi, esi
  611. ;
  612. ;***************************************************************************
  613.  
  614. align 4
  615. probe:                  ; Tested - ok
  616.  
  617.         DEBUGF  1,"Probing 3com card\n"
  618.  
  619.         make_bus_master [device.pci_bus], [device.pci_dev]
  620.  
  621. ; wake up the card
  622.         call    wake_up
  623.  
  624.         movzx   ecx, [device.pci_bus]
  625.         movzx   edx, [device.pci_dev]
  626.         stdcall PciRead32, ecx ,edx ,0                                ; get device/vendor id
  627.  
  628.         DEBUGF  1,"Vendor id: 0x%x\n", ax
  629.  
  630.         cmp     ax , 0x10B7
  631.         jne     .notfound
  632.         shr     eax, 16
  633.  
  634.         DEBUGF  1,"Vendor ok!, device id: 0x%x\n", ax
  635.  
  636. ; get chip version
  637.         mov     ecx, HW_VERSIONS_SIZE/4-1
  638. .loop:
  639.         cmp     ax , [hw_versions+ecx*4]
  640.         jz      .found
  641.         loop    .loop
  642.         DEBUGF  1,"ecx: %u\n", ecx
  643. .notfound:
  644.         DEBUGF  1,"Device id not found in list!\n"
  645.         or      eax, -1
  646.         ret
  647. .found:
  648.         mov     esi, [hw_str+ecx*4]
  649.         DEBUGF  1,"Hardware type: %s\n", esi
  650.         mov     [device.name], esi
  651.  
  652.         mov     [device.ver_id], cl
  653.         test    word [hw_versions+2+ecx*4], HAS_HWCKSM
  654.         setnz   [device.has_hwcksm]
  655. ; set pci latency for vortex cards
  656.         test    word [hw_versions+2+ecx*4], IS_VORTEX
  657.         jz      .not_vortex
  658.  
  659.         mov     eax, 11111000b ; 248 = max latency
  660.         movzx   ecx, [device.pci_bus]
  661.         movzx   edx, [device.pci_dev]
  662.         stdcall PciWrite32, ecx, edx, PCI_REG_LATENCY, eax
  663.  
  664. .not_vortex:
  665. ; set RX/TX functions
  666.         mov     ax, EEPROM_REG_CAPABILITIES
  667.         call    read_eeprom
  668.         test    al, 100000b ; full bus master?
  669.         setnz   [device.full_bus_master]
  670.         jnz     .boomerang_func
  671.         mov     [device.transmit], vortex_transmit
  672.         DEBUGF  1,"Device is a vortex type\n"
  673.         jmp     @f
  674. .boomerang_func: ; full bus master, so use boomerang functions
  675.         mov     [device.transmit], boomerang_transmit
  676.         DEBUGF  1,"Device is a boomerang type\n"
  677. @@:
  678.         call    read_mac_eeprom
  679.  
  680.         test    byte [device.full_bus_master], 0xff
  681.         jz      .set_preamble
  682. ; switch to register window 2
  683.         set_io  0
  684.         set_io  REG_COMMAND
  685.         mov     ax, SELECT_REGISTER_WINDOW+2
  686.         out     dx, ax
  687. ; activate xcvr by setting some magic bits
  688.         set_io  REG_RESET_OPTIONS
  689.         in      ax, dx
  690.         and     ax, not 0x4010
  691.         movzx   ecx, [device.ver_id]
  692.         test    word [ecx*4+hw_versions+2], INVERT_LED_PWR
  693.         jz      @f
  694.         or      al, 0x10
  695. @@:
  696.         test    word [ecx*4+hw_versions+2], INVERT_MII_PWR
  697.         jz      @f
  698.         or      ah, 0x40
  699. @@:
  700.         out     dx, ax
  701. .set_preamble:
  702. ; use preamble as default
  703.         mov     byte [device.preamble], 1 ; enable preamble
  704.  
  705.         call    global_reset
  706.  
  707. ;--------------------------
  708. ; RESET
  709.  
  710. align 4
  711. reset:
  712.  
  713.         movzx   eax, [device.irq_line]
  714.         DEBUGF  1,"Attaching int handler to irq %x\n",eax:1
  715.  
  716.         movzx   ecx, [device.ver_id]
  717.         test    word [hw_versions+2+ecx*4], IS_VORTEX
  718.         jz      .not_vortex
  719.  
  720.         mov     esi, int_vortex
  721.         jmp     .reg_int
  722.  
  723. .not_vortex:
  724.         mov     esi, int_boomerang
  725.  
  726. .reg_int:
  727.         stdcall AttachIntHandler, eax, esi, dword 0
  728.         test    eax, eax
  729.         jnz     @f
  730.         DEBUGF  1,"\nCould not attach int handler!\n"
  731. ;        or      eax, -1
  732. ;        ret
  733.   @@:
  734.  
  735.         set_io  0
  736.         set_io  REG_COMMAND
  737.         mov     ax, SELECT_REGISTER_WINDOW + 0
  738.         out     dx, ax
  739.  
  740.         mov     ax, StopCoax
  741.         out     dx, ax                        ; stop transceiver
  742.  
  743.         mov     ax, SELECT_REGISTER_WINDOW + 4
  744.         out     dx, ax                        ; disable UTP
  745.  
  746.         set_io  REG_MEDIA_STATUS
  747.         mov     ax, 0x0
  748.  
  749.         set_io  REG_COMMAND
  750.         mov     ax, SELECT_REGISTER_WINDOW + 0
  751.         out     dx, ax
  752.  
  753.         set_io  REG_FIFO_DIAGNOSTIC
  754.         mov     ax, 0
  755.         out     dx, ax                        ; disable card
  756.  
  757.         mov     ax, 1
  758.         out     dx, ax                        ; enable card
  759.  
  760.         call    write_mac
  761.  
  762.         call    rx_reset
  763.         call    tx_reset
  764.  
  765.         set_io  REG_COMMAND
  766.         mov     ax, SELECT_REGISTER_WINDOW + 1
  767.         out     dx, ax
  768.  
  769.         mov     ecx, 32
  770.         set_io  0x0b
  771.   .loop:
  772.         in      al, dx
  773.         loop    .loop
  774.  
  775. ; Get rid of stary ints
  776.         set_io  REG_COMMAND
  777.         mov     ax, AckIntr + 0xff
  778.         out     dx, ax
  779.  
  780.         mov     ax, SetStatusEnb + S_5_INTS
  781.         out     dx, ax
  782.  
  783.         mov     ax, SetIntrEnb + S_5_INTS
  784.         out     dx, ax
  785.  
  786.         call    set_rx_mode
  787.         call    set_active_port
  788.  
  789.         set_io  0
  790.         set_io  REG_COMMAND
  791.         mov     ax, RxEnable
  792.         out     dx, ax
  793.  
  794.         mov     ax, TxEnable
  795.         out     dx, ax
  796.  
  797.         set_io  REG_COMMAND
  798.         mov     ax, SetRxThreshold + 208
  799.         out     dx, ax
  800.  
  801.         mov     ax, SetTxThreshold + 60 ;16 ; recommended by the manual :)
  802.         out     dx, ax
  803.  
  804.         mov     ax, SELECT_REGISTER_WINDOW + 1
  805.         out     dx, ax
  806.  
  807.         xor     eax, eax
  808. ; clear packet/byte counters
  809.  
  810.         lea     edi, [device.bytes_tx]
  811.         mov     ecx, 6
  812.         rep     stosd
  813.  
  814.         ret
  815.  
  816.  
  817.  
  818.  
  819.  
  820. align 4
  821. start:
  822.  
  823.         set_io  0
  824.         set_io  REG_COMMAND
  825.         mov     ax, SetTxThreshold + 60 ;2047 ; recommended by the manual :)
  826.         out     dx, ax
  827.  
  828.         call    check_tx_status
  829.  
  830.         set_io  0
  831.         set_io  REG_COMMAND
  832. ; switch to register window 4
  833.         mov     ax, SELECT_REGISTER_WINDOW+4
  834.         out     dx, ax
  835.  
  836. ; wait for linkDetect
  837.         set_io  REG_MEDIA_STATUS
  838.         mov     ecx, 20 ; wait for max 2s
  839. .link_detect_loop:
  840.         mov     esi, 10
  841.         stdcall Sleep ; 100 ms
  842.         in      ax, dx
  843.         test    ah, 1000b ; linkDetect
  844.         jnz     @f
  845.         loop    .link_detect_loop
  846. @@:
  847.  
  848. ; print link type
  849.         xor     eax, eax
  850.         bsr     ax, word [device.mode]
  851.         jz      @f
  852.         sub     ax, 4
  853. @@:
  854.         mov     esi, [link_str+eax*4]
  855.         DEBUGF 1,"Established Link type: %s\n", esi
  856.  
  857.  
  858.         set_io  0
  859.         set_io  REG_COMMAND
  860.         mov     ax, SELECT_REGISTER_WINDOW + 1
  861.         out     dx, ax
  862.  
  863.         mov     ax, AckIntr + 0xff
  864.         out     dx, ax
  865.  
  866.         mov     ax, SetStatusEnb + S_5_INTS
  867.         out     dx, ax
  868.  
  869.         mov     ax, SetIntrEnb + S_5_INTS
  870.         out     dx, ax
  871.  
  872.         set_io  0
  873.         set_io  REG_COMMAND
  874.         mov     ax, SELECT_REGISTER_WINDOW + 1
  875.  
  876.  
  877.         ret
  878.  
  879.  
  880.  
  881.  
  882.  
  883.  
  884.  
  885. align 4
  886. set_rx_mode:
  887.  
  888.         set_io  0
  889.         set_io  REG_COMMAND
  890.  
  891.         if      defined PROMISCIOUS
  892.         mov     ax, SetRxFilter + RxStation + RxMulticast + RxBroadcast + RxProm
  893.         else if  defined ALLMULTI
  894.         mov     ax, SetRxFilter + RxStation + RxMulticast + RxBroadcast
  895.         else
  896.         mov     ax, SetRxFilter + RxStation + RxBroadcast
  897.         end if
  898.  
  899.         out     dx, ax
  900.  
  901.         ret
  902.  
  903.  
  904.  
  905.  
  906.  
  907. ;***************************************************************************
  908. ;   Function
  909. ;      global_reset
  910. ;   Description
  911. ;      resets the device
  912. ;   Parameters:
  913. ;      ebp - io_addr
  914. ;   Return value:
  915. ;   Destroyed registers
  916. ;      ax, ecx, edx, esi
  917. ;
  918. ;***************************************************************************1
  919.  
  920. align 4
  921. global_reset:
  922.  
  923.         DEBUGF 1,"Global reset: "
  924.  
  925. ; GlobalReset
  926.         set_io  0
  927.         set_io  REG_COMMAND
  928.         xor     eax, eax
  929. ;       or      al, 0x14
  930.         out     dx, ax
  931. ; wait for GlobalReset to complete
  932.         mov     ecx, 64000
  933. .loop:
  934.         in      ax , dx
  935.         test    ah , 10000b ; check CmdInProgress
  936. ;        jz      .finish
  937.         loopz   .loop
  938. ;.finish:
  939. ;        DEBUGF 1,"Waiting for nic to boot..\n"
  940. ; wait for 2 seconds for NIC to boot
  941.         mov     esi, 200
  942.         stdcall Sleep ; 2 seconds
  943.  
  944.         DEBUGF 1,"Ok!\n"
  945.  
  946.         ret
  947.  
  948.  
  949.  
  950. ;***************************************************************************
  951. ;   Function
  952. ;      tx_reset
  953. ;   Description
  954. ;      resets and enables transmitter engine
  955. ;
  956. ;***************************************************************************
  957.  
  958. align 4
  959. tx_reset:
  960.         DEBUGF 1,"tx reset\n"
  961.  
  962. ; TxReset
  963.         set_io  0
  964.         set_io  REG_COMMAND
  965.         mov     ax, TxReset
  966.         out     dx, ax
  967. ; Wait for TxReset to complete
  968.         mov     ecx, 200000
  969. .tx_reset_loop:
  970.         in      ax, dx
  971.         test    ah, 10000b ; check CmdInProgress
  972.         jz      .tx_set_prev
  973.         dec     ecx
  974.         jnz     .tx_reset_loop
  975. .tx_set_prev:
  976. ; init last_dpd
  977.         mov     eax, [device.dpd_buffer]
  978.         add     eax, (NUM_TX_DESC-1)*dpd.size
  979.         mov     [device.prev_dpd], eax
  980.  
  981.         mov     eax, [device.tx_buffer]
  982.         add     eax, (NUM_TX_DESC-1)*MAX_ETH_FRAME_SIZE
  983.         mov     [device.prev_tx_frame], eax
  984. .tx_enable:
  985.         ret
  986.  
  987.  
  988.  
  989. ;***************************************************************************
  990. ;   Function
  991. ;      rx_reset
  992. ;   Description
  993. ;      resets and enables receiver engine
  994. ;
  995. ;***************************************************************************
  996.  
  997. align 4
  998. rx_reset:
  999.  
  1000.         DEBUGF 1,"rx reset\n"
  1001.  
  1002.         set_io  0
  1003.         set_io  REG_COMMAND
  1004.         mov     ax, RxReset or 0x4
  1005.         out     dx, ax
  1006. ; wait for RxReset to complete
  1007.         mov     ecx, 200000
  1008. .rx_reset_loop:
  1009.         in      ax, dx
  1010.         test    ah, 10000b ; check CmdInProgress
  1011.         dec     ecx
  1012.         jnz     .rx_reset_loop
  1013. ; create upd ring
  1014.  
  1015.         mov     eax, [device.upd_buffer]
  1016.         mov     [device.curr_upd], eax
  1017.         call    GetPgAddr
  1018.         mov     esi, eax
  1019.  
  1020.         mov     eax, [device.rx_buffer]
  1021.         call    GetPgAddr
  1022.         mov     edi, eax
  1023.  
  1024.         mov     edx, [device.upd_buffer]
  1025.         add     edx, (NUM_RX_DESC-1)*upd.size
  1026.  
  1027.         mov     eax, [device.upd_buffer]
  1028.  
  1029.         push    ebx
  1030.         mov     ebx, [device.rx_buffer]
  1031.  
  1032.         mov     ecx, NUM_RX_DESC
  1033. .upd_loop:
  1034.         mov     [edx + upd.next_ptr], esi                               ; edx = upd buff
  1035.  
  1036.         and     [eax + upd.pkt_status], 0                               ; eax = next upd buff
  1037.         mov     [eax + upd.frag_addr], edi
  1038.         mov     [eax + upd.frag_len], MAX_ETH_FRAME_SIZE or (1 shl 31)
  1039.         mov     [eax + upd.realaddr], ebx
  1040.  
  1041.         add     edi, MAX_ETH_FRAME_SIZE
  1042.         add     ebx, MAX_ETH_FRAME_SIZE
  1043.         add     esi, upd.size
  1044.         mov     edx, eax
  1045.         add     eax, upd.size
  1046.  
  1047.         dec     ecx
  1048.         jnz     .upd_loop
  1049.  
  1050.         pop     ebx
  1051.  
  1052.         mov     eax, [device.upd_buffer]
  1053.         call    GetPgAddr
  1054.         set_io  0
  1055.         set_io  REG_UP_LIST_PTR
  1056.         out     dx, eax
  1057.  
  1058. .rx_enable:
  1059.         ret
  1060.  
  1061.  
  1062.  
  1063.  
  1064. ;---------------------------------------------------------------------------
  1065. ;   Function
  1066. ;      try_link_detect
  1067. ;   Description
  1068. ;      try_link_detect checks if link exists
  1069. ;   Parameters
  1070. ;      ebx = device structure
  1071. ;   Return value
  1072. ;      al - 0 ; no link detected
  1073. ;      al - 1 ; link detected
  1074. ;   Destroyed registers
  1075. ;      eax, ebx, ecx, edx, edi, esi
  1076. ;
  1077. ;---------------------------------------------------------------------------
  1078.  
  1079. align 4
  1080. try_link_detect:
  1081.  
  1082.         DEBUGF 1,"trying to detect link\n"
  1083.  
  1084. ; create self-directed packet
  1085.         lea     esi, [device.mac]
  1086.         lea     edi, [device.self_directed_packet]
  1087.         movsw
  1088.         movsd
  1089.         sub     esi, 6
  1090.         movsw
  1091.         movsd
  1092.         mov     ax , 0x0608
  1093.         stosw
  1094.  
  1095. ; download self-directed packet
  1096.         push    20
  1097.         lea     eax, [device.self_directed_packet]
  1098.         push    eax
  1099.         call    [device.transmit]
  1100.  
  1101. ; switch to register window 4
  1102.         set_io  0
  1103.         set_io  REG_COMMAND
  1104.         mov     ax, SELECT_REGISTER_WINDOW+4
  1105.         out     dx, ax
  1106.  
  1107. ; See if we have received the packet by now..
  1108.         cmp     [device.packets_rx], 0
  1109.         jnz     .link_detected
  1110.  
  1111. ; switch to register window 4
  1112.         set_io  REG_COMMAND
  1113.         mov     ax, SELECT_REGISTER_WINDOW+4
  1114.         out     dx, ax
  1115.  
  1116. ; read linkbeatdetect
  1117.         set_io  REG_MEDIA_STATUS
  1118.         in      ax, dx
  1119.         test    ah, 1000b ; test linkBeatDetect
  1120.         jnz     .link_detected
  1121.         xor     al, al
  1122.         jmp     .finish
  1123.  
  1124. .link_detected:
  1125.         setb    al
  1126.  
  1127. .finish:
  1128.         test    al, al
  1129.         jz      @f
  1130.         or      byte [device.mode+1], 100b
  1131. @@:
  1132.         ret
  1133.  
  1134.  
  1135.  
  1136. ;***************************************************************************
  1137. ;   Function
  1138. ;      try_phy
  1139. ;   Description
  1140. ;      try_phy checks the auto-negotiation function
  1141. ;      in the PHY at PHY index. It can also be extended to
  1142. ;      include link detection for non-IEEE 802.3u
  1143. ;      auto-negotiation devices, for instance the BCM5000.
  1144. ;   Parameters
  1145. ;       ah - PHY index
  1146. ;       ebx - device stucture
  1147. ;   Return value
  1148. ;      al - 0 link is auto-negotiated
  1149. ;      al - 1 no link is auto-negotiated
  1150. ;   Destroyed registers
  1151. ;       eax, ebx, ecx, edx, esi
  1152. ;
  1153. ;***************************************************************************
  1154.  
  1155. align 4
  1156. try_phy:
  1157.  
  1158.         DEBUGF 1,"trying phy\n"
  1159.  
  1160.         mov     al, REG_MII_BMCR
  1161.         push    eax
  1162.         call    mdio_read       ; returns with window #4
  1163.         or      ah , 0x80       ; software reset
  1164.         mov     esi, eax
  1165.         mov     eax, dword [esp]
  1166.         call    mdio_write      ; returns with window #4
  1167.  
  1168. ; wait for reset to complete
  1169.         mov     esi, 200
  1170.         stdcall Sleep      ; 2s
  1171.         mov     eax, [esp]
  1172.         call    mdio_read       ; returns with window #4
  1173.         test    ah , 0x80
  1174.         jnz     .fail_finish
  1175.         mov     eax, [esp]
  1176.  
  1177. ; wait for a while after reset
  1178.         mov     esi, 2
  1179.         stdcall Sleep      ; 20ms
  1180.         mov     eax, [esp]
  1181.         mov     al , REG_MII_BMSR
  1182.         call    mdio_read       ; returns with window #4
  1183.         test    al , 1           ; extended capability supported?
  1184.         jz      .no_ext_cap
  1185.  
  1186. ; auto-neg capable?
  1187.         test    al , 1000b
  1188.         jz      .fail_finish    ; not auto-negotiation capable
  1189.  
  1190. ; auto-neg complete?
  1191.         test    al , 100000b
  1192.         jnz     .auto_neg_ok
  1193.  
  1194. ; restart auto-negotiation
  1195.         mov     eax, [esp]
  1196.         mov     al , REG_MII_ANAR
  1197.         push    eax
  1198.         call    mdio_read       ; returns with window #4
  1199.         or      ax , 1111b shl 5; advertise only 10base-T and 100base-TX
  1200.         mov     esi, eax
  1201.         pop     eax
  1202.         call    mdio_write      ; returns with window #4
  1203.         mov     eax, [esp]
  1204.         call    mdio_read       ; returns with window #4
  1205.         mov     esi, eax
  1206.         or      bh , 10010b     ; restart auto-negotiation
  1207.         mov     eax, [esp]
  1208.         call    mdio_write      ; returns with window #4
  1209.         mov     esi, 400
  1210.         stdcall Sleep  ; 4 seconds
  1211.         mov     eax, [esp]
  1212.         mov     al , REG_MII_BMSR
  1213.         call    mdio_read ; returns with window #4
  1214.         test    al , 100000b ; auto-neg complete?
  1215.         jnz     .auto_neg_ok
  1216.         jmp     .fail_finish
  1217. .auto_neg_ok:
  1218.  
  1219. ; compare advertisement and link partner ability registers
  1220.         mov     eax, [esp]
  1221.         mov     al , REG_MII_ANAR
  1222.         call    mdio_read       ; returns with window #4
  1223.         xchg    eax, [esp]
  1224.         mov     al , REG_MII_ANLPAR
  1225.         call    mdio_read       ; returns with window #4
  1226.         pop     esi
  1227.         and     eax, esi
  1228.         and     eax, 1111100000b
  1229.         push    eax
  1230.  
  1231.         mov     word[device.mode+2], ax
  1232.  
  1233. ; switch to register window 3
  1234.         set_io  0
  1235.         set_io  REG_COMMAND
  1236.         mov     ax , SELECT_REGISTER_WINDOW+3
  1237.         out     dx , ax
  1238.  
  1239. ; set full-duplex mode
  1240.         set_io  REG_MAC_CONTROL
  1241.         in      ax , dx
  1242.         and     ax , not 0x120  ; clear full duplex and flow control
  1243.         pop     esi
  1244.         test    esi, 1010b shl 5; check for full-duplex
  1245.         jz      .half_duplex
  1246.         or      ax , 0x120      ; set full duplex and flow control
  1247. .half_duplex:
  1248.         out     dx , ax
  1249.         mov     al , 1
  1250.         ret
  1251. .no_ext_cap:
  1252.  
  1253. ; not yet implemented BCM5000
  1254. .fail_finish:
  1255.         pop     eax
  1256.         xor     al, al
  1257.         ret
  1258.  
  1259.  
  1260.  
  1261. ;***************************************************************************
  1262. ;   Function
  1263. ;      try_mii
  1264. ;   Description
  1265. ;      try_MII checks the on-chip auto-negotiation logic
  1266. ;      or an off-chip MII PHY, depending upon what is set in
  1267. ;      xcvrSelect by the caller.
  1268. ;      It exits when it finds the first device with a good link.
  1269. ;   Parameters
  1270. ;      ebp - io_addr
  1271. ;   Return value
  1272. ;      al - 0
  1273. ;      al - 1
  1274. ;   Destroyed registers
  1275. ;      eax, ebx, ecx, edx, esi
  1276. ;
  1277. ;***************************************************************************
  1278.  
  1279. align 4
  1280. try_mii:
  1281.  
  1282.         DEBUGF 1,"trying mii\n"
  1283.  
  1284. ; switch to register window 3
  1285.         set_io  0
  1286.         set_io  REG_COMMAND
  1287.         mov     ax, SELECT_REGISTER_WINDOW+3
  1288.         out     dx, ax
  1289.         set_io  REG_INTERNAL_CONFIG
  1290.         in      eax, dx
  1291.         and     eax, (1111b shl 20)
  1292.         cmp     eax, (1000b shl 20) ; is auto-negotiation set?
  1293.         jne     .mii_device
  1294. ; auto-negotiation is set
  1295. ; switch to register window 4
  1296.         set_io  REG_COMMAND
  1297.         mov     ax , SELECT_REGISTER_WINDOW+4
  1298.         out     dx , ax
  1299. ; PHY==24 is the on-chip auto-negotiation logic
  1300. ; it supports only 10base-T and 100base-TX
  1301.         mov     ah , 24
  1302.         call    try_phy
  1303.         test    al , al
  1304.         jz      .fail_finish
  1305.         mov     cl , 24
  1306.         jmp     .check_preamble
  1307. .mii_device:
  1308.         cmp     eax, (0110b shl 20)
  1309.         jne     .fail_finish
  1310.         set_io  0
  1311.         set_io  REG_COMMAND
  1312.         mov     ax , SELECT_REGISTER_WINDOW+4
  1313.         out     dx , ax
  1314.         set_io  REG_PHYSICAL_MGMT
  1315.         in      ax , dx
  1316.         and     al , (1 shl BIT_MGMT_DIR) or (1 shl BIT_MGMT_DATA)
  1317.         cmp     al , (1 shl BIT_MGMT_DATA)
  1318.         je      .search_for_phy
  1319.         xor     al , al
  1320.         ret
  1321. .search_for_phy:
  1322. ; search for PHY
  1323.         mov     cx , 31
  1324. .search_phy_loop:
  1325.         cmp     cx , 24
  1326.         je      .next_phy
  1327.         mov     ah , cl ; ah = phy
  1328.         mov     al , REG_MII_BMCR ; al = Basic Mode Status Register
  1329.         push    cx
  1330.         call    mdio_read
  1331.         pop     cx
  1332.         test    ax , ax
  1333.         jz      .next_phy
  1334.         cmp     ax , 0xffff
  1335.         je      .next_phy
  1336.         mov     ah , cl ; ah = phy
  1337.         push    cx
  1338.         call    try_phy
  1339.         pop     cx
  1340.         test    al , al
  1341.         jnz     .check_preamble
  1342. .next_phy:
  1343.         loopw   .search_phy_loop
  1344. .fail_finish:
  1345.         xor     al, al
  1346.         ret
  1347. ; epilog
  1348. .check_preamble:
  1349.         push    eax ; eax contains the return value of try_phy
  1350. ; check hard coded preamble forcing
  1351.         movzx   eax, [device.ver_id]
  1352.         test    word [eax*4+hw_versions+2], EXTRA_PREAMBLE
  1353.         setnz   [device.preamble] ; force preamble
  1354.         jnz     .finish
  1355. ; check mii for preamble suppression
  1356.         mov     ah, cl
  1357.         mov     al, REG_MII_BMSR
  1358.         call    mdio_read
  1359.         test    al, 1000000b ; preamble suppression?
  1360.         setz    [device.preamble] ; no
  1361. .finish:
  1362.         pop     eax
  1363.         ret
  1364.  
  1365.  
  1366.  
  1367. ;***************************************************************************
  1368. ;   Function
  1369. ;      test_packet
  1370. ;   Description
  1371. ;      try_loopback try a loopback packet for 10BASE2 or AUI port
  1372. ;   Parameters
  1373. ;      ebx = device structure
  1374. ;
  1375. ;***************************************************************************
  1376.  
  1377. align 4
  1378. test_packet:
  1379.  
  1380.         DEBUGF 1,"sending test packet\n"
  1381.  
  1382. ; switch to register window 3
  1383.         set_io  0
  1384.         set_io  REG_COMMAND
  1385.         mov     ax, SELECT_REGISTER_WINDOW+3
  1386.         out     dx, ax
  1387.  
  1388. ; set fullDuplexEnable in MacControl register
  1389.         set_io  REG_MAC_CONTROL
  1390.         in      ax, dx
  1391.         or      ax, 0x120
  1392.         out     dx, ax
  1393.  
  1394. ; switch to register window 5
  1395.         set_io  REG_COMMAND
  1396.         mov     ax, SELECT_REGISTER_WINDOW+5
  1397.         out     dx, ax
  1398.  
  1399. ; set RxFilter to enable individual address matches
  1400.         mov     ax, (10000b shl 11)
  1401.         set_io  REG_RX_FILTER
  1402.         in      al, dx
  1403.         or      al, 1
  1404.         set_io  REG_COMMAND
  1405.         out     dx, ax
  1406.  
  1407. ; issue RxEnable and TxEnable
  1408.         call    rx_reset
  1409.         call    tx_reset
  1410.  
  1411. ; download a self-directed test packet
  1412.         lea     esi, [device.mac]
  1413.         lea     edi, [device.self_directed_packet]
  1414.         movsw
  1415.         movsd
  1416.         sub     esi, 6
  1417.         movsw
  1418.         movsd
  1419.         mov     ax , 0x0608
  1420.         stosw
  1421.  
  1422.         push    20
  1423.         lea     eax, [device.self_directed_packet]
  1424.         push    eax
  1425.         call    [device.transmit]
  1426.  
  1427. ; wait for 2s
  1428.         mov     esi, 200
  1429.         stdcall Sleep    ; 2s
  1430.  
  1431. ; check if self-directed packet is received
  1432.         mov     eax, [device.packets_rx]
  1433.         test    eax, eax
  1434.         jnz     .finish
  1435.  
  1436. ; switch to register window 3
  1437.         set_io  0
  1438.         set_io  REG_COMMAND
  1439.         mov     ax, SELECT_REGISTER_WINDOW+3
  1440.         out     dx, ax
  1441.  
  1442. ; clear fullDuplexEnable in MacControl register
  1443.         set_io  REG_MAC_CONTROL
  1444.         in      ax , dx
  1445.         and     ax , not 0x120
  1446.         out     dx , ax
  1447.         xor     eax, eax
  1448.  
  1449. .finish:
  1450.         ret
  1451.  
  1452.  
  1453.  
  1454. ;***************************************************************************
  1455. ;   Function
  1456. ;      try_loopback
  1457. ;   Description
  1458. ;      tries a loopback packet for 10BASE2 or AUI port
  1459. ;   Parameters
  1460. ;      al -  0: 10Mbps AUI connector
  1461. ;            1: 10BASE-2
  1462. ;      ebp - io_addr
  1463. ;   Return value
  1464. ;      al - 0
  1465. ;      al - 1
  1466. ;   Destroyed registers
  1467. ;      eax, ebx, ecx, edx, edi, esi
  1468. ;
  1469. ;***************************************************************************
  1470.  
  1471. align 4
  1472. try_loopback:
  1473.  
  1474.         DEBUGF 1,"trying loopback\n"
  1475.  
  1476.         push    eax
  1477. ; switch to register window 3
  1478.         set_io  0
  1479.         set_io  REG_COMMAND
  1480.         mov     ax, SELECT_REGISTER_WINDOW+3
  1481.         out     dx, ax
  1482.         mov     eax, [esp]
  1483.  
  1484.         mov     cl, al
  1485.         inc     cl
  1486.         shl     cl, 3
  1487.         or      byte [device.mode+1], cl
  1488.  
  1489.         test    al, al ; aui or coax?
  1490.         jz      .complete_loopback
  1491. ; enable 100BASE-2 DC-DC converter
  1492.         mov     ax, (10b shl 11) ; EnableDcConverter
  1493.         out     dx, ax
  1494. .complete_loopback:
  1495.         mov     cx, 2 ; give a port 3 chances to complete a loopback
  1496. .next_try:
  1497.         push    ecx
  1498.         call    test_packet
  1499.         pop     ecx
  1500.         test    eax, eax
  1501.         loopzw  .next_try
  1502. .finish:
  1503.         xchg    eax, [esp]
  1504.         test    al, al
  1505.         jz      .aui_finish
  1506. ; issue DisableDcConverter command
  1507.         set_io  0
  1508.         set_io  REG_COMMAND
  1509.         mov     ax, (10111b shl 11)
  1510.         out     dx, ax
  1511. .aui_finish:
  1512.         pop     eax ; al contains the result of operation
  1513.  
  1514.         test    al, al
  1515.         jnz     @f
  1516.         and     byte [device.mode+1], not 11000b
  1517. @@:
  1518.  
  1519.         ret
  1520.  
  1521.  
  1522. ;***************************************************************************
  1523. ;   Function
  1524. ;      set_active_port
  1525. ;   Description
  1526. ;      It selects the media port (transceiver) to be used
  1527. ;   Return value:
  1528. ;   Destroyed registers
  1529. ;      eax, ebx, ecx, edx, edi, esi
  1530. ;
  1531. ;***************************************************************************
  1532.  
  1533. align 4
  1534. set_active_port:
  1535.  
  1536.         DEBUGF 1,"Setting active port: "
  1537.  
  1538. ; switch to register window 3
  1539.         set_io  0
  1540.         set_io  REG_COMMAND
  1541.         mov     ax, SELECT_REGISTER_WINDOW+3
  1542.         out     dx, ax
  1543.         set_io  REG_INTERNAL_CONFIG
  1544.         in      eax, dx
  1545.         test    eax, (1 shl 24) ; check if autoselect enable
  1546.         jz      .set_first_available_media
  1547.  
  1548. ; check 100BASE-TX and 10BASE-T
  1549.         set_io  REG_MEDIA_OPTIONS
  1550.         in      ax, dx
  1551.         test    al, 1010b       ; check whether 100BASE-TX or 10BASE-T available
  1552.         jz      .mii_device     ; they are not available
  1553.  
  1554. ; set auto-negotiation
  1555.         set_io  REG_INTERNAL_CONFIG
  1556.         in      eax, dx
  1557.         and     eax, not (1111b shl 20)
  1558.         or      eax, (1000b shl 20)
  1559.         out     dx, eax
  1560.         call    try_mii
  1561.         test    al, al
  1562.         jz      .mii_device
  1563.         DEBUGF 1,"Using auto negotiation\n"
  1564.         ret
  1565. .mii_device:
  1566.  
  1567. ; switch to register window 3
  1568.         set_io  0
  1569.         set_io  REG_COMMAND
  1570.         mov     ax, SELECT_REGISTER_WINDOW+3
  1571.         out     dx, ax
  1572.  
  1573. ; check for off-chip mii device
  1574.         set_io  REG_MEDIA_OPTIONS
  1575.         in      ax, dx
  1576.         test    al, 1000000b ; check miiDevice
  1577.         jz      .base_fx
  1578.         set_io  REG_INTERNAL_CONFIG
  1579.         in      eax, dx
  1580.         and     eax, not (1111b shl 20)
  1581.         or      eax, (0110b shl 20) ; set MIIDevice
  1582.         out     dx, eax
  1583.         call    try_mii
  1584.         test    al, al
  1585.         jz      .base_fx
  1586.         DEBUGF 1,"Using off-chip mii device\n"
  1587.         ret
  1588. .base_fx:
  1589.  
  1590. ; switch to register window 3
  1591.         set_io  0
  1592.         set_io  REG_COMMAND
  1593.         mov     ax, SELECT_REGISTER_WINDOW+3
  1594.         out     dx, ax
  1595. ; check for 100BASE-FX
  1596.         set_io  REG_MEDIA_OPTIONS
  1597.         in      ax, dx ; read media option register
  1598.         test    al, 100b ; check 100BASE-FX
  1599.         jz      .aui_enable
  1600.         set_io  REG_INTERNAL_CONFIG
  1601.         in      eax, dx
  1602.         and     eax, not (1111b shl 20)
  1603.         or      eax, (0101b shl 20) ; set 100base-FX
  1604.         out     dx, eax
  1605.         call    try_link_detect
  1606.         test    al, al
  1607.         jz      .aui_enable
  1608.         DEBUGF 1,"Using 100Base-FX\n"
  1609.         ret
  1610. .aui_enable:
  1611.  
  1612. ; switch to register window 3
  1613.         set_io  0
  1614.         set_io  REG_COMMAND
  1615.         mov     ax, SELECT_REGISTER_WINDOW+3
  1616.         out     dx, ax
  1617. ; check for 10Mbps AUI connector
  1618.         set_io  REG_MEDIA_OPTIONS
  1619.         in      ax, dx ; read media option register
  1620.         test    al, 100000b ; check 10Mbps AUI connector
  1621.         jz      .coax_available
  1622.         set_io  REG_INTERNAL_CONFIG
  1623.         in      eax, dx
  1624.         and     eax, not (1111b shl 20)
  1625.         or      eax, (0001b shl 20) ; set 10Mbps AUI connector
  1626.         out     dx, eax
  1627.         xor     al, al ; try 10Mbps AUI connector
  1628.         call    try_loopback
  1629.         test    al, al
  1630.         jz      .coax_available
  1631.         DEBUGF 1,"Using 10Mbps aui\n"
  1632.         ret
  1633. .coax_available:
  1634.  
  1635. ; switch to register window 3
  1636.         set_io  0
  1637.         set_io  REG_COMMAND
  1638.         mov     ax, SELECT_REGISTER_WINDOW+3
  1639.         out     dx, ax
  1640. ; check for coaxial 10BASE-2 port
  1641.         set_io  REG_MEDIA_OPTIONS
  1642.         in      ax, dx ; read media option register
  1643.         test    al, 10000b ; check 10BASE-2
  1644.         jz      .set_first_available_media
  1645.         set_io  REG_INTERNAL_CONFIG
  1646.         in      eax, dx
  1647.         and     eax, not (1111b shl 20)
  1648.         or      eax, (0011b shl 20) ; set 10BASE-2
  1649.         out     dx, eax
  1650.         mov     al, 1
  1651.         call    try_loopback
  1652.         test    al, al
  1653.         jz      .set_first_available_media
  1654.         DEBUGF 1,"Using 10BASE-2 port\n"
  1655.         ret
  1656. .set_first_available_media:
  1657.  
  1658.  
  1659. ;***************************************************************************
  1660. ;   Function
  1661. ;      set_available_media
  1662. ;   Description
  1663. ;      sets the first available media
  1664. ;   Parameters
  1665. ;      ebp - io_addr
  1666. ;   Return value
  1667. ;      al - 0
  1668. ;      al - 1
  1669. ;   Destroyed registers
  1670. ;      eax, edx
  1671. ;
  1672. ;***************************************************************************
  1673.  
  1674. align 4
  1675. set_available_media:
  1676.  
  1677.         DEBUGF 1,"Using the first available media\n"
  1678.  
  1679. ; switch to register window 3
  1680.         set_io  0
  1681.         set_io  REG_COMMAND
  1682.         mov     ax, SELECT_REGISTER_WINDOW+3
  1683.         out     dx, ax
  1684.         set_io  REG_INTERNAL_CONFIG
  1685.         in      eax, dx
  1686.         push    eax
  1687.         set_io  REG_MEDIA_OPTIONS
  1688.         in      ax, dx
  1689.         test    al, 10b
  1690.         jz      @f
  1691. ; baseTXAvailable
  1692.         pop     eax
  1693.         and     eax, not (1111b shl 20)
  1694.         or      eax, (100b shl 20)
  1695. if defined FORCE_FD
  1696.         mov     word [device.mode], (1 shl 8)
  1697. else
  1698.         mov     word [device.mode], (1 shl 7)
  1699. end if
  1700.         jmp     .set_media
  1701. @@:
  1702.         test    al, 100b
  1703.         jz      @f
  1704. ; baseFXAvailable
  1705.         pop     eax
  1706.         and     eax, not (1111b shl 20)
  1707.         or      eax, (101b shl 20)
  1708.  
  1709.         mov     word [device.mode], (1 shl 10)
  1710.  
  1711.         jmp     .set_media
  1712. @@:
  1713.         test    al, 1000000b
  1714.         jz      @f
  1715. ; miiDevice
  1716.         pop     eax
  1717.         and     eax, not (1111b shl 20)
  1718.         or      eax, (0110b shl 20)
  1719.  
  1720.         mov     word [device.mode], (1 shl 13)
  1721.  
  1722.         jmp     .set_media
  1723. @@:
  1724.         test    al, 1000b
  1725.         jz      @f
  1726. .set_default:
  1727. ; 10bTAvailable
  1728.         pop     eax
  1729.         and     eax, not (1111b shl 20)
  1730. if FORCE_FD
  1731.         mov     word [device.mode], (1 shl 6)
  1732. else
  1733.         mov     word [device.mode], (1 shl 5)
  1734. end if ; FORCE_FD
  1735.         jmp     .set_media
  1736. @@:
  1737.         test    al, 10000b
  1738.         jz      @f
  1739. ; coaxAvailable
  1740.         set_io  REG_COMMAND
  1741.         mov     ax, (10b shl 11) ; EnableDcConverter
  1742.         out     dx, ax
  1743.         pop     eax
  1744.         and     eax, not (1111b shl 20)
  1745.         or      eax, (11b shl 20)
  1746.  
  1747.         mov     word [device.mode], (1 shl 12)
  1748.  
  1749.         jmp     .set_media
  1750. @@:
  1751.         test    al, 10000b
  1752.         jz      .set_default
  1753. ; auiAvailable
  1754.         pop     eax
  1755.         and     eax, not (1111b shl 20)
  1756.         or      eax, (1 shl 20)
  1757.  
  1758.         mov     word [device.mode], (1 shl 11)
  1759.  
  1760. .set_media:
  1761.         set_io  REG_INTERNAL_CONFIG
  1762.         out     dx, eax
  1763. if FORCE_FD
  1764. ; set fullDuplexEnable in MacControl register
  1765.         set_io  REG_MAC_CONTROL
  1766.         in      ax, dx
  1767.         or      ax, 0x120
  1768.         out     dx, ax
  1769. end if ; FORCE_FD
  1770.         mov     al, 1
  1771.  
  1772.         ret
  1773.  
  1774.  
  1775.  
  1776. ;***************************************************************************
  1777. ;   Function
  1778. ;      wake_up
  1779. ;   Description
  1780. ;      set the power state to D0
  1781. ;
  1782. ;***************************************************************************
  1783.  
  1784. align 4
  1785. wake_up:
  1786.  
  1787.         DEBUGF 1,"Waking up NIC: "
  1788.  
  1789. ; wake up - we directly do it by programming PCI
  1790. ; check if the device is power management capable
  1791.         movzx   ecx, [device.pci_bus]
  1792.         movzx   edx, [device.pci_dev]
  1793.         stdcall PciRead32, ecx, edx, PCI_REG_STATUS
  1794.  
  1795.         test    al, 10000b      ; is there "new capabilities" linked list?
  1796.         jz      .device_awake
  1797.  
  1798.         DEBUGF 1,"1 "
  1799.  
  1800. ; search for power management register
  1801.         stdcall PciRead16, ecx, edx, PCI_REG_CAP_PTR
  1802.         cmp     al, 0x3f
  1803.         jbe     .device_awake
  1804.  
  1805.         DEBUGF 1,"2 "
  1806.  
  1807. ; traverse the list
  1808.         movzx   esi, al
  1809. .pm_loop:
  1810.         stdcall PciRead32, ecx, edx, esi
  1811.  
  1812.         cmp     al , 1
  1813.         je      .set_pm_state
  1814.  
  1815.         movzx   esi, ah
  1816.  
  1817.         test    ah , ah
  1818.         jnz     .pm_loop
  1819.         jmp     .device_awake
  1820.  
  1821. ; waku up the device if necessary
  1822. .set_pm_state:
  1823.  
  1824.         DEBUGF 1,"3 "
  1825.  
  1826.         add     esi, PCI_REG_PM_CTRL
  1827.         stdcall PciRead32, ecx, edx, esi
  1828.         test    al, 3
  1829.         jz      .device_awake
  1830.         and     al, not 11b ; set state to D0
  1831.         stdcall PciWrite32, ecx, edx, esi, eax
  1832. .device_awake:
  1833.  
  1834.         DEBUGF 1,"Device is awake\n"
  1835.  
  1836.         ret
  1837.  
  1838.  
  1839.  
  1840.  
  1841. ;***************************************************************************
  1842. ;   Function
  1843. ;      write_eeprom
  1844. ;   Description
  1845. ;      reads eeprom
  1846. ;      Note : the caller must switch to the register window 0
  1847. ;             before calling this function
  1848. ;   Parameters:
  1849. ;      ax - register to be read (only the first 63 words can be read)
  1850. ;      cx - value to be read into the register
  1851. ;   Return value:
  1852. ;      ax - word read
  1853. ;   Destroyed registers
  1854. ;      ax, ebx, edx
  1855. ;
  1856. ;***************************************************************************
  1857. ;       align 4
  1858. ;write_eeprom:
  1859. ;       mov     edx, [io_addr]
  1860. ;       add     edx, REG_EEPROM_COMMAND
  1861. ;       cmp     ah, 11b
  1862. ;       ja      .finish ; address may have a value of maximal 1023
  1863. ;       shl     ax, 2
  1864. ;       shr     al, 2
  1865. ;       push    eax
  1866. ;; wait for busy
  1867. ;       mov     ebx, 0xffff
  1868. ;@@:
  1869. ;       in      ax, dx
  1870. ;       test    ah, 0x80
  1871. ;       jz      .write_enable
  1872. ;       dec     ebx
  1873. ;       jns     @r
  1874. ;; write enable
  1875. ;.write_enable:
  1876. ;       xor     eax, eax
  1877. ;       mov     eax, (11b shl 4)
  1878. ;       out     dx, ax
  1879. ;; wait for busy
  1880. ;       mov     ebx, 0xffff
  1881. ;@@:
  1882. ;       in      ax, dx
  1883. ;       test    ah, 0x80
  1884. ;       jz      .erase_loop
  1885. ;       dec     ebx
  1886. ;       jns     @r
  1887. ;.erase_loop:
  1888. ;       pop     eax
  1889. ;       push    eax
  1890. ;       or      ax, (11b shl 6) ; erase register
  1891. ;       out     dx, ax
  1892. ;       mov     ebx, 0xffff
  1893. ;@@:
  1894. ;       in      ax, dx
  1895. ;       test    ah, 0x80
  1896. ;       jz      .write_reg
  1897. ;       dec     ebx
  1898. ;       jns     @r
  1899. ;.write_reg:
  1900. ;       add     edx, REG_EEPROM_DATA-REG_EEPROM_COMMAND
  1901. ;       mov     eax, ecx
  1902. ;       out     dx, ax
  1903. ;; write enable
  1904. ;       add     edx, REG_EEPROM_COMMAND-REG_EEPROM_DATA
  1905. ;       xor     eax, eax
  1906. ;       mov     eax, (11b shl 4)
  1907. ;       out     dx, ax
  1908. ; wait for busy
  1909. ;       mov     ebx, 0xffff
  1910. ;@@:
  1911. ;       in      ax, dx
  1912. ;       test    ah, 0x80
  1913. ;       jz      .issue_write_reg
  1914. ;       dec     ebx
  1915. ;       jns     @r
  1916. ;.issue_write_reg:
  1917. ;       pop     eax
  1918. ;       or      ax, 01b shl 6
  1919. ;       out     dx, ax
  1920. ;.finish:
  1921. ;       ret
  1922. ;***************************************************************************
  1923. ;   Function
  1924. ;      read_eeprom
  1925. ;   Description
  1926. ;      reads eeprom
  1927. ;   Parameters:
  1928. ;       ax - register to be read (only the first 63 words can be read)
  1929. ;      ebx = driver structure
  1930. ;   Return value:
  1931. ;      ax - word read
  1932. ;   Destroyed registers
  1933. ;      ax, ebx, edx, ebp
  1934. ;
  1935. ;***************************************************************************
  1936.  
  1937. align 4
  1938. read_eeprom:
  1939.  
  1940.         DEBUGF 1,"Reading from eeprom:\n"
  1941.  
  1942.         push    eax
  1943. ; switch to register window 0
  1944.         set_io  0
  1945.         set_io  REG_COMMAND
  1946.         mov     ax, SELECT_REGISTER_WINDOW+0
  1947.         out     dx, ax
  1948.         pop     eax
  1949.         and     ax, 111111b ; take only the first 6 bits into account
  1950.         movzx   esi, [device.ver_id]
  1951.  
  1952.         test    word [esi*4+hw_versions+2], EEPROM_8BIT
  1953.         jz      @f
  1954.         add     ax, 0x230 ; hardware constant
  1955.         jmp     .read
  1956. @@:
  1957.  
  1958.         add     ax, EEPROM_CMD_READ
  1959.         test    word [esi*4+hw_versions+2], EEPROM_OFFSET
  1960.         jz      .read
  1961.         add     ax, 0x30
  1962. .read:
  1963.  
  1964.         set_io  REG_EEPROM_COMMAND
  1965.         out     dx, ax
  1966.         mov     ecx, 0xffff ; duration of about 162 us ;-)
  1967. .wait_for_reading:
  1968.         in      ax, dx
  1969.         test    ah, 0x80 ; check bit eepromBusy
  1970.         jz      .read_data
  1971.         loop    .wait_for_reading
  1972. .read_data:
  1973.         set_io  REG_EEPROM_DATA
  1974.         in      ax, dx
  1975.  
  1976.         DEBUGF 1,"ok!\n"
  1977.  
  1978.         ret
  1979.  
  1980. ;***************************************************************************
  1981. ;   Function
  1982. ;      mdio_sync
  1983. ;   Description
  1984. ;      initial synchronization
  1985. ;   Parameters
  1986. ;      ebp - io_addr
  1987. ;   Return value
  1988. ;   Destroyed registers
  1989. ;      ax, edx, cl
  1990. ;
  1991. ;***************************************************************************
  1992.  
  1993. align 4
  1994. mdio_sync:
  1995.  
  1996.         DEBUGF 1,"syncing mdio\n"
  1997.  
  1998. ; switch to register window 4
  1999.         set_io  0
  2000.         set_io  REG_COMMAND
  2001.         mov     ax, SELECT_REGISTER_WINDOW+4
  2002.         out     dx, ax
  2003.         cmp     [device.preamble], 0
  2004.         je      .no_preamble
  2005. ; send 32 logic ones
  2006.         set_io  REG_PHYSICAL_MGMT
  2007.         mov     ecx, 31
  2008. .loop:
  2009.         mov     ax, (1 shl BIT_MGMT_DATA) or (1 shl BIT_MGMT_DIR)
  2010.         out     dx, ax
  2011.         in      ax, dx ; delay
  2012.         mov     ax, (1 shl BIT_MGMT_DATA) or (1 shl BIT_MGMT_DIR) or (1 shl BIT_MGMT_CLK)
  2013.         out     dx, ax
  2014.         in      ax, dx ; delay
  2015.         loop    .loop
  2016. .no_preamble:
  2017.  
  2018.         ret
  2019.  
  2020. ;***************************************************************************
  2021. ;   Function
  2022. ;      mdio_read
  2023. ;   Description
  2024. ;      read MII register
  2025. ;      see page 16 in D83840A.pdf
  2026. ;   Parameters
  2027. ;       ah - PHY addr
  2028. ;       al - register addr
  2029. ;      ebx = device structure
  2030. ;   Return value
  2031. ;      ax - register read
  2032. ;
  2033. ;***************************************************************************
  2034.  
  2035. align 4
  2036. mdio_read:
  2037.  
  2038.         DEBUGF 1,"reading MII registers\n"
  2039.  
  2040.         push    eax
  2041.         call    mdio_sync ; returns with window #4
  2042.         pop     eax
  2043.         set_io  0
  2044.         set_io  REG_PHYSICAL_MGMT
  2045.         shl     al, 3
  2046.         shr     ax, 3
  2047.         and     ax, not MII_CMD_MASK
  2048.         or      ax, MII_CMD_READ
  2049.  
  2050.         mov     esi, eax
  2051.         mov     ecx, 13
  2052. .cmd_loop:
  2053.         mov     ax, (1 shl BIT_MGMT_DIR) ; write mii
  2054.         bt      esi, ecx
  2055.         jnc     .zero_bit
  2056.         or      al, (1 shl BIT_MGMT_DATA)
  2057.  
  2058. .zero_bit:
  2059.         out     dx, ax
  2060.         push    ax
  2061.         in      ax, dx ; delay
  2062.         pop     ax
  2063.         or      al, (1 shl BIT_MGMT_CLK) ; write
  2064.         out     dx, ax
  2065.         in      ax, dx ; delay
  2066.         loop    .cmd_loop
  2067.  
  2068. ; read data (18 bits with the two transition bits)
  2069.         mov     ecx, 17
  2070.         xor     esi, esi
  2071. .read_loop:
  2072.         shl     esi, 1
  2073.         xor     eax, eax ; read comand
  2074.         out     dx, ax
  2075.         in      ax, dx ; delay
  2076.         in      ax, dx
  2077.         test    al, (1 shl BIT_MGMT_DATA)
  2078.         jz      .dont_set
  2079.         inc     esi
  2080. .dont_set:
  2081.         mov     ax, (1 shl BIT_MGMT_CLK)
  2082.         out     dx, ax
  2083.         in      ax, dx ; delay
  2084.         loop    .read_loop
  2085.         mov     eax, esi
  2086.  
  2087.         ret
  2088.  
  2089.  
  2090.  
  2091. ;***************************************************************************
  2092. ;   Function
  2093. ;      mdio_write
  2094. ;   Description
  2095. ;      write MII register
  2096. ;      see page 16 in D83840A.pdf
  2097. ;   Parameters
  2098. ;       ah - PHY addr
  2099. ;       al - register addr
  2100. ;       si - word to be written
  2101. ;   Return value
  2102. ;      ax - register read
  2103. ;
  2104. ;***************************************************************************
  2105.  
  2106. align 4
  2107. mdio_write:
  2108.  
  2109.         DEBUGF 1,"Writing MII registers\n"
  2110.  
  2111.         push    eax
  2112.         call    mdio_sync
  2113.         pop     eax
  2114.         set_io  0
  2115.         set_io  REG_PHYSICAL_MGMT
  2116.         shl     al, 3
  2117.         shr     ax, 3
  2118.         and     ax, not MII_CMD_MASK
  2119.         or      ax, MII_CMD_WRITE
  2120.         shl     eax, 2
  2121.         or      eax, 10b ; transition bits
  2122.         shl     eax, 16
  2123.         mov     ax, si
  2124.         mov     esi, eax
  2125.         mov     ecx, 31
  2126. .cmd_loop:
  2127.         mov     ax, (1 shl BIT_MGMT_DIR) ; write mii
  2128.         bt      esi, ecx
  2129.         jnc     .zero_bit
  2130.         or      al, (1 shl BIT_MGMT_DATA)
  2131. .zero_bit:
  2132.         out     dx, ax
  2133.         push    eax
  2134.         in      ax, dx ; delay
  2135.         pop     eax
  2136.         or      al, (1 shl BIT_MGMT_CLK) ; write
  2137.         out     dx, ax
  2138.         in      ax, dx ; delay
  2139.         loop    .cmd_loop
  2140.  
  2141.         ret
  2142.  
  2143.  
  2144. ;***************************************************************************
  2145. ;   Function
  2146. ;      check_tx_status
  2147. ;   Description
  2148. ;      Checks TxStatus queue.
  2149. ;   Return value
  2150. ;      al - 0 no error was found
  2151. ;      al - 1 error was found TxReset is needed
  2152. ;   Destroyed registers
  2153. ;      eax, ecx, edx, ebp
  2154. ;
  2155. ;***************************************************************************
  2156.  
  2157. align 4
  2158. check_tx_status:
  2159.  
  2160.         DEBUGF 1,"Checking TX status\n"
  2161.  
  2162. ; clear TxStatus queue
  2163.         set_io  0
  2164.         set_io  REG_TX_STATUS
  2165.         mov     ecx, 31 ; max number of queue entries
  2166. .tx_status_loop:
  2167.         in      al, dx
  2168.         test    al, al
  2169.         jz      .finish ; no error
  2170.         test    al, 0x3f
  2171.         jnz     .finish ; error
  2172. .no_error_found:
  2173. ; clear current TxStatus entry which advances the next one
  2174.         xor     al, al
  2175.         out     dx, al
  2176.         loop    .tx_status_loop
  2177. .finish:
  2178.  
  2179.         ret
  2180.  
  2181.  
  2182.  
  2183. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2184. ;;                                         ;;
  2185. ;; Transmit (vortex)                       ;;
  2186. ;;                                         ;;
  2187. ;; In: buffer pointer in [esp+4]           ;;
  2188. ;;     size of buffer in [esp+8]           ;;
  2189. ;;     pointer to device structure in ebx  ;;
  2190. ;;                                         ;;
  2191. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2192.  
  2193. align 4
  2194. vortex_transmit:
  2195.  
  2196.         DEBUGF 1,"Sending packet (vortex)\n"
  2197.  
  2198.         cmp     dword [esp+8], MAX_ETH_FRAME_SIZE
  2199.         ja      .finish ; packet is too long
  2200.  
  2201.         call    check_tx_status
  2202.         test    al, al
  2203.         jnz     tx_reset
  2204.  
  2205. ; switch to register window 7
  2206.         set_io  0
  2207.         set_io  REG_COMMAND
  2208.         mov     ax, SELECT_REGISTER_WINDOW+7
  2209.         out     dx, ax
  2210. ; check for master operation in progress
  2211.         set_io  REG_MASTER_STATUS
  2212.         in      ax, dx
  2213.         test    ah, 0x80
  2214.         jnz     .finish ; no DMA for sending
  2215. ; program frame address to be sent
  2216.         set_io  REG_MASTER_ADDRESS
  2217.         mov     eax, [esp+4]
  2218.         call    GetPgAddr
  2219.         out     dx, eax
  2220. ; program frame length
  2221.         set_io  REG_MASTER_LEN
  2222.         mov     eax, [esp+8]
  2223. ;;;        and     eax, not 3
  2224.         out     dx, ax
  2225. ; start DMA Down
  2226.         set_io  REG_COMMAND
  2227.         mov     ax, (10100b shl 11) + 1 ; StartDMADown
  2228.         out     dx, ax
  2229. .finish:
  2230.         ret
  2231.  
  2232.  
  2233.  
  2234. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2235. ;;                                         ;;
  2236. ;; Transmit (boomerang)                    ;;
  2237. ;;                                         ;;
  2238. ;; In: buffer pointer in [esp+4]           ;;
  2239. ;;     size of buffer in [esp+8]           ;;
  2240. ;;     pointer to device structure in ebx  ;;
  2241. ;;                                         ;;
  2242. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2243.  
  2244. align 4
  2245. boomerang_transmit:
  2246.  
  2247.         DEBUGF  1,"Sending packet (boomerang)\n"
  2248.  
  2249.         cmp     dword [esp+8], MAX_ETH_FRAME_SIZE
  2250.         ja      .finish ; packet is too long
  2251.  
  2252.         call    check_tx_status
  2253.         test    al, al
  2254.         jnz     tx_reset
  2255.  
  2256. ; calculate descriptor address
  2257.         mov     eax, [device.prev_dpd]
  2258.         DEBUGF  1,"Previous DPD: %x\n", eax
  2259.         add     eax, dpd.size
  2260.         mov     ecx, [device.dpd_buffer]
  2261.         add     ecx, NUM_TX_DESC*dpd.size
  2262.         cmp     eax, ecx
  2263.         cmovae  eax, [device.dpd_buffer]        ; Wrap if needed
  2264.  
  2265.         DEBUGF  1,"Found a free DPD: %x\n", eax
  2266.         push    eax
  2267. ; check DnListPtr
  2268.         set_io  0
  2269.         set_io  REG_DN_LIST_PTR
  2270.         in      eax, dx
  2271. ; mark if Dn_List_Ptr is cleared
  2272.         test    eax, eax
  2273.         setz    [device.dn_list_ptr_cleared]
  2274. ; finish if no more free descriptor is available - FIXME!
  2275.         cmp     eax, [esp]
  2276.         pop     eax
  2277.         jz      .finish
  2278.  
  2279.  
  2280.         push    eax             ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  2281. ; calculate tx_buffer address
  2282.         mov     edi, [device.prev_tx_frame]
  2283.         DEBUGF  1,"Previous TX frame:: %x\n", edi
  2284.         add     edi, MAX_ETH_FRAME_SIZE
  2285.  
  2286.         mov     ecx, [device.tx_buffer]
  2287.         add     ecx, NUM_TX_DESC*MAX_ETH_FRAME_SIZE
  2288.         cmp     edi, ecx
  2289.         cmovae  edi, [device.tx_buffer]         ; Wrap if needed
  2290.  
  2291.         DEBUGF  1,"Found place in TX buffer: %x\n", edi
  2292.         push    edi             ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  2293.  
  2294. ; update statistics
  2295.         inc     [device.packets_tx]
  2296.  
  2297.         mov     ecx, [esp+8+8]
  2298.         add     dword [device.bytes_tx], ecx
  2299.         adc     dword [device.bytes_tx + 4], 0
  2300.  
  2301. ; copy packet data
  2302.         mov     esi, [esp+4+8]
  2303.         DEBUGF  1,"Copying %u bytes from %x to %x\n", ecx, esi, edi
  2304.         shr     cx , 1
  2305.         jnc     .nb
  2306.         movsb
  2307.   .nb:
  2308.         shr     cx , 1
  2309.         jnc     .nw
  2310.         movsw
  2311.   .nw:
  2312.         rep     movsd
  2313.  
  2314. ; program DPD
  2315.         mov     eax, [esp]              ; Tx buffer address
  2316.         call    GetPgAddr
  2317.         mov     edi, [esp]
  2318.         and     edi, 4096 - 1
  2319.         or      edi, eax
  2320.  
  2321.         mov     eax, [esp+4]            ; descriptor
  2322.         DEBUGF  1,"Frag addr is: %x\n", edi
  2323.         and     [eax+dpd.next_ptr], 0
  2324.         mov     [eax+dpd.frag_addr], edi
  2325.  
  2326.         mov     ecx, [esp+8+8]          ; packet size
  2327.         or      ecx, 0x80000000         ; last fragment
  2328.         DEBUGF  1,"Frag size + flag is: %x\n", ecx
  2329.         mov     [eax+dpd.frag_len], ecx
  2330.  
  2331.         mov     ecx, [esp+8+8]          ; packet size
  2332.         or      ecx, 0x8000             ; transmission complete notification
  2333. ;        test    byte [device.has_hwcksm], 0xff
  2334. ;        jz      @f
  2335. ;        or      ecx, (1 shl 26) ; set AddTcpChecksum
  2336. ;@@:
  2337.         DEBUGF  1,"Frag start_hdr + flag is: %x\n", ecx
  2338.         mov     [eax+dpd.frame_start_hdr], ecx
  2339.  
  2340.  
  2341. ; calculate physical address
  2342.         mov     edi, eax
  2343.         call    GetPgAddr
  2344.         and     edi, 4096 - 1
  2345.         or      eax, edi
  2346.         cmp     [device.dn_list_ptr_cleared], 0
  2347.         jz      .add_to_list
  2348.  
  2349.         DEBUGF  1,"DN list ptr: %x\n", eax
  2350. ; write Dn_List_Ptr
  2351.         set_io  0
  2352.         set_io  REG_DN_LIST_PTR
  2353.         out     dx, eax
  2354.         jmp     .finish_pop
  2355. .add_to_list:
  2356.  
  2357.         DEBUGF  1,"Adding To list\n"
  2358.  
  2359. ; DnStall
  2360.         set_io  0
  2361.         set_io  REG_COMMAND
  2362.         mov     ax, ((110b shl 11)+2)
  2363.         out     dx, ax
  2364.  
  2365. ; wait for DnStall to complete
  2366.  
  2367.         DEBUGF  1,"Waiting for DnStall\n"
  2368.         mov     ecx, 6000
  2369. .wait_for_stall:
  2370.         in      ax, dx                  ; read REG_INT_STATUS
  2371.         test    ah, 10000b
  2372.         jz      .dnstall_ok
  2373.         dec     ecx
  2374.         jnz     .wait_for_stall
  2375.  
  2376. .dnstall_ok:
  2377.         DEBUGF  1,"DnStall ok!\n"
  2378.         mov     eax, [esp]              ; prev_tx_frame
  2379.         mov     ecx, [device.prev_dpd]
  2380.         mov     [ecx+dpd.next_ptr], eax
  2381.  
  2382.         set_io  0
  2383.         set_io  REG_DN_LIST_PTR
  2384.         in      eax, dx
  2385.  
  2386.         test    eax, eax
  2387.         jnz     .dnunstall
  2388. ; if Dn_List_Ptr has been cleared fill it up
  2389.         DEBUGF  1,"DnList Ptr has been cleared\n"
  2390.         mov     eax, [esp]
  2391.         out     dx, eax
  2392.  
  2393. .dnunstall:
  2394. ; DnUnStall
  2395.         set_io  0
  2396.         set_io  REG_COMMAND
  2397.         mov     ax, ((110b shl 11)+3)
  2398.         out     dx, ax
  2399.  
  2400. .finish_pop:
  2401.         pop     [device.prev_tx_frame]
  2402.         pop     [device.prev_dpd]
  2403.  
  2404. .finish:
  2405.         xor     eax, eax
  2406.         ret
  2407.  
  2408.  
  2409. ;---------------------------------
  2410. ; Write MAC
  2411.  
  2412.  
  2413. align 4
  2414. write_mac:   ; Tested - ok
  2415.  
  2416.         DEBUGF 1,"Writing mac\n"
  2417.  
  2418.         set_io  0
  2419.         set_io  REG_COMMAND
  2420.  
  2421. ; switch to register window 2
  2422.         mov     ax, SELECT_REGISTER_WINDOW+2
  2423.         out     dx, ax
  2424.  
  2425. ; write MAC addres back into the station address registers
  2426.         set_io  REG_STATION_ADDRESS_LO
  2427.         lea     esi, [device.mac]
  2428.         outsw
  2429.         inc     dx
  2430.         inc     dx
  2431.         outsw
  2432.         inc     dx
  2433.         inc     dx
  2434.         outsw
  2435.  
  2436. ;----------------------------
  2437. ; Read MAC
  2438.  
  2439.  
  2440. align 4
  2441. read_mac:    ; Tested - ok
  2442.  
  2443.  
  2444.  
  2445.         set_io  0
  2446.         set_io  REG_COMMAND
  2447.  
  2448. ; switch to register window 2
  2449.         mov     ax, SELECT_REGISTER_WINDOW+2
  2450.         out     dx, ax
  2451.  
  2452. ; write MAC addres back into the station address registers
  2453.         set_io  REG_STATION_ADDRESS_LO
  2454.         lea     edi, [device.mac]
  2455.         insw
  2456.         inc     dx
  2457.         inc     dx
  2458.         insw
  2459.         inc     dx
  2460.         inc     dx
  2461.         insw
  2462.  
  2463.         DEBUGF 1,"%x-%x-%x-%x-%x-%x\n",[device.mac]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
  2464.  
  2465.         ret
  2466.  
  2467.  
  2468. ;------------------------------------
  2469. ; Read MAC from eeprom
  2470.  
  2471.  
  2472. align 4
  2473. read_mac_eeprom:        ; Tested - ok
  2474.  
  2475.         DEBUGF 1,"Reading mac from eeprom\n"
  2476.  
  2477. ; read MAC from eeprom
  2478.         mov     ecx, 3
  2479. .mac_loop:
  2480.         lea     ax, [EEPROM_REG_OEM_NODE_ADDR+ecx-1]
  2481.         push    ecx
  2482.         call    read_eeprom
  2483.         pop     ecx
  2484.         xchg    ah, al ; htons
  2485.         mov     word [device.mac+ecx*2-2], ax
  2486.  
  2487.         loop    .mac_loop
  2488.  
  2489.         DEBUGF 1,"%x-%x-%x-%x-%x-%x\n",[device.mac]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
  2490.  
  2491.         ret
  2492.  
  2493.  
  2494.  
  2495.  
  2496.  
  2497. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2498. ;;                          ;;
  2499. ;; Vortex Interrupt handler ;;
  2500. ;;                          ;;
  2501. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2502.  
  2503. align 4
  2504. int_vortex:
  2505.  
  2506.         DEBUGF  1,"vortex IRQ %x ",eax:2
  2507.  
  2508. ; find pointer of device wich made IRQ occur
  2509.  
  2510.         mov     esi, VORTEX_LIST
  2511.         mov     ecx, [VORTEX_DEVICES]
  2512.         test    ecx, ecx
  2513.         jz      .fail
  2514.   .nextdevice:
  2515.         mov     ebx, dword [esi]
  2516.  
  2517.  
  2518.         set_io  0
  2519.         set_io  REG_INT_STATUS
  2520.         in      ax, dx
  2521. ;;        and     ax, INT_MASK
  2522.         jnz     .got_it
  2523.  
  2524.  
  2525.         add     esi, 4
  2526.  
  2527.         test    ax , ax
  2528.         jnz     .got_it
  2529.         loop    .nextdevice
  2530.  
  2531.   .fail:
  2532.  
  2533.         ret
  2534.  
  2535. .got_it:
  2536.  
  2537.         DEBUGF  1,"Device: %x Status: %x ",ebx,eax:4
  2538.  
  2539.         test    ax, RxComplete
  2540.         jz      .noRX
  2541.  
  2542.         set_io  0
  2543.   .rx_status_loop:
  2544. ; examine RxStatus
  2545.         set_io  REG_RX_STATUS
  2546.         in      ax, dx
  2547.         test    ax, ax
  2548.         jz      .finish
  2549.  
  2550.         test    ah, 0x80 ; rxIncomplete
  2551.         jnz     .finish
  2552.  
  2553.         test    ah, 0x40
  2554.         jz      .check_length
  2555.  
  2556. ; discard the top frame received advancing the next one
  2557.         set_io  REG_COMMAND
  2558.         mov     ax, (01000b shl 11)
  2559.         out     dx, ax
  2560.         jmp     .rx_status_loop
  2561.  
  2562.   .check_length:
  2563.         and     eax, 0x1fff
  2564.         cmp     eax, MAX_ETH_PKT_SIZE
  2565.         ja      .discard_frame ; frame is too long discard it
  2566.  
  2567.   .check_dma:
  2568.         mov     ecx, eax
  2569. ; switch to register window 7
  2570.         set_io  0
  2571.         set_io  REG_COMMAND
  2572.         mov     ax, SELECT_REGISTER_WINDOW+7
  2573.         out     dx, ax
  2574. ; check for master operation in progress
  2575.         set_io  REG_MASTER_STATUS
  2576.         in      ax, dx
  2577.  
  2578.         test    ah, 0x80
  2579.         jnz     .finish
  2580.  
  2581.   .read_frame:
  2582. ; program buffer address to read in
  2583.         stdcall KernelAlloc, ecx ; Allocate a buffer to put packet into
  2584.         test    eax, eax
  2585.         jz      .finish
  2586.  
  2587.         push    .discard_frame
  2588.         push    ecx
  2589.         push    eax
  2590. ;        zero_to_dma eax
  2591.         set_io  REG_MASTER_ADDRESS
  2592.         out     dx, eax
  2593.  
  2594. ; program frame length
  2595.         set_io  REG_MASTER_LEN
  2596.         mov     ax, 1560
  2597.         out     dx, ax
  2598.  
  2599. ; start DMA Up
  2600.         set_io  REG_COMMAND
  2601.         mov     ax, (10100b shl 11) ; StartDMAUp
  2602.         out     dx, ax
  2603.  
  2604. ; check for master operation in progress
  2605.         set_io  REG_MASTER_STATUS   ; TODO: use timeout and reset after timeout expired
  2606.   .dma_loop:
  2607.         xor     esi, esi
  2608.         stdcall Sleep
  2609.         in      ax, dx
  2610.         test    ah, 0x80
  2611.         jnz     .dma_loop
  2612.  
  2613. ; registrate the received packet to kernel
  2614.         jmp     EthReceiver
  2615.  
  2616. ; discard the top frame received
  2617.   .discard_frame:
  2618.         set_io  0
  2619.         set_io  REG_COMMAND
  2620.         mov     ax, (01000b shl 11)
  2621.         out     dx, ax
  2622.  
  2623.   .finish:
  2624.  
  2625.  
  2626. .noRX:
  2627.  
  2628.         test    ax, DMADone
  2629.         jz      .noDMA
  2630.  
  2631.         push    ax
  2632.  
  2633.         set_io  0
  2634.         set_io  12
  2635.         in      ax, dx
  2636.         test    ax, 0x1000
  2637.         jz      .nodmaclear
  2638.  
  2639.         mov     ax, 0x1000
  2640.         out     dx, ax
  2641.  
  2642.   .nodmaclear:
  2643.  
  2644.         pop     ax
  2645.  
  2646.         DEBUGF  1, "DMA Done!\n", cx
  2647.  
  2648.  
  2649.  
  2650. .noDMA:
  2651.  
  2652.  
  2653.  
  2654. .ACK:
  2655.         set_io  0
  2656.         set_io  REG_COMMAND
  2657.         mov     ax, AckIntr + IntReq + IntLatch
  2658.         out     dx, ax
  2659.  
  2660.         ret
  2661.  
  2662.  
  2663.  
  2664.  
  2665. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2666. ;;                             ;;
  2667. ;; Boomerang Interrupt handler ;;
  2668. ;;                             ;;
  2669. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2670.  
  2671. align 4
  2672. int_boomerang:
  2673.  
  2674. ;        DEBUGF  1,"\nIRQ %x Boomerang\n",eax:2
  2675.  
  2676. ; find pointer of device wich made IRQ occur
  2677.  
  2678.         mov     esi, BOOMERANG_LIST
  2679.         mov     ecx, [BOOMERANG_DEVICES]
  2680.  
  2681. ;        DEBUGF  1,"Devices: %u\n", ecx
  2682.         test    ecx, ecx
  2683.         jz      .fail
  2684.   .nextdevice:
  2685.         mov     ebx, dword[esi]
  2686.  
  2687.         set_io  0
  2688.         set_io  REG_INT_STATUS
  2689.         in      ax, dx
  2690.         test    ax, IntLatch
  2691.         jnz     .got_it
  2692.  
  2693.         add     esi, 4
  2694.  
  2695.         test    ax , ax
  2696.         jnz     .got_it
  2697.         dec     ecx
  2698.         jnz     .nextdevice
  2699.  
  2700.   .fail:
  2701.         DEBUGF  1,"Failed!\n"
  2702.         ret
  2703.  
  2704. .got_it:
  2705.  
  2706.         DEBUGF  1,"Device: %x Status: %x ", ebx, eax
  2707.  
  2708.         push    ax
  2709. ; disable all INTS
  2710.  
  2711.         set_io  REG_COMMAND
  2712.         mov     ax, SetIntrEnb
  2713.         out     dx, ax
  2714.  
  2715. ;; acknowledge all int sources
  2716. ;
  2717. ;        mov     ax, word [esp]
  2718. ;        and     ax, 0xff
  2719. ;        or      ax, AckIntr
  2720. ;        out     dx, ax
  2721.  
  2722. ;--------------------------------------------------------------------------
  2723.         test    word[esp], UpComplete
  2724.         jz      .noRX
  2725.  
  2726.         push    ebx
  2727.  
  2728.   .receive:
  2729.         DEBUGF  1,"UpComplete\n"
  2730.  
  2731. ; check if packet is uploaded
  2732.         mov     eax, [device.curr_upd]
  2733.         test    byte [eax+upd.pkt_status+1], 0x80 ; upPktComplete
  2734.         jz      .finish
  2735. ; packet is uploaded check for any error
  2736.   .check_error:
  2737.         test    byte [eax+upd.pkt_status+1], 0x40 ; upError
  2738.         jz      .copy_packet_length
  2739.         DEBUGF  1,"Error in packet\n"
  2740.         and     [eax+upd.pkt_status], 0           ; mark packet as read
  2741.         jmp     .finish
  2742.   .copy_packet_length:
  2743.         mov     ecx, [eax+upd.pkt_status]
  2744.         and     ecx, 0x1fff
  2745.         cmp     ecx, MAX_ETH_PKT_SIZE
  2746.         jbe     .copy_packet
  2747.         and     [eax+upd.pkt_status], 0
  2748.         jmp     .finish
  2749.  
  2750.   .copy_packet:
  2751.         DEBUGF  1, " data hw addr:%x\n", [eax+upd.frag_addr]
  2752.  
  2753.         mov     esi, [eax+upd.realaddr]
  2754.  
  2755.         push    esi ecx
  2756.         stdcall KernelAlloc, ecx ; Allocate a buffer to put packet into
  2757.         pop     ecx esi
  2758.         test    eax, eax
  2759.         jz      .finish
  2760.  
  2761.         push    dword .loop ;.finish
  2762.         push    ecx eax
  2763.         mov     edi, eax
  2764.  
  2765.         DEBUGF  1, " copying %u bytes from %x to %x\n", ecx, esi, edi
  2766.  
  2767. ; update statistics
  2768.         inc     [device.packets_rx]
  2769.  
  2770.         add     dword [device.bytes_rx], ecx
  2771.         adc     dword [device.bytes_rx + 4], 0
  2772.  
  2773. ; copy packet data
  2774.         shr     cx , 1
  2775.         jnc     .nb
  2776.         movsb
  2777.   .nb:
  2778.         shr     cx , 1
  2779.         jnc     .nw
  2780.         movsw
  2781.   .nw:
  2782.         rep     movsd
  2783.  
  2784.         mov     eax, [device.curr_upd]
  2785.         DEBUGF  1, "current upd: %x\n", eax
  2786.         and     [eax + upd.pkt_status], 0       ; clear the ring buffer entry for reuse
  2787.         mov     [eax + upd.frag_len], MAX_ETH_FRAME_SIZE or (1 shl 31) ;;;
  2788.         add     eax, upd.size
  2789.  
  2790.         mov     ecx, [device.upd_buffer]
  2791.         add     ecx, (NUM_RX_DESC)*upd.size
  2792.  
  2793.         cmp     eax, ecx
  2794.         cmovae  eax, [device.upd_buffer]
  2795.         mov     [device.curr_upd], eax
  2796.         DEBUGF  1, "next upd: %x\n", eax
  2797.  
  2798.         jmp     EthReceiver
  2799.  
  2800.   .loop:
  2801.         mov     ebx, [esp]
  2802.         jmp     .receive
  2803.  
  2804.   .finish:
  2805.         pop     ebx
  2806.  
  2807. ; check if the NIC is in the upStall state
  2808.         set_io  0
  2809.         set_io  REG_UP_PKT_STATUS
  2810.         in      eax, dx
  2811.         test    ah, 0x20             ; UpStalled
  2812.         jz      .noUpUnStall
  2813. ; issue upUnStall command
  2814.         set_io  REG_COMMAND
  2815.         mov     ax, ((11b shl 12)+1) ; upUnStall
  2816.         out     dx, ax
  2817.         DEBUGF  1, "upUnStalling\n"
  2818.   .noUpUnStall:
  2819.  
  2820. .noRX:
  2821.         pop     ax
  2822.  
  2823.         set_io  0
  2824.         set_io  REG_COMMAND
  2825.         or      ax, AckIntr
  2826.         out     dx, ax
  2827.  
  2828.     ;    set_io  REG_COMMAND
  2829.     ;    mov     ax, AckIntr + IntLatch
  2830.     ;    out     dx, ax
  2831.  
  2832.  
  2833.         set_io  REG_INT_STATUS
  2834.         in      ax, dx
  2835.         test    ax, S_5_INTS
  2836.         jnz     .got_it
  2837.  
  2838. ;re-enable ints
  2839.         set_io  REG_COMMAND
  2840.         mov     ax, SetIntrEnb + S_5_INTS
  2841.         out     dx, ax
  2842.  
  2843.  
  2844.         ret
  2845.  
  2846.  
  2847.  
  2848.  
  2849. ; End of code
  2850.  
  2851. align 4                                         ; Place all initialised data here
  2852.  
  2853.  
  2854.  
  2855. macro strtbl name, [string]
  2856. {
  2857. common
  2858.         label name dword
  2859. forward
  2860.         local label
  2861.         dd label
  2862. forward
  2863.         label db string, 0
  2864. }
  2865.  
  2866. VORTEX_DEVICES       dd 0
  2867. BOOMERANG_DEVICES    dd 0
  2868. version              dd (5 shl 16) or (API_VERSION and 0xFFFF)
  2869. my_service           db '3C59X',0                    ; max 16 chars include zero
  2870.  
  2871.  
  2872. strtbl link_str, \
  2873.         "No valid link type detected", \
  2874.         "10BASE-T half duplex", \
  2875.         "10BASE-T full-duplex", \
  2876.         "100BASE-TX half duplex", \
  2877.         "100BASE-TX full duplex", \
  2878.         "100BASE-T4", \
  2879.         "100BASE-FX", \
  2880.         "10Mbps AUI", \
  2881.         "10Mbps COAX (BNC)", \
  2882.         "miiDevice - not supported"
  2883.  
  2884. strtbl hw_str, \
  2885.         "3c590 Vortex 10Mbps", \
  2886.         "3c592 EISA 10Mbps Demon/Vortex", \
  2887.         "3c597 EISA Fast Demon/Vortex", \
  2888.         "3c595 Vortex 100baseTx", \
  2889.         "3c595 Vortex 100baseT4", \
  2890.         "3c595 Vortex 100base-MII", \
  2891.         "3c900 Boomerang 10baseT", \
  2892.         "3c900 Boomerang 10Mbps Combo", \
  2893.         "3c900 Cyclone 10Mbps TPO", \
  2894.         "3c900 Cyclone 10Mbps Combo", \
  2895.         "3c900 Cyclone 10Mbps TPC", \
  2896.         "3c900B-FL Cyclone 10base-FL", \
  2897.         "3c905 Boomerang 100baseTx", \
  2898.         "3c905 Boomerang 100baseT4", \
  2899.         "3c905B Cyclone 100baseTx", \
  2900.         "3c905B Cyclone 10/100/BNC", \
  2901.         "3c905B-FX Cyclone 100baseFx", \
  2902.         "3c905C Tornado", \
  2903.         "3c980 Cyclone", \
  2904.         "3c982 Dual Port Server Cyclone", \
  2905.         "3cSOHO100-TX Hurricane", \
  2906.         "3c555 Laptop Hurricane", \
  2907.         "3c556 Laptop Tornado", \
  2908.         "3c556B Laptop Hurricane", \
  2909.         "3c575 [Megahertz] 10/100 LAN CardBus", \
  2910.         "3c575 Boomerang CardBus", \
  2911.         "3CCFE575BT Cyclone CardBus", \
  2912.         "3CCFE575CT Tornado CardBus", \
  2913.         "3CCFE656 Cyclone CardBus", \
  2914.         "3CCFEM656B Cyclone+Winmodem CardBus", \
  2915.         "3CXFEM656C Tornado+Winmodem CardBus", \
  2916.         "3c450 HomePNA Tornado", \
  2917.         "3c920 Tornado", \
  2918.         "3c982 Hydra Dual Port A", \
  2919.         "3c982 Hydra Dual Port B", \
  2920.         "3c905B-T4", \
  2921.         "3c920B-EMB-WNM Tornado"
  2922.  
  2923.  
  2924.  
  2925. align 4
  2926. hw_versions:
  2927. dw 0x5900, IS_VORTEX
  2928. ; 3c590 Vortex 10Mbps
  2929. dw 0x5920, IS_VORTEX
  2930. ; 3c592 EISA 10Mbps Demon/Vortex
  2931. dw 0x5970, IS_VORTEX
  2932. ; 3c597 EISA Fast Demon/Vortex
  2933. dw 0x5950, IS_VORTEX
  2934. ; 3c595 Vortex 100baseTx
  2935. dw 0x5951, IS_VORTEX
  2936. ; 3c595 Vortex 100baseT4
  2937. dw 0x5952, IS_VORTEX
  2938. ; 3c595 Vortex 100base-MII
  2939. dw 0x9000, IS_BOOMERANG
  2940. ; 3c900 Boomerang 10baseT
  2941. dw 0x9001, IS_BOOMERANG
  2942. ; 3c900 Boomerang 10Mbps Combo
  2943. dw 0x9004, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM
  2944. ; 3c900 Cyclone 10Mbps TPO
  2945. dw 0x9005, IS_CYCLONE or HAS_HWCKSM
  2946. ; 3c900 Cyclone 10Mbps Combo
  2947. dw 0x9006, IS_CYCLONE or HAS_HWCKSM
  2948. ; 3c900 Cyclone 10Mbps TPC
  2949. dw 0x900A, IS_CYCLONE or HAS_HWCKSM
  2950. ; 3c900B-FL Cyclone 10base-FL
  2951. dw 0x9050, IS_BOOMERANG or HAS_MII
  2952. ; 3c905 Boomerang 100baseTx
  2953. dw 0x9051, IS_BOOMERANG or HAS_MII
  2954. ; 3c905 Boomerang 100baseT4
  2955. dw 0x9055, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE
  2956. ; 3c905B Cyclone 100baseTx
  2957. dw 0x9058, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM
  2958. ; 3c905B Cyclone 10/100/BNC
  2959. dw 0x905A, IS_CYCLONE or HAS_HWCKSM
  2960. ; 3c905B-FX Cyclone 100baseFx
  2961. dw 0x9200, IS_TORNADO or HAS_NWAY or HAS_HWCKSM
  2962. ; 3c905C Tornado
  2963. dw 0x9800, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM
  2964. ; 3c980 Cyclone
  2965. dw 0x9805, IS_TORNADO or HAS_NWAY or HAS_HWCKSM
  2966. ; 3c982 Dual Port Server Cyclone
  2967. dw 0x7646, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM
  2968. ; 3cSOHO100-TX Hurricane
  2969. dw 0x5055, IS_CYCLONE or EEPROM_8BIT or HAS_HWCKSM
  2970. ; 3c555 Laptop Hurricane
  2971. dw 0x6055, IS_TORNADO or HAS_NWAY or EEPROM_8BIT or HAS_CB_FNS or INVERT_MII_PWR or HAS_HWCKSM
  2972. ; 3c556 Laptop Tornado
  2973. dw 0x6056, IS_TORNADO or HAS_NWAY or EEPROM_OFFSET or HAS_CB_FNS or INVERT_MII_PWR or HAS_HWCKSM
  2974. ; 3c556B Laptop Hurricane
  2975. dw 0x5b57, IS_BOOMERANG or HAS_MII or EEPROM_8BIT
  2976. ; 3c575 [Megahertz] 10/100 LAN CardBus
  2977. dw 0x5057, IS_BOOMERANG or HAS_MII or EEPROM_8BIT
  2978. ; 3c575 Boomerang CardBus
  2979. dw 0x5157, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_LED_PWR or HAS_HWCKSM
  2980. ; 3CCFE575BT Cyclone CardBus
  2981. dw 0x5257, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR or MAX_COLLISION_RESET or HAS_HWCKSM
  2982. ; 3CCFE575CT Tornado CardBus
  2983. dw 0x6560, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR or INVERT_LED_PWR or HAS_HWCKSM
  2984. ; 3CCFE656 Cyclone CardBus
  2985. dw 0x6562, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR or INVERT_LED_PWR or HAS_HWCKSM
  2986. ; 3CCFEM656B Cyclone+Winmodem CardBus
  2987. dw 0x6564, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR or MAX_COLLISION_RESET or HAS_HWCKSM
  2988. ; 3CXFEM656C Tornado+Winmodem CardBus
  2989. dw 0x4500, IS_TORNADO or HAS_NWAY or HAS_HWCKSM
  2990. ; 3c450 HomePNA Tornado
  2991. dw 0x9201, IS_TORNADO or HAS_NWAY or HAS_HWCKSM
  2992. ; 3c920 Tornado
  2993. dw 0x1201, IS_TORNADO or HAS_HWCKSM or HAS_NWAY
  2994. ; 3c982 Hydra Dual Port A
  2995. dw 0x1202, IS_TORNADO or HAS_HWCKSM or HAS_NWAY
  2996. ; 3c982 Hydra Dual Port B
  2997. dw 0x9056, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE
  2998. ; 3c905B-T4
  2999. dw 0x9210, IS_TORNADO or HAS_NWAY or HAS_HWCKSM
  3000. ; 3c920B-EMB-WNM Tornado
  3001. HW_VERSIONS_SIZE = $ - hw_versions
  3002.  
  3003.  
  3004. include_debug_strings                           ; All data wich FDO uses will be included here
  3005.  
  3006. section '.data' data readable writable align 16 ; place all uninitialized data place here
  3007.  
  3008. VORTEX_LIST    rd MAX_DEVICES                   ; This list contains all pointers to device structures the driver is handling
  3009. BOOMERANG_LIST rd MAX_DEVICES
  3010.  
  3011.  
  3012.  
  3013.  
  3014.