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

📄 lasi_82596.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 3 页
字号:
	pcc2[0x2b] = 0x1d;	printk("%s: Error interrupt\n", dev->name);	i596_display_data(dev);}#endif#define virt_to_dma(lp,v) ((char *)(v)-(char *)(lp)+(char *)((lp)->dma_addr))static inline void init_rx_bufs(struct net_device *dev){	struct i596_private *lp = (struct i596_private *)dev->priv;	int i;	struct i596_rfd *rfd;	struct i596_rbd *rbd;	/* First build the Receive Buffer Descriptor List */	for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) {		dma_addr_t dma_addr;		struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ + 4);		if (skb == NULL)			panic("82596: alloc_skb() failed");		skb_reserve(skb, 2);		dma_addr = pci_map_single(NULL, skb->tail,PKT_BUF_SZ,					PCI_DMA_FROMDEVICE);		skb->dev = dev;		rbd->v_next = rbd+1;		rbd->b_next = WSWAPrbd(virt_to_dma(lp,rbd+1));		rbd->b_addr = WSWAPrbd(virt_to_dma(lp,rbd));		rbd->skb = skb;		rbd->v_data = skb->tail;		rbd->b_data = WSWAPchar(dma_addr);		rbd->size = PKT_BUF_SZ;	}	lp->rbd_head = lp->rbds;	rbd = lp->rbds + rx_ring_size - 1;	rbd->v_next = lp->rbds;	rbd->b_next = WSWAPrbd(virt_to_dma(lp,lp->rbds));	/* Now build the Receive Frame Descriptor List */	for (i = 0, rfd = lp->rfds; i < rx_ring_size; i++, rfd++) {		rfd->rbd = I596_NULL;		rfd->v_next = rfd+1;		rfd->v_prev = rfd-1;		rfd->b_next = WSWAPrfd(virt_to_dma(lp,rfd+1));		rfd->cmd = CMD_FLEX;	}	lp->rfd_head = lp->rfds;	lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds));	rfd = lp->rfds;	rfd->rbd = lp->rbd_head;	rfd->v_prev = lp->rfds + rx_ring_size - 1;	rfd = lp->rfds + rx_ring_size - 1;	rfd->v_next = lp->rfds;	rfd->b_next = WSWAPrfd(virt_to_dma(lp,lp->rfds));	rfd->cmd = CMD_EOL|CMD_FLEX;	CHECK_WBACK_INV(lp, sizeof(struct i596_private));}static inline void remove_rx_bufs(struct net_device *dev){	struct i596_private *lp = (struct i596_private *)dev->priv;	struct i596_rbd *rbd;	int i;	for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) {		if (rbd->skb == NULL)			break;		pci_unmap_single(NULL,(dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, PCI_DMA_FROMDEVICE);		dev_kfree_skb(rbd->skb);	}}static void rebuild_rx_bufs(struct net_device *dev){	struct i596_private *lp = (struct i596_private *) dev->priv;	int i;	/* Ensure rx frame/buffer descriptors are tidy */	for (i = 0; i < rx_ring_size; i++) {		lp->rfds[i].rbd = I596_NULL;		lp->rfds[i].cmd = CMD_FLEX;	}	lp->rfds[rx_ring_size-1].cmd = CMD_EOL|CMD_FLEX;	lp->rfd_head = lp->rfds;	lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds));	lp->rbd_head = lp->rbds;	lp->rfds[0].rbd = WSWAPrbd(virt_to_dma(lp,lp->rbds));	CHECK_WBACK_INV(lp, sizeof(struct i596_private));}static int init_i596_mem(struct net_device *dev){	struct i596_private *lp = (struct i596_private *) dev->priv;	unsigned long flags;	disable_irq(dev->irq);	/* disable IRQs from LAN */	DEB(DEB_INIT,		printk("RESET 82596 port: %08lX (with IRQ%d disabled)\n",		       dev->base_addr + PA_I82596_RESET,		       dev->irq));		gsc_writel(0, (void*)(dev->base_addr + PA_I82596_RESET)); /* Hard Reset */	udelay(100);			/* Wait 100us - seems to help */	/* change the scp address */	lp->last_cmd = jiffies;	lp->scp.sysbus = 0x0000006c;	lp->scp.iscp = WSWAPiscp(virt_to_dma(lp,&(lp->iscp)));	lp->iscp.scb = WSWAPscb(virt_to_dma(lp,&(lp->scb)));	lp->iscp.stat = ISCP_BUSY;	lp->cmd_backlog = 0;	lp->cmd_head = lp->scb.cmd = I596_NULL;	DEB(DEB_INIT,printk("%s: starting i82596.\n", dev->name));	CHECK_WBACK(&(lp->scp), sizeof(struct i596_scp));	CHECK_WBACK(&(lp->iscp), sizeof(struct i596_iscp));	MPU_PORT(dev, PORT_ALTSCP, (void *)virt_to_dma(lp,&lp->scp));		CA(dev);	if (wait_istat(dev,lp,1000,"initialization timed out"))		goto failed;	DEB(DEB_INIT,printk("%s: i82596 initialization successful\n", dev->name));	/* Ensure rx frame/buffer descriptors are tidy */	rebuild_rx_bufs(dev);	lp->scb.command = 0;	CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb));	enable_irq(dev->irq);	/* enable IRQs from LAN */	DEB(DEB_INIT,printk("%s: queuing CmdConfigure\n", dev->name));	memcpy(lp->cf_cmd.i596_config, init_setup, 14);	lp->cf_cmd.cmd.command = CmdConfigure;	CHECK_WBACK(&(lp->cf_cmd), sizeof(struct cf_cmd));	i596_add_cmd(dev, &lp->cf_cmd.cmd);	DEB(DEB_INIT,printk("%s: queuing CmdSASetup\n", dev->name));	memcpy(lp->sa_cmd.eth_addr, dev->dev_addr, 6);	lp->sa_cmd.cmd.command = CmdSASetup;	CHECK_WBACK(&(lp->sa_cmd), sizeof(struct sa_cmd));	i596_add_cmd(dev, &lp->sa_cmd.cmd);	DEB(DEB_INIT,printk("%s: queuing CmdTDR\n", dev->name));	lp->tdr_cmd.cmd.command = CmdTDR;	CHECK_WBACK(&(lp->tdr_cmd), sizeof(struct tdr_cmd));	i596_add_cmd(dev, &lp->tdr_cmd.cmd);	spin_lock_irqsave (&lp->lock, flags);	if (wait_cmd(dev,lp,1000,"timed out waiting to issue RX_START")) {		spin_unlock_irqrestore (&lp->lock, flags);		goto failed;	}	DEB(DEB_INIT,printk("%s: Issuing RX_START\n", dev->name));	lp->scb.command = RX_START;	lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds));	CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb));	CA(dev);	spin_unlock_irqrestore (&lp->lock, flags);	if (wait_cmd(dev,lp,1000,"RX_START not processed"))		goto failed;	DEB(DEB_INIT,printk("%s: Receive unit started OK\n", dev->name));	return 0;failed:	printk("%s: Failed to initialise 82596\n", dev->name);	MPU_PORT(dev, PORT_RESET, 0);	return -1;}static inline int i596_rx(struct net_device *dev){	struct i596_private *lp = (struct i596_private *)dev->priv;	struct i596_rfd *rfd;	struct i596_rbd *rbd;	int frames = 0;	DEB(DEB_RXFRAME,printk ("i596_rx(), rfd_head %p, rbd_head %p\n",			lp->rfd_head, lp->rbd_head));	rfd = lp->rfd_head;		/* Ref next frame to check */	CHECK_INV(rfd, sizeof(struct i596_rfd));	while ((rfd->stat) & STAT_C) {	/* Loop while complete frames */		if (rfd->rbd == I596_NULL)			rbd = I596_NULL;		else if (rfd->rbd == lp->rbd_head->b_addr) {			rbd = lp->rbd_head;			CHECK_INV(rbd, sizeof(struct i596_rbd));		}		else {			printk("%s: rbd chain broken!\n", dev->name);			/* XXX Now what? */			rbd = I596_NULL;		}		DEB(DEB_RXFRAME, printk("  rfd %p, rfd.rbd %p, rfd.stat %04x\n",			rfd, rfd->rbd, rfd->stat));				if (rbd != I596_NULL && ((rfd->stat) & STAT_OK)) {			/* a good frame */			int pkt_len = rbd->count & 0x3fff;			struct sk_buff *skb = rbd->skb;			int rx_in_place = 0;			DEB(DEB_RXADDR,print_eth(rbd->v_data, "received"));			frames++;			/* Check if the packet is long enough to just accept			 * without copying to a properly sized skbuff.			 */			if (pkt_len > rx_copybreak) {				struct sk_buff *newskb;				dma_addr_t dma_addr;				pci_unmap_single(NULL,(dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, PCI_DMA_FROMDEVICE);				/* Get fresh skbuff to replace filled one. */				newskb = dev_alloc_skb(PKT_BUF_SZ + 4);				if (newskb == NULL) {					skb = NULL;	/* drop pkt */					goto memory_squeeze;				}				skb_reserve(newskb, 2);				/* Pass up the skb already on the Rx ring. */				skb_put(skb, pkt_len);				rx_in_place = 1;				rbd->skb = newskb;				newskb->dev = dev;				dma_addr = pci_map_single(NULL, newskb->tail, PKT_BUF_SZ, PCI_DMA_FROMDEVICE);				rbd->v_data = newskb->tail;				rbd->b_data = WSWAPchar(dma_addr);				CHECK_WBACK_INV(rbd, sizeof(struct i596_rbd));			}			else				skb = dev_alloc_skb(pkt_len + 2);memory_squeeze:			if (skb == NULL) {				/* XXX tulip.c can defer packets here!! */				printk ("%s: i596_rx Memory squeeze, dropping packet.\n", dev->name);				lp->stats.rx_dropped++;			}			else {				skb->dev = dev;				if (!rx_in_place) {					/* 16 byte align the data fields */					pci_dma_sync_single(NULL, (dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, PCI_DMA_FROMDEVICE);					skb_reserve(skb, 2);					memcpy(skb_put(skb,pkt_len), rbd->v_data, pkt_len);				}				skb->len = pkt_len;				skb->protocol=eth_type_trans(skb,dev);				netif_rx(skb);				lp->stats.rx_packets++;				lp->stats.rx_bytes+=pkt_len;			}		}		else {			DEB(DEB_ERRORS, printk("%s: Error, rfd.stat = 0x%04x\n",					dev->name, rfd->stat));			lp->stats.rx_errors++;			if ((rfd->stat) & 0x0001)				lp->stats.collisions++;			if ((rfd->stat) & 0x0080)				lp->stats.rx_length_errors++;			if ((rfd->stat) & 0x0100)				lp->stats.rx_over_errors++;			if ((rfd->stat) & 0x0200)				lp->stats.rx_fifo_errors++;			if ((rfd->stat) & 0x0400)				lp->stats.rx_frame_errors++;			if ((rfd->stat) & 0x0800)				lp->stats.rx_crc_errors++;			if ((rfd->stat) & 0x1000)				lp->stats.rx_length_errors++;		}		/* Clear the buffer descriptor count and EOF + F flags */		if (rbd != I596_NULL && (rbd->count & 0x4000)) {			rbd->count = 0;			lp->rbd_head = rbd->v_next;			CHECK_WBACK_INV(rbd, sizeof(struct i596_rbd));		}		/* Tidy the frame descriptor, marking it as end of list */		rfd->rbd = I596_NULL;		rfd->stat = 0;		rfd->cmd = CMD_EOL|CMD_FLEX;		rfd->count = 0;		/* Remove end-of-list from old end descriptor */		rfd->v_prev->cmd = CMD_FLEX;		/* Update record of next frame descriptor to process */		lp->scb.rfd = rfd->b_next;		lp->rfd_head = rfd->v_next;		CHECK_WBACK_INV(rfd->v_prev, sizeof(struct i596_rfd));		CHECK_WBACK_INV(rfd, sizeof(struct i596_rfd));		rfd = lp->rfd_head;		CHECK_INV(rfd, sizeof(struct i596_rfd));	}	DEB(DEB_RXFRAME,printk ("frames %d\n", frames));	return 0;}static inline void i596_cleanup_cmd(struct net_device *dev, struct i596_private *lp){	struct i596_cmd *ptr;	while (lp->cmd_head != I596_NULL) {		ptr = lp->cmd_head;		lp->cmd_head = ptr->v_next;		lp->cmd_backlog--;		switch ((ptr->command) & 0x7) {		case CmdTx:			{				struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;				struct sk_buff *skb = tx_cmd->skb;				pci_unmap_single(NULL, tx_cmd->dma_addr, skb->len, PCI_DMA_TODEVICE);				dev_kfree_skb(skb);				lp->stats.tx_errors++;				lp->stats.tx_aborted_errors++;				ptr->v_next = ptr->b_next = I596_NULL;				tx_cmd->cmd.command = 0;  /* Mark as free */				break;			}		default:			ptr->v_next = ptr->b_next = I596_NULL;		}		CHECK_WBACK_INV(ptr, sizeof(struct i596_cmd));	}	wait_cmd(dev,lp,100,"i596_cleanup_cmd timed out");	lp->scb.cmd = I596_NULL;	CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb));}static inline void i596_reset(struct net_device *dev, struct i596_private *lp, int ioaddr){	unsigned long flags;	DEB(DEB_RESET,printk("i596_reset\n"));	spin_lock_irqsave (&lp->lock, flags);	wait_cmd(dev,lp,100,"i596_reset timed out");	netif_stop_queue(dev);	/* FIXME: this command might cause an lpmc */	lp->scb.command = CUC_ABORT | RX_ABORT;	CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb));	CA(dev);	/* wait for shutdown */	wait_cmd(dev,lp,1000,"i596_reset 2 timed out");	spin_unlock_irqrestore (&lp->lock, flags);	i596_cleanup_cmd(dev,lp);	i596_rx(dev);	netif_start_queue(dev);	init_i596_mem(dev);}static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd){	struct i596_private *lp = (struct i596_private *) dev->priv;	int ioaddr = dev->base_addr;	unsigned long flags;	DEB(DEB_ADDCMD,printk("i596_add_cmd cmd_head %p\n", lp->cmd_head));	cmd->status = 0;	cmd->command |= (CMD_EOL | CMD_INTR);	cmd->v_next = cmd->b_next = I596_NULL;	CHECK_WBACK(cmd, sizeof(struct i596_cmd));	spin_lock_irqsave (&lp->lock, flags);	if (lp->cmd_head != I596_NULL) {		lp->cmd_tail->v_next = cmd;		lp->cmd_tail->b_next = WSWAPcmd(virt_to_dma(lp,&cmd->status));		CHECK_WBACK(lp->cmd_tail, sizeof(struct i596_cmd));	} else {		lp->cmd_head = cmd;		wait_cmd(dev,lp,100,"i596_add_cmd timed out");		lp->scb.cmd = WSWAPcmd(virt_to_dma(lp,&cmd->status));		lp->scb.command = CUC_START;		CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb));		CA(dev);	}	lp->cmd_tail = cmd;	lp->cmd_backlog++;	spin_unlock_irqrestore (&lp->lock, flags);	if (lp->cmd_backlog > max_cmd_backlog) {		unsigned long tickssofar = jiffies - lp->last_cmd;		if (tickssofar < ticks_limit)			return;		printk("%s: command unit timed out, status resetting.\n", dev->name);#if 1		i596_reset(dev, lp, ioaddr);#endif	}}#if 0/* this function makes a perfectly adequate probe...  but we have a   device list */static int i596_test(struct net_device *dev){	struct i596_private *lp = (struct i596_private *) dev->priv;	volatile int *tint;	u32 data;	tint = (volatile int *)(&(lp->scp));	data = virt_to_dma(lp,tint);		tint[1] = -1;	CHECK_WBACK(tint,PAGE_SIZE);	MPU_PORT(dev, 1, data);	for(data = 1000000; data; data--) {		CHECK_INV(tint,PAGE_SIZE);		if(tint[1] != -1)			break;	}	printk("i596_test result %d\n", tint[1]);}#endifstatic int i596_open(struct net_device *dev){	int res = 0;	DEB(DEB_OPEN,printk("%s: i596_open() irq %d.\n", dev->name, dev->irq));	if (request_irq(dev->irq, &i596_interrupt, 0, "i82596", dev)) {		printk("%s: IRQ %d not free\n", dev->name, dev->irq);		return -EAGAIN;	}	request_region(dev->base_addr, 12, dev->name);	init_rx_bufs(dev);	netif_start_queue(dev);	MOD_INC_USE_COUNT;	/* Initialize the 82596 memory */	if (init_i596_mem(dev)) {		res = -EAGAIN;		free_irq(dev->irq, dev);	}	return res;}static void i596_tx_timeout (struct net_device *dev){	struct i596_private *lp = (struct i596_private *) dev->priv;	int ioaddr = dev->base_addr;	/* Transmitter timeout, serious problems. */	DEB(DEB_ERRORS,printk("%s: transmit timed out, status resetting.\n",			dev->name));	lp->stats.tx_errors++;	/* Try to restart the adaptor */	if (lp->last_restart == lp->stats.tx_packets) {		DEB(DEB_ERRORS,printk ("Resetting board.\n"));

⌨️ 快捷键说明

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