📄 mp_nic.c
字号:
ASSERT(Adapter->nReadyRecv <= Adapter->CurrNumRfd);
}
NDIS_STATUS NICStartRecv(
IN PMP_ADAPTER Adapter
)
/*++
Routine Description:
Start the receive unit if it's not in a ready state
Assumption: Rcv spinlock has been acquired
Arguments:
Adapter Pointer to our adapter
Return Value:
NDIS_STATUS_SUCCESS
NDIS_STATUS_HARD_ERRROS
--*/
{
PMP_RFD pMpRfd;
NDIS_STATUS Status;
DBGPRINT(MP_TRACE, ("---> NICStartRecv\n"));
//
// If the receiver is ready, then don't try to restart.
//
if (NIC_IS_RECV_READY(Adapter))
{
DBGPRINT(MP_LOUD, ("Receive unit already active\n"));
return NDIS_STATUS_SUCCESS;
}
DBGPRINT(MP_LOUD, ("Re-start receive unit...\n"));
ASSERT(!IsListEmpty(&Adapter->RecvList));
//
// Get the MP_RFD head
//
pMpRfd = (PMP_RFD)GetListHeadEntry(&Adapter->RecvList);
//
// If more packets are received, clean up RFD chain again
//
if (NIC_RFD_GET_STATUS(pMpRfd->HwRfd))
{
MpHandleRecvInterrupt(Adapter);
ASSERT(!IsListEmpty(&Adapter->RecvList));
//
// Get the new MP_RFD head
//
pMpRfd = (PMP_RFD)GetListHeadEntry(&Adapter->RecvList);
}
//
// Start the receive unit with the next free RFD
//
while(NIC_RFD_GET_STATUS(pMpRfd->HwRfd))
{
pMpRfd = (PMP_RFD)GetListFLink(&pMpRfd->List);
if (&Adapter->RecvList == (PLIST_ENTRY)pMpRfd)
{
//
// If all RFDs are being used we exit without
// restarting the receive unit. Another
// interrupt may be needed to restart the receive unit
//
Status = NDIS_STATUS_SUCCESS;
MP_EXIT;
}
}
//
// Wait for the SCB to clear before we set the general pointer
//
if (!WaitScb(Adapter))
{
Status = NDIS_STATUS_HARD_ERRORS;
MP_EXIT;
}
if (Adapter->CurrentPowerState > NdisDeviceStateD0)
{
Status = NDIS_STATUS_HARD_ERRORS;
MP_EXIT;
}
//
// Set the SCB General Pointer to point the current Rfd
//
Adapter->CSRAddress->ScbGeneralPointer = pMpRfd->HwRfdPhys;
//
// Issue the SCB RU start command
//
Status = D100IssueScbCommand(Adapter, SCB_RUC_START, FALSE);
if (Status == NDIS_STATUS_SUCCESS)
{
// wait for the command to be accepted
if (!WaitScb(Adapter))
{
Status = NDIS_STATUS_HARD_ERRORS;
}
}
exit:
DBGPRINT_S(Status, ("<--- NICStartRecv, Status=%x\n", Status));
return Status;
}
VOID MpFreeQueuedSendPackets(
IN PMP_ADAPTER Adapter
)
/*++
Routine Description:
Free and complete the pended sends on SendWaitQueue
Assumption: spinlock has been acquired
Arguments:
Adapter Pointer to our adapter
Return Value:
None
--*/
{
PQUEUE_ENTRY pEntry;
PNDIS_PACKET Packet;
NDIS_STATUS Status = MP_GET_STATUS_FROM_FLAGS(Adapter);
DBGPRINT(MP_TRACE, ("--> MpFreeQueuedSendPackets\n"));
while (!IsQueueEmpty(&Adapter->SendWaitQueue))
{
pEntry = RemoveHeadQueue(&Adapter->SendWaitQueue);
Adapter->nWaitSend--;
NdisReleaseSpinLock(&Adapter->SendLock);
ASSERT(pEntry);
Packet = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReserved);
NdisMSendComplete(
MP_GET_ADAPTER_HANDLE(Adapter),
Packet,
Status);
NdisAcquireSpinLock(&Adapter->SendLock);
}
DBGPRINT(MP_TRACE, ("<-- MpFreeQueuedSendPackets\n"));
}
void MpFreeBusySendPackets(
IN PMP_ADAPTER Adapter
)
/*++
Routine Description:
Free and complete the stopped active sends
Assumption: Send spinlock has been acquired
Arguments:
Adapter Pointer to our adapter
Return Value:
None
--*/
{
PMP_TCB pMpTcb;
DBGPRINT(MP_TRACE, ("--> MpFreeBusySendPackets\n"));
//
// Any packets being sent? Check the first TCB on the send list
//
while (Adapter->nBusySend > 0)
{
pMpTcb = Adapter->CurrSendHead;
//
// Is this TCB completed?
//
if ((pMpTcb->HwTcb->TxCbHeader.CbCommand & CB_CMD_MASK) != CB_MULTICAST)
{
MP_FREE_SEND_PACKET_FUN(Adapter, pMpTcb);
}
else
{
break;
}
}
DBGPRINT(MP_TRACE, ("<-- MpFreeBusySendPackets\n"));
}
VOID NICResetRecv(
IN PMP_ADAPTER Adapter
)
/*++
Routine Description:
Reset the receive list
Assumption: Rcv spinlock has been acquired
Arguments:
Adapter Pointer to our adapter
Return Value:
None
--*/
{
PMP_RFD pMpRfd;
PHW_RFD pHwRfd;
LONG RfdCount;
DBGPRINT(MP_TRACE, ("--> NICResetRecv\n"));
ASSERT(!IsListEmpty(&Adapter->RecvList));
//
// Get the MP_RFD head
//
pMpRfd = (PMP_RFD)GetListHeadEntry(&Adapter->RecvList);
for (RfdCount = 0; RfdCount < Adapter->nReadyRecv; RfdCount++)
{
pHwRfd = pMpRfd->HwRfd;
pHwRfd->RfdCbHeader.CbStatus = 0;
pMpRfd = (PMP_RFD)GetListFLink(&pMpRfd->List);
}
DBGPRINT(MP_TRACE, ("<-- NICResetRecv\n"));
}
VOID MpLinkDetectionDpc(
IN PVOID SystemSpecific1,
IN PVOID FunctionContext,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3
)
/*++
Routine Description:
Timer function for postponed link negotiation
Arguments:
SystemSpecific1 Not used
FunctionContext Pointer to our adapter
SystemSpecific2 Not used
SystemSpecific3 Not used
Return Value:
None
--*/
{
PMP_ADAPTER Adapter = (PMP_ADAPTER)FunctionContext;
NDIS_STATUS Status;
NDIS_MEDIA_STATE CurrMediaState;
NDIS_STATUS IndicateStatus;
UNREFERENCED_PARAMETER(SystemSpecific1);
UNREFERENCED_PARAMETER(SystemSpecific2);
UNREFERENCED_PARAMETER(SystemSpecific3);
//
// Handle the link negotiation.
//
if (Adapter->bLinkDetectionWait)
{
Status = ScanAndSetupPhy(Adapter);
}
else
{
Status = PhyDetect(Adapter);
}
if (Status == NDIS_STATUS_PENDING)
{
// Wait for 100 ms
Adapter->bLinkDetectionWait = TRUE;
NdisMSetTimer(&Adapter->LinkDetectionTimer, NIC_LINK_DETECTION_DELAY);
return;
}
//
// Reset some variables for link detection
//
Adapter->bLinkDetectionWait = FALSE;
DBGPRINT(MP_WARN, ("MpLinkDetectionDpc - negotiation done\n"));
NdisDprAcquireSpinLock(&Adapter->Lock);
MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_LINK_DETECTION);
NdisDprReleaseSpinLock(&Adapter->Lock);
//
// Any OID query request?
//
if (Adapter->bQueryPending)
{
switch(Adapter->QueryRequest.Oid)
{
case OID_GEN_LINK_SPEED:
*((PULONG) Adapter->QueryRequest.InformationBuffer) = Adapter->usLinkSpeed * 10000;
*((PULONG) Adapter->QueryRequest.BytesWritten) = sizeof(ULONG);
break;
case OID_GEN_MEDIA_CONNECT_STATUS:
default:
ASSERT(Adapter->QueryRequest.Oid == OID_GEN_MEDIA_CONNECT_STATUS);
CurrMediaState = NICGetMediaState(Adapter);
NdisMoveMemory(Adapter->QueryRequest.InformationBuffer,
&CurrMediaState,
sizeof(NDIS_MEDIA_STATE));
NdisDprAcquireSpinLock(&Adapter->Lock);
if (Adapter->MediaState != CurrMediaState)
{
Adapter->MediaState = CurrMediaState;
DBGPRINT(MP_WARN, ("Media state changed to %s\n",
((CurrMediaState == NdisMediaStateConnected)?
"Connected": "Disconnected")));
IndicateStatus = (CurrMediaState == NdisMediaStateConnected) ?
NDIS_STATUS_MEDIA_CONNECT : NDIS_STATUS_MEDIA_DISCONNECT;
if (IndicateStatus == 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, IndicateStatus, (PVOID)0, 0);
NdisMIndicateStatusComplete(Adapter->AdapterHandle);
}
else
{
NdisDprReleaseSpinLock(&Adapter->Lock);
}
*((PULONG) Adapter->QueryRequest.BytesWritten) = sizeof(NDIS_MEDIA_STATE);
}
Adapter->bQueryPending = FALSE;
NdisMQueryInformationComplete(Adapter->AdapterHandle, NDIS_STATUS_SUCCESS);
}
//
// Any OID set request?
//
if (Adapter->bSetPending)
{
ULONG PacketFilter;
if (Adapter->SetRequest.Oid == OID_GEN_CURRENT_PACKET_FILTER)
{
NdisMoveMemory(&PacketFilter, Adapter->SetRequest.InformationBuffer, sizeof(ULONG));
NdisDprAcquireSpinLock(&Adapter->Lock);
Status = NICSetPacketFilter(
Adapter,
PacketFilter);
NdisDprReleaseSpinLock(&Adapter->Lock);
if (Status == NDIS_STATUS_SUCCESS)
{
Adapter->PacketFilter = PacketFilter;
}
Adapter->bSetPending = FALSE;
NdisMSetInformationComplete(Adapter->AdapterHandle, Status);
}
}
NdisDprAcquireSpinLock(&Adapter->Lock);
//
// Any pendingf reset?
//
if (Adapter->bResetPending)
{
// The link detection may have held some requests and caused reset.
// Complete the reset with NOT_READY status
Adapter->bResetPending = FALSE;
MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_RESET_IN_PROGRESS);
NdisDprReleaseSpinLock(&Adapter->Lock);
NdisMResetComplete(
Adapter->AdapterHandle,
NDIS_STATUS_ADAPTER_NOT_READY,
FALSE);
}
else
{
NdisDprReleaseSpinLock(&Adapter->Lock);
}
NdisDprAcquireSpinLock(&Adapter->RcvLock);
//
// Start the NIC receive unit
//
Status = NICStartRecv(Adapter);
if (Status != NDIS_STATUS_SUCCESS)
{
MP_SET_HARDWARE_ERROR(Adapter);
}
NdisDprReleaseSpinLock(&Adapter->RcvLock);
NdisDprAcquireSpinLock(&Adapter->SendLock);
//
// Send packets which have been queued while link detection was going on.
//
if (MP_IS_READY(Adapter))
{
while (!IsQueueEmpty(&Adapter->SendWaitQueue) &&
MP_TCB_RESOURCES_AVAIABLE(Adapter))
{
PNDIS_PACKET Packet;
PQUEUE_ENTRY pEntry;
#if OFFLOAD
if (MP_TEST_FLAG(Adapter, fMP_SHARED_MEM_IN_USE))
{
break;
}
#endif
pEntry = RemoveHeadQueue(&Adapter->SendWaitQueue);
ASSERT(pEntry);
Adapter->nWaitSend--;
Packet = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReserved);
DBGPRINT(MP_INFO, ("MpLinkDetectionDpc - send a queued packet\n"));
Status = MpSendPacketFun(Adapter, Packet, TRUE);
if (Status != NDIS_STATUS_SUCCESS)
{
break;
}
}
}
MP_DEC_REF(Adapter);
if (MP_GET_REF(Adapter) == 0)
{
NdisSetEvent(&Adapter->ExitEvent);
}
NdisDprReleaseSpinLock(&Adapter->SendLock);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -