;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; ;; 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 + 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_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/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,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" ;: 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 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" ;: 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 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