Subversion Repositories Kolibri OS

Rev

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