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

📄 3c90x.c

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



/*++

Routine Name:
	
	tc90x_CheckDCConverter
		
Routine Description:


Arguments:

	IN PNIC_INFORMATION Adapter
	IN BOOLEAN EnabledState

Return Value:

    BOOLEAN

--*/

BOOLEAN 
tc90x_CheckDCConverter (
	IN PNIC_INFORMATION Adapter,
	IN BOOLEAN EnabledState
	)
{
	PNIC_INFORMATION pAdapter = Adapter;
	NIC_COMMAND(pAdapter,COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);
	MediaStatus_g = NIC_READ_PORT_USHORT(pAdapter,MEDIA_STATUS_REGISTER);
	NIC_DELAY(1000);

	if( ((EnabledState) && !(MediaStatus_g & MEDIA_STATUS_DC_CONVERTER_ENABLED) ) ||
		((!EnabledState) && (MediaStatus_g & MEDIA_STATUS_DC_CONVERTER_ENABLED)) )
	{	
		DCConverterEnabledState_g = EnabledState;  /* for waittimer */
		pAdapter->WaitCases = CHECK_DC_CONVERTER;
		TimeOutCount = jiffies + 3; // 30ms
		if(!InWaitTimer)
		{	WaitTimer.expires = RUN_AT(HZ/100);
			add_timer(&WaitTimer);
			InWaitTimer = TRUE;
		}
		while(TimeOutCount > jiffies) ;
		if( (EnabledState && !(MediaStatus_g & MEDIA_STATUS_DC_CONVERTER_ENABLED)) || 
		    (!EnabledState && (MediaStatus_g & MEDIA_STATUS_DC_CONVERTER_ENABLED))
		  )
		{	pAdapter->Hardware.Status = HARDWARE_STATUS_FAILURE;
			DBGPRINT_ERROR(("ConfigureDCConverter: Timeout setting DC Converter \n"));
			return FALSE;
		}
	}
	return TRUE;
}


/*++

Routine Name:
	
	tc90x_SetupConnector
		
Routine Description:

	Setup new transceiver type in InternalConfig. Determine whether to 
	set JabberGuardEnable, enableSQEStats and linkBeatEnable in MediaStatus.
	Determine if the coax transceiver also needs to be enabled/disabled.

Arguments:

	IN PNIC_INFORMATION Adapter
 	IN CONNECTOR_TYPE NewConnector
  	OUT PCONNECTOR_TYPE OldConnector 

Return Value:

	VOID

--*/

VOID
tc90x_SetupConnector(    
	IN PNIC_INFORMATION Adapter,
 	IN CONNECTOR_TYPE NewConnector,
  	OUT PCONNECTOR_TYPE OldConnector 
  	) 
{
	PNIC_INFORMATION pAdapter = Adapter;
    ULONG InternalConfig = 0;
    ULONG OldInternalConfig = 0;
    USHORT MediaStatus = 0;
	
	NIC_COMMAND(
		pAdapter, 
        COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_3);

	InternalConfig = NIC_READ_PORT_ULONG(
				pAdapter, 
				INTERNAL_CONFIG_REGISTER);
	OldInternalConfig = InternalConfig;
	//
	// Save old choice
	//
	*OldConnector = 
		(InternalConfig & INTERNAL_CONFIG_TRANSCEIVER_MASK) >> 20;
	//
	// Program the MII registers if forcing the configuration to 10/100BaseT.
	//
	if ((NewConnector == CONNECTOR_10BASET) ||
		(NewConnector == CONNECTOR_100BASETX)){
	   	//
		// Clear transceiver type and change to new transceiver type.
		//
   		InternalConfig &= ~(INTERNAL_CONFIG_TRANSCEIVER_MASK);
   		InternalConfig |= (CONNECTOR_AUTONEGOTIATION << 20);
		//
		// Update the internal config register. Only do this if the value has
		//changed to avoid dropping link.
		//
		if (OldInternalConfig != InternalConfig) {
			NIC_WRITE_PORT_ULONG(
				pAdapter, 
				INTERNAL_CONFIG_REGISTER, 
				InternalConfig);
		}
		//
		// Force the MII registers to the correct settings.
		//
		if ( !CheckMIIConfiguration(
				pAdapter,
				(USHORT)((NewConnector == CONNECTOR_100BASETX) 
							? MEDIA_OPTIONS_100BASETX_AVAILABLE
							: MEDIA_OPTIONS_10BASET_AVAILABLE)) ) {
			//
			// If the forced configuration didn't work, check the results and see why.
			//
			CheckMIIAutoNegotiationStatus(pAdapter);
			return;
		}
	}
	else {
   		//
		// Clear transceiver type and change to new transceiver type
		//
   		InternalConfig = InternalConfig & (~INTERNAL_CONFIG_TRANSCEIVER_MASK);
   		InternalConfig |= (NewConnector << 20);
		//
		// Update the internal config register. Only do this if the value has
		// changed to avoid dropping link.
		//
		if (OldInternalConfig != InternalConfig) {
			NIC_WRITE_PORT_ULONG(
				pAdapter, 
				INTERNAL_CONFIG_REGISTER, 
				InternalConfig);
		}
	}
    //
    // Determine whether to set enableSQEStats and linkBeatEnable 
    // Automatically set JabberGuardEnable in MediaStatus register.	
	//
	NIC_COMMAND(
			pAdapter, 
			COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);

	MediaStatus = NIC_READ_PORT_USHORT(
					pAdapter, 
					MEDIA_STATUS_REGISTER);

	MediaStatus &= ~(
		MEDIA_STATUS_SQE_STATISTICS_ENABLE |
		MEDIA_STATUS_LINK_BEAT_ENABLE |
		MEDIA_STATUS_JABBER_GUARD_ENABLE);

	MediaStatus |= MEDIA_STATUS_JABBER_GUARD_ENABLE;

    if (NewConnector == CONNECTOR_10AUI)
		MediaStatus |= MEDIA_STATUS_SQE_STATISTICS_ENABLE;

   	if (NewConnector == CONNECTOR_AUTONEGOTIATION)
		MediaStatus |= MEDIA_STATUS_LINK_BEAT_ENABLE;
	else {
		if ((NewConnector == CONNECTOR_10BASET) ||
			(NewConnector == CONNECTOR_100BASETX) ||
			(NewConnector == CONNECTOR_100BASEFX)) {
			if (!pAdapter->Hardware.LinkBeatDisable)
				MediaStatus |= MEDIA_STATUS_LINK_BEAT_ENABLE;
    	}
	}
	NIC_WRITE_PORT_USHORT(pAdapter,	MEDIA_STATUS_REGISTER, MediaStatus);

   	DBGPRINT_INITIALIZE((
		"tc90x_SetupConnector: MediaStatus = %x \n",MediaStatus));
	//
	// If configured for coax we must start the internal transceiver. 
	// If not, we stop it (in case the configuration changed across a
	// warm boot).  
	//
    if (NewConnector == CONNECTOR_10BASE2) {
		NIC_COMMAND(pAdapter, COMMAND_ENABLE_DC_CONVERTER);
		//
		// Check if DC convertor has been enabled
		//
		tc90x_CheckDCConverter(pAdapter, TRUE);
	}
	else {
		NIC_COMMAND(pAdapter, COMMAND_DISABLE_DC_CONVERTER);
		//
		// Check if DC convertor has been disabled
		//
		tc90x_CheckDCConverter(pAdapter, FALSE);
	}
}


/*++

Routine Name: 

	tc90x_TryMII

Routine Description:

    Used to detect if 10Base-T, 100Base-TX, or external MII is available. 

Arguments:

    IN pAdapter pAdapter - Pointer to the adapter structure
    IN CONNECTOR_TYPE newconnector

Return Value:
	BOOLEAN

--*/

BOOLEAN
tc90x_TryMII(    
	IN PNIC_INFORMATION Adapter,
  	IN USHORT MediaOptions 
  	) 
{
    PNIC_INFORMATION pAdapter = Adapter;
    BOOLEAN Handles100Mbit = FALSE;
    //CONNECTOR_TYPE NotUsed;
    //USHORT PhyControl;
    //BOOLEAN PhyResponding;
    //USHORT PhyStatus;
        
    DBGPRINT_FUNCTION(("tc90x_TryMII: IN \n"));
    //
    // First see if there's anything connected to the MII
    //
    if (!FindMIIPhy(pAdapter)) {
		DBGPRINT_ERROR(("tc90x_TryMII: FindMIIPhy failed \n"));
		pAdapter->Hardware.Status = HARDWARE_STATUS_FAILURE;
		return FALSE;
    }
    //
    // Nowhere is it written that the register must be latched, and since
    // reset is the last bit out, the contents might not be valid.  read
    // it one more time.
    //
    /*PhyResponding_g = ReadMIIPhy(pAdapter, MII_PHY_CONTROL, &PhyControl);
    if (!PhyResponding_g) {
		
	DBGPRINT_ERROR(("tc90x_TryMII: Phy not responding (1) \n"));
	pAdapter->Hardware.Status = HARDWARE_STATUS_FAILURE;
	return FALSE;
    }*/
    //
    // Now we can read the status and try to figure out what's out there.
    //
    PhyResponding_g = ReadMIIPhy(pAdapter, MII_PHY_STATUS, &PhyStatus_g);
    if (!PhyResponding_g) {
	DBGPRINT_ERROR(("tc90x_TryMII: Phy not responding (2) \n"));
	pAdapter->Hardware.Status = HARDWARE_STATUS_FAILURE;
	return FALSE;
    }
    
    if ((PhyStatus_g & MII_STATUS_AUTO) && 
	    (PhyStatus_g & MII_STATUS_EXTENDED)) {
    	//
    	//  If it is capable of auto negotiation, see if it has
	// been done already.
    	//
	DBGPRINT_INITIALIZE(("MII Capable of Autonegotiation\n")); 
	//
	// Check the current MII auto-negotiation state and see if we need to
	// start auto-neg over.
	//
	if (!CheckMIIConfiguration(pAdapter, MediaOptions))
		return FALSE;
	//
	// See if link is up...
	//
    PhyResponding_g = ReadMIIPhy(pAdapter, MII_PHY_STATUS, &PhyStatus_g);
    if (!PhyResponding_g) {
	DBGPRINT_ERROR(("tc90x_TryMII: Phy not responding (3) \n"));
	pAdapter->Hardware.Status = HARDWARE_STATUS_FAILURE;
	return FALSE;
    }
	if (PhyStatus_g & MII_STATUS_LINK_UP) {
		if (!GetLinkSpeed(pAdapter, &Handles100Mbit)) {
				DBGPRINT_ERROR(("TryMII: Unknown link speed \n"));
				pAdapter->Hardware.Status = HARDWARE_STATUS_FAILURE;
				return FALSE;
		}
		if (Handles100Mbit) { 
			DBGPRINT_INITIALIZE(("TryMII: Link speed set to 100\n"));
		    	pAdapter->Hardware.LinkSpeed = LINK_SPEED_100;
		} 
		else {
			DBGPRINT_INITIALIZE(("TryMII: Link speed set to 10\n"));
		    	pAdapter->Hardware.LinkSpeed = LINK_SPEED_10;
		}			
		return TRUE;
   	
	} else {
		//
		// Assume 10Mbit if no link
		//
		if (PhyStatus_g & MII_STATUS_100MB_MASK) {
			DBGPRINT_INITIALIZE((
			"TryMII: Link speed defaulted to 100 \n"));
			pAdapter->Hardware.LinkSpeed = LINK_SPEED_100;		
		}
		else {
			DBGPRINT_INITIALIZE((
			"TryMII: Link speed defaulted to 10 \n"));
			pAdapter->Hardware.LinkSpeed = LINK_SPEED_10;			
		}
		return TRUE;
    } 
	
	}
    return FALSE;
}


/*++

Routine Name:
	
	tc90x_TryLinkBeat

Routine Description:

	Download a self-directed packet. If successful, 100BASE-FX is available.

Arguments:

	IN PNIC_INFORMATION Adapter
	IN CONNECTOR_TYPE NewConnector

Return Value:

	BOOLEAN

--*/

BOOLEAN
tc90x_TryLinkBeat(   
	IN PNIC_INFORMATION Adapter,
	IN CONNECTOR_TYPE NewConnector
	) 
{
	PNIC_INFORMATION pAdapter = Adapter;
	USHORT MediaStatus = 0;
	BOOLEAN retval = FALSE;
  	CONNECTOR_TYPE NotUsed;

   	DBGPRINT_FUNCTION(("tc90x_TryLinkBeat: IN \n"));
	//
    	// Go quiet for 1.5 seconds to get any N-Way hub into a receptive 
	// state to sense the new link speed.  We go quiet by switching over
	// to 10BT and disabling Linkbeat.
	//
	pAdapter->Hardware.LinkBeatDisable = TRUE;
    	tc90x_SetupConnector(pAdapter, CONNECTOR_10BASET, &NotUsed);
	//
	// Delay 1.5 seconds
	//
	TimeOutCount = jiffies + 15*HZ/10;
	while(TimeOutCount > jiffies) ;

    	NIC_COMMAND_WAIT(pAdapter, COMMAND_TX_RESET | TX_RESET_MASK_NETWORK_RESET);
    	NIC_COMMAND_WAIT(pAdapter, COMMAND_RX_RESET | RX_RESET_MASK_NETWORK_RESET);
    	//
    	// Set up for TP transceiver
    	//
    	tc90x_SetupConnector(pAdapter, NewConnector, &NotUsed);

	// delay 5 milliseconds
	TimeOutCount = jiffies + 1; //make it 10ms
	while(TimeOutCount > jiffies) ;
	//
    	// We need to send a test packet to clear the
    	// the Partition if for some reason it's partitioned
    	// (i.e., we were testing 100mb before.)
    	// Download a 20 byte packet into the TxFIFO, from us, to us
   	//
    	if (!DownloadSelfDirected(pAdapter)) {
		return FALSE;
	}
	//
	// Acknowledge the down complete
	//
	NIC_COMMAND(
		pAdapter, 
		COMMAND_ACKNOWLEDGE_INTERRUPT + INTSTATUS_DOWN_COMPLETE);
 	//
    	// Check MediaStatus for linkbeat indication
    	//
	NIC_COMMAND(
		pAdapter, 
		COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);

	MediaStatus = NIC_READ_PORT_USHORT(pAdapter, MEDIA_STATUS_REGISTER);

    	if (MediaStatus & MEDIA_STATUS_LINK_DETECT) {		
		retval = TRUE;
	}

	NIC_COMMAND_WAIT(pAdapter, COMMAND_TX_RESET | TX_RESET_MASK_NETWORK_RESET);
    	NIC_COMMAND_WAIT(pAdapter, COMMAND_RX_RESET | RX_RESET_MASK_NETWORK_RESET);

	DBGPRINT_INITIALIZE(("tc90x_TryLinkBeat: OUT with success\n"));
    	return retval;
}

/*++
Routine Name:

	DownloadSelfDirected

Routine Description:

    Download a 20 byte packet into the TxFIFO, from us, to us.

Arguments:

	IN PNIC_INFORMATION Adapter

Return Value:

	BOOLEAN

--*/

BOOLEAN
DownloadSelfDirected(  
	IN PNIC_INFORMATION Adapter
	) 
{
	PNIC_INFORMATION pAdapter = Adapter;
	PDPD_LIST_ENTRY dpdVirtual;
	ULONG PacketBufPhysAddr;
    UCHAR *PacketBuffer;
    PUCHAR pbuffer;
	//
	// Set allocated buffer for transmit
	//
	PacketBuffer = (PUCHAR)pAdapter->TestBufferVirtual[0];
	PacketBufPhysAddr = pAdapter->TestBufferPhysical[0];
	//
    // Fill data in the buffer
	//
	pbuffer = pAdapter->StationAddress;
	memcpy(PacketBuffer, pbuffer, 6);	// destination is me 
	memcpy(PacketBuffer + 6, pbuffer, 6);	// source is me 
	*(ULONG *)(PacketBuffer + 12) = 0;		 
	*(ULONG *)(PacketBuffer + 16) = 0;		 
	//
	// Create a single DPD  
	//
	dpdVirtual = (PDPD_LIST_ENTRY)pAdapter->TestDPDVirtual[0];

	dpdVirtual->DownNextPointer = 0;
	dpdVirtual->FrameStartHeader = 20 | FSH_ROUND_UP_DEFEAT;
	dpdVirtual->SGList[0].Address = PacketBufPhysAddr;
	dpdVirtual->SGList[0].Count = 20 | 0x80000000;
	//
	// Download DPD
	//
	NIC_COMMAND_WAIT(pAdapter, COMMAND_DOWN_STALL);
	
	NIC_WRITE_PORT_ULONG(
		pAdapter, 
		DOWN_LIST_POINTER_REGISTER, 
		dpdVirtual->DPDPhysicalAddress);

	NIC_COMMAND(pAdapter, COMMAND_DOWN_UNSTALL);
	//
	// Check if the DPD is done with
    //
	DownListPointer_g = NIC_READ_PORT_ULONG(pAdapter,DOWN_LIST_POINTER_REGISTER);

	NIC_DELAY(100);

	if(DownListPointer_g == dpdVirtual->DPDPhysicalAddress)
	{	
		pAdapter->WaitCases = CHECK_DOWNLOAD_SELFDIRECTED;
		TimeOutCount = jiffies + 3*HZ;  //max = 3s
		//WaitTimer.expires = RUN_AT(HZ/100);
		//add_timer(&WaitTimer);
		//InWaitTimer = TRUE;
		while(TimeOutCount > jiffies) ;
		if(DownListPointer_g != dpdVirtual->DPDPhysicalAddress)
		{	pAdapter->Hardware.Status = HARDWARE_STATUS_FAILURE;
			DBGPRINT_ERROR(("DownloadSelfDirected: DPD not finished\n"));
			return FALSE;
		}
	}
	return TRUE;
}

BOOLEAN
CheckTransmitInProgress(
	IN PNIC_INFORMATION Adapter

⌨️ 快捷键说明

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