0,0 → 1,1204 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; RTL8169.INC ;; |
;; ;; |
;; Ethernet driver for Menuet OS ;; |
;; ;; |
;; Version 0.1 11 February 2007 ;; |
;; ;; |
;; Driver for chips of RealTek 8169 family ;; |
;; References: ;; |
;; r8169.c - linux driver (etherboot project) ;; |
;; ethernet driver template by Mike Hibbett ;; |
;; ;; |
;; The copyright statement is ;; |
;; ;; |
;; GNU GENERAL PUBLIC LICENSE ;; |
;; Version 2, June 1991 ;; |
;; ;; |
;; Copyright 2007 mike.dld, ;; |
;; mike.dld@gmail.com ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|
ETH_ALEN equ 6 |
ETH_HLEN equ (2 * ETH_ALEN + 2) |
ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for |
; mininmum 64bytes frame length |
|
RTL8169_REG_MAC0 equ 0x0 ; Ethernet hardware address |
RTL8169_REG_MAR0 equ 0x8 ; Multicast filter |
RTL8169_REG_TxDescStartAddr equ 0x20 |
RTL8169_REG_TxHDescStartAddr equ 0x28 |
RTL8169_REG_FLASH equ 0x30 |
RTL8169_REG_ERSR equ 0x36 |
RTL8169_REG_ChipCmd equ 0x37 |
RTL8169_REG_TxPoll equ 0x38 |
RTL8169_REG_IntrMask equ 0x3C |
RTL8169_REG_IntrStatus equ 0x3E |
RTL8169_REG_TxConfig equ 0x40 |
RTL8169_REG_RxConfig equ 0x44 |
RTL8169_REG_RxMissed equ 0x4C |
RTL8169_REG_Cfg9346 equ 0x50 |
RTL8169_REG_Config0 equ 0x51 |
RTL8169_REG_Config1 equ 0x52 |
RTL8169_REG_Config2 equ 0x53 |
RTL8169_REG_Config3 equ 0x54 |
RTL8169_REG_Config4 equ 0x55 |
RTL8169_REG_Config5 equ 0x56 |
RTL8169_REG_MultiIntr equ 0x5C |
RTL8169_REG_PHYAR equ 0x60 |
RTL8169_REG_TBICSR equ 0x64 |
RTL8169_REG_TBI_ANAR equ 0x68 |
RTL8169_REG_TBI_LPAR equ 0x6A |
RTL8169_REG_PHYstatus equ 0x6C |
RTL8169_REG_RxMaxSize equ 0xDA |
RTL8169_REG_CPlusCmd equ 0xE0 |
RTL8169_REG_RxDescStartAddr equ 0xE4 |
RTL8169_REG_ETThReg equ 0xEC |
RTL8169_REG_FuncEvent equ 0xF0 |
RTL8169_REG_FuncEventMask equ 0xF4 |
RTL8169_REG_FuncPresetState equ 0xF8 |
RTL8169_REG_FuncForceEvent equ 0xFC |
|
; InterruptStatusBits |
RTL8169_ISB_SYSErr equ 0x8000 |
RTL8169_ISB_PCSTimeout equ 0x4000 |
RTL8169_ISB_SWInt equ 0x0100 |
RTL8169_ISB_TxDescUnavail equ 0x80 |
RTL8169_ISB_RxFIFOOver equ 0x40 |
RTL8169_ISB_LinkChg equ 0x20 |
RTL8169_ISB_RxOverflow equ 0x10 |
RTL8169_ISB_TxErr equ 0x08 |
RTL8169_ISB_TxOK equ 0x04 |
RTL8169_ISB_RxErr equ 0x02 |
RTL8169_ISB_RxOK equ 0x01 |
|
; RxStatusDesc |
RTL8169_SD_RxRES equ 0x00200000 |
RTL8169_SD_RxCRC equ 0x00080000 |
RTL8169_SD_RxRUNT equ 0x00100000 |
RTL8169_SD_RxRWT equ 0x00400000 |
|
; ChipCmdBits |
RTL8169_CMD_Reset equ 0x10 |
RTL8169_CMD_RxEnb equ 0x08 |
RTL8169_CMD_TxEnb equ 0x04 |
RTL8169_CMD_RxBufEmpty equ 0x01 |
|
; Cfg9346Bits |
RTL8169_CFG_9346_Lock equ 0x00 |
RTL8169_CFG_9346_Unlock equ 0xC0 |
|
; rx_mode_bits |
RTL8169_RXM_AcceptErr equ 0x20 |
RTL8169_RXM_AcceptRunt equ 0x10 |
RTL8169_RXM_AcceptBroadcast equ 0x08 |
RTL8169_RXM_AcceptMulticast equ 0x04 |
RTL8169_RXM_AcceptMyPhys equ 0x02 |
RTL8169_RXM_AcceptAllPhys equ 0x01 |
|
; RxConfigBits |
RTL8169_RXC_FIFOShift equ 13 |
RTL8169_RXC_DMAShift equ 8 |
|
; TxConfigBits |
RTL8169_TXC_InterFrameGapShift equ 24 |
RTL8169_TXC_DMAShift equ 8 ; DMA burst value (0-7) is shift this many bits |
|
; rtl8169_PHYstatus |
RTL8169_PHYS_TBI_Enable equ 0x80 |
RTL8169_PHYS_TxFlowCtrl equ 0x40 |
RTL8169_PHYS_RxFlowCtrl equ 0x20 |
RTL8169_PHYS_1000bpsF equ 0x10 |
RTL8169_PHYS_100bps equ 0x08 |
RTL8169_PHYS_10bps equ 0x04 |
RTL8169_PHYS_LinkStatus equ 0x02 |
RTL8169_PHYS_FullDup equ 0x01 |
|
; GIGABIT_PHY_registers |
RTL8169_PHY_CTRL_REG equ 0 |
RTL8169_PHY_STAT_REG equ 1 |
RTL8169_PHY_AUTO_NEGO_REG equ 4 |
RTL8169_PHY_1000_CTRL_REG equ 9 |
|
; GIGABIT_PHY_REG_BIT |
RTL8169_PHY_Restart_Auto_Nego equ 0x0200 |
RTL8169_PHY_Enable_Auto_Nego equ 0x1000 |
|
; PHY_STAT_REG = 1; |
RTL8169_PHY_Auto_Neco_Comp equ 0x0020 |
|
; PHY_AUTO_NEGO_REG = 4; |
RTL8169_PHY_Cap_10_Half equ 0x0020 |
RTL8169_PHY_Cap_10_Full equ 0x0040 |
RTL8169_PHY_Cap_100_Half equ 0x0080 |
RTL8169_PHY_Cap_100_Full equ 0x0100 |
|
; PHY_1000_CTRL_REG = 9; |
RTL8169_PHY_Cap_1000_Full equ 0x0200 |
RTL8169_PHY_Cap_1000_Half equ 0x0100 |
|
RTL8169_PHY_Cap_PAUSE equ 0x0400 |
RTL8169_PHY_Cap_ASYM_PAUSE equ 0x0800 |
|
RTL8169_PHY_Cap_Null equ 0x0 |
|
; _MediaType |
RTL8169_MT_10_Half equ 0x01 |
RTL8169_MT_10_Full equ 0x02 |
RTL8169_MT_100_Half equ 0x04 |
RTL8169_MT_100_Full equ 0x08 |
RTL8169_MT_1000_Full equ 0x10 |
|
; _TBICSRBit |
RTL8169_TBI_LinkOK equ 0x02000000 |
|
; _DescStatusBit |
RTL8169_DSB_OWNbit equ 0x80000000 |
RTL8169_DSB_EORbit equ 0x40000000 |
RTL8169_DSB_FSbit equ 0x20000000 |
RTL8169_DSB_LSbit equ 0x10000000 |
|
; MAC address length |
MAC_ADDR_LEN equ 6 |
|
; max supported gigabit ethernet frame size -- must be at least (dev->mtu+14+4) |
MAX_ETH_FRAME_SIZE equ 1536 |
|
TX_FIFO_THRESH equ 256 ; In bytes |
|
RX_FIFO_THRESH equ 7 ; 7 means NO threshold, Rx buffer level before first PCI xfer |
RX_DMA_BURST equ 7 ; Maximum PCI burst, '6' is 1024 |
TX_DMA_BURST equ 7 ; Maximum PCI burst, '6' is 1024 |
ETTh equ 0x3F ; 0x3F means NO threshold |
|
EarlyTxThld equ 0x3F ; 0x3F means NO early transmit |
RxPacketMaxSize equ 0x0800 ; Maximum size supported is 16K-1 |
InterFrameGap equ 0x03 ; 3 means InterFrameGap = the shortest one |
|
NUM_TX_DESC equ 1 ; Number of Tx descriptor registers |
NUM_RX_DESC equ 4 ; Number of Rx descriptor registers |
RX_BUF_SIZE equ 1536 ; Rx Buffer size |
|
HZ equ 1000 |
|
RTL_MIN_IO_SIZE equ 0x80 |
TX_TIMEOUT equ (6*HZ) |
|
RTL8169_TIMER_EXPIRE_TIME equ 100 |
|
ETH_HDR_LEN equ 14 |
DEFAULT_MTU equ 1500 |
DEFAULT_RX_BUF_LEN equ 1536 |
|
|
;#ifdef RTL8169_JUMBO_FRAME_SUPPORT |
;#define MAX_JUMBO_FRAME_MTU ( 10000 ) |
;#define MAX_RX_SKBDATA_SIZE ( MAX_JUMBO_FRAME_MTU + ETH_HDR_LEN ) |
;#else |
MAX_RX_SKBDATA_SIZE equ 1600 |
;#endif //end #ifdef RTL8169_JUMBO_FRAME_SUPPORT |
|
;#ifdef RTL8169_USE_IO |
;!!!#define RTL_W8(reg, val8) outb ((val8), ioaddr + (reg)) |
macro RTL_W8 reg,val8 { |
if ~reg eq dx |
mov dx,word[rtl8169_tpc.mmio_addr] |
add dx,reg |
end if |
if ~val8 eq al |
mov al,val8 |
end if |
out dx,al |
} |
;!!!#define RTL_W16(reg, val16) outw ((val16), ioaddr + (reg)) |
macro RTL_W16 reg,val16 { |
if ~reg eq dx |
mov dx,word[rtl8169_tpc.mmio_addr] |
add dx,reg |
end if |
if ~val16 eq ax |
mov ax,val16 |
end if |
out dx,ax |
} |
;!!!#define RTL_W32(reg, val32) outl ((val32), ioaddr + (reg)) |
macro RTL_W32 reg,val32 { |
if ~reg eq dx |
mov dx,word[rtl8169_tpc.mmio_addr] |
add dx,reg |
end if |
if ~val32 eq eax |
mov eax,val32 |
end if |
out dx,eax |
} |
;!!!#define RTL_R8(reg) inb (ioaddr + (reg)) |
macro RTL_R8 reg { |
if ~reg eq dx |
mov dx,word[rtl8169_tpc.mmio_addr] |
add dx,reg |
end if |
in al,dx |
} |
;!!!#define RTL_R16(reg) inw (ioaddr + (reg)) |
macro RTL_R16 reg { |
if ~reg eq dx |
mov dx,word[rtl8169_tpc.mmio_addr] |
add dx,reg |
end if |
in ax,dx |
} |
;!!!#define RTL_R32(reg) ((unsigned long) inl (ioaddr + (reg))) |
macro RTL_R32 reg { |
if ~reg eq dx |
mov dx,word[rtl8169_tpc.mmio_addr] |
add dx,reg |
end if |
in eax,dx |
} |
;#else |
; write/read MMIO register |
;#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) |
;#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) |
;#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) |
;#define RTL_R8(reg) readb (ioaddr + (reg)) |
;#define RTL_R16(reg) readw (ioaddr + (reg)) |
;#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) |
;#endif |
|
MCFG_METHOD_01 equ 0x01 |
MCFG_METHOD_02 equ 0x02 |
MCFG_METHOD_03 equ 0x03 |
MCFG_METHOD_04 equ 0x04 |
MCFG_METHOD_05 equ 0x05 |
MCFG_METHOD_11 equ 0x0b |
MCFG_METHOD_12 equ 0x0c |
MCFG_METHOD_13 equ 0x0d |
MCFG_METHOD_14 equ 0x0e |
MCFG_METHOD_15 equ 0x0f |
|
PCFG_METHOD_1 equ 0x01 ; PHY Reg 0x03 bit0-3 == 0x0000 |
PCFG_METHOD_2 equ 0x02 ; PHY Reg 0x03 bit0-3 == 0x0001 |
PCFG_METHOD_3 equ 0x03 ; PHY Reg 0x03 bit0-3 == 0x0002 |
|
PCI_COMMAND_IO equ 0x1 ; Enable response in I/O space |
PCI_COMMAND_MEM equ 0x2 ; Enable response in mem space |
PCI_COMMAND_MASTER equ 0x4 ; Enable bus mastering |
PCI_LATENCY_TIMER equ 0x0d ; 8 bits |
PCI_COMMAND_SPECIAL equ 0x8 ; Enable response to special cycles |
PCI_COMMAND_INVALIDATE equ 0x10 ; Use memory write and invalidate |
PCI_COMMAND_VGA_PALETTE equ 0x20 ; Enable palette snooping |
PCI_COMMAND_PARITY equ 0x40 ; Enable parity checking |
PCI_COMMAND_WAIT equ 0x80 ; Enable address/data stepping |
PCI_COMMAND_SERR equ 0x100 ; Enable SERR |
PCI_COMMAND_FAST_BACK equ 0x200 ; Enable back-to-back writes |
|
struc rtl8169_TxDesc { |
.status dd ? |
.vlan_tag dd ? |
.buf_addr dd ? |
.buf_Haddr dd ? |
} |
virtual at 0 |
rtl8169_TxDesc rtl8169_TxDesc |
sizeof.rtl8169_TxDesc = $ - rtl8169_TxDesc |
end virtual |
|
struc rtl8169_RxDesc { |
.status dd ? |
.vlan_tag dd ? |
.buf_addr dd ? |
.buf_Haddr dd ? |
} |
virtual at 0 |
rtl8169_RxDesc rtl8169_RxDesc |
sizeof.rtl8169_RxDesc = $ - rtl8169_RxDesc |
end virtual |
|
virtual at eth_data_start |
|
; Define the TX Descriptor |
align 256 |
rtl8169_tx_ring rb NUM_TX_DESC * sizeof.rtl8169_TxDesc |
|
; Create a static buffer of size RX_BUF_SZ for each |
; TX Descriptor. All descriptors point to a |
; part of this buffer |
align 256 |
rtl8169_txb rb NUM_TX_DESC * RX_BUF_SIZE |
|
; Define the RX Descriptor |
align 256 |
rtl8169_rx_ring rb NUM_RX_DESC * sizeof.rtl8169_TxDesc |
|
; Create a static buffer of size RX_BUF_SZ for each |
; RX Descriptor All descriptors point to a |
; part of this buffer |
align 256 |
rtl8169_rxb rb NUM_RX_DESC * RX_BUF_SIZE |
|
rtl8169_tpc: |
.mmio_addr dd ? ; memory map physical address |
.chipset dd ? |
.pcfg dd ? |
.mcfg dd ? |
.cur_rx dd ? ; Index into the Rx descriptor buffer of next Rx pkt |
.cur_tx dd ? ; Index into the Tx descriptor buffer of next Rx pkt |
.TxDescArrays dd ? ; Index of Tx Descriptor buffer |
.RxDescArrays dd ? ; Index of Rx Descriptor buffer |
.TxDescArray dd ? ; Index of 256-alignment Tx Descriptor buffer |
.RxDescArray dd ? ; Index of 256-alignment Rx Descriptor buffer |
.RxBufferRing rd NUM_RX_DESC ; Index of Rx Buffer array |
.Tx_skbuff rd NUM_TX_DESC |
|
end virtual |
|
rtl8169_intr_mask = RTL8169_ISB_LinkChg or RTL8169_ISB_RxOverflow or RTL8169_ISB_RxFIFOOver or RTL8169_ISB_TxErr or RTL8169_ISB_TxOK or RTL8169_ISB_RxErr or RTL8169_ISB_RxOK |
rtl8169_rx_config = (RX_FIFO_THRESH shl RTL8169_RXC_FIFOShift) or (RX_DMA_BURST shl RTL8169_RXC_DMAShift) or 0x0000000E |
|
iglobal |
|
;static struct { |
; const char *name; |
; u8 mcfg; /* depend on RTL8169 docs */ |
; u32 RxConfigMask; /* should clear the bits supported by this chip */ |
;} |
rtl_chip_info dd \ |
MCFG_METHOD_01, 0xff7e1880, \ ; RTL8169 |
MCFG_METHOD_02, 0xff7e1880, \ ; RTL8169s/8110s |
MCFG_METHOD_03, 0xff7e1880, \ ; RTL8169s/8110s |
MCFG_METHOD_04, 0xff7e1880, \ ; RTL8169sb/8110sb |
MCFG_METHOD_05, 0xff7e1880, \ ; RTL8169sc/8110sc |
MCFG_METHOD_11, 0xff7e1880, \ ; RTL8168b/8111b // PCI-E |
MCFG_METHOD_12, 0xff7e1880, \ ; RTL8168b/8111b // PCI-E |
MCFG_METHOD_13, 0xff7e1880, \ ; RTL8101e // PCI-E 8139 |
MCFG_METHOD_14, 0xff7e1880, \ ; RTL8100e // PCI-E 8139 |
MCFG_METHOD_15, 0xff7e1880 ; RTL8100e // PCI-E 8139 |
|
mac_info dd \ |
0x38800000, MCFG_METHOD_15, \ |
0x38000000, MCFG_METHOD_12, \ |
0x34000000, MCFG_METHOD_13, \ |
0x30800000, MCFG_METHOD_14, \ |
0x30000000, MCFG_METHOD_11, \ |
0x18000000, MCFG_METHOD_05, \ |
0x10000000, MCFG_METHOD_04, \ |
0x04000000, MCFG_METHOD_03, \ |
0x00800000, MCFG_METHOD_02, \ |
0x00000000, MCFG_METHOD_01 ; catch-all |
|
endg |
|
PCI_COMMAND_IO equ 0x1 ; Enable response in I/O space |
PCI_COMMAND_MEM equ 0x2 ; Enable response in mem space |
PCI_COMMAND_MASTER equ 0x4 ; Enable bus mastering |
PCI_LATENCY_TIMER equ 0x0d ; 8 bits |
PCI_COMMAND_SPECIAL equ 0x8 ; Enable response to special cycles |
PCI_COMMAND_INVALIDATE equ 0x10 ; Use memory write and invalidate |
PCI_COMMAND_VGA_PALETTE equ 0x20 ; Enable palette snooping |
PCI_COMMAND_PARITY equ 0x40 ; Enable parity checking |
PCI_COMMAND_WAIT equ 0x80 ; Enable address/data stepping |
PCI_COMMAND_SERR equ 0x100 ; Enable SERR |
PCI_COMMAND_FAST_BACK equ 0x200 ; Enable back-to-back writes |
|
PCI_VENDOR_ID equ 0x00 ; 16 bits |
PCI_DEVICE_ID equ 0x02 ; 16 bits |
PCI_COMMAND equ 0x04 ; 16 bits |
|
PCI_BASE_ADDRESS_0 equ 0x10 ; 32 bits |
PCI_BASE_ADDRESS_1 equ 0x14 ; 32 bits |
PCI_BASE_ADDRESS_2 equ 0x18 ; 32 bits |
PCI_BASE_ADDRESS_3 equ 0x1c ; 32 bits |
PCI_BASE_ADDRESS_4 equ 0x20 ; 32 bits |
PCI_BASE_ADDRESS_5 equ 0x24 ; 32 bits |
|
PCI_BASE_ADDRESS_MEM_TYPE_MASK equ 0x06 |
PCI_BASE_ADDRESS_MEM_TYPE_32 equ 0x00 ; 32 bit address |
PCI_BASE_ADDRESS_MEM_TYPE_1M equ 0x02 ; Below 1M [obsolete] |
PCI_BASE_ADDRESS_MEM_TYPE_64 equ 0x04 ; 64 bit address |
|
PCI_BASE_ADDRESS_IO_MASK equ (not 0x03) |
PCI_BASE_ADDRESS_MEM_MASK equ (not 0x0f) |
PCI_BASE_ADDRESS_SPACE_IO equ 0x01 |
PCI_ROM_ADDRESS equ 0x30 ; 32 bits |
|
proc CONFIG_CMD,where:byte |
movzx eax,byte[pci_bus] |
shl eax,8 |
mov al,[pci_dev] |
shl eax,8 |
mov al,[where] |
and al,not 3 |
or eax,0x80000000 |
ret |
endp |
|
proc pci_read_config_byte,where:dword |
push edx |
stdcall CONFIG_CMD,[where] |
mov dx,0xCF8 |
out dx,eax |
mov edx,[where] |
and edx,3 |
add edx,0xCFC |
in al,dx |
pop edx |
ret |
endp |
|
proc pci_read_config_word,where:dword |
push edx |
stdcall CONFIG_CMD,[where] |
mov dx,0xCF8 |
out dx,eax |
mov edx,[where] |
and edx,2 |
add edx,0xCFC |
in ax,dx |
pop edx |
ret |
endp |
|
proc pci_read_config_dword,where:dword |
push edx |
stdcall CONFIG_CMD,[where] |
mov edx,0xCF8 |
out dx,eax |
mov edx,0xCFC |
in eax,dx |
pop edx |
ret |
endp |
|
proc pci_write_config_byte,where:dword,value:byte |
push edx |
stdcall CONFIG_CMD,[where] |
mov dx,0xCF8 |
out dx,eax |
mov edx,[where] |
and edx,3 |
add edx,0xCFC |
mov al,[value] |
out dx,al |
pop edx |
ret |
endp |
|
proc pci_write_config_word,where:dword,value:word |
push edx |
stdcall CONFIG_CMD,[where] |
mov dx,0xCF8 |
out dx,eax |
mov edx,[where] |
and edx,2 |
add edx,0xCFC |
mov ax,[value] |
out dx,ax |
pop edx |
ret |
endp |
|
proc pci_write_config_dword,where:dword,value:dword |
push edx |
stdcall CONFIG_CMD,[where] |
mov edx,0xCF8 |
out dx,eax |
mov edx,0xCFC |
mov eax,[value] |
out dx,eax |
pop edx |
ret |
endp |
|
; Set device to be a busmaster in case BIOS neglected to do so. |
; Also adjust PCI latency timer to a reasonable value, 32. |
proc adjust_pci_device |
|
DEBUGF 1,"K : adjust_pci_device\n" |
|
stdcall pci_read_config_word,PCI_COMMAND |
mov bx,ax |
or bx,PCI_COMMAND_MASTER or PCI_COMMAND_IO |
cmp ax,bx |
je @f |
DEBUGF 1,"K : adjust_pci_device: The PCI BIOS has not enabled this device!\nK : Updating PCI command %x->%x. pci_bus %x pci_device_fn %x\n",ax,bx,[pci_bus]:2,[pci_dev]:2 |
stdcall pci_write_config_word,PCI_COMMAND,ebx |
@@: |
stdcall pci_read_config_byte,PCI_LATENCY_TIMER |
cmp al,32 |
jae @f |
DEBUGF 1,"K : adjust_pci_device: PCI latency timer (CFLT) is unreasonably low at %d.\nK : Setting to 32 clocks.\n",al |
stdcall pci_write_config_byte,PCI_LATENCY_TIMER,32 |
@@: |
ret |
endp |
|
; Find the start of a pci resource |
proc pci_bar_start,index:dword |
stdcall pci_read_config_dword,[index] |
test eax,PCI_BASE_ADDRESS_SPACE_IO |
jz @f |
and eax,PCI_BASE_ADDRESS_IO_MASK |
jmp .exit |
@@: push eax |
and eax,PCI_BASE_ADDRESS_MEM_TYPE_MASK |
cmp eax,PCI_BASE_ADDRESS_MEM_TYPE_64 |
jne .not64 |
mov eax,[index] |
add eax,4 |
stdcall pci_read_config_dword,eax |
or eax,eax |
jz .not64 |
DEBUGF 1,"K : pci_bar_start: Unhandled 64bit BAR\n" |
add esp,4 |
or eax,-1 |
ret |
.not64: |
pop eax |
and eax,PCI_BASE_ADDRESS_MEM_MASK |
.exit: |
ret |
endp |
|
proc rtl8169_init_board |
|
DEBUGF 1,"K : rtl8169_init_board\n" |
|
call adjust_pci_device |
|
stdcall pci_bar_start,PCI_BASE_ADDRESS_0 |
mov [rtl8169_tpc.mmio_addr],eax |
; Soft reset the chip |
RTL_W8 RTL8169_REG_ChipCmd,RTL8169_CMD_Reset |
|
; Check that the chip has finished the reset |
mov ecx,1000 |
@@: RTL_R8 RTL8169_REG_ChipCmd |
test al,RTL8169_CMD_Reset |
jz @f |
stdcall udelay,10 |
loop @b |
@@: |
; identify config method |
RTL_R32 RTL8169_REG_TxConfig |
and eax,0x7c800000 |
DEBUGF 1,"K : rtl8169_init_board: TxConfig & 0x7c800000 = 0x%x\n",eax |
mov esi,mac_info-8 |
@@: add esi,8 |
mov ecx,eax |
and ecx,[esi] |
cmp ecx,[esi] |
jne @b |
mov eax,[esi+4] |
mov [rtl8169_tpc.mcfg],eax |
|
mov [rtl8169_tpc.pcfg],PCFG_METHOD_3 |
stdcall RTL8169_READ_GMII_REG,3 |
and al,0x0f |
or al,al |
jnz @f |
mov [rtl8169_tpc.pcfg],PCFG_METHOD_1 |
jmp .pconf |
@@: dec al |
jnz .pconf |
mov [rtl8169_tpc.pcfg],PCFG_METHOD_2 |
.pconf: |
|
; identify chip attached to board |
mov ecx,10 |
mov eax,[rtl8169_tpc.mcfg] |
@@: dec ecx |
js @f |
cmp eax,[rtl_chip_info+ecx*8] |
jne @b |
mov [rtl8169_tpc.chipset],ecx |
jmp .match |
@@: |
; if unknown chip, assume array element #0, original RTL-8169 in this case |
DEBUGF 1,"K : rtl8169_init_board: PCI device: unknown chip version, assuming RTL-8169\n" |
RTL_R32 RTL8169_REG_TxConfig |
DEBUGF 1,"K : rtl8169_init_board: PCI device: TxConfig = 0x%x\n",eax |
|
mov [rtl8169_tpc.chipset],0 |
|
xor eax,eax |
inc eax |
ret |
|
.match: |
xor eax,eax |
ret |
endp |
|
proc rtl8169_hw_PHY_config |
|
DEBUGF 1,"K : rtl8169_hw_PHY_config: priv.mcfg=%d, priv.pcfg=%d\n",[rtl8169_tpc.mcfg],[rtl8169_tpc.pcfg] |
|
; DBG_PRINT("priv->mcfg=%d, priv->pcfg=%d\n", tpc->mcfg, tpc->pcfg); |
|
cmp [rtl8169_tpc.mcfg],MCFG_METHOD_04 |
jne .not_4 |
; stdcall RTL8169_WRITE_GMII_REG,0x1F,0x0001 |
; stdcall RTL8169_WRITE_GMII_REG,0x1b,0x841e |
; stdcall RTL8169_WRITE_GMII_REG,0x0e,0x7bfb |
; stdcall RTL8169_WRITE_GMII_REG,0x09,0x273a |
stdcall RTL8169_WRITE_GMII_REG,0x1F,0x0002 |
stdcall RTL8169_WRITE_GMII_REG,0x01,0x90D0 |
stdcall RTL8169_WRITE_GMII_REG,0x1F,0x0000 |
jmp .exit |
.not_4: |
cmp [rtl8169_tpc.mcfg],MCFG_METHOD_02 |
je @f |
cmp [rtl8169_tpc.mcfg],MCFG_METHOD_03 |
jne .not_2_or_3 |
@@: stdcall RTL8169_WRITE_GMII_REG,0x1F,0x0001 |
stdcall RTL8169_WRITE_GMII_REG,0x15,0x1000 |
stdcall RTL8169_WRITE_GMII_REG,0x18,0x65C7 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0x0000 |
stdcall RTL8169_WRITE_GMII_REG,0x03,0x00A1 |
stdcall RTL8169_WRITE_GMII_REG,0x02,0x0008 |
stdcall RTL8169_WRITE_GMII_REG,0x01,0x1020 |
stdcall RTL8169_WRITE_GMII_REG,0x00,0x1000 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0x0800 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0x0000 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0x7000 |
stdcall RTL8169_WRITE_GMII_REG,0x03,0xFF41 |
stdcall RTL8169_WRITE_GMII_REG,0x02,0xDE60 |
stdcall RTL8169_WRITE_GMII_REG,0x01,0x0140 |
stdcall RTL8169_WRITE_GMII_REG,0x00,0x0077 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0x7800 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0x7000 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0xA000 |
stdcall RTL8169_WRITE_GMII_REG,0x03,0xDF01 |
stdcall RTL8169_WRITE_GMII_REG,0x02,0xDF20 |
stdcall RTL8169_WRITE_GMII_REG,0x01,0xFF95 |
stdcall RTL8169_WRITE_GMII_REG,0x00,0xFA00 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0xA800 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0xA000 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0xB000 |
stdcall RTL8169_WRITE_GMII_REG,0x03,0xFF41 |
stdcall RTL8169_WRITE_GMII_REG,0x02,0xDE20 |
stdcall RTL8169_WRITE_GMII_REG,0x01,0x0140 |
stdcall RTL8169_WRITE_GMII_REG,0x00,0x00BB |
stdcall RTL8169_WRITE_GMII_REG,0x04,0xB800 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0xB000 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0xF000 |
stdcall RTL8169_WRITE_GMII_REG,0x03,0xDF01 |
stdcall RTL8169_WRITE_GMII_REG,0x02,0xDF20 |
stdcall RTL8169_WRITE_GMII_REG,0x01,0xFF95 |
stdcall RTL8169_WRITE_GMII_REG,0x00,0xBF00 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0xF800 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0xF000 |
stdcall RTL8169_WRITE_GMII_REG,0x04,0x0000 |
stdcall RTL8169_WRITE_GMII_REG,0x1F,0x0000 |
stdcall RTL8169_WRITE_GMII_REG,0x0B,0x0000 |
jmp .exit |
.not_2_or_3: |
; DBG_PRINT("tpc->mcfg=%d. Discard hw PHY config.\n", tpc->mcfg); |
DEBUGF 1,"K : tpc.mcfg=%d, discard hw PHY config\n",[rtl8169_tpc.mcfg] |
.exit: |
ret |
endp |
|
;proc pci_write_config_byte |
; ret |
;endp |
|
proc RTL8169_WRITE_GMII_REG,RegAddr:byte,value:dword |
|
DEBUGF 1,"K : RTL8169_WRITE_GMII_REG: 0x%x 0x%x\n",[RegAddr]:2,[value] |
|
movzx eax,[RegAddr] |
shl eax,16 |
or eax,[value] |
or eax,0x80000000 |
RTL_W32 RTL8169_REG_PHYAR,eax |
stdcall udelay,1000 |
|
mov ecx,2000 |
; Check if the RTL8169 has completed writing to the specified MII register |
@@: RTL_R32 RTL8169_REG_PHYAR |
test eax,0x80000000 |
jz .exit |
stdcall udelay,100 |
loop @b |
.exit: |
ret |
endp |
|
proc RTL8169_READ_GMII_REG,RegAddr:byte |
|
DEBUGF 1,"K : RTL8169_READ_GMII_REG: 0x%x\n",[RegAddr]:2 |
|
push ecx |
movzx eax,[RegAddr] |
shl eax,16 |
; or eax,0x0 |
RTL_W32 RTL8169_REG_PHYAR,eax |
stdcall udelay,1000 |
|
mov ecx,2000 |
; Check if the RTL8169 has completed retrieving data from the specified MII register |
@@: RTL_R32 RTL8169_REG_PHYAR |
test eax,0x80000000 |
jnz .exit |
stdcall udelay,100 |
loop @b |
|
or eax,-1 |
pop ecx |
ret |
.exit: |
RTL_R32 RTL8169_REG_PHYAR |
and eax,0xFFFF |
pop ecx |
ret |
endp |
|
proc rtl8169_set_rx_mode |
|
DEBUGF 1,"K : rtl8169_set_rx_mode\n" |
|
; IFF_ALLMULTI |
; Too many to filter perfectly -- accept all multicasts |
RTL_R32 RTL8169_REG_RxConfig |
mov ecx,[rtl8169_tpc.chipset] |
and eax,[rtl_chip_info + ecx * 8 + 4] ; RxConfigMask |
or eax,rtl8169_rx_config or (RTL8169_RXM_AcceptBroadcast or RTL8169_RXM_AcceptMulticast or RTL8169_RXM_AcceptMyPhys) |
RTL_W32 RTL8169_REG_RxConfig,eax |
|
; Multicast hash filter |
RTL_W32 RTL8169_REG_MAR0 + 0,0xffffffff |
RTL_W32 RTL8169_REG_MAR0 + 4,0xffffffff |
ret |
endp |
|
proc rtl8169_init_ring |
|
DEBUGF 1,"K : rtl8169_init_ring\n" |
|
xor eax,eax |
mov [rtl8169_tpc.cur_rx],eax |
mov [rtl8169_tpc.cur_tx],eax |
|
mov edi,[rtl8169_tpc.TxDescArray] |
mov ecx,(NUM_TX_DESC * sizeof.rtl8169_TxDesc) / 4 |
cld |
rep stosd |
mov edi,[rtl8169_tpc.RxDescArray] |
mov ecx,(NUM_RX_DESC * sizeof.rtl8169_RxDesc) / 4 |
rep stosd |
|
mov edi,rtl8169_tpc.Tx_skbuff |
mov eax,rtl8169_txb |
mov ecx,NUM_TX_DESC |
@@: stosd |
inc eax ; add eax,RX_BUF_SIZE ??? |
loop @b |
|
;!!! for (i = 0; i < NUM_RX_DESC; i++) { |
;!!! if (i == (NUM_RX_DESC - 1)) |
;!!! tpc->RxDescArray[i].status = (OWNbit | EORbit) | RX_BUF_SIZE; |
;!!! else |
;!!! tpc->RxDescArray[i].status = OWNbit | RX_BUF_SIZE; |
;!!! tpc->RxBufferRing[i] = &rxb[i * RX_BUF_SIZE]; |
;!!! tpc->RxDescArray[i].buf_addr = virt_to_bus(tpc->RxBufferRing[i]); |
;!!! } |
mov esi,rtl8169_tpc.RxBufferRing |
mov edi,[rtl8169_tpc.RxDescArray] |
mov eax,rtl8169_rxb |
mov ecx,NUM_RX_DESC |
@@: mov [esi],eax |
mov [edi+rtl8169_RxDesc.buf_addr],eax |
mov [edi+rtl8169_RxDesc.status],RTL8169_DSB_OWNbit or RX_BUF_SIZE |
add esi,4 |
add edi,sizeof.rtl8169_RxDesc |
add eax,RX_BUF_SIZE |
loop @b |
|
or [edi - sizeof.rtl8169_RxDesc + rtl8169_RxDesc.status],RTL8169_DSB_EORbit |
|
ret |
endp |
|
proc rtl8169_hw_start |
|
DEBUGF 1,"K : rtl8169_hw_start\n" |
|
; Soft reset the chip |
RTL_W8 RTL8169_REG_ChipCmd,RTL8169_CMD_Reset |
; Check that the chip has finished the reset |
mov ecx,1000 |
@@: RTL_R8 RTL8169_REG_ChipCmd |
and al,RTL8169_CMD_Reset |
jz @f |
stdcall udelay,10 |
loop @b |
@@: |
RTL_W8 RTL8169_REG_Cfg9346,RTL8169_CFG_9346_Unlock |
RTL_W8 RTL8169_REG_ChipCmd,RTL8169_CMD_TxEnb or RTL8169_CMD_RxEnb |
RTL_W8 RTL8169_REG_ETThReg,ETTh |
; For gigabit rtl8169 |
RTL_W16 RTL8169_REG_RxMaxSize,RxPacketMaxSize |
; Set Rx Config register |
RTL_R32 RTL8169_REG_RxConfig |
mov ecx,[rtl8169_tpc.chipset] |
and eax,[rtl_chip_info + ecx * 8 + 4] ; RxConfigMask |
or eax,rtl8169_rx_config |
RTL_W32 RTL8169_REG_RxConfig,eax |
; Set DMA burst size and Interframe Gap Time |
RTL_W32 RTL8169_REG_TxConfig,(TX_DMA_BURST shl RTL8169_TXC_DMAShift) or (InterFrameGap shl RTL8169_TXC_InterFrameGapShift) |
RTL_R16 RTL8169_REG_CPlusCmd |
RTL_W16 RTL8169_REG_CPlusCmd,ax |
|
RTL_R16 RTL8169_REG_CPlusCmd |
or ax,1 shl 3 |
cmp [rtl8169_tpc.mcfg],MCFG_METHOD_02 |
jne @f |
cmp [rtl8169_tpc.mcfg],MCFG_METHOD_03 |
jne @f |
or ax,1 shl 14 |
; DEBUGF 1,"K : Set MAC Reg C+CR Offset 0xE0: bit-3 and bit-14\n" |
jmp .set |
@@:;DEBUGF 1,"K : Set MAC Reg C+CR Offset 0xE0: bit-3\n" |
.set: RTL_W16 RTL8169_REG_CPlusCmd,ax |
|
; RTL_W16 0xE2,0x1517 |
; RTL_W16 0xE2,0x152a |
; RTL_W16 0xE2,0x282a |
RTL_W16 0xE2,0x0000 |
|
MOV [rtl8169_tpc.cur_rx],0 |
RTL_W32 RTL8169_REG_TxDescStartAddr,[rtl8169_tpc.TxDescArray] |
RTL_W32 RTL8169_REG_RxDescStartAddr,[rtl8169_tpc.RxDescArray] |
RTL_W8 RTL8169_REG_Cfg9346,RTL8169_CFG_9346_Lock |
stdcall udelay,10 |
RTL_W32 RTL8169_REG_RxMissed,0 |
call rtl8169_set_rx_mode |
; no early-rx interrupts |
RTL_R16 RTL8169_REG_MultiIntr |
and ax,0xF000 |
RTL_W16 RTL8169_REG_MultiIntr,ax |
RTL_W16 RTL8169_REG_IntrMask,0 ; rtl8169_intr_mask |
ret |
endp |
|
proc udelay,msec:dword |
push esi |
mov esi,[msec] |
call delay_ms |
pop esi |
ret |
endp |
|
;*************************************************************************** |
; Function |
; rtl8169_probe |
; Description |
; Searches for an ethernet card, enables it and clears the rx buffer |
; If a card was found, it enables the ethernet -> TCPIP link |
; Destroyed registers |
; eax, ebx, ecx, edx |
; |
;*************************************************************************** |
proc rtl8169_probe |
|
DEBUGF 1,"K : rtl8169_probe: 0x%x : 0x%x 0x%x\n",[io_addr]:8,[pci_bus]:2,[pci_dev]:2 |
|
call rtl8169_init_board |
|
mov ecx,MAC_ADDR_LEN |
mov edx,[rtl8169_tpc.mmio_addr] |
add edx,RTL8169_REG_MAC0 |
xor ebx,ebx |
; Get MAC address. FIXME: read EEPROM |
@@: RTL_R8 dx |
mov [node_addr+ebx],al |
inc edx |
inc ebx |
loop @b |
|
DEBUGF 1,"K : rtl8169_probe: MAC = %x-%x-%x-%x-%x-%x\n",[node_addr+0]:2,[node_addr+1]:2,[node_addr+2]:2,[node_addr+3]:2,[node_addr+4]:2,[node_addr+5]:2 |
|
; Config PHY |
stdcall rtl8169_hw_PHY_config |
; DEBUGF 1,"K : Set MAC Reg C+CR Offset 0x82h = 0x01h\n" |
RTL_W8 0x82,0x01 |
cmp [rtl8169_tpc.mcfg],MCFG_METHOD_03 |
jae @f |
; DEBUGF 1,"K : Set PCI Latency=0x40\n" |
; stdcall pci_write_config_byte,PCI_LATENCY_TIMER,0x40 |
@@: |
cmp [rtl8169_tpc.mcfg],MCFG_METHOD_02 |
jne @f |
; DEBUGF 1,"K : Set MAC Reg C+CR Offset 0x82h = 0x01h\n" |
RTL_W8 0x82,0x01 |
; DEBUGF 1,"K : Set PHY Reg 0x0bh = 0x00h\n" |
stdcall RTL8169_WRITE_GMII_REG,0x0b,0x0000 ; w 0x0b 15 0 0 |
@@: |
; if TBI is not enabled |
RTL_R8 RTL8169_REG_PHYstatus |
test al,RTL8169_PHYS_TBI_Enable |
jz .tbi_dis |
stdcall RTL8169_READ_GMII_REG,RTL8169_PHY_AUTO_NEGO_REG |
; enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged |
and eax,0x0C1F |
or eax,RTL8169_PHY_Cap_10_Half or RTL8169_PHY_Cap_10_Full or RTL8169_PHY_Cap_100_Half or RTL8169_PHY_Cap_100_Full |
stdcall RTL8169_WRITE_GMII_REG,RTL8169_PHY_AUTO_NEGO_REG,eax |
; enable 1000 Full Mode |
stdcall RTL8169_WRITE_GMII_REG,RTL8169_PHY_1000_CTRL_REG,RTL8169_PHY_Cap_1000_Full or RTL8169_PHY_Cap_1000_Half ; rtl8168 |
; Enable auto-negotiation and restart auto-nigotiation |
stdcall RTL8169_WRITE_GMII_REG,RTL8169_PHY_CTRL_REG,RTL8169_PHY_Enable_Auto_Nego or RTL8169_PHY_Restart_Auto_Nego |
stdcall udelay,100 |
mov ecx,10000 |
; wait for auto-negotiation process |
@@: dec ecx |
jz @f |
stdcall RTL8169_READ_GMII_REG,RTL8169_PHY_STAT_REG |
stdcall udelay,100 |
test eax,RTL8169_PHY_Auto_Neco_Comp |
jz @b |
RTL_R8 RTL8169_REG_PHYstatus |
jmp @f |
.tbi_dis: |
stdcall udelay,100 |
@@: |
call rtl8169_reset |
ret |
endp |
|
;*************************************************************************** |
; Function |
; rt8169_reset |
; Description |
; Place the chip (ie, the ethernet card) into a virgin state |
; Destroyed registers |
; eax, ebx, ecx, edx |
; |
;*************************************************************************** |
proc rtl8169_reset |
|
DEBUGF 1,"K : rtl8169_reset: 0x%x : 0x%x 0x%x\n",[io_addr]:8,[pci_bus]:2,[pci_dev]:2 |
|
mov [rtl8169_tpc.TxDescArrays],rtl8169_tx_ring |
; Tx Desscriptor needs 256 bytes alignment |
mov [rtl8169_tpc.TxDescArray],rtl8169_tx_ring |
|
mov [rtl8169_tpc.RxDescArrays],rtl8169_rx_ring |
; Rx Desscriptor needs 256 bytes alignment |
mov [rtl8169_tpc.RxDescArray],rtl8169_rx_ring |
|
call rtl8169_init_ring |
call rtl8169_hw_start |
; Construct a perfect filter frame with the mac address as first match |
; and broadcast for all others |
mov edi,rtl8169_txb |
or al,-1 |
mov ecx,192 |
cld |
rep stosb |
|
mov esi,node_addr |
mov edi,rtl8169_txb |
movsd |
movsw |
|
mov eax,[pci_data] |
mov [eth_status],eax |
ret |
endp |
|
;*************************************************************************** |
; Function |
; rtl8169_transmit |
; Description |
; Transmits a packet of data via the ethernet card |
; d - edi - Pointer to 48 bit destination address |
; t - bx - Type of packet |
; s - ecx - size of packet |
; p - esi - pointer to packet data |
; Destroyed registers |
; eax, edx, esi, edi |
; |
;*************************************************************************** |
proc rtl8169_transmit |
|
DEBUGF 1,"K : rtl8169_transmit\n" ;: 0x%x : 0x%x 0x%x 0x%x 0x%x\n",[io_addr]:8,edi,bx,ecx,esi |
|
push ecx edx esi |
mov eax,MAX_ETH_FRAME_SIZE |
mul [rtl8169_tpc.cur_tx] |
mov esi,edi |
; point to the current txb incase multiple tx_rings are used |
mov edi,[rtl8169_tpc.Tx_skbuff + eax * 4] |
mov eax,edi |
cld |
; copy destination address |
movsd |
movsw |
; copy source address |
mov esi,node_addr |
movsd |
movsw |
; copy packet type |
mov [edi],bx |
add edi,2 |
; copy the packet data |
pop esi edx ecx |
push ecx |
shr ecx,2 |
rep movsd |
pop ecx |
push ecx |
and ecx,3 |
rep movsb |
|
;!!! s += ETH_HLEN; |
;!!! s &= 0x0FFF; |
;!!! while (s < ETH_ZLEN) |
;!!! ptxb[s++] = '\0'; |
mov edi,eax |
pop ecx |
push eax |
add ecx,ETH_HLEN |
and ecx,0x0FFF |
xor al,al |
add edi,ecx |
@@: cmp ecx,ETH_ZLEN |
jae @f |
stosb |
inc ecx |
jmp @b |
@@: pop eax |
|
mov ebx,eax |
mov eax,sizeof.rtl8169_TxDesc |
mul [rtl8169_tpc.cur_tx] |
add eax,[rtl8169_tpc.TxDescArray] |
xchg eax,ebx |
mov [ebx + rtl8169_TxDesc.buf_addr],eax |
|
mov eax,ecx |
cmp eax,ETH_ZLEN |
jae @f |
mov eax,ETH_ZLEN |
@@: or eax,RTL8169_DSB_OWNbit or RTL8169_DSB_FSbit or RTL8169_DSB_LSbit |
cmp [rtl8169_tpc.cur_tx],NUM_TX_DESC - 1 |
jne @f |
or eax,RTL8169_DSB_EORbit |
@@: mov [ebx + rtl8169_TxDesc.status],eax |
|
RTL_W8 RTL8169_REG_TxPoll,0x40 ; set polling bit |
|
inc [rtl8169_tpc.cur_tx] |
and [rtl8169_tpc.cur_tx],NUM_TX_DESC - 1 |
|
;!!! to = currticks() + TX_TIMEOUT; |
;!!! while ((tpc->TxDescArray[entry].status & OWNbit) && (currticks() < to)); /* wait */ |
mov ecx,TX_TIMEOUT / 10 |
@@: test [ebx + rtl8169_TxDesc.status],RTL8169_DSB_OWNbit |
jnz @f |
stdcall udelay,10 |
loop @b |
DEBUGF 1,"K : rtl8169_transmit: TX Time Out\n" |
@@: |
|
ret |
endp |
|
;*************************************************************************** |
; Function |
; rtl8169_poll |
; |
; Description |
; Polls the ethernet card for a received packet |
; Received data, if any, ends up in Ether_buffer |
; Destroyed register(s) |
; eax, edx, ecx |
; |
;*************************************************************************** |
proc rtl8169_poll |
|
; DEBUGF 1,"K : rtl8169_poll\n" ;: 0x%x : none\n",[io_addr]:8 |
|
mov word[eth_rx_data_len],0 |
|
mov eax,sizeof.rtl8169_RxDesc |
mul [rtl8169_tpc.cur_rx] |
add eax,[rtl8169_tpc.RxDescArray] |
mov ebx,eax |
|
; DEBUGF 1,"K : rtl8169_RxDesc.status = 0x%x\n",[ebx + rtl8169_RxDesc.status] |
|
test [ebx + rtl8169_RxDesc.status],RTL8169_DSB_OWNbit ; 0x80000600 |
jnz .exit |
|
; DEBUGF 1,"K : rtl8169_tpc.cur_rx = %u\n",[rtl8169_tpc.cur_rx] |
|
; h/w no longer present (hotplug?) or major error, bail |
RTL_R16 RTL8169_REG_IntrStatus |
|
; DEBUGF 1,"K : IntrStatus = 0x%x\n",ax |
|
cmp ax,0xFFFF |
je .exit |
|
push eax |
and ax,not (RTL8169_ISB_RxFIFOOver or RTL8169_ISB_RxOverflow or RTL8169_ISB_RxOK) |
RTL_W16 RTL8169_REG_IntrStatus,ax |
|
mov eax,[ebx + rtl8169_RxDesc.status] |
|
; DEBUGF 1,"K : RxDesc.status = 0x%x\n",eax |
|
test eax,RTL8169_SD_RxRES |
jnz .else |
and eax,0x00001FFF |
; jz .exit.pop |
add eax,-4 |
mov [eth_rx_data_len],ax |
|
DEBUGF 1,"K : rtl8169_poll: data length = %u\n",ax |
|
push eax |
mov ecx,eax |
shr ecx,2 |
mov eax,[rtl8169_tpc.cur_rx] |
mov edx,[rtl8169_tpc.RxBufferRing + eax * 4] |
mov esi,edx |
mov edi,Ether_buffer |
cld |
rep movsd |
pop ecx |
and ecx,3 |
rep movsb |
|
mov eax,RTL8169_DSB_OWNbit or RX_BUF_SIZE |
cmp [rtl8169_tpc.cur_rx],NUM_RX_DESC - 1 |
jne @f |
or eax,RTL8169_DSB_EORbit |
@@: mov [ebx + rtl8169_RxDesc.status],eax |
|
mov [ebx + rtl8169_RxDesc.buf_addr],edx |
jmp @f |
.else: |
DEBUGF 1,"K : rtl8169_poll: Rx Error\n" |
; FIXME: shouldn't I reset the status on an error |
@@: |
inc [rtl8169_tpc.cur_rx] |
and [rtl8169_tpc.cur_rx],NUM_RX_DESC - 1 |
.exit.pop: |
pop eax |
and ax,RTL8169_ISB_RxFIFOOver or RTL8169_ISB_RxOverflow or RTL8169_ISB_RxOK |
RTL_W16 RTL8169_REG_IntrStatus,ax |
.exit: |
ret |
endp |
|
proc rtl8169_cable |
ret |
endp |