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

📄 3c90x.c

📁 3c90x网卡的驱动(Linux环境下的)
💻 C
📖 第 1 页 / 共 5 页
字号:

		Device = 0;
		noAdapterFound++;
	}


	DBGPRINT_FUNCTION((KERN_CRIT "tc90xbc_ScanDevices: OUT\n"));
	
	if (noAdapterFound) {

		DBGPRINT_INITIALIZE(("NoAdapter = %x\n", noAdapterFound));
		return NIC_STATUS_SUCCESS;
	}
	else
		return NIC_STATUS_FAILURE;
}



/*++

Routine Name:

    tc90x_FillDeviceStructure

Routine Description:

    This routine fills the device structure 

Arguments:

	Device - Pointer to the device structure.
	IoBaseAddress - IoBase address for the adapter.
	Irq - Irq of the adapter.
	

Return Value:

	-ENODEV if no adapter found
	noAdapterFound if adapter(s) found

--*/

NIC_STATUS 
tc90x_FillDeviceStructure(
	IN PNIC_INFORMATION Adapter
	)
{

	PNIC_INFORMATION pAdapter = Adapter;
	PDEVICE device = pAdapter->Device;

	DBGPRINT_INIT(("FillDeviceStructure: IN\n"));
	device->base_addr = pAdapter->PCI.IoBaseAddress;
	device->irq = pAdapter->PCI.InterruptVector;
	device->mtu = MTU;
	//
	// Set the routine addresses
	//
	device->open = &NICOpen;
	device->hard_start_xmit  = &NICSendPacket;
	device->stop = &NICClose;
	device->get_stats = &NICGetStatistics;
	device->do_ioctl = &NICIoctl;
#ifdef NEW_MULTICAST
	device->set_multicast_list = &NICSetReceiveMode;
#else
	device->set_multicast_list = &NICSetMulticastList;
#endif
	DBGPRINT_INIT(("FillDeviceStructure: OUT\n"));
	return NIC_STATUS_SUCCESS;
}


/*++

Routine Name:

    NICOpen

Routine Description:

    This routine opens the interface. 

Arguments:

	Device - Pointer to the device structure.

Return Value:

	0 if SUCCESS
	-ENODEV if FAILURE

--*/


INT
NICOpen(
	IN PDEVICE Device
	)

{
	PNIC_INFORMATION pAdapter = (PNIC_INFORMATION)Device->priv;
	
	DBGPRINT_FUNCTION(("New NICOpen: IN\n"));
	//
	// Initialize general wait timer used during driver init
	//
	init_timer(&WaitTimer);
	WaitTimer.data = (ULONG)Device;
	WaitTimer.function = &WaitTimerHandler;
	pAdapter->WaitCases = NONE;
	add_timer(&WaitTimer);
	InWaitTimer = TRUE;
	pAdapter->ResourcesReserved |= WAIT_TIMER_REGISTERED;

#if LINUX_VERSION_CODE >= 0x20200
	pAdapter->SpinLock_int = (spinlock_t) SPIN_LOCK_UNLOCKED;
	pAdapter->SpinLock_send = (spinlock_t) SPIN_LOCK_UNLOCKED;
	pAdapter->SpinLock_misc = (spinlock_t) SPIN_LOCK_UNLOCKED;
	pAdapter->SpinLock_m = (spinlock_t) SPIN_LOCK_UNLOCKED;
#endif
	//
	// Register IOBase and Irq with the OS
	//
	if (tc90x_RegisterAdapter(pAdapter) != NIC_STATUS_SUCCESS) {

		DBGPRINT_ERROR(("NICOpen: RegisterAdapter failed\n"));
		DBGPRINT_FUNCTION(("NICOpen: Out with ERROR\n"));
		tc90x_FreeAdapterResources(pAdapter);
		return -ENODEV;
	}

	if (tc90x_GetAdapterProperties(pAdapter) != NIC_STATUS_SUCCESS) {

		DBGPRINT_ERROR(("NICOpen: GetAdapterProperties failed\n"));
		DBGPRINT_FUNCTION(("NICOpen: Out with ERROR\n"));
		tc90x_FreeAdapterResources(pAdapter);
		return -ENODEV;
	}	

	if (tc90x_BasicInitializeAdapter(pAdapter) != NIC_STATUS_SUCCESS) {

		DBGPRINT_ERROR(("NICOpen: BasicInitializeAdapter failed\n"));
		DBGPRINT_FUNCTION(("NICOpen: Out with error\n"));
		tc90x_FreeAdapterResources(pAdapter);
		return -ENODEV;
	}

	if (tc90x_TestAdapter(pAdapter) != NIC_STATUS_SUCCESS) {

		DBGPRINT_ERROR(("NICOpen: TestAdapter failed\n"));
		DBGPRINT_FUNCTION(("NICOpen: Out with error\n"));
		tc90x_FreeAdapterResources(pAdapter);
		return -ENODEV;
	}

	if (tc90x_SetupMedia(Device) != NIC_STATUS_SUCCESS) {

		DBGPRINT_ERROR(("NICOpen: SetupMedia failed\n"));
		DBGPRINT_FUNCTION(("NICOpen: Out with error\n"));
		tc90x_FreeAdapterResources(pAdapter);
		return -ENODEV;
	}

	if (tc90x_SoftwareWork(pAdapter) != NIC_STATUS_SUCCESS) {

		DBGPRINT_ERROR((
			"NICOpen: EnableSoftwareWork failed\n"));
		DBGPRINT_FUNCTION(("NICOpen: Out with error\n"));	
		tc90x_FreeAdapterResources(pAdapter);
		return -ENODEV;
	}

	if (tc90x_StartAdapter(pAdapter) != NIC_STATUS_SUCCESS) {

		DBGPRINT_ERROR(("NICOpen: StartAdapter failed\n"));
		DBGPRINT_FUNCTION(("NICOpen: Out with error\n"));
		tc90x_FreeAdapterResources(pAdapter);
		return -ENODEV;
	}

	Device->tbusy = 0;
	Device->interrupt = 0;
	Device->start = 1;
	//
	// Initialize the timer.
	//
	pAdapter->Resources.TimerInterval = 100;
	init_timer(&pAdapter->Resources.Timer);
	pAdapter->Resources.Timer.expires = RUN_AT(HZ/10);
	pAdapter->Resources.Timer.data = (ULONG)Device;
	pAdapter->Resources.Timer.function = &NICTimer;
	add_timer(&pAdapter->Resources.Timer);
	//
	// Initialize task queue for hosterr task, just in case
	//
	pAdapter->Resources.hostErr_task.routine = ReStartAdapter;
	pAdapter->Resources.hostErr_task.data = (void *)&pAdapter;
	pAdapter->Resources.hostErr_task.sync = 0;
	//
	// Timer has been registered.
	//
	pAdapter->ResourcesReserved |= NIC_TIMER_REGISTERED;

	MOD_INC_USE_COUNT;

	DBGPRINT_FUNCTION(("NICOpen:  OUT with SUCCESS\n"));
	return	0;

}

/*++

Routine Name:

    NICClose

Routine Description:

    This routine closes the interface. 

Arguments:

	Device - Pointer to the device structure.

Return Value:

	-ENODEV if no adapter found
	noAdapterFound if adapter(s) found

--*/
INT
NICClose(
	IN PDEVICE Device
	)
{

	PNIC_INFORMATION pAdapter = (PNIC_INFORMATION)Device->priv;
	PDEVICE device = pAdapter->Device;

	DBGPRINT_FUNCTION(("NICClose: IN\n"));

#if LINUX_VERSION_CODE >= 0x20200
	spin_lock(&pAdapter->SpinLock_misc);
#endif

	Device->start = 0;
	Device->tbusy = 1;
	//
	// Disable transmit and receive.
	//
	NIC_COMMAND(pAdapter, COMMAND_TX_DISABLE);
	NIC_COMMAND(pAdapter, COMMAND_RX_DISABLE);
	//
	// Wait for the transmit in progress to go off.
	//
	NIC_COMMAND(pAdapter,COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);
	MediaStatus_g = NIC_READ_PORT_USHORT(pAdapter,MEDIA_STATUS_REGISTER);
	NIC_DELAY(10);
	
	if(MediaStatus_g & MEDIA_STATUS_TX_IN_PROGRESS)
	{	pAdapter->WaitCases = CHECK_TRANSMIT_IN_PROGRESS;
		TimeOutCount = jiffies + HZ;  //max = 1s
		if(!InWaitTimer)
		{	WaitTimer.expires = RUN_AT(HZ/100);
			add_timer(&WaitTimer);
			InWaitTimer = TRUE;
		}
		while(TimeOutCount > jiffies) ;
		if(!(MediaStatus_g & MEDIA_STATUS_TX_IN_PROGRESS)) 	 
			DBGPRINT_ERROR(("NICClose: Adapter is not responding\n"));
	}
	// Issue Global reset. 
	//
	NIC_COMMAND_WAIT(pAdapter,
		COMMAND_GLOBAL_RESET |
		GLOBAL_RESET_MASK_TP_AUI_RESET |
		GLOBAL_RESET_MASK_ENDEC_RESET |
		GLOBAL_RESET_MASK_AISM_RESET |
		GLOBAL_RESET_MASK_SMB_RESET |
		GLOBAL_RESET_MASK_VCO_RESET);

	NIC_COMMAND_WAIT(pAdapter, COMMAND_TX_RESET);
	NIC_COMMAND_WAIT(pAdapter, COMMAND_RX_RESET);
    //
	// Mask and acknowledge all interrupts.
	//
	NIC_MASK_ALL_INTERRUPT(pAdapter);
	NIC_ACKNOWLEDGE_ALL_INTERRUPT(pAdapter);	
	tc90x_CleanupSendLogic(Device);
	//
	// Unregister the interrupt handler. 
	//
	if (pAdapter->ResourcesReserved & NIC_INTERRUPT_REGISTERED) {

		DBGPRINT_INITIALIZE(("Releasing interrupt\n"));
		free_irq(device->irq, device);
		pAdapter->ResourcesReserved &= ~NIC_INTERRUPT_REGISTERED;
	}
	//
	// Unregister the timer handler. 
	//
	if (pAdapter->ResourcesReserved & NIC_TIMER_REGISTERED) {
		DBGPRINT_INITIALIZE((KERN_CRIT "Releasing Timer\n"));
		if (del_timer(&pAdapter->Resources.Timer)) {			
			DBGPRINT_INITIALIZE(("Timer already queued\n"));
		}
		pAdapter->ResourcesReserved &= ~NIC_TIMER_REGISTERED;
	}
	if (pAdapter->ResourcesReserved & WAIT_TIMER_REGISTERED) {
		DBGPRINT_INITIALIZE((KERN_CRIT "Releasing WaitTimer\n"));								
		if (del_timer(&WaitTimer))				
			DBGPRINT_INITIALIZE(("WaitTimer already queued\n"));
		pAdapter->ResourcesReserved &= ~WAIT_TIMER_REGISTERED;
	}
	MOD_DEC_USE_COUNT;

#if LINUX_VERSION_CODE >= 0x20200
	spin_unlock(&pAdapter->SpinLock_misc);
#endif

	DBGPRINT_FUNCTION(("NICClose: OUT\n"));
	return 0;
}


/*++

Routine Name:

    cleanup_module

Routine Description:

    This routine releases the resources. 

Arguments:

	None

Return Value:

	None

--*/

#ifdef MODULE

VOID
cleanup_module(
	VOID
	)
{
	PDEVICE nextDevice;
	PNIC_INFORMATION pAdapter;

	DBGPRINT_FUNCTION(("cleanup_module: IN\n"));

	while (RootNICDevice) {

		nextDevice = ((PNIC_INFORMATION)
			      (RootNICDevice->priv))->NextDevice;
		
		unregister_netdev(RootNICDevice);
		pAdapter = (PNIC_INFORMATION)RootNICDevice->priv;
		tc90x_FreeAdapterResources(pAdapter);
		kfree(RootNICDevice);
		kfree(pAdapter);
		RootNICDevice = nextDevice;
	}

	DBGPRINT_FUNCTION(("cleanup_module: OUT\n"));
}
#endif






/*++

Routine Name: 

	MainAutoSelectionRoutine

Routine Description:

	If autoselection is set, determine the connector and link speed
	by trying the various transceiver types.

Arguments:

	IN PNIC_INFORMATION Adapter
	IN USHORT Options

Return Value:

	VOID

--*/

VOID 
tc90x_MainAutoSelectionRoutine(
	IN PNIC_INFORMATION Adapter,
	IN USHORT Options
	)
{
	PNIC_INFORMATION pAdapter = Adapter;
	CONNECTOR_TYPE NotUsed;
	USHORT index;

	DBGPRINT_FUNCTION(("MainAutoSelectionRoutine: IN \n"));

	pAdapter->Hardware.Connector = CONNECTOR_UNKNOWN;   
	//
	// Try 100MB Connectors
	//
	if ((Options & MEDIA_OPTIONS_100BASETX_AVAILABLE) ||
   	    (Options & MEDIA_OPTIONS_10BASET_AVAILABLE) ||
    	    (Options & MEDIA_OPTIONS_MII_AVAILABLE)) {	       	  
    		//
	    	// For 10Base-T and 100Base-TX, select autonegotiation
	    	// instead of autoselect before calling trymii
    		//
	    	if ((Options & MEDIA_OPTIONS_100BASETX_AVAILABLE) ||
    	    	    (Options & MEDIA_OPTIONS_10BASET_AVAILABLE)) {
				pAdapter->Hardware.Connector = 
					CONNECTOR_AUTONEGOTIATION;
    		} 
    		else        	
				pAdapter->Hardware.Connector = CONNECTOR_MII;

		DBGPRINT_INITIALIZE(("Trying MII\n"));
	   
		if (!tc90x_TryMII(pAdapter, Options))	       
			pAdapter->Hardware.Connector = CONNECTOR_UNKNOWN;
	}
	//
	// Transceiver available is 100Base-FX
	//
	if ((Options & MEDIA_OPTIONS_100BASEFX_AVAILABLE) &&
		(pAdapter->Hardware.Connector == CONNECTOR_UNKNOWN)) {		
		DBGPRINT_INITIALIZE(("Trying 100BFX\n"));	   		
		if (tc90x_TryLinkBeat(pAdapter, CONNECTOR_100BASEFX)) {			
			pAdapter->Hardware.Connector = CONNECTOR_100BASEFX;
			pAdapter->Hardware.LinkSpeed = LINK_SPEED_100;
   		}
	}
	//
	// Transceiver available is 10AUI
	//
   	if ((Options & MEDIA_OPTIONS_10AUI_AVAILABLE) &&
		(pAdapter->Hardware.Connector == CONNECTOR_UNKNOWN)) {			
		DBGPRINT_INITIALIZE(("Trying 10AUI\n"));
		tc90x_SetupConnector(pAdapter, CONNECTOR_10AUI, &NotUsed);
		//
		// Try to loopback packet
		//
		for (index = 0; index < 3; index++) {
			if (TestPacket(pAdapter)) {
				pAdapter->Hardware.Connector = CONNECTOR_10AUI;
				pAdapter->Hardware.LinkSpeed = LINK_SPEED_10;
				DBGPRINT_INITIALIZE(("Found AUI\n"));
				break;
			}
		}
		if (index == 3)
			DBGPRINT_INITIALIZE(("Unable to find AUI\n"));
	}
	//
	// Transceiver available is 10Base-2
	//
	if ((Options & MEDIA_OPTIONS_10BASE2_AVAILABLE) &&
		(pAdapter->Hardware.Connector == CONNECTOR_UNKNOWN)) {			
		DBGPRINT_INITIALIZE(("Trying 10BASEB2\n"));
		//
		// Set up the connector
		//
		tc90x_SetupConnector(pAdapter, CONNECTOR_10BASE2, &NotUsed);
		//
		// Try to loopback packet
		//
		for (index = 0; index < 3; index++) {
			if (TestPacket(pAdapter)) {
				pAdapter->Hardware.Connector = CONNECTOR_10BASE2;
				pAdapter->Hardware.LinkSpeed = LINK_SPEED_10;
	
				DBGPRINT_INITIALIZE(("Found 10Base2 \n"));
				break;
			}
		}
		if (index == 3)
			DBGPRINT_INITIALIZE(("Unable to find 10Base2\n"));
		//
		// Disable DC converter
		//
		NIC_COMMAND(pAdapter, COMMAND_DISABLE_DC_CONVERTER);
		//
		// Check if DC convertor has been disabled
		//
		tc90x_CheckDCConverter(pAdapter, FALSE);
	}	
	//
	// Nothing left to try!
	//
	if (pAdapter->Hardware.Connector == CONNECTOR_UNKNOWN) {
		
		pAdapter->Hardware.Connector = pAdapter->Hardware.ConfigConnector;
		pAdapter->Hardware.LinkSpeed = LINK_SPEED_10;
		DBGPRINT_INITIALIZE(("AutoSelection failed. Using default.\n"));
		DBGPRINT_INITIALIZE(("Connector: %x\n",pAdapter->Hardware.Connector));
		pAdapter->Hardware.LinkState = LINK_DOWN_AT_INIT;
	}

	tc90x_SetupConnector(
		pAdapter, 
		pAdapter->Hardware.Connector, 
		&NotUsed);

	DBGPRINT_FUNCTION(("MainAutoSelectionRoutine: OUT \n"));

⌨️ 快捷键说明

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