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

📄 ni52.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
			dev->mem_start = memaddrs[i];			size = 0x2000; /* check for 8K mem */			if(check586(dev,(char *)dev->mem_start,size)) /* 8K-check */				break;			size = 0x4000; /* check for 16K mem */			if(check586(dev,(char *)dev->mem_start,size)) /* 16K-check */				break;		}	}	dev->mem_end = dev->mem_start + size; /* set mem_end showed by 'ifconfig' */#endif	dev->priv = (void *) kmalloc(sizeof(struct priv),GFP_KERNEL);	if(dev->priv == NULL)	{		printk("%s: Ooops .. can't allocate private driver memory.\n",dev->name);		return -ENOMEM;	}																	/* warning: we don't free it on errors */	memset((char *) dev->priv,0,sizeof(struct priv));	((struct priv *) (dev->priv))->memtop = bus_to_virt(dev->mem_start) + size;	((struct priv *) (dev->priv))->base =	(unsigned long) bus_to_virt(dev->mem_start) + size - 0x01000000;	alloc586(dev);	/* set number of receive-buffs according to memsize */	if(size == 0x2000)		((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_8;	else		((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_16;	printk("Memaddr: 0x%lx, Memsize: %d, ",dev->mem_start,size);	if(dev->irq < 2)	{		autoirq_setup(0);		ni_reset586();		ni_attn586();		if(!(dev->irq = autoirq_report(2)))		{			printk("?autoirq, Failed to detect IRQ line!\n");			return 1;		}		printk("IRQ %d (autodetected).\n",dev->irq);	}	else	{		if(dev->irq == 2)			dev->irq = 9;		printk("IRQ %d (assigned and not checked!).\n",dev->irq);	}	dev->open		= &ni52_open;	dev->stop		= &ni52_close;	dev->get_stats		= &ni52_get_stats;	dev->hard_start_xmit 	= &ni52_send_packet;	dev->set_multicast_list = &set_multicast_list;	dev->if_port 		= 0;	ether_setup(dev);	dev->tbusy		= 0;	dev->interrupt		= 0;	dev->start		= 0;	return 0;}/********************************************** * init the chip (ni52-interrupt should be disabled?!) * needs a correct 'allocated' memory */static int init586(struct device *dev){	void *ptr;	int i,result=0;	struct priv *p = (struct priv *) dev->priv;	volatile struct configure_cmd_struct	*cfg_cmd;	volatile struct iasetup_cmd_struct *ias_cmd;	volatile struct tdr_cmd_struct *tdr_cmd;	volatile struct mcsetup_cmd_struct *mc_cmd;	struct dev_mc_list *dmi=dev->mc_list;	int num_addrs=dev->mc_count;	ptr = (void *) ((char *)p->scb + sizeof(struct scb_struct));	cfg_cmd = (struct configure_cmd_struct *)ptr; /* configure-command */	cfg_cmd->cmd_status	= 0;	cfg_cmd->cmd_cmd	= CMD_CONFIGURE | CMD_LAST;	cfg_cmd->cmd_link	= 0xffff;	cfg_cmd->byte_cnt	= 0x0a; /* number of cfg bytes */	cfg_cmd->fifo		= fifo; /* fifo-limit (8=tx:32/rx:64) */	cfg_cmd->sav_bf		= 0x40; /* hold or discard bad recv frames (bit 7) */	cfg_cmd->adr_len	= 0x2e; /* addr_len |!src_insert |pre-len |loopback */	cfg_cmd->priority	= 0x00;	cfg_cmd->ifs		= 0x60;	cfg_cmd->time_low	= 0x00;	cfg_cmd->time_high	= 0xf2;	cfg_cmd->promisc	= 0;	if(dev->flags & IFF_ALLMULTI) {		int len = ((char *) p->iscp - (char *) ptr - 8) / 6;		if(num_addrs > len)	{			printk("%s: switching to promisc. mode\n",dev->name);			dev->flags|=IFF_PROMISC;		}	}	if(dev->flags&IFF_PROMISC)	{			 cfg_cmd->promisc=1;			 dev->flags|=IFF_PROMISC;	}	cfg_cmd->carr_coll	= 0x00;	p->scb->cbl_offset	= make16(cfg_cmd);	p->scb->cmd_ruc		= 0;	p->scb->cmd_cuc		= CUC_START; /* cmd.-unit start */	ni_attn586();	WAIT_4_STAT_COMPL(cfg_cmd);	if((cfg_cmd->cmd_status & (STAT_OK|STAT_COMPL)) != (STAT_COMPL|STAT_OK))	{		printk("%s: configure command failed: %x\n",dev->name,cfg_cmd->cmd_status);		return 1;	}	/*	 * individual address setup	 */	ias_cmd = (struct iasetup_cmd_struct *)ptr;	ias_cmd->cmd_status	= 0;	ias_cmd->cmd_cmd	= CMD_IASETUP | CMD_LAST;	ias_cmd->cmd_link	= 0xffff;	memcpy((char *)&ias_cmd->iaddr,(char *) dev->dev_addr,ETH_ALEN);	p->scb->cbl_offset = make16(ias_cmd);	p->scb->cmd_cuc = CUC_START; /* cmd.-unit start */	ni_attn586();	WAIT_4_STAT_COMPL(ias_cmd);	if((ias_cmd->cmd_status & (STAT_OK|STAT_COMPL)) != (STAT_OK|STAT_COMPL)) {		printk("%s (ni52): individual address setup command failed: %04x\n",dev->name,ias_cmd->cmd_status);		return 1;	}	/*	 * TDR, wire check .. e.g. no resistor e.t.c	 */	 	tdr_cmd = (struct tdr_cmd_struct *)ptr;	tdr_cmd->cmd_status	= 0;	tdr_cmd->cmd_cmd	= CMD_TDR | CMD_LAST;	tdr_cmd->cmd_link	= 0xffff;	tdr_cmd->status		= 0;	p->scb->cbl_offset = make16(tdr_cmd);	p->scb->cmd_cuc = CUC_START; /* cmd.-unit start */	ni_attn586();	WAIT_4_STAT_COMPL(tdr_cmd);	if(!(tdr_cmd->cmd_status & STAT_COMPL))	{		printk("%s: Problems while running the TDR.\n",dev->name);	}	else	{		DELAY_16(); /* wait for result */		result = tdr_cmd->status;		p->scb->cmd_cuc = p->scb->cus & STAT_MASK;		ni_attn586(); /* ack the interrupts */		if(result & TDR_LNK_OK)			;		else if(result & TDR_XCVR_PRB)			printk("%s: TDR: Transceiver problem. Check the cable(s)!\n",dev->name);		else if(result & TDR_ET_OPN)			printk("%s: TDR: No correct termination %d clocks away.\n",dev->name,result & TDR_TIMEMASK);		else if(result & TDR_ET_SRT)		{			if (result & TDR_TIMEMASK) /* time == 0 -> strange :-) */				printk("%s: TDR: Detected a short circuit %d clocks away.\n",dev->name,result & TDR_TIMEMASK);		}		else			printk("%s: TDR: Unknown status %04x\n",dev->name,result);	}	/*	 * Multicast setup	 */	if(num_addrs && !(dev->flags & IFF_PROMISC) )	{		mc_cmd = (struct mcsetup_cmd_struct *) ptr;		mc_cmd->cmd_status = 0;		mc_cmd->cmd_cmd = CMD_MCSETUP | CMD_LAST;		mc_cmd->cmd_link = 0xffff;		mc_cmd->mc_cnt = num_addrs * 6;		for(i=0;i<num_addrs;i++,dmi=dmi->next)			memcpy((char *) mc_cmd->mc_list[i], dmi->dmi_addr,6);		p->scb->cbl_offset = make16(mc_cmd);		p->scb->cmd_cuc = CUC_START;		ni_attn586();		WAIT_4_STAT_COMPL(mc_cmd);		if( (mc_cmd->cmd_status & (STAT_COMPL|STAT_OK)) != (STAT_COMPL|STAT_OK) )			printk("%s: Can't apply multicast-address-list.\n",dev->name);	}	/*	 * alloc nop/xmit-cmds	 */#if (NUM_XMIT_BUFFS == 1)	for(i=0;i<2;i++)	{		p->nop_cmds[i] 			= (struct nop_cmd_struct *)ptr;		p->nop_cmds[i]->cmd_cmd		= CMD_NOP;		p->nop_cmds[i]->cmd_status 	= 0;		p->nop_cmds[i]->cmd_link	= make16((p->nop_cmds[i]));		ptr = (char *) ptr + sizeof(struct nop_cmd_struct);	}#else	for(i=0;i<NUM_XMIT_BUFFS;i++)	{		p->nop_cmds[i]			= (struct nop_cmd_struct *)ptr;		p->nop_cmds[i]->cmd_cmd		= CMD_NOP;		p->nop_cmds[i]->cmd_status	= 0;		p->nop_cmds[i]->cmd_link	= make16((p->nop_cmds[i]));		ptr = (char *) ptr + sizeof(struct nop_cmd_struct);	}#endif	ptr = alloc_rfa(dev,(void *)ptr); /* init receive-frame-area */	/*	 * alloc xmit-buffs / init xmit_cmds	 */	for(i=0;i<NUM_XMIT_BUFFS;i++)	{		p->xmit_cmds[i] = (struct transmit_cmd_struct *)ptr; /*transmit cmd/buff 0*/		ptr = (char *) ptr + sizeof(struct transmit_cmd_struct);		p->xmit_cbuffs[i] = (char *)ptr; /* char-buffs */		ptr = (char *) ptr + XMIT_BUFF_SIZE;		p->xmit_buffs[i] = (struct tbd_struct *)ptr; /* TBD */		ptr = (char *) ptr + sizeof(struct tbd_struct);		if((void *)ptr > (void *)p->iscp)		{			printk("%s: not enough shared-mem for your configuration!\n",dev->name);			return 1;		}		memset((char *)(p->xmit_cmds[i]) ,0, sizeof(struct transmit_cmd_struct));		memset((char *)(p->xmit_buffs[i]),0, sizeof(struct tbd_struct));		p->xmit_cmds[i]->cmd_link = make16(p->nop_cmds[(i+1)%NUM_XMIT_BUFFS]);		p->xmit_cmds[i]->cmd_status = STAT_COMPL;		p->xmit_cmds[i]->cmd_cmd = CMD_XMIT | CMD_INT;		p->xmit_cmds[i]->tbd_offset = make16((p->xmit_buffs[i]));		p->xmit_buffs[i]->next = 0xffff;		p->xmit_buffs[i]->buffer = make24((p->xmit_cbuffs[i]));	}	p->xmit_count = 0;	p->xmit_last	= 0;#ifndef NO_NOPCOMMANDS	p->nop_point	= 0;#endif	 /*		* 'start transmitter'		*/#ifndef NO_NOPCOMMANDS	p->scb->cbl_offset = make16(p->nop_cmds[0]);	p->scb->cmd_cuc = CUC_START;	ni_attn586();	WAIT_4_SCB_CMD();#else	p->xmit_cmds[0]->cmd_link = make16(p->xmit_cmds[0]);	p->xmit_cmds[0]->cmd_cmd	= CMD_XMIT | CMD_SUSPEND | CMD_INT;#endif	/*	 * ack. interrupts	 */	p->scb->cmd_cuc = p->scb->cus & STAT_MASK;	ni_attn586();	DELAY_16();	ni_enaint();	return 0;}/****************************************************** * This is a helper routine for ni52_rnr_int() and init586(). * It sets up the Receive Frame Area (RFA). */static void *alloc_rfa(struct device *dev,void *ptr){	volatile struct rfd_struct *rfd = (struct rfd_struct *)ptr;	volatile struct rbd_struct *rbd;	int i;	struct priv *p = (struct priv *) dev->priv;	memset((char *) rfd,0,sizeof(struct rfd_struct)*(p->num_recv_buffs+rfdadd));	p->rfd_first = rfd;	for(i = 0; i < (p->num_recv_buffs+rfdadd); i++) {		rfd[i].next = make16(rfd + (i+1) % (p->num_recv_buffs+rfdadd) );		rfd[i].rbd_offset = 0xffff;	}	rfd[p->num_recv_buffs-1+rfdadd].last = RFD_SUSP;	 /* RU suspend */	ptr = (void *) (rfd + (p->num_recv_buffs + rfdadd) );	rbd = (struct rbd_struct *) ptr;	ptr = (void *) (rbd + p->num_recv_buffs);	 /* clr descriptors */	memset((char *) rbd,0,sizeof(struct rbd_struct)*(p->num_recv_buffs));	for(i=0;i<p->num_recv_buffs;i++)	{		rbd[i].next = make16((rbd + (i+1) % p->num_recv_buffs));		rbd[i].size = RECV_BUFF_SIZE;		rbd[i].buffer = make24(ptr);		ptr = (char *) ptr + RECV_BUFF_SIZE;	}	p->rfd_top	= p->rfd_first;	p->rfd_last = p->rfd_first + (p->num_recv_buffs - 1 + rfdadd);	p->scb->rfa_offset		= make16(p->rfd_first);	p->rfd_first->rbd_offset	= make16(rbd);	return ptr;}/************************************************** * Interrupt Handler ... */static void ni52_interrupt(int irq,void *dev_id,struct pt_regs *reg_ptr){	struct device *dev = dev_id;	unsigned short stat;	int cnt=0;	struct priv *p;	if (!dev) {		printk ("ni5210-interrupt: irq %d for unknown device.\n",irq);		return;	}	p = (struct priv *) dev->priv;	if(debuglevel > 1)		printk("I");	dev->interrupt = 1;	WAIT_4_SCB_CMD(); /* wait for last command	*/	while((stat=p->scb->cus & STAT_MASK))	{		p->scb->cmd_cuc = stat;		ni_attn586();		if(stat & STAT_FR)	 /* received a frame */			ni52_rcv_int(dev);		if(stat & STAT_RNR) /* RU went 'not ready' */		{			printk("(R)");			if(p->scb->rus & RU_SUSPEND) /* special case: RU_SUSPEND */			{				WAIT_4_SCB_CMD();				p->scb->cmd_ruc = RUC_RESUME;				ni_attn586();				WAIT_4_SCB_CMD_RUC();			}			else			{				printk("%s: Receiver-Unit went 'NOT READY': %04x/%02x.\n",dev->name,(int) stat,(int) p->scb->rus);				ni52_rnr_int(dev);			}		}		if(stat & STAT_CX)		/* command with I-bit set complete */			 ni52_xmt_int(dev);#ifndef NO_NOPCOMMANDS		if(stat & STAT_CNA)	/* CU went 'not ready' */		{			if(dev->start)				printk("%s: oops! CU has left active state. stat: %04x/%02x.\n",dev->name,(int) stat,(int) p->scb->cus);		}#endif		if(debuglevel > 1)			printk("%d",cnt++);		WAIT_4_SCB_CMD(); /* wait for ack. (ni52_xmt_int can be faster than ack!!) */		if(p->scb->cmd_cuc)	 /* timed out? */		{			printk("%s: Acknowledge timed out.\n",dev->name);			ni_disint();			break;		}	}	if(debuglevel > 1)		printk("i");	dev->interrupt = 0;}/******************************************************* * receive-interrupt */static void ni52_rcv_int(struct device *dev){	int status,cnt=0;	unsigned short totlen;	struct sk_buff *skb;	struct rbd_struct *rbd;	struct priv *p = (struct priv *) dev->priv;	if(debuglevel > 0)		printk("R");	for(;(status = p->rfd_top->stat_high) & RFD_COMPL;)	{			rbd = (struct rbd_struct *) make32(p->rfd_top->rbd_offset);			if(status & RFD_OK) /* frame received without error? */			{				if( (totlen = rbd->status) & RBD_LAST) /* the first and the last buffer? */				{					totlen &= RBD_MASK; /* length of this frame */					rbd->status = 0;					skb = (struct sk_buff *) dev_alloc_skb(totlen+2);					if(skb != NULL)					{						skb->dev = dev;						skb_reserve(skb,2);						skb_put(skb,totlen);						eth_copy_and_sum(skb,(char *) p->base+(unsigned long) rbd->buffer,totlen,0);						skb->protocol=eth_type_trans(skb,dev);						netif_rx(skb);						p->stats.rx_packets++;

⌨️ 快捷键说明

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