📄 8139too.c
字号:
AutoNegoAbility10half = 0x21, AutoNegoAbility10full = 0x41, AutoNegoAbility100half = 0x81, AutoNegoAbility100full = 0x101,};enum MediaStatusBits { DuplexMode = 0x0100, //in BasicModeControlRegister Speed_10 = 0x08, //in Media Status Register};#define PARA78_default 0x78fa8388#define PARA7c_default 0xcb38de43 /* param[0][3] */#define PARA7c_xxx 0xcb38de43static const unsigned long param[4][4] = { {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83}};struct ring_info { struct sk_buff *skb; dma_addr_t mapping;};typedef enum { CH_8139 = 0, CH_8139_K, CH_8139A, CH_8139B, CH_8130, CH_8139C, CH_8139CP,} chip_t;/* directly indexed by chip_t, above */const static struct { const char *name; u8 version; /* from RTL8139C docs */ u32 RxConfigMask; /* should clear the bits supported by this chip */} rtl_chip_info[] = { { "RTL-8139", 0x40, 0xf0fe0040, /* XXX copied from RTL8139A, verify */ }, { "RTL-8139 rev K", 0x60, 0xf0fe0040, }, { "RTL-8139A", 0x70, 0xf0fe0040, }, { "RTL-8139B", 0x78, 0xf0fc0040 }, { "RTL-8130", 0x7C, 0xf0fe0040, /* XXX copied from RTL8139A, verify */ }, { "RTL-8139C", 0x74, 0xf0fc0040, /* XXX copied from RTL8139B, verify */ }, { "RTL-8139CP", 0x76, 0xf0fc0040, /* XXX copied from RTL8139B, verify */ },};struct CPlusTxDesc { u32 status; u32 vlan_tag; u32 buf_addr; u32 buf_Haddr;};struct CPlusRxDesc { u32 status; u32 vlan_tag; u32 buf_addr; u32 buf_Haddr;};/********************************************************************** */#define IP_PROTOCOL 0x0008 /* Network Byte order */#define TCP_PROTOCOL 6#define UDP_PROTOCOL 17#define ADDRESS_LEN 6struct ethernet_ii_header { uint8_t DestAddr[ADDRESS_LEN]; uint8_t SourceAddr[ADDRESS_LEN]; uint16_t TypeLength;};/********************************************************************** *//* Internet Protocol Version 4 (IPV4) Header Definition *//********************************************************************** */typedef struct _ip_v4_header_ { uint32_t HdrLength:4, /* Network Byte order */ HdrVersion:4, /* Network Byte order */ TOS:8, /* Network Byte order */ Length:16; /* Network Byte order */ union { uint32_t IdThruOffset; struct { uint32_t DatagramId:16, FragOffset1:5, /* Network Byte order */ MoreFragments:1, NoFragment:1, Reserved2:1, FragOffset:8; } Bits; struct { uint32_t DatagramId:16, FragsNFlags:16; /* Network Byte order */ } Fields; } FragmentArea; uint8_t TimeToLive; uint8_t ProtocolCarried; uint16_t Checksum; union { uint32_t SourceIPAddress; struct { uint32_t SrcAddrLo:16, /* Network Byte order */ SrcAddrHi:16; } Fields; struct { uint32_t OctA:8, OctB:8, OctC:8, OctD:8; } SFields; } SrcAddr; union { uint32_t TargetIPAddress; struct { uint32_t DestAddrLo:16, /* Network Byte order */ DestAddrHi:16; } Fields; struct { uint32_t OctA:8, OctB:8, OctC:8, OctD:8; } DFields; } DestAddr; uint16_t IpOptions[20]; /* Maximum of 40 bytes (20 words) of IP options */} ip_v4_header;/********************************************************************** */struct rtl8139_private { void *mmio_addr; int drv_flags; struct pci_dev *pci_dev; struct net_device_stats stats; unsigned char *rx_ring; unsigned int cur_rx; /* Index into the Rx buffer of next Rx pkt. */ unsigned int tx_flag; unsigned long cur_tx; unsigned long dirty_tx; /* The saved address of a sent-in-place packet/buffer, for skfree(). */ struct ring_info tx_info[NUM_TX_DESC]; unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ unsigned char *tx_bufs; /* Tx bounce buffer region. */ dma_addr_t rx_ring_dma; dma_addr_t tx_bufs_dma; signed char phys[4]; /* MII device addresses. */ u16 advertising; /* NWay media advertisement */ char twistie, twist_row, twist_col; /* Twister tune state. */ unsigned int full_duplex:1; /* Full-duplex operation requested. */ unsigned int duplex_lock:1; unsigned int default_port:4; /* Last dev->if_port value. */ unsigned int media2:4; /* Secondary monitored media port. */ unsigned int medialock:1; /* Don't sense media type. */ unsigned int mediasense:1; /* Media sensing in progress. */ spinlock_t lock; chip_t chipset; pid_t thr_pid; wait_queue_head_t thr_wait;#if LINUX_VERSION_CODE < 0x20407 struct semaphore thr_exited; #else struct completion thr_exited;#endif // For 8139C+ int AutoNegoAbility; unsigned long CP_cur_tx; unsigned long CP_dirty_tx; unsigned long CP_cur_rx; unsigned char *TxDescArrays; unsigned char *RxDescArrays; struct CPlusTxDesc *TxDescArray; struct CPlusRxDesc *RxDescArray; unsigned char *RxBufferRings; unsigned char *RxBufferRing[NUM_CP_RX_DESC]; struct sk_buff* Tx_skbuff[NUM_CP_TX_DESC];};MODULE_AUTHOR ("Jeff Garzik <jgarzik@mandrakesoft.com>");MODULE_DESCRIPTION ("RealTek RTL-8139CP Fast Ethernet driver");MODULE_PARM (multicast_filter_limit, "i");MODULE_PARM (max_interrupt_work, "i");MODULE_PARM (media, "1-" __MODULE_STRING(MAX_UNITS) "i");MODULE_PARM (full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");static int read_eeprom (void *ioaddr, int location, int addr_len);static int rtl8139CP_open (struct net_device *dev);static int rtl8139CP_start_xmit (struct sk_buff *skb, struct net_device *dev);static void rtl8139CP_interrupt (int irq, void *dev_instance, struct pt_regs *regs);static void rtl8139CP_init_ring (struct net_device *dev);static void rtl8139CP_hw_start (struct net_device *dev);static int rtl8139CP_close (struct net_device *dev); static void rtl8139CP_tx_timeout (struct net_device *dev);static int rtl8139_open (struct net_device *dev);static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev);static void rtl8139_interrupt (int irq, void *dev_instance, struct pt_regs *regs);static void rtl8139_init_ring (struct net_device *dev);static void rtl8139_hw_start (struct net_device *dev);static int rtl8139_close (struct net_device *dev); static void rtl8139_tx_timeout (struct net_device *dev);static int mdio_read (struct net_device *dev, int phy_id, int location);static void mdio_write (struct net_device *dev, int phy_id, int location, int val);static int rtl8139_thread (void *data);static int mii_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);static struct net_device_stats *rtl8139_get_stats (struct net_device *dev);static inline u32 ether_crc (int length, unsigned char *data);static void rtl8139_set_rx_mode (struct net_device *dev);#ifdef USE_IO_OPS#define RTL_R8(reg) inb (((unsigned long)ioaddr) + (reg))#define RTL_R16(reg) inw (((unsigned long)ioaddr) + (reg))#define RTL_R32(reg) ((unsigned long) inl (((unsigned long)ioaddr) + (reg)))#define RTL_W8(reg, val8) outb ((val8), ((unsigned long)ioaddr) + (reg))#define RTL_W16(reg, val16) outw ((val16), ((unsigned long)ioaddr) + (reg))#define RTL_W32(reg, val32) outl ((val32), ((unsigned long)ioaddr) + (reg))#define RTL_W8_F RTL_W8#define RTL_W16_F RTL_W16#define RTL_W32_F RTL_W32#undef readb#undef readw#undef readl#undef writeb#undef writew#undef writel#define readb(addr) inb((unsigned long)(addr))#define readw(addr) inw((unsigned long)(addr))#define readl(addr) inl((unsigned long)(addr))#define writeb(val,addr) outb((val),(unsigned long)(addr))#define writew(val,addr) outw((val),(unsigned long)(addr))#define writel(val,addr) outl((val),(unsigned long)(addr))#else/* write MMIO register, with flush *//* Flush avoids rtl8139 bug w/ posted MMIO writes */#define RTL_W8_F(reg, val8) do { writeb ((val8), ioaddr + (reg)); readb (ioaddr + (reg)); } while (0)#define RTL_W16_F(reg, val16) do { writew ((val16), ioaddr + (reg)); readw (ioaddr + (reg)); } while (0)#define RTL_W32_F(reg, val32) do { writel ((val32), ioaddr + (reg)); readl (ioaddr + (reg)); } while (0)#if MMIO_FLUSH_AUDIT_COMPLETE/* write 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))#else/* write MMIO register, then flush */#define RTL_W8 RTL_W8_F#define RTL_W16 RTL_W16_F#define RTL_W32 RTL_W32_F#endif /* MMIO_FLUSH_AUDIT_COMPLETE *//* read MMIO register */#define RTL_R8(reg) readb (ioaddr + (reg))#define RTL_R16(reg) readw (ioaddr + (reg))#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg)))#endif /* USE_IO_OPS */static const u16 rtl8139_intr_mask = PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK;static const unsigned int rtl8139_rx_config = RxCfgEarlyRxNone | RxCfgRcv32K | RxNoWrap | (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift);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; 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; } rc = pci_request_regions (pdev, dev->name); if (rc) goto err_out; /* enable PCI bus-mastering */ pci_set_master (pdev);#ifdef USE_IO_OPS ioaddr = (void *) pio_start;#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; }#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&0x00800000)<<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,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -