Sample Code
Windows Driver Samples/ Native Wi-Fi Miniport Sample Driver/ C++/ hw/ hw_oids.c/
/*++ Copyright (c) Microsoft Corporation. All rights reserved. Module Name: hw_oids.c Abstract: Implements the OIDs for the HW layer Revision History: When What ---------- ---------------------------------------------- 09-04-2007 Created Notes: --*/ #include "precomp.h" #include "hw_oids.h" #include "hw_mac.h" #include "hw_phy.h" #include "hw_main.h" #include "hw_rate.h" #if DOT11_TRACE_ENABLED #include "hw_oids.tmh" #endif NDIS_STATUS Hw11Fill80211Attributes( _In_ PHW Hw, _Out_ PNDIS_MINIPORT_ADAPTER_NATIVE_802_11_ATTRIBUTES attr ) { PDOT11_PHY_ATTRIBUTES PhyAttr; ULONG PhyId; ULONG index; UCHAR rate; PNICPHYMIB phyMib; attr->NumOfTXBuffers = Hw->RegInfo.NumTXBuffers; attr->NumOfRXBuffers = Hw->RegInfo.NumRXBuffers; attr->MultiDomainCapabilityImplemented = HwQueryMultiDomainCapabilityImplemented(Hw); attr->NumSupportedPhys = HalGetSupportedPhyTypes(Hw->Hal)->uNumOfEntries; MP_ALLOCATE_MEMORY(Hw->MiniportAdapterHandle, &attr->SupportedPhyAttributes, attr->NumSupportedPhys * sizeof(DOT11_PHY_ATTRIBUTES), HW_MEMORY_TAG); if (attr->SupportedPhyAttributes == NULL) { return NDIS_STATUS_RESOURCES; } // // Fill the PHY attributes // for (PhyId = 0, PhyAttr = attr->SupportedPhyAttributes; PhyId < attr->NumSupportedPhys; PhyId++, PhyAttr++) { MP_ASSIGN_NDIS_OBJECT_HEADER(PhyAttr->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_PHY_ATTRIBUTES_REVISION_1, sizeof(DOT11_PHY_ATTRIBUTES)); phyMib = HalGetPhyMIB(Hw->Hal, PhyId); PhyAttr->PhyType = phyMib->PhyType; PhyAttr->bHardwarePhyState = HwQueryHardwarePhyState(Hw, PhyId); PhyAttr->bSoftwarePhyState = HwQuerySoftwarePhyState(Hw, PhyId); PhyAttr->bCFPollable = FALSE; PhyAttr->uMPDUMaxLength = HW11_MAX_FRAME_SIZE; PhyAttr->TempType = HwQueryTempType(Hw, PhyId); PhyAttr->DiversitySupport = HwQueryDiversitySupport(Hw, PhyId); PhyAttr->uNumberSupportedPowerLevels = Hw->PhyState.SupportedPowerLevels.uNumOfSupportedPowerLevels; for (index = 0; index < PhyAttr->uNumberSupportedPowerLevels; index++) { PhyAttr->TxPowerLevels[index] = Hw->PhyState.SupportedPowerLevels.uTxPowerLevelValues[index]; } switch (PhyAttr->PhyType) { case dot11_phy_type_hrdsss: PhyAttr->HRDSSSAttributes.bShortPreambleOptionImplemented = HwQueryShortPreambleOptionImplemented(Hw, PhyId); PhyAttr->HRDSSSAttributes.bPBCCOptionImplemented = HwQueryPbccOptionImplemented(Hw, PhyId); PhyAttr->HRDSSSAttributes.bChannelAgilityPresent = HwQueryChannelAgilityPresent(Hw, PhyId); PhyAttr->HRDSSSAttributes.uHRCCAModeSupported = HwQueryCCAModeSupported(Hw, PhyId); break; case dot11_phy_type_ofdm: PhyAttr->OFDMAttributes.uFrequencyBandsSupported = HwQueryFrequencyBandsSupported(Hw, PhyId); break; case dot11_phy_type_erp: PhyAttr->ERPAttributes.bShortPreambleOptionImplemented = HwQueryShortPreambleOptionImplemented(Hw, PhyId); PhyAttr->ERPAttributes.bPBCCOptionImplemented = HwQueryPbccOptionImplemented(Hw, PhyId); PhyAttr->ERPAttributes.bChannelAgilityPresent = HwQueryChannelAgilityPresent(Hw, PhyId); PhyAttr->ERPAttributes.uHRCCAModeSupported = HwQueryCCAModeSupported(Hw, PhyId); PhyAttr->ERPAttributes.bERPPBCCOptionImplemented = FALSE; PhyAttr->ERPAttributes.bDSSSOFDMOptionImplemented = FALSE; PhyAttr->ERPAttributes.bShortSlotTimeOptionImplemented = HwQueryShortSlotTimeOptionImplemented(Hw, PhyId); break; default: break; } NdisMoveMemory(&PhyAttr->SupportedDataRatesValue, &HalGetPhyMIB(Hw->Hal, PhyId)->SupportedDataRatesValue, sizeof(DOT11_SUPPORTED_DATA_RATES_VALUE_V2)); index = 0; while ((rate = PhyAttr->SupportedDataRatesValue.ucSupportedTxDataRatesValue[index]) != 0 && index < DOT11_RATE_SET_MAX_LENGTH) { PhyAttr->DataRateMappingEntries[index].ucDataRateIndex = rate; PhyAttr->DataRateMappingEntries[index].ucDataRateFlag = 0; PhyAttr->DataRateMappingEntries[index].usDataRateValue = (USHORT)rate; index++; } PhyAttr->uNumDataRateMappingEntries = index; } return NDIS_STATUS_SUCCESS; } VOID Hw11Cleanup80211Attributes( _In_ PHW Hw, _In_ PNDIS_MINIPORT_ADAPTER_NATIVE_802_11_ATTRIBUTES attr ) { UNREFERENCED_PARAMETER(Hw); if (attr->SupportedPhyAttributes) { MP_FREE_MEMORY(attr->SupportedPhyAttributes); } } PDOT11_MAC_ADDRESS Hw11QueryMACAddress( _In_ PHW_MAC_CONTEXT HwMac ) { // Return the address assigned to this MAC return &HwMac->MacAddress; } PDOT11_MAC_ADDRESS Hw11QueryCurrentAddress( _In_ PHW Hw ) { // Return the MAC address programmed on the hardware return &Hw->MacState.MacAddress; } VOID Hw11QueryPnPCapabilities( _In_ PHW Hw, _Out_ PNDIS_PNP_CAPABILITIES NdisPnPCapabilities ) { UNREFERENCED_PARAMETER(Hw); NdisZeroMemory(NdisPnPCapabilities, sizeof(NDIS_PNP_CAPABILITIES)); // If we support WOL, we would fill in additional capabilities here } VOID Hw11QueryPMCapabilities( _In_ PHW Hw, _Out_ PNDIS_PM_CAPABILITIES NdisPmCapabilities ) { UNREFERENCED_PARAMETER(Hw); NdisZeroMemory(NdisPmCapabilities, sizeof(NDIS_PM_CAPABILITIES)); // Fill in the PM capabilities NdisPmCapabilities->Header.Type = NDIS_OBJECT_TYPE_DEFAULT; NdisPmCapabilities->Header.Revision = NDIS_PM_CAPABILITIES_REVISION_1; NdisPmCapabilities->Header.Size = NDIS_SIZEOF_NDIS_PM_CAPABILITIES_REVISION_1; // If we supported WOL, we would fill in additional capabilities here } BOOLEAN Hw11WEP104Implemented( _In_ PHW Hw ) { UNREFERENCED_PARAMETER(Hw); return TRUE; } BOOLEAN Hw11WEP40Implemented( _In_ PHW Hw ) { UNREFERENCED_PARAMETER(Hw); return TRUE; } BOOLEAN Hw11TKIPImplemented( _In_ PHW Hw ) { return (HalGetEncryptionCapabilities(Hw->Hal) & HAL_ENCRYPTION_SUPPORT_TKIP) ? TRUE : FALSE; } BOOLEAN Hw11CCMPImplemented( _In_ PHW Hw, _In_ DOT11_BSS_TYPE bssType ) { ULONG ndisVersion; if (!(HalGetEncryptionCapabilities(Hw->Hal) & HAL_ENCRYPTION_SUPPORT_CCMP)) return FALSE; if (bssType == dot11_BSS_type_infrastructure) { // Due to our dependency on BCrypt API, CCMP in adhoc is only supported // on Vista SP1 & above ndisVersion = NdisGetVersion(); if (ndisVersion < MP_NDIS_VERSION_VISTASP1_SRV2008) { // Not supported return FALSE; } } return TRUE; } ULONG Hw11DefaultKeyTableSize( _In_ PHW Hw ) { UNREFERENCED_PARAMETER(Hw); return DOT11_MAX_NUM_DEFAULT_KEY; } ULONG Hw11KeyMappingKeyTableSize( _In_ PHW Hw ) { return (HalGetEncryptionCapabilities(Hw->Hal) & HAL_ENCRYPTION_SUPPORT_KEYMAPPINGKEYTABLE) ? 0 : HW_KEY_MAPPING_KEY_TABLE_SIZE; } ULONG Hw11PerStaKeyTableSize( _In_ PHW Hw ) { UNREFERENCED_PARAMETER(Hw); return HW_PER_STA_KEY_TABLE_SIZE; } NDIS_STATUS Hw11ValidateOperationalRates( _In_ PHW_MAC_CONTEXT HwMac, _In_ ULONG PhyId, _In_reads_bytes_(RateSetLength) PUCHAR DataRateSet, _In_ ULONG RateSetLength ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; ULONG i, j; BOOLEAN rateFound; PDOT11_RATE_SET opRateSet; do { opRateSet = &(HalGetPhyMIB(HwMac->Hw->Hal, PhyId)->OperationalRateSet); if (RateSetLength > DOT11_RATE_SET_MAX_LENGTH) { MpTrace(COMP_ASSOC, DBG_LOUD, ("Bad rate set size in Rate Set\n")); ndisStatus = NDIS_STATUS_INVALID_DATA; break; } for (i = 0; i < RateSetLength; i++) { rateFound = FALSE; for (j = 0; j < opRateSet->uRateSetLength; j++) { if ((DataRateSet[i] & 0x7F) == opRateSet->ucRateSet[j]) { rateFound = TRUE; break; } } if (rateFound == FALSE) { MpTrace(COMP_ASSOC, DBG_LOUD, ("Bad data rate %d detected\n", DataRateSet[i])); ndisStatus = NDIS_STATUS_INVALID_DATA; break; } } } while(FALSE); return ndisStatus; } PDOT11_MAC_ADDRESS Hw11QueryCurrentBSSID( _In_ PHW_MAC_CONTEXT HwMac ) { return &HwMac->DesiredBSSID; } ULONG Hw11QueryBeaconPeriod( _In_ PHW_MAC_CONTEXT HwMac ) { return HwMac->BeaconPeriod; } DOT11_PHY_TYPE Hw11QueryCurrentPhyType( _In_ PHW_MAC_CONTEXT HwMac ) { PNICPHYMIB operatingPhyMib; // // Get the PHY MIB for the operating phy of this MAC context // operatingPhyMib = HalGetPhyMIB(HwMac->Hw->Hal, HwMac->OperatingPhyId); return operatingPhyMib->PhyType; } BOOLEAN Hw11QueryShortSlotTimeOptionImplemented( _In_ PHW_MAC_CONTEXT HwMac, _In_ BOOLEAN SelectedPhy ) { // // Determine the PHY that the user wants to query // if (SelectedPhy) return HwQueryShortSlotTimeOptionImplemented(HwMac->Hw, HwMac->SelectedPhyId); else return HwQueryShortSlotTimeOptionImplemented(HwMac->Hw, HwMac->OperatingPhyId); } BOOLEAN Hw11QueryShortSlotTimeOptionEnabled( _In_ PHW_MAC_CONTEXT HwMac, _In_ BOOLEAN SelectedPhy ) { PNICPHYMIB phyMib; // // Determine the PHY that the user wants to query // if (SelectedPhy) phyMib = HalGetPhyMIB(HwMac->Hw->Hal, HwMac->SelectedPhyId); else phyMib = HalGetPhyMIB(HwMac->Hw->Hal, HwMac->OperatingPhyId); // // Information about short slot time option is stored in the MAC context // if (phyMib->PhyType == dot11_phy_type_erp) return HwMac->ShortSlotTimeOptionEnabled; else return FALSE; } BOOLEAN Hw11QueryDsssOfdmOptionImplemented( _In_ PHW_MAC_CONTEXT HwMac, _In_ BOOLEAN SelectedPhy ) { if (SelectedPhy) return HwQueryDsssOfdmOptionImplemented(HwMac->Hw, HwMac->SelectedPhyId); else return HwQueryDsssOfdmOptionImplemented(HwMac->Hw, HwMac->OperatingPhyId); } BOOLEAN Hw11QueryDsssOfdmOptionEnabled( _In_ PHW_MAC_CONTEXT HwMac, _In_ BOOLEAN SelectedPhy ) { UNREFERENCED_PARAMETER(HwMac); UNREFERENCED_PARAMETER(SelectedPhy); // // Not implemented, so always returning false // return FALSE; } BOOLEAN Hw11QueryShortPreambleOptionImplemented( _In_ PHW_MAC_CONTEXT HwMac, _In_ BOOLEAN SelectedPhy ) { // // Determine the PHY that the user wants to query // if (SelectedPhy) return HwQueryShortPreambleOptionImplemented(HwMac->Hw, HwMac->SelectedPhyId); else return HwQueryShortPreambleOptionImplemented(HwMac->Hw, HwMac->OperatingPhyId); } BOOLEAN Hw11QueryPbccOptionImplemented( _In_ PHW_MAC_CONTEXT HwMac, _In_ BOOLEAN SelectedPhy ) { // // Determine the PHY that the user wants to query // if (SelectedPhy) return HwQueryPbccOptionImplemented(HwMac->Hw, HwMac->SelectedPhyId); else return HwQueryPbccOptionImplemented(HwMac->Hw, HwMac->OperatingPhyId); } BOOLEAN Hw11QueryChannelAgilityPresent( _In_ PHW_MAC_CONTEXT HwMac, _In_ BOOLEAN SelectedPhy ) { // // Determine the PHY that the user wants to query // if (SelectedPhy) return HwQueryChannelAgilityPresent(HwMac->Hw, HwMac->SelectedPhyId); else return HwQueryChannelAgilityPresent(HwMac->Hw, HwMac->OperatingPhyId); } BOOLEAN Hw11QueryChannelAgilityEnabled( _In_ PHW_MAC_CONTEXT HwMac, _In_ BOOLEAN SelectedPhy ) { UNREFERENCED_PARAMETER(HwMac); UNREFERENCED_PARAMETER(SelectedPhy); // // Not present, so always returning false // return FALSE; } BOOLEAN Hw11QueryCFPollable( _In_ PHW Hw ) { UNREFERENCED_PARAMETER(Hw); return FALSE; } VOID Hw11QueryBasicRateSet( _In_ PHW_MAC_CONTEXT HwMac, _Out_ PDOT11_RATE_SET Dot11RateSet, _In_ BOOLEAN SelectedPhy ) { PNICPHYMIB phyMib; ULONG index; // // Determine the PHY that the user wants to query // if (SelectedPhy) phyMib = HalGetPhyMIB(HwMac->Hw->Hal, HwMac->SelectedPhyId); else phyMib = HalGetPhyMIB(HwMac->Hw->Hal, HwMac->OperatingPhyId); // // Copy the rate set // for (index = 0; (index < phyMib->BasicRateSet.uRateSetLength) && (index < DOT11_RATE_SET_MAX_LENGTH); index++) { Dot11RateSet->ucRateSet[index] = phyMib->BasicRateSet.ucRateSet[index]; } Dot11RateSet->uRateSetLength = index; } VOID Hw11QueryOperationalRateSet( _In_ PHW_MAC_CONTEXT HwMac, _Out_ PDOT11_RATE_SET Dot11RateSet, _In_ BOOLEAN SelectedPhy ) { PDOT11_RATE_SET rateTable = NULL; // // Determine the PHY that the user wants to query // if (SelectedPhy) rateTable = &HwMac->PhyContext[HwMac->SelectedPhyId].OperationalRateSet; else rateTable = &HwMac->PhyContext[HwMac->OperatingPhyId].OperationalRateSet; // // Copy the rate set // NdisMoveMemory(Dot11RateSet, rateTable, sizeof(DOT11_RATE_SET)); } NDIS_STATUS Hw11QuerySupportedPHYTypes( _In_ PHW Hw, _In_ ULONG NumMaxEntries, _Out_ PDOT11_SUPPORTED_PHY_TYPES Dot11SupportedPhyTypes ) { USHORT index; PDOT11_SUPPORTED_PHY_TYPES supportedPhyTypes = HalGetSupportedPhyTypes(Hw->Hal); if (NumMaxEntries < supportedPhyTypes->uNumOfEntries) { Dot11SupportedPhyTypes->uTotalNumOfEntries = supportedPhyTypes->uNumOfEntries; Dot11SupportedPhyTypes->uNumOfEntries = NumMaxEntries; for (index = 0; index < NumMaxEntries; index++) Dot11SupportedPhyTypes->dot11PHYType[index] = supportedPhyTypes->dot11PHYType[index]; return NDIS_STATUS_BUFFER_OVERFLOW; } else { Dot11SupportedPhyTypes->uTotalNumOfEntries = supportedPhyTypes->uNumOfEntries; Dot11SupportedPhyTypes->uNumOfEntries = supportedPhyTypes->uNumOfEntries; for (index = 0; index < supportedPhyTypes->uNumOfEntries; index++) Dot11SupportedPhyTypes->dot11PHYType[index] = supportedPhyTypes->dot11PHYType[index]; return NDIS_STATUS_SUCCESS; } } NDIS_STATUS Hw11QuerySupportedChannels( _In_ PHW_MAC_CONTEXT HwMac, _In_ ULONG PhyId, _Out_ PULONG ChannelCount, _Out_opt_ PULONG ChannelList ) { return HalGetChannelList(HwMac->Hw->Hal, PhyId, ChannelCount, ChannelList); } ULONG Hw11QueryCurrentChannel( _In_ PHW_MAC_CONTEXT HwMac, _In_ BOOLEAN SelectedPhy ) { // // Determine the PHY that the user wants to query // if (SelectedPhy) return HwMac->PhyContext[HwMac->SelectedPhyId].Channel; else return HwMac->PhyContext[HwMac->OperatingPhyId].Channel; } ULONG Hw11QueryATIMWindow( _In_ PHW_MAC_CONTEXT HwMac ) { return HwMac->AtimWindow; } ULONG Hw11QueryOperatingPhyId( _In_ PHW_MAC_CONTEXT HwMac ) { return HwMac->OperatingPhyId; } BOOLEAN Hw11IsConnected( _In_ PHW_MAC_CONTEXT HwMac ) { return ((HwMac->Status & HW_MAC_CONTEXT_LINK_UP)?TRUE:FALSE); } USHORT Hw11QueryRSNCapabilityField( _In_ PHW Hw ) { UNREFERENCED_PARAMETER(Hw); return 0; } DOT11_PHY_TYPE Hw11DeterminePHYType( _In_ PHW_MAC_CONTEXT HwMac, _In_ DOT11_CAPABILITY Capability, _In_ UCHAR Channel ) { PNICPHYMIB phyMib; if (Channel > 14) { return dot11_phy_type_ofdm; } else { phyMib = HalGetPhyMIB(HwMac->Hw->Hal, HwMac->OperatingPhyId); // // We have to determine between B and G. // If the Capability contains G-only field, it must be G // Otherwise, use our current operating PHY type. // if (Capability.ShortSlotTime || Capability.DSSSOFDM || phyMib->PhyType == dot11_phy_type_ofdm) { return dot11_phy_type_erp; } else { return phyMib->PhyType; } } } BOOLEAN Hw11IsKeyMappingKeyAvailable( _In_ PHW_MAC_CONTEXT HwMac, _In_reads_bytes_(DOT11_ADDRESS_SIZE) DOT11_MAC_ADDRESS MacAddr ) { UCHAR index; UCHAR count = HwMac->KeyMappingKeyCount; PHW_KEY_ENTRY keyEntry; // // This is quicker more optimal version than HwFindKeyMappingKeyIndex used // on the data path // if (count == 0) return FALSE; for (index = DOT11_MAX_NUM_DEFAULT_KEY; index < HW11_KEY_TABLE_SIZE; index++) { keyEntry = &HwMac->KeyTable[index]; if (keyEntry->Key.Valid) { if (MP_COMPARE_MAC_ADDRESS(keyEntry->Key.MacAddr, MacAddr)) { return TRUE; } count--; if (count == 0) { return FALSE; } } } // // Can reach here if we dont find a key for the specific AP // return FALSE; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS Hw11QueryDot11Statistics( _In_ PHW_MAC_CONTEXT HwMac, _Inout_updates_bytes_to_(InformationBufferLength, *BytesWritten) PDOT11_STATISTICS Dot11Stats, _In_ ULONG InformationBufferLength, _Out_ PULONG BytesWritten, _Out_when_invalid_ndis_length_ PULONG BytesNeeded ) { PDOT11_SUPPORTED_PHY_TYPES supportedPhyTypes = HalGetSupportedPhyTypes(HwMac->Hw->Hal); ULONG statsSize = sizeof(DOT11_STATISTICS) + (supportedPhyTypes->uNumOfEntries - 1) * sizeof(DOT11_PHY_FRAME_STATISTICS); PDOT11_PHY_FRAME_STATISTICS phyStats; ULONG phyId; if (InformationBufferLength < statsSize) { *BytesNeeded = statsSize; return NDIS_STATUS_BUFFER_OVERFLOW; } // Unicast counters NdisMoveMemory(&Dot11Stats->MacUcastCounters, &HwMac->UnicastCounters, sizeof(DOT11_MAC_FRAME_STATISTICS) ); // Multicast counters NdisMoveMemory(&Dot11Stats->MacMcastCounters, &HwMac->MulticastCounters, sizeof(DOT11_MAC_FRAME_STATISTICS) ); // Phy counters for (phyId = 0, phyStats = Dot11Stats->PhyCounters; phyId < supportedPhyTypes->uNumOfEntries; phyId++, phyStats++ ) { NdisMoveMemory(phyStats, &HwMac->Hw->Stats.PhyCounters[phyId], sizeof(DOT11_PHY_FRAME_STATISTICS) ); } *BytesWritten = statsSize; return NDIS_STATUS_SUCCESS; } BOOLEAN Hw11QueryNicPowerState( _In_ PHW_MAC_CONTEXT HwMac, _In_ BOOLEAN SelectedPhy ) { // // Determine the PHY that the user wants to query // if (SelectedPhy) return HwQueryNicPowerState(HwMac->Hw, HwMac->SelectedPhyId); else return HwQueryNicPowerState(HwMac->Hw, HwMac->OperatingPhyId); } NDIS_STATUS Hw11QueryRecvSensitivityList( _In_ PHW_MAC_CONTEXT HwMac, _In_ ULONG MaxEntries, _Inout_ PDOT11_RECV_SENSITIVITY_LIST Dot11RecvSensitivityList ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; ULONG i; PNICPHYMIB phyMib = NULL; PDOT11_SUPPORTED_PHY_TYPES supportedPhyTypes = HalGetSupportedPhyTypes(HwMac->Hw->Hal); do { if (Dot11RecvSensitivityList->uPhyId >= supportedPhyTypes->uNumOfEntries) { MpTrace(COMP_OID, DBG_SERIOUS, ("Phy Id not supported by the NIC\n")); ndisStatus = NDIS_STATUS_FAILURE; break; } phyMib = HalGetPhyMIB(HwMac->Hw->Hal, Dot11RecvSensitivityList->uPhyId); Dot11RecvSensitivityList->uTotalNumOfEntries = 0; for (i = 0; i < MAX_NUM_SUPPORTED_RATES_V2; i++) { if (phyMib->SupportedDataRatesValue.ucSupportedRxDataRatesValue[i] != 0) Dot11RecvSensitivityList->uTotalNumOfEntries++; } // // Find out how many entries can we place? // if (MaxEntries < Dot11RecvSensitivityList->uTotalNumOfEntries) { Dot11RecvSensitivityList->uNumOfEntries = MaxEntries; ndisStatus = NDIS_STATUS_INVALID_LENGTH; } else { Dot11RecvSensitivityList->uNumOfEntries = Dot11RecvSensitivityList->uTotalNumOfEntries; ndisStatus = NDIS_STATUS_SUCCESS; } MPASSERT(Dot11RecvSensitivityList->uNumOfEntries >= 1 && Dot11RecvSensitivityList->uNumOfEntries <= 4); // // There is at least one element we can fill. // for (i = 0; i < Dot11RecvSensitivityList->uNumOfEntries; i++) { Dot11RecvSensitivityList->dot11RecvSensitivity[i].ucDataRate = phyMib->SupportedDataRatesValue.ucSupportedRxDataRatesValue[i]; Dot11RecvSensitivityList->dot11RecvSensitivity[i].lRSSIMax = HwQueryMaxRSSI(HwMac->Hw, Dot11RecvSensitivityList->dot11RecvSensitivity[i].ucDataRate); Dot11RecvSensitivityList->dot11RecvSensitivity[i].lRSSIMin = HwQueryMinRSSI(HwMac->Hw, Dot11RecvSensitivityList->dot11RecvSensitivity[i].ucDataRate); } } while(FALSE); return ndisStatus; } ULONG Hw11QueryDefaultKeyId( _In_ PHW_MAC_CONTEXT HwMac ) { return HwMac->DefaultKeyIndex; } ULONG Hw11QuerySelectedPhyId( _In_ PHW_MAC_CONTEXT HwMac ) { return HwMac->SelectedPhyId; } BOOLEAN Hw11QueryHardwarePhyState( _In_ PHW_MAC_CONTEXT HwMac ) { return HwQueryHardwarePhyState(HwMac->Hw, HwMac->SelectedPhyId); } BOOLEAN Hw11QuerySoftwarePhyState( _In_ PHW_MAC_CONTEXT HwMac ) { return HwQuerySoftwarePhyState(HwMac->Hw, HwMac->SelectedPhyId); } NDIS_STATUS Hw11QueryInterruptModerationSettings( _In_ PHW Hw, _Out_ PNDIS_INTERRUPT_MODERATION_PARAMETERS IntModParams ) { UNREFERENCED_PARAMETER(Hw); // Interrupt moderation not supported IntModParams->Flags = 0; IntModParams->InterruptModeration = NdisInterruptModerationNotSupported; return NDIS_STATUS_SUCCESS; } NDIS_STATUS Hw11QueryLinkParameters( _In_ PHW_MAC_CONTEXT HwMac, _Out_ PNDIS_LINK_PARAMETERS LinkParams ) { // // Report the current link speed to the OS // LinkParams->MediaDuplexState = MediaDuplexStateHalf; LinkParams->XmitLinkSpeed = HwDataRateToLinkSpeed((UCHAR)HwMac->DefaultTXDataRate); LinkParams->RcvLinkSpeed = HwDataRateToLinkSpeed((UCHAR)HwMac->DefaultTXDataRate); LinkParams->PauseFunctions = NdisPauseFunctionsUnsupported; LinkParams->AutoNegotiationFlags = NDIS_LINK_STATE_DUPLEX_AUTO_NEGOTIATED; return NDIS_STATUS_SUCCESS; } NDIS_STATUS Hw11QueryDataRateMappingTable( _In_ PHW_MAC_CONTEXT HwMac, _Out_ PDOT11_DATA_RATE_MAPPING_TABLE DataRateMappingTable, _In_ ULONG TotalLength ) { UNREFERENCED_PARAMETER(HwMac); UNREFERENCED_PARAMETER(DataRateMappingTable); UNREFERENCED_PARAMETER(TotalLength); // // We don't support non-standard data rate. // return NDIS_STATUS_NOT_SUPPORTED; } NDIS_STATUS Hw11QuerySupportedPowerLevels( _In_ PHW_MAC_CONTEXT HwMac, _Out_ PDOT11_SUPPORTED_POWER_LEVELS Dot11SupportedPowerLevels ) { USHORT Index; // HwMac->Hw->PhyState.SupportedPowerLevels.uNumOfSupportedPowerLevels <= 8 Dot11SupportedPowerLevels->uNumOfSupportedPowerLevels = HwMac->Hw->PhyState.SupportedPowerLevels.uNumOfSupportedPowerLevels; for( Index=0; Index < HwMac->Hw->PhyState.SupportedPowerLevels.uNumOfSupportedPowerLevels; Index++ ) Dot11SupportedPowerLevels->uTxPowerLevelValues[Index] = HwMac->Hw->PhyState.SupportedPowerLevels.uTxPowerLevelValues[Index]; return NDIS_STATUS_SUCCESS; } NDIS_STATUS Hw11QuerySupportedRXAntenna( _In_ PHW Hw, _In_ ULONG MaxEntries, _Out_ PDOT11_SUPPORTED_ANTENNA_LIST Dot11SupportedAntennaList ) { ULONG i; UNREFERENCED_PARAMETER(Hw); if (MaxEntries < HW11_MAX_RX_ANTENNA) { Dot11SupportedAntennaList->uNumOfEntries = 0; Dot11SupportedAntennaList->uTotalNumOfEntries = HW11_MAX_RX_ANTENNA; return NDIS_STATUS_BUFFER_OVERFLOW; } else { Dot11SupportedAntennaList->uTotalNumOfEntries = HW11_MAX_RX_ANTENNA; for(i = 0; i < HW11_MAX_RX_ANTENNA && i < MaxEntries;i++) { Dot11SupportedAntennaList->dot11SupportedAntenna[i].uAntennaListIndex = i+1; Dot11SupportedAntennaList->dot11SupportedAntenna[i].bSupportedAntenna = TRUE; } Dot11SupportedAntennaList->uNumOfEntries = HW11_MAX_RX_ANTENNA; return NDIS_STATUS_SUCCESS; } } NDIS_STATUS Hw11QuerySupportedTXAntenna( _In_ PHW Hw, _In_ ULONG MaxEntries, _Out_ PDOT11_SUPPORTED_ANTENNA_LIST Dot11SupportedAntennaList ) { ULONG i; UNREFERENCED_PARAMETER(Hw); if (MaxEntries < HW11_MAX_TX_ANTENNA) { Dot11SupportedAntennaList->uNumOfEntries = 0; Dot11SupportedAntennaList->uTotalNumOfEntries = HW11_MAX_TX_ANTENNA; return NDIS_STATUS_BUFFER_OVERFLOW; } else { Dot11SupportedAntennaList->uTotalNumOfEntries = HW11_MAX_TX_ANTENNA; for(i = 0; i < HW11_MAX_TX_ANTENNA && i < MaxEntries;i++) { Dot11SupportedAntennaList->dot11SupportedAntenna[i].uAntennaListIndex = i+1; Dot11SupportedAntennaList->dot11SupportedAntenna[i].bSupportedAntenna = TRUE; } Dot11SupportedAntennaList->uNumOfEntries = HW11_MAX_TX_ANTENNA; return NDIS_STATUS_SUCCESS; } } NDIS_STATUS Hw11QueryDiversitySelectionRX( _In_ PHW_MAC_CONTEXT HwMac, _In_ BOOLEAN SelectedPhy, _In_ ULONG MaxEntries, _Out_ PDOT11_DIVERSITY_SELECTION_RX_LIST Dot11DiversitySelectionRXList ) { // // Determine the PHY that the user wants to query // if (SelectedPhy) return HwQueryDiversitySelectionRX(HwMac->Hw, HwMac->SelectedPhyId, MaxEntries, Dot11DiversitySelectionRXList ); else return HwQueryDiversitySelectionRX(HwMac->Hw, HwMac->SelectedPhyId, MaxEntries, Dot11DiversitySelectionRXList ); } NDIS_STATUS Hw11QueryRegDomainsSupportValue( _In_ PHW_MAC_CONTEXT HwMac, _In_ BOOLEAN SelectedPhy, _In_ ULONG MaxEntries, _Out_ PDOT11_REG_DOMAINS_SUPPORT_VALUE Dot11RegDomainsSupportValue ) { // // Determine the PHY that the user wants to query // if (SelectedPhy) return HwQueryRegDomainsSupportValue(HwMac->Hw, HwMac->SelectedPhyId, MaxEntries, Dot11RegDomainsSupportValue ); else return HwQueryRegDomainsSupportValue(HwMac->Hw, HwMac->OperatingPhyId, MaxEntries, Dot11RegDomainsSupportValue ); } ULONG Hw11QueryLookahead( _In_ PHW_MAC_CONTEXT HwMac ) { UNREFERENCED_PARAMETER(HwMac); // We always return the same lookahead size return (DOT11_MIN_PDU_SIZE - (sizeof(DOT11_DATA_SHORT_HEADER) + 12)); } ULONG Hw11QueryHardwareStatus( _In_ PHW Hw ) { // // We are currently only using the software status to report the hardware // status. We can also look at the physical hardware status to report this // if (HW_TEST_ADAPTER_STATUS(Hw, (HW_ADAPTER_SURPRISE_REMOVED | HW_ADAPTER_HALTING | HW_ADAPTER_IN_LOW_POWER))) { return NdisHardwareStatusNotReady; } else if (HW_TEST_ADAPTER_STATUS(Hw, (HW_ADAPTER_IN_RESET))) { return NdisHardwareStatusReset; } else { return NdisHardwareStatusReady; } } ULONG Hw11QueryReceiveBufferSpace( _In_ PHW Hw ) { return HW11_MAX_FRAME_SIZE * Hw->RegInfo.NumRXBuffers; } ULONG Hw11QueryTransmitBufferSpace( _In_ PHW Hw ) { return HW11_MAX_FRAME_SIZE * Hw->RegInfo.NumTXBuffers; } NDIS_STATUS Hw11QueryVendorDescription( _In_ PHW Hw, _Out_writes_bytes_(InformationBufferLength) PVOID InformationBuffer, _In_ ULONG InformationBufferLength, _Out_ PULONG BytesWritten, _Out_ PULONG BytesNeeded ) { UCHAR VendorDesc[] = HW11_VENDOR_DESCRIPTION; UNREFERENCED_PARAMETER(Hw); *BytesNeeded = sizeof(VendorDesc); if (InformationBufferLength < *BytesNeeded) { return NDIS_STATUS_BUFFER_OVERFLOW; } NdisMoveMemory(InformationBuffer, VendorDesc, *BytesNeeded); *BytesWritten = *BytesNeeded; return NDIS_STATUS_SUCCESS; } ULONG Hw11QueryVendorId( _In_ PHW Hw ) { UNREFERENCED_PARAMETER(Hw); return MP_VENDOR_ID; } NDIS_STATUS Hw11QueryCurrentOptionalCapability( _In_ PHW Hw, _In_ PDOT11_CURRENT_OPTIONAL_CAPABILITY Dot11CurrentOptionalCapability ) { UNREFERENCED_PARAMETER(Hw); // // Support for nothing // Dot11CurrentOptionalCapability->uReserved = 0; Dot11CurrentOptionalCapability->bDot11CFPollable = FALSE; Dot11CurrentOptionalCapability->bDot11PCF = FALSE; Dot11CurrentOptionalCapability->bDot11PCFMPDUTransferToPC = FALSE; Dot11CurrentOptionalCapability->bStrictlyOrderedServiceClass = FALSE; return NDIS_STATUS_SUCCESS; } ULONG Hw11QueryMaxMPDULength( _In_ PHW_MAC_CONTEXT HwMac ) { // // Always reporting the same list to the caller // UNREFERENCED_PARAMETER(HwMac); return HW11_MAX_FRAME_SIZE; } NDIS_STATUS Hw11QueryMulticastList( _In_ PHW_MAC_CONTEXT HwMac, _Out_ PVOID AddressBuffer, _In_ ULONG AddressBufferLength, _Out_ PULONG BytesWritten, _Out_ PULONG BytesNeeded ) { *BytesNeeded = HwMac->MulticastAddressCount * DOT11_ADDRESS_SIZE; *BytesWritten = 0; if (AddressBufferLength < *BytesNeeded) { return NDIS_STATUS_BUFFER_OVERFLOW; } // Copy the addresses over NdisMoveMemory(AddressBuffer, HwMac->MulticastAddressList, *BytesNeeded); *BytesWritten = *BytesNeeded; return NDIS_STATUS_SUCCESS; } NDIS_STATUS Hw11QueryOperationModeCapability( _In_ PHW Hw, _Out_ PDOT11_OPERATION_MODE_CAPABILITY Dot11OpModeCapability ) { Dot11OpModeCapability->uReserved = 0; Dot11OpModeCapability->uMajorVersion = MP_OPERATION_MODE_CAPABILITY_MAJOR_VERSION; Dot11OpModeCapability->uMinorVersion = MP_OPERATION_MODE_CAPABILITY_MINOR_VERSION; // We can buffer as many packets as OS sends. Dot11OpModeCapability->uNumOfTXBuffers = Hw->RegInfo.NumTXBuffers; Dot11OpModeCapability->uNumOfRXBuffers = Hw->RegInfo.NumRXBuffers; Dot11OpModeCapability->uOpModeCapability = DOT11_OPERATION_MODE_EXTENSIBLE_STATION | DOT11_OPERATION_MODE_NETWORK_MONITOR | DOT11_OPERATION_MODE_EXTENSIBLE_AP; return NDIS_STATUS_SUCCESS; } NDIS_STATUS Hw11QueryOptionalCapability( _In_ PHW Hw, _Out_ PDOT11_OPTIONAL_CAPABILITY Dot11OptionalCapability ) { UNREFERENCED_PARAMETER(Hw); // // Support for nothing // Dot11OptionalCapability->uReserved = 0; Dot11OptionalCapability->bDot11PCF = FALSE; Dot11OptionalCapability->bDot11PCFMPDUTransferToPC = FALSE; Dot11OptionalCapability->bStrictlyOrderedServiceClass = FALSE; return NDIS_STATUS_SUCCESS; } PDOT11_MAC_ADDRESS Hw11QueryHardwareAddress( _In_ PHW Hw ) { return (PDOT11_MAC_ADDRESS)HalGetPermanentAddress(Hw->Hal); } ULONG Hw11QueryRFUsage( _In_ PHW Hw ) { UNREFERENCED_PARAMETER(Hw); // // NOTE: The hardware does not support this. // return 10; // In percentage } NDIS_STATUS Hw11QuerySupportedDataRatesValue( _In_ PHW_MAC_CONTEXT HwMac, _Out_ PDOT11_SUPPORTED_DATA_RATES_VALUE_V2 Dot11SupportedDataRatesValue, _In_ BOOLEAN SelectedPhy ) { // // Determine the PHY that the user wants to query // if (SelectedPhy) return HwQuerySupportedDataRatesValue(HwMac->Hw, HwMac->SelectedPhyId, Dot11SupportedDataRatesValue ); else return HwQuerySupportedDataRatesValue(HwMac->Hw, HwMac->OperatingPhyId, Dot11SupportedDataRatesValue ); } ULONG Hw11QueryCCAModeSupported( _In_ PHW_MAC_CONTEXT HwMac, _In_ BOOLEAN SelectedPhy ) { // // Determine the PHY that the user wants to query // if (SelectedPhy) return HwQueryCCAModeSupported(HwMac->Hw, HwMac->SelectedPhyId ); else return HwQueryCCAModeSupported(HwMac->Hw, HwMac->OperatingPhyId ); } NDIS_STATUS Hw11QueryCountryString( _In_ PHW_MAC_CONTEXT HwMac, _Out_ PDOT11_COUNTRY_OR_REGION_STRING Dot11CountryString ) { UNREFERENCED_PARAMETER(HwMac); UNREFERENCED_PARAMETER(Dot11CountryString); return NDIS_STATUS_NOT_SUPPORTED; } ULONG Hw11QueryCurrentCCAMode( _In_ PHW_MAC_CONTEXT HwMac, _In_ BOOLEAN SelectedPhy ) { PNICPHYMIB phyMib; if (SelectedPhy) phyMib = HalGetPhyMIB(HwMac->Hw->Hal, HwMac->SelectedPhyId); else phyMib = HalGetPhyMIB(HwMac->Hw->Hal, HwMac->OperatingPhyId); if (phyMib->PhyType == dot11_phy_type_dsss || phyMib->PhyType == dot11_phy_type_hrdsss || phyMib->PhyType == dot11_phy_type_erp) { // NOTE: Hardcoded value is being used here return DOT11_CCA_MODE_CS_ONLY; } else { return 0; } } ULONG Hw11QueryCurrentFrequency( _In_ PHW_MAC_CONTEXT HwMac, _In_ BOOLEAN SelectedPhy ) { PHW_PHY_CONTEXT phyContext; PNICPHYMIB phyMib; if (SelectedPhy) { phyContext = &HwMac->PhyContext[HwMac->SelectedPhyId]; phyMib = HalGetPhyMIB(HwMac->Hw->Hal, HwMac->SelectedPhyId); } else { phyContext = &HwMac->PhyContext[HwMac->OperatingPhyId]; phyMib = HalGetPhyMIB(HwMac->Hw->Hal, HwMac->OperatingPhyId); } if (phyMib->PhyType == dot11_phy_type_ofdm) { return phyContext->Channel; } return 0; } ULONG Hw11QueryCurrentRegDomain( _In_ PHW_MAC_CONTEXT HwMac ) { return HwMac->CurrentRegDomain; } ULONG Hw11QueryCurrentTXPowerLevel( _In_ PHW_MAC_CONTEXT HwMac, _In_ BOOLEAN SelectedPhy ) { // // We dont throttle the TX power level per MAC context // if (SelectedPhy) { return HwQueryCurrentTXPowerLevel(HwMac->Hw, HwMac->SelectedPhyId); } else { return HwQueryCurrentTXPowerLevel(HwMac->Hw, HwMac->OperatingPhyId); } } DOT11_DIVERSITY_SUPPORT Hw11QueryDiversitySupport( _In_ PHW_MAC_CONTEXT HwMac, _In_ BOOLEAN SelectedPhy ) { if (SelectedPhy) return HwQueryDiversitySupport(HwMac->Hw, HwMac->SelectedPhyId); else return HwQueryDiversitySupport(HwMac->Hw, HwMac->OperatingPhyId); } ULONG Hw11QueryEDThreshold( _In_ PHW_MAC_CONTEXT HwMac, _In_ BOOLEAN SelectedPhy ) { if (SelectedPhy) return HwQueryEDThreshold(HwMac->Hw, HwMac->SelectedPhyId); else return HwQueryEDThreshold(HwMac->Hw, HwMac->OperatingPhyId); } BOOLEAN Hw11QueryErpPbccOptionEnabled( _In_ PHW_MAC_CONTEXT HwMac, _In_ BOOLEAN SelectedPhy ) { UNREFERENCED_PARAMETER(HwMac); UNREFERENCED_PARAMETER(SelectedPhy); // // Not implemented so its always false // return FALSE; } BOOLEAN Hw11QueryErpPbccOptionImplemented( _In_ PHW_MAC_CONTEXT HwMac, _In_ BOOLEAN SelectedPhy ) { UNREFERENCED_PARAMETER(HwMac); UNREFERENCED_PARAMETER(SelectedPhy); // // Not implemented // return FALSE; } ULONG Hw11QueryFragmentationThreshold( _In_ PHW_MAC_CONTEXT HwMac ) { return HwMac->FragmentationThreshold; } ULONG Hw11QueryFrequencyBandsSupported( _In_ PHW_MAC_CONTEXT HwMac, _In_ BOOLEAN SelectedPhy ) { if (SelectedPhy) return HwQueryFrequencyBandsSupported(HwMac->Hw, HwMac->SelectedPhyId); else return HwQueryFrequencyBandsSupported(HwMac->Hw, HwMac->OperatingPhyId); } ULONG Hw11QueryLongRetryLimit( _In_ PHW_MAC_CONTEXT HwMac ) { return HwMac->LongRetryLimit; } ULONG Hw11QueryMaxReceiveLifetime( _In_ PHW Hw ) { return Hw->MacState.MaxReceiveLifetime; } ULONG Hw11QueryMaxTransmitMSDULifetime( _In_ PHW Hw ) { return Hw->MacState.MaxTransmitMSDULifetime; } BOOLEAN Hw11QueryMultiDomainCapabilityEnabled( _In_ PHW_MAC_CONTEXT HwMac ) { UNREFERENCED_PARAMETER(HwMac); // // Not implemented so not enabled // return FALSE; } BOOLEAN Hw11QueryMultiDomainCapabilityImplemented( _In_ PHW_MAC_CONTEXT HwMac ) { return HwQueryMultiDomainCapabilityImplemented(HwMac->Hw); } ULONG Hw11QueryRTSThreshold( _In_ PHW_MAC_CONTEXT HwMac ) { return HwMac->RTSThreshold; } ULONG Hw11QueryShortRetryLimit( _In_ PHW_MAC_CONTEXT HwMac ) { return HwMac->ShortRetryLimit; } DOT11_TEMP_TYPE Hw11QueryTempType( _In_ PHW_MAC_CONTEXT HwMac, _In_ BOOLEAN SelectedPhy ) { if (SelectedPhy) return HwQueryTempType(HwMac->Hw, HwMac->SelectedPhyId); else return HwQueryTempType(HwMac->Hw, HwMac->OperatingPhyId); } ULONG Hw11QueryPacketFilter( _In_ PHW_MAC_CONTEXT HwMac ) { return HwMac->PacketFilter; } DOT11_CIPHER_ALGORITHM Hw11QueryUnicastCipher( _In_ PHW_MAC_CONTEXT HwMac ) { return HwMac->UnicastCipher; } DOT11_CIPHER_ALGORITHM Hw11QueryMulticastCipher( _In_ PHW_MAC_CONTEXT HwMac ) { return HwMac->MulticastCipher; } DOT11_AUTH_ALGORITHM Hw11QueryAuthentication( _In_ PHW_MAC_CONTEXT HwMac ) { return HwMac->AuthAlgorithm; } UCHAR Hw11QueryDefaultKeyMask( _In_ PHW_MAC_CONTEXT HwMac ) { UCHAR validKeyMask = 0; // Since the NicKeyIndex can change, acquire the lock HW_ACQUIRE_HARDWARE_LOCK(HwMac->Hw, FALSE); validKeyMask = HwQueryDefaultKeyMask(HwMac); HW_RELEASE_HARDWARE_LOCK(HwMac->Hw, FALSE); return validKeyMask; } DOT11_BSS_TYPE Hw11QueryCurrentBSSType( _In_ PHW_MAC_CONTEXT HwMac ) { return HwMac->BssType; } NDIS_STATUS Hw11SetLookahead( _In_ PHW_MAC_CONTEXT HwMac, _In_ ULONG Lookahead, _In_ BOOLEAN fProgramHardware ) { UNREFERENCED_PARAMETER(HwMac); UNREFERENCED_PARAMETER(fProgramHardware); if (Lookahead > (DOT11_MIN_PDU_SIZE - (sizeof(DOT11_DATA_SHORT_HEADER) + 12))) { return NDIS_STATUS_NOT_SUPPORTED; } // Else this is the default lookahead that we have return NDIS_STATUS_SUCCESS; } NDIS_STATUS Hw11SetInterruptModerationSettings( _In_ PHW Hw, _In_ PNDIS_INTERRUPT_MODERATION_PARAMETERS IntModParams ) { UNREFERENCED_PARAMETER(Hw); UNREFERENCED_PARAMETER(IntModParams); // Interrupt moderation not supported return NDIS_STATUS_INVALID_DATA; } NDIS_STATUS Hw11SetLinkParameters( _In_ PHW_MAC_CONTEXT HwMac, _In_ PNDIS_LINK_PARAMETERS LinkParams, _In_ BOOLEAN fProgramHardware ) { PDOT11_RATE_SET myRateSet; ULONG index; UCHAR dataRate; UNREFERENCED_PARAMETER(fProgramHardware); // // We dont program the hardware. So the fProgramHardware flag is not // relevant // if (LinkParams->RcvLinkSpeed != LinkParams->XmitLinkSpeed) { // For us the TX and RX rates must be the same return NDIS_STATUS_INVALID_DATA; } // If the rate specified by the user is valid, we are going to attempt to // transmit at that rate (even if it may not be acceptable to the AP) dataRate = HwLinkSpeedToDataRate(LinkParams->XmitLinkSpeed); myRateSet = &HwMac->PhyContext[HwMac->OperatingPhyId].OperationalRateSet; // Is this a supported data rate? for (index = 0; index < myRateSet->uRateSetLength; index++) { if (myRateSet->ucRateSet[index] == dataRate) { HwMac->DefaultTXDataRate = myRateSet->ucRateSet[index]; MpTrace(COMP_ASSOC, DBG_LOUD, ("TX Data rate: %d\n", myRateSet->ucRateSet[index])); // // Indicate NDIS_STATUS_LINK_STATE to inform the OS about the new // link speed // HwIndicateLinkSpeed(HwMac, HwMac->DefaultTXDataRate); return NDIS_STATUS_SUCCESS; } } // Unsupported data rate return NDIS_STATUS_INVALID_DATA; } NDIS_STATUS Hw11SetMulticastList( _In_ PHW_MAC_CONTEXT HwMac, _In_ PVOID AddressBuffer, _In_ ULONG AddressBufferLength, _In_ BOOLEAN fProgramHardware ) { NDIS_STATUS ndisStatus; if(AddressBufferLength > 0) { if (AddressBufferLength > (HW11_MAX_MULTICAST_LIST_SIZE * DOT11_ADDRESS_SIZE)) { MpTrace(COMP_OID, DBG_LOUD, ("Too many multicast addresses being set\n")); return NDIS_STATUS_MULTICAST_FULL; } // // Save address list // HwMac->MulticastAddressCount = (UCHAR)(AddressBufferLength / DOT11_ADDRESS_SIZE); NdisMoveMemory(HwMac->MulticastAddressList, AddressBuffer, AddressBufferLength); if (fProgramHardware) { // // Set the multicast address on the NIC // if (HwMac->PacketFilter & (NDIS_PACKET_TYPE_ALL_MULTICAST | NDIS_PACKET_TYPE_802_11_ALL_MULTICAST_MGMT)) { HwMac->AcceptAllMulticast = TRUE; ndisStatus = HwUpdateMulticastAddressList(HwMac->Hw, HwMac ); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_OID, DBG_LOUD, ("Unable to set multicast address list\n")); return ndisStatus; } } else if (HwMac->PacketFilter & (NDIS_PACKET_TYPE_MULTICAST | NDIS_PACKET_TYPE_802_11_MULTICAST_MGMT)) { HwMac->AcceptAllMulticast = FALSE; ndisStatus = HwUpdateMulticastAddressList(HwMac->Hw, HwMac ); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_OID, DBG_LOUD, ("Unable to set multicast address list\n")); return ndisStatus; } } } } else { HwMac->MulticastAddressCount = 0; // We dont program the hardware for this } return NDIS_STATUS_SUCCESS; } NDIS_STATUS Hw11SetOperationalRateSet( _In_ PHW_MAC_CONTEXT HwMac, _In_ PDOT11_RATE_SET Dot11RateSet, _In_ BOOLEAN SelectedPhy, _In_ BOOLEAN fProgramHardware ) { ULONG phyId; PHW_PHY_CONTEXT phyContext; NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; // We dont program the operational rate set on the HAL. This set is maintained in // software & we use it internally to determine the rates to use for transmission set UNREFERENCED_PARAMETER(fProgramHardware); // // Determine the PHY that the user wants to query // if (SelectedPhy) phyId = HwMac->SelectedPhyId; else phyId = HwMac->OperatingPhyId; // Validate the rate set is compatible with our hardware ndisStatus = Hw11ValidateOperationalRates(HwMac, phyId, Dot11RateSet->ucRateSet, Dot11RateSet->uRateSetLength); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_MISC, DBG_SERIOUS, ("Invalid data in operational rate set request\n")); return ndisStatus; } // Save the rate set on the MAC phy context phyContext = &HwMac->PhyContext[phyId]; // // Copy the rates into the phy context for this MAC // HW_ACQUIRE_HARDWARE_LOCK(HwMac->Hw, FALSE); NdisMoveMemory(&phyContext->OperationalRateSet, Dot11RateSet, sizeof(DOT11_RATE_SET)); // // Note that we dont change the rate set we will use with our current association // HW_RELEASE_HARDWARE_LOCK(HwMac->Hw, FALSE); return NDIS_STATUS_SUCCESS; } NDIS_STATUS Hw11SetDefaultKeyId( _In_ PHW_MAC_CONTEXT HwMac, _In_ ULONG KeyId, _In_ BOOLEAN fProgramHardware ) { // Check for valid default key ID if (KeyId >= DOT11_MAX_NUM_DEFAULT_KEY) { return NDIS_STATUS_INVALID_DATA; } // Save the default key HwMac->DefaultKeyIndex = (UCHAR)KeyId; if (fProgramHardware) { HwSetDefaultKeyId(HwMac->Hw, HwMac, KeyId); } return NDIS_STATUS_SUCCESS; } NDIS_STATUS Hw11SetSelectedPhyId( _In_ PHW_MAC_CONTEXT HwMac, _In_ ULONG PhyId, _In_ BOOLEAN fProgramHardware ) { PDOT11_SUPPORTED_PHY_TYPES supportedPhyTypes = HalGetSupportedPhyTypes(HwMac->Hw->Hal); UNREFERENCED_PARAMETER(fProgramHardware); if (PhyId >= supportedPhyTypes->uNumOfEntries) { return NDIS_STATUS_INVALID_DATA; } else { HwMac->SelectedPhyId = PhyId; // // We dont need to do anything on the NIC when the Phy Id is selected // } return NDIS_STATUS_SUCCESS; } NDIS_STATUS Hw11SetSafeModeOption( _In_ PHW_MAC_CONTEXT HwMac, _In_ BOOLEAN SafeModeEnabled, _In_ BOOLEAN fProgramHardware ) { if (SafeModeEnabled) { // // We would program the hardware to not do any encryption (both unicast and multicast ciphers) // Hw11SetCipher(HwMac, TRUE, DOT11_CIPHER_ALGO_NONE, fProgramHardware); Hw11SetCipher(HwMac, FALSE, DOT11_CIPHER_ALGO_NONE, fProgramHardware); } else { // // Cipher would have already been set when safe mode is configured // (enabled or disabled) // } // Program the hardware HwMac->Hw->MacState.SafeModeEnabled = SafeModeEnabled; HalEnableSafeMode(HwMac->Hw->Hal, SafeModeEnabled); return NDIS_STATUS_SUCCESS; } NDIS_STATUS HwOidChannelSwitchComplete( _In_ PHW Hw, _In_ PHW_MAC_CONTEXT MacContext, _In_ PVOID Data ) { VNIC11_GENERIC_CALLBACK_FUNC completionHandler; MpTrace(COMP_SCAN, DBG_LOUD, ("Oid channel switched\n")); UNREFERENCED_PARAMETER(Hw); completionHandler = MacContext->OidChannelSwitchCallback; MacContext->OidChannelSwitchCallback = NULL; MPASSERT(completionHandler != NULL); // Invoke the completion handler completionHandler(MacContext->VNic, MacContext->ChannelSwitchContext, Data); return NDIS_STATUS_SUCCESS; } NDIS_STATUS Hw11SetChannel( _In_ PHW_MAC_CONTEXT HwMac, _In_ ULONG ChannelOrFrequency, _In_ ULONG PhyId, _In_ BOOLEAN SwitchPhy, _In_ VNIC11_GENERIC_CALLBACK_FUNC CompletionHandler, _In_ PVOID ChannelSwitchContext ) { PHW_PHY_CONTEXT phyContext; NDIS_STATUS ndisStatus; MPASSERT(HwMac->OidChannelSwitchCallback == NULL); // // Validate that this channel set is OK // ndisStatus = HwValidateChannel(HwMac->Hw, PhyId, (UCHAR)ChannelOrFrequency); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_MISC, DBG_SERIOUS, ("Invalid phy(%d) & channel/frequency(%d) set requested\n", PhyId, ChannelOrFrequency)); // Maintain asynchronous semantics for this API even in case of failure CompletionHandler(HwMac->VNic, ChannelSwitchContext, &ndisStatus); ndisStatus = NDIS_STATUS_PENDING; return ndisStatus; } phyContext = &HwMac->PhyContext[PhyId]; phyContext->Channel = (UCHAR)ChannelOrFrequency; // If this is the current PHY programmed on the hardware or the caller has requested a phy set, set it if ((PhyId == HwMac->OperatingPhyId) || (SwitchPhy)) { // If PhyId != HwMac->OperationPhyId, change it to be in sync if (PhyId != HwMac->OperatingPhyId) { ndisStatus = Hw11SetOperatingPhyId(HwMac, PhyId, FALSE); MPASSERT(ndisStatus == NDIS_STATUS_SUCCESS); // Software only state change } HwMac->OidChannelSwitchCallback = CompletionHandler; HwMac->ChannelSwitchContext = ChannelSwitchContext; return HwProgramPhy(HwMac->Hw, HwMac, PhyId, phyContext, HwOidChannelSwitchComplete ); } else { // Maintain asynchronous semantics for this API even in case of failure CompletionHandler(HwMac->VNic, ChannelSwitchContext, &ndisStatus); // This really translates to ndisStatus = NDIS_STATUS_PENDING; } return NDIS_STATUS_SUCCESS; } NDIS_STATUS Hw11SetOperatingPhyId( _In_ PHW_MAC_CONTEXT HwMac, _In_ ULONG PhyId, _In_ BOOLEAN fProgramHardware ) { HwMac->OperatingPhyId = PhyId; // Change the rates to be appropriate for this phy HwMac->DefaultTXMgmtRate = HalGetBeaconRate(HwMac->Hw->Hal, PhyId); if (fProgramHardware) { return HwProgramPhy(HwMac->Hw, HwMac, PhyId, &HwMac->PhyContext[PhyId], NULL ); } return NDIS_STATUS_SUCCESS; } VOID Hw11DeleteNonPersistentKey( _In_ PHW_MAC_CONTEXT HwMac, _In_ BOOLEAN fProgramHardware ) { PHW_KEY_ENTRY keyEntry; PHW_PEER_NODE peerNode; UCHAR index, defaultIndex; // // Protect the send path from a key delete // HW_ACQUIRE_HARDWARE_LOCK(HwMac->Hw, FALSE); // // Go through the key table, invalidate any key which is not persistent. // for (index = 0; index < HW11_KEY_TABLE_SIZE; index++) { keyEntry = &HwMac->KeyTable[index]; if (keyEntry->Key.Valid && !keyEntry->Key.Persistent) { // // Was valid/non-persistent key, remove it // HwDeleteKeyFromContext(HwMac, index, fProgramHardware); } } // // Invalidate any per-STA key which is not persistent. // for (index = 0; index < HW11_PEER_TABLE_SIZE; index++) { peerNode = &HwMac->PeerTable[index]; if (peerNode->Valid) { for (defaultIndex = 0; defaultIndex < DOT11_MAX_NUM_DEFAULT_KEY; defaultIndex++) { keyEntry = &peerNode->PrivateKeyTable[defaultIndex]; if (keyEntry->Key.Valid && !keyEntry->Key.Persistent) { // We dont have to delete it from the hardware (that is done // above). Here we just invalidate it HwFreeKey(keyEntry); } } } } HW_RELEASE_HARDWARE_LOCK(HwMac->Hw, FALSE); } VOID Hw11DeleteNonPersistentMappingKey( _In_ PHW_MAC_CONTEXT HwMac, _In_reads_bytes_(DOT11_ADDRESS_SIZE) DOT11_MAC_ADDRESS MacAddr, _In_ BOOLEAN fProgramHardware ) { PHW_KEY_ENTRY keyEntry; PHW_PEER_NODE peerNode; UCHAR index, defaultIndex; // // Protect the send path from a key delete // HW_ACQUIRE_HARDWARE_LOCK(HwMac->Hw, FALSE); // // Go through the key mapping table, invalidate any key which is not persistent. // for (index = DOT11_MAX_NUM_DEFAULT_KEY; index < HW11_KEY_TABLE_SIZE; index++) { keyEntry = &HwMac->KeyTable[index]; if (keyEntry->Key.Valid && !keyEntry->Key.Persistent) { if (MP_COMPARE_MAC_ADDRESS(MacAddr, keyEntry->Key.MacAddr)) { // // Was valid/non-persistent key, remove it // HwDeleteKeyFromContext(HwMac, index, fProgramHardware); } } } // // Invalidate any per-STA key which is not persistent. // for (index = 0; index < HW11_PEER_TABLE_SIZE; index++) { peerNode = &HwMac->PeerTable[index]; if (peerNode->Valid) { if (MP_COMPARE_MAC_ADDRESS(MacAddr, peerNode->PeerMac)) { for (defaultIndex = 0; defaultIndex < DOT11_MAX_NUM_DEFAULT_KEY; defaultIndex++) { keyEntry = &peerNode->PrivateKeyTable[defaultIndex]; if (keyEntry->Key.Valid && !keyEntry->Key.Persistent) { // We dont have to delete it from the hardware (that is done // above). Here we just invalidate it HwFreeKey(keyEntry); } } } } } HW_RELEASE_HARDWARE_LOCK(HwMac->Hw, FALSE); } NDIS_STATUS Hw11SetPacketFilter( _In_ PHW_MAC_CONTEXT HwMac, _In_ ULONG PacketFilter, _In_ BOOLEAN fProgramHardware ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; do { HwMac->PacketFilter = PacketFilter; if (fProgramHardware) { ndisStatus = HwUpdatePacketFilter(HwMac->Hw, HwMac); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_OID, DBG_LOUD, ("Unable to set packet filter to %d\n", PacketFilter)); break; } // Set the multicast address if (PacketFilter & (NDIS_PACKET_TYPE_ALL_MULTICAST | NDIS_PACKET_TYPE_802_11_ALL_MULTICAST_MGMT)) { HwMac->AcceptAllMulticast = TRUE; ndisStatus = HwUpdateMulticastAddressList(HwMac->Hw, HwMac ); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_OID, DBG_LOUD, ("Unable to set multicast address list\n")); break; } } else if (PacketFilter & (NDIS_PACKET_TYPE_MULTICAST | NDIS_PACKET_TYPE_802_11_MULTICAST_MGMT)) { HwMac->AcceptAllMulticast = FALSE; ndisStatus = HwUpdateMulticastAddressList(HwMac->Hw, HwMac ); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_OID, DBG_LOUD, ("Unable to set multicast address list\n")); break; } } } } while (FALSE); return ndisStatus; } NDIS_STATUS Hw11SetATIMWindow( _In_ PHW_MAC_CONTEXT HwMac, _In_ ULONG Value, _In_ BOOLEAN fProgramHardware ) { HwMac->AtimWindow = HW_LIMIT_BEACON_PERIOD(Value); // // If we are supposed to program the hardware, let that happen // if (fProgramHardware) return HwSetATIMWindow(HwMac->Hw, Value); return NDIS_STATUS_SUCCESS; } VOID Hw11SetCipher( _In_ PHW_MAC_CONTEXT HwMac, _In_ BOOLEAN IsUnicast, _In_ DOT11_CIPHER_ALGORITHM AlgoId, _In_ BOOLEAN fProgramHardware ) { /*** Valid combinations of multicast/unicast cipher algorithms Multicast\Unicast WEP WEP40 WEP104 TKIP CCMP NONE WEP Y WEP40 Y* Y Y WEP104 Y* Y Y TKIP Y Y CCMP Y NONE Y Y*: Not currently used by Microsoft 802.11 Security module but can be supported by vendors if they want to connect to WPA AP that does not support pairwise keys. ***/ // // Update the encryption algorithm // if (IsUnicast) { // // Protect the send path from a key delete // HW_ACQUIRE_HARDWARE_LOCK(HwMac->Hw, FALSE); // // When set unicast cipher, also clear all keys. // HwDeleteAllKeysFromContext(HwMac, fProgramHardware); HwMac->UnicastCipher = AlgoId; HW_RELEASE_HARDWARE_LOCK(HwMac->Hw, FALSE); if (fProgramHardware) { HwUpdateUnicastCipher(HwMac->Hw, HwMac); } } else { // // Save the multicast cipher in our software state // HwMac->MulticastCipher = AlgoId; } } UCHAR Hw11SelectTXDataRate( _In_ PHW_MAC_CONTEXT HwMac, _In_ PDOT11_RATE_SET PeerRateSet, _In_ ULONG LinkQuality, _In_ BOOLEAN fProgramHardware ) { UNREFERENCED_PARAMETER(fProgramHardware); return (UCHAR)HwSelectTXDataRate(HwMac, PeerRateSet, LinkQuality); } NDIS_STATUS Hw11SetDefaultKey( _In_ PHW_MAC_CONTEXT HwMac, _In_reads_bytes_(DOT11_ADDRESS_SIZE) DOT11_MAC_ADDRESS MacAddr, _In_ ULONG KeyID, _In_ BOOLEAN Persistent, _In_ DOT11_CIPHER_ALGORITHM AlgoId, _In_ ULONG KeyLength, _In_reads_bytes_(KeyLength) PUCHAR KeyValue, _In_ BOOLEAN fProgramHardware ) { // // Note that both this function and other functions accessing key table are called // as a result of OID set. As such, no locking is needed since NDIS serializes // the OID set operation. If this premise is no longer valid, locking will // be needed. // if (KeyID >= DOT11_MAX_NUM_DEFAULT_KEY) return NDIS_STATUS_INVALID_DATA; if ((HwMac->BssType == dot11_BSS_type_independent) && (HwMac->AuthAlgorithm == DOT11_AUTH_ALGO_RSNA_PSK)) { // // For WPA2 Adhoc we store default keys in the peer node because we dont // want to program this to the H/W // return HwSetSoftwareDefaultKeyInContext(HwMac, MacAddr, (UCHAR)KeyID, Persistent, AlgoId, KeyLength, KeyValue ); } else { // // Save the new default key in the key table. // return HwSetDefaultKeyInContext(HwMac, MacAddr, (UCHAR)KeyID, Persistent, AlgoId, KeyLength, KeyValue, fProgramHardware ); } } NDIS_STATUS Hw11SetKeyMappingKey( _In_ PHW_MAC_CONTEXT HwMac, _In_reads_bytes_(DOT11_ADDRESS_SIZE) DOT11_MAC_ADDRESS MacAddr, _In_ DOT11_DIRECTION Direction, _In_ BOOLEAN Persistent, _In_ DOT11_CIPHER_ALGORITHM AlgoId, _In_ ULONG KeyLength, _In_reads_bytes_(KeyLength) PUCHAR KeyValue, _In_ BOOLEAN fProgramHardware ) { return HwSetKeyMappingKeyInContext(HwMac, MacAddr, Direction, Persistent, AlgoId, KeyLength, KeyValue, fProgramHardware ); } NDIS_STATUS Hw11SetOperationMode( _In_ PHW_MAC_CONTEXT HwMac, _In_ PDOT11_CURRENT_OPERATION_MODE Dot11CurrentOperationMode, _In_ BOOLEAN fProgramHardware ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; // // Save the value locally // HwMac->CurrentOpMode = Dot11CurrentOperationMode->uCurrentOpMode; HwMac->Hw->MacState.NetmonModeEnabled = FALSE; if (fProgramHardware) { ndisStatus = HwUpdateOperationMode(HwMac->Hw, HwMac); if (Dot11CurrentOperationMode->uCurrentOpMode == DOT11_OPERATION_MODE_NETWORK_MONITOR) { // // Turn off encryption in the hardware // HwMac->UnicastCipher = DOT11_CIPHER_ALGO_NONE; HwUpdateUnicastCipher(HwMac->Hw, HwMac); } } return ndisStatus; } NDIS_STATUS Hw11SetCurrentBSSType( _In_ PHW_MAC_CONTEXT HwMac, _In_ DOT11_BSS_TYPE Type, _In_ BOOLEAN fProgramHardware ) { // // Save the value locally // HwMac->BssType = Type; if (fProgramHardware) { return HwUpdateBSSType(HwMac->Hw, HwMac); } return NDIS_STATUS_SUCCESS; } NDIS_STATUS Hw11SetPowerMgmtMode( _In_ PHW_MAC_CONTEXT HwMac, _In_ PDOT11_POWER_MGMT_MODE PMMode, _In_ BOOLEAN fProgramHardware ) { NdisMoveMemory(&HwMac->PowerMgmtMode, PMMode, sizeof(DOT11_POWER_MGMT_MODE)); if (fProgramHardware) { return HwSetPowerMgmtMode(HwMac->Hw, HwMac, PMMode); } return NDIS_STATUS_SUCCESS; } VOID Hw11SetCTSToSelfOption( _In_ PHW_MAC_CONTEXT HwMac, _In_ BOOLEAN Enable, _In_ BOOLEAN fProgramHardware ) { UNREFERENCED_PARAMETER(fProgramHardware); // // We just set it here. The send routines would pick it up // when sending packets for this node // HwMac->CTSToSelfEnabled = Enable; } NDIS_STATUS Hw11SetDesiredPhyIdList( _In_ PHW_MAC_CONTEXT HwMac, _In_ PULONG PhyIDList, _In_ ULONG PhyIDCount, _In_ BOOLEAN fProgramHardware ) { ULONG phyId; if (PhyIDCount < 1) return NDIS_STATUS_INVALID_DATA; if (PhyIDList[0] == DOT11_PHY_ID_ANY) return NDIS_STATUS_SUCCESS; phyId = PhyIDList[0]; if (HwMac->CurrentOpMode == DOT11_OPERATION_MODE_NETWORK_MONITOR) { // // In netmon mode, we should be active // MPASSERT(fProgramHardware == TRUE); // // Immediately switch to the first PHY in the list // fProgramHardware = TRUE; } else { // // Automatically set the PHY to the first PHY in the list. This // can change later // if (phyId == HwMac->OperatingPhyId) { // // Already set, dont need to set again // fProgramHardware = FALSE; } } HwMac->OperatingPhyId = phyId; if (fProgramHardware) { // // Set the operating phy ID on the hardware // return HwProgramPhy(HwMac->Hw, HwMac, phyId, &HwMac->PhyContext[phyId], NULL ); } return NDIS_STATUS_SUCCESS; } NDIS_STATUS Hw11SetAuthentication( _In_ PHW_MAC_CONTEXT HwMac, _In_ DOT11_AUTH_ALGORITHM AlgoId, _In_ BOOLEAN fProgramHardware ) { UNREFERENCED_PARAMETER(fProgramHardware); HwMac->AuthAlgorithm = AlgoId; return NDIS_STATUS_SUCCESS; } NDIS_STATUS Hw11SetNicPowerState( _In_ PHW_MAC_CONTEXT HwMac, _In_ BOOLEAN PowerState, _In_ BOOLEAN SelectedPhy, _In_ BOOLEAN fProgramHardware ) { UNREFERENCED_PARAMETER(fProgramHardware); // When this OID is submitted we have to do it immediately // // Determine the PHY that the user wants to query // if (SelectedPhy) return HwSetNicPowerState(HwMac->Hw, HwMac->SelectedPhyId, PowerState); else return HwSetNicPowerState(HwMac->Hw, HwMac->OperatingPhyId, PowerState); } NDIS_STATUS Hw11SetBeaconPeriod( _In_ PHW_MAC_CONTEXT HwMac, _In_ ULONG BeaconPeriod, _In_ BOOLEAN fProgramHardware ) { UNREFERENCED_PARAMETER(fProgramHardware); // Update our local value HwMac->BeaconPeriod = BeaconPeriod; return NDIS_STATUS_SUCCESS; } NDIS_STATUS Hw11SetFragmentationThreshold( _In_ PHW_MAC_CONTEXT HwMac, _In_ ULONG FragmentationThreshold, _In_ BOOLEAN fProgramHardware ) { if(FragmentationThreshold > 2346) HwMac->FragmentationThreshold = 2346; else if(FragmentationThreshold < 256) HwMac->FragmentationThreshold = 256; else HwMac->FragmentationThreshold = FragmentationThreshold; // We dont support fragmentation, so we dont UNREFERENCED_PARAMETER(fProgramHardware); return NDIS_STATUS_SUCCESS; } NDIS_STATUS Hw11SetMultiDomainCapabilityEnabled( _In_ PHW_MAC_CONTEXT HwMac, _In_ BOOLEAN MultiDomainCapabilityEnabled, _In_ BOOLEAN fProgramHardware ) { UNREFERENCED_PARAMETER(HwMac); UNREFERENCED_PARAMETER(MultiDomainCapabilityEnabled); UNREFERENCED_PARAMETER(fProgramHardware); // // Multidomain capability is not supported // return NDIS_STATUS_NOT_SUPPORTED; } NDIS_STATUS Hw11SetRTSThreshold( _In_ PHW_MAC_CONTEXT HwMac, _In_ ULONG RTSThreshold, _In_ BOOLEAN fProgramHardware ) { UNREFERENCED_PARAMETER(fProgramHardware); // Update our local value if(RTSThreshold > 2347) HwMac->RTSThreshold = 2347; else HwMac->RTSThreshold = RTSThreshold; return NDIS_STATUS_SUCCESS; } NDIS_STATUS Hw11CanTransitionPower( _In_ PHW Hw, _In_ NDIS_DEVICE_POWER_STATE NewDevicePowerState ) { // // Transition is always possible. If ever a need occurs for the driver // to veto a power transtion, we will do it here. // UNREFERENCED_PARAMETER(Hw); UNREFERENCED_PARAMETER(NewDevicePowerState); return NDIS_STATUS_SUCCESS; } // Called at device IRQL (via SynchronizeWithInterrupt) _Function_class_(MINIPORT_SYNCHRONIZE_INTERRUPT) VOID HwSetHardwarePowerState( _In_ PHW Hw ) { NDIS_DEVICE_POWER_STATE devicePowerState = Hw->NextDevicePowerState; // // When coming out of low power, we set the bit before resuming the hardware. // When going to low power we set the bit after resuming the hardware. This is // because interrupts can be enabled (or disabled) before the call returns and // HWIsr may reject it if it thinks the hardware is still in low power // if (devicePowerState == NdisDeviceStateD0) { HW_CLEAR_ADAPTER_STATUS(Hw, HW_ADAPTER_IN_LOW_POWER); } MpTrace(COMP_POWER, DBG_LOUD, ("Setting device to power state D%d\n", devicePowerState-1)); HalSetDevicePowerState(Hw->Hal, devicePowerState); // If going to low power, set the low power bit if (devicePowerState != NdisDeviceStateD0) { HW_SET_ADAPTER_STATUS(Hw, HW_ADAPTER_IN_LOW_POWER); } } NDIS_STATUS Hw11SetPower( _In_ PHW Hw, _In_ NDIS_DEVICE_POWER_STATE NewDevicePowerState ) { HW_HAL_RESET_PARAMETERS resetParams; ULONG size; NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; UCHAR buffer[HW11_PCI_CONFIG_BUFFER_LENGTH]; PPCI_COMMON_CONFIG pciConfig = (PPCI_COMMON_CONFIG) buffer; // // Hardware power state change must be synchronized with Interrupt // Hw->NextDevicePowerState = NewDevicePowerState; if (NewDevicePowerState == NdisDeviceStateD0) { // // Some BIOS modify the PCI configuration space on resume. // We go read that again // do { // Load the PCI config information into our local buffer size = NdisMGetBusData(Hw->MiniportAdapterHandle, PCI_WHICHSPACE_CONFIG, FIELD_OFFSET(PCI_COMMON_CONFIG,VendorID), pciConfig, HW11_PCI_CONFIG_BUFFER_LENGTH ); if (size != HW11_PCI_CONFIG_BUFFER_LENGTH) { MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("NdisReadPciSlotInformation failed. Number of bytes of PCI config info returned is %d\n", size)); ndisStatus = NDIS_STATUS_ADAPTER_NOT_FOUND; break; } ndisStatus = HalParsePciConfiguration(Hw->Hal, buffer, size); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("HalParsePciConfiguration failed. Status = 0x%08x\n", ndisStatus)); break; } }while (FALSE); } else { // If radio is OFF, turn it on for now if (Hw->PhyState.Debug_SoftwareRadioOff) HalSetRFPowerState(Hw->Hal, RF_ON); } NdisMSynchronizeWithInterruptEx( Hw->InterruptHandle, 0, (MINIPORT_SYNCHRONIZE_INTERRUPT_HANDLER)HwSetHardwarePowerState, (PVOID)Hw ); if (NewDevicePowerState == NdisDeviceStateD0) { // // Do an internal reset to start fresh // NdisZeroMemory(&resetParams, sizeof(HW_HAL_RESET_PARAMETERS)); resetParams.FullReset = TRUE; HwResetHAL(Hw, &resetParams, FALSE); if (Hw->PhyState.Debug_SoftwareRadioOff) HalSetRFPowerState(Hw->Hal, RF_OFF); } return NDIS_STATUS_SUCCESS; }
Our Services
-
What our customers say about us?
Read our customer testimonials to find out why our clients keep returning for their projects.
View Testimonials