Subversion Repositories Kolibri OS

Rev

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

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