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

📄 lanstreamer.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
{	struct streamer_private *streamer_priv = (struct streamer_private *) dev->priv;	__u8 *streamer_mmio = streamer_priv->streamer_mmio;	unsigned long flags;	char open_error[255];	int i, open_finished = 1;	__u16 srb_word;	__u16 srb_open;	int rc;	if (readw(streamer_mmio+BMCTL_SUM) & BMCTL_RX_ENABLED) {	        rc=streamer_reset(dev);	}	if (request_irq(dev->irq, &streamer_interrupt, SA_SHIRQ, "streamer", dev)) {		return -EAGAIN;	}#if STREAMER_DEBUG	printk("BMCTL: %x\n", readw(streamer_mmio + BMCTL_SUM));	printk("pending ints: %x\n", readw(streamer_mmio + SISR));#endif	writew(SISR_MI | SISR_SRB_REPLY, streamer_mmio + SISR_MASK);	/* more ints later, doesn't stop arb cmd interrupt */	writew(LISR_LIE, streamer_mmio + LISR);	/* more ints later */	/* adapter is closed, so SRB is pointed to by LAPWWO */	writew(readw(streamer_mmio + LAPWWO), streamer_mmio + LAPA);#if STREAMER_DEBUG	printk("LAPWWO: %x, LAPA: %x\n", readw(streamer_mmio + LAPWWO),	       readw(streamer_mmio + LAPA));	printk("LAPE: %x\n", readw(streamer_mmio + LAPE));	printk("SISR Mask = %04x\n", readw(streamer_mmio + SISR_MASK));#endif	do {		int i;		save_flags(flags);		cli();		for (i = 0; i < SRB_COMMAND_SIZE; i += 2) {			writew(0, streamer_mmio + LAPDINC);		}		writew(readw(streamer_mmio+LAPWWO),streamer_mmio+LAPA);		writew(htons(SRB_OPEN_ADAPTER<<8),streamer_mmio+LAPDINC) ; 	/* open */		writew(htons(STREAMER_CLEAR_RET_CODE<<8),streamer_mmio+LAPDINC);		writew(STREAMER_CLEAR_RET_CODE, streamer_mmio + LAPDINC);		writew(readw(streamer_mmio + LAPWWO) + 8, streamer_mmio + LAPA);#if STREAMER_NETWORK_MONITOR		/* If Network Monitor, instruct card to copy MAC frames through the ARB */		writew(htons(OPEN_ADAPTER_ENABLE_FDX | OPEN_ADAPTER_PASS_ADC_MAC | OPEN_ADAPTER_PASS_ATT_MAC | OPEN_ADAPTER_PASS_BEACON), streamer_mmio + LAPDINC);	/* offset 8 word contains open options */#else		writew(htons(OPEN_ADAPTER_ENABLE_FDX), streamer_mmio + LAPDINC);	/* Offset 8 word contains Open.Options */#endif		if (streamer_priv->streamer_laa[0]) {			writew(readw(streamer_mmio + LAPWWO) + 12, streamer_mmio + LAPA);			writew(htons((streamer_priv->streamer_laa[0] << 8) | 				     streamer_priv->streamer_laa[1]),streamer_mmio+LAPDINC);			writew(htons((streamer_priv->streamer_laa[2] << 8) | 				     streamer_priv->streamer_laa[3]),streamer_mmio+LAPDINC);			writew(htons((streamer_priv->streamer_laa[4] << 8) | 				     streamer_priv->streamer_laa[5]),streamer_mmio+LAPDINC);			memcpy(dev->dev_addr, streamer_priv->streamer_laa, dev->addr_len);		}		/* save off srb open offset */		srb_open = readw(streamer_mmio + LAPWWO);#if STREAMER_DEBUG		writew(readw(streamer_mmio + LAPWWO),		       streamer_mmio + LAPA);		printk("srb open request: \n");		for (i = 0; i < 16; i++) {			printk("%x:", ntohs(readw(streamer_mmio + LAPDINC)));		}		printk("\n");#endif		streamer_priv->srb_queued = 1;		/* signal solo that SRB command has been issued */		writew(LISR_SRB_CMD, streamer_mmio + LISR_SUM);		while (streamer_priv->srb_queued) {			interruptible_sleep_on_timeout(&streamer_priv->srb_wait, 5 * HZ);			if (signal_pending(current)) {				printk(KERN_WARNING "%s: SRB timed out.\n", dev->name);				printk(KERN_WARNING "SISR=%x MISR=%x, LISR=%x\n",				       readw(streamer_mmio + SISR),				       readw(streamer_mmio + MISR_RUM),				       readw(streamer_mmio + LISR));				streamer_priv->srb_queued = 0;				break;			}		}		restore_flags(flags);#if STREAMER_DEBUG		printk("SISR_MASK: %x\n", readw(streamer_mmio + SISR_MASK));		printk("srb open response:\n");		writew(srb_open, streamer_mmio + LAPA);		for (i = 0; i < 10; i++) {			printk("%x:",			       ntohs(readw(streamer_mmio + LAPDINC)));		}#endif		/* If we get the same return response as we set, the interrupt wasn't raised and the open		 * timed out.		 */		writew(srb_open + 2, streamer_mmio + LAPA);		srb_word = ntohs(readw(streamer_mmio + LAPD)) & 0xFF;		if (srb_word == STREAMER_CLEAR_RET_CODE) {			printk(KERN_WARNING "%s: Adapter Open time out or error.\n",			       dev->name);			return -EIO;		}		if (srb_word != 0) {			if (srb_word == 0x07) {				if (!streamer_priv->streamer_ring_speed && open_finished) {	/* Autosense , first time around */					printk(KERN_WARNING "%s: Retrying at different ring speed \n",					       dev->name);					open_finished = 0;				} else {					__u16 error_code;					writew(srb_open + 6, streamer_mmio + LAPA);					error_code = ntohs(readw(streamer_mmio + LAPD));					strcpy(open_error, open_maj_error[(error_code & 0xf0) >> 4]);					strcat(open_error, " - ");					strcat(open_error, open_min_error[(error_code & 0x0f)]);					if (!streamer_priv->streamer_ring_speed					    && ((error_code & 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, srb_word);				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 */	writew(srb_open + 18, streamer_mmio + LAPA);	srb_word=ntohs(readw(streamer_mmio+LAPD)) >> 8;	if (srb_word & (1 << 3))		if (streamer_priv->streamer_message_level)			printk(KERN_INFO "%s: Opened in FDX Mode\n", dev->name);	if (srb_word & 1)		streamer_priv->streamer_ring_speed = 16;	else		streamer_priv->streamer_ring_speed = 4;	if (streamer_priv->streamer_message_level)		printk(KERN_INFO "%s: Opened in %d Mbps mode\n", 			dev->name,			streamer_priv->streamer_ring_speed);	writew(srb_open + 8, streamer_mmio + LAPA);	streamer_priv->asb = ntohs(readw(streamer_mmio + LAPDINC));	streamer_priv->srb = ntohs(readw(streamer_mmio + LAPDINC));	streamer_priv->arb = ntohs(readw(streamer_mmio + LAPDINC));	readw(streamer_mmio + LAPDINC);	/* offset 14 word is rsvd */	streamer_priv->trb = ntohs(readw(streamer_mmio + LAPDINC));	streamer_priv->streamer_receive_options = 0x00;	streamer_priv->streamer_copy_all_options = 0;	/* setup rx ring */	/* enable rx channel */	writew(~BMCTL_RX_DIS, streamer_mmio + BMCTL_RUM);	/* setup rx descriptors */	streamer_priv->streamer_rx_ring=	    kmalloc( sizeof(struct streamer_rx_desc)*		     STREAMER_RX_RING_SIZE,GFP_KERNEL);	if (!streamer_priv->streamer_rx_ring) {	    printk(KERN_WARNING "%s ALLOC of streamer rx ring FAILED!!\n",dev->name);	    return -EIO;	}	for (i = 0; i < STREAMER_RX_RING_SIZE; i++) {		struct sk_buff *skb;		skb = dev_alloc_skb(streamer_priv->pkt_buf_sz);		if (skb == NULL)			break;		skb->dev = dev;		streamer_priv->streamer_rx_ring[i].forward = virt_to_bus(&streamer_priv->streamer_rx_ring[i + 1]);		streamer_priv->streamer_rx_ring[i].status = 0;		streamer_priv->streamer_rx_ring[i].buffer = virt_to_bus(skb->data);		streamer_priv->streamer_rx_ring[i].framelen_buflen = streamer_priv->pkt_buf_sz;		streamer_priv->rx_ring_skb[i] = skb;	}	streamer_priv->streamer_rx_ring[STREAMER_RX_RING_SIZE - 1].forward =				virt_to_bus(&streamer_priv->streamer_rx_ring[0]);	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;	}	streamer_priv->rx_ring_last_received = STREAMER_RX_RING_SIZE - 1;	/* last processed rx status */	writel(virt_to_bus(&streamer_priv->streamer_rx_ring[0]), streamer_mmio + RXBDA);	writel(virt_to_bus(&streamer_priv->streamer_rx_ring[STREAMER_RX_RING_SIZE - 1]), streamer_mmio + RXLBDA);	/* set bus master interrupt event mask */	writew(MISR_RX_NOBUF | MISR_RX_EOF, streamer_mmio + MISR_MASK);	/* setup tx ring */	streamer_priv->streamer_tx_ring=kmalloc(sizeof(struct streamer_tx_desc)*						STREAMER_TX_RING_SIZE,GFP_KERNEL);	if (!streamer_priv->streamer_tx_ring) {	    printk(KERN_WARNING "%s ALLOC of streamer_tx_ring FAILED\n",dev->name);	    return -EIO;	}	writew(~BMCTL_TX2_DIS, streamer_mmio + BMCTL_RUM);	/* Enables TX channel 2 */	for (i = 0; i < STREAMER_TX_RING_SIZE; i++) {		streamer_priv->streamer_tx_ring[i].forward = virt_to_bus(&streamer_priv->streamer_tx_ring[i + 1]);		streamer_priv->streamer_tx_ring[i].status = 0;		streamer_priv->streamer_tx_ring[i].bufcnt_framelen = 0;		streamer_priv->streamer_tx_ring[i].buffer = 0;		streamer_priv->streamer_tx_ring[i].buflen = 0;	}	streamer_priv->streamer_tx_ring[STREAMER_TX_RING_SIZE - 1].forward =					virt_to_bus(&streamer_priv->streamer_tx_ring[0]);;	streamer_priv->free_tx_ring_entries = STREAMER_TX_RING_SIZE;	streamer_priv->tx_ring_free = 0;	/* next entry in tx ring to use */	streamer_priv->tx_ring_last_status = STREAMER_TX_RING_SIZE - 1;	/* set Busmaster interrupt event mask (handle receives on interrupt only */	writew(MISR_TX2_EOF | MISR_RX_NOBUF | MISR_RX_EOF, streamer_mmio + MISR_MASK);	/* set system event interrupt mask */	writew(SISR_ADAPTER_CHECK | SISR_ARB_CMD | SISR_TRB_REPLY | SISR_ASB_FREE, streamer_mmio + SISR_MASK_SUM);#if STREAMER_DEBUG	printk("BMCTL: %x\n", readw(streamer_mmio + BMCTL_SUM));	printk("SISR MASK: %x\n", readw(streamer_mmio + SISR_MASK));#endif#if STREAMER_NETWORK_MONITOR	writew(streamer_priv->streamer_addr_table_addr, streamer_mmio + LAPA);	printk("%s: Node Address: %04x:%04x:%04x\n", dev->name,		ntohs(readw(streamer_mmio + LAPDINC)),		ntohs(readw(streamer_mmio + LAPDINC)),		ntohs(readw(streamer_mmio + LAPDINC)));	readw(streamer_mmio + LAPDINC);	readw(streamer_mmio + LAPDINC);	printk("%s: Functional Address: %04x:%04x\n", dev->name,		ntohs(readw(streamer_mmio + LAPDINC)),		ntohs(readw(streamer_mmio + LAPDINC)));	writew(streamer_priv->streamer_parms_addr + 4,		streamer_mmio + LAPA);	printk("%s: NAUN Address: %04x:%04x:%04x\n", dev->name,		ntohs(readw(streamer_mmio + LAPDINC)),		ntohs(readw(streamer_mmio + LAPDINC)),		ntohs(readw(streamer_mmio + LAPDINC)));#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 streamer_rx(struct net_device *dev){	struct streamer_private *streamer_priv =	    (struct streamer_private *) dev->priv;	__u8 *streamer_mmio = streamer_priv->streamer_mmio;	struct streamer_rx_desc *rx_desc;	int rx_ring_last_received, length, frame_length, buffer_cnt = 0;	struct sk_buff *skb, *skb2;	/* setup the next rx descriptor to be received */	rx_desc = &streamer_priv->streamer_rx_ring[(streamer_priv->rx_ring_last_received + 1) & (STREAMER_RX_RING_SIZE - 1)];	rx_ring_last_received = streamer_priv->rx_ring_last_received;	while (rx_desc->status & 0x01000000) {	/* While processed descriptors are available */		if (rx_ring_last_received != streamer_priv->rx_ring_last_received) 		{			printk(KERN_WARNING "RX Error 1 rx_ring_last_received not the same %x %x\n",				rx_ring_last_received, streamer_priv->rx_ring_last_received);		}		streamer_priv->rx_ring_last_received = (streamer_priv->rx_ring_last_received + 1) & (STREAMER_RX_RING_SIZE - 1);		rx_ring_last_received = streamer_priv->rx_ring_last_received;		length = rx_desc->framelen_buflen & 0xffff;	/* buffer length */		frame_length = (rx_desc->framelen_buflen >> 16) & 0xffff;		if (rx_desc->status & 0x7E830000) {	/* errors */			if (streamer_priv->streamer_message_level) {				printk(KERN_WARNING "%s: Rx Error %x \n",				       dev->name, rx_desc->status);			}		} else {	/* received without errors */			if (rx_desc->status & 0x80000000) {	/* frame complete */				buffer_cnt = 1;				skb = dev_alloc_skb(streamer_priv->pkt_buf_sz);			} else {				skb = dev_alloc_skb(frame_length);			}			if (skb == NULL) 			{				printk(KERN_WARNING "%s: Not enough memory to copy packet to upper layers. \n",	dev->name);				streamer_priv->streamer_stats.rx_dropped++;			} else {	/* we allocated an skb OK */				skb->dev = dev;				if (buffer_cnt == 1) {					skb2 = streamer_priv->rx_ring_skb[rx_ring_last_received];#if STREAMER_DEBUG_PACKETS					{						int i;						printk("streamer_rx packet print: skb->data2 %p  skb->head %p\n", skb2->data, skb2->head);						for (i = 0; i < frame_length; i++) 						{							printk("%x:", skb2->data[i]);							if (((i + 1) % 16) == 0)								printk("\n");						}						printk("\n");					}#endif					skb_put(skb2, length);					skb2->protocol = tr_type_trans(skb2, dev);					/* recycle this descriptor */					streamer_priv->streamer_rx_ring[rx_ring_last_received].status = 0;					streamer_priv->streamer_rx_ring[rx_ring_last_received].framelen_buflen = streamer_priv->pkt_buf_sz;					streamer_priv->streamer_rx_ring[rx_ring_last_received].buffer = virt_to_bus(skb->data);					streamer_priv-> rx_ring_skb[rx_ring_last_received] = skb;					/* place recycled descriptor back on the adapter */					writel(virt_to_bus(&streamer_priv->streamer_rx_ring[rx_ring_last_received]),streamer_mmio + RXLBDA);					/* pass the received skb up to the protocol */					netif_rx(skb2);				} else {					do {	/* Walk the buffers */						memcpy(skb_put(skb, length),bus_to_virt(rx_desc->buffer), length);	/* copy this fragment */						streamer_priv->streamer_rx_ring[rx_ring_last_received].status = 0;						streamer_priv->streamer_rx_ring[rx_ring_last_received].framelen_buflen = streamer_priv->pkt_buf_sz;												/* give descriptor back to the adapter */						writel(virt_to_bus(&streamer_priv->streamer_rx_ring[rx_ring_last_received]), streamer_mmio + RXLBDA);						if (rx_desc->status & 0x80000000)							break;	/* this descriptor completes the frame */						/* else get the next pending descriptor */						if (rx_ring_last_received!= streamer_priv->rx_ring_last_received)						{							printk("RX Error rx_ring_last_received not the same %x %x\n",								rx_ring_last_received,								streamer_priv->rx_ring_last_received);						}						rx_desc = &streamer_priv->streamer_rx_ring[(streamer_priv->rx_ring_last_received+1) & (STREAMER_RX_RING_SIZE-1)];						length = rx_desc->framelen_buflen & 0xffff;	/* buffer length */						streamer_priv->rx_ring_last_received =	(streamer_priv->rx_ring_last_received+1) & (STREAMER_RX_RING_SIZE - 1);						rx_ring_last_received = streamer_priv->rx_ring_last_received;					} while (1);					skb->protocol = tr_type_trans(skb, dev);					/* send up to the protocol */					netif_rx(skb);				}				streamer_priv->streamer_stats.rx_packets++;				streamer_priv->streamer_stats.rx_bytes += length;			}	/* if skb == null */		}		/* end received without errors */		/* try the next one */		rx_desc = &streamer_priv->streamer_rx_ring[(rx_ring_last_received + 1) & (STREAMER_RX_RING_SIZE - 1)];	}			/* end for all completed rx descriptors */}static void streamer_interrupt(int irq, void *dev_id, struct pt_regs *regs){	struct net_device *dev = (struct net_device *) dev_id;	struct streamer_private *streamer_priv =	    (struct streamer_private *) dev->priv;	__u8 *streamer_mmio = streamer_priv->streamer_mmio;	__u16 sisr;	__u16 misr;	__u16 sisrmask;	sisrmask = SISR_MI;	writew(~sisrmask, streamer_mmio + SISR_MASK_RUM);	sisr = readw(streamer_mmio + SISR);	writew(~sisr, streamer_mmio + SISR_RUM);	misr = readw(streamer_mmio + MISR_RUM);	writew(~misr, streamer_mmio + MISR_RUM);	if (!sisr) 	{		/* Interrupt isn't for us */  	        writew(~misr,streamer_mmio+MISR_RUM);		return;	}	spin_lock(&streamer_priv->streamer_lock);	if ((sisr & (SISR_SRB_REPLY | SISR_ADAPTER_CHECK | SISR_ASB_FREE | SISR_ARB_CMD | SISR_TRB_REPLY))	    || (misr & (MISR_TX2_EOF | MISR_RX_NOBUF | MISR_RX_EOF))) {		if (sisr & SISR_SRB_REPLY) {			if (streamer_priv->srb_queued == 1) {				wake_up_interruptible(&streamer_priv->srb_wait);			} else if (streamer_priv->srb_queued == 2) {				streamer_srb_bh(dev);			}			streamer_priv->srb_queued = 0;		}		/* SISR_SRB_REPLY */		if (misr & MISR_TX2_EOF) {			while (streamer_priv->streamer_tx_ring[(streamer_priv->tx_ring_last_status + 1) & (STREAMER_TX_RING_SIZE - 1)].status) 			{				streamer_priv->tx_ring_last_status = (streamer_priv->tx_ring_last_status + 1) & (STREAMER_TX_RING_SIZE - 1);

⌨️ 快捷键说明

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