Exemple #1
0
VOID
kmdf1394_EvtDeviceSelfManagedIoCleanup (
                                        IN  WDFDEVICE Device)
/*++

Routine Description:

    EvtDeviceSelfManagedIoCleanup is called by the Framework when the device is
    being torn down, either in response to IRP_MN_REMOVE_DEVICE or
    IRP_MN_SURPRISE_REMOVE_DEVICE.  It will be called only once.  Its job is to
    stop all outstanding I/O in the driver that the Framework is not managing.

Arguments:

    Device - Handle to a framework device object.

Return Value:

    None

--*/
{
    PDEVICE_EXTENSION deviceExtension = NULL;
    PLIST_ENTRY listEntry = NULL;


    Enter();

    deviceExtension = GetDeviceContext(Device);

    DoTraceLevelMessage(TRACE_LEVEL_WARNING, 
                        TRACE_FLAG_PNP,
                        "Removing KMDF1394VDEV.SYS.\n");

    //
    // lets free up any crom data structs we've allocated...
    //
    WdfSpinLockAcquire (deviceExtension->CromSpinLock);

    while (!IsListEmpty (&deviceExtension->CromData))
    {
        PCROM_DATA      CromData;

        //
        // get struct off list
        //
        listEntry = RemoveHeadList (&deviceExtension->CromData);
        CromData = CONTAINING_RECORD (listEntry, CROM_DATA, CromList);

        //
        // need to free up everything associated with this allocate...
        //
        if (CromData)
        {
            if (CromData->Buffer)
            {
                ExFreePoolWithTag (CromData->Buffer, POOLTAG_KMDF_VDEV);
            }

            if (CromData->pMdl)
            {
                IoFreeMdl (CromData->pMdl);
            }
            //
            // we already checked CromData
            //
            ExFreePoolWithTag (CromData, POOLTAG_KMDF_VDEV);
        }
    }

    WdfSpinLockRelease (deviceExtension->CromSpinLock);

    //
    // lets free up any allocated addresses and deallocate all
    // memory associated with them...
    //
    WdfSpinLockAcquire (deviceExtension->AsyncSpinLock);

    while (!IsListEmpty (&deviceExtension->AsyncAddressData)) 
    {
        PASYNC_ADDRESS_DATA     AsyncAddressData;

        //
        // get struct off list
        //
        listEntry = RemoveHeadList (&deviceExtension->AsyncAddressData);

        AsyncAddressData = CONTAINING_RECORD (
            listEntry, 
            ASYNC_ADDRESS_DATA,
            AsyncAddressList);

        // 
        // need to free up everything associated with this allocate...
        //
        if (AsyncAddressData->pMdl)
        {
            IoFreeMdl (AsyncAddressData->pMdl);
        }

        if (AsyncAddressData->Buffer)
        {
            ExFreePoolWithTag(AsyncAddressData->Buffer, POOLTAG_KMDF_VDEV);
        }

        if (AsyncAddressData->AddressRange)
        {
            ExFreePoolWithTag(AsyncAddressData->AddressRange, POOLTAG_KMDF_VDEV);
        }

        ExFreePoolWithTag(AsyncAddressData, POOLTAG_KMDF_VDEV);
    }


    WdfSpinLockRelease(deviceExtension->AsyncSpinLock);

    //
    // TODO: Free up any attached isoch buffers when
    // we get the attach / detach code inserted again.
    //

    //
    // Remove any isoch resource data
    //
    WHILE (TRUE) 
    {
        WdfSpinLockAcquire(deviceExtension->IsochResourceSpinLock);

        if (!IsListEmpty(&deviceExtension->IsochResourceData)) 
        {
            PISOCH_RESOURCE_DATA    IsochResourceData = NULL;

            listEntry = RemoveHeadList(&deviceExtension->CromData);

            IsochResourceData = CONTAINING_RECORD (
                listEntry,
                ISOCH_RESOURCE_DATA,
                IsochResourceList);

            WdfSpinLockRelease(deviceExtension->IsochResourceSpinLock);

            DoTraceLevelMessage(TRACE_LEVEL_INFORMATION, 
                                TRACE_FLAG_PNP, 
                                "Surprise Removal: IsochResourceData = 0x%p\n",
                                IsochResourceData);

            if (IsochResourceData) 
            {
                PIRB pIrb;
                WDFREQUEST request;
                NTSTATUS ntStatus;

                DoTraceLevelMessage(TRACE_LEVEL_INFORMATION, 
                                    TRACE_FLAG_PNP, 
                                    "Surprise Removal: Freeing hResource = 0x%p\n",
                                    IsochResourceData->hResource);

                ntStatus = WdfRequestCreate (
                    WDF_NO_OBJECT_ATTRIBUTES,
                    deviceExtension->StackIoTarget,
                    &request);
                if (!NT_SUCCESS (ntStatus)) 
                {
                    DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                                        TRACE_FLAG_PNP, 
                                        "Failed to allocate request %!STATUS!\n", 
                                        ntStatus);
                }
                else 
                {
                    pIrb = ExAllocatePoolWithTag(
                        NonPagedPool, 
                        sizeof(IRB), 
                        POOLTAG_KMDF_VDEV);
                    if (!pIrb) 
                    {
                        WdfObjectDelete(request);
                        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                                            TRACE_FLAG_PNP, 
                                            "Failed to allocate pIrb!\n");
                    }
                    else 
                    {
                        RtlZeroMemory (pIrb, sizeof (IRB));
                        pIrb->FunctionNumber = REQUEST_ISOCH_FREE_RESOURCES;
                        pIrb->Flags = 0;
                        pIrb->u.IsochFreeResources.hResource = \
                            IsochResourceData->hResource;

                        ntStatus = kmdf1394_SubmitIrpSynch (
                            deviceExtension->StackIoTarget, 
                            request, 
                            pIrb);
                        if (!NT_SUCCESS (ntStatus)) 
                        {
                            DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                                                TRACE_FLAG_PNP, 
                                                "SubmitIrpSync failed = %!STATUS!\n", 
                                                ntStatus);
                        }

                        ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV);
                        WdfObjectDelete (request);
                    } // else
                } // else
            } // if (IsochResourceData) 
        } //  if (!IsListEmpty(&deviceExtension->IsochResourceData)) 
        else 
        {
            WdfSpinLockRelease (deviceExtension->IsochResourceSpinLock);
            break;
        }
    }

    ExitS(STATUS_SUCCESS);
} // kmdf1394_EvtDeviceSelfManagedIoCleanup
Exemple #2
0
NTSTATUS
kmdf1394_AsyncWrite (
                     IN WDFDEVICE             Device,
                     IN WDFREQUEST         Request,
                     IN PASYNC_WRITE       AsyncWrite)
/*++

Routine Description:

    Async Write routine.

Arguments:

    Device - the current WDFDEVICE Object.

    Request - the current request.

    AsyncWrite - the Data buffer from usermode to be worked on.

Return Value:

    VOID
--*/
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PDEVICE_EXTENSION deviceExtension = GetDeviceContext(Device);
    PIRB pIrb = NULL;
    PMDL   pMdl = NULL;
    WDFIOTARGET ioTarget = NULL;
    WDFMEMORY Memory;

    Enter();

    ioTarget = deviceExtension->StackIoTarget;


    pIrb = ExAllocatePoolWithTag(NonPagedPool, sizeof(IRB), POOLTAG_KMDF_VDEV);
    if (!pIrb) 
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_ASYNC, 
                            "Failed to allocate pIrb!\n");
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    RtlZeroMemory (pIrb, sizeof (IRB));
    pIrb->FunctionNumber = REQUEST_ASYNC_WRITE;
    pIrb->Flags = 0;
    pIrb->u.AsyncWrite.DestinationAddress = AsyncWrite->DestinationAddress;
    pIrb->u.AsyncWrite.nNumberOfBytesToWrite = AsyncWrite->nNumberOfBytesToWrite;
    pIrb->u.AsyncWrite.nBlockSize = AsyncWrite->nBlockSize;
    pIrb->u.AsyncWrite.fulFlags = AsyncWrite->fulFlags;

    if (AsyncWrite->bGetGeneration) 
    {
        DoTraceLevelMessage(TRACE_LEVEL_INFORMATION, 
                            TRACE_FLAG_ASYNC, 
                            "Retrieved Generation Count = 0x%X\n", 
                            pIrb->u.AsyncRead.ulGeneration);

        pIrb->u.AsyncRead.ulGeneration = deviceExtension->GenerationCount;
    }
    else 
    {
        pIrb->u.AsyncRead.ulGeneration = AsyncWrite->ulGeneration;
    }

    pMdl = IoAllocateMdl (
        AsyncWrite->Data,
        AsyncWrite->nNumberOfBytesToWrite,
        FALSE,
        FALSE,
        NULL);
    if(NULL == pMdl) 
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_ASYNC, 
                            "Failed to allocate mdl!\n");

        ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    MmBuildMdlForNonPagedPool (pMdl);

    pIrb->u.AsyncWrite.Mdl = pMdl;

    //
    // We need to create a WDF Memory object for the IRB to nestle in
    // for an async request.
    //
    ntStatus = WdfMemoryCreatePreallocated (
        WDF_NO_OBJECT_ATTRIBUTES,
        pIrb,
        sizeof (IRB),
        &Memory);

    if (!NT_SUCCESS (ntStatus))
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_ASYNC,
                            "Failed WdfMemoryCreate %d\n", 
                            ntStatus);

        IoFreeMdl (pIrb->u.AsyncWrite.Mdl);
        ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV);

        return ntStatus;
    }

    WdfRequestSetCompletionRoutine (
        Request, 
        kmdf1394_AsyncWriteCompletion, 
        Memory);

    ntStatus = kmdf1394_SubmitIrpAsync (ioTarget, Request, Memory);
    if (!NT_SUCCESS(ntStatus)) 
    {
        if (ntStatus != STATUS_INVALID_GENERATION) 
        {
            DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                                TRACE_FLAG_ASYNC, 
                                "SubmitIrpSync failed = %!STATUS!\n", 
                                ntStatus);
        }
        else
        {
            DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                                TRACE_FLAG_ASYNC, 
                                "Invalid Generation count\n");
        }

        IoFreeMdl (pIrb->u.AsyncWrite.Mdl);
        ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV);
        WdfObjectDelete (Memory);
    }

    ExitS(ntStatus);
    return ntStatus;
} // kmdf1394_AsyncWrite
Exemple #3
0
NTSTATUS
kmdf1394_EvtDeviceAdd (
                       IN WDFDRIVER        Driver,
                       IN PWDFDEVICE_INIT  DeviceInit)
/*++
Routine Description:

    EvtDeviceAdd is called by the framework in response to AddDevice
    call from the PnP manager.

Arguments:

    Driver - Handle to a framework driver object created in DriverEntry

    DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.

Return Value:

    NTSTATUS

--*/
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PDEVICE_EXTENSION deviceExtension;
    WDF_PNPPOWER_EVENT_CALLBACKS  pnpPowerCallbacks;
    WDF_OBJECT_ATTRIBUTES fdoAttributes,lockAttributes;
    WDFDEVICE device;
    WDF_DEVICE_PNP_CAPABILITIES pnpCaps;
    WDF_IO_QUEUE_CONFIG ioQueueConfig;

    UNREFERENCED_PARAMETER (Driver);

    PAGED_CODE();

    Enter();

    //
    // Zero out the PnpPowerCallbacks structure.
    //
    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);

    //
    // Set Callbacks for any of the functions we are interested in.
    // If no callback is set, Framework will take the default action
    // by itself.

    //
    // These two callbacks set up and tear down hardware state,
    // specifically that which only has to be done once.
    //

    pnpPowerCallbacks.EvtDevicePrepareHardware = kmdf1394_EvtPrepareHardware;
    pnpPowerCallbacks.EvtDeviceReleaseHardware = kmdf1394_EvtReleaseHardware;

    pnpPowerCallbacks.EvtDeviceSelfManagedIoCleanup = \
        kmdf1394_EvtDeviceSelfManagedIoCleanup;

    pnpPowerCallbacks.EvtDeviceD0Entry = kmdf1394_EvtDeviceD0Entry;
    pnpPowerCallbacks.EvtDeviceD0Exit  = kmdf1394_EvtDeviceD0Exit;

    //
    // Register the PnP and power callbacks. Power policy related callbacks
    // will be registered// later in SotwareInit.
    //
    WdfDeviceInitSetPnpPowerEventCallbacks (DeviceInit, &pnpPowerCallbacks);
    if (!NT_SUCCESS (ntStatus))
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_PNP, 
                            "WdfDeviceInitSetPnpPowerEventCallbacks failed %!STATUS!\n",
                            ntStatus);
        return ntStatus;
    }

    //
    // We'll allow multiple handles to be opened to this device driver
    // so we'll set exclusivity to FALSE.
    //
    WdfDeviceInitSetExclusive (DeviceInit, FALSE);

    //
    // Specify the size and type of device context.
    //
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE (&fdoAttributes, DEVICE_EXTENSION);

    ntStatus = WdfDeviceCreate (&DeviceInit, &fdoAttributes, &device);

    if (!NT_SUCCESS (ntStatus)) 
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_PNP, 
                            "WdfDeviceInitialize failed %!STATUS!\n", 
                            ntStatus);
        return ntStatus;
    }


    deviceExtension = GetDeviceContext (device);
    deviceExtension->WdfDevice = device;

    DoTraceLevelMessage(TRACE_LEVEL_INFORMATION, 
                        TRACE_FLAG_PNP,
                        "PDO(0x%p) FDO(0x%p), Lower(0x%p) DevExt (0x%p)\n",
                        WdfDeviceWdmGetPhysicalDevice (device),
                        WdfDeviceWdmGetDeviceObject (device),
                        WdfDeviceWdmGetAttachedDevice(device),
                        deviceExtension);

    //
    // Tell the Framework that this device will need an interface so that
    // application can interact with it.
    //

    ntStatus = WdfDeviceCreateDeviceInterface (
        device,
        (LPGUID) &GUID_KMDF_VDEV,
        NULL);
    if (!NT_SUCCESS (ntStatus)) 
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_PNP, 
                            "WdfDeviceCreateDeviceInterface failed %!STATUS!\n", 
                            ntStatus);
        return ntStatus;
    }

    //
    // Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so
    // that you don't get the popup in usermode (on Win2K) when you surprise
    // remove the device.
    //
    WDF_DEVICE_PNP_CAPABILITIES_INIT (&pnpCaps);
    pnpCaps.SurpriseRemovalOK = WdfTrue;

    WdfDeviceSetPnpCapabilities (device, &pnpCaps);

    //
    // save the device object we created as our physical device object
    //
    deviceExtension->PhysicalDeviceObject = \
        WdfDeviceWdmGetPhysicalDevice (device);

    if (NULL == deviceExtension->PhysicalDeviceObject) 
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_PNP, 
                            "WdfDeviceWdmGetPhysicalDevice: NULL DeviceObject\n");
        return STATUS_UNSUCCESSFUL;
    }

    //
    // This is our default IoTarget representing the deviceobject
    // we are attached to.
    //
    deviceExtension->StackIoTarget = WdfDeviceGetIoTarget(device);
    deviceExtension->StackDeviceObject = WdfDeviceWdmGetAttachedDevice(device);

    if (NULL == deviceExtension->StackDeviceObject) 
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_PNP, 
                            "WdfDeviceWdmGetAttachedDevice: NULL DeviceObject\n");
        return STATUS_UNSUCCESSFUL;
    }


    //
    // Create a automanaged queue for dispatching ioctl requests.
    // All other requests are automatically failed by the framework.
    // By creating an automanaged queue we don't have to worry about
    // PNP/Power synchronization.
    // A default queue gets all the requests that are not
    // configure-fowarded using WdfDeviceConfigureRequestDispatching.
    //
    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE (
        &ioQueueConfig,
        WdfIoQueueDispatchParallel);

    ioQueueConfig.EvtIoDeviceControl = kmdf1394_EvtIoDeviceControl;
    
    __analysis_assume(ioQueueConfig.EvtIoStop != 0);
    ntStatus = WdfIoQueueCreate (
        deviceExtension->WdfDevice,
        &ioQueueConfig,
        WDF_NO_OBJECT_ATTRIBUTES,
        &deviceExtension->IoctlQueue);
    __analysis_assume(ioQueueConfig.EvtIoStop == 0);
    if (!NT_SUCCESS (ntStatus)) 
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_PNP, 
                            "WdfIoQueueCreate failed %!STATUS!\n", 
                            ntStatus);
        return ntStatus;
    }

    //
    // Create an additional queue to hold bus reset requests.
    //
    WDF_IO_QUEUE_CONFIG_INIT (&ioQueueConfig, WdfIoQueueDispatchManual);

    __analysis_assume(ioQueueConfig.EvtIoStop != 0);
    ntStatus = WdfIoQueueCreate (
        deviceExtension->WdfDevice,
        &ioQueueConfig,
        WDF_NO_OBJECT_ATTRIBUTES,
        &deviceExtension->BusResetRequestsQueue);
    __analysis_assume(ioQueueConfig.EvtIoStop == 0);
    if(!NT_SUCCESS (ntStatus))
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_PNP, 
                            "Error Creating Reset Request Queue %!STATUS!\n",
                            ntStatus);
        return ntStatus;
    }
    WDF_OBJECT_ATTRIBUTES_INIT (&lockAttributes);
    lockAttributes.ParentObject = device;

    ntStatus = WdfSpinLockCreate (&lockAttributes,&deviceExtension->CromSpinLock);
    if(!NT_SUCCESS (ntStatus))
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_PNP, 
                            "WdfSpinLockCreate CromSpinLock failed %!STATUS!\n", 
                            ntStatus);
        return ntStatus;
    }


    WDF_OBJECT_ATTRIBUTES_INIT (&lockAttributes);
    lockAttributes.ParentObject = device;

    ntStatus = WdfSpinLockCreate (
        &lockAttributes,
        &deviceExtension->AsyncSpinLock);
    if(!NT_SUCCESS (ntStatus))
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_PNP, 
                            "WdfSpinLockCreate AsyncSpinLock failed %!STATUS!\n", 
                            ntStatus);
        return ntStatus;
    }

    WDF_OBJECT_ATTRIBUTES_INIT (&lockAttributes);
    lockAttributes.ParentObject = device;

    ntStatus = WdfSpinLockCreate (
        &lockAttributes,
        &deviceExtension->IsochSpinLock );
    if(!NT_SUCCESS (ntStatus))
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_PNP, 
                            "WdfSpinLockCreate IsochSpinLock failed %!STATUS!\n", 
                            ntStatus);
        return ntStatus;
    }

    WDF_OBJECT_ATTRIBUTES_INIT (&lockAttributes);
    lockAttributes.ParentObject = device;

    ntStatus = WdfSpinLockCreate (
        &lockAttributes,
        &deviceExtension->IsochResourceSpinLock);
    if(!NT_SUCCESS (ntStatus))
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_PNP, 
                            "WdfSpinLockCreate IsochResourceSpinLock failed %!STATUS!\n", 
                            ntStatus);
        return ntStatus;
    }

    InitializeListHead (&deviceExtension->CromData);
    InitializeListHead (&deviceExtension->AsyncAddressData);
    InitializeListHead (&deviceExtension->IsochDetachData);
    InitializeListHead (&deviceExtension->IsochResourceData);

    ExitS(ntStatus);
    return(ntStatus);
} // kmdf1394_PnpAddDevice
Exemple #4
0
NTSTATUS
kmdf1394_SetAddressData (
                         IN WDFDEVICE Device,
                         IN WDFREQUEST Request,
                         IN PSET_ADDRESS_DATA SetAddrData)
/*++

Routine Description:

    Set Address Range routine.

Arguments:

    Device - the current WDFDEVICE Object.

    Request - the current request.

    SetAddrData - the Data buffer from usermode to be worked on.

Return Value:

    VOID
--*/
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PDEVICE_EXTENSION  deviceExtension = GetDeviceContext(Device);
    PASYNC_ADDRESS_DATA AsyncAddressData = NULL;
    PLIST_ENTRY listHead, thisEntry;

    UNREFERENCED_PARAMETER(Request);

    Enter();

    //
    // have to find our struct...
    //
    WdfSpinLockAcquire(deviceExtension->AsyncSpinLock);

    listHead = &deviceExtension->AsyncAddressData;

    for(thisEntry = listHead->Flink; thisEntry != listHead;
        AsyncAddressData = NULL, thisEntry = thisEntry->Flink)
    {
        AsyncAddressData = CONTAINING_RECORD(
            thisEntry, 
            ASYNC_ADDRESS_DATA,
            AsyncAddressList);
        if (AsyncAddressData->hAddressRange == SetAddrData->hAddressRange) 
        {
            PULONG  pBuffer;

            // 
            // found it, let's copy over the contents from data...
            //
            pBuffer = \
                (PULONG)((ULONG_PTR)AsyncAddressData->Buffer + \
                SetAddrData->ulOffset);

            DoTraceLevelMessage(TRACE_LEVEL_INFORMATION, 
                                TRACE_FLAG_ASYNC, 
                                "pBuffer = 0x%p\n", 
                                pBuffer);
            DoTraceLevelMessage(TRACE_LEVEL_INFORMATION, 
                                TRACE_FLAG_ASYNC, 
                                "Data = 0x%p\n", 
                                SetAddrData->Data);

#pragma warning(suppress:28649) // PREFast warning is incorrectly issued here
            if(pBuffer && SetAddrData->Data) 
            {
                RtlCopyMemory(pBuffer, SetAddrData->Data, SetAddrData->nLength);
            }
            break;
        }
    }

    WdfSpinLockRelease(deviceExtension->AsyncSpinLock);

    // 
    // never found an entry...
    //
    if (!AsyncAddressData) 
    {
        ntStatus = STATUS_INVALID_PARAMETER;
    }

    ExitS(ntStatus);
    return ntStatus;
} // kmdf1394_SetAddressData
Exemple #5
0
NTSTATUS
kmdf1394_FreeAddressRange (
                           IN WDFDEVICE Device,
                           IN WDFREQUEST Request,
                           IN HANDLE hAddressRange)
/*++

Routine Description:

    Allocate Address Range routine.

Arguments:

    Device - the current WDFDEVICE Object.

    Request - the current request.

    hAddressRange - The Address Range to be freed.

Return Value:

    VOID
--*/
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PDEVICE_EXTENSION deviceExtension = GetDeviceContext(Device);
    PIRB pIrb = NULL;
    PASYNC_ADDRESS_DATA AsyncAddressData  = NULL;
    PLIST_ENTRY listHead, thisEntry;

    UNREFERENCED_PARAMETER(Request);

    Enter();

    //
    // have to find our struct...
    //
    WdfSpinLockAcquire (deviceExtension->AsyncSpinLock);

    listHead = &deviceExtension->AsyncAddressData;

    for (thisEntry = listHead->Flink; 
        thisEntry != listHead; 
        AsyncAddressData = NULL, thisEntry = thisEntry->Flink)
    {
        AsyncAddressData = CONTAINING_RECORD (
            thisEntry, 
            ASYNC_ADDRESS_DATA,
            AsyncAddressList);

        if (AsyncAddressData->hAddressRange == hAddressRange) 
        {
            RemoveEntryList(&AsyncAddressData->AsyncAddressList);
            break;
        }
    }

    WdfSpinLockRelease(deviceExtension->AsyncSpinLock);

    //
    // never found an entry...
    //
    if (!AsyncAddressData) 
    {
        return STATUS_INVALID_PARAMETER;
    }

    // 
    // got it, lets free it...
    //
    pIrb = ExAllocatePoolWithTag (NonPagedPool, sizeof(IRB), POOLTAG_KMDF_VDEV);
    if (!pIrb) 
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_ASYNC, 
                            "Failed to allocate pIrb!\n");

        //
        // Catasrophic failure, insert the AddressData element back on 
        // the list before existing
        //
        WdfSpinLockAcquire (deviceExtension->AsyncSpinLock);

        InsertHeadList (
            &deviceExtension->AsyncAddressData, 
            &AsyncAddressData->AsyncAddressList);

        WdfSpinLockRelease (deviceExtension->AsyncSpinLock);

        return STATUS_INSUFFICIENT_RESOURCES;
    }

    RtlZeroMemory (pIrb, sizeof (IRB));
    pIrb->FunctionNumber = REQUEST_FREE_ADDRESS_RANGE;
    pIrb->Flags = 0;
    pIrb->u.FreeAddressRange.nAddressesToFree = \
        AsyncAddressData->nAddressesReturned;
    pIrb->u.FreeAddressRange.p1394AddressRange = AsyncAddressData->AddressRange;
    pIrb->u.FreeAddressRange.pAddressRange = &AsyncAddressData->hAddressRange;
    pIrb->u.FreeAddressRange.DeviceExtension = (PVOID)deviceExtension;

    //
    // We're going to send this one synchronously
    //
    ntStatus = kmdf1394_SubmitIrpSynch (
        deviceExtension->StackIoTarget, 
        Request, 
        pIrb);
    if (!NT_SUCCESS (ntStatus))
    {
        //
        // The free request failed, insert the element back on to our tracking 
        // list and either try to free later, or release the resources on 
        // driver tear down.
        //
        WdfSpinLockAcquire (deviceExtension->AsyncSpinLock);

        InsertHeadList (
            &deviceExtension->AsyncAddressData, 
            &AsyncAddressData->AsyncAddressList);

        WdfSpinLockRelease (deviceExtension->AsyncSpinLock);
    }
    else
    {
        // 
        //  need to free up everything associated with this from the allocate...
        //
        IoFreeMdl (AsyncAddressData->pMdl);
        ExFreePoolWithTag (AsyncAddressData->Buffer, POOLTAG_KMDF_VDEV);
        ExFreePoolWithTag (AsyncAddressData->AddressRange, POOLTAG_KMDF_VDEV);
        ExFreePoolWithTag (AsyncAddressData, POOLTAG_KMDF_VDEV);
    }

    ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV);

    ExitS(ntStatus);
    return ntStatus;
} // kmdf1394_FreeAddressRange
Exemple #6
0
NTSTATUS
kmdf1394_AllocateAddressRange (
                               IN WDFDEVICE Device,
                               IN WDFREQUEST Request,
                               IN OUT PALLOCATE_ADDRESS_RANGE AllocateAddrRange)
/*++

Routine Description:

    Allocate Address Range routine.

Arguments:

    Device - the current WDFDEVICE Object.

    Request - the current request.

    AllocateAddressRange - the Data buffer from usermode to be worked on.

Return Value:

    VOID
--*/
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PDEVICE_EXTENSION deviceExtension = GetDeviceContext(Device);
    PIRB pIrb = NULL;
    PASYNC_ADDRESS_DATA pAsyncAddressData = NULL;
    ULONG nPages;
    WDFMEMORY Memory;
    CONTEXT_BUNDLE ContextBundle;

    Enter();

    pIrb = ExAllocatePoolWithTag (NonPagedPool, sizeof(IRB), POOLTAG_KMDF_VDEV);
    if (!pIrb)
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_ASYNC, 
                            "Failed to allocate pIrb!\n");
        return STATUS_INSUFFICIENT_RESOURCES;
    } 

    ContextBundle.Context0 = AllocateAddrRange;

    pAsyncAddressData = ExAllocatePoolWithTag (
        NonPagedPool,
        sizeof(ASYNC_ADDRESS_DATA),
        POOLTAG_KMDF_VDEV);
    if (!pAsyncAddressData)
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_ASYNC, 
                            "Failed to allocate pAsyncAddressData!\n");

        ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    ContextBundle.Context1 = pAsyncAddressData;

    pAsyncAddressData->Buffer = ExAllocatePoolWithTag (
        NonPagedPool, 
        AllocateAddrRange->nLength, 
        POOLTAG_KMDF_VDEV);
    if (!pAsyncAddressData->Buffer) 
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_ASYNC, 
                            "Failed to allocate Buffer!\n");

        ExFreePoolWithTag (pAsyncAddressData, POOLTAG_KMDF_VDEV);
        ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    if ((0 == AllocateAddrRange->MaxSegmentSize) || 
        (PAGE_SIZE == AllocateAddrRange->MaxSegmentSize))
    {
        nPages = \
            ADDRESS_AND_SIZE_TO_SPAN_PAGES (
            AllocateAddrRange->Data, 
            AllocateAddrRange->nLength);
    }
    else
    {
        nPages = \
            (AllocateAddrRange->nLength % AllocateAddrRange->MaxSegmentSize) ? \
            AllocateAddrRange->nLength / AllocateAddrRange->MaxSegmentSize + 1 : \
            AllocateAddrRange->nLength / AllocateAddrRange->MaxSegmentSize;
    }

    pAsyncAddressData->AddressRange = ExAllocatePoolWithTag (
        NonPagedPool,
        sizeof(ADDRESS_RANGE)*nPages,
        POOLTAG_KMDF_VDEV);
    if (!pAsyncAddressData->AddressRange) 
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_ASYNC, 
                            "Failed to allocate AddressRange!\n");

        ExFreePoolWithTag(pAsyncAddressData->Buffer, POOLTAG_KMDF_VDEV);
        ExFreePoolWithTag(pAsyncAddressData, POOLTAG_KMDF_VDEV);
        ExFreePoolWithTag(pIrb, POOLTAG_KMDF_VDEV);

        return STATUS_INSUFFICIENT_RESOURCES;
    }

    pAsyncAddressData->pMdl = IoAllocateMdl (
        pAsyncAddressData->Buffer,
        AllocateAddrRange->nLength,
        FALSE,
        FALSE,
        NULL);

    if (!pAsyncAddressData->pMdl) 
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_ASYNC, 
                            "Failed to create pMdl!\n");

        ExFreePoolWithTag (pAsyncAddressData->AddressRange, POOLTAG_KMDF_VDEV);
        ExFreePoolWithTag (pAsyncAddressData->Buffer, POOLTAG_KMDF_VDEV);
        ExFreePoolWithTag (pAsyncAddressData, POOLTAG_KMDF_VDEV);
        ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV);

        return STATUS_INSUFFICIENT_RESOURCES;
    }

    MmBuildMdlForNonPagedPool (pAsyncAddressData->pMdl);

    DoTraceLevelMessage(TRACE_LEVEL_INFORMATION, 
                        TRACE_FLAG_ASYNC, 
                        "pMdl = 0x%p\n", 
                        pAsyncAddressData->pMdl);

    //
    // copy over the contents of data to our driver buffer
    //
    RtlCopyMemory (
        pAsyncAddressData->Buffer, 
        AllocateAddrRange->Data, 
        AllocateAddrRange->nLength);

    pAsyncAddressData->nLength = AllocateAddrRange->nLength;

    RtlZeroMemory (pIrb, sizeof (IRB));
    pIrb->FunctionNumber = REQUEST_ALLOCATE_ADDRESS_RANGE;
    pIrb->Flags = 0;
    pIrb->u.AllocateAddressRange.Mdl = pAsyncAddressData->pMdl;
    pIrb->u.AllocateAddressRange.fulFlags = AllocateAddrRange->fulFlags;
    pIrb->u.AllocateAddressRange.nLength = AllocateAddrRange->nLength;
    pIrb->u.AllocateAddressRange.MaxSegmentSize = \
        AllocateAddrRange->MaxSegmentSize;
    pIrb->u.AllocateAddressRange.fulAccessType = \
        AllocateAddrRange->fulAccessType;
    pIrb->u.AllocateAddressRange.fulNotificationOptions = \
        AllocateAddrRange->fulNotificationOptions;

    pIrb->u.AllocateAddressRange.Callback = NULL;
    pIrb->u.AllocateAddressRange.Context = NULL;

    pIrb->u.AllocateAddressRange.Required1394Offset = \
        AllocateAddrRange->Required1394Offset;
    pIrb->u.AllocateAddressRange.FifoSListHead = NULL;
    pIrb->u.AllocateAddressRange.FifoSpinLock = NULL;
    pIrb->u.AllocateAddressRange.AddressesReturned = 0;
    pIrb->u.AllocateAddressRange.p1394AddressRange = \
        pAsyncAddressData->AddressRange;
    pIrb->u.AllocateAddressRange.DeviceExtension = deviceExtension;

    //
    // We need to create a WDF Memory object for the IRB to nestle in
    // for an async request.
    //
    ntStatus = WdfMemoryCreatePreallocated (
        WDF_NO_OBJECT_ATTRIBUTES,
        pIrb,
        sizeof (IRB),
        &Memory);
    if (!NT_SUCCESS (ntStatus))
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_ASYNC,
                            "Failed WdfMemoryCreate %d\n", 
                            ntStatus);

        IoFreeMdl (pAsyncAddressData->pMdl);
        ExFreePoolWithTag (pAsyncAddressData->AddressRange, POOLTAG_KMDF_VDEV);
        ExFreePoolWithTag (pAsyncAddressData->Buffer, POOLTAG_KMDF_VDEV);
        ExFreePoolWithTag (pAsyncAddressData, POOLTAG_KMDF_VDEV);
        ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV);

        return ntStatus;
    }

    ContextBundle.Context2 = Memory;
    ContextBundle.Context3 = deviceExtension;

    WdfRequestSetCompletionRoutine (
        Request, 
        kmdf1394_AllocateAddressRangeCompletion, 
        &ContextBundle);

    ntStatus = kmdf1394_SubmitIrpAsync (
        deviceExtension->StackIoTarget, 
        Request, 
        Memory);

    ExitS(ntStatus);
    return ntStatus;
} //kmdf1394_AllocateAddressRange
Exemple #7
0
NTSTATUS
kmdf1394_AsyncStream (
                      IN WDFDEVICE Device,
                      IN WDFREQUEST Request,
                      IN OUT PASYNC_STREAM AsyncStream)
/*++

Routine Description:

    Async Stream routine.

Arguments:

    Device - the current WDFDEVICE Object.

    Request - the current request.

    AsyncStream - the Data buffer from usermode to be worked on.

Return Value:

    VOID
--*/
{
    NTSTATUS    ntStatus = STATUS_SUCCESS;
    PDEVICE_EXTENSION  deviceExtension = GetDeviceContext (Device);
    PIRB pIrb = NULL;
    WDFIOTARGET ioTarget = deviceExtension->StackIoTarget;
    WDFMEMORY Memory;
    PMDL pMdl = NULL;

    Enter();

    pIrb = ExAllocatePoolWithTag(NonPagedPool, sizeof(IRB), POOLTAG_KMDF_VDEV);
    if (!pIrb)
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_ASYNC, 
                            "Failed to allocate pIrb!\n");
        return STATUS_INSUFFICIENT_RESOURCES;
    } 

    RtlZeroMemory (pIrb, sizeof (IRB));
    pIrb->FunctionNumber = REQUEST_ASYNC_STREAM;
    pIrb->Flags = 0;
    pIrb->u.AsyncStream.nNumberOfBytesToStream = \
        AsyncStream->nNumberOfBytesToStream;
    pIrb->u.AsyncStream.fulFlags = AsyncStream->fulFlags;
    pIrb->u.AsyncStream.ulTag = AsyncStream->ulTag;
    pIrb->u.AsyncStream.nChannel = AsyncStream->nChannel;
    pIrb->u.AsyncStream.ulSynch = AsyncStream->ulSynch;
    pIrb->u.AsyncStream.nSpeed = (UCHAR) AsyncStream->nSpeed;

    pMdl = IoAllocateMdl (
        AsyncStream->Data,
        AsyncStream->nNumberOfBytesToStream,
        FALSE,
        FALSE,
        NULL);
    if (!pMdl) 
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_ASYNC, 
                            "Failed to allocate pMdl!\n");

        ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    MmBuildMdlForNonPagedPool(pMdl);

    pIrb->u.AsyncStream.Mdl = pMdl;

    //
    // We need to create a WDF Memory object for the IRB to nestle in
    // for an async request.
    //
    ntStatus = WdfMemoryCreatePreallocated (
        WDF_NO_OBJECT_ATTRIBUTES,
        pIrb,
        sizeof (IRB),
        &Memory);
    if (!NT_SUCCESS (ntStatus))
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_ASYNC,
                            "Failed WdfMemoryCreate %d\n", 
                            ntStatus);

        IoFreeMdl (pIrb->u.AsyncStream.Mdl);
        ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV);

        return ntStatus;
    }

    WdfRequestSetCompletionRoutine (
        Request, 
        kmdf1394_AsyncStreamCompletion, 
        Memory);

    ntStatus = kmdf1394_SubmitIrpAsync (ioTarget, Request, Memory);
    if (!NT_SUCCESS(ntStatus)) 
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_ASYNC, 
                            "SubmitIrpAsync failed = %!STATUS!\n", 
                            ntStatus);

        IoFreeMdl (pIrb->u.AsyncStream.Mdl);
        ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV);
        WdfObjectDelete (Memory);
    }

    ExitS(ntStatus);
    return ntStatus;
} // kmdf1394_AsyncStream
Exemple #8
0
NTSTATUS
kmdf1394_AsyncLock (
                    IN WDFDEVICE         Device,
                    IN WDFREQUEST     Request,
                    IN OUT PASYNC_LOCK   AsyncLock)
/*++

Routine Description:

    Async Lock routine.

Arguments:

    Device - the current WDFDEVICE Object.

    Request - the current request.

    AsyncLock - the Data buffer from usermode to be worked on.

Return Value:

    VOID
--*/
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PIRB pIrb = NULL;
    WDFMEMORY Memory;
    PDEVICE_EXTENSION  deviceExtension = GetDeviceContext (Device);
    WDFIOTARGET ioTarget = NULL;

    Enter();

    ioTarget = deviceExtension->StackIoTarget;

    pIrb = ExAllocatePoolWithTag (NonPagedPool, sizeof(IRB), POOLTAG_KMDF_VDEV);
    if (!pIrb) 
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_ASYNC, 
                            "Failed to allocate pIrb!\n");
        return STATUS_INSUFFICIENT_RESOURCES;  
    } 

    RtlZeroMemory (pIrb, sizeof (IRB));
    pIrb->FunctionNumber = REQUEST_ASYNC_LOCK;
    pIrb->Flags = 0;
    pIrb->u.AsyncLock.DestinationAddress = AsyncLock->DestinationAddress;
    pIrb->u.AsyncLock.nNumberOfArgBytes = AsyncLock->nNumberOfArgBytes;
    pIrb->u.AsyncLock.nNumberOfDataBytes = AsyncLock->nNumberOfDataBytes;
    pIrb->u.AsyncLock.fulTransactionType = AsyncLock->fulTransactionType;
    pIrb->u.AsyncLock.fulFlags = AsyncLock->fulFlags;
    pIrb->u.AsyncLock.Arguments[0] = AsyncLock->Arguments[0];
    pIrb->u.AsyncLock.Arguments[1] = AsyncLock->Arguments[1];
    pIrb->u.AsyncLock.DataValues[0] = AsyncLock->DataValues[0];
    pIrb->u.AsyncLock.DataValues[1] = AsyncLock->DataValues[1];
    pIrb->u.AsyncLock.pBuffer = AsyncLock->Buffer;

    if (AsyncLock->bGetGeneration) 
    {
        pIrb->u.AsyncLock.ulGeneration = deviceExtension->GenerationCount;

        DoTraceLevelMessage(TRACE_LEVEL_INFORMATION, 
                            TRACE_FLAG_ASYNC, 
                            "Retrieved Generation Count = 0x%X\n", 
                            pIrb->u.AsyncLock.ulGeneration);
    }
    else 
    {
        pIrb->u.AsyncLock.ulGeneration = AsyncLock->ulGeneration;
    }

    //
    // We need to create a WDF Memory object for the IRB to nestle in
    // for an async request.
    //
    ntStatus = WdfMemoryCreatePreallocated (
        WDF_NO_OBJECT_ATTRIBUTES,
        pIrb,
        sizeof (IRB),
        &Memory);
    if (!NT_SUCCESS (ntStatus))
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_ASYNC,
                            "Failed WdfMemoryCreate %d\n", 
                            ntStatus);

        ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV);

        return ntStatus;
    }

    WdfRequestSetCompletionRoutine (
        Request, 
        kmdf1394_AsyncLockCompletion, 
        Memory);


    ntStatus = kmdf1394_SubmitIrpAsync (ioTarget, Request, Memory);
    if (!NT_SUCCESS(ntStatus)) 
    {
        if (STATUS_INVALID_GENERATION == ntStatus) 
        {
            DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                                TRACE_FLAG_ASYNC, 
                                "Invalid Geneation count\n");
        }
        else
        {
            DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                                TRACE_FLAG_ASYNC, 
                                "SubmitIrpSync failed = %!STATUS!\n", 
                                ntStatus);
        }

        ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV);
        WdfObjectDelete (Memory);
    }

    ExitS(ntStatus);
    return ntStatus;
} // kmdf1394_AsyncLock