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

📄 smc9194.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 4 页
字号:
	/* and tell the card to stay away from that nasty outside world */	SMC_SELECT_BANK(0);	smc_outw(RCR_CLEAR, ioaddr, RCR);	smc_outw(TCR_CLEAR, ioaddr, TCR);	outb( RCR_CLEAR, ioaddr + RCR );	outb( TCR_CLEAR, ioaddr + TCR );#if 0	/* finally, shut the chip down */	SMC_SELECT_BANK(1);	smc_outw(smc_inw(ioaddr, CONTROL), CTL_POWERDOWN, ioaddr, CONTROL);	outw( inw( ioaddr + CONTROL ), CTL_POWERDOWN, ioaddr + CONTROL  );#endif}/* . Function: smc_setmulticast( int ioaddr, int count, dev_mc_list * adds ) . Purpose: .    This sets the internal hardware table to filter out unwanted multicast .    packets before they take up memory. . .    The SMC chip uses a hash table where the high 6 bits of the CRC of .    address are the offset into the table.  If that bit is 1, then the .    multicast packet is accepted.  Otherwise, it's dropped silently. . .    To use the 6 bits as an offset into the table, the high 3 bits are the .    number of the 8 bit register, while the low 3 bits are the bit within .    that register. . . This routine is based very heavily on the one provided by Peter Cammaert.*/static void smc_setmulticast( int ioaddr, int count, struct dev_mc_list * addrs ) {	int			i;	unsigned char		multicast_table[8];	struct dev_mc_list	* cur_addr;	/* table for flipping the order of 3 bits */	unsigned char invert3[] = { 0, 4, 2, 6, 1, 5, 3, 7 };	/* start with a table of all zeros: reject all */	memset(multicast_table, 0, sizeof(multicast_table));	cur_addr = addrs;	for (i = 0; i < count ; i ++, cur_addr = cur_addr->next) {		int position;		/* do we have a pointer here? */		if (!cur_addr)			break;		/* make sure this is a multicast address - shouldn't this		   be a given if we have it here ? */		if (!(*cur_addr->dmi_addr & 1))			continue;		/* only use the low order bits */		position = ether_crc_le(6, cur_addr->dmi_addr) & 0x3f;		/* do some messy swapping to put the bit in the right spot */		multicast_table[invert3[position&7]] |=					(1<<invert3[(position>>3)&7]);	}	/* now, the table can be loaded into the chipset */	SMC_SELECT_BANK(3);	for ( i = 0; i < 8 ; i++ ) {		outb( multicast_table[i], ioaddr + MULTICAST1 + i );	}}/* . Function: smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * ) . Function: smc_wait_to_send_packet(struct sk_buff * skb, struct net_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 int smc_wait_to_send_packet(struct sk_buff * skb, struct net_device * dev){	struct smc_local *lp = netdev_priv(dev);	unsigned int ioaddr 	= dev->base_addr;	word 			length;	unsigned short 		numPages;	word			time_out;	netif_stop_queue(dev);	/* Well, I want to send the packet.. but I don't know	   if I can send it right now...  */	if (lp->saved_skb) {		/* THIS SHOULD NEVER HAPPEN. */		lp->stats.tx_aborted_errors++;		printk(CARDNAME": Bad Craziness - sent packet while busy.\n" );		return 1;	}	lp->saved_skb = skb;	length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;			/*	** 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 :))	**	** Pkt size for allocating is data length +6 (for additional status words,	** length and ctl!) If odd size last byte is included in this header.	*/	numPages = ((length & 0xfffe) + 6) / 256;	if (numPages > 7) {		printk("%s: Far too big packet error.\n", dev->name);		printk(CARDNAME": Far too big packet error. \n");		/* 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;	}	/* either way, a packet is waiting now */	lp->packets_waiting++;	/* now, try to allocate the memory */	SMC_SELECT_BANK(2);	smc_outw(MC_ALLOC | numPages, ioaddr, MMU_CMD);	/* 	. 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 {		word	status;		status = smc_inb(ioaddr, INTERRUPT);		if (status & IM_ALLOC_INT) {			/* acknowledge the interrupt */			outb( IM_ALLOC_INT, ioaddr + INTERRUPT );  			break;		}   	} while ( -- time_out );   	if ( !time_out ) {		/* oh well, wait until the chip finds memory later */		SMC_ENABLE_INT(IM_ALLOC_INT);      		PRINTK2((CARDNAME": memory allocation deferred. \n"));		/* it's deferred, but I'll handle it later */      		return 0;   	}	/* or YES! I can send the packet now.. */	smc_hardware_send_packet(dev);	netif_wake_queue(dev);	return 0;}/* . Function:  smc_hardware_send_packet(struct net_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 void smc_hardware_send_packet(struct net_device *dev){	struct smc_local *lp = netdev_priv(dev);	byte	 		packet_no;	struct sk_buff * 	skb = lp->saved_skb;	word			length;	unsigned int		ioaddr;	byte			* buf;	ioaddr = dev->base_addr;		PRINTK((CARDNAME": In XMIT with no packet to send \n"));		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, PNR_ARR + 1);	if (packet_no & 0x80) {		/* or isn't there?  BAD CHIP! */		printk(KERN_DEBUG CARDNAME": Memory allocation failed. \n");		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, PNR_ARR);	/* point to the beginning of the packet */	smc_outw(PTR_AUTOINC, ioaddr, POINTER);   	PRINTK3((CARDNAME": Trying to xmit packet of length %x\n", length ));#if SMC_DEBUG > 2	print_packet( buf, length );#endif	/* send the packet length (+6 for status, length and ctl byte) 	   and the status word (set to zeros) */	smc_outl((length + 6) << 16, ioaddr, DATA_1);	outw( 0, ioaddr + DATA_1 );	outb( (length+6) & 0xFF,ioaddr + DATA_1 );	outb( (length+6) >> 8 , ioaddr + DATA_1 );	/* 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?	*/	smc_outs(ioaddr, DATA_1, buf, length);#if !defined(__H8300H__) && !defined(__H8300S__)#else		ctrl_outw( *((word *)(buf + (length & 0xFFFFFFFC))),ioaddr +DATA_1);#endif	/* Send the last byte, if there is one.   */	if ((length & 1) == 0)	if ( (length & 1) == 0 ) {		outw( 0, ioaddr + DATA_1 );	} else {		outb( buf[length -1 ], ioaddr + DATA_1 );		outb( 0x20, ioaddr + DATA_1);	}	/* enable the interrupts */	SMC_ENABLE_INT(IM_TX_INT | IM_TX_EMPTY_INT);	/* and let the chipset deal with it */	smc_outw(MC_ENQUEUE, ioaddr, MMU_CMD);	PRINTK2((CARDNAME": Sent packet of length %d \n",length));	lp->saved_skb = NULL;	dev_kfree_skb_any (skb);	dev->trans_start = jiffies;	/* we can send another packet */	netif_wake_queue(dev);	return;}#ifdef CONFIG_OMAP_INNOVATOR_CEE  /* MVL-CEE */#include <linux/device.h>static int smc9194_suspend(struct device * dev, u32 state, u32 level);static int smc9194_resume(struct device * dev, u32 level);static struct device_driver smc9194_driver_ldm = {       name:      "smc9194",       devclass:  NULL,       probe:     NULL,       suspend:   smc9194_suspend,       resume:    smc9194_resume,       remove:    NULL,};static struct device smc9194_device_ldm = {       name: "SMC9194 ethernet",       bus_id: "eth",       driver: NULL,       power_state: DPM_POWER_ON,};static void smc9194_ldm_register(struct net_device *netdev){   extern void dsp_public_driver_register(struct device_driver *driver);   extern void dsp_public_device_register(struct device *device);   smc9194_device_ldm.platform_data = (void *) netdev;   dsp_public_driver_register(&smc9194_driver_ldm);   dsp_public_device_register(&smc9194_device_ldm);}static int smc9194_suspend(struct device * dev, u32 state, u32 level){	struct net_device *netdev = (struct net_device *) dev->platform_data;	u_int ioaddr = netdev->base_addr;	switch (level) {	case SUSPEND_POWER_DOWN:		SMC_SELECT_BANK(1);		smc_outw(smc_inw(ioaddr, CONTROL) | CTL_POWERDOWN, ioaddr,			 CONTROL);		break;        }	return 0;}static int smc9194_resume(struct device * dev, u32 level){	struct net_device *netdev = (struct net_device *) dev->platform_data;	u_int ioaddr = netdev->base_addr;	switch (level) {	case RESUME_POWER_ON:		SMC_SELECT_BANK(1);		smc_outw((smc_inw(ioaddr, CONTROL) & ~CTL_POWERDOWN)			 | CTL_AUTO_RELEASE, ioaddr, CONTROL);		break;        }	return 0;}#endif /* MVL-CEE *//*------------------------------------------------------------------------- | | smc_init(struct net_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 | ---------------------------------------------------------------------------*/static int io;static int irq;static int ifport;	static struct devlist *smcdev = smc_devlist;#ifndef NO_AUTOPROBE	smcdev = smc_devlist;#endif	SET_MODULE_OWNER(dev);	dev->irq = INT_ETHER_H4;	if (smc_probe(dev, base_addr) == 0) {		return 0;	}#else#error unknown OMAP type#endif#else	/* Assume default is CONFIG_ISA */	int i;	int base_addr = dev->base_addr;	SET_MODULE_OWNER(dev);	/*  try a specific location */	if (base_addr > 0x1ff)		return smc_probe(dev, base_addr);	else if (base_addr != 0)		return -ENXIO;	/* check every ethernet address */	for (i = 0; smc_portlist[i]; i++)		if (smc_probe(dev, smc_portlist[i]) == 0)		for (;smcdev->port; smcdev++) {			if (smc_probe(dev, smcdev->port) == 0)		if (!smcdev->port)			return 0;	/* couldn't find anything */#endif	/* Assume default is CONFIG_ISA */	return ret;}/*---------------------------------------------------------------------- . 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 __init smc_findirq( int ioaddr ){#ifndef NO_AUTOPROBE	int	timeout = 20;	unsigned long cookie;	/* 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

⌨️ 快捷键说明

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