Subversion Repositories Kolibri OS

Rev

Rev 1492 | Go to most recent revision | 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.         mov     [device.type], NET_TYPE_ETH
  549.         call    NetRegDev
  550.  
  551.         cmp     eax, -1
  552.         je      .destroy
  553.  
  554.         call    start
  555.  
  556.         ret
  557.  
  558.   .not_vortex:
  559.  
  560.         mov     eax, [BOOMERANG_DEVICES]                                          ; Add the device structure to our device list
  561.         mov     [BOOMERANG_LIST+4*eax], ebx                                ; (IRQ handler uses this list to find device)
  562.         inc     [BOOMERANG_DEVICES]
  563.  
  564.         call    .register
  565.  
  566. ; If the device was already loaded, find the device number and return it in eax
  567.  
  568.   .find_devicenum:
  569.         DEBUGF  1,"Trying to find device number of already registered device\n"
  570.         call    NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
  571.                                                                         ; into a device number in edi
  572.         mov     eax, edi                                                ; Application wants it in eax instead
  573.         DEBUGF  1,"Kernel says: %u\n", eax
  574.         ret
  575.  
  576. ; If an error occured, remove all allocated data and exit (returning -1 in eax)
  577.  
  578.   .destroy:
  579.         ; todo: reset device into virgin state
  580.  
  581.   .err:
  582.         stdcall KernelFree, [device.rx_buffer]
  583.         stdcall KernelFree, [device.tx_buffer]
  584.         stdcall KernelFree, ebx
  585.  
  586.  
  587.   .fail:
  588.         or      eax, -1
  589.         ret
  590.  
  591. ;------------------------------------------------------
  592. endp
  593.  
  594.  
  595. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  596. ;;                                                                        ;;
  597. ;;        Actual Hardware dependent code starts here                      ;;
  598. ;;                                                                        ;;
  599. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  600.  
  601.  
  602.  
  603.  
  604.  
  605. ;***************************************************************************
  606. ;   Function
  607. ;      probe
  608. ;   Description
  609. ;      Searches for an ethernet card, enables it and clears the rx buffer
  610. ;   Destroyed registers
  611. ;      eax, ebx, ecx, edx, edi, esi
  612. ;
  613. ;***************************************************************************
  614.  
  615. align 4
  616. probe:                  ; Tested - ok
  617.  
  618.         DEBUGF  1,"Probing 3com card\n"
  619.  
  620.         make_bus_master [device.pci_bus], [device.pci_dev]
  621.  
  622. ; wake up the card
  623.         call    wake_up
  624.  
  625.         movzx   ecx, [device.pci_bus]
  626.         movzx   edx, [device.pci_dev]
  627.         stdcall PciRead32, ecx ,edx ,0                                ; get device/vendor id
  628.  
  629.         DEBUGF  1,"Vendor id: 0x%x\n", ax
  630.  
  631.         cmp     ax , 0x10B7
  632.         jne     .notfound
  633.         shr     eax, 16
  634.  
  635.         DEBUGF  1,"Vendor ok!, device id: 0x%x\n", ax
  636.  
  637. ; get chip version
  638.         mov     ecx, HW_VERSIONS_SIZE/4-1
  639. .loop:
  640.         cmp     ax , [hw_versions+ecx*4]
  641.         jz      .found
  642.         loop    .loop
  643.         DEBUGF  1,"ecx: %u\n", ecx
  644. .notfound:
  645.         DEBUGF  1,"Device id not found in list!\n"
  646.         or      eax, -1
  647.         ret
  648. .found:
  649.         mov     esi, [hw_str+ecx*4]
  650.         DEBUGF  1,"Hardware type: %s\n", esi
  651.         mov     [device.name], esi
  652.  
  653.         mov     [device.ver_id], cl
  654.         test    word [hw_versions+2+ecx*4], HAS_HWCKSM
  655.         setnz   [device.has_hwcksm]
  656. ; set pci latency for vortex cards
  657.         test    word [hw_versions+2+ecx*4], IS_VORTEX
  658.         jz      .not_vortex
  659.  
  660.         mov     eax, 11111000b ; 248 = max latency
  661.         movzx   ecx, [device.pci_bus]
  662.         movzx   edx, [device.pci_dev]
  663.         stdcall PciWrite32, ecx, edx, PCI_REG_LATENCY, eax
  664.  
  665. .not_vortex:
  666. ; set RX/TX functions
  667.         mov     ax, EEPROM_REG_CAPABILITIES
  668.         call    read_eeprom
  669.         test    al, 100000b ; full bus master?
  670.         setnz   [device.full_bus_master]
  671.         jnz     .boomerang_func
  672.         mov     [device.transmit], vortex_transmit
  673.         DEBUGF  1,"Device is a vortex type\n"
  674.         jmp     @f
  675. .boomerang_func: ; full bus master, so use boomerang functions
  676.         mov     [device.transmit], boomerang_transmit
  677.         DEBUGF  1,"Device is a boomerang type\n"
  678. @@:
  679.         call    read_mac_eeprom
  680.  
  681.         test    byte [device.full_bus_master], 0xff
  682.         jz      .set_preamble
  683. ; switch to register window 2
  684.         set_io  0
  685.         set_io  REG_COMMAND
  686.         mov     ax, SELECT_REGISTER_WINDOW+2
  687.         out     dx, ax
  688. ; activate xcvr by setting some magic bits
  689.         set_io  REG_RESET_OPTIONS
  690.         in      ax, dx
  691.         and     ax, not 0x4010
  692.         movzx   ecx, [device.ver_id]
  693.         test    word [ecx*4+hw_versions+2], INVERT_LED_PWR
  694.         jz      @f
  695.         or      al, 0x10
  696. @@:
  697.         test    word [ecx*4+hw_versions+2], INVERT_MII_PWR
  698.         jz      @f
  699.         or      ah, 0x40
  700. @@:
  701.         out     dx, ax
  702. .set_preamble:
  703. ; use preamble as default
  704.         mov     byte [device.preamble], 1 ; enable preamble
  705.  
  706.         call    global_reset
  707.  
  708. ;--------------------------
  709. ; RESET
  710.  
  711. align 4
  712. reset:
  713.  
  714.         movzx   eax, [device.irq_line]
  715.         DEBUGF  1,"Attaching int handler to irq %x\n",eax:1
  716.  
  717.         movzx   ecx, [device.ver_id]
  718.         test    word [hw_versions+2+ecx*4], IS_VORTEX
  719.         jz      .not_vortex
  720.  
  721.         mov     esi, int_vortex
  722.         jmp     .reg_int
  723.  
  724. .not_vortex:
  725.         mov     esi, int_boomerang
  726.  
  727. .reg_int:
  728.         stdcall AttachIntHandler, eax, esi, dword 0
  729.         test    eax, eax
  730.         jnz     @f
  731.         DEBUGF  1,"\nCould not attach int handler!\n"
  732. ;        or      eax, -1
  733. ;        ret
  734.   @@:
  735.  
  736.         set_io  0
  737.         set_io  REG_COMMAND
  738.         mov     ax, SELECT_REGISTER_WINDOW + 0
  739.         out     dx, ax
  740.  
  741.         mov     ax, StopCoax
  742.         out     dx, ax                        ; stop transceiver
  743.  
  744.         mov     ax, SELECT_REGISTER_WINDOW + 4
  745.         out     dx, ax                        ; disable UTP
  746.  
  747.         set_io  REG_MEDIA_STATUS
  748.         mov     ax, 0x0
  749.  
  750.         set_io  REG_COMMAND
  751.         mov     ax, SELECT_REGISTER_WINDOW + 0
  752.         out     dx, ax
  753.  
  754.         set_io  REG_FIFO_DIAGNOSTIC
  755.         mov     ax, 0
  756.         out     dx, ax                        ; disable card
  757.  
  758.         mov     ax, 1
  759.         out     dx, ax                        ; enable card
  760.  
  761.         call    write_mac
  762.  
  763.         call    rx_reset
  764.         call    tx_reset
  765.  
  766.         set_io  REG_COMMAND
  767.         mov     ax, SELECT_REGISTER_WINDOW + 1
  768.         out     dx, ax
  769.  
  770.         mov     ecx, 32
  771.         set_io  0x0b
  772.   .loop:
  773.         in      al, dx
  774.         loop    .loop
  775.  
  776. ; Get rid of stary ints
  777.         set_io  REG_COMMAND
  778.         mov     ax, AckIntr + 0xff
  779.         out     dx, ax
  780.  
  781.         mov     ax, SetStatusEnb + S_5_INTS
  782.         out     dx, ax
  783.  
  784.         mov     ax, SetIntrEnb + S_5_INTS
  785.         out     dx, ax
  786.  
  787.         call    set_rx_mode
  788.         call    set_active_port
  789.  
  790.         set_io  0
  791.         set_io  REG_COMMAND
  792.         mov     ax, RxEnable
  793.         out     dx, ax
  794.  
  795.         mov     ax, TxEnable
  796.         out     dx, ax
  797.  
  798.         set_io  REG_COMMAND
  799.         mov     ax, SetRxThreshold + 208
  800.         out     dx, ax
  801.  
  802.         mov     ax, SetTxThreshold + 60 ;16 ; recommended by the manual :)
  803.         out     dx, ax
  804.  
  805.         mov     ax, SELECT_REGISTER_WINDOW + 1
  806.         out     dx, ax
  807.  
  808.         xor     eax, eax
  809. ; clear packet/byte counters
  810.  
  811.         lea     edi, [device.bytes_tx]
  812.         mov     ecx, 6
  813.         rep     stosd
  814.  
  815.         ret
  816.  
  817.  
  818.  
  819.  
  820.  
  821. align 4
  822. start:
  823.  
  824.         set_io  0
  825.         set_io  REG_COMMAND
  826.         mov     ax, SetTxThreshold + 60 ;2047 ; recommended by the manual :)
  827.         out     dx, ax
  828.  
  829.         call    check_tx_status
  830.  
  831.         set_io  0
  832.         set_io  REG_COMMAND
  833. ; switch to register window 4
  834.         mov     ax, SELECT_REGISTER_WINDOW+4
  835.         out     dx, ax
  836.  
  837. ; wait for linkDetect
  838.         set_io  REG_MEDIA_STATUS
  839.         mov     ecx, 20 ; wait for max 2s
  840. .link_detect_loop:
  841.         mov     esi, 10
  842.         stdcall Sleep ; 100 ms
  843.         in      ax, dx
  844.         test    ah, 1000b ; linkDetect
  845.         jnz     @f
  846.         loop    .link_detect_loop
  847. @@:
  848.  
  849. ; print link type
  850.         xor     eax, eax
  851.         bsr     ax, word [device.mode]
  852.         jz      @f
  853.         sub     ax, 4
  854. @@:
  855.         mov     esi, [link_str+eax*4]
  856.         DEBUGF 1,"Established Link type: %s\n", esi
  857.  
  858.  
  859.         set_io  0
  860.         set_io  REG_COMMAND
  861.         mov     ax, SELECT_REGISTER_WINDOW + 1
  862.         out     dx, ax
  863.  
  864.         mov     ax, AckIntr + 0xff
  865.         out     dx, ax
  866.  
  867.         mov     ax, SetStatusEnb + S_5_INTS
  868.         out     dx, ax
  869.  
  870.         mov     ax, SetIntrEnb + S_5_INTS
  871.         out     dx, ax
  872.  
  873.         set_io  0
  874.         set_io  REG_COMMAND
  875.         mov     ax, SELECT_REGISTER_WINDOW + 1
  876.  
  877.  
  878.         ret
  879.  
  880.  
  881.  
  882.  
  883.  
  884.  
  885.  
  886. align 4
  887. set_rx_mode:
  888.  
  889.         set_io  0
  890.         set_io  REG_COMMAND
  891.  
  892.         if      defined PROMISCIOUS
  893.         mov     ax, SetRxFilter + RxStation + RxMulticast + RxBroadcast + RxProm
  894.         else if  defined ALLMULTI
  895.         mov     ax, SetRxFilter + RxStation + RxMulticast + RxBroadcast
  896.         else
  897.         mov     ax, SetRxFilter + RxStation + RxBroadcast
  898.         end if
  899.  
  900.         out     dx, ax
  901.  
  902.         ret
  903.  
  904.  
  905.  
  906.  
  907.  
  908. ;***************************************************************************
  909. ;   Function
  910. ;      global_reset
  911. ;   Description
  912. ;      resets the device
  913. ;   Parameters:
  914. ;      ebp - io_addr
  915. ;   Return value:
  916. ;   Destroyed registers
  917. ;      ax, ecx, edx, esi
  918. ;
  919. ;***************************************************************************1
  920.  
  921. align 4
  922. global_reset:
  923.  
  924.         DEBUGF 1,"Global reset: "
  925.  
  926. ; GlobalReset
  927.         set_io  0
  928.         set_io  REG_COMMAND
  929.         xor     eax, eax
  930. ;       or      al, 0x14
  931.         out     dx, ax
  932. ; wait for GlobalReset to complete
  933.         mov     ecx, 64000
  934. .loop:
  935.         in      ax , dx
  936.         test    ah , 10000b ; check CmdInProgress
  937. ;        jz      .finish
  938.         loopz   .loop
  939. ;.finish:
  940. ;        DEBUGF 1,"Waiting for nic to boot..\n"
  941. ; wait for 2 seconds for NIC to boot
  942.         mov     esi, 200
  943.         stdcall Sleep ; 2 seconds
  944.  
  945.         DEBUGF 1,"Ok!\n"
  946.  
  947.         ret
  948.  
  949.  
  950.  
  951. ;***************************************************************************
  952. ;   Function
  953. ;      tx_reset
  954. ;   Description
  955. ;      resets and enables transmitter engine
  956. ;
  957. ;***************************************************************************
  958.  
  959. align 4
  960. tx_reset:
  961.         DEBUGF 1,"tx reset\n"
  962.  
  963. ; TxReset
  964.         set_io  0
  965.         set_io  REG_COMMAND
  966.         mov     ax, TxReset
  967.         out     dx, ax
  968. ; Wait for TxReset to complete
  969.         mov     ecx, 200000
  970. .tx_reset_loop:
  971.         in      ax, dx
  972.         test    ah, 10000b ; check CmdInProgress
  973.         jz      .tx_set_prev
  974.         dec     ecx
  975.         jnz     .tx_reset_loop
  976. .tx_set_prev:
  977. ; init last_dpd
  978.         mov     eax, [device.dpd_buffer]
  979.         add     eax, (NUM_TX_DESC-1)*dpd.size
  980.         mov     [device.prev_dpd], eax
  981.  
  982.         mov     eax, [device.tx_buffer]
  983.         add     eax, (NUM_TX_DESC-1)*MAX_ETH_FRAME_SIZE
  984.         mov     [device.prev_tx_frame], eax
  985. .tx_enable:
  986.         ret
  987.  
  988.  
  989.  
  990. ;***************************************************************************
  991. ;   Function
  992. ;      rx_reset
  993. ;   Description
  994. ;      resets and enables receiver engine
  995. ;
  996. ;***************************************************************************
  997.  
  998. align 4
  999. rx_reset:
  1000.  
  1001.         DEBUGF 1,"rx reset\n"
  1002.  
  1003.         set_io  0
  1004.         set_io  REG_COMMAND
  1005.         mov     ax, RxReset or 0x4
  1006.         out     dx, ax
  1007. ; wait for RxReset to complete
  1008.         mov     ecx, 200000
  1009. .rx_reset_loop:
  1010.         in      ax, dx
  1011.         test    ah, 10000b ; check CmdInProgress
  1012.         dec     ecx
  1013.         jnz     .rx_reset_loop
  1014. ; create upd ring
  1015.  
  1016.         mov     eax, [device.upd_buffer]
  1017.         mov     [device.curr_upd], eax
  1018.         call    GetPgAddr
  1019.         mov     esi, eax
  1020.  
  1021.         mov     eax, [device.rx_buffer]
  1022.         call    GetPgAddr
  1023.         mov     edi, eax
  1024.  
  1025.         mov     edx, [device.upd_buffer]
  1026.         add     edx, (NUM_RX_DESC-1)*upd.size
  1027.  
  1028.         mov     eax, [device.upd_buffer]
  1029.  
  1030.         push    ebx
  1031.         mov     ebx, [device.rx_buffer]
  1032.  
  1033.         mov     ecx, NUM_RX_DESC
  1034. .upd_loop:
  1035.         mov     [edx + upd.next_ptr], esi                               ; edx = upd buff
  1036.  
  1037.         and     [eax + upd.pkt_status], 0                               ; eax = next upd buff
  1038.         mov     [eax + upd.frag_addr], edi
  1039.         mov     [eax + upd.frag_len], MAX_ETH_FRAME_SIZE or (1 shl 31)
  1040.         mov     [eax + upd.realaddr], ebx
  1041.  
  1042.         add     edi, MAX_ETH_FRAME_SIZE
  1043.         add     ebx, MAX_ETH_FRAME_SIZE
  1044.         add     esi, upd.size
  1045.         mov     edx, eax
  1046.         add     eax, upd.size
  1047.  
  1048.         dec     ecx
  1049.         jnz     .upd_loop
  1050.  
  1051.         pop     ebx
  1052.  
  1053.         mov     eax, [device.upd_buffer]
  1054.         call    GetPgAddr
  1055.         set_io  0
  1056.         set_io  REG_UP_LIST_PTR
  1057.         out     dx, eax
  1058.  
  1059. .rx_enable:
  1060.         ret
  1061.  
  1062.  
  1063.  
  1064.  
  1065. ;---------------------------------------------------------------------------
  1066. ;   Function
  1067. ;      try_link_detect
  1068. ;   Description
  1069. ;      try_link_detect checks if link exists
  1070. ;   Parameters
  1071. ;      ebx = device structure
  1072. ;   Return value
  1073. ;      al - 0 ; no link detected
  1074. ;      al - 1 ; link detected
  1075. ;   Destroyed registers
  1076. ;      eax, ebx, ecx, edx, edi, esi
  1077. ;
  1078. ;---------------------------------------------------------------------------
  1079.  
  1080. align 4
  1081. try_link_detect:
  1082.  
  1083.         DEBUGF 1,"trying to detect link\n"
  1084.  
  1085. ; create self-directed packet
  1086.         lea     esi, [device.mac]
  1087.         lea     edi, [device.self_directed_packet]
  1088.         movsw
  1089.         movsd
  1090.         sub     esi, 6
  1091.         movsw
  1092.         movsd
  1093.         mov     ax , 0x0608
  1094.         stosw
  1095.  
  1096. ; download self-directed packet
  1097.         push    20
  1098.         lea     eax, [device.self_directed_packet]
  1099.         push    eax
  1100.         call    [device.transmit]
  1101.  
  1102. ; switch to register window 4
  1103.         set_io  0
  1104.         set_io  REG_COMMAND
  1105.         mov     ax, SELECT_REGISTER_WINDOW+4
  1106.         out     dx, ax
  1107.  
  1108. ; See if we have received the packet by now..
  1109.         cmp     [device.packets_rx], 0
  1110.         jnz     .link_detected
  1111.  
  1112. ; switch to register window 4
  1113.         set_io  REG_COMMAND
  1114.         mov     ax, SELECT_REGISTER_WINDOW+4
  1115.         out     dx, ax
  1116.  
  1117. ; read linkbeatdetect
  1118.         set_io  REG_MEDIA_STATUS
  1119.         in      ax, dx
  1120.         test    ah, 1000b ; test linkBeatDetect
  1121.         jnz     .link_detected
  1122.         xor     al, al
  1123.         jmp     .finish
  1124.  
  1125. .link_detected:
  1126.         setb    al
  1127.  
  1128. .finish:
  1129.         test    al, al
  1130.         jz      @f
  1131.         or      byte [device.mode+1], 100b
  1132. @@:
  1133.         ret
  1134.  
  1135.  
  1136.  
  1137. ;***************************************************************************
  1138. ;   Function
  1139. ;      try_phy
  1140. ;   Description
  1141. ;      try_phy checks the auto-negotiation function
  1142. ;      in the PHY at PHY index. It can also be extended to
  1143. ;      include link detection for non-IEEE 802.3u
  1144. ;      auto-negotiation devices, for instance the BCM5000.
  1145. ;   Parameters
  1146. ;       ah - PHY index
  1147. ;       ebx - device stucture
  1148. ;   Return value
  1149. ;      al - 0 link is auto-negotiated
  1150. ;      al - 1 no link is auto-negotiated
  1151. ;   Destroyed registers
  1152. ;       eax, ebx, ecx, edx, esi
  1153. ;
  1154. ;***************************************************************************
  1155.  
  1156. align 4
  1157. try_phy:
  1158.  
  1159.         DEBUGF 1,"trying phy\n"
  1160.  
  1161.         mov     al, REG_MII_BMCR
  1162.         push    eax
  1163.         call    mdio_read       ; returns with window #4
  1164.         or      ah , 0x80       ; software reset
  1165.         mov     esi, eax
  1166.         mov     eax, dword [esp]
  1167.         call    mdio_write      ; returns with window #4
  1168.  
  1169. ; wait for reset to complete
  1170.         mov     esi, 200
  1171.         stdcall Sleep      ; 2s
  1172.         mov     eax, [esp]
  1173.         call    mdio_read       ; returns with window #4
  1174.         test    ah , 0x80
  1175.         jnz     .fail_finish
  1176.         mov     eax, [esp]
  1177.  
  1178. ; wait for a while after reset
  1179.         mov     esi, 2
  1180.         stdcall Sleep      ; 20ms
  1181.         mov     eax, [esp]
  1182.         mov     al , REG_MII_BMSR
  1183.         call    mdio_read       ; returns with window #4
  1184.         test    al , 1           ; extended capability supported?
  1185.         jz      .no_ext_cap
  1186.  
  1187. ; auto-neg capable?
  1188.         test    al , 1000b
  1189.         jz      .fail_finish    ; not auto-negotiation capable
  1190.  
  1191. ; auto-neg complete?
  1192.         test    al , 100000b
  1193.         jnz     .auto_neg_ok
  1194.  
  1195. ; restart auto-negotiation
  1196.         mov     eax, [esp]
  1197.         mov     al , REG_MII_ANAR
  1198.         push    eax
  1199.         call    mdio_read       ; returns with window #4
  1200.         or      ax , 1111b shl 5; advertise only 10base-T and 100base-TX
  1201.         mov     esi, eax
  1202.         pop     eax
  1203.         call    mdio_write      ; returns with window #4
  1204.         mov     eax, [esp]
  1205.         call    mdio_read       ; returns with window #4
  1206.         mov     esi, eax
  1207.         or      bh , 10010b     ; restart auto-negotiation
  1208.         mov     eax, [esp]
  1209.         call    mdio_write      ; returns with window #4
  1210.         mov     esi, 400
  1211.         stdcall Sleep  ; 4 seconds
  1212.         mov     eax, [esp]
  1213.         mov     al , REG_MII_BMSR
  1214.         call    mdio_read ; returns with window #4
  1215.         test    al , 100000b ; auto-neg complete?
  1216.         jnz     .auto_neg_ok
  1217.         jmp     .fail_finish
  1218. .auto_neg_ok:
  1219.  
  1220. ; compare advertisement and link partner ability registers
  1221.         mov     eax, [esp]
  1222.         mov     al , REG_MII_ANAR
  1223.         call    mdio_read       ; returns with window #4
  1224.         xchg    eax, [esp]
  1225.         mov     al , REG_MII_ANLPAR
  1226.         call    mdio_read       ; returns with window #4
  1227.         pop     esi
  1228.         and     eax, esi
  1229.         and     eax, 1111100000b
  1230.         push    eax
  1231.  
  1232.         mov     word[device.mode+2], ax
  1233.  
  1234. ; switch to register window 3
  1235.         set_io  0
  1236.         set_io  REG_COMMAND
  1237.         mov     ax , SELECT_REGISTER_WINDOW+3
  1238.         out     dx , ax
  1239.  
  1240. ; set full-duplex mode
  1241.         set_io  REG_MAC_CONTROL
  1242.         in      ax , dx
  1243.         and     ax , not 0x120  ; clear full duplex and flow control
  1244.         pop     esi
  1245.         test    esi, 1010b shl 5; check for full-duplex
  1246.         jz      .half_duplex
  1247.         or      ax , 0x120      ; set full duplex and flow control
  1248. .half_duplex:
  1249.         out     dx , ax
  1250.         mov     al , 1
  1251.         ret
  1252. .no_ext_cap:
  1253.  
  1254. ; not yet implemented BCM5000
  1255. .fail_finish:
  1256.         pop     eax
  1257.         xor     al, al
  1258.         ret
  1259.  
  1260.  
  1261.  
  1262. ;***************************************************************************
  1263. ;   Function
  1264. ;      try_mii
  1265. ;   Description
  1266. ;      try_MII checks the on-chip auto-negotiation logic
  1267. ;      or an off-chip MII PHY, depending upon what is set in
  1268. ;      xcvrSelect by the caller.
  1269. ;      It exits when it finds the first device with a good link.
  1270. ;   Parameters
  1271. ;      ebp - io_addr
  1272. ;   Return value
  1273. ;      al - 0
  1274. ;      al - 1
  1275. ;   Destroyed registers
  1276. ;      eax, ebx, ecx, edx, esi
  1277. ;
  1278. ;***************************************************************************
  1279.  
  1280. align 4
  1281. try_mii:
  1282.  
  1283.         DEBUGF 1,"trying mii\n"
  1284.  
  1285. ; switch to register window 3
  1286.         set_io  0
  1287.         set_io  REG_COMMAND
  1288.         mov     ax, SELECT_REGISTER_WINDOW+3
  1289.         out     dx, ax
  1290.         set_io  REG_INTERNAL_CONFIG
  1291.         in      eax, dx
  1292.         and     eax, (1111b shl 20)
  1293.         cmp     eax, (1000b shl 20) ; is auto-negotiation set?
  1294.         jne     .mii_device
  1295. ; auto-negotiation is set
  1296. ; switch to register window 4
  1297.         set_io  REG_COMMAND
  1298.         mov     ax , SELECT_REGISTER_WINDOW+4
  1299.         out     dx , ax
  1300. ; PHY==24 is the on-chip auto-negotiation logic
  1301. ; it supports only 10base-T and 100base-TX
  1302.         mov     ah , 24
  1303.         call    try_phy
  1304.         test    al , al
  1305.         jz      .fail_finish
  1306.         mov     cl , 24
  1307.         jmp     .check_preamble
  1308. .mii_device:
  1309.         cmp     eax, (0110b shl 20)
  1310.         jne     .fail_finish
  1311.         set_io  0
  1312.         set_io  REG_COMMAND
  1313.         mov     ax , SELECT_REGISTER_WINDOW+4
  1314.         out     dx , ax
  1315.         set_io  REG_PHYSICAL_MGMT
  1316.         in      ax , dx
  1317.         and     al , (1 shl BIT_MGMT_DIR) or (1 shl BIT_MGMT_DATA)
  1318.         cmp     al , (1 shl BIT_MGMT_DATA)
  1319.         je      .search_for_phy
  1320.         xor     al , al
  1321.         ret
  1322. .search_for_phy:
  1323. ; search for PHY
  1324.         mov     cx , 31
  1325. .search_phy_loop:
  1326.         cmp     cx , 24
  1327.         je      .next_phy
  1328.         mov     ah , cl ; ah = phy
  1329.         mov     al , REG_MII_BMCR ; al = Basic Mode Status Register
  1330.         push    cx
  1331.         call    mdio_read
  1332.         pop     cx
  1333.         test    ax , ax
  1334.         jz      .next_phy
  1335.         cmp     ax , 0xffff
  1336.         je      .next_phy
  1337.         mov     ah , cl ; ah = phy
  1338.         push    cx
  1339.         call    try_phy
  1340.         pop     cx
  1341.         test    al , al
  1342.         jnz     .check_preamble
  1343. .next_phy:
  1344.         loopw   .search_phy_loop
  1345. .fail_finish:
  1346.         xor     al, al
  1347.         ret
  1348. ; epilog
  1349. .check_preamble:
  1350.         push    eax ; eax contains the return value of try_phy
  1351. ; check hard coded preamble forcing
  1352.         movzx   eax, [device.ver_id]
  1353.         test    word [eax*4+hw_versions+2], EXTRA_PREAMBLE
  1354.         setnz   [device.preamble] ; force preamble
  1355.         jnz     .finish
  1356. ; check mii for preamble suppression
  1357.         mov     ah, cl
  1358.         mov     al, REG_MII_BMSR
  1359.         call    mdio_read
  1360.         test    al, 1000000b ; preamble suppression?
  1361.         setz    [device.preamble] ; no
  1362. .finish:
  1363.         pop     eax
  1364.         ret
  1365.  
  1366.  
  1367.  
  1368. ;***************************************************************************
  1369. ;   Function
  1370. ;      test_packet
  1371. ;   Description
  1372. ;      try_loopback try a loopback packet for 10BASE2 or AUI port
  1373. ;   Parameters
  1374. ;      ebx = device structure
  1375. ;
  1376. ;***************************************************************************
  1377.  
  1378. align 4
  1379. test_packet:
  1380.  
  1381.         DEBUGF 1,"sending test packet\n"
  1382.  
  1383. ; switch to register window 3
  1384.         set_io  0
  1385.         set_io  REG_COMMAND
  1386.         mov     ax, SELECT_REGISTER_WINDOW+3
  1387.         out     dx, ax
  1388.  
  1389. ; set fullDuplexEnable in MacControl register
  1390.         set_io  REG_MAC_CONTROL
  1391.         in      ax, dx
  1392.         or      ax, 0x120
  1393.         out     dx, ax
  1394.  
  1395. ; switch to register window 5
  1396.         set_io  REG_COMMAND
  1397.         mov     ax, SELECT_REGISTER_WINDOW+5
  1398.         out     dx, ax
  1399.  
  1400. ; set RxFilter to enable individual address matches
  1401.         mov     ax, (10000b shl 11)
  1402.         set_io  REG_RX_FILTER
  1403.         in      al, dx
  1404.         or      al, 1
  1405.         set_io  REG_COMMAND
  1406.         out     dx, ax
  1407.  
  1408. ; issue RxEnable and TxEnable
  1409.         call    rx_reset
  1410.         call    tx_reset
  1411.  
  1412. ; download a self-directed test packet
  1413.         lea     esi, [device.mac]
  1414.         lea     edi, [device.self_directed_packet]
  1415.         movsw
  1416.         movsd
  1417.         sub     esi, 6
  1418.         movsw
  1419.         movsd
  1420.         mov     ax , 0x0608
  1421.         stosw
  1422.  
  1423.         push    20
  1424.         lea     eax, [device.self_directed_packet]
  1425.         push    eax
  1426.         call    [device.transmit]
  1427.  
  1428. ; wait for 2s
  1429.         mov     esi, 200
  1430.         stdcall Sleep    ; 2s
  1431.  
  1432. ; check if self-directed packet is received
  1433.         mov     eax, [device.packets_rx]
  1434.         test    eax, eax
  1435.         jnz     .finish
  1436.  
  1437. ; switch to register window 3
  1438.         set_io  0
  1439.         set_io  REG_COMMAND
  1440.         mov     ax, SELECT_REGISTER_WINDOW+3
  1441.         out     dx, ax
  1442.  
  1443. ; clear fullDuplexEnable in MacControl register
  1444.         set_io  REG_MAC_CONTROL
  1445.         in      ax , dx
  1446.         and     ax , not 0x120
  1447.         out     dx , ax
  1448.         xor     eax, eax
  1449.  
  1450. .finish:
  1451.         ret
  1452.  
  1453.  
  1454.  
  1455. ;***************************************************************************
  1456. ;   Function
  1457. ;      try_loopback
  1458. ;   Description
  1459. ;      tries a loopback packet for 10BASE2 or AUI port
  1460. ;   Parameters
  1461. ;      al -  0: 10Mbps AUI connector
  1462. ;            1: 10BASE-2
  1463. ;      ebp - io_addr
  1464. ;   Return value
  1465. ;      al - 0
  1466. ;      al - 1
  1467. ;   Destroyed registers
  1468. ;      eax, ebx, ecx, edx, edi, esi
  1469. ;
  1470. ;***************************************************************************
  1471.  
  1472. align 4
  1473. try_loopback:
  1474.  
  1475.         DEBUGF 1,"trying loopback\n"
  1476.  
  1477.         push    eax
  1478. ; switch to register window 3
  1479.         set_io  0
  1480.         set_io  REG_COMMAND
  1481.         mov     ax, SELECT_REGISTER_WINDOW+3
  1482.         out     dx, ax
  1483.         mov     eax, [esp]
  1484.  
  1485.         mov     cl, al
  1486.         inc     cl
  1487.         shl     cl, 3
  1488.         or      byte [device.mode+1], cl
  1489.  
  1490.         test    al, al ; aui or coax?
  1491.         jz      .complete_loopback
  1492. ; enable 100BASE-2 DC-DC converter
  1493.         mov     ax, (10b shl 11) ; EnableDcConverter
  1494.         out     dx, ax
  1495. .complete_loopback:
  1496.         mov     cx, 2 ; give a port 3 chances to complete a loopback
  1497. .next_try:
  1498.         push    ecx
  1499.         call    test_packet
  1500.         pop     ecx
  1501.         test    eax, eax
  1502.         loopzw  .next_try
  1503. .finish:
  1504.         xchg    eax, [esp]
  1505.         test    al, al
  1506.         jz      .aui_finish
  1507. ; issue DisableDcConverter command
  1508.         set_io  0
  1509.         set_io  REG_COMMAND
  1510.         mov     ax, (10111b shl 11)
  1511.         out     dx, ax
  1512. .aui_finish:
  1513.         pop     eax ; al contains the result of operation
  1514.  
  1515.         test    al, al
  1516.         jnz     @f
  1517.         and     byte [device.mode+1], not 11000b
  1518. @@:
  1519.  
  1520.         ret
  1521.  
  1522.  
  1523. ;***************************************************************************
  1524. ;   Function
  1525. ;      set_active_port
  1526. ;   Description
  1527. ;      It selects the media port (transceiver) to be used
  1528. ;   Return value:
  1529. ;   Destroyed registers
  1530. ;      eax, ebx, ecx, edx, edi, esi
  1531. ;
  1532. ;***************************************************************************
  1533.  
  1534. align 4
  1535. set_active_port:
  1536.  
  1537.         DEBUGF 1,"Setting active port: "
  1538.  
  1539. ; switch to register window 3
  1540.         set_io  0
  1541.         set_io  REG_COMMAND
  1542.         mov     ax, SELECT_REGISTER_WINDOW+3
  1543.         out     dx, ax
  1544.         set_io  REG_INTERNAL_CONFIG
  1545.         in      eax, dx
  1546.         test    eax, (1 shl 24) ; check if autoselect enable
  1547.         jz      .set_first_available_media
  1548.  
  1549. ; check 100BASE-TX and 10BASE-T
  1550.         set_io  REG_MEDIA_OPTIONS
  1551.         in      ax, dx
  1552.         test    al, 1010b       ; check whether 100BASE-TX or 10BASE-T available
  1553.         jz      .mii_device     ; they are not available
  1554.  
  1555. ; set auto-negotiation
  1556.         set_io  REG_INTERNAL_CONFIG
  1557.         in      eax, dx
  1558.         and     eax, not (1111b shl 20)
  1559.         or      eax, (1000b shl 20)
  1560.         out     dx, eax
  1561.         call    try_mii
  1562.         test    al, al
  1563.         jz      .mii_device
  1564.         DEBUGF 1,"Using auto negotiation\n"
  1565.         ret
  1566. .mii_device:
  1567.  
  1568. ; switch to register window 3
  1569.         set_io  0
  1570.         set_io  REG_COMMAND
  1571.         mov     ax, SELECT_REGISTER_WINDOW+3
  1572.         out     dx, ax
  1573.  
  1574. ; check for off-chip mii device
  1575.         set_io  REG_MEDIA_OPTIONS
  1576.         in      ax, dx
  1577.         test    al, 1000000b ; check miiDevice
  1578.         jz      .base_fx
  1579.         set_io  REG_INTERNAL_CONFIG
  1580.         in      eax, dx
  1581.         and     eax, not (1111b shl 20)
  1582.         or      eax, (0110b shl 20) ; set MIIDevice
  1583.         out     dx, eax
  1584.         call    try_mii
  1585.         test    al, al
  1586.         jz      .base_fx
  1587.         DEBUGF 1,"Using off-chip mii device\n"
  1588.         ret
  1589. .base_fx:
  1590.  
  1591. ; switch to register window 3
  1592.         set_io  0
  1593.         set_io  REG_COMMAND
  1594.         mov     ax, SELECT_REGISTER_WINDOW+3
  1595.         out     dx, ax
  1596. ; check for 100BASE-FX
  1597.         set_io  REG_MEDIA_OPTIONS
  1598.         in      ax, dx ; read media option register
  1599.         test    al, 100b ; check 100BASE-FX
  1600.         jz      .aui_enable
  1601.         set_io  REG_INTERNAL_CONFIG
  1602.         in      eax, dx
  1603.         and     eax, not (1111b shl 20)
  1604.         or      eax, (0101b shl 20) ; set 100base-FX
  1605.         out     dx, eax
  1606.         call    try_link_detect
  1607.         test    al, al
  1608.         jz      .aui_enable
  1609.         DEBUGF 1,"Using 100Base-FX\n"
  1610.         ret
  1611. .aui_enable:
  1612.  
  1613. ; switch to register window 3
  1614.         set_io  0
  1615.         set_io  REG_COMMAND
  1616.         mov     ax, SELECT_REGISTER_WINDOW+3
  1617.         out     dx, ax
  1618. ; check for 10Mbps AUI connector
  1619.         set_io  REG_MEDIA_OPTIONS
  1620.         in      ax, dx ; read media option register
  1621.         test    al, 100000b ; check 10Mbps AUI connector
  1622.         jz      .coax_available
  1623.         set_io  REG_INTERNAL_CONFIG
  1624.         in      eax, dx
  1625.         and     eax, not (1111b shl 20)
  1626.         or      eax, (0001b shl 20) ; set 10Mbps AUI connector
  1627.         out     dx, eax
  1628.         xor     al, al ; try 10Mbps AUI connector
  1629.         call    try_loopback
  1630.         test    al, al
  1631.         jz      .coax_available
  1632.         DEBUGF 1,"Using 10Mbps aui\n"
  1633.         ret
  1634. .coax_available:
  1635.  
  1636. ; switch to register window 3
  1637.         set_io  0
  1638.         set_io  REG_COMMAND
  1639.         mov     ax, SELECT_REGISTER_WINDOW+3
  1640.         out     dx, ax
  1641. ; check for coaxial 10BASE-2 port
  1642.         set_io  REG_MEDIA_OPTIONS
  1643.         in      ax, dx ; read media option register
  1644.         test    al, 10000b ; check 10BASE-2
  1645.         jz      .set_first_available_media
  1646.         set_io  REG_INTERNAL_CONFIG
  1647.         in      eax, dx
  1648.         and     eax, not (1111b shl 20)
  1649.         or      eax, (0011b shl 20) ; set 10BASE-2
  1650.         out     dx, eax
  1651.         mov     al, 1
  1652.         call    try_loopback
  1653.         test    al, al
  1654.         jz      .set_first_available_media
  1655.         DEBUGF 1,"Using 10BASE-2 port\n"
  1656.         ret
  1657. .set_first_available_media:
  1658.  
  1659.  
  1660. ;***************************************************************************
  1661. ;   Function
  1662. ;      set_available_media
  1663. ;   Description
  1664. ;      sets the first available media
  1665. ;   Parameters
  1666. ;      ebp - io_addr
  1667. ;   Return value
  1668. ;      al - 0
  1669. ;      al - 1
  1670. ;   Destroyed registers
  1671. ;      eax, edx
  1672. ;
  1673. ;***************************************************************************
  1674.  
  1675. align 4
  1676. set_available_media:
  1677.  
  1678.         DEBUGF 1,"Using the first available media\n"
  1679.  
  1680. ; switch to register window 3
  1681.         set_io  0
  1682.         set_io  REG_COMMAND
  1683.         mov     ax, SELECT_REGISTER_WINDOW+3
  1684.         out     dx, ax
  1685.         set_io  REG_INTERNAL_CONFIG
  1686.         in      eax, dx
  1687.         push    eax
  1688.         set_io  REG_MEDIA_OPTIONS
  1689.         in      ax, dx
  1690.         test    al, 10b
  1691.         jz      @f
  1692. ; baseTXAvailable
  1693.         pop     eax
  1694.         and     eax, not (1111b shl 20)
  1695.         or      eax, (100b shl 20)
  1696. if defined FORCE_FD
  1697.         mov     word [device.mode], (1 shl 8)
  1698. else
  1699.         mov     word [device.mode], (1 shl 7)
  1700. end if
  1701.         jmp     .set_media
  1702. @@:
  1703.         test    al, 100b
  1704.         jz      @f
  1705. ; baseFXAvailable
  1706.         pop     eax
  1707.         and     eax, not (1111b shl 20)
  1708.         or      eax, (101b shl 20)
  1709.  
  1710.         mov     word [device.mode], (1 shl 10)
  1711.  
  1712.         jmp     .set_media
  1713. @@:
  1714.         test    al, 1000000b
  1715.         jz      @f
  1716. ; miiDevice
  1717.         pop     eax
  1718.         and     eax, not (1111b shl 20)
  1719.         or      eax, (0110b shl 20)
  1720.  
  1721.         mov     word [device.mode], (1 shl 13)
  1722.  
  1723.         jmp     .set_media
  1724. @@:
  1725.         test    al, 1000b
  1726.         jz      @f
  1727. .set_default:
  1728. ; 10bTAvailable
  1729.         pop     eax
  1730.         and     eax, not (1111b shl 20)
  1731. if FORCE_FD
  1732.         mov     word [device.mode], (1 shl 6)
  1733. else
  1734.         mov     word [device.mode], (1 shl 5)
  1735. end if ; FORCE_FD
  1736.         jmp     .set_media
  1737. @@:
  1738.         test    al, 10000b
  1739.         jz      @f
  1740. ; coaxAvailable
  1741.         set_io  REG_COMMAND
  1742.         mov     ax, (10b shl 11) ; EnableDcConverter
  1743.         out     dx, ax
  1744.         pop     eax
  1745.         and     eax, not (1111b shl 20)
  1746.         or      eax, (11b shl 20)
  1747.  
  1748.         mov     word [device.mode], (1 shl 12)
  1749.  
  1750.         jmp     .set_media
  1751. @@:
  1752.         test    al, 10000b
  1753.         jz      .set_default
  1754. ; auiAvailable
  1755.         pop     eax
  1756.         and     eax, not (1111b shl 20)
  1757.         or      eax, (1 shl 20)
  1758.  
  1759.         mov     word [device.mode], (1 shl 11)
  1760.  
  1761. .set_media:
  1762.         set_io  REG_INTERNAL_CONFIG
  1763.         out     dx, eax
  1764. if FORCE_FD
  1765. ; set fullDuplexEnable in MacControl register
  1766.         set_io  REG_MAC_CONTROL
  1767.         in      ax, dx
  1768.         or      ax, 0x120
  1769.         out     dx, ax
  1770. end if ; FORCE_FD
  1771.         mov     al, 1
  1772.  
  1773.         ret
  1774.  
  1775.  
  1776.  
  1777. ;***************************************************************************
  1778. ;   Function
  1779. ;      wake_up
  1780. ;   Description
  1781. ;      set the power state to D0
  1782. ;
  1783. ;***************************************************************************
  1784.  
  1785. align 4
  1786. wake_up:
  1787.  
  1788.         DEBUGF 1,"Waking up NIC: "
  1789.  
  1790. ; wake up - we directly do it by programming PCI
  1791. ; check if the device is power management capable
  1792.         movzx   ecx, [device.pci_bus]
  1793.         movzx   edx, [device.pci_dev]
  1794.         stdcall PciRead32, ecx, edx, PCI_REG_STATUS
  1795.  
  1796.         test    al, 10000b      ; is there "new capabilities" linked list?
  1797.         jz      .device_awake
  1798.  
  1799.         DEBUGF 1,"1 "
  1800.  
  1801. ; search for power management register
  1802.         stdcall PciRead16, ecx, edx, PCI_REG_CAP_PTR
  1803.         cmp     al, 0x3f
  1804.         jbe     .device_awake
  1805.  
  1806.         DEBUGF 1,"2 "
  1807.  
  1808. ; traverse the list
  1809.         movzx   esi, al
  1810. .pm_loop:
  1811.         stdcall PciRead32, ecx, edx, esi
  1812.  
  1813.         cmp     al , 1
  1814.         je      .set_pm_state
  1815.  
  1816.         movzx   esi, ah
  1817.  
  1818.         test    ah , ah
  1819.         jnz     .pm_loop
  1820.         jmp     .device_awake
  1821.  
  1822. ; waku up the device if necessary
  1823. .set_pm_state:
  1824.  
  1825.         DEBUGF 1,"3 "
  1826.  
  1827.         add     esi, PCI_REG_PM_CTRL
  1828.         stdcall PciRead32, ecx, edx, esi
  1829.         test    al, 3
  1830.         jz      .device_awake
  1831.         and     al, not 11b ; set state to D0
  1832.         stdcall PciWrite32, ecx, edx, esi, eax
  1833. .device_awake:
  1834.  
  1835.         DEBUGF 1,"Device is awake\n"
  1836.  
  1837.         ret
  1838.  
  1839.  
  1840.  
  1841.  
  1842. ;***************************************************************************
  1843. ;   Function
  1844. ;      write_eeprom
  1845. ;   Description
  1846. ;      reads eeprom
  1847. ;      Note : the caller must switch to the register window 0
  1848. ;             before calling this function
  1849. ;   Parameters:
  1850. ;      ax - register to be read (only the first 63 words can be read)
  1851. ;      cx - value to be read into the register
  1852. ;   Return value:
  1853. ;      ax - word read
  1854. ;   Destroyed registers
  1855. ;      ax, ebx, edx
  1856. ;
  1857. ;***************************************************************************
  1858. ;       align 4
  1859. ;write_eeprom:
  1860. ;       mov     edx, [io_addr]
  1861. ;       add     edx, REG_EEPROM_COMMAND
  1862. ;       cmp     ah, 11b
  1863. ;       ja      .finish ; address may have a value of maximal 1023
  1864. ;       shl     ax, 2
  1865. ;       shr     al, 2
  1866. ;       push    eax
  1867. ;; wait for busy
  1868. ;       mov     ebx, 0xffff
  1869. ;@@:
  1870. ;       in      ax, dx
  1871. ;       test    ah, 0x80
  1872. ;       jz      .write_enable
  1873. ;       dec     ebx
  1874. ;       jns     @r
  1875. ;; write enable
  1876. ;.write_enable:
  1877. ;       xor     eax, eax
  1878. ;       mov     eax, (11b shl 4)
  1879. ;       out     dx, ax
  1880. ;; wait for busy
  1881. ;       mov     ebx, 0xffff
  1882. ;@@:
  1883. ;       in      ax, dx
  1884. ;       test    ah, 0x80
  1885. ;       jz      .erase_loop
  1886. ;       dec     ebx
  1887. ;       jns     @r
  1888. ;.erase_loop:
  1889. ;       pop     eax
  1890. ;       push    eax
  1891. ;       or      ax, (11b shl 6) ; erase register
  1892. ;       out     dx, ax
  1893. ;       mov     ebx, 0xffff
  1894. ;@@:
  1895. ;       in      ax, dx
  1896. ;       test    ah, 0x80
  1897. ;       jz      .write_reg
  1898. ;       dec     ebx
  1899. ;       jns     @r
  1900. ;.write_reg:
  1901. ;       add     edx, REG_EEPROM_DATA-REG_EEPROM_COMMAND
  1902. ;       mov     eax, ecx
  1903. ;       out     dx, ax
  1904. ;; write enable
  1905. ;       add     edx, REG_EEPROM_COMMAND-REG_EEPROM_DATA
  1906. ;       xor     eax, eax
  1907. ;       mov     eax, (11b shl 4)
  1908. ;       out     dx, ax
  1909. ; wait for busy
  1910. ;       mov     ebx, 0xffff
  1911. ;@@:
  1912. ;       in      ax, dx
  1913. ;       test    ah, 0x80
  1914. ;       jz      .issue_write_reg
  1915. ;       dec     ebx
  1916. ;       jns     @r
  1917. ;.issue_write_reg:
  1918. ;       pop     eax
  1919. ;       or      ax, 01b shl 6
  1920. ;       out     dx, ax
  1921. ;.finish:
  1922. ;       ret
  1923. ;***************************************************************************
  1924. ;   Function
  1925. ;      read_eeprom
  1926. ;   Description
  1927. ;      reads eeprom
  1928. ;   Parameters:
  1929. ;       ax - register to be read (only the first 63 words can be read)
  1930. ;      ebx = driver structure
  1931. ;   Return value:
  1932. ;      ax - word read
  1933. ;   Destroyed registers
  1934. ;      ax, ebx, edx, ebp
  1935. ;
  1936. ;***************************************************************************
  1937.  
  1938. align 4
  1939. read_eeprom:
  1940.  
  1941.         DEBUGF 1,"Reading from eeprom:\n"
  1942.  
  1943.         push    eax
  1944. ; switch to register window 0
  1945.         set_io  0
  1946.         set_io  REG_COMMAND
  1947.         mov     ax, SELECT_REGISTER_WINDOW+0
  1948.         out     dx, ax
  1949.         pop     eax
  1950.         and     ax, 111111b ; take only the first 6 bits into account
  1951.         movzx   esi, [device.ver_id]
  1952.  
  1953.         test    word [esi*4+hw_versions+2], EEPROM_8BIT
  1954.         jz      @f
  1955.         add     ax, 0x230 ; hardware constant
  1956.         jmp     .read
  1957. @@:
  1958.  
  1959.         add     ax, EEPROM_CMD_READ
  1960.         test    word [esi*4+hw_versions+2], EEPROM_OFFSET
  1961.         jz      .read
  1962.         add     ax, 0x30
  1963. .read:
  1964.  
  1965.         set_io  REG_EEPROM_COMMAND
  1966.         out     dx, ax
  1967.         mov     ecx, 0xffff ; duration of about 162 us ;-)
  1968. .wait_for_reading:
  1969.         in      ax, dx
  1970.         test    ah, 0x80 ; check bit eepromBusy
  1971.         jz      .read_data
  1972.         loop    .wait_for_reading
  1973. .read_data:
  1974.         set_io  REG_EEPROM_DATA
  1975.         in      ax, dx
  1976.  
  1977.         DEBUGF 1,"ok!\n"
  1978.  
  1979.         ret
  1980.  
  1981. ;***************************************************************************
  1982. ;   Function
  1983. ;      mdio_sync
  1984. ;   Description
  1985. ;      initial synchronization
  1986. ;   Parameters
  1987. ;      ebp - io_addr
  1988. ;   Return value
  1989. ;   Destroyed registers
  1990. ;      ax, edx, cl
  1991. ;
  1992. ;***************************************************************************
  1993.  
  1994. align 4
  1995. mdio_sync:
  1996.  
  1997.         DEBUGF 1,"syncing mdio\n"
  1998.  
  1999. ; switch to register window 4
  2000.         set_io  0
  2001.         set_io  REG_COMMAND
  2002.         mov     ax, SELECT_REGISTER_WINDOW+4
  2003.         out     dx, ax
  2004.         cmp     [device.preamble], 0
  2005.         je      .no_preamble
  2006. ; send 32 logic ones
  2007.         set_io  REG_PHYSICAL_MGMT
  2008.         mov     ecx, 31
  2009. .loop:
  2010.         mov     ax, (1 shl BIT_MGMT_DATA) or (1 shl BIT_MGMT_DIR)
  2011.         out     dx, ax
  2012.         in      ax, dx ; delay
  2013.         mov     ax, (1 shl BIT_MGMT_DATA) or (1 shl BIT_MGMT_DIR) or (1 shl BIT_MGMT_CLK)
  2014.         out     dx, ax
  2015.         in      ax, dx ; delay
  2016.         loop    .loop
  2017. .no_preamble:
  2018.  
  2019.         ret
  2020.  
  2021. ;***************************************************************************
  2022. ;   Function
  2023. ;      mdio_read
  2024. ;   Description
  2025. ;      read MII register
  2026. ;      see page 16 in D83840A.pdf
  2027. ;   Parameters
  2028. ;       ah - PHY addr
  2029. ;       al - register addr
  2030. ;      ebx = device structure
  2031. ;   Return value
  2032. ;      ax - register read
  2033. ;
  2034. ;***************************************************************************
  2035.  
  2036. align 4
  2037. mdio_read:
  2038.  
  2039.         DEBUGF 1,"reading MII registers\n"
  2040.  
  2041.         push    eax
  2042.         call    mdio_sync ; returns with window #4
  2043.         pop     eax
  2044.         set_io  0
  2045.         set_io  REG_PHYSICAL_MGMT
  2046.         shl     al, 3
  2047.         shr     ax, 3
  2048.         and     ax, not MII_CMD_MASK
  2049.         or      ax, MII_CMD_READ
  2050.  
  2051.         mov     esi, eax
  2052.         mov     ecx, 13
  2053. .cmd_loop:
  2054.         mov     ax, (1 shl BIT_MGMT_DIR) ; write mii
  2055.         bt      esi, ecx
  2056.         jnc     .zero_bit
  2057.         or      al, (1 shl BIT_MGMT_DATA)
  2058.  
  2059. .zero_bit:
  2060.         out     dx, ax
  2061.         push    ax
  2062.         in      ax, dx ; delay
  2063.         pop     ax
  2064.         or      al, (1 shl BIT_MGMT_CLK) ; write
  2065.         out     dx, ax
  2066.         in      ax, dx ; delay
  2067.         loop    .cmd_loop
  2068.  
  2069. ; read data (18 bits with the two transition bits)
  2070.         mov     ecx, 17
  2071.         xor     esi, esi
  2072. .read_loop:
  2073.         shl     esi, 1
  2074.         xor     eax, eax ; read comand
  2075.         out     dx, ax
  2076.         in      ax, dx ; delay
  2077.         in      ax, dx
  2078.         test    al, (1 shl BIT_MGMT_DATA)
  2079.         jz      .dont_set
  2080.         inc     esi
  2081. .dont_set:
  2082.         mov     ax, (1 shl BIT_MGMT_CLK)
  2083.         out     dx, ax
  2084.         in      ax, dx ; delay
  2085.         loop    .read_loop
  2086.         mov     eax, esi
  2087.  
  2088.         ret
  2089.  
  2090.  
  2091.  
  2092. ;***************************************************************************
  2093. ;   Function
  2094. ;      mdio_write
  2095. ;   Description
  2096. ;      write MII register
  2097. ;      see page 16 in D83840A.pdf
  2098. ;   Parameters
  2099. ;       ah - PHY addr
  2100. ;       al - register addr
  2101. ;       si - word to be written
  2102. ;   Return value
  2103. ;      ax - register read
  2104. ;
  2105. ;***************************************************************************
  2106.  
  2107. align 4
  2108. mdio_write:
  2109.  
  2110.         DEBUGF 1,"Writing MII registers\n"
  2111.  
  2112.         push    eax
  2113.         call    mdio_sync
  2114.         pop     eax
  2115.         set_io  0
  2116.         set_io  REG_PHYSICAL_MGMT
  2117.         shl     al, 3
  2118.         shr     ax, 3
  2119.         and     ax, not MII_CMD_MASK
  2120.         or      ax, MII_CMD_WRITE
  2121.         shl     eax, 2
  2122.         or      eax, 10b ; transition bits
  2123.         shl     eax, 16
  2124.         mov     ax, si
  2125.         mov     esi, eax
  2126.         mov     ecx, 31
  2127. .cmd_loop:
  2128.         mov     ax, (1 shl BIT_MGMT_DIR) ; write mii
  2129.         bt      esi, ecx
  2130.         jnc     .zero_bit
  2131.         or      al, (1 shl BIT_MGMT_DATA)
  2132. .zero_bit:
  2133.         out     dx, ax
  2134.         push    eax
  2135.         in      ax, dx ; delay
  2136.         pop     eax
  2137.         or      al, (1 shl BIT_MGMT_CLK) ; write
  2138.         out     dx, ax
  2139.         in      ax, dx ; delay
  2140.         loop    .cmd_loop
  2141.  
  2142.         ret
  2143.  
  2144.  
  2145. ;***************************************************************************
  2146. ;   Function
  2147. ;      check_tx_status
  2148. ;   Description
  2149. ;      Checks TxStatus queue.
  2150. ;   Return value
  2151. ;      al - 0 no error was found
  2152. ;      al - 1 error was found TxReset is needed
  2153. ;   Destroyed registers
  2154. ;      eax, ecx, edx, ebp
  2155. ;
  2156. ;***************************************************************************
  2157.  
  2158. align 4
  2159. check_tx_status:
  2160.  
  2161.         DEBUGF 1,"Checking TX status\n"
  2162.  
  2163. ; clear TxStatus queue
  2164.         set_io  0
  2165.         set_io  REG_TX_STATUS
  2166.         mov     ecx, 31 ; max number of queue entries
  2167. .tx_status_loop:
  2168.         in      al, dx
  2169.         test    al, al
  2170.         jz      .finish ; no error
  2171.         test    al, 0x3f
  2172.         jnz     .finish ; error
  2173. .no_error_found:
  2174. ; clear current TxStatus entry which advances the next one
  2175.         xor     al, al
  2176.         out     dx, al
  2177.         loop    .tx_status_loop
  2178. .finish:
  2179.  
  2180.         ret
  2181.  
  2182.  
  2183.  
  2184. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2185. ;;                                         ;;
  2186. ;; Transmit (vortex)                       ;;
  2187. ;;                                         ;;
  2188. ;; In: buffer pointer in [esp+4]           ;;
  2189. ;;     size of buffer in [esp+8]           ;;
  2190. ;;     pointer to device structure in ebx  ;;
  2191. ;;                                         ;;
  2192. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2193.  
  2194. align 4
  2195. vortex_transmit:
  2196.  
  2197.         DEBUGF 1,"Sending packet (vortex)\n"
  2198.  
  2199.         cmp     dword [esp+8], MAX_ETH_FRAME_SIZE
  2200.         ja      .finish ; packet is too long
  2201.  
  2202.         call    check_tx_status
  2203.         test    al, al
  2204.         jnz     tx_reset
  2205.  
  2206. ; switch to register window 7
  2207.         set_io  0
  2208.         set_io  REG_COMMAND
  2209.         mov     ax, SELECT_REGISTER_WINDOW+7
  2210.         out     dx, ax
  2211. ; check for master operation in progress
  2212.         set_io  REG_MASTER_STATUS
  2213.         in      ax, dx
  2214.         test    ah, 0x80
  2215.         jnz     .finish ; no DMA for sending
  2216. ; program frame address to be sent
  2217.         set_io  REG_MASTER_ADDRESS
  2218.         mov     eax, [esp+4]
  2219.         call    GetPgAddr
  2220.         out     dx, eax
  2221. ; program frame length
  2222.         set_io  REG_MASTER_LEN
  2223.         mov     eax, [esp+8]
  2224. ;;;        and     eax, not 3
  2225.         out     dx, ax
  2226. ; start DMA Down
  2227.         set_io  REG_COMMAND
  2228.         mov     ax, (10100b shl 11) + 1 ; StartDMADown
  2229.         out     dx, ax
  2230. .finish:
  2231.         ret
  2232.  
  2233.  
  2234.  
  2235. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2236. ;;                                         ;;
  2237. ;; Transmit (boomerang)                    ;;
  2238. ;;                                         ;;
  2239. ;; In: buffer pointer in [esp+4]           ;;
  2240. ;;     size of buffer in [esp+8]           ;;
  2241. ;;     pointer to device structure in ebx  ;;
  2242. ;;                                         ;;
  2243. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2244.  
  2245. align 4
  2246. boomerang_transmit:
  2247.  
  2248.         DEBUGF  1,"Sending packet (boomerang)\n"
  2249.  
  2250.         cmp     dword [esp+8], MAX_ETH_FRAME_SIZE
  2251.         ja      .finish ; packet is too long
  2252.  
  2253.         call    check_tx_status
  2254.         test    al, al
  2255.         jnz     tx_reset
  2256.  
  2257. ; calculate descriptor address
  2258.         mov     eax, [device.prev_dpd]
  2259.         DEBUGF  1,"Previous DPD: %x\n", eax
  2260.         add     eax, dpd.size
  2261.         mov     ecx, [device.dpd_buffer]
  2262.         add     ecx, NUM_TX_DESC*dpd.size
  2263.         cmp     eax, ecx
  2264.         cmovae  eax, [device.dpd_buffer]        ; Wrap if needed
  2265.  
  2266.         DEBUGF  1,"Found a free DPD: %x\n", eax
  2267.         push    eax
  2268. ; check DnListPtr
  2269.         set_io  0
  2270.         set_io  REG_DN_LIST_PTR
  2271.         in      eax, dx
  2272. ; mark if Dn_List_Ptr is cleared
  2273.         test    eax, eax
  2274.         setz    [device.dn_list_ptr_cleared]
  2275. ; finish if no more free descriptor is available - FIXME!
  2276.         cmp     eax, [esp]
  2277.         pop     eax
  2278.         jz      .finish
  2279.  
  2280.  
  2281.         push    eax             ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  2282. ; calculate tx_buffer address
  2283.         mov     edi, [device.prev_tx_frame]
  2284.         DEBUGF  1,"Previous TX frame:: %x\n", edi
  2285.         add     edi, MAX_ETH_FRAME_SIZE
  2286.  
  2287.         mov     ecx, [device.tx_buffer]
  2288.         add     ecx, NUM_TX_DESC*MAX_ETH_FRAME_SIZE
  2289.         cmp     edi, ecx
  2290.         cmovae  edi, [device.tx_buffer]         ; Wrap if needed
  2291.  
  2292.         DEBUGF  1,"Found place in TX buffer: %x\n", edi
  2293.         push    edi             ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  2294.  
  2295. ; update statistics
  2296.         inc     [device.packets_tx]
  2297.  
  2298.         mov     ecx, [esp+8+8]
  2299.         add     dword [device.bytes_tx], ecx
  2300.         adc     dword [device.bytes_tx + 4], 0
  2301.  
  2302. ; copy packet data
  2303.         mov     esi, [esp+4+8]
  2304.         DEBUGF  1,"Copying %u bytes from %x to %x\n", ecx, esi, edi
  2305.         shr     cx , 1
  2306.         jnc     .nb
  2307.         movsb
  2308.   .nb:
  2309.         shr     cx , 1
  2310.         jnc     .nw
  2311.         movsw
  2312.   .nw:
  2313.         rep     movsd
  2314.  
  2315. ; program DPD
  2316.         mov     eax, [esp]              ; Tx buffer address
  2317.         call    GetPgAddr
  2318.         mov     edi, [esp]
  2319.         and     edi, 4096 - 1
  2320.         or      edi, eax
  2321.  
  2322.         mov     eax, [esp+4]            ; descriptor
  2323.         DEBUGF  1,"Frag addr is: %x\n", edi
  2324.         and     [eax+dpd.next_ptr], 0
  2325.         mov     [eax+dpd.frag_addr], edi
  2326.  
  2327.         mov     ecx, [esp+8+8]          ; packet size
  2328.         or      ecx, 0x80000000         ; last fragment
  2329.         DEBUGF  1,"Frag size + flag is: %x\n", ecx
  2330.         mov     [eax+dpd.frag_len], ecx
  2331.  
  2332.         mov     ecx, [esp+8+8]          ; packet size
  2333.         or      ecx, 0x8000             ; transmission complete notification
  2334. ;        test    byte [device.has_hwcksm], 0xff
  2335. ;        jz      @f
  2336. ;        or      ecx, (1 shl 26) ; set AddTcpChecksum
  2337. ;@@:
  2338.         DEBUGF  1,"Frag start_hdr + flag is: %x\n", ecx
  2339.         mov     [eax+dpd.frame_start_hdr], ecx
  2340.  
  2341.  
  2342. ; calculate physical address
  2343.         mov     edi, eax
  2344.         call    GetPgAddr
  2345.         and     edi, 4096 - 1
  2346.         or      eax, edi
  2347.         cmp     [device.dn_list_ptr_cleared], 0
  2348.         jz      .add_to_list
  2349.  
  2350.         DEBUGF  1,"DN list ptr: %x\n", eax
  2351. ; write Dn_List_Ptr
  2352.         set_io  0
  2353.         set_io  REG_DN_LIST_PTR
  2354.         out     dx, eax
  2355.         jmp     .finish_pop
  2356. .add_to_list:
  2357.  
  2358.         DEBUGF  1,"Adding To list\n"
  2359.  
  2360. ; DnStall
  2361.         set_io  0
  2362.         set_io  REG_COMMAND
  2363.         mov     ax, ((110b shl 11)+2)
  2364.         out     dx, ax
  2365.  
  2366. ; wait for DnStall to complete
  2367.  
  2368.         DEBUGF  1,"Waiting for DnStall\n"
  2369.         mov     ecx, 6000
  2370. .wait_for_stall:
  2371.         in      ax, dx                  ; read REG_INT_STATUS
  2372.         test    ah, 10000b
  2373.         jz      .dnstall_ok
  2374.         dec     ecx
  2375.         jnz     .wait_for_stall
  2376.  
  2377. .dnstall_ok:
  2378.         DEBUGF  1,"DnStall ok!\n"
  2379.         mov     eax, [esp]              ; prev_tx_frame
  2380.         mov     ecx, [device.prev_dpd]
  2381.         mov     [ecx+dpd.next_ptr], eax
  2382.  
  2383.         set_io  0
  2384.         set_io  REG_DN_LIST_PTR
  2385.         in      eax, dx
  2386.  
  2387.         test    eax, eax
  2388.         jnz     .dnunstall
  2389. ; if Dn_List_Ptr has been cleared fill it up
  2390.         DEBUGF  1,"DnList Ptr has been cleared\n"
  2391.         mov     eax, [esp]
  2392.         out     dx, eax
  2393.  
  2394. .dnunstall:
  2395. ; DnUnStall
  2396.         set_io  0
  2397.         set_io  REG_COMMAND
  2398.         mov     ax, ((110b shl 11)+3)
  2399.         out     dx, ax
  2400.  
  2401. .finish_pop:
  2402.         pop     [device.prev_tx_frame]
  2403.         pop     [device.prev_dpd]
  2404.  
  2405. .finish:
  2406.         xor     eax, eax
  2407.         ret
  2408.  
  2409.  
  2410. ;---------------------------------
  2411. ; Write MAC
  2412.  
  2413.  
  2414. align 4
  2415. write_mac:   ; Tested - ok
  2416.  
  2417.         DEBUGF 1,"Writing mac\n"
  2418.  
  2419.         set_io  0
  2420.         set_io  REG_COMMAND
  2421.  
  2422. ; switch to register window 2
  2423.         mov     ax, SELECT_REGISTER_WINDOW+2
  2424.         out     dx, ax
  2425.  
  2426. ; write MAC addres back into the station address registers
  2427.         set_io  REG_STATION_ADDRESS_LO
  2428.         lea     esi, [device.mac]
  2429.         outsw
  2430.         inc     dx
  2431.         inc     dx
  2432.         outsw
  2433.         inc     dx
  2434.         inc     dx
  2435.         outsw
  2436.  
  2437. ;----------------------------
  2438. ; Read MAC
  2439.  
  2440.  
  2441. align 4
  2442. read_mac:    ; Tested - ok
  2443.  
  2444.  
  2445.  
  2446.         set_io  0
  2447.         set_io  REG_COMMAND
  2448.  
  2449. ; switch to register window 2
  2450.         mov     ax, SELECT_REGISTER_WINDOW+2
  2451.         out     dx, ax
  2452.  
  2453. ; write MAC addres back into the station address registers
  2454.         set_io  REG_STATION_ADDRESS_LO
  2455.         lea     edi, [device.mac]
  2456.         insw
  2457.         inc     dx
  2458.         inc     dx
  2459.         insw
  2460.         inc     dx
  2461.         inc     dx
  2462.         insw
  2463.  
  2464.         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
  2465.  
  2466.         ret
  2467.  
  2468.  
  2469. ;------------------------------------
  2470. ; Read MAC from eeprom
  2471.  
  2472.  
  2473. align 4
  2474. read_mac_eeprom:        ; Tested - ok
  2475.  
  2476.         DEBUGF 1,"Reading mac from eeprom\n"
  2477.  
  2478. ; read MAC from eeprom
  2479.         mov     ecx, 3
  2480. .mac_loop:
  2481.         lea     ax, [EEPROM_REG_OEM_NODE_ADDR+ecx-1]
  2482.         push    ecx
  2483.         call    read_eeprom
  2484.         pop     ecx
  2485.         xchg    ah, al ; htons
  2486.         mov     word [device.mac+ecx*2-2], ax
  2487.  
  2488.         loop    .mac_loop
  2489.  
  2490.         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
  2491.  
  2492.         ret
  2493.  
  2494.  
  2495.  
  2496.  
  2497.  
  2498. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2499. ;;                          ;;
  2500. ;; Vortex Interrupt handler ;;
  2501. ;;                          ;;
  2502. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2503.  
  2504. align 4
  2505. int_vortex:
  2506.  
  2507.         DEBUGF  1,"vortex IRQ %x ",eax:2
  2508.  
  2509. ; find pointer of device wich made IRQ occur
  2510.  
  2511.         mov     esi, VORTEX_LIST
  2512.         mov     ecx, [VORTEX_DEVICES]
  2513.         test    ecx, ecx
  2514.         jz      .fail
  2515.   .nextdevice:
  2516.         mov     ebx, dword [esi]
  2517.  
  2518.  
  2519.         set_io  0
  2520.         set_io  REG_INT_STATUS
  2521.         in      ax, dx
  2522. ;;        and     ax, INT_MASK
  2523.         jnz     .got_it
  2524.  
  2525.  
  2526.         add     esi, 4
  2527.  
  2528.         test    ax , ax
  2529.         jnz     .got_it
  2530.         loop    .nextdevice
  2531.  
  2532.   .fail:
  2533.  
  2534.         ret
  2535.  
  2536. .got_it:
  2537.  
  2538.         DEBUGF  1,"Device: %x Status: %x ",ebx,eax:4
  2539.  
  2540.         test    ax, RxComplete
  2541.         jz      .noRX
  2542.  
  2543.         set_io  0
  2544.   .rx_status_loop:
  2545. ; examine RxStatus
  2546.         set_io  REG_RX_STATUS
  2547.         in      ax, dx
  2548.         test    ax, ax
  2549.         jz      .finish
  2550.  
  2551.         test    ah, 0x80 ; rxIncomplete
  2552.         jnz     .finish
  2553.  
  2554.         test    ah, 0x40
  2555.         jz      .check_length
  2556.  
  2557. ; discard the top frame received advancing the next one
  2558.         set_io  REG_COMMAND
  2559.         mov     ax, (01000b shl 11)
  2560.         out     dx, ax
  2561.         jmp     .rx_status_loop
  2562.  
  2563.   .check_length:
  2564.         and     eax, 0x1fff
  2565.         cmp     eax, MAX_ETH_PKT_SIZE
  2566.         ja      .discard_frame ; frame is too long discard it
  2567.  
  2568.   .check_dma:
  2569.         mov     ecx, eax
  2570. ; switch to register window 7
  2571.         set_io  0
  2572.         set_io  REG_COMMAND
  2573.         mov     ax, SELECT_REGISTER_WINDOW+7
  2574.         out     dx, ax
  2575. ; check for master operation in progress
  2576.         set_io  REG_MASTER_STATUS
  2577.         in      ax, dx
  2578.  
  2579.         test    ah, 0x80
  2580.         jnz     .finish
  2581.  
  2582.   .read_frame:
  2583. ; program buffer address to read in
  2584.         stdcall KernelAlloc, ecx ; Allocate a buffer to put packet into
  2585.         test    eax, eax
  2586.         jz      .finish
  2587.  
  2588.         push    .discard_frame
  2589.         push    ecx
  2590.         push    eax
  2591. ;        zero_to_dma eax
  2592.         set_io  REG_MASTER_ADDRESS
  2593.         out     dx, eax
  2594.  
  2595. ; program frame length
  2596.         set_io  REG_MASTER_LEN
  2597.         mov     ax, 1560
  2598.         out     dx, ax
  2599.  
  2600. ; start DMA Up
  2601.         set_io  REG_COMMAND
  2602.         mov     ax, (10100b shl 11) ; StartDMAUp
  2603.         out     dx, ax
  2604.  
  2605. ; check for master operation in progress
  2606.         set_io  REG_MASTER_STATUS   ; TODO: use timeout and reset after timeout expired
  2607.   .dma_loop:
  2608.         xor     esi, esi
  2609.         stdcall Sleep
  2610.         in      ax, dx
  2611.         test    ah, 0x80
  2612.         jnz     .dma_loop
  2613.  
  2614. ; registrate the received packet to kernel
  2615.         jmp     EthReceiver
  2616.  
  2617. ; discard the top frame received
  2618.   .discard_frame:
  2619.         set_io  0
  2620.         set_io  REG_COMMAND
  2621.         mov     ax, (01000b shl 11)
  2622.         out     dx, ax
  2623.  
  2624.   .finish:
  2625.  
  2626.  
  2627. .noRX:
  2628.  
  2629.         test    ax, DMADone
  2630.         jz      .noDMA
  2631.  
  2632.         push    ax
  2633.  
  2634.         set_io  0
  2635.         set_io  12
  2636.         in      ax, dx
  2637.         test    ax, 0x1000
  2638.         jz      .nodmaclear
  2639.  
  2640.         mov     ax, 0x1000
  2641.         out     dx, ax
  2642.  
  2643.   .nodmaclear:
  2644.  
  2645.         pop     ax
  2646.  
  2647.         DEBUGF  1, "DMA Done!\n", cx
  2648.  
  2649.  
  2650.  
  2651. .noDMA:
  2652.  
  2653.  
  2654.  
  2655. .ACK:
  2656.         set_io  0
  2657.         set_io  REG_COMMAND
  2658.         mov     ax, AckIntr + IntReq + IntLatch
  2659.         out     dx, ax
  2660.  
  2661.         ret
  2662.  
  2663.  
  2664.  
  2665.  
  2666. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2667. ;;                             ;;
  2668. ;; Boomerang Interrupt handler ;;
  2669. ;;                             ;;
  2670. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2671.  
  2672. align 4
  2673. int_boomerang:
  2674.  
  2675. ;        DEBUGF  1,"\nIRQ %x Boomerang\n",eax:2
  2676.  
  2677. ; find pointer of device wich made IRQ occur
  2678.  
  2679.         mov     esi, BOOMERANG_LIST
  2680.         mov     ecx, [BOOMERANG_DEVICES]
  2681.  
  2682. ;        DEBUGF  1,"Devices: %u\n", ecx
  2683.         test    ecx, ecx
  2684.         jz      .fail
  2685.   .nextdevice:
  2686.         mov     ebx, dword[esi]
  2687.  
  2688.         set_io  0
  2689.         set_io  REG_INT_STATUS
  2690.         in      ax, dx
  2691.         test    ax, IntLatch
  2692.         jnz     .got_it
  2693.  
  2694.         add     esi, 4
  2695.  
  2696.         test    ax , ax
  2697.         jnz     .got_it
  2698.         dec     ecx
  2699.         jnz     .nextdevice
  2700.  
  2701.   .fail:
  2702.         DEBUGF  1,"Failed!\n"
  2703.         ret
  2704.  
  2705. .got_it:
  2706.  
  2707.         DEBUGF  1,"Device: %x Status: %x ", ebx, eax
  2708.  
  2709.         push    ax
  2710. ; disable all INTS
  2711.  
  2712.         set_io  REG_COMMAND
  2713.         mov     ax, SetIntrEnb
  2714.         out     dx, ax
  2715.  
  2716. ;; acknowledge all int sources
  2717. ;
  2718. ;        mov     ax, word [esp]
  2719. ;        and     ax, 0xff
  2720. ;        or      ax, AckIntr
  2721. ;        out     dx, ax
  2722.  
  2723. ;--------------------------------------------------------------------------
  2724.         test    word[esp], UpComplete
  2725.         jz      .noRX
  2726.  
  2727.         push    ebx
  2728.  
  2729.   .receive:
  2730.         DEBUGF  1,"UpComplete\n"
  2731.  
  2732. ; check if packet is uploaded
  2733.         mov     eax, [device.curr_upd]
  2734.         test    byte [eax+upd.pkt_status+1], 0x80 ; upPktComplete
  2735.         jz      .finish
  2736. ; packet is uploaded check for any error
  2737.   .check_error:
  2738.         test    byte [eax+upd.pkt_status+1], 0x40 ; upError
  2739.         jz      .copy_packet_length
  2740.         DEBUGF  1,"Error in packet\n"
  2741.         and     [eax+upd.pkt_status], 0           ; mark packet as read
  2742.         jmp     .finish
  2743.   .copy_packet_length:
  2744.         mov     ecx, [eax+upd.pkt_status]
  2745.         and     ecx, 0x1fff
  2746.         cmp     ecx, MAX_ETH_PKT_SIZE
  2747.         jbe     .copy_packet
  2748.         and     [eax+upd.pkt_status], 0
  2749.         jmp     .finish
  2750.  
  2751.   .copy_packet:
  2752.         DEBUGF  1, " data hw addr:%x\n", [eax+upd.frag_addr]
  2753.  
  2754.         mov     esi, [eax+upd.realaddr]
  2755.  
  2756.         push    esi ecx
  2757.         stdcall KernelAlloc, ecx ; Allocate a buffer to put packet into
  2758.         pop     ecx esi
  2759.         test    eax, eax
  2760.         jz      .finish
  2761.  
  2762.         push    dword .loop ;.finish
  2763.         push    ecx eax
  2764.         mov     edi, eax
  2765.  
  2766.         DEBUGF  1, " copying %u bytes from %x to %x\n", ecx, esi, edi
  2767.  
  2768. ; update statistics
  2769.         inc     [device.packets_rx]
  2770.  
  2771.         add     dword [device.bytes_rx], ecx
  2772.         adc     dword [device.bytes_rx + 4], 0
  2773.  
  2774. ; copy packet data
  2775.         shr     cx , 1
  2776.         jnc     .nb
  2777.         movsb
  2778.   .nb:
  2779.         shr     cx , 1
  2780.         jnc     .nw
  2781.         movsw
  2782.   .nw:
  2783.         rep     movsd
  2784.  
  2785.         mov     eax, [device.curr_upd]
  2786.         DEBUGF  1, "current upd: %x\n", eax
  2787.         and     [eax + upd.pkt_status], 0       ; clear the ring buffer entry for reuse
  2788.         mov     [eax + upd.frag_len], MAX_ETH_FRAME_SIZE or (1 shl 31) ;;;
  2789.         add     eax, upd.size
  2790.  
  2791.         mov     ecx, [device.upd_buffer]
  2792.         add     ecx, (NUM_RX_DESC)*upd.size
  2793.  
  2794.         cmp     eax, ecx
  2795.         cmovae  eax, [device.upd_buffer]
  2796.         mov     [device.curr_upd], eax
  2797.         DEBUGF  1, "next upd: %x\n", eax
  2798.  
  2799.         jmp     EthReceiver
  2800.  
  2801.   .loop:
  2802.         mov     ebx, [esp]
  2803.         jmp     .receive
  2804.  
  2805.   .finish:
  2806.         pop     ebx
  2807.  
  2808. ; check if the NIC is in the upStall state
  2809.         set_io  0
  2810.         set_io  REG_UP_PKT_STATUS
  2811.         in      eax, dx
  2812.         test    ah, 0x20             ; UpStalled
  2813.         jz      .noUpUnStall
  2814. ; issue upUnStall command
  2815.         set_io  REG_COMMAND
  2816.         mov     ax, ((11b shl 12)+1) ; upUnStall
  2817.         out     dx, ax
  2818.         DEBUGF  1, "upUnStalling\n"
  2819.   .noUpUnStall:
  2820.  
  2821. .noRX:
  2822.         pop     ax
  2823.  
  2824.         set_io  0
  2825.         set_io  REG_COMMAND
  2826.         or      ax, AckIntr
  2827.         out     dx, ax
  2828.  
  2829.     ;    set_io  REG_COMMAND
  2830.     ;    mov     ax, AckIntr + IntLatch
  2831.     ;    out     dx, ax
  2832.  
  2833.  
  2834.         set_io  REG_INT_STATUS
  2835.         in      ax, dx
  2836.         test    ax, S_5_INTS
  2837.         jnz     .got_it
  2838.  
  2839. ;re-enable ints
  2840.         set_io  REG_COMMAND
  2841.         mov     ax, SetIntrEnb + S_5_INTS
  2842.         out     dx, ax
  2843.  
  2844.  
  2845.         ret
  2846.  
  2847.  
  2848.  
  2849.  
  2850. ; End of code
  2851.  
  2852. align 4                                         ; Place all initialised data here
  2853.  
  2854.  
  2855.  
  2856. macro strtbl name, [string]
  2857. {
  2858. common
  2859.         label name dword
  2860. forward
  2861.         local label
  2862.         dd label
  2863. forward
  2864.         label db string, 0
  2865. }
  2866.  
  2867. VORTEX_DEVICES       dd 0
  2868. BOOMERANG_DEVICES    dd 0
  2869. version              dd (5 shl 16) or (API_VERSION and 0xFFFF)
  2870. my_service           db '3C59X',0                    ; max 16 chars include zero
  2871.  
  2872.  
  2873. strtbl link_str, \
  2874.         "No valid link type detected", \
  2875.         "10BASE-T half duplex", \
  2876.         "10BASE-T full-duplex", \
  2877.         "100BASE-TX half duplex", \
  2878.         "100BASE-TX full duplex", \
  2879.         "100BASE-T4", \
  2880.         "100BASE-FX", \
  2881.         "10Mbps AUI", \
  2882.         "10Mbps COAX (BNC)", \
  2883.         "miiDevice - not supported"
  2884.  
  2885. strtbl hw_str, \
  2886.         "3c590 Vortex 10Mbps", \
  2887.         "3c592 EISA 10Mbps Demon/Vortex", \
  2888.         "3c597 EISA Fast Demon/Vortex", \
  2889.         "3c595 Vortex 100baseTx", \
  2890.         "3c595 Vortex 100baseT4", \
  2891.         "3c595 Vortex 100base-MII", \
  2892.         "3c900 Boomerang 10baseT", \
  2893.         "3c900 Boomerang 10Mbps Combo", \
  2894.         "3c900 Cyclone 10Mbps TPO", \
  2895.         "3c900 Cyclone 10Mbps Combo", \
  2896.         "3c900 Cyclone 10Mbps TPC", \
  2897.         "3c900B-FL Cyclone 10base-FL", \
  2898.         "3c905 Boomerang 100baseTx", \
  2899.         "3c905 Boomerang 100baseT4", \
  2900.         "3c905B Cyclone 100baseTx", \
  2901.         "3c905B Cyclone 10/100/BNC", \
  2902.         "3c905B-FX Cyclone 100baseFx", \
  2903.         "3c905C Tornado", \
  2904.         "3c980 Cyclone", \
  2905.         "3c982 Dual Port Server Cyclone", \
  2906.         "3cSOHO100-TX Hurricane", \
  2907.         "3c555 Laptop Hurricane", \
  2908.         "3c556 Laptop Tornado", \
  2909.         "3c556B Laptop Hurricane", \
  2910.         "3c575 [Megahertz] 10/100 LAN CardBus", \
  2911.         "3c575 Boomerang CardBus", \
  2912.         "3CCFE575BT Cyclone CardBus", \
  2913.         "3CCFE575CT Tornado CardBus", \
  2914.         "3CCFE656 Cyclone CardBus", \
  2915.         "3CCFEM656B Cyclone+Winmodem CardBus", \
  2916.         "3CXFEM656C Tornado+Winmodem CardBus", \
  2917.         "3c450 HomePNA Tornado", \
  2918.         "3c920 Tornado", \
  2919.         "3c982 Hydra Dual Port A", \
  2920.         "3c982 Hydra Dual Port B", \
  2921.         "3c905B-T4", \
  2922.         "3c920B-EMB-WNM Tornado"
  2923.  
  2924.  
  2925.  
  2926. align 4
  2927. hw_versions:
  2928. dw 0x5900, IS_VORTEX
  2929. ; 3c590 Vortex 10Mbps
  2930. dw 0x5920, IS_VORTEX
  2931. ; 3c592 EISA 10Mbps Demon/Vortex
  2932. dw 0x5970, IS_VORTEX
  2933. ; 3c597 EISA Fast Demon/Vortex
  2934. dw 0x5950, IS_VORTEX
  2935. ; 3c595 Vortex 100baseTx
  2936. dw 0x5951, IS_VORTEX
  2937. ; 3c595 Vortex 100baseT4
  2938. dw 0x5952, IS_VORTEX
  2939. ; 3c595 Vortex 100base-MII
  2940. dw 0x9000, IS_BOOMERANG
  2941. ; 3c900 Boomerang 10baseT
  2942. dw 0x9001, IS_BOOMERANG
  2943. ; 3c900 Boomerang 10Mbps Combo
  2944. dw 0x9004, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM
  2945. ; 3c900 Cyclone 10Mbps TPO
  2946. dw 0x9005, IS_CYCLONE or HAS_HWCKSM
  2947. ; 3c900 Cyclone 10Mbps Combo
  2948. dw 0x9006, IS_CYCLONE or HAS_HWCKSM
  2949. ; 3c900 Cyclone 10Mbps TPC
  2950. dw 0x900A, IS_CYCLONE or HAS_HWCKSM
  2951. ; 3c900B-FL Cyclone 10base-FL
  2952. dw 0x9050, IS_BOOMERANG or HAS_MII
  2953. ; 3c905 Boomerang 100baseTx
  2954. dw 0x9051, IS_BOOMERANG or HAS_MII
  2955. ; 3c905 Boomerang 100baseT4
  2956. dw 0x9055, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE
  2957. ; 3c905B Cyclone 100baseTx
  2958. dw 0x9058, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM
  2959. ; 3c905B Cyclone 10/100/BNC
  2960. dw 0x905A, IS_CYCLONE or HAS_HWCKSM
  2961. ; 3c905B-FX Cyclone 100baseFx
  2962. dw 0x9200, IS_TORNADO or HAS_NWAY or HAS_HWCKSM
  2963. ; 3c905C Tornado
  2964. dw 0x9800, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM
  2965. ; 3c980 Cyclone
  2966. dw 0x9805, IS_TORNADO or HAS_NWAY or HAS_HWCKSM
  2967. ; 3c982 Dual Port Server Cyclone
  2968. dw 0x7646, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM
  2969. ; 3cSOHO100-TX Hurricane
  2970. dw 0x5055, IS_CYCLONE or EEPROM_8BIT or HAS_HWCKSM
  2971. ; 3c555 Laptop Hurricane
  2972. dw 0x6055, IS_TORNADO or HAS_NWAY or EEPROM_8BIT or HAS_CB_FNS or INVERT_MII_PWR or HAS_HWCKSM
  2973. ; 3c556 Laptop Tornado
  2974. dw 0x6056, IS_TORNADO or HAS_NWAY or EEPROM_OFFSET or HAS_CB_FNS or INVERT_MII_PWR or HAS_HWCKSM
  2975. ; 3c556B Laptop Hurricane
  2976. dw 0x5b57, IS_BOOMERANG or HAS_MII or EEPROM_8BIT
  2977. ; 3c575 [Megahertz] 10/100 LAN CardBus
  2978. dw 0x5057, IS_BOOMERANG or HAS_MII or EEPROM_8BIT
  2979. ; 3c575 Boomerang CardBus
  2980. dw 0x5157, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_LED_PWR or HAS_HWCKSM
  2981. ; 3CCFE575BT Cyclone CardBus
  2982. 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
  2983. ; 3CCFE575CT Tornado CardBus
  2984. 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
  2985. ; 3CCFE656 Cyclone CardBus
  2986. 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
  2987. ; 3CCFEM656B Cyclone+Winmodem CardBus
  2988. 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
  2989. ; 3CXFEM656C Tornado+Winmodem CardBus
  2990. dw 0x4500, IS_TORNADO or HAS_NWAY or HAS_HWCKSM
  2991. ; 3c450 HomePNA Tornado
  2992. dw 0x9201, IS_TORNADO or HAS_NWAY or HAS_HWCKSM
  2993. ; 3c920 Tornado
  2994. dw 0x1201, IS_TORNADO or HAS_HWCKSM or HAS_NWAY
  2995. ; 3c982 Hydra Dual Port A
  2996. dw 0x1202, IS_TORNADO or HAS_HWCKSM or HAS_NWAY
  2997. ; 3c982 Hydra Dual Port B
  2998. dw 0x9056, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE
  2999. ; 3c905B-T4
  3000. dw 0x9210, IS_TORNADO or HAS_NWAY or HAS_HWCKSM
  3001. ; 3c920B-EMB-WNM Tornado
  3002. HW_VERSIONS_SIZE = $ - hw_versions
  3003.  
  3004.  
  3005. include_debug_strings                           ; All data wich FDO uses will be included here
  3006.  
  3007. section '.data' data readable writable align 16 ; place all uninitialized data place here
  3008.  
  3009. VORTEX_LIST    rd MAX_DEVICES                   ; This list contains all pointers to device structures the driver is handling
  3010. BOOMERANG_LIST rd MAX_DEVICES
  3011.  
  3012.  
  3013.  
  3014.  
  3015.