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

📄 marvell.c

📁 Windows CE 6.0 BSP for VOIP sample phone. Intel PXA270 platform.
💻 C
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//

#include <windows.h>
#include <ntddndis.h>
#include <nuiouser.h>
#include "zones.h"

extern BOOL g_HostWakeSet;
int SetPowerMode(HANDLE hNDisUIO, LPTSTR pszDeviceName, ULONG nPowerMode);
int QueryPowerMode(HANDLE hNDisUIO, LPTSTR pszDeviceName, PULONG pulPowerMode);

typedef enum
{   	// card is in full power
	PS_STATE_FULL_POWER,
    	// PS mode, but card is ready for TX
	PS_STATE_WAKEUP,
    	// PS Mode, card is not ready for TX
	PS_STATE_SLEEP, 
    	// SLEEP event is already received, but have not sent confirm yet
    	PS_STATE_SLEEP_PENDING,     
} PS_STATE;

typedef enum
{
    HTWK_STATE_FULL_POWER, 
    HTWK_STATE_PRESLEEP, 
    HTWK_STATE_SLEEP, 
} HTWK_STATE;

typedef struct _Mrvl_EthTypeEntry
{
    USHORT  AddressType; 
    USHORT  EthType; 
    ULONG   Ipv4Addr;
} MRVL_ETHTYPE_ENTRY, *PMRVL_ETHTYPE_ENTRY;

#pragma pack(1)
typedef struct _MrvlIEtypesHeader {
    USHORT  Type;
    USHORT  Len;
} MrvlIEtypesHeader_t;

typedef struct _OID_MRVL_DS_HOST_WAKEUP_FILTER
{
       MrvlIEtypesHeader_t  Header;
    USHORT          AddressType; 
        USHORT          EthType; 
        ULONG       Ipv4Addr;
} OID_MRVL_DS_HOST_WAKEUP_FILTER, *POID_MRVL_DS_HOST_WAKEUP_FILTER;

typedef struct _OID_MRVL_DS_HOST_WAKEUP
{
    ULONG       ulCriteria; 
    UCHAR       ucGPIO; 
    UCHAR       ucGap;
    OID_MRVL_DS_HOST_WAKEUP_FILTER pFilter[1];  
} OID_MRVL_DS_HOST_WAKEUP, *POID_MRVL_DS_HOST_WAKEUP;

typedef struct _OID_MRVL_DS_HOST_WAKEUP_STATUS
{
    ULONG  hwState;
    ULONG  psState;
} OID_MRVL_DS_HOST_WAKEUP_STATUS, *POID_MRVL_DS_HOST_WAKEUP_STATUS;

#pragma pack()

#define OID_MRVL_HOST_SLEEP_CFG             0xff010224
#define OID_MRVL_DEEP_SLEEP                 0xff010220
#define OID_MRVL_HOST_SLEEP_STATUS          0xff010242

//
// This function removes the host wake configuration from the chipset firmware.
// With the configuration removed, the chip will not go into hostwake mode during
// suspend, unless it is set again. This is typically done when the device resumes
// from a suspended state, so that the hostwake feature will not interfere with 
// the normal power save feature.
//
int RemoveHostWakeupEx(HANDLE hNDisUIO, LPTSTR pszDeviceName)
{
    BOOL fRetVal = TRUE;
    PNDISUIO_SET_OID pSetOid = NULL;
    UCHAR SetBuffer[sizeof(NDISUIO_SET_OID) + sizeof(OID_MRVL_DS_HOST_WAKEUP)];
    DWORD cbBuffer = 0;
    DWORD cbDataSize = 0;
    DWORD cbSize = 0;
    DWORD dwBytesReturned = 0;

    OID_MRVL_DS_HOST_WAKEUP HostWakeCfg;


    // CmdLen field needs only the size of the Cmd Body.
    // That is the size of everything minus the OID and the CmdLen field
    memset(&HostWakeCfg, 0, sizeof(HostWakeCfg));
    HostWakeCfg.ucGap = 0xF0; 
    HostWakeCfg.ucGPIO = 0x1;
    HostWakeCfg.ulCriteria = 0xFFFFFFFF; 

    pSetOid = (PNDISUIO_SET_OID) & SetBuffer[0];
    pSetOid->ptcDeviceName = (LPTSTR) (LPCTSTR) pszDeviceName;
    pSetOid->Oid = OID_MRVL_HOST_SLEEP_CFG;

    cbSize = sizeof(OID_MRVL_DS_HOST_WAKEUP) - sizeof(OID_MRVL_DS_HOST_WAKEUP_FILTER);
    memcpy((pSetOid->Data), (UCHAR *) &HostWakeCfg, cbSize);
    cbDataSize += cbSize;

    cbBuffer = cbDataSize + sizeof(NDISUIO_SET_OID); // - sizeof(ULONG);
    fRetVal = DeviceIoControl(hNDisUIO, IOCTL_NDISUIO_SET_OID_VALUE,
                (LPVOID) pSetOid, 
                cbBuffer,
                (LPVOID) pSetOid, 
                cbBuffer,
                &dwBytesReturned, NULL);

    if (fRetVal == 0)
    {
        DEBUGMSG(ZONE_ERROR, (TEXT("Ethman: RemoveHostWakeupEx DeviceIoControl failed. Err = %d\r\n"), GetLastError()));
        return STATUS_UNSUCCESSFUL;
    }
    else
    {
        DEBUGMSG(ZONE_VERBOSE, (TEXT("Ethman: RemoveHostWakeupEx succeeded\r\n")));
        g_HostWakeSet = FALSE;
    }

    return STATUS_SUCCESS;
}


//
// This function sets up the hostwake mode conviguration in the Wifi chipset firmware.
// Configuration involves specifying which wakeup filters are to be used and 
// the criteria upon which the chip should wake up the host. Details about the 
// criteria and parameters are mentioned in the Marvell documentation.
//
int SetHostWakeupEx(HANDLE hNDisUIO, LPTSTR pszDeviceName, DWORD dwIPAddress)
{
    BOOL fRetVal = TRUE;
    PNDISUIO_SET_OID pSetOid = NULL;
    UCHAR SetBuffer[sizeof(NDISUIO_SET_OID) + sizeof(OID_MRVL_DS_HOST_WAKEUP) + sizeof(MRVL_ETHTYPE_ENTRY)];
    DWORD cbBuffer = 0;
    DWORD cbDataSize = 0;
    DWORD cbSize = 0;
    DWORD dwBytesReturned = 0;

    MrvlIEtypesHeader_t EthTypeHeader;
    MRVL_ETHTYPE_ENTRY EthTypeEntry[2];
    OID_MRVL_DS_HOST_WAKEUP HostWakeCfg;

    EthTypeHeader.Type = 0x0115;
    EthTypeHeader.Len = 2 * sizeof(MRVL_ETHTYPE_ENTRY); // 2 EthTypeEntry items
    
    EthTypeEntry[1].AddressType = 2; // unicast
    EthTypeEntry[1].EthType = 0x0008; // IPv4 0x0800 in network byte order.
    EthTypeEntry[1].Ipv4Addr = 0xFFFFFFFF ; // 'match all' IP address

    EthTypeEntry[0].AddressType = 1; // broadcast
    EthTypeEntry[0].EthType = 0x0608; // ARP 0x0806 in network byte order
    EthTypeEntry[0].Ipv4Addr = dwIPAddress; // IP address, already in network byte order

    HostWakeCfg.ucGap = 0xF0; // 240ms after wake
    HostWakeCfg.ucGPIO = 1;
    HostWakeCfg.ulCriteria = 0x3; // any broadcast (0x1) or unicast data (0x2)

    pSetOid = (PNDISUIO_SET_OID) & SetBuffer[0];
    pSetOid->ptcDeviceName = (LPTSTR) (LPCTSTR) pszDeviceName;
    pSetOid->Oid = OID_MRVL_HOST_SLEEP_CFG;

    cbSize = sizeof(OID_MRVL_DS_HOST_WAKEUP) - sizeof(OID_MRVL_DS_HOST_WAKEUP_FILTER);
    memcpy((pSetOid->Data), (UCHAR *) &HostWakeCfg, cbSize);
    cbDataSize += cbSize;

    cbSize = sizeof(MrvlIEtypesHeader_t);
    memcpy((pSetOid->Data + cbDataSize), (UCHAR *) &EthTypeHeader, cbSize);
    cbDataSize += cbSize;

    cbSize = sizeof(MRVL_ETHTYPE_ENTRY);
    memcpy((pSetOid->Data + cbDataSize), (UCHAR *) &EthTypeEntry[0], cbSize);
    cbDataSize += cbSize;

    cbSize = sizeof(MRVL_ETHTYPE_ENTRY);
    memcpy((pSetOid->Data + cbDataSize), (UCHAR *) &EthTypeEntry[1], cbSize);
    cbDataSize += cbSize;

    cbBuffer = sizeof(NDISUIO_SET_OID) + cbDataSize; 

    fRetVal = DeviceIoControl(hNDisUIO, IOCTL_NDISUIO_SET_OID_VALUE,
                (LPVOID) pSetOid, 
                cbBuffer,
                (LPVOID) pSetOid, 
                cbBuffer,
                &dwBytesReturned, NULL);

    if (fRetVal == 0)
    {
        DEBUGMSG(ZONE_ERROR, (TEXT("Ethman: SetHostWakeupEx DeviceIoControl failed. Err = %d\r\n"), GetLastError()));
        return STATUS_UNSUCCESSFUL;
    }
    else
    {
        DEBUGMSG(ZONE_VERBOSE, (TEXT("Ethman: SetHostWakeupEx succeeded\r\n")));
        g_HostWakeSet = TRUE;
    }

    return STATUS_SUCCESS;
}

int SetDeepSleep(HANDLE hNDisUIO, LPTSTR pszDeviceName, BOOL fSleep)
{
    BOOL fRetVal = TRUE;
    PNDISUIO_SET_OID pSetOid = NULL;
    UCHAR SetBuffer[sizeof(NDISUIO_SET_OID) + sizeof(ULONG)];
    DWORD dwBytesReturned = 0;

    pSetOid = (PNDISUIO_SET_OID) & SetBuffer[0];
    pSetOid->ptcDeviceName = (LPTSTR) (LPCTSTR) pszDeviceName;
    pSetOid->Oid = OID_MRVL_DEEP_SLEEP;

    *((ULONG *) (pSetOid->Data)) = fSleep ? 1 : 0;

    fRetVal = DeviceIoControl(hNDisUIO, 
                              IOCTL_NDISUIO_SET_OID_VALUE,
                              (LPVOID) pSetOid, 
                              sizeof(NDISUIO_SET_OID) + sizeof(ULONG),
                              (LPVOID) pSetOid, 
                              sizeof(NDISUIO_SET_OID) + sizeof(ULONG),
                              &dwBytesReturned, 
                              NULL);
    if (fRetVal == 0)
    {
        DEBUGMSG(ZONE_ERROR, (TEXT("Ethman: SetDeepSleep:: SetDeepSleep DeviceIoControl failed. Err = %d\r\n"), GetLastError()));
        return STATUS_UNSUCCESSFUL;
    }

    return STATUS_SUCCESS;
}

int QueryHostWakeState(HANDLE hNDisUIO, LPTSTR pszDeviceName, POID_MRVL_DS_HOST_WAKEUP_STATUS phwStatus)
{
    BOOL fRetVal = TRUE;
    PNDISUIO_QUERY_OID pQueryOid = NULL;
    UCHAR GetBuffer[sizeof(NDISUIO_QUERY_OID) + sizeof(POID_MRVL_DS_HOST_WAKEUP_STATUS)];
    DWORD dwBytesReturned = 0;
    POID_MRVL_DS_HOST_WAKEUP_STATUS phwStatusIn;


    pQueryOid = (PNDISUIO_QUERY_OID) & GetBuffer[0];
    pQueryOid->ptcDeviceName = (LPTSTR) (LPCTSTR) pszDeviceName;
    pQueryOid->Oid = OID_MRVL_HOST_SLEEP_STATUS;

    fRetVal = DeviceIoControl(hNDisUIO, IOCTL_NDISUIO_QUERY_OID_VALUE,
                (LPVOID) pQueryOid, sizeof(NDISUIO_QUERY_OID) + sizeof(POID_MRVL_DS_HOST_WAKEUP_STATUS),
                (LPVOID) pQueryOid, sizeof(NDISUIO_QUERY_OID) + sizeof(POID_MRVL_DS_HOST_WAKEUP_STATUS),
                &dwBytesReturned, NULL);


    if (fRetVal == 0)
        return STATUS_UNSUCCESSFUL;

    phwStatusIn = (POID_MRVL_DS_HOST_WAKEUP_STATUS) (pQueryOid->Data);
    phwStatus->hwState = phwStatusIn->hwState;
    phwStatus->psState = phwStatusIn->psState;
    return STATUS_SUCCESS;
}



BOOL PrepareForHostSleep(HANDLE hNdisUio, LPTSTR pszDeviceName, DWORD dwIPAddress)
{
    OID_MRVL_DS_HOST_WAKEUP_STATUS hwStatus;
    int retryCount;

    if (!dwIPAddress || NULL == pszDeviceName || TEXT('\0') == pszDeviceName[0])
    {
        DEBUGMSG(ZONE_ERROR, (TEXT("Ethman: PrepareForHostSleep:: Error - Invalid parameters\r\n")));
        return FALSE;
    }
    
    SetPowerMode(hNdisUio, pszDeviceName, Ndis802_11PowerModeCAM);
    retryCount = 128;
    do 
    {
        QueryHostWakeState(hNdisUio, pszDeviceName, &hwStatus);
        Sleep(10);
    } 
    while ((--retryCount) && (hwStatus.psState != PS_STATE_FULL_POWER)); 
    
    if (retryCount == 0)
    {
        RETAILMSG(ZONE_ERROR, (TEXT("Ethman: PrepareForHostHostSleep:: Error - wait for PS_STATE_FULL_POWER timed out.\r\n")));
    }

    SetHostWakeupEx(hNdisUio, pszDeviceName, dwIPAddress);

    retryCount = 128;
    do 
    {
        QueryHostWakeState(hNdisUio, pszDeviceName, &hwStatus);
        Sleep(10);
    } 
    while ((--retryCount) && (hwStatus.hwState != HTWK_STATE_SLEEP)); 
    
    if (retryCount == 0)
    {
        RETAILMSG(ZONE_ERROR, (TEXT("Ethman: PrepareForHostHostSleep:: Error - wait for HTWK_STATE_SLEEP timed out.\r\n")));
    }

    SetPowerMode(hNdisUio, pszDeviceName, Ndis802_11PowerModeMAX_PSP);

    retryCount = 128;
    do 
    {
        QueryHostWakeState(hNdisUio, pszDeviceName, &hwStatus);
        Sleep(10);
    } 
    while ((--retryCount) && (hwStatus.psState != PS_STATE_SLEEP)); 
    
    if (retryCount == 0)
    {
        RETAILMSG(ZONE_ERROR, (TEXT("Ethman: PrepareForHostHostSleep:: Error - wait for PS_STATE_SLEEP timed out.\r\n")));
    }

    return TRUE;
}



BOOL RecoverFromHostSleep(HANDLE hNdisUio, LPTSTR pszDeviceName)
{
    OID_MRVL_DS_HOST_WAKEUP_STATUS hwStatus;
    int retryCount;

    if (NULL == pszDeviceName || TEXT('\0') == pszDeviceName[0])
    {
        DEBUGMSG(ZONE_ERROR, (TEXT("Ethman: RecoverFromHostSleep:: Error - no device name.\r\n")));
        return FALSE;
    }

    retryCount = 128;
    do 
    {
        QueryHostWakeState(hNdisUio, pszDeviceName, &hwStatus);
        Sleep(10);
    } 
    while ((--retryCount) && (hwStatus.hwState != HTWK_STATE_FULL_POWER)); 
    
    if (retryCount == 0)
    {
        RETAILMSG(ZONE_ERROR, (TEXT("Ethman: RecoverFromHostSleep:: Error - wait for HTWK_STATE_FULL_POWER timed out.\r\n")));
    }
 
    RemoveHostWakeupEx(hNdisUio, pszDeviceName);

    return TRUE;
}


⌨️ 快捷键说明

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