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

📄 sbni.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
     	/* 	 *	Initialize the device structure. 	 */	dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);	if(dev->priv == NULL)	{		DP( printk("%s: cannot allocate memory\n", dev->name); )		free_irq(dev->irq, dev);		return -ENOMEM;	}   	memset(dev->priv, 0, sizeof(struct net_local));	dev->base_addr = ioaddr;	request_region(ioaddr, SBNI_IO_EXTENT, "sbni");	/* 	 * generate Ethernet address (0x00ff01xxxxxx)	 */	*(u16*)dev->dev_addr = htons(0x00ff);	*(u32*)(dev->dev_addr+2) = htonl(((def_mac ? def_mac : (u32) dev->priv) & 0x00ffffff) | 0x01000000);   	lp = dev->priv;	if(def_rxl < 0)	{		/* autodetect receive level */		lp->rxl_curr = 0xf;		lp->rxl_delta = -1;	} else {		/* fixed receive level */		lp->rxl_curr = def_rxl & 0xf;		lp->rxl_delta = 0;	}	lp->csr1.rxl = rxl_tab[lp->rxl_curr];	lp->csr1.rate = def_baud & 3;	lp->frame_len = DEF_FRAME_LEN;	printk("%s: sbni adapter at %#lx, using %sIRQ %d, MAC: 00:ff:01:%x:%x:%x\n", 		dev->name, dev->base_addr, autoirq ? "auto":"assigned ", dev->irq,	       *(unsigned char*)(dev->dev_addr+3),	       *(unsigned char*)(dev->dev_addr+4),	       *(unsigned char*)(dev->dev_addr+5)	);	printk("%s: receive level: ", dev->name);	if(lp->rxl_delta == 0)		printk ("%#1x (fixed)", lp->rxl_curr); 	else		printk ("autodetect");	printk(", baud rate: %u\n", (unsigned)lp->csr1.rate);   	/*	 *	The SBNI-specific entries in the device structure. 	 */	dev->open = &sbni_open;	dev->hard_start_xmit = &sbni_start_xmit;	dev->stop = &sbni_close;	dev->get_stats = &sbni_get_stats;	dev->set_multicast_list = &set_multicast_list;	dev->set_mac_address = &sbni_set_mac_address;	dev->do_ioctl = &sbni_ioctl;   	/*	 *	Setup the generic properties 	 */	ether_setup(dev);   	dev->hard_header = sbni_header;	dev->hard_header_len = sizeof(struct sbni_hard_header);	dev->rebuild_header=sbni_rebuild_header;	dev->mtu = DEF_FRAME_LEN;	dev->hard_header_cache = sbni_header_cache;	dev->header_cache_update = sbni_header_cache_update;    	spin_lock_init(&lp->lock);	lp->m=dev;	lp->me=dev;	lp->next_lp=NULL;  	return 0;}/* *	Open/initialize the board.  */static int sbni_open(struct net_device *dev){	struct net_local* lp = (struct net_local*)dev->priv;	struct timer_list* watchdog = &lp->watchdog;	unsigned long flags;         	DP( printk("%s: sbni_open\n", dev->name); )          	save_flags(flags);	cli();	lp->currframe = NULL;   	card_start(dev);	/* set timer  watchdog */	init_timer(watchdog);	watchdog->expires = jiffies + SBNI_TIMEOUT;	watchdog->data = (unsigned long)dev;	watchdog->function = sbni_watchdog;	add_timer(watchdog);	DP( printk("%s: sbni timer watchdog initialized\n", dev->name); );   	restore_flags(flags);	   	netif_start_queue(dev);	MOD_INC_USE_COUNT;	return 0;}static int sbni_close(struct net_device *dev){	int ioaddr = dev->base_addr;	struct net_local* lp = (struct net_local*) dev->priv;	struct timer_list* watchdog = &lp->watchdog;	unsigned long flags;		DP( printk("%s: sbni_close\n", dev->name); )	netif_stop_queue(dev);	save_flags(flags);	cli();	sbni_drop_tx_queue(dev);		del_timer(watchdog);	outb(0, ioaddr + CSR0);	restore_flags(flags);	MOD_DEC_USE_COUNT;	return 0;}static int sbni_start_xmit(struct sk_buff *skb, struct net_device *dev){	struct net_local *lp = (struct net_local*)dev->priv;	struct sbni_hard_header *hh=(struct sbni_hard_header *)skb->data;	unsigned long flags;  #ifdef KATYUSHA   	struct net_local *nl;	int stop;#endif  	DP( printk("%s: sbni_start_xmit In \n", dev->name); );    	if(lp->me != dev)		panic("sbni: lp->me != dev !!!\nMail to developer (xenon@granch.ru) if you noticed this error\n");  	hh->number = 1;	hh->reserv = 0;  	hh->packetlen =  (skb->len - sizeof (unsigned short) - 			(sizeof(struct sbni_hard_header) - SBNI_HH_SZ)) 			| PACKET_SEND_OK | PACKET_FIRST_FRAME;  	/* we should use hairy method to calculate crc because of extra bytes are 	  livin between hard header and data*/	hh->crc = calc_crc((void*)&hh->packetlen, SBNI_HH_SZ - sizeof(unsigned), CRC32_INITIAL);	hh->crc = calc_crc(skb->data + sizeof(struct sbni_hard_header),		       skb->len - sizeof(struct sbni_hard_header),		       hh->crc);    	spin_lock_irqsave(&lp->lock, flags);#ifdef KATYUSHA	/* looking for first idle device */	for (stop=0,nl=lp; nl && !stop; nl=nl->next_lp)	{		if((!nl->currframe) && (nl->carrier)) /* if idle */		{			skb->dev = lp->me;			nl->currframe = skb;			/* set request for transmit */			outb(inb(nl->me->base_addr + CSR0) | TR_REQ, 				nl->me->base_addr + CSR0);			stop=1;		}	}  	if(!stop) /* we havent found any idle.*/	{		skb_queue_tail(&lp->queue,skb);		outb(inb(dev->base_addr + CSR0) | TR_REQ, dev->base_addr + CSR0);      	}		#else 	if (lp->currframe || 1)	{		skb_queue_tail(&lp->queue,skb);		  	}	else	{		lp->currframe = skb;	}	/* set request for transmit */	outb(inb(dev->base_addr + CSR0) | TR_REQ, dev->base_addr + CSR0);#endif	spin_unlock_irqrestore(&lp->lock, flags);	return 0;}static void card_start(struct net_device *dev){	struct net_local *lp = (struct net_local*)dev->priv;   	DP( printk("%s: card_start\n",dev->name); )	lp->wait_frame_number = 0;	lp->inppos = lp->outpos = 0;	lp->eth_trans_buffer_len = 0;	lp->tr_err = TR_ERROR_COUNT;	lp->last_receive_OK = FALSE;	lp->tr_resend = FALSE;	lp->timer_ticks = CHANGE_LEVEL_START_TICKS;	lp->timeout_rxl = 0;	lp->waitack=0;	skb_queue_head_init(&lp->queue);	sbni_drop_tx_queue(dev);	/* Reset the card and set start parameters */	outb(PR_RES | *(char*)&lp->csr1, dev->base_addr + CSR1);	outb(EN_INT, dev->base_addr + CSR0);}void sbni_nirvana(struct net_device *dev){	sbni_outs(dev->base_addr+DAT,magic_reply,9);}static inline unsigned short sbni_recv(struct net_device *dev){	struct net_local *lp = (struct net_local*)dev->priv;	unsigned long crc;	unsigned short packetlen = 0;	unsigned short packetinf, packetfirst, receiveframeresend;	unsigned char current_frame;	unsigned int i, j;	unsigned char delme,rcv_res=RCV_WR;  	lp->in_stats.all_rx_number++;  	if((delme=inb(dev->base_addr + DAT)) == SBNI_SIG)	{		crc = CRC32_INITIAL;		*(((unsigned char *)&packetlen) + 0) = inb(dev->base_addr + DAT);		crc = CRC32(*(((unsigned char *)&packetlen) + 0), crc);		*(((unsigned char *)&packetlen) + 1) = inb(dev->base_addr + DAT);		crc = CRC32(*(((unsigned char *)&packetlen) + 1), crc);		packetinf = packetlen & PACKET_INF_MASK;		packetfirst = packetlen & PACKET_FIRST_FRAME;		receiveframeresend = packetlen & RECEIVE_FRAME_RESEND;		packetlen = packetlen & PACKET_LEN_MASK;        		if((packetlen <= SB_MAX_BUFFER_ARRAY - 3) && (packetlen >= 6))		{			/* read frame number */			current_frame = inb(dev->base_addr + DAT);			crc = CRC32(current_frame, crc);			/* read HandShake counter */			lp->HSCounter = inb(dev->base_addr + DAT);			crc = CRC32(lp->HSCounter, crc);			packetlen -= 2;      			sbni_ins(dev->base_addr + DAT, lp->eth_rcv_buffer + lp->inppos, packetlen);      			for(i = lp->inppos; i < (packetlen + lp->inppos); i++)			{				crc = CRC32(lp->eth_rcv_buffer[i], crc);			}      			if(crc == CRC32_REMAINDER)			{				if(packetlen > 4) 					rcv_res=RCV_OK;				else if(packetlen == 4) 					rcv_res=RCV_NO;      						if(lp->waitack && packetinf == PACKET_RESEND)					lp->in_stats.resend_tx_number++;						switch(packetinf)				{				case PACKET_SEND_OK:				{					lp->tr_err = TR_ERROR_COUNT;					lp->tr_resend = FALSE;					/* if(lp->trans_frame_number){ */					lp->outpos += lp->realframelen;	      					/* SendComplete					 * not supported					 */					DP( printk("%s: sbni_recv SendComplete\n",dev->name); );					/*					 *	We sucessfully sent current packet					 */	      					if(lp->waitack)					{						dev_kfree_skb(lp->currframe);						lp->stats.tx_packets++;#ifdef KATYUSHA						lp->currframe=skb_dequeue(&(((struct net_local*) (lp->m->priv))->queue));#else						lp->currframe=skb_dequeue(&lp->queue);#endif		       						lp->in_stats.all_tx_number++;						lp->waitack=0;					}	      					/*	      				 * reset output active flags					 */					netif_wake_queue(dev);					/*} if */				}				case PACKET_RESEND:				{					if(lp->tr_err) /**/						lp->tr_err--;					if(lp->ok_curr < 0xffffffff)						lp->ok_curr++;					if(packetlen > 4 && !(lp->last_receive_OK && receiveframeresend))					{						if(packetfirst)						{							if(lp->wait_frame_number)							{								for(i = lp->inppos, j = 0; 									i < (lp->inppos + packetlen - 4); 									i++, j++)								lp->eth_rcv_buffer[j] = lp->eth_rcv_buffer[i];							}							lp->wait_frame_number = current_frame;							lp->inppos = 0;						}						if(current_frame == lp->wait_frame_number)						{							lp->inppos += (packetlen - 4);							if(lp->wait_frame_number == 1)		  					{								sbni_get_packet(dev);								lp->inppos = 0;							}							lp->wait_frame_number--;						}					}					lp->last_receive_OK = TRUE;					break;				}				default:					break;				}			}			else 			{				DP(printk("%s: bad CRC32\n",dev->name));				change_level(dev);			}		}		else 		{			DP(printk("%s: bad len\n ",dev->name));			change_level(dev);			lp->stats.rx_over_errors++;		}	}	else 	{		DP(printk("%s: bad sig\n",dev->name));		change_level(dev);	}	outb(inb(dev->base_addr + CSR0) ^ CT_ZER, dev->base_addr + CSR0);	return (rcv_res);}void change_level(struct net_device *dev){	struct net_local *lp = (struct net_local*)dev->priv;	lp->in_stats.bad_rx_number++;	lp->stats.tx_errors++;	if(lp->rxl_delta == 0)		return;	/* 	 * set new rxl_delta value	 */	if(lp->rxl_curr == 0)		lp->rxl_delta = 1;	else if(lp->rxl_curr == 0xf)		lp->rxl_delta = -1;	else if(lp->ok_curr < lp->ok_prev)		lp->rxl_delta = -lp->rxl_delta;	/*	 * set new rxl_curr value	 */	lp->csr1.rxl = rxl_tab[lp->rxl_curr += lp->rxl_delta];	outb(*(char*)&lp->csr1, dev->base_addr + CSR1);    	/*	 * update ok_prev/ok_curr counters	 */	lp->ok_prev = lp->ok_curr;	lp->ok_curr = 0;	DP( printk("%s: receive error, rxl_curr = %d, rxl_delta = %d\n",\		   dev->name,lp->rxl_curr, lp->rxl_delta); )     }static inline void sbni_xmit(struct net_device *dev){	struct net_local* lp = (struct net_local *)dev->priv;	struct sk_buff *skb; 	skb=lp->currframe;  	DP( printk("%s: sbni_xmit CSR0=%02x\n",dev->name, (unsigned char)inb(dev->base_addr + CSR0)); );	  	/* push signature*/  	outb(SBNI_SIG, dev->base_addr + DAT);		/* push frame w/o crc [HAiRY]*/	sbni_outs(dev->base_addr + DAT,	      &((struct sbni_hard_header *)(skb->data))->packetlen,	      SBNI_HH_SZ - sizeof(unsigned)); 		sbni_outs(dev->base_addr + DAT,	      skb->data + sizeof(struct sbni_hard_header),	      skb->len - sizeof(struct sbni_hard_header)); /* 沼信磐 泡

⌨️ 快捷键说明

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