📄 ndiswdm.c
字号:
//
if(Adapter->nBusyRecv)
{
DEBUGP(MP_INFO, ("nBusyRecv = %d\n", Adapter->nBusyRecv));
bDone = FALSE;
}
//
// Are there any outstanding send packets?
//
if(Adapter->nBusySend)
{
DEBUGP(MP_INFO, ("nBusySend = %d\n", Adapter->nBusySend));
bDone = FALSE;
}
if(bDone)
{
break;
}
if((++nHaltCount % 100) == 0)
{
DEBUGP(MP_ERROR, ("Halt timed out!!!\n"));
ASSERT(FALSE);
}
DEBUGP(MP_INFO, ("MPHalt - waiting ...\n"));
NdisMSleep(1000);
}
ASSERT(bDone);
#ifdef NDIS50_MINIPORT
//
// Deregister shutdown handler as it's being halted
//
NdisMDeregisterAdapterShutdownHandler(Adapter->AdapterHandle);
#endif
NICDetachAdapter(Adapter);
NICFreeRecvResources(Adapter);
NICFreeSendResources(Adapter);
NICFreeAdapter(Adapter);
DEBUGP(MP_WARNING, ("<--- MPHalt\n"));
}
NDIS_STATUS
MPReset(
OUT PBOOLEAN AddressingReset,
IN NDIS_HANDLE MiniportAdapterContext
)
/*++
Routine Description:
MiniportReset is a required to issue a hardware reset to the NIC
and/or to reset the driver's software state.
1) The miniport driver can optionally complete any pending
OID requests. NDIS will submit no further OID requests
to the miniport driver for the NIC being reset until
the reset operation has finished. If you return Status_success
and still have any pending OIDs, NDIS will complete the OID
on your behalf. So make sure to complete the pending OIDs
before returning SUCCESS.
2) A deserialized miniport driver must complete any pending send
operations. NDIS will not requeue pending send packets for
a deserialized driver since NDIS does not maintain the send
queue for such a driver.
3) If MiniportReset returns NDIS_STATUS_PENDING, the driver must
complete the original request subsequently with a call to
NdisMResetComplete.
MiniportReset runs at IRQL = DISPATCH_LEVEL.
Arguments:
AddressingReset - If multicast or functional addressing information
or the lookahead size, is changed by a reset,
MiniportReset must set the variable at AddressingReset
to TRUE before it returns control. This causes NDIS to
call the MiniportSetInformation function to restore
the information.
MiniportAdapterContext - Pointer to our adapter
Return Value:
NDIS_STATUS
--*/
{
PMP_ADAPTER Adapter = (PMP_ADAPTER) MiniportAdapterContext;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
DEBUGP(MP_TRACE, ("---> MPReset\n"));
*AddressingReset = FALSE;
ASSERT(Adapter->ResetPending == FALSE);
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
NdisDprAcquireSpinLock(&Adapter->Lock);
//
// If there is a pending request, we must wait for it to complete
// before completing the reset. Since the reset handler is called
// at DISPATCH_LEVEL, we can't really wait here. So we will return
// STATUS_PENDING, and in the completion handler for forwarded
// OID requests, we will call NdisMResetComplete().
//
if(Adapter->RequestPending){
Adapter->ResetPending = TRUE;
Status = NDIS_STATUS_PENDING;
}
NdisDprReleaseSpinLock(&Adapter->Lock);
DEBUGP(MP_TRACE, ("<--- MPReset\n"));
return Status;
}
VOID
MPUnload(
IN PDRIVER_OBJECT DriverObject
)
/*++
Routine Description:
The unload handler is called during driver unload to free up resources
acquired in DriverEntry. This handler is registered through
NdisMRegisterUnloadHandler. Note that an unload handler differs from
a MiniportHalt function in that the unload handler has a more global
scope, whereas the scope of the MiniportHalt function is restricted
to a particular miniport driver instance.
Runs at IRQL = PASSIVE_LEVEL.
Arguments:
DriverObject Not used
Return Value:
None
--*/
{
DEBUGP(MP_WARNING, ("--> MPUnload\n"));
PAGED_CODE();
ASSERT(IsListEmpty(&GlobalData.AdapterList));
NdisFreeSpinLock(&GlobalData.Lock);
DEBUGP(MP_WARNING, ("<--- MPUnload\n"));
}
VOID
MPShutdown(
IN NDIS_HANDLE MiniportAdapterContext
)
/*++
Routine Description:
The MiniportShutdown handler restores a NIC to its initial state when
the system is shut down, whether by the user or because an unrecoverable
system error occurred. This is to ensure that the NIC is in a known
state and ready to be reinitialized when the machine is rebooted after
a system shutdown occurs for any reason, including a crash dump.
Here just disable the interrupt and stop the DMA engine.
Do not free memory resources or wait for any packet transfers
to complete.
Runs at an arbitrary IRQL <= DIRQL. So do not call any passive-level
function.
Arguments:
MiniportAdapterContext Pointer to our adapter
Return Value:
None
--*/
{
PMP_ADAPTER Adapter = (PMP_ADAPTER) MiniportAdapterContext;
DEBUGP(MP_TRACE, ("---> MPShutdown\n"));
DEBUGP(MP_TRACE, ("<--- MPShutdown\n"));
}
BOOLEAN
MPCheckForHang(
IN NDIS_HANDLE MiniportAdapterContext
)
/*++
Routine Description:
The MiniportCheckForHang handler is called to report the state of the
NIC, or to monitor the responsiveness of an underlying device driver.
This is an optional function. If this handler is not specified, NDIS
judges the driver unresponsive when the driver holds
MiniportQueryInformation or MiniportSetInformation requests for a
time-out interval (deafult 4 sec), and then calls the driver's
MiniportReset function. A NIC driver's MiniportInitialize function can
extend NDIS's time-out interval by calling NdisMSetAttributesEx to
avoid unnecessary resets.
Always runs at IRQL = DISPATCH_LEVEL.
Arguments:
MiniportAdapterContext Pointer to our adapter
Return Value:
TRUE NDIS calls the driver's MiniportReset function.
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
--*/
{
//DEBUGP(MP_LOUD, ("---> MPCheckForHang\n"));
//DEBUGP(MP_LOUD, ("<--- MPCheckForHang\n"));
return(FALSE);
}
#ifdef NDIS51_MINIPORT
VOID
MPCancelSendPackets(
IN NDIS_HANDLE MiniportAdapterContext,
IN PVOID CancelId
)
/*++
Routine Description:
MiniportCancelSendPackets cancels the transmission of all packets that
are marked with a specified cancellation identifier. Miniport drivers
that queue send packets for more than one second should export this
handler. When a protocol driver or intermediate driver calls the
NdisCancelSendPackets function, NDIS calls the MiniportCancelSendPackets
function of the appropriate lower-level driver (miniport driver or
intermediate driver) on the binding.
Runs at IRQL <= DISPATCH_LEVEL.
Available - NDIS5.1 (WinXP) and later.
Arguments:
MiniportAdapterContext Pointer to our adapter
CancelId All the packets with this Id should be cancelled
Return Value:
None
--*/
{
PNDIS_PACKET Packet;
PVOID PacketId;
PLIST_ENTRY thisEntry, nextEntry, listHead;
SINGLE_LIST_ENTRY SendCancelList;
PSINGLE_LIST_ENTRY entry;
PMP_ADAPTER Adapter = (PMP_ADAPTER)MiniportAdapterContext;
#define MP_GET_PACKET_MR(_p) (PSINGLE_LIST_ENTRY)(&(_p)->MiniportReserved[0])
DEBUGP(MP_TRACE, ("---> MPCancelSendPackets\n"));
SendCancelList.Next = NULL;
NdisAcquireSpinLock(&Adapter->SendLock);
//
// Walk through the send wait queue and complete the sends with matching Id
//
listHead = &Adapter->SendWaitList;
for(thisEntry = listHead->Flink,nextEntry = thisEntry->Flink;
thisEntry != listHead;
thisEntry = nextEntry,nextEntry = thisEntry->Flink) {
Packet = CONTAINING_RECORD(thisEntry, NDIS_PACKET, MiniportReserved);
PacketId = NdisGetPacketCancelId(Packet);
if (PacketId == CancelId)
{
//
// This packet has the right CancelId
//
RemoveEntryList(thisEntry);
//
// Put this packet on SendCancelList
//
PushEntryList(&SendCancelList, MP_GET_PACKET_MR(Packet));
}
}
NdisReleaseSpinLock(&Adapter->SendLock);
//
// Get the packets from SendCancelList and complete them if any
//
entry = PopEntryList(&SendCancelList);
while (entry)
{
Packet = CONTAINING_RECORD(entry, NDIS_PACKET, MiniportReserved);
NdisMSendComplete(
Adapter->AdapterHandle,
Packet,
NDIS_STATUS_REQUEST_ABORTED);
entry = PopEntryList(&SendCancelList);
}
DEBUGP(MP_TRACE, ("<--- MPCancelSendPackets\n"));
}
VOID MPPnPEventNotify(
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_DEVICE_PNP_EVENT PnPEvent,
IN PVOID InformationBuffer,
IN ULONG InformationBufferLength
)
/*++
Routine Description:
MPPnPEventNotify is to handle PnP notification messages.
An NDIS miniport driver with a WDM lower edge should export a
MiniportPnPEventNotify function so that it can be notified
when its NIC is removed without prior notification through
the user interface. When a miniport driver receives
notification of a surprise removal, it should note internally
that the device has been removed and cancel any pending IRPs
that it sent down to the underlying bus driver. After calling
the MiniportPnPEventNotify function to indicate the surprise
removal, NDIS calls the miniport抯 MiniportHalt function.
If the miniport driver receives any requests to send packets
or query or set OIDs before its MiniportHalt function is
called, it should immediately complete such requests with a
status value of NDIS_STATUS_NOT_ACCEPTED.
All NDIS 5.1 miniport drivers must export a MPPnPEventNotify
function.
Runs at IRQL = PASSIVE_LEVEL in the context of system thread.
Available - NDIS5.1 (WinXP) and later.
Arguments:
MiniportAdapterContext Pointer to our adapter
PnPEvent Self-explanatory
InformationBuffer Self-explanatory
InformationBufferLength Self-explanatory
Return Value:
None
--*/
{
PMP_ADAPTER Adapter = (PMP_ADAPTER)MiniportAdapterContext;
PNDIS_POWER_PROFILE NdisPowerProfile;
DEBUGP(MP_TRACE, ("---> MPPnPEventNotify\n"));
//
// NDIS currently sends only SurpriseRemoved and
// PowerProfileChange Notification events.
//
switch (PnPEvent)
{
case NdisDevicePnPEventQueryRemoved:
//
// Called when NDIS receives IRP_MN_QUERY_REMOVE_DEVICE.
//
DEBUGP(MP_LOUD, ("MPPnPEventNotify: NdisDevicePnPEventQueryRemoved\n"));
break;
case NdisDevicePnPEventRemoved:
//
// Called when NDIS receives IRP_MN_REMOVE_DEVICE.
// NDIS calls MiniportHalt function after this call returns.
//
DEBUGP(MP_LOUD, ("MPPnPEventNotify: NdisDevicePnPEventRemoved\n"));
break;
case NdisDevicePnPEventSurpriseRemoved:
//
// Called when NDIS receives IRP_MN_SUPRISE_REMOVAL.
// NDIS calls MiniportHalt function after this call returns.
//
MP_SET_FLAG(Adapter, fMP_SURPRISE_REMOVED);
DEBUGP(MP_LOUD, ("MPPnPEventNotify: NdisDevicePnPEventSurpriseRemoved\n"));
break;
case NdisDevicePnPEventQueryStopped:
//
// Called when NDIS receives IRP_MN_QUERY_STOP_DEVICE. ??
//
DEBUGP(MP_LOUD, ("MPPnPEventNotify: NdisDevicePnPEventQueryStopped\n"));
break;
case NdisDevicePnPEventStopped:
//
// Called when NDIS receives IRP_MN_STOP_DEVICE.
// NDIS calls MiniportHalt function after this call returns.
//
//
DEBUGP(MP_LOUD, ("MPPnPEventNotify: NdisDevicePnPEventStopped\n"));
break;
case NdisDevicePnPEventPowerProfileChanged:
//
// After initializing a miniport driver and after miniport driver
// receives an OID_PNP_SET_POWER notification that specifies
// a device power state of NdisDeviceStateD0 (the powered-on state),
// NDIS calls the miniport's MiniportPnPEventNotify function with
// PnPEvent set to NdisDevicePnPEventPowerProfileChanged.
//
DEBUGP(MP_LOUD, ("MPPnPEventNotify: NdisDevicePnPEventPowerProfileChanged\n"));
if(InformationBufferLength == sizeof(NDIS_POWER_PROFILE)) {
NdisPowerProfile = (PNDIS_POWER_PROFILE)InformationBuffer;
if(*NdisPowerProfile == NdisPowerProfileBattery) {
DEBUGP(MP_LOUD,
("The host system is running on battery power\n"));
}
if(*NdisPowerProfile == NdisPowerProfileAcOnLine) {
DEBUGP(MP_LOUD,
("The host system is running on AC power\n"));
}
}
break;
default:
DEBUGP(MP_ERROR, ("MPPnPEventNotify: unknown PnP event %x \n", PnPEvent));
break;
}
DEBUGP(MP_TRACE, ("<--- MPPnPEventNotify\n"));
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -