2011-10-14 23:38:50 +02:00
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
2012-03-13 17:51:57 +01:00
;; Copyright ( C ) KolibriOS team 2004 - 2011. All rights reserved . ;;
2011-10-14 23:38:50 +02:00
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; 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 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
$Revision $
ETH_ALEN equ 6
ETH_HLEN equ ( 2 * ETH_ALEN + 2 )
ETH_ZLEN equ 60 ; 60 + 4 bytes auto payload for
; mininmum 64 bytes 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 16 K - 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_RxDesc
; 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 / 8110 s
MCFG_METHOD_03 , 0xff7e1880 , \ ; RTL8169s / 8110 s
MCFG_METHOD_04 , 0xff7e1880 , \ ; RTL8169sb / 8110 sb
MCFG_METHOD_05 , 0xff7e1880 , \ ; RTL8169sc / 8110 sc
MCFG_METHOD_11 , 0xff7e1880 , \ ; RTL8168b / 8111 b // PCI-E
MCFG_METHOD_12 , 0xff7e1880 , \ ; RTL8168b / 8111 b // 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 1 M [ 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! \n K : 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. \n K : 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 , 1 ;;; 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 , 1 ;;; 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 , 1 ;;; 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 , 1 ;;; 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
sub [ edi + rtl8169_RxDesc . buf_addr ], OS_BASE ; shurf 28.09 . 2008
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
push eax ; shurf 28.09 . 2008
mov eax , [ rtl8169_tpc . TxDescArray ] ; shurf 28.09 . 2008
sub eax , OS_BASE ; shurf 28.09 . 2008
RTL_W32 RTL8169_REG_TxDescStartAddr , eax ;[ rtl8169_tpc . TxDescArray ] ; shurf 28.09 . 2008
mov eax , [ rtl8169_tpc . RxDescArray ] ; shurf 28.09 . 2008
sub eax , OS_BASE ; shurf 28.09 . 2008
RTL_W32 RTL8169_REG_RxDescStartAddr , eax ;[ rtl8169_tpc . RxDescArray ] ; shurf 28.09 . 2008
pop eax ; shurf 28.09 . 2008
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 " ; : 0 x % x : 0 x % x 0 x % x 0 x % x 0 x % 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
sub [ ebx + rtl8169_TxDesc . buf_addr ], OS_BASE ; shurf 28.09 . 2008
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 " ; : 0 x % 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
sub [ ebx + rtl8169_RxDesc . buf_addr ], OS_BASE ; shurf 28.09 . 2008
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