📄 mp_main.c
字号:
/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
mp_main.c
Abstract:
This module contains NDIS miniport handlers
Revision History:
Who When What
-------- -------- ----------------------------------------------
DChen 11-01-99 created
Notes:
--*/
#include "precomp.h"
#if DBG
#define _FILENUMBER 'NIAM'
#endif
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#endif
//
// Global data for LBFO
//
#if LBFO
LIST_ENTRY g_AdapterList;
NDIS_SPIN_LOCK g_Lock;
#endif
NDIS_STATUS DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
Arguments:
DriverObject - pointer to the driver object
RegistryPath - pointer to the driver registry path
Return Value:
NDIS_STATUS - the value returned by NdisMRegisterMiniport
--*/
{
NDIS_STATUS Status;
NDIS_HANDLE NdisWrapperHandle;
NDIS_MINIPORT_CHARACTERISTICS MPChar;
DBGPRINT(MP_TRACE, ("====> DriverEntry\n"));
//
// Notify the NDIS wrapper about this driver, get a NDIS wrapper handle back
//
NdisMInitializeWrapper(
&NdisWrapperHandle,
DriverObject,
RegistryPath,
NULL);
if (NdisWrapperHandle == NULL)
{
Status = NDIS_STATUS_FAILURE;
DBGPRINT_S(Status, ("<==== DriverEntry failed to InitWrapper, Status=%x\n", Status));
return Status;
}
#if LBFO
//
// Init the global data
//
InitializeListHead(&g_AdapterList);
NdisAllocateSpinLock(&g_Lock);
//
// For regular miniports, there is NO need to have an Unload handler
// For a LBFO miniport, register an Unload handler for global data cleanup
// The unload handler has a more global scope, whereas the scope of the
// MiniportHalt function is restricted to a particular miniport instance.
//
NdisMRegisterUnloadHandler(NdisWrapperHandle, MPUnload);
#endif
//
// Fill in the Miniport characteristics structure with the version numbers
// and the entry points for driver-supplied MiniportXxx
//
NdisZeroMemory(&MPChar, sizeof(MPChar));
MPChar.MajorNdisVersion = MP_NDIS_MAJOR_VERSION;
MPChar.MinorNdisVersion = MP_NDIS_MINOR_VERSION;
MPChar.CheckForHangHandler = MPCheckForHang;
MPChar.DisableInterruptHandler = NULL;
MPChar.EnableInterruptHandler = NULL;
MPChar.HaltHandler = MPHalt;
MPChar.InitializeHandler = MPInitialize;
MPChar.QueryInformationHandler = MPQueryInformation;
MPChar.ResetHandler = MPReset;
MPChar.ReturnPacketHandler = MPReturnPacket;
MPChar.SendPacketsHandler = MpSendPacketsHandler;
MPChar.SetInformationHandler = MPSetInformation;
MPChar.AllocateCompleteHandler = MPAllocateComplete;
MPChar.HandleInterruptHandler = MPHandleInterrupt;
MPChar.ISRHandler = MPIsr;
MPChar.CancelSendPacketsHandler = MPCancelSendPackets;
MPChar.PnPEventNotifyHandler = MPPnPEventNotify;
MPChar.AdapterShutdownHandler = MPShutdown;
DBGPRINT(MP_LOUD, ("Calling NdisMRegisterMiniport...\n"));
Status = NdisMRegisterMiniport(
NdisWrapperHandle,
&MPChar,
sizeof(NDIS_MINIPORT_CHARACTERISTICS));
if (Status != NDIS_STATUS_SUCCESS)
{
NdisTerminateWrapper(NdisWrapperHandle, NULL);
}
DBGPRINT_S(Status, ("<==== DriverEntry, Status=%x\n", Status));
return Status;
}
NDIS_STATUS MPInitialize(
OUT PNDIS_STATUS OpenErrorStatus,
OUT PUINT SelectedMediumIndex,
IN PNDIS_MEDIUM MediumArray,
IN UINT MediumArraySize,
IN NDIS_HANDLE MiniportAdapterHandle,
IN NDIS_HANDLE WrapperConfigurationContext
)
/*++
Routine Description:
MiniportInitialize handler
Arguments:
OpenErrorStatus Not used
SelectedMediumIndex Place-holder for what media we are using
MediumArray Array of ndis media passed down to us to pick from
MediumArraySize Size of the array
MiniportAdapterHandle The handle NDIS uses to refer to us
WrapperConfigurationContext For use by NdisOpenConfiguration
Return Value:
NDIS_STATUS_SUCCESS unless something goes wrong
--*/
{
NDIS_STATUS Status;
PMP_ADAPTER Adapter = NULL;
UINT index;
#if DBG
LARGE_INTEGER TS, TD, TE;
#endif
DBGPRINT(MP_TRACE, ("====> MPInitialize\n"));
#if DBG
NdisGetCurrentSystemTime(&TS);
#endif
do
{
//
// Find the media type we support
//
for (index = 0; index < MediumArraySize; ++index)
{
if (MediumArray[index] == NIC_MEDIA_TYPE)
{
break;
}
}
if (index == MediumArraySize)
{
DBGPRINT(MP_ERROR, ("Expected media (%x) is not in MediumArray.\n", NIC_MEDIA_TYPE));
Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
break;
}
*SelectedMediumIndex = index;
//
// Allocate MP_ADAPTER structure
//
Status = MpAllocAdapterBlock(&Adapter);
if (Status != NDIS_STATUS_SUCCESS)
{
break;
}
Adapter->AdapterHandle = MiniportAdapterHandle;
//
// Read the registry parameters
//
Status = NICReadRegParameters(
Adapter,
WrapperConfigurationContext);
if (Status != NDIS_STATUS_SUCCESS)
{
break;
}
//
// Inform NDIS of the attributes of our adapter.
// This has to be done before calling NdisMRegisterXxx or NdisXxxx function
// that depends on the information supplied to NdisMSetAttributesEx
// e.g. NdisMInitializeScatterGatherDma
// As this is NDIS51 miniport, it should use safe APIs.
//
NdisMSetAttributesEx(
MiniportAdapterHandle,
(NDIS_HANDLE) Adapter,
0,
NDIS_ATTRIBUTE_DESERIALIZE |
NDIS_ATTRIBUTE_BUS_MASTER,
NIC_INTERFACE_TYPE);
//
// Find the physical adapter
//
Status = MpFindAdapter(Adapter, WrapperConfigurationContext);
if (Status != NDIS_STATUS_SUCCESS)
{
break;
}
//
// Map bus-relative IO range to system IO space
//
Status = NdisMRegisterIoPortRange(
(PVOID *)&Adapter->PortOffset,
Adapter->AdapterHandle,
Adapter->IoBaseAddress,
Adapter->IoRange);
if (Status != NDIS_STATUS_SUCCESS)
{
DBGPRINT(MP_ERROR, ("NdisMRegisterioPortRange failed\n"));
NdisWriteErrorLogEntry(
Adapter->AdapterHandle,
NDIS_ERROR_CODE_BAD_IO_BASE_ADDRESS,
0);
break;
}
//
// Read additional info from NIC such as MAC address
//
Status = NICReadAdapterInfo(Adapter);
if (Status != NDIS_STATUS_SUCCESS)
{
break;
}
//
// Allocate all other memory blocks including shared memory
//
Status = NICAllocAdapterMemory(Adapter);
if (Status != NDIS_STATUS_SUCCESS)
{
break;
}
//
// Init send data structures
//
NICInitSend(Adapter);
//
// Init receive data structures
//
Status = NICInitRecv(Adapter);
if (Status != NDIS_STATUS_SUCCESS)
{
break;
}
// Map bus-relative registers to virtual system-space
Status = NdisMMapIoSpace(
(PVOID *) &(Adapter->CSRAddress),
Adapter->AdapterHandle,
Adapter->MemPhysAddress,
NIC_MAP_IOSPACE_LENGTH);
if (Status != NDIS_STATUS_SUCCESS)
{
DBGPRINT(MP_ERROR, ("NdisMMapIoSpace failed\n"));
NdisWriteErrorLogEntry(
Adapter->AdapterHandle,
NDIS_ERROR_CODE_RESOURCE_CONFLICT,
1,
ERRLOG_MAP_IO_SPACE);
break;
}
DBGPRINT(MP_INFO, ("CSRAddress="PTR_FORMAT"\n", Adapter->CSRAddress));
//
// Disable interrupts here which is as soon as possible
//
NICDisableInterrupt(Adapter);
//
// Register the interrupt
//
Status = NdisMRegisterInterrupt(
&Adapter->Interrupt,
Adapter->AdapterHandle,
Adapter->InterruptLevel,
Adapter->InterruptLevel,
TRUE, // RequestISR
TRUE, // SharedInterrupt
NIC_INTERRUPT_MODE);
if (Status != NDIS_STATUS_SUCCESS)
{
DBGPRINT(MP_ERROR, ("NdisMRegisterInterrupt failed\n"));
NdisWriteErrorLogEntry(
Adapter->AdapterHandle,
NDIS_ERROR_CODE_INTERRUPT_CONNECT,
0);
break;
}
MP_SET_FLAG(Adapter, fMP_ADAPTER_INTERRUPT_IN_USE);
//
// Test our adapter hardware
//
Status = NICSelfTest(Adapter);
if (Status != NDIS_STATUS_SUCCESS)
{
break;
}
//
// Init the hardware and set up everything
//
Status = NICInitializeAdapter(Adapter);
if (Status != NDIS_STATUS_SUCCESS)
{
break;
}
//
// Enable the interrupt
//
NICEnableInterrupt(Adapter);
//
// Minimize init-time
//
NdisMInitializeTimer(
&Adapter->LinkDetectionTimer,
Adapter->AdapterHandle,
MpLinkDetectionDpc,
Adapter);
//
// Set the link detection flag
//
MP_SET_FLAG(Adapter, fMP_ADAPTER_LINK_DETECTION);
//
// Increment the reference count so halt handler will wait
//
MP_INC_REF(Adapter);
NdisMSetTimer(&Adapter->LinkDetectionTimer, NIC_LINK_DETECTION_DELAY);
#if LBFO
//
// Add this adapter to the global miniport list
//
MpAddAdapterToList(Adapter);
#endif
} while (FALSE);
if (Adapter && Status != NDIS_STATUS_SUCCESS)
{
//
// Undo everything if it failed
//
MP_DEC_REF(Adapter);
MpFreeAdapter(Adapter);
}
#if DBG
NdisGetCurrentSystemTime(&TE);
TD.QuadPart = TE.QuadPart - TS.QuadPart;
TD.QuadPart /= 10000; // Convert to ms
DBGPRINT(MP_WARN, ("Init time = %d ms\n", TD.LowPart));
#endif
DBGPRINT_S(Status, ("<==== MPInitialize, Status=%x\n", Status));
//
// Ndis doesn't check OpenErrorStatus.
//
*OpenErrorStatus = Status;
return Status;
}
BOOLEAN MPCheckForHang(
IN NDIS_HANDLE MiniportAdapterContext
)
/*++
Routine Description:
MiniportCheckForHang handler
Arguments:
MiniportAdapterContext Pointer to our adapter
Return Value:
TRUE This NIC needs a reset
FALSE Everything is fine
Note:
CheckForHang handler is called in the context of a timer DPC.
take advantage of this fact when acquiring/releasing spinlocks
--*/
{
PMP_ADAPTER Adapter = (PMP_ADAPTER) MiniportAdapterContext;
NDIS_MEDIA_STATE CurrMediaState;
NDIS_STATUS Status;
PMP_TCB pMpTcb;
//
// Just skip this part if the adapter is doing link detection
//
if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_LINK_DETECTION))
{
return(FALSE);
}
//
// any nonrecoverable hardware error?
//
if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_NON_RECOVER_ERROR))
{
DBGPRINT(MP_WARN, ("Non recoverable error - remove\n"));
return (TRUE);
}
//
// hardware failure?
//
if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_HARDWARE_ERROR))
{
DBGPRINT(MP_WARN, ("hardware error - reset\n"));
return(TRUE);
}
//
// Is send stuck?
//
NdisDprAcquireSpinLock(&Adapter->SendLock);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -