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

📄 smc9194.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 4 页
字号:
	 * when done.	 */	SMC_SELECT_BANK(2);	/* enable ALLOCation interrupts ONLY */	outb( IM_ALLOC_INT, ioaddr + INT_MASK );	/* 	 . 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);	/*	 . Wait until positive that the interrupt has been generated	*/	while (timeout) {		byte	int_status;		int_status = smc_inb(ioaddr, INTERRUPT);		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.	*/	SMC_DELAY();	SMC_DELAY();	/* and disable all interrupts again */	outb( 0, ioaddr + INT_MASK );	/* 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);#else /* NO_AUTOPROBE */	struct devlist *smcdev;	for (smcdev = smc_devlist; smcdev->port; smcdev++) {		if (smcdev->port == ioaddr)			return smcdev->irq;	}	return 0;#endif}/*---------------------------------------------------------------------- . Function: smc_probe( int ioaddr ) . . Purpose: .	Tests to see if a given ioaddr points to an SMC9xxx 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 __init smc_probe(struct net_device *dev, int ioaddr){	int i, memory, retval;	static unsigned version_printed;	unsigned int bank;	const char *version_string;	const char *if_string;	/* registers */	word revision_register;	word base_address_register;	word configuration_register;	word memory_info_register;	word memory_cfg_register;	/* Grab the region so that no one else tries to probe our ioports. */	if (!request_region(ioaddr, SMC_IO_EXTENT, DRV_NAME))	dev->irq = irq;	dev->if_port = ifport;	/* First, see if the high byte is 0x33 */	bank = inw( ioaddr + BANK_SELECT );	if ( (bank & 0xFF00) != 0x3300 ) {		retval = -ENODEV;		goto err_out;	}	/* The above MIGHT indicate a device, but I need to write to further 	 	test this.  */	outw( 0x0, ioaddr + BANK_SELECT );	bank = inw( ioaddr + BANK_SELECT );	if ( (bank & 0xFF00 ) != 0x3300 ) {		retval = -ENODEV;		goto err_out;	}#if !defined(CONFIG_H8S_EDOSK2674)	/* well, we've already written once, so hopefully another time won't 	   hurt.  This time, I need to switch the bank register to bank 1,	   so I can access the base address register */	SMC_SELECT_BANK(1);	base_address_register = inw( ioaddr + BASE );	if ( ioaddr != ( base_address_register >> 3 & 0x3E0 ) )  {		printk(CARDNAME ": IOADDR %x doesn't match configuration (%x)."			"Probably not a SMC chip\n",			ioaddr, base_address_register >> 3 & 0x3E0 );		/* well, the base address register didn't match.  Must not have		   been a SMC chip after all. */		retval = -ENODEV;		goto err_out;	}#else	(void)base_address_register; /* Warning suppression */#endif	/*  check if the revision register is something that I recognize.	    These might need to be added to later, as future revisions	    could be added.  */	SMC_SELECT_BANK(3);	revision_register = smc_inw(ioaddr, REVISION);	if ( !chip_ids[ ( revision_register  >> 4 ) & 0xF  ] ) {		/* I don't recognize this chip, so... */		printk(CARDNAME ": IO %x: Unrecognized revision register:"			" %x, Contact author. \n", ioaddr, revision_register );		retval = -ENODEV;		goto err_out;	}	/* at this point I'll assume that the chip is an SMC9xxx.	   It might be prudent to check a listing of MAC addresses	   against the hardware address, or do some other tests. */	if (version_printed++ == 0)		printk("%s", version);	/* fill in some of the fields */	dev->base_addr = ioaddr;	/* 	 . Get the MAC address (bank 1, regs 4 - 9)	*/	SMC_SELECT_BANK(1);	for (i = 0; i < 6; i += 2) {		word	address;		address = smc_inw(ioaddr, ADDR0 + i);		dev->dev_addr[i + 1] = address >> 8;		dev->dev_addr[i] = address & 0xFF;	}	/* get the memory information */	SMC_SELECT_BANK(0);	memory_info_register = smc_inw(ioaddr, MIR);	memory_cfg_register = smc_inw(ioaddr, MCR);	memory = (memory_cfg_register >> 9) & 0x7;  /* multiplier */	memory *= 256 * (memory_info_register & 0xFF);	memory = ( memory_cfg_register >> 9 )  & 0x7;  /* multiplier */	/*	 Now, I want to find out more about the chip.  This is sort of 	 redundant, but it's cleaner to have it in both, rather than having 	 one VERY long probe procedure.	*/	SMC_SELECT_BANK(3);	revision_register  = inw( ioaddr + REVISION );	version_string = chip_ids[ ( revision_register  >> 4 ) & 0xF  ];	if ( !version_string ) {		/* I shouldn't get here because this call was done before.... */		retval = -ENODEV;		goto err_out;	}	/* is it using AUI or 10BaseT ? */	if ( dev->if_port == 0 ) {		SMC_SELECT_BANK(1);		configuration_register = inw( ioaddr + CONFIG );		if ( configuration_register & CFG_AUI_SELECT )			dev->if_port = 2;		else			dev->if_port = 1;	}	if_string = interfaces[ dev->if_port - 1 ];	/* now, reset the chip, and put it into a known state */	smc_reset( ioaddr );	/*	 . If dev->irq is 0, then the device has to be banged on to see	 . what the IRQ is. 	 .	 . This banging doesn't always detect the IRQ, for unknown reasons.	 . a workaround is to reset the chip and try again.	 .	 . Interestingly, the DOS packet driver *SETS* the IRQ on the card to	 . be what is requested on the command line.   I don't do that, mostly	 . because the card that I have uses a non-standard method of accessing	 . the IRQs, and because this _should_ work in most configurations.	 .	 . Specifying an IRQ is done with the assumption that the user knows	 . what (s)he is doing.  No checking is done!!!! 	 .	*/	if ( dev->irq < 2 ) {		int	trials;		trials = 3;		while ( trials-- ) {			dev->irq = smc_findirq( ioaddr );			if ( dev->irq )				break;			/* kick the card and try again */			smc_reset( ioaddr );		}	}	if (dev->irq == 0 ) {		printk(CARDNAME": Couldn't autodetect your IRQ. Use irq=xx.\n");		retval = -ENODEV;		goto err_out;	}	/* now, print out the card info, in a short format.. */	printk("%s: %s(r:%d) at %#3x IRQ:%d INTF:%s MEM:%db ", dev->name,		version_string, revision_register & 0xF, ioaddr, dev->irq,		if_string, memory );	/*	 . Print the Ethernet address	*/	printk("ADDR: ");	for (i = 0; i < 5; i++)		printk("%2.2x:", dev->dev_addr[i] );	printk("%2.2x \n", dev->dev_addr[5] );	/* set the private data to zero by default */	memset(dev->priv, 0, sizeof(struct smc_local));	/* Grab the IRQ */      	retval = request_irq(dev->irq, &smc_interrupt, 0, DRV_NAME, dev);      	if (retval) {		printk("%s: unable to get IRQ %d (irqval=%d).\n", DRV_NAME,			dev->irq, retval);  	  	goto err_out;      	}	dev->open		        = smc_open;	dev->stop		        = smc_close;	dev->hard_start_xmit    	= smc_wait_to_send_packet;	dev->tx_timeout		    	= smc_timeout;	dev->watchdog_timeo		= HZ/20;	dev->get_stats			= smc_query_statistics;	dev->set_multicast_list 	= smc_set_multicast_list;	return 0;err_out:	release_region(ioaddr, SMC_IO_EXTENT);	return retval;}#if SMC_DEBUG > 2static void print_packet( byte * buf, int length ){#if 0	int i;	int remainder;	int lines;	printk("Packet of length %d \n", length );	lines = length / 16;	remainder = length % 16;	for ( i = 0; i < lines ; i ++ ) {		int cur;		for ( cur = 0; cur < 8; cur ++ ) {			byte a, b;			a = *(buf ++ );			b = *(buf ++ );			printk("%02x%02x ", a, b );		}		printk("\n");	}	for ( i = 0; i < remainder/2 ; i++ ) {		byte a, b;		a = *(buf ++ );		b = *(buf ++ );		printk("%02x%02x ", a, b );	}	printk("\n");#endif}#endif/* * Open and Initialize the board * * Set up everything, reset the card, etc .. * */static int smc_open(struct net_device *dev){	int	ioaddr = dev->base_addr;	int	i;	/* used to set hw ethernet address */	/* clear out all the junk that was put here before... */	memset(dev->priv, 0, sizeof(struct smc_local));	/* reset the hardware */	smc_reset( ioaddr );	smc_enable( ioaddr );	/* Select which interface to use */	SMC_SELECT_BANK( 1 );	if ( dev->if_port == 1 ) {		outw( inw( ioaddr + CONFIG ) & ~CFG_AUI_SELECT,			ioaddr + CONFIG );	}	else if ( dev->if_port == 2 ) {		outw( inw( ioaddr + CONFIG ) | CFG_AUI_SELECT,			ioaddr + CONFIG );	}	/*  		According to Becker, I have to set the hardware address		at this point, because the (l)user can set it with an		ioctl.  Easily done...	*/		address  |= dev->dev_addr[ i ];	netif_start_queue(dev);	return 0;}/*-------------------------------------------------------- . Called by the kernel to send a packet out into the void . of the net.  This routine is largely based on . skeleton.c, from Becker. .--------------------------------------------------------*/static void smc_timeout(struct net_device *dev){	/* If we get here, some higher level has decided we are broken.	   There should really be a "kick me" function call instead. */	printk(KERN_WARNING CARDNAME": transmit timed out, %s?\n",		tx_done(dev) ? "IRQ conflict" :		"network cable problem");	/* "kick" the adaptor */	smc_reset( dev->base_addr );	smc_enable( dev->base_addr );	dev->trans_start = jiffies;	/* clear anything saved */	((struct smc_local *)dev->priv)->saved_skb = NULL;	netif_wake_queue(dev);}/*------------------------------------------------------------- . . smc_rcv -  receive a packet from the card . . There is ( at least ) a packet waiting to be read from . chip-memory. . . o Read the status . o If an error, record it . o otherwise, read in the packet --------------------------------------------------------------*/static void smc_rcv(struct net_device *dev){	struct smc_local *lp = netdev_priv(dev);	int 	ioaddr = dev->base_addr;	int 	packet_number;	word	status;	word	packet_length;	/* assume bank 2 */	packet_number = inw( ioaddr + FIFO_PORTS );	if ( packet_number & FP_RXEMPTY ) {		/* we got called , but nothing was on the FIFO */		PRINTK((CARDNAME ": WARNING: smc_rcv with nothing on FIFO. \n"));		/* don't need to restore anything */		return;	}	/*  start reading from the start of the packet */	outw( PTR_READ | PTR_RCV | PTR_AUTOINC, ioaddr + POINTER );

⌨️ 快捷键说明

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