Subversion Repositories Kolibri OS

Rev

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