📄 8139too.c
字号:
{
int i, j;
unsigned long c;
unsigned char *p=(unsigned char *)&c, *p1;
unsigned char k;
struct rtl8139_private *tp = dev->priv;
;
atomic_set( &tp->CRC32DoubleCheck_ERR, 0 );
c = 0x12340000;
for (i = 0; i < 256; ++i)
{
k = ReverseBit((unsigned char)i);
for (c = ((unsigned long)k) << 24, j = 8; j > 0; --j)
c = c & 0x80000000 ? (c << 1) ^ CRC32_POLY : (c << 1);
p1 = (unsigned char *)(&crc32_table[i]);
p1[0] = ReverseBit(p[3]);
p1[1] = ReverseBit(p[2]);
p1[2] = ReverseBit(p[1]);
p1[3] = ReverseBit(p[0]);
}
}
unsigned long crc32(unsigned char *buf, int len)
{
unsigned char *p;
unsigned long crc;
crc = 0xffffffff; /* preload shift register, per CRC-32 spec */
for (p = buf; len > 0; ++p, --len)
{
crc = crc32_table[ (crc ^ *p) & 0xff] ^ (crc >> 8);
}
return ~crc; /* transmit complement, per CRC-32 spec */
}
//int DoubleCheck( &rx_ring[ring_offset + 4], pkt_size )
//----------------------------------------------------------------------
// rx_data_ptr : the start pointer of the received data
// pkt_size : the received data length excluding 4-bytes CRC
//----------------------------------------------------------------------
static inline int CRC32DoubleCheck( unsigned char *rx_data_ptr, unsigned int pkt_size )
{
unsigned short EtherType = *( (unsigned short *)(rx_data_ptr + 12) );
unsigned char IPType = *(rx_data_ptr + 23);
unsigned long SWCRC = 0xffffffff;
unsigned long HWCRC;
//----------------------------------------------------------------------
// If this is the packet of type TCP/IP, skip CRC32 double-check.
//----------------------------------------------------------------------
if( (EtherType == 0x0008) && (IPType == 0x06) )
{
return 0;
}
HWCRC = *( (unsigned long *)(rx_data_ptr + pkt_size) );
SWCRC = crc32( rx_data_ptr, pkt_size );
// printk(KERN_INFO "RTL8139: %s( pkt_size = %d, EtherType = 0x%4.4x, IPType = 0x%2.2x). HWCRC = 0x%8.8lx, SWCRC = 0x%8.8lx\n",
// __FUNCTION__, pkt_size, EtherType, IPType, HWCRC, SWCRC );
return ( (SWCRC == HWCRC) ? 0 : -1 );
}
#ifdef RTL8139_PROC_DEBUG
//==========================================================================================
struct proc_dir_entry *rtl8139_Proc_root;
struct proc_dir_entry *rtl8139_Proc;
static int rtl8139_proc_status(char *buffer,
char **buffer_location,
off_t offset,
int buffer_length,
int *eof,
void *data)
{
char *buf = buffer;
struct net_device *dev = (struct net_device *)data;
buf += sprintf( buf, " ************ Current driver status ************\n\n\n" );
buf += sprintf( buf, " MAC address = %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5] );
buf += sprintf( buf, " ioaddr = 0x%8.8lx\n", (unsigned long)dev->base_addr );
buf += sprintf( buf, " irq = %d\n", dev->irq );
return (buf - buffer);
}
static void rtl8139_init_proc(struct net_device *dev)
{
if(rtl8139_Proc_root == NULL)
rtl8139_Proc_root = proc_mkdir("rtl8139", NULL);
if(rtl8139_Proc_root != NULL)
{
rtl8139_Proc = create_proc_read_entry(
"status",0644, rtl8139_Proc_root, rtl8139_proc_status, (void *)dev);
}
}
static void rtl8139_remove_proc(struct net_device *dev)
{
if(rtl8139_Proc_root != NULL)
{
remove_proc_entry("status", rtl8139_Proc_root );
remove_proc_entry("rtl8139", NULL );
}
}
//==========================================================================================
#endif //#ifdef RTL8139_PROC_DEBUG
//------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------
static int __devinit rtl8139_init_board (struct pci_dev *pdev, struct net_device **dev_out, void **ioaddr_out)
{
void *ioaddr = NULL;
struct net_device *dev;
struct rtl8139_private *tp;
u8 tmp8;
int rc, i;
u32 pio_start, pio_end, pio_flags, pio_len;
unsigned long mmio_start, mmio_end, mmio_flags, mmio_len;
u32 tmp;
DPRINTK ("ENTER\n");
assert (pdev != NULL);
assert (ioaddr_out != NULL);
*ioaddr_out = NULL;
*dev_out = NULL;
/* dev zeroed in init_etherdev */
dev = init_etherdev (NULL, sizeof (*tp));
if (dev == NULL)
{
printk (KERN_ERR PFX "unable to alloc new ethernet\n");
DPRINTK ("EXIT, returning -ENOMEM\n");
return -ENOMEM;
}
SET_MODULE_OWNER(dev);
tp = dev->priv;
/* enable device (incl. PCI PM wakeup and hotplug setup) */
rc = pci_enable_device (pdev);
if (rc)
goto err_out;
//不知道是否是使用mm io 还是端口io
pio_start = pci_resource_start (pdev, 0);
pio_end = pci_resource_end (pdev, 0);
pio_flags = pci_resource_flags (pdev, 0);
pio_len = pci_resource_len (pdev, 0);
mmio_start = pci_resource_start (pdev, 1);
mmio_end = pci_resource_end (pdev, 1);
mmio_flags = pci_resource_flags (pdev, 1);
mmio_len = pci_resource_len (pdev, 1);
/* set this immediately, we need to know before
* we talk to the chip directly */
DPRINTK("PIO region size == 0x%02X\n", pio_len);
DPRINTK("MMIO region size == 0x%02lX\n", mmio_len);
if (pio_len == RTL8139B_IO_SIZE)
tp->chipset = CH_8139B;
/* make sure PCI base addr 0 is PIO */
if (!(pio_flags & IORESOURCE_IO))
{
printk (KERN_ERR PFX "region #0 not a PIO resource, aborting\n");
rc = -ENODEV;
goto err_out;
}
/* make sure PCI base addr 1 is MMIO */
if (!(mmio_flags & IORESOURCE_MEM))
{
printk (KERN_ERR PFX "region #1 not an MMIO resource, aborting\n");
rc = -ENODEV;
goto err_out;
}
/* check for weird/broken PCI region reporting */
if ((pio_len < RTL_MIN_IO_SIZE) ||
(mmio_len < RTL_MIN_IO_SIZE))
{
printk (KERN_ERR PFX "Invalid PCI region size(s), aborting\n");
rc = -ENODEV;
goto err_out;
}
#ifndef USE_IO_OPS
rc = pci_request_regions (pdev, dev->name);
if (rc)
goto err_out;
#endif /* !USE_IO_OPS */
/* enable PCI bus-mastering */
pci_set_master (pdev);
//如果使用io空间
#ifdef USE_IO_OPS
ioaddr = (void *) pio_start;
printk ("%s: use pci IO map. ioaddr=0x%08lx\n", dev->name, (unsigned long)ioaddr);
#else
/* ioremap MMIO region */
ioaddr = ioremap (mmio_start, mmio_len);
if (ioaddr == NULL)
{
printk (KERN_ERR PFX "cannot remap MMIO, aborting\n");
rc = -EIO;
goto err_out_free_res;
}
printk ("%s: use memory map. ioaddr=0x%08lx\n", dev->name, (unsigned long)ioaddr);
#endif /* USE_IO_OPS */
/* Soft reset the chip. */
RTL_W8 (ChipCmd, (RTL_R8 (ChipCmd) & ChipCmdClear) | CmdReset);
/* Check that the chip has finished the reset. */
for (i = 1000; i > 0; i--)
if ((RTL_R8 (ChipCmd) & CmdReset) == 0)
break;
else
udelay (10);
/* Bring the chip out of low-power mode. */
if (tp->chipset == CH_8139B)
{
RTL_W8 (Config1, RTL_R8 (Config1) & ~(1<<4));
RTL_W8 (Config4, RTL_R8 (Config4) & ~(1<<2));
}
else
{
/* handle RTL8139A and RTL8139 cases */
/* XXX from becker driver. is this right?? */
RTL_W8 (Config1, 0);
}
/* make sure chip thinks PIO and MMIO are enabled */
tmp8 = RTL_R8 (Config1);
if ((tmp8 & Cfg1_PIO) == 0)
{
printk (KERN_ERR PFX "PIO not enabled, Cfg1=%02X, aborting\n", tmp8);
rc = -EIO;
goto err_out_iounmap;
}
if ((tmp8 & Cfg1_MMIO) == 0)
{
printk (KERN_ERR PFX "MMIO not enabled, Cfg1=%02X, aborting\n", tmp8);
rc = -EIO;
goto err_out_iounmap;
}
/* identify chip attached to board */
// tmp = RTL_R8 (ChipVersion);
tmp = RTL_R32 (TxConfig);
tmp = ( (tmp&0x7c000000) + ( (tmp&0x00C00000)<<2 ) )>>24;
for (i = ARRAY_SIZE (rtl_chip_info) - 1; i >= 0; i--)
if (tmp == rtl_chip_info[i].version)
{
tp->chipset = i;
goto match;
}
/* if unknown chip, assume array element #0, original RTL-8139 in this case */
printk (KERN_DEBUG PFX "PCI device %s: unknown chip version, assuming RTL-8139\n",
pdev->slot_name);
printk (KERN_DEBUG PFX "PCI device %s: TxConfig = 0x%lx\n", pdev->slot_name, RTL_R32 (TxConfig));
tp->chipset = 0;
match:
#ifdef FORCE_CPlus_Mode
if(tp->chipset >= (ARRAY_SIZE (rtl_chip_info) - 2))
tp->chipset = ARRAY_SIZE (rtl_chip_info) - 1;
#endif
#ifdef FORCE_C_Mode
if(tp->chipset > (ARRAY_SIZE (rtl_chip_info) - 2))
tp->chipset = ARRAY_SIZE (rtl_chip_info) - 2;
#endif
DPRINTK ("chipset id (%d) == index %d, '%s'\n",
tmp,
tp->chipset,
rtl_chip_info[tp->chipset].name);
DPRINTK ("EXIT, returning 0\n");
*ioaddr_out = ioaddr;
*dev_out = dev;
return 0;
err_out_iounmap:
assert (ioaddr > 0);
#ifndef USE_IO_OPS
iounmap (ioaddr);
err_out_free_res:
pci_release_regions (pdev);
#endif /* !USE_IO_OPS */
err_out:
unregister_netdev (dev);
kfree (dev);
DPRINTK ("EXIT, returning %d\n", rc);
return rc;
}
static int __devinit rtl8139_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct net_device *dev = NULL;
struct rtl8139_private *tp;
int i, addr_len, option;
void *ioaddr = NULL;
static int board_idx = -1;
static int printed_version;
u8 tmp;
DPRINTK ("ENTER\n");
assert (pdev != NULL);
assert (ent != NULL);
board_idx++;
if (!printed_version)
{
printk (KERN_INFO RTL8139_DRIVER_NAME " loaded\n");
printed_version = 1;
}
i = rtl8139_init_board (pdev, &dev, &ioaddr);
if (i < 0)
{
DPRINTK ("EXIT, returning %d\n", i);
return i;
}
tp = dev->priv;
assert (ioaddr != NULL);
assert (dev != NULL);
assert (tp != NULL);
init_crc32( dev );
addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6;
for (i = 0; i < 3; i++)
((u16 *) (dev->dev_addr))[i] =
le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len));
/* The Rtl8139-specific entries in the device structure. */
if( rtl_chip_info[tp->chipset].name == "RTL-8139CP" )
{
dev->open = rtl8139CP_open;
dev->hard_start_xmit = rtl8139CP_start_xmit;
dev->stop = rtl8139CP_close;
dev->tx_timeout = rtl8139CP_tx_timeout;
dev->features |= NETIF_F_IP_CSUM; /* Can checksum only TCP/UDP over IPv4. */
printk (KERN_DEBUG "%s: Identified 8139CP chip type '%s'. Support TCP/UDP checksumOffload\n",dev->name,rtl_chip_info[tp->chipset].name);
}
else
{
dev->open = rtl8139_open;
dev->hard_start_xmit = rtl8139_start_xmit;
dev->stop = rtl8139_close;
dev->tx_timeout = rtl8139_tx_timeout;
printk (KERN_DEBUG "%s: Identified 8139CP chip type '%s'\n", dev->name, rtl_chip_info[tp->chipset].name);
}
dev->get_stats = rtl8139_get_stats;
dev->set_multicast_list = rtl8139_set_rx_mode;
dev->do_ioctl = mii_ioctl;
dev->watchdog_timeo = TX_TIMEOUT;
dev->irq = pdev->irq;
dev->base_addr = (unsigned long) ioaddr;
/* dev->priv/tp zeroed and aligned in init_etherdev */
tp = dev->priv;
/* note: tp->chipset set in rtl8139_init_board */
tp->drv_flags = board_info[ent->driver_data].hw_flags;
tp->pci_dev = pdev;
tp->mmio_addr = ioaddr;
spin_lock_init (&tp->lock)
;
pdev->driver_data = dev;
printk (KERN_INFO "%s: %s at 0x%lx, "
"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
"IRQ %d\n",
dev->name,
board_info[ent->driver_data].name,
dev->base_addr,
dev->dev_addr[0], dev->dev_addr[1],
dev->dev_addr[2], dev->dev_addr[3],
dev->dev_addr[4], dev->dev_addr[5],
dev->irq);
// dev->tx_queue_len=500;
/* Find the connected MII xcvrs.
Doing this in open() would allow detecting external xcvrs later, but
takes too much time. */
if (tp->drv_flags & HAS_MII_XCVR)
{
int phy, phy_idx = 0;
for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++)
{
int mii_status = mdio_read(dev, phy, 1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -