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

📄 tlan.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
	priv->speed =      ( ( dev->mem_start & 0x30 ) == 0x30 ) ? 0 : ( dev->mem_start & 0x30 ) >> 4;	if ( priv->speed == 0x1 ) {		priv->speed = TLAN_SPEED_10;	} else if ( priv->speed == 0x2 ) {		priv->speed = TLAN_SPEED_100;	}	priv->sa_int =     dev->mem_start & 0x02;	priv->debug =      dev->mem_end;	printk("TLAN %d.%d:  %s irq=%2d io=%04x, %s, Rev. %d\n",		TLanVersionMajor,		TLanVersionMinor,		dev->name, 		(int) irq, 		io_base,		priv->adapter->deviceLabel,		priv->adapterRev );	TLan_Init( dev );			   	return 0;} /* tlan_probe */#endif /* MODULE */	/***************************************************************	 *	TLan_PciProbe	 *	 *	Returns:	 *		1 if another TLAN card was found, 0 if not.	 *	Parms:	 *		pci_dfn		The PCI whatever the card was	 *				found at.	 *		pci_irq		The IRQ of the found adapter.	 *		pci_rev		The revision of the adapter.	 *		pci_io_base	The first IO port used by the	 *				adapter.	 *		dl_ix		The index in the device list	 *				of the adapter.	 *	 *	This function searches for an adapter with PCI vendor	 *	and device IDs matching those in the TLanAdapterList.	 *	The function 'remembers' the last device it found,	 *	and so finds a new device (if anymore are to be found)	 *	each time the function is called.  It then looks up	 *	pertinent PCI info and returns it to the caller.	 *	 **************************************************************/int TLan_PciProbe(u8 *pci_dfn, u8 *pci_irq, u8 *pci_rev, u32 *pci_io_base, u32 *dl_ix ){	static int dl_index = 0;	static struct pci_dev * pdev = NULL;	u16	pci_command;	int	reg;	if ( ! pci_present() ) {		printk( "TLAN:   PCI Bios not present.\n" );		return 0;	}	for (; TLanAdapterList[dl_index].vendorId != 0; dl_index++) {		pdev = pci_find_device(			TLanAdapterList[dl_index].vendorId,			TLanAdapterList[dl_index].deviceId, pdev);		if ( pdev ) {			TLAN_DBG(				TLAN_DEBUG_GNRL,				"TLAN:  found: Vendor Id = 0x%hx, Device Id = 0x%hx\n",				TLanAdapterList[dl_index].vendorId,				TLanAdapterList[dl_index].deviceId			);			*pci_irq = pdev->irq;			*pci_io_base = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;			*pci_dfn = pdev->devfn;			pci_read_config_byte ( pdev, PCI_REVISION_ID, pci_rev);			pci_read_config_word ( pdev,  PCI_COMMAND, &pci_command);			for ( reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg +=4 ) {				pci_read_config_dword( pdev, reg, pci_io_base);				if ((pci_command & PCI_COMMAND_IO) && (*pci_io_base & 0x3)) {					*pci_io_base &= PCI_BASE_ADDRESS_IO_MASK;					TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:    IO mapping is available at %x.\n", *pci_io_base);					break;				} else {					*pci_io_base = 0;				}			}			if ( *pci_io_base == 0 )				printk("TLAN:    IO mapping not available, ignoring device.\n");			pci_set_master(pdev);			if ( *pci_io_base ) {				*dl_ix = dl_index;				return 1;			}		} else {			pdev = NULL;		}	}	return 0;} /* TLan_PciProbe */	/***************************************************************	 *	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.	 *		 **************************************************************/int TLan_Init( struct device *dev ){	int		dma_size;	int		err;	int		i;	TLanPrivateInfo	*priv;	priv = (TLanPrivateInfo *) dev->priv;	err = check_region( dev->base_addr, 0x10 );	if ( err ) {		printk( "TLAN:  %s: Io port region 0x%lx size 0x%x in use.\n",			dev->name,			dev->base_addr,			0x10 );		return -EIO;	}	request_region( dev->base_addr, 0x10, TLanSignature );	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( "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( "TLAN:  %s: Error reading MAC from eeprom: %d\n",			dev->name,			err );	}	dev->addr_len = 6;	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;	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.	 *	 **************************************************************/int TLan_Open( struct device *dev ){	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;	int		err;	priv->tlanRev = TLan_DioRead8( dev->base_addr, TLAN_DEF_REVISION );	if ( priv->sa_int ) {		TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:   Using SA_INTERRUPT\n" ); 		err = request_irq( dev->irq, TLan_HandleInterrupt, SA_SHIRQ | SA_INTERRUPT, TLanSignature, dev );	} else {		err = request_irq( dev->irq, TLan_HandleInterrupt, SA_SHIRQ, TLanSignature, dev );	}	if ( err ) {		printk( "TLAN:  Cannot open %s because IRQ %d is already in use.\n", dev->name, dev->irq );		return -EAGAIN;	}		MOD_INC_USE_COUNT;	dev->tbusy = 0;	dev->interrupt = 0;	dev->start = 1;	/* 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, "TLAN:  %s: Opened.  TLAN Chip Rev: %x\n", dev->name, priv->tlanRev );	return 0;} /* TLan_Open */	/***************************************************************	 *	TLan_StartTx	 *  	 *	Returns:	 *		0 on success, non-zero on failure.	 *	Parms:	 *		skb	A pointer to the sk_buff containing the	 *			frame to be sent.	 *		dev	The device to send the data on.	 *	 *	This function adds a frame to the Tx list to be sent	 *	ASAP.  First it	verifies that the adapter is ready and	 *	there is room in the queue.  Then it sets up the next	 *	available list, copies the frame to the	corresponding	 *	buffer.  If the adapter Tx channel is idle, it gives	 *	the adapter a Tx Go command on the list, otherwise it	 *	sets the forward address of the previous list to point	 *	to this one.  Then it frees the sk_buff.	 *	 **************************************************************/int TLan_StartTx( struct sk_buff *skb, struct device *dev ){	TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;	TLanList	*tail_list;	u8		*tail_buffer;	int		pad;	if ( ! priv->phyOnline ) {		TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT:  %s PHY is not ready\n", dev->name );		dev_kfree_skb( skb );		return 0;	}	tail_list = priv->txList + priv->txTail;	if ( tail_list->cStat != TLAN_CSTAT_UNUSED ) {		TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT:  %s is busy (Head=%d Tail=%d)\n", dev->name, priv->txHead, priv->txTail );		dev->tbusy = 1;		priv->txBusyCount++;		return 1;	}	tail_list->forward = 0;	if ( bbuf ) {		tail_buffer = priv->txBuffer + ( priv->txTail * TLAN_MAX_FRAME_SIZE );		memcpy( tail_buffer, skb->data, skb->len );	} else {		tail_list->buffer[0].address = virt_to_bus( skb->data );		tail_list->buffer[9].address = (u32) skb;	}	pad = TLAN_MIN_FRAME_SIZE - skb->len;	if ( pad > 0 ) {		tail_list->frameSize = (u16) skb->len + pad;		tail_list->buffer[0].count = (u32) skb->len;		tail_list->buffer[1].count = TLAN_LAST_BUFFER | (u32) pad;		tail_list->buffer[1].address = virt_to_bus( TLanPadBuffer );	} else {		tail_list->frameSize = (u16) skb->len;		tail_list->buffer[0].count = TLAN_LAST_BUFFER | (u32) skb->len;		tail_list->buffer[1].count = 0;		tail_list->buffer[1].address = 0;	}	cli();	tail_list->cStat = TLAN_CSTAT_READY;	if ( ! priv->txInProgress ) {		priv->txInProgress = 1;		outw( 0x4, dev->base_addr + TLAN_HOST_INT );		TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT:  Starting TX on buffer %d\n", priv->txTail );		outl( virt_to_bus( tail_list ), dev->base_addr + TLAN_CH_PARM );		outl( TLAN_HC_GO | TLAN_HC_ACK, dev->base_addr + TLAN_HOST_CMD );	} else {		TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT:  Adding buffer %d to TX channel\n", priv->txTail );		if ( priv->txTail == 0 ) {			( priv->txList + ( TLAN_NUM_TX_LISTS - 1 ) )->forward = virt_to_bus( tail_list );		} else {			( priv->txList + ( priv->txTail - 1 ) )->forward = virt_to_bus( tail_list );		}	}	sti();	CIRC_INC( priv->txTail, TLAN_NUM_TX_LISTS );	if ( bbuf ) {		dev_kfree_skb( skb );	}			dev->trans_start = jiffies;	return 0;} /* TLan_StartTx */	/***************************************************************	 *	TLan_HandleInterrupt	 *  	 *	Returns:		 *		Nothing	 *	Parms:	 *		irq	The line on which the interrupt	 *			occurred.	 *		dev_id	A pointer to the device assigned to	 *			this irq line.	 *		regs	???	 *	 *	This function handles an interrupt generated by its	 *	assigned TLAN adapter.  The function deactivates	 *	interrupts on its adapter, records the type of	 *	interrupt, executes the appropriate subhandler, and	 *	acknowdges the interrupt to the adapter (thus	 *	re-enabling adapter interrupts.	 *	 **************************************************************/void TLan_HandleInterrupt(int irq, void *dev_id, struct pt_regs *regs){	u32		ack;	struct device	*dev;	u32		host_cmd;	u16		host_int;	int		type;	dev = (struct device *) dev_id;	cli();	if ( dev->interrupt ) {		printk( "TLAN:   Re-entering interrupt handler for %s: %ld.\n" , dev->name, dev->interrupt );	}	dev->interrupt++;	host_int = inw( dev->base_addr + TLAN_HOST_INT );	outw( host_int, dev->base_addr + TLAN_HOST_INT );	type = ( host_int & TLAN_HI_IT_MASK ) >> 2;	ack = TLanIntVector[type]( dev, host_int );	if ( ack ) {		host_cmd = TLAN_HC_ACK | ack | ( type << 18 );		outl( host_cmd, dev->base_addr + TLAN_HOST_CMD );	}	dev->interrupt--;	sti();} /* TLan_HandleInterrupts */	/***************************************************************	 *	TLan_Close	 *  	 * 	Returns:	 *		An error code.	 *	Parms:	 *		dev	The device structure of the device to	 *			close.	 *	 *	This function shuts down the adapter.  It records any	 *	stats, puts the adapter into reset state, deactivates	 *	its time as needed, and	frees the irq it is using.	 *	 **************************************************************/int TLan_Close(struct device *dev){	TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;	dev->start = 0;	dev->tbusy = 1;	TLan_ReadAndClearStats( dev, TLAN_RECORD );	outl( TLAN_HC_AD_RST, dev->base_addr + TLAN_HOST_CMD );	if ( priv->timer.function != NULL )		del_timer( &priv->timer );	free_irq( dev->irq, dev );	TLan_FreeLists( dev );	TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:  Device %s closed.\n", dev->name );	MOD_DEC_USE_COUNT;	return 0;} /* TLan_Close */	/***************************************************************	 *	TLan_GetStats	 *  	 *	Returns:	 *		A pointer to the device's statistics structure.	 *	Parms:	 *		dev	The device structure to return the	 *			stats for.	 *	 *	This function updates the devices statistics by reading	 *	the TLAN chip's onboard registers.  Then it returns the

⌨️ 快捷键说明

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