📄 mp_main.c
字号:
if (Adapter->nBusySend > 0)
{
pMpTcb = Adapter->CurrSendHead;
pMpTcb->Count++;
if (pMpTcb->Count > NIC_SEND_HANG_THRESHOLD)
{
NdisDprReleaseSpinLock(&Adapter->SendLock);
DBGPRINT(MP_WARN, ("Send stuck - reset\n"));
return(TRUE);
}
}
NdisDprReleaseSpinLock(&Adapter->SendLock);
NdisDprAcquireSpinLock(&Adapter->RcvLock);
//
// Update the RFD shrink count
//
if (Adapter->CurrNumRfd > Adapter->NumRfd)
{
Adapter->RfdShrinkCount++;
}
NdisDprReleaseSpinLock(&Adapter->RcvLock);
NdisDprAcquireSpinLock(&Adapter->Lock);
CurrMediaState = NICGetMediaState(Adapter);
if (CurrMediaState != Adapter->MediaState)
{
DBGPRINT(MP_WARN, ("Media state changed to %s\n",
((CurrMediaState == NdisMediaStateConnected)?
"Connected": "Disconnected")));
Adapter->MediaState = CurrMediaState;
Status = (CurrMediaState == NdisMediaStateConnected) ?
NDIS_STATUS_MEDIA_CONNECT : NDIS_STATUS_MEDIA_DISCONNECT;
if (Status == NDIS_STATUS_MEDIA_CONNECT)
{
MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_NO_CABLE);
}
else
{
MP_SET_FLAG(Adapter, fMP_ADAPTER_NO_CABLE);
}
NdisDprReleaseSpinLock(&Adapter->Lock);
// Indicate the media event
NdisMIndicateStatus(Adapter->AdapterHandle, Status, (PVOID)0, 0);
NdisMIndicateStatusComplete(Adapter->AdapterHandle);
}
else
{
NdisDprReleaseSpinLock(&Adapter->Lock);
}
return(FALSE);
}
VOID MPHalt(
IN NDIS_HANDLE MiniportAdapterContext)
/*++
Routine Description:
MiniportHalt handler
Arguments:
MiniportAdapterContext Pointer to our adapter
Return Value:
None
--*/
{
LONG Count;
PMP_ADAPTER Adapter = (PMP_ADAPTER) MiniportAdapterContext;
MP_SET_FLAG(Adapter, fMP_ADAPTER_HALT_IN_PROGRESS);
DBGPRINT(MP_TRACE, ("====> MPHalt\n"));
//
// Call Shutdown handler to disable interrupt and turn the hardware off
// by issuing a full reset
//
MPShutdown(MiniportAdapterContext);
//
// Deregister interrupt as early as possible
//
if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_INTERRUPT_IN_USE))
{
NdisMDeregisterInterrupt(&Adapter->Interrupt);
MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_INTERRUPT_IN_USE);
}
#if LBFO
MpRemoveAdapterFromList(Adapter);
//
// For a regualr miniport, no send packets and OID requests should be outstanding
// when Halt handler is called. But for a LBFO miniport in secondary mode,
// some packets from primary miniport may be still around
//
NdisAcquireSpinLock(&Adapter->SendLock);
//
// Free the packets on SendWaitList
//
MpFreeQueuedSendPackets(Adapter);
//
// Free the packets being actively sent & stopped
//
MpFreeBusySendPackets(Adapter);
NdisReleaseSpinLock(&Adapter->SendLock);
#endif
//
// Decrement the ref count which was incremented in MPInitialize
//
Count = MP_DEC_REF(Adapter);
//
// Possible non-zero ref counts mean one or more of the following conditions:
// 1) Pending async shared memory allocation;
// 2) DPC's are not finished (e.g. link detection)
//
if (Count)
{
DBGPRINT(MP_WARN, ("RefCount=%d --- waiting!\n", MP_GET_REF(Adapter)));
while (TRUE)
{
if (NdisWaitEvent(&Adapter->ExitEvent, 2000))
{
break;
}
DBGPRINT(MP_WARN, ("RefCount=%d --- rewaiting!\n", MP_GET_REF(Adapter)));
}
}
NdisAcquireSpinLock(&Adapter->RcvLock);
//
// wait for all the received packets to return
//
MP_DEC_RCV_REF(Adapter);
Count = MP_GET_RCV_REF(Adapter);
NdisReleaseSpinLock(&Adapter->RcvLock);
if (Count)
{
DBGPRINT(MP_WARN, ("RcvRefCount=%d --- waiting!\n", Count));
while (TRUE)
{
if (NdisWaitEvent(&Adapter->AllPacketsReturnedEvent, 2000))
{
break;
}
DBGPRINT(MP_WARN, ("RcvRefCount=%d --- rewaiting!\n", MP_GET_RCV_REF(Adapter)));
}
}
//
// Reset the PHY chip. We do this so that after a warm boot, the PHY will
// be in a known state, with auto-negotiation enabled.
//
ResetPhy(Adapter);
//
// Free the entire adapter object, including the shared memory structures.
//
MpFreeAdapter(Adapter);
DBGPRINT(MP_TRACE, ("<==== MPHalt\n"));
}
NDIS_STATUS MPReset(
OUT PBOOLEAN AddressingReset,
IN NDIS_HANDLE MiniportAdapterContext)
/*++
Routine Description:
MiniportReset handler
Arguments:
AddressingReset To let NDIS know whether we need help from it with our reset
MiniportAdapterContext Pointer to our adapter
Return Value:
NDIS_STATUS_SUCCESS
NDIS_STATUS_PENDING
NDIS_STATUS_RESET_IN_PROGRESS
NDIS_STATUS_HARD_ERRORS
Note:
ResetHandler is called at DPC. take advantage of this fact when acquiring or releasing
spinlocks
--*/
{
NDIS_STATUS Status;
PMP_ADAPTER Adapter = (PMP_ADAPTER) MiniportAdapterContext;
DBGPRINT(MP_TRACE, ("====> MPReset\n"));
*AddressingReset = TRUE;
NdisDprAcquireSpinLock(&Adapter->Lock);
NdisDprAcquireSpinLock(&Adapter->SendLock);
NdisDprAcquireSpinLock(&Adapter->RcvLock);
do
{
ASSERT(!MP_TEST_FLAG(Adapter, fMP_ADAPTER_HALT_IN_PROGRESS));
//
// Is this adapter already doing a reset?
//
if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_RESET_IN_PROGRESS))
{
Status = NDIS_STATUS_RESET_IN_PROGRESS;
MP_EXIT;
}
MP_SET_FLAG(Adapter, fMP_ADAPTER_RESET_IN_PROGRESS);
//
// Is this adapter doing link detection?
//
if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_LINK_DETECTION))
{
DBGPRINT(MP_WARN, ("Reset is pended...\n"));
Adapter->bResetPending = TRUE;
Status = NDIS_STATUS_PENDING;
MP_EXIT;
}
//
// Is this adapter going to be removed
//
if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_NON_RECOVER_ERROR))
{
Status = NDIS_STATUS_HARD_ERRORS;
if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_REMOVE_IN_PROGRESS))
{
MP_EXIT;
}
// This is an unrecoverable hardware failure.
// We need to tell NDIS to remove this miniport
MP_SET_FLAG(Adapter, fMP_ADAPTER_REMOVE_IN_PROGRESS);
MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_RESET_IN_PROGRESS);
NdisDprReleaseSpinLock(&Adapter->RcvLock);
NdisDprReleaseSpinLock(&Adapter->SendLock);
NdisDprReleaseSpinLock(&Adapter->Lock);
NdisWriteErrorLogEntry(
Adapter->AdapterHandle,
NDIS_ERROR_CODE_HARDWARE_FAILURE,
1,
ERRLOG_REMOVE_MINIPORT);
NdisMRemoveMiniport(Adapter->AdapterHandle);
DBGPRINT_S(Status, ("<==== MPReset, Status=%x\n", Status));
return Status;
}
//
// Disable the interrupt and issue a reset to the NIC
//
NICDisableInterrupt(Adapter);
NICIssueSelectiveReset(Adapter);
//
// release all the locks and then acquire back the send lock
// we are going to clean up the send queues
// which may involve calling Ndis APIs
// release all the locks before grabbing the send lock to
// avoid deadlocks
//
NdisDprReleaseSpinLock(&Adapter->RcvLock);
NdisDprReleaseSpinLock(&Adapter->SendLock);
NdisDprReleaseSpinLock(&Adapter->Lock);
NdisDprAcquireSpinLock(&Adapter->SendLock);
//
// This is a deserialized miniport, we need to free all the send packets
// Free the packets on SendWaitList
//
MpFreeQueuedSendPackets(Adapter);
//
// Free the packets being actively sent & stopped
//
MpFreeBusySendPackets(Adapter);
#if DBG
if (MP_GET_REF(Adapter) > 1)
{
DBGPRINT(MP_WARN, ("RefCount=%d\n", MP_GET_REF(Adapter)));
}
#endif
NdisZeroMemory(Adapter->MpTcbMem, Adapter->MpTcbMemSize);
//
// Re-initialize the send structures
//
NICInitSend(Adapter);
NdisDprReleaseSpinLock(&Adapter->SendLock);
//
// get all the locks again in the right order
//
NdisDprAcquireSpinLock(&Adapter->Lock);
NdisDprAcquireSpinLock(&Adapter->SendLock);
NdisDprAcquireSpinLock(&Adapter->RcvLock);
//
// Reset the RFD list and re-start RU
//
NICResetRecv(Adapter);
Status = NICStartRecv(Adapter);
if (Status != NDIS_STATUS_SUCCESS)
{
// Are we having failures in a few consecutive resets?
if (Adapter->HwErrCount < NIC_HARDWARE_ERROR_THRESHOLD)
{
// It's not over the threshold yet, let it to continue
Adapter->HwErrCount++;
}
else
{
// This is an unrecoverable hardware failure.
// We need to tell NDIS to remove this miniport
MP_SET_FLAG(Adapter, fMP_ADAPTER_REMOVE_IN_PROGRESS);
MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_RESET_IN_PROGRESS);
NdisDprReleaseSpinLock(&Adapter->RcvLock);
NdisDprReleaseSpinLock(&Adapter->SendLock);
NdisDprReleaseSpinLock(&Adapter->Lock);
NdisWriteErrorLogEntry(
Adapter->AdapterHandle,
NDIS_ERROR_CODE_HARDWARE_FAILURE,
1,
ERRLOG_REMOVE_MINIPORT);
NdisMRemoveMiniport(Adapter->AdapterHandle);
DBGPRINT_S(Status, ("<==== MPReset, Status=%x\n", Status));
return(Status);
}
break;
}
Adapter->HwErrCount = 0;
MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_HARDWARE_ERROR);
NICEnableInterrupt(Adapter);
} while (FALSE);
MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_RESET_IN_PROGRESS);
exit:
NdisDprReleaseSpinLock(&Adapter->RcvLock);
NdisDprReleaseSpinLock(&Adapter->SendLock);
NdisDprReleaseSpinLock(&Adapter->Lock);
DBGPRINT_S(Status, ("<==== MPReset, Status=%x\n", Status));
return(Status);
}
VOID MPReturnPacket(
IN NDIS_HANDLE MiniportAdapterContext,
IN PNDIS_PACKET Packet
)
/*++
Routine Description:
MiniportReturnPacket handler
Arguments:
MiniportAdapterContext Pointer to our adapter
Packet Pointer to a packet being returned to the miniport
Return Value:
None
Note:
ReturnPacketHandler is called at DPC. take advantage of this fact when acquiring or releasing
spinlocks
--*/
{
PMP_ADAPTER Adapter = (PMP_ADAPTER)MiniportAdapterContext;
PMP_RFD pMpRfd = MP_GET_PACKET_RFD(Packet);
ULONG Count;
DBGPRINT(MP_TRACE, ("====> MPReturnPacket\n"));
ASSERT(pMpRfd);
ASSERT(MP_TEST_FLAG(pMpRfd, fMP_RFD_RECV_PEND));
MP_CLEAR_FLAG(pMpRfd, fMP_RFD_RECV_PEND);
NdisDprAcquireSpinLock(&Adapter->RcvLock);
RemoveEntryList((PLIST_ENTRY)pMpRfd);
// Decrement the Power Mgmt Ref.
Adapter->PoMgmt.OutstandingRecv --;
//
// If we have set power pending, then complete it
//
if (((Adapter->bSetPending == TRUE)
&& (Adapter->SetRequest.Oid == OID_PNP_SET_POWER))
&& (Adapter->PoMgmt.OutstandingRecv == 0))
{
MpSetPowerLowComplete(Adapter);
}
if (Adapter->RfdShrinkCount < NIC_RFD_SHRINK_THRESHOLD)
{
NICReturnRFD(Adapter, pMpRfd);
}
else
{
ASSERT(Adapter->CurrNumRfd > Adapter->NumRfd);
Adapter->RfdShrinkCount = 0;
NICFreeRfd(Adapter, pMpRfd);
Adapter->CurrNumRfd--;
DBGPRINT(MP_TRACE, ("Shrink... CurrNumRfd = %d\n", Adapter->CurrNumRfd));
}
//
// note that we get the ref count here, but check
// to see if it is zero and signal the event -after-
// releasign the SpinLock. otherwise, we may let the Halthandler
// continue while we are holding a lock.
//
MP_DEC_RCV_REF(Adapter);
Count = MP_GET_RCV_REF(Adapter);
NdisDprReleaseSpinLock(&Adapter->RcvLock);
if (Count == 0)
NdisSetEvent(&Adapter->AllPacketsReturnedEvent);
DBGPRINT(MP_TRACE, ("<==== MPReturnPacket\n"));
}
VOID MPSendPackets(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -