Subversion Repositories Kolibri OS

Rev

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