Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 7808 → Rev 7809

/drivers/ethernet/ar81xx.asm
0,0 → 1,1754
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2018-2020. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; AR81XX driver for KolibriOS ;;
;; ;;
;; based on alx driver from TI-OpenLink ;;
;; ;;
;; Written by hidnplayr (hidnplayr@gmail.com) ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format PE DLL native
entry START
 
CURRENT_API = 0x0200
COMPATIBLE_API = 0x0100
API_VERSION = (COMPATIBLE_API shl 16) + CURRENT_API
 
MAX_DEVICES = 16
 
__DEBUG__ = 1
__DEBUG_LEVEL__ = 2
 
TX_RING_SIZE = 128 ; RING sizes must be a power of 2
RX_RING_SIZE = 128
 
RX_BUFFER_SIZE = 1536
 
SMB_TIMER = 400
IMT = 200
ITH_TPD = TX_RING_SIZE / 3
 
section '.flat' readable writable executable
 
include '../proc32.inc'
include '../struct.inc'
include '../macros.inc'
include '../fdo.inc'
include '../netdrv.inc'
 
include 'ar81xx.inc'
 
; Transmit Packet Descriptor
 
struct alx_tpd
length dw ?
vlan_tag dw ?
word1 dd ?
addr_l dd ?
addr_h dd ?
ends
 
; Receive Return Descriptor
 
struct alx_rrd
word0 dd ? ; IP payload cksum + number of RFDs + start index of RFD-ring
rss_hash dd ?
word2 dd ? ; VLAN tag + Protocol ID + RSS Q num + RSS Hash algorithm
word3 dd ? ; Packet length + status
ends
 
; Receive Free Descriptor
 
struct alx_rfd
addr_l dd ?
addr_h dd ?
ends
 
 
struct device ETH_DEVICE
 
io_addr dd ?
pci_bus dd ?
pci_dev dd ?
irq_line dd ?
pci_rev dd ?
chip_rev dd ?
mmio_addr dd ?
 
; dma_chnl dd ?
max_dma_chnl dd ?
 
int_mask dd ?
rx_ctrl dd ?
 
rxq_read_idx dd ?
rxq_write_idx dd ?
; rxq_rrd_read_idx dd ?
txq_read_idx dd ?
txq_write_idx dd ?
 
rb 0x100 - ($ and 0xff) ; align 256
tpd_ring rb ((TX_RING_SIZE*sizeof.alx_tpd+16) and 0xfffffff0)
rrd_ring rb ((RX_RING_SIZE*sizeof.alx_rrd+16) and 0xfffffff0)
rfd_ring rb ((RX_RING_SIZE*sizeof.alx_rfd+16) and 0xfffffff0)
tpd_ring_virt rd TX_RING_SIZE
rfd_ring_virt rd RX_RING_SIZE
 
ends
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc START ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
proc START c, reason:dword, cmdline:dword
 
cmp [reason], DRV_ENTRY
jne .fail
 
DEBUGF 2,"Loading driver\n"
invoke RegService, my_service, service_proc
ret
 
.fail:
xor eax, eax
ret
 
endp
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc SERVICE_PROC ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
proc service_proc stdcall, ioctl:dword
 
mov edx, [ioctl]
mov eax, [edx + IOCTL.io_code]
 
;------------------------------------------------------
 
cmp eax, 0 ;SRV_GETVERSION
jne @F
 
cmp [edx + IOCTL.out_size], 4
jb .fail
mov eax, [edx + IOCTL.output]
mov [eax], dword API_VERSION
 
xor eax, eax
ret
 
;------------------------------------------------------
@@:
cmp eax, 1 ;SRV_HOOK
jne .fail
 
cmp [edx + IOCTL.inp_size], 3 ; Data input must be at least 3 bytes
jb .fail
 
mov eax, [edx + IOCTL.input]
cmp byte [eax], 1 ; 1 means device number and bus number (pci) are given
jne .fail ; other types arent supported for this card yet
 
; check if the device is already listed
 
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .firstdevice
 
; mov eax, [edx + IOCTL.input] ; get the pci bus and device numbers
mov ax , [eax+1] ;
.nextdevice:
mov ebx, [esi]
cmp al, byte[ebx + device.pci_bus]
jne @f
cmp ah, byte[ebx + device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
@@:
add esi, 4
loop .nextdevice
 
 
; This device doesnt have its own eth_device structure yet, lets create one
.firstdevice:
cmp [devices], MAX_DEVICES ; First check if the driver can handle one more card
jae .fail
 
allocate_and_clear ebx, sizeof.device, .fail ; Allocate the buffer for device structure
 
; Fill in the direct call addresses into the struct
 
mov [ebx + device.reset], reset
mov [ebx + device.transmit], transmit
mov [ebx + device.unload], unload
mov [ebx + device.name], my_service
 
; save the pci bus and device numbers
 
mov eax, [edx + IOCTL.input]
movzx ecx, byte[eax+1]
mov [ebx + device.pci_bus], ecx
movzx ecx, byte[eax+2]
mov [ebx + device.pci_dev], ecx
 
; Now, it's time to find the base mmio addres of the PCI device
 
stdcall PCI_find_mmio, [ebx + device.pci_bus], [ebx + device.pci_dev] ; returns in eax
test eax, eax
jz .destroy
 
; Create virtual mapping of the physical memory
 
invoke MapIoMem, eax, 10000h, PG_SW+PG_NOCACHE
mov [ebx + device.mmio_addr], eax
 
; We've found the mmio address, find IRQ now
invoke PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
and eax, 0xff
mov [ebx + device.irq_line], eax
 
DEBUGF 1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
[ebx + device.pci_dev]:1, [ebx + device.pci_bus]:1, [ebx + device.irq_line]:1, [ebx + device.mmio_addr]:8
 
; Ok, the eth_device structure is ready, let's probe the device
 
mov eax, [devices] ; Add the device structure to our device list
mov [device_list+4*eax], ebx ; (IRQ handler uses this list to find device)
inc [devices] ;
 
call probe ; this function will output in eax
test eax, eax
jnz .err2
 
DEBUGF 2,"Initialised OK\n"
 
mov [ebx + device.type], NET_TYPE_ETH
invoke NetRegDev
 
cmp eax, -1
je .destroy
 
ret
 
; If the device was already loaded, find the device number and return it in eax
 
.find_devicenum:
DEBUGF 2,"Trying to find device number of already registered device\n"
invoke NetPtrToNum ; This kernel procedure converts a pointer to device struct in ebx
; into a device number in edi
mov eax, edi ; Application wants it in eax instead
DEBUGF 2,"Kernel says: %u\n", eax
ret
 
; If an error occured, remove all allocated data and exit (returning -1 in eax)
 
.destroy:
; todo: reset device into virgin state
 
.err2:
dec [devices]
.err:
invoke KernelFree, ebx
.fail:
DEBUGF 2, "Failed to load\n"
or eax, -1
ret
 
;------------------------------------------------------
endp
 
 
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
;; ;;
;; Actual Hardware dependent code starts here ;;
;; ;;
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
 
 
align 4
unload:
; TODO: (in this particular order)
;
; - Stop the device
; - Detach int handler
; - Remove device from local list (device_list)
; - call unregister function in kernel
; - Remove all allocated structures and buffers the card used
 
or eax, -1
ret
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; probe: enables the device (if it really is AR81XX)
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
probe:
DEBUGF 1,"Probing\n"
 
; Make the device a bus master
invoke PciRead16, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
or al, PCI_CMD_MASTER + PCI_CMD_MMIO + PCI_CMD_PIO
and ax, not(PCI_CMD_INTX_DISABLE)
invoke PciWrite16, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
 
; get revision id.
invoke PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.revision_id
and eax, 0xff
mov [ebx + device.pci_rev], eax
shr al, ALX_PCI_REVID_SHIFT
mov [ebx + device.chip_rev], eax
 
DEBUGF 1,"revision: %u\n", al
 
;;; call alx_reset_pcie
 
mov ecx, (ALX_PMCTRL_L0S_EN or ALX_PMCTRL_L1_EN or ALX_PMCTRL_ASPM_FCEN)
call alx_enable_aspm
 
call alx_reset_phy
 
call alx_reset_mac
 
call alx_get_perm_macaddr
 
align 4
reset:
 
DEBUGF 1,"Resetting\n"
 
; alx init_sw
 
call alx_identify_hw
 
; mov eax, [ebx + device.max_dma_chnl]
; mov [ebx + device.dma_chnl], eax
 
mov [ebx + device.int_mask], ALX_ISR_MISC
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)
 
call alx_alloc_rings
 
call alx_configure
 
call alx_request_irq
 
; attach interrupt handler
 
mov eax, [ebx + device.irq_line]
DEBUGF 1,"Attaching int handler to irq %x\n", eax:1
invoke AttachIntHandler, eax, int_handler, ebx
test eax, eax
jnz @f
DEBUGF 2,"Could not attach int handler!\n"
or eax, -1
ret
@@:
 
; Clear old interrupts
mov edi, [ebx + device.mmio_addr]
mov eax, not ALX_ISR_DIS
mov [edi + ALX_ISR], eax
 
call alx_irq_enable
 
; Set the mtu, kernel will be able to send now
mov [ebx + device.mtu], 1514
 
call alx_check_link
 
DEBUGF 1,"Reset ok\n"
xor eax, eax
ret
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Transmit ;;
;; ;;
;; In: pointer to device structure in ebx ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
;; alx_start_xmit
;; alx_map_tx_skb
 
proc transmit stdcall bufferptr
 
pushf
cli
 
mov esi, [bufferptr]
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length]
lea eax, [esi + NET_BUFF.data]
DEBUGF 1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
[eax+13]:2,[eax+12]:2
 
cmp [esi + NET_BUFF.length], 1514
ja .fail
cmp [esi + NET_BUFF.length], 60
jb .fail
 
; Program the descriptor
mov edi, [ebx + device.txq_write_idx]
DEBUGF 1, "Using TPD: %u\n", edi
mov dword[ebx + device.tpd_ring_virt + edi*4], esi
shl edi, 4
lea edi, [ebx + device.tpd_ring + edi]
mov eax, esi
add eax, [esi + NET_BUFF.offset]
invoke GetPhysAddr
mov [edi + alx_tpd.addr_l], eax
mov [edi + alx_tpd.addr_h], 0
 
mov ecx, [esi + NET_BUFF.length]
mov [edi + alx_tpd.length], cx
 
mov [edi + alx_tpd.word1], 1 shl TPD_EOP_SHIFT
 
; Update Producer Index
mov eax, [ebx + device.txq_write_idx]
inc eax
and eax, TX_RING_SIZE - 1
mov [ebx + device.txq_write_idx], eax
 
mov edi, [ebx + device.mmio_addr]
mov word[edi + ALX_TPD_PRI0_PIDX], ax
 
; Update stats
inc [ebx + device.packets_tx]
mov eax, [esi + NET_BUFF.length]
add dword[ebx + device.bytes_tx], eax
adc dword[ebx + device.bytes_tx + 4], 0
 
popf
xor eax, eax
ret
 
.fail:
DEBUGF 2,"Send failed\n"
invoke NetFree, [bufferptr]
popf
or eax, -1
ret
 
endp
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Interrupt handler ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
int_handler:
 
push ebx esi edi
 
DEBUGF 1,"int\n"
 
; Find pointer of device wich made IRQ occur
 
mov ecx, [devices]
test ecx, ecx
jz .nothing
mov esi, device_list
.nextdevice:
mov ebx, [esi]
mov edi, [ebx + device.mmio_addr]
mov eax, [edi + ALX_ISR]
test eax, eax
jnz .got_it
.continue:
add esi, 4
dec ecx
jnz .nextdevice
.nothing:
pop edi esi ebx
xor eax, eax
 
ret ; If no device was found, abort
 
; At this point, test for all possible reasons, and handle accordingly
 
.got_it:
or eax, ALX_ISR_DIS
mov [edi + ALX_ISR], eax ; ACK interrupt
DEBUGF 1,"Device: %x Status: %x\n", ebx, eax
 
test eax, ALX_ISR_TX_Q0
jz .no_tx
DEBUGF 1,"TX interrupt\n"
pusha
call alx_clean_tx_irq
popa
.no_tx:
 
test eax, ALX_ISR_RX_Q0
jz .no_rx
DEBUGF 1,"RX interrupt\n"
pusha
call alx_clean_rx_irq
popa
 
.no_rx:
test eax, ALX_ISR_PHY
jz .no_phy
DEBUGF 1,"PHY interrupt\n"
pusha
; TODO: queue link check and disable this interrupt cause meanwhile??
call alx_check_link
popa
 
.no_phy:
mov dword[edi + ALX_ISR], 0
pop edi esi ebx
ret
 
 
align 16
alx_identify_hw:
 
cmp [ebx + device.chip_rev], ALX_REV_C0
ja .einval
 
mov [ebx + device.max_dma_chnl], 2
cmp [ebx + device.chip_rev], ALX_REV_B0
jb @f
mov [ebx + device.max_dma_chnl], 4
@@:
xor eax, eax
ret
 
.einval:
xor eax, eax
dec eax
ret
 
 
 
align 16
alx_clean_tx_irq:
 
mov eax, [ebx + device.txq_read_idx]
movzx ecx, word[edi + ALX_TPD_PRI0_CIDX]
 
.loop:
cmp eax, ecx
je .done
 
DEBUGF 1,"Cleaning TX desc %u buffer 0x%x\n", eax, [ebx + device.tpd_ring_virt + eax*4]
push eax ecx
invoke NetFree, [ebx + device.tpd_ring_virt + eax*4]
pop ecx eax
 
inc eax
and eax, TX_RING_SIZE-1
jmp .loop
.done:
mov [ebx + device.txq_read_idx], eax
 
ret
 
 
align 16
alx_clean_rx_irq:
 
mov ecx, [ebx + device.rxq_read_idx]
.loop:
shl ecx, 2
lea esi, [ebx + device.rrd_ring + ecx*4]
test [esi + alx_rrd.word3], 1 shl RRD_UPDATED_SHIFT
jz .done
and [esi + alx_rrd.word3], not(1 shl RRD_UPDATED_SHIFT)
DEBUGF 1,"RRD=%u updated\n", [ebx + device.rxq_read_idx]
 
mov eax, [esi + alx_rrd.word0]
shr eax, RRD_SI_SHIFT
and eax, RRD_SI_MASK
cmp eax, [ebx + device.rxq_read_idx]
; jne .error
DEBUGF 1,"RFD=%u\n", eax
 
mov eax, [esi + alx_rrd.word0]
shr eax, RRD_NOR_SHIFT
and eax, RRD_NOR_MASK
cmp eax, 1
; jne .error
 
mov eax, [esi + alx_rrd.word3]
; shr eax, RRD_PKTLEN_SHIFT
and eax, RRD_PKTLEN_MASK
sub eax, 4 ;;;;;
mov edx, [ebx + device.rfd_ring_virt + ecx]
DEBUGF 1,"Received %u bytes in buffer 0x%x\n", eax, edx
 
mov [edx + NET_BUFF.length], eax
mov [edx + NET_BUFF.device], ebx
mov [edx + NET_BUFF.offset], NET_BUFF.data
 
; Update stats
add dword[ebx + device.bytes_rx], eax
adc dword[ebx + device.bytes_rx + 4], 0
inc [ebx + device.packets_rx]
 
; Allocate new descriptor
push esi ecx edx
invoke NetAlloc, RX_BUFFER_SIZE+NET_BUFF.data
pop edx ecx esi
test eax, eax
; jz .out_of_mem
mov [ebx + device.rfd_ring_virt + ecx], eax
add eax, NET_BUFF.data
invoke GetPhysAddr
mov dword[ebx + device.rfd_ring + ecx*2], eax
 
push ecx ebx
push .retaddr
push edx
jmp [EthInput]
.retaddr:
pop ebx ecx
 
shr ecx, 2
inc ecx
and ecx, RX_RING_SIZE-1
jmp .loop
 
.done:
shr ecx, 2
mov [ebx + device.rxq_read_idx], ecx
 
; Update producer index
mov esi, [ebx + device.mmio_addr]
mov [esi + ALX_RFD_PIDX], cx
 
ret
 
 
align 16
; ecx = additional bit flags (ALX_PMCTRL_L0S_EN, ALX_PMCTRL_L1_EN, ALX_PMCTRL_ASPM_FCEN)
alx_enable_aspm:
 
DEBUGF 1,"alx_enable_aspm (0x%x)\n", ecx
 
mov esi, [ebx + device.mmio_addr]
mov eax, dword[esi + ALX_PMCTRL]
 
and eax, not(ALX_PMCTRL_LCKDET_TIMER_MASK shl ALX_PMCTRL_LCKDET_TIMER_SHIFT)
or eax, (ALX_PMCTRL_LCKDET_TIMER_DEF shl ALX_PMCTRL_LCKDET_TIMER_SHIFT)
 
or eax, (ALX_PMCTRL_RCVR_WT_1US or ALX_PMCTRL_L1_CLKSW_EN or ALX_PMCTRL_L1_SRDSRX_PWD)
 
and eax, not(ALX_PMCTRL_L1REQ_TO_MASK shl ALX_PMCTRL_L1REQ_TO_SHIFT)
or eax, (ALX_PMCTRL_L1REG_TO_DEF shl ALX_PMCTRL_L1REQ_TO_SHIFT)
 
and eax, not(ALX_PMCTRL_L1_TIMER_MASK shl ALX_PMCTRL_L1_TIMER_SHIFT)
or eax, (ALX_PMCTRL_L1_TIMER_16US shl ALX_PMCTRL_L1_TIMER_SHIFT)
 
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)
 
cmp [ebx + device.chip_rev], ALX_REV_A1
ja @f
test [ebx + device.pci_rev], 1
jz @f
or eax, ALX_PMCTRL_L1_SRDS_EN or ALX_PMCTRL_L1_SRDSPLL_EN
@@:
 
or eax, ecx
mov dword[esi + ALX_PMCTRL], eax
 
ret
 
align 16
alx_reset_mac:
 
DEBUGF 1, "reset mac\n"
 
; disable all interrupts, RXQ/TXQ
mov esi, [ebx + device.mmio_addr]
mov dword[esi + ALX_MSIX_MASK], 0xffffffff
mov dword[esi + ALX_IMR], 0x0
mov dword[esi + ALX_ISR], ALX_ISR_DIS
 
call alx_stop_mac
 
; mac reset workaround
mov dword[esi + ALX_RFD_PIDX], 1
 
; disable l0s/l1 before mac reset on some chips
cmp [ebx + device.chip_rev], ALX_REV_A1
ja @f
test [ebx + device.pci_rev], 1 ; Card reader function? FIXME: according register definitions, this should be bit 1 ISO 0
jz @f
mov eax, [esi + ALX_PMCTRL]
mov edx, eax
and eax, not(ALX_PMCTRL_L1_EN or ALX_PMCTRL_L0S_EN)
mov [esi + ALX_PMCTRL], eax
@@:
 
; reset whole mac safely
mov eax, [esi + ALX_MASTER]
or eax, ALX_MASTER_DMA_MAC_RST + ALX_MASTER_OOB_DIS
mov [esi + ALX_MASTER], eax
 
; make sure it's real idle
push esi ecx edx
xor esi, esi
inc esi
invoke Sleep ; FIXME
pop edx ecx esi
 
mov ecx, ALX_DMA_MAC_RST_TO
.loop1:
mov eax, dword[esi + ALX_RFD_PIDX]
test eax, eax
jz @f
dec ecx
jnz .loop1
jmp .error
@@:
.loop2:
mov eax, dword[esi + ALX_MASTER]
test eax, ALX_MASTER_DMA_MAC_RST
jz @f
dec ecx
jnz .loop2
jmp .error
@@:
 
; restore l0s/l1
cmp [ebx + device.chip_rev], ALX_REV_A1
ja @f
test [ebx + device.pci_rev], 1 ; Card reader function? FIXME: according register definitions, this should be bit 1 ISO 0
jz @f
or eax, ALX_MASTER_PCLKSEL_SRDS
mov [esi + ALX_MASTER], eax
 
mov [esi + ALX_PMCTRL], edx
@@:
 
call alx_reset_osc
 
; clear Internal OSC settings, switching OSC by hw itself, disable isolate for rev A devices
 
mov eax, [esi + ALX_MISC3]
and eax, not (ALX_MISC3_25M_BY_SW)
or eax, ALX_MISC3_25M_NOTO_INTNL
mov [esi + ALX_MISC3], eax
 
mov eax, [esi + ALX_MISC]
and eax, not (ALX_MISC_INTNLOSC_OPEN)
 
cmp [ebx + device.chip_rev], ALX_REV_A1
ja @f
and eax, not ALX_MISC_ISO_EN
@@:
mov [esi + ALX_MISC], eax
 
push esi
xor esi, esi
inc esi
invoke Sleep ;; FIXME: udelay(20);
pop esi
 
; driver control speed/duplex, hash-alg
mov eax, [ebx + device.rx_ctrl]
mov [esi + ALX_MAC_CTRL], eax
 
mov eax, dword[esi + ALX_SERDES]
or eax, ALX_SERDES_MACCLK_SLWDWN or ALX_SERDES_PHYCLK_SLWDWN
mov dword[esi + ALX_SERDES], eax
 
DEBUGF 1, "OK\n"
xor eax, eax
ret
 
.error:
DEBUGF 1, "error\n"
xor eax, eax
dec eax
ret
 
 
align 16
alx_reset_phy:
 
DEBUGF 1, "Reset phy\n"
 
mov esi, [ebx + device.mmio_addr]
 
;; TODO
 
; set phy interrupt mask
stdcall alx_read_phy_reg, 0, ALX_MII_IER
or eax, ALX_IER_LINK_UP or ALX_IER_LINK_DOWN
stdcall alx_write_phy_reg, 0, ALX_MII_IER , eax
 
DEBUGF 1, "OK\n"
xor eax, eax
ret
 
.error:
DEBUGF 1, "error\n"
xor eax, eax
dec eax
ret
 
 
;align 16
;alx_enable_osc:
;
; mov esi, [ebx + device.mmio_addr]
;
;; rising edge
; mov eax, dword[esi + ALX_MISC]
; and eax, not ALX_MISC_INTNLOSC_OPEN
; mov dword[esi + ALX_MISC], eax
; or eax, ALX_MISC_INTNLOSC_OPEN
; mov dword[esi + ALX_MISC], eax
;
; ret
 
 
align 16
alx_reset_osc:
 
mov esi, [ebx + device.mmio_addr]
 
; clear Internal OSC settings, switching OSC by hw itself
mov eax, dword[esi + ALX_MISC3]
and eax, not ALX_MISC3_25M_BY_SW
or eax, ALX_MISC3_25M_NOTO_INTNL
mov dword[esi + ALX_MISC3], eax
 
; clk from chipset may be unstable 1s after de-assert of
; PERST, driver need re-calibrate before enter Sleep for WoL
mov eax, dword[esi + ALX_MISC]
cmp [ebx + device.chip_rev], ALX_REV_B0
jb .rev_a
 
; restore over current protection def-val, this val could be reset by MAC-RST
and eax, not (ALX_MISC_PSW_OCP_MASK shl ALX_MISC_PSW_OCP_SHIFT)
or eax, ALX_MISC_PSW_OCP_DEF shl ALX_MISC_PSW_OCP_SHIFT
; a 0->1 change will update the internal val of osc
and eax, not ALX_MISC_INTNLOSC_OPEN
mov dword[esi + ALX_MISC], eax
or eax, ALX_MISC_INTNLOSC_OPEN
mov dword[esi + ALX_MISC], eax
 
; hw will automatically dis OSC after cab
mov eax, dword[esi + ALX_MSIC2]
and eax, not ALX_MSIC2_CALB_START
mov dword[esi + ALX_MSIC2], eax
or eax, ALX_MSIC2_CALB_START
mov dword[esi + ALX_MSIC2], eax
 
push esi ecx
xor esi, esi
inc esi
invoke Sleep ;; FIXME: udelay(20)
pop ecx esi
 
ret
 
.rev_a:
 
; disable isolate for rev A devices
and eax, not ( ALX_MISC_ISO_EN)
or eax, ALX_MISC_INTNLOSC_OPEN
mov dword[esi + ALX_MISC], eax
and eax, not ALX_MISC_INTNLOSC_OPEN
mov dword[esi + ALX_MISC], eax
 
push esi ecx
xor esi, esi
inc esi
invoke Sleep ;; FIXME: udelay(20)
pop ecx esi
 
ret
 
align 16
alx_read_macaddr:
 
mov esi, [ebx + device.mmio_addr]
mov eax, dword[esi + ALX_STAD0]
bswap eax
mov dword[ebx + device.mac + 2], eax
mov ax, word[esi + ALX_STAD1]
xchg al, ah
mov word[ebx + device.mac], ax
 
DEBUGF 1,"MAC = %x-%x-%x-%x-%x-%x\n",\
[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
 
; check if it is a valid MAC
cmp dword[ebx + device.mac], 0x0
jne @f
cmp word[ebx + device.mac + 4], 0x0
je .invalid
@@:
cmp dword[ebx + device.mac], 0xffffffff
jne @f
cmp word[ebx + device.mac + 4], 0xffff
je .invalid
@@:
; TODO: check if it's not a multicast
xor eax, eax
ret
 
.invalid:
xor eax, eax
inc eax
ret
 
 
align 16
alx_get_perm_macaddr:
 
; try to get it from register first
call alx_read_macaddr
test eax, eax
jz .done
 
; try to load from efuse
mov esi, [ebx + device.mmio_addr]
mov ecx, ALX_SLD_MAX_TO
.loop1:
mov eax, dword[esi + ALX_SLD]
test eax, ALX_SLD_STAT or ALX_SLD_START
jz @f
 
dec ecx
jz .error
 
push esi ecx
xor esi, esi
inc esi
invoke Sleep
pop ecx esi
jmp .loop1
@@:
or eax, ALX_SLD_START
mov dword[esi + ALX_SLD], eax
 
mov ecx, ALX_SLD_MAX_TO
.loop2:
mov eax, dword[esi + ALX_SLD]
test eax, ALX_SLD_START
jz @f
 
dec ecx
jz .error
 
push esi ecx
xor esi, esi
inc esi
invoke Sleep
pop ecx esi
jmp .loop2
@@:
 
call alx_read_macaddr
test eax, eax
jz .done
 
; try to load from flash/eeprom (if present)
set_io [ebx + device.io_addr], 0
set_io [ebx + device.io_addr], ALX_EFLD
in eax, dx
test eax, ALX_EFLD_F_EXIST or ALX_EFLD_E_EXIST
jz .error
 
mov ecx, ALX_SLD_MAX_TO
.loop3:
in eax, dx
test eax, ALX_EFLD_STAT or ALX_EFLD_START
jz @f
 
dec ecx
jz .error
 
push esi edx ecx
xor esi, esi
inc esi
invoke Sleep
pop ecx edx esi
jmp .loop3
@@:
or eax, ALX_EFLD_START
out dx, eax
 
mov ecx, ALX_SLD_MAX_TO
.loop4:
in eax, dx
test eax, ALX_EFLD_START
jz @f
 
dec ecx
jz .error
 
push esi edx ecx
xor esi, esi
inc esi
invoke Sleep
pop ecx edx esi
jmp .loop4
@@:
 
call alx_read_macaddr
test eax, eax
jz .done
 
.error:
DEBUGF 1, "error obtaining MAC\n"
xor eax, eax
dec eax
ret
 
.done:
DEBUGF 1, "MAC OK\n"
xor eax, eax
ret
 
align 16
alx_stop_mac:
 
DEBUGF 1,"alx_stop_mac\n"
 
mov esi, [ebx + device.mmio_addr]
 
mov eax, dword[esi + ALX_RXQ0]
and eax, not ALX_RXQ0_EN
mov dword[esi + ALX_RXQ0], eax
 
mov eax, dword[esi + ALX_TXQ0]
and eax, not ALX_TXQ0_EN
mov dword[esi + ALX_TXQ0], eax
 
push esi
xor esi, esi
inc esi
invoke Sleep ; FIME: udelay(40)
pop esi
 
mov eax, [ebx + device.rx_ctrl]
and eax, not(ALX_MAC_CTRL_TX_EN or ALX_MAC_CTRL_RX_EN)
mov [ebx + device.rx_ctrl], eax
mov [esi + ALX_MAC_CTRL], eax
 
mov ecx, ALX_DMA_MAC_RST_TO
.loop:
mov eax, [esi + ALX_MAC_STS]
test eax, ALX_MAC_STS_IDLE
jz .done
 
push esi
xor esi, esi
inc esi
invoke Sleep ; FIME: udelay(10)
pop esi
 
dec ecx
jnz .loop
 
DEBUGF 1,"alx_stop_mac timeout!\n"
xor eax, eax
dec eax
ret
 
.done:
DEBUGF 1,"alx_stop_mac ok\n"
xor eax, eax
ret
 
 
align 16
alx_start_mac:
 
DEBUGF 1,"alx_start_mac\n"
 
mov esi, [ebx + device.mmio_addr]
 
mov eax, dword[esi + ALX_RXQ0]
or eax, ALX_RXQ0_EN
mov dword[esi + ALX_RXQ0], eax
 
mov eax, dword[esi + ALX_TXQ0]
or eax, ALX_TXQ0_EN
mov dword[esi + ALX_TXQ0], eax
 
mov eax, [ebx + device.rx_ctrl]
or eax, ALX_MAC_CTRL_TX_EN or ALX_MAC_CTRL_RX_EN
and eax, not ALX_MAC_CTRL_FULLD
test [ebx + device.state], ETH_LINK_FD
jz @f
or eax, ALX_MAC_CTRL_FULLD
@@:
and eax, not (ALX_MAC_CTRL_SPEED_MASK shl ALX_MAC_CTRL_SPEED_SHIFT)
test [ebx + device.state], ETH_LINK_1G
jz .10_100
or eax, (ALX_MAC_CTRL_SPEED_1000 shl ALX_MAC_CTRL_SPEED_SHIFT)
 
mov [ebx + device.rx_ctrl], eax
mov [esi + ALX_MAC_CTRL], eax
 
ret
 
.10_100:
or eax, (ALX_MAC_CTRL_SPEED_10_100 shl ALX_MAC_CTRL_SPEED_SHIFT)
 
mov [ebx + device.rx_ctrl], eax
mov [esi + ALX_MAC_CTRL], eax
 
ret
 
 
 
align 16
alx_init_ring_ptrs:
 
DEBUGF 1,"alx_init_ring_ptrs\n"
 
mov esi, [ebx + device.mmio_addr]
 
; Receive descriptors
mov [ebx + device.rxq_read_idx], 0
mov [ebx + device.rxq_write_idx], 0
; mov [ebx + device.rxq_rrd_read_idx], 0
 
mov dword[esi + ALX_RX_BASE_ADDR_HI], 0
 
lea eax, [ebx + device.rrd_ring]
invoke GetPhysAddr
mov dword[esi + ALX_RRD_ADDR_LO], eax
mov dword[esi + ALX_RRD_RING_SZ], RX_RING_SIZE
 
lea eax, [ebx + device.rfd_ring]
invoke GetPhysAddr
mov dword[esi + ALX_RFD_ADDR_LO], eax
mov dword[esi + ALX_RFD_RING_SZ], RX_RING_SIZE
mov dword[esi + ALX_RFD_BUF_SZ], RX_BUFFER_SIZE
 
; Transmit descriptors
mov [ebx + device.txq_read_idx], 0
mov [ebx + device.txq_write_idx], 0
 
mov dword[esi + ALX_TX_BASE_ADDR_HI], 0
 
lea eax, [ebx + device.tpd_ring]
invoke GetPhysAddr
mov dword[esi + ALX_TPD_PRI0_ADDR_LO], eax
mov dword[esi + ALX_TPD_RING_SZ], TX_RING_SIZE
 
; Load these pointers into the chip
mov dword[esi + ALX_SRAM9], ALX_SRAM_LOAD_PTR
 
xor eax, eax
 
ret
 
 
align 16
alx_alloc_descriptors:
 
DEBUGF 1,"alx_alloc_descriptors\n"
 
; physical tx/rx ring descriptors
 
; alx->descmem.size = sizeof.tx_desc * TX_RING_SIZE + sizeof.rx_desc * RX_RING_SIZE + sizeof(struct alx_rfd) * RX_RING_SIZE;
; alx->descmem.virt = dma_zalloc_coherent(&alx->hw.pdev->dev, alx->descmem.size, &alx->descmem.dma, GFP_KERNEL);
; if (!alx->descmem.virt)
; goto out_free;
;
; alx->txq.tpd = (void *)alx->descmem.virt;
; alx->txq.tpd_dma = alx->descmem.dma;
 
; alignment requirement for next block
; BUILD_BUG_ON(tx_desc.sizeof % 8);
;
; alx->rxq.rrd = (void *)((u8 *)alx->descmem.virt + tx_desc.sizeof * TX_RING_SIZE);
; alx->rxq.rrd_dma = alx->descmem.dma + sizeof.tx_desc * TX_RING_SIZE;
;
; alignment requirement for next block
; BUILD_BUG_ON(rx_desc.sizeof % 8);
;
; alx->rxq.rfd = (void *)((u8 *)alx->descmem.virt + sizeof.tx_desx * TX_RING_SIZE + sizeof.rx_desc * RX_RING_SIZE);
; alx->rxq.rfd_dma = alx->descmem.dma + sizeof.tx_desc * TX_RING_SIZE + sizeof.rx_desc * RX_RING_SIZE;
 
xor eax, eax
ret
 
 
align 16
alx_alloc_rings:
 
DEBUGF 1,"alx_alloc_rings\n"
 
call alx_alloc_descriptors
test eax, eax
jnz .ret_err
 
and [ebx + device.int_mask], not ALX_ISR_ALL_QUEUES
or [ebx + device.int_mask], ALX_ISR_TX_Q0 or ALX_ISR_RX_Q0
; netif_napi_add(alx->dev, &alx->napi, alx_poll, 64);
 
call alx_reinit_rings
.ret_err:
ret
 
 
align 16
alx_reinit_rings:
 
DEBUGF 1,"alx_reinit_rings\n"
 
call alx_free_rx_ring
call alx_init_ring_ptrs
call alx_refill_rx_ring
 
ret
 
 
align 16
alx_refill_rx_ring:
 
DEBUGF 1,"alx_refill_rx_ring\n"
 
mov ecx, [ebx + device.rxq_write_idx]
.loop:
cmp dword[ebx + device.rfd_ring+ecx*sizeof.alx_rfd + alx_rfd.addr_l], 0
jne .done
 
invoke NetAlloc, NET_BUFF.data+RX_BUFFER_SIZE
test eax, eax
jz .done
mov [ebx + device.rfd_ring_virt + ecx*4], eax
add eax, NET_BUFF.data
invoke GetPhysAddr
mov dword[ebx + device.rfd_ring+ecx*sizeof.alx_rfd + alx_rfd.addr_l], eax
mov dword[ebx + device.rfd_ring+ecx*sizeof.alx_rfd + alx_rfd.addr_h], 0
 
mov eax, ecx
inc ecx
and ecx, RX_RING_SIZE - 1
 
cmp ecx, [ebx + device.rxq_read_idx]
jne .loop
 
mov ecx, eax
 
.done:
cmp ecx, [ebx + device.rxq_write_idx]
je .none
 
mov [ebx + device.rxq_write_idx], ecx
mov esi, [ebx + device.mmio_addr]
mov [esi + ALX_RFD_PIDX], cx
 
.none:
xor eax, eax
 
ret
 
 
align 16
alx_free_rx_ring:
 
DEBUGF 1,"alx_free_rx_ring\n"
 
xor ecx, ecx
.loop:
mov eax, [ebx + device.rfd_ring_virt + ecx*4]
test eax, eax
jz .next
 
invoke NetFree, eax
 
xor eax, eax
mov dword[ebx + device.rfd_ring+ecx*sizeof.alx_rfd + alx_rfd.addr_l], eax
mov dword[ebx + device.rfd_ring+ecx*sizeof.alx_rfd + alx_rfd.addr_h], eax
mov [ebx + device.rfd_ring_virt + ecx*4], eax
 
.next:
inc ecx
cmp ecx, RX_RING_SIZE
jb .loop
 
ret
 
 
align 16
alx_configure:
 
DEBUGF 1,"alx_configure\n"
 
call alx_configure_basic
call alx_disable_rss
call __alx_set_rx_mode
 
mov esi, [ebx + device.mmio_addr]
mov eax, [ebx + device.rx_ctrl]
mov [esi + ALX_MAC_CTRL], eax
 
xor eax, eax
ret
 
 
align 16
alx_irq_enable:
 
DEBUGF 1,"alx_irq_enable\n"
 
mov esi, [ebx + device.mmio_addr]
mov dword[esi + ALX_ISR], 0
mov eax, [ebx + device.int_mask]
mov [esi + ALX_IMR], eax
 
call alx_post_write
 
ret
 
align 16
alx_irq_disable:
 
DEBUGF 1,"alx_irq_disable\n"
 
mov esi, [ebx + device.mmio_addr]
mov dword[esi + ALX_ISR], ALX_ISR_DIS
mov dword[esi + ALX_IMR], 0
 
call alx_post_write
 
ret
 
 
align 16
alx_post_write:
 
push eax
mov esi, [ebx + device.mmio_addr]
mov eax, [esi]
pop eax
 
ret
 
 
align 16
alx_configure_basic:
 
DEBUGF 1,"alx_configure_basic\n"
 
mov esi, [ebx + device.mmio_addr]
 
;;; call alx_set_macaddr
 
mov dword[esi + ALX_CLK_GATE], ALX_CLK_GATE_ALL
 
; idle timeout to switch clk_125M
 
cmp [ebx + device.chip_rev], ALX_REV_B0
jb @f
mov dword[esi + ALX_IDLE_DECISN_TIMER], ALX_IDLE_DECISN_TIMER_DEF
@@:
 
mov dword[esi + ALX_SMB_TIMER], SMB_TIMER * 500
 
mov eax, [esi + ALX_MASTER]
or eax, ALX_MASTER_IRQMOD2_EN or ALX_MASTER_IRQMOD1_EN or ALX_MASTER_SYSALVTIMER_EN
mov [esi + ALX_MASTER], eax
 
mov dword[esi + ALX_IRQ_MODU_TIMER], (IMT / 2) shl ALX_IRQ_MODU_TIMER1_SHIFT
 
; intr re-trig timeout
mov dword[esi + ALX_INT_RETRIG], ALX_INT_RETRIG_TO
 
; tpd threshold to trig int
mov dword[esi + ALX_TINT_TPD_THRSHLD], ITH_TPD
mov dword[esi + ALX_TINT_TIMER], IMT
 
mov dword[esi + ALX_MTU], RX_BUFFER_SIZE + 8 ;;;;
 
mov dword[esi + ALX_TXQ1], (((RX_BUFFER_SIZE + 8 + 7) shr 3) or ALX_TXQ1_ERRLGPKT_DROP_EN)
 
; rxq, flow control
 
; TODO set ALX_RXQ2
 
; RXQ0
mov eax, (ALX_RXQ0_NUM_RFD_PREF_DEF shl ALX_RXQ0_NUM_RFD_PREF_SHIFT) \
or (ALX_RXQ0_RSS_MODE_DIS shl ALX_RXQ0_RSS_MODE_SHIFT) \
or (ALX_RXQ0_IDT_TBL_SIZE_DEF shl ALX_RXQ0_IDT_TBL_SIZE_SHIFT) \
or ALX_RXQ0_RSS_HSTYP_ALL or ALX_RXQ0_RSS_HASH_EN or ALX_RXQ0_IPV6_PARSE_EN
 
test [ebx + device.pci_dev], 1 ;;; FIXME: is gigabit device?
jz @f
or eax, ALX_RXQ0_ASPM_THRESH_100M shl ALX_RXQ0_ASPM_THRESH_SHIFT
@@:
mov dword[esi + ALX_RXQ0], eax
 
; TODO: DMA
; mov eax, [esi + ALX_DMA] ; read and ignore?
; mov eax, [ebx + device.dma_chnl]
; dec eax
; shl eax, ALX_DMA_RCHNL_SEL_SHIFT
; or eax, (ALX_DMA_RORDER_MODE_OUT shl ALX_DMA_RORDER_MODE_SHIFT) \
; or ALX_DMA_RREQ_PRI_DATA \
; or (max_payload shl ALX_DMA_RREQ_BLEN_SHIFT ) \
; or (ALX_DMA_WDLY_CNT_DEF shl ALX_DMA_WDLY_CNT_SHIFT ) \
; or (ALX_DMA_RDLY_CNT_DEF shl ALX_DMA_RDLY_CNT_SHIFT )
; mov [esi + ALX_DMA], eax
 
 
; default multi-tx-q weights
mov eax, (ALX_WRR_PRI_RESTRICT_NONE shl ALX_WRR_PRI_SHIFT) \
or (4 shl ALX_WRR_PRI0_SHIFT) \
or (4 shl ALX_WRR_PRI1_SHIFT) \
or (4 shl ALX_WRR_PRI2_SHIFT) \
or (4 shl ALX_WRR_PRI3_SHIFT)
mov [esi + ALX_WRR], eax
 
ret
 
 
align 16
alx_disable_rss:
 
DEBUGF 1,"alx_disable_rss\n"
 
mov esi, [ebx + device.mmio_addr]
 
mov eax, [esi + ALX_RXQ0]
and eax, not (ALX_RXQ0_RSS_HASH_EN)
mov [esi + ALX_RXQ0] , eax
 
ret
 
align 16
__alx_set_rx_mode:
 
DEBUGF 1,"__alx_set_rx_mode\n"
 
mov esi, [ebx + device.mmio_addr]
 
; if (!(netdev->flags & IFF_ALLMULTI)) {
; netdev_for_each_mc_addr(ha, netdev)
; alx_add_mc_addr(hw, ha->addr, mc_hash);
;
; alx_write_mem32(hw, ALX_HASH_TBL0, mc_hash[0]);
; alx_write_mem32(hw, ALX_HASH_TBL1, mc_hash[1]);
; }
 
mov eax, [ebx + device.rx_ctrl]
or eax, ALX_MAC_CTRL_PROMISC_EN or ALX_MAC_CTRL_MULTIALL_EN
mov [ebx + device.rx_ctrl], eax
mov dword[esi + ALX_MAC_CTRL], eax
 
ret
 
 
align 16
alx_check_link:
 
call alx_clear_phy_intr
 
mov edx, [ebx + device.state]
 
call alx_get_phy_link
cmp eax, 0
jl .reset
 
mov esi, [ebx + device.mmio_addr]
 
spin_lock_irqsave
or [ebx + device.int_mask], ALX_ISR_PHY
mov eax, [ebx + device.int_mask]
mov [esi + ALX_IMR], eax
spin_unlock_irqrestore
 
cmp edx, [ebx + device.state]
je .no_change
 
cmp [ebx + device.state], ETH_LINK_DOWN
je .link_down
 
call alx_post_phy_link
mov ecx, (ALX_PMCTRL_L0S_EN or ALX_PMCTRL_L1_EN or ALX_PMCTRL_ASPM_FCEN)
call alx_enable_aspm
call alx_start_mac
 
invoke NetLinkChanged
 
ret
 
.no_change:
DEBUGF 1, "link state unchanged\n"
 
ret
 
.link_down:
; Link is now down
 
call alx_reset_mac
test eax, eax
jnz .reset
 
call alx_irq_disable
 
; MAC reset causes all HW settings to be lost, restore all
call alx_reinit_rings
test eax, eax
jnz .reset
 
call alx_configure
mov ecx, (ALX_PMCTRL_L1_EN or ALX_PMCTRL_ASPM_FCEN)
call alx_enable_aspm
call alx_post_phy_link
call alx_irq_enable
 
invoke NetLinkChanged
 
ret
 
.reset:
DEBUGF 1, "alx_schedule_reset"
;;; call alx_schedule_reset
 
ret
 
 
align 16
alx_post_phy_link:
 
cmp [ebx + device.chip_rev], ALX_REV_B0
ja .done
 
cmp [ebx + device.state], ETH_LINK_UNKNOWN
jae @f
 
; TODO
; stdcall alx_read_phy_ext, ALX_MIIEXT_AFE, ALX_MIIEXT_ANEG
; and eax, not (ALX_AFE_10BT_100M_TH)
; stdcall alx_write_phy_ext, ALX_MIIEXT_AFE, ALX_MIIEXT_ANEG, eax
 
ret
@@:
 
.done:
 
ret
 
 
align 16
alx_clear_phy_intr:
 
stdcall alx_read_phy_reg, 0, ALX_MII_ISR
 
ret
 
 
align 16
alx_get_phy_link:
 
DEBUGF 1,"alx_get_phy_link\n"
 
stdcall alx_read_phy_reg, 0, MII_BMSR
stdcall alx_read_phy_reg, 0, MII_BMSR
 
mov [ebx + device.state], ETH_LINK_DOWN
 
test ax, BMSR_LSTATUS
jnz @f
DEBUGF 1,"link is down\n"
xor eax, eax
ret
@@:
stdcall alx_read_phy_reg, 0, ALX_MII_GIGA_PSSR
test ax, ALX_GIGA_PSSR_SPD_DPLX_RESOLVED
jz .wrong_speed
 
DEBUGF 1,"link is up\n"
 
test ax, ALX_GIGA_PSSR_DPLX
jz @f
or [ebx + device.state], ETH_LINK_FD
DEBUGF 1,"full duplex\n"
@@:
 
and ax, ALX_GIGA_PSSR_SPEED
cmp ax, ALX_GIGA_PSSR_1000MBS
jne @f
or [ebx + device.state], ETH_LINK_1G
DEBUGF 1,"1 gigabit\n"
ret
 
@@:
cmp ax, ALX_GIGA_PSSR_100MBS
jne @f
or [ebx + device.state], ETH_LINK_100M
DEBUGF 1,"100 mbit\n"
ret
 
@@:
cmp ax, ALX_GIGA_PSSR_10MBS
jne @f
or [ebx + device.state], ETH_LINK_10M
DEBUGF 1,"10 mbit\n"
ret
 
@@:
mov [ebx + device.state], ETH_LINK_UNKNOWN
DEBUGF 1,"speed unknown\n"
ret
 
.wrong_speed:
DEBUGF 1,"wrong speed\n"
xor eax, eax
dec eax
ret
 
 
 
 
align 16
proc alx_read_phy_reg stdcall, phy_addr:dword, reg:dword
 
; FIXME: Only internal PHY for now, fixed clock
 
DEBUGF 1,"PHY read, addr=0x%x reg=0x%x\n", [phy_addr]:8, [reg]:8
 
mov esi, [ebx + device.mmio_addr]
 
mov eax, [reg]
shl eax, ALX_MDIO_REG_SHIFT
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
mov dword[esi + ALX_MDIO], eax
 
mov ecx, ALX_MDIO_MAX_AC_TO
.loop:
mov eax, dword[esi + ALX_MDIO]
test eax, ALX_MDIO_BUSY
jz .ready
 
push esi ecx
xor esi, esi
inc esi
invoke Sleep ;; FIXME: udelay(10)
pop ecx esi
 
dec ecx
jnz .loop
 
DEBUGF 1,"PHY read timeout!\n"
xor eax, eax
dec eax
ret
 
.ready:
; shr eax, ALX_MDIO_DATA_SHIFT
and eax, ALX_MDIO_DATA_MASK
 
DEBUGF 1,"PHY read, val=0x%x\n", eax:4
 
ret
 
endp
 
 
 
 
align 16
proc alx_write_phy_reg stdcall, phy_addr:dword, reg:dword, val:dword
 
; FIXME: Only internal PHY for now, fixed clock
 
DEBUGF 1,"PHY write, addr=0x%x reg=0x%x, data=0x%x\n", [phy_addr]:8, [reg]:8, [val]:8
 
mov esi, [ebx + device.mmio_addr]
 
mov eax, [reg]
shl eax, ALX_MDIO_REG_SHIFT
mov ax, word[val] ; data must be in 16 lower bits :)
or eax, ALX_MDIO_SPRES_PRMBL or (ALX_MDIO_CLK_SEL_25MD4 shl ALX_MDIO_CLK_SEL_SHIFT) or ALX_MDIO_START
mov dword[esi + ALX_MDIO], eax
 
mov ecx, ALX_MDIO_MAX_AC_TO
.loop:
mov eax, dword[esi + ALX_MDIO]
test eax, ALX_MDIO_BUSY
jz .ready
 
push esi ecx
xor esi, esi
inc esi
invoke Sleep ;; FIXME: udelay(10)
pop ecx esi
 
dec ecx
jnz .loop
 
DEBUGF 1,"PHY write timeout!\n"
xor eax, eax
dec eax
ret
 
.ready:
DEBUGF 1,"PHY write OK\n"
xor eax, eax
 
ret
endp
 
align 16
alx_request_irq:
 
DEBUGF 1,"Request IRQ\n"
 
mov esi, [ebx + device.mmio_addr]
 
; Only legacy interrupts supported for now.
mov dword[esi + ALX_MSI_RETRANS_TIMER], 0
 
ret
 
 
; End of code
 
data fixups
end data
 
include '../peimport.inc'
 
my_service db 'AR81XX',0 ; max 16 chars include zero
 
include_debug_strings
 
align 4
devices dd 0
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
 
/drivers/ethernet/ar81xx.inc
0,0 → 1,924
ALX_DEV_ID_AR8161 = 0x1091
ALX_DEV_ID_E2200 = 0xe091
ALX_DEV_ID_E2400 = 0xe0a1
ALX_DEV_ID_E2500 = 0xe0b1
ALX_DEV_ID_AR8162 = 0x1090
ALX_DEV_ID_AR8171 = 0x10A1
ALX_DEV_ID_AR8172 = 0x10A0
 
; rev definition,
; bit0: with xD support
; bit1: with Card Reader function
; bit(7:2): real revision
 
ALX_PCI_REVID_SHIFT = 3
ALX_REV_A0 = 0
ALX_REV_A1 = 1
ALX_REV_B0 = 2
ALX_REV_C0 = 3
 
ALX_DEV_CTRL = 0x0060
ALX_DEV_CTRL_MAXRRS_MIN = 2
 
ALX_MSIX_MASK = 0x0090
 
ALX_UE_SVRT = 0x010C
ALX_UE_SVRT_FCPROTERR = (1 shl 13)
ALX_UE_SVRT_DLPROTERR = (1 shl 4)
 
; eeprom & flash load register
ALX_EFLD = 0x0204
ALX_EFLD_F_EXIST = (1 shl 10)
ALX_EFLD_E_EXIST = (1 shl 9)
ALX_EFLD_STAT = (1 shl 5)
ALX_EFLD_START = (1 shl 0)
 
; eFuse load register
ALX_SLD = 0x0218
ALX_SLD_STAT = (1 shl 12)
ALX_SLD_START = (1 shl 11)
ALX_SLD_MAX_TO = 100
 
ALX_PDLL_TRNS1 = 0x1104
ALX_PDLL_TRNS1_D3PLLOFF_EN = (1 shl 11)
 
ALX_PMCTRL = 0x12F8
ALX_PMCTRL_HOTRST_WTEN = (1 shl 31)
; bit30: L0s/L1 controlled by MAC based on throughput(setting in 15A0)
ALX_PMCTRL_ASPM_FCEN = (1 shl 30)
ALX_PMCTRL_SADLY_EN = (1 shl 29)
ALX_PMCTRL_LCKDET_TIMER_MASK = 0xF
ALX_PMCTRL_LCKDET_TIMER_SHIFT = 24
ALX_PMCTRL_LCKDET_TIMER_DEF = 0xC
; bit[23:20] if pm_request_l1 time > @, then enter L0s not L1
ALX_PMCTRL_L1REQ_TO_MASK = 0xF
ALX_PMCTRL_L1REQ_TO_SHIFT = 20
ALX_PMCTRL_L1REG_TO_DEF = 0xF
ALX_PMCTRL_TXL1_AFTER_L0S = (1 shl 19)
ALX_PMCTRL_L1_TIMER_MASK = 0x7
ALX_PMCTRL_L1_TIMER_SHIFT = 16
ALX_PMCTRL_L1_TIMER_16US = 4
ALX_PMCTRL_RCVR_WT_1US = (1 shl 15)
; bit13: enable pcie clk switch in L1 state
ALX_PMCTRL_L1_CLKSW_EN = (1 shl 13)
ALX_PMCTRL_L0S_EN = (1 shl 12)
ALX_PMCTRL_RXL1_AFTER_L0S = (1 shl 11)
ALX_PMCTRL_L1_BUFSRX_EN = (1 shl 7)
; bit6: power down serdes RX
ALX_PMCTRL_L1_SRDSRX_PWD = (1 shl 6)
ALX_PMCTRL_L1_SRDSPLL_EN = (1 shl 5)
ALX_PMCTRL_L1_SRDS_EN = (1 shl 4)
ALX_PMCTRL_L1_EN = (1 shl 3)
 
;******************************************************
; following registers are mapped only to memory space
;******************************************************
 
ALX_MASTER = 0x1400
; bit12: 1:alwys select pclk from serdes, not sw to 25M
ALX_MASTER_PCLKSEL_SRDS = (1 shl 12)
; bit11: irq moduration for rx
ALX_MASTER_IRQMOD2_EN = (1 shl 11)
; bit10: irq moduration for tx/rx
ALX_MASTER_IRQMOD1_EN = (1 shl 10)
ALX_MASTER_SYSALVTIMER_EN = (1 shl 7)
ALX_MASTER_OOB_DIS = (1 shl 6)
; bit5: wakeup without pcie clk
ALX_MASTER_WAKEN_25M = (1 shl 5)
; bit0: MAC & DMA reset
ALX_MASTER_DMA_MAC_RST = (1 shl 0)
ALX_DMA_MAC_RST_TO = 50
 
ALX_IRQ_MODU_TIMER = 0x1408
ALX_IRQ_MODU_TIMER1_MASK = 0xFFFF
ALX_IRQ_MODU_TIMER1_SHIFT = 0
 
ALX_PHY_CTRL = 0x140C
ALX_PHY_CTRL_100AB_EN = (1 shl 17)
; bit14: affect MAC & PHY, go to low power sts
ALX_PHY_CTRL_POWER_DOWN = (1 shl 14)
; bit13: 1:pll always ON, 0:can switch in lpw
ALX_PHY_CTRL_PLL_ON = (1 shl 13)
ALX_PHY_CTRL_RST_ANALOG = (1 shl 12)
ALX_PHY_CTRL_HIB_PULSE = (1 shl 11)
ALX_PHY_CTRL_HIB_EN = (1 shl 10)
ALX_PHY_CTRL_IDDQ = (1 shl 7)
ALX_PHY_CTRL_GATE_25M = (1 shl 5)
ALX_PHY_CTRL_LED_MODE = (1 shl 2)
; bit0: out of dsp RST state
ALX_PHY_CTRL_DSPRST_OUT = (1 shl 0)
ALX_PHY_CTRL_DSPRST_TO = 80
ALX_PHY_CTRL_CLS = (ALX_PHY_CTRL_LED_MODE or ALX_PHY_CTRL_100AB_EN or ALX_PHY_CTRL_PLL_ON)
 
ALX_MAC_STS = 0x1410
ALX_MAC_STS_TXQ_BUSY = (1 shl 3)
ALX_MAC_STS_RXQ_BUSY = (1 shl 2)
ALX_MAC_STS_TXMAC_BUSY = (1 shl 1)
ALX_MAC_STS_RXMAC_BUSY = (1 shl 0)
ALX_MAC_STS_IDLE = (ALX_MAC_STS_TXQ_BUSY or ALX_MAC_STS_RXQ_BUSY or ALX_MAC_STS_TXMAC_BUSY or ALX_MAC_STS_RXMAC_BUSY)
 
ALX_MDIO = 0x1414
ALX_MDIO_MODE_EXT = (1 shl 30)
ALX_MDIO_BUSY = (1 shl 27)
ALX_MDIO_CLK_SEL_MASK = 0x7
ALX_MDIO_CLK_SEL_SHIFT = 24
ALX_MDIO_CLK_SEL_25MD4 = 0
ALX_MDIO_CLK_SEL_25MD128 = 7
ALX_MDIO_START = (1 shl 23)
ALX_MDIO_SPRES_PRMBL = (1 shl 22)
; bit21: 1:read,0:write
ALX_MDIO_OP_READ = (1 shl 21)
ALX_MDIO_REG_MASK = 0x1F
ALX_MDIO_REG_SHIFT = 16
ALX_MDIO_DATA_MASK = 0xFFFF
ALX_MDIO_DATA_SHIFT = 0
ALX_MDIO_MAX_AC_TO = 120
 
ALX_MDIO_EXTN = 0x1448
ALX_MDIO_EXTN_DEVAD_MASK = 0x1F
ALX_MDIO_EXTN_DEVAD_SHIFT = 16
ALX_MDIO_EXTN_REG_MASK = 0xFFFF
ALX_MDIO_EXTN_REG_SHIFT = 0
 
ALX_SERDES = 0x1424
ALX_SERDES_PHYCLK_SLWDWN = (1 shl 18)
ALX_SERDES_MACCLK_SLWDWN = (1 shl 17)
 
ALX_LPI_CTRL = 0x1440
ALX_LPI_CTRL_EN = (1 shl 0)
 
; for B0+, bit[13..] for C0+
ALX_HRTBT_EXT_CTRL = 0x1AD0
L1F_HRTBT_EXT_CTRL_PERIOD_HIGH_MASK = 0x3F
L1F_HRTBT_EXT_CTRL_PERIOD_HIGH_SHIFT = 24
L1F_HRTBT_EXT_CTRL_SWOI_STARTUP_PKT_EN = (1 shl 23)
L1F_HRTBT_EXT_CTRL_IOAC_2_FRAGMENTED = (1 shl 22)
L1F_HRTBT_EXT_CTRL_IOAC_1_FRAGMENTED = (1 shl 21)
L1F_HRTBT_EXT_CTRL_IOAC_1_KEEPALIVE_EN = (1 shl 20)
L1F_HRTBT_EXT_CTRL_IOAC_1_HAS_VLAN = (1 shl 19)
L1F_HRTBT_EXT_CTRL_IOAC_1_IS_8023 = (1 shl 18)
L1F_HRTBT_EXT_CTRL_IOAC_1_IS_IPV6 = (1 shl 17)
L1F_HRTBT_EXT_CTRL_IOAC_2_KEEPALIVE_EN = (1 shl 16)
L1F_HRTBT_EXT_CTRL_IOAC_2_HAS_VLAN = (1 shl 15)
L1F_HRTBT_EXT_CTRL_IOAC_2_IS_8023 = (1 shl 14)
L1F_HRTBT_EXT_CTRL_IOAC_2_IS_IPV6 = (1 shl 13)
ALX_HRTBT_EXT_CTRL_NS_EN = (1 shl 12)
ALX_HRTBT_EXT_CTRL_FRAG_LEN_MASK = 0xFF
ALX_HRTBT_EXT_CTRL_FRAG_LEN_SHIFT = 4
ALX_HRTBT_EXT_CTRL_IS_8023 = (1 shl 3)
ALX_HRTBT_EXT_CTRL_IS_IPV6 = (1 shl 2)
ALX_HRTBT_EXT_CTRL_WAKEUP_EN = (1 shl 1)
ALX_HRTBT_EXT_CTRL_ARP_EN = (1 shl 0)
 
ALX_HRTBT_REM_IPV4_ADDR = 0x1AD4
ALX_HRTBT_HOST_IPV4_ADDR = 0x1478
ALX_HRTBT_REM_IPV6_ADDR3 = 0x1AD8
ALX_HRTBT_REM_IPV6_ADDR2 = 0x1ADC
ALX_HRTBT_REM_IPV6_ADDR1 = 0x1AE0
ALX_HRTBT_REM_IPV6_ADDR0 = 0x1AE4
 
; 1B8C ~ 1B94 for C0+
ALX_SWOI_ACER_CTRL = 0x1B8C
ALX_SWOI_ORIG_ACK_NAK_EN = (1 shl 20)
ALX_SWOI_ORIG_ACK_NAK_PKT_LEN_MASK = 0xFF
ALX_SWOI_ORIG_ACK_NAK_PKT_LEN_SHIFT = 12
ALX_SWOI_ORIG_ACK_ADDR_MASK = 0xFFF
ALX_SWOI_ORIG_ACK_ADDR_SHIFT = 0
 
ALX_SWOI_IOAC_CTRL_2 = 0x1B90
ALX_SWOI_IOAC_CTRL_2_SWOI_1_FRAG_LEN_MASK = 0xFF
ALX_SWOI_IOAC_CTRL_2_SWOI_1_FRAG_LEN_SHIFT = 24
ALX_SWOI_IOAC_CTRL_2_SWOI_1_PKT_LEN_MASK = 0xFFF
ALX_SWOI_IOAC_CTRL_2_SWOI_1_PKT_LEN_SHIFT = 12
ALX_SWOI_IOAC_CTRL_2_SWOI_1_HDR_ADDR_MASK = 0xFFF
ALX_SWOI_IOAC_CTRL_2_SWOI_1_HDR_ADDR_SHIFT = 0
 
ALX_SWOI_IOAC_CTRL_3 = 0x1B94
ALX_SWOI_IOAC_CTRL_3_SWOI_2_FRAG_LEN_MASK = 0xFF
ALX_SWOI_IOAC_CTRL_3_SWOI_2_FRAG_LEN_SHIFT = 24
ALX_SWOI_IOAC_CTRL_3_SWOI_2_PKT_LEN_MASK = 0xFFF
ALX_SWOI_IOAC_CTRL_3_SWOI_2_PKT_LEN_SHIFT = 12
ALX_SWOI_IOAC_CTRL_3_SWOI_2_HDR_ADDR_MASK = 0xFFF
ALX_SWOI_IOAC_CTRL_3_SWOI_2_HDR_ADDR_SHIFT = 0
 
; for B0
ALX_IDLE_DECISN_TIMER = 0x1474
; 1ms
ALX_IDLE_DECISN_TIMER_DEF = 0x400
 
ALX_MAC_CTRL = 0x1480
ALX_MAC_CTRL_FAST_PAUSE = (1 shl 31)
ALX_MAC_CTRL_WOLSPED_SWEN = (1 shl 30)
; bit29: 1:legacy(hi5b), 0:marvl(lo5b)
ALX_MAC_CTRL_MHASH_ALG_HI5B = (1 shl 29)
ALX_MAC_CTRL_BRD_EN = (1 shl 26)
ALX_MAC_CTRL_MULTIALL_EN = (1 shl 25)
ALX_MAC_CTRL_SPEED_MASK = 0x3
ALX_MAC_CTRL_SPEED_SHIFT = 20
ALX_MAC_CTRL_SPEED_10_100 = 1
ALX_MAC_CTRL_SPEED_1000 = 2
ALX_MAC_CTRL_PROMISC_EN = (1 shl 15)
ALX_MAC_CTRL_VLANSTRIP = (1 shl 14)
ALX_MAC_CTRL_PRMBLEN_MASK = 0xF
ALX_MAC_CTRL_PRMBLEN_SHIFT = 10
ALX_MAC_CTRL_PCRCE = (1 shl 7)
ALX_MAC_CTRL_CRCE = (1 shl 6)
ALX_MAC_CTRL_FULLD = (1 shl 5)
ALX_MAC_CTRL_RXFC_EN = (1 shl 3)
ALX_MAC_CTRL_TXFC_EN = (1 shl 2)
ALX_MAC_CTRL_RX_EN = (1 shl 1)
ALX_MAC_CTRL_TX_EN = (1 shl 0)
 
ALX_STAD0 = 0x1488
ALX_STAD1 = 0x148C
 
ALX_HASH_TBL0 = 0x1490
ALX_HASH_TBL1 = 0x1494
 
ALX_MTU = 0x149C
ALX_MTU_JUMBO_TH = 1514
ALX_MTU_STD_ALGN = 1536
 
ALX_SRAM5 = 0x1524
ALX_SRAM_RXF_LEN_MASK = 0xFFF
ALX_SRAM_RXF_LEN_SHIFT = 0
ALX_SRAM_RXF_LEN_8K = (8*1024)
 
ALX_SRAM9 = 0x1534
ALX_SRAM_LOAD_PTR = (1 shl 0)
 
ALX_RX_BASE_ADDR_HI = 0x1540
 
ALX_TX_BASE_ADDR_HI = 0x1544
 
ALX_RFD_ADDR_LO = 0x1550
ALX_RFD_RING_SZ = 0x1560
ALX_RFD_BUF_SZ = 0x1564
 
ALX_RRD_ADDR_LO = 0x1568
ALX_RRD_RING_SZ = 0x1578
 
; pri3: highest, pri0: lowest
ALX_TPD_PRI3_ADDR_LO = 0x14E4
ALX_TPD_PRI2_ADDR_LO = 0x14E0
ALX_TPD_PRI1_ADDR_LO = 0x157C
ALX_TPD_PRI0_ADDR_LO = 0x1580
 
; producer index is 16bit
ALX_TPD_PRI3_PIDX = 0x1618
ALX_TPD_PRI2_PIDX = 0x161A
ALX_TPD_PRI1_PIDX = 0x15F0
ALX_TPD_PRI0_PIDX = 0x15F2
 
; consumer index is 16bit
ALX_TPD_PRI3_CIDX = 0x161C
ALX_TPD_PRI2_CIDX = 0x161E
ALX_TPD_PRI1_CIDX = 0x15F4
ALX_TPD_PRI0_CIDX = 0x15F6
 
ALX_TPD_RING_SZ = 0x1584
 
ALX_TXQ0 = 0x1590
ALX_TXQ0_TXF_BURST_PREF_MASK = 0xFFFF
ALX_TXQ0_TXF_BURST_PREF_SHIFT = 16
ALX_TXQ_TXF_BURST_PREF_DEF = 0x200
ALX_TXQ0_LSO_8023_EN = (1 shl 7)
ALX_TXQ0_MODE_ENHANCE = (1 shl 6)
ALX_TXQ0_EN = (1 shl 5)
ALX_TXQ0_SUPT_IPOPT = (1 shl 4)
ALX_TXQ0_TPD_BURSTPREF_MASK = 0xF
ALX_TXQ0_TPD_BURSTPREF_SHIFT = 0
ALX_TXQ_TPD_BURSTPREF_DEF = 5
 
ALX_TXQ1 = 0x1594
; bit11: drop large packet, len > (rfd buf)
ALX_TXQ1_ERRLGPKT_DROP_EN = (1 shl 11)
ALX_TXQ1_JUMBO_TSO_TH = (7*1024)
 
ALX_RXQ0 = 0x15A0
ALX_RXQ0_EN = (1 shl 31)
ALX_RXQ0_RSS_HASH_EN = (1 shl 29)
ALX_RXQ0_RSS_MODE_MASK = 0x3
ALX_RXQ0_RSS_MODE_SHIFT = 26
ALX_RXQ0_RSS_MODE_DIS = 0
ALX_RXQ0_RSS_MODE_MQMI = 3
ALX_RXQ0_NUM_RFD_PREF_MASK = 0x3F
ALX_RXQ0_NUM_RFD_PREF_SHIFT = 20
ALX_RXQ0_NUM_RFD_PREF_DEF = 8
ALX_RXQ0_IDT_TBL_SIZE_MASK = 0x1FF
ALX_RXQ0_IDT_TBL_SIZE_SHIFT = 8
ALX_RXQ0_IDT_TBL_SIZE_DEF = 0x100
ALX_RXQ0_IDT_TBL_SIZE_NORMAL = 128
ALX_RXQ0_IPV6_PARSE_EN = (1 shl 7)
ALX_RXQ0_RSS_HSTYP_MASK = 0xF
ALX_RXQ0_RSS_HSTYP_SHIFT = 2
ALX_RXQ0_RSS_HSTYP_IPV6_TCP_EN = (1 shl 5)
ALX_RXQ0_RSS_HSTYP_IPV6_EN = (1 shl 4)
ALX_RXQ0_RSS_HSTYP_IPV4_TCP_EN = (1 shl 3)
ALX_RXQ0_RSS_HSTYP_IPV4_EN = (1 shl 2)
ALX_RXQ0_RSS_HSTYP_ALL = (ALX_RXQ0_RSS_HSTYP_IPV6_TCP_EN or ALX_RXQ0_RSS_HSTYP_IPV4_TCP_EN or ALX_RXQ0_RSS_HSTYP_IPV6_EN or ALX_RXQ0_RSS_HSTYP_IPV4_EN)
ALX_RXQ0_ASPM_THRESH_MASK = 0x3
ALX_RXQ0_ASPM_THRESH_SHIFT = 0
ALX_RXQ0_ASPM_THRESH_100M = 3
 
ALX_RXQ2 = 0x15A8
ALX_RXQ2_RXF_XOFF_THRESH_MASK = 0xFFF
ALX_RXQ2_RXF_XOFF_THRESH_SHIFT = 16
ALX_RXQ2_RXF_XON_THRESH_MASK = 0xFFF
ALX_RXQ2_RXF_XON_THRESH_SHIFT = 0
; Size = tx-packet(1522) + IPG(12) + SOF(8) + 64(Pause) + IPG(12) + SOF(8) +
; rx-packet(1522) + delay-of-link(64)
; = 3212.
 
ALX_RXQ2_RXF_FLOW_CTRL_RSVD = 3212
 
ALX_DMA = 0x15C0
ALX_DMA_RCHNL_SEL_MASK = 0x3
ALX_DMA_RCHNL_SEL_SHIFT = 26
ALX_DMA_WDLY_CNT_MASK = 0xF
ALX_DMA_WDLY_CNT_SHIFT = 16
ALX_DMA_WDLY_CNT_DEF = 4
ALX_DMA_RDLY_CNT_MASK = 0x1F
ALX_DMA_RDLY_CNT_SHIFT = 11
ALX_DMA_RDLY_CNT_DEF = 15
; bit10: 0:tpd with pri, 1: data
ALX_DMA_RREQ_PRI_DATA = (1 shl 10)
ALX_DMA_RREQ_BLEN_MASK = 0x7
ALX_DMA_RREQ_BLEN_SHIFT = 4
ALX_DMA_RORDER_MODE_MASK = 0x7
ALX_DMA_RORDER_MODE_SHIFT = 0
ALX_DMA_RORDER_MODE_OUT = 4
 
ALX_WOL0 = 0x14A0
ALX_WOL0_PME_LINK = (1 shl 5)
ALX_WOL0_LINK_EN = (1 shl 4)
ALX_WOL0_PME_MAGIC_EN = (1 shl 3)
ALX_WOL0_MAGIC_EN = (1 shl 2)
 
; RFD Producer index
ALX_RFD_PIDX = 0x15E0
 
; RFD Consumer indef
ALX_RFD_CIDX = 0x15F8
 
; MIB
ALX_MIB_BASE = 0x1700
 
ALX_MIB_RX_OK = (ALX_MIB_BASE + 0)
ALX_MIB_RX_BCAST = (ALX_MIB_BASE + 4)
ALX_MIB_RX_MCAST = (ALX_MIB_BASE + 8)
ALX_MIB_RX_PAUSE = (ALX_MIB_BASE + 12)
ALX_MIB_RX_CTRL = (ALX_MIB_BASE + 16)
ALX_MIB_RX_FCS_ERR = (ALX_MIB_BASE + 20)
ALX_MIB_RX_LEN_ERR = (ALX_MIB_BASE + 24)
ALX_MIB_RX_BYTE_CNT = (ALX_MIB_BASE + 28)
ALX_MIB_RX_RUNT = (ALX_MIB_BASE + 32)
ALX_MIB_RX_FRAG = (ALX_MIB_BASE + 36)
ALX_MIB_RX_SZ_64B = (ALX_MIB_BASE + 40)
ALX_MIB_RX_SZ_127B = (ALX_MIB_BASE + 44)
ALX_MIB_RX_SZ_255B = (ALX_MIB_BASE + 48)
ALX_MIB_RX_SZ_511B = (ALX_MIB_BASE + 52)
ALX_MIB_RX_SZ_1023B = (ALX_MIB_BASE + 56)
ALX_MIB_RX_SZ_1518B = (ALX_MIB_BASE + 60)
ALX_MIB_RX_SZ_MAX = (ALX_MIB_BASE + 64)
ALX_MIB_RX_OV_SZ = (ALX_MIB_BASE + 68)
ALX_MIB_RX_OV_RXF = (ALX_MIB_BASE + 72)
ALX_MIB_RX_OV_RRD = (ALX_MIB_BASE + 76)
ALX_MIB_RX_ALIGN_ERR = (ALX_MIB_BASE + 80)
ALX_MIB_RX_BCCNT = (ALX_MIB_BASE + 84)
ALX_MIB_RX_MCCNT = (ALX_MIB_BASE + 88)
ALX_MIB_RX_ERRADDR = (ALX_MIB_BASE + 92)
 
ALX_MIB_TX_OK = (ALX_MIB_BASE + 96)
ALX_MIB_TX_BCAST = (ALX_MIB_BASE + 100)
ALX_MIB_TX_MCAST = (ALX_MIB_BASE + 104)
ALX_MIB_TX_PAUSE = (ALX_MIB_BASE + 108)
ALX_MIB_TX_EXC_DEFER = (ALX_MIB_BASE + 112)
ALX_MIB_TX_CTRL = (ALX_MIB_BASE + 116)
ALX_MIB_TX_DEFER = (ALX_MIB_BASE + 120)
ALX_MIB_TX_BYTE_CNT = (ALX_MIB_BASE + 124)
ALX_MIB_TX_SZ_64B = (ALX_MIB_BASE + 128)
ALX_MIB_TX_SZ_127B = (ALX_MIB_BASE + 132)
ALX_MIB_TX_SZ_255B = (ALX_MIB_BASE + 136)
ALX_MIB_TX_SZ_511B = (ALX_MIB_BASE + 140)
ALX_MIB_TX_SZ_1023B = (ALX_MIB_BASE + 144)
ALX_MIB_TX_SZ_1518B = (ALX_MIB_BASE + 148)
ALX_MIB_TX_SZ_MAX = (ALX_MIB_BASE + 152)
ALX_MIB_TX_SINGLE_COL = (ALX_MIB_BASE + 156)
ALX_MIB_TX_MULTI_COL = (ALX_MIB_BASE + 160)
ALX_MIB_TX_LATE_COL = (ALX_MIB_BASE + 164)
ALX_MIB_TX_ABORT_COL = (ALX_MIB_BASE + 168)
ALX_MIB_TX_UNDERRUN = (ALX_MIB_BASE + 172)
ALX_MIB_TX_TRD_EOP = (ALX_MIB_BASE + 176)
ALX_MIB_TX_LEN_ERR = (ALX_MIB_BASE + 180)
ALX_MIB_TX_TRUNC = (ALX_MIB_BASE + 184)
ALX_MIB_TX_BCCNT = (ALX_MIB_BASE + 188)
ALX_MIB_TX_MCCNT = (ALX_MIB_BASE + 192)
ALX_MIB_UPDATE = (ALX_MIB_BASE + 196)
 
 
ALX_ISR = 0x1600
ALX_ISR_DIS = (1 shl 31)
ALX_ISR_RX_Q7 = (1 shl 30)
ALX_ISR_RX_Q6 = (1 shl 29)
ALX_ISR_RX_Q5 = (1 shl 28)
ALX_ISR_RX_Q4 = (1 shl 27)
ALX_ISR_PCIE_LNKDOWN = (1 shl 26)
ALX_ISR_RX_Q3 = (1 shl 19)
ALX_ISR_RX_Q2 = (1 shl 18)
ALX_ISR_RX_Q1 = (1 shl 17)
ALX_ISR_RX_Q0 = (1 shl 16)
ALX_ISR_TX_Q0 = (1 shl 15)
ALX_ISR_PHY = (1 shl 12)
ALX_ISR_DMAW = (1 shl 10)
ALX_ISR_DMAR = (1 shl 9)
ALX_ISR_TXF_UR = (1 shl 8)
ALX_ISR_TX_Q3 = (1 shl 7)
ALX_ISR_TX_Q2 = (1 shl 6)
ALX_ISR_TX_Q1 = (1 shl 5)
ALX_ISR_RFD_UR = (1 shl 4)
ALX_ISR_RXF_OV = (1 shl 3)
ALX_ISR_MANU = (1 shl 2)
ALX_ISR_TIMER = (1 shl 1)
ALX_ISR_SMB = (1 shl 0)
 
ALX_IMR = 0x1604
 
; re-send assert msg if SW no response
ALX_INT_RETRIG = 0x1608
; 40ms
ALX_INT_RETRIG_TO = 20000
 
ALX_SMB_TIMER = 0x15C4
 
ALX_TINT_TPD_THRSHLD = 0x15C8
 
ALX_TINT_TIMER = 0x15CC
 
ALX_CLK_GATE = 0x1814
ALX_CLK_GATE_RXMAC = (1 shl 5)
ALX_CLK_GATE_TXMAC = (1 shl 4)
ALX_CLK_GATE_RXQ = (1 shl 3)
ALX_CLK_GATE_TXQ = (1 shl 2)
ALX_CLK_GATE_DMAR = (1 shl 1)
ALX_CLK_GATE_DMAW = (1 shl 0)
ALX_CLK_GATE_ALL = (ALX_CLK_GATE_RXMAC or ALX_CLK_GATE_TXMAC or ALX_CLK_GATE_RXQ or ALX_CLK_GATE_TXQ or ALX_CLK_GATE_DMAR or ALX_CLK_GATE_DMAW)
 
; interop between drivers
ALX_DRV = 0x1804
ALX_DRV_PHY_AUTO = (1 shl 28)
ALX_DRV_PHY_1000 = (1 shl 27)
ALX_DRV_PHY_100 = (1 shl 26)
ALX_DRV_PHY_10 = (1 shl 25)
ALX_DRV_PHY_DUPLEX = (1 shl 24)
; bit23: adv Pause
ALX_DRV_PHY_PAUSE = (1 shl 23)
; bit22: adv Asym Pause
ALX_DRV_PHY_MASK = 0xFF
ALX_DRV_PHY_SHIFT = 21
ALX_DRV_PHY_UNKNOWN = 0
 
; flag of phy inited
ALX_PHY_INITED = 0x003F
 
; reg 1830 ~ 186C for C0+, 16 bit map patterns and wake packet detection
ALX_WOL_CTRL2 = 0x1830
ALX_WOL_CTRL2_DATA_STORE = (1 shl 3)
ALX_WOL_CTRL2_PTRN_EVT = (1 shl 2)
ALX_WOL_CTRL2_PME_PTRN_EN = (1 shl 1)
ALX_WOL_CTRL2_PTRN_EN = (1 shl 0)
 
ALX_WOL_CTRL3 = 0x1834
ALX_WOL_CTRL3_PTRN_ADDR_MASK = 0xFFFFF
ALX_WOL_CTRL3_PTRN_ADDR_SHIFT = 0
 
ALX_WOL_CTRL4 = 0x1838
ALX_WOL_CTRL4_PT15_MATCH = (1 shl 31)
ALX_WOL_CTRL4_PT14_MATCH = (1 shl 30)
ALX_WOL_CTRL4_PT13_MATCH = (1 shl 29)
ALX_WOL_CTRL4_PT12_MATCH = (1 shl 28)
ALX_WOL_CTRL4_PT11_MATCH = (1 shl 27)
ALX_WOL_CTRL4_PT10_MATCH = (1 shl 26)
ALX_WOL_CTRL4_PT9_MATCH = (1 shl 25)
ALX_WOL_CTRL4_PT8_MATCH = (1 shl 24)
ALX_WOL_CTRL4_PT7_MATCH = (1 shl 23)
ALX_WOL_CTRL4_PT6_MATCH = (1 shl 22)
ALX_WOL_CTRL4_PT5_MATCH = (1 shl 21)
ALX_WOL_CTRL4_PT4_MATCH = (1 shl 20)
ALX_WOL_CTRL4_PT3_MATCH = (1 shl 19)
ALX_WOL_CTRL4_PT2_MATCH = (1 shl 18)
ALX_WOL_CTRL4_PT1_MATCH = (1 shl 17)
ALX_WOL_CTRL4_PT0_MATCH = (1 shl 16)
ALX_WOL_CTRL4_PT15_EN = (1 shl 15)
ALX_WOL_CTRL4_PT14_EN = (1 shl 14)
ALX_WOL_CTRL4_PT13_EN = (1 shl 13)
ALX_WOL_CTRL4_PT12_EN = (1 shl 12)
ALX_WOL_CTRL4_PT11_EN = (1 shl 11)
ALX_WOL_CTRL4_PT10_EN = (1 shl 10)
ALX_WOL_CTRL4_PT9_EN = (1 shl 9)
ALX_WOL_CTRL4_PT8_EN = (1 shl 8)
ALX_WOL_CTRL4_PT7_EN = (1 shl 7)
ALX_WOL_CTRL4_PT6_EN = (1 shl 6)
ALX_WOL_CTRL4_PT5_EN = (1 shl 5)
ALX_WOL_CTRL4_PT4_EN = (1 shl 4)
ALX_WOL_CTRL4_PT3_EN = (1 shl 3)
ALX_WOL_CTRL4_PT2_EN = (1 shl 2)
ALX_WOL_CTRL4_PT1_EN = (1 shl 1)
ALX_WOL_CTRL4_PT0_EN = (1 shl 0)
 
ALX_WOL_CTRL5 = 0x183C
ALX_WOL_CTRL5_PT3_LEN_MASK = 0xFF
ALX_WOL_CTRL5_PT3_LEN_SHIFT = 24
ALX_WOL_CTRL5_PT2_LEN_MASK = 0xFF
ALX_WOL_CTRL5_PT2_LEN_SHIFT = 16
ALX_WOL_CTRL5_PT1_LEN_MASK = 0xFF
ALX_WOL_CTRL5_PT1_LEN_SHIFT = 8
ALX_WOL_CTRL5_PT0_LEN_MASK = 0xFF
ALX_WOL_CTRL5_PT0_LEN_SHIFT = 0
 
ALX_WOL_CTRL6 = 0x1840
ALX_WOL_CTRL5_PT7_LEN_MASK = 0xFF
ALX_WOL_CTRL5_PT7_LEN_SHIFT = 24
ALX_WOL_CTRL5_PT6_LEN_MASK = 0xFF
ALX_WOL_CTRL5_PT6_LEN_SHIFT = 16
ALX_WOL_CTRL5_PT5_LEN_MASK = 0xFF
ALX_WOL_CTRL5_PT5_LEN_SHIFT = 8
ALX_WOL_CTRL5_PT4_LEN_MASK = 0xFF
ALX_WOL_CTRL5_PT4_LEN_SHIFT = 0
 
ALX_WOL_CTRL7 = 0x1844
ALX_WOL_CTRL5_PT11_LEN_MASK = 0xFF
ALX_WOL_CTRL5_PT11_LEN_SHIFT = 24
ALX_WOL_CTRL5_PT10_LEN_MASK = 0xFF
ALX_WOL_CTRL5_PT10_LEN_SHIFT = 16
ALX_WOL_CTRL5_PT9_LEN_MASK = 0xFF
ALX_WOL_CTRL5_PT9_LEN_SHIFT = 8
ALX_WOL_CTRL5_PT8_LEN_MASK = 0xFF
ALX_WOL_CTRL5_PT8_LEN_SHIFT = 0
 
ALX_WOL_CTRL8 = 0x1848
ALX_WOL_CTRL5_PT15_LEN_MASK = 0xFF
ALX_WOL_CTRL5_PT15_LEN_SHIFT = 24
ALX_WOL_CTRL5_PT14_LEN_MASK = 0xFF
ALX_WOL_CTRL5_PT14_LEN_SHIFT = 16
ALX_WOL_CTRL5_PT13_LEN_MASK = 0xFF
ALX_WOL_CTRL5_PT13_LEN_SHIFT = 8
ALX_WOL_CTRL5_PT12_LEN_MASK = 0xFF
ALX_WOL_CTRL5_PT12_LEN_SHIFT = 0
 
ALX_ACER_FIXED_PTN0 = 0x1850
ALX_ACER_FIXED_PTN0_MASK = 0xFFFFFFFF
ALX_ACER_FIXED_PTN0_SHIFT = 0
 
ALX_ACER_FIXED_PTN1 = 0x1854
ALX_ACER_FIXED_PTN1_MASK = 0xFFFF
ALX_ACER_FIXED_PTN1_SHIFT = 0
 
ALX_ACER_RANDOM_NUM0 = 0x1858
ALX_ACER_RANDOM_NUM0_MASK = 0xFFFFFFFF
ALX_ACER_RANDOM_NUM0_SHIFT = 0
 
ALX_ACER_RANDOM_NUM1 = 0x185C
ALX_ACER_RANDOM_NUM1_MASK = 0xFFFFFFFF
ALX_ACER_RANDOM_NUM1_SHIFT = 0
 
ALX_ACER_RANDOM_NUM2 = 0x1860
ALX_ACER_RANDOM_NUM2_MASK = 0xFFFFFFFF
ALX_ACER_RANDOM_NUM2_SHIFT = 0
 
ALX_ACER_RANDOM_NUM3 = 0x1864
ALX_ACER_RANDOM_NUM3_MASK = 0xFFFFFFFF
ALX_ACER_RANDOM_NUM3_SHIFT = 0
 
ALX_ACER_MAGIC = 0x1868
ALX_ACER_MAGIC_EN = (1 shl 31)
ALX_ACER_MAGIC_PME_EN = (1 shl 30)
ALX_ACER_MAGIC_MATCH = (1 shl 29)
ALX_ACER_MAGIC_FF_CHECK = (1 shl 10)
ALX_ACER_MAGIC_RAN_LEN_MASK = 0x1F
ALX_ACER_MAGIC_RAN_LEN_SHIFT = 5
ALX_ACER_MAGIC_FIX_LEN_MASK = 0x1F
ALX_ACER_MAGIC_FIX_LEN_SHIFT = 0
 
ALX_ACER_TIMER = 0x186C
ALX_ACER_TIMER_EN = (1 shl 31)
ALX_ACER_TIMER_PME_EN = (1 shl 30)
ALX_ACER_TIMER_MATCH = (1 shl 29)
ALX_ACER_TIMER_THRES_MASK = 0x1FFFF
ALX_ACER_TIMER_THRES_SHIFT = 0
ALX_ACER_TIMER_THRES_DEF = 1
 
; RSS definitions
ALX_RSS_KEY0 = 0x14B0
ALX_RSS_KEY1 = 0x14B4
ALX_RSS_KEY2 = 0x14B8
ALX_RSS_KEY3 = 0x14BC
ALX_RSS_KEY4 = 0x14C0
ALX_RSS_KEY5 = 0x14C4
ALX_RSS_KEY6 = 0x14C8
ALX_RSS_KEY7 = 0x14CC
ALX_RSS_KEY8 = 0x14D0
ALX_RSS_KEY9 = 0x14D4
 
ALX_RSS_IDT_TBL0 = 0x1B00
 
ALX_MSI_MAP_TBL1 = 0x15D0
ALX_MSI_MAP_TBL1_TXQ1_SHIFT = 20
ALX_MSI_MAP_TBL1_TXQ0_SHIFT = 16
ALX_MSI_MAP_TBL1_RXQ3_SHIFT = 12
ALX_MSI_MAP_TBL1_RXQ2_SHIFT = 8
ALX_MSI_MAP_TBL1_RXQ1_SHIFT = 4
ALX_MSI_MAP_TBL1_RXQ0_SHIFT = 0
 
ALX_MSI_MAP_TBL2 = 0x15D8
ALX_MSI_MAP_TBL2_TXQ3_SHIFT = 20
ALX_MSI_MAP_TBL2_TXQ2_SHIFT = 16
ALX_MSI_MAP_TBL2_RXQ7_SHIFT = 12
ALX_MSI_MAP_TBL2_RXQ6_SHIFT = 8
ALX_MSI_MAP_TBL2_RXQ5_SHIFT = 4
ALX_MSI_MAP_TBL2_RXQ4_SHIFT = 0
 
ALX_MSI_ID_MAP = 0x15D4
 
ALX_MSI_RETRANS_TIMER = 0x1920
; bit16: 1:line,0:standard
ALX_MSI_MASK_SEL_LINE = (1 shl 16)
ALX_MSI_RETRANS_TM_MASK = 0xFFFF
ALX_MSI_RETRANS_TM_SHIFT = 0
 
; CR DMA ctrl
 
; TX QoS
ALX_WRR = 0x1938
ALX_WRR_PRI_MASK = 0x3
ALX_WRR_PRI_SHIFT = 29
ALX_WRR_PRI_RESTRICT_NONE = 3
ALX_WRR_PRI3_MASK = 0x1F
ALX_WRR_PRI3_SHIFT = 24
ALX_WRR_PRI2_MASK = 0x1F
ALX_WRR_PRI2_SHIFT = 16
ALX_WRR_PRI1_MASK = 0x1F
ALX_WRR_PRI1_SHIFT = 8
ALX_WRR_PRI0_MASK = 0x1F
ALX_WRR_PRI0_SHIFT = 0
 
ALX_HQTPD = 0x193C
ALX_HQTPD_BURST_EN = (1 shl 31)
ALX_HQTPD_Q3_NUMPREF_MASK = 0xF
ALX_HQTPD_Q3_NUMPREF_SHIFT = 8
ALX_HQTPD_Q2_NUMPREF_MASK = 0xF
ALX_HQTPD_Q2_NUMPREF_SHIFT = 4
ALX_HQTPD_Q1_NUMPREF_MASK = 0xF
ALX_HQTPD_Q1_NUMPREF_SHIFT = 0
 
ALX_MISC = 0x19C0
ALX_MISC_PSW_OCP_MASK = 0x7
ALX_MISC_PSW_OCP_SHIFT = 21
ALX_MISC_PSW_OCP_DEF = 0x7
ALX_MISC_ISO_EN = (1 shl 12)
ALX_MISC_INTNLOSC_OPEN = (1 shl 3)
 
ALX_MSIC2 = 0x19C8
ALX_MSIC2_CALB_START = (1 shl 0)
 
ALX_MISC3 = 0x19CC
; bit1: 1:Software control 25M
ALX_MISC3_25M_BY_SW = (1 shl 1)
; bit0: 25M switch to intnl OSC
ALX_MISC3_25M_NOTO_INTNL = (1 shl 0)
 
; MSIX tbl in memory space
ALX_MSIX_ENTRY_BASE = 0x2000
 
;******************** PHY regs definition;**************************
 
; PHY Specific Status Register
ALX_MII_GIGA_PSSR = 0x11
ALX_GIGA_PSSR_SPD_DPLX_RESOLVED = 0x0800
ALX_GIGA_PSSR_DPLX = 0x2000
ALX_GIGA_PSSR_SPEED = 0xC000
ALX_GIGA_PSSR_10MBS = 0x0000
ALX_GIGA_PSSR_100MBS = 0x4000
ALX_GIGA_PSSR_1000MBS = 0x8000
 
; PHY Interrupt Enable Register
ALX_MII_IER = 0x12
ALX_IER_LINK_UP = 0x0400
ALX_IER_LINK_DOWN = 0x0800
 
; PHY Interrupt Status Register
ALX_MII_ISR = 0x13
 
ALX_MII_DBG_ADDR = 0x1D
ALX_MII_DBG_DATA = 0x1E
 
;**************************** debug port;************************************
 
ALX_MIIDBG_ANACTRL = 0x00
ALX_ANACTRL_DEF = 0x02EF
 
ALX_MIIDBG_SYSMODCTRL = 0x04
; en half bias
ALX_SYSMODCTRL_IECHOADJ_DEF = 0xBB8B
 
ALX_MIIDBG_SRDSYSMOD = 0x05
ALX_SRDSYSMOD_DEEMP_EN = 0x0040
ALX_SRDSYSMOD_DEF = 0x2C46
 
ALX_MIIDBG_HIBNEG = 0x0B
ALX_HIBNEG_PSHIB_EN = 0x8000
ALX_HIBNEG_HIB_PSE = 0x1000
ALX_HIBNEG_DEF = 0xBC40
ALX_HIBNEG_NOHIB = (ALX_HIBNEG_DEF and not(ALX_HIBNEG_PSHIB_EN or ALX_HIBNEG_HIB_PSE))
 
ALX_MIIDBG_TST10BTCFG = 0x12
ALX_TST10BTCFG_DEF = 0x4C04
 
ALX_MIIDBG_AZ_ANADECT = 0x15
ALX_AZ_ANADECT_DEF = 0x3220
ALX_AZ_ANADECT_LONG = 0x3210
 
ALX_MIIDBG_MSE16DB = 0x18
ALX_MSE16DB_UP = 0x05EA
ALX_MSE16DB_DOWN = 0x02EA
 
ALX_MIIDBG_MSE20DB = 0x1C
ALX_MSE20DB_TH_MASK = 0x7F
ALX_MSE20DB_TH_SHIFT = 2
ALX_MSE20DB_TH_DEF = 0x2E
ALX_MSE20DB_TH_HI = 0x54
 
ALX_MIIDBG_AGC = 0x23
ALX_AGC_2_VGA_MASK = 0x3F
ALX_AGC_2_VGA_SHIFT = 8
ALX_AGC_LONG1G_LIMT = 40
ALX_AGC_LONG100M_LIMT = 44
 
ALX_MIIDBG_LEGCYPS = 0x29
ALX_LEGCYPS_EN = 0x8000
ALX_LEGCYPS_DEF = 0x129D
 
ALX_MIIDBG_TST100BTCFG = 0x36
ALX_TST100BTCFG_DEF = 0xE12C
 
ALX_MIIDBG_GREENCFG = 0x3B
ALX_GREENCFG_DEF = 0x7078
 
ALX_MIIDBG_GREENCFG2 = 0x3D
ALX_GREENCFG2_BP_GREEN = 0x8000
ALX_GREENCFG2_GATE_DFSE_EN = 0x0080
 
;****** dev 3;********
ALX_MIIEXT_PCS = 3
 
ALX_MIIEXT_CLDCTRL3 = 0x8003
ALX_CLDCTRL3_BP_CABLE1TH_DET_GT = 0x8000
 
ALX_MIIEXT_CLDCTRL5 = 0x8005
ALX_CLDCTRL5_BP_VD_HLFBIAS = 0x4000
 
ALX_MIIEXT_CLDCTRL6 = 0x8006
ALX_CLDCTRL6_CAB_LEN_MASK = 0xFF
ALX_CLDCTRL6_CAB_LEN_SHIFT = 0
ALX_CLDCTRL6_CAB_LEN_SHORT1G = 116
ALX_CLDCTRL6_CAB_LEN_SHORT100M = 152
 
ALX_MIIEXT_VDRVBIAS = 0x8062
ALX_VDRVBIAS_DEF = 0x3
 
;******** dev 7;*********
ALX_MIIEXT_ANEG = 7
 
ALX_MIIEXT_LOCAL_EEEADV = 0x3C
ALX_LOCAL_EEEADV_1000BT = 0x0004
ALX_LOCAL_EEEADV_100BT = 0x0002
 
ALX_MIIEXT_AFE = 0x801A
ALX_AFE_10BT_100M_TH = 0x0040
 
ALX_MIIEXT_S3DIG10 = 0x8023
; bit0: 1:bypass 10BT rx fifo, 0:original 10BT rx
ALX_MIIEXT_S3DIG10_SL = 0x0001
ALX_MIIEXT_S3DIG10_DEF = 0
 
ALX_MIIEXT_NLP78 = 0x8027
ALX_MIIEXT_NLP78_120M_DEF = 0x8A05
 
 
; tpd word 1
TPD_CXSUMSTART_MASK = 0x00FF
TPD_CXSUMSTART_SHIFT = 0
TPD_L4HDROFFSET_MASK = 0x00FF
TPD_L4HDROFFSET_SHIFT = 0
TPD_CXSUM_EN_MASK = 0x0001
TPD_CXSUM_EN_SHIFT = 8
TPD_IP_XSUM_MASK = 0x0001
TPD_IP_XSUM_SHIFT = 9
TPD_TCP_XSUM_MASK = 0x0001
TPD_TCP_XSUM_SHIFT = 10
TPD_UDP_XSUM_MASK = 0x0001
TPD_UDP_XSUM_SHIFT = 11
TPD_LSO_EN_MASK = 0x0001
TPD_LSO_EN_SHIFT = 12
TPD_LSO_V2_MASK = 0x0001
TPD_LSO_V2_SHIFT = 13
TPD_VLTAGGED_MASK = 0x0001
TPD_VLTAGGED_SHIFT = 14
TPD_INS_VLTAG_MASK = 0x0001
TPD_INS_VLTAG_SHIFT = 15
TPD_IPV4_MASK = 0x0001
TPD_IPV4_SHIFT = 16
TPD_ETHTYPE_MASK = 0x0001
TPD_ETHTYPE_SHIFT = 17
TPD_CXSUMOFFSET_MASK = 0x00FF
TPD_CXSUMOFFSET_SHIFT = 18
TPD_MSS_MASK = 0x1FFF
TPD_MSS_SHIFT = 18
TPD_EOP_MASK = 0x0001
TPD_EOP_SHIFT = 31
 
 
; rrd word 0
RRD_XSUM_MASK = 0xFFFF
RRD_XSUM_SHIFT = 0
RRD_NOR_MASK = 0x000F
RRD_NOR_SHIFT = 16
RRD_SI_MASK = 0x0FFF
RRD_SI_SHIFT = 20
 
; rrd word 2
RRD_VLTAG_MASK = 0xFFFF
RRD_VLTAG_SHIFT = 0
RRD_PID_MASK = 0x00FF
RRD_PID_SHIFT = 16
; non-ip packet
RRD_PID_NONIP = 0
; ipv4(only)
RRD_PID_IPV4 = 1
; tcp/ipv6
RRD_PID_IPV6TCP = 2
; tcp/ipv4
RRD_PID_IPV4TCP = 3
; udp/ipv6
RRD_PID_IPV6UDP = 4
; udp/ipv4
RRD_PID_IPV4UDP = 5
; ipv6(only)
RRD_PID_IPV6 = 6
; LLDP packet
RRD_PID_LLDP = 7
; 1588 packet
RRD_PID_1588 = 8
RRD_RSSQ_MASK = 0x0007
RRD_RSSQ_SHIFT = 25
RRD_RSSALG_MASK = 0x000F
RRD_RSSALG_SHIFT = 28
RRD_RSSALG_TCPV6 = 0x1
RRD_RSSALG_IPV6 = 0x2
RRD_RSSALG_TCPV4 = 0x4
RRD_RSSALG_IPV4 = 0x8
 
; rrd word 3
RRD_PKTLEN_MASK = 0x3FFF
RRD_PKTLEN_SHIFT = 0
RRD_ERR_L4_MASK = 0x0001
RRD_ERR_L4_SHIFT = 14
RRD_ERR_IPV4_MASK = 0x0001
RRD_ERR_IPV4_SHIFT = 15
RRD_VLTAGGED_MASK = 0x0001
RRD_VLTAGGED_SHIFT = 16
RRD_OLD_PID_MASK = 0x0007
RRD_OLD_PID_SHIFT = 17
RRD_ERR_RES_MASK = 0x0001
RRD_ERR_RES_SHIFT = 20
RRD_ERR_FCS_MASK = 0x0001
RRD_ERR_FCS_SHIFT = 21
RRD_ERR_FAE_MASK = 0x0001
RRD_ERR_FAE_SHIFT = 22
RRD_ERR_TRUNC_MASK = 0x0001
RRD_ERR_TRUNC_SHIFT = 23
RRD_ERR_RUNT_MASK = 0x0001
RRD_ERR_RUNT_SHIFT = 24
RRD_ERR_ICMP_MASK = 0x0001
RRD_ERR_ICMP_SHIFT = 25
RRD_BCAST_MASK = 0x0001
RRD_BCAST_SHIFT = 26
RRD_MCAST_MASK = 0x0001
RRD_MCAST_SHIFT = 27
RRD_ETHTYPE_MASK = 0x0001
RRD_ETHTYPE_SHIFT = 28
RRD_ERR_FIFOV_MASK = 0x0001
RRD_ERR_FIFOV_SHIFT = 29
RRD_ERR_LEN_MASK = 0x0001
RRD_ERR_LEN_SHIFT = 30
RRD_UPDATED_MASK = 0x0001
RRD_UPDATED_SHIFT = 31
 
 
ALX_ISR_MISC = ALX_ISR_PCIE_LNKDOWN or ALX_ISR_DMAW or ALX_ISR_DMAR or ALX_ISR_SMB or ALX_ISR_MANU or ALX_ISR_TIMER
 
ALX_ISR_FATAL = ALX_ISR_PCIE_LNKDOWN or ALX_ISR_DMAW or ALX_ISR_DMAR
 
ALX_ISR_ALERT = ALX_ISR_RXF_OV or ALX_ISR_TXF_UR or ALX_ISR_RFD_UR
 
ALX_ISR_ALL_QUEUES = ALX_ISR_TX_Q0 or ALX_ISR_TX_Q1 or ALX_ISR_TX_Q2 or ALX_ISR_TX_Q3 or ALX_ISR_RX_Q0 or ALX_ISR_RX_Q1 or ALX_ISR_RX_Q2 or ALX_ISR_RX_Q3 or ALX_ISR_RX_Q4 or ALX_ISR_RX_Q5 or ALX_ISR_RX_Q6 or ALX_ISR_RX_Q7
/drivers/ethernet/i8254x.asm
28,8 → 28,8
 
MAX_PKT_SIZE = 1514 ; Maximum packet size
 
RX_RING_SIZE = 8 ; Must be a power of 2, and minimum 8
TX_RING_SIZE = 8 ; Must be a power of 2, and minimum 8
RX_RING_SIZE = 64 ; Must be a power of 2, and minimum 8
TX_RING_SIZE = 64 ; Must be a power of 2, and minimum 8
 
section '.flat' readable writable executable