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

📄 olympic.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
			if (sisr & SISR_ASB_FREE) {			/* Wake up anything that is waiting for the asb response */  			if (olympic_priv->asb_queued) {				olympic_asb_bh(dev) ; 			}		} /* SISR_ASB_FREE */			if (sisr & SISR_ARB_CMD) {			olympic_arb_cmd(dev) ; 		} /* SISR_ARB_CMD */			if (sisr & SISR_TRB_REPLY) {			/* Wake up anything that is waiting for the trb response */			if (olympic_priv->trb_queued) {				wake_up_interruptible(&olympic_priv->trb_wait);			}			olympic_priv->trb_queued = 0 ; 		} /* SISR_TRB_REPLY */				if (sisr & SISR_RX_NOBUF) {			/* According to the documentation, we don't have to do anything, but trapping it keeps it out of                  	   	   /var/log/messages.  */		} /* SISR_RX_NOBUF */	} else { 		printk(KERN_WARNING "%s: Unexpected interrupt: %x\n",dev->name, sisr);		printk(KERN_WARNING "%s: SISR_MASK: %x\n",dev->name, readl(olympic_mmio+SISR_MASK)) ;	} /* One if the interrupts we want */	writel(SISR_MI,olympic_mmio+SISR_MASK_SUM);		spin_unlock(&olympic_priv->olympic_lock) ; }	static int olympic_xmit(struct sk_buff *skb, struct net_device *dev) {	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;	__u8 *olympic_mmio=olympic_priv->olympic_mmio;	unsigned long flags ; 	spin_lock_irqsave(&olympic_priv->olympic_lock, flags);	netif_stop_queue(dev);		if(olympic_priv->free_tx_ring_entries) {		olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_free].buffer = cpu_to_le32(virt_to_bus(skb->data));		olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_free].status_length = cpu_to_le32(skb->len | (0x80000000));		olympic_priv->tx_ring_skb[olympic_priv->tx_ring_free]=skb;		olympic_priv->free_tx_ring_entries--;        	olympic_priv->tx_ring_free++;        	olympic_priv->tx_ring_free &= (OLYMPIC_TX_RING_SIZE-1);		writew((((readw(olympic_mmio+TXENQ_1)) & 0x8000) ^ 0x8000) | 1,olympic_mmio+TXENQ_1);		netif_wake_queue(dev);		spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags);		return 0;	} else {		spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags);		return 1;	} }	static int olympic_close(struct net_device *dev) {	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;    	__u8 *olympic_mmio=olympic_priv->olympic_mmio,*srb;	unsigned long flags;	int i;	netif_stop_queue(dev);		writel(olympic_priv->srb,olympic_mmio+LAPA);	srb=olympic_priv->olympic_lap + (olympic_priv->srb & (~0xf800));	    	writeb(SRB_CLOSE_ADAPTER,srb+0);	writeb(0,srb+1);	writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);	save_flags(flags);	cli();		olympic_priv->srb_queued=1;	writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);	while(olympic_priv->srb_queued) {	        interruptible_sleep_on_timeout(&olympic_priv->srb_wait, jiffies+60*HZ);        	if(signal_pending(current))	{            			printk(KERN_WARNING "%s: SRB timed out.\n",                		dev->name);            		printk(KERN_WARNING "SISR=%x MISR=%x\n",                	readl(olympic_mmio+SISR),                	readl(olympic_mmio+LISR));            		olympic_priv->srb_queued=0;            		break;        	}    	}	restore_flags(flags) ; 	olympic_priv->rx_status_last_received++;	olympic_priv->rx_status_last_received&=OLYMPIC_RX_RING_SIZE-1;		for(i=0;i<OLYMPIC_RX_RING_SIZE;i++) {		dev_kfree_skb(olympic_priv->rx_ring_skb[olympic_priv->rx_status_last_received]);		olympic_priv->rx_status_last_received++;		olympic_priv->rx_status_last_received&=OLYMPIC_RX_RING_SIZE-1;	}	/* reset tx/rx fifo's and busmaster logic */	writel(readl(olympic_mmio+BCTL)|(3<<13),olympic_mmio+BCTL);	udelay(1);	writel(readl(olympic_mmio+BCTL)&~(3<<13),olympic_mmio+BCTL);#if OLYMPIC_DEBUG	printk("srb(%p): ",srb);	for(i=0;i<4;i++)		printk("%x ",readb(srb+i));	printk("\n");#endif	free_irq(dev->irq,dev);	MOD_DEC_USE_COUNT ; 	return 0;	}static void olympic_set_rx_mode(struct net_device *dev) {	struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ;    	__u8 *olympic_mmio = olympic_priv->olympic_mmio ; 	__u8 options = 0; 	__u8 *srb;	struct dev_mc_list *dmi ; 	unsigned char dev_mc_address[4] ; 	int i ; 	writel(olympic_priv->srb,olympic_mmio+LAPA);	srb=olympic_priv->olympic_lap + (olympic_priv->srb & (~0xf800));	options = olympic_priv->olympic_copy_all_options; 	if (dev->flags&IFF_PROMISC)  		options |= 0x61 ;	else		options &= ~0x61 ; 	/* Only issue the srb if there is a change in options */	if ((options ^ olympic_priv->olympic_copy_all_options)) { 			/* Now to issue the srb command to alter the copy.all.options */			writeb(SRB_MODIFY_RECEIVE_OPTIONS,srb);		writeb(0,srb+1);		writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);		writeb(0,srb+3);		writeb(olympic_priv->olympic_receive_options,srb+4);		writeb(options,srb+5);		olympic_priv->srb_queued=2; /* Can't sleep, use srb_bh */		writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);		olympic_priv->olympic_copy_all_options = options ;				return ;  	} 	/* Set the functional addresses we need for multicast */	dev_mc_address[0] = dev_mc_address[1] = dev_mc_address[2] = dev_mc_address[3] = 0 ; 	for (i=0,dmi=dev->mc_list;i < dev->mc_count; i++,dmi = dmi->next) { 		dev_mc_address[0] |= dmi->dmi_addr[2] ; 		dev_mc_address[1] |= dmi->dmi_addr[3] ; 		dev_mc_address[2] |= dmi->dmi_addr[4] ; 		dev_mc_address[3] |= dmi->dmi_addr[5] ; 	}	writeb(SRB_SET_FUNC_ADDRESS,srb+0);	writeb(0,srb+1);	writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);	writeb(0,srb+3);	writeb(0,srb+4);	writeb(0,srb+5);	writeb(dev_mc_address[0],srb+6);	writeb(dev_mc_address[1],srb+7);	writeb(dev_mc_address[2],srb+8);	writeb(dev_mc_address[3],srb+9);	olympic_priv->srb_queued = 2 ;	writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);}static void olympic_srb_bh(struct net_device *dev) { 	struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ;    	__u8 *olympic_mmio = olympic_priv->olympic_mmio ; 	__u8 *srb;	writel(olympic_priv->srb,olympic_mmio+LAPA);	srb=olympic_priv->olympic_lap + (olympic_priv->srb & (~0xf800));	switch (readb(srb)) { 		/* SRB_MODIFY_RECEIVE_OPTIONS i.e. set_multicast_list options (promiscuous)                  * At some point we should do something if we get an error, such as                 * resetting the IFF_PROMISC flag in dev		 */		case SRB_MODIFY_RECEIVE_OPTIONS:			switch (readb(srb+2)) { 				case 0x01:					printk(KERN_WARNING "%s: Unrecognized srb command\n",dev->name) ; 					break ; 				case 0x04:					printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name);					break ; 				default:					if (olympic_priv->olympic_message_level) 						printk(KERN_WARNING "%s: Receive Options Modified to %x,%x\n",dev->name,olympic_priv->olympic_copy_all_options, olympic_priv->olympic_receive_options) ; 					break ; 				} /* switch srb[2] */ 			break ;				/* SRB_SET_GROUP_ADDRESS - Multicast group setting                  */		case SRB_SET_GROUP_ADDRESS:			switch (readb(srb+2)) { 				case 0x00:					break ; 				case 0x01:					printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ; 					break ;				case 0x04:					printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name); 					break ;				case 0x3c:					printk(KERN_WARNING "%s: Group/Functional address indicator bits not set correctly\n",dev->name) ; 					break ;				case 0x3e: /* If we ever implement individual multicast addresses, will need to deal with this */					printk(KERN_WARNING "%s: Group address registers full\n",dev->name) ; 					break ;  				case 0x55:					printk(KERN_INFO "%s: Group Address already set.\n",dev->name) ; 					break ;				default:					break ; 			} /* switch srb[2] */ 			break ; 		/* SRB_RESET_GROUP_ADDRESS - Remove a multicast address from group list 		 */		case SRB_RESET_GROUP_ADDRESS:			switch (readb(srb+2)) { 				case 0x00:					break ; 				case 0x01:					printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ; 					break ; 				case 0x04:					printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name) ; 					break ; 				case 0x39: /* Must deal with this if individual multicast addresses used */					printk(KERN_INFO "%s: Group address not found \n",dev->name); 					break ;				default:					break ; 			} /* switch srb[2] */			break ; 				/* SRB_SET_FUNC_ADDRESS - Called by the set_rx_mode 		 */		case SRB_SET_FUNC_ADDRESS:			switch (readb(srb+2)) { 				case 0x00:					if (olympic_priv->olympic_message_level)						printk(KERN_INFO "%s: Functional Address Mask Set \n",dev->name) ; 					break ;				case 0x01:					printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ; 					break ; 				case 0x04:					printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name) ; 					break ; 				default:					break ; 			} /* switch srb[2] */			break ; 			/* SRB_READ_LOG - Read and reset the adapter error counters 		 */		case SRB_READ_LOG:			switch (readb(srb+2)) { 				case 0x00: 					if (olympic_priv->olympic_message_level) 						printk(KERN_INFO "%s: Read Log issued\n",dev->name) ; 					break ; 				case 0x01:					printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ; 					break ; 				case 0x04:					printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name) ; 					break ; 						} /* switch srb[2] */			break ; 				/* SRB_READ_SR_COUNTERS - Read and reset the source routing bridge related counters */		case SRB_READ_SR_COUNTERS:			switch (readb(srb+2)) { 				case 0x00: 					if (olympic_priv->olympic_message_level) 						printk(KERN_INFO "%s: Read Source Routing Counters issued\n",dev->name) ; 					break ; 				case 0x01:					printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ; 					break ; 				case 0x04:					printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name) ; 					break ; 				default:					break ; 			} /* switch srb[2] */			break ; 		default:			printk(KERN_WARNING "%s: Unrecognized srb bh return value.\n",dev->name);			break ; 	} /* switch srb[0] */} static struct net_device_stats * olympic_get_stats(struct net_device *dev){	struct olympic_private *olympic_priv ;	olympic_priv=(struct olympic_private *) dev->priv;	return (struct net_device_stats *) &olympic_priv->olympic_stats; }static int olympic_set_mac_address (struct net_device *dev, void *addr) {	struct sockaddr *saddr = addr ; 	struct olympic_private *olympic_priv = (struct olympic_private *)dev->priv ; 	if (netif_running(dev)) { 		printk(KERN_WARNING "%s: Cannot set mac/laa address while card is open\n", dev->name) ; 		return -EIO ; 	}	memcpy(olympic_priv->olympic_laa, saddr->sa_data,dev->addr_len) ; 		if (olympic_priv->olympic_message_level) {  		printk(KERN_INFO "%s: MAC/LAA Set to  = %x.%x.%x.%x.%x.%x\n",dev->name, olympic_priv->olympic_laa[0],		olympic_priv->olympic_laa[1], olympic_priv->olympic_laa[2],		olympic_priv->olympic_laa[3], olympic_priv->olympic_laa[4],		olympic_priv->olympic_laa[5]);	} 	return 0 ; }static void olympic_arb_cmd(struct net_device *dev){	struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv;    	__u8 *olympic_mmio=olympic_priv->olympic_mmio;	__u8 *arb_block, *asb_block, *srb  ; 	__u8 header_len ; 	__u16 frame_len, buffer_len ;	struct sk_buff *mac_frame ;  	__u8 *buf_ptr ;	__u8 *frame_data ;  	__u16 buff_off ; 	__u16 lan_status = 0, lan_status_diff  ; /* Initialize to stop compiler warning */	__u8 fdx_prot_error ; 	__u16 next_ptr;	int i ; #if OLYMPIC_NETWORK_MONITOR	struct trh_hdr *mac_hdr ; #endif	arb_block = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->arb) ; 	asb_block = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->asb) ; 	srb = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->srb) ; 	writel(readl(olympic_mmio+LAPA),olympic_mmio+LAPWWO);	if (readb(arb_block+0) == ARB_RECEIVE_DATA) { /* Receive.data, MAC frames */		header_len = readb(arb_block+8) ; /* 802.5 Token-Ring Header Length */			frame_len = swab16(readw(arb_block + 10)) ; 		buff_off = swab16(readw(arb_block + 6)) ;				buf_ptr = olympic_priv->olympic_lap + buff_off ; #if OLYMPIC_DEBUG{		int i;		frame_data = buf_ptr+offsetof(struct mac_receive_buffer,frame_data) ; 		for (i=0 ;  i < 14 ; i++) { 			printk("Loc %d = %02x\n",i,readb(frame_data + i)); 		}		printk("next %04x, fs %02x, len %04x \n",readw(buf_ptr+offsetof(struct mac_receive_buffer,next)), readb(buf_ptr+offsetof(struct mac_receive_buffer,frame_status)), readw(buf_ptr+offsetof(struct mac_receive_buffer,buffer_length))); }#endif 

⌨️ 快捷键说明

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