⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 3c575_cb.c

📁 pcmcia source code
💻 C
📖 第 1 页 / 共 5 页
字号:
	Media_LnkBeat = 0x0800,};enum Window7 {					/* Window 7: Bus Master control. */	Wn7_MasterAddr = 0, Wn7_MasterLen = 6, Wn7_MasterStatus = 12,};/* Boomerang bus master control registers. */enum MasterCtrl {	PktStatus = 0x20, DownListPtr = 0x24, FragAddr = 0x28, FragLen = 0x2c,	DownBurstThresh=0x2a, DownPollRate = 0x2d, TxFreeThreshold = 0x2f,	UpPktStatus = 0x30, UpListPtr = 0x38,};/* The Rx and Tx descriptor lists.   Caution Alpha hackers: these types are 32 bits!  Note also the 8 byte   alignment contraint on tx_ring[] and rx_ring[]. */#define LAST_FRAG  0x80000000			/* Last Addr/Len pair in descriptor. */struct boom_rx_desc {	u32 next;					/* Last entry points to 0.   */	s32 status;	u32 addr;					/* Up to 63 addr/len pairs possible. */	s32 length;					/* Set LAST_FRAG to indicate last pair. */};/* Values for the Rx status entry. */enum rx_desc_status {	RxDComplete=0x00008000, RxDError=0x4000,	/* See boomerang_rx() for actual error bits */	IPChksumErr=1<<25, TCPChksumErr=1<<26, UDPChksumErr=1<<27,	IPChksumValid=1<<29, TCPChksumValid=1<<30, UDPChksumValid=1<<31,};struct boom_tx_desc {	u32 next;					/* Last entry points to 0.   */	s32 status;					/* bits 0:12 length, others see below.  */	u32 addr;	s32 length;};/* Values for the Tx status entry. */enum tx_desc_status {	CRCDisable=0x2000, TxDComplete=0x8000,	AddIPChksum=0x02000000, AddTCPChksum=0x04000000, AddUDPChksum=0x08000000,	TxIntrUploaded=0x80000000,		/* IRQ when in FIFO, but maybe not sent. */};/* Chip features we care about in vp->capabilities, read from the EEPROM. */enum ChipCaps { CapBusMaster=0x20, CapPwrMgmt=0x2000 };#define PRIV_ALIGN	15 	/* Required alignment mask */struct vortex_private {	/* The Rx and Tx rings should be quad-word-aligned. */	struct boom_rx_desc rx_ring[RX_RING_SIZE];	struct boom_tx_desc tx_ring[TX_RING_SIZE];	/* The addresses of transmit- and receive-in-place skbuffs. */	struct sk_buff* rx_skbuff[RX_RING_SIZE];	struct sk_buff* tx_skbuff[TX_RING_SIZE];	struct net_device *next_module;	void *priv_addr;	/* Keep the Rx and Tx variables grouped on their own cache lines. */	struct boom_rx_desc *rx_head_desc;	unsigned int cur_rx, dirty_rx;		/* Producer/consumer ring indices */	unsigned int rx_buf_sz;				/* Based on MTU+slack. */	struct boom_tx_desc *tx_desc_tail;	unsigned int cur_tx, dirty_tx;	struct sk_buff *tx_skb;		/* Packet being eaten by bus master ctrl.  */	long last_reset;	struct net_device_stats stats;	char *cb_fn_base;			/* CardBus function status addr space. */	int chip_id, drv_flags;	u8 pci_bus, pci_devfn;		/* PCI configuration space information. */	/* The remainder are related to chip state, mostly media selection. */	struct timer_list timer;	/* Media selection timer. */	int options;				/* User-settable misc. driver options. */	unsigned int media_override:4, 			/* Passed-in media type. */		default_media:4,				/* Read from the EEPROM/Wn3_Config. */		full_duplex:1, medialock:1, autoselect:1,		bus_master:1,				/* Vortex can only do a fragment bus-m. */		full_bus_master_tx:1, full_bus_master_rx:2, /* Boomerang  */		hw_csums:1,				/* Has hardware checksums. */		tx_full:1, restart_tx:1,		open:1, reap:1,		polling:1;	u16 status_enable;	u16 intr_enable;	u16 available_media;				/* From Wn3_Options. */	u16 capabilities, info1, info2;		/* Various, from EEPROM. */	u16 advertising;					/* NWay media advertisement */	unsigned char phys[2];				/* MII device addresses. */	u16 deferred_irqs;	spinlock_t lock;};/* The action to take with a media selection timer tick.   Note that we deviate from the 3Com order by checking 10base2 before AUI. */enum xcvr_types {	XCVR_10baseT=0, XCVR_AUI, XCVR_10baseTOnly, XCVR_10base2, XCVR_100baseTx,	XCVR_100baseFx, XCVR_MII=6, XCVR_NWAY=8, XCVR_ExtMII=9, XCVR_Default=10,};static struct media_table {	char *name;	unsigned int media_bits:16,		/* Bits to set in Wn4_Media register. */		mask:8,				/* The transceiver-present bit in Wn3_Config.*/		next:8;				/* The media type to try next. */	int wait;			/* Time before we check media status. */} media_tbl[] = {  {	"10baseT",   Media_10TP,0x08, XCVR_10base2, (14*HZ)/10},  { "10Mbs AUI", Media_SQE, 0x20, XCVR_Default, (1*HZ)/10},  { "undefined", 0,			0x80, XCVR_10baseT, 10000},  { "10base2",   0,			0x10, XCVR_AUI,		(1*HZ)/10},  { "100baseTX", Media_Lnk, 0x02, XCVR_100baseFx, (14*HZ)/10},  { "100baseFX", Media_Lnk, 0x04, XCVR_MII,		(14*HZ)/10},  { "MII",		 0,			0x41, XCVR_10baseT, 3*HZ },  { "undefined", 0,			0x01, XCVR_10baseT, 10000},  { "Autonegotiate", 0,		0x41, XCVR_10baseT, 3*HZ},  { "MII-External",	 0,		0x41, XCVR_10baseT, 3*HZ },  { "Default",	 0,			0xFF, XCVR_10baseT, 10000},};static void vortex_up(struct net_device *dev);static void vortex_down(struct net_device *dev);static int vortex_open(struct net_device *dev);static void set_media_type(struct net_device *dev);static void activate_xcvr(struct net_device *dev);static void start_operation(struct net_device *dev);static void mdio_sync(long ioaddr, int bits);static int mdio_read(long ioaddr, int phy_id, int location);static void mdio_write(long ioaddr, int phy_id, int location, int value);static void vortex_timer(unsigned long arg);static void vortex_tx_timeout(struct net_device *dev);static int vortex_start_xmit(struct sk_buff *skb, struct net_device *dev);static int boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev);static int vortex_rx(struct net_device *dev);static int boomerang_rx(struct net_device *dev);static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs);static int vortex_close(struct net_device *dev);static void update_stats(long ioaddr, struct net_device *dev);static struct net_device_stats *vortex_get_stats(struct net_device *dev);static void set_rx_mode(struct net_device *dev);static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);static void acpi_wake(int pci_bus, int pci_devfn);static void acpi_set_WOL(struct net_device *dev);/* A list of all installed Vortex devices, for removing the driver module. */static struct net_device *root_vortex_dev = NULL;#include <pcmcia/driver_ops.h>static void vortex_reap(void){	struct net_device **devp, **next;	for (devp = &root_vortex_dev; *devp; devp = next) {		struct vortex_private *vp = (*devp)->priv;		next = &vp->next_module;		if (vp->open || !vp->reap) continue;		unregister_netdev(*devp);		if (vp->cb_fn_base) iounmap(vp->cb_fn_base);		kfree(*devp);		*devp = *next; next = devp;		kfree(vp->priv_addr);	}}static dev_node_t *vortex_attach(dev_locator_t *loc){	u16 dev_id, vendor_id;	u32 io;	u8 bus, devfn, irq;	struct net_device *dev;	int chip_idx;	vortex_reap();	if (loc->bus != LOC_PCI) return NULL;	bus = loc->b.pci.bus; devfn = loc->b.pci.devfn;	pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io);	pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq);	pcibios_read_config_word(bus, devfn, PCI_VENDOR_ID, &vendor_id);	pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id);	printk(KERN_INFO "vortex_attach(device %02x:%02x.%d)\n",		   bus, PCI_SLOT(devfn), PCI_FUNC(devfn));	io &= ~3;	if (io == 0 || irq == 0) {		printk(KERN_ERR "The 3Com CardBus Ethernet interface was not "			   "assigned an %s.\n" KERN_ERR "  It will not be activated.\n",			   io == 0 ? "I/O address" : "IRQ");		return NULL;	}	for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)		if (vendor_id == pci_tbl[chip_idx].vendor_id			&& (dev_id & pci_tbl[chip_idx].device_id_mask) ==			pci_tbl[chip_idx].device_id)			break;	if (pci_tbl[chip_idx].vendor_id == 0) { 		/* Compiled out! */		printk(KERN_INFO "Unable to match chip type %4.4x %4.4x in "			   "vortex_attach().\n", vendor_id, dev_id);		return NULL;	}	dev = vortex_probe1(bus, devfn, NULL, io, irq, chip_idx, MAX_UNITS+1);	if (dev) {		dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL);		strcpy(node->dev_name, dev->name);		node->major = node->minor = 0;		node->next = NULL;		MOD_INC_USE_COUNT;		return node;	}	return NULL;}static void vortex_detach(dev_node_t *node){	struct net_device *dev, *next;	printk(KERN_DEBUG "vortex_detach(%s)\n", node->dev_name);	for (dev = root_vortex_dev; dev; dev = next) {		next = ((struct vortex_private *)dev->priv)->next_module;		if (strcmp(dev->name, node->dev_name) == 0) break;	}	if (dev && dev->priv) {		struct vortex_private *vp = dev->priv;		netif_device_detach(dev);		if (vp->open) vortex_down(dev);		vp->reap = 1;		kfree(node);		MOD_DEC_USE_COUNT;	}}static void vortex_suspend(dev_node_t *node){	struct net_device *dev, *next;	printk(KERN_DEBUG "vortex_suspend(%s)\n", node->dev_name);	for (dev = root_vortex_dev; dev; dev = next) {		next = ((struct vortex_private *)dev->priv)->next_module;		if (strcmp(dev->name, node->dev_name) == 0) break;	}	if (dev && dev->priv) {		struct vortex_private *vp = (struct vortex_private *)dev->priv;		netif_device_detach(dev);		if (vp->open) vortex_down(dev);	}}static void vortex_resume(dev_node_t *node){	struct net_device *dev, *next;	printk(KERN_DEBUG "vortex_resume(%s)\n", node->dev_name);	for (dev = root_vortex_dev; dev; dev = next) {		next = ((struct vortex_private *)dev->priv)->next_module;		if (strcmp(dev->name, node->dev_name) == 0) break;	}	if (dev && dev->priv) {		struct vortex_private *vp = (struct vortex_private *)dev->priv;		if (vp->open) vortex_up(dev);		netif_device_attach(dev);	}}struct driver_operations vortex_ops = {	"3c575_cb", vortex_attach, vortex_suspend, vortex_resume, vortex_detach};int init_module(void){	if (debug)		printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);	register_driver(&vortex_ops);	return 0;}static struct net_device *vortex_probe1(int pci_bus, int pci_devfn,									struct net_device *dev, long ioaddr,									int irq, int chip_idx, int find_cnt){	struct vortex_private *vp;	void *priv_mem;	int option;	unsigned int eeprom[0x40], checksum = 0;		/* EEPROM contents */	int drv_flags = pci_tbl[chip_idx].drv_flags;	int i, step;	dev = init_etherdev(dev, 0);	printk(KERN_INFO "%s: 3Com %s at 0x%lx,",		   dev->name, pci_tbl[chip_idx].name, ioaddr);	/* Make certain elements e.g. descriptor lists are aligned. */	priv_mem = kmalloc(sizeof(*vp) + PRIV_ALIGN, GFP_KERNEL);	/* Check for the very unlikely case of no memory. */	if (priv_mem == NULL) {		printk(" INTERFACE MEMORY ALLOCATION FAILURE.\n");		return NULL;	}	dev->base_addr = ioaddr;	dev->irq = irq;	dev->mtu = mtu;	dev->priv = vp = (void *)(((long)priv_mem + PRIV_ALIGN) & ~PRIV_ALIGN);	memset(vp, 0, sizeof(*vp));	vp->lock = SPIN_LOCK_UNLOCKED;	vp->priv_addr = priv_mem;	vp->next_module = root_vortex_dev;	root_vortex_dev = dev;	vp->chip_id = chip_idx;	vp->pci_bus = pci_bus;	vp->pci_devfn = pci_devfn;	vp->drv_flags = drv_flags;	/* The lower four bits are the media type. */	if (dev->mem_start)		option = dev->mem_start;	else if (find_cnt < MAX_UNITS)		option = options[find_cnt];	else		option = -1;	if (option >= 0) {		vp->media_override = ((option & 7) == 2)  ?  0  :  option & 15;		vp->full_duplex = (option & 0x200) ? 1 : 0;		vp->bus_master = (option & 16) ? 1 : 0;	} else {		vp->media_override = 7;		vp->full_duplex = 0;		vp->bus_master = 0;	}	if (find_cnt < MAX_UNITS  &&  full_duplex[find_cnt] > 0)		vp->full_duplex = 1;	if (vp->full_duplex)		vp->medialock = 1;	vp->options = option;	/* Read the station address from the EEPROM. */	EL3WINDOW(0);	for (i = 0; i < 0x40; i++) {		int timer;		outw((drv_flags & EEPROM_8BIT ? 0x230 : EEPROM_Read) + i,			 ioaddr + Wn0EepromCmd);		/* The read may take up to 162 usec, timed with PCI cycles. */		for (timer = 162*5; timer >= 0; timer--) {			if ((inw(ioaddr + Wn0EepromCmd) & 0x8000) == 0)				break;		}		eeprom[i] = inw(ioaddr + Wn0EepromData);	}	for (i = 0; i < 0x18; i++)		checksum ^= eeprom[i];	checksum = (checksum ^ (checksum >> 8)) & 0xff;	if (checksum != 0x00) {		/* Grrr, needless incompatible change 3Com. */		while (i < 0x21)			checksum ^= eeprom[i++];		checksum = (checksum ^ (checksum >> 8)) & 0xff;	}	if (checksum != 0x00  &&  !(drv_flags & IS_TORNADO))		printk(" ***INVALID CHECKSUM %4.4x*** ", checksum);	for (i = 0; i < 3; i++)		((u16 *)dev->dev_addr)[i] = htons(eeprom[i + 10]);	for (i = 0; i < 6; i++)		printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i]);	EL3WINDOW(2);	for (i = 0; i < 6; i++)		outb(dev->dev_addr[i], ioaddr + i);#ifdef __sparc__	printk(", irq %s\n", __irq_itoa(dev->irq));#else	printk(", irq %d\n", dev->irq);	/* Tell them about an invalid IRQ. */	if (vortex_debug && (dev->irq <= 0))		printk(KERN_WARNING " *** Warning: IRQ %d is unlikely to work! ***\n",			   dev->irq);#endif	EL3WINDOW(4);	step = (inb(ioaddr + Wn4_NetDiag) & 0x1e) >> 1;	printk(KERN_INFO "  product code '%c%c' rev %02x.%d date %02d-"		   "%02d-%02d\n", eeprom[6]&0xff, eeprom[6]>>8, eeprom[0x14],		   step, (eeprom[4]>>5) & 15, eeprom[4] & 31, eeprom[4]>>9);	if ((eeprom[0x14] == 0x07) && (step == 1))		vp->drv_flags = drv_flags |= HAS_FIFO_BUG;	if (drv_flags & HAS_CB_FNS) {		u32 fn_st_addr;			/* Cardbus function status space */		pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_2,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -