Subversion Repositories Kolibri OS

Rev

Rev 3545 | Rev 4467 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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