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

📄 rrunner.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 3 页
字号:
				dev_kfree_skb(rrpriv->rx_skbuff[i]);				rrpriv->rx_skbuff[i] = NULL;			}		}		if (rr_init1(dev)) {			spin_lock_irqsave(&rrpriv->lock, flags);			writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT, 			       &regs->HostCtrl);			spin_unlock_irqrestore(&rrpriv->lock, flags);		}	}	rrpriv->timer.expires = RUN_AT(5*HZ);	add_timer(&rrpriv->timer);}static int rr_open(struct net_device *dev){	struct rr_private *rrpriv;	struct rr_regs *regs;	int ecode = 0;	unsigned long flags;	rrpriv = (struct rr_private *)dev->priv;	regs = rrpriv->regs;	if (rrpriv->fw_rev < 0x00020000) {		printk(KERN_WARNING "%s: trying to configure device with "		       "obsolete firmware\n", dev->name);		ecode = -EBUSY;		goto error;	}	rrpriv->rx_ctrl = kmalloc(256*sizeof(struct ring_ctrl), GFP_KERNEL);	if (!rrpriv->rx_ctrl) {		ecode = -ENOMEM;		goto error;	}	rrpriv->info = kmalloc(sizeof(struct rr_info), GFP_KERNEL);	if (!rrpriv->info){		rrpriv->rx_ctrl = NULL;		ecode = -ENOMEM;		goto error;	}	memset(rrpriv->rx_ctrl, 0, 256 * sizeof(struct ring_ctrl));	memset(rrpriv->info, 0, sizeof(struct rr_info));	wmb();	spin_lock_irqsave(&rrpriv->lock, flags);	writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT, &regs->HostCtrl);	spin_unlock_irqrestore(&rrpriv->lock, flags);	if (request_irq(dev->irq, rr_interrupt, SA_SHIRQ, rrpriv->name, dev))	{		printk(KERN_WARNING "%s: Requested IRQ %d is busy\n",		       dev->name, dev->irq);		ecode = -EAGAIN;		goto error;	}	if ((ecode = rr_init1(dev)))		goto error;	/* Set the timer to switch to check for link beat and perhaps switch	   to an alternate media type. */	init_timer(&rrpriv->timer);	rrpriv->timer.expires = RUN_AT(5*HZ);           /* 5 sec. watchdog */	rrpriv->timer.data = (unsigned long)dev;	rrpriv->timer.function = &rr_timer;               /* timer handler */	add_timer(&rrpriv->timer);	netif_start_queue(dev);	MOD_INC_USE_COUNT;	return ecode; error:	spin_lock_irqsave(&rrpriv->lock, flags);	writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT, &regs->HostCtrl);	spin_unlock_irqrestore(&rrpriv->lock, flags);	if (rrpriv->info) {		kfree(rrpriv->info);		rrpriv->info = NULL;	}	if (rrpriv->rx_ctrl) {		kfree(rrpriv->rx_ctrl);		rrpriv->rx_ctrl = NULL;	}	netif_stop_queue(dev);	rr_if_down(dev);		return ecode;}static void rr_dump(struct net_device *dev){	struct rr_private *rrpriv;	struct rr_regs *regs;	u32 index, cons;	short i;	int len;	rrpriv = (struct rr_private *)dev->priv;	regs = rrpriv->regs;	printk("%s: dumping NIC TX rings\n", dev->name);	printk("RxPrd %08x, TxPrd %02x, EvtPrd %08x, TxPi %02x, TxCtrlPi %02x\n",	       readl(&regs->RxPrd), readl(&regs->TxPrd),	       readl(&regs->EvtPrd), readl(&regs->TxPi),	       rrpriv->info->tx_ctrl.pi);	printk("Error code 0x%x\n", readl(&regs->Fail1));	index = (((readl(&regs->EvtPrd) >> 8) & 0xff ) - 1) % EVT_RING_ENTRIES;	cons = rrpriv->dirty_tx;	printk("TX ring index %i, TX consumer %i\n",	       index, cons);	if (rrpriv->tx_skbuff[index]){		len = min(0x80, rrpriv->tx_skbuff[index]->len);		printk("skbuff for index %i is valid - dumping data (0x%x bytes - DMA len 0x%x)\n", index, len, rrpriv->tx_ring[index].size);		for (i = 0; i < len; i++){			if (!(i & 7))				printk("\n");			printk("%02x ", (unsigned char) rrpriv->tx_skbuff[index]->data[i]);		}		printk("\n");	}	if (rrpriv->tx_skbuff[cons]){		len = min(0x80, rrpriv->tx_skbuff[cons]->len);		printk("skbuff for cons %i is valid - dumping data (0x%x bytes - skbuff len 0x%x)\n", cons, len, rrpriv->tx_skbuff[cons]->len);		printk("mode 0x%x, size 0x%x,\n phys %08x (virt %08lx), skbuff-addr %08lx, truesize 0x%x\n",		       rrpriv->tx_ring[cons].mode,		       rrpriv->tx_ring[cons].size,		       rrpriv->tx_ring[cons].addr.addrlo,		       (unsigned long)bus_to_virt(rrpriv->tx_ring[cons].addr.addrlo),		       (unsigned long)rrpriv->tx_skbuff[cons]->data,		       (unsigned int)rrpriv->tx_skbuff[cons]->truesize);		for (i = 0; i < len; i++){			if (!(i & 7))				printk("\n");			printk("%02x ", (unsigned char)rrpriv->tx_ring[cons].size);		}		printk("\n");	}	printk("dumping TX ring info:\n");	for (i = 0; i < TX_RING_ENTRIES; i++)		printk("mode 0x%x, size 0x%x, phys-addr %08x\n",		       rrpriv->tx_ring[i].mode,		       rrpriv->tx_ring[i].size,		       rrpriv->tx_ring[i].addr.addrlo);}static int rr_close(struct net_device *dev){	struct rr_private *rrpriv;	struct rr_regs *regs;	u32 tmp;	short i;	netif_stop_queue(dev);	rr_if_down(dev);		rrpriv = (struct rr_private *)dev->priv;	regs = rrpriv->regs;	/*	 * Lock to make sure we are not cleaning up while another CPU	 * handling interrupts.	 */	spin_lock(&rrpriv->lock);	tmp = readl(&regs->HostCtrl);	if (tmp & NIC_HALTED){		printk("%s: NIC already halted\n", dev->name);		rr_dump(dev);	}else{		tmp |= HALT_NIC | RR_CLEAR_INT;		writel(tmp, &regs->HostCtrl);		wmb();	}	rrpriv->fw_running = 0;	del_timer(&rrpriv->timer);	writel(0, &regs->TxPi);	writel(0, &regs->IpRxPi);	writel(0, &regs->EvtCon);	writel(0, &regs->EvtPrd);	for (i = 0; i < CMD_RING_ENTRIES; i++)		writel(0, &regs->CmdRing[i]);	rrpriv->info->tx_ctrl.entries = 0;	rrpriv->info->cmd_ctrl.pi = 0;	rrpriv->info->evt_ctrl.pi = 0;	rrpriv->rx_ctrl[4].entries = 0;	for (i = 0; i < TX_RING_ENTRIES; i++) {		if (rrpriv->tx_skbuff[i]) {			rrpriv->tx_ring[i].size = 0;			set_rraddr(&rrpriv->tx_ring[i].addr, 0);			dev_kfree_skb(rrpriv->tx_skbuff[i]);			rrpriv->tx_skbuff[i] = NULL;		}	}	for (i = 0; i < RX_RING_ENTRIES; i++) {		if (rrpriv->rx_skbuff[i]) {			rrpriv->rx_ring[i].size = 0;			set_rraddr(&rrpriv->rx_ring[i].addr, 0);			dev_kfree_skb(rrpriv->rx_skbuff[i]);			rrpriv->rx_skbuff[i] = NULL;		}	}	if (rrpriv->rx_ctrl) {		kfree(rrpriv->rx_ctrl);		rrpriv->rx_ctrl = NULL;	}	if (rrpriv->info) {		kfree(rrpriv->info);		rrpriv->info = NULL;	}	free_irq(dev->irq, dev);	spin_unlock(&rrpriv->lock);	MOD_DEC_USE_COUNT;	return 0;}static int rr_start_xmit(struct sk_buff *skb, struct net_device *dev){	struct rr_private *rrpriv = (struct rr_private *)dev->priv;	struct rr_regs *regs = rrpriv->regs;	struct ring_ctrl *txctrl;	unsigned long flags;	u32 index, len = skb->len;	u32 *ifield;	struct sk_buff *new_skb;	if (readl(&regs->Mode) & FATAL_ERR)		printk("error codes Fail1 %02x, Fail2 %02x\n",		       readl(&regs->Fail1), readl(&regs->Fail2));	/*	 * We probably need to deal with tbusy here to prevent overruns.	 */	if (skb_headroom(skb) < 8){		printk("incoming skb too small - reallocating\n");		if (!(new_skb = dev_alloc_skb(len + 8))) {			dev_kfree_skb(skb);			netif_wake_queue(dev);			return -EBUSY;		}		skb_reserve(new_skb, 8);		skb_put(new_skb, len);		memcpy(new_skb->data, skb->data, len);		dev_kfree_skb(skb);		skb = new_skb;	}	ifield = (u32 *)skb_push(skb, 8);	ifield[0] = 0;	ifield[1] = skb->private.ifield;	/*	 * We don't need the lock before we are actually going to start	 * fiddling with the control blocks.	 */	spin_lock_irqsave(&rrpriv->lock, flags);	txctrl = &rrpriv->info->tx_ctrl;	index = txctrl->pi;	rrpriv->tx_skbuff[index] = skb;	set_rraddr(&rrpriv->tx_ring[index].addr, skb->data);	rrpriv->tx_ring[index].size = len + 8; /* include IFIELD */	rrpriv->tx_ring[index].mode = PACKET_START | PACKET_END;	txctrl->pi = (index + 1) % TX_RING_ENTRIES;	wmb();	writel(txctrl->pi, &regs->TxPi);	if (txctrl->pi == rrpriv->dirty_tx){		rrpriv->tx_full = 1;		netif_stop_queue(dev);	}	spin_unlock_irqrestore(&rrpriv->lock, flags);	dev->trans_start = jiffies;	return 0;}static struct net_device_stats *rr_get_stats(struct net_device *dev){	struct rr_private *rrpriv;	rrpriv = (struct rr_private *)dev->priv;	return(&rrpriv->stats);}/* * Read the firmware out of the EEPROM and put it into the SRAM * (or from user space - later) * * This operation requires the NIC to be halted and is performed with * interrupts disabled and with the spinlock hold. */static int rr_load_firmware(struct net_device *dev){	struct rr_private *rrpriv;	struct rr_regs *regs;	unsigned long eptr, segptr;	int i, j;	u32 localctrl, sptr, len, tmp;	u32 p2len, p2size, nr_seg, revision, io, sram_size;	struct eeprom *hw = NULL;	rrpriv = (struct rr_private *)dev->priv;	regs = rrpriv->regs;	if (dev->flags & IFF_UP)		return -EBUSY;	if (!(readl(&regs->HostCtrl) & NIC_HALTED)){		printk("%s: Trying to load firmware to a running NIC.\n", 		       dev->name);		return -EBUSY;	}	localctrl = readl(&regs->LocalCtrl);	writel(0, &regs->LocalCtrl);	writel(0, &regs->EvtPrd);	writel(0, &regs->RxPrd);	writel(0, &regs->TxPrd);	/*	 * First wipe the entire SRAM, otherwise we might run into all	 * kinds of trouble ... sigh, this took almost all afternoon	 * to track down ;-(	 */	io = readl(&regs->ExtIo);	writel(0, &regs->ExtIo);	sram_size = rr_read_eeprom_word(rrpriv, (void *)8);	for (i = 200; i < sram_size / 4; i++){		writel(i * 4, &regs->WinBase);		mb();		writel(0, &regs->WinData);		mb();	}	writel(io, &regs->ExtIo);	mb();	eptr = (unsigned long)rr_read_eeprom_word(rrpriv,					       &hw->rncd_info.AddrRunCodeSegs);	eptr = ((eptr & 0x1fffff) >> 3);	p2len = rr_read_eeprom_word(rrpriv, (void *)(0x83*4));	p2len = (p2len << 2);	p2size = rr_read_eeprom_word(rrpriv, (void *)(0x84*4));	p2size = ((p2size & 0x1fffff) >> 3);	if ((eptr < p2size) || (eptr > (p2size + p2len))){		printk("%s: eptr is invalid\n", dev->name);		goto out;	}	revision = rr_read_eeprom_word(rrpriv, &hw->manf.HeaderFmt);	if (revision != 1){		printk("%s: invalid firmware format (%i)\n",		       dev->name, revision);		goto out;	}	nr_seg = rr_read_eeprom_word(rrpriv, (void *)eptr);	eptr +=4;#if (DEBUG > 1)	printk("%s: nr_seg %i\n", dev->name, nr_seg);#endif	for (i = 0; i < nr_seg; i++){		sptr = rr_read_eeprom_word(rrpriv, (void *)eptr);		eptr += 4;		len = rr_read_eeprom_word(rrpriv, (void *)eptr);		eptr += 4;		segptr = (unsigned long)rr_read_eeprom_word(rrpriv, (void *)eptr);		segptr = ((segptr & 0x1fffff) >> 3);		eptr += 4;#if (DEBUG > 1)		printk("%s: segment %i, sram address %06x, length %04x, segptr %06x\n",		       dev->name, i, sptr, len, segptr);#endif		for (j = 0; j < len; j++){			tmp = rr_read_eeprom_word(rrpriv, (void *)segptr);			writel(sptr, &regs->WinBase);			mb();			writel(tmp, &regs->WinData);			mb();			segptr += 4;			sptr += 4;		}	}out:	writel(localctrl, &regs->LocalCtrl);	mb();	return 0;}static int rr_ioctl(struct net_device *dev, struct ifreq *rq, int cmd){	struct rr_private *rrpriv;	unsigned char *image, *oldimage;	unsigned int i;	int error = -EOPNOTSUPP;	rrpriv = dev->priv;	switch(cmd){	case SIOCRRGFW:		if (!capable(CAP_SYS_RAWIO)){			return -EPERM;		}		image = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL);		if (!image){			printk(KERN_ERR "%s: Unable to allocate memory "			       "for EEPROM image\n", dev->name);			return -ENOMEM;		}				spin_lock(&rrpriv->lock);				if (rrpriv->fw_running){			printk("%s: Firmware already running\n", dev->name);			error = -EPERM;			goto out_spin;		}		i = rr_read_eeprom(rrpriv, 0, image, EEPROM_BYTES);		if (i != EEPROM_BYTES){			printk(KERN_ERR "%s: Error reading EEPROM\n", dev->name);			error = -EFAULT;			goto out_spin;		}		spin_unlock(&rrpriv->lock);		error = copy_to_user(rq->ifr_data, image, EEPROM_BYTES);		if (error)			error = -EFAULT;		kfree(image);		return error;			case SIOCRRPFW:		if (!capable(CAP_SYS_RAWIO)){			return -EPERM;		}		image = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL);		if (!image){			printk(KERN_ERR "%s: Unable to allocate memory "			       "for EEPROM image\n", dev->name);			return -ENOMEM;		}		oldimage = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL);		if (!oldimage){			kfree(image);			printk(KERN_ERR "%s: Unable to allocate memory "			       "for old EEPROM image\n", dev->name);			return -ENOMEM;		}		error = copy_from_user(image, rq->ifr_data, EEPROM_BYTES);		if (error) {			kfree(image);			kfree(oldimage);			return -EFAULT;		}		spin_lock(&rrpriv->lock);		if (rrpriv->fw_running){			kfree(oldimage);			printk("%s: Firmware already running\n", dev->name);			error = -EPERM;			goto out_spin;		}		printk("%s: Updating EEPROM firmware\n", dev->name);		error = write_eeprom(rrpriv, 0, image, EEPROM_BYTES);		if (error)			printk(KERN_ERR "%s: Error writing EEPROM\n",			       dev->name);		i = rr_read_eeprom(rrpriv, 0, oldimage, EEPROM_BYTES);		if (i != EEPROM_BYTES)			printk(KERN_ERR "%s: Error reading back EEPROM "			       "image\n", dev->name);		spin_unlock(&rrpriv->lock);		error = memcmp(image, oldimage, EEPROM_BYTES);		if (error){			printk(KERN_ERR "%s: Error verifying EEPROM image\n",			       dev->name);			error = -EFAULT;		}		kfree(image);		kfree(oldimage);		return error;			case SIOCRRID:		return put_user(0x52523032, (int *)(&rq->ifr_data[0]));	default:		return error;	} out_spin:	kfree(image);	spin_unlock(&rrpriv->lock);	return error;}/* * Local variables: * compile-command: "gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -pipe -fomit-frame-pointer -fno-strength-reduce -m486 -malign-loops=2 -malign-jumps=2 -malign-functions=2 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h -c rrunner.c" * End: */

⌨️ 快捷键说明

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