Esempio n. 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);
}
Esempio n. 2
0
// First disable interrupts and then deregister interrupts
VOID
Hw11Stop(
    __in  PHW                     Hw,
    __in  NDIS_HALT_ACTION        HaltAction
    )
{
    UNREFERENCED_PARAMETER(HaltAction);
    HW_ACQUIRE_HARDWARE_LOCK(Hw, FALSE);
    HW_SET_ADAPTER_STATUS(Hw, HW_ADAPTER_HALTING);
    HW_RELEASE_HARDWARE_LOCK(Hw, FALSE);

    //
    // Deregister interrupts. We must disable them before deregistering interrupts
    //
//    MpTrace(COMP_TESTING, DBG_SERIOUS, ("Hw11Stop \n"));    
    HwDisableInterrupt(Hw, HW_ISR_TRACKING_HWSTOP);
    HwDeregisterInterrupt(Hw);

    // There must be no pending operations at this time
    MPASSERT(Hw->AsyncFuncRef == 0);
    
    //
    // Ensure that we have stop beaconing
    //
    Hw->MacState.BeaconEnabled = FALSE;
    Hw->MacState.BSSStarted = FALSE;

    //
    // Flush all the MSDU in the reassembly line
    //
    HwFlushMSDUReassemblyLine(Hw);

    // Stop everything in the H/W (We may restart things for context switches, etc)
    HalStop(Hw->Hal);
}
Esempio n. 3
0
//
// Reset Step 1 - Cleanup any "pending" operations
//
VOID
Hw11NdisResetStep1(
    __in  PHW                     Hw
    )
{
    NDIS_STATUS                 ndisStatus = NDIS_STATUS_SUCCESS;

    // if we are being reset because our sends are hung, we do not want to assert. however
    // if sends are not the cause, we do want to assert.
    if (!Hw11ArePktsPending(Hw))
    {
        MPASSERT(FALSE);
    }
        
    //
    // Set state as in reset
    //
    HW_ACQUIRE_HARDWARE_LOCK(Hw, FALSE);
    HW_SET_ADAPTER_STATUS(Hw, HW_ADAPTER_IN_RESET);
    HW_RELEASE_HARDWARE_LOCK(Hw, FALSE);

    //
    // Now cleanup everything
    //

    // Cancel scan (if it is running)
    HwCancelScan(Hw);
    
    // Wait for pending operations in the hardware to finish
    HW_WAIT_FOR_ACTIVE_OPERATIONS_TO_FINISH(Hw);

    // Wait for active sends to be finish
    HW_WAIT_FOR_ACTIVE_SENDS_TO_FINISH(Hw);

    // Disable interrupts
    HwDisableInterrupt(Hw, HW_ISR_TRACKING_NDIS_RESET);

    ndisStatus = HalResetStart(Hw->Hal);
    MPASSERT(ndisStatus == NDIS_STATUS_SUCCESS);

    HalStop(Hw->Hal);    

    HwFlushSendEngine(Hw, FALSE);
    
    // Dont wait for pending receives here. They may be stuck in protocols on
    // sends & the sends may be queued in the ports. That would cause a deadlock
}
Esempio n. 4
0
VOID 
MPReturnNetBufferLists(
    NDIS_HANDLE             MiniportAdapterContext,
    PNET_BUFFER_LIST        NetBufferLists,
    ULONG                   ReturnFlags
    )
{
    PADAPTER                    adapter = (PADAPTER)MiniportAdapterContext;
    PMP_PORT                    destinationPort = NULL;
    PNET_BUFFER_LIST            currentNetBufferList = NetBufferLists, nextNetBufferList;

    //
    // We increment the port list refcount. This would avoid a pause from finishing
    // while we are processing this NBL and that ensures that the port list does not
    // change
    //    
    MP_INCREMENT_PORTLIST_REFCOUNT(adapter);

    //
    // Walk the chain of netbuffer lists
    //
    while (currentNetBufferList != NULL)
    {
        // 
        // Currently we return 1 NET_BUFFER_LIST at a time since we may be getting
        // back NET_BUFFER_LISTS indicated by different ports on 1 call. 
        // This can be optimized
        //        
        nextNetBufferList = NET_BUFFER_LIST_NEXT_NBL(currentNetBufferList);
        NET_BUFFER_LIST_NEXT_NBL(currentNetBufferList) = NULL;
        
        destinationPort = MP_NBL_SOURCE_PORT(currentNetBufferList);
        MPASSERT(destinationPort != NULL);
        
        //
        // Pass it to the appropriate port for processing
        //
        Port11HandleReturnNetBufferLists(
            destinationPort,
            currentNetBufferList,
            ReturnFlags
            );

        currentNetBufferList = nextNetBufferList;
    }

    //
    // We were protecting the port list only until we hand it to the port. After this point, the port
    // is responsible for ensuring that it does not let the port get deleted while
    // it has packets pending on it
    //
    MP_DECREMENT_PORTLIST_REFCOUNT(adapter);

}
Esempio n. 5
0
VOID
HelperPortTerminateBSSList(
    __in  PMP_HELPER_PORT         HelperPort
    )
{
    PMP_BSS_LIST                BSSList = &(HelperPort->BSSList);

    MPASSERT(IsListEmpty(&(BSSList->List)));
    
    MP_FREE_READ_WRITE_LOCK(&(BSSList->ListLock));
Esempio n. 6
0
VOID
Hw11Terminate(
    __in  PHW                     Hw
    )
{
    //
    // Deregister the DMA from NDIS
    //
    if (Hw->MiniportDmaHandle != NULL)
    {
        NdisMDeregisterScatterGatherDma(Hw->MiniportDmaHandle);
    }

    //
    // Cancel all other timers (these are all stopped already)
    //
    MPASSERT(NdisCancelTimerObject(Hw->ScanContext.Timer_Scan) == FALSE);
    MPASSERT(NdisCancelTimerObject(Hw->PhyState.Timer_Doze) == FALSE);
    MPASSERT(NdisCancelTimerObject(Hw->PhyState.Timer_Awake) == FALSE);

}
Esempio n. 7
0
VOID 
MPCancelSendNetBufferLists(
    NDIS_HANDLE             MiniportAdapterContext,
    PVOID                   CancelId
    )
{
    // TODO: Unsure how to identify which port the packets have been
    // sent on
    UNREFERENCED_PARAMETER(MiniportAdapterContext);
    UNREFERENCED_PARAMETER(CancelId);
    MPASSERT(FALSE);
}
Esempio n. 8
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;
    }
}
Esempio n. 9
0
#if DBG
NDIS_STATUS
HelperPortCheckForExtraRef(
    __in PMP_HELPER_PORT         HelperPort
    )
{
    MP_RW_LOCK_STATE          LockState;
    PLIST_ENTRY         pListEntry;
    PMP_BSS_ENTRY      pBSSEntry = NULL;
    PMP_BSS_LIST       pDiscoveredBSSList = &(HelperPort->BSSList);
    LIST_ENTRY          TempList;

    //
    // Entries that are currently in use (eg for connection)
    // we cannot flush and instead would put in the temporary queue
    //
    InitializeListHead(&TempList);
    
    MP_ACQUIRE_WRITE_LOCK(&(HelperPort->BSSList.ListLock), &LockState);
        
    while (!IsListEmpty(&(pDiscoveredBSSList->List)))
    {
        pListEntry = RemoveHeadList(&(pDiscoveredBSSList->List));
        pBSSEntry = CONTAINING_RECORD(pListEntry, MP_BSS_ENTRY, Link);

        //
        // Check that the BSS entry does not have an extra ref count
        //
        MPASSERT(pBSSEntry->RefCount <= 1);
        InsertTailList(&TempList, pListEntry);
    }
    pDiscoveredBSSList->NumOfBSSEntries = 0;

    //
    // Restore entries that are in use
    //
    while (!IsListEmpty(&TempList))
    {
        pListEntry = RemoveHeadList(&TempList);

        InsertTailList(&(pDiscoveredBSSList->List), pListEntry);
        pDiscoveredBSSList->NumOfBSSEntries++;
    }
    
    MP_RELEASE_WRITE_LOCK(&(HelperPort->BSSList.ListLock), &LockState);

    return NDIS_STATUS_SUCCESS;
Esempio n. 10
0
NDIS_STATUS
HwSetChannel(
    _In_  PHW                     Hw,
    _In_  ULONG                   PhyId,
    _In_  UCHAR                   Channel
    )
{
    // Must only be called for the active phy
    MPASSERT(PhyId == Hw->PhyState.OperatingPhyId);

    // When setting the channel, we dont check if we are not already on that 
    // channel. This is because this may be called after setting a PhyID and
    // that does not necessarily set the channel

    HW_ACQUIRE_HARDWARE_LOCK(Hw, FALSE);
    HW_SET_ADAPTER_STATUS(Hw, HW_ADAPTER_IN_CHANNEL_SWITCH);
    HW_RELEASE_HARDWARE_LOCK(Hw, FALSE);

    // Wait for active send threads to finish. We dont wait
    // for anything else on an HAL reset since some of those
    // operations themselves may be causing the reset (Eg. channel
    // switch of a scan)
    HW_WAIT_FOR_ACTIVE_SENDS_TO_FINISH(Hw);
//    MpTrace(COMP_TESTING, DBG_SERIOUS, ("HwSetChannel \n"));    
    HwDisableInterrupt(Hw, HW_ISR_TRACKING_CHANNEL);

    // Flush the sends
    HwFlushSendEngine(Hw, FALSE);

    HalSwitchChannel(Hw->Hal, 
        PhyId,
        Channel, 
        FALSE
        );

    HwResetSendEngine(Hw, FALSE);
    HwResetReceiveEngine(Hw, FALSE);
    HalStartReceive(Hw->Hal);
//    MpTrace(COMP_TESTING, DBG_SERIOUS, ("HwSetChannel \n"));    
    HwEnableInterrupt(Hw, HW_ISR_TRACKING_CHANNEL);

    HW_CLEAR_ADAPTER_STATUS(Hw, HW_ADAPTER_IN_CHANNEL_SWITCH);

    return NDIS_STATUS_SUCCESS;
}
Esempio n. 11
0
VOID
HelperPortTerminateScanContext(
    _In_  PMP_HELPER_PORT         HelperPort
    )
{
    PMP_SCAN_PARAMETERS         scanParameters = NULL;

    ULONG                       i;

    // There can be scan requests around if we were waiting for exclusive access
    // for a request and it did not get satisfied
    if (HelperPort->ScanContext.ParametersCount != 0)
    {
        // We may have scan requests structures allocated, waiting for exclusive access
        // but that is never going to get satisfied. Free the requests
        for (i = 0; i < MP_MAX_NUMBER_OF_PORT; i++)
        {
            scanParameters = &HelperPort->ScanContext.ScanParameters[i];
            if (scanParameters->State != SCAN_EMPTY_REQUEST)
            {
                // The only condition in which this is OK is when we are waiting for 
                // an exclusive access
                MPASSERT(scanParameters->UsageCount == 1);
                HelperPortScanParametersReleaseRef(HelperPort, scanParameters);
            }
        }        
    }

    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;
        }
    }
}
Esempio n. 12
0
/*
    NOTE
    This packet gives up the VNIC lock before calling into the hardware. The VNIC state might get
    changed during the course of the call
    */
VOID
VNicSendPktsToHw(    
    _In_ PVNIC                   pVNic,
    _In_ ULONG                   ulNumPkts,
    _In_ PMP_TX_MSDU             PacketList,
    _In_ ULONG                   SendFlags
    )
{
    BOOLEAN fDispatchLevel = SendFlags & NDIS_SEND_FLAGS_DISPATCH_LEVEL ? TRUE : FALSE;
    PMP_TX_MSDU currentPacket = NULL;
    ULONG myCount = 0;

    currentPacket = PacketList;
    while (currentPacket != NULL)
    {
        myCount++;
        currentPacket = MP_TX_MSDU_NEXT_MSDU(currentPacket);
    }
    MPASSERT(myCount == ulNumPkts);

    ASSERT(VNicIsLocked(pVNic));
    ASSERT(VNicIsActive(pVNic));
    
    MpTrace(COMP_HVL, DBG_LOUD, ("VNic(%d): Sending %d packets to the hardware \n", VNIC_PORT_NO, ulNumPkts));

    /*
        We can call the hardware for sending packets. We need to increment the context 
        switch ref count to avoid becoming inactive. The context switch ref count will be 
        decremented when we receive the send completionAlso we need to give up our lock 
        before calling the hardware. 
        */
    VNicIncCtxSRef(pVNic, ulNumPkts, REF_SEND_PKTS);

    // we also need to keep track of the sends outstanding to the hardware
    VNicIncOutstandingSends(pVNic, ulNumPkts);
    
    _Analysis_assume_lock_held_((& pVNic->Lock)->SpinLock);
    VNicUnlockAtDispatch(pVNic, fDispatchLevel);
    
    Hw11SendPackets(pVNic->pvHwContext, PacketList, SendFlags);

    VNicLockAtDispatch(pVNic, fDispatchLevel);
}
Esempio n. 13
0
VOID
HwPhyProgramWorkItem(
    PVOID                   Context,
    NDIS_HANDLE             NdisIoWorkItemHandle
    )
{
    NDIS_STATUS                 ndisStatus = NDIS_STATUS_SUCCESS;
    PHW                         hw = (PHW)Context;
    HW_GENERIC_CALLBACK_FUNC    completionHandler = NULL;
    PHW_PHY_CONTEXT             newPhyContext = NULL;
    PHW_MAC_CONTEXT             completeContext = NULL;

    if (NULL == hw)
    {
        MPASSERT(hw);
        return;
    }

    newPhyContext = hw->PhyState.NewPhyContext;

    UNREFERENCED_PARAMETER(NdisIoWorkItemHandle);

    ndisStatus = HwSetPhyContext(hw, 
                    hw->PhyState.DestinationPhyId, 
                    newPhyContext
                    );

    // Complete the phy programming
    completionHandler = hw->PhyState.PendingPhyProgramCallback;
    completeContext = hw->PhyState.PhyProgramMacContext;
    hw->PhyState.PendingPhyProgramCallback = NULL;

    // Remove the extra ref. We do this before the workitem call since otherwise
    // if from the completion handler context the upper layer calls back into us, we 
    // could deadlock (Hw11CtxSStart is one function that can deadlock)
    HW_DECREMENT_ACTIVE_OPERATION_REF(hw);

    // Invoke the completion handler
    completionHandler(hw, completeContext, &ndisStatus);
}
Esempio n. 14
0
VOID
Sta11TerminatePort(
    _In_  PMP_PORT                Port
    )
{
    PMP_EXTSTA_PORT             extStaPort = MP_GET_STA_PORT(Port);

    //
    // We should have been paused and have already
    // stopped periodic scanning. Ensure that that is the case
    //
    MPASSERT(STA_TEST_SCAN_FLAG(extStaPort, STA_STOP_PERIODIC_SCAN));

    //
    // Cleanup all the connection state
    //
    StaResetConnection(extStaPort, FALSE);

    // Cleanup station configuration
    StaInitializeStationConfig(extStaPort);

    // Cleanup the AdHoc station list
    StaResetAdHocStaInfo(extStaPort, TRUE);
}
Esempio n. 15
0
NDIS_STATUS
MPReset(
    NDIS_HANDLE             MiniportAdapterContext,
    PBOOLEAN                AddressingReset
    )
{
    PADAPTER                    adapter = (PADAPTER)MiniportAdapterContext;
    NDIS_STATUS                 ndisStatus = NDIS_STATUS_PENDING;
    NDIS_HANDLE                 workitemHandle;

    *AddressingReset = TRUE;
    
#if DBG
    if (adapter->Debug_BreakOnReset)
    {
        DbgPrint("Received NdisReset\n");
        DbgBreakPoint();
    }
#endif

    do
    {
        //
        // Set the flag so that other routines stop proceeding
        //
        MP_SET_ADAPTER_STATUS(adapter, MP_ADAPTER_IN_RESET);
        
        //
        // If our halt handler has been called, we should not reset
        //
        if (MP_TEST_ADAPTER_STATUS(adapter, MP_ADAPTER_HALTING))
        {
            MPASSERT(FALSE);    // Would be an interesting scenario to investigate
            ndisStatus = NDIS_STATUS_SUCCESS;
            break;
        }

        //
        // Handle the reset asynchronously since we can be called at either dispatch
        // or passive IRQL
        //
        workitemHandle = NdisAllocateIoWorkItem(adapter->MiniportAdapterHandle);
        if(workitemHandle == NULL)
        {
            MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to allocate Reset workitem\n"));
            NdisWriteErrorLogEntry(adapter->MiniportAdapterHandle,
                NDIS_ERROR_CODE_OUT_OF_RESOURCES,
                0
                );
            ndisStatus = NDIS_STATUS_RESOURCES;
            break;
        }

        // Queue the workitem
        NdisQueueIoWorkItem(workitemHandle, 
            MpResetWorkItem,
            adapter
            );

    } while (FALSE);   

    if (ndisStatus != NDIS_STATUS_PENDING)
    {
        // Something failed, clear the in reset flag
        MP_CLEAR_ADAPTER_STATUS(adapter, MP_ADAPTER_IN_RESET);
    }
    return ndisStatus;
}
Esempio n. 16
0
NDIS_STATUS
HwResetHAL(
    __in  PHW                     Hw,
    __in  PHW_HAL_RESET_PARAMETERS ResetParams,
    __in  BOOLEAN                 DispatchLevel
    )
{
    UNREFERENCED_PARAMETER(ResetParams);
    UNREFERENCED_PARAMETER(DispatchLevel);

    MPASSERT(!DispatchLevel);

    // Since we wait, we cannot be called at dispatch    
    HW_ACQUIRE_HARDWARE_LOCK(Hw, FALSE);
    HW_SET_ADAPTER_STATUS(Hw, HW_ADAPTER_HAL_IN_RESET);
    HW_RELEASE_HARDWARE_LOCK(Hw, FALSE);

    // Wait for active send threads to finish. We dont wait
    // for anything else on an HAL reset since some of those
    // operations themselves may be causing the reset (Eg. channel
    // switch of a scan)
    HW_WAIT_FOR_ACTIVE_SENDS_TO_FINISH(Hw);
    HwDisableInterrupt(Hw, HW_ISR_TRACKING_HAL_RESET);

    if (ResetParams->FullReset)
    {
        // Perform a full reset of the HW
        HalResetStart(Hw->Hal);

        HalStop(Hw->Hal);    

        // Reset the send and receive engine
        HwWaitForPendingReceives(Hw, NULL);
        HwResetSendEngine(Hw, FALSE);
        HwResetReceiveEngine(Hw, FALSE);
        // Remove old keys, etc
        HwClearNicState(Hw);
        
        // Reset our MAC & PHY state
        HwResetSoftwareMacState(Hw);
        HwResetSoftwarePhyState(Hw);

        HalStart(Hw->Hal, TRUE);
        
        // Push the new state on the hardware
        HwSetNicState(Hw);

        HalResetEnd(Hw->Hal);
    }
    else
    {
        // TODO: Currently we are overloading the HalSwitchChannel API for doing a HalReset
        HalSwitchChannel(Hw->Hal, 
            Hw->PhyState.OperatingPhyId,
            HalGetPhyMIB(Hw->Hal, Hw->PhyState.OperatingPhyId)->Channel, 
            FALSE
            );

        HwResetReceiveEngine(Hw, FALSE);
        HwResetSendEngine(Hw, FALSE);
        HalStartReceive(Hw->Hal);
    }
    HwEnableInterrupt(Hw, HW_ISR_TRACKING_HAL_RESET);

    HW_CLEAR_ADAPTER_STATUS(Hw, HW_ADAPTER_HAL_IN_RESET);

    return NDIS_STATUS_SUCCESS;
}
Esempio n. 17
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
        );
    }
}
Esempio n. 18
0
VOID
VNic11SendPackets(
    __in PVNIC                   pVNic,
    __in PMP_TX_MSDU             PacketList,
    __in ULONG                   ulNumPkts,
    __in ULONG                   SendFlags
    )
{
    BOOLEAN fDispatchLevel = SendFlags & NDIS_SEND_FLAGS_DISPATCH_LEVEL ? TRUE : FALSE;
    BOOLEAN fFailSends = FALSE;
#if DBG
    PMP_TX_MSDU             currentPacket;
    ULONG                   myCount = 0;

    currentPacket = PacketList;
    while (currentPacket != NULL)
    {
        myCount++;
        currentPacket = MP_TX_MSDU_NEXT_MSDU(currentPacket);
    }

    MPASSERT(myCount == ulNumPkts);
#endif

    VNicLockAtDispatch(pVNic, fDispatchLevel);

    do
    {
        if (VNicIsInReset(pVNic))
        {
            MpTrace(COMP_HVL, DBG_NORMAL, ("VNIC(%d) is in reset. Failing %d sends. \n", VNIC_PORT_NO, ulNumPkts));
            fFailSends = TRUE;
            break;
        }
        
        if (VNicIsActive(pVNic) && Hw11CanTransmit(pVNic->pvHwContext) && (0 == PktQueueDepth(&pVNic->TxQueue)))
        {        
            VNicSendPktsToHw(pVNic, ulNumPkts, PacketList, SendFlags);
        }
        else
        {
            /*
                We are either 
                a. not currently active or 
                b. the packets cannot be submitted to the hardware or
                c. there are packets pending in the send queue already
                
                Queue the send requests internally
                */
            VNicQueueSendRequests(pVNic, ulNumPkts, PacketList);
        }
    } while (FALSE);
    
    VNicUnlockAtDispatch(pVNic, fDispatchLevel);

    if (fFailSends)
    {
        Port11SendCompletePackets(pVNic->pvPort, PacketList, SendFlags);
    }
    
    return;
}
Esempio n. 19
0
VOID
BasePortIndicateReceivePackets(
    __in  PMP_PORT                Port,
    __in  PMP_RX_MSDU             PacketList,
    __in  ULONG                   ReceiveFlags
    )
{
    NDIS_STATUS                 ndisStatus = NDIS_STATUS_SUCCESS;
    PMP_RX_MSDU                 currentPacket = PacketList, nextPacket;
    PMP_RX_MSDU                 packetListToIndicate = NULL, prevPacketToIndicate = NULL;
    PMP_RX_MSDU                 packetListToReturn = NULL, prevPacketToReturn = NULL;
    PNET_BUFFER_LIST            nblChainToIndicate;
    ULONG                       indicateCount = 0;
    ULONG                       returnCount = 0;

    //
    // Currently the lower layer only indicates single MSDUs. We cannot handle
    // receiving more than one MSDU since we break the chain that the HW provides
    // and that is not acceptable in the RESOURCES case
    // 
    MPASSERT(MP_RX_MSDU_NEXT_MSDU(currentPacket) == NULL);
    
    
    // Process each of the packets internally
    while (currentPacket != NULL)
    {
        nextPacket = MP_RX_MSDU_NEXT_MSDU(currentPacket);

        MP_RX_MSDU_NEXT_MSDU(currentPacket) = NULL;
       
        do
        {
            //
            // Pass the packet to the port to determine if this 
            // packet should be indicated up to the OS or not
            //
            ndisStatus = Port11NotifyReceive(Port, currentPacket, ReceiveFlags);            
            if (ndisStatus == NDIS_STATUS_SUCCESS)
            {
                // We only pass 1 packet at a time to the port,
                // lets look at whether we should indicate this packet up to
                // the OS or not
                ndisStatus = MP_RX_MSDU_STATUS(currentPacket);
            }

            if (ndisStatus != NDIS_STATUS_SUCCESS)
            {
                // This packet should not be indicated up
                break;
            }

            // Perform filtering of the packet to determine if this need to go up to the OS
            if (BasePortFilterFragment(Port, currentPacket) == FALSE)
            {
                // Drop these packets
                ndisStatus = NDIS_STATUS_NOT_ACCEPTED;                

                // Since we have already given this packet to the port, let it undo 
                // anything it may have done before
                Port11NotifyReturn(Port, 
                    currentPacket, 
                    NDIS_TEST_RECEIVE_AT_DISPATCH_LEVEL(ReceiveFlags) ? NDIS_RETURN_FLAGS_DISPATCH_LEVEL 
                        : 0
                    );
                break;
            }

        } while (FALSE);

        if (ndisStatus == NDIS_STATUS_SUCCESS)
        {
            // This packet gets indicated to the OS
            if (packetListToIndicate == NULL)
            {
                packetListToIndicate = currentPacket;
            }
            else
            {
                MP_RX_MSDU_NEXT_MSDU(prevPacketToIndicate) = currentPacket;
            }
            indicateCount++;
            prevPacketToIndicate = currentPacket;

            //
            // From this point on the packets must be completed
            //
        }
        else
        {
            // This (failed) packet gets returned back to the HW
            if (packetListToReturn == NULL)
            {
                packetListToReturn = currentPacket;
            }
            else
            {
                MP_RX_MSDU_NEXT_MSDU(prevPacketToReturn) = currentPacket;
            }
            returnCount++;
            prevPacketToReturn = currentPacket;
        }

        // Next packet
        currentPacket = nextPacket;
    }

    // Convert the packets we want to indicate into
    if (packetListToIndicate != NULL)
    {
        ndisStatus = BasePortTranslateRxPacketsToRxNBLs(Port, 
                        packetListToIndicate, 
                        &nblChainToIndicate
                        );
        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            MpTrace(COMP_SEND, DBG_SERIOUS, ("Failed to allocate NET_BUFFER_LIST chain for MP_RX_MSDU   chain\n"));

            //
            // Notify port that these packets have been returned
            //
            Port11NotifyReturn(Port, 
                packetListToIndicate, 
                NDIS_TEST_RECEIVE_AT_DISPATCH_LEVEL(ReceiveFlags) ? NDIS_RETURN_FLAGS_DISPATCH_LEVEL 
                    : 0
                );

            //
            // Prepend these "failed" MSDUs to the list that we wont indicate to the OS. These
            // would get freed below. The order doesnt matter here
            //
            currentPacket = packetListToIndicate;
            while (currentPacket != NULL)
            {
                nextPacket = MP_RX_MSDU_NEXT_MSDU(currentPacket);
                MP_RX_MSDU_NEXT_MSDU(currentPacket) = packetListToReturn;
                packetListToReturn = currentPacket;

                currentPacket = nextPacket;                
                returnCount++;
            }
            
        }
        else
        {
            if (NDIS_TEST_RECEIVE_CAN_PEND(ReceiveFlags))
            {
                //
                // Increment the counter for the number of packets we have submitted 
                // to the OS. This would block the port from pausing, etc
                //
                PORT_ADD_PNP_REFCOUNT(Port, indicateCount);
            }
        
            // Indicate these to the OS
            NdisMIndicateReceiveNetBufferLists(
                Port->MiniportAdapterHandle,
                nblChainToIndicate,
                Port->PortNumber,
                indicateCount,
                ReceiveFlags
                );

            if (NDIS_TEST_RECEIVE_CANNOT_PEND(ReceiveFlags))
            {
                // We wont get a return for these. Free the NBLs
                BasePortFreeTranslatedRxNBLs(Port, nblChainToIndicate);

                // Notify the ports about the return
                Port11NotifyReturn(Port, 
                    packetListToIndicate, 
                    NDIS_TEST_RECEIVE_AT_DISPATCH_LEVEL(ReceiveFlags) ? NDIS_RETURN_FLAGS_DISPATCH_LEVEL 
                        : 0
                    );
            }
        }

    }
    
    // Return all the non-used packets back to the HW (if we are permitted to call
    // return)
    if ((packetListToReturn != NULL) && (NDIS_TEST_RECEIVE_CAN_PEND(ReceiveFlags)))
    {
        VNic11ReturnPackets(Port->VNic, 
            packetListToReturn, 
            NDIS_TEST_RECEIVE_AT_DISPATCH_LEVEL(ReceiveFlags) ? NDIS_RETURN_FLAGS_DISPATCH_LEVEL : 0
            );
    }

}
Esempio n. 20
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;
}
Esempio n. 21
0
// Programs the parameters from the PhyContext on the HW for the specified PhyID.
// The PhyId is also made active. If CompletionCallback is NULL, the call completes
// synchronously. If this is not NULL, the completion handler is always called even 
// in case of a failure
NDIS_STATUS
HwProgramPhy(
    _In_  PHW                     Hw,
    _In_  PHW_MAC_CONTEXT         HwMac,
    _In_  ULONG                   PhyId,
    _In_  PHW_PHY_CONTEXT         PhyContext,
    _In_opt_  HW_GENERIC_CALLBACK_FUNC    CompletionCallback
    )    
{
    NDIS_STATUS                 ndisStatus = NDIS_STATUS_PENDING;
    UCHAR                       i ,numActive = 0;
    BOOLEAN                     programmingDone = FALSE;
    
    do
    {
        //
        // if there are multiple active MACs program the channel only for the first one
        //
        for (i = 0; i < HW_MAX_NUMBER_OF_MAC; i++)
        {
            if (HW_MAC_CONTEXT_MUST_MERGE(&Hw->MacContext[i]))
            {
                numActive++;
            }
        }

        if (numActive > 1)
        {
            // These are multiple MACs active. 
            MpTrace(COMP_MISC, DBG_NORMAL, ("Multiple MACs active. Not programming new phy setting\n"));

            // The new MAC should be programming the H/W on the current channel itself
            MPASSERT((Hw->PhyState.OperatingPhyId == PhyId) &&
                      (HalGetOperatingPhyMIB(Hw->Hal)->Channel == PhyContext->Channel));

            // Success
            ndisStatus = NDIS_STATUS_SUCCESS;
            programmingDone = TRUE;
            break;
        }

        if (HwAwake(Hw, FALSE) != TRUE)
        {        
            // Phy is OFF, we cannot finish this operation
            MpTrace(COMP_MISC, DBG_SERIOUS, ("Unable to activate PHY, not programming new phy settings\n"));
            ndisStatus = NDIS_STATUS_DOT11_POWER_STATE_INVALID;
            programmingDone = TRUE;
            break;
        }
        
        // We could optimize here by checking if we are already on the target Phy or Channel
        // and bailing out here

        // Only one phy programming call is permitted
        MPASSERT(Hw->PhyState.PendingPhyProgramCallback == NULL);

        if (CompletionCallback != NULL)
        {
            // Save the MAC context, etc
            Hw->PhyState.PhyProgramMacContext = HwMac;
            Hw->PhyState.PendingPhyProgramCallback = CompletionCallback;
            Hw->PhyState.DestinationPhyId = PhyId;
            Hw->PhyState.NewPhyContext = PhyContext;

            // Add a ref since we are going to do an async operation
            HW_INCREMENT_ACTIVE_OPERATION_REF(Hw);

            // Caller is OK with asynchronous behavior
            NdisQueueIoWorkItem(
                Hw->PhyState.PhyProgramWorkItem,
                HwPhyProgramWorkItem,
                Hw
                );

            // Completed asynchronously
            ndisStatus = NDIS_STATUS_PENDING;
        }
        else
        {
            // Caller expect synchronous behavior. Do the work inline
            ndisStatus = HwSetPhyContext(Hw, 
                            PhyId,
                            PhyContext
                            );
        }
        
    }while (FALSE);


    if (programmingDone)
    {        
        if (CompletionCallback != NULL)
        {
            // Call the completion handler
            CompletionCallback(Hw, HwMac, &ndisStatus);

            // Already called the complete
            ndisStatus = NDIS_STATUS_PENDING;
        }
        else
        {
            // Caller expects synchronous behavior
            // we are done
        }
    }

    return ndisStatus;
}
Esempio n. 22
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;
Esempio n. 23
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);
    }
}
Esempio n. 24
0
VOID
HvlCtxSWorkItem(
    PVOID            Context,
    NDIS_HANDLE      NdisIoWorkItemHandle
    )
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PHVL pHvl = NULL;
    LARGE_INTEGER waitTime = {0};
    #define NUM_EVENTS  3
    PVOID EventArray[NUM_EVENTS];  
    BOOLEAN fTerminating = FALSE;
    
    UNREFERENCED_PARAMETER(NdisIoWorkItemHandle);

    if (NULL == Context)
    {
        MPASSERT(Context != NULL);
        return;
    }

    pHvl = (PHVL) Context;
    EventArray[0] = &pHvl->TerminatingEvent;
    EventArray[1] = &pHvl->CtxSEvent;
    EventArray[2] = &pHvl->ExAccessEvent;

    /*
        The waitTime should ideally be a function of the beacon period. For now 
        assume a constant
        */
    waitTime.QuadPart = HVL_DEFAULT_CONTEXT_SWITCH_PARK_TIME_MSEC * -1;
    
    do
    {
        ntStatus = KeWaitForMultipleObjects(NUM_EVENTS, EventArray, WaitAny, Executive, KernelMode, FALSE, &waitTime, NULL);
        switch (ntStatus)
        {
            case STATUS_TIMEOUT:
                // timed context switch processing. 
                HvlProcessTimedCtxSwitch(pHvl);

                // optionally set a different waitTime for the next wait
                break;

            case STATUS_WAIT_0:
                // we are terminating. Time to get rid of this work item processing
                HvlLock(pHvl);
                pHvl->ulNumThreadsPending--;
                HvlUnlock(pHvl);  
                fTerminating = TRUE;
                break;

            case STATUS_WAIT_1:
                // we are asked to do context switch processing
                HvlProcessTimedCtxSwitch(pHvl);
                break;

            case STATUS_WAIT_2:
                // we have a new request for exclusive access
                HvlProcessExAccessReq(pHvl);
                break;
                
            default:
                MpTrace(COMP_HVL, DBG_SERIOUS, ("KeWaitForMultipleObjects returned error 0x%x", ntStatus));
                break;
        }        
    } while (!fTerminating);
}
Esempio n. 25
0
/**
 * This routine is called to free memory which was previously allocated using MpAllocateMemory function.
 * Before freeing the memory, this function checks and makes sure that no overflow or underflows have
 * happened and will also try to detect multiple frees of the same memory chunk.
 * 
 * \warning Do not use this function directly. Using MP_FREE_MEMORY ensures that
 * this function gets called for debug version of the driver. Retail builds will use Ndis API
 * for freeing of memory
 * \param Memory    Pointer to memory allocated using MP_FREE_MEMORY
 * \sa MpAllocateMemory, MP_ALLOCATE_MEMORY, MP_FREE_MEMORY, NdisFreeMemory, MpFreeAllocatedBlocks
 */
VOID 
MpFreeMemory (
    PVOID    Memory
    )
{
    PMP_MEMORY_BLOCK  memoryBlockHeader;

    MPASSERTMSG ("NULL memory being freed", Memory);
    MPASSERTMSG ("Allocated blocks list is empty. This is an extra free\n", !IsListEmpty(&GlobalMemoryList));

    // Jump back by memory header size so we can get to the header
    memoryBlockHeader = (PMP_MEMORY_BLOCK) (((PUCHAR)Memory) - sizeof(MP_MEMORY_BLOCK));

    //
    // Check that header was not corrupted
    //
    if (memoryBlockHeader->HeaderPattern != MP_HEADER_PATTERN)
    {
        if (memoryBlockHeader->HeaderPattern == MP_FREED_PATTERN)
        {
            MpTrace(COMP_DBG, DBG_SERIOUS, ("Possible double free of memory block at %p\n", memoryBlockHeader));
        }
        else
        {
            MpTrace(COMP_DBG, DBG_SERIOUS, ("Memory corruption due to underflow detected at memory block %p\n", memoryBlockHeader));
        }

        MpTrace(COMP_DBG, DBG_SERIOUS, ("Dumping information about memory block. This information may itself have been corrupted and could cause machine to bugcheck.\n"));
        MpTrace(COMP_DBG, DBG_SERIOUS, ("Memory was allocated from %s at line %d\n", memoryBlockHeader->File, memoryBlockHeader->Length));
        MPASSERT (FALSE);
    }

    //
    // Now corrupt the header so that double frees will fail.
    // Note simultaneous frees of same memory will not get caught this way!
    //
    memoryBlockHeader->HeaderPattern = MP_FREED_PATTERN;

    //
    // Check that trailer was not corrupted
    //
    if (*(PULONG) ((PUCHAR)Memory + memoryBlockHeader->Length) != MP_TRAILER_PATTERN)
    {
        MpTrace(COMP_DBG, DBG_SERIOUS, ("Memory corruption due to overflow detected at %p\n", Memory));
        MpTrace(COMP_DBG, DBG_SERIOUS, ("Dumping information about memory block. This information may itself have been corrupted and could cause machine to bugcheck.\n"));
        MpTrace(COMP_DBG, DBG_SERIOUS, ("Memory was allocated from %s at line %d\n", memoryBlockHeader->File, memoryBlockHeader->Length));
        MPASSERT (FALSE);
    }

    //
    // Remove this memory block from the list of allocations
    //
    NdisAcquireSpinLock (&GlobalMemoryLock);
    RemoveEntryList (&memoryBlockHeader->ListEntry);
    NdisReleaseSpinLock (&GlobalMemoryLock);

    //
    // Zero out data and trailer and then free the memory chunk back to the OS
    //
    NdisZeroMemory (Memory, sizeof (ULONG) + (memoryBlockHeader->Length));
    NdisFreeMemory (memoryBlockHeader, 0, 0);
}
Esempio n. 26
0
NDIS_STATUS
HelperPortFlushBSSList(
    __in PMP_PORT                 Port
    )
{
    MP_RW_LOCK_STATE          LockState;
    PLIST_ENTRY         pListEntry;
    PMP_BSS_ENTRY      pBSSEntry = NULL;
    LONG                APRefCount;
    LIST_ENTRY          TempList;
    PMP_HELPER_PORT     HelperPort = MP_GET_HELPPORT(Port);
    PMP_BSS_LIST       pDiscoveredBSSList = &(HelperPort->BSSList);

    //
    // Entries that are currently in use (eg for connection)
    // we cannot flush and instead would put in the temporary queue
    //
    InitializeListHead(&TempList);
    
    MP_ACQUIRE_WRITE_LOCK(&(HelperPort->BSSList.ListLock), &LockState);
        
    while (!IsListEmpty(&(pDiscoveredBSSList->List)))
    {
        pListEntry = RemoveHeadList(&(pDiscoveredBSSList->List));
        pBSSEntry = CONTAINING_RECORD(pListEntry, MP_BSS_ENTRY, Link);

        APRefCount = NdisInterlockedDecrement(&(pBSSEntry->RefCount));
        if (APRefCount == 0)
        {        
            NdisAcquireSpinLock(&(pBSSEntry->Lock));
            MPASSERT(pBSSEntry->pAssocRequest == NULL);
            MPASSERT(pBSSEntry->pAssocResponse == 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;            
            NdisReleaseSpinLock(&(pBSSEntry->Lock));
            
            MP_FREE_MEMORY(pBSSEntry);        
        }
        else
        {
            // Restore refcount and save for adding back to list
            NdisInterlockedIncrement(&(pBSSEntry->RefCount));
            InsertTailList(&TempList, pListEntry);
        }
    }
    pDiscoveredBSSList->NumOfBSSEntries = 0;

    //
    // Restore entries that are in use
    //
    while (!IsListEmpty(&TempList))
    {
        pListEntry = RemoveHeadList(&TempList);

        InsertTailList(&(pDiscoveredBSSList->List), pListEntry);
        pDiscoveredBSSList->NumOfBSSEntries++;
    }

    // Since our scan list is flushed, also clear the last scan time
    HelperPort->ScanContext.LastScanTime = 0;
    
    MP_RELEASE_WRITE_LOCK(&(HelperPort->BSSList.ListLock), &LockState);

    return NDIS_STATUS_SUCCESS;