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

📄 smsc9118.c

📁 SMSC9118网卡驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
/*****************************************************************************
   
	Copyright (c) 2004-2006 SMSC. All rights reserved.

	Use of this source code is subject to the terms of the SMSC Software
	License Agreement (SLA) under which you licensed this software product.	 
	If you did not accept the terms of the SLA, you are not authorized to use
	this source code. 

	This code and information is provided as is without warranty of any kind,
	either expressed or implied, including but not limited to the implied
	warranties of merchantability and/or fitness for a particular purpose.
	 
	File name   : smsc9118.c 
	Description : smsc9118 driver 

	History	    :
		03-16-05 WH			First Release
		08-12-05 MDG		ver 1.01 
			- add LED1 inversion, add PHY work around
		11-07-05 WH			ver 1.02
			- Fixed middle buffer handling bug
			  (Driver didn't handle middle buffers correctly if it is less than 
               4bytes size)
			- workaround for Multicast bug
			- Workaround for MAC RXEN bug
		11-17-05 WH			ver 1.03
			- 1.02 didn't have 1.01 patches
			- 1.03 is 1.02 + 1.01
		12-06-05 WH			ver 1.04
			- Fixed RX doesn't work on Silicon A1 (REV_ID = 0x011x0002)
			- Support SMSC9118x/117x/116x/115x family
		02-27-06 WH			ver 1.05
			- Fixing External Phy bug that doesn't work with 117x/115x
		03-23-06 WH			ver 1.06
			- Put the variable to avoid PHY_WORKAROUND for External PHY
			- Change product name to 9118x->9218, 9115x->9215
		07-26-06 WH, MDG, NL		ver 1.07
			- Add RXE and TXE interrupt handlers
			- Workaround Code for direct GPIO connection from 9118 family 
			  Interrupt (Level Interrupt -> Edge Interrupt)
			- Change GPT interrupt interval to 200mSec from 50mSec
			- clean up un-used SH3 code
		08-25-06  WH, MDG, NL       ver 1.08
		    - Fixed RXE and TXE interrupt handlers bug
			- support for direct and nondirect Interrupt
*****************************************************************************/

#pragma warning(disable:4127 4201 4214 4115 4100 4514 4152)
#include "smsc9118.h"

static const char date_code[] = BUILD_NUMBER;

static void DumpSIMRegs(const SMSC9118_ADAPTER * const pAdapter);
static void DumpMACRegs(const SMSC9118_ADAPTER * const pAdapter);
static void DumpPHYRegs(const SMSC9118_ADAPTER * const pAdapter);
static void DumpAllRegs(const SMSC9118_ADAPTER * const pAdapter);

static DRIVER_BLOCK gSmsc9118MiniportBlock = { (NDIS_HANDLE)0, NULL };	/*lint !e956 */

#ifdef DEBUG
DBGPARAM dpCurSettings = {
	TEXT("SMSC9118"), {
	TEXT("Errors"),TEXT("Warnings"),TEXT("Functions"),TEXT("Init"),
	TEXT("Interrupts"),TEXT("Receives"),TEXT("Transmits"),TEXT("Link"),
	TEXT("Undefined"),TEXT("Undefined"),TEXT("Undefined"),TEXT("Undefined"),
	TEXT("Undefined"),TEXT("Undefined"),TEXT("Undefined"),TEXT("Undefined") },
	0
};
#endif

#define OID_NDIS_SMSC_DUMP_ALL_REGS 	0xFFFFFF01U

static const UINT Smsc9118SupportedOids[] = {
	(UINT)OID_GEN_SUPPORTED_LIST,
	(UINT)OID_GEN_HARDWARE_STATUS,
	(UINT)OID_GEN_MEDIA_SUPPORTED,
	(UINT)OID_GEN_MEDIA_IN_USE,
	(UINT)OID_GEN_MAXIMUM_LOOKAHEAD,
	(UINT)OID_GEN_MAXIMUM_FRAME_SIZE,
	(UINT)OID_GEN_MAXIMUM_TOTAL_SIZE,
	(UINT)OID_GEN_MAC_OPTIONS,
	(UINT)OID_GEN_PROTOCOL_OPTIONS,
	(UINT)OID_GEN_LINK_SPEED,
	(UINT)OID_GEN_TRANSMIT_BUFFER_SPACE,
	(UINT)OID_GEN_RECEIVE_BUFFER_SPACE,
	(UINT)OID_GEN_TRANSMIT_BLOCK_SIZE,
	(UINT)OID_GEN_RECEIVE_BLOCK_SIZE,
	(UINT)OID_GEN_VENDOR_DESCRIPTION,
	(UINT)OID_GEN_VENDOR_ID,
	(UINT)OID_GEN_DRIVER_VERSION,
	(UINT)OID_GEN_CURRENT_PACKET_FILTER,
	(UINT)OID_GEN_CURRENT_LOOKAHEAD,
	(UINT)OID_GEN_XMIT_OK,
	(UINT)OID_GEN_RCV_OK,
	(UINT)OID_GEN_XMIT_ERROR,
	(UINT)OID_GEN_RCV_ERROR,
	(UINT)OID_GEN_RCV_NO_BUFFER,
	(UINT)OID_802_3_PERMANENT_ADDRESS,
	(UINT)OID_802_3_CURRENT_ADDRESS,
	(UINT)OID_802_3_MULTICAST_LIST,
	(UINT)OID_802_3_MAXIMUM_LIST_SIZE,
	(UINT)OID_GEN_MEDIA_CONNECT_STATUS,
	(UINT)OID_GEN_MAXIMUM_SEND_PACKETS,
	(UINT)OID_GEN_VENDOR_DRIVER_VERSION,
	(UINT)OID_802_3_RCV_ERROR_ALIGNMENT,
	(UINT)OID_802_3_XMIT_ONE_COLLISION,
	(UINT)OID_802_3_XMIT_MORE_COLLISIONS,
	//	Power Management
	(UINT)OID_PNP_CAPABILITIES,
	(UINT)OID_PNP_SET_POWER,
	(UINT)OID_PNP_QUERY_POWER,
	(UINT)OID_PNP_ADD_WAKE_UP_PATTERN,
	(UINT)OID_PNP_REMOVE_WAKE_UP_PATTERN,
	(UINT)OID_PNP_ENABLE_WAKE_UP,
	// SMSC Proprietary
	OID_NDIS_SMSC_DUMP_ALL_REGS,
};

#ifdef	TRACE_BUFFER
volatile DWORD	dwTxReported = 0UL, dwTxSent = 0UL, dwTxPend = 0UL;
volatile DWORD	dwRxPktToFull = 0UL, dwRxPktToEmpty = 0UL;
volatile DWORD	dwRxPktFromFull = 0UL, dwRxPktFromEmpty = 0UL;
volatile DWORD	dwRxTotalPkt = 0UL, dwRxDiscard = 0UL;
volatile DWORD	dwRxNumIndicate = 0UL;
#endif

/*
   Since Windows CE NDIS miniports are implemented as DLLs, 
   a DLL entrypoint isneeded.
*/
BOOL __stdcall DllEntry (HANDLE hDLL, DWORD dwReason, LPVOID lpReserved)
{
	BOOL	bRet;

	/* Make Lint Happy */
	SMSC_TRACE1(DBG_INIT, "date_code = %a", date_code);

	SMSC_TRACE0(DBG_INIT,"+DllEntry\r\n");
	switch (dwReason)
	{
		case DLL_PROCESS_ATTACH:
#ifdef	DEBUG
			DEBUGREGISTER (hDLL);
#endif
			SMSC_TRACE0(DBG_INIT,"DLL_PROCESS_ATTACH\r\n");
			bRet = DisableThreadLibraryCalls((HMODULE) hDLL);
			if (bRet != TRUE) {
				SMSC_TRACE0(DBG_INIT,"Failed to DisableThreadLibraryCalls()\r\n");
			}
			break;
		case DLL_PROCESS_DETACH:
			SMSC_TRACE0(DBG_INIT,"DLL_PROCESS_DETACH\r\n");
			break;
		default:
			break;
	}

	dwReason = dwReason;
	lpReserved = lpReserved;
	SMSC_TRACE0(DBG_INIT,"-DllEntry\r\n");
	return (TRUE);
}

/*----------------------------------------------------------------------------
	DriverEntry
		NDIS miniport function
*/
NDIS_STATUS DriverEntry (IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
	NDIS_MINIPORT_CHARACTERISTICS Characteristics;
	NDIS_STATUS Status;
	
	SMSC_TRACE0(DBG_INIT,"+DriverEntry\r\n");

	RETAILMSG(1, (TEXT("DRIVER_VERSION : %X, "), DRIVER_VERSION));
	RETAILMSG(1, (TEXT("DATECODE : %s\r\n"), TEXT(BUILD_NUMBER)));

	PlatformInitialize();
	PlatformDisplayInfo();

	NdisMInitializeWrapper(&gSmsc9118MiniportBlock.NdisWrapperHandle, DriverObject, RegistryPath, NULL);

	gSmsc9118MiniportBlock.AdapterQueue = (PSMSC9118_ADAPTER)NULL;

	NdisZeroMemory (&Characteristics, sizeof (Characteristics));
	Characteristics.MajorNdisVersion = (UCHAR)SMSC9118_NDIS_MAJOR_VERSION;
	Characteristics.MinorNdisVersion = (UCHAR)SMSC9118_NDIS_MINOR_VERSION;
	Characteristics.CheckForHangHandler = Smsc9118CheckForHang;
	Characteristics.DisableInterruptHandler = NULL;
	Characteristics.EnableInterruptHandler = NULL;
	Characteristics.HaltHandler = Smsc9118Halt;
	Characteristics.HandleInterruptHandler = Smsc9118HandleInterrupt;
	Characteristics.InitializeHandler = Smsc9118Initialize;
	Characteristics.ISRHandler = Smsc9118Isr;
	Characteristics.QueryInformationHandler = Smsc9118QueryInformation;
	Characteristics.ReconfigureHandler = NULL;
	Characteristics.ResetHandler = Smsc9118Reset;
	Characteristics.SendHandler = NULL;
	Characteristics.SetInformationHandler = Smsc9118SetInformation;
	Characteristics.TransferDataHandler = NULL;
	Characteristics.ReturnPacketHandler = Smsc9118GetReturnedPackets;
	Characteristics.SendPacketsHandler = Smsc9118SendPackets;
	Characteristics.AllocateCompleteHandler = NULL;

	Status = NdisMRegisterMiniport (gSmsc9118MiniportBlock.NdisWrapperHandle, 
									&Characteristics, 
									sizeof (Characteristics));

	if (Status == NDIS_STATUS_SUCCESS)
	{
		SMSC_TRACE0(DBG_INIT, "NdisMRegisterMiniport OK.\r\n");
	}
	else 
	{
		// Terminate the wrapper.
		NdisTerminateWrapper (gSmsc9118MiniportBlock.NdisWrapperHandle, NULL);
		gSmsc9118MiniportBlock.NdisWrapperHandle = NULL;
		SMSC_TRACE0(DBG_INIT,"    NdisMRegisterMiniport failed.\r\n");
	}
	
	SMSC_TRACE0(DBG_INIT,"-DriverEntry\r\n");
	return (Status);
}


/*----------------------------------------------------------------------------
	InitializeQueues
		Initialization of data structures used by the driver.

*/
NDIS_STATUS InitializeQueues(IN PSMSC9118_ADAPTER pAdapter)
{
	NDIS_STATUS Status;
	UINT dw;
	PSMSC9118_SHAREDMEM pSharedMem;

	SMSC_TRACE0(DBG_INIT,"+InitializeQueues\r\n");

	//
	// Initialize Tx queues, etc.
	//
	QUEUE_INIT(&(pAdapter->TxRdyToComplete));
	QUEUE_INIT(&(pAdapter->TxWaitToSend));
	QUEUE_INIT(&(pAdapter->TxDeferedPkt));

	//
	// Initialize Rx queues, etc.
	//
	NdisAllocatePacketPool(&Status, 
						   &(pAdapter->hPacketPool),
						   MAX_RXPACKETS_IN_QUEUE,
						   PROTOCOL_RESERVED_LENGTH);

	if (Status != NDIS_STATUS_SUCCESS)
	{
		SMSC_TRACE0(DBG_INIT,"NdisAllocatePacketPool failed.\r\n");
		return (Status);
	}

	for (dw=0U; dw<MAX_RXPACKETS_IN_QUEUE; dw++)
	{
		NdisAllocatePacket(&Status, &(pAdapter->RxPacketArray[dw]), pAdapter->hPacketPool);
		if (Status != NDIS_STATUS_SUCCESS)
		{
			SMSC_TRACE1(DBG_INIT,"NdisAllocatePacket failed. dw=%d\r\n", dw);
			return (Status);
		}
	}

	NdisAllocateBufferPool(&Status,
						   &(pAdapter->hBufferPool),
						   MAX_RXPACKETS_IN_QUEUE);

	if (Status != NDIS_STATUS_SUCCESS)
	{
		SMSC_TRACE0(DBG_INIT,"NdisAllocateBufferPool failed.\r\n");
		return (Status);
	}

	pSharedMem = (PSMSC9118_SHAREDMEM)(pAdapter->pSharedMemVA);
	for (dw=0U; dw<MAX_RXPACKETS_IN_QUEUE; dw++)
	{
		if (pAdapter->fRxDMAMode)
		{
			NdisAllocateBuffer(&Status, 
							   &(pAdapter->RxBufferArray[dw]), 
							   pAdapter->hBufferPool,
							   (PVOID)((PUCHAR)(((DWORD)pSharedMem->RxBuffer[dw]+(RX_END_ALIGNMENT-1UL))&~((DWORD)RX_END_ALIGNMENT-1UL))+2UL),   //DMA - 16-bit aligned
							   MAX_PACKET);
		}
		else
		{
			NdisAllocateBuffer(&Status, 
							   &(pAdapter->RxBufferArray[dw]), 
							   pAdapter->hBufferPool,
							   (PVOID)((PUCHAR)(pSharedMem->RxBuffer[dw])+2),	// PIO with 2-byte offset
//								 (PVOID)(pSharedMem->RxBuffer[dw]), // PIO w/o 2-byte offset
							   MAX_PACKET);
		}
		
		if (Status != NDIS_STATUS_SUCCESS)
		{
			SMSC_TRACE0(DBG_INIT,"NdisAllocateBuffer failed.\r\n");
			return (Status);
		}
	}

	for (dw=0U; dw<MAX_RXPACKETS_IN_QUEUE; dw++) 
	{
		NdisChainBufferAtBack((pAdapter->RxPacketArray[dw]), (pAdapter->RxBufferArray[dw]));
		{
		UINT	ArraySize;
		NDIS_PHYSICAL_ADDRESS_UNIT SegmentArray[MAX_NUM_SEGMENTS];

		NdisMStartBufferPhysicalMapping(pAdapter->hMiniportAdapterHandle,
				pAdapter->RxBufferArray[dw],
				0UL, (BOOLEAN)TRUE, SegmentArray, &ArraySize);
		if (ArraySize != 1U) 
		{
			RETAILMSG(1, (TEXT("Error! ArraySize = %d\r\n"), ArraySize));
		}
		SET_PACKET_RESERVED_PA(pAdapter->RxPacketArray[dw], 
				NdisGetPhysicalAddressLow(SegmentArray[0].PhysicalAddress));
		}
	}

	// Initialize EmptyPktArray
	pAdapter->EmptyPkt.dwRdPtr = pAdapter->EmptyPkt.dwWrPtr = 0UL;
	for (dw=0U; dw<MAX_RXPACKETS_IN_QUEUE; dw++) {
		pAdapter->EmptyPkt.dwPktArray[dw] = pAdapter->RxPacketArray[dw];
	}
	pAdapter->EmptyPkt.dwRdPtr = 0UL;
	pAdapter->EmptyPkt.dwWrPtr = pAdapter->EmptyPkt.dwRdPtr + (DWORD)MAX_RXPACKETS_IN_QUEUE;

	// Initialize FullPktArray
	pAdapter->FullPkt.dwRdPtr = pAdapter->FullPkt.dwWrPtr = 0UL;

	pAdapter->TxDPCNeeded = (BOOLEAN)FALSE;
	pAdapter->RxDPCNeeded = (BOOLEAN)FALSE;
	pAdapter->PhyDPCNeeded = (BOOLEAN)FALSE;
	pAdapter->SWDPCNeeded = (BOOLEAN)FALSE;
	pAdapter->RxOverRun = (BOOLEAN)FALSE;
	
	pAdapter->f100RxEnWorkaroundDone = 1L;

	SMSC_TRACE0(DBG_INIT,"-InitializeQueues\r\n");
	return (NDIS_STATUS_SUCCESS);

}

/*----------------------------------------------------------------------------
	Smsc9118Initialize
		NDIS miniport function
*/
NDIS_STATUS
Smsc9118Initialize (OUT PNDIS_STATUS OpenErrorStatus, 
				   OUT PUINT puiSelectedMediumIndex, 
				   IN  NDIS_MEDIUM * MediumArray, 
				   IN  UINT uiMediumArraySize, 
				   IN  NDIS_HANDLE hMiniportAdapterHandle, 
				   IN  NDIS_HANDLE hConfigurationHandle)
{
	PSMSC9118_ADAPTER pAdapter;
	NDIS_HANDLE hConfigHandle;
	BOOL bResult;
	UINT uiIndex;
	NDIS_STATUS Status;
	NDIS_PHYSICAL_ADDRESS HighestAcceptableMax;
	ULONG oldKmode;

	PNDIS_CONFIGURATION_PARAMETER ReturnedValue;
	NDIS_STRING IOAddressStr = IOADDRESS;
	NDIS_STRING PhyAddressStr = PHYADDRESS;
	NDIS_STRING InterruptStr = INTERRUPT;
	NDIS_STRING RxDMAMode = RXDMAMODE;
	NDIS_STRING TxDMAMode = TXDMAMODE;
	NDIS_STRING LinkMode = LINKMODE;
	NDIS_STRING FlowControl = FLOWCONTROL;

	SMSC_TRACE0(DBG_INIT,"+Smsc9118Initialize\r\n");

	*OpenErrorStatus = NDIS_STATUS_SUCCESS;

	for (uiIndex = 0U; uiIndex < uiMediumArraySize; uiIndex++)
	{
		if (MediumArray[uiIndex] == NdisMedium802_3) {
			break;
		}
	}

	if (uiIndex == uiMediumArraySize)
	{
		SMSC_TRACE0(DBG_INIT,"  No supported media\r\n");
		return (NDIS_STATUS_UNSUPPORTED_MEDIA);
	}

	*puiSelectedMediumIndex = uiIndex;

	// Allocate adapter context memory.
	HighestAcceptableMax.LowPart = 0xFFFFFFFFUL;		// DWORD
	HighestAcceptableMax.HighPart = -1L;				// LONG
	Status = NdisAllocateMemory ((PVOID *)&pAdapter,
								 sizeof (SMSC9118_ADAPTER),
								 NDIS_ALLOC_FLAG, HighestAcceptableMax);

	if (Status != NDIS_STATUS_SUCCESS)
	{
		SMSC_TRACE0(DBG_INIT,"  NdisAllocateMemory (SMSC9118_ADAPTER) failed.\r\n");
		return NDIS_STATUS_RESOURCES;
	}
	SMSC_TRACE1(DBG_INIT,"  pAdapter allocated at 0x%x.\r\n", pAdapter);
	NdisZeroMemory (pAdapter, sizeof (SMSC9118_ADAPTER));

	// Read configuration from registry.
	NdisOpenConfiguration (&Status, &hConfigHandle, hConfigurationHandle);
	if (Status != NDIS_STATUS_SUCCESS)
	{
		NdisFreeMemory(pAdapter, (UINT)sizeof(SMSC9118_ADAPTER), NDIS_ALLOC_FLAG);
		SMSC_TRACE1(DBG_INIT,"  NdisOpenConfiguration failed 0x%x\r\n", Status);
		return NDIS_STATUS_RESOURCES;
	}

⌨️ 快捷键说明

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