tlan.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,212 行 · 第 1/5 页

C
2,212
字号
	if ( priv->dmaStorage ) {		pci_free_consistent(priv->pciDev, priv->dmaSize, priv->dmaStorage, priv->dmaStorageDMA );	}#ifdef CONFIG_PCI	pci_release_regions(pdev);#endif		free_netdev( dev );			pci_set_drvdata( pdev, NULL );} static struct pci_driver tlan_driver = {	.name		= "tlan",	.id_table	= tlan_pci_tbl,	.probe		= tlan_init_one,	.remove		= __devexit_p(tlan_remove_one),	};static int __init tlan_probe(void){	static int	pad_allocated;		printk(KERN_INFO "%s", tlan_banner);		TLanPadBuffer = (u8 *) pci_alloc_consistent(NULL, TLAN_MIN_FRAME_SIZE, &TLanPadBufferDMA);	if (TLanPadBuffer == NULL) {		printk(KERN_ERR "TLAN: Could not allocate memory for pad buffer.\n");		return -ENOMEM;	}	memset(TLanPadBuffer, 0, TLAN_MIN_FRAME_SIZE);	pad_allocated = 1;	TLAN_DBG(TLAN_DEBUG_PROBE, "Starting PCI Probe....\n");		/* Use new style PCI probing. Now the kernel will	   do most of this for us */	pci_register_driver(&tlan_driver);	TLAN_DBG(TLAN_DEBUG_PROBE, "Starting EISA Probe....\n");	TLan_EisaProbe();			printk(KERN_INFO "TLAN: %d device%s installed, PCI: %d  EISA: %d\n", 		 TLanDevicesInstalled, TLanDevicesInstalled == 1 ? "" : "s",		 tlan_have_pci, tlan_have_eisa);	if (TLanDevicesInstalled == 0) {		pci_unregister_driver(&tlan_driver);		pci_free_consistent(NULL, TLAN_MIN_FRAME_SIZE, TLanPadBuffer, TLanPadBufferDMA);		return -ENODEV;	}	return 0;}	static int __devinit tlan_init_one( struct pci_dev *pdev,				    const struct pci_device_id *ent){	return TLan_probe1( pdev, -1, -1, 0, ent);}/*	***************************************************************	 *	tlan_probe1	 *	 *	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;	int		   reg, rc = -ENODEV;	if (pdev) {		rc = pci_enable_device(pdev);		if (rc)			return rc;		rc = pci_request_regions(pdev, TLanSignature);		if (rc) {			printk(KERN_ERR "TLAN: Could not reserve IO regions\n");			goto err_out;		}	}	dev = alloc_etherdev(sizeof(TLanPrivateInfo));	if (dev == NULL) {		printk(KERN_ERR "TLAN: Could not allocate memory for device.\n");		rc = -ENOMEM;		goto err_out_regions;	}	SET_MODULE_OWNER(dev);	SET_NETDEV_DEV(dev, &pdev->dev);		priv = dev->priv;	priv->pciDev = pdev;		/* Is this a PCI device? */	if (pdev) {		u32 		   pci_io_base = 0;		priv->adapter = &board_info[ent->driver_data];		rc = pci_set_dma_mask(pdev, 0xFFFFFFFF);		if (rc) {			printk(KERN_ERR "TLAN: No suitable PCI mapping available.\n");			goto err_out_free_dev;		}		pci_read_config_byte ( pdev, PCI_REVISION_ID, &pci_rev);		for ( reg= 0; reg <= 5; reg ++ ) {			if (pci_resource_flags(pdev, reg) & IORESOURCE_IO) {				pci_io_base = pci_resource_start(pdev, reg);				TLAN_DBG( TLAN_DEBUG_GNRL, "IO mapping is available at %x.\n",						pci_io_base);				break;			}		}		if (!pci_io_base) {			printk(KERN_ERR "TLAN: No IO mappings available\n");			rc = -EIO;			goto err_out_free_dev;		}				dev->base_addr = pci_io_base;		dev->irq = pdev->irq;		priv->adapterRev = pci_rev; 		pci_set_master(pdev);		pci_set_drvdata(pdev, 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 */		}		dev->base_addr = ioaddr;		dev->irq = irq;	}	/* 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 {		priv->aui    = aui[boards_found];		priv->speed  = speed[boards_found];		priv->duplex = duplex[boards_found];		priv->debug = debug;	}		/* This will be used when we get an adapter error from	 * within our irq handler */	INIT_WORK(&priv->tlan_tqueue, (void *)(void*)TLan_tx_timeout, dev);	spin_lock_init(&priv->lock);		rc = TLan_Init(dev);	if (rc) {		printk(KERN_ERR "TLAN: Could not set up device.\n");		goto err_out_free_dev;	}	rc = register_netdev(dev);	if (rc) {		printk(KERN_ERR "TLAN: Could not register device.\n");		goto err_out_uninit;	}		TLanDevicesInstalled++;	boards_found++;		/* 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;err_out_uninit:	pci_free_consistent(priv->pciDev, priv->dmaSize, priv->dmaStorage,			    priv->dmaStorageDMA );err_out_free_dev:	free_netdev(dev);err_out_regions:#ifdef CONFIG_PCI	if (pdev)		pci_release_regions(pdev);#endiferr_out:	if (pdev)		pci_disable_device(pdev);	return rc;}static void TLan_Eisa_Cleanup(void){	struct net_device *dev;	TLanPrivateInfo *priv;		while( tlan_have_eisa ) {		dev = TLan_Eisa_Devices;		priv = dev->priv;		if (priv->dmaStorage) {			pci_free_consistent(priv->pciDev, priv->dmaSize, priv->dmaStorage, priv->dmaStorageDMA );		}		release_region( dev->base_addr, 0x10);		unregister_netdev( dev );		TLan_Eisa_Devices = priv->nextDevice;		free_netdev( dev );		tlan_have_eisa--;	}}			static void __exit tlan_exit(void){	pci_unregister_driver(&tlan_driver);	if (tlan_have_eisa)		TLan_Eisa_Cleanup();	pci_free_consistent(NULL, TLAN_MIN_FRAME_SIZE, TLanPadBuffer, TLanPadBufferDMA);}/* 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 */#ifdef CONFIG_NET_POLL_CONTROLLERstatic void TLan_Poll(struct net_device *dev){	disable_irq(dev->irq);	TLan_HandleInterrupt(dev->irq, dev, NULL);	enable_irq(dev->irq);}#endif		/***************************************************************	 *	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 = dev->priv;		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 = pci_alloc_consistent(priv->pciDev, dma_size, &priv->dmaStorageDMA);	priv->dmaSize = dma_size;		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->rxListDMA = ( ( ( (u32) priv->dmaStorageDMA ) + 7 ) & 0xFFFFFFF8 );	priv->txList = priv->rxList + TLAN_NUM_RX_LISTS;	priv->txListDMA = priv->rxListDMA + sizeof(TLanList) * TLAN_NUM_RX_LISTS;	if ( bbuf ) {		priv->rxBuffer = (u8 *) ( priv->txList + TLAN_NUM_TX_LISTS );		priv->rxBufferDMA =priv->txListDMA + sizeof(TLanList) * TLAN_NUM_TX_LISTS;		priv->txBuffer = priv->rxBuffer + ( TLAN_NUM_RX_LISTS * TLAN_MAX_FRAME_SIZE );		priv->txBufferDMA = priv->rxBufferDMA + ( TLAN_NUM_RX_LISTS * TLAN_MAX_FRAME_SIZE );	}

⌨️ 快捷键说明

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