📄 miniport.c
字号:
//
// Free the packets on SendWaitList
//
NICFreeQueuedSendPackets(Adapter);
//
// Cancel the ResetTimer.
//
NdisCancelTimer(&Adapter->ResetTimer, &bCancelled);
//
// Cancel the ReceiveIndication Timer.
//
NdisCancelTimer(&Adapter->RecvTimer, &bCancelled);
if(bCancelled) {
//
// We are able to cancel a queued Timer. So there is a
// possibility for the packets to be waiting in the
// RecvWaitList. So let us free them by calling..
//
NICFreeQueuedRecvPackets(Adapter);
}
//
// Decrement the ref count which was incremented in MPInitialize
//
MP_DEC_REF(Adapter);
//
// Possible non-zero ref counts mean one or more of the following conditions:
// 1) Reset DPC is still running.
// 2) Receive Indication DPC is still running.
//
DEBUGP(MP_INFO, ("RefCount=%d --- waiting!\n", MP_GET_REF(Adapter)));
NdisWaitEvent(&Adapter->RemoveEvent, 0);
while(TRUE)
{
bDone = TRUE;
//
// Are all the packets indicated up returned?
//
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)
{
DEBUGP(MP_ERROR, ("Halt timed out!!!\n"));
DEBUGP(MP_ERROR, ("RecvWaitList = %p\n", &Adapter->RecvWaitList));
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
//
// Unregister the ioctl interface.
//
NICDeregisterDevice();
NICDetachAdapter(Adapter);
NICFreeAdapter(Adapter);
DEBUGP(MP_TRACE, ("<--- 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. After the reset,
NDIS will resubmit to the miniport driver any OID requests
that were pending but not completed by the miniport driver
before the reset.
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
--*/
{
NDIS_STATUS Status;
PMP_ADAPTER Adapter = (PMP_ADAPTER) MiniportAdapterContext;
BOOLEAN bDone = TRUE;
DEBUGP(MP_TRACE, ("---> MPReset\n"));
do
{
ASSERT(!MP_TEST_FLAG(Adapter, fMP_ADAPTER_HALT_IN_PROGRESS));
if(MP_TEST_FLAG(Adapter, fMP_RESET_IN_PROGRESS))
{
Status = NDIS_STATUS_RESET_IN_PROGRESS;
break;
}
MP_SET_FLAG(Adapter, fMP_RESET_IN_PROGRESS);
//
// Complete all the queued up send packets
//
NICFreeQueuedSendPackets(Adapter);
//
// Check to see if all the packets indicated up are returned.
//
if(Adapter->nBusyRecv)
{
DEBUGP(MP_INFO, ("nBusyRecv = %d\n", Adapter->nBusyRecv));
bDone = FALSE;
}
//
// Are there any send packets in the processes of being
// transmitted?
//
if(Adapter->nBusySend)
{
DEBUGP(MP_INFO, ("nBusySend = %d\n", Adapter->nBusySend));
bDone = FALSE;
}
if(!bDone)
{
Adapter->nResetTimerCount = 0;
//
// We can't complete the reset request now. So let us queue
// a timer callback for 500ms and check again whether we can
// successfully reset the hardware.
//
NdisSetTimer(&Adapter->ResetTimer, 500);
//
// By returning NDIS_STATUS_PENDING, we are promising NDIS that
// we will complete the reset request by calling NdisMResetComplete.
//
Status = NDIS_STATUS_PENDING;
break;
}
*AddressingReset = FALSE;
MP_CLEAR_FLAG(Adapter, fMP_RESET_IN_PROGRESS);
Status = NDIS_STATUS_SUCCESS;
} while(FALSE);
DEBUGP(MP_TRACE, ("<--- MPReset Status = 0x%08x\n", Status));
return(Status);
}
VOID
NICResetCompleteTimerDpc(
IN PVOID SystemSpecific1,
IN PVOID FunctionContext,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3)
/*++
Routine Description:
Timer callback function for Reset operation.
Arguments:
FunctionContext - Pointer to our adapter
Return Value:
VOID
--*/
{
PMP_ADAPTER Adapter = (PMP_ADAPTER)FunctionContext;
BOOLEAN bDone = TRUE;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
DEBUGP(MP_TRACE, ("--> NICResetCompleteTimerDpc\n"));
//
// Increment the ref count on the adapter to prevent the driver from
// unloding while the DPC is running. The Halt handler waits for the
// ref count to drop to zero before returning.
//
MP_INC_REF(Adapter);
//
// Check to see if all the packets indicated up are returned.
//
if(Adapter->nBusyRecv)
{
DEBUGP(MP_INFO, ("nBusyRecv = %d\n", Adapter->nBusyRecv));
bDone = FALSE;
}
//
// Are there any send packets in the processes of being
// transmitted?
//
if(Adapter->nBusySend)
{
DEBUGP(MP_INFO, ("nBusySend = %d\n", Adapter->nBusySend));
bDone = FALSE;
}
if(!bDone && ++Adapter->nResetTimerCount <= 20)
{
//
// Let us try one more time.
//
NdisSetTimer(&Adapter->ResetTimer, 500);
}
else
{
if(!bDone)
{
//
// We have tried enough. Something is wrong. Let us
// just complete the reset request with failure.
//
DEBUGP(MP_ERROR, ("Reset timed out!!!\n"));
DEBUGP(MP_ERROR, ("nBusySend = %d\n", Adapter->nBusySend));
DEBUGP(MP_ERROR, ("RecvWaitList = %p\n", &Adapter->RecvWaitList));
DEBUGP(MP_ERROR, ("nBusyRecv = %d\n", Adapter->nBusyRecv));
ASSERT(FALSE);
Status = NDIS_STATUS_FAILURE;
}
DEBUGP(MP_INFO, ("Done - NdisMResetComplete\n"));
MP_CLEAR_FLAG(Adapter, fMP_RESET_IN_PROGRESS);
NdisMResetComplete(
Adapter->AdapterHandle,
Status,
FALSE);
}
MP_DEC_REF(Adapter);
DEBUGP(MP_TRACE, ("<-- NICResetCompleteTimerDpc Status = 0x%08x\n", 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_TRACE, ("--> MPUnload\n"));
ASSERT(IsListEmpty(&GlobalData.AdapterList));
NdisFreeSpinLock(&GlobalData.Lock);
DEBUGP(MP_TRACE, ("<--- 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:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -