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

📄 tlan.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	 *	 *	Returns:	 *		0 on success, error code on error	 *	Parms: 	 *		none	 *	 *	The name is lower case to fit in with all the rest of	 *	the netcard_probe names.  This function looks for 	 *	another TLan based adapter, setting it up with the	 *	allocated device struct if one is found.	 *	tlan_probe has been ported to the new net API and	 *	now allocates its own device structure. This function	 *	is also used by modules.	 *	 **************************************************************/static int __devinit TLan_probe1(struct pci_dev *pdev, 				long ioaddr, int irq, int rev, const struct pci_device_id *ent ){	struct net_device  *dev;	TLanPrivateInfo    *priv;	u8		   pci_rev;	u16		   device_id;	dev = init_etherdev(NULL, sizeof(TLanPrivateInfo));	if (dev == NULL) {		printk(KERN_ERR "TLAN: Could not allocate memory for device.\n");		return -ENOMEM;	}	SET_MODULE_OWNER(dev);		priv = dev->priv;			dev->base_addr = ioaddr;	dev->irq = irq;	 	/* Is this a PCI device? */	if (pdev) {		priv->adapter = &board_info[ent->driver_data];		if (pci_enable_device(pdev)) {			unregister_netdev(dev);			kfree(dev);			return -1;		}		pci_read_config_byte ( pdev, PCI_REVISION_ID, &pci_rev);		priv->adapterRev = pci_rev; 		pci_set_master(pdev);		pdev->driver_data = dev;	} else	{     /* EISA card */		/* This is a hack. We need to know which board structure		 * is suited for this adapter */		device_id = inw(ioaddr + EISA_ID2);		priv->is_eisa = 1;		if (device_id == 0x20F1) {			priv->adapter = &board_info[13]; 	/* NetFlex-3/E */			priv->adapterRev = 23;			/* TLAN 2.3 */		} else {			priv->adapter = &board_info[14];			priv->adapterRev = 10;			/* TLAN 1.0 */		}	}	/* Kernel parameters */	if (dev->mem_start) {		priv->aui    = dev->mem_start & 0x01;		priv->duplex = ((dev->mem_start & 0x06) == 0x06) ? 0 : (dev->mem_start & 0x06) >> 1;		priv->speed  = ((dev->mem_start & 0x18) == 0x18) ? 0 : (dev->mem_start & 0x18) >> 3;			if (priv->speed == 0x1) {			priv->speed = TLAN_SPEED_10;		} else if (priv->speed == 0x2) {			priv->speed = TLAN_SPEED_100;		}		debug = priv->debug = dev->mem_end;	} else {		if ( ( duplex != 1 ) && ( duplex != 2 ) ) 			duplex = 0;				priv->duplex = duplex;		if ( ( speed != 10 ) && ( speed != 100 ) )			speed = 0;				priv->aui   = aui;		priv->speed = speed;		priv->debug = debug;			}		spin_lock_init(&priv->lock);		if (TLan_Init(dev)) {		printk(KERN_ERR "TLAN: Could not register device.\n");		unregister_netdev(dev);		kfree(dev);		return -EAGAIN;	} else {		TLanDevicesInstalled++;		/* pdev is NULL if this is an EISA device */	if (pdev)		tlan_have_pci++;	else {		priv->nextDevice = TLan_Eisa_Devices;		TLan_Eisa_Devices = dev;		tlan_have_eisa++;	}		printk(KERN_INFO "TLAN: %s irq=%2d, io=%04x, %s, Rev. %d\n",			dev->name,			(int) dev->irq,			(int) dev->base_addr,			priv->adapter->deviceLabel,			priv->adapterRev);	return 0;	}}static void TLan_Eisa_Cleanup(void){	struct net_device *dev;	TLanPrivateInfo *priv;		while( tlan_have_eisa ) {		dev = TLan_Eisa_Devices;		priv = (TLanPrivateInfo *) dev->priv;		if (priv->dmaStorage) {			kfree(priv->dmaStorage);		}		release_region( dev->base_addr, 0x10);		unregister_netdev( dev );		TLan_Eisa_Devices = priv->nextDevice;		kfree( dev );		tlan_have_eisa--;	}}			static void __exit tlan_exit(void){	if (tlan_have_pci)		pci_unregister_driver(&tlan_driver);	if (tlan_have_eisa)		TLan_Eisa_Cleanup();	kfree( TLanPadBuffer );}/* Module loading/unloading */module_init(tlan_probe);module_exit(tlan_exit);	/**************************************************************	 * 	TLan_EisaProbe	 *	 *  	Returns: 0 on success, 1 otherwise	 *	 *  	Parms:	 None	 *	 *	 *  	This functions probes for EISA devices and calls 	 *  	TLan_probe1 when one is found. 	 *	 *************************************************************/static void  __init TLan_EisaProbe (void) {	long 	ioaddr;	int 	rc = -ENODEV;	int 	irq;	u16	device_id;	if (!EISA_bus) {			TLAN_DBG(TLAN_DEBUG_PROBE, "No EISA bus present\n");		return;	}		/* Loop through all slots of the EISA bus */	for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) {			TLAN_DBG(TLAN_DEBUG_PROBE,"EISA_ID 0x%4x: 0x%4x\n", (int) ioaddr + 0xC80, inw(ioaddr + EISA_ID));		TLAN_DBG(TLAN_DEBUG_PROBE,"EISA_ID 0x%4x: 0x%4x\n", (int) ioaddr + 0xC82, inw(ioaddr + EISA_ID2));		TLAN_DBG(TLAN_DEBUG_PROBE, "Probing for EISA adapter at IO: 0x%4x : ",				   	(int) ioaddr);		if (request_region(ioaddr, 0x10, TLanSignature) == NULL) 			goto out;		if (inw(ioaddr + EISA_ID) != 0x110E) {					release_region(ioaddr, 0x10);			goto out;		}				device_id = inw(ioaddr + EISA_ID2);		if (device_id !=  0x20F1 && device_id != 0x40F1) { 					release_region (ioaddr, 0x10);			goto out;		}			 	if (inb(ioaddr + EISA_CR) != 0x1) { 	/* Check if adapter is enabled */			release_region (ioaddr, 0x10);			goto out2;		}				if (debug == 0x10)					printk("Found one\n");		/* Get irq from board */		switch (inb(ioaddr + 0xCC0)) {			case(0x10):				irq=5;				break;			case(0x20):				irq=9;				break;			case(0x40):				irq=10;				break;			case(0x80):				irq=11;				break;			default:				goto out;		}               						/* Setup the newly found eisa adapter */		rc = TLan_probe1( NULL, ioaddr, irq,					12, NULL);		continue;				out:			if (debug == 0x10)				printk("None found\n");			continue;		out2:	if (debug == 0x10)				printk("Card found but it is not enabled, skipping\n");			continue;			}} /* TLan_EisaProbe */		/***************************************************************	 *	TLan_Init	 *	 *	Returns:	 *		0 on success, error code otherwise.	 *	Parms:	 *		dev	The structure of the device to be	 *			init'ed.	 *	 *	This function completes the initialization of the	 *	device structure and driver.  It reserves the IO	 *	addresses, allocates memory for the lists and bounce	 *	buffers, retrieves the MAC address from the eeprom	 *	and assignes the device's methods.	 *		 **************************************************************/static int TLan_Init( struct net_device *dev ){	int		dma_size;	int 		err;	int		i;	TLanPrivateInfo	*priv;	priv = (TLanPrivateInfo *) dev->priv;		if (!priv->is_eisa)	/* EISA devices have already requested IO */		if (!request_region( dev->base_addr, 0x10, TLanSignature )) {			printk(KERN_ERR "TLAN: %s: IO port region 0x%lx size 0x%x in use.\n",				dev->name,				dev->base_addr,				0x10 );			return -EIO;		}		if ( bbuf ) {		dma_size = ( TLAN_NUM_RX_LISTS + TLAN_NUM_TX_LISTS )	           * ( sizeof(TLanList) + TLAN_MAX_FRAME_SIZE );	} else {		dma_size = ( TLAN_NUM_RX_LISTS + TLAN_NUM_TX_LISTS )	           * ( sizeof(TLanList) );	}	priv->dmaStorage = kmalloc(dma_size, GFP_KERNEL | GFP_DMA);	if ( priv->dmaStorage == NULL ) {		printk(KERN_ERR "TLAN:  Could not allocate lists and buffers for %s.\n",			dev->name );		return -ENOMEM;	}	memset( priv->dmaStorage, 0, dma_size );	priv->rxList = (TLanList *) 		       ( ( ( (u32) priv->dmaStorage ) + 7 ) & 0xFFFFFFF8 );	priv->txList = priv->rxList + TLAN_NUM_RX_LISTS;	if ( bbuf ) {		priv->rxBuffer = (u8 *) ( priv->txList + TLAN_NUM_TX_LISTS );		priv->txBuffer = priv->rxBuffer				 + ( TLAN_NUM_RX_LISTS * TLAN_MAX_FRAME_SIZE );	}	err = 0;	for ( i = 0;  i < 6 ; i++ )		err |= TLan_EeReadByte( dev,					(u8) priv->adapter->addrOfs + i,					(u8 *) &dev->dev_addr[i] );	if ( err ) {		printk(KERN_ERR "TLAN: %s: Error reading MAC from eeprom: %d\n",			dev->name,			err );	}	dev->addr_len = 6;		/* Device methods */	dev->open = &TLan_Open;	dev->hard_start_xmit = &TLan_StartTx;	dev->stop = &TLan_Close;	dev->get_stats = &TLan_GetStats;	dev->set_multicast_list = &TLan_SetMulticastList;	dev->do_ioctl = &TLan_ioctl;	dev->tx_timeout = &TLan_tx_timeout;	dev->watchdog_timeo = TX_TIMEOUT;	return 0;} /* TLan_Init */	/***************************************************************	 *	TLan_Open	 *	 *	Returns:	 *		0 on success, error code otherwise.	 *	Parms:	 *		dev	Structure of device to be opened.	 *	 *	This routine puts the driver and TLAN adapter in a	 *	state where it is ready to send and receive packets.	 *	It allocates the IRQ, resets and brings the adapter	 *	out of reset, and allows interrupts.  It also delays	 *	the startup for autonegotiation or sends a Rx GO	 *	command to the adapter, as appropriate.	 *	 **************************************************************/static int TLan_Open( struct net_device *dev ){	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;	int		err;		priv->tlanRev = TLan_DioRead8( dev->base_addr, TLAN_DEF_REVISION );	err = request_irq( dev->irq, TLan_HandleInterrupt, SA_SHIRQ, TLanSignature, dev );		if ( err ) {		printk(KERN_ERR "TLAN:  Cannot open %s because IRQ %d is already in use.\n", dev->name, dev->irq );		return err;	}		init_timer(&priv->timer);	netif_start_queue(dev);		/* NOTE: It might not be necessary to read the stats before a			 reset if you don't care what the values are.	*/	TLan_ResetLists( dev );	TLan_ReadAndClearStats( dev, TLAN_IGNORE );	TLan_ResetAdapter( dev );	TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Opened.  TLAN Chip Rev: %x\n", dev->name, priv->tlanRev );	return 0;} /* TLan_Open */	/**************************************************************	 *	TLan_ioctl	 *		 *	Returns:	 *		0 on success, error code otherwise	 *	Params:	 *		dev	structure of device to receive ioctl.	 *			 *		rq	ifreq structure to hold userspace data.	 *	 *		cmd	ioctl command.	 *	 *	 *************************************************************/static int TLan_ioctl(struct net_device *dev, struct ifreq *rq, int cmd){	TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;	u16 *data = (u16 *)&rq->ifr_data;	u32 phy   = priv->phy[priv->phyNum];		if (!priv->phyOnline)		return -EAGAIN;	switch(cmd) {		case SIOCDEVPRIVATE:			data[0] = phy;		case SIOCDEVPRIVATE+1: /* Read MII register */			TLan_MiiReadReg(dev, data[0], data[1], &data[3]);			return 0;				case SIOCDEVPRIVATE+2: /* Write MII register */			if (!capable(CAP_NET_ADMIN))				return -EPERM;			TLan_MiiWriteReg(dev, data[0], data[1], data[2]);			return 0;		default:			return -EOPNOTSUPP;	}} /* tlan_ioctl */	/***************************************************************	 * 	TLan_tx_timeout	 *	 * 	Returns: nothing	 *	 * 	Params:

⌨️ 快捷键说明

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