📄 smsc9118.c
字号:
/*****************************************************************************
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 + -