Subversion Repositories Kolibri OS

Rev

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