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

📄 ni65.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			}		}		if(cards[i].vendor_id) {			for(j=0;j<3;j++)				if(inb(ioaddr+cards[i].addr_offset+j) != cards[i].vendor_id[j]) {					release_region(ioaddr, cards[i].total_size);					continue;			  }		}		break;	}	if(i == NUM_CARDS)		return -ENODEV;	for(j=0;j<6;j++)		dev->dev_addr[j] = inb(ioaddr+cards[i].addr_offset+j);	if( (j=ni65_alloc_buffer(dev)) < 0) {		release_region(ioaddr, cards[i].total_size);		return j;	}	p = (struct priv *) dev->priv;	p->cmdr_addr = ioaddr + cards[i].cmd_offset;	p->cardno = i;	spin_lock_init(&p->ring_lock);	printk(KERN_INFO "%s: %s found at %#3x, ", dev->name, cards[p->cardno].cardname , ioaddr);	outw(inw(PORT+L_RESET),PORT+L_RESET); /* first: reset the card */	if( (j=readreg(CSR0)) != 0x4) {		 printk("failed.\n");		 printk(KERN_ERR "%s: Can't RESET card: %04x\n", dev->name, j);		 ni65_free_buffer(p);		 release_region(ioaddr, cards[p->cardno].total_size);		 return -EAGAIN;	}	outw(88,PORT+L_ADDRREG);	if(inw(PORT+L_ADDRREG) == 88) {		unsigned long v;		v = inw(PORT+L_DATAREG);		v <<= 16;		outw(89,PORT+L_ADDRREG);		v |= inw(PORT+L_DATAREG);		printk("Version %#08lx, ",v);		p->features = INIT_RING_BEFORE_START;	}	else {		printk("ancient LANCE, ");		p->features = 0x0;	}	if(test_bit(0,&cards[i].config)) {		dev->irq = irqtab[(inw(ioaddr+L_CONFIG)>>2)&3];		dev->dma = dmatab[inw(ioaddr+L_CONFIG)&3];		printk("IRQ %d (from card), DMA %d (from card).\n",dev->irq,dev->dma);	}	else {		if(dev->dma == 0) {		/* 'stuck test' from lance.c */			long dma_channels = ((inb(DMA1_STAT_REG) >> 4) & 0x0f) |					    (inb(DMA2_STAT_REG) & 0xf0);			for(i=1;i<5;i++) {				int dma = dmatab[i];				if(test_bit(dma,&dma_channels) || request_dma(dma,"ni6510"))					continue;				flags=claim_dma_lock();				disable_dma(dma);				set_dma_mode(dma,DMA_MODE_CASCADE);				enable_dma(dma);				release_dma_lock(flags);				ni65_init_lance(p,dev->dev_addr,0,0); /* trigger memory access */				flags=claim_dma_lock();				disable_dma(dma);				free_dma(dma);				release_dma_lock(flags);				if(readreg(CSR0) & CSR0_IDON)					break;			}			if(i == 5) {				printk("failed.\n");				printk(KERN_ERR "%s: Can't detect DMA channel!\n", dev->name);				ni65_free_buffer(p);				release_region(ioaddr, cards[p->cardno].total_size);				return -EAGAIN;			}			dev->dma = dmatab[i];			printk("DMA %d (autodetected), ",dev->dma);		}		else			printk("DMA %d (assigned), ",dev->dma);		if(dev->irq < 2)		{			unsigned long irq_mask;			ni65_init_lance(p,dev->dev_addr,0,0);			irq_mask = probe_irq_on();			writereg(CSR0_INIT|CSR0_INEA,CSR0); /* trigger interrupt */			msleep(20);			dev->irq = probe_irq_off(irq_mask);			if(!dev->irq)			{				printk("Failed to detect IRQ line!\n");				ni65_free_buffer(p);				release_region(ioaddr, cards[p->cardno].total_size);				return -EAGAIN;			}			printk("IRQ %d (autodetected).\n",dev->irq);		}		else			printk("IRQ %d (assigned).\n",dev->irq);	}	if(request_dma(dev->dma, cards[p->cardno].cardname ) != 0)	{		printk(KERN_ERR "%s: Can't request dma-channel %d\n",dev->name,(int) dev->dma);		ni65_free_buffer(p);		release_region(ioaddr, cards[p->cardno].total_size);		return -EAGAIN;	}	dev->base_addr = ioaddr;	dev->open		= ni65_open;	dev->stop		= ni65_close;	dev->hard_start_xmit	= ni65_send_packet;	dev->tx_timeout		= ni65_timeout;	dev->watchdog_timeo	= HZ/2;	dev->get_stats		= ni65_get_stats;	dev->set_multicast_list = set_multicast_list;	return 0; /* everything is OK */}/* * set lance register and trigger init */static void ni65_init_lance(struct priv *p,unsigned char *daddr,int filter,int mode){	int i;	u32 pib;	writereg(CSR0_CLRALL|CSR0_STOP,CSR0);	for(i=0;i<6;i++)		p->ib.eaddr[i] = daddr[i];	for(i=0;i<8;i++)		p->ib.filter[i] = filter;	p->ib.mode = mode;	p->ib.trp = (u32) isa_virt_to_bus(p->tmdhead) | TMDNUMMASK;	p->ib.rrp = (u32) isa_virt_to_bus(p->rmdhead) | RMDNUMMASK;	writereg(0,CSR3);	/* busmaster/no word-swap */	pib = (u32) isa_virt_to_bus(&p->ib);	writereg(pib & 0xffff,CSR1);	writereg(pib >> 16,CSR2);	writereg(CSR0_INIT,CSR0); /* this changes L_ADDRREG to CSR0 */	for(i=0;i<32;i++)	{		mdelay(4);		if(inw(PORT+L_DATAREG) & (CSR0_IDON | CSR0_MERR) )			break; /* init ok ? */	}}/* * allocate memory area and check the 16MB border */static void *ni65_alloc_mem(struct net_device *dev,char *what,int size,int type){	struct sk_buff *skb=NULL;	unsigned char *ptr;	void *ret;	if(type) {		ret = skb = alloc_skb(2+16+size,GFP_KERNEL|GFP_DMA);		if(!skb) {			printk(KERN_WARNING "%s: unable to allocate %s memory.\n",dev->name,what);			return NULL;		}		skb_reserve(skb,2+16);		skb_put(skb,R_BUF_SIZE);	 /* grab the whole space .. (not necessary) */		ptr = skb->data;	}	else {		ret = ptr = kmalloc(T_BUF_SIZE,GFP_KERNEL | GFP_DMA);		if(!ret) {			printk(KERN_WARNING "%s: unable to allocate %s memory.\n",dev->name,what);			return NULL;		}	}	if( (u32) virt_to_phys(ptr+size) > 0x1000000) {		printk(KERN_WARNING "%s: unable to allocate %s memory in lower 16MB!\n",dev->name,what);		if(type)			kfree_skb(skb);		else			kfree(ptr);		return NULL;	}	return ret;}/* * allocate all memory structures .. send/recv buffers etc ... */static int ni65_alloc_buffer(struct net_device *dev){	unsigned char *ptr;	struct priv *p;	int i;	/*	 * we need 8-aligned memory ..	 */	ptr = ni65_alloc_mem(dev,"BUFFER",sizeof(struct priv)+8,0);	if(!ptr)		return -ENOMEM;	p = dev->priv = (struct priv *) (((unsigned long) ptr + 7) & ~0x7);	memset((char *) dev->priv,0,sizeof(struct priv));	p->self = ptr;	for(i=0;i<TMDNUM;i++)	{#ifdef XMT_VIA_SKB		p->tmd_skb[i] = NULL;#endif		p->tmdbounce[i] = ni65_alloc_mem(dev,"XMIT",T_BUF_SIZE,0);		if(!p->tmdbounce[i]) {			ni65_free_buffer(p);			return -ENOMEM;		}	}	for(i=0;i<RMDNUM;i++)	{#ifdef RCV_VIA_SKB		p->recv_skb[i] = ni65_alloc_mem(dev,"RECV",R_BUF_SIZE,1);		if(!p->recv_skb[i]) {			ni65_free_buffer(p);			return -ENOMEM;		}#else		p->recvbounce[i] = ni65_alloc_mem(dev,"RECV",R_BUF_SIZE,0);		if(!p->recvbounce[i]) {			ni65_free_buffer(p);			return -ENOMEM;		}#endif	}	return 0; /* everything is OK */}/* * free buffers and private struct */static void ni65_free_buffer(struct priv *p){	int i;	if(!p)		return;	for(i=0;i<TMDNUM;i++) {		kfree(p->tmdbounce[i]);#ifdef XMT_VIA_SKB		if(p->tmd_skb[i])			dev_kfree_skb(p->tmd_skb[i]);#endif	}	for(i=0;i<RMDNUM;i++)	{#ifdef RCV_VIA_SKB		if(p->recv_skb[i])			dev_kfree_skb(p->recv_skb[i]);#else		kfree(p->recvbounce[i]);#endif	}	kfree(p->self);}/* * stop and (re)start lance .. e.g after an error */static void ni65_stop_start(struct net_device *dev,struct priv *p){	int csr0 = CSR0_INEA;	writedatareg(CSR0_STOP);	if(debuglevel > 1)		printk(KERN_DEBUG "ni65_stop_start\n");	if(p->features & INIT_RING_BEFORE_START) {		int i;#ifdef XMT_VIA_SKB		struct sk_buff *skb_save[TMDNUM];#endif		unsigned long buffer[TMDNUM];		short blen[TMDNUM];		if(p->xmit_queued) {			while(1) {				if((p->tmdhead[p->tmdlast].u.s.status & XMIT_OWN))					break;				p->tmdlast = (p->tmdlast + 1) & (TMDNUM-1);				if(p->tmdlast == p->tmdnum)					break;			}		}		for(i=0;i<TMDNUM;i++) {			struct tmd *tmdp = p->tmdhead + i;#ifdef XMT_VIA_SKB			skb_save[i] = p->tmd_skb[i];#endif			buffer[i] = (u32) isa_bus_to_virt(tmdp->u.buffer);			blen[i] = tmdp->blen;			tmdp->u.s.status = 0x0;		}		for(i=0;i<RMDNUM;i++) {			struct rmd *rmdp = p->rmdhead + i;			rmdp->u.s.status = RCV_OWN;		}		p->tmdnum = p->xmit_queued = 0;		writedatareg(CSR0_STRT | csr0);		for(i=0;i<TMDNUM;i++) {			int num = (i + p->tmdlast) & (TMDNUM-1);			p->tmdhead[i].u.buffer = (u32) isa_virt_to_bus((char *)buffer[num]); /* status is part of buffer field */			p->tmdhead[i].blen = blen[num];			if(p->tmdhead[i].u.s.status & XMIT_OWN) {				 p->tmdnum = (p->tmdnum + 1) & (TMDNUM-1);				 p->xmit_queued = 1;	 writedatareg(CSR0_TDMD | CSR0_INEA | csr0);			}#ifdef XMT_VIA_SKB			p->tmd_skb[i] = skb_save[num];#endif		}		p->rmdnum = p->tmdlast = 0;		if(!p->lock)			if (p->tmdnum || !p->xmit_queued)				netif_wake_queue(dev);		dev->trans_start = jiffies;	}	else		writedatareg(CSR0_STRT | csr0);}/* * init lance (write init-values .. init-buffers) (open-helper) */static int ni65_lance_reinit(struct net_device *dev){	 int i;	 struct priv *p = (struct priv *) dev->priv;	 unsigned long flags;	 p->lock = 0;	 p->xmit_queued = 0;	 flags=claim_dma_lock();	 disable_dma(dev->dma); /* I've never worked with dma, but we do it like the packetdriver */	 set_dma_mode(dev->dma,DMA_MODE_CASCADE);	 enable_dma(dev->dma);	 release_dma_lock(flags);	 outw(inw(PORT+L_RESET),PORT+L_RESET); /* first: reset the card */	 if( (i=readreg(CSR0) ) != 0x4)	 {		 printk(KERN_ERR "%s: can't RESET %s card: %04x\n",dev->name,							cards[p->cardno].cardname,(int) i);		 flags=claim_dma_lock();		 disable_dma(dev->dma);		 release_dma_lock(flags);		 return 0;	 }	 p->rmdnum = p->tmdnum = p->tmdlast = p->tmdbouncenum = 0;	 for(i=0;i<TMDNUM;i++)	 {		 struct tmd *tmdp = p->tmdhead + i;#ifdef XMT_VIA_SKB		 if(p->tmd_skb[i]) {			 dev_kfree_skb(p->tmd_skb[i]);			 p->tmd_skb[i] = NULL;		 }#endif		 tmdp->u.buffer = 0x0;		 tmdp->u.s.status = XMIT_START | XMIT_END;		 tmdp->blen = tmdp->status2 = 0;	 }	 for(i=0;i<RMDNUM;i++)	 {		 struct rmd *rmdp = p->rmdhead + i;#ifdef RCV_VIA_SKB		 rmdp->u.buffer = (u32) isa_virt_to_bus(p->recv_skb[i]->data);#else		 rmdp->u.buffer = (u32) isa_virt_to_bus(p->recvbounce[i]);#endif		 rmdp->blen = -(R_BUF_SIZE-8);		 rmdp->mlen = 0;		 rmdp->u.s.status = RCV_OWN;	 }	 if(dev->flags & IFF_PROMISC)		 ni65_init_lance(p,dev->dev_addr,0x00,M_PROM);	 else if(dev->mc_count || dev->flags & IFF_ALLMULTI)		 ni65_init_lance(p,dev->dev_addr,0xff,0x0);	 else		 ni65_init_lance(p,dev->dev_addr,0x00,0x00);

⌨️ 快捷键说明

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