📄 8139too.c
字号:
CSCR_LinkStatusBits = 0x0f000, CSCR_LinkDownOffCmd = 0x003c0, CSCR_LinkDownCmd = 0x0f3c0,};enum Cfg9346Bits { Cfg9346_Lock = 0x00, Cfg9346_Unlock = 0xC0,};enum NegotiationBits { AutoNegotiationEnable = 0x1000, AutoNegotiationRestart = 0x0200, 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 */ }, { "RTL-8101", 0x77, 0xf0fc0040, /* RTL8101 */ },};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; // 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]; atomic_t CRC32DoubleCheck_ERR;};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 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);//==========================================================================================unsigned long crc32_table[256];#define CRC32_POLY 0x04c11db7#define ReverseBit(data) ( ((data<<7)&0x80) | ((data<<5)&0x40) | ((data<<3)&0x20) | ((data<<1)&0x10) |\ ((data>>1)&0x08) | ((data>>3)&0x04) | ((data>>5)&0x02) | ((data>>7)&0x01) )//==========================================================================================void init_crc32( struct net_device *dev ){ 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -