Subversion Repositories Kolibri OS

Rev

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

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