Beispiel #1
0
VOID
HelperPortCompleteScanProcess(
    _In_  PMP_HELPER_PORT         HelperPort,
    _In_  PMP_SCAN_PARAMETERS     ScanParameters,
    _In_  PNDIS_STATUS            CompletionStatus
    )
{
    MpTrace(COMP_SCAN, DBG_NORMAL, ("Completed the scan process of %p for port %p\n", 
        ScanParameters, ScanParameters->RequestingPort));

    MP_ACQUIRE_PORT_LOCK(HELPPORT_GET_MP_PORT(HelperPort), FALSE);
    
    // Clear the active pointer
    MPASSERT(ScanParameters == HelperPort->ScanContext.ActiveScanParameters);
    HelperPort->ScanContext.ActiveScanParameters = NULL;
    ScanParameters->State = SCAN_REQUEST_IN_USE;

    MP_RELEASE_PORT_LOCK(HELPPORT_GET_MP_PORT(HelperPort), FALSE);

    // Now perform the indication
    HelperPortIndicateScanCompletion(HelperPort, ScanParameters, CompletionStatus);

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

    // If another scan is queued, run it now
    HelperPortProcessPendingScans(HelperPort);
}
Beispiel #2
0
VOID
BasePortFlushQueuedTxPackets(
    __in  PMP_PORT                Port
    )
{
    PMP_TX_MSDU                 currentPacket, packetListToComplete = NULL;
    ULONG                       count = 0;
    NDIS_STATUS                 completionStatus = BasePortGetPortStatus(Port);

    // Empty the pending TX queue
    MP_ACQUIRE_PORT_LOCK(Port, FALSE);
    while (!MpPacketQueueIsEmpty(&Port->PendingTxQueue))
    {
        currentPacket = MP_MSDU_FROM_QUEUE_ENTRY(MpDequeuePacket(&Port->PendingTxQueue));
        count++;

        MP_TX_MSDU_NEXT_MSDU(currentPacket) = NULL;
        MP_TX_MSDU_STATUS(currentPacket) = completionStatus;

        MP_TX_MSDU_NEXT_MSDU(currentPacket) = packetListToComplete;
        packetListToComplete = currentPacket;
    }
    MP_RELEASE_PORT_LOCK(Port, FALSE);

    if (packetListToComplete != NULL)
    {
        BasePortCompleteFailedPackets(Port, 
            packetListToComplete,
            0
            );
    }    
}
Beispiel #3
0
NDIS_STATUS
HelperPortScanExAccessCallback(
    _In_  PMP_PORT                Port, 
    _In_  PVOID                   Ctx
    )
{
    PMP_SCAN_PARAMETERS         scanParameters = (PMP_SCAN_PARAMETERS)Ctx;
    PMP_HELPER_PORT             helperPort = MP_GET_HELPPORT(Port);
    BOOLEAN                     performScan = TRUE;
    
    // The cancellation here is handled specially. Since we cannot abort
    // a request for exclusive access, its possible that our exclusive
    // access request gets honored after we have cancelled a scan

    HelperPortExclusiveAccessGranted(helperPort);
    
    MP_ACQUIRE_PORT_LOCK(HELPPORT_GET_MP_PORT(helperPort), FALSE);
    if ((scanParameters->State != SCAN_EXCLUSIVE_ACCESS_QUEUED) ||
        (scanParameters->CancelScan))
    {
        // The request has been cancelled and would get completed
        MpTrace(COMP_SCAN, DBG_NORMAL, ("Ignored exclusive access for cancelled/old scan request %p\n", scanParameters));
        performScan = FALSE;
    }
    else
    {
        // Move forward with the scan
        scanParameters->State = SCAN_EXCLUSIVE_ACCESS_ACQUIRED;
    }
    MP_RELEASE_PORT_LOCK(HELPPORT_GET_MP_PORT(helperPort), FALSE);

    if (performScan)
    {
        HelperPortStartPartialScan(helperPort, scanParameters);
    }
    else
    {
        // Release exclusive access back to the HW
        HelperPortReleaseExclusiveAccess(helperPort);

        // Free the scan request
        HelperPortScanParametersReleaseRef(helperPort, scanParameters);
    }
    return NDIS_STATUS_SUCCESS;
}
Beispiel #4
0
VOID
HelperPortNotify(
    _In_  PMP_PORT        Port,
    PVOID               Notif
    )
{
    PMP_HELPER_PORT             helperPort = MP_GET_HELPPORT(Port);
    PNOTIFICATION_DATA_HEADER   notifyHeader = (PNOTIFICATION_DATA_HEADER)Notif;

    switch (notifyHeader->Type)
    {
        case NotificationOpLinkState:
        {
            POP_LINK_STATE_NOTIFICATION pMediaNotif = (POP_LINK_STATE_NOTIFICATION)Notif;
            
            MP_ACQUIRE_PORT_LOCK(Port, FALSE);
            
            if (pMediaNotif->MediaConnected)
            {
                MpTrace(COMP_SCAN, DBG_NORMAL, ("Incrementing connect count for CONNECT. current = %d\n", helperPort->ScanContext.MediaConnectedCount));
                MPASSERT(helperPort->ScanContext.MediaConnectedCount < MP_MAX_NUMBER_OF_PORT);
                helperPort->ScanContext.MediaConnectedCount++;
            }
            else
            {
                MpTrace(COMP_SCAN, DBG_NORMAL, ("Decrementing connect count for DISCONNECT. current = %d\n", helperPort->ScanContext.MediaConnectedCount));
                MPASSERT(helperPort->ScanContext.MediaConnectedCount > 0);
                helperPort->ScanContext.MediaConnectedCount--;
            }
            
            MP_RELEASE_PORT_LOCK(Port, FALSE);
            break;
        }
        default:
            break;
    }
}
Beispiel #5
0
VOID
BasePortTransmitQueuedPackets(
    __in  PMP_PORT                Port,
    __in  ULONG                   SendFlags
    )
{
    PMP_TX_MSDU                 currentPacket, prevPacketToForward = NULL, packetListToForward = NULL;
    ULONG                       count = 0, numPktToFwd = 0;
    NDIS_STATUS                 ndisStatus;
    PMP_TX_MSDU                 packetListToFail = NULL;

    // PORT_LOCK must be held

    // If I am pausing, this flag is set. We would not
    // be processing any pending packets. These packets get flushed on a pause
    
    // then not process these pending packets
    if (MP_TEST_PORT_STATUS(Port, MP_PORT_CANNOT_SEND_MASK))
    {   
        //
        // We dont do anything
        //
        MpTrace(COMP_SEND, DBG_NORMAL, ("Dropping sends as port should not be sending\n"));                
        
        return;
    }

    while ((!MpPacketQueueIsEmpty(&Port->PendingTxQueue) &&
            (count < MAX_SEND_MSDU_TO_PROCESS)))
    {
        //
        // Dequeue the first packet from the list
        //
        currentPacket = MP_MSDU_FROM_QUEUE_ENTRY(MpDequeuePacket(&Port->PendingTxQueue));
        count++;

        // 
        // Let the port pre-process the packets. We only let one
        // packet to get processed at a time
        //
        MP_TX_MSDU_NEXT_MSDU(currentPacket) = NULL;
        MP_TX_MSDU_STATUS(currentPacket) = NDIS_STATUS_SUCCESS;
        ndisStatus = Port11NotifySend(Port, currentPacket, SendFlags);
        if (ndisStatus == NDIS_STATUS_SUCCESS)
        {
            //
            // Look at the per-packet status values
            //
            ndisStatus = MP_TX_MSDU_STATUS(currentPacket);
            if (ndisStatus == NDIS_STATUS_SUCCESS)
            {
                //
                // Port is fine with processing these packets. Let us check if we can
                // continue sending this down. We only check with the VNIC
                //
                if (VNic11CanTransmit(PORT_GET_VNIC(Port)) == FALSE)
                {
                    //
                    // Some reason we cannot submit this packet to the
                    // HW yet. Queue it in the pending Tx queue
                    //
                    ndisStatus = NDIS_STATUS_PENDING;

                    //
                    // In this case we indicate the packet to the Port again
                    // the next time we attempt to send. Ensure that the port
                    // can handle that
                    //
                }
            }
        }
        else
        {
            //
            // Port returned PENDING or FAILURE for the packet list. We wont
            // be sending any of these packets
            //
        }
        
        //
        // All the above processing would give us one of the following status codes
        //
        // NDIS_STATUS_SUCCESS - The packets can be processed furthers. In this case
        //                       we forward the packet to the lower layer
        // NDIS_STATUS_PENDING - This packet should not be sent now, but can be sent later
        //                       In this case we requeue the packet and stop processing
        //                       further packets
        // NDIS_STATUS_FAILURE or anything other failure status
        //                     - The packet is not sent and we continue processing
        //                       other packets
        if (ndisStatus == NDIS_STATUS_SUCCESS)
        {
            numPktToFwd++;
            
            // Add this to the end of the chain we are forwarding to the HW
            if (packetListToForward == NULL)
            {
                packetListToForward = currentPacket;
            }
            else
            {
                MP_TX_MSDU_NEXT_MSDU(prevPacketToForward) = currentPacket;
            }
            prevPacketToForward = currentPacket;

            //
            // Increment the counter for the number of packets we have submitted 
            // to the hardware. This would block the port from pausing, etc
            //
            PORT_INCREMENT_PNP_REFCOUNT(Port);
        }
        else if (ndisStatus == NDIS_STATUS_PENDING)
        {
            //
            // Put the packet back at the head of the packet queue. To avoid out of
            // order delivery we dont go forward and give any more packets to the 
            // lower layer 
            //
            MpQueuePacketPriority(&Port->PendingTxQueue, QUEUE_ENTRY_FROM_MP_MSDU(currentPacket));
            break;
        }
        else
        {
            //
            // Put this packet in the list of packets to be failed
            //
            MpTrace(COMP_SEND, DBG_NORMAL, ("Port or VNic failed sends with status 0x%08x\n", ndisStatus));
            MP_TX_MSDU_STATUS(currentPacket) = ndisStatus;
            MP_TX_MSDU_NEXT_MSDU(currentPacket) = packetListToFail;
            packetListToFail = currentPacket;
        }

    }

    if ((packetListToForward != NULL) || (packetListToFail != NULL))
    {
        // Forward this list to the VNIC
        MP_RELEASE_PORT_LOCK(Port, NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags));
        if (packetListToForward != NULL)
        {
            VNic11SendPackets(PORT_GET_VNIC(Port), packetListToForward, numPktToFwd, SendFlags);
        }
        
        //
        // Complete the failed packets
        //
        if (packetListToFail != NULL)
        {
            BasePortCompleteFailedPackets(Port, 
                packetListToFail,
                NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags) ? NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL : 0
                );
        }
        
        MP_ACQUIRE_PORT_LOCK(Port, NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags));
    }
}
Beispiel #6
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
        );
    }

}
Beispiel #7
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
        );
    }
}
Beispiel #8
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);
    }
}        
Beispiel #9
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);        
    }

}
Beispiel #10
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;
}
Beispiel #11
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
        );
    }
}
Beispiel #12
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);
    }
}