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

📄 3c575_cb.c

📁 pcmcia source code
💻 C
📖 第 1 页 / 共 5 页
字号:
								  &fn_st_addr);		if (fn_st_addr)			vp->cb_fn_base = ioremap(fn_st_addr & ~3, 128);		if (vortex_debug > 1)			printk(KERN_DEBUG "%s: CardBus functions mapped %8.8x->%p.\n",				   dev->name, fn_st_addr, vp->cb_fn_base);	}	/* 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;	/* Turn on the transceiver. */	activate_xcvr(dev);	{		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;				if (vortex_debug > 1)					printk(KERN_DEBUG "  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 & CapPwrMgmt)		acpi_set_WOL(dev);	if (vp->capabilities & CapBusMaster) {		vp->full_bus_master_tx = 1;		if (vortex_debug > 1)			printk(KERN_DEBUG "  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;#ifdef HAVE_TX_TIMEOUT	dev->tx_timeout = vortex_tx_timeout;	dev->watchdog_timeo = TX_TIMEOUT;#endif	return dev;}static void issue_and_wait(struct net_device *dev, int cmd){	int i = 2000;	outw(cmd, dev->base_addr + EL3_CMD);	while (--i > 0)		if (!(inw(dev->base_addr + EL3_STATUS) & CmdInProgress))			break;	if (i == 0)		printk(KERN_NOTICE "%s: command 0x%04x did not complete!\n",			   dev->name, cmd);}static voidvortex_up(struct net_device *dev){	struct vortex_private *vp = (struct vortex_private *)dev->priv;	long ioaddr = dev->base_addr;	int i;	acpi_wake(vp->pci_bus, vp->pci_devfn);	activate_xcvr(dev);	/* Before initializing select the active media port. */	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) {		if (vp->drv_flags & HAS_NWAY)			dev->if_port = XCVR_NWAY;		else {			/* 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;	if (! vp->medialock)		vp->full_duplex = 0;	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;	if (vortex_debug > 1)		printk(KERN_DEBUG "%s: Initial media type %s %s-duplex.\n",			   dev->name, media_tbl[dev->if_port].name,			   vp->full_duplex ? "full":"half");	set_media_type(dev);	start_operation(dev);	spin_lock(&vp->lock);	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));	}	/* 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);	spin_unlock(&vp->lock);	vp->tx_full = 0;	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);		for (i = 0; i < RX_RING_SIZE; i++)			vp->rx_ring[i].status = 0;		vp->rx_head_desc = &vp->rx_ring[0];		outl(virt_to_bus(vp->rx_head_desc), ioaddr + UpListPtr);	}	if (vp->full_bus_master_tx) { 		/* Boomerang bus master Tx. */		vp->cur_tx = vp->dirty_tx = 0;		vp->tx_desc_tail = &vp->tx_ring[TX_RING_SIZE - 1];		if ((vp->drv_flags & IS_BOOMERANG) || !down_poll_rate) {			/* Room for a packet, to avoid long DownStall delays. */			outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold);		} else			outb(down_poll_rate, ioaddr + DownPollRate);		/* Clear the Tx ring. */		for (i = 0; i < TX_RING_SIZE; i++)			vp->tx_skbuff[i] = 0;		outl(0, ioaddr + DownListPtr);		vp->restart_tx = 1;	}	/* Set receiver mode: presumably accept b-cast and phys addr only. */	set_rx_mode(dev);	outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */	if (vp->drv_flags & HAS_FIFO_BUG) /* max out the tx fifo threshold */		outb(0x1f, ioaddr + DownBurstThresh);	outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */	outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */	/* Allow status bits to be seen. */	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);	outw(vp->intr_enable, ioaddr + EL3_CMD);	if (vp->cb_fn_base)			/* The PCMCIA people are idiots.  */		writel(0x8000, vp->cb_fn_base + 4);	init_timer(&vp->timer);	vp->timer.expires = jiffies + media_tbl[dev->if_port].wait;	vp->timer.data = (unsigned long)dev;	vp->timer.function = &vortex_timer;		/* timer handler */	add_timer(&vp->timer);}static void set_media_type(struct net_device *dev){	struct vortex_private *vp = (struct vortex_private *)dev->priv;	long ioaddr = dev->base_addr;	union wn3_config config;	EL3WINDOW(3);	config.i = inl(ioaddr + Wn3_Config);	config.u.xcvr = dev->if_port;	if ( ! (vp->drv_flags & HAS_NWAY))		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 {			mii_reg5 &= vp->advertising;			if ((mii_reg5 & 0x0100) ||	/* 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");		if (!auto_polarity) {			/* works for TDK 78Q2120 series MII's */			int i = mdio_read(ioaddr, vp->phys[0], 16) | 0x20;			mdio_write(ioaddr, vp->phys[0], 16, 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);	}	/* Set the full-duplex bit. */	EL3WINDOW(3);	outb(((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) |		 (dev->mtu > 1500 ? 0x40 : 0), ioaddr + Wn3_MAC_Ctrl);}static void activate_xcvr(struct net_device *dev){	struct vortex_private *vp = (struct vortex_private *)dev->priv;	long ioaddr = dev->base_addr;	int reset_opts;	/* Correct some magic bits. */	EL3WINDOW(2);	reset_opts = inw(ioaddr + Wn2_ResetOptions);	if (vp->drv_flags & INVERT_LED_PWR)		reset_opts |= 0x0010;	if (vp->drv_flags & MII_XCVR_PWR)		reset_opts |= 0x4000;	outw(reset_opts, ioaddr + Wn2_ResetOptions);}static void start_operation(struct net_device *dev){	long ioaddr = dev->base_addr;	int i;	issue_and_wait(dev, TxReset);	issue_and_wait(dev, RxReset);	outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);	/* Reset the station address and mask. */	EL3WINDOW(2);	for (i = 0; i < 6; i++)		outb(dev->dev_addr[i], ioaddr + i);	for (; i < 12; i+=2)		outw(0, ioaddr + i);}static intvortex_open(struct net_device *dev){	struct vortex_private *vp = (struct vortex_private *)dev->priv;	int i;#ifdef CARDBUS	if (vp->reap)		return -ENODEV;#endif	/* Use the now-standard shared IRQ implementation. */	if (request_irq(dev->irq, &vortex_interrupt, SA_SHIRQ, dev->name, dev)) {		return -EAGAIN;	}	if (vp->full_bus_master_rx) { /* Boomerang bus master. */		if (vortex_debug > 2)			printk(KERN_DEBUG "%s:  Filling in the Rx ring.\n", dev->name);		vp->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);		for (i = 0; i < RX_RING_SIZE; i++) {			struct sk_buff *skb;			vp->rx_ring[i].length = cpu_to_le32(vp->rx_buf_sz | LAST_FRAG);			vp->rx_ring[i].next = virt_to_le32desc(&vp->rx_ring[i+1]);			skb = dev_alloc_skb(vp->rx_buf_sz);			vp->rx_skbuff[i] = skb;			if (skb == NULL)				break;			/* Bad news!  */			skb->dev = dev;			/* Mark as being used by this device. */			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */			vp->rx_ring[i].addr = virt_to_le32desc(skb->tail);		}		/* Wrap the ring. */		vp->rx_ring[i-1].next = virt_to_le32desc(&vp->rx_ring[0]);	}	if (vp->full_bus_master_tx)		dev->hard_start_xmit = &boomerang_start_xmit;	vortex_up(dev);	vp->open = 1;	netif_start_queue(dev);	netif_mark_up(dev);	MOD_INC_USE_COUNT;	return 0;}static void vortex_timer(unsigned long data){	struct net_device *dev = (struct net_device *)data;	struct vortex_private *vp = (struct vortex_private *)dev->priv;	long ioaddr = dev->base_addr;	int next_tick = 60*HZ;	int ok = 0;	int media_status, mii_status, old_window;	unsigned long flags;	if (vortex_debug > 1)		printk(KERN_DEBUG "%s: Media selection timer tick happened, %s.\n",			   dev->name, media_tbl[dev->if_port].name);	/* This only works with bus-master (non-3c590) chips. */

⌨️ 快捷键说明

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