⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nic_pm.c

📁 ddk开发pci范例,使用9054芯片
💻 C
📖 第 1 页 / 共 4 页
字号:
    }

    
    // Lets move to the next DWORD. Init variables
    pCurrentByte += 4 ;
    NumBytesWritten = 4;
    pCurrentUlong = (PULONG)pCurrentByte;
    
    // We Copy in the Mask over here
    {
        // The Mask is at the end of the pattern

        PUCHAR pMask = (PUCHAR)pNdisPattern + sizeof(*pNdisPattern);

        //Dump (pMask,pNdisPattern->MaskSize, 0,1);

        RtlMoveMemory (pCurrentByte, pMask, pNdisPattern->MaskSize);

        NumBytesWritten += pNdisPattern->MaskSize;
            
    }


    // Update the output value        
    {
        ULONG NumUlongs = (NumBytesWritten /4);

        if ((NumBytesWritten %4) != 0)
        {
            NumUlongs ++;
        }

        ASSERT (NumUlongs == LengthOfFilter);

        *pNext = *pNext + NumUlongs;
    }

    DebugPrint(TRACE, DBG_POWER, "<-- MPCreateProgrammableFilter\n");

    return;
}

NTSTATUS
MPSetPowerD0(
    PFDO_DATA  FdoData
    )
/*++
Routine Description:

    This routine is called when the adapter receives a SetPower 
    to D0.
    
Arguments:
    
    Adapter                 Pointer to the adapter structure
    PowerState              NewPowerState
    
Return Value:

    
--*/
{
    NTSTATUS            status;
    KIRQL               oldIrql;
    LARGE_INTEGER       DueTime;
    
    //
    // MPSetPowerD0Private Initializes the adapte, issues a selective reset.
    // 
    MPSetPowerD0Private (FdoData); 
    ASSERT(FdoData->DevicePowerState == PowerDeviceD0);
    //
    // Set up the packet filter
    //
    KeAcquireSpinLock(&FdoData->Lock, &oldIrql);
    status = NICSetPacketFilter(
                 FdoData,
                 FdoData->OldPacketFilter);
    //
    // If Set Packet Filter succeeds, restore the old packet filter
    // 
    if (status == STATUS_SUCCESS)
    {
        FdoData->PacketFilter = FdoData->OldPacketFilter;
    }

    KeReleaseSpinLock(&FdoData->Lock, oldIrql);
    
    //
    // Set up the multicast list address
    //
    //
    // We need to raise the IRQL before acquiring the lock
    // because the functions called inside the guarded
    // region assume that they are called at Dpc level and release
    // and reacquire the lock using DpcLevel spinlock functions.
    //
    KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
    KeAcquireSpinLockAtDpcLevel(&FdoData->RcvLock);

    status = NICSetMulticastList(FdoData);

    NICStartRecv(FdoData);

    KeReleaseSpinLockFromDpcLevel(&FdoData->RcvLock);
    KeLowerIrql(oldIrql);

    //
    // Restart the watchdog timer.
    //
    KeClearEvent(&FdoData->WatchDogTimerEvent);    
    DueTime.QuadPart = NIC_CHECK_FOR_HANG_DELAY;    
    KeSetTimer( &FdoData->WatchDogTimer,   // Timer
                        DueTime,         // DueTime
                        &FdoData->WatchDogTimerDpc      // Dpc  
                        );           
    
    //
    // Register the interrupt if it's not done already
    //
    if(!MP_TEST_FLAG(FdoData, fMP_ADAPTER_INTERRUPT_IN_USE)) {

        status = IoConnectInterrupt(&FdoData->Interrupt,
                                  NICInterruptHandler,
                                  FdoData, // ISR Context
                                  NULL,
                                  FdoData->InterruptVector,
                                  FdoData->InterruptLevel,
                                  FdoData->InterruptLevel,
                                  FdoData->InterruptMode,
                                  TRUE, // shared interrupt
                                  FdoData->InterruptAffinity,
                                  FALSE);   
        if (!NT_SUCCESS(status)) {
            DebugPrint(ERROR, DBG_INIT, "IoConnectInterrupt failed %x\n", status);
        } 
        else { 
        
            MP_SET_FLAG(FdoData, fMP_ADAPTER_INTERRUPT_IN_USE);
            //
            // Enable the interrupt, so the driver can send/receive packets
            //
            NICEnableInterrupt(FdoData);
        }
    } else {
        NICEnableInterrupt(FdoData);
    }
    
    return status;
}

NTSTATUS
MPSetPowerLow(
    PFDO_DATA              FdoData,
    DEVICE_POWER_STATE  PowerState 
    )
/*++
Routine Description:

    This routine is called when the FdoData receives a SetPower 
    to a PowerState > D0
    
Arguments:
    
    FdoData                 Pointer to the FdoData structure
    PowerState              NewPowerState
    
Return Value:

    NT Status code
    
--*/
{

    NTSTATUS status = STATUS_SUCCESS;

    do
    {
        //FdoData->DevicePowerState = PowerState;

        //        
        // Stop sending packets. Create a new flag and make it part 
        // of the Send Fail Mask
        //

        //
        // Stop hardware from receiving packets - Set the RU to idle 
        //
        
        //
        // Check the current status of the receive unit
        //
        if ((FdoData->CSRAddress->ScbStatus & SCB_RUS_MASK) != SCB_RUS_IDLE)
        {
            //
            // Issue an RU abort.  Since an interrupt will be issued, the
            // RU will be started by the DPC.
            //
            status = D100IssueScbCommand(FdoData, SCB_RUC_ABORT, TRUE);
        }

        if (status != STATUS_SUCCESS)
        {
            break;
        }
       
        //
        // MPSetPowerLowPrivate first disables the interrupt, acknowledges all the pending 
        // interrupts and sets FdoData->DevicePowerState to the given low power state
        // then starts Hardware specific part of the transition to low power state
        // Setting up wake-up patterns, filters, wake-up events etc
        //
        KeSynchronizeExecution(
                FdoData->Interrupt,
                (PKSYNCHRONIZE_ROUTINE)MPSetPowerLowPrivate,
                FdoData);

        //
        // Disconnect the interrupt when the device is in low power state.
        // This is to avoid being in the ISR calling chain in case our interrupt
        // line is shared by other devices, which is pretty normal for PCI
        // devices. We will register our ISR when we resume from sleep.
        //
        IoDisconnectInterrupt(FdoData->Interrupt);
        FdoData->Interrupt = NULL;
        MP_CLEAR_FLAG(FdoData, fMP_ADAPTER_INTERRUPT_IN_USE);

        status = STATUS_SUCCESS;

    } while (FALSE);

    return status;
}

BOOLEAN 
MPAreTwoPatternsEqual(
    IN PNDIS_PM_PACKET_PATTERN pNdisPattern1,
    IN PNDIS_PM_PACKET_PATTERN pNdisPattern2
    )
/*++
Routine Description:

    This routine will compare two wake up patterns to see if they are equal

Arguments:
    
    pNdisPattern1 - Pattern1 
    pNdisPattern2 - Pattern 2
    
    
Return Value:

    True - if patterns are equal
    False - Otherwise
--*/
{
    BOOLEAN bEqual = FALSE;

    // Local variables used later in the compare section of this function
    PUCHAR  pMask1, pMask2;
    PUCHAR  pPattern1, pPattern2;
    UINT    MaskSize, PatternSize;

    do
    {
    	
        bEqual = (BOOLEAN)(pNdisPattern1->Priority == pNdisPattern2->Priority);

        if (bEqual == FALSE)
        {
            break;
        }

        bEqual = (BOOLEAN)(pNdisPattern1->MaskSize == pNdisPattern2->MaskSize);
        if (bEqual == FALSE)
        {
            break;
        }

        //
        // Verify the Mask 
        //
        MaskSize = pNdisPattern1->MaskSize ; 
        pMask1 = (PUCHAR) pNdisPattern1 + sizeof (NDIS_PM_PACKET_PATTERN);
        pMask2 = (PUCHAR) pNdisPattern2 + sizeof (NDIS_PM_PACKET_PATTERN);
        
        bEqual = (BOOLEAN)RtlEqualMemory (pMask1, pMask2, MaskSize);

        if (bEqual == FALSE)
        {
            break;
        }

        //
        // Verify the Pattern
        //
        bEqual = (BOOLEAN)(pNdisPattern1->PatternSize == pNdisPattern2->PatternSize);
        
        if (bEqual == FALSE)
        {
            break;
        }

        PatternSize = pNdisPattern2->PatternSize;
        pPattern1 = (PUCHAR) pNdisPattern1 + pNdisPattern1->PatternOffset;
        pPattern2 = (PUCHAR) pNdisPattern2 + pNdisPattern2->PatternOffset;
        
        bEqual  = (BOOLEAN)RtlEqualMemory (pPattern1, pPattern2, PatternSize );

        if (bEqual == FALSE)
        {
            break;
        }

    } while (FALSE);

    return bEqual;
}

VOID 
NICExtractPMInfoFromPciSpace(
    PFDO_DATA FdoData,
    PUCHAR pPciConfig
    )
/*++
Routine Description:

    Looks at the PM information in the 
    device specific section of the PCI Config space.
    
    Interprets the register values and stores it 
    in the adapter structure
  
    Definitions from Table 4.2 & 4.3, Pg 4-9 & 4-10 
    of the 10/100 Mbit Ethernet Family Software Technical 
    Reference Manual
  

Arguments:

    Adapter     Pointer to our adapter
    pPciConfig  Pointer to Common Pci Space

Return Value:

--*/    
{
    PMP_PM_PCI_SPACE    pPmPciConfig = (PMP_PM_PCI_SPACE )pPciConfig;
    MP_PMCSR            PMCSR;

    //
    // First interpret the PM Capabities register
    //
    {
        MP_PM_CAP_REG   PmCaps;

        PmCaps = pPmPciConfig->PMCaps;

        if(PmCaps.PME_Support &  E100_PMC_WAKE_FROM_D0)
        {
            FdoData->PoMgmt.bWakeFromD0 = TRUE;       
        }
    
        if(PmCaps.PME_Support &  E100_PMC_WAKE_FROM_D1)
        {
            FdoData->PoMgmt.bWakeFromD1 = TRUE;       
        }

        if(PmCaps.PME_Support &  E100_PMC_WAKE_FROM_D2)
        {
            FdoData->PoMgmt.bWakeFromD2 = TRUE;       
        }

        if(PmCaps.PME_Support &  E100_PMC_WAKE_FROM_D3HOT)
        {
            FdoData->PoMgmt.bWakeFromD3Hot = TRUE;       
        }

        if(PmCaps.PME_Support &  E100_PMC_WAKE_FROM_D3_AUX)
        {
            FdoData->PoMgmt.bWakeFromD3Aux = TRUE;       
        }

    }

    //
    // Interpret the PM Control/Status Register
    //
    {
        PMCSR = pPmPciConfig->PMCSR;

        if (PMCSR.PME_En == 1)
        {
            //
            // PME is enabled. Clear the PME_En bit.
            // So that it is not asserted
            //
            MpClearPME_En (FdoData,PMCSR);

        }

    }        

}


NTSTATUS
NICSetPower(
    PFDO_DATA     FdoData ,
    DEVICE_POWER_STATE   PowerState 
    )
/*++
Routine Description:

    This routine is called when the FdoData receives a SetPower 
    request. It redirects the call to an appropriate routine to
    Set the New PowerState
    
Arguments:
    
    FdoData                 Pointer to the FdoData structure
    PowerState              NewPowerState
    
Return Value:
   
    NTSTATUS Code
    
--*/
{
    NTSTATUS      status = STATUS_SUCCESS;

      
    if (PowerState == PowerDeviceD0)
    {
        DebugPrint(TRACE, DBG_POWER, "Entering fully on state\n");          

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -