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

📄 3c359.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
				temp_ring_loc++ ; 				temp_ring_loc &= (XL_RX_RING_SIZE-1) ; 			}			frame_length = xl_priv->xl_rx_ring[temp_ring_loc].framestatus & 0x7FFF ; 			skb = dev_alloc_skb(frame_length) ; 			if (skb==NULL) { /* No memory for frame, still need to roll forward the rx ring */				printk(KERN_WARNING "%s: dev_alloc_skb failed - multi buffer !\n", dev->name) ; 				while (xl_priv->rx_ring_tail != temp_ring_loc)  					adv_rx_ring(dev) ; 								adv_rx_ring(dev) ; /* One more time just for luck :) */ 				xl_priv->xl_stats.rx_dropped++ ; 				writel(ACK_INTERRUPT | UPCOMPACK | LATCH_ACK , xl_mmio + MMIO_COMMAND) ; 				return ; 							}				skb->dev = dev ; 			while (xl_priv->rx_ring_tail != temp_ring_loc) { 				copy_len = xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfraglen & 0x7FFF ; 				frame_length -= copy_len ;  				pci_dma_sync_single_for_cpu(xl_priv->pdev,xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr,xl_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE) ;				memcpy(skb_put(skb,copy_len), xl_priv->rx_ring_skb[xl_priv->rx_ring_tail]->data, copy_len) ; 				pci_dma_sync_single_for_device(xl_priv->pdev,xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr,xl_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE) ;				adv_rx_ring(dev) ; 			} 			/* Now we have found the last fragment */			pci_dma_sync_single_for_cpu(xl_priv->pdev,xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr,xl_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE) ;			memcpy(skb_put(skb,copy_len), xl_priv->rx_ring_skb[xl_priv->rx_ring_tail]->data, frame_length) ; /*			memcpy(skb_put(skb,frame_length), bus_to_virt(xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr), frame_length) ; */			pci_dma_sync_single_for_device(xl_priv->pdev,xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr,xl_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE) ;			adv_rx_ring(dev) ; 			skb->protocol = tr_type_trans(skb,dev) ; 			netif_rx(skb) ; 		} else { /* Single Descriptor Used, simply swap buffers over, fast path  */			frame_length = xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].framestatus & 0x7FFF ; 						skb = dev_alloc_skb(xl_priv->pkt_buf_sz) ; 			if (skb==NULL) { /* Still need to fix the rx ring */				printk(KERN_WARNING "%s: dev_alloc_skb failed in rx, single buffer \n",dev->name) ; 				adv_rx_ring(dev) ; 				xl_priv->xl_stats.rx_dropped++ ; 				writel(ACK_INTERRUPT | UPCOMPACK | LATCH_ACK , xl_mmio + MMIO_COMMAND) ; 				return ; 			}			skb->dev = dev ; 			skb2 = xl_priv->rx_ring_skb[xl_priv->rx_ring_tail] ; 			pci_unmap_single(xl_priv->pdev, xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr, xl_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE) ; 			skb_put(skb2, frame_length) ; 			skb2->protocol = tr_type_trans(skb2,dev) ; 			xl_priv->rx_ring_skb[xl_priv->rx_ring_tail] = skb ; 				xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr = pci_map_single(xl_priv->pdev,skb->data,xl_priv->pkt_buf_sz, PCI_DMA_FROMDEVICE) ; 			xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfraglen = xl_priv->pkt_buf_sz | RXUPLASTFRAG ; 			adv_rx_ring(dev) ; 			xl_priv->xl_stats.rx_packets++ ; 			xl_priv->xl_stats.rx_bytes += frame_length ; 				netif_rx(skb2) ; 				 } /* if multiple buffers */		dev->last_rx = jiffies ; 		} /* while packet to do */	/* Clear the updComplete interrupt */	writel(ACK_INTERRUPT | UPCOMPACK | LATCH_ACK , xl_mmio + MMIO_COMMAND) ; 	return ; 	}/* * This is ruthless, it doesn't care what state the card is in it will  * completely reset the adapter. */static void xl_reset(struct net_device *dev) {	struct xl_private *xl_priv=(struct xl_private *)dev->priv;	u8 __iomem * xl_mmio = xl_priv->xl_mmio ; 	unsigned long t; 	writew( GLOBAL_RESET, xl_mmio + MMIO_COMMAND ) ; 	/* 	 * Must wait for cmdInProgress bit (12) to clear before continuing with	 * card configuration.	 */	t=jiffies;	while (readw(xl_mmio + MMIO_INTSTATUS) & INTSTAT_CMD_IN_PROGRESS) { 		if(jiffies-t > 40*HZ) {			printk(KERN_ERR "3COM 3C359 Velocity XL  card not responding.\n");			break ; 		}	}	}static void xl_freemem(struct net_device *dev) {	struct xl_private *xl_priv=(struct xl_private *)dev->priv ; 	int i ; 	for (i=0;i<XL_RX_RING_SIZE;i++) {		dev_kfree_skb_irq(xl_priv->rx_ring_skb[xl_priv->rx_ring_tail]) ; 		pci_unmap_single(xl_priv->pdev,xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr,xl_priv->pkt_buf_sz, PCI_DMA_FROMDEVICE) ; 		xl_priv->rx_ring_tail++ ; 		xl_priv->rx_ring_tail &= XL_RX_RING_SIZE-1; 	} 	/* unmap ring */	pci_unmap_single(xl_priv->pdev,xl_priv->rx_ring_dma_addr, sizeof(struct xl_rx_desc) * XL_RX_RING_SIZE, PCI_DMA_FROMDEVICE) ; 		pci_unmap_single(xl_priv->pdev,xl_priv->tx_ring_dma_addr, sizeof(struct xl_tx_desc) * XL_TX_RING_SIZE, PCI_DMA_TODEVICE) ; 	kfree(xl_priv->xl_rx_ring) ; 	kfree(xl_priv->xl_tx_ring) ; 	return  ; }static irqreturn_t xl_interrupt(int irq, void *dev_id, struct pt_regs *regs) {	struct net_device *dev = (struct net_device *)dev_id; 	struct xl_private *xl_priv =(struct xl_private *)dev->priv;	u8 __iomem * xl_mmio = xl_priv->xl_mmio ; 	u16 intstatus, macstatus  ;	if (!dev) { 		printk(KERN_WARNING "Device structure dead, aaahhhh !\n") ;		return IRQ_NONE; 	}	intstatus = readw(xl_mmio + MMIO_INTSTATUS) ;  	if (!(intstatus & 1)) /* We didn't generate the interrupt */		return IRQ_NONE;	spin_lock(&xl_priv->xl_lock) ; 	/*	 * Process the interrupt	 */	/*	 * Something fishy going on here, we shouldn't get 0001 ints, not fatal though.	 */	if (intstatus == 0x0001) {  		writel(ACK_INTERRUPT | LATCH_ACK, xl_mmio + MMIO_COMMAND) ;		printk(KERN_INFO "%s: 00001 int received \n",dev->name) ;  	} else {  		if (intstatus &	(HOSTERRINT | SRBRINT | ARBCINT | UPCOMPINT | DNCOMPINT | HARDERRINT | (1<<8) | TXUNDERRUN | ASBFINT)) { 						/* 			 * Host Error.			 * It may be possible to recover from this, but usually it means something			 * is seriously fubar, so we just close the adapter.			 */			if (intstatus & HOSTERRINT) {				printk(KERN_WARNING "%s: Host Error, performing global reset, intstatus = %04x \n",dev->name,intstatus) ; 				writew( GLOBAL_RESET, xl_mmio + MMIO_COMMAND ) ;				printk(KERN_WARNING "%s: Resetting hardware: \n", dev->name); 				netif_stop_queue(dev) ;				xl_freemem(dev) ; 				free_irq(dev->irq,dev); 					xl_reset(dev) ; 				writel(ACK_INTERRUPT | LATCH_ACK, xl_mmio + MMIO_COMMAND) ; 				spin_unlock(&xl_priv->xl_lock) ; 				return IRQ_HANDLED;			} /* Host Error */			if (intstatus & SRBRINT ) {  /* Srbc interrupt */				writel(ACK_INTERRUPT | SRBRACK | LATCH_ACK, xl_mmio + MMIO_COMMAND) ;				if (xl_priv->srb_queued)					xl_srb_bh(dev) ; 			} /* SRBR Interrupt */			if (intstatus & TXUNDERRUN) { /* Issue DnReset command */				writel(DNRESET, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 				while (readw(xl_mmio + MMIO_INTSTATUS) & INTSTAT_CMD_IN_PROGRESS) { /* Wait for command to run */					/* !!! FIX-ME !!!! 					Must put a timeout check here ! */					/* Empty Loop */				} 				printk(KERN_WARNING "%s: TX Underrun received \n",dev->name) ;				writel(ACK_INTERRUPT | LATCH_ACK, xl_mmio + MMIO_COMMAND) ; 			} /* TxUnderRun */				if (intstatus & ARBCINT ) { /* Arbc interrupt */				xl_arb_cmd(dev) ; 			} /* Arbc */			if (intstatus & ASBFINT) { 				if (xl_priv->asb_queued == 1) {					xl_asb_cmd(dev) ; 				} else if (xl_priv->asb_queued == 2) {					xl_asb_bh(dev) ; 				} else { 					writel(ACK_INTERRUPT | LATCH_ACK | ASBFACK, xl_mmio + MMIO_COMMAND) ; 				}  			} /* Asbf */			if (intstatus & UPCOMPINT ) /* UpComplete */				xl_rx(dev) ; 			if (intstatus & DNCOMPINT )  /* DnComplete */				xl_dn_comp(dev) ; 			if (intstatus & HARDERRINT ) { /* Hardware error */				writel(MMIO_WORD_READ | MACSTATUS, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 				macstatus = readw(xl_mmio + MMIO_MACDATA) ; 				printk(KERN_WARNING "%s: MacStatusError, details: ", dev->name);				if (macstatus & (1<<14)) 					printk(KERN_WARNING "tchk error: Unrecoverable error \n") ; 				if (macstatus & (1<<3))					printk(KERN_WARNING "eint error: Internal watchdog timer expired \n") ;				if (macstatus & (1<<2))					printk(KERN_WARNING "aint error: Host tried to perform invalid operation \n") ; 				printk(KERN_WARNING "Instatus = %02x, macstatus = %02x\n",intstatus,macstatus) ; 				printk(KERN_WARNING "%s: Resetting hardware: \n", dev->name); 				netif_stop_queue(dev) ;				xl_freemem(dev) ; 				free_irq(dev->irq,dev); 				unregister_netdev(dev) ; 				free_netdev(dev) ;  				xl_reset(dev) ; 				writel(ACK_INTERRUPT | LATCH_ACK, xl_mmio + MMIO_COMMAND) ; 				spin_unlock(&xl_priv->xl_lock) ; 				return IRQ_HANDLED;			}		} else { 			printk(KERN_WARNING "%s: Received Unknown interrupt : %04x \n", dev->name, intstatus) ;			writel(ACK_INTERRUPT | LATCH_ACK, xl_mmio + MMIO_COMMAND) ; 			}	} 	/* Turn interrupts back on */	writel( SETINDENABLE | INT_MASK, xl_mmio + MMIO_COMMAND) ; 	writel( SETINTENABLE | INT_MASK, xl_mmio + MMIO_COMMAND) ; 	spin_unlock(&xl_priv->xl_lock) ;	return IRQ_HANDLED;}	/* *	Tx - Polling configuration */	static int xl_xmit(struct sk_buff *skb, struct net_device *dev) {	struct xl_private *xl_priv=(struct xl_private *)dev->priv;	struct xl_tx_desc *txd ; 	int tx_head, tx_tail, tx_prev ; 	unsigned long flags ; 		spin_lock_irqsave(&xl_priv->xl_lock,flags) ; 	netif_stop_queue(dev) ; 	if (xl_priv->free_ring_entries > 1 ) { 			/*		 * Set up the descriptor for the packet 		 */		tx_head = xl_priv->tx_ring_head ; 		tx_tail = xl_priv->tx_ring_tail ; 		txd = &(xl_priv->xl_tx_ring[tx_head]) ; 		txd->dnnextptr = 0 ; 		txd->framestartheader = skb->len | TXDNINDICATE ; 		txd->buffer = pci_map_single(xl_priv->pdev, skb->data, skb->len, PCI_DMA_TODEVICE) ; 		txd->buffer_length = skb->len | TXDNFRAGLAST  ; 		xl_priv->tx_ring_skb[tx_head] = skb ; 		xl_priv->xl_stats.tx_packets++ ; 		xl_priv->xl_stats.tx_bytes += skb->len ;		/* 		 * Set the nextptr of the previous descriptor equal to this descriptor, add XL_TX_RING_SIZE -1 		 * to ensure no negative numbers in unsigned locations.		 */ 			tx_prev = (xl_priv->tx_ring_head + XL_TX_RING_SIZE - 1) & (XL_TX_RING_SIZE - 1) ; 		xl_priv->tx_ring_head++ ; 		xl_priv->tx_ring_head &= (XL_TX_RING_SIZE - 1) ;		xl_priv->free_ring_entries-- ; 		xl_priv->xl_tx_ring[tx_prev].dnnextptr = xl_priv->tx_ring_dma_addr + (sizeof (struct xl_tx_desc) * tx_head) ; 		/* Sneaky, by doing a read on DnListPtr we can force the card to poll on the DnNextPtr */		/* readl(xl_mmio + MMIO_DNLISTPTR) ; */		netif_wake_queue(dev) ; 		spin_unlock_irqrestore(&xl_priv->xl_lock,flags) ;  		return 0;	} else {		spin_unlock_irqrestore(&xl_priv->xl_lock,flags) ; 		return 1;	}}	/*  * The NIC has told us that a packet has been downloaded onto the card, we must * find out which packet it has done, clear the skb and information for the packet * then advance around the ring for all tranmitted packets */static void xl_dn_comp(struct net_device *dev) {	struct xl_private *xl_priv=(struct xl_private *)dev->priv;	u8 __iomem * xl_mmio = xl_priv->xl_mmio ; 	struct xl_tx_desc *txd ; 	if (xl_priv->tx_ring_tail == 255) {/* First time */		xl_priv->xl_tx_ring[0].framestartheader = 0 ; 		xl_priv->xl_tx_ring[0].dnnextptr = 0 ;  		xl_priv->tx_ring_tail = 1 ; 	}	while (xl_priv->xl_tx_ring[xl_priv->tx_ring_tail].framestartheader & TXDNCOMPLETE ) { 		txd = &(xl_priv->xl_tx_ring[xl_priv->tx_ring_tail]) ;		pci_unmap_single(xl_priv->pdev,txd->buffer, xl_priv->tx_ring_skb[xl_priv->tx_ring_tail]->len, PCI_DMA_TODEVICE) ; 		txd->framestartheader = 0 ; 		txd->buffer = 0xdeadbeef  ; 		txd->buffer_length  = 0 ;  		dev_kfree_skb_irq(xl_priv->tx_ring_skb[xl_priv->tx_ring_tail]) ;		xl_priv->tx_ring_tail++ ; 		xl_priv->tx_ring_tail &= (XL_TX_RING_SIZE - 1) ; 		xl_priv->free_ring_entries++ ; 	}	netif_wake_queue(dev) ; 	writel(ACK_INTERRUPT | DNCOMPACK | LATCH_ACK , xl_mmio + MMIO_COMMAND) ; }/* * Close the adapter properly. * This srb reply cannot be handled from interrupt context as we have * to free the interrupt from the driver.  */static int xl_close(struct net_device *dev) {	struct xl_private *xl_priv = (struct xl_private *) dev->priv ; 	u8 __iomem * xl_mmio = xl_priv->xl_mmio ; 	unsigned long t ; 	netif_stop_queue(dev) ; 	/*	 * Close the adapter, need to stall the rx and tx queues.	 */    	writew(DNSTALL, xl_mmio + MMIO_COMMAND) ; 	t=jiffies;	while (readw(xl_mmio + MMIO_INTSTATUS) & INTSTAT_CMD_IN_PROGRESS) { 		schedule();				if(jiffies-t > 10*HZ) {			printk(KERN_ERR "%s: 3COM 3C359 Velocity XL-DNSTALL not responding.\n", dev->name);			break ; 		}	}    	writew(DNDISABLE, xl_mmio + MMIO_COMMAND) ; 	t=jiffies;	while (readw(xl_mmio + MMIO_INTSTATUS) & INTSTAT_CMD_IN_PROGRESS) { 		schedule();				if(jiffies-t > 10*HZ) {			printk(KERN_ERR "%s: 3COM 3C359 Velocity XL-DNDISABLE not responding.\n", dev->name);			break ;		}	}    	writew(UPSTALL, xl_mmio + MMIO_COMMAND) ; 	t=jiffies;	while (readw(xl_mmio + MMIO_INTSTATUS) & INTSTAT_CMD_IN_PROGRESS) { 		schedule();				if(jiffies-t > 10*HZ) {			printk(KERN_ERR "%s: 3COM 3C359 Velocity XL-UPSTALL not responding.\n", dev->name);			break ; 		}	}	/* Turn off interrupts, we will still get the indication though 	 * so we can trap it	 */	writel(SETINTENABLE, xl_mmio + MMIO_COMMAND) ; 	xl_srb_cmd(dev,CLOSE_NIC) ; 	t=jiffies;	while (!(readw(xl_mmio + MMIO_INTSTATUS) & INTSTAT_SRB)) { 		schedule();				if(jiffies-t > 10*HZ) {			printk(KERN_ERR "%s: 3COM 3C359 Velocity XL-CLOSENIC not responding.\n", dev->name);			break ; 		}	}	/* Read the srb response from the adapter */	writel(MEM_BYTE_READ | 0xd0000 | xl_priv->srb, xl_mmio + MMIO_MAC_ACCESS_CMD);	if (readb(xl_mmio + MMIO_MACDATA) != CLOSE_NIC) { 		printk(KERN_INFO "%s: CLOSE_NIC did not get a CLOSE_NIC response \n",dev->name) ; 	} else { 		writel((MEM_BYTE_READ | 0xd0000 | xl_priv->srb) +2, xl_mmio + MMIO_MAC_ACCESS_CMD) ;		if (readb(xl_mmio + MMIO_MACDATA)==0) { 			printk(KERN_INFO "%s: Adapter has been closed \n",dev->name) ;			writew(ACK_INTERRUPT | SRBRACK | LATCH_ACK, xl_mmio + MMIO_COMMAND) ; 			xl_freemem(dev) ; 			free_irq(dev->irq,dev) ; 		} else { 			printk(KERN_INFO "%s: Close nic command returned error code %02x\n",dev->name, readb(xl_mmio + MMIO_MACDATA)) ;		} 	}	/* Reset the upload and download logic */     	writew(UPRESET, xl_mmio + MMIO_COMMAND) ; 	t=jiffies;	while (readw(xl_mmio + MMIO_INTSTATUS) & INTSTAT_CMD_IN_PROGRESS) { 		schedule();				if(jiffies-t > 10*HZ) {			printk(KERN_ERR "%s: 3COM 3C359 Velocity XL-UPRESET not responding.\n", dev->name);			break ; 		}	}    	writew(DNRESET, xl_mmio + MMIO_COMMAND) ; 	t=jiffies;	while (readw(xl_mmio + MMIO_INTSTATUS) & INTSTAT_CMD_IN_PROGRESS) { 		schedule();				if(jiffies-t > 10*HZ) {			printk(KERN_ERR "%s: 3COM 3C359 Velocity XL-DNRESET not responding.\n", dev->name);			break ; 		}	}	xl_hw_reset(dev) ; 	return 0 ;}static void xl_set_rx_mode(struct net_device *dev) {	struct xl_private *xl_priv = (struct xl_private *) dev->priv ; 	struct dev_mc_list *dmi ; 	unsigned char dev_mc_address[4] ; 	u16 options ; 

⌨️ 快捷键说明

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