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

📄 smc91113.c

📁 SMSC lan91c113 uclinux driver source
💻 C
📖 第 1 页 / 共 5 页
字号:
int __init smc_init(struct net_device *dev){	int i;	int base_addr = dev ? dev->base_addr : 0;	PRINTK2("CARDNAME:smc_init\n");	SET_MODULE_OWNER (dev);    smc_cpu_init();	/*  try a specific location */	if (base_addr > 0x1ff)		return smc_probe(dev, base_addr);	else if ( 0 != base_addr ) 			return -ENXIO;			/* check every ethernet address */	for (i = 0; smc_portlist[i]; i++) 		if ( smc_probe(dev,smc_portlist[i]) ==0)			return 0;	/* couldn't find anything */	return -ENODEV;}/*------------------------------------------------------------------------- | | smc_destructor( struct device * dev ) |   Input parameters: |	dev, pointer to the device structure | |   Output: |	None. | ---------------------------------------------------------------------------*/void smc_destructor(struct net_device *dev){	PRINTK2("CARDNAME:smc_destructor\n");}/*---------------------------------------------------------------------- . Function: smc_probe( int ioaddr ) . . Purpose: .	Tests to see if a given ioaddr points to an SMC91113 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 = 0;	unsigned int	bank;    const char *version_string;	/*registers */	word	revision_register;	word	base_address_register;	word  	memory_info_register;	/*=> Pramod */	struct smc_local *lp;	/*<= Pramod */	PRINTK2("CARDNAME:smc_probe\n");	/* Grab the region so that no one else tries to probe our ioports. */	if (!request_region(ioaddr, SMC_IO_EXTENT, dev->name)) 	    return -EBUSY;	/* First, see if the high byte is 0x33 */	bank = inw( ioaddr + BANK_SELECT );     /* Qinwei say, high byte will always be 0x33*/	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 );      /* Qinwei say , switch to bank 0 and test again!*/	bank = inw( ioaddr + BANK_SELECT );	if ( (bank & 0xFF00 ) != 0x3300 )	{		retval = -ENODEV;		goto err_out;	}	/* 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_REG ); /* Qinwei : should get 0x1801 in EV44b0*/	if ( (ioaddr - CONFIG_SMC91113_CS) != ( 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;	}	/*  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  = inw( ioaddr + REV_REG ); /* Qinwei: must get 0x3391 on EV44b0II*/	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 );    /*Read the value from Chip, when reset,chip maybe read from eeprom.*/    if (iic_mac(&(dev->dev_addr[0])))    {        /*	for ( i = 0; i < 6; i += 2 )
        	{
        		word	address;
        
        		address = inw( ioaddr + ADDR0_REG + i  );
        		dev->dev_addr[ i + 1] = address >> 8;
        		dev->dev_addr[ i ] = address & 0xFF;
        	}*/
    }    else    {        // set default MAC address // Qinwei, can read the MAC from EEprom on reset    	dev->dev_addr[0] = 0x00;    	dev->dev_addr[1] = 0x0B;    	dev->dev_addr[2] = 0x51;    	dev->dev_addr[3] = 0x00;    	dev->dev_addr[4] = 0x0F;    	dev->dev_addr[5] = 0xFF;    }    	for ( i = 0; i < 6; i += 2 )	{		word	address;				address = dev->dev_addr[ i ];		address += dev->dev_addr[ i + 1] << 8;		outw( address, ioaddr + ADDR0_REG + i );	}	/* Qinwei:get the memory information from chip, as 91c113, should 04*/	SMC_SELECT_BANK( 0 );	memory_info_register = inw( ioaddr + MIR_REG );	memory = memory_info_register & (word)0x00ff;	memory *= LAN91C113_MEMORY_MULTIPLIER; /*Qinwei: now we have 8K*/	/*	 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 + REV_REG );	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;	}	/* Qinwei: reset the chip, and put it into a known state */	smc_reset( dev );	/* Qinwei: every thing seems OK, print out the card info, in a short format.. */	printk("%s: %s(rev:%d) at %#3x IRQ:%d MEMSIZE:%db NOWAIT:%d ",		dev->name,		version_string, revision_register & 0xF, ioaddr, dev->irq,		memory, dev->dma);		/* Qinwei: Print the Ethernet address */	printk("\n      Deafult MAC ADDR: ");	for (i = 0; i < 5; i++)		printk("%2.2x:", dev->dev_addr[i] );	printk("%2.2x \n", dev->dev_addr[5] );	/* Create the private structure. */	if (dev->priv == NULL) {		dev->priv = kmalloc(sizeof(struct smc_local), GFP_KERNEL);		if (dev->priv == NULL) {			retval = -ENOMEM;			goto err_out;		}	}	/* set the private data to zero by default */	memset(dev->priv, 0, sizeof(struct smc_local));	/* Fill in the fields of the device structure with ethernet values. */	ether_setup(dev);	/* Grab the IRQ */	disable_irq(dev->irq); /* Qinwei : Disable the interrupt first.*/	    retval = request_irq(dev->irq, &smc_interrupt, SA_INTERRUPT, "ether Rx/Tx", dev);    if (retval) {       	  printk("%s: unable to get IRQ %d (irqval=%d).\n",		dev->name, dev->irq, retval);		  kfree (dev->priv);		  dev->priv = NULL;		  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->get_stats			= smc_query_statistics;#ifdef	HAVE_MULTICAST	dev->set_multicast_list = &smc_set_multicast_list;#endif	/* => Store the ChipRevision and ChipID, to be used in resolving the Odd-Byte issue in RevB of LAN91C113; Pramod */	SMC_SELECT_BANK(3);	revision_register  = inw( ioaddr + REV_REG );	lp = (struct smc_local *)dev->priv;	lp->ChipID = (revision_register >> 4) & 0xF;	lp->ChipRev = revision_register & 0xF;	/* Qinwei: for config the PHY on kernel, remove the initial PHY on smc_open  */	lp->rpc_cur_mode = RPC_DEFAULT;	lp->tcr_cur_mode = TCR_DEFAULT;	lp->rcr_cur_mode = RCR_DEFAULT;	smc_enable( dev );	smc_phy_configure(dev);	return 0;err_out:	release_region (ioaddr, SMC_IO_EXTENT);	return retval;}#if SMC_DEBUG > 2static void print_packet( byte * buf, int length ){#if 1	int i;	int remainder;	int lines;	printk("Packet of length %d \n", length );#if SMC_DEBUG > 3	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}#endif/* * Open and Initialize the board * * Set up everything, reset the card, etc .. * */static int smc_open(struct net_device *dev){	struct smc_local *lp 	= (struct smc_local *)dev->priv;	unsigned int	ioaddr = dev->base_addr;	int	i;	/* used to set hw ethernet address */	PRINTK2("%s:smc_open\n", dev->name);	/* clear out all the junk that was put here before... */	/* Qinwei: we already clear it on SMC_probe, and fill some infomation, so mark following line.*/    //	memset(dev->priv, 0, sizeof(struct smc_local));     /* Qinwei: Start the transmit queue*/	netif_start_queue(dev);	// Setup the default Register Modes	lp->tcr_cur_mode = TCR_DEFAULT;	lp->rcr_cur_mode = RCR_DEFAULT;#ifdef CONFIG_SYSCTL	// Set default parameters (files)	lp->ctl_swfdup = 0;	lp->ctl_ephloop = 0;	lp->ctl_miiop = 0;	lp->ctl_autoneg = 1;	lp->ctl_rfduplx = 1;	lp->ctl_rspeed = 100;	lp->ctl_afduplx = 1;	lp->ctl_aspeed = 100;	lp->ctl_lnkfail = 1;	lp->ctl_forcol = 0;	lp->ctl_filtcar = 0;#endif// CONFIG_SYSCTL	/* reset the hardware */	/* Qinwei: we already do it on SMC_probe,so can mark following line.*/    //	smc_reset( dev );	smc_enable( dev );	/* Configure the PHY *//*	lp->rpc_cur_mode = RPC_DEFAULT;	smc_phy_configure(dev);*/	/*  		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...	*/	SMC_SELECT_BANK( 1 );	for ( i = 0; i < 6; i += 2 ) {		word	address;		address = dev->dev_addr[ i + 1 ] << 8 ;		address  |= dev->dev_addr[ i ];		outw( address, ioaddr + ADDR0_REG + i );	}#ifdef CONFIG_SYSCTL	smc_sysctl_register(dev);#endif /* CONFIG_SYSCTL */ 	netif_start_queue(dev);	enable_irq(dev->irq); /* Qinwei; now open the interrupt*/	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){	PRINTK3("%s:smc_send_packet\n", dev->name);	/* 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 "%s: transmit timed out, %s?\n",dev->name, tx_done(dev) ? "IRQ conflict" :"network cable problem");	/* "kick" the adaptor */	smc_reset( dev );	smc_enable( dev );	/* Reconfigure the PHY */	smc_phy_configure(dev);	netif_wake_queue(dev);	dev->trans_start = jiffies;	/* clear anything saved */	((struct smc_local *)dev->priv)->saved_skb = NULL;	enable_irq(dev->irq); /* Qinwei; now open the interrupt*/}/*-------------------------------------------------------------------- . . This is the main routine of the driver, to handle the net_device when . it needs some attention. . . So: .   first, save state of the chipset .   branch off into routines to handle each case, and acknowledge .	    each to the interrupt register .   and finally restore state. . ---------------------------------------------------------------------*/static void smc_interrupt(int irq, void * dev_id,  struct pt_regs * regs){	struct net_device *dev 	= dev_id;	int    ioaddr 		= dev->base_addr;	struct smc_local *lp 	= (struct smc_local *)dev->priv;	byte	status;	word	card_stats;	byte	mask;	int	timeout;	/* state registers */	word	saved_bank;	word	saved_pointer;	PRINTK3("%s: SMC interrupt started \n", dev->name);	if (dev == NULL) {		printk(KERN_WARNING "%s: irq %d for unknown device.\n",			dev->name, irq);		return;	}/* will Linux let this happen ??  If not, this costs some speed	if ( dev->interrupt ) {		printk(KERN_WARNING "%s: interrupt inside interrupt.\n",			dev->name);		return;	}	dev->interrupt = 1; */	saved_bank = inw( ioaddr + BANK_SELECT );	SMC_SELECT_BANK(2);	saved_pointer = inw( ioaddr + PTR_REG );	/* read the interrupt status register */	mask = inb( ioaddr + IM_REG );	/* disable all interrupts */	outb( 0, ioaddr + IM_REG );	/* set a timeout value, so I don't stay here forever */	timeout = 4;	PRINTK2(KERN_WARNING "%s: MASK IS %x \n", dev->name, mask);	do {		/* read the status flag, and mask it */

⌨️ 快捷键说明

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