Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2018-2021. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  AR81XX driver for KolibriOS                                    ;;
  7. ;;                                                                 ;;
  8. ;;  based on alx driver from TI-OpenLink                           ;;
  9. ;;                                                                 ;;
  10. ;;  Written by hidnplayr (hidnplayr@gmail.com)                     ;;
  11. ;;                                                                 ;;
  12. ;;  Thanks to: floppy121 for kindly providing me with the hardware ;;
  13. ;;              that made the development of this driver possible. ;;
  14. ;;                                                                 ;;
  15. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  16. ;;             Version 2, June 1991                                ;;
  17. ;;                                                                 ;;
  18. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  19.  
  20. format PE DLL native
  21. entry START
  22.  
  23.         CURRENT_API             = 0x0200
  24.         COMPATIBLE_API          = 0x0100
  25.         API_VERSION             = (COMPATIBLE_API shl 16) + CURRENT_API
  26.  
  27. ; configureable area
  28.  
  29.         MAX_DEVICES             = 16    ; Maximum number of devices this driver may handle
  30.  
  31.         __DEBUG__               = 1     ; 1 = on, 0 = off
  32.         __DEBUG_LEVEL__         = 2     ; 1 = verbose, 2 = errors only
  33.  
  34.         TX_RING_SIZE            = 128   ; Number of packets in send ring buffer
  35.         RX_RING_SIZE            = 128   ; Number of packets in receive ring buffer
  36.  
  37.         RX_BUFFER_SIZE          = 1536
  38.  
  39.         SMB_TIMER               = 400
  40.         IMT                     = 200                   ; IRQ Modulo Timer
  41.         ITH_TPD                 = TX_RING_SIZE / 3      ; Interrupt Threshold TPD
  42.  
  43. ; end configureable area
  44.  
  45. section '.flat' readable writable executable
  46.  
  47. include '../proc32.inc'
  48. include '../struct.inc'
  49. include '../macros.inc'
  50. include '../fdo.inc'
  51. include '../netdrv.inc'
  52.  
  53. include 'ar81xx.inc'
  54.  
  55. if (bsr TX_RING_SIZE)>(bsf TX_RING_SIZE)
  56.   display 'TX_RING_SIZE must be a power of two'
  57.   err
  58. end if
  59.  
  60. if (bsr RX_RING_SIZE)>(bsf RX_RING_SIZE)
  61.   display 'RX_RING_SIZE must be a power of two'
  62.   err
  63. end if
  64.  
  65. ; Transmit Packet Descriptor
  66. struct alx_tpd
  67.         length          dw ?
  68.         vlan_tag        dw ?
  69.         word1           dd ?
  70.         addr_l          dd ?
  71.         addr_h          dd ?
  72. ends
  73.  
  74. ; Receive Return Descriptor
  75. struct alx_rrd
  76.         word0           dd ?    ; IP payload cksum + number of RFDs + start index of RFD-ring
  77.         rss_hash        dd ?
  78.         word2           dd ?    ; VLAN tag + Protocol ID + RSS Q num + RSS Hash algorithm
  79.         word3           dd ?    ; Packet length + status
  80. ends
  81.  
  82. ; Receive Free Descriptor
  83. struct alx_rfd
  84.         addr_l          dd ?
  85.         addr_h          dd ?
  86. ends
  87.  
  88. struct  device          ETH_DEVICE
  89.  
  90.         io_addr         dd ?
  91.         pci_bus         dd ?
  92.         pci_dev         dd ?
  93.         pci_vid         dw ?    ; Vendor ID
  94.         pci_did         dw ?    ; Device ID
  95.         irq_line        dd ?
  96.         pci_rev         dd ?
  97.         chip_rev        dd ?
  98.         mmio_addr       dd ?
  99.  
  100.         max_dma_chnl    dd ?
  101.  
  102.         int_mask        dd ?
  103.         rx_ctrl         dd ?
  104.  
  105.         rxq_read_idx            dd ?
  106.         rxq_write_idx           dd ?
  107. ;        rxq_rrd_read_idx        dd ?
  108.         txq_read_idx            dd ?
  109.         txq_write_idx           dd ?
  110.  
  111.         rb 0x100 - ($ and 0xff) ; align 256
  112.         tpd_ring        rb ((TX_RING_SIZE*sizeof.alx_tpd+16) and 0xfffffff0)
  113.         rrd_ring        rb ((RX_RING_SIZE*sizeof.alx_rrd+16) and 0xfffffff0)
  114.         rfd_ring        rb ((RX_RING_SIZE*sizeof.alx_rfd+16) and 0xfffffff0)
  115.         tpd_ring_virt   rd TX_RING_SIZE
  116.         rfd_ring_virt   rd RX_RING_SIZE
  117.  
  118. ends
  119.  
  120. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  121. ;;                        ;;
  122. ;; proc START             ;;
  123. ;;                        ;;
  124. ;; (standard driver proc) ;;
  125. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  126.  
  127. proc START c, reason:dword, cmdline:dword
  128.  
  129.         cmp     [reason], DRV_ENTRY
  130.         jne     .fail
  131.  
  132.         DEBUGF  2,"Loading driver\n"
  133.         invoke  RegService, my_service, service_proc
  134.         ret
  135.  
  136.   .fail:
  137.         xor     eax, eax
  138.         ret
  139.  
  140. endp
  141.  
  142. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  143. ;;                        ;;
  144. ;; proc SERVICE_PROC      ;;
  145. ;;                        ;;
  146. ;; (standard driver proc) ;;
  147. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  148.  
  149. proc service_proc stdcall, ioctl:dword
  150.  
  151.         mov     edx, [ioctl]
  152.         mov     eax, [edx + IOCTL.io_code]
  153.  
  154. ;------------------------------------------------------
  155.  
  156.         cmp     eax, 0 ;SRV_GETVERSION
  157.         jne     @F
  158.  
  159.         cmp     [edx + IOCTL.out_size], 4
  160.         jb      .fail
  161.         mov     eax, [edx + IOCTL.output]
  162.         mov     [eax], dword API_VERSION
  163.  
  164.         xor     eax, eax
  165.         ret
  166.  
  167. ;------------------------------------------------------
  168.   @@:
  169.         cmp     eax, 1 ;SRV_HOOK
  170.         jne     .fail
  171.  
  172.         cmp     [edx + IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
  173.         jb      .fail
  174.  
  175.         mov     eax, [edx + IOCTL.input]
  176.         cmp     byte [eax], 1                           ; 1 means device number and bus number (pci) are given
  177.         jne     .fail                                   ; other types arent supported for this card yet
  178.  
  179. ; check if the device is already listed
  180.  
  181.         mov     esi, device_list
  182.         mov     ecx, [devices]
  183.         test    ecx, ecx
  184.         jz      .firstdevice
  185.  
  186. ;        mov     eax, [edx + IOCTL.input]               ; get the pci bus and device numbers
  187.         mov     ax , [eax+1]                            ;
  188.   .nextdevice:
  189.         mov     ebx, [esi]
  190.         cmp     al, byte[ebx + device.pci_bus]
  191.         jne     @f
  192.         cmp     ah, byte[ebx + device.pci_dev]
  193.         je      .find_devicenum                         ; Device is already loaded, let's find it's device number
  194.        @@:
  195.         add     esi, 4
  196.         loop    .nextdevice
  197.  
  198. ; This device doesnt have its own eth_device structure yet, lets create one
  199.   .firstdevice:
  200.         cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
  201.         jae     .fail
  202.  
  203.         allocate_and_clear ebx, sizeof.device, .fail    ; Allocate the buffer for device structure
  204.  
  205. ; Fill in the direct call addresses into the struct
  206.  
  207.         mov     [ebx + device.reset], reset
  208.         mov     [ebx + device.transmit], transmit
  209.         mov     [ebx + device.unload], unload
  210.         mov     [ebx + device.name], my_service
  211.  
  212. ; save the pci bus and device numbers
  213.  
  214.         mov     eax, [edx + IOCTL.input]
  215.         movzx   ecx, byte[eax+1]
  216.         mov     [ebx + device.pci_bus], ecx
  217.         movzx   ecx, byte[eax+2]
  218.         mov     [ebx + device.pci_dev], ecx
  219.  
  220. ; Now, it's time to find the base mmio addres of the PCI device
  221.  
  222.         stdcall PCI_find_mmio, [ebx + device.pci_bus], [ebx + device.pci_dev] ; returns in eax
  223.         test    eax, eax
  224.         jz      .destroy
  225.  
  226. ; Create virtual mapping of the physical memory
  227.  
  228.         invoke  MapIoMem, eax, 10000h, PG_SW+PG_NOCACHE
  229.         mov     [ebx + device.mmio_addr], eax
  230.  
  231. ; We've found the mmio address, find IRQ now
  232.         invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
  233.         and     eax, 0xff
  234.         mov     [ebx + device.irq_line], eax
  235.  
  236.         DEBUGF  1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
  237.         [ebx + device.pci_dev]:1, [ebx + device.pci_bus]:1, [ebx + device.irq_line]:1, [ebx + device.mmio_addr]:8
  238.  
  239. ; Ok, the eth_device structure is ready, let's probe the device
  240.  
  241.         mov     eax, [devices]                                          ; Add the device structure to our device list
  242.         mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
  243.         inc     [devices]                                               ;
  244.  
  245.         call    probe                                                   ; this function will output in eax
  246.         test    eax, eax
  247.         jnz     .err2
  248.  
  249.         DEBUGF  2,"Initialised OK\n"
  250.  
  251.         mov     [ebx + device.type], NET_TYPE_ETH
  252.         invoke  NetRegDev
  253.  
  254.         cmp     eax, -1
  255.         je      .destroy
  256.  
  257.         ret
  258.  
  259. ; If the device was already loaded, find the device number and return it in eax
  260.  
  261.   .find_devicenum:
  262.         DEBUGF  2,"Trying to find device number of already registered device\n"
  263.         invoke  NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
  264.                                                                         ; into a device number in edi
  265.         mov     eax, edi                                                ; Application wants it in eax instead
  266.         DEBUGF  2,"Kernel says: %u\n", eax
  267.         ret
  268.  
  269. ; If an error occured, remove all allocated data and exit (returning -1 in eax)
  270.  
  271.   .destroy:
  272.         ; todo: reset device into virgin state
  273.  
  274.   .err2:
  275.         dec     [devices]
  276.   .err:
  277.         invoke  KernelFree, ebx
  278.   .fail:
  279.         DEBUGF  2, "Failed to load\n"
  280.         or      eax, -1
  281.         ret
  282.  
  283. ;------------------------------------------------------
  284. endp
  285.  
  286. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  287. ;;                                                                        ;;
  288. ;;        Actual Hardware dependent code starts here                      ;;
  289. ;;                                                                        ;;
  290. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  291.  
  292. align 4
  293. unload:
  294.         ; TODO: (in this particular order)
  295.         ;
  296.         ; - Stop the device
  297.         ; - Detach int handler
  298.         ; - Remove device from local list (device_list)
  299.         ; - call unregister function in kernel
  300.         ; - Remove all allocated structures and buffers the card used
  301.  
  302.         or      eax, -1
  303.         ret
  304.  
  305. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  306. ;;
  307. ;;  probe: enables the device (if it really is AR81XX)
  308. ;;
  309. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  310.  
  311. align 4
  312. probe:
  313.         DEBUGF  1,"Probing\n"
  314.  
  315. ; Make the device a bus master
  316.         invoke  PciRead16, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header.command
  317.         or      al, PCI_CMD_MASTER + PCI_CMD_MMIO + PCI_CMD_PIO
  318.         and     ax, not(PCI_CMD_INTX_DISABLE)
  319.         invoke  PciWrite16, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header.command, eax
  320.  
  321. ; get device ID
  322.         invoke  PciRead16, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header.device_id
  323.         mov     [ebx + device.pci_did], ax
  324.  
  325.         mov     esi, chiplist
  326.   .loop:
  327.         cmp     word[esi+2], ax
  328.         je      .got_it
  329.         add     esi, 8
  330.         cmp     esi, chiplist + 6*8
  331.         jbe     .loop
  332.         DEBUGF  2, "Unknown chip: 0x%x, continuing anyway\n", ax
  333.         jmp     .done
  334.   .got_it:
  335.         mov     eax, dword[esi+4]
  336.         mov     [ebx + device.name], eax
  337.         DEBUGF  1, "Chip type = %s\n", eax
  338.   .done:
  339.  
  340. ; get revision ID
  341.         invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header.revision_id
  342.         and     eax, 0xff
  343.         DEBUGF  1,"PCI Revision: %u\n", eax
  344.         mov     [ebx + device.pci_rev], eax
  345.         shr     al, ALX_PCI_REVID_SHIFT
  346.         mov     [ebx + device.chip_rev], eax
  347.         DEBUGF  1,"ALX Revision: %u\n", eax
  348.  
  349.         stdcall alx_reset_pcie
  350.  
  351.         mov     ecx, (ALX_PMCTRL_L0S_EN or ALX_PMCTRL_L1_EN or ALX_PMCTRL_ASPM_FCEN)
  352.         stdcall alx_enable_aspm
  353.  
  354.         stdcall alx_reset_phy
  355.  
  356.         stdcall alx_reset_mac
  357.  
  358. ; Setup link to put it in a known good starting state
  359.         stdcall alx_write_phy_reg, ALX_MII_DBG_ADDR, 0
  360.  
  361.         mov     esi, [ebx + device.mmio_addr]
  362.         mov     eax, dword[esi + ALX_DRV]
  363.  
  364.         stdcall alx_write_phy_reg, MII_ADVERTISE, ADVERTISE_CSMA or ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL or ADVERTISE_PAUSE_CAP
  365.  
  366.         xor     eax, eax
  367.         test    [ebx + device.pci_did], 1       ;;; FIXME: is gigabit device?
  368.         jz      @f
  369.         mov     eax, ADVERTISE_1000XFULL
  370.   @@:
  371.         stdcall alx_write_phy_reg, MII_CTRL1000, eax
  372.  
  373.         stdcall alx_write_phy_reg, MII_BMCR, BMCR_RESET or BMCR_ANENABLE or BMCR_ANRESTART
  374.  
  375.         stdcall alx_get_perm_macaddr
  376.  
  377. align 4
  378. reset:
  379.  
  380.         DEBUGF  1,"Resetting\n"
  381.  
  382. ; alx init_sw
  383.  
  384.         stdcall alx_identify_hw
  385.  
  386.         mov     [ebx + device.int_mask], ALX_ISR_MISC
  387.         mov     [ebx + device.rx_ctrl], ALX_MAC_CTRL_WOLSPED_SWEN or ALX_MAC_CTRL_MHASH_ALG_HI5B or ALX_MAC_CTRL_BRD_EN or ALX_MAC_CTRL_PCRCE or ALX_MAC_CTRL_CRCE or ALX_MAC_CTRL_RXFC_EN or ALX_MAC_CTRL_TXFC_EN or (7 shl ALX_MAC_CTRL_PRMBLEN_SHIFT)
  388.  
  389.         stdcall alx_alloc_rings
  390.  
  391.         stdcall alx_configure
  392.  
  393.         stdcall alx_request_irq
  394.  
  395. ; attach interrupt handler
  396.  
  397.         mov     eax, [ebx + device.irq_line]
  398.         DEBUGF  1,"Attaching int handler to irq %x\n", eax:1
  399.         invoke  AttachIntHandler, eax, int_handler, ebx
  400.         test    eax, eax
  401.         jnz     @f
  402.         DEBUGF  2,"Could not attach int handler!\n"
  403.         or      eax, -1
  404.         ret
  405.   @@:
  406.  
  407. ; Clear old interrupts
  408.         mov     edi, [ebx + device.mmio_addr]
  409.         mov     eax, not ALX_ISR_DIS
  410.         mov     [edi + ALX_ISR], eax
  411.  
  412.         stdcall alx_irq_enable
  413.  
  414. ; Set the MTU, kernel will be able to send now
  415.         mov     [ebx + device.mtu], 1514
  416.  
  417.         stdcall alx_check_link
  418.  
  419.         DEBUGF  1,"Reset ok\n"
  420.         xor     eax, eax
  421.         ret
  422.  
  423. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  424. ;;                                         ;;
  425. ;; Transmit                                ;;
  426. ;;                                         ;;
  427. ;; In: pointer to device structure in ebx  ;;
  428. ;; Out: eax = 0 on success                 ;;
  429. ;;                                         ;;
  430. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  431. align 16
  432. proc transmit stdcall bufferptr
  433.  
  434.         spin_lock_irqsave
  435.  
  436.         mov     esi, [bufferptr]
  437.         DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length]
  438.         lea     eax, [esi + NET_BUFF.data]
  439.         DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
  440.         [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
  441.         [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
  442.         [eax+13]:2,[eax+12]:2
  443.  
  444.         cmp     [esi + NET_BUFF.length], 1514
  445.         ja      .error
  446.         cmp     [esi + NET_BUFF.length], 60
  447.         jb      .error
  448.  
  449. ; Program the descriptor
  450.         mov     edi, [ebx + device.txq_write_idx]
  451.         DEBUGF  1, "Using TPD: %u\n", edi
  452.         cmp     dword[ebx + device.tpd_ring_virt + edi*4], 0
  453.         jne     .overrun
  454.         mov     dword[ebx + device.tpd_ring_virt + edi*4], esi
  455.         shl     edi, 4
  456.         lea     edi, [ebx + device.tpd_ring + edi]
  457.         mov     eax, esi
  458.         add     eax, [esi + NET_BUFF.offset]
  459.         invoke  GetPhysAddr
  460.         mov     [edi + alx_tpd.addr_l], eax
  461.         mov     [edi + alx_tpd.addr_h], 0
  462.  
  463.         mov     ecx, [esi + NET_BUFF.length]
  464.         mov     [edi + alx_tpd.length], cx
  465.  
  466.         mov     [edi + alx_tpd.word1], 1 shl TPD_EOP_SHIFT
  467.  
  468. ; Update Producer Index
  469.         mov     eax, [ebx + device.txq_write_idx]
  470.         inc     eax
  471.         and     eax, TX_RING_SIZE - 1
  472.         mov     [ebx + device.txq_write_idx], eax
  473.  
  474.         mov     edi, [ebx + device.mmio_addr]
  475.         mov     word[edi + ALX_TPD_PRI0_PIDX], ax
  476.  
  477. ; Update stats
  478.         inc     [ebx + device.packets_tx]
  479.         mov     eax, [esi + NET_BUFF.length]
  480.         add     dword[ebx + device.bytes_tx], eax
  481.         adc     dword[ebx + device.bytes_tx + 4], 0
  482.  
  483.         spin_unlock_irqrestore
  484.         xor     eax, eax
  485.         ret
  486.  
  487.   .error:
  488.         DEBUGF  2, "TX packet error\n"
  489.         inc     [ebx + device.packets_tx_err]
  490.         invoke  NetFree, [bufferptr]
  491.  
  492.         spin_unlock_irqrestore
  493.         or      eax, -1
  494.         ret
  495.  
  496.   .overrun:
  497.         DEBUGF  2, "TX overrun\n"
  498.         inc     [ebx + device.packets_tx_ovr]
  499.         invoke  NetFree, [bufferptr]
  500.  
  501.         spin_unlock_irqrestore
  502.         or      eax, -1
  503.         ret
  504.  
  505. endp
  506.  
  507. ;;;;;;;;;;;;;;;;;;;;;;;
  508. ;;                   ;;
  509. ;; Interrupt handler ;;
  510. ;;                   ;;
  511. ;;;;;;;;;;;;;;;;;;;;;;;
  512. align 16
  513. int_handler:
  514.  
  515.         push    ebx esi edi
  516.  
  517.         mov     ebx, [esp+4*4]
  518.         DEBUGF  1,"INT for 0x%x\n", ebx
  519.  
  520. ; TODO? if we are paranoid, we can check that the value from ebx is present in the current device_list
  521.  
  522.         mov     edi, [ebx + device.mmio_addr]
  523.         mov     eax, [edi + ALX_ISR]
  524.         test    eax, eax
  525.         jz      .nothing
  526.  
  527.         or      eax, ALX_ISR_DIS
  528.         mov     [edi + ALX_ISR], eax    ; ACK interrupt
  529.         DEBUGF  1,"Status: %x\n", eax
  530.  
  531.         test    eax, ALX_ISR_TX_Q0
  532.         jz      .no_tx
  533.         DEBUGF  1,"TX interrupt\n"
  534.         pusha
  535.         stdcall alx_clean_tx_irq
  536.         popa
  537.   .no_tx:
  538.  
  539.         test    eax, ALX_ISR_RX_Q0
  540.         jz      .no_rx
  541.         DEBUGF  1,"RX interrupt\n"
  542.         pusha
  543.         stdcall alx_clean_rx_irq
  544.         popa
  545.  
  546.   .no_rx:
  547.         test    eax, ALX_ISR_PHY
  548.         jz      .no_phy
  549.         DEBUGF  1,"PHY interrupt\n"
  550.         pusha
  551. ; TODO: queue link check and disable this interrupt cause meanwhile??
  552.         stdcall alx_check_link
  553.         popa
  554.  
  555.   .no_phy:
  556.         mov     dword[edi + ALX_ISR], 0
  557.         pop     edi esi ebx
  558.         xor     eax, eax
  559.         inc     eax
  560.  
  561.         ret
  562.  
  563.   .nothing:
  564.         pop     edi esi ebx
  565.         xor     eax, eax
  566.  
  567.         ret
  568.  
  569. proc alx_identify_hw stdcall
  570.  
  571.         cmp     [ebx + device.pci_did], ALX_DEV_ID_AR8131
  572.         je      .alc
  573.  
  574.         cmp     [ebx + device.chip_rev], ALX_REV_C0
  575.         ja      .einval
  576.  
  577.         mov     [ebx + device.max_dma_chnl], 2
  578.         cmp     [ebx + device.chip_rev], ALX_REV_B0
  579.         jb      @f
  580.         mov     [ebx + device.max_dma_chnl], 4
  581.   @@:
  582.         xor     eax, eax
  583.         ret
  584.  
  585.   .einval:
  586.         DEBUGF  1, "Invalid revision 0x%x\n", [ebx + device.chip_rev]
  587.  
  588.         xor     eax, eax
  589.         dec     eax
  590.         ret
  591.  
  592.   .alc:
  593.         mov     [ebx + device.max_dma_chnl], 2
  594.         xor     eax, eax
  595.         ret
  596.  
  597. endp
  598.  
  599. proc udelay stdcall microseconds
  600.  
  601. ; FIXME
  602.  
  603.         push    esi ecx edx
  604.         xor     esi, esi
  605.         inc     esi
  606.         invoke  Sleep
  607.         pop     edx ecx esi
  608.  
  609.         ret
  610.  
  611. endp
  612.  
  613. proc alx_reset_pcie stdcall
  614.  
  615.         DEBUGF  1,"alx_reset_pcie\n"
  616.  
  617. ; Make the device a bus master
  618.         invoke  PciRead16, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
  619.         or      al, PCI_CMD_MASTER or PCI_CMD_MMIO or PCI_CMD_PIO
  620.         and     ax, not(PCI_CMD_INTX_DISABLE)
  621.         invoke  PciWrite16, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
  622.  
  623. ; Clear any powersaving setting
  624.         invoke  PciWrite16, [ebx + device.pci_bus], [ebx + device.pci_dev], 0x44, 0x0000        ;; FIXME
  625.  
  626. ; Mask some pcie error bits
  627.         mov     esi, [ebx + device.mmio_addr]
  628.         mov     eax, [esi + ALX_UE_SVRT]
  629.         and     eax, not(ALX_UE_SVRT_DLPROTERR or ALX_UE_SVRT_FCPROTERR)
  630.         mov     [esi + ALX_UE_SVRT], eax
  631.  
  632. ; pclk
  633.         mov     eax, [esi + ALX_MASTER]
  634.         or      eax, ALX_MASTER_WAKEN_25M
  635.         and     eax, not (ALX_MASTER_PCLKSEL_SRDS)
  636.         cmp     [ebx + device.chip_rev], ALX_REV_A1
  637.         ja      @f
  638.         test    [ebx + device.pci_rev], ALX_PCI_REVID_WITH_CR
  639.         jz      @f
  640.         or      eax, ALX_MASTER_PCLKSEL_SRDS
  641.   @@:
  642.         mov     [esi + ALX_MASTER], eax
  643.  
  644.         xor     eax, eax
  645.         ret
  646.  
  647. endp
  648.  
  649. proc alx_clean_tx_irq stdcall
  650.  
  651.         mov     eax, [ebx + device.txq_read_idx]
  652.         movzx   ecx, word[edi + ALX_TPD_PRI0_CIDX]
  653.  
  654.   .loop:
  655.         cmp     eax, ecx
  656.         je      .done
  657.  
  658.         DEBUGF  1,"Cleaning TX desc %u buffer 0x%x\n", eax, [ebx + device.tpd_ring_virt + eax*4]
  659.         push    eax ecx
  660.         invoke  NetFree, [ebx + device.tpd_ring_virt + eax*4]
  661.         pop     ecx eax
  662.         mov     [ebx + device.tpd_ring_virt + eax*4], 0
  663.  
  664.         inc     eax
  665.         and     eax, TX_RING_SIZE-1
  666.         jmp     .loop
  667.   .done:
  668.         mov     [ebx + device.txq_read_idx], eax
  669.  
  670.         ret
  671.  
  672. endp
  673.  
  674. proc alx_clean_rx_irq stdcall
  675.  
  676.         mov     ecx, [ebx + device.rxq_read_idx]
  677.   .loop:
  678.         shl     ecx, 2
  679.         lea     esi, [ebx + device.rrd_ring + ecx*4]
  680.         test    [esi + alx_rrd.word3], 1 shl RRD_UPDATED_SHIFT
  681.         jz      .done
  682.         and     [esi + alx_rrd.word3], not(1 shl RRD_UPDATED_SHIFT)
  683.         DEBUGF  1,"RRD=%u updated\n", [ebx + device.rxq_read_idx]
  684.  
  685.         mov     eax, [esi + alx_rrd.word0]
  686.         shr     eax, RRD_SI_SHIFT
  687.         and     eax, RRD_SI_MASK
  688.         cmp     eax, [ebx + device.rxq_read_idx]
  689. ;        jne     .error
  690.         DEBUGF  1,"RFD=%u\n", eax
  691.  
  692.         mov     eax, [esi + alx_rrd.word0]
  693.         shr     eax, RRD_NOR_SHIFT
  694.         and     eax, RRD_NOR_MASK
  695.         cmp     eax, 1
  696. ;        jne     .error
  697.  
  698.         mov     eax, [esi + alx_rrd.word3]
  699. ;        shr     eax, RRD_PKTLEN_SHIFT
  700.         and     eax, RRD_PKTLEN_MASK
  701.         sub     eax, 4                          ;;;;;
  702.         mov     edx, [ebx + device.rfd_ring_virt + ecx]
  703.         DEBUGF  1,"Received %u bytes in buffer 0x%x\n", eax, edx
  704.  
  705.         mov     [edx + NET_BUFF.length], eax
  706.         mov     [edx + NET_BUFF.device], ebx
  707.         mov     [edx + NET_BUFF.offset], NET_BUFF.data
  708.  
  709. ; Update stats
  710.         add     dword[ebx + device.bytes_rx], eax
  711.         adc     dword[ebx + device.bytes_rx + 4], 0
  712.         inc     [ebx + device.packets_rx]
  713.  
  714. ; Allocate new descriptor
  715.         push    esi ecx edx
  716.         invoke  NetAlloc, RX_BUFFER_SIZE+NET_BUFF.data
  717.         pop     edx ecx esi
  718.         test    eax, eax
  719.         jz      .rx_overrun
  720.         mov     [ebx + device.rfd_ring_virt + ecx], eax
  721.         add     eax, NET_BUFF.data
  722.         invoke  GetPhysAddr
  723.         mov     dword[ebx + device.rfd_ring + ecx*2], eax
  724.  
  725.         push    ecx ebx
  726.         push    .retaddr
  727.         push    edx
  728.         jmp     [EthInput]
  729.   .retaddr:
  730.         pop     ebx ecx
  731.  
  732.         shr     ecx, 2
  733.         inc     ecx
  734.         and     ecx, RX_RING_SIZE-1
  735.         jmp     .loop
  736.  
  737.   .rx_overrun:
  738.         DEBUGF  2,"RX FIFO overrun\n"
  739.         inc     [ebx + device.packets_rx_ovr]
  740.         shr     ecx, 2
  741.         inc     ecx
  742.         and     ecx, RX_RING_SIZE-1
  743.         jmp     .loop
  744.  
  745.   .done:
  746.         shr     ecx, 2
  747.         mov     [ebx + device.rxq_read_idx], ecx
  748.  
  749. ; Update producer index
  750.         mov     esi, [ebx + device.mmio_addr]
  751.         mov     [esi + ALX_RFD_PIDX], cx
  752.  
  753.         ret
  754.  
  755. endp
  756.  
  757. ; IN: ecx = additional bit flags (ALX_PMCTRL_L0S_EN, ALX_PMCTRL_L1_EN, ALX_PMCTRL_ASPM_FCEN)
  758. proc alx_enable_aspm stdcall
  759.  
  760.         DEBUGF  1,"alx_enable_aspm (0x%x)\n", ecx
  761.  
  762.         mov     esi, [ebx + device.mmio_addr]
  763.  
  764.         cmp     [ebx + device.pci_did], ALX_DEV_ID_AR8131
  765.         je      .alc_l1c
  766.  
  767.         cmp     [ebx + device.chip_rev], ALX_REV_A1
  768.         ja      @f
  769.         test    [ebx + device.pci_rev], ALX_PCI_REVID_WITH_CR
  770.         jz      @f
  771.         or      ecx, ALX_PMCTRL_L1_SRDS_EN or ALX_PMCTRL_L1_SRDSPLL_EN
  772.   @@:
  773.  
  774.         mov     eax, dword[esi + ALX_PMCTRL]
  775.         and     eax, not((ALX_PMCTRL_LCKDET_TIMER_MASK shl ALX_PMCTRL_LCKDET_TIMER_SHIFT) or \
  776.                          (ALX_PMCTRL_L1REQ_TO_MASK shl ALX_PMCTRL_L1REQ_TO_SHIFT) or \
  777.                          (ALX_PMCTRL_L1_TIMER_MASK shl ALX_PMCTRL_L1_TIMER_SHIFT) or \
  778.                          ALX_PMCTRL_L1_SRDS_EN or \
  779.                          ALX_PMCTRL_L1_SRDSPLL_EN or \
  780.                          ALX_PMCTRL_L1_BUFSRX_EN or \
  781.                          ALX_PMCTRL_SADLY_EN or \
  782.                          ALX_PMCTRL_HOTRST_WTEN or \
  783.                          ALX_PMCTRL_L0S_EN or \
  784.                          ALX_PMCTRL_L1_EN or \
  785.                          ALX_PMCTRL_ASPM_FCEN or \
  786.                          ALX_PMCTRL_TXL1_AFTER_L0S or \
  787.                          ALX_PMCTRL_RXL1_AFTER_L0S)
  788.         or      eax, (ALX_PMCTRL_LCKDET_TIMER_DEF shl ALX_PMCTRL_LCKDET_TIMER_SHIFT) or \
  789.                      (ALX_PMCTRL_RCVR_WT_1US or ALX_PMCTRL_L1_CLKSW_EN or ALX_PMCTRL_L1_SRDSRX_PWD) or \
  790.                      (ALX_PMCTRL_L1REG_TO_DEF shl ALX_PMCTRL_L1REQ_TO_SHIFT) or \
  791.                      (ALX_PMCTRL_L1_TIMER_16US shl ALX_PMCTRL_L1_TIMER_SHIFT)
  792.         or      eax, ecx
  793.         mov     dword[esi + ALX_PMCTRL], eax
  794.  
  795.         ret
  796.  
  797.   .alc_l1c:
  798.  
  799.         DEBUGF  1, "aspm for L1C\n"
  800.  
  801.         mov     esi, [ebx + device.mmio_addr]
  802.         mov     eax, dword[esi + ALX_PMCTRL]
  803.  
  804.         and     eax, not(ALX_PMCTRL_L0S_EN or ALX_PMCTRL_L1_EN or ALX_PMCTRL_ASPM_FCEN)
  805.         or      eax, (ALX_PMCTRL_LCKDET_TIMER_DEF shl ALX_PMCTRL_LCKDET_TIMER_SHIFT) ;\
  806.                 ;     or (0 shl ALX_PMCTRL_L1_TIMER_SHIFT)
  807.  
  808.         or      eax, ecx
  809.  
  810. ;;; FIXME if(linkon)
  811.  
  812.         or      eax, (ALX_PMCTRL_L1_SRDS_EN or ALX_PMCTRL_L1_SRDSPLL_EN or ALX_PMCTRL_L1_BUFSRX_EN)
  813.         and     eax, not(ALX_PMCTRL_L1_SRDSRX_PWD or ALX_PMCTRL_L1_CLKSW_EN or ALX_PMCTRL_L0S_EN or ALX_PMCTRL_L1_EN)
  814.  
  815. ;;
  816.  
  817.         mov     dword[esi + ALX_PMCTRL], eax
  818.  
  819.         ret
  820.  
  821. endp
  822.  
  823. proc alx_reset_mac stdcall
  824.  
  825.         DEBUGF  1, "reset mac\n"
  826.  
  827. ; disable all interrupts, RXQ/TXQ
  828.         mov     esi, [ebx + device.mmio_addr]
  829.         mov     dword[esi + ALX_MSIX_MASK], 0xffffffff
  830.         mov     dword[esi + ALX_IMR], 0x0
  831.         mov     dword[esi + ALX_ISR], ALX_ISR_DIS
  832.  
  833.         stdcall alx_stop_mac
  834.  
  835. ; mac reset workaround
  836.         mov     dword[esi + ALX_RFD_PIDX], 1
  837.  
  838. ; disable l0s/l1 before MAC reset on some chips
  839.         cmp     [ebx + device.chip_rev], ALX_REV_A1
  840.         ja      @f
  841.         test    [ebx + device.pci_rev], ALX_PCI_REVID_WITH_CR
  842.         jz      @f
  843.         mov     eax, [esi + ALX_PMCTRL]
  844.         mov     edx, eax
  845.         test    eax, ALX_PMCTRL_L1_EN or ALX_PMCTRL_L0S_EN
  846.         jz      @f
  847.         and     eax, not(ALX_PMCTRL_L1_EN or ALX_PMCTRL_L0S_EN)
  848.         mov     [esi + ALX_PMCTRL], eax
  849.   @@:
  850.  
  851. ; reset whole MAC safely
  852.         mov     eax, [esi + ALX_MASTER]
  853.         or      eax, ALX_MASTER_DMA_MAC_RST or ALX_MASTER_OOB_DIS
  854.         mov     [esi + ALX_MASTER], eax
  855.  
  856. ; make sure it's real idle
  857.         stdcall udelay, 10
  858.  
  859.         mov     ecx, ALX_DMA_MAC_RST_TO ; timeout
  860.   .loop1:
  861.         mov     eax, dword[esi + ALX_RFD_PIDX]
  862.         test    eax, eax
  863.         jz      @f
  864.  
  865.         stdcall udelay, 10
  866.  
  867.         dec     ecx
  868.         jnz     .loop1
  869.         jmp     .error
  870.   @@:
  871.  
  872.   .loop2:
  873.         mov     eax, dword[esi + ALX_MASTER]
  874.         test    eax, ALX_MASTER_DMA_MAC_RST
  875.         jz      @f
  876.  
  877.         stdcall udelay, 10
  878.  
  879.         dec     ecx
  880.         jnz     .loop2
  881.         jmp     .error
  882.   @@:
  883.  
  884. ; restore l0s/l1
  885.         cmp     [ebx + device.chip_rev], ALX_REV_A1
  886.         ja      @f
  887.         test    [ebx + device.pci_rev], ALX_PCI_REVID_WITH_CR
  888.         jz      @f
  889.         or      eax, ALX_MASTER_PCLKSEL_SRDS
  890.         mov     [esi + ALX_MASTER], eax
  891.         mov     [esi + ALX_PMCTRL], edx
  892.   @@:
  893.  
  894.         stdcall alx_reset_osc
  895.  
  896. ; clear Internal OSC settings, switching OSC by hw itself, disable isolate for rev A devices
  897.  
  898.         mov     eax, [esi + ALX_MISC3]
  899.         and     eax, not (ALX_MISC3_25M_BY_SW)
  900.         or      eax, ALX_MISC3_25M_NOTO_INTNL
  901.         mov     [esi + ALX_MISC3], eax
  902.  
  903.         mov     eax, [esi + ALX_MISC]
  904.         and     eax, not (ALX_MISC_INTNLOSC_OPEN)
  905.  
  906.         cmp     [ebx + device.chip_rev], ALX_REV_A1
  907.         ja      @f
  908.         and     eax, not ALX_MISC_ISO_EN
  909.   @@:
  910.         mov     [esi + ALX_MISC], eax
  911.  
  912.         stdcall udelay, 20
  913.  
  914. ; driver control speed/duplex, hash-alg
  915.         mov     eax, [ebx + device.rx_ctrl]
  916.         mov     [esi + ALX_MAC_CTRL], eax
  917.  
  918. ; clk sw
  919.         mov     eax, dword[esi + ALX_SERDES]
  920.         or      eax, ALX_SERDES_MACCLK_SLWDWN or ALX_SERDES_PHYCLK_SLWDWN
  921.         mov     dword[esi + ALX_SERDES], eax
  922.  
  923.         DEBUGF  1, "OK\n"
  924.         xor     eax, eax
  925.         ret
  926.  
  927.   .error:
  928.         DEBUGF  1, "error\n"
  929.         xor     eax, eax
  930.         dec     eax
  931.         ret
  932.  
  933. endp
  934.  
  935. proc alx_reset_phy stdcall
  936.  
  937.         DEBUGF  1, "Reset phy\n"
  938.  
  939.         mov     esi, [ebx + device.mmio_addr]
  940.  
  941.         mov     eax, dword [esi + ALX_PHY_CTRL]
  942.         DEBUGF 1, "read ALX_PHY_CTRL = %x\n", eax
  943.         and     eax, not (ALX_PHY_CTRL_DSPRST_OUT or ALX_PHY_CTRL_IDDQ or ALX_PHY_CTRL_GATE_25M or ALX_PHY_CTRL_POWER_DOWN or ALX_PHY_CTRL_CLS)
  944.         or      eax, ALX_PHY_CTRL_RST_ANALOG
  945.         or      eax, ALX_PHY_CTRL_HIB_PULSE or ALX_PHY_CTRL_HIB_EN ; assume pws is enabled
  946.  
  947.         DEBUGF 1, "write ALX_PHY_CTRL = %x\n", eax
  948.         mov     [esi + ALX_PHY_CTRL], eax
  949.  
  950.         stdcall udelay, 5
  951.  
  952.         or      eax, ALX_PHY_CTRL_DSPRST_OUT
  953.         mov     [esi + ALX_PHY_CTRL], eax
  954.  
  955.         stdcall udelay, 10
  956.  
  957.         or      eax, ALX_PHY_CTRL_DSPRST_OUT
  958.         DEBUGF 1, "write ALX_PHY_CTRL = %x\n", eax
  959.         mov     dword [esi + ALX_PHY_CTRL], eax
  960.  
  961.         stdcall udelay, 800
  962.  
  963. ; PHY power saving & hibernate
  964.         stdcall alx_write_phy_dbg, ALX_MIIDBG_LEGCYPS, ALX_LEGCYPS_DEF
  965.         stdcall alx_write_phy_dbg, ALX_MIIDBG_SYSMODCTRL, ALX_SYSMODCTRL_IECHOADJ_DEF
  966.         stdcall alx_write_phy_ext, ALX_MIIEXT_PCS, ALX_MIIEXT_VDRVBIAS, ALX_VDRVBIAS_DEF
  967.  
  968. ; EEE advertisement
  969.         mov     eax, [esi + ALX_LPI_CTRL]
  970.         and     eax, not (ALX_LPI_CTRL_EN)
  971.         mov     [esi + ALX_LPI_CTRL], eax
  972.         stdcall alx_write_phy_ext, ALX_MIIEXT_ANEG, ALX_MIIEXT_LOCAL_EEEADV, 0
  973.  
  974. ; PHY power saving
  975.         stdcall alx_write_phy_dbg, ALX_MIIDBG_TST10BTCFG, ALX_TST10BTCFG_DEF
  976.         stdcall alx_write_phy_dbg, ALX_MIIDBG_SRDSYSMOD, ALX_SRDSYSMOD_DEF
  977.         stdcall alx_write_phy_dbg, ALX_MIIDBG_TST100BTCFG, ALX_TST100BTCFG_DEF
  978.         stdcall alx_write_phy_dbg, ALX_MIIDBG_ANACTRL, ALX_ANACTRL_DEF
  979.         stdcall alx_read_phy_dbg, ALX_MIIDBG_GREENCFG2
  980.         and     eax, not ALX_GREENCFG2_GATE_DFSE_EN
  981.         stdcall alx_write_phy_dbg, ALX_MIIDBG_GREENCFG2, eax
  982. ; rtl8139c, 120m issue */
  983.         stdcall alx_write_phy_ext, ALX_MIIEXT_ANEG, ALX_MIIEXT_NLP78, ALX_MIIEXT_NLP78_120M_DEF
  984.         stdcall alx_write_phy_ext, ALX_MIIEXT_ANEG, ALX_MIIEXT_S3DIG10, ALX_MIIEXT_S3DIG10_DEF
  985.  
  986. ; TODO: link patch ?
  987.  
  988. ; set PHY interrupt mask
  989.         stdcall alx_read_phy_reg, ALX_MII_IER
  990.         or      eax, ALX_IER_LINK_UP or ALX_IER_LINK_DOWN
  991.         stdcall alx_write_phy_reg, ALX_MII_IER , eax
  992.  
  993.         DEBUGF  1, "OK\n"
  994.         xor     eax, eax
  995.         ret
  996.  
  997.   .error:
  998.         DEBUGF  1, "error\n"
  999.         xor     eax, eax
  1000.         dec     eax
  1001.         ret
  1002.  
  1003. endp
  1004.  
  1005. proc alx_set_macaddr stdcall
  1006.  
  1007.         mov     esi, [ebx + device.mmio_addr]
  1008.  
  1009.         mov     eax, dword[ebx + device.mac+2]
  1010.         bswap   eax
  1011.         mov     [esi + ALX_STAD0], eax
  1012.         mov     ax, word[ebx + device.mac]
  1013.         xchg    al, ah
  1014.         mov     [esi + ALX_STAD1], ax
  1015.  
  1016.  
  1017.         ret
  1018. endp
  1019.  
  1020. proc alx_enable_osc stdcall
  1021.  
  1022.         mov     esi, [ebx + device.mmio_addr]
  1023.  
  1024. ; rising edge
  1025.         mov     eax, dword[esi + ALX_MISC]
  1026.         and     eax, not ALX_MISC_INTNLOSC_OPEN
  1027.         mov     dword[esi + ALX_MISC], eax
  1028.         or      eax, ALX_MISC_INTNLOSC_OPEN
  1029.         mov     dword[esi + ALX_MISC], eax
  1030.  
  1031.         ret
  1032.  
  1033. endp
  1034.  
  1035. proc alx_reset_osc stdcall
  1036.  
  1037.         mov     esi, [ebx + device.mmio_addr]
  1038.  
  1039. ; clear Internal OSC settings, switching OSC by hw itself
  1040.         mov     eax, dword[esi + ALX_MISC3]
  1041.         and     eax, not ALX_MISC3_25M_BY_SW
  1042.         or      eax, ALX_MISC3_25M_NOTO_INTNL
  1043.         mov     dword[esi + ALX_MISC3], eax
  1044.  
  1045. ; clk from chipset may be unstable 1s after de-assert of
  1046. ; PERST, driver need re-calibrate before enter Sleep for WoL
  1047.         mov     eax, dword[esi + ALX_MISC]
  1048.         cmp     [ebx + device.chip_rev], ALX_REV_B0
  1049.         jb      .rev_A
  1050.  
  1051. ; restore over current protection def-val, this val could be reset by MAC-RST
  1052.         and     eax, not (ALX_MISC_PSW_OCP_MASK shl ALX_MISC_PSW_OCP_SHIFT)
  1053.         or      eax, ALX_MISC_PSW_OCP_DEF shl ALX_MISC_PSW_OCP_SHIFT
  1054. ; a 0->1 change will update the internal val of osc
  1055.         and     eax, not ALX_MISC_INTNLOSC_OPEN
  1056.         mov     dword[esi + ALX_MISC], eax
  1057.         or      eax, ALX_MISC_INTNLOSC_OPEN
  1058.         mov     dword[esi + ALX_MISC], eax
  1059.  
  1060. ; hw will automatically dis OSC after cab
  1061.         mov     eax, dword[esi + ALX_MSIC2]
  1062.         and     eax, not ALX_MSIC2_CALB_START
  1063.         mov     dword[esi + ALX_MSIC2], eax
  1064.         or      eax, ALX_MSIC2_CALB_START
  1065.         mov     dword[esi + ALX_MSIC2], eax
  1066.  
  1067.         stdcall udelay, 20
  1068.  
  1069.         ret
  1070.  
  1071.   .rev_A:
  1072.  
  1073. ;  disable isolate for rev A devices
  1074.         and     eax, not (ALX_MISC_ISO_EN)
  1075.         or      eax, ALX_MISC_INTNLOSC_OPEN
  1076.         mov     dword[esi + ALX_MISC], eax
  1077.         and     eax, not ALX_MISC_INTNLOSC_OPEN
  1078.         mov     dword[esi + ALX_MISC], eax
  1079.  
  1080.         stdcall udelay, 20
  1081.  
  1082.         ret
  1083.  
  1084. endp
  1085.  
  1086. proc alx_read_macaddr stdcall
  1087.  
  1088.         mov     esi, [ebx + device.mmio_addr]
  1089.         mov     eax, dword[esi + ALX_STAD0]
  1090.         bswap   eax
  1091.         mov     dword[ebx + device.mac + 2], eax
  1092.         mov     ax, word[esi + ALX_STAD1]
  1093.         xchg    al, ah
  1094.         mov     word[ebx + device.mac], ax
  1095.  
  1096.         DEBUGF  1,"MAC = %x-%x-%x-%x-%x-%x\n",\
  1097.         [ebx + device.mac+0]:2, [ebx + device.mac+1]:2, [ebx + device.mac+2]:2, [ebx + device.mac+3]:2, [ebx + device.mac+4]:2, [ebx + device.mac+5]:2
  1098.  
  1099. ; check if it is a valid MAC
  1100.         cmp     dword[ebx + device.mac], 0x0
  1101.         jne     @f
  1102.         cmp     word[ebx + device.mac + 4], 0x0
  1103.         je      .invalid
  1104.   @@:
  1105.         cmp     dword[ebx + device.mac], 0xffffffff
  1106.         jne     @f
  1107.         cmp     word[ebx + device.mac + 4], 0xffff
  1108.         je      .invalid
  1109.   @@:
  1110.         test    byte[ebx + device.mac + 5], 0x01        ; Multicast
  1111.         jnz     .invalid
  1112.   @@:
  1113.         xor     eax, eax
  1114.         ret
  1115.  
  1116.   .invalid:
  1117.         DEBUGF  1, "Invalid MAC!\n"
  1118.         xor     eax, eax
  1119.         inc     eax
  1120.         ret
  1121.  
  1122. endp
  1123.  
  1124. proc alx_get_perm_macaddr stdcall
  1125.  
  1126. ; try to get it from register first
  1127.         stdcall alx_read_macaddr
  1128.         test    eax, eax
  1129.         jz      .done
  1130.  
  1131. ; try to load from efuse
  1132.         mov     esi, [ebx + device.mmio_addr]
  1133.         mov     ecx, ALX_SLD_MAX_TO
  1134.   .loop1:
  1135.         mov     eax, dword[esi + ALX_SLD]
  1136.         test    eax, ALX_SLD_STAT or ALX_SLD_START
  1137.         jz      @f
  1138.  
  1139.         dec     ecx
  1140.         jz      .error
  1141.  
  1142.         push    esi ecx
  1143.         xor     esi, esi
  1144.         inc     esi
  1145.         invoke  Sleep
  1146.         pop     ecx esi
  1147.         jmp     .loop1
  1148.   @@:
  1149.         or      eax, ALX_SLD_START
  1150.         mov     dword[esi + ALX_SLD], eax
  1151.  
  1152.         mov     ecx, ALX_SLD_MAX_TO
  1153.   .loop2:
  1154.         mov     eax, dword[esi + ALX_SLD]
  1155.         test    eax, ALX_SLD_START
  1156.         jz      @f
  1157.  
  1158.         dec     ecx
  1159.         jz      .error
  1160.  
  1161.         push    esi ecx
  1162.         xor     esi, esi
  1163.         inc     esi
  1164.         invoke  Sleep
  1165.         pop     ecx esi
  1166.         jmp     .loop2
  1167.   @@:
  1168.  
  1169.         stdcall alx_read_macaddr
  1170.         test    eax, eax
  1171.         jz      .done
  1172.  
  1173. ; try to load from flash/eeprom (if present)
  1174.         set_io  [ebx + device.io_addr], 0
  1175.         set_io  [ebx + device.io_addr], ALX_EFLD
  1176.         in      eax, dx
  1177.         test    eax, ALX_EFLD_F_EXIST or ALX_EFLD_E_EXIST
  1178.         jz      .error
  1179.  
  1180.         mov     ecx, ALX_SLD_MAX_TO
  1181.   .loop3:
  1182.         in      eax, dx
  1183.         test    eax, ALX_EFLD_STAT or ALX_EFLD_START
  1184.         jz      @f
  1185.  
  1186.         dec     ecx
  1187.         jz      .error
  1188.  
  1189.         push    esi edx ecx
  1190.         xor     esi, esi
  1191.         inc     esi
  1192.         invoke  Sleep
  1193.         pop     ecx edx esi
  1194.         jmp     .loop3
  1195.   @@:
  1196.         or      eax, ALX_EFLD_START
  1197.         out     dx, eax
  1198.  
  1199.         mov     ecx, ALX_SLD_MAX_TO
  1200.   .loop4:
  1201.         in      eax, dx
  1202.         test    eax, ALX_EFLD_START
  1203.         jz      @f
  1204.  
  1205.         dec     ecx
  1206.         jz      .error
  1207.  
  1208.         push    esi edx ecx
  1209.         xor     esi, esi
  1210.         inc     esi
  1211.         invoke  Sleep
  1212.         pop     ecx edx esi
  1213.         jmp     .loop4
  1214.   @@:
  1215.  
  1216.         stdcall alx_read_macaddr
  1217.         test    eax, eax
  1218.         jz      .done
  1219.  
  1220.   .error:
  1221.         DEBUGF  1, "error obtaining MAC\n"
  1222.         xor     eax, eax
  1223.         dec     eax
  1224.         ret
  1225.  
  1226.   .done:
  1227.         DEBUGF  1, "MAC OK\n"
  1228.         xor     eax, eax
  1229.         ret
  1230.  
  1231. endp
  1232.  
  1233. proc alx_stop_mac stdcall
  1234.  
  1235.         DEBUGF  1,"alx_stop_mac\n"
  1236.  
  1237.         mov     esi, [ebx + device.mmio_addr]
  1238.  
  1239.         mov     eax, dword[esi + ALX_RXQ0]
  1240.         and     eax, not ALX_RXQ0_EN
  1241.         mov     dword[esi + ALX_RXQ0], eax
  1242.  
  1243.         mov     eax, dword[esi + ALX_TXQ0]
  1244.         and     eax, not ALX_TXQ0_EN
  1245.         mov     dword[esi + ALX_TXQ0], eax
  1246.  
  1247.         stdcall udelay, 40
  1248.  
  1249.         mov     eax, [ebx + device.rx_ctrl]
  1250.         and     eax, not(ALX_MAC_CTRL_TX_EN or ALX_MAC_CTRL_RX_EN)
  1251.         mov     [ebx + device.rx_ctrl], eax
  1252.         mov     [esi + ALX_MAC_CTRL], eax
  1253.  
  1254.         mov     ecx, ALX_DMA_MAC_RST_TO
  1255.   .loop:
  1256.         mov     eax, [esi + ALX_MAC_STS]
  1257.         test    eax, ALX_MAC_STS_IDLE
  1258.         jz      .done
  1259.  
  1260.         stdcall udelay, 10
  1261.  
  1262.         dec     ecx
  1263.         jnz     .loop
  1264.  
  1265.         DEBUGF  1,"alx_stop_mac timeout!\n"
  1266.         xor     eax, eax
  1267.         dec     eax
  1268.         ret
  1269.  
  1270.   .done:
  1271.         DEBUGF  1,"alx_stop_mac ok\n"
  1272.         xor     eax, eax
  1273.         ret
  1274.  
  1275. endp
  1276.  
  1277. proc alx_start_mac stdcall
  1278.  
  1279.         DEBUGF  1,"alx_start_mac\n"
  1280.  
  1281.         mov     esi, [ebx + device.mmio_addr]
  1282.  
  1283.         mov     eax, dword[esi + ALX_RXQ0]
  1284.         or      eax, ALX_RXQ0_EN
  1285.         mov     dword[esi + ALX_RXQ0], eax
  1286.  
  1287.         mov     eax, dword[esi + ALX_TXQ0]
  1288.         or      eax, ALX_TXQ0_EN
  1289.         mov     dword[esi + ALX_TXQ0], eax
  1290.  
  1291.         mov     eax, [ebx + device.rx_ctrl]
  1292.         or      eax, ALX_MAC_CTRL_TX_EN or ALX_MAC_CTRL_RX_EN
  1293.         and     eax, not ALX_MAC_CTRL_FULLD
  1294.         test    [ebx + device.state], ETH_LINK_FULL_DUPLEX
  1295.         jz      .no_fd
  1296.         or      eax, ALX_MAC_CTRL_FULLD
  1297.   .no_fd:
  1298.         and     eax, not (ALX_MAC_CTRL_SPEED_MASK shl ALX_MAC_CTRL_SPEED_SHIFT)
  1299.         mov     ecx, [ebx + device.state]
  1300.         and     ecx, ETH_LINK_SPEED_MASK
  1301.         cmp     ecx, ETH_LINK_SPEED_1G
  1302.         jne      .10_100
  1303.         or      eax, (ALX_MAC_CTRL_SPEED_1000 shl ALX_MAC_CTRL_SPEED_SHIFT)
  1304.         jmp     .done
  1305.  
  1306.   .10_100:
  1307.         or      eax, (ALX_MAC_CTRL_SPEED_10_100 shl ALX_MAC_CTRL_SPEED_SHIFT)
  1308.  
  1309.   .done:
  1310.         DEBUGF  1,"mac ctrl=0x%x\n", eax
  1311.         mov     [ebx + device.rx_ctrl], eax
  1312.         mov     [esi + ALX_MAC_CTRL], eax
  1313.  
  1314.         ret
  1315.  
  1316. endp
  1317.  
  1318. proc alx_init_ring_ptrs stdcall
  1319.  
  1320.         DEBUGF  1,"alx_init_ring_ptrs\n"
  1321.  
  1322.         mov     esi, [ebx + device.mmio_addr]
  1323.  
  1324. ; Receive descriptors
  1325.         mov     [ebx + device.rxq_read_idx], 0
  1326.         mov     [ebx + device.rxq_write_idx], 0
  1327. ;        mov     [ebx + device.rxq_rrd_read_idx], 0
  1328.  
  1329.         mov     dword[esi + ALX_RX_BASE_ADDR_HI], 0
  1330.  
  1331.         lea     eax, [ebx + device.rrd_ring]
  1332.         invoke  GetPhysAddr
  1333.         mov     dword[esi + ALX_RRD_ADDR_LO], eax
  1334.         mov     dword[esi + ALX_RRD_RING_SZ], RX_RING_SIZE
  1335.  
  1336.         lea     eax, [ebx + device.rfd_ring]
  1337.         invoke  GetPhysAddr
  1338.         mov     dword[esi + ALX_RFD_ADDR_LO], eax
  1339.         mov     dword[esi + ALX_RFD_RING_SZ], RX_RING_SIZE
  1340.         mov     dword[esi + ALX_RFD_BUF_SZ], RX_BUFFER_SIZE
  1341.  
  1342. ; Transmit descriptors
  1343.         mov     [ebx + device.txq_read_idx], 0
  1344.         mov     [ebx + device.txq_write_idx], 0
  1345.  
  1346.         mov     dword[esi + ALX_TX_BASE_ADDR_HI], 0
  1347.  
  1348.         lea     eax, [ebx + device.tpd_ring]
  1349.         invoke  GetPhysAddr
  1350.         mov     dword[esi + ALX_TPD_PRI0_ADDR_LO], eax
  1351.         mov     dword[esi + ALX_TPD_RING_SZ], TX_RING_SIZE
  1352.  
  1353. ; Load these pointers into the chip
  1354.         mov     dword[esi + ALX_SRAM9], ALX_SRAM_LOAD_PTR
  1355.  
  1356.         xor     eax, eax
  1357.  
  1358.         ret
  1359.  
  1360. endp
  1361.  
  1362. proc alx_alloc_rings stdcall
  1363.  
  1364.         DEBUGF  1,"alx_alloc_rings\n"
  1365.  
  1366.         and     [ebx + device.int_mask], not ALX_ISR_ALL_QUEUES
  1367.         or      [ebx + device.int_mask], ALX_ISR_TX_Q0 or ALX_ISR_RX_Q0
  1368.         stdcall alx_reinit_rings
  1369.  
  1370.         ret
  1371.  
  1372. endp
  1373.  
  1374. proc alx_reinit_rings stdcall
  1375.  
  1376.         DEBUGF  1,"alx_reinit_rings\n"
  1377.  
  1378.         stdcall alx_free_rx_ring
  1379.         stdcall alx_init_ring_ptrs
  1380.         stdcall alx_refill_rx_ring
  1381.  
  1382.         ret
  1383.  
  1384. endp
  1385.  
  1386. proc alx_refill_rx_ring stdcall
  1387.  
  1388.         DEBUGF  1,"alx_refill_rx_ring\n"
  1389.  
  1390.         mov     ecx, [ebx + device.rxq_write_idx]
  1391.   .loop:
  1392.         cmp     dword[ebx + device.rfd_ring+ecx*sizeof.alx_rfd + alx_rfd.addr_l], 0
  1393.         jne     .done
  1394.  
  1395.         invoke  NetAlloc, NET_BUFF.data+RX_BUFFER_SIZE
  1396.         test    eax, eax
  1397.         jz      .done
  1398.         mov     [ebx + device.rfd_ring_virt + ecx*4], eax
  1399.         add     eax, NET_BUFF.data
  1400.         invoke  GetPhysAddr
  1401.         mov     dword[ebx + device.rfd_ring+ecx*sizeof.alx_rfd + alx_rfd.addr_l], eax
  1402.         mov     dword[ebx + device.rfd_ring+ecx*sizeof.alx_rfd + alx_rfd.addr_h], 0
  1403.  
  1404.         mov     eax, ecx
  1405.         inc     ecx
  1406.         and     ecx, RX_RING_SIZE - 1
  1407.  
  1408.         cmp     ecx, [ebx + device.rxq_read_idx]
  1409.         jne     .loop
  1410.  
  1411.         mov     ecx, eax
  1412.  
  1413.   .done:
  1414.         cmp     ecx, [ebx + device.rxq_write_idx]
  1415.         je      .none
  1416.  
  1417.         mov     [ebx + device.rxq_write_idx], ecx
  1418.         mov     esi, [ebx + device.mmio_addr]
  1419.         mov     [esi + ALX_RFD_PIDX], cx
  1420.  
  1421.   .none:
  1422.         xor     eax, eax
  1423.  
  1424.         ret
  1425.  
  1426. endp
  1427.  
  1428. proc alx_free_rx_ring stdcall
  1429.  
  1430.         DEBUGF  1,"alx_free_rx_ring\n"
  1431.  
  1432.         xor     ecx, ecx
  1433.   .loop:
  1434.         mov     eax, [ebx + device.rfd_ring_virt + ecx*4]
  1435.         test    eax, eax
  1436.         jz      .next
  1437.  
  1438.         invoke  NetFree, eax
  1439.  
  1440.         xor     eax, eax
  1441.         mov     dword[ebx + device.rfd_ring+ecx*sizeof.alx_rfd + alx_rfd.addr_l], eax
  1442.         mov     dword[ebx + device.rfd_ring+ecx*sizeof.alx_rfd + alx_rfd.addr_h], eax
  1443.         mov     [ebx + device.rfd_ring_virt + ecx*4], eax
  1444.  
  1445.   .next:
  1446.         inc     ecx
  1447.         cmp     ecx, RX_RING_SIZE
  1448.         jb      .loop
  1449.  
  1450.         ret
  1451.  
  1452. endp
  1453.  
  1454. proc alx_configure stdcall
  1455.  
  1456.         DEBUGF  1,"alx_configure\n"
  1457.  
  1458.         stdcall alx_configure_basic
  1459.         stdcall alx_disable_rss
  1460.         call    alx_set_rx_mode
  1461.  
  1462.         mov     esi, [ebx + device.mmio_addr]
  1463.         mov     eax, [ebx + device.rx_ctrl]
  1464.         mov     [esi + ALX_MAC_CTRL], eax
  1465.  
  1466.         xor     eax, eax
  1467.         ret
  1468.  
  1469. endp
  1470.  
  1471. proc alx_irq_enable stdcall
  1472.  
  1473.         DEBUGF  1,"alx_irq_enable\n"
  1474.  
  1475.         mov     esi, [ebx + device.mmio_addr]
  1476.         mov     dword[esi + ALX_ISR], 0
  1477.         mov     eax, [ebx + device.int_mask]
  1478.         mov     [esi + ALX_IMR], eax
  1479.  
  1480.         stdcall alx_post_write
  1481.  
  1482.         ret
  1483.  
  1484. endp
  1485.  
  1486. proc alx_irq_disable stdcall
  1487.  
  1488.         DEBUGF  1,"alx_irq_disable\n"
  1489.  
  1490.         mov     esi, [ebx + device.mmio_addr]
  1491.         mov     dword[esi + ALX_ISR], ALX_ISR_DIS
  1492.         mov     dword[esi + ALX_IMR], 0
  1493.  
  1494.         stdcall alx_post_write
  1495.  
  1496.         ret
  1497.  
  1498. endp
  1499.  
  1500. proc alx_post_write stdcall
  1501.  
  1502.         push    eax
  1503.         mov     esi, [ebx + device.mmio_addr]
  1504.         mov     eax, [esi]
  1505.         pop     eax
  1506.  
  1507.         ret
  1508.  
  1509. endp
  1510.  
  1511. proc alx_configure_basic stdcall
  1512.  
  1513.         DEBUGF  1,"alx_configure_basic\n"
  1514.  
  1515.         mov     esi, [ebx + device.mmio_addr]
  1516.  
  1517.         stdcall alx_set_macaddr
  1518.  
  1519.         mov     dword[esi + ALX_CLK_GATE], ALX_CLK_GATE_ALL
  1520.  
  1521. ; idle timeout to switch clk_125M
  1522.         cmp     [ebx + device.chip_rev], ALX_REV_B0
  1523.         jb      @f
  1524.         mov     dword[esi + ALX_IDLE_DECISN_TIMER], ALX_IDLE_DECISN_TIMER_DEF
  1525.   @@:
  1526.  
  1527.         mov     dword[esi + ALX_SMB_TIMER], SMB_TIMER * 500
  1528.  
  1529. ; Interrupt moderation
  1530.         mov     eax, [esi + ALX_MASTER]
  1531.         or      eax, ALX_MASTER_IRQMOD2_EN or ALX_MASTER_IRQMOD1_EN or ALX_MASTER_SYSALVTIMER_EN
  1532.         mov     [esi + ALX_MASTER], eax
  1533.  
  1534. ; Set interupt moderator timer (max interupts per second)
  1535.         mov     dword[esi + ALX_IRQ_MODU_TIMER], ((IMT) shl ALX_IRQ_MODU_TIMER1_SHIFT) or ((IMT / 2) shl ALX_IRQ_MODU_TIMER2_SHIFT)
  1536.  
  1537. ; Interrupt re-trigger timeout
  1538.         mov     dword[esi + ALX_INT_RETRIG], ALX_INT_RETRIG_TO
  1539.  
  1540. ; tpd threshold to trig int
  1541.         mov     dword[esi + ALX_TINT_TPD_THRSHLD], ITH_TPD
  1542.         mov     dword[esi + ALX_TINT_TIMER], IMT
  1543.  
  1544.         mov     dword[esi + ALX_MTU], RX_BUFFER_SIZE + 8 ;;;;
  1545.  
  1546.         mov     dword[esi + ALX_TXQ1], (((RX_BUFFER_SIZE + 8 + 7) shr 3) or ALX_TXQ1_ERRLGPKT_DROP_EN)
  1547.  
  1548. ; rxq, flow control
  1549.  
  1550. ; TODO set ALX_RXQ2
  1551.  
  1552. ; RXQ0
  1553.         mov     eax, (ALX_RXQ0_NUM_RFD_PREF_DEF shl ALX_RXQ0_NUM_RFD_PREF_SHIFT) \
  1554.                 or (ALX_RXQ0_RSS_MODE_DIS shl ALX_RXQ0_RSS_MODE_SHIFT) \
  1555.                 or (ALX_RXQ0_IDT_TBL_SIZE_DEF shl ALX_RXQ0_IDT_TBL_SIZE_SHIFT) \
  1556.                 or ALX_RXQ0_RSS_HSTYP_ALL or ALX_RXQ0_RSS_HASH_EN or ALX_RXQ0_IPV6_PARSE_EN
  1557.  
  1558.         test    [ebx + device.pci_did], 1       ;;; FIXME: is gigabit device?
  1559.         jz      @f
  1560.         or      eax, ALX_RXQ0_ASPM_THRESH_100M shl ALX_RXQ0_ASPM_THRESH_SHIFT
  1561.   @@:
  1562.         mov     [esi + ALX_RXQ0], eax
  1563.  
  1564. ; DMA
  1565.         max_payload equ 2               ;;;; FIXME
  1566.  
  1567.         mov     eax, [esi + ALX_DMA]            ; Read and ignore?
  1568.         ; Pre-B0 devices have 2 DMA channels
  1569.         mov     eax, (ALX_DMA_RORDER_MODE_OUT shl ALX_DMA_RORDER_MODE_SHIFT) \
  1570.                 or ALX_DMA_RREQ_PRI_DATA \
  1571.                 or (max_payload shl ALX_DMA_RREQ_BLEN_SHIFT) \
  1572.                 or (ALX_DMA_WDLY_CNT_DEF shl ALX_DMA_WDLY_CNT_SHIFT ) \
  1573.                 or (ALX_DMA_RDLY_CNT_DEF shl ALX_DMA_RDLY_CNT_SHIFT ) \
  1574.                 or ((2-1) shl ALX_DMA_RCHNL_SEL_SHIFT)
  1575.  
  1576.         cmp     [ebx + device.chip_rev], ALX_REV_B0
  1577.         jb      @f
  1578.         ; B0 and newer have 4 DMA channels
  1579.         mov     eax, (ALX_DMA_RORDER_MODE_OUT shl ALX_DMA_RORDER_MODE_SHIFT) \
  1580.                 or ALX_DMA_RREQ_PRI_DATA \
  1581.                 or (max_payload shl ALX_DMA_RREQ_BLEN_SHIFT) \
  1582.                 or (ALX_DMA_WDLY_CNT_DEF shl ALX_DMA_WDLY_CNT_SHIFT ) \
  1583.                 or (ALX_DMA_RDLY_CNT_DEF shl ALX_DMA_RDLY_CNT_SHIFT ) \
  1584.                 or ((4-1) shl ALX_DMA_RCHNL_SEL_SHIFT)
  1585.   @@:
  1586.         mov     [esi + ALX_DMA], eax
  1587.  
  1588. ; default multi-tx-q weights
  1589.         mov      eax, (ALX_WRR_PRI_RESTRICT_NONE shl ALX_WRR_PRI_SHIFT) \
  1590.                  or (4 shl ALX_WRR_PRI0_SHIFT) \
  1591.                  or (4 shl ALX_WRR_PRI1_SHIFT) \
  1592.                  or (4 shl ALX_WRR_PRI2_SHIFT) \
  1593.                  or (4 shl ALX_WRR_PRI3_SHIFT)
  1594.         mov      [esi + ALX_WRR], eax
  1595.  
  1596.         ret
  1597.  
  1598. endp
  1599.  
  1600. proc alx_disable_rss stdcall
  1601.  
  1602.         DEBUGF  1,"alx_disable_rss\n"
  1603.  
  1604.         mov     esi, [ebx + device.mmio_addr]
  1605.  
  1606.         mov     eax, [esi + ALX_RXQ0]
  1607.         and     eax, not (ALX_RXQ0_RSS_HASH_EN)
  1608.         mov     [esi + ALX_RXQ0] , eax
  1609.  
  1610.         ret
  1611.  
  1612. endp
  1613.  
  1614. proc alx_set_rx_mode stdcall
  1615.  
  1616.         DEBUGF  1,"__alx_set_rx_mode\n"
  1617.  
  1618.         mov     esi, [ebx + device.mmio_addr]
  1619.  
  1620. ; TODO: proper multicast
  1621.  
  1622. ;        if (!(netdev->flags & IFF_ALLMULTI)) {
  1623. ;                netdev_for_each_mc_addr(ha, netdev)
  1624. ;                        alx_add_mc_addr(hw, ha->addr, mc_hash);
  1625. ;
  1626. ;                alx_write_mem32(hw, ALX_HASH_TBL0, mc_hash[0]);
  1627. ;                alx_write_mem32(hw, ALX_HASH_TBL1, mc_hash[1]);
  1628. ;        }
  1629.  
  1630.         mov     eax, [ebx + device.rx_ctrl]
  1631.         or      eax, ALX_MAC_CTRL_PROMISC_EN or ALX_MAC_CTRL_MULTIALL_EN        ; FIXME: dont force promiscous mode..
  1632.         mov     [ebx + device.rx_ctrl], eax
  1633.         mov     dword[esi + ALX_MAC_CTRL], eax
  1634.  
  1635.         ret
  1636.  
  1637. endp
  1638.  
  1639. proc alx_check_link stdcall
  1640.  
  1641.         stdcall alx_clear_phy_intr
  1642.  
  1643.         mov     edx, [ebx + device.state]
  1644.  
  1645.         stdcall alx_get_phy_link
  1646.         cmp     eax, 0
  1647.         jl      .reset
  1648.  
  1649.         mov     esi, [ebx + device.mmio_addr]
  1650.  
  1651.         spin_lock_irqsave
  1652.         or      [ebx + device.int_mask], ALX_ISR_PHY
  1653.         mov     eax, [ebx + device.int_mask]
  1654.         mov     [esi + ALX_IMR], eax
  1655.         spin_unlock_irqrestore
  1656.  
  1657.         cmp     edx, [ebx + device.state]
  1658.         je      .no_change
  1659.  
  1660.         cmp     [ebx + device.state], ETH_LINK_DOWN
  1661.         je      .link_down
  1662.  
  1663.         stdcall alx_post_phy_link
  1664.         mov     ecx, (ALX_PMCTRL_L0S_EN or ALX_PMCTRL_L1_EN or ALX_PMCTRL_ASPM_FCEN)
  1665.         stdcall alx_enable_aspm
  1666.         stdcall alx_start_mac
  1667.  
  1668.         invoke  NetLinkChanged
  1669.  
  1670.         ret
  1671.  
  1672.   .no_change:
  1673.         DEBUGF  1, "link state unchanged\n"
  1674.  
  1675.         ret
  1676.  
  1677.   .link_down:
  1678. ; Link is now down
  1679.  
  1680.         stdcall alx_reset_mac
  1681.         test    eax, eax
  1682.         jnz     .reset
  1683.  
  1684.         stdcall alx_irq_disable
  1685.  
  1686. ; MAC reset causes all HW settings to be lost, restore all
  1687.         stdcall alx_reinit_rings
  1688.         test    eax, eax
  1689.         jnz     .reset
  1690.  
  1691.         stdcall alx_configure
  1692.         mov     ecx, (ALX_PMCTRL_L1_EN or ALX_PMCTRL_ASPM_FCEN)
  1693.         stdcall alx_enable_aspm
  1694.         stdcall alx_post_phy_link
  1695.         stdcall alx_irq_enable
  1696.  
  1697.         invoke  NetLinkChanged
  1698.  
  1699.         ret
  1700.  
  1701.   .reset:
  1702.         DEBUGF  1, "alx_schedule_reset\n"
  1703. ;;;        stdcall alx_schedule_reset
  1704.  
  1705.         ret
  1706.  
  1707. endp
  1708.  
  1709. proc alx_post_phy_link stdcall
  1710.  
  1711.         DEBUGF  1, "alx_post_phy_link\n"
  1712.  
  1713.         cmp     [ebx + device.chip_rev], ALX_REV_B0
  1714.         ja      .done
  1715.  
  1716.         cmp     [ebx + device.state], ETH_LINK_UNKNOWN
  1717.         jae     @f
  1718.  
  1719. ; TODO: vendor hocus-pocus to tune the PHY according the detected cable length
  1720.         stdcall alx_write_phy_dbg, ALX_MIIDBG_AZ_ANADECT, ALX_AZ_ANADECT_DEF
  1721.         stdcall alx_read_phy_ext, ALX_MIIEXT_AFE, ALX_MIIEXT_ANEG
  1722.         and     eax, not (ALX_AFE_10BT_100M_TH)
  1723.         stdcall alx_write_phy_ext, ALX_MIIEXT_AFE, ALX_MIIEXT_ANEG, eax
  1724.  
  1725.         ret
  1726.   @@:
  1727.  
  1728.   .done:
  1729.  
  1730.         ret
  1731.  
  1732. endp
  1733.  
  1734. proc alx_clear_phy_intr stdcall
  1735.  
  1736.         DEBUGF  1,"alx_clear_phy_intr\n"
  1737.         stdcall alx_read_phy_reg, ALX_MII_ISR
  1738.  
  1739.         ret
  1740.  
  1741. endp
  1742.  
  1743. proc alx_get_phy_link stdcall
  1744.  
  1745.         DEBUGF  1,"alx_get_phy_link\n"
  1746.  
  1747.         stdcall alx_read_phy_reg, MII_BMSR
  1748.         stdcall alx_read_phy_reg, MII_BMSR
  1749.  
  1750.         mov     [ebx + device.state], ETH_LINK_DOWN
  1751.  
  1752.         test    ax, BMSR_LSTATUS
  1753.         jnz     @f
  1754.         DEBUGF  1,"link is down\n"
  1755.         xor     eax, eax
  1756.         ret
  1757.   @@:
  1758.         stdcall alx_read_phy_reg, ALX_MII_GIGA_PSSR
  1759.         test    ax, ALX_GIGA_PSSR_SPD_DPLX_RESOLVED
  1760.         jz      .wrong_speed
  1761.  
  1762.         DEBUGF  1,"link is up\n"
  1763.  
  1764.         test    ax, ALX_GIGA_PSSR_DPLX
  1765.         jz      @f
  1766.         or      [ebx + device.state], ETH_LINK_FULL_DUPLEX
  1767.         DEBUGF  1,"full duplex\n"
  1768.   @@:
  1769.  
  1770.         and     ax, ALX_GIGA_PSSR_SPEED
  1771.         cmp     ax, ALX_GIGA_PSSR_1000MBS
  1772.         jne     @f
  1773.         or      [ebx + device.state], ETH_LINK_SPEED_1G
  1774.         DEBUGF  1,"1 gigabit\n"
  1775.         ret
  1776.  
  1777.   @@:
  1778.         cmp     ax, ALX_GIGA_PSSR_100MBS
  1779.         jne     @f
  1780.         or      [ebx + device.state], ETH_LINK_SPEED_100M
  1781.         DEBUGF  1,"100 Mbit\n"
  1782.         ret
  1783.  
  1784.   @@:
  1785.         cmp     ax, ALX_GIGA_PSSR_10MBS
  1786.         jne     @f
  1787.         or      [ebx + device.state], ETH_LINK_SPEED_10M
  1788.         DEBUGF  1,"10 Mbit\n"
  1789.         ret
  1790.  
  1791.   @@:
  1792.         mov     [ebx + device.state], ETH_LINK_UNKNOWN
  1793.         DEBUGF  1,"speed unknown\n"
  1794.         ret
  1795.  
  1796.   .wrong_speed:
  1797.         DEBUGF  1,"wrong speed\n"
  1798.         xor     eax, eax
  1799.         dec     eax
  1800.         ret
  1801.  
  1802. endp
  1803.  
  1804. proc alx_read_phy_reg stdcall, reg:dword
  1805.  
  1806. ; FIXME: fixed clock
  1807.  
  1808.         DEBUGF  1,"alx_read_phy_reg reg=0x%x\n", [reg]:4
  1809.  
  1810.         mov     esi, [ebx + device.mmio_addr]
  1811.  
  1812.         mov     eax, [reg]
  1813.         shl     eax, ALX_MDIO_REG_SHIFT
  1814.         or      eax, ALX_MDIO_SPRES_PRMBL or (ALX_MDIO_CLK_SEL_25MD4 shl ALX_MDIO_CLK_SEL_SHIFT) or ALX_MDIO_START or ALX_MDIO_OP_READ
  1815.         mov     dword[esi + ALX_MDIO], eax
  1816.  
  1817.         mov     ecx, ALX_MDIO_MAX_AC_TO
  1818.   .loop:
  1819.         mov     eax, dword[esi + ALX_MDIO]
  1820.         test    eax, ALX_MDIO_BUSY
  1821.         jz      .ready
  1822.  
  1823.         stdcall udelay, 10
  1824.  
  1825.         dec     ecx
  1826.         jnz     .loop
  1827.  
  1828.         DEBUGF  1,"alx_read_phy_reg read timeout!\n"
  1829.         xor     eax, eax
  1830.         dec     eax
  1831.         ret
  1832.  
  1833.   .ready:
  1834. ;        shr     eax, ALX_MDIO_DATA_SHIFT
  1835.         and     eax, ALX_MDIO_DATA_MASK
  1836.  
  1837.         DEBUGF  1,"alx_read_phy_reg data=0x%x\n", eax:4
  1838.  
  1839.         ret
  1840.  
  1841. endp
  1842.  
  1843. proc  alx_read_phy_ext stdcall, dev:dword, reg:dword
  1844.  
  1845. ; FIXME: fixed clock
  1846.  
  1847.         DEBUGF  1,"alx_read_phy_ext dev=0x%x reg=0x%x\n", [dev]:4, [reg]:4
  1848.  
  1849.         mov     esi, [ebx + device.mmio_addr]
  1850.  
  1851.         mov     eax, [dev]
  1852.         shl     eax, ALX_MDIO_EXTN_DEVAD_SHIFT
  1853.         mov     ax, word[reg]
  1854. ;        shl     eax, ALX_MDIO_EXTN_REG_SHIFT
  1855.         mov     dword[esi + ALX_MDIO_EXTN], eax
  1856.  
  1857.         mov     eax, ALX_MDIO_SPRES_PRMBL or (ALX_MDIO_CLK_SEL_25MD4 shl ALX_MDIO_CLK_SEL_SHIFT) or ALX_MDIO_START or ALX_MDIO_OP_READ or ALX_MDIO_MODE_EXT
  1858.         mov     dword[esi + ALX_MDIO], eax
  1859.  
  1860.         mov     ecx, ALX_MDIO_MAX_AC_TO
  1861.   .loop:
  1862.         mov     eax, dword[esi + ALX_MDIO]
  1863.         test    eax, ALX_MDIO_BUSY
  1864.         jz      .ready
  1865.  
  1866.         stdcall udelay, 10
  1867.  
  1868.         dec     ecx
  1869.         jnz     .loop
  1870.  
  1871.         DEBUGF  1,"alx_read_phy_ext read timeout!\n"
  1872.         xor     eax, eax
  1873.         dec     eax
  1874.         ret
  1875.  
  1876.   .ready:
  1877. ;        shr     eax, ALX_MDIO_DATA_SHIFT
  1878.         and     eax, ALX_MDIO_DATA_MASK
  1879.  
  1880.         DEBUGF  1,"alx_read_phy_ext data=0x%x\n", eax:4
  1881.  
  1882.         ret
  1883.  
  1884. endp
  1885.  
  1886. proc  alx_write_phy_reg stdcall, reg:dword, val:dword
  1887.  
  1888. ; FIXME: fixed clock
  1889.  
  1890.         DEBUGF  1,"alx_write_phy_reg reg=0x%x data=0x%x\n", [reg]:4, [val]:4
  1891.  
  1892.         mov     esi, [ebx + device.mmio_addr]
  1893.  
  1894.         mov     eax, [reg]
  1895.         shl     eax, ALX_MDIO_REG_SHIFT
  1896.         mov     ax, word[val]                   ; data must be in 16 lower bits :)
  1897.         or      eax, ALX_MDIO_SPRES_PRMBL or (ALX_MDIO_CLK_SEL_25MD4 shl ALX_MDIO_CLK_SEL_SHIFT) or ALX_MDIO_START
  1898.         mov     dword[esi + ALX_MDIO], eax
  1899.  
  1900.         mov     ecx, ALX_MDIO_MAX_AC_TO
  1901.   .loop:
  1902.         mov     eax, dword[esi + ALX_MDIO]
  1903.         test    eax, ALX_MDIO_BUSY
  1904.         jz      .ready
  1905.  
  1906.         stdcall udelay, 10
  1907.  
  1908.         dec     ecx
  1909.         jnz     .loop
  1910.  
  1911.         DEBUGF  1,"alx_write_phy_reg timeout!\n"
  1912.         xor     eax, eax
  1913.         dec     eax
  1914.         ret
  1915.  
  1916.   .ready:
  1917.         DEBUGF  1,"alx_write_phy_reg OK\n"
  1918.         xor     eax, eax
  1919.  
  1920.         ret
  1921. endp
  1922.  
  1923. proc  alx_write_phy_dbg stdcall, reg:dword, val:dword
  1924.  
  1925.         DEBUGF  1,"alx_write_phy_dbg\n"
  1926.  
  1927.         stdcall alx_write_phy_reg, ALX_MII_DBG_ADDR, [reg]
  1928.         test    eax, eax
  1929.         jnz     @f
  1930.         stdcall alx_write_phy_reg, ALX_MII_DBG_DATA, [val]
  1931.  
  1932.         ret
  1933.   @@:
  1934.         DEBUGF  1,"alx_write_phy_dbg ERROR\n"
  1935.  
  1936.         ret
  1937.  
  1938. endp
  1939.  
  1940. proc  alx_read_phy_dbg stdcall, reg:dword
  1941.  
  1942.         DEBUGF  1,"alx_read_phy_dbg\n"
  1943.  
  1944.         stdcall alx_write_phy_reg, ALX_MII_DBG_ADDR, [reg]
  1945.         test    eax, eax
  1946.         jnz     @f
  1947.         stdcall alx_read_phy_reg, ALX_MII_DBG_DATA
  1948.  
  1949.         ret
  1950.   @@:
  1951.         DEBUGF  1,"alx_read_phy_dbg ERROR\n"
  1952.  
  1953.         ret
  1954.  
  1955. endp
  1956.  
  1957. proc  alx_write_phy_ext stdcall, dev:dword, reg:dword, val:dword
  1958.  
  1959. ; FIXME: fixed clock
  1960.  
  1961.         DEBUGF  1,"alx_write_phy_ext dev=0x%x reg=0x%x, data=0x%x\n", [dev]:4, [reg]:4, [val]:4
  1962.  
  1963.         mov     esi, [ebx + device.mmio_addr]
  1964.  
  1965.         mov     eax, [dev]
  1966.         shl     eax, ALX_MDIO_EXTN_DEVAD_SHIFT
  1967.         mov     ax, word[reg]
  1968. ;        shl     eax, ALX_MDIO_EXTN_REG_SHIFT
  1969.         mov     dword[esi + ALX_MDIO_EXTN], eax
  1970.  
  1971.         movzx   eax, word[val]                   ; data must be in 16 lower bits :)
  1972.         or      eax, ALX_MDIO_SPRES_PRMBL or (ALX_MDIO_CLK_SEL_25MD4 shl ALX_MDIO_CLK_SEL_SHIFT) or ALX_MDIO_START or ALX_MDIO_MODE_EXT
  1973.         mov     dword[esi + ALX_MDIO], eax
  1974.  
  1975.         mov     ecx, ALX_MDIO_MAX_AC_TO
  1976.   .loop:
  1977.         mov     eax, dword[esi + ALX_MDIO]
  1978.         test    eax, ALX_MDIO_BUSY
  1979.         jz      .ready
  1980.  
  1981.         stdcall udelay, 10
  1982.  
  1983.         dec     ecx
  1984.         jnz     .loop
  1985.  
  1986.         DEBUGF  1,"alx_write_phy_ext timeout!\n"
  1987.         xor     eax, eax
  1988.         dec     eax
  1989.         ret
  1990.  
  1991.   .ready:
  1992.         DEBUGF  1,"alx_write_phy_ext OK\n"
  1993.         xor     eax, eax
  1994.  
  1995.         ret
  1996. endp
  1997.  
  1998. alx_request_irq:
  1999.  
  2000.         DEBUGF  1,"Request IRQ\n"
  2001.  
  2002.         mov     esi, [ebx + device.mmio_addr]
  2003.  
  2004. ; Only legacy interrupts supported for now.
  2005.         mov     dword[esi + ALX_MSI_RETRANS_TIMER], 0
  2006.  
  2007.         ret
  2008.  
  2009. ; End of code
  2010.  
  2011. data fixups
  2012. end data
  2013.  
  2014. include '../peimport.inc'
  2015.  
  2016. my_service      db 'AR81XX',0                    ; max 16 chars include zero
  2017.  
  2018. chiplist:
  2019.                 dd (ALX_DEV_ID_AR8131 shl 16) or ALX_VEN_ID, ar8131_sz
  2020.                 dd (ALX_DEV_ID_AR8132 shl 16) or ALX_VEN_ID, ar8132_sz
  2021.                 dd (ALX_DEV_ID_AR8151_1 shl 16) or ALX_VEN_ID, ar8151_1_sz
  2022.                 dd (ALX_DEV_ID_AR8151_2 shl 16) or ALX_VEN_ID, ar8151_2_sz
  2023.                 dd (ALX_DEV_ID_AR8152_1 shl 16) or ALX_VEN_ID, ar8152_1_sz
  2024.                 dd (ALX_DEV_ID_AR8152_2 shl 16) or ALX_VEN_ID, ar8152_2_sz
  2025.                 dd (ALX_DEV_ID_AR8161 shl 16) or ALX_VEN_ID, ar8161_sz
  2026.                 dd (ALX_DEV_ID_E2200 shl 16) or ALX_VEN_ID, e2200_sz
  2027.                 dd (ALX_DEV_ID_E2400 shl 16) or ALX_VEN_ID, e2400_sz
  2028.                 dd (ALX_DEV_ID_E2500 shl 16) or ALX_VEN_ID, e2500_sz
  2029.                 dd (ALX_DEV_ID_AR8162 shl 16) or ALX_VEN_ID, ar8162_sz
  2030.                 dd (ALX_DEV_ID_AR8171 shl 16) or ALX_VEN_ID, ar8171_sz
  2031.                 dd (ALX_DEV_ID_AR8172 shl 16) or ALX_VEN_ID, ar8172_sz
  2032.                 dd 0
  2033.  
  2034. ar8131_sz       db "AR8131", 0
  2035. ar8132_sz       db "AR8132", 0
  2036. ar8151_1_sz     db "AR8151 rev1", 0
  2037. ar8151_2_sz     db "AR8151 rev2", 0
  2038. ar8152_1_sz     db "AR8152 rev1", 0
  2039. ar8152_2_sz     db "AR8152 rev2", 0
  2040. ar8161_sz       db "AR8161", 0
  2041. ar8162_sz       db "AR8162", 0
  2042. ar8171_sz       db "QCA8171", 0
  2043. ar8172_sz       db "QCA8172", 0
  2044. e2200_sz        db "Killer E2200", 0
  2045. e2400_sz        db "Killer E2400", 0
  2046. e2500_sz        db "Killer E2500", 0
  2047.  
  2048. include_debug_strings
  2049.  
  2050. align 4
  2051. devices         dd 0
  2052. device_list     rd MAX_DEVICES                  ; This list contains all pointers to device structures the driver is handling
  2053.  
  2054.