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

📄 olympic.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
#if OLYMPIC_DEBUG	printk("LAPWWO: %x, LAPA: %x\n",readl(olympic_mmio+LAPWWO), readl(olympic_mmio+LAPA));	printk("SISR Mask = %04x\n", readl(olympic_mmio+SISR_MASK));	printk("Before the open command \n");#endif		do {		int i;		save_flags(flags);		cli();		for(i=0;i<SRB_COMMAND_SIZE;i+=4)			writel(0,init_srb+i);		if(SRB_COMMAND_SIZE & 2)			writew(0,init_srb+(SRB_COMMAND_SIZE & ~3));		if(SRB_COMMAND_SIZE & 1)			writeb(0,init_srb+(SRB_COMMAND_SIZE & ~1));		writeb(SRB_OPEN_ADAPTER,init_srb) ; 	/* open */		writeb(OLYMPIC_CLEAR_RET_CODE,init_srb+2);		/* If Network Monitor, instruct card to copy MAC frames through the ARB */#if OLYMPIC_NETWORK_MONITOR		writew(swab16(OPEN_ADAPTER_ENABLE_FDX | OPEN_ADAPTER_PASS_ADC_MAC | OPEN_ADAPTER_PASS_ATT_MAC | OPEN_ADAPTER_PASS_BEACON), init_srb+8);#else		writew(swab16(OPEN_ADAPTER_ENABLE_FDX), init_srb+8);#endif				if (olympic_priv->olympic_laa[0]) {			writeb(olympic_priv->olympic_laa[0],init_srb+12);			writeb(olympic_priv->olympic_laa[1],init_srb+13);			writeb(olympic_priv->olympic_laa[2],init_srb+14);			writeb(olympic_priv->olympic_laa[3],init_srb+15);			writeb(olympic_priv->olympic_laa[4],init_srb+16);			writeb(olympic_priv->olympic_laa[5],init_srb+17);			memcpy(dev->dev_addr,olympic_priv->olympic_laa,dev->addr_len) ;  		} 			writeb(1,init_srb+30);			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, 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);#if OLYMPIC_DEBUG		printk("init_srb(%p): ",init_srb);		for(i=0;i<20;i++)			printk("%02x ",readb(init_srb+i));		printk("\n");#endif				/* If we get the same return response as we set, the interrupt wasn't raised and the open                 * timed out.		 */		if(readb(init_srb+2)== OLYMPIC_CLEAR_RET_CODE) {			printk(KERN_WARNING "%s: Adapter Open time out or error.\n", dev->name) ; 			return -EIO ; 		}			if(readb(init_srb+2)!=0) {			if (readb(init_srb+2) == 0x07) {  				if (!olympic_priv->olympic_ring_speed && open_finished) { /* Autosense , first time around */					printk(KERN_WARNING "%s: Retrying at different ring speed \n", dev->name); 					open_finished = 0 ;  				} else {					strcpy(open_error, open_maj_error[(readb(init_srb+7) & 0xf0) >> 4]) ; 					strcat(open_error," - ") ; 					strcat(open_error, open_min_error[(readb(init_srb+7) & 0x0f)]) ;					if (!olympic_priv->olympic_ring_speed && ((readb(init_srb+7) & 0x0f) == 0x0d)) { 						printk(KERN_WARNING "%s: Tried to autosense ring speed with no monitors present\n",dev->name);						printk(KERN_WARNING "%s: Please try again with a specified ring speed \n",dev->name);						free_irq(dev->irq, dev);						return -EIO ;					}					printk(KERN_WARNING "%s: %s\n",dev->name,open_error);					free_irq(dev->irq,dev) ; 					return -EIO ;  				}	/* if autosense && open_finished */			} else {  				printk(KERN_WARNING "%s: Bad OPEN response: %x\n", dev->name,init_srb[2]);				free_irq(dev->irq, dev);				return -EIO;			} 		} else 			open_finished = 1 ; 	} while (!(open_finished)) ; /* Will only loop if ring speed mismatch re-open attempted && autosense is on */		if (readb(init_srb+18) & (1<<3)) 		if (olympic_priv->olympic_message_level) 			printk(KERN_INFO "%s: Opened in FDX Mode\n",dev->name);	if (readb(init_srb+18) & (1<<1))		olympic_priv->olympic_ring_speed = 100 ; 	else if (readb(init_srb+18) & 1)		olympic_priv->olympic_ring_speed = 16 ; 	else		olympic_priv->olympic_ring_speed = 4 ; 	if (olympic_priv->olympic_message_level) 		printk(KERN_INFO "%s: Opened in %d Mbps mode\n",dev->name, olympic_priv->olympic_ring_speed);	olympic_priv->asb = swab16(readw(init_srb+8));	olympic_priv->srb = swab16(readw(init_srb+10));	olympic_priv->arb = swab16(readw(init_srb+12));	olympic_priv->trb = swab16(readw(init_srb+16));	olympic_priv->olympic_receive_options = 0x01 ; 	olympic_priv->olympic_copy_all_options = 0 ; 		/* setup rx ring */		writel((3<<16),olympic_mmio+BMCTL_RWM); /* Ensure end of frame generated interrupts */ 	writel(BMCTL_RX_DIS|3,olympic_mmio+BMCTL_RWM); /* Yes, this the enables RX channel */	for(i=0;i<OLYMPIC_RX_RING_SIZE;i++) {		struct sk_buff *skb;				skb=dev_alloc_skb(olympic_priv->pkt_buf_sz);		if(skb == NULL)			break;		skb->dev = dev;		olympic_priv->olympic_rx_ring[i].buffer = cpu_to_le32(virt_to_bus(skb->data));		olympic_priv->olympic_rx_ring[i].res_length = cpu_to_le32(olympic_priv->pkt_buf_sz); 		olympic_priv->rx_ring_skb[i]=skb;	}	if (i==0) {		printk(KERN_WARNING "%s: Not enough memory to allocate rx buffers. Adapter disabled\n",dev->name);		free_irq(dev->irq, dev);		return -EIO;	}	writel(virt_to_bus(&olympic_priv->olympic_rx_ring[0]), olympic_mmio+RXDESCQ);	writel(virt_to_bus(&olympic_priv->olympic_rx_ring[0]), olympic_mmio+RXCDA);	writew(i, olympic_mmio+RXDESCQCNT);			writel(virt_to_bus(&olympic_priv->olympic_rx_status_ring[0]), olympic_mmio+RXSTATQ);	writel(virt_to_bus(&olympic_priv->olympic_rx_status_ring[0]), olympic_mmio+RXCSA);	 	olympic_priv->rx_ring_last_received = OLYMPIC_RX_RING_SIZE - 1;	/* last processed rx status */	olympic_priv->rx_status_last_received = OLYMPIC_RX_RING_SIZE - 1;  	writew(i, olympic_mmio+RXSTATQCNT);#if OLYMPIC_DEBUG 	printk("# of rx buffers: %d, RXENQ: %x\n",i, readw(olympic_mmio+RXENQ));	printk("RXCSA: %x, rx_status_ring[0]: %p\n",bus_to_virt(readl(olympic_mmio+RXCSA)),&olympic_priv->olympic_rx_status_ring[0]);	printk(" stat_ring[1]: %p, stat_ring[2]: %p, stat_ring[3]: %p\n", &(olympic_priv->olympic_rx_status_ring[1]), &(olympic_priv->olympic_rx_status_ring[2]), &(olympic_priv->olympic_rx_status_ring[3]) );	printk(" stat_ring[4]: %p, stat_ring[5]: %p, stat_ring[6]: %p\n", &(olympic_priv->olympic_rx_status_ring[4]), &(olympic_priv->olympic_rx_status_ring[5]), &(olympic_priv->olympic_rx_status_ring[6]) );	printk(" stat_ring[7]: %p\n", &(olympic_priv->olympic_rx_status_ring[7])  );	printk("RXCDA: %x, rx_ring[0]: %p\n",bus_to_virt(readl(olympic_mmio+RXCDA)),&olympic_priv->olympic_rx_ring[0]);#endif	writew((((readw(olympic_mmio+RXENQ)) & 0x8000) ^ 0x8000) | i,olympic_mmio+RXENQ);#if OLYMPIC_DEBUG 	printk("# of rx buffers: %d, RXENQ: %x\n",i, readw(olympic_mmio+RXENQ));	printk("RXCSA: %x, rx_ring[0]: %p\n",bus_to_virt(readl(olympic_mmio+RXCSA)),&olympic_priv->olympic_rx_status_ring[0]);	printk("RXCDA: %x, rx_ring[0]: %p\n",bus_to_virt(readl(olympic_mmio+RXCDA)),&olympic_priv->olympic_rx_ring[0]);#endif 	writel(SISR_RX_STATUS | SISR_RX_NOBUF,olympic_mmio+SISR_MASK_SUM);	/* setup tx ring */	writel(BMCTL_TX1_DIS,olympic_mmio+BMCTL_RWM); /* Yes, this enables TX channel 1 */	for(i=0;i<OLYMPIC_TX_RING_SIZE;i++) 		olympic_priv->olympic_tx_ring[i].buffer=0xdeadbeef;	olympic_priv->free_tx_ring_entries=OLYMPIC_TX_RING_SIZE;	writel(virt_to_bus(&olympic_priv->olympic_tx_ring[0]), olympic_mmio+TXDESCQ_1);	writel(virt_to_bus(&olympic_priv->olympic_tx_ring[0]), olympic_mmio+TXCDA_1);	writew(OLYMPIC_TX_RING_SIZE, olympic_mmio+TXDESCQCNT_1);		writel(virt_to_bus(&olympic_priv->olympic_tx_status_ring[0]),olympic_mmio+TXSTATQ_1);	writel(virt_to_bus(&olympic_priv->olympic_tx_status_ring[0]),olympic_mmio+TXCSA_1);	writew(OLYMPIC_TX_RING_SIZE,olympic_mmio+TXSTATQCNT_1);			olympic_priv->tx_ring_free=0; /* next entry in tx ring to use */	olympic_priv->tx_ring_last_status=OLYMPIC_TX_RING_SIZE-1; /* last processed tx status */	writel(SISR_TX1_EOF | SISR_ADAPTER_CHECK | SISR_ARB_CMD | SISR_TRB_REPLY | SISR_ASB_FREE,olympic_mmio+SISR_MASK_SUM);#if OLYMPIC_DEBUG 	printk("BMCTL: %x\n",readl(olympic_mmio+BMCTL_SUM));	printk("SISR MASK: %x\n",readl(olympic_mmio+SISR_MASK));#endif#if OLYMPIC_NETWORK_MONITOR	oat = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ; 	opt = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ; 	printk("%s: Node Address: %02x:%02x:%02x:%02x:%02x:%02x\n",dev->name, 		    readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)), 		    readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+1),		    readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+2),		    readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+3),		    readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+4),		    readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+5));	printk("%s: Functional Address: %02x:%02x:%02x:%02x\n",dev->name, 		    readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)), 		    readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+1),		    readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+2),		    readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+3));	printk("%s: NAUN Address: %02x:%02x:%02x:%02x:%02x:%02x\n",dev->name, 			readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)),			readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+1),			readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+2),			readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+3),			readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+4),			readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+5));#endif 			netif_start_queue(dev);	MOD_INC_USE_COUNT ;	return 0;	}	/* *	When we enter the rx routine we do not know how many frames have been  *	queued on the rx channel.  Therefore we start at the next rx status *	position and travel around the receive ring until we have completed *	all the frames. * *	This means that we may process the frame before we receive the end *	of frame interrupt. This is why we always test the status instead *	of blindly processing the next frame. *	 */static void olympic_rx(struct net_device *dev){	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;	__u8 *olympic_mmio=olympic_priv->olympic_mmio;	struct olympic_rx_status *rx_status;	struct olympic_rx_desc *rx_desc ; 	int rx_ring_last_received,length, buffer_cnt, cpy_length, frag_len;	struct sk_buff *skb, *skb2;	int i;	rx_status=&(olympic_priv->olympic_rx_status_ring[(olympic_priv->rx_status_last_received + 1) & (OLYMPIC_RX_RING_SIZE - 1)]) ;  	while (rx_status->status_buffercnt) {                 __u32 l_status_buffercnt;		olympic_priv->rx_status_last_received++ ;		olympic_priv->rx_status_last_received &= (OLYMPIC_RX_RING_SIZE -1);#if OLYMPIC_DEBUG		printk(" stat_ring addr: %x \n", &(olympic_priv->olympic_rx_status_ring[olympic_priv->rx_status_last_received]) ); 		printk("rx status: %x rx len: %x \n", le32_to_cpu(rx_status->status_buffercnt), le32_to_cpu(rx_status->fragmentcnt_framelen));#endif		length = le32_to_cpu(rx_status->fragmentcnt_framelen) & 0xffff;		buffer_cnt = le32_to_cpu(rx_status->status_buffercnt) & 0xffff; 		i = buffer_cnt ; /* Need buffer_cnt later for rxenq update */ 		frag_len = le32_to_cpu(rx_status->fragmentcnt_framelen) >> 16; #if OLYMPIC_DEBUG 		printk("length: %x, frag_len: %x, buffer_cnt: %x\n", length, frag_len, buffer_cnt);#endif                l_status_buffercnt = le32_to_cpu(rx_status->status_buffercnt);		if(l_status_buffercnt & 0xC0000000) {			if (l_status_buffercnt & 0x3B000000) {				if (olympic_priv->olympic_message_level) {					if (l_status_buffercnt & (1<<29))  /* Rx Frame Truncated */						printk(KERN_WARNING "%s: Rx Frame Truncated \n",dev->name);					if (l_status_buffercnt & (1<<28)) /*Rx receive overrun */						printk(KERN_WARNING "%s: Rx Frame Receive overrun \n",dev->name);					if (l_status_buffercnt & (1<<27)) /* No receive buffers */						printk(KERN_WARNING "%s: No receive buffers \n",dev->name);					if (l_status_buffercnt & (1<<25)) /* Receive frame error detect */						printk(KERN_WARNING "%s: Receive frame error detect \n",dev->name);					if (l_status_buffercnt & (1<<24)) /* Received Error Detect */						printk(KERN_WARNING "%s: Received Error Detect \n",dev->name);				} 				olympic_priv->rx_ring_last_received += i ; 				olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE -1) ; 				olympic_priv->olympic_stats.rx_errors++;	 			} else {								if (buffer_cnt == 1) {					skb = dev_alloc_skb(olympic_priv->pkt_buf_sz) ; 				} else {					skb = dev_alloc_skb(length) ; 				}				if (skb == NULL) {					printk(KERN_WARNING "%s: Not enough memory to copy packet to upper layers. \n",dev->name) ;					olympic_priv->olympic_stats.rx_dropped++ ; 					/* Update counters even though we don't transfer the frame */					olympic_priv->rx_ring_last_received += i ; 					olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE -1) ;  				} else  {					skb->dev = dev ; 					/* Optimise based upon number of buffers used. 			   	   	   If only one buffer is used we can simply swap the buffers around.			   	   	   If more than one then we must use the new buffer and copy the information			   	   	   first. Ideally all frames would be in a single buffer, this can be tuned by                               	   	   altering the buffer size. */				 					if (buffer_cnt==1) {						olympic_priv->rx_ring_last_received++ ; 						olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE -1);						rx_ring_last_received = olympic_priv->rx_ring_last_received ;						skb2=olympic_priv->rx_ring_skb[rx_ring_last_received] ; 						skb_put(skb2,length);						skb2->protocol = tr_type_trans(skb2,dev);						olympic_priv->olympic_rx_ring[rx_ring_last_received].buffer = cpu_to_le32(virt_to_bus(skb->data));						olympic_priv->olympic_rx_ring[rx_ring_last_received].res_length = cpu_to_le32(olympic_priv->pkt_buf_sz); 						olympic_priv->rx_ring_skb[rx_ring_last_received] = skb ; 						netif_rx(skb2) ; 					} else {						do { /* Walk the buffers */ 							olympic_priv->rx_ring_last_received++ ; 							olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE -1);							rx_ring_last_received = olympic_priv->rx_ring_last_received ; 							rx_desc = &(olympic_priv->olympic_rx_ring[rx_ring_last_received]);							cpy_length = (i == 1 ? frag_len : le32_to_cpu(rx_desc->res_length)); 							memcpy(skb_put(skb, cpy_length), bus_to_virt(le32_to_cpu(rx_desc->buffer)), cpy_length) ; 						} while (--i) ; 								skb->protocol = tr_type_trans(skb,dev);						netif_rx(skb) ; 					} 					olympic_priv->olympic_stats.rx_packets++ ; 					olympic_priv->olympic_stats.rx_bytes += length ; 				} /* if skb == null */			} /* If status & 0x3b */		} else { /*if buffercnt & 0xC */			olympic_priv->rx_ring_last_received += i ; 			olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE - 1) ; 		} 		rx_status->fragmentcnt_framelen = 0 ; 		rx_status->status_buffercnt = 0 ; 		rx_status = &(olympic_priv->olympic_rx_status_ring[(olympic_priv->rx_status_last_received+1) & (OLYMPIC_RX_RING_SIZE -1) ]);		writew((((readw(olympic_mmio+RXENQ)) & 0x8000) ^ 0x8000) |  buffer_cnt , olympic_mmio+RXENQ); 	} /* while */}static void olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs) {	struct net_device *dev= (struct net_device *)dev_id;	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;	__u8 *olympic_mmio=olympic_priv->olympic_mmio;	__u32 sisr;	__u8 *adapter_check_area ; 		sisr=readl(olympic_mmio+SISR_RR) ; /* Reset sisr */ 		if (!(sisr & SISR_MI)) /* Interrupt isn't for us */ 		return ;	spin_lock(&olympic_priv->olympic_lock);	if (sisr & (SISR_SRB_REPLY | SISR_TX1_EOF | SISR_RX_STATUS | SISR_ADAPTER_CHECK |  			SISR_ASB_FREE | SISR_ARB_CMD | SISR_TRB_REPLY | SISR_RX_NOBUF)) {  			if(sisr & SISR_SRB_REPLY) {			if(olympic_priv->srb_queued==1) {				wake_up_interruptible(&olympic_priv->srb_wait);			} else if (olympic_priv->srb_queued==2) { 				olympic_srb_bh(dev) ; 			}			olympic_priv->srb_queued=0;		} /* SISR_SRB_REPLY */		if (sisr & SISR_TX1_EOF) {			olympic_priv->tx_ring_last_status++;			olympic_priv->tx_ring_last_status &= (OLYMPIC_TX_RING_SIZE-1);			olympic_priv->free_tx_ring_entries++;			olympic_priv->olympic_stats.tx_bytes += olympic_priv->tx_ring_skb[olympic_priv->tx_ring_last_status]->len;			olympic_priv->olympic_stats.tx_packets++ ; 			dev_kfree_skb_irq(olympic_priv->tx_ring_skb[olympic_priv->tx_ring_last_status]);			olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_last_status].buffer=0xdeadbeef;			olympic_priv->olympic_tx_status_ring[olympic_priv->tx_ring_last_status].status=0;			netif_wake_queue(dev);		} /* SISR_TX1_EOF */			if (sisr & SISR_RX_STATUS) {			olympic_rx(dev);		} /* SISR_RX_STATUS */			if (sisr & SISR_ADAPTER_CHECK) {			printk(KERN_WARNING "%s: Adapter Check Interrupt Raised, 8 bytes of information follow:\n", dev->name);			writel(readl(olympic_mmio+LAPWWO),olympic_mmio+LAPA);			adapter_check_area = (__u8 *)(olympic_mmio+LAPWWO) ; 			printk(KERN_WARNING "%s: Bytes %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",dev->name, readb(adapter_check_area+0), readb(adapter_check_area+1), readb(adapter_check_area+2), readb(adapter_check_area+3), readb(adapter_check_area+4), readb(adapter_check_area+5), readb(adapter_check_area+6), readb(adapter_check_area+7)) ; 			free_irq(dev->irq, dev) ; 			} /* SISR_ADAPTER_CHECK */

⌨️ 快捷键说明

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