Subversion Repositories Kolibri OS

Rev

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