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

📄 smc91111.c

📁 smc9111网卡芯片的linux驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
static intcrc32(char *s, int length){	/* indices */	int perByte;	int perBit;	/* crc polynomial for Ethernet */	const unsigned long poly = 0xedb88320;	/* crc value - preinitialized to all 1's */	unsigned long crc_value = 0xffffffff;	for (perByte = 0; perByte < length; perByte++) {		unsigned char c;		c = *(s++);		for (perBit = 0; perBit < 8; perBit++) {			crc_value = (crc_value >> 1) ^			    (((crc_value ^ c) & 0x01) ? poly : 0);			c >>= 1;		}	}	return crc_value;}/* . Function: smc_wait_to_send_packet( struct sk_buff * skb, struct device * ) . Purpose: .    Attempt to allocate memory for a packet, if chip-memory is not .    available, then tell the card to generate an interrupt when it .    is available. . . Algorithm: . . o	if the saved_skb is not currently null, then drop this packet .	on the floor.  This should never happen, because of TBUSY. . o	if the saved_skb is null, then replace it with the current packet, . o	See if I can sending it now. . o 	(NO): Enable interrupts and let the interrupt handler deal with it. . o	(YES):Send it now.*/static intsmc_wait_to_send_packet(struct sk_buff *skb, struct net_device *dev){	struct smc_local *lp = (struct smc_local *) dev->priv;	unsigned int ioaddr = dev->base_addr;	u16 length;	unsigned short numPages;#ifdef USE_AUTO_RELEASE	u16 time_out;	u16 status;#endif	PRINTK3("%s:smc_wait_to_send_packet\n", dev->name);	if (lp->saved_skb) {		/* THIS SHOULD NEVER HAPPEN. */		lp->stats.tx_aborted_errors++;		printk("%s: Bad Craziness - sent packet while busy.\n",		       dev->name);		return 1;	}	lp->saved_skb = skb;	length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;#if 0	/*	   ** The MMU wants the number of pages to be the number of 256 bytes	   ** 'pages', minus 1 ( since a packet can't ever have 0 pages :) )	   **	   ** The 91C111 ignores the size bits, but the code is left intact	   ** for backwards and future compatibility.	   **	   ** Pkt size for allocating is data length +6 (for additional status	   ** words, length and ctl!)	   **	   ** If odd size then last byte is included in this header.	 */	numPages = ((length & 0xfffe) + 6);	numPages >>= 8;		// Divide by 256	if (numPages > 7) {		printk("%s: Far too big packet error. \n", dev->name);		/* freeing the packet is a good thing here... but should		   . any packets of this size get down here?   */		dev_kfree_skb(skb);		lp->saved_skb = NULL;		/* this IS an error, but, i don't want the skb saved */		netif_wake_queue(dev);		return 0;	}#else	numPages = 0;#endif	/* either way, a packet is waiting now */	lp->packets_waiting++;	/* now, try to allocate the memory */	SMC_SELECT_BANK(2);#ifdef USE_AUTO_RELEASE        smc_wait_mmu_release_complete( ioaddr);	SMC_outw((MC_ALLOC | numPages), ioaddr, MMU_CMD_REG);	/*	   . Performance Hack	   .	   . wait a short amount of time.. if I can send a packet now, I send	   . it now.  Otherwise, I enable an interrupt and wait for one to be	   . available.	   .	   . I could have handled this a slightly different way, by checking to	   . see if any memory was available in the FREE MEMORY register.  However,	   . either way, I need to generate an allocation, and the allocation works	   . no matter what, so I saw no point in checking free memory.	 */	time_out = MEMORY_WAIT_TIME;	do {		status = SMC_inb(ioaddr, INT_REG);		if (status & IM_ALLOC_INT) {			/* acknowledge the interrupt */			SMC_outb(IM_ALLOC_INT, ioaddr, INT_REG);			break;		}	} while (--time_out);	if (!time_out) {		netif_stop_queue (dev);		/* oh well, wait until the chip finds memory later */		SMC_ENABLE_INT(IM_ALLOC_INT);		/* Check the status bit one more time just in case */		/* it snuk in between the time we last checked it */		/* and when we set the interrupt bit */		status = SMC_inb(ioaddr, INT_REG);		if (!(status & IM_ALLOC_INT)) {			PRINTK2("%s: memory allocation deferred. \n",					dev->name);			/* it's deferred, but I'll handle it later */			return 0;		}		/* Looks like it did sneak in, so disable */		/* the interrupt */		SMC_DISABLE_INT(IM_ALLOC_INT);	}	/* or YES! I can send the packet now.. */	smc_hardware_send_packet(dev);#else        /* dont use performance hack */        /* stop the queue and wait for alloc interrupt */        netif_stop_queue (dev);        spin_lock_irq(&lp->mmu_lock);        SMC_ENABLE_INT( IM_ALLOC_INT );        smc_wait_mmu_release_complete( ioaddr);        SMC_outw((MC_ALLOC | numPages), ioaddr, MMU_CMD_REG);	spin_unlock_irq(&lp->mmu_lock);#endif	return 0;}/* . Function:  smc_hardware_send_packet(struct device * ) . Purpose: .	This sends the actual packet to the SMC9xxx chip. . . Algorithm: . 	First, see if a saved_skb is available. .		( this should NOT be called if there is no 'saved_skb' .	Now, find the packet number that the chip allocated .	Point the data pointers at it in memory .	Set the length word in the chip's memory .	Dump the packet to chip memory .	Check if a last byte is needed ( odd length packet ) .		if so, set the control flag right . 	Tell the card to send it .	Enable the transmit interrupt, so I know if it failed . 	Free the kernel data if I actually sent it.*/static voidsmc_hardware_send_packet(struct net_device *dev){	struct smc_local *lp = (struct smc_local *) dev->priv;	u8 packet_no;	struct sk_buff *skb = lp->saved_skb;	u16 length;	unsigned int ioaddr;	unsigned char *buf;	PRINTK3("%s:smc_hardware_send_packet\n", dev->name);	ioaddr = dev->base_addr;	if (!skb) {		PRINTK("%s: In XMIT with no packet to send \n", dev->name);		return;	}	length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;	buf = skb->data;	/* If I get here, I _know_ there is a packet slot waiting for me */	packet_no = SMC_inb(ioaddr, AR_REG);	if (packet_no & AR_FAILED) {		/* or isn't there?  BAD CHIP! */		printk(KERN_INFO "%s: Memory allocation failed. \n",		       dev->name);		dev_kfree_skb_any(skb);		lp->saved_skb = NULL;		netif_wake_queue(dev);		return;	}	/* we have a packet address, so tell the card to use it */	SMC_outb(packet_no, ioaddr, PN_REG);	/* point to the beginning of the packet */	SMC_outw(PTR_AUTOINC, ioaddr, PTR_REG);	PRINTK3("%s: Trying to xmit packet of length %x\n", dev->name, length);#if SMC_DEBUG > 2	printk("Transmitting Packet\n");	print_packet(buf, length);#endif	/* send the packet length ( +6 for status, length and ctl byte )	   and the status word ( set to zeros ) */	if( lp->use_32bit) 		SMC_outl((length + 6) << 16, ioaddr, DATA_REG);	else	{		SMC_outw(0, ioaddr, DATA_REG);		/* send the packet length ( +6 for status words, length, and ctl */		SMC_outb((length + 6) & 0xFF, ioaddr, DATA_REG);		SMC_outb((length + 6) >> 8, ioaddr, DATA_REG);	}	/* send the actual data	   . I _think_ it's faster to send the longs first, and then	   . mop up by sending the last word.  It depends heavily	   . on alignment, at least on the 486.  Maybe it would be	   . a good idea to check which is optimal?  But that could take	   . almost as much time as is saved?	   . Well, the data fifo is dword aligned, hopefully buf ptr is	   . dword aligned, so sending longs is definitely a win... [jws]	 */	if( lp->use_32bit) 	{		if((unsigned int)buf & 2) { //gah, the sk buff is misaligned...			SMC_outw(*((u16 *) buf)++, ioaddr, DATA_REG);			length -=2;		}		SMC_outsl(ioaddr, DATA_REG, buf, length);		if (length & 0x2)			SMC_outw(*((u16 *) (buf + (length & ~3))), ioaddr, DATA_REG);	}	else  		SMC_outsw(ioaddr, DATA_REG, buf, length);	/* Send the last byte, if there is one.   */	if ((length & 1) == 0) {		SMC_outw(0, ioaddr, DATA_REG);	} else {		SMC_outb(buf[length - 1], ioaddr, DATA_REG);		SMC_outb(0x20, ioaddr, DATA_REG);	// Set odd bit in CONTROL BYTE	}	/* enable the interrupts */#ifdef USE_AUTO_RELEASE	SMC_ENABLE_INT((IM_TX_INT | IM_TX_EMPTY_INT));#else        SMC_ENABLE_INT( (IM_TX_INT) );        SMC_SELECT_BANK( 0 );        SMC_outw( SMC_inw( ioaddr , TCR_REG ) | TCR_ENABLE, ioaddr , TCR_REG );        SMC_SELECT_BANK( 2 );#endif	/* and let the chipset deal with it */	SMC_outw(MC_ENQUEUE, ioaddr, MMU_CMD_REG);	PRINTK2("%s: Sent packet of length %d \n", dev->name, length);        lp->tx_bytes += length;	lp->saved_skb = NULL;	dev_kfree_skb_any(skb);	dev->trans_start = jiffies;	/* we can send another packet */	/* but let's give the receiver some more time by waiting *///	netif_wake_queue(dev);	return;}/*------------------------------------------------------------------------- | | smc_init( struct device * dev ) |   Input parameters: |	dev->base_addr == 0, try to find all possible locations |	dev->base_addr == 1, return failure code |	dev->base_addr == 2, always allocate space,  and return success |	dev->base_addr == <anything else>   this is the address to check | |   Output: |	0 --> there is a device |	anything else, error | ---------------------------------------------------------------------------*/int __initsmc_init(struct net_device *dev){	#ifdef CONFIG_ARCH_S3C2410	unsigned long base_addr = dev->base_addr;       	SET_MODULE_OWNER(dev);	PRINTK2("%s: smc_init\n", dev->name);	/* try a specific location... */	if (base_addr)		return smc_probe(dev, base_addr);#endif	/* couldn't find anything */	return -ENODEV;}/*------------------------------------------------------------------------- | | smc_destructor( struct device * dev ) |   Input parameters: |	dev, pointer to the device structure | |   Output: |	None. | ---------------------------------------------------------------------------*/voidsmc_destructor(struct net_device *dev){	PRINTK2("%s: smc_destructor\n", dev->name);}#ifndef NO_AUTOPROBE/*---------------------------------------------------------------------- . smc_findirq . . This routine has a simple purpose -- make the SMC chip generate an . interrupt, so an auto-detect routine can detect it, and find the IRQ, ------------------------------------------------------------------------*/int __initsmc_findirq(unsigned int ioaddr){	int timeout = 20;	unsigned long cookie;	PRINTK2("%s:smc_findirq\n", CARDNAME);	/* I have to do a STI() here, because this is called from	   a routine that does an CLI during this process, making it	   rather difficult to get interrupts for auto detection */	sti();	cookie = probe_irq_on();	/*	 * What I try to do here is trigger an ALLOC_INT. This is done	 * by allocating a small chunk of memory, which will give an interrupt	 * when done.	 */	SMC_SELECT_BANK(2);	/* enable ALLOCation interrupts ONLY */	SMC_outb(IM_ALLOC_INT, ioaddr, IM_REG);	/*	   . Allocate 512 bytes of memory.  Note that the chip was just	   . reset so all the memory is available	 */	SMC_outw(MC_ALLOC | 1, ioaddr, MMU_CMD_REG);	/*	   . Wait until positive that the interrupt has been generated	 */	while (timeout) {		u8 int_status;		int_status = SMC_inb(ioaddr, INT_REG);		if (int_status & IM_ALLOC_INT)			break;	/* got the interrupt */		timeout--;	}	/* there is really nothing that I can do here if timeout fails,	   as autoirq_report will return a 0 anyway, which is what I	   want in this case.   Plus, the clean up is needed in both	   cases.  */	/* DELAY HERE!	   On a fast machine, the status might change before the interrupt	   is given to the processor.  This means that the interrupt was	   never detected, and autoirq_report fails to report anything.	   This should fix autoirq_* problems.	 */	mdelay(10);	/* and disable all interrupts again */	SMC_outb(0, ioaddr, IM_REG);	/* clear hardware interrupts again, because that's how it	   was when I was called... */	cli();	/* and return what I found */	return probe_irq_off(cookie);}#endif/*---------------------------------------------------------------------- . Function: smc_probe( int ioaddr ) . . Purpose: .	Tests to see if a given ioaddr points to an SMC91111 chip. .	Returns a 0 on success . . Algorithm: .	(1) see if the high byte of BANK_SELECT is 0x33 . 	(2) compare the ioaddr with the base register's address .	(3) see if I recognize the chip ID in the appropriate register . .--------------------------------------------------------------------- *//*--------------------------------------------------------------- . Here I do typical initialization tasks. . . o  Initialize the structure if needed . o  print out my vanity message if not done so already . o  print out what type of hardware is detected . o  print out the ethernet address . o  find the IRQ . o  set up my private data . o  configure the dev structure with my subroutines . o  actually GRAB the irq. . o  GRAB the region .-----------------------------------------------------------------*/static int __initsmc_probe(struct net_device *dev, unsigned int ioaddr){	int i, memory, retval;	static unsigned version_printed = 0;	unsigned int bank;	const char *version_string;	int interface;	/*registers */	u16 revision_register;	u16 base_address_register;	u16 memory_info_register;	/*=> Pramod */	struct smc_local *lp;	/*<= Pramod */	/* find the interface numbed */	for (interface = 0; interface < MAX_NETWORK_INTERFACE_COUNT; interface++) {		if ( smc_config[interface].port == dev->base_addr)		{			break;		}

⌨️ 快捷键说明

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