1
0
mirror of https://github.com/deadw00d/AROS.git synced 2025-12-08 14:34:41 +00:00
Files
AROS-v0/workbench/devs/networks/rtl8168/rtl8168.c
2021-04-24 10:29:42 +02:00

2300 lines
82 KiB
C

/*
* $Id$
*/
/*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA.
*/
#include "rtl8168.h"
#include <exec/types.h>
#include <exec/resident.h>
#include <exec/io.h>
#include <exec/ports.h>
#include <aros/libcall.h>
#include <aros/macros.h>
#include <aros/io.h>
#include <oop/oop.h>
#include <devices/sana2.h>
#include <devices/sana2specialstats.h>
#include <utility/utility.h>
#include <utility/tagitem.h>
#include <utility/hooks.h>
#include <hidd/pci.h>
#include <proto/oop.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/battclock.h>
#include <hardware/intbits.h>
#include <stdlib.h>
#include <string.h>
#include "unit.h"
#include LC_LIBDEFS_FILE
#undef LIBBASE
#define LIBBASE (unit->rtl8168u_device)
#define _R(NAME,MAC,RCR,MASK, JumFrameSz) \
{ .name = NAME, .mcfg = MAC, .RCR_Cfg = RCR, .RxConfigMask = MASK, .jumbo_frame_sz = JumFrameSz }
static const struct {
const char *name;
UBYTE mcfg;
ULONG RCR_Cfg;
ULONG RxConfigMask; /* Clears the bits supported by this chip */
ULONG jumbo_frame_sz;
} rtl_chip_info[] = {
_R("RTL8168B/8111B",
CFG_METHOD_1,
(Reserved2_data << Reserved2_shift) | (RX_DMA_BURST << RxCfgDMAShift),
0xff7e1880,
Jumbo_Frame_4k),
_R("RTL8168B/8111B",
CFG_METHOD_2,
(Reserved2_data << Reserved2_shift) | (RX_DMA_BURST << RxCfgDMAShift),
0xff7e1880,
Jumbo_Frame_4k),
_R("RTL8168B/8111B",
CFG_METHOD_3,
(Reserved2_data << Reserved2_shift) | (RX_DMA_BURST << RxCfgDMAShift),
0xff7e1880,
Jumbo_Frame_4k),
_R("RTL8168C/8111C",
CFG_METHOD_4, RxCfg_128_int_en | RxCfg_fet_multi_en | (RX_DMA_BURST << RxCfgDMAShift),
0xff7e1880,
Jumbo_Frame_6k),
_R("RTL8168C/8111C",
CFG_METHOD_5,
RxCfg_128_int_en | RxCfg_fet_multi_en | (RX_DMA_BURST << RxCfgDMAShift),
0xff7e1880,
Jumbo_Frame_6k),
_R("RTL8168C/8111C",
CFG_METHOD_6,
RxCfg_128_int_en | RxCfg_fet_multi_en | (RX_DMA_BURST << RxCfgDMAShift),
0xff7e1880,
Jumbo_Frame_6k),
_R("RTL8168CP/8111CP",
CFG_METHOD_7,
RxCfg_128_int_en | RxCfg_fet_multi_en | (RX_DMA_BURST << RxCfgDMAShift),
0xff7e1880,
Jumbo_Frame_6k),
_R("RTL8168CP/8111CP",
CFG_METHOD_8,
RxCfg_128_int_en | RxCfg_fet_multi_en | (RX_DMA_BURST << RxCfgDMAShift),
0xff7e1880,
Jumbo_Frame_6k),
_R("RTL8168D/8111D",
CFG_METHOD_9,
RxCfg_128_int_en | (RX_DMA_BURST << RxCfgDMAShift),
0xff7e1880,
Jumbo_Frame_9k),
_R("RTL8168D/8111D",
CFG_METHOD_10,
RxCfg_128_int_en | (RX_DMA_BURST << RxCfgDMAShift),
0xff7e1880,
Jumbo_Frame_9k),
_R("RTL8168D/8111D",
CFG_METHOD_11,
RxCfg_128_int_en | (RX_DMA_BURST << RxCfgDMAShift),
0xff7e1880,
Jumbo_Frame_9k),
};
#undef _R
void rtl8168nic_USecDelay(struct net_device *unit, ULONG usec)
{
if (unit != NULL)
{
unit->rtl8168u_DelayPort.mp_SigTask = FindTask(NULL);
unit->rtl8168u_DelayReq.tr_node.io_Command = TR_ADDREQUEST;
unit->rtl8168u_DelayReq.tr_time.tv_micro = usec % 1000000;
unit->rtl8168u_DelayReq.tr_time.tv_secs = usec / 1000000;
DoIO((struct IORequest *)&unit->rtl8168u_DelayReq);
}
}
static inline struct rtl8168_priv *get_pcnpriv(struct net_device *unit)
{
return unit->rtl8168u_priv;
}
static inline UBYTE *get_hwbase(struct net_device *unit)
{
return (UBYTE *)unit->rtl8168u_BaseMem;
}
void MMIO_W8(APTR addr, UBYTE val8)
{
*((volatile UBYTE *)(addr)) = (val8);
RTL_R8(addr);
}
void MMIO_W16(APTR addr, UWORD val16)
{
*((volatile UWORD *)(addr)) = (val16);
RTL_R16(addr);
}
void MMIO_W32(APTR addr, ULONG val32)
{
*((volatile ULONG *)(addr)) = (val32);
RTL_R32(addr);
}
static void mdio_write(struct net_device *unit, int RegAddr, UWORD value)
{
APTR base = get_hwbase(unit);
int i;
RTL_W32(base + (PHYAR), PHYAR_Write |
(RegAddr & PHYAR_Reg_Mask) << PHYAR_Reg_shift |
(value & PHYAR_Data_Mask));
for (i = 0; i < 10; i++) {
/* Check if the RTL8168 has completed writing to the specified MII register */
if (!(RTL_R32(base + (PHYAR)) & PHYAR_Flag))
break;
udelay(100);
}
}
static ULONG mdio_read(struct net_device *unit, int RegAddr)
{
APTR base = get_hwbase(unit);
UWORD value = 0xffff;
int i;
RTL_W32(base + (PHYAR), PHYAR_Read | (RegAddr & PHYAR_Reg_Mask) << PHYAR_Reg_shift);
for (i = 0; i < 10; i++) {
/* Check if the RTL8168 has completed retrieving data from the specified MII register */
if (RTL_R32(base + (PHYAR)) & PHYAR_Flag) {
value = (UWORD)(RTL_R32(base + (PHYAR)) & PHYAR_Data_Mask);
break;
}
udelay(100);
}
return value;
}
static void rtl8168nic_EPHYWrite(struct net_device *unit, int RegAddr, UWORD value)
{
APTR base = get_hwbase(unit);
int i;
RTL_W32(base + (EPHYAR),
EPHYAR_Write |
(RegAddr & EPHYAR_Reg_Mask) << EPHYAR_Reg_shift |
(value & EPHYAR_Data_Mask));
for (i = 0; i < 10; i++) {
udelay(100);
/* Check if the RTL8168 has completed EPHY write */
if (!(RTL_R32(base + (EPHYAR)) & EPHYAR_Flag))
break;
}
udelay(20);
}
static UWORD rtl8168nic_EPHYRead(struct net_device *unit, int RegAddr)
{
APTR base = get_hwbase(unit);
UWORD value = 0xffff;
int i;
RTL_W32(base + (EPHYAR),
EPHYAR_Read | (RegAddr & EPHYAR_Reg_Mask) << EPHYAR_Reg_shift);
for (i = 0; i < 10; i++) {
udelay(100);
/* Check if the RTL8168 has completed EPHY read */
if (RTL_R32(base + (EPHYAR)) & EPHYAR_Flag) {
value = (UWORD)(RTL_R32(base + (EPHYAR)) & EPHYAR_Data_Mask);
break;
}
}
udelay(20);
return value;
}
static void rtl8168nic_CSIWrite(struct net_device *unit, int addr, ULONG value)
{
APTR base = get_hwbase(unit);
int i;
RTL_W32(base + (CSIDR), value);
RTL_W32(base + (CSIAR),
CSIAR_Write |
CSIAR_ByteEn << CSIAR_ByteEn_shift |
(addr & CSIAR_Addr_Mask));
for (i = 0; i < 10; i++) {
udelay(100);
/* Check if the RTL8168 has completed CSI write */
if (!(RTL_R32(base + (CSIAR)) & CSIAR_Flag))
break;
}
udelay(20);
}
static ULONG rtl8168nic_CSIRead(struct net_device *unit, int addr)
{
APTR base = get_hwbase(unit);
ULONG value = 0xffffffff;
int i;
RTL_W32(base + (CSIAR),
CSIAR_Read |
CSIAR_ByteEn << CSIAR_ByteEn_shift |
(addr & CSIAR_Addr_Mask));
for (i = 0; i < 10; i++) {
udelay(100);
/* Check if the RTL8168 has completed CSI read */
if (RTL_R32(base + (CSIAR)) & CSIAR_Flag) {
value = RTL_R32(base + (CSIDR));
break;
}
}
udelay(20);
return value;
}
static void rtl8168nic_PHYPowerUP(struct net_device *unit)
{
// APTR base = get_hwbase(unit);
RTLD(bug("[%s] rtl8168nic_PHYPowerUP()\n", unit->rtl8168u_name))
mdio_write(unit, 0x1F, 0x0000);
mdio_write(unit, 0x0E, 0x0000);
}
static void rtl8168nic_GetMACVersion(struct net_device *unit)
{
struct rtl8168_priv *np = get_pcnpriv(unit);
APTR base = get_hwbase(unit);
ULONG reg, val32;
ULONG ICVerID;
RTLD(bug("[%s] rtl8168nic_GetMACVersion()\n", unit->rtl8168u_name))
val32 = RTL_R32(base + (TxConfig));
reg = val32 & 0x7c800000;
ICVerID = val32 & 0x00700000;
switch(reg)
{
case 0x30000000:
np->mcfg = CFG_METHOD_1;
break;
case 0x38000000:
if(ICVerID == 0x00000000) {
np->mcfg = CFG_METHOD_2;
} else if(ICVerID == 0x00500000) {
np->mcfg = CFG_METHOD_3;
} else {
np->mcfg = CFG_METHOD_3;
}
break;
case 0x3C000000:
if(ICVerID == 0x00000000) {
np->mcfg = CFG_METHOD_4;
} else if(ICVerID == 0x00200000) {
np->mcfg = CFG_METHOD_5;
} else if(ICVerID == 0x00400000) {
np->mcfg = CFG_METHOD_6;
} else {
np->mcfg = CFG_METHOD_6;
}
break;
case 0x3C800000:
if (ICVerID == 0x00100000){
np->mcfg = CFG_METHOD_7;
} else if (ICVerID == 0x00300000){
np->mcfg = CFG_METHOD_8;
} else {
np->mcfg = CFG_METHOD_8;
}
break;
case 0x28000000:
if(ICVerID == 0x00100000) {
np->mcfg = CFG_METHOD_9;
} else if(ICVerID == 0x00200000) {
np->mcfg = CFG_METHOD_10;
} else if(ICVerID == 0x00300000) {
np->mcfg = CFG_METHOD_11;
} else {
np->mcfg = CFG_METHOD_11;
}
break;
default:
np->mcfg = 0xFFFFFFFF;
RTLD(bug("[%s] rtl8168nic_GetMACVersion: unknown chip version (%x)\n", unit->rtl8168u_name, reg))
break;
}
}
static void rtl8168nic_PrintMACVersion(struct net_device *unit)
{
struct rtl8168_priv *np = get_pcnpriv(unit);
int i;
RTLD(bug("[%s] rtl8168nic_PrintMACVersion()\n", unit->rtl8168u_name))
for (i = (sizeof(rtl_chip_info) / sizeof(rtl_chip_info[0])) - 1; i >= 0; i--)
{
if (np->mcfg == rtl_chip_info[i].mcfg)
{
RTLD(bug("[%s] rtl8168nic_PrintMACVersion: mcfg == %s (%04d)\n", unit->rtl8168u_name,
rtl_chip_info[i].name,
rtl_chip_info[i].mcfg))
return;
}
}
RTLD(bug("[%s] rtl8168nic_PrintMACVersion: mac_version == Unknown\n", unit->rtl8168u_name))
}
static void rtl8168nic_HWPHYConfig(struct net_device *unit)
{
struct rtl8168_priv *np = get_pcnpriv(unit);
// APTR base = get_hwbase(unit);
// int data;
RTLD(bug("[%s] rtl8168nic_HWPHYConfig()\n", unit->rtl8168u_name))
if (np->mcfg == CFG_METHOD_1)
{
mdio_write(unit, 0x1F, 0x0001);
mdio_write(unit, 0x0B, 0x94B0);
mdio_write(unit, 0x1F, 0x0003);
mdio_write(unit, 0x12, 0x6096);
mdio_write(unit, 0x1F, 0x0000);
mdio_write(unit, 0x0D, 0xF8A0);
} else if (np->mcfg == CFG_METHOD_2) {
mdio_write(unit, 0x1F, 0x0001);
mdio_write(unit, 0x0B, 0x94B0);
mdio_write(unit, 0x1F, 0x0003);
mdio_write(unit, 0x12, 0x6096);
mdio_write(unit, 0x1F, 0x0000);
} else if (np->mcfg == CFG_METHOD_3) {
mdio_write(unit, 0x1F, 0x0001);
mdio_write(unit, 0x0B, 0x94B0);
mdio_write(unit, 0x1F, 0x0003);
mdio_write(unit, 0x12, 0x6096);
mdio_write(unit, 0x1F, 0x0000);
} else if (np->mcfg == CFG_METHOD_4) {
mdio_write(unit, 0x1F, 0x0001);
mdio_write(unit, 0x12, 0x2300);
mdio_write(unit, 0x1F, 0x0000);
mdio_write(unit, 0x1F, 0x0003);
mdio_write(unit, 0x16, 0x000A);
mdio_write(unit, 0x1F, 0x0000);
mdio_write(unit, 0x1F, 0x0003);
mdio_write(unit, 0x12, 0xC096);
mdio_write(unit, 0x1F, 0x0000);
mdio_write(unit, 0x1F, 0x0002);
mdio_write(unit, 0x00, 0x88DE);
mdio_write(unit, 0x01, 0x82B1);
mdio_write(unit, 0x1F, 0x0000);
mdio_write(unit, 0x1F, 0x0002);
mdio_write(unit, 0x08, 0x9E30);
mdio_write(unit, 0x09, 0x01F0);
mdio_write(unit, 0x1F, 0x0000);
mdio_write(unit, 0x1F, 0x0002);
mdio_write(unit, 0x0A, 0x5500);
mdio_write(unit, 0x1F, 0x0000);
mdio_write(unit, 0x1F, 0x0002);
mdio_write(unit, 0x03, 0x7002);
mdio_write(unit, 0x1F, 0x0000);
mdio_write(unit, 0x1F, 0x0002);
mdio_write(unit, 0x0C, 0x00C8);
mdio_write(unit, 0x1F, 0x0000);
mdio_write(unit, 0x1F, 0x0000);
mdio_write(unit, 0x14, mdio_read(unit, 0x14) | (1 << 5));
mdio_write(unit, 0x0D, mdio_read(unit, 0x0D) | (1 << 5));
} else if (np->mcfg == CFG_METHOD_5) {
mdio_write(unit, 0x1F, 0x0001);
mdio_write(unit, 0x12, 0x2300);
mdio_write(unit, 0x1F, 0x0003);
mdio_write(unit, 0x16, 0x0F0A);
mdio_write(unit, 0x1F, 0x0000);
mdio_write(unit, 0x1F, 0x0002);
mdio_write(unit, 0x00, 0x88DE);
mdio_write(unit, 0x01, 0x82B1);
mdio_write(unit, 0x1F, 0x0000);
mdio_write(unit, 0x1F, 0x0002);
mdio_write(unit, 0x0C, 0x7EB8);
mdio_write(unit, 0x1F, 0x0000);
mdio_write(unit, 0x1F, 0x0002);
mdio_write(unit, 0x06, 0x0761);
mdio_write(unit, 0x1F, 0x0000);
mdio_write(unit, 0x1F, 0x0001);
mdio_write(unit, 0x03, 0x802F);
mdio_write(unit, 0x02, 0x4F02);
mdio_write(unit, 0x01, 0x0409);
mdio_write(unit, 0x00, 0xF099);
mdio_write(unit, 0x04, 0x9800);
mdio_write(unit, 0x04, 0x9000);
mdio_write(unit, 0x1F, 0x0000);
mdio_write(unit, 0x1F, 0x0000);
mdio_write(unit, 0x16, mdio_read(unit, 0x16) | (1 << 0));
mdio_write(unit, 0x1F, 0x0000);
mdio_write(unit, 0x14, mdio_read(unit, 0x14) | (1 << 5));
mdio_write(unit, 0x0D, mdio_read(unit, 0x0D) | (1 << 5));
mdio_write(unit, 0x1F, 0x0001);
mdio_write(unit, 0x1D, 0x3D98);
mdio_write(unit, 0x1F, 0x0000);
mdio_write(unit, 0x1F, 0x0001);
mdio_write(unit, 0x17, 0x0CC0);
mdio_write(unit, 0x1F, 0x0000);
} else if (np->mcfg == CFG_METHOD_6) {
mdio_write(unit, 0x1F, 0x0001);
mdio_write(unit, 0x12, 0x2300);
mdio_write(unit, 0x1F, 0x0003);
mdio_write(unit, 0x16, 0x0F0A);
mdio_write(unit, 0x1F, 0x0000);
mdio_write(unit, 0x1F, 0x0002);
mdio_write(unit, 0x00, 0x88DE);
mdio_write(unit, 0x01, 0x82B1);
mdio_write(unit, 0x1F, 0x0000);
mdio_write(unit, 0x1F, 0x0002);
mdio_write(unit, 0x0C, 0x7EB8);
mdio_write(unit, 0x1F, 0x0000);
mdio_write(unit, 0x1F, 0x0002);
mdio_write(unit, 0x06, 0x0761);
mdio_write(unit, 0x1F, 0x0000);
mdio_write(unit, 0x1F, 0x0000);
mdio_write(unit, 0x16, mdio_read(unit, 0x16) | (1 << 0));
mdio_write(unit, 0x1F, 0x0000);
mdio_write(unit, 0x14, mdio_read(unit, 0x14) | (1 << 5));
mdio_write(unit, 0x0D, mdio_read(unit, 0x0D) | (1 << 5));
mdio_write(unit, 0x1F, 0x0001);
mdio_write(unit, 0x1D, 0x3D98);
mdio_write(unit, 0x1F, 0x0000);
mdio_write(unit, 0x1f, 0x0001);
mdio_write(unit, 0x17, 0x0CC0);
mdio_write(unit, 0x1F, 0x0000);
} else if (np->mcfg == CFG_METHOD_7) {
mdio_write(unit, 0x1F, 0x0000);
mdio_write(unit, 0x14, mdio_read(unit, 0x14) | (1 << 5));
mdio_write(unit, 0x0D, mdio_read(unit, 0x0D) | (1 << 5));
mdio_write(unit, 0x1F, 0x0001);
mdio_write(unit, 0x1D, 0x3D98);
mdio_write(unit, 0x1F, 0x0001);
mdio_write(unit, 0x14, 0xCAA3);
mdio_write(unit, 0x1C, 0x000A);
mdio_write(unit, 0x18, 0x65D0);
mdio_write(unit, 0x1F, 0x0003);
mdio_write(unit, 0x17, 0xB580);
mdio_write(unit, 0x18, 0xFF54);
mdio_write(unit, 0x19, 0x3954);
mdio_write(unit, 0x1F, 0x0002);
mdio_write(unit, 0x0D, 0x310C);
mdio_write(unit, 0x0E, 0x310C);
mdio_write(unit, 0x0F, 0x311C);
mdio_write(unit, 0x06, 0x0761);
mdio_write(unit, 0x1F, 0x0003);
mdio_write(unit, 0x18, 0xFF55);
mdio_write(unit, 0x19, 0x3955);
mdio_write(unit, 0x18, 0xFF54);
mdio_write(unit, 0x19, 0x3954);
mdio_write(unit, 0x1f, 0x0001);
mdio_write(unit, 0x17, 0x0CC0);
mdio_write(unit, 0x1F, 0x0000);
} else if (np->mcfg == CFG_METHOD_8) {
mdio_write(unit, 0x1F, 0x0000);
mdio_write(unit, 0x0D, mdio_read(unit, 0x0D) | (1 << 5));
mdio_write(unit, 0x1F, 0x0001);
mdio_write(unit, 0x14, 0xCAA3);
mdio_write(unit, 0x1C, 0x000A);
mdio_write(unit, 0x18, 0x65D0);
mdio_write(unit, 0x1F, 0x0003);
mdio_write(unit, 0x17, 0xB580);
mdio_write(unit, 0x18, 0xFF54);
mdio_write(unit, 0x19, 0x3954);
mdio_write(unit, 0x1F, 0x0002);
mdio_write(unit, 0x0D, 0x310C);
mdio_write(unit, 0x0E, 0x310C);
mdio_write(unit, 0x0F, 0x311C);
mdio_write(unit, 0x06, 0x0761);
mdio_write(unit, 0x1F, 0x0003);
mdio_write(unit, 0x18, 0xFF55);
mdio_write(unit, 0x19, 0x3955);
mdio_write(unit, 0x18, 0xFF54);
mdio_write(unit, 0x19, 0x3954);
mdio_write(unit, 0x1f, 0x0001);
mdio_write(unit, 0x17, 0x0CC0);
mdio_write(unit, 0x1F, 0x0000);
} else if (np->mcfg == CFG_METHOD_9) {
mdio_write(unit, 0x1F, 0x0001);
mdio_write(unit, 0x06, 0x4064);
mdio_write(unit, 0x07, 0x2863);
mdio_write(unit, 0x08, 0x059C);
mdio_write(unit, 0x09, 0x26B4);
mdio_write(unit, 0x0A, 0x6A19);
mdio_write(unit, 0x0B, 0xACC0);
mdio_write(unit, 0x10, 0xF06D);
mdio_write(unit, 0x14, 0x7F68);
mdio_write(unit, 0x18, 0x7FD9);
mdio_write(unit, 0x1C, 0xF0FF);
mdio_write(unit, 0x1D, 0x3D9C);
mdio_write(unit, 0x1F, 0x0003);
mdio_write(unit, 0x12, 0xF49F);
mdio_write(unit, 0x13, 0x070B);
mdio_write(unit, 0x1A, 0x05AD);
mdio_write(unit, 0x14, 0x94C0);
mdio_write(unit, 0x1F, 0x0002);
mdio_write(unit, 0x0B, 0x0B10);
mdio_write(unit, 0x0C, 0xA2F7);
mdio_write(unit, 0x1F, 0x0002);
mdio_write(unit, 0x06, 0x5571);
mdio_write(unit, 0x1F, 0x0002);
mdio_write(unit, 0x02, 0xC107);
mdio_write(unit, 0x03, 0x1002);
mdio_write(unit, 0x1F, 0x0001);
mdio_write(unit, 0x17, 0x0CC0);
mdio_write(unit, 0x1F, 0x0005);
mdio_write(unit, 0x05, 0x8200);
mdio_write(unit, 0x06, 0xF8F9);
mdio_write(unit, 0x06, 0xFAEF);
mdio_write(unit, 0x06, 0x59EE);
mdio_write(unit, 0x06, 0xF8EA);
mdio_write(unit, 0x06, 0x00EE);
mdio_write(unit, 0x06, 0xF8EB);
mdio_write(unit, 0x06, 0x00E0);
mdio_write(unit, 0x06, 0xF87C);
mdio_write(unit, 0x06, 0xE1F8);
mdio_write(unit, 0x06, 0x7D59);
mdio_write(unit, 0x06, 0x0FEF);
mdio_write(unit, 0x06, 0x0139);
mdio_write(unit, 0x06, 0x029E);
mdio_write(unit, 0x06, 0x06EF);
mdio_write(unit, 0x06, 0x1039);
mdio_write(unit, 0x06, 0x089F);
mdio_write(unit, 0x06, 0x2AEE);
mdio_write(unit, 0x06, 0xF8EA);
mdio_write(unit, 0x06, 0x00EE);
mdio_write(unit, 0x06, 0xF8EB);
mdio_write(unit, 0x06, 0x01E0);
mdio_write(unit, 0x06, 0xF87C);
mdio_write(unit, 0x06, 0xE1F8);
mdio_write(unit, 0x06, 0x7D58);
mdio_write(unit, 0x06, 0x409E);
mdio_write(unit, 0x06, 0x0F39);
mdio_write(unit, 0x06, 0x46AA);
mdio_write(unit, 0x06, 0x0BBF);
mdio_write(unit, 0x06, 0x8251);
mdio_write(unit, 0x06, 0xD682);
mdio_write(unit, 0x06, 0x5902);
mdio_write(unit, 0x06, 0x014F);
mdio_write(unit, 0x06, 0xAE09);
mdio_write(unit, 0x06, 0xBF82);
mdio_write(unit, 0x06, 0x59D6);
mdio_write(unit, 0x06, 0x8261);
mdio_write(unit, 0x06, 0x0201);
mdio_write(unit, 0x06, 0x4FEF);
mdio_write(unit, 0x06, 0x95FE);
mdio_write(unit, 0x06, 0xFDFC);
mdio_write(unit, 0x06, 0x054D);
mdio_write(unit, 0x06, 0x2000);
mdio_write(unit, 0x06, 0x024E);
mdio_write(unit, 0x06, 0x2200);
mdio_write(unit, 0x06, 0x024D);
mdio_write(unit, 0x06, 0xDFFF);
mdio_write(unit, 0x06, 0x014E);
mdio_write(unit, 0x06, 0xDDFF);
mdio_write(unit, 0x06, 0x0100);
mdio_write(unit, 0x06, 0x6010);
mdio_write(unit, 0x05, 0xFFF6);
mdio_write(unit, 0x06, 0x00EC);
mdio_write(unit, 0x05, 0x83D4);
mdio_write(unit, 0x06, 0x8200);
mdio_write(unit, 0x1F, 0x0000);
} else if (np->mcfg == CFG_METHOD_10) {
mdio_write(unit, 0x1F, 0x0001);
mdio_write(unit, 0x06, 0x4064);
mdio_write(unit, 0x07, 0x2863);
mdio_write(unit, 0x08, 0x059C);
mdio_write(unit, 0x09, 0x26B4);
mdio_write(unit, 0x0A, 0x6A19);
mdio_write(unit, 0x0B, 0xACC0);
mdio_write(unit, 0x10, 0xF06D);
mdio_write(unit, 0x14, 0x7F68);
mdio_write(unit, 0x18, 0x7FD9);
mdio_write(unit, 0x1C, 0xF0FF);
mdio_write(unit, 0x1D, 0x3D9C);
mdio_write(unit, 0x1F, 0x0003);
mdio_write(unit, 0x12, 0xF49F);
mdio_write(unit, 0x13, 0x070B);
mdio_write(unit, 0x1A, 0x05AD);
mdio_write(unit, 0x14, 0x94C0);
mdio_write(unit, 0x1F, 0x0002);
mdio_write(unit, 0x06, 0x5571);
mdio_write(unit, 0x1F, 0x0002);
mdio_write(unit, 0x05, 0x2642);
mdio_write(unit, 0x1F, 0x0002);
mdio_write(unit, 0x02, 0xC107);
mdio_write(unit, 0x03, 0x1002);
mdio_write(unit, 0x1F, 0x0001);
mdio_write(unit, 0x17, 0x0CC0);
mdio_write(unit, 0x1F, 0x0002);
mdio_write(unit, 0x0F, 0x0017);
mdio_write(unit, 0x1F, 0x0005);
mdio_write(unit, 0x05, 0x8200);
mdio_write(unit, 0x06, 0xF8F9);
mdio_write(unit, 0x06, 0xFAEF);
mdio_write(unit, 0x06, 0x59EE);
mdio_write(unit, 0x06, 0xF8EA);
mdio_write(unit, 0x06, 0x00EE);
mdio_write(unit, 0x06, 0xF8EB);
mdio_write(unit, 0x06, 0x00E0);
mdio_write(unit, 0x06, 0xF87C);
mdio_write(unit, 0x06, 0xE1F8);
mdio_write(unit, 0x06, 0x7D59);
mdio_write(unit, 0x06, 0x0FEF);
mdio_write(unit, 0x06, 0x0139);
mdio_write(unit, 0x06, 0x029E);
mdio_write(unit, 0x06, 0x06EF);
mdio_write(unit, 0x06, 0x1039);
mdio_write(unit, 0x06, 0x089F);
mdio_write(unit, 0x06, 0x2AEE);
mdio_write(unit, 0x06, 0xF8EA);
mdio_write(unit, 0x06, 0x00EE);
mdio_write(unit, 0x06, 0xF8EB);
mdio_write(unit, 0x06, 0x01E0);
mdio_write(unit, 0x06, 0xF87C);
mdio_write(unit, 0x06, 0xE1F8);
mdio_write(unit, 0x06, 0x7D58);
mdio_write(unit, 0x06, 0x409E);
mdio_write(unit, 0x06, 0x0F39);
mdio_write(unit, 0x06, 0x46AA);
mdio_write(unit, 0x06, 0x0BBF);
mdio_write(unit, 0x06, 0x8251);
mdio_write(unit, 0x06, 0xD682);
mdio_write(unit, 0x06, 0x5902);
mdio_write(unit, 0x06, 0x014F);
mdio_write(unit, 0x06, 0xAE09);
mdio_write(unit, 0x06, 0xBF82);
mdio_write(unit, 0x06, 0x59D6);
mdio_write(unit, 0x06, 0x8261);
mdio_write(unit, 0x06, 0x0201);
mdio_write(unit, 0x06, 0x4FEF);
mdio_write(unit, 0x06, 0x95FE);
mdio_write(unit, 0x06, 0xFDFC);
mdio_write(unit, 0x06, 0x054D);
mdio_write(unit, 0x06, 0x2000);
mdio_write(unit, 0x06, 0x024E);
mdio_write(unit, 0x06, 0x2200);
mdio_write(unit, 0x06, 0x024D);
mdio_write(unit, 0x06, 0xDFFF);
mdio_write(unit, 0x06, 0x014E);
mdio_write(unit, 0x06, 0xDDFF);
mdio_write(unit, 0x06, 0x0100);
mdio_write(unit, 0x02, 0x6010);
mdio_write(unit, 0x05, 0xFFF6);
mdio_write(unit, 0x06, 0x00EC);
mdio_write(unit, 0x05, 0x83D4);
mdio_write(unit, 0x06, 0x8200);
mdio_write(unit, 0x1F, 0x0000);
} else if (np->mcfg == CFG_METHOD_11) {
mdio_write(unit, 0x1F, 0x0001);
mdio_write(unit, 0x06, 0x4064);
mdio_write(unit, 0x07, 0x2863);
mdio_write(unit, 0x08, 0x059C);
mdio_write(unit, 0x09, 0x26B4);
mdio_write(unit, 0x0A, 0x6A19);
mdio_write(unit, 0x0B, 0xACC0);
mdio_write(unit, 0x10, 0xF06D);
mdio_write(unit, 0x14, 0x7F68);
mdio_write(unit, 0x18, 0x7FD9);
mdio_write(unit, 0x1C, 0xF0FF);
mdio_write(unit, 0x1D, 0x3D9C);
mdio_write(unit, 0x1F, 0x0003);
mdio_write(unit, 0x12, 0xF49F);
mdio_write(unit, 0x13, 0x070B);
mdio_write(unit, 0x1A, 0x05AD);
mdio_write(unit, 0x14, 0x94C0);
mdio_write(unit, 0x1F, 0x0002);
mdio_write(unit, 0x06, 0x5571);
mdio_write(unit, 0x1F, 0x0002);
mdio_write(unit, 0x05, 0x2642);
mdio_write(unit, 0x1F, 0x0002);
mdio_write(unit, 0x02, 0xC107);
mdio_write(unit, 0x03, 0x1002);
mdio_write(unit, 0x1F, 0x0001);
mdio_write(unit, 0x17, 0x0CC0);
mdio_write(unit, 0x1F, 0x0002);
mdio_write(unit, 0x0F, 0x0017);
}
}
static void rtl8168nic_DSM(struct net_device *unit, int dev_state)
{
struct rtl8168_priv *np = get_pcnpriv(unit);
APTR base = get_hwbase(unit);
switch (dev_state) {
case DSM_MAC_INIT:
if ((np->mcfg == CFG_METHOD_5) || (np->mcfg == CFG_METHOD_6)) {
if (RTL_R8(base + (MACDBG)) & 0x80) {
RTL_W8(base + (GPIO), RTL_R8(base + (GPIO)) | GPIO_en);
} else {
RTL_W8(base + (GPIO), RTL_R8(base + (GPIO)) & ~GPIO_en);
}
}
break;
case DSM_NIC_GOTO_D3:
case DSM_IF_DOWN:
if ((np->mcfg == CFG_METHOD_5) || (np->mcfg == CFG_METHOD_6))
if (RTL_R8(base + (MACDBG)) & 0x80)
RTL_W8(base + (GPIO), RTL_R8(base + (GPIO)) & ~GPIO_en);
break;
case DSM_NIC_RESUME_D3:
case DSM_IF_UP:
if ((np->mcfg == CFG_METHOD_5) || (np->mcfg == CFG_METHOD_6))
if (RTL_R8(base + (MACDBG)) & 0x80)
RTL_W8(base + (GPIO), RTL_R8(base + (GPIO)) | GPIO_en);
break;
}
}
static int rtl8168nic_SetSpeedXMII(struct net_device *unit,
UBYTE autoneg,
UWORD speed,
UBYTE duplex)
{
struct rtl8168_priv *np = get_pcnpriv(unit);
// APTR base = get_hwbase(unit);
int auto_nego = 0;
int giga_ctrl = 0;
int bmcr_true_force = 0;
// unsigned long flags;
RTLD(bug("[%s] rtl8168nic_SetSpeedXMII()\n", unit->rtl8168u_name))
if ((speed != SPEED_1000) &&
(speed != SPEED_100) &&
(speed != SPEED_10)) {
speed = SPEED_1000;
duplex = DUPLEX_FULL;
}
if ((autoneg == AUTONEG_ENABLE) || (speed == SPEED_1000)) {
/*n-way force*/
if ((speed == SPEED_10) && (duplex == DUPLEX_HALF)) {
auto_nego |= ADVERTISE_10HALF;
} else if ((speed == SPEED_10) && (duplex == DUPLEX_FULL)) {
auto_nego |= ADVERTISE_10HALF |
ADVERTISE_10FULL;
} else if ((speed == SPEED_100) && (duplex == DUPLEX_HALF)) {
auto_nego |= ADVERTISE_100HALF |
ADVERTISE_10HALF |
ADVERTISE_10FULL;
} else if ((speed == SPEED_100) && (duplex == DUPLEX_FULL)) {
auto_nego |= ADVERTISE_100HALF |
ADVERTISE_100FULL |
ADVERTISE_10HALF |
ADVERTISE_10FULL;
} else if (speed == SPEED_1000) {
giga_ctrl |= ADVERTISE_1000HALF |
ADVERTISE_1000FULL;
auto_nego |= ADVERTISE_100HALF |
ADVERTISE_100FULL |
ADVERTISE_10HALF |
ADVERTISE_10FULL;
}
//disable flow contorol
auto_nego &= ~ADVERTISE_PAUSE_CAP;
auto_nego &= ~ADVERTISE_PAUSE_ASYM;
np->phy_auto_nego_reg = auto_nego;
np->phy_1000_ctrl_reg = giga_ctrl;
np->autoneg = autoneg;
np->speed = speed;
np->duplex = duplex;
rtl8168nic_PHYPowerUP(unit);
mdio_write(unit, 0x1f, 0x0000);
mdio_write(unit, MII_ADVERTISE, auto_nego);
mdio_write(unit, MII_CTRL1000, giga_ctrl);
mdio_write(unit, MII_BMCR, BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART);
} else {
/*true force*/
#ifndef BMCR_SPEED100
#define BMCR_SPEED100 0x0040
#endif
#ifndef BMCR_SPEED10
#define BMCR_SPEED10 0x0000
#endif
if ((speed == SPEED_10) && (duplex == DUPLEX_HALF)) {
bmcr_true_force = BMCR_SPEED10;
} else if ((speed == SPEED_10) && (duplex == DUPLEX_FULL)) {
bmcr_true_force = BMCR_SPEED10 | BMCR_FULLDPLX;
} else if ((speed == SPEED_100) && (duplex == DUPLEX_HALF)) {
bmcr_true_force = BMCR_SPEED100;
} else if ((speed == SPEED_100) && (duplex == DUPLEX_FULL)) {
bmcr_true_force = BMCR_SPEED100 | BMCR_FULLDPLX;
}
mdio_write(unit, 0x1f, 0x0000);
mdio_write(unit, MII_BMCR, bmcr_true_force);
}
return 0;
}
#if 0
static void rtl8168nic_start_rx(struct net_device *unit)
{
// struct rtl8168_priv *np = get_pcnpriv(unit);
// APTR base = get_hwbase(unit);
RTLD(bug("[%s] rtl8168nic_start_rx\n", unit->rtl8168u_name))
// Already running? Stop it.
/* TODO: Handle starting/stopping Rx */
}
static void rtl8168nic_stop_rx(struct net_device *unit)
{
// APTR base = get_hwbase(unit);
RTLD(bug("[%s] rtl8168nic_stop_rx\n", unit->rtl8168u_name))
/* TODO: Handle starting/stopping Rx */
}
static void rtl8168nic_start_tx(struct net_device *unit)
{
// APTR base = get_hwbase(unit);
RTLD(bug("[%s] rtl8168nic_start_tx()\n", unit->rtl8168u_name))
/* TODO: Handle starting/stopping Tx */
}
static void rtl8168nic_stop_tx(struct net_device *unit)
{
// APTR base = get_hwbase(unit);
RTLD(bug("[%s] rtl8168nic_stop_tx()\n", unit->rtl8168u_name))
/* TODO: Handle starting/stopping Tx */
}
static void rtl8168nic_txrx_reset(struct net_device *unit)
{
// struct rtl8168_priv *np = get_pcnpriv(unit);
// APTR base = get_hwbase(unit);
RTLD(bug("[%s] rtl8168nic_txrx_reset()\n", unit->rtl8168u_name))
}
#endif
/*
* rtl8168nic_SetMulticast: unit->set_multicast function
* Called with unit->xmit_lock held.
*/
static void rtl8168nic_SetMulticast(struct net_device *unit)
{
// struct rtl8168_priv *np = get_pcnpriv(unit);
// APTR base = get_hwbase(unit);
ULONG addr[2];
ULONG mask[2];
// ULONG pff;
RTLD(bug("[%s] rtl8168nic_SetMulticast()\n", unit->rtl8168u_name))
memset(addr, 0, sizeof(addr));
memset(mask, 0, sizeof(mask));
}
static void rtl8168nic_DeInit(struct net_device *unit)
{
/* TODO: Clean up / DeInit hardware */
}
static void rtl8168nic_GetMACAddr(struct net_device *unit, char *addr, BOOL fromROM)
{
APTR base = get_hwbase(unit);
int i;
RTLD(bug("[%s] rtl8168nic_GetMACAddr()\n",unit->rtl8168u_name))
/* Get MAC address. FIXME: read EEPROM */
for (i = 0; i < MAC_ADDR_LEN; i++)
addr[i] = RTL_R8(base + MAC0 + i);
}
static void rtl8168nic_SetMACAddr(struct net_device *unit)
{
APTR base = get_hwbase(unit);
// int i,j;
RTLD(bug("[%s] rtl8168nic_SetMACAddr()\n",unit->rtl8168u_name))
RTL_W8(base + (Cfg9346), Cfg9346_Unlock);
RTL_W32(base + (MAC0),
unit->rtl8168u_dev_addr[0] |
(unit->rtl8168u_dev_addr[1] << 8) |
(unit->rtl8168u_dev_addr[2] << 16) |
(unit->rtl8168u_dev_addr[3] << 24));
RTL_W32(base + (MAC4),
unit->rtl8168u_dev_addr[4] |
(unit->rtl8168u_dev_addr[5] << 8));
RTL_W8(base + (Cfg9346), Cfg9346_Lock);
RTLD(
/* Read it back to be certain! */
TEXT newmac[6];
rtl8168nic_GetMACAddr(unit, newmac, FALSE);
bug("[%s] rtl8168nic_SetMACAddr: New MAC Address %02x:%02x:%02x:%02x:%02x:%02x\n", unit->rtl8168u_name,
newmac[0], newmac[1], newmac[2],
newmac[3], newmac[4], newmac[5])
)
}
static void rtl8168nic_LinkOption(struct net_device *unit, UBYTE *aut, UWORD *spd, UBYTE *dup)
{
unsigned char opt_speed;
unsigned char opt_duplex;
unsigned char opt_autoneg;
opt_speed = ((unit->rtl8168u_UnitNum < MAX_UNITS) && (unit->rtl8168u_UnitNum >= 0)) ? unit->rtl8168u_device->speed[unit->rtl8168u_UnitNum] : 0xff;
opt_duplex = ((unit->rtl8168u_UnitNum < MAX_UNITS) && (unit->rtl8168u_UnitNum >= 0)) ? unit->rtl8168u_device->duplex[unit->rtl8168u_UnitNum] : 0xff;
opt_autoneg = ((unit->rtl8168u_UnitNum < MAX_UNITS) && (unit->rtl8168u_UnitNum >= 0)) ? unit->rtl8168u_device->autoneg[unit->rtl8168u_UnitNum] : 0xff;
if ((opt_speed == 0xff) |
(opt_duplex == 0xff) |
(opt_autoneg == 0xff)) {
*spd = SPEED_1000;
*dup = DUPLEX_FULL;
*aut = AUTONEG_ENABLE;
} else {
*spd = unit->rtl8168u_device->speed[unit->rtl8168u_UnitNum];
*dup = unit->rtl8168u_device->duplex[unit->rtl8168u_UnitNum];
*aut = unit->rtl8168u_device->autoneg[unit->rtl8168u_UnitNum];
}
}
static void rtl8168nic_Init(struct net_device *unit)
{
struct pHidd_PCIDevice_WriteConfigByte pcibyte;
struct rtl8168_priv *np = get_pcnpriv(unit);
APTR base = get_hwbase(unit);
UBYTE autoneg, duplex;
UWORD speed;
int i;
// int config1;
RTLD(bug("[%s] rtl8168nic_Init(unit @ %p)\n", unit->rtl8168u_name, unit))
/* Identify chip attached to board */
rtl8168nic_GetMACVersion(unit);
rtl8168nic_PrintMACVersion(unit);
for (i = (sizeof(rtl_chip_info) / sizeof(rtl_chip_info[0])) - 1; i >= 0; i--) {
if (np->mcfg == rtl_chip_info[i].mcfg)
break;
}
if (i < 0) {
/* Unknown chip: assume array element #0, original RTL-8168 */
RTLD(bug("[%s] rtl8168nic_Init: Unknown Realtek chip version, assuming %s\n", unit->rtl8168u_name, rtl_chip_info[0].name))
i++;
}
np->chipset = i;
unit->rtl8168u_rtl_chipname = rtl_chip_info[np->chipset].name;
RTL_W8(base + (Cfg9346), Cfg9346_Unlock);
RTL_W8(base + (Config1), RTL_R8(base + Config1) | PMEnable);
RTL_W8(base + (Config5), RTL_R8(base + Config5) & PMEStatus);
RTL_W8(base + (Cfg9346), Cfg9346_Lock);
RTLD(bug("[%s] rtl8168nic_Init: Power Management enabled\n", unit->rtl8168u_name))
/* RTL_W8(base + (Cfg9346), Cfg9346_Unlock);
np->features |= rtl8168_try_msi(pdev, base);
RTL_W8(base + (Cfg9346), Cfg9346_Lock); */
rtl8168nic_GetMACAddr(unit, &np->orig_mac[0], TRUE);
unit->rtl8168u_dev_addr[0] = unit->rtl8168u_org_addr[0] = np->orig_mac[0];
unit->rtl8168u_dev_addr[1] = unit->rtl8168u_org_addr[1] = np->orig_mac[1];
unit->rtl8168u_dev_addr[2] = unit->rtl8168u_org_addr[2] = np->orig_mac[2];
unit->rtl8168u_dev_addr[3] = unit->rtl8168u_org_addr[3] = np->orig_mac[3];
unit->rtl8168u_dev_addr[4] = unit->rtl8168u_org_addr[4] = np->orig_mac[4];
unit->rtl8168u_dev_addr[5] = unit->rtl8168u_org_addr[5] = np->orig_mac[5];
RTLD(bug("[%s] rtl8168nic_Init: MAC Address %02x:%02x:%02x:%02x:%02x:%02x\n", unit->rtl8168u_name,
unit->rtl8168u_dev_addr[0], unit->rtl8168u_dev_addr[1], unit->rtl8168u_dev_addr[2],
unit->rtl8168u_dev_addr[3], unit->rtl8168u_dev_addr[4], unit->rtl8168u_dev_addr[5]))
bug("[%s] rtl8168nic_Init: This product is covered by one or more of the following patents:\n", unit->rtl8168u_name);
bug("[%s] rtl8168nic_Init: US5,307,459, US5,434,872, US5,732,094, US6,570,884, US6,115,776, and US6,327,625.\n", unit->rtl8168u_name);
/*
unit->features |= NETIF_F_IP_CSUM;
*/
np->cp_cmd |= RxChkSum;
np->cp_cmd |= RTL_R16(base + (CPlusCmd));
np->intr_mask = unit->rtl8168u_intr_mask;
rtl8168nic_HWPHYConfig(unit);
RTLD(bug("[%s] rtl8168nic_Init: PHY Configured\n", unit->rtl8168u_name))
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
pcibyte.reg = PCI_LATENCY_TIMER;
pcibyte.val = 0x40;
OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
rtl8168nic_LinkOption(unit, &autoneg, &speed, &duplex);
rtl8168nic_SetSpeedXMII(unit, autoneg, speed, duplex);
RTLD(bug("[%s] rtl8168nic_Init: Link Speed %dbps %s duplex %s\n", unit->rtl8168u_name, speed, (duplex == DUPLEX_HALF) ? "half" :"full", (autoneg == AUTONEG_ENABLE) ? "(autoneg)" :""))
}
static void rtl8168nic_drain_tx(struct net_device *unit)
{
// struct rtl8168_priv *np = get_pcnpriv(unit);
// int i;
// for (i = 0; i < NUM_TX_DESC; i++) {
/* TODO: rtl8168nic_drain_tx does nothing atm. */
// }
}
static void rtl8168nic_drain_rx(struct net_device *unit)
{
// struct rtl8168_priv *np = get_pcnpriv(unit);
// int i;
// for (i = 0; i < RX_RING_SIZE; i++) {
/* TODO: rtl8168nic_drain_rx does nothing atm. */
// }
}
static void drain_ring(struct net_device *unit)
{
rtl8168nic_drain_tx(unit);
rtl8168nic_drain_rx(unit);
}
static int request_irq(struct net_device *unit)
{
RTLD(bug("[%s] request_irq()\n", unit->rtl8168u_name))
if (!unit->rtl8168u_IntsAdded)
{
AddIntServer(INTB_KERNEL + unit->rtl8168u_IRQ,
&unit->rtl8168u_irqhandler);
AddIntServer(INTB_VERTB, &unit->rtl8168u_touthandler);
unit->rtl8168u_IntsAdded = TRUE;
}
RTLD(bug("[%s] request_irq: IRQ Handlers configured\n", unit->rtl8168u_name))
return 0;
}
static void free_irq(struct net_device *unit)
{
if (unit->rtl8168u_IntsAdded)
{
RemIntServer(INTB_KERNEL + unit->rtl8168u_IRQ,
&unit->rtl8168u_irqhandler);
RemIntServer(INTB_VERTB, &unit->rtl8168u_touthandler);
unit->rtl8168u_IntsAdded = FALSE;
}
}
static void rtl8168nic_SetRXBufSize(struct net_device *unit)
{
struct rtl8168_priv *np = get_pcnpriv(unit);
APTR base = get_hwbase(unit);
unsigned int mtu = unit->rtl8168u_mtu;
RTLD(bug("[%s] rtl8168nic_SetRXBufSize()\n", unit->rtl8168u_name))
np->rx_buf_sz = (mtu > ETH_DATA_LEN) ? mtu + ETH_HLEN + 8 : RX_BUF_SIZE;
RTL_W16(base + (RxMaxSize), np->rx_buf_sz + 1);
}
static void rtl8168nic_NICReset(struct net_device *unit)
{
struct rtl8168_priv *np = get_pcnpriv(unit);
APTR base = get_hwbase(unit);
int i;
RTLD(bug("[%s] rtl8168nic_NICReset()\n", unit->rtl8168u_name))
if ((np->mcfg != CFG_METHOD_1) &&
(np->mcfg != CFG_METHOD_2) &&
(np->mcfg != CFG_METHOD_3)) {
RTL_W8(base + (ChipCmd), StopReq | CmdRxEnb | CmdTxEnb);
udelay(100);
}
/* Soft reset the chip. */
RTL_W8(base + (ChipCmd), CmdReset);
/* Check that the chip has finished the reset. */
for (i = 1000; i > 0; i--) {
if ((RTL_R8(base + (ChipCmd)) & CmdReset) == 0)
break;
udelay(100);
}
}
static void rtl8168nic_SetRxMode(struct net_device *unit)
{
struct rtl8168_priv *np = get_pcnpriv(unit);
APTR base = get_hwbase(unit);
// unsigned long flags;
ULONG mc_filter[2]; /* Multicast hash filter */
int i, j, k, rx_mode;
ULONG tmp = 0;
RTLD(bug("[%s] rtl8168nic_SetRxMode()\n", unit->rtl8168u_name))
if (unit->rtl8168u_flags & IFF_PROMISC) {
/* Unconditionally log net taps. */
RTLD(bug("[%s] rtl8168nic_SetRxMode: Promiscuous mode enabled\n", unit->rtl8168u_name))
rx_mode =
AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
AcceptAllPhys;
mc_filter[1] = mc_filter[0] = 0xffffffff;
} else if ((unit->rtl8168u_mc_count > unit->rtl8168u_device->rtl8168b_MulticastFilterLimit)
|| (unit->rtl8168u_flags & IFF_ALLMULTI)) {
/* Too many to filter perfectly -- accept all multicasts. */
rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
mc_filter[1] = mc_filter[0] = 0xffffffff;
} else {
struct dev_mc_list *mclist;
rx_mode = AcceptBroadcast | AcceptMyPhys;
mc_filter[1] = mc_filter[0] = 0;
for (i = 0, mclist = unit->rtl8168u_mc_list; mclist && i < unit->rtl8168u_mc_count;
i++, mclist = mclist->next) {
// int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26;
// mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
rx_mode |= AcceptMulticast;
}
}
np->rtl8168_rx_config = rtl_chip_info[np->chipset].RCR_Cfg;
tmp = np->rtl8168_rx_config | rx_mode | (RTL_R32(base + (RxConfig)) & rtl_chip_info[np->chipset].RxConfigMask);
for (j = 0; j < 2; j++) {
ULONG mask = 0x000000ff;
ULONG tmp1 = 0;
ULONG tmp2 = 0;
int x = 0;
int y = 0;
for (k = 0; k < 4; k++) {
tmp1 = mc_filter[j] & mask;
x = 32 - (8 + 16 * k);
y = x - 2 * x;
if (x > 0)
tmp2 = tmp2 | (tmp1 << x);
else
tmp2 = tmp2 | (tmp1 >> y);
mask = mask << 8;
}
mc_filter[j] = tmp2;
}
RTL_W32(base + (RxConfig), tmp);
RTL_W32(base + (MAR0 + 0), mc_filter[1]);
RTL_W32(base + (MAR0 + 4), mc_filter[0]);
}
static void rtl8168nic_HWStart(struct net_device *unit)
{
struct rtl8168_priv *np = get_pcnpriv(unit);
APTR base = get_hwbase(unit);
struct pHidd_PCIDevice_WriteConfigByte pcibyte;
UBYTE device_control;
UWORD ephy_data;
ULONG csi_tmp;
RTLD(bug("[%s] rtl8168nic_HWStart()\n", unit->rtl8168u_name))
rtl8168nic_NICReset(unit);
RTL_W8(base + (Cfg9346), Cfg9346_Unlock);
RTL_W8(base + (Reserved1), Reserved1_data);
np->cp_cmd |= PktCntrDisable | INTT_1;
RTL_W16(base + (CPlusCmd), np->cp_cmd);
RTL_W16(base + (IntrMitigate), 0x5151);
//Work around for RxFIFO overflow
if (np->mcfg == CFG_METHOD_1) {
unit->rtl8168u_intr_mask |= RxFIFOOver | PCSTimeout;
unit->rtl8168u_intr_mask &= ~RxDescUnavail;
}
RTL_W32(base + (TxDescStartAddrLow), ((UQUAD) (IPTR)np->TxPhyAddr & DMA_32BIT_MASK));
RTL_W32(base + (TxDescStartAddrHigh), ((UQUAD) (IPTR)np->TxPhyAddr >> 32));
RTL_W32(base + (RxDescAddrLow), ((UQUAD) (IPTR)np->RxPhyAddr & DMA_32BIT_MASK));
RTL_W32(base + (RxDescAddrHigh), ((UQUAD) (IPTR)np->RxPhyAddr >> 32));
/* Set Rx Config register */
rtl8168nic_SetRxMode(unit);
/* Set DMA burst size and Interframe Gap Time */
if (np->mcfg == CFG_METHOD_1) {
RTL_W32(base + (TxConfig), (TX_DMA_BURST_512 << TxDMAShift) |
(InterFrameGap << TxInterFrameGapShift));
} else {
RTL_W32(base + (TxConfig), (TX_DMA_BURST_unlimited << TxDMAShift) |
(InterFrameGap << TxInterFrameGapShift));
}
/* Clear the interrupt status register. */
RTL_W16(base + (IntrStatus), 0xFFFF);
if (np->rx_fifo_overflow == 0) {
/* Enable all known interrupts by setting the interrupt mask. */
RTL_W16(base + (IntrMask), unit->rtl8168u_intr_mask);
netif_start_queue(unit);
}
if (np->mcfg == CFG_METHOD_4) {
/*set PCI configuration space offset 0x70F to 0x27*/
/*When the register offset of PCI configuration space larger than 0xff, use CSI to access it.*/
csi_tmp = rtl8168nic_CSIRead(unit, 0x70c) & 0x00ffffff;
rtl8168nic_CSIWrite(unit, 0x70c, csi_tmp | 0x27000000);
RTL_W8(base + (DBG_reg), (0x0E << 4) | Fix_Nak_1 | Fix_Nak_2);
/*Set EPHY registers begin*/
/*Set EPHY register offset 0x02 bit 11 to 0 and bit 12 to 1*/
ephy_data = rtl8168nic_EPHYRead(unit, 0x02);
ephy_data &= ~(1 << 11);
ephy_data |= (1 << 12);
rtl8168nic_EPHYWrite(unit, 0x02, ephy_data);
/*Set EPHY register offset 0x03 bit 1 to 1*/
ephy_data = rtl8168nic_EPHYRead(unit, 0x03);
ephy_data |= (1 << 1);
rtl8168nic_EPHYWrite(unit, 0x03, ephy_data);
/*Set EPHY register offset 0x06 bit 7 to 0*/
ephy_data = rtl8168nic_EPHYRead(unit, 0x06);
ephy_data &= ~(1 << 7);
rtl8168nic_EPHYWrite(unit, 0x06, ephy_data);
/*Set EPHY registers end*/
RTL_W8(base + (Config3), RTL_R8(base + (Config3)) & ~Beacon_en);
//disable clock request.
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
pcibyte.reg = 0x81;
pcibyte.val = 0x00;
OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
RTL_W16(base + (CPlusCmd), RTL_R16(base + (CPlusCmd)) &
~(EnableBist | Macdbgo_oe | Force_halfdup | Force_rxflow_en | Force_txflow_en |
Cxpl_dbg_sel | ASF | PktCntrDisable | Macdbgo_sel));
if (unit->rtl8168u_mtu > ETH_DATA_LEN) {
RTL_W8(base + (Reserved1), Reserved1_data);
RTL_W8(base + (Config3), RTL_R8(base + (Config3)) | Jumbo_En0);
RTL_W8(base + (Config4), RTL_R8(base + (Config4)) | Jumbo_En1);
//Set PCI configuration space offset 0x79 to 0x20
/*Increase the Tx performance*/
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_ReadConfigByte);
pcibyte.reg = 0x79;
device_control = (UBYTE)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
device_control &= ~0x70;
device_control |= 0x20;
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
pcibyte.reg = 0x79;
pcibyte.val = device_control;
OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
//tx checksum offload disable
// unit->features &= ~NETIF_F_IP_CSUM;
//rx checksum offload disable
np->cp_cmd &= ~RxChkSum;
RTL_W16(base + (CPlusCmd), np->cp_cmd);
} else {
RTL_W8(base + (Reserved1), Reserved1_data);
RTL_W8(base + (Config3), RTL_R8(base + (Config3)) & ~Jumbo_En0);
RTL_W8(base + (Config4), RTL_R8(base + (Config4)) & ~Jumbo_En1);
//Set PCI configuration space offset 0x79 to 0x50
/*Increase the Tx performance*/
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_ReadConfigByte);
pcibyte.reg = 0x79;
device_control = (UBYTE)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
device_control &= ~0x70;
device_control |= 0x50;
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
pcibyte.reg = 0x79;
pcibyte.val = device_control;
OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
//tx checksum offload enable
// unit->features |= NETIF_F_IP_CSUM;
//rx checksum offload enable
np->cp_cmd |= RxChkSum;
RTL_W16(base + (CPlusCmd), np->cp_cmd);
}
} else if (np->mcfg == CFG_METHOD_5) {
/*set PCI configuration space offset 0x70F to 0x27*/
/*When the register offset of PCI configuration space larger than 0xff, use CSI to access it.*/
csi_tmp = rtl8168nic_CSIRead(unit, 0x70c) & 0x00ffffff;
rtl8168nic_CSIWrite(unit, 0x70c, csi_tmp | 0x27000000);
/******set EPHY registers for RTL8168CP begin******/
//Set EPHY register offset 0x01 bit 0 to 1.
ephy_data = rtl8168nic_EPHYRead(unit, 0x01);
ephy_data |= (1 << 0);
rtl8168nic_EPHYWrite(unit, 0x01, ephy_data);
//Set EPHY register offset 0x03 bit 10 to 0, bit 9 to 1 and bit 5 to 1.
ephy_data = rtl8168nic_EPHYRead(unit, 0x03);
ephy_data &= ~(1 << 10);
ephy_data |= (1 << 9);
ephy_data |= (1 << 5);
rtl8168nic_EPHYWrite(unit, 0x03, ephy_data);
/******set EPHY registers for RTL8168CP end******/
RTL_W8(base + (Config3), RTL_R8(base + (Config3)) & ~Beacon_en);
//disable clock request.
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
pcibyte.reg = 0x81;
pcibyte.val = 0x00;
OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
RTL_W16(base + (CPlusCmd), RTL_R16(base + (CPlusCmd)) &
~(EnableBist | Macdbgo_oe | Force_halfdup | Force_rxflow_en | Force_txflow_en |
Cxpl_dbg_sel | ASF | PktCntrDisable | Macdbgo_sel));
if (unit->rtl8168u_mtu > ETH_DATA_LEN) {
RTL_W8(base + (Reserved1), Reserved1_data);
RTL_W8(base + (Config3), RTL_R8(base + (Config3)) | Jumbo_En0);
RTL_W8(base + (Config4), RTL_R8(base + (Config4)) | Jumbo_En1);
//Set PCI configuration space offset 0x79 to 0x20
/*Increase the Tx performance*/
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_ReadConfigByte);
pcibyte.reg = 0x79;
device_control = (UBYTE)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
device_control &= ~0x70;
device_control |= 0x20;
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
pcibyte.reg = 0x79;
pcibyte.val = device_control;
OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
//tx checksum offload disable
// unit->features &= ~NETIF_F_IP_CSUM;
//rx checksum offload disable
np->cp_cmd &= ~RxChkSum;
RTL_W16(base + (CPlusCmd), np->cp_cmd);
} else {
RTL_W8(base + (Reserved1), Reserved1_data);
RTL_W8(base + (Config3), RTL_R8(base + (Config3)) & ~Jumbo_En0);
RTL_W8(base + (Config4), RTL_R8(base + (Config4)) & ~Jumbo_En1);
//Set PCI configuration space offset 0x79 to 0x50
/*Increase the Tx performance*/
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_ReadConfigByte);
pcibyte.reg = 0x79;
device_control = (UBYTE)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
device_control &= ~0x70;
device_control |= 0x50;
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
pcibyte.reg = 0x79;
pcibyte.val = device_control;
OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
//tx checksum offload enable
// unit->features |= NETIF_F_IP_CSUM;
//rx checksum offload enable
np->cp_cmd |= RxChkSum;
RTL_W16(base + (CPlusCmd), np->cp_cmd);
}
} else if (np->mcfg == CFG_METHOD_6) {
/*set PCI configuration space offset 0x70F to 0x27*/
/*When the register offset of PCI configuration space larger than 0xff, use CSI to access it.*/
csi_tmp = rtl8168nic_CSIRead(unit, 0x70c) & 0x00ffffff;
rtl8168nic_CSIWrite(unit, 0x70c, csi_tmp | 0x27000000);
RTL_W8(base + (Config3), RTL_R8(base + (Config3)) & ~Beacon_en);
RTL_W16(base + (CPlusCmd), RTL_R16(base + (CPlusCmd)) &
~(EnableBist | Macdbgo_oe | Force_halfdup | Force_rxflow_en | Force_txflow_en |
Cxpl_dbg_sel | ASF | PktCntrDisable | Macdbgo_sel));
if (unit->rtl8168u_mtu > ETH_DATA_LEN) {
RTL_W8(base + (Reserved1), Reserved1_data);
RTL_W8(base + (Config3), RTL_R8(base + (Config3)) | Jumbo_En0);
RTL_W8(base + (Config4), RTL_R8(base + (Config4)) | Jumbo_En1);
//Set PCI configuration space offset 0x79 to 0x20
/*Increase the Tx performance*/
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_ReadConfigByte);
pcibyte.reg = 0x79;
device_control = (UBYTE)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
device_control &= ~0x70;
device_control |= 0x20;
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
pcibyte.reg = 0x79;
pcibyte.val = device_control;
OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
//tx checksum offload disable
// unit->features &= ~NETIF_F_IP_CSUM;
//rx checksum offload disable
np->cp_cmd &= ~RxChkSum;
RTL_W16(base + (CPlusCmd), np->cp_cmd);
} else {
RTL_W8(base + (Reserved1), Reserved1_data);
RTL_W8(base + (Config3), RTL_R8(base + (Config3)) & ~Jumbo_En0);
RTL_W8(base + (Config4), RTL_R8(base + (Config4)) & ~Jumbo_En1);
//Set PCI configuration space offset 0x79 to 0x50
/*Increase the Tx performance*/
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_ReadConfigByte);
pcibyte.reg = 0x79;
device_control = (UBYTE)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
device_control &= ~0x70;
device_control |= 0x50;
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
pcibyte.reg = 0x79;
pcibyte.val = device_control;
OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
//tx checksum offload enable
// unit->features |= NETIF_F_IP_CSUM;
//rx checksum offload enable
np->cp_cmd |= RxChkSum;
RTL_W16(base + (CPlusCmd), np->cp_cmd);
}
} else if (np->mcfg == CFG_METHOD_7) {
/*set PCI configuration space offset 0x70F to 0x27*/
/*When the register offset of PCI configuration space larger than 0xff, use CSI to access it.*/
csi_tmp = rtl8168nic_CSIRead(unit, 0x70c) & 0x00ffffff;
rtl8168nic_CSIWrite(unit, 0x70c, csi_tmp | 0x27000000);
RTL_W16(base + (CPlusCmd), RTL_R16(base + (CPlusCmd)) &
~(EnableBist | Macdbgo_oe | Force_halfdup | Force_rxflow_en | Force_txflow_en |
Cxpl_dbg_sel | ASF | PktCntrDisable | Macdbgo_sel));
RTL_W8(base + (Config3), RTL_R8(base + (Config3)) & ~Beacon_en);
if (unit->rtl8168u_mtu > ETH_DATA_LEN) {
RTL_W8(base + (Reserved1), Reserved1_data);
RTL_W8(base + (Config3), RTL_R8(base + (Config3)) | Jumbo_En0);
RTL_W8(base + (Config4), RTL_R8(base + (Config4)) | Jumbo_En1);
//Set PCI configuration space offset 0x79 to 0x20
/*Increase the Tx performance*/
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_ReadConfigByte);
pcibyte.reg = 0x79;
device_control = (UBYTE)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
device_control &= ~0x70;
device_control |= 0x20;
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
pcibyte.reg = 0x79;
pcibyte.val = device_control;
OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
//tx checksum offload disable
// unit->features &= ~NETIF_F_IP_CSUM;
//rx checksum offload disable
np->cp_cmd &= ~RxChkSum;
RTL_W16(base + (CPlusCmd), np->cp_cmd);
} else {
RTL_W8(base + (Reserved1), Reserved1_data);
RTL_W8(base + (Config3), RTL_R8(base + (Config3)) & ~Jumbo_En0);
RTL_W8(base + (Config4), RTL_R8(base + (Config4)) & ~Jumbo_En1);
//Set PCI configuration space offset 0x79 to 0x50
/*Increase the Tx performance*/
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_ReadConfigByte);
pcibyte.reg = 0x79;
device_control = (UBYTE)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
device_control &= ~0x70;
device_control |= 0x50;
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
pcibyte.reg = 0x79;
pcibyte.val = device_control;
OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
//tx checksum offload enable
// unit->features |= NETIF_F_IP_CSUM;
//rx checksum offload enable
np->cp_cmd |= RxChkSum;
RTL_W16(base + (CPlusCmd), np->cp_cmd);
}
} else if (np->mcfg == CFG_METHOD_8) {
/*set PCI configuration space offset 0x70F to 0x27*/
/*When the register offset of PCI configuration space larger than 0xff, use CSI to access it.*/
csi_tmp = rtl8168nic_CSIRead(unit, 0x70c) & 0x00ffffff;
rtl8168nic_CSIWrite(unit, 0x70c, csi_tmp | 0x27000000);
RTL_W16(base + (CPlusCmd), RTL_R16(base + (CPlusCmd)) &
~(EnableBist | Macdbgo_oe | Force_halfdup | Force_rxflow_en | Force_txflow_en |
Cxpl_dbg_sel | ASF | PktCntrDisable | Macdbgo_sel));
RTL_W8(base + (Config3), RTL_R8(base + (Config3)) & ~Beacon_en);
RTL_W8(base + (0xD1), 0x20);
if (unit->rtl8168u_mtu > ETH_DATA_LEN) {
RTL_W8(base + (Reserved1), Reserved1_data);
RTL_W8(base + (Config3), RTL_R8(base + (Config3)) | Jumbo_En0);
RTL_W8(base + (Config4), RTL_R8(base + (Config4)) | Jumbo_En1);
//Set PCI configuration space offset 0x79 to 0x20
/*Increase the Tx performance*/
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_ReadConfigByte);
pcibyte.reg = 0x79;
device_control = (UBYTE)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
device_control &= ~0x70;
device_control |= 0x20;
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
pcibyte.reg = 0x79;
pcibyte.val = device_control;
OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
//tx checksum offload disable
// unit->features &= ~NETIF_F_IP_CSUM;
//rx checksum offload disable
np->cp_cmd &= ~RxChkSum;
RTL_W16(base + (CPlusCmd), np->cp_cmd);
} else {
RTL_W8(base + (Reserved1), Reserved1_data);
RTL_W8(base + (Config3), RTL_R8(base + (Config3)) & ~Jumbo_En0);
RTL_W8(base + (Config4), RTL_R8(base + (Config4)) & ~Jumbo_En1);
//Set PCI configuration space offset 0x79 to 0x50
/*Increase the Tx performance*/
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_ReadConfigByte);
pcibyte.reg = 0x79;
device_control = (UBYTE)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
device_control &= ~0x70;
device_control |= 0x50;
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
pcibyte.reg = 0x79;
pcibyte.val = device_control;
OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
//tx checksum offload enable
// unit->features |= NETIF_F_IP_CSUM;
//rx checksum offload enable
np->cp_cmd |= RxChkSum;
RTL_W16(base + (CPlusCmd), np->cp_cmd);
}
} else if (np->mcfg == CFG_METHOD_9) {
/*set PCI configuration space offset 0x70F to 0x27*/
/*When the register offset of PCI configuration space larger than 0xff, use CSI to access it.*/
csi_tmp = rtl8168nic_CSIRead(unit, 0x70c) & 0x00ffffff;
rtl8168nic_CSIWrite(unit, 0x70c, csi_tmp | 0x27000000);
//disable clock request.
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
pcibyte.reg = 0x81;
pcibyte.val = 0x00;
OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
RTL_W8(base + (Config1), 0xCF);
RTL_W8(base + (Config2), 0x9C);
RTL_W8(base + (Config3), 0x62);
if (unit->rtl8168u_mtu > ETH_DATA_LEN) {
RTL_W8(base + (Reserved1), Reserved1_data);
RTL_W8(base + (Config3), RTL_R8(base + (Config3)) | Jumbo_En0);
RTL_W8(base + (Config4), RTL_R8(base + (Config4)) | Jumbo_En1);
//Set PCI configuration space offset 0x79 to 0x20
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_ReadConfigByte);
pcibyte.reg = 0x79;
device_control = (UBYTE)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
device_control &= ~0x70;
device_control |= 0x20;
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
pcibyte.reg = 0x79;
pcibyte.val = device_control;
OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
//tx checksum offload disable
// unit->features &= ~NETIF_F_IP_CSUM;
//rx checksum offload disable
np->cp_cmd &= ~RxChkSum;
RTL_W16(base + (CPlusCmd), np->cp_cmd);
} else {
RTL_W8(base + (Reserved1), Reserved1_data);
RTL_W8(base + (Config3), RTL_R8(base + (Config3)) & ~Jumbo_En0);
RTL_W8(base + (Config4), RTL_R8(base + (Config4)) & ~Jumbo_En1);
//Set PCI configuration space offset 0x79 to 0x50
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_ReadConfigByte);
pcibyte.reg = 0x79;
device_control = (UBYTE)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
device_control &= ~0x70;
device_control |= 0x50;
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
pcibyte.reg = 0x79;
pcibyte.val = device_control;
OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
//tx checksum offload enable
// unit->features |= NETIF_F_IP_CSUM;
//rx checksum offload enable
np->cp_cmd |= RxChkSum;
RTL_W16(base + (CPlusCmd), np->cp_cmd);
}
/******set EPHY registers begin******/
rtl8168nic_EPHYWrite(unit, 0x01, 0x7C7D);
rtl8168nic_EPHYWrite(unit, 0x02, 0x091F);
rtl8168nic_EPHYWrite(unit, 0x06, 0xB271);
rtl8168nic_EPHYWrite(unit, 0x07, 0xCE00);
/******set EPHY registers end******/
} else if (np->mcfg == CFG_METHOD_10) {
/*set PCI configuration space offset 0x70F to 0x27*/
/*When the register offset of PCI configuration space larger than 0xff, use CSI to access it.*/
csi_tmp = rtl8168nic_CSIRead(unit, 0x70c) & 0x00ffffff;
rtl8168nic_CSIWrite(unit, 0x70c, csi_tmp | 0x27000000);
if (unit->rtl8168u_mtu > ETH_DATA_LEN) {
RTL_W8(base + (Reserved1), Reserved1_data);
RTL_W8(base + (Config3), RTL_R8(base + (Config3)) | Jumbo_En0);
RTL_W8(base + (Config4), RTL_R8(base + (Config4)) | Jumbo_En1);
//Set PCI configuration space offset 0x79 to 0x20
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_ReadConfigByte);
pcibyte.reg = 0x79;
device_control = (UBYTE)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
device_control &= ~0x70;
device_control |= 0x20;
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
pcibyte.reg = 0x79;
pcibyte.val = device_control;
OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
//tx checksum offload disable
// unit->features &= ~NETIF_F_IP_CSUM;
//rx checksum offload disable
np->cp_cmd &= ~RxChkSum;
RTL_W16(base + (CPlusCmd), np->cp_cmd);
} else {
RTL_W8(base + (Reserved1), Reserved1_data);
RTL_W8(base + (Config3), RTL_R8(base + (Config3)) & ~Jumbo_En0);
RTL_W8(base + (Config4), RTL_R8(base + (Config4)) & ~Jumbo_En1);
//Set PCI configuration space offset 0x79 to 0x50
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_ReadConfigByte);
pcibyte.reg = 0x79;
device_control = (UBYTE)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
device_control &= ~0x70;
device_control |= 0x50;
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
pcibyte.reg = 0x79;
pcibyte.val = device_control;
OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
//tx checksum offload enable
// unit->features |= NETIF_F_IP_CSUM;
//rx checksum offload enable
np->cp_cmd |= RxChkSum;
RTL_W16(base + (CPlusCmd), np->cp_cmd);
}
RTL_W8(base + (Config1), 0xDF);
/******set EPHY registers begin******/
rtl8168nic_EPHYWrite(unit, 0x01, 0x7C7D);
rtl8168nic_EPHYWrite(unit, 0x02, 0x091F);
rtl8168nic_EPHYWrite(unit, 0x03, 0xC5BA);
rtl8168nic_EPHYWrite(unit, 0x06, 0xB279);
rtl8168nic_EPHYWrite(unit, 0x07, 0xAF00);
rtl8168nic_EPHYWrite(unit, 0x1E, 0xB8EB);
/******set EPHY registers end******/
//disable clock request.
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
pcibyte.reg = 0x81;
pcibyte.val = 0x00;
OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
} else if (np->mcfg == CFG_METHOD_11) {
/*set PCI configuration space offset 0x70F to 0x27*/
/*When the register offset of PCI configuration space larger than 0xff, use CSI to access it.*/
csi_tmp = rtl8168nic_CSIRead(unit, 0x70c) & 0x00ffffff;
rtl8168nic_CSIWrite(unit, 0x70c, csi_tmp | 0x27000000);
if (unit->rtl8168u_mtu > ETH_DATA_LEN) {
RTL_W8(base + (Reserved1), Reserved1_data);
RTL_W8(base + (Config3), RTL_R8(base + (Config3)) | Jumbo_En0);
RTL_W8(base + (Config4), RTL_R8(base + (Config4)) | Jumbo_En1);
//Set PCI configuration space offset 0x79 to 0x20
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_ReadConfigByte);
pcibyte.reg = 0x79;
device_control = (UBYTE)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
device_control &= ~0x70;
device_control |= 0x20;
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
pcibyte.reg = 0x79;
pcibyte.val = device_control;
OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
//tx checksum offload disable
// unit->features &= ~NETIF_F_IP_CSUM;
//rx checksum offload disable
np->cp_cmd &= ~RxChkSum;
RTL_W16(base + (CPlusCmd), np->cp_cmd);
} else {
RTL_W8(base + (Reserved1), Reserved1_data);
RTL_W8(base + (Config3), RTL_R8(base + (Config3)) & ~Jumbo_En0);
RTL_W8(base + (Config4), RTL_R8(base + (Config4)) & ~Jumbo_En1);
//Set PCI configuration space offset 0x79 to 0x50
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_ReadConfigByte);
pcibyte.reg = 0x79;
device_control = (UBYTE)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
device_control &= ~0x70;
device_control |= 0x50;
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
pcibyte.reg = 0x79;
pcibyte.val = device_control;
OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
//tx checksum offload enable
// unit->features |= NETIF_F_IP_CSUM;
//rx checksum offload enable
np->cp_cmd |= RxChkSum;
RTL_W16(base + (CPlusCmd), np->cp_cmd);
}
RTL_W8(base + (Config1), 0xDF);
/******set EPHY registers begin******/
rtl8168nic_EPHYWrite(unit, 0x01, 0x6C7F);
rtl8168nic_EPHYWrite(unit, 0x02, 0x011F);
rtl8168nic_EPHYWrite(unit, 0x03, 0xC1B2);
rtl8168nic_EPHYWrite(unit, 0x1A, 0x0546);
rtl8168nic_EPHYWrite(unit, 0x1C, 0x80C4);
rtl8168nic_EPHYWrite(unit, 0x1D, 0x78E4);
/******set EPHY registers end******/
//disable clock request.
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
pcibyte.reg = 0x81;
pcibyte.val = 0x00;
OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
RTL_W8(base + (0xF3), RTL_R8(base + (0xF3)) | (1 << 2));
} else if (np->mcfg == CFG_METHOD_1) {
RTL_W8(base + (Config3), RTL_R8(base + (Config3)) & ~Beacon_en);
RTL_W16(base + (CPlusCmd), RTL_R16(base + (CPlusCmd)) &
~(EnableBist | Macdbgo_oe | Force_halfdup | Force_rxflow_en | Force_txflow_en |
Cxpl_dbg_sel | ASF | PktCntrDisable | Macdbgo_sel));
if (unit->rtl8168u_mtu > ETH_DATA_LEN) {
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_ReadConfigByte);
pcibyte.reg = 0x69;
device_control = (UBYTE)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
device_control &= ~0x70;
device_control |= 0x28;
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
pcibyte.reg = 0x69;
pcibyte.val = device_control;
OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
} else {
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_ReadConfigByte);
pcibyte.reg = 0x69;
device_control = (UBYTE)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
device_control &= ~0x70;
device_control |= 0x58;
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
pcibyte.reg = 0x69;
pcibyte.val = device_control;
OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
}
} else if (np->mcfg == CFG_METHOD_2) {
RTL_W8(base + (Config3), RTL_R8(base + (Config3)) & ~Beacon_en);
RTL_W16(base + (CPlusCmd), RTL_R16(base + (CPlusCmd)) &
~(EnableBist | Macdbgo_oe | Force_halfdup | Force_rxflow_en | Force_txflow_en |
Cxpl_dbg_sel | ASF | PktCntrDisable | Macdbgo_sel));
if (unit->rtl8168u_mtu > ETH_DATA_LEN) {
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_ReadConfigByte);
pcibyte.reg = 0x69;
device_control = (UBYTE)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
device_control &= ~0x70;
device_control |= 0x28;
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
pcibyte.reg = 0x69;
pcibyte.val = device_control;
OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
RTL_W8(base + (Reserved1), Reserved1_data);
RTL_W8(base + (Config4), RTL_R8(base + (Config4)) | (1 << 0));
} else {
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_ReadConfigByte);
pcibyte.reg = 0x69;
device_control = (UBYTE)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
device_control &= ~0x70;
device_control |= 0x58;
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
pcibyte.reg = 0x69;
pcibyte.val = device_control;
OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
RTL_W8(base + (Reserved1), Reserved1_data);
RTL_W8(base + (Config4), RTL_R8(base + (Config4)) & ~(1 << 0));
}
} else if (np->mcfg == CFG_METHOD_3) {
RTL_W8(base + (Config3), RTL_R8(base + (Config3)) & ~Beacon_en);
RTL_W16(base + (CPlusCmd), RTL_R16(base + (CPlusCmd)) &
~(EnableBist | Macdbgo_oe | Force_halfdup | Force_rxflow_en | Force_txflow_en |
Cxpl_dbg_sel | ASF | PktCntrDisable | Macdbgo_sel));
if (unit->rtl8168u_mtu > ETH_DATA_LEN) {
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_ReadConfigByte);
pcibyte.reg = 0x69;
device_control = (UBYTE)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
device_control &= ~0x70;
device_control |= 0x28;
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
pcibyte.reg = 0x69;
pcibyte.val = device_control;
OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
RTL_W8(base + (Reserved1), Reserved1_data);
RTL_W8(base + (Config4), RTL_R8(base + (Config4)) | (1 << 0));
} else {
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_ReadConfigByte);
pcibyte.reg = 0x69;
device_control = (UBYTE)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
device_control &= ~0x70;
device_control |= 0x58;
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
pcibyte.reg = 0x69;
pcibyte.val = device_control;
OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
RTL_W8(base + (Reserved1), Reserved1_data);
RTL_W8(base + (Config4), RTL_R8(base + (Config4)) & ~(1 << 0));
}
}
if ((np->mcfg == CFG_METHOD_1) || (np->mcfg == CFG_METHOD_2) || (np->mcfg == CFG_METHOD_3)) {
/* csum offload command for RTL8168B/8111B */
np->tx_tcp_csum_cmd = TxIPCS | TxTCPCS;
np->tx_udp_csum_cmd = TxIPCS | TxUDPCS;
np->tx_ip_csum_cmd = TxIPCS;
} else {
/* csum offload command for RTL8168C/8111C and RTL8168CP/8111CP */
np->tx_tcp_csum_cmd = TxIPCS_C | TxTCPCS_C;
np->tx_udp_csum_cmd = TxIPCS_C | TxUDPCS_C;
np->tx_ip_csum_cmd = TxIPCS_C;
}
RTL_W8(base + (ChipCmd), CmdTxEnb | CmdRxEnb);
RTL_W8(base + (Cfg9346), Cfg9346_Lock);
if (!np->pci_cfg_is_read) {
struct pHidd_PCIDevice_ReadConfigWord readpciword;
pcibyte.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_ReadConfigByte);
pcibyte.reg = PCI_COMMAND;
np->pci_cfg_space.cmd = (UBYTE)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
pcibyte.reg = PCI_CACHE_LINE_SIZE;
np->pci_cfg_space.cls = (UBYTE)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
readpciword.mID = OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_ReadConfigWord);
readpciword.reg = PCI_BASE_ADDRESS_0;
np->pci_cfg_space.io_base_l = (UWORD)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&readpciword);
readpciword.reg = PCI_BASE_ADDRESS_0 + 2;
np->pci_cfg_space.io_base_h = (UWORD)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&readpciword);
readpciword.reg = PCI_BASE_ADDRESS_2;
np->pci_cfg_space.mem_base_l = (UWORD)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&readpciword);
readpciword.reg = PCI_BASE_ADDRESS_2 + 2;
np->pci_cfg_space.mem_base_h = (UWORD)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&readpciword);
pcibyte.reg = PCI_INTERRUPT_LINE;
np->pci_cfg_space.ilr = (UBYTE)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&pcibyte);
readpciword.reg = PCI_BASE_ADDRESS_4;
np->pci_cfg_space.resv_0x20_l = (UWORD)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&readpciword);
readpciword.reg = PCI_BASE_ADDRESS_4 + 2;
np->pci_cfg_space.resv_0x20_h = (UWORD)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&readpciword);
readpciword.reg = PCI_BASE_ADDRESS_5;
np->pci_cfg_space.resv_0x24_l = (UWORD)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&readpciword);
readpciword.reg = PCI_BASE_ADDRESS_5 + 2;
np->pci_cfg_space.resv_0x24_h = (UWORD)OOP_DoMethod(unit->rtl8168u_PCIDevice, (OOP_Msg)&readpciword);
np->pci_cfg_is_read = 1;
}
rtl8168nic_DSM(unit, DSM_MAC_INIT);
udelay(10);
}
static unsigned int rtl8168nic_XMIILinkOK(struct net_device *unit)
{
// struct rtl8168_priv *np = get_pcnpriv(unit);
APTR base = get_hwbase(unit);
mdio_write(unit, 0x1f, 0x0000);
return RTL_R8(base + (PHYstatus)) & LinkStatus;
}
void rtl8168_CheckLinkStatus(struct net_device *unit)
{
// struct rtl8168_priv *np = get_pcnpriv(unit);
// APTR base = get_hwbase(unit);
// unsigned long flags;
if (rtl8168nic_XMIILinkOK(unit)) {
netif_carrier_on(unit);
RTLD(bug("[%s] rtl8168_CheckLinkStatus: Link Up\n", unit->rtl8168u_name))
} else {
RTLD(bug("[%s] rtl8168_CheckLinkStatus: Link Down\n", unit->rtl8168u_name))
netif_carrier_off(unit);
}
}
static void rtl8168nic_InitRingIndexes(struct rtl8168_priv *np)
{
np->dirty_tx = 0;
np->dirty_rx = 0;
np->cur_tx = 0;
np->cur_rx = 0;
}
static void rtl8168nic_TxDescInit(struct rtl8168_priv *np)
{
int i = 0;
// memset(np->TxDescArray, 0x0, NUM_TX_DESC * sizeof(struct TxDesc));
for (i = 0; i < NUM_TX_DESC; i++)
if(i == (NUM_TX_DESC - 1))
np->TxDescArray[i].opts1 = AROS_LONG2LE(RingEnd);
}
static void rtl8168nic_RxDescInit(struct rtl8168_priv *np)
{
int i = 0;
// memset(np->RxDescArray, 0x0, NUM_RX_DESC * sizeof(struct RxDesc));
for (i = 0; i < NUM_RX_DESC; i++) {
if(i == (NUM_RX_DESC - 1))
np->RxDescArray[i].opts1 = AROS_LONG2LE((DescOwn | RingEnd | (ULONG)np->rx_buf_sz));
else
np->RxDescArray[i].opts1 = AROS_LONG2LE(DescOwn | (ULONG)np->rx_buf_sz);
}
}
static ULONG rtl8168nic_RxFill(struct net_device *unit, ULONG start, ULONG end)
{
struct rtl8168_priv *np = get_pcnpriv(unit);
ULONG cur;
for (cur = start; end - cur > 0; cur++) {
int i = cur % NUM_RX_DESC;
if (np->RxDescArray[i].addr)
continue;
if ((np->RxDescArray[i].addr = (IPTR)HIDD_PCIDriver_AllocPCIMem(unit->rtl8168u_PCIDriver, np->rx_buf_sz)) == 0)
break;
// RTLD(bug("[%s] rtl8168nic_RxFill: Rx Buffer %d Allocated @ %p\n", unit->rtl8168u_name, i, np->RxDescArray[i].addr))
}
return cur - start;
}
static inline void rtl8168nic_MarkAsLastDescriptor(struct RxDesc *desc)
{
desc->opts1 |= AROS_LONG2LE(RingEnd);
}
static int rtl8168nic_InitRings(struct net_device *unit)
{
struct rtl8168_priv *np = get_pcnpriv(unit);
RTLD(bug("[%s] rtl8168nic_InitRings(unit @ %p)\n", unit->rtl8168u_name, unit))
rtl8168nic_InitRingIndexes(np);
rtl8168nic_TxDescInit(np);
rtl8168nic_RxDescInit(np);
if (rtl8168nic_RxFill(unit, 0, NUM_RX_DESC) != NUM_RX_DESC)
goto err_out;
rtl8168nic_MarkAsLastDescriptor(np->RxDescArray + NUM_RX_DESC - 1);
return 0;
err_out:
// rtl8168_rx_clear(np);
return -1;
}
static int rtl8168nic_Open(struct net_device *unit)
{
struct rtl8168_priv *np = get_pcnpriv(unit);
// APTR base = get_hwbase(unit);
int ret;
RTLD(bug("[%s] rtl8168nic_Open(unit @ %p)\n", unit->rtl8168u_name, unit))
rtl8168nic_SetRXBufSize(unit);
ret = request_irq(unit);
if (ret)
goto out_drain;
np->TxDescArray = HIDD_PCIDriver_AllocPCIMem(unit->rtl8168u_PCIDriver, R8168_TX_RING_BYTES);
np->TxPhyAddr = np->TxDescArray;
np->RxDescArray = HIDD_PCIDriver_AllocPCIMem(unit->rtl8168u_PCIDriver, R8168_RX_RING_BYTES);
np->RxPhyAddr = np->RxDescArray;
if ((np->TxDescArray) && (np->RxDescArray))
{
RTLD(bug("[%s] rtl8168nic_Open: Allocated Descriptor Arrays - Tx @ %p (%d bytes), Rx @ %p (%d bytes)\n", unit->rtl8168u_name,
np->TxDescArray, R8168_TX_RING_BYTES,
np->RxDescArray, R8168_RX_RING_BYTES))
if (rtl8168nic_InitRings(unit) == 0)
{
rtl8168nic_HWStart(unit);
// if (np->esd_flag == 0) {
// rtl8168_request_esd_timer(unit);
// }
// rtl8168_request_link_timer(unit);
rtl8168nic_DSM(unit, DSM_IF_UP);
rtl8168_CheckLinkStatus(unit);
}
else
{
RTLD(bug("[%s] rtl8168nic_Open: Failed to initialise Descriptor Arrays!\n",unit->rtl8168u_name))
}
}
else
{
RTLD(bug("[%s] rtl8168nic_Open: Failed to Allocate Descriptor Arrays!\n",unit->rtl8168u_name))
}
return 0;
out_drain:
drain_ring(unit);
return ret;
}
static int rtl8168nic_Close(struct net_device *unit)
{
struct rtl8168_priv *np = get_pcnpriv(unit);
RTLD(bug("[%s] rtl8168nic_Close()\n", unit->rtl8168u_name))
unit->rtl8168u_flags &= ~IFF_UP;
ObtainSemaphore(&np->lock);
// np->in_shutdown = 1;
ReleaseSemaphore(&np->lock);
unit->rtl8168u_toutNEED = FALSE;
netif_stop_queue(unit);
ObtainSemaphore(&np->lock);
rtl8168nic_DeInit(unit);
ReleaseSemaphore(&np->lock);
free_irq(unit);
drain_ring(unit);
// HIDD_PCIDriver_FreePCIMem(unit->rtl8168u_PCIDriver, np->rx_buffer);
// HIDD_PCIDriver_FreePCIMem(unit->rtl8168u_PCIDriver, np->tx_buffer);
ReportEvents(LIBBASE, unit, S2EVENT_OFFLINE);
return 0;
}
void rtl8168nic_get_functions(struct net_device *Unit)
{
Unit->initialize = rtl8168nic_Init;
Unit->deinitialize = rtl8168nic_DeInit;
Unit->start = rtl8168nic_Open;
Unit->stop = rtl8168nic_Close;
Unit->set_mac_address = rtl8168nic_SetMACAddr;
Unit->set_multicast = rtl8168nic_SetMulticast;
}