Пример #1
0
NDIS_STATUS
Hw11FindNic(
    __in  PHW                     Hw,
    __out NDIS_ERROR_CODE*        ErrorCode,
    __out PULONG                  ErrorValue
    )
{
    ULONG                       size;
    NDIS_STATUS                 ndisStatus = NDIS_STATUS_SUCCESS;
    UCHAR                       buffer[HW11_PCI_CONFIG_BUFFER_LENGTH];
    PPCI_COMMON_CONFIG          pciConfig = (PPCI_COMMON_CONFIG) buffer;

    //
    // Make sure adapter is present on the bus.
    // If present,verify the PCI configuration values.
    //

    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));

            *ErrorCode = NDIS_ERROR_CODE_ADAPTER_NOT_FOUND;
            *ErrorValue = ERRLOG_READ_PCI_SLOT_FAILED;
            ndisStatus = NDIS_STATUS_ADAPTER_NOT_FOUND;
            break;
        }

        //
        // We have read the hardware ID, etc. Create the appropriate HAL
        // object that corresponds to our hardware. This allocates the HAL
        // structure and populates the HAL function pointers
        //
#ifdef EXPORT_DRIVER_HAL
        // Invoke the export driver
        ndisStatus = HalDriverCreateWLANHal(Hw->MiniportAdapterHandle, 
                        pciConfig->VendorID, 
                        pciConfig->DeviceID, 
                        pciConfig->RevisionID, 
                        &Hw->Hal
                        );

#else
        // Invoke the HAL library
        ndisStatus = HalCreateWLANHal(Hw->MiniportAdapterHandle, 
                        pciConfig->VendorID, 
                        pciConfig->DeviceID, 
                        pciConfig->RevisionID, 
                        &Hw->Hal
                        );
#endif
        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            MpTrace(COMP_INIT_PNP,
                    DBG_SERIOUS,
                    ("HalCreateWLANHal failed. Status = 0x%08x\n", ndisStatus));

            *ErrorCode = NDIS_ERROR_CODE_ADAPTER_NOT_FOUND;
            *ErrorValue = ERRLOG_VENDOR_DEVICE_MISMATCH;

            break;
        }

        //
        // Let the HAL layer read the registry. This may depend on the NIC
        // and hence we do this here after we have found the NIC and create the HAL
        // and not during the first Hw11ReadRegistryConfiguration call
        //
        ndisStatus = HalReadRegistryConfiguration(Hw->Hal);
        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            // Read registry should only fail for test purposes. If registry data is invalid the 
            // driver should load the defaults and NOT fail driver initialize        
            MpTrace(COMP_INIT_PNP,
                    DBG_SERIOUS,
                    ("HalReadRegistryConfiguration failed. Status = 0x%08x\n", ndisStatus));

            MPASSERT(ndisStatus == NDIS_STATUS_RESOURCES);
        }

        //
        // Allow the HAL to look at PCI config information. This may also modify the
        // HAL
        //
        ndisStatus = HalParsePciConfiguration(Hw->Hal, buffer, size);    
        if (ndisStatus != NDIS_STATUS_SUCCESS) 
        {
            MpTrace(COMP_INIT_PNP, 
                    DBG_SERIOUS, 
                    ("HalParsePciConfiguration failed. Status = 0x%08x\n", ndisStatus));

            *ErrorCode = NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION;
            *ErrorValue = ERRLOG_INVALID_PCI_CONFIGURATION;

            break;                
        }

    }while (FALSE);

    if (ndisStatus != NDIS_STATUS_SUCCESS)
    {
        // The only thing done so far is create the WLAN hal
        if (Hw->Hal != NULL)
        {
            HalFreeNic(Hw->Hal);
            Hw->Hal = NULL;
        }

    }
    
    return ndisStatus;
}
Пример #2
0
USHORT
HwSelectTXDataRate(
    __in  PHW_MAC_CONTEXT         HwMac,
    __in  PDOT11_RATE_SET         RemoteRateSet,
    __in  ULONG                   LinkQuality
    )
{
    PDOT11_RATE_SET             operationalRateSet;
    PDOT11_RATE_SET             activeRateSet;
    ULONG                       indexLocalRates;
    ULONG                       indexRemoteRates;
    USHORT                      maximumRate;
    OP_RATE_CHANGE_NOTIFICATION rateNotification;

    // The active rate set structure needs to be protected
    HW_ACQUIRE_HARDWARE_LOCK(HwMac->Hw, FALSE);
    
    //
    // Select the best rate supported by both AP and us. 
    //
    operationalRateSet = &(HwMac->PhyContext[HwMac->OperatingPhyId].OperationalRateSet);
    activeRateSet = &(HwMac->PhyContext[HwMac->OperatingPhyId].ActiveRateSet);

    activeRateSet->uRateSetLength = 0;
    
    //
    // We merge the rates from the AP and the client to create the 
    // currently active data rates table
    //
    for (indexLocalRates = 0; indexLocalRates < operationalRateSet->uRateSetLength; indexLocalRates++) 
    {
        for (indexRemoteRates = 0; indexRemoteRates < RemoteRateSet->uRateSetLength; indexRemoteRates++)
        {
            if (operationalRateSet->ucRateSet[indexLocalRates] == (RemoteRateSet->ucRateSet[indexRemoteRates] & 0x7f))
            {

                activeRateSet->ucRateSet[activeRateSet->uRateSetLength] = 
                    operationalRateSet->ucRateSet[indexLocalRates];
                activeRateSet->uRateSetLength++;
                break;
            }
        }
    }

    //
    // If we dont find any rates, we will stick with our management packet rate
    //
    if (activeRateSet->uRateSetLength == 0)
    {
        activeRateSet->ucRateSet[0] = (UCHAR)HalGetBeaconRate(HwMac->Hw->Hal, HwMac->OperatingPhyId);
        activeRateSet->uRateSetLength = 1;
    }
    else if (activeRateSet->uRateSetLength > 1)
    {
        // bubble sort data rates in ascending order
        INT     i, j;
        UCHAR   temp;
        for (i = activeRateSet->uRateSetLength - 1; i >= 0; i--)
        {
            for (j = 1; j <= i; j++)
            {
                if (activeRateSet->ucRateSet[j - 1] > 
                    activeRateSet->ucRateSet[j])
                {
                    temp = activeRateSet->ucRateSet[j - 1];
                    activeRateSet->ucRateSet[j - 1] = 
                        activeRateSet->ucRateSet[j];
                    activeRateSet->ucRateSet[j] = temp;
                }
            }
        }
    }

    //
    // Now that the active rate set is populated and updated, select
    // the best rate
    //
    
    //
    // Determine what the maximum TX rate should be
    //
    maximumRate = HW11_MAX_DATA_RATE;  // Start with max supported by HW
    if (LinkQuality < HW_LOW_RATE_LINK_QUALITY_THRESHOLD)
    {
        //
        // The link quality is low, we will go for the lower start rate instead of 
        // the max supported. The hardware does rate fallback, so we pick
        // something that would cause the least number of retrys
        //
        maximumRate = HW_LOW_RATE_MAX_DATA_RATE;
    }

    // 
    // Check if this is greater than max permitted value read from the registry
    //
    if (maximumRate > HwMac->Hw->RegInfo.MaximumTxRate)
    {
        maximumRate = (USHORT)HwMac->Hw->RegInfo.MaximumTxRate;
    }

    //
    // Now find the best matching rate between us and the AP
    //
    for (indexLocalRates = activeRateSet->uRateSetLength - 1; 
         indexLocalRates > 0;
         indexLocalRates--) 
    {
        //
        // Check for a rate supported by both us and the AP that is below the max we prefer to use
        //
        if (activeRateSet->ucRateSet[indexLocalRates] <= maximumRate)
        {
            //
            // Found the rate we want to use
            //
            break;
        }
    }

    HwMac->DefaultTXDataRate = activeRateSet->ucRateSet[indexLocalRates];

    // Update our rate info table. In our current implementation this is not-per peer
    HwMac->RateInfo.CurrentTXDataRate = HwMac->DefaultTXDataRate;

    MpTrace(COMP_ASSOC, DBG_LOUD, ("TX Data rate: %d\n", HwMac->DefaultTXDataRate));

    
    HW_RELEASE_HARDWARE_LOCK(HwMac->Hw, FALSE);

    //
    // Indicate NDIS_STATUS_LINK_STATE to inform the OS about the new 
    // link speed
    //
    HwIndicateLinkSpeed(HwMac, HwMac->DefaultTXDataRate);    

    // Indicate change of link speed to the port so that it 
    // can take any necessary action
    rateNotification.Header.Type = NotificationOpRateChange;
    rateNotification.Header.Size = sizeof(OP_RATE_CHANGE_NOTIFICATION);
    rateNotification.Header.pSourceVNic = NULL;
    
    rateNotification.NewRate = HwMac->DefaultTXDataRate;
    rateNotification.OldRate = 0;
    
    rateNotification.LowestRate = FALSE;
    
    VNic11Notify(HwMac->VNic, &rateNotification);

    return (UCHAR)HwMac->DefaultTXDataRate;
}
Пример #3
0
NDIS_STATUS
Hw11Allocate(
    __in  NDIS_HANDLE             MiniportAdapterHandle,
    __deref_out_opt PHW*          Hw,
    __in  PADAPTER                Adapter
    )
{
    NDIS_STATUS                 ndisStatus = NDIS_STATUS_SUCCESS;
    PHW                         newHw = NULL;
    ULONG                       size;
    NDIS_TIMER_CHARACTERISTICS  timerChar;               

    *Hw = NULL;
    do
    {
        // Allocate a HW data structure
        MP_ALLOCATE_MEMORY(MiniportAdapterHandle, &newHw, sizeof(HW), HW_MEMORY_TAG);
        if (newHw == NULL)
        {
            MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to allocate %d bytes for HW\n",
                                 sizeof(HW)));
            ndisStatus = NDIS_STATUS_RESOURCES;
            break;
        }

        // Clear everything
        NdisZeroMemory(newHw, sizeof(HW));

        // We start in the PAUSED state
        HW_SET_ADAPTER_STATUS(newHw, HW_ADAPTER_PAUSED);
        newHw->InterruptDisableCount = 1;       // Since we are paused, we want the interrupts to be disabled
#if DBG
        NdisInterlockedIncrement(&newHw->Tracking_InterruptDisable[HW_ISR_TRACKING_PAUSE]);
#endif
        
        // Allocate memory for fields inside the HW structure
        size = sizeof(DOT11_REG_DOMAINS_SUPPORT_VALUE) + 
               (HW_MAX_NUM_DOT11_REG_DOMAINS_VALUE - 1) * sizeof(DOT11_REG_DOMAIN_VALUE);
        MP_ALLOCATE_MEMORY(MiniportAdapterHandle,
                           &(newHw->PhyState.RegDomainsSupportValue),
                           size,
                           HW_MEMORY_TAG);
        if (newHw->PhyState.RegDomainsSupportValue == NULL)
        {
            MpTrace(COMP_INIT_PNP,
                    DBG_SERIOUS,
                    ("Failed to allocate memory for RegDomainsSupportValue\n"));
            ndisStatus = NDIS_STATUS_RESOURCES;
            break;
        }
        NdisZeroMemory(newHw->PhyState.RegDomainsSupportValue, size);

        size = sizeof(DOT11_DIVERSITY_SELECTION_RX_LIST) +
              (HW_MAX_NUM_DIVERSITY_SELECTION_RX_LIST - 1) * sizeof(DOT11_DIVERSITY_SELECTION_RX);
        MP_ALLOCATE_MEMORY(MiniportAdapterHandle,
                           &(newHw->PhyState.DiversitySelectionRxList),
                           size, 
                           HW_MEMORY_TAG);
        if (newHw->PhyState.DiversitySelectionRxList == NULL) 
        {
            MpTrace(COMP_INIT_PNP,
                    DBG_SERIOUS,
                    ("Failed to allocate memory for DiversitySelectionRxList\n"));
            ndisStatus = NDIS_STATUS_RESOURCES;
            break;
        }
        NdisZeroMemory(newHw->PhyState.DiversitySelectionRxList, size);        

        NdisZeroMemory(&timerChar, sizeof(NDIS_TIMER_CHARACTERISTICS));
        
        // Allocate the power save wake timer
        timerChar.Header.Type = NDIS_OBJECT_TYPE_TIMER_CHARACTERISTICS;
        timerChar.Header.Revision = NDIS_TIMER_CHARACTERISTICS_REVISION_1;
        timerChar.Header.Size = sizeof(NDIS_TIMER_CHARACTERISTICS);
        timerChar.AllocationTag = HW_MEMORY_TAG;
        
        timerChar.TimerFunction = HwAwakeTimer;
        timerChar.FunctionContext = newHw;

        ndisStatus = NdisAllocateTimerObject(
                        MiniportAdapterHandle,
                        &timerChar,
                        &newHw->PhyState.Timer_Awake
                        );
        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to allocate power save awake timer\n"));
            break;
        }

        // Allocate the power save sleep timer
        timerChar.TimerFunction = HwDozeTimer;
        timerChar.FunctionContext = newHw;

        ndisStatus = NdisAllocateTimerObject(
                        MiniportAdapterHandle,
                        &timerChar,
                        &newHw->PhyState.Timer_Doze
                        );
        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to allocate power save doze timer\n"));
            break;
        }
        
        // Allocate the scan timer
        timerChar.TimerFunction = HwScanTimer;
        timerChar.FunctionContext = newHw;

        ndisStatus = NdisAllocateTimerObject(
                        MiniportAdapterHandle,
                        &timerChar,
                        &newHw->ScanContext.Timer_Scan
                        );
        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to allocate scan timer\n"));
            break;
        }

        newHw->PhyState.PhyProgramWorkItem = NdisAllocateIoWorkItem(MiniportAdapterHandle);
        if(newHw->PhyState.PhyProgramWorkItem == NULL)
        {
            MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to allocate channel switch work item\n"));
            ndisStatus = NDIS_STATUS_RESOURCES;
            break;
        }

        // The hardware lock
        NdisAllocateSpinLock(&newHw->Lock);

        // Save the Adapter pointer in the HW
        newHw->Adapter = Adapter;
        newHw->MiniportAdapterHandle = MiniportAdapterHandle;

        // Return the newly created structure to the caller
        *Hw = newHw;

    } while (FALSE);

    if (ndisStatus != NDIS_STATUS_SUCCESS)
    {
        if (newHw != NULL)
        {
            Hw11Free(newHw);
        }
    }

    return ndisStatus;
}
Пример #4
0
/**
 This implementation picks the NDIS 6.2 Read/Write lock structures & API on OS versions 
 where NDIS support those and would pick the older API on NDIS 6.0. Since the new API 
 are not available on NDIS 6.0 OS, it does not link the new API into the binary, instead 
 it dynamically loads the API address & uses them. This way the same binary can run on 
 both NDIS 6.0 & 6.2 OSes, using the correct API for that OS.
 */
NDIS_STATUS
MpDetermineRWLockType()
{
    NDIS_STATUS                 ndisStatus = NDIS_STATUS_SUCCESS;    
    ULONG                       ndisVersion;
    NDIS_STRING                 allocateRoutineName;
    NDIS_STRING                 freeRoutineName;
    NDIS_STRING                 acquireReadRoutineName;
    NDIS_STRING                 acquireWriteRoutineName;
    NDIS_STRING                 releaseRoutineName;

    do
    {
        NdisZeroMemory(&GlobalRWLockHandlers, sizeof(MP_RW_LOCK_HANDLERS));
            
        // Start with pre NDIS 6.2 using the old API. If this is NDIS 6.2+ and
        // we cannot find address of new API, we will fail
        GlobalRWLockHandlers.AllocateHandler = MpAllocateOldRWLock;
        GlobalRWLockHandlers.FreeHandler = MpFreeOldRWLock;
        GlobalRWLockHandlers.AcquireReadHandler = MpAcquireOldRWLockForRead;
        GlobalRWLockHandlers.AcquireWriteHandler = MpAcquireOldRWLockForWrite;
        GlobalRWLockHandlers.ReleaseHandler = MpReleaseOldRWLock;
        
        ndisVersion = NdisGetVersion();
        if (ndisVersion > MP_NDIS_VERSION_NEEDS_COMPATIBILITY)        
        {
            // NDIS 6.2 or above. Use the new API

            // Load the address of the new NDisRead/Write lock API
            NdisInitUnicodeString(&allocateRoutineName, L"NdisAllocateRWLock");
            
            NdisInitUnicodeString(&freeRoutineName, L"NdisFreeRWLock");
            NdisInitUnicodeString(&acquireReadRoutineName, L"NdisAcquireRWLockRead");
            NdisInitUnicodeString(&acquireWriteRoutineName, L"NdisAcquireRWLockWrite");
            NdisInitUnicodeString(&releaseRoutineName, L"NdisReleaseRWLock");
            
            *((PVOID *)&MpNdisAllocateRWLock) = NdisGetRoutineAddress(&allocateRoutineName);
            if (MpNdisAllocateRWLock == NULL)
            {
                MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to find address of NdisAllocateRWLock\n"));
                break;                
            }

            *((PVOID *)&MpNdisFreeRWLock) = NdisGetRoutineAddress(&freeRoutineName);
            if (MpNdisFreeRWLock == NULL)
            {
                MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to find address of NdisFreeRWLock\n"));
                break;                
            }

            *((PVOID *)&MpNdisAcquireRWLockRead) = NdisGetRoutineAddress(&acquireReadRoutineName);
            if (MpNdisAcquireRWLockRead == NULL)
            {
                MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to find address of NdisAcquireRWLockRead\n"));
                break;                
            }

            *((PVOID *)&MpNdisAcquireRWLockWrite) = NdisGetRoutineAddress(&acquireWriteRoutineName);
            if (MpNdisAcquireRWLockWrite == NULL)
            {
                MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to find address of NdisAcquireRWLockWrite\n"));
                break;                
            }

            *((PVOID *)&MpNdisReleaseRWLock) = NdisGetRoutineAddress(&releaseRoutineName);
            if (MpNdisReleaseRWLock == NULL)
            {
                MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to find address of NdisReleaseRWLock\n"));
                break;                
            }

            // Set our pointers
            GlobalRWLockHandlers.AllocateHandler = MpAllocateNewRWLock;
            GlobalRWLockHandlers.FreeHandler = MpFreeNewRWLock;
            GlobalRWLockHandlers.AcquireReadHandler = MpAcquireNewRWLockForRead;
            GlobalRWLockHandlers.AcquireWriteHandler = MpAcquireNewRWLockForWrite;
            GlobalRWLockHandlers.ReleaseHandler = MpReleaseNewRWLock;

        }
    }while (FALSE);

    return ndisStatus;
}
Пример #5
0
// Called when scan on a set of channels is completed
VOID
HelperPortCompletePartialScan(
    _In_  PMP_HELPER_PORT         HelperPort,
    _In_  PMP_SCAN_PARAMETERS     ScanParameters,
    _In_  PNDIS_STATUS            CompletionStatus
    )
{
    LARGE_INTEGER               rescheduleTime;
    BOOLEAN                     requeueScan = TRUE;
    ULONG                       i;

    // release exclusive access
    HelperPortReleaseExclusiveAccess(HelperPort);

    // Determine the next step for scan
    MP_ACQUIRE_PORT_LOCK(HELPPORT_GET_MP_PORT(HelperPort), FALSE);

    if (ScanParameters->PortScanRequest->ChannelCount != 0)
    {
        // All port specified channels are scanned in one shot
        requeueScan = FALSE;
    }
    else
    {
        // Determine if we are done with all the channels on current PHY
        if (ScanParameters->NextChannelIndex >= 
                HelperPort->ScanContext.ScanChannels[ScanParameters->CurrentPhyIndex].ChannelCount)
        {
            // We are done with all phys on current channel, check if there is another
            // phy we need to scan

            requeueScan = FALSE;    // Start with a negative
            for (i = ScanParameters->CurrentPhyIndex + 1; i < HW11_MAX_PHY_COUNT; i++)
            {
                if (HelperPort->ScanContext.ScanChannels[i].ChannelCount > 0)
                {
                    // Found a phy to scan we will requeue the scan.
                    requeueScan = TRUE;

                    // Start from first channel on this new phy
                    ScanParameters->CurrentPhyIndex = i;
                    ScanParameters->NextChannelIndex = 0;
                }
            }
        }
    }
    
    if (ScanParameters->CancelScan)
    {
        // Cancelled
        requeueScan = FALSE;
    }
    
    if (requeueScan == FALSE)
    {
        // We will queuing the scan timer
        ScanParameters->State = SCAN_WAITING_FOR_TIMER;
    }

    if ((*CompletionStatus) != NDIS_STATUS_SUCCESS)
    {
        // Partial scan failed
        MpTrace(COMP_SCAN, DBG_NORMAL, ("Partial scan failed. Status = 0x%08x\n", (*CompletionStatus)));
        
        requeueScan = FALSE;
    }
    
    MP_RELEASE_PORT_LOCK(HELPPORT_GET_MP_PORT(HelperPort), FALSE);

    MpTrace(COMP_SCAN, DBG_LOUD, ("Completed partial scan of %p\n", ScanParameters));

    if (requeueScan)
    {
        if (HelperPort->ScanContext.MediaConnectedCount > 0)
        {    
            // Queue the timer for another scan. We try to schedule this after one
            // context switch interval
            rescheduleTime.QuadPart = Int32x32To64(HelperPort->RegInfo->ScanRescheduleTime, -10000);
        }
        else
        {
            // Noboby is connected yet, Queue the timer for another scan
            rescheduleTime.QuadPart = Int32x32To64(MP_SCAN_RESCHEDULE_TIME_NOT_CONNECTED, -10000);
        }
        
        NdisSetTimerObject(HelperPort->ScanContext.Timer_Scan, rescheduleTime, 0, NULL);
    }
    else
    {
        // We have finished scanning all channels, call the scan completion
        HelperPortCompleteScanProcess(
            HelperPort,
            ScanParameters,
            CompletionStatus
        );
    }
}
Пример #6
0
NDIS_STATUS
Hw11Start(
    __in  PHW                     Hw,
    __out NDIS_ERROR_CODE*        ErrorCode,
    __out PULONG                  ErrorValue
    )
{
    NDIS_STATUS                 ndisStatus = NDIS_STATUS_SUCCESS;
    BOOLEAN                     interruptRegistered = FALSE, hardwareStarted = FALSE;
    
    //
    // Disable interrupts
    // We should disable interrupts before the are registered.
    // They will be enabled right at the end of Initialize
    //
    HwDisableInterrupt(Hw, HW_ISR_TRACKING_HWSTART);

    do
    {
        //
        // Register interrupt with NDIS
        //
        ndisStatus = HwRegisterInterrupt(
                        Hw,
                        ErrorCode, 
                        ErrorValue
                        );
        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to register interrupt with NDIS\n"));
            break;
        }
        interruptRegistered = TRUE;
        
        Hw->PhyState.Debug_SoftwareRadioOff = Hw->PhyState.SoftwareRadioOff;
        if (Hw->PhyState.SoftwareRadioOff)
        {
            HalSetRFPowerState(Hw->Hal, RF_SHUT_DOWN);
        }
        else
        {
            HalSetRFPowerState(Hw->Hal, RF_ON);
        }

        //
        // Start the HAL. If anything fails after this point,
        // we must issue a Halt to the HAL before returning
        // from initialize
        //
        ndisStatus = HalStart(Hw->Hal, FALSE);
        if(ndisStatus != NDIS_STATUS_SUCCESS)
        {
            MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to start HAL successfully.\n"));
            break;
        }
        hardwareStarted = TRUE;
        
        // Enable the interrupts on the hardware
        HwEnableInterrupt(Hw, HW_ISR_TRACKING_HWSTART);
                
    }while (FALSE);

    if (ndisStatus != NDIS_STATUS_SUCCESS)
    {
        // Disable interrupts and deregister them first
        HwDisableInterrupt(Hw, HW_ISR_TRACKING_HWSTART);
        
        if (interruptRegistered)
            HwDeregisterInterrupt(Hw);

        if (hardwareStarted)
        {
            HalStop(Hw->Hal);
            HalHaltNic(Hw->Hal);
        }
    }

    return ndisStatus;
}
Пример #7
0
NDIS_STATUS 
HelperPortInsertBSSEntry(
    __in  PMP_HELPER_PORT        HelperPort,
    __in  PMP_RX_MPDU        pFragment,
    __in  PDOT11_BEACON_FRAME pDot11BeaconFrame,
    __in  ULONG           BeaconDataLength
    )
{
    NDIS_STATUS         ndisStatus = NDIS_STATUS_SUCCESS;
    ULONGLONG           ullHostTimeStamp;
    MP_RW_LOCK_STATE          LockState;
    PMP_BSS_ENTRY      pBSSEntry = NULL;
    PDOT11_MGMT_HEADER  pMgmtPktHeader;
    BOOLEAN             bNewAp = FALSE;
    PMP_BSS_LIST       pDiscoveredBSSList = &(HelperPort->BSSList);

    pMgmtPktHeader = (PDOT11_MGMT_HEADER)MP_RX_MPDU_DATA(pFragment);
    NdisGetCurrentSystemTime((PLARGE_INTEGER)&ullHostTimeStamp);

    //
    // We acquire the write lock as we are adding entries to the list
    //
    MP_ACQUIRE_WRITE_LOCK(&(HelperPort->BSSList.ListLock), &LockState);

    do
    {
        //
        // Check again if this entry already exists in the list. This is to handle
        // if the AP was added since we first checked (possible if the
        // flush routine was running)
        //
        pBSSEntry = HelperPortFindBSSEntry(
            pDiscoveredBSSList,
            pMgmtPktHeader->SA
            );

        if (pBSSEntry == NULL)
        {
            bNewAp = TRUE;      // New AP
            //
            // We havent found this AP yet, we would add it to the list
            //
            if (pDiscoveredBSSList->NumOfBSSEntries >= pDiscoveredBSSList->MaxNumOfBSSEntries)
            {
                //
                // We need to replace an entry thats in the list
                //
                pBSSEntry = HelperPortExpireBSSEntry(
                    pDiscoveredBSSList,
                    HelperPort->RegInfo->BSSEntryExpireTime,
                    ullHostTimeStamp
                    );

                if (pBSSEntry != NULL)
                {
                    //
                    // Add initial in-use refcount
                    //
                    pBSSEntry->RefCount = 1;
                }
                
                //
                // Dont zero out the AP entry so that we can
                // reuse the info element blob
                //
            }
            else
            {
                //
                // Create a new entry for this AP
                //
                MP_ALLOCATE_MEMORY(HELPPORT_GET_MP_PORT(HelperPort)->MiniportAdapterHandle, 
                    &pBSSEntry, 
                    sizeof(MP_BSS_ENTRY), 
                    PORT_MEMORY_TAG
                    );
                if (pBSSEntry != NULL)
                {
                    //
                    // Initialize the new entry
                    //
                    NdisZeroMemory(pBSSEntry, sizeof(MP_BSS_ENTRY));
                    
                    pBSSEntry->RefCount = 1; // Add initial in-use refcount
                    NdisAllocateSpinLock(&(pBSSEntry->Lock));
                }
            }

            if (pBSSEntry == NULL)
            {
                MpTrace(COMP_SCAN, DBG_SERIOUS, ("Not enough space to add AP: %02X-%02X-%02X-%02X-%02X-%02X\n",
                    pMgmtPktHeader->SA[0], pMgmtPktHeader->SA[1], pMgmtPktHeader->SA[2], 
                    pMgmtPktHeader->SA[3], pMgmtPktHeader->SA[4], pMgmtPktHeader->SA[5]));
            
                ndisStatus = NDIS_STATUS_RESOURCES;
                break;
            }

            //
            // This Entry is not yet in the list
            //
            
            // We will be updating the beacon & probe response frames
            pBSSEntry->BeaconFrameSize = 0;
            pBSSEntry->ProbeFrameSize = 0;
            
            pBSSEntry->AssocCost = 0;

            NdisMoveMemory(
                pBSSEntry->Dot11BSSID,
                pMgmtPktHeader->BSSID,
                sizeof(DOT11_MAC_ADDRESS)
                );

            NdisMoveMemory(
                pBSSEntry->MacAddress,
                pMgmtPktHeader->SA,
                sizeof(DOT11_MAC_ADDRESS)
                );
        }

        // Update the information in this BSS entry (either new or reused entry)
        ndisStatus = HelperPortUpdateBSSEntry(
            HelperPort, 
            pBSSEntry, 
            pFragment, 
            pDot11BeaconFrame, 
            BeaconDataLength
            );
        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            break;
        }

        //
        // Add the new BSS to our list
        //
        if (bNewAp)
        {
            MpTrace(COMP_SCAN, DBG_LOUD, ("AP %02X-%02X-%02X-%02X-%02X-%02X at channel: %d (%d)\n", 
                    pBSSEntry->Dot11BSSID[0], pBSSEntry->Dot11BSSID[1], pBSSEntry->Dot11BSSID[2], 
                    pBSSEntry->Dot11BSSID[3], pBSSEntry->Dot11BSSID[4], pBSSEntry->Dot11BSSID[5],
                    pBSSEntry->Channel, pFragment->Msdu->Channel));

            HelperPortAddBSSEntry(pDiscoveredBSSList, pBSSEntry);
        }

        //
        // Note: If any code is added below here, remember to remove entry
        // from the list
        //
    } while (FALSE);

    MP_RELEASE_WRITE_LOCK(&(HelperPort->BSSList.ListLock), &LockState);

    if (ndisStatus != NDIS_STATUS_SUCCESS)
    {
        // Free the new entry we may have created
        if ((bNewAp) && (pBSSEntry != NULL))
        {
            if (pBSSEntry->pDot11BeaconFrame != NULL)
            {
                MP_FREE_MEMORY(pBSSEntry->pDot11BeaconFrame);
                pBSSEntry->pDot11BeaconFrame = NULL;
                pBSSEntry->BeaconFrameSize = 0;
                pBSSEntry->MaxBeaconFrameSize= 0;
            }

            if (pBSSEntry->pDot11ProbeFrame != NULL)
            {
                MP_FREE_MEMORY(pBSSEntry->pDot11ProbeFrame);
                pBSSEntry->pDot11ProbeFrame = NULL;
                pBSSEntry->ProbeFrameSize = 0;
                pBSSEntry->MaxProbeFrameSize= 0;
            }
                        
            pBSSEntry->pDot11InfoElemBlob = NULL;                
            pBSSEntry->InfoElemBlobSize = 0;
            MP_FREE_MEMORY(pBSSEntry);
        }
    }

    return ndisStatus;
Пример #8
0
VOID
HelperPortScanTimerCallback(
    _In_  PMP_HELPER_PORT         HelperPort
    )
{
    NDIS_STATUS                 ndisStatus = NDIS_STATUS_SUCCESS;
    PMP_SCAN_PARAMETERS         scanParameters;
    BOOLEAN                     queueExAccess = TRUE;
    
    MP_ACQUIRE_PORT_LOCK(HELPPORT_GET_MP_PORT(HelperPort), FALSE);
    MPASSERT(HelperPort->ScanContext.ActiveScanParameters != NULL);
    scanParameters = HelperPort->ScanContext.ActiveScanParameters;
    
    if (scanParameters->CancelScan)
    {
        // Scan is being cancelled, dont need to queue exclusive access
        MpTrace(COMP_SCAN, DBG_NORMAL, ("Ignored scan timer for cancelled/old scan request %p\n", scanParameters));
        queueExAccess = FALSE;
    }
    else
    {
        scanParameters->State = SCAN_EXCLUSIVE_ACCESS_QUEUED;
    }
    MP_RELEASE_PORT_LOCK(HELPPORT_GET_MP_PORT(HelperPort), FALSE);

    if (queueExAccess)
    {
        //
        // Queue an exclusive access. The scan would be done in there
        //
        ndisStatus = HelperPortRequestExclusiveAccess(HelperPort,
            HelperPortScanExAccessCallback, 
            HelperPort->ScanContext.ActiveScanParameters,
            FALSE
            );

        if ((ndisStatus != NDIS_STATUS_SUCCESS) && (ndisStatus != NDIS_STATUS_PENDING))
        {
            // Exclusive access request was rejected
            MpTrace(COMP_SCAN, DBG_SERIOUS, ("Exclusive access request in scan timer failed. Status = 0x%08x\n", ndisStatus));
            
            HelperPortCompleteScanProcess(
                HelperPort,
                scanParameters,
                &ndisStatus
            );
            
        }
        else if (NDIS_STATUS_SUCCESS == ndisStatus)
        {
            // the function completed synchronously, call the callback ourselves
            HelperPortScanExAccessCallback(HELPPORT_GET_MP_PORT(HelperPort), HelperPort->ScanContext.ActiveScanParameters);
        }
    }
    else
    {
        // Abort the scan
        ndisStatus = NDIS_STATUS_REQUEST_ABORTED;
        HelperPortCompleteScanProcess(
            HelperPort,
            scanParameters,
            &ndisStatus
        );
    }
}
Пример #9
0
VOID
HelperPortStartScanProcess(
    _In_  PMP_HELPER_PORT         HelperPort,
    _In_  PMP_SCAN_PARAMETERS     ScanParameters
    )
{
    NDIS_STATUS                 ndisStatus = NDIS_STATUS_SUCCESS;
    ULONG                       scanChannelCount = 0;
    ULONG                       i;
    
    do
    {
        MpTrace(COMP_SCAN, DBG_NORMAL, ("Starting the scan process of %p for port %p\n", 
            ScanParameters, ScanParameters->RequestingPort));

        //
        // For optimal scanning, we specify the list of channels
        // that the HW should use if the port hasnt specified any.
        // Note that for ExtSTA the channels in the PhyTypeInfo 
        // structures of the DOT11_SCAN_REQUEST are invalid. So we dont
        // need to consider those
        //
        if (ScanParameters->PortScanRequest->ChannelCount != 0)
        {
            // Use the list of channels specified by the port
            scanChannelCount = ScanParameters->PortScanRequest->ChannelCount;
        }
        else
        {        
            if (HelperPort->ScanContext.MediaConnectedCount > 0)
            {
                // A port is connected (STA associated/AP started/Adhoc running)
                // We dont scan all channels in one shot. We do multiple partial
                // scans

                // The scan type determines the number of channels we scan at a time
                if (ScanParameters->PortScanRequest->Dot11ScanRequest->dot11ScanType & dot11_scan_type_active)
                    scanChannelCount = HelperPort->RegInfo->ActiveScanChannelCount;
                else
                    scanChannelCount = HelperPort->RegInfo->PassiveScanChannelCount;
                    
                MpTrace(COMP_SCAN, DBG_NORMAL, ("Link Up scan will scan atmost %d channels at a time\n",
                    scanChannelCount));
            }
            else
            {
                // We can scan each phy in one scan. Find the maximum number of
                // channels in a phy & use that as our scan channels limit
                scanChannelCount = 0;
                for (i = 0; i < HW11_MAX_PHY_COUNT; i++)
                {
                    if (HelperPort->ScanContext.ScanChannels[i].ChannelCount > scanChannelCount)
                    {
                        scanChannelCount = HelperPort->ScanContext.ScanChannels[i].ChannelCount;
                    }
                }            
                MpTrace(COMP_SCAN, DBG_NORMAL, ("Link Down scan will scan upto %d channels at a time\n",
                    scanChannelCount));
            }
        }

        ScanParameters->MaxChannelCount = scanChannelCount;
        
        //
        // Create a channel buffer that we would give to the lower layer
        //
        MP_ALLOCATE_MEMORY(
            HELPPORT_GET_MP_PORT(HelperPort)->MiniportAdapterHandle,
            &ScanParameters->VNicScanRequest.ChannelList,
            scanChannelCount * sizeof(ULONG),
            PORT_MEMORY_TAG
            );
        
        if (ScanParameters->VNicScanRequest.ChannelList == NULL)
        {
            ndisStatus = NDIS_STATUS_RESOURCES;
            break;
        }
        
        //
        // Save scan start time
        //
        NdisGetCurrentSystemTime((PLARGE_INTEGER)&HelperPort->ScanContext.LastScanTime);        

        ScanParameters->VNicScanRequest.Dot11ScanRequest = ScanParameters->PortScanRequest->Dot11ScanRequest;
        ScanParameters->VNicScanRequest.ScanRequestBufferLength = 
            ScanParameters->PortScanRequest->ScanRequestBufferLength;

        MP_ACQUIRE_PORT_LOCK(HELPPORT_GET_MP_PORT(HelperPort), FALSE);
        if (ScanParameters->CancelScan)
        {
            MpTrace(COMP_SCAN, DBG_NORMAL, ("Aborting scan start for a cancelled scan request\n"));        
            ndisStatus = NDIS_STATUS_REQUEST_ABORTED;
        }
        else
        {
            // We will queue an exclusive access request
            ScanParameters->State = SCAN_EXCLUSIVE_ACCESS_QUEUED;
        }
        MP_RELEASE_PORT_LOCK(HELPPORT_GET_MP_PORT(HelperPort), FALSE);

        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            break;
        }

        //
        // Queue an exclusive access. The scan would be done in there
        //
        ndisStatus = HelperPortRequestExclusiveAccess(HelperPort, 
            HelperPortScanExAccessCallback, 
            ScanParameters,
            FALSE
            );

        if (NDIS_STATUS_SUCCESS == ndisStatus)
        {
            // the function completed synchronously, call the callback ourselves
            HelperPortScanExAccessCallback(HELPPORT_GET_MP_PORT(HelperPort), ScanParameters);
        }
        else if (ndisStatus == NDIS_STATUS_PENDING)
        {
            // Pending is same as success
            if (ndisStatus == NDIS_STATUS_PENDING)
            {
                ndisStatus = NDIS_STATUS_SUCCESS;
            }
        }
        else
        {
            // The exclusive access request failed
            MpTrace(COMP_SCAN, DBG_SERIOUS, ("Exclusive access request for scan start failed. Status = 0x%08x\n", ndisStatus)); 
        }
    }while (FALSE);

    if (ndisStatus != NDIS_STATUS_SUCCESS)
    {
        HelperPortCompleteScanProcess(
            HelperPort,
            ScanParameters,
            &ndisStatus
        );
    }

}
Пример #10
0
VOID
HelperPortCancelScan(
    _In_  PMP_PORT                Port,
    _In_  PMP_PORT                RequestingPort
    )
{
    ULONG                       i;
    PMP_HELPER_PORT             helperPort = MP_GET_HELPPORT(Port);
    PMP_SCAN_PARAMETERS         scanParameters = NULL;
    MP_SCAN_STATE               preCancelState = SCAN_EMPTY_REQUEST;
    NDIS_STATUS                 ndisStatus;
    BOOLEAN                     timerCancelled = FALSE;

    // Add this scan request to the list
    MP_ACQUIRE_PORT_LOCK(Port, FALSE);

    // Search for the scan request in our list
    for (i = 0; i < MP_MAX_NUMBER_OF_PORT; i++)
    {
        if ((helperPort->ScanContext.ScanParameters[i].State != SCAN_EMPTY_REQUEST) && 
            (helperPort->ScanContext.ScanParameters[i].State != SCAN_COMPLETED) && 
            (helperPort->ScanContext.ScanParameters[i].RequestingPort == RequestingPort))
        {
            // The scan request from this port is in the queue
            scanParameters = &helperPort->ScanContext.ScanParameters[i];
            scanParameters->CancelScan = TRUE;

            // Add a refcount to ensure that the structure does not get deleted on us
            MP_INCREMENT_SCAN_PARAMETER_REF(scanParameters);

            preCancelState = scanParameters->State;

            // Save the previous state (for tracking)
            scanParameters->TrackingPreCancelState = preCancelState;
            
            if (preCancelState == SCAN_QUEUED_FOR_PROCESSING)
            {
                // This request is not yet activated for processing.
                // Remove the request from the pending scan list. This is done right now
                // with the lock held so that the request does not get requeued
                scanParameters->State = SCAN_REQUEST_IN_USE;
                MpTrace(COMP_SCAN, DBG_NORMAL, ("Canceling unprocessed scan request\n"));
            }
            else if (preCancelState == SCAN_EXCLUSIVE_ACCESS_QUEUED)
            {
                // We are unsure if the exclusive access request would
                // be granted or not. It would be granted if the cancel was part of
                // a pause or something. It would not be granted if this was
                // a halt
                MpTrace(COMP_SCAN, DBG_NORMAL, ("Canceling scan request waiting for exclusive access\n"));
            }

            break;
        }
    }

    MP_RELEASE_PORT_LOCK(Port, FALSE);

    if (scanParameters == NULL)
    {
        // No scan to cancel.
        return;
    }

    if (preCancelState != SCAN_QUEUED_FOR_PROCESSING)
    {
        // NOTE: Since we added the ref, we know that the ScanParameters buffer is available

        // If we have the timer running, force fire the timer
        timerCancelled = NdisCancelTimerObject(helperPort->ScanContext.Timer_Scan);
        if (timerCancelled == TRUE)
        {
            // We cancelled the timer, so we would need to invoke the complete ourselves
            MpTrace(COMP_SCAN, DBG_NORMAL, ("Canceling scan request waiting for scan timer\n"));
            HelperPortScanTimerCallback(helperPort);
        }
        else
        {
            // We could be waiting for exclusive access
            if (preCancelState == SCAN_EXCLUSIVE_ACCESS_QUEUED)
            {
                // We would complete the scan here. Because of the cancel flag, the
                // exclusive access routine would not proceed with the scan 
                // if it got called
                ndisStatus = NDIS_STATUS_REQUEST_ABORTED;

                MP_ACQUIRE_PORT_LOCK(HELPPORT_GET_MP_PORT(helperPort), FALSE);
                
                // Clear the active pointer
                helperPort->ScanContext.ActiveScanParameters = NULL;
                scanParameters->State = SCAN_COMPLETED;

                MP_RELEASE_PORT_LOCK(HELPPORT_GET_MP_PORT(helperPort), FALSE);

                // Now perform the indication
                HelperPortIndicateScanCompletion(helperPort, scanParameters, &ndisStatus);

                // We dont remove the reference here. We wait for the ex or the scan
                // to do it
            }

            // Ask the HW to cancel the scan (if it has it)
            VNic11CancelScan(HELPPORT_GET_VNIC(helperPort));
        }

        // Now wait for the scan complete to get indicated
        while (scanParameters->State != SCAN_COMPLETED)
        {
            MpTrace(COMP_SCAN, DBG_NORMAL, ("Waiting for scan operation to complete\n"));
            NdisMSleep(20 * 1000);
        }

        // This lock is acquired to ensure that the free here does not conflict with an
        // in progress scan completion
        MP_ACQUIRE_PORT_LOCK(Port, FALSE);
        HelperPortScanParametersReleaseRef(helperPort, scanParameters);
        MP_RELEASE_PORT_LOCK(Port, FALSE);

        // If there is a different second scan pending, process it
        HelperPortProcessPendingScans(helperPort);
    }
    else
    {
        // This scan was never started, we need to complete the scan request & we are done
        ndisStatus = NDIS_STATUS_REQUEST_ABORTED;
        HelperPortIndicateScanCompletion(helperPort, scanParameters, &ndisStatus);

        MP_ACQUIRE_PORT_LOCK(Port, FALSE);        
        scanParameters->State = SCAN_COMPLETED;        
        HelperPortScanParametersReleaseRef(helperPort, scanParameters);
        MP_RELEASE_PORT_LOCK(Port, FALSE);        
    }

}
Пример #11
0
VOID
HelperPortProcessPendingScans(
    _In_  PMP_HELPER_PORT         HelperPort
    )
{
    ULONG                       i;
    PMP_SCAN_PARAMETERS         scanParameters = NULL;
    BOOLEAN                     processScan = FALSE;
    NDIS_STATUS                 ndisStatus = NDIS_STATUS_SUCCESS;
    
    // Add this scan request to the list
    MP_ACQUIRE_PORT_LOCK(HELPPORT_GET_MP_PORT(HelperPort), FALSE);

    if (HelperPort->ScanContext.ActiveScanParameters != NULL)
    {
        // There is already a scan in progress. We dont do anything here
    }
    else
    {
        // Search for a scan request in our list
        for (i = 0; i < MP_MAX_NUMBER_OF_PORT; i++)
        {
            if (HelperPort->ScanContext.ScanParameters[i].State == SCAN_QUEUED_FOR_PROCESSING)
            {
                // Found a scan request, we will queue it up
                scanParameters = &HelperPort->ScanContext.ScanParameters[i];
                break;
            }
        }
    }

    // If there is an active scan, check if we should perform the scan
    if (scanParameters != NULL)
    {
        // Check if we should perform this scan
        processScan = HelperPortShouldPerformScan(HelperPort, scanParameters);
        if (processScan)
        {
            // Set this as the active scan
            HelperPort->ScanContext.ActiveScanParameters = scanParameters;
            scanParameters->State = SCAN_STARTED;            
        }
        else
        {
            // We will successfully complete this scan without processing
            scanParameters->State = SCAN_REQUEST_IN_USE;
        }
    }

    MP_RELEASE_PORT_LOCK(HELPPORT_GET_MP_PORT(HelperPort), FALSE);

    if (scanParameters == NULL)
    {
        // Nothing to process, we are done
        return;
    }

    if (processScan)
    {
        // Start the scan
        HelperPortStartScanProcess(HelperPort, scanParameters);
    }
    else
    {
        // There is a scan request that wont do a scan for, complete it without
        // actually processing it
        ndisStatus = NDIS_STATUS_SUCCESS;
        MpTrace(COMP_SCAN, DBG_NORMAL, ("Vetoed a scan request\n"));
        
        // Now perform the indication
        HelperPortIndicateScanCompletion(HelperPort, scanParameters, &ndisStatus);

        // We reacquire the lock to ensure that the cancel does not conflict
        // with this completion
        MP_ACQUIRE_PORT_LOCK(HELPPORT_GET_MP_PORT(HelperPort), FALSE);

        // The scan is done
        scanParameters->State = SCAN_COMPLETED;
        HelperPortScanParametersReleaseRef(HelperPort, scanParameters);
        MP_RELEASE_PORT_LOCK(HELPPORT_GET_MP_PORT(HelperPort), FALSE);
    }
}        
Пример #12
0
NDIS_STATUS
HelperPortHandleScan(
    _In_  PMP_PORT                Port,
    _In_  PMP_PORT                RequestingPort,
    _In_  PMP_SCAN_REQUEST        ScanRequest,
    _In_  PORT11_GENERIC_CALLBACK_FUNC    CompletionHandler
    )
{
    PMP_SCAN_PARAMETERS         scanParameters = NULL;
    // If we cannot find an empty slot, we return media in use
    NDIS_STATUS                 ndisStatus = NDIS_STATUS_DOT11_MEDIA_IN_USE; 
    PMP_HELPER_PORT             helperPort = MP_GET_HELPPORT(Port);
    ULONG                       i;

    do
    {
        // Add this scan request to the pending scan list
        MP_ACQUIRE_PORT_LOCK(Port, FALSE);

        // Find a structure we can use
        for (i = 0; i < MP_MAX_NUMBER_OF_PORT; i++)
        {
            if (helperPort->ScanContext.ScanParameters[i].State == SCAN_EMPTY_REQUEST)
            {
                scanParameters = &helperPort->ScanContext.ScanParameters[i];
                helperPort->ScanContext.ParametersCount++;

                MP_INCREMENT_SCAN_PARAMETER_REF(scanParameters);
                
                // Save the passed in information
                scanParameters->RequestingPort = RequestingPort;
                scanParameters->PortScanRequest = ScanRequest;
                scanParameters->CompletionHandler = CompletionHandler;

                // Scan would start at the first channel of the first phy
                scanParameters->NextChannelIndex = 0;
                scanParameters->CurrentPhyIndex = 0;

                // Queue it for processing
                scanParameters->CancelScan = 0;
                scanParameters->State = SCAN_QUEUED_FOR_PROCESSING;
                
                ndisStatus = NDIS_STATUS_SUCCESS;
                break;
            }
        }
        MP_RELEASE_PORT_LOCK(Port, FALSE);

        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            MpTrace(COMP_SCAN, DBG_SERIOUS, ("Unable to save scan parameters\n"));    
            break;
        }

        // Let the scan request proceed
        HelperPortProcessPendingScans(helperPort);
    }while (FALSE);

    if (ndisStatus != NDIS_STATUS_SUCCESS)
    {
        // Free stuff that we may have allocated
        if (scanParameters != NULL)
        {
            // This cannot be left in our list
            HelperPortScanParametersReleaseRef(helperPort, scanParameters);
        }
    }
    
    return ndisStatus;
}
Пример #13
0
NDIS_STATUS
HelperPortInitializeScanContext(
    _In_  PMP_HELPER_PORT         HelperPort
    )
{
    NDIS_STATUS                 ndisStatus = NDIS_STATUS_SUCCESS;
    NDIS_TIMER_CHARACTERISTICS  timerChar;               
    ULONG                       i;
    do
    {
        HelperPort->ScanContext.ActiveScanParameters = NULL;

        // Allocate the power save timeout call back
        NdisZeroMemory(&timerChar, sizeof(NDIS_TIMER_CHARACTERISTICS));
        
        timerChar.Header.Type = NDIS_OBJECT_TYPE_TIMER_CHARACTERISTICS;
        timerChar.Header.Revision = NDIS_TIMER_CHARACTERISTICS_REVISION_1;
        timerChar.Header.Size = sizeof(NDIS_TIMER_CHARACTERISTICS);
        timerChar.AllocationTag = PORT_MEMORY_TAG;
        
        timerChar.TimerFunction = HelperPortScanTimer;
        timerChar.FunctionContext = HelperPort;

        ndisStatus = NdisAllocateTimerObject(
                        HELPPORT_GET_MP_PORT(HelperPort)->MiniportAdapterHandle,
                        &timerChar,
                        &HelperPort->ScanContext.Timer_Scan
                        );
        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to allocate helper port scan timer\n"));
            break;
        }

        //
        // Get list of channels we would scan
        //
        ndisStatus = HelperPortCreateScanChannelList(HelperPort);
        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to create helper port scan list\n"));
            break;
        }        

        // Initialize the preallocated scan parameter structures
        for (i = 0; i < MP_MAX_NUMBER_OF_PORT; i++)
        {
            NdisZeroMemory(&HelperPort->ScanContext.ScanParameters[i], sizeof(MP_SCAN_PARAMETERS));
            
            HelperPort->ScanContext.ScanParameters[i].State = SCAN_EMPTY_REQUEST;
            HelperPort->ScanContext.ScanParameters[i].UsageCount = 0;
        }

        // To maintain the scan list, we need to receive all beacons and probe responses. Set the
        // appropriate packet filter
        VNic11SetPacketFilter(HELPPORT_GET_VNIC(HelperPort), 
            NDIS_PACKET_TYPE_802_11_BROADCAST_MGMT | NDIS_PACKET_TYPE_802_11_DIRECTED_MGMT
            );
        
    }while (FALSE);

    if (ndisStatus != NDIS_STATUS_SUCCESS)
    {
        if (HelperPort->ScanContext.Timer_Scan)
        {
            NdisFreeTimerObject(HelperPort->ScanContext.Timer_Scan);
            HelperPort->ScanContext.Timer_Scan = NULL;
        }
    
        for (i = 0; i < HW11_MAX_PHY_COUNT; i++)
        {
            if (HelperPort->ScanContext.ScanChannels[i].ChannelList != NULL)
            {
                MP_FREE_MEMORY(HelperPort->ScanContext.ScanChannels[i].ChannelList);
                HelperPort->ScanContext.ScanChannels[i].ChannelList = NULL;
            }
        }

    }
    
    return ndisStatus;
}
Пример #14
0
NDIS_STATUS
HelperPortCreateScanChannelList(
    _In_  PMP_HELPER_PORT         HelperPort
    )
{
    NDIS_STATUS                 ndisStatus = NDIS_STATUS_SUCCESS;
    ULONG                       phyId, channelListIndex = 0;
    PDOT11_SUPPORTED_PHY_TYPES  supportedPhyTypes;
    UCHAR                       buffer[(sizeof(DOT11_SUPPORTED_PHY_TYPES) + 
                                    sizeof(DOT11_PHY_TYPE) * HW11_MAX_PHY_COUNT)];  
    PMP_SCAN_CHANNEL_LIST       currentChannelList;
    DOT11_PHY_TYPE              bgScanPhy;

    do
    {
        //
        // Get supported PHY types.
        //
        supportedPhyTypes = (PDOT11_SUPPORTED_PHY_TYPES) buffer;
        supportedPhyTypes->uNumOfEntries = 0;
        VNic11QuerySupportedPHYTypes(HELPPORT_GET_VNIC(HelperPort), 
            HW11_MAX_PHY_COUNT, 
            supportedPhyTypes
            );

        //
        // For devices supporting both b & g phys, we only scan on g. Check if
        // we need to do this here
        //
        bgScanPhy = dot11_phy_type_hrdsss;
        for (phyId = 0; phyId < supportedPhyTypes->uNumOfEntries; phyId++)
        {
            if (supportedPhyTypes->dot11PHYType[phyId] == dot11_phy_type_erp)
            {
                // Support g, no need to scan b
                bgScanPhy = dot11_phy_type_erp;
                break;
            }
        }        

        //
        // Go through the list to see if there is a phy type we scan for
        //
        for (phyId = 0; phyId < supportedPhyTypes->uNumOfEntries; phyId++)
        {
            // We only scan on g(or b) & a phy
            if ((supportedPhyTypes->dot11PHYType[phyId] == bgScanPhy) ||
                (supportedPhyTypes->dot11PHYType[phyId] == dot11_phy_type_ofdm))
            {
                // Query for the channel list
                currentChannelList = &HelperPort->ScanContext.ScanChannels[channelListIndex];

                // Start with a zero length buffer to determine the size
                currentChannelList->ChannelCount = 0;
                ndisStatus = VNic11QuerySupportedChannels(HELPPORT_GET_VNIC(HelperPort), 
                                    phyId,
                                    &currentChannelList->ChannelCount, 
                                    NULL
                                    );
                if (ndisStatus != NDIS_STATUS_BUFFER_TOO_SHORT)
                {
                    MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Unable to query size of the channel list for phy ID %d\n", phyId));    
                    // We skip this PHY
                    ndisStatus = NDIS_STATUS_SUCCESS;
                    break;
                }
                
                MP_ALLOCATE_MEMORY(HELPPORT_GET_MP_PORT(HelperPort)->MiniportAdapterHandle,
                    &currentChannelList->ChannelList,
                    currentChannelList->ChannelCount * sizeof(ULONG),
                    PORT_MEMORY_TAG
                    );
                if (currentChannelList->ChannelList == NULL)
                {
                    MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Unable to allocate memory for the channel list for phy ID %d\n", phyId));
                    ndisStatus = NDIS_STATUS_RESOURCES;
                    break;
                }

                // Query again
                ndisStatus = VNic11QuerySupportedChannels(HELPPORT_GET_VNIC(HelperPort), 
                                    phyId,
                                    &currentChannelList->ChannelCount, 
                                    currentChannelList->ChannelList
                                    );
                if (ndisStatus != NDIS_STATUS_SUCCESS)
                {
                    MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Unable to query channel list for phy ID %d\n", phyId));
                    break;
                }

                currentChannelList->PhyId = phyId;
                
                // Populated one set of channels
                channelListIndex++;
            }

            if (ndisStatus != NDIS_STATUS_SUCCESS)
            {
                break;
            }
        }
    } while (FALSE);

    if (ndisStatus != NDIS_STATUS_SUCCESS)
    {
        for (channelListIndex = 0; channelListIndex < HW11_MAX_PHY_COUNT; channelListIndex++)
        {
            if (HelperPort->ScanContext.ScanChannels[channelListIndex].ChannelList != NULL)
            {
                MP_FREE_MEMORY(HelperPort->ScanContext.ScanChannels[channelListIndex].ChannelList);
                HelperPort->ScanContext.ScanChannels[channelListIndex].ChannelList = NULL;
            }
        }
    }

    return ndisStatus;
}
Пример #15
0
NDIS_STATUS
Hw11DiscoverNicResources(
    __in  PHW                     Hw,
    __in  PNDIS_RESOURCE_LIST     ResList,
    __out NDIS_ERROR_CODE*        ErrorCode,
    __out PULONG                  ErrorValue
    )
{
    ULONG                       index;
    NDIS_STATUS                 ndisStatus = NDIS_STATUS_SUCCESS;
    BOOLEAN                     resPort = FALSE, resInterrupt = FALSE, resMemory = FALSE;
    PCM_PARTIAL_RESOURCE_DESCRIPTOR resDesc;
    
    do
    {
        for(index=0; index < ResList->Count; index++)
        {
            resDesc = &ResList->PartialDescriptors[index];

            //
            // Notify Hw11 about the resources found
            //
            ndisStatus = HalAddAdapterResource(Hw->Hal, resDesc);
            
            //
            // If the resource was successfully accepted, remember its type
            //
            if (ndisStatus == NDIS_STATUS_SUCCESS)
            {
                switch(resDesc->Type)
                {
                    case CmResourceTypePort:
                        resPort = TRUE;
                        break;

                    case CmResourceTypeInterrupt:
                        resInterrupt = TRUE;
                        break;

                    case CmResourceTypeMemory:
                        resMemory = TRUE;
                        break;
                }
            }
            else if(ndisStatus != NDIS_STATUS_NOT_ACCEPTED)
            {
                //
                // This is an unrecoverable error. The Hw11 probably came across a resource
                // that caused fatal error while being mapped or used. Details about the
                // the failure should be in the event log. Bail out.
                //
                MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to add adapter resource. Status = 0x%08x\n", ndisStatus));
                break;
            }
        }

        //
        // Make sure that the hardware has found its port, interrupt and memory resources.
        // If any of them is missing, fail initialization
        //
        if(!resInterrupt || !resMemory)
        {
            ndisStatus = NDIS_STATUS_RESOURCE_CONFLICT;
            *ErrorCode = NDIS_ERROR_CODE_RESOURCE_CONFLICT;
            
            if(!resPort)
                *ErrorValue = ERRLOG_NO_IO_RESOURCE;
            else if(!resInterrupt)
                *ErrorValue = ERRLOG_NO_INTERRUPT_RESOURCE;
            else 
                *ErrorValue = ERRLOG_NO_MEMORY_RESOURCE;            
            break;
        }
    } while(FALSE);

    return ndisStatus;


}
Пример #16
0
void SocTransport::OnTimer(long tCurrent)
{
	// If we're Advertising broadcast a SERVERINFO message

	if (m_socBroadcast != INVALID_SOCKET) {
		sockaddr_in soca;
		soca.sin_family = AF_INET;
        
#ifdef IPHONE
		soca.sin_addr.s_addr = INADDR_BROADCAST;        
#else
		soca.sin_addr.S_un.S_addr = INADDR_BROADCAST;
#endif

		ServerInfoNetMessage nm(m_szGameName);
		MpTrace("> %s", PszFromNetMessage(&nm));

		// Broadcast to 4 ports to support running 4 clients on the same machine

		for (int i = 0; i < 4; i++) {
			soca.sin_port = htons(SERVERINFO_BROADCAST_PORT + i);
			if (sendto(m_socBroadcast, (char *)&nm, sizeof(nm), 0, (sockaddr *)&soca, sizeof(soca)) == SOCKET_ERROR) {
#ifdef DEBUG
				HostMessageBox(TEXT("sendto err: %s"), PszFromSocError());
#endif
			}
		}
	}

	// If we're searching for hosts check for receipt of a SERVERINFO message

	if (m_socBroadcastListen != INVALID_SOCKET) {
		NetAddress nad;
        
#ifdef IPHONE
		socklen_t cbSocaServer = sizeof(nad);        
#else
		int cbSocaServer = sizeof(nad);
#endif
		ServerInfoNetMessage sinm;
		if (recvfrom(m_socBroadcastListen, (char *)&sinm, sizeof(sinm), 0, (sockaddr *)&nad, &cbSocaServer) == SOCKET_ERROR) {
			int err = WSAGetLastError();
			if (err != WSAEWOULDBLOCK && err != WSAETIMEDOUT) {
#ifdef DEBUG
				HostMessageBox(TEXT("recvfrom err: %s"), PszFromSocError(err));

				// UNDONE: If we discover any errors that would cause us to want to abort the
				// game search operation...

//				if (m_ptcb != NULL)
//					m_ptcb->OnTransportError(ktraeGameSearchFailed);

#endif
				return;
			}
		} else {
			MpTrace("< GAMEHOSTFOUND");

			if (m_fBlockNextGameHost)
				return;

			// Fill in a NetAddress ourselves so we can be sure no random numbers are present

			NetAddress nadT;
			memset(&nadT, 0, sizeof(nadT));
			// HACK: this is the port the game is going to want to connect to
			((sockaddr_in *)&nadT)->sin_port = htons(SERVER_LISTEN_PORT);
			((sockaddr_in *)&nadT)->sin_family = ((sockaddr_in *)&nad)->sin_family;
			((sockaddr_in *)&nadT)->sin_addr = ((sockaddr_in *)&nad)->sin_addr;

			if (m_ptcb != NULL) {
				m_fBlockNextGameHost = true;
				m_ptcb->OnGameHostFound(&nadT);
			}
		}
	}
}
Пример #17
0
NDIS_STATUS
Hw11Initialize(
    __in  PHW                     Hw,
    __in  PHVL                    Hvl,
    __out NDIS_ERROR_CODE*        ErrorCode,
    __out PULONG                  ErrorValue
    )
{
    NDIS_STATUS                 ndisStatus = NDIS_STATUS_SUCCESS;
    Hw->Hvl = Hvl;

    do
    {
        //
        // Initialize the HAL layer
        //
        ndisStatus = HalInitialize(Hw->Hal);
        if (ndisStatus != NDIS_STATUS_SUCCESS) 
        {
            MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("HalInitialize failed. Status = 0x%08x\n", ndisStatus));
            break;
        }
        
        //
        // Read the HW capabilities
        //
        HalGetPowerSaveCapabilities(Hw->Hal, &Hw->MacState.HalPowerSaveCapability);

        //
        // Reset our state to its initial value
        //        
        HwResetSoftwareMacState(Hw);     // Resets the software data
        HwResetSoftwarePhyState(Hw);     // Resets the software data
        NdisZeroMemory(&Hw->Stats, sizeof(NIC_STATISTICS));

        //
        // Clear any stale state from the hardware
        //
        ndisStatus = HwClearNicState(Hw);
        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("HwClearNicState failed. Status = 0x%08x\n", ndisStatus));
            break;
        }

        //
        // Program our new state on the hardware
        //
        ndisStatus = HwSetNicState(Hw);
        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("HwSetNicState failed. Status = 0x%08x\n", ndisStatus));
            break;
        }

        //
        // Initialize the scatter gather DMA with NDIS for send. This also allocates stuff
        // for receive shared memory allocation
        //
        ndisStatus = HwInitializeScatterGatherDma(Hw, ErrorCode, ErrorValue);
        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            break;
        }


    } while (FALSE);


    if (ndisStatus != NDIS_STATUS_SUCCESS)
    {       
        //
        // Deregister the DMA from NDIS
        //
        if (Hw->MiniportDmaHandle != NULL)
        {
            NdisMDeregisterScatterGatherDma(Hw->MiniportDmaHandle);
        }
    }
    
    return ndisStatus;
}
Пример #18
0
Connection *SocTransport::AsyncConnect(NetAddress *pnad)
{
	MpTrace("AsyncConnect(%s)", pnad != NULL ? inet_ntoa(((sockaddr_in *)pnad)->sin_addr) : "loopback");

	Connection *pcon;

	// A NULL pnad means this device is the server and is now trying to
	// connect to itself as a client. Use the LoopbackConnection to satisfy
	// this.

	if (pnad == NULL) {
		pcon = new LoopbackConnection(this);
		Assert(pcon != NULL, "out of memory!");
		if (pcon == NULL)
			return NULL;
		m_fAsyncConnectLoopback = true;

	} else {
		// Create the socket for connecting to the server

		SOCKET soc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
		if (soc == INVALID_SOCKET) {
#ifdef DEBUG
			HostMessageBox(TEXT("socket err: 0x%lx"), PszFromSocError());
#endif
			return NULL;
		}

		// Disable nagle algorithm

		int nTrue = 1;
		setsockopt(soc, IPPROTO_TCP, TCP_NODELAY, (NetBuff)&nTrue, sizeof(int));
                
		// Disable excessive 'lingering' (particularly a problem on PalmOS <=5 which has only 16 sockets)

		linger lngr;
		lngr.l_onoff = 1;
		lngr.l_linger = 0;
		setsockopt(soc, SOL_SOCKET, SO_LINGER, (NetBuff)&lngr, sizeof(lngr));

		// Connect to the server
		// UNDONE: On PalmOS <=5 this occasionally times out after 2 secs. Longer would be better

		if (connect(soc, (const sockaddr *)pnad, sizeof(sockaddr_in)) != 0) {
			switch (WSAGetLastError()) {
			case WSAEHOSTUNREACH:
				HtMessageBox(kfMbWhiteBorder, "Comm Problem", "Host unreachable.");
				break;

			case WSAECONNREFUSED:
				HtMessageBox(kfMbWhiteBorder, "Comm Problem", "Connection refused.");
				break;

			case WSAETIMEDOUT:
				HtMessageBox(kfMbWhiteBorder, "Comm Problem", "Timed out trying to connect to host.");
				break;

			default:
				HtMessageBox(kfMbWhiteBorder, "Comm Problem", "Unable to connect. Error %d", WSAGetLastError());
				break;
			}
			closesocket(soc);
			return NULL;
		}

		pcon = NewConnection(soc);
		if (pcon == NULL) {
			closesocket(soc);
			return NULL;
		}
		m_fAsyncConnectLoopback = false;
	}

	AddConnection(pcon);

	Assert(m_pconAsyncConnect == NULL, "Can only have one pending AsyncConnect at a time");
	m_pconAsyncConnect = pcon;

	return pcon;
}
Пример #19
0
// Write lock on the list must be held
// Returns an entry that can be expired. The caller frees it
PMP_BSS_ENTRY
HelperPortExpireBSSEntry(
    __in  PMP_BSS_LIST           pBSSList,
    __in  ULONGLONG               ullMaxActiveTime,
    __in  ULONGLONG               ullExpireTimeStamp
    )
{
    PLIST_ENTRY         pHead = NULL, pEntry = NULL;
    PMP_BSS_ENTRY      pBSSEntry = NULL;
    BOOLEAN             bFound = FALSE;

    //
    // We can expire an entry that has been around for longer 
    // than this time
    //
    if (ullMaxActiveTime <= ullExpireTimeStamp)
        ullExpireTimeStamp -= ullMaxActiveTime;

    pHead = &(pBSSList->List);
    pEntry = pHead->Flink;
    while(pEntry != pHead) 
    {
        pBSSEntry = CONTAINING_RECORD(pEntry, MP_BSS_ENTRY, Link);
        pEntry = pEntry->Flink;

        NdisAcquireSpinLock(&(pBSSEntry->Lock));

        //
        // If the entry is older than we expected and its not in
        // use, we can expire it
        //
        if (pBSSEntry->HostTimestamp < ullExpireTimeStamp)
        {
            if (NdisInterlockedDecrement(&(pBSSEntry->RefCount)) == 0)
            {
                MpTrace(COMP_SCAN, DBG_LOUD, ("Expiring AP: %02X-%02X-%02X-%02X-%02X-%02X\n", 
                    pBSSEntry->Dot11BSSID[0], pBSSEntry->Dot11BSSID[1], pBSSEntry->Dot11BSSID[2], 
                    pBSSEntry->Dot11BSSID[3], pBSSEntry->Dot11BSSID[4], pBSSEntry->Dot11BSSID[5]));

                MPASSERT(pBSSEntry->pAssocRequest == NULL);
                MPASSERT(pBSSEntry->pAssocResponse == NULL);
                
                //
                // This is the entry we can expire. Remove it from the list.
                //
                NdisReleaseSpinLock(&(pBSSEntry->Lock));
                HelperPortRemoveBSSEntry(pBSSList, pBSSEntry);
                
                bFound = TRUE;
                break;
            }
            else
            {
                // Someone is using the entry, we cannot remove/delete this. Add back
                // a ref and we will delete later on

                // This is subobtimal. Ideally the last person to decrement
                // refcount should delete the entry and not us. Modify to remove
                // the entry from the list, decrement its refcount and only free
                // the memory if the refcount has gone to zero
                NdisInterlockedIncrement(&(pBSSEntry->RefCount));
            }
        }
        NdisReleaseSpinLock(&(pBSSEntry->Lock));
    }

    if (bFound != TRUE)
    {
        pBSSEntry = NULL;
    }
    
    return pBSSEntry;
Пример #20
0
bool SocConnection::Poll()
{
	if (m_fDisconnecting) {
		m_fDisconnecting = false;
		if (m_pccb != NULL)
			m_pccb->OnDisconnect(this);
		return false;
	}

	if (m_soc == INVALID_SOCKET)
		return false;

	// Test if any incoming data is pending

	fd_set fds;
	FD_ZERO(&fds);
	FD_SET(m_soc, &fds);
	TIMEVAL tvTimeout;
	tvTimeout.tv_sec = 0;
	tvTimeout.tv_usec = 0;
	fd_set fdsDummy;
	FD_ZERO(&fdsDummy);
//	MpTrace("m_soc = %d, fds = %ld", (UInt16)m_soc, (UInt32)fds);
	int nSelected = select(((int)m_soc) + 1, &fds, &fdsDummy, &fdsDummy, &tvTimeout);

	if (nSelected == SOCKET_ERROR) {
#ifdef DEBUG
		HostMessageBox(TEXT("select err: %s"), PszFromSocError());
#endif
		return false;
	}

	if (nSelected == 1) {
		NetMessage nm;
		int cb = recv(m_soc, (char *)&nm, sizeof(NetMessage), 0);
//		MpTrace("recv: cb %d", cb);
		if (cb != sizeof(NetMessage)) {
			HandleRecvError();
			return false;
		}
		int cbT = BigWord(nm.cb);
		NetMessage *pnm = (NetMessage *)new byte[cbT];
		if (pnm == NULL) {
			// Data is still pending but we can't do anything about it.
			// Follow the usual course of action (HandleRecvError will close the Connection)

			HandleRecvError();
			return false;
		}
		memcpy(pnm, &nm, sizeof(NetMessage));
		int cbRemaining = cbT - sizeof(NetMessage);

		// UNDONE: this now is a blocking operation until all of the message is
		// received. Better would be to accumulate the pieces of the message in
		// a temp buffer (SocConnection member) until it is complete, in a non-
		// blocking fashion.

		byte *pbT = (byte *)(pnm + 1);
		while (cbRemaining != 0) {
			cbT = recv(m_soc, (char *)pbT, cbRemaining, 0);
			if (cbT == SOCKET_ERROR) {
				int err = WSAGetLastError();
				if (err != WSAEWOULDBLOCK) {
					delete[] pnm;
					HandleRecvError();
					return false;
				}
			}
			pbT += cbT;
			cbRemaining -= cbT;
		}

		if (m_pccb != NULL) {
			// Before calling OnReceive, order in native byte order

			NetMessageByteOrderSwap(pnm, false);

			MpTrace("< %s", PszFromNetMessage(pnm));
			m_pccb->OnReceive(this, pnm);
		}
		delete[] pnm;
	}

	return true;
}
Пример #21
0
// BSS list lock acquired & called at Dispatch
NDIS_STATUS 
HelperPortUpdateBSSEntry(
    __in  PMP_HELPER_PORT        HelperPort,
    __in  PMP_BSS_ENTRY  pBSSEntry,
    __in  PMP_RX_MPDU        pFragment,
    __in  PDOT11_BEACON_FRAME pDot11BeaconPRFrame,
    __in  ULONG           BeaconPRDataLength
    )
{
    NDIS_STATUS         ndisStatus = NDIS_STATUS_SUCCESS;
    PDOT11_MGMT_HEADER  pMgmtPktHeader;
    ULONGLONG           ullHostTimeStamp;
    PVOID               pSavedBeaconPRBuffer = NULL;
    ULONG               uOffsetOfInfoElemBlob = FIELD_OFFSET(DOT11_BEACON_FRAME, InfoElements);
    UCHAR               channel;
    DOT11_PHY_TYPE      PhyType;

    pMgmtPktHeader = (PDOT11_MGMT_HEADER)MP_RX_MPDU_DATA(pFragment);
    NdisGetCurrentSystemTime((PLARGE_INTEGER)&ullHostTimeStamp);
    
    do
    {
        // 
        // Modifying data in the AP entry
        //
        NdisDprAcquireSpinLock(&(pBSSEntry->Lock));

        if (pDot11BeaconPRFrame->Capability.IBSS)
        {
            pBSSEntry->Dot11BSSType = dot11_BSS_type_independent;
        }
        else
        {   
            pBSSEntry->Dot11BSSType = dot11_BSS_type_infrastructure;
        }
        
        //
        // Adhoc station can leave adhoc cell and create a new cell. SoftAPs
        // can move. This means the BSSID can change
        //
        NdisMoveMemory(
            pBSSEntry->Dot11BSSID,
            pMgmtPktHeader->BSSID,
            sizeof(DOT11_MAC_ADDRESS)
            );

        pBSSEntry->HostTimestamp = ullHostTimeStamp;
        pBSSEntry->BeaconTimestamp = pDot11BeaconPRFrame->Timestamp;
        pBSSEntry->BeaconInterval = pDot11BeaconPRFrame->BeaconInterval;
        pBSSEntry->Dot11Capability = pDot11BeaconPRFrame->Capability;
        pBSSEntry->RSSI = pFragment->Msdu->RecvContext.lRSSI;
        pBSSEntry->LinkQuality = pFragment->Msdu->LinkQuality;
        pBSSEntry->ChannelCenterFrequency 
            = pFragment->Msdu->RecvContext.uChCenterFrequency;

        //
        // If signal strength was below our threshold, catch that
        //
        if (pBSSEntry->LinkQuality < HelperPort->RegInfo->RSSILinkQualityThreshold)
        {
            pBSSEntry->LowQualityCount++;
        }
        else
        {
            pBSSEntry->LowQualityCount = 0;
        }

#if 0
        if (pBSSEntry->AssocState == dot11_assoc_state_auth_assoc)
        {
            MpTrace(COMP_ASSOC, DBG_LOUD, ("Received beacon from associated AP: %02X-%02X-%02X-%02X-%02X-%02X\n",
                pMgmtPktHeader->SA[0], pMgmtPktHeader->SA[1], pMgmtPktHeader->SA[2], 
                pMgmtPktHeader->SA[3], pMgmtPktHeader->SA[4], pMgmtPktHeader->SA[5]));
        }
#endif

        //
        // Get channel number at which the frame was received.
        //
        if (Dot11GetChannelForDSPhy(Add2Ptr(pDot11BeaconPRFrame, uOffsetOfInfoElemBlob),
                                    BeaconPRDataLength - uOffsetOfInfoElemBlob, 
                                    &channel) != NDIS_STATUS_SUCCESS)
        {
            channel = pFragment->Msdu->Channel;
        }

        if (channel != 0)
        {
            pBSSEntry->Channel = channel;
        }

        //
        // Get PhyType and PhyId
        //
        PhyType = VNic11DeterminePHYType(HELPPORT_GET_VNIC(HelperPort), 
                                       pBSSEntry->Dot11Capability,
                                       pBSSEntry->Channel);
        if (pBSSEntry->Dot11PhyType != PhyType)
        {
            pBSSEntry->Dot11PhyType = PhyType;
            pBSSEntry->PhyId = BasePortGetPhyIdFromType(HELPPORT_GET_MP_PORT(HelperPort), PhyType);
        }

        if (pMgmtPktHeader->FrameControl.Subtype == DOT11_MGMT_SUBTYPE_BEACON)
        {
            //
            // Increase the beacon frame size if necessary
            //
            if (pBSSEntry->MaxBeaconFrameSize < BeaconPRDataLength)
            {
                MP_ALLOCATE_MEMORY(HELPPORT_GET_MP_PORT(HelperPort)->MiniportAdapterHandle, 
                    &pSavedBeaconPRBuffer, 
                    BeaconPRDataLength,
                    PORT_MEMORY_TAG
                    );
                    
                if (pSavedBeaconPRBuffer == NULL)
                {
                    //
                    // Unable to allocate memory for information elements.
                    // If this is a new AP entry, we wont be adding it to the list.
                    // For existing entries, we end up ignoring the new IE blob
                    //
                    ndisStatus = NDIS_STATUS_RESOURCES;
                    NdisDprReleaseSpinLock(&(pBSSEntry->Lock));
                    break;
                }
                //
                // Delete any old blob buffer
                //
                if (pBSSEntry->pDot11BeaconFrame != NULL)
                {
                    MP_FREE_MEMORY(pBSSEntry->pDot11BeaconFrame);
                }

                pBSSEntry->pDot11BeaconFrame = pSavedBeaconPRBuffer;
                pBSSEntry->MaxBeaconFrameSize = BeaconPRDataLength;
            }

            // Update the beacon
            pBSSEntry->BeaconFrameSize = BeaconPRDataLength;
            
            // Also save this as the IE blob pointer
            pBSSEntry->InfoElemBlobSize = BeaconPRDataLength - uOffsetOfInfoElemBlob;
            pBSSEntry->pDot11InfoElemBlob = (PUCHAR)pBSSEntry->pDot11BeaconFrame + uOffsetOfInfoElemBlob;
            
            //
            // Update/Save the beacon information element block
            //
            NdisMoveMemory(
                pBSSEntry->pDot11BeaconFrame,
                pDot11BeaconPRFrame,
                BeaconPRDataLength
                );
        }
    
        if (pMgmtPktHeader->FrameControl.Subtype == DOT11_MGMT_SUBTYPE_PROBE_RESPONSE)
        {
            //
            // Increase the probe response frame size if necessary
            //
            if (pBSSEntry->MaxProbeFrameSize < BeaconPRDataLength)
            {
                MP_ALLOCATE_MEMORY(HELPPORT_GET_MP_PORT(HelperPort)->MiniportAdapterHandle, 
                    &pSavedBeaconPRBuffer, 
                    BeaconPRDataLength,
                    PORT_MEMORY_TAG
                    );
                    
                if (pSavedBeaconPRBuffer == NULL)
                {
                    //
                    // Unable to allocate memory for information elements.
                    // If this is a new AP entry, we wont be adding it to the list.
                    // For existing entries, we end up ignoring the new IE blob
                    //
                    ndisStatus = NDIS_STATUS_RESOURCES;
                    NdisDprReleaseSpinLock(&(pBSSEntry->Lock));
                    break;
                }
                //
                // Delete any old blob buffer
                //
                if (pBSSEntry->pDot11ProbeFrame != NULL)
                {
                    MP_FREE_MEMORY(pBSSEntry->pDot11ProbeFrame);
                }

                pBSSEntry->pDot11ProbeFrame = pSavedBeaconPRBuffer;
                pBSSEntry->MaxProbeFrameSize = BeaconPRDataLength;
            }
            
            pBSSEntry->ProbeFrameSize = BeaconPRDataLength;

            // Also save this as the IE blob pointer
            pBSSEntry->InfoElemBlobSize = BeaconPRDataLength - uOffsetOfInfoElemBlob;
            pBSSEntry->pDot11InfoElemBlob = (PUCHAR)pBSSEntry->pDot11ProbeFrame + uOffsetOfInfoElemBlob;

            //
            // Update/Save the beacon information element block
            //
            NdisMoveMemory(
                pBSSEntry->pDot11ProbeFrame,
                pDot11BeaconPRFrame,
                BeaconPRDataLength
                );

        }

#if 0
        if (pBSSEntry->AssocState == dot11_assoc_state_auth_assoc)
        {
            MpTrace(COMP_SCAN, DBG_LOUD, ("Received %d for AP %02X-%02X-%02X-%02X-%02X-%02X \n", 
                    pMgmtPktHeader->FrameControl.Subtype,
                    pBSSEntry->Dot11BSSID[0], pBSSEntry->Dot11BSSID[1], pBSSEntry->Dot11BSSID[2], 
                    pBSSEntry->Dot11BSSID[3], pBSSEntry->Dot11BSSID[4], pBSSEntry->Dot11BSSID[5]));
        }
#endif

        //
        // Done with our modification of the AP entry
        //
        NdisDprReleaseSpinLock(&(pBSSEntry->Lock));
        
    } while (FALSE);

    return ndisStatus;
Пример #22
0
/*
    Tx rate adaptation algorithm:
    Preconditions to update tx data rate:
            1) device is in connect state; 
            2)device has sent at least 100 data packets

    retransmitPercentage = (toal retry) / (total packets sent)

    if retransmit percentage <= threshold for rate increase which default to 35%
        if not sending at the highest rate
            if previously came down from higher rate and wait count < wait required
                increase wait count and exit
            else
                if not previously came down from higher rate
                    reset wait required
                else leave wait required unchanged
                increase current tx rate to next higher rate, reset all other counters and exit

    if retransmit percentage >= threshold for roam which default to 350%
        if already send at the lowest rate
            try to roam to a better AP, reset all counters and exit
        else if there are at least fallback skip (which default to 3) lower data rates available
            reduce current tx rate to third lower data rate, reset all counters and exit
        else if current sending at second lowest rate
            set current tx rate to the lowest value, reset all counters and exit
        else fall through to following rate fallback handler

    if retransmit percentage >= threshold for rate fallback which default to 125%
    and not sending at the lowest rate
        if previously came up from lower rate
            double current wait required
        else reset wait required
        reduce current tx rate to next lower value, reset all other counters and exit
*/
VOID 
HwUpdateTxDataRate(
    __in  PHW_MAC_CONTEXT         MacContext
    )
{
    PDOT11_RATE_SET             activeRateSet;
    PHW_RATE_INFO               rateInfo = &MacContext->RateInfo;     // We are not doing per peer rate adaptation
    ULONG                       rateIndex = 0;
    USHORT                      prevTxRate = 0;
    ULONG                       totalRetry = rateInfo->TotalRetryCount;
    ULONG                       totalSend = rateInfo->PacketsSentForTxRateCheck;
    ULONG                       retransmitPercentage = 0;
    OP_RATE_CHANGE_NOTIFICATION rateNotification;

    if (HW_TEST_MAC_CONTEXT_STATUS(MacContext, HW_MAC_CONTEXT_CANNOT_SEND_FLAGS) ||
        !HW_TEST_MAC_CONTEXT_STATUS(MacContext, HW_MAC_CONTEXT_LINK_UP))
    {
        // MAC context wont be sending to a peer. There isnt anything for us to do
        return;
    }

    // Check the send threshold
    if (totalSend < MacContext->Hw->RegInfo.MinPacketsSentForTxRateUpdate)
    {
        return;
    }

    // reset counters
    InterlockedExchange(&rateInfo->TotalRetryCount, 0);
    InterlockedExchange((LONG*)&rateInfo->PacketsSentForTxRateCheck, 0);

    // The active rate set structure needs to be protected
    HW_ACQUIRE_HARDWARE_LOCK(MacContext->Hw, FALSE);

    do
    {
        activeRateSet = &(MacContext->PhyContext[MacContext->OperatingPhyId].ActiveRateSet);
        for (rateIndex = 0; rateIndex < activeRateSet->uRateSetLength; rateIndex++)
        {
            if (rateInfo->CurrentTXDataRate == activeRateSet->ucRateSet[rateIndex])
            {
                prevTxRate = rateInfo->CurrentTXDataRate;
                break;
            }
        }    

        // prevTxRate equals 0 means rateInfo->CurrentTXDataRate 
        // is not in activeRateSet->ucRateSet list
        if (prevTxRate == 0)
        {   
            MpTrace(COMP_MISC, DBG_LOUD, ("Current TX data rate is not in active rate set\n"));
            break;
        }

        retransmitPercentage = totalRetry * 100 / totalSend;

        MpTrace(COMP_TESTING, DBG_TRACE, ("%s: retransmitPercentage=%d(%d/%d), waitCount=%d, "
            "waitRequired=%d, prevRate=%d\n", 
            __FUNCTION__, 
            retransmitPercentage, totalRetry, totalSend, 
            rateInfo->TxRateIncreaseWaitCount, 
            rateInfo->TxRateIncreaseWaitRequired, 
            rateInfo->PrevTxDataRate));

        if (retransmitPercentage <= MacContext->Hw->RegInfo.TxFailureThresholdForRateIncrease)
        {
            // Consider going up
            
            if (rateIndex < activeRateSet->uRateSetLength - 1)
            {
                if ((rateInfo->PrevTxDataRate == activeRateSet->ucRateSet[rateIndex + 1]) &&
                    (rateInfo->TxRateIncreaseWaitCount + 1 < rateInfo->TxRateIncreaseWaitRequired))
                {
                    // I just came down from the rate above me, i dont want to go up yet due to WaitRequired
                    rateInfo->TxRateIncreaseWaitCount++;
                    
                    MpTrace(COMP_TESTING, DBG_TRACE, ("%s: WAIT before increasing Tx rate. retransmitPercentage=%d(%d/%d), "
                        "waitCount=%d, waitRequired=%d, prevRate=%d\n",
                        __FUNCTION__,
                        retransmitPercentage, totalRetry, totalSend, rateInfo->TxRateIncreaseWaitCount, 
                        rateInfo->TxRateIncreaseWaitRequired, rateInfo->PrevTxDataRate));
                }
                else
                {
                    // 1. I came down rate above me and WaitCount >= WaitRequired
                    // 2. I came up from rate below me, no need to wait for additional time
                    if (rateInfo->PrevTxDataRate != activeRateSet->ucRateSet[rateIndex + 1])
                    {
                        // Case 2 above
                        rateInfo->TxRateIncreaseWaitRequired = 1;
                    }
                    else
                    {
                        // Case 1 above
                        /** don't reset TxRateIncreaseWaitRequired as we need to double */
                        /** the value if fallback to the current rate again */
                    }
                    rateInfo->PrevTxDataRate = rateInfo->CurrentTXDataRate;
                    rateInfo->TxRateIncreaseWaitCount = 0;

                    MpTrace(COMP_TESTING, DBG_TRACE, ("%s: increasing Tx data rate from %d to %d. "
                        "retransmitPercentage = %d(%d/%d), waitCount=%d, waitRequired=%d, prevRate=%d\n",
                        __FUNCTION__, 
                        rateInfo->CurrentTXDataRate, activeRateSet->ucRateSet[rateIndex + 1],
                        retransmitPercentage, totalRetry, totalSend,
                        rateInfo->TxRateIncreaseWaitCount, 
                        rateInfo->TxRateIncreaseWaitRequired, 
                        rateInfo->PrevTxDataRate));

                    rateInfo->CurrentTXDataRate = activeRateSet->ucRateSet[rateIndex + 1];
                }
            }
            break;
        }

        if (retransmitPercentage >= MacContext->Hw->RegInfo.TxFailureThresholdForRoam)
        {
            ULONG   rateSkipLevel = MacContext->Hw->RegInfo.TxDataRateFallbackSkipLevel;
            
            // Really large retry count, consider roaming
            
            if (rateIndex == 0)
            {
                // I am sending at the lowest rate. Either roam or disconnect.
                MpTrace(COMP_TESTING, DBG_TRACE, ("%s: too many retransmit happened while "
                    "transmitting at the lowest data rate. Attempting to roam. "
                    "retransmitPercentage=%d(%d/%d), waitCount=%d, waitRequired=%d, prevRate=%d", 
                    __FUNCTION__,
                    retransmitPercentage, totalRetry, totalSend, 
                    rateInfo->TxRateIncreaseWaitCount,
                    rateInfo->TxRateIncreaseWaitRequired, 
                    rateInfo->PrevTxDataRate));

                // Our packets arent going through, jump up to using best data rate &
                // hopefully our packets will go through
                rateInfo->CurrentTXDataRate = activeRateSet->ucRateSet[activeRateSet->uRateSetLength - 1];

                // reset counters
                rateInfo->PrevTxDataRate = 0;
                rateInfo->TxRateIncreaseWaitRequired = 1;
                rateInfo->TxRateIncreaseWaitCount = 0;
                break;
            }
            else if (rateIndex >= rateSkipLevel)
            {
                // try to go down three rates
                MpTrace(COMP_TESTING, DBG_TRACE, ("%s: too many retransmit happened. Reducing Tx rate from %d to %d.\n",
                        __FUNCTION__, 
                        rateInfo->CurrentTXDataRate,
                        activeRateSet->ucRateSet[rateIndex - rateSkipLevel]));

                rateInfo->CurrentTXDataRate = activeRateSet->ucRateSet[rateIndex - rateSkipLevel];
                rateInfo->PrevTxDataRate = 0;
                rateInfo->TxRateIncreaseWaitRequired = 1;
                rateInfo->TxRateIncreaseWaitCount = 0;
                break;
            }
            else if (rateIndex != 1)
            {
                // set tx rate to the lowest rate
                MpTrace(COMP_TESTING, DBG_TRACE, ("%s: too many retransmit happened. Reducing Tx rate from "
                        "%d to lowest %d.\n",
                        __FUNCTION__, 
                        rateInfo->CurrentTXDataRate,
                        activeRateSet->ucRateSet[0]));

                rateInfo->CurrentTXDataRate = activeRateSet->ucRateSet[0];
                rateInfo->PrevTxDataRate = 0;
                rateInfo->TxRateIncreaseWaitRequired = 1;
                rateInfo->TxRateIncreaseWaitCount = 0;
                break;
            }
            else
            {
                // rateIndex equals to 1. this is the same as lowering tx rate by 1 level
                // which is what rate fallback handler does. fall through.
            }
        }

        if ((retransmitPercentage >= MacContext->Hw->RegInfo.TxFailureThresholdForRateFallback) && (rateIndex > 0))
        {
            // consider going down. no need to wait for additional time
            
            if (rateInfo->PrevTxDataRate == activeRateSet->ucRateSet[rateIndex - 1])
            {
                rateInfo->TxRateIncreaseWaitRequired *= 2;
            }
            else
            {
                rateInfo->TxRateIncreaseWaitRequired = 1;
            }
            rateInfo->PrevTxDataRate = rateInfo->CurrentTXDataRate;
            rateInfo->TxRateIncreaseWaitCount = 0;
            
            MpTrace(COMP_TESTING, DBG_TRACE, ("%s: reducing Tx data rate from %d to %d. "
                "retransmitPercentage=%d(%d/%d), waitCount=%d, waitRequired=%d, prevRate=%d\n",
                __FUNCTION__, 
                rateInfo->CurrentTXDataRate, 
                activeRateSet->ucRateSet[rateIndex - 1],
                retransmitPercentage, totalRetry, totalSend, 
                rateInfo->TxRateIncreaseWaitCount, 
                rateInfo->TxRateIncreaseWaitRequired,
                rateInfo->PrevTxDataRate));

            rateInfo->CurrentTXDataRate = activeRateSet->ucRateSet[rateIndex - 1];
            break;
        }
    } while (FALSE);

    HW_RELEASE_HARDWARE_LOCK(MacContext->Hw, FALSE);

    if (prevTxRate != rateInfo->CurrentTXDataRate)
    {
        // Indicate new link speed
        HwIndicateLinkSpeed(MacContext, rateInfo->CurrentTXDataRate);    

        // Indicate change of link speed to the port so that it 
        // can take any necessary action
        rateNotification.Header.Type = NotificationOpRateChange;
        rateNotification.Header.Size = sizeof(OP_RATE_CHANGE_NOTIFICATION);
        rateNotification.Header.pSourceVNic = NULL;

        rateNotification.NewRate = rateInfo->CurrentTXDataRate;
        rateNotification.OldRate = prevTxRate;

        if (rateIndex == 0)
            rateNotification.LowestRate = TRUE;
        else
            rateNotification.LowestRate = FALSE;

        VNic11Notify(MacContext->VNic, &rateNotification);
    }
}
Пример #23
0
NDIS_STATUS
VNic11JoinBSS(
    _In_  PVNIC                   pVNic,
    _In_  PMP_BSS_DESCRIPTION     BSSDescription,
    _In_  ULONG                   JoinFailureTimeout,
    _In_  PORT11_GENERIC_CALLBACK_FUNC CompletionHandler
    )
{
    NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS;
    BOOLEAN fLocked = FALSE;
    BOOLEAN fProcessReqNow = FALSE;
    PVNIC_COMPLETION_CTX pCtx = NULL;
    
    do
    {
        VNicLock(pVNic);
        fLocked = TRUE;

        ndisStatus = VNicCanProcessReqNow(pVNic, &fProcessReqNow);
        if (NDIS_STATUS_SUCCESS != ndisStatus)
        {
            MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d): VNicCanProcessReqNow failed 0x%x\n", VNIC_PORT_NO, ndisStatus));
            break;
        }
        
        if (fProcessReqNow)
        {
            ndisStatus = ALLOC_MEM(pVNic->MiniportAdapterHandle, sizeof(VNIC_COMPLETION_CTX), &pCtx);
            if (NDIS_STATUS_SUCCESS != ndisStatus)
            {
                MpTrace(COMP_HVL, DBG_SERIOUS, ("VNic(%d): Failed to allocate memory for a new completion context \n", VNIC_PORT_NO));

                /*
                    Do not call the station's callback function since the station doesn't 
                    expect to be called back if there is a failure                    
                    */
                break;
            }

            pCtx->CompletionFn = CompletionHandler;
            
            ndisStatus = VNicJoinBSSHelper(pVNic, BSSDescription, JoinFailureTimeout, pCtx);

            if (NDIS_STATUS_PENDING != ndisStatus)
            {
                MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d): VNicJoinBSSHelper completed synchronously %!x!\n", VNIC_PORT_NO, ndisStatus));
                
                /*
                    The call to the hardware completed synchronously. Do not call the station's 
                    callback function.
                    */
                FREE_MEM(pCtx);
                break;
            }    
        }
        else
        {
            /*
                We are not currently active or there are pending operations. Queue the Join request 
                internally
                */
            ndisStatus = VNicQueueJoinRequest(
                        pVNic, 
                        BSSDescription, 
                        JoinFailureTimeout, 
                        CompletionHandler
                        );
            if (NDIS_STATUS_SUCCESS == ndisStatus)
            {
                MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d): Queued the join request \n", VNIC_PORT_NO));
                // Return pending since the request is not going to be completed synchrnously
                ndisStatus = NDIS_STATUS_PENDING;
            }
            else
            {
                MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d): VNicQueueJoinRequest failed %!x!\n", VNIC_PORT_NO, ndisStatus));
            }
        }
    } while (FALSE);
    
    if (fLocked)
    {
        VNicUnlock(pVNic);
    }
    
    return ndisStatus;
}
Пример #24
0
// Scans a set of channels. Called with exclusive access held. Also only called when we have a channel
// to scan.
VOID
HelperPortStartPartialScan(
    _In_  PMP_HELPER_PORT         HelperPort,
    _In_  PMP_SCAN_PARAMETERS     ScanParameters
    )
{
    NDIS_STATUS                 ndisStatus = NDIS_STATUS_SUCCESS;
    ULONG                       i, currentChannelCount;
    PMP_SCAN_CHANNEL_LIST       currentChannelList;

    do
    {
        MpTrace(COMP_SCAN, DBG_LOUD, ("Starting partial scan of %p\n", ScanParameters));
    
        MP_ACQUIRE_PORT_LOCK(HELPPORT_GET_MP_PORT(HelperPort), FALSE);
        // Check if the request should be cancelled
        if (ScanParameters->CancelScan)
        {
            MpTrace(COMP_SCAN, DBG_NORMAL, ("Aborting partial scan for cancelled/old scan request %p\n", ScanParameters));
            ndisStatus = NDIS_STATUS_REQUEST_ABORTED;
        }
        else
        {
            // We are going to send this on the hardware
            ScanParameters->State = SCAN_HARDWARE_SCANNING;
        }
        MP_RELEASE_PORT_LOCK(HELPPORT_GET_MP_PORT(HelperPort), FALSE);

        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            break;
        }

        // Determine the channels to scan. If specified by the port, use those, else
        // use our
        if (ScanParameters->PortScanRequest->ChannelCount != 0)
        {
            currentChannelCount = ScanParameters->PortScanRequest->ChannelCount;
            
            //
            // Populate the channels for this scan with what the port requested
            //
            ScanParameters->VNicScanRequest.ChannelCount = currentChannelCount;
            for (i = 0; i < currentChannelCount; i++)
            {
                ScanParameters->VNicScanRequest.ChannelList[i] = ScanParameters->PortScanRequest->ChannelList[i];
            }
            ScanParameters->VNicScanRequest.PhyId = ScanParameters->PortScanRequest->PhyId;
        }
        else
        {
            currentChannelList = &HelperPort->ScanContext.ScanChannels[ScanParameters->CurrentPhyIndex];
            // We must have atleast one channel in the current phy index that we can scan
            MPASSERT(currentChannelList->ChannelCount > ScanParameters->NextChannelIndex);

            // Determine the number of channels to use for this scan
            currentChannelCount = ScanParameters->MaxChannelCount;

            if ((ScanParameters->NextChannelIndex + currentChannelCount) > 
                    currentChannelList->ChannelCount)
            {
                // We have fewer remaining channels that our MaxChannelCount, adjust the channel count
                currentChannelCount = currentChannelList->ChannelCount 
                                            - ScanParameters->NextChannelIndex;
            }
            
            //
            // Populate the channels for this scan
            //
            ScanParameters->VNicScanRequest.ChannelCount = currentChannelCount;
            for (i = 0; i < currentChannelCount; i++)
            {
                ScanParameters->VNicScanRequest.ChannelList[i] = currentChannelList->ChannelList[ScanParameters->NextChannelIndex + i];
            }
            ScanParameters->VNicScanRequest.PhyId = currentChannelList->PhyId;

            // Next time we start scan at the next channel
            ScanParameters->NextChannelIndex = ScanParameters->NextChannelIndex + currentChannelCount;
        }

        ndisStatus = VNic11StartScan(HELPPORT_GET_VNIC(HelperPort), 
                        &ScanParameters->VNicScanRequest,
                        HelperPortScanCompleteCallback
                        );
        
        if (ndisStatus == NDIS_STATUS_SUCCESS)
        {
            // the function completed synchronously - call the callback ourselves
            HelperPortScanCompleteCallback(HELPPORT_GET_MP_PORT(HelperPort), &ndisStatus);
        }
        else if (NDIS_STATUS_PENDING != ndisStatus)
        {
            MpTrace(COMP_SCAN, DBG_SERIOUS, ("VNic11StartScan failed for channel index %d\n",
                        ScanParameters->NextChannelIndex - currentChannelCount));
            break;
        }
    }
    while (FALSE);   

    if (ndisStatus != NDIS_STATUS_PENDING && ndisStatus != NDIS_STATUS_SUCCESS)
    {
        // We call the complete function
        HelperPortCompletePartialScan(HelperPort, ScanParameters, &ndisStatus);
    }
}