📄 nic_pm.c
字号:
}
} while (FALSE);
DebugPrint(TRACE, DBG_POWER, "<--MPSetPowerLowPrivate\n");
}
NTSTATUS
MPSetPowerD0Private (
IN PFDO_DATA FdoData
)
{
PUCHAR pPMDR;
NTSTATUS status;
DebugPrint(TRACE, DBG_POWER, "-->MPSetPowerD0Private\n");
do
{
// Dump the packet if necessary
//Cause of Wake Up
pPMDR = HwReadPowerPMDR(FdoData);
status = NICInitializeAdapter(FdoData);
// Clear the PMDR
MP_CLEAR_PMDR(pPMDR);
NICIssueSelectiveReset(FdoData);
} while (FALSE);
DebugPrint(TRACE, DBG_POWER, "<--MPSetPowerD0Private\n");
return status;
}
VOID
HwSetWakeUpConfigure(
IN PFDO_DATA FdoData,
PUCHAR pPoMgmtConfigType,
UINT WakeUpParameter
)
{
if (IsPoMgmtSupported( FdoData) == TRUE)
{
(*pPoMgmtConfigType)= ((*pPoMgmtConfigType)| CB_WAKE_ON_LINK_BYTE9 |CB_WAKE_ON_ARP_PKT_BYTE9 );
}
}
NTSTATUS
MPSetUpFilterCB(
IN PFDO_DATA FdoData
)
{
NTSTATUS status = STATUS_SUCCESS;
PCB_HEADER_STRUC NonTxCmdBlockHdr = (PCB_HEADER_STRUC)FdoData->NonTxCmdBlock;
PFILTER_CB_STRUC pFilterCb = (PFILTER_CB_STRUC)NonTxCmdBlockHdr;
ULONG Curr = 0;
ULONG Next = 0;
PLIST_ENTRY pPatternEntry = ListNext(&FdoData->PoMgmt.PatternList) ;
DebugPrint(TRACE, DBG_POWER, "--> MPSetUpFilterCB\n");
RtlZeroMemory (pFilterCb, sizeof(*pFilterCb));
// Individual Address Setup
NonTxCmdBlockHdr->CbStatus = 0;
NonTxCmdBlockHdr->CbCommand = CB_EL_BIT | CB_LOAD_PROG_FILTER;
NonTxCmdBlockHdr->CbLinkPointer = DRIVER_NULL;
// go through each filter in the list.
while (pPatternEntry != (&FdoData->PoMgmt.PatternList))
{
PMP_WAKE_PATTERN pWakeUpPattern = NULL;
// initialize local variables
pWakeUpPattern = CONTAINING_RECORD(pPatternEntry, MP_WAKE_PATTERN, linkListEntry);
// increment the iterator
pPatternEntry = ListNext (pPatternEntry);
// Update the Curr Array Pointer
Curr = Next;
// Create the Programmable filter for this device.
MPCreateProgrammableFilter (pWakeUpPattern , (PUCHAR)&pFilterCb->Pattern[Curr], &Next);
if (Next >=16)
{
break;
}
}
{
// Set the EL bit on the last pattern
PUCHAR pLastPattern = (PUCHAR) &pFilterCb->Pattern[Curr];
// Get to bit 31
pLastPattern[3] |= CB_FILTER_EL ;
}
ASSERT(FdoData->CSRAddress->ScbCommandLow == 0);
// Wait for the CU to Idle before giving it this command
if(!WaitScb(FdoData))
{
status = STATUS_DEVICE_DATA_ERROR;
}
DebugPrint(TRACE, DBG_POWER, "<-- MPSetUpFilterCB\n");
return status;
}
NTSTATUS
MPIssueScbPoMgmtCommand(
IN PFDO_DATA FdoData,
IN PCSR_FILTER_STRUC pNewFilter,
IN BOOLEAN WaitForScb
)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
DebugPrint(TRACE, DBG_POWER, "--> MPIssueScbPoMgmtCommand\n");
do
{
// Set up SCB to issue this command
status = MPSetUpFilterCB(FdoData);
if (status != STATUS_SUCCESS)
{
break;
}
// Submit the configure command to the chip, and wait for it to complete.
FdoData->CSRAddress->ScbGeneralPointer = FdoData->NonTxCmdBlockPhys;
status = D100SubmitCommandBlockAndWait(FdoData);
if(status != STATUS_SUCCESS)
{
status = STATUS_DEVICE_DATA_ERROR;
break;
}
} while (FALSE);
DebugPrint(TRACE, DBG_POWER, "<-- MPIssueScbPoMgmtCommand %x\n", status);
return status;
}
NTSTATUS
MPCalculateE100PatternForFilter (
IN PUCHAR pFrame,
IN ULONG FrameLength,
IN PUCHAR pMask,
IN ULONG MaskLength,
OUT PULONG pSignature
)
/*++
Routine Description:
This function outputs the E100 specific Pattern Signature
used to wake up the machine.
Section C.2.4 - CRC word calculation of a Flexible Filer
Arguments:
pFrame - Pattern Set by the protocols
FrameLength - Length of the Pattern
pMask - Mask set by the Protocols
MaskLength - Length of the Mask
pSignature - caller allocated return structure
Return Value:
Returns Success
Failure - if the Pattern is greater than 129 bytes
--*/
{
const ULONG Coefficients = 0x04c11db7;
ULONG Signature = 0;
ULONG n = 0;
ULONG i= 0;
PUCHAR pCurrentMaskByte = pMask - 1; // init to -1
ULONG MaskOffset = 0;
ULONG BitOffsetInMask = 0;
ULONG MaskBit = 0;
ULONG ShiftBy = 0;
UCHAR FrameByte = 0;
NTSTATUS status = STATUS_UNSUCCESSFUL;
DebugPrint(TRACE, DBG_POWER, "--> MPCalculateE100PatternForFilter\n");
*pSignature = 0;
do
{
if (FrameLength > 128)
{
status = STATUS_UNSUCCESSFUL;
break;
}
// The E100 driver can only accept 3 DWORDS of Mask in a single pattern
if (MaskLength > (3*sizeof(ULONG)))
{
status = STATUS_UNSUCCESSFUL;
break;
}
for (n=i=0;(n<128) && (n < FrameLength); ++n)
{
// The first half deals with the question -
// Is the nth Frame byte to be included in the Filter
//
BitOffsetInMask = (n % 8);
if (BitOffsetInMask == 0)
{
//
// We need to move to a new byte.
// [0] for 0th byte, [1] for 8th byte, [2] for 16th byte, etc.
//
MaskOffset = n/8; // This is the new byte we need to go
//
//
if (MaskOffset == MaskLength)
{
break;
}
pCurrentMaskByte ++;
ASSERT (*pCurrentMaskByte == pMask[n/8]);
}
// Now look at the actual bit in the mask
MaskBit = 1 << BitOffsetInMask ;
// If the current Mask Bit is set in the Mask then
// we need to use it in the CRC calculation, otherwise we ignore it
if (!(MaskBit & pCurrentMaskByte[0]))
{
continue;
}
// We are suppossed to take in the current byte as part of the CRC calculation
// Initialize the variables
FrameByte = pFrame[n];
ShiftBy = (i % 3 ) * 8;
ASSERT (ShiftBy!= 24); // Bit 24 is never used
if (Signature & 0x80000000)
{
Signature = ((Signature << 1) ^ ( FrameByte << ShiftBy) ^ Coefficients);
}
else
{
Signature = ((Signature << 1 ) ^ (FrameByte << ShiftBy));
}
++i;
}
// Clear bits 22-31
Signature &= 0x00ffffff;
// Update the result
*pSignature = Signature;
// We have succeeded
status = STATUS_SUCCESS;
} while (FALSE);
DebugPrint(TRACE, DBG_POWER, "<-- MPCalculateE100PatternForFilter\n");
return status;
}
VOID
MPCreateProgrammableFilter (
IN PMP_WAKE_PATTERN pMpWakePattern ,
IN PUCHAR pFilter,
IN OUT PULONG pNext
)
/*++
Routine Description:
This function outputs the E100 specific Pattern Signature
used to wake up the machine.
Section C.2.4 - Load Programmable Filter page C.20
Arguments:
pMpWakePattern - Filter will be created for this pattern,
pFilter - Filter will be stored here,
pNext - Used for validation . This Ulong will also be incremented by the size
of the filter (in ulongs)
Return Value:
--*/
{
PUCHAR pCurrentByte = pFilter;
ULONG NumBytesWritten = 0;
PULONG pCurrentUlong = (PULONG)pFilter;
PNDIS_PM_PACKET_PATTERN pNdisPattern = (PNDIS_PM_PACKET_PATTERN)(&pMpWakePattern->Pattern[0]);
ULONG LengthOfFilter = 0;
DebugPrint(TRACE, DBG_POWER, "--> MPCreateProgrammableFilter\n");
// Is there enough room for this pattern
//
{
// Length in DWORDS
LengthOfFilter = pNdisPattern->MaskSize /4;
if (pNdisPattern->MaskSize % 4 != 0)
{
LengthOfFilter++;
}
// Increment LengthOfFilter to account for the 1st DWORD
LengthOfFilter++;
// We are only allowed 16 DWORDS in a filter
if (*pNext + LengthOfFilter >= 16)
{
// Failure - early exit
return;
}
}
// Clear the Predefined bit; already cleared in the previous function.
// first , initialize -
*pCurrentUlong = 0;
// Mask Length goes into Bits 27-29 of the 1st DWORD. MaskSize is measured in DWORDs
{
ULONG dwMaskSize = pNdisPattern->MaskSize /4;
ULONG dwMLen = 0;
// If there is a remainder a remainder then increment
if (pNdisPattern->MaskSize % 4 != 0)
{
dwMaskSize++;
}
//
// If we fail this assertion, it means our
// MaskSize is greater than 16 bytes.
// This filter should have been failed upfront at the time of the request
//
ASSERT (0 < dwMaskSize <5);
//
// In the Spec, 0 - Single DWORD maske, 001 - 2 DWORD mask,
// 011 - 3 DWORD mask, 111 - 4 Dword Mask.
//
if (dwMaskSize == 1) dwMLen = 0;
if (dwMaskSize == 2) dwMLen = 1;
if (dwMaskSize == 3) dwMLen = 3;
if (dwMaskSize == 4) dwMLen = 7;
// Adjust the Mlen, so it is in the correct position
dwMLen = (dwMLen << 3);
if (dwMLen != 0)
{
ASSERT (dwMLen <= 0x38 && dwMLen >= 0x08);
}
// These go into bits 27,28,29 (bits 3,4 and 5 of the 4th byte)
pCurrentByte[3] |= dwMLen ;
}
// Add the signature to bits 0-23 of the 1st DWORD
{
PUCHAR pSignature = (PUCHAR)&pMpWakePattern->Signature;
// Bits 0-23 are also the 1st three bytes of the DWORD
pCurrentByte[0] = pSignature[0];
pCurrentByte[1] = pSignature[1];
pCurrentByte[2] = pSignature[2];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -