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

📄 3c59x.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
static struct device *vortex_probe1(int pci_bus, int pci_devfn,									struct device *dev, long ioaddr,									int irq, int chip_idx, int card_idx){	struct vortex_private *vp;	int option;	unsigned int eeprom[0x40], checksum = 0;		/* EEPROM contents */	int i;	dev = init_etherdev(dev, 0);	printk(KERN_INFO "%s: 3Com %s at 0x%lx, ",		   dev->name, pci_tbl[chip_idx].name, ioaddr);	dev->base_addr = ioaddr;	dev->irq = irq;	dev->mtu = mtu;	/* Make certain the descriptor lists are aligned. */	{		void *mem = kmalloc(sizeof(*vp) + 15, GFP_KERNEL);		vp =  (void *)(((long)mem + 15) & ~15);		vp->priv_addr = mem;	}	memset(vp, 0, sizeof(*vp));	dev->priv = vp;	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;	/* The lower four bits are the media type. */	if (dev->mem_start)		option = dev->mem_start;	else if (card_idx < MAX_UNITS)		option = options[card_idx];	else		option = -1;	if (option >= 0) {		vp->media_override = ((option & 7) == 2)  ?  0  :  option & 7;		vp->full_duplex = (option & 8) ? 1 : 0;		vp->bus_master = (option & 16) ? 1 : 0;	} else {		vp->media_override = 7;		vp->full_duplex = 0;		vp->bus_master = 0;	}	if (card_idx < MAX_UNITS  &&  full_duplex[card_idx] > 0)		vp->full_duplex = 1;	vp->force_fd = vp->full_duplex;	vp->options = option;	/* Read the station address from the EEPROM. */	EL3WINDOW(0);	for (i = 0; i < 0x40; i++) {		int timer;#ifdef CARDBUS		outw(0x230 + i, ioaddr + Wn0EepromCmd);#else		outw(EEPROM_Read + i, ioaddr + Wn0EepromCmd);#endif		/* Pause for at least 162 us. for the read to take place. */		for (timer = 10; timer >= 0; timer--) {			udelay(162);			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)		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]);#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 || dev->irq >= NR_IRQS))		printk(KERN_WARNING " *** Warning: IRQ %d is unlikely to work! ***\n",			   dev->irq);#endif	if (pci_tbl[vp->chip_id].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,								  &fn_st_addr);		if (fn_st_addr)			vp->cb_fn_base = ioremap(fn_st_addr & ~3, 128);		printk("%s: CardBus functions mapped %8.8x->%p (PCMCIA committee"			   " brain-damage).\n", dev->name, fn_st_addr, vp->cb_fn_base);		EL3WINDOW(2);		outw(0x10 | inw(ioaddr + Wn2_ResetOptions), ioaddr + Wn2_ResetOptions);	}	/* Extract our information from the EEPROM data. */	vp->info1 = eeprom[13];	vp->info2 = eeprom[15];	vp->capabilities = eeprom[16];	if (vp->info1 & 0x8000)		vp->full_duplex = 1;	{		char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};		union wn3_config config;		EL3WINDOW(3);		vp->available_media = inw(ioaddr + Wn3_Options);		if ((vp->available_media & 0xff) == 0)		/* Broken 3c916 */			vp->available_media = 0x40;		config.i = inl(ioaddr + Wn3_Config);		if (vortex_debug > 1)			printk(KERN_DEBUG "  Internal config register is %4.4x, "				   "transceivers %#x.\n", config.i, inw(ioaddr + Wn3_Options));		printk(KERN_INFO "  %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",			   8 << config.u.ram_size,			   config.u.ram_width ? "word" : "byte",			   ram_split[config.u.ram_split],			   config.u.autoselect ? "autoselect/" : "",			   config.u.xcvr > XCVR_ExtMII ? "<invalid transceiver>" :			   media_tbl[config.u.xcvr].name);		vp->default_media = config.u.xcvr;		vp->autoselect = config.u.autoselect;	}	if (vp->media_override != 7) {		printk(KERN_INFO "  Media override to transceiver type %d (%s).\n",			   vp->media_override, media_tbl[vp->media_override].name);		dev->if_port = vp->media_override;	} else		dev->if_port = vp->default_media;	if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) {		int phy, phy_idx = 0;		EL3WINDOW(4);		mii_preamble_required++;		mii_preamble_required++;		mdio_read(ioaddr, 24, 1);		for (phy = 1; phy <= 32 && phy_idx < sizeof(vp->phys); phy++) {			int mii_status, phyx = phy & 0x1f;			mii_status = mdio_read(ioaddr, phyx, 1);			if (mii_status  &&  mii_status != 0xffff) {				vp->phys[phy_idx++] = phyx;				printk(KERN_INFO "  MII transceiver found at address %d,"					   " status %4x.\n", phyx, mii_status);				if ((mii_status & 0x0040) == 0)					mii_preamble_required++;			}		}		mii_preamble_required--;		if (phy_idx == 0) {			printk(KERN_WARNING"  ***WARNING*** No MII transceivers found!\n");			vp->phys[0] = 24;		} else {			vp->advertising = mdio_read(ioaddr, vp->phys[0], 4);			if (vp->full_duplex) {				/* Only advertise the FD media types. */				vp->advertising &= ~0x02A0;				mdio_write(ioaddr, vp->phys[0], 4, vp->advertising);			}		}	}	if (vp->capabilities & CapBusMaster) {		vp->full_bus_master_tx = 1;		printk(KERN_INFO"  Enabling bus-master transmits and %s receives.\n",			   (vp->info2 & 1) ? "early" : "whole-frame" );		vp->full_bus_master_rx = (vp->info2 & 1) ? 1 : 2;	}	/* We do a request_region() to register /proc/ioports info. */	request_region(ioaddr, pci_tbl[chip_idx].io_size, dev->name);	/* The 3c59x-specific entries in the device structure. */	dev->open = &vortex_open;	dev->hard_start_xmit = &vortex_start_xmit;	dev->stop = &vortex_close;	dev->get_stats = &vortex_get_stats;	dev->do_ioctl = &vortex_ioctl;	dev->set_multicast_list = &set_rx_mode;	return dev;}static intvortex_open(struct device *dev){	long ioaddr = dev->base_addr;	struct vortex_private *vp = (struct vortex_private *)dev->priv;	union wn3_config config;	int i;	/* Before initializing select the active media port. */	EL3WINDOW(3);	config.i = inl(ioaddr + Wn3_Config);	if (vp->media_override != 7) {		if (vortex_debug > 1)			printk(KERN_INFO "%s: Media override to transceiver %d (%s).\n",				   dev->name, vp->media_override,				   media_tbl[vp->media_override].name);		dev->if_port = vp->media_override;	} else if (vp->autoselect && pci_tbl[vp->chip_id].drv_flags & HAS_NWAY) {			dev->if_port = XCVR_NWAY;	} else if (vp->autoselect) {		/* Find first available media type, starting with 100baseTx. */		dev->if_port = XCVR_100baseTx;		while (! (vp->available_media & media_tbl[dev->if_port].mask))			dev->if_port = media_tbl[dev->if_port].next;	} else		dev->if_port = vp->default_media;	init_timer(&vp->timer);	vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait);	vp->timer.data = (unsigned long)dev;	vp->timer.function = &vortex_timer;		/* timer handler */	add_timer(&vp->timer);	if (vortex_debug > 1)		printk(KERN_DEBUG "%s: Initial media type %s.\n",			   dev->name, media_tbl[dev->if_port].name);	vp->full_duplex = vp->force_fd;	config.u.xcvr = dev->if_port;	outl(config.i, ioaddr + Wn3_Config);	if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) {		int mii_reg1, mii_reg5;		EL3WINDOW(4);		/* Read BMSR (reg1) only to clear old status. */		mii_reg1 = mdio_read(ioaddr, vp->phys[0], 1);		mii_reg5 = mdio_read(ioaddr, vp->phys[0], 5);		if (mii_reg5 == 0xffff  ||  mii_reg5 == 0x0000)			;					/* No MII device or no link partner report */		else if ((mii_reg5 & 0x0100) != 0	/* 100baseTx-FD */				 || (mii_reg5 & 0x00C0) == 0x0040) /* 10T-FD, but not 100-HD */			vp->full_duplex = 1;		if (vortex_debug > 1)			printk(KERN_INFO "%s: MII #%d status %4.4x, link partner capability %4.4x,"				   " setting %s-duplex.\n", dev->name, vp->phys[0],				   mii_reg1, mii_reg5, vp->full_duplex ? "full" : "half");		EL3WINDOW(3);	}	/* Set the full-duplex bit. */	outb(((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) |		 (dev->mtu > 1500 ? 0x40 : 0), ioaddr + Wn3_MAC_Ctrl);	if (vortex_debug > 1) {		printk(KERN_DEBUG "%s: vortex_open() InternalConfig %8.8x.\n",			dev->name, config.i);	}	outw(TxReset, ioaddr + EL3_CMD);	for (i = 2000; i >= 0 ; i--)		if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))			break;	outw(RxReset, ioaddr + EL3_CMD);	/* Wait a few ticks for the RxReset command to complete. */	for (i = 2000; i >= 0 ; i--)		if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))			break;	outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);	/* Use the now-standard shared IRQ implementation. */	if (request_irq(dev->irq, &vortex_interrupt, SA_SHIRQ, dev->name, dev)) {		return -EAGAIN;	}	if (vortex_debug > 1) {		EL3WINDOW(4);		printk(KERN_DEBUG "%s: vortex_open() irq %d media status %4.4x.\n",			   dev->name, dev->irq, inw(ioaddr + Wn4_Media));	}	/* Set the station address and mask in window 2 each time opened. */	EL3WINDOW(2);	for (i = 0; i < 6; i++)		outb(dev->dev_addr[i], ioaddr + i);	for (; i < 12; i+=2)		outw(0, ioaddr + i);	if (dev->if_port == XCVR_10base2)		/* Start the thinnet transceiver. We should really wait 50ms...*/		outw(StartCoax, ioaddr + EL3_CMD);	if (dev->if_port != XCVR_NWAY) {		EL3WINDOW(4);		outw((inw(ioaddr + Wn4_Media) & ~(Media_10TP|Media_SQE)) |			 media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);	}	/* Switch to the stats window, and clear all stats by reading. */	outw(StatsDisable, ioaddr + EL3_CMD);	EL3WINDOW(6);	for (i = 0; i < 10; i++)		inb(ioaddr + i);	inw(ioaddr + 10);	inw(ioaddr + 12);	/* New: On the Vortex we must also clear the BadSSD counter. */	EL3WINDOW(4);	inb(ioaddr + 12);	/* ..and on the Boomerang we enable the extra statistics bits. */	outw(0x0040, ioaddr + Wn4_NetDiag);	/* Switch to register set 7 for normal use. */	EL3WINDOW(7);	if (vp->full_bus_master_rx) { /* Boomerang bus master. */		vp->cur_rx = vp->dirty_rx = 0;		/* Initialize the RxEarly register as recommended. */		outw(SetRxThreshold + (1536>>2), ioaddr + EL3_CMD);		outl(0x0020, ioaddr + PktStatus);		if (vortex_debug > 2)			printk(KERN_DEBUG "%s:  Filling in the Rx ring.\n", dev->name);		for (i = 0; i < RX_RING_SIZE; i++) {			struct sk_buff *skb;			vp->rx_ring[i].next = cpu_to_le32(virt_to_bus(&vp->rx_ring[i+1]));			vp->rx_ring[i].status = 0;	/* Clear complete bit. */			vp->rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ | LAST_FRAG);			skb = dev_alloc_skb(PKT_BUF_SZ);			vp->rx_skbuff[i] = skb;			if (skb == NULL)				break;			/* Bad news!  */			skb->dev = dev;			/* Mark as being used by this device. */#if LINUX_VERSION_CODE >= 0x10300			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */			vp->rx_ring[i].addr = cpu_to_le32(virt_to_bus(skb->tail));#else			vp->rx_ring[i].addr = virt_to_bus(skb->data);#endif		}		/* Wrap the ring. */		vp->rx_ring[i-1].next = cpu_to_le32(virt_to_bus(&vp->rx_ring[0]));		outl(virt_to_bus(&vp->rx_ring[0]), ioaddr + UpListPtr);	}	if (vp->full_bus_master_tx) { 		/* Boomerang bus master Tx. */		dev->hard_start_xmit = &boomerang_start_xmit;		vp->cur_tx = vp->dirty_tx = 0;		outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); /* Room for a packet. */		/* Clear the Tx ring. */		for (i = 0; i < TX_RING_SIZE; i++)			vp->tx_skbuff[i] = 0;		outl(0, ioaddr + DownListPtr);	}	/* Set reciever mode: presumably accept b-case and phys addr only. */	set_rx_mode(dev);	outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */	vp->in_interrupt = 0;	dev->tbusy = 0;	dev->interrupt = 0;	dev->start = 1;	outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */	outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */	/* Allow status bits to be seen. */	vp->status_enable = SetStatusEnb | HostError|IntReq|StatsFull|TxComplete|		(vp->full_bus_master_tx ? DownComplete : TxAvailable) |		(vp->full_bus_master_rx ? UpComplete : RxComplete) |		(vp->bus_master ? DMADone : 0);	vp->intr_enable = SetIntrEnb | IntLatch | TxAvailable | RxComplete |		StatsFull | HostError | TxComplete | IntReq		| (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete;	outw(vp->status_enable, ioaddr + EL3_CMD);	/* Ack all pending events, and set active indicator mask. */	outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,		 ioaddr + EL3_CMD);

⌨️ 快捷键说明

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