Subversion Repositories Kolibri OS

Rev

Rev 2935 | Blame | Last modification | View Log | Download | RSS feed

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