Subversion Repositories Kolibri OS

Rev

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