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

📄 3c59x.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
	outw(vp->intr_enable, ioaddr + EL3_CMD);	if (vp->cb_fn_base)			/* The PCMCIA people are idiots.  */		writel(0x8000, vp->cb_fn_base + 4);	MOD_INC_USE_COUNT;	return 0;}static void vortex_timer(unsigned long data){	struct device *dev = (struct device *)data;	struct vortex_private *vp = (struct vortex_private *)dev->priv;	long ioaddr = dev->base_addr;	int next_tick = 0;	int ok = 0;	int media_status, mii_status, old_window;	if (vortex_debug > 1)		printk(KERN_DEBUG "%s: Media selection timer tick happened, %s.\n",			   dev->name, media_tbl[dev->if_port].name);	disable_irq(dev->irq);	old_window = inw(ioaddr + EL3_CMD) >> 13;	EL3WINDOW(4);	media_status = inw(ioaddr + Wn4_Media);	switch (dev->if_port) {	case XCVR_10baseT:  case XCVR_100baseTx:  case XCVR_100baseFx:		if (media_status & Media_LnkBeat) {		  ok = 1;		  if (vortex_debug > 1)			printk(KERN_DEBUG "%s: Media %s has link beat, %x.\n",				   dev->name, media_tbl[dev->if_port].name, media_status);		} else if (vortex_debug > 1)		  printk(KERN_DEBUG "%s: Media %s is has no link beat, %x.\n",				   dev->name, media_tbl[dev->if_port].name, media_status);		break;	  case XCVR_MII: case XCVR_NWAY:		  mii_status = mdio_read(ioaddr, vp->phys[0], 1);		  ok = 1;		  if (debug > 1)			  printk(KERN_DEBUG "%s: MII transceiver has status %4.4x.\n",					 dev->name, mii_status);		  if (mii_status & 0x0004) {			  int mii_reg5 = mdio_read(ioaddr, vp->phys[0], 5);			  if (! vp->force_fd  &&  mii_reg5 != 0xffff) {				  int duplex = (mii_reg5&0x0100) ||					  (mii_reg5 & 0x01C0) == 0x0040;				  if (vp->full_duplex != duplex) {					  vp->full_duplex = duplex;					  printk(KERN_INFO "%s: Setting %s-duplex based on MII "							 "#%d link partner capability of %4.4x.\n",							 dev->name, vp->full_duplex ? "full" : "half",							 vp->phys[0], mii_reg5);					  /* Set the full-duplex bit. */					  outb((vp->full_duplex ? 0x20 : 0) |						   (dev->mtu > 1500 ? 0x40 : 0),						   ioaddr + Wn3_MAC_Ctrl);				  }				  next_tick = 60*HZ;			  }		  }		  break;	  default:					/* Other media types handled by Tx timeouts. */		if (vortex_debug > 1)		  printk(KERN_DEBUG "%s: Media %s is has no indication, %x.\n",				 dev->name, media_tbl[dev->if_port].name, media_status);		ok = 1;	}	if ( ! ok) {		union wn3_config config;		do {			dev->if_port = media_tbl[dev->if_port].next;		} while ( ! (vp->available_media & media_tbl[dev->if_port].mask));		if (dev->if_port == XCVR_Default) { /* Go back to default. */		  dev->if_port = vp->default_media;		  if (vortex_debug > 1)			printk(KERN_DEBUG "%s: Media selection failing, using default "				   "%s port.\n",				   dev->name, media_tbl[dev->if_port].name);		} else {		  if (vortex_debug > 1)			printk(KERN_DEBUG "%s: Media selection failed, now trying "				   "%s port.\n",				   dev->name, media_tbl[dev->if_port].name);		  next_tick = media_tbl[dev->if_port].wait;		}		outw((media_status & ~(Media_10TP|Media_SQE)) |			 media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);		EL3WINDOW(3);		config.i = inl(ioaddr + Wn3_Config);		config.u.xcvr = dev->if_port;		outl(config.i, ioaddr + Wn3_Config);		outw(dev->if_port == XCVR_10base2 ? StartCoax : StopCoax,			 ioaddr + EL3_CMD);	}	EL3WINDOW(old_window);	enable_irq(dev->irq);	if (vortex_debug > 2)	  printk(KERN_DEBUG "%s: Media selection timer finished, %s.\n",			 dev->name, media_tbl[dev->if_port].name);	if (next_tick) {		vp->timer.expires = RUN_AT(next_tick);		add_timer(&vp->timer);	}	return;}static void vortex_tx_timeout(struct device *dev){	struct vortex_private *vp = (struct vortex_private *)dev->priv;	long ioaddr = dev->base_addr;	int j;	printk(KERN_ERR "%s: transmit timed out, tx_status %2.2x status %4.4x.\n",		   dev->name, inb(ioaddr + TxStatus),		   inw(ioaddr + EL3_STATUS));	/* Slight code bloat to be user friendly. */	if ((inb(ioaddr + TxStatus) & 0x88) == 0x88)		printk(KERN_ERR "%s: Transmitter encountered 16 collisions --"			   " network cable problem?\n", dev->name);	if (inw(ioaddr + EL3_STATUS) & IntLatch) {		printk(KERN_ERR "%s: Interrupt posted but not delivered --"			   " IRQ blocked by another device?\n", dev->name);		/* Bad idea here.. but we might as well handle a few events. */		vortex_interrupt(dev->irq, dev, 0);	}	outw(TxReset, ioaddr + EL3_CMD);	for (j = 200; j >= 0 ; j--)		if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))			break;#if ! defined(final_version) && LINUX_VERSION_CODE >= 0x10300	if (vp->full_bus_master_tx) {		int i;		printk(KERN_DEBUG "  Flags; bus-master %d, full %d; dirty %d "			   "current %d.\n",			   vp->full_bus_master_tx, vp->tx_full, vp->dirty_tx, vp->cur_tx);		printk(KERN_DEBUG "  Transmit list %8.8x vs. %p.\n",			   inl(ioaddr + DownListPtr),			   &vp->tx_ring[vp->dirty_tx % TX_RING_SIZE]);		for (i = 0; i < TX_RING_SIZE; i++) {			printk(KERN_DEBUG "  %d: @%p  length %8.8x status %8.8x\n", i,				   &vp->tx_ring[i],				   le32_to_cpu(vp->tx_ring[i].length),				   le32_to_cpu(vp->tx_ring[i].status));		}	}#endif	vp->stats.tx_errors++;	if (vp->full_bus_master_tx) {		if (vortex_debug > 0)			printk(KERN_DEBUG "%s: Resetting the Tx ring pointer.\n",				   dev->name);		if (vp->cur_tx - vp->dirty_tx > 0  &&  inl(ioaddr + DownListPtr) == 0)			outl(virt_to_bus(&vp->tx_ring[vp->dirty_tx % TX_RING_SIZE]),				 ioaddr + DownListPtr);		if (vp->tx_full && (vp->cur_tx - vp->dirty_tx <= TX_RING_SIZE - 1)) {			vp->tx_full = 0;			clear_bit(0, (void*)&dev->tbusy);		}		outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold);		outw(DownUnstall, ioaddr + EL3_CMD);	} else		vp->stats.tx_dropped++;		/* Issue Tx Enable */	outw(TxEnable, ioaddr + EL3_CMD);	dev->trans_start = jiffies;		/* Switch to register set 7 for normal use. */	EL3WINDOW(7);}/* * Handle uncommon interrupt sources.  This is a separate routine to minimize * the cache impact. */static voidvortex_error(struct device *dev, int status){	struct vortex_private *vp = (struct vortex_private *)dev->priv;	long ioaddr = dev->base_addr;	int do_tx_reset = 0;	int i;	if (status & TxComplete) {			/* Really "TxError" for us. */		unsigned char tx_status = inb(ioaddr + TxStatus);		/* Presumably a tx-timeout. We must merely re-enable. */		if (vortex_debug > 2			|| (tx_status != 0x88 && vortex_debug > 0))			printk(KERN_DEBUG"%s: Transmit error, Tx status register %2.2x.\n",				   dev->name, tx_status);		if (tx_status & 0x14)  vp->stats.tx_fifo_errors++;		if (tx_status & 0x38)  vp->stats.tx_aborted_errors++;		outb(0, ioaddr + TxStatus);		if (tx_status & 0x30)			do_tx_reset = 1;		else					/* Merely re-enable the transmitter. */			outw(TxEnable, ioaddr + EL3_CMD);	}	if (status & RxEarly) {				/* Rx early is unused. */		vortex_rx(dev);		outw(AckIntr | RxEarly, ioaddr + EL3_CMD);	}	if (status & StatsFull) {			/* Empty statistics. */		static int DoneDidThat = 0;		if (vortex_debug > 4)			printk(KERN_DEBUG "%s: Updating stats.\n", dev->name);		update_stats(ioaddr, dev);		/* HACK: Disable statistics as an interrupt source. */		/* This occurs when we have the wrong media type! */		if (DoneDidThat == 0  &&			inw(ioaddr + EL3_STATUS) & StatsFull) {			printk(KERN_WARNING "%s: Updating statistics failed, disabling "				   "stats as an interrupt source.\n", dev->name);			EL3WINDOW(5);			outw(SetIntrEnb | (inw(ioaddr + 10) & ~StatsFull), ioaddr + EL3_CMD);			EL3WINDOW(7);			DoneDidThat++;		}	}	if (status & IntReq) {		/* Restore all interrupt sources.  */		outw(vp->status_enable, ioaddr + EL3_CMD);		outw(vp->intr_enable, ioaddr + EL3_CMD);	}	if (status & HostError) {		u16 fifo_diag;		EL3WINDOW(4);		fifo_diag = inw(ioaddr + Wn4_FIFODiag);		if (vortex_debug > 0)			printk(KERN_ERR "%s: Host error, FIFO diagnostic register %4.4x.\n",				   dev->name, fifo_diag);		/* Adapter failure requires Tx/Rx reset and reinit. */		if (vp->full_bus_master_tx) {			outw(TotalReset | 0xff, ioaddr + EL3_CMD);			for (i = 2000; i >= 0 ; i--)				if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))					break;			/* Re-enable the receiver. */			outw(RxEnable, ioaddr + EL3_CMD);			outw(TxEnable, ioaddr + EL3_CMD);		} else if (fifo_diag & 0x0400)			do_tx_reset = 1;		if (fifo_diag & 0x3000) {			outw(RxReset, ioaddr + EL3_CMD);			for (i = 2000; i >= 0 ; i--)				if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))					break;			/* Set the Rx filter to the current state. */			set_rx_mode(dev);			outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */			outw(AckIntr | HostError, ioaddr + EL3_CMD);		}	}	if (do_tx_reset) {		int j;		outw(TxReset, ioaddr + EL3_CMD);		for (j = 200; j >= 0 ; j--)			if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))				break;		outw(TxEnable, ioaddr + EL3_CMD);	}}static intvortex_start_xmit(struct sk_buff *skb, struct device *dev){	struct vortex_private *vp = (struct vortex_private *)dev->priv;	long ioaddr = dev->base_addr;	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {		if (jiffies - dev->trans_start >= TX_TIMEOUT)			vortex_tx_timeout(dev);		return 1;	}	/* Put out the doubleword header... */	outl(skb->len, ioaddr + TX_FIFO);	if (vp->bus_master) {		/* Set the bus-master controller to transfer the packet. */		outl(virt_to_bus(skb->data), ioaddr + Wn7_MasterAddr);		outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen);		vp->tx_skb = skb;		outw(StartDMADown, ioaddr + EL3_CMD);		/* dev->tbusy will be cleared at the DMADone interrupt. */	} else {		/* ... and the packet rounded to a doubleword. */		outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);		DEV_FREE_SKB(skb);		if (inw(ioaddr + TxFree) > 1536) {			clear_bit(0, (void*)&dev->tbusy);		} else			/* Interrupt us when the FIFO has room for max-sized packet. */			outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);	}	dev->trans_start = jiffies;	/* Clear the Tx status stack. */	{		int tx_status;		int i = 32;		while (--i > 0	&&	(tx_status = inb(ioaddr + TxStatus)) > 0) {			if (tx_status & 0x3C) {		/* A Tx-disabling error occurred.  */				if (vortex_debug > 2)				  printk(KERN_DEBUG "%s: Tx error, status %2.2x.\n",						 dev->name, tx_status);				if (tx_status & 0x04) vp->stats.tx_fifo_errors++;				if (tx_status & 0x38) vp->stats.tx_aborted_errors++;				if (tx_status & 0x30) {					int j;					outw(TxReset, ioaddr + EL3_CMD);					for (j = 200; j >= 0 ; j--)						if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))							break;				}				outw(TxEnable, ioaddr + EL3_CMD);			}			outb(0x00, ioaddr + TxStatus); /* Pop the status stack. */		}	}	vp->stats.tx_bytes += skb->len;	return 0;}static intboomerang_start_xmit(struct sk_buff *skb, struct device *dev){	struct vortex_private *vp = (struct vortex_private *)dev->priv;	long ioaddr = dev->base_addr;	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {		if (jiffies - dev->trans_start >= TX_TIMEOUT)			vortex_tx_timeout(dev);		return 1;	} else {		/* Calculate the next Tx descriptor entry. */		int entry = vp->cur_tx % TX_RING_SIZE;		struct boom_tx_desc *prev_entry =			&vp->tx_ring[(vp->cur_tx-1) % TX_RING_SIZE];		unsigned long flags;		int i;		if (vortex_debug > 3)			printk(KERN_DEBUG "%s: Trying to send a packet, Tx index %d.\n",				   dev->name, vp->cur_tx);		if (vp->tx_full) {			if (vortex_debug >0)				printk(KERN_WARNING "%s: Tx Ring full, refusing to send buffer.\n",					   dev->name);			return 1;		}		vp->tx_skbuff[entry] = skb;		vp->tx_ring[entry].next = 0;		vp->tx_ring[entry].addr = cpu_to_le32(virt_to_bus(skb->data));		vp->tx_ring[entry].length = cpu_to_le32(skb->len | LAST_FRAG);		vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded);		save_flags(flags);		cli();		outw(DownStall, ioaddr + EL3_CMD);		/* Wait for the stall to complete. */		for (i = 600; i >= 0 ; i--)			if ( (inw(ioaddr + EL3_STATUS) & CmdInProgress) == 0)				break;		prev_entry->next = cpu_to_le32(virt_to_bus(&vp->tx_ring[entry]));		if (inl(ioaddr + DownListPtr) == 0) {			outl(virt_to_bus(&vp->tx_ring[entry]), ioaddr + DownListPtr);			queued_packet++;		}		outw(DownUnstall, ioaddr + EL3_CMD);		restore_flags(flags);		vp->cur_tx++;		if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1)			vp->tx_full = 1;		else {					/* Clear previous interrupt enable. */			prev_entry->status &= cpu_to_le32(~TxIntrUploaded);

⌨️ 快捷键说明

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