Esempio n. 1
0
static
NTSTATUS
VIOSerialInitInterruptHandling(
    IN WDFDEVICE hDevice)
{
    WDF_OBJECT_ATTRIBUTES        attributes;
    WDF_INTERRUPT_CONFIG         interruptConfig;
    PPORTS_DEVICE                pContext = GetPortsDevice(hDevice);
    NTSTATUS                     status = STATUS_SUCCESS;

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_HW_ACCESS, "--> %s\n", __FUNCTION__);

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, PORTS_DEVICE);
    WDF_INTERRUPT_CONFIG_INIT(
                                 &interruptConfig,
                                 VIOSerialInterruptIsr,
                                 VIOSerialInterruptDpc
                                 );

    interruptConfig.EvtInterruptEnable = VIOSerialInterruptEnable;
    interruptConfig.EvtInterruptDisable = VIOSerialInterruptDisable;

    status = WdfInterruptCreate(
                                 hDevice,
                                 &interruptConfig,
                                 &attributes,
                                 &pContext->WdfInterrupt
                                 );

    if (!NT_SUCCESS (status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_HW_ACCESS,
            "Failed to create control queue interrupt: %x\n", status);
        return status;
    }

    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    WDF_INTERRUPT_CONFIG_INIT(&interruptConfig,
        VIOSerialInterruptIsr, VIOSerialQueuesInterruptDpc);

    status = WdfInterruptCreate(hDevice, &interruptConfig, &attributes,
        &pContext->QueuesInterrupt);

    if (!NT_SUCCESS (status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_HW_ACCESS,
            "Failed to create general queue interrupt: %x\n", status);
        return status;
    }

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_HW_ACCESS, "<-- %s\n", __FUNCTION__);
    return status;
}
Esempio n. 2
0
NTSTATUS
PLxInterruptCreate(
    IN PDEVICE_EXTENSION DevExt
    )
/*++
Routine Description:

    Configure and create the WDFINTERRUPT object.
    This routine is called by EvtDeviceAdd callback.

Arguments:

    DevExt      Pointer to our DEVICE_EXTENSION

Return Value:

    NTSTATUS code

--*/
{
    NTSTATUS                    status;
    WDF_INTERRUPT_CONFIG        InterruptConfig;

    WDF_INTERRUPT_CONFIG_INIT( &InterruptConfig,
                               PLxEvtInterruptIsr,
                               PLxEvtInterruptDpc );

    InterruptConfig.EvtInterruptEnable  = PLxEvtInterruptEnable;
    InterruptConfig.EvtInterruptDisable = PLxEvtInterruptDisable;

    // JOHNR: Enable testing of the DpcForIsr Synchronization
    InterruptConfig.AutomaticSerialization = TRUE;

    //
    // Unlike WDM, framework driver should create interrupt object in EvtDeviceAdd and
    // let the framework do the resource parsing and registration of ISR with the kernel.
    // Framework connects the interrupt after invoking the EvtDeviceD0Entry callback
    // and disconnect before invoking EvtDeviceD0Exit. EvtInterruptEnable is called after
    // the interrupt interrupt is connected and EvtInterruptDisable before the interrupt is
    // disconnected.
    //
    status = WdfInterruptCreate( DevExt->Device,
                                 &InterruptConfig,
                                 WDF_NO_OBJECT_ATTRIBUTES,
                                 &DevExt->Interrupt );

    if( !NT_SUCCESS(status) ) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "WdfInterruptCreate failed: %!STATUS!", status);
    }

    return status;
}
Esempio n. 3
0
/*++
Routine Description:

Configure and create the WDFINTERRUPT object.
This routine is called by EvtDeviceAdd callback.

Arguments:

pDevExt      Pointer to our DEVICE_EXTENSION

Return Value:

NTSTATUS code

--*/
NTSTATUS
PCIEInterruptCreate(IN PDEVICE_EXTENSION pDevExt)
{
    NTSTATUS                    Status;
    WDF_INTERRUPT_CONFIG        InterruptConfig;

    WDF_INTERRUPT_CONFIG_INIT( &InterruptConfig,
                               PCIEEvtInterruptIsr,
                               PCIEEvtInterruptDpc );

    InterruptConfig.EvtInterruptEnable  = PCIEEvtInterruptEnable;
    InterruptConfig.EvtInterruptDisable = PCIEEvtInterruptDisable;

    InterruptConfig.AutomaticSerialization = TRUE;

    //
    // Unlike WDM, framework driver should create interrupt object in EvtDeviceAdd and
    // let the framework do the resource parsing and registration of ISR with the kernel.
    // Framework connects the interrupt after invoking the EvtDeviceD0Entry callback
    // and disconnect before invoking EvtDeviceD0Exit. EvtInterruptEnable is called after
    // the interrupt interrupt is connected and EvtInterruptDisable before the interrupt is
    // disconnected.
    //
    Status = WdfInterruptCreate( 
                pDevExt->Device, 
                &InterruptConfig, 
                WDF_NO_OBJECT_ATTRIBUTES, 
                &pDevExt->Interrupt );

    if( !NT_SUCCESS(Status) )
    {
        KdPrint(("PCIEInterruptCreate: Failed: %x", Status));
    }
    
    return Status;
}
Esempio n. 4
0
_Use_decl_annotations_
NTSTATUS OnDeviceAdd (WDFDRIVER /*WdfDriver*/, WDFDEVICE_INIT* DeviceInitPtr)
{
    PAGED_CODE();
    BCM_I2C_ASSERT_MAX_IRQL(PASSIVE_LEVEL);

    NTSTATUS status;

    //
    // Configure DeviceInit structure
    //
    status = SpbDeviceInitConfig(DeviceInitPtr);
    if (!NT_SUCCESS(status)) {
        BSC_LOG_ERROR(
            "SpbDeviceInitConfig() failed. (DeviceInitPtr = %p, status = %!STATUS!)",
            DeviceInitPtr,
            status);
        return status;
    }

    //
    // Setup PNP/Power callbacks.
    //
    {
        WDF_PNPPOWER_EVENT_CALLBACKS pnpCallbacks;
        WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpCallbacks);

        pnpCallbacks.EvtDevicePrepareHardware = OnPrepareHardware;
        pnpCallbacks.EvtDeviceReleaseHardware = OnReleaseHardware;
        pnpCallbacks.EvtDeviceD0Entry = OnD0Entry;
        pnpCallbacks.EvtDeviceD0Exit = OnD0Exit;

        WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInitPtr, &pnpCallbacks);
    }

    //
    // Create the device.
    //
    WDFDEVICE wdfDevice;
    BCM_I2C_DEVICE_CONTEXT* devicePtr;
    {
        WDF_OBJECT_ATTRIBUTES deviceAttributes;
        WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(
            &deviceAttributes,
            BCM_I2C_DEVICE_CONTEXT);

        status = WdfDeviceCreate(
            &DeviceInitPtr,
            &deviceAttributes,
            &wdfDevice);
        if (!NT_SUCCESS(status)) {
            BSC_LOG_ERROR(
                "Failed to create WDFDEVICE. (DeviceInitPtr = %p, status = %!STATUS!)",
                DeviceInitPtr,
                status);
            return status;
        }

        devicePtr = GetDeviceContext(wdfDevice);
        NT_ASSERT(devicePtr);
        devicePtr->WdfDevice = wdfDevice;
    }

    //
    // Query registry for ClockStretchTimeout
    //
    {
        WDFKEY wdfKey;
        status = WdfDeviceOpenRegistryKey(
                wdfDevice,
                PLUGPLAY_REGKEY_DEVICE,
                KEY_QUERY_VALUE,
                WDF_NO_OBJECT_ATTRIBUTES,
                &wdfKey);
        if (!NT_SUCCESS(status)) {
            BSC_LOG_ERROR(
                "Failed to open device parameters registry key. (status=%!STATUS!)",
                status);
            return status;
        }
        auto closeRegKey = Finally([&] {
            PAGED_CODE();
            WdfRegistryClose(wdfKey);
        });

        DECLARE_CONST_UNICODE_STRING(
            regValString,
            REGSTR_VAL_CLOCK_STRETCH_TIMEOUT);

        ULONG clockStretchTimeout;
        status = WdfRegistryQueryULong(
                wdfKey,
                &regValString,
                &clockStretchTimeout);
        if (NT_SUCCESS(status)) {
            if ((clockStretchTimeout & BCM_I2C_REG_CLKT_TOUT_MASK) !=
                 clockStretchTimeout) {

                BSC_LOG_ERROR(
                    "Clock stretch timeout value from registry is out of range. (clockStretchTimeout=0x%x, BCM_I2C_REG_CLKT_TOUT_MASK=0x%x)",
                    clockStretchTimeout,
                    BCM_I2C_REG_CLKT_TOUT_MASK);
                return STATUS_INVALID_PARAMETER;
            }

            BSC_LOG_INFORMATION(
                "Using ClockStretchTimeout value from registry. (clockStretchTimeout=0x%x)",
                clockStretchTimeout);

        } else {
            switch (status) {
            case STATUS_OBJECT_NAME_NOT_FOUND:
                clockStretchTimeout = BCM_I2C_REG_CLKT_TOUT_DEFAULT;
                status = STATUS_SUCCESS;
                break;
            default:
                BSC_LOG_ERROR(
                    "Failed to query clock stretch timeout from registry. (status=%!STATUS!, REGSTR_VAL_CLOCK_STRETCH_TIMEOUT=%S)",
                    status,
                    REGSTR_VAL_CLOCK_STRETCH_TIMEOUT);
                return status;
            }
        }

        devicePtr->ClockStretchTimeout = clockStretchTimeout;
    }

    //
    // Ensure device is disable-able
    //
    {
        WDF_DEVICE_STATE deviceState;
        WDF_DEVICE_STATE_INIT(&deviceState);
        deviceState.NotDisableable = WdfFalse;
        WdfDeviceSetDeviceState(wdfDevice, &deviceState);
    }

    //
    // Bind a SPB controller object to the device.
    //
    {
        SPB_CONTROLLER_CONFIG spbConfig;
        SPB_CONTROLLER_CONFIG_INIT(&spbConfig);

        //
        // Register for target connect callback.  The driver
        // does not need to respond to target disconnect.
        //

        spbConfig.EvtSpbTargetConnect = OnTargetConnect;

        //
        // Register for IO callbacks.
        //

        spbConfig.ControllerDispatchType = WdfIoQueueDispatchSequential;
        spbConfig.EvtSpbIoRead = OnRead;
        spbConfig.EvtSpbIoWrite = OnWrite;
        spbConfig.EvtSpbIoSequence = OnSequence;

        status = SpbDeviceInitialize(wdfDevice, &spbConfig);
        if (!NT_SUCCESS(status)) {
            BSC_LOG_ERROR(
                "SpbDeviceInitialize failed. (wdfDevice = %p, status = %!STATUS!)",
                wdfDevice,
                status);
            return status;
        }
    }

    //
    // Set target object attributes.
    //
    {
        WDF_OBJECT_ATTRIBUTES targetAttributes;
        WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(
            &targetAttributes,
            BCM_I2C_TARGET_CONTEXT);

        SpbControllerSetTargetAttributes(wdfDevice, &targetAttributes);
    }

    //
    // Create an interrupt object
    //
    BCM_I2C_INTERRUPT_CONTEXT* interruptContextPtr;
    {
        WDF_OBJECT_ATTRIBUTES interruptObjectAttributes;
        WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(
            &interruptObjectAttributes,
            BCM_I2C_INTERRUPT_CONTEXT);

        WDF_INTERRUPT_CONFIG interruptConfig;
        WDF_INTERRUPT_CONFIG_INIT(
            &interruptConfig,
            OnInterruptIsr,
            OnInterruptDpc);

        status = WdfInterruptCreate(
            wdfDevice,
            &interruptConfig,
            &interruptObjectAttributes,
            &devicePtr->WdfInterrupt);
        if (!NT_SUCCESS(status)) {
            BSC_LOG_ERROR(
                "Failed to create interrupt object. (wdfDevice = %p, status = %!STATUS!)",
                wdfDevice,
                status);
            return status;
        }

        interruptContextPtr = GetInterruptContext(devicePtr->WdfInterrupt);
        interruptContextPtr->WdfInterrupt = devicePtr->WdfInterrupt;
    }
    devicePtr->InterruptContextPtr = interruptContextPtr;

    NT_ASSERT(NT_SUCCESS(status));
    return STATUS_SUCCESS;
}
Esempio n. 5
0
File: device.c Progetto: MHesham/bsp
/*++

Routine Description:

     In this callback, the driver does whatever is necessary to make the
     hardware ready to use.

Arguments:

     Device - A handle to a framework device object.

     ResourcesRaw - A handle to a framework resource-list object that identifies
          the raw hardware resources that the Plug and Play manager has assigned
          to the device.

     ResourcesTranslated - A handle to a framework resource-list object that
          identifies the translated hardware resources that the Plug and Play
          manager has assigned to the device.

Return Value:

     NTSTATUS value

--*/
_Use_decl_annotations_
NTSTATUS VchiqPrepareHardware (
    WDFDEVICE Device,
    WDFCMRESLIST ResourcesRaw,
    WDFCMRESLIST ResourcesTranslated
    )
{
    NTSTATUS status;
    DEVICE_CONTEXT* deviceContextPtr;
    ULONG resourceCount;
    ULONG MemoryResourceCount = 0;
    ULONG InterruptResourceCount = 0;

    PAGED_CODE();

    deviceContextPtr = VchiqGetDeviceContext(Device);
    resourceCount = WdfCmResourceListGetCount(ResourcesTranslated);

    for (ULONG i = 0; i < resourceCount; ++i) {
        PCM_PARTIAL_RESOURCE_DESCRIPTOR res;

        res = WdfCmResourceListGetDescriptor(ResourcesTranslated, i);
        switch (res->Type)
        {
        case CmResourceTypeMemory:
            {
                VCHIQ_LOG_INFORMATION(
                    "Memory Resource Start: 0x%08x, Length: 0x%08x",
                    res->u.Memory.Start.LowPart,
                    res->u.Memory.Length);

                deviceContextPtr->VchiqRegisterPtr =
                    MmMapIoSpaceEx(
                        res->u.Memory.Start,
                        res->u.Memory.Length,
                        PAGE_READWRITE | PAGE_NOCACHE);
                if (deviceContextPtr->VchiqRegisterPtr == NULL) {
                    VCHIQ_LOG_ERROR("Failed to map VCHIQ register");
                    status = STATUS_UNSUCCESSFUL;
                    goto End;
                }
                deviceContextPtr->VchiqRegisterLength = res->u.Memory.Length;
                ++MemoryResourceCount;
            }
            break;
        case CmResourceTypeInterrupt:
            {
                VCHIQ_LOG_INFORMATION(
                    "Interrupt Level: 0x%08x, Vector: 0x%08x\n",
                    res->u.Interrupt.Level,
                    res->u.Interrupt.Vector);

                WDF_INTERRUPT_CONFIG interruptConfig;

                WDF_INTERRUPT_CONFIG_INIT (
                    &interruptConfig,
                    VchiqIsr,
                    VchiqDpc);

                interruptConfig.InterruptRaw =
                    WdfCmResourceListGetDescriptor (ResourcesRaw, i);
                interruptConfig.InterruptTranslated = res;

                status = WdfInterruptCreate(
                    Device,
                    &interruptConfig,
                    WDF_NO_OBJECT_ATTRIBUTES,
                    &deviceContextPtr->VchiqIntObj);
                if (!NT_SUCCESS (status)) {
                    VCHIQ_LOG_ERROR (
                        "Fail to initialize VCHIQ interrupt object");
                    return status;
                }
                ++InterruptResourceCount;
            }
            break;
        default:
            {
                VCHIQ_LOG_WARNING("Unsupported resources, ignoring");
            }
            break;
        }
        if (MemoryResourceCount && InterruptResourceCount)
            break;
    }

    if (MemoryResourceCount != VCHIQ_MEMORY_RESOURCE_TOTAL &&
        InterruptResourceCount != VCHIQ_INT_RESOURCE_TOTAL) {
        status = STATUS_UNSUCCESSFUL;
        VCHIQ_LOG_ERROR("Unknown resource assignment");
        goto End;
    }

    status = STATUS_SUCCESS;

End:
    if (!NT_SUCCESS(status)) {
        VCHIQ_LOG_ERROR("VchiqPrepareHardware failed %!STATUS!", status);
    }

    return status;
}
Esempio n. 6
0
NTSTATUS
AmccPciAddDevice(
    _In_    WDFDRIVER        Driver,
    _Inout_ PWDFDEVICE_INIT  DeviceInit
    )
/*++

Routine Description:

    EvtDeviceAdd is called by the framework in response to AddDevice
    call from the PnP manager.  It is responsible for initializing and
    creating a WDFDEVICE object.

    Any work that should be done after the object is created should be
    deferred until EvtDeviceSoftwareInit, as that callback will be made
    with the device lock held (if there is one.)

Arguments:

    Driver - Handle to a framework driver object created in DriverEntry

    DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.

Return Value:

    NTSTATUS

--*/
{
    NTSTATUS                   status = STATUS_SUCCESS;
    WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
    WDF_OBJECT_ATTRIBUTES       fdoAttributes;
    WDF_INTERRUPT_CONFIG        interruptConfig;
    WDF_OBJECT_ATTRIBUTES       interruptAttributes;
    WDF_IO_QUEUE_CONFIG         ioQueueConfig;
    PAMCC_DEVICE_EXTENSION           devExt;
    WDFQUEUE                    hQueue;
    WDFDEVICE                   device;

    PAGED_CODE();

    TraceEvents(TRACE_LEVEL_INFORMATION, AMCC_TRACE_INIT,
                        "AmccPciAddDevice: 0x%p", Driver);

    //
    // 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.
    //
    pnpPowerCallbacks.EvtDevicePrepareHardware = AmccPciEvtDevicePrepareHardware;
    pnpPowerCallbacks.EvtDeviceReleaseHardware = AmccPciEvtDeviceReleaseHardware;
    pnpPowerCallbacks.EvtDeviceD0Entry         = AmccPciEvtDeviceD0Entry;
    pnpPowerCallbacks.EvtDeviceD0Exit          = AmccPciEvtDeviceD0Exit;

    //
    // Register the PnP Callbacks..
    //
    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

    //
    // Set various attributes for this device
    //
    WdfDeviceInitSetIoType( DeviceInit, WdfDeviceIoDirect );

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fdoAttributes, AMCC_DEVICE_EXTENSION);
    fdoAttributes.EvtCleanupCallback = AmccPciContextCleanup;
    //
    // We want all the queue callbacks, cancel routine, and DpcForIsr to be serialized
    // at the device level, so we don't have worry about any synchronization issues.
    //
    fdoAttributes.SynchronizationScope = WdfSynchronizationScopeDevice;

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

    if ( !NT_SUCCESS(status) ) {
        TraceEvents(TRACE_LEVEL_ERROR, AMCC_TRACE_INIT,
                                "WdfDeviceInitialize failed 0x%X", status);
        return status;
    }

    //
    // Device Initialization is complete.
    // Get the Device Extension and initialize it.
    //
    devExt = AmccPciGetDevExt(device);

    devExt->Device = device;

    TraceEvents(TRACE_LEVEL_INFORMATION, AMCC_TRACE_INIT,
                        "PDO 0x%p, FDO 0x%p, DevExt 0x%p",
                        WdfDeviceWdmGetPhysicalDevice(device),
                        WdfDeviceWdmGetDeviceObject( device ), devExt);

    //
    // This device generates an interrupt.  So create an interrupt object which
    // will later be associated with the devices resources and connected
    // by the Framework.
    //

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&interruptAttributes, INTERRUPT_DATA);

    //
    // Configure the Interrupt object
    //
    WDF_INTERRUPT_CONFIG_INIT(&interruptConfig,
                              AmccPciEvtInterruptIsr,
                              AmccPciEvtInterruptDpc);

    status = WdfInterruptCreate(device,
                                &interruptConfig,
                                &interruptAttributes,
                                &devExt->WdfInterrupt);
    if (!NT_SUCCESS (status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, AMCC_TRACE_INIT,
                    "WdfInterruptCreate failed: %!STATUS!\n", status);
        return status;
    }

    //
    // The S5933 requires DMA buffers be aligned on a 32-bit boundary
    //
    // NOTE: Read the existing alignment value. If it is greater than
    //       or equal then keep it.  If it is less then update the
    //       alignment requirement field with this device's required
    //       value.
    //
    // NOTE: See the MSDN section titled "Initializing a Device Object"
    //       for details on how to specify this alignment value.
    //
    // NOTE: AMCC5933_ALIGNMENT__32BITS is equated to (4-1) for 32-bit
    //       alignment.
    //
    {
        ULONG alignReq;

        alignReq = WdfDeviceGetAlignmentRequirement( device );

        if (alignReq < AMCC5933_ALIGNMENT__32BITS) {

            //
            // Set the S5933 alignment requirement as new value.
            //
            WdfDeviceSetAlignmentRequirement( device,
                                              AMCC5933_ALIGNMENT__32BITS);
        }
    }

    //
    // Register I/O callbacks.
    //
    // Create a sequential IO Queue for serial operation. That means all the requests (Read/Write
    // & IOCTL) are serialized to the device. Until the driver completes the request presented to it,
    // the framework will not schedule another one. The requests held in the framework will be
    // cancelled automatically if the source of request (application) terminate or cancels it.
    //
    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE( &ioQueueConfig,
                              WdfIoQueueDispatchSequential);

    ioQueueConfig.EvtIoDefault = AmccPciEvtIoDefault;
    
    //
    // By default, Static Driver Verifier (SDV) displays a warning if it 
    // doesn't find the EvtIoStop callback on a power-managed queue. 
    // The 'assume' below causes SDV to suppress this warning. If the driver 
    // has not explicitly set PowerManaged to WdfFalse, the framework creates
    // power-managed queues when the device is not a filter driver.  Normally 
    // the EvtIoStop is required for power-managed queues, but for this driver
    // it is not needed b/c the driver doesn't hold on to the requests for 
    // long time or forward them to other drivers. 
    // If the EvtIoStop callback is not implemented, the framework waits for
    // all driver-owned requests to be done before moving in the Dx/sleep 
    // states or before removing the device, which is the correct behavior 
    // for this type of driver. If the requests were taking an indeterminate
    // amount of time to complete, or if the driver forwarded the requests
    // to a lower driver/another stack, the queue should have an 
    // EvtIoStop/EvtIoResume.
    //
    __analysis_assume(ioQueueConfig.EvtIoStop != 0);
    status = WdfIoQueueCreate( device,
                               &ioQueueConfig,
                               WDF_NO_OBJECT_ATTRIBUTES,
                               &hQueue );
    __analysis_assume(ioQueueConfig.EvtIoStop == 0);
    if (!NT_SUCCESS (status)) {
        //
        // We don't have worry about deleting the device here because framework will automatically
        // cleanup that when the driver unloads.
        //
        TraceEvents(TRACE_LEVEL_ERROR, AMCC_TRACE_INIT,
                                "WdfIoQueueCreate failed %!STATUS!", status);
        return status;
    }

    //
    // Register an interface so that application can find and talk to us.
    // NOTE: See the note in Public.h concerning this GUID value.
    //
    status = WdfDeviceCreateDeviceInterface( device,
                                             (LPGUID) &GUID_DEVINTERFACE_AMCC_PCI,
                                             NULL );

    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, AMCC_TRACE_INIT,
                "<-- AMCCAddDevice: WdfDeviceCreateDeviceInterface failed %!STATUS!", status);
        return status;
    }

    devExt->MaximumTransferLength = MAXIMUM_REQUEST_CONTEXT_LENGTH;

    //
    // Set the maximum physical pages for now, but this value may change if
    // there aren't enough map registers
    //
    devExt->MaximumPhysicalPages = MAXIMUM_PHYSICAL_PAGES;

    return status;
}
Esempio n. 7
0
NTSTATUS
OnDeviceAdd(
    _In_    WDFDRIVER       FxDriver,
    _Inout_ PWDFDEVICE_INIT FxDeviceInit
    )
/*++
 
  Routine Description:

    This routine creates the device object for an SPB 
    controller and the device's child objects.

  Arguments:

    FxDriver - the WDF driver object handle
    FxDeviceInit - information about the PDO that we are loading on

  Return Value:

    Status

--*/
{
    FuncEntry(TRACE_FLAG_WDFLOADING);

    PDEVICE_CONTEXT pDevice;
	WDFDEVICE fxDevice;
	WDF_INTERRUPT_CONFIG interruptConfig;
    NTSTATUS status;
    
    UNREFERENCED_PARAMETER(FxDriver);

	//
	// Tell framework this is a filter driver. Filter drivers by default are  
	// not power policy owners. This works well for this driver because
	// HIDclass driver is the power policy owner for HID minidrivers.
	//
	WdfFdoInitSetFilter(FxDeviceInit);

    //
    // Setup PNP/Power callbacks.
    //

    {
        WDF_PNPPOWER_EVENT_CALLBACKS pnpCallbacks;
        WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpCallbacks);

        pnpCallbacks.EvtDevicePrepareHardware = OnPrepareHardware;
        pnpCallbacks.EvtDeviceReleaseHardware = OnReleaseHardware;
        pnpCallbacks.EvtDeviceD0Entry = OnD0Entry;
        pnpCallbacks.EvtDeviceD0Exit = OnD0Exit;

        WdfDeviceInitSetPnpPowerEventCallbacks(FxDeviceInit, &pnpCallbacks);
    }
	
    //
    // Set request attributes.
    //

    {
        WDF_OBJECT_ATTRIBUTES attributes;
        WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(
            &attributes,
            REQUEST_CONTEXT);

        WdfDeviceInitSetRequestAttributes(FxDeviceInit, &attributes);
    }

    //
    // Create the device.
    //

    {
        WDF_OBJECT_ATTRIBUTES deviceAttributes;
        WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT);

        status = WdfDeviceCreate(
            &FxDeviceInit, 
            &deviceAttributes,
            &fxDevice);

        if (!NT_SUCCESS(status))
        {
			CyapaPrint(
                TRACE_LEVEL_ERROR, 
                TRACE_FLAG_WDFLOADING,
                "Error creating WDFDEVICE - %!STATUS!", 
                status);

            goto exit;
        }

        pDevice = GetDeviceContext(fxDevice);
        NT_ASSERT(pDevice != nullptr);

        pDevice->FxDevice = fxDevice;
    }

    //
    // Ensure device is disable-able
    //
    
    {
        WDF_DEVICE_STATE deviceState;
        WDF_DEVICE_STATE_INIT(&deviceState);
        
        deviceState.NotDisableable = WdfFalse;
        WdfDeviceSetDeviceState(pDevice->FxDevice, &deviceState);
    }

    //
    // Create queues to handle IO
    //

    {
        WDF_IO_QUEUE_CONFIG queueConfig;
        WDFQUEUE queue;

        //
        // Top-level queue
        //

        WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(
            &queueConfig, 
            WdfIoQueueDispatchParallel);

        queueConfig.EvtIoDefault = OnTopLevelIoDefault;
        queueConfig.PowerManaged = WdfFalse;

        status = WdfIoQueueCreate(
            pDevice->FxDevice,
            &queueConfig,
            WDF_NO_OBJECT_ATTRIBUTES,
            &queue
            );

        if (!NT_SUCCESS(status))
        {
			CyapaPrint(
                TRACE_LEVEL_ERROR, 
                TRACE_FLAG_WDFLOADING,
                "Error creating top-level IO queue - %!STATUS!", 
                status);

            goto exit;
        }

        //
        // Sequential SPB queue
        //

        WDF_IO_QUEUE_CONFIG_INIT(
            &queueConfig, 
			WdfIoQueueDispatchSequential);

		queueConfig.EvtIoInternalDeviceControl = OnIoDeviceControl;
        queueConfig.PowerManaged = WdfFalse;

        status = WdfIoQueueCreate(
            fxDevice,
            &queueConfig,
            WDF_NO_OBJECT_ATTRIBUTES,
			&pDevice->SpbQueue
            );

        if (!NT_SUCCESS(status))
        {
			CyapaPrint(DEBUG_LEVEL_ERROR, DBG_PNP,
				"WdfIoQueueCreate failed 0x%x\n", status);

            goto exit;
        }
    }

	WDF_IO_QUEUE_CONFIG           queueConfig;

	WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual);

	queueConfig.PowerManaged = WdfFalse;

	status = WdfIoQueueCreate(pDevice->FxDevice,
		&queueConfig,
		WDF_NO_OBJECT_ATTRIBUTES,
		&pDevice->ReportQueue
		);

	if (!NT_SUCCESS(status))
	{
		CyapaPrint(DEBUG_LEVEL_ERROR, DBG_PNP, "Queue 2!\n");
		CyapaPrint(DEBUG_LEVEL_ERROR, DBG_PNP,
			"WdfIoQueueCreate failed 0x%x\n", status);

		return status;
	}

	//
	// Create an interrupt object for hardware notifications
	//
	WDF_INTERRUPT_CONFIG_INIT(
		&interruptConfig,
		OnInterruptIsr,
		NULL);
	interruptConfig.PassiveHandling = TRUE;

	status = WdfInterruptCreate(
		fxDevice,
		&interruptConfig,
		WDF_NO_OBJECT_ATTRIBUTES,
		&pDevice->Interrupt);

	if (!NT_SUCCESS(status))
	{
		CyapaPrint(DEBUG_LEVEL_ERROR, DBG_PNP,
			"Error creating WDF interrupt object - %!STATUS!",
			status);

		goto exit;
	}

	WDF_TIMER_CONFIG              timerConfig;
	WDFTIMER                      hTimer;
	WDF_OBJECT_ATTRIBUTES         attributes;

	WDF_TIMER_CONFIG_INIT_PERIODIC(&timerConfig, CyapaTimerFunc, 10);

	WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
	attributes.ParentObject = fxDevice;
	status = WdfTimerCreate(&timerConfig, &attributes, &hTimer);
	pDevice->Timer = hTimer;
	if (!NT_SUCCESS(status))
	{
		CyapaPrint(DEBUG_LEVEL_ERROR, DBG_PNP, "(%!FUNC!) WdfTimerCreate failed status:%!STATUS!\n", status);
		return status;
	}

	CyapaPrint(DEBUG_LEVEL_ERROR, DBG_PNP,
		"Success! 0x%x\n", status);

	pDevice->DeviceMode = DEVICE_MODE_MOUSE;

exit:

    FuncExit(TRACE_FLAG_WDFLOADING);

    return status;
}
NTSTATUS
BalloonDeviceAdd(
    IN WDFDRIVER  Driver,
    IN PWDFDEVICE_INIT  DeviceInit)
{
    NTSTATUS                     status = STATUS_SUCCESS;
    WDFDEVICE                    device;
    PDEVICE_CONTEXT              devCtx = NULL;
    WDF_INTERRUPT_CONFIG         interruptConfig;
    WDF_FILEOBJECT_CONFIG        fileConfig;
    WDF_OBJECT_ATTRIBUTES        attributes;
    WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;

    UNREFERENCED_PARAMETER(Driver);
    PAGED_CODE();

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> %s\n", __FUNCTION__);

    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);

    pnpPowerCallbacks.EvtDevicePrepareHardware      = BalloonEvtDevicePrepareHardware;
    pnpPowerCallbacks.EvtDeviceReleaseHardware      = BalloonEvtDeviceReleaseHardware;
    pnpPowerCallbacks.EvtDeviceD0Entry              = BalloonEvtDeviceD0Entry;
    pnpPowerCallbacks.EvtDeviceD0Exit               = BalloonEvtDeviceD0Exit;
    pnpPowerCallbacks.EvtDeviceD0ExitPreInterruptsDisabled = BalloonEvtDeviceD0ExitPreInterruptsDisabled;

    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

    WDF_FILEOBJECT_CONFIG_INIT(
                            &fileConfig,
                            WDF_NO_EVENT_CALLBACK,
                            BalloonEvtFileClose,
                            WDF_NO_EVENT_CALLBACK
                            );

    WdfDeviceInitSetFileObjectConfig(DeviceInit,
                            &fileConfig,
                            WDF_NO_OBJECT_ATTRIBUTES);

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);
    attributes.EvtCleanupCallback = BalloonEvtDeviceContextCleanup;
    status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
    if(!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
           "WdfDeviceCreate failed with status 0x%08x\n", status);
        return status;
    }

    devCtx = GetDeviceContext(device);

    WDF_INTERRUPT_CONFIG_INIT(&interruptConfig,
                            BalloonInterruptIsr,
                            BalloonInterruptDpc);

    interruptConfig.EvtInterruptEnable  = BalloonInterruptEnable;
    interruptConfig.EvtInterruptDisable = BalloonInterruptDisable;

    status = WdfInterruptCreate(device,
                            &interruptConfig,
                            WDF_NO_OBJECT_ATTRIBUTES,
                            &devCtx->WdfInterrupt);
    if (!NT_SUCCESS (status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
           "WdfInterruptCreate failed: 0x%08x\n", status);
        return status;
    }

    status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_BALLOON, NULL);
    if(!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
           "WdfDeviceCreateDeviceInterface failed with status 0x%08x\n", status);
        return status;
    }
    devCtx->bShutDown = FALSE;
    devCtx->num_pages = 0;
    devCtx->PageListHead.Next = NULL;
    ExInitializeNPagedLookasideList(
                      &devCtx->LookAsideList,
                      NULL,
                      NULL,
                      0,
                      sizeof(PAGE_LIST_ENTRY),
                      BALLOON_MGMT_POOL_TAG,
                      0
                      );
    devCtx->bListInitialized = TRUE;
    devCtx->pfns_table = (PPFN_NUMBER)
              ExAllocatePoolWithTag(
                      NonPagedPool,
                      PAGE_SIZE,
                      BALLOON_MGMT_POOL_TAG
                      );

    if(devCtx->pfns_table == NULL)
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,"ExAllocatePoolWithTag failed\n");
        status = STATUS_INSUFFICIENT_RESOURCES;
        return status;
    }

    devCtx->MemStats = (PBALLOON_STAT)
              ExAllocatePoolWithTag(
                      NonPagedPool,
                      sizeof (BALLOON_STAT) * VIRTIO_BALLOON_S_NR,
                      BALLOON_MGMT_POOL_TAG
                      );

    if(devCtx->MemStats == NULL)
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,"ExAllocatePoolWithTag failed\n");
        status = STATUS_INSUFFICIENT_RESOURCES;
        return status;
    }

    RtlFillMemory (devCtx->MemStats, sizeof (BALLOON_STAT) * VIRTIO_BALLOON_S_NR, -1);

    KeInitializeEvent(&devCtx->HostAckEvent,
                      SynchronizationEvent,
                      FALSE
                      );

    status = BalloonQueueInitialize(device);
    if(!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
           "BalloonQueueInitialize failed with status 0x%08x\n", status);
        return status;
    }

    KeInitializeEvent(&devCtx->WakeUpThread,
                      SynchronizationEvent,
                      FALSE
                      );

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- %s\n", __FUNCTION__);
    return status;
}
Esempio n. 9
0
_Use_decl_annotations_
NTSTATUS
SampleDrvEvtDeviceAdd (
    WDFDRIVER Driver,
    PWDFDEVICE_INIT DeviceInit
)

/*++

Routine Description:

    This routine is the AddDevice entry point for the sample device driver.
    It sets the ISR and DPC routine handlers for the interrupt and the passive
    level callback for the passive interrupt

    N.B. The sample device expects two interrupt resources in connecting its
    DIRQL ISR and PASSIVE_LEVEL callback.

Arguments:

    Driver - Supplies a handle to the driver object created in DriverEntry.

    DeviceInit - Supplies a pointer to a framework-allocated WDFDEVICE_INIT
        structure.

Return Value:

    NTSTATUS code.

--*/

{

    WDF_PNPPOWER_EVENT_CALLBACKS Callbacks;
    WDFDEVICE Device;
    WDF_OBJECT_ATTRIBUTES FdoAttributes;
    WDF_INTERRUPT_CONFIG InterruptConfiguration;
    NTSTATUS Status;
    WDFINTERRUPT WdfInterrupt;

    UNREFERENCED_PARAMETER(Driver);

    PAGED_CODE();

    //
    // Set PnP callbacks for prepare/release hardware and D0 entry/exit. All
    // callbacks not overriden here will be handled by the framework in the
    // default manner.
    //

    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&Callbacks);
    Callbacks.EvtDevicePrepareHardware = SampleDrvEvtDevicePrepareHardware;
    Callbacks.EvtDeviceD0Entry = SampleDrvEvtDeviceD0Entry;

    //
    // Register the PnP callbacks with the framework.
    //

    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &Callbacks);

    //
    // Initialize FDO attributes with the sample device extension.
    //

    WDF_OBJECT_ATTRIBUTES_INIT(&FdoAttributes);
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&FdoAttributes, SAMPLE_DRV_DEVICE_EXTENSION);

    //
    // Call the framework to create the device and attach it to the lower stack.
    //

    Status = WdfDeviceCreate(&DeviceInit, &FdoAttributes, &Device);
    if (!NT_SUCCESS(Status)) {
        goto EvtDeviceAddEnd;
    }

    //
    // Create an interrupt object for the DIRQL ISR
    //

    WDF_INTERRUPT_CONFIG_INIT(&InterruptConfiguration,
                              SampleDrvInterruptIsr,
                              SampleDrvInterruptDpc);

    Status = WdfInterruptCreate(Device,
                                &InterruptConfiguration,
                                WDF_NO_OBJECT_ATTRIBUTES,
                                &WdfInterrupt);

    if (!NT_SUCCESS(Status)) {

        goto EvtDeviceAddEnd;
    }

#if 0
    //
    // Create an interrupt object for the passive interrupt callback. Note that
    // the interrupt object is chained to the same interrupt line/IDT as the
    // DIRQL one.
    //

    WDF_INTERRUPT_CONFIG_INIT(&InterruptConfiguration,
                              SampleDrvInterruptIsr,
                              NULL);

    //
    //  Set passive handling to true
    //

    InterruptConfiguration.PassiveHandling = TRUE;

    Status = WdfInterruptCreate(Device,
                                &InterruptConfiguration,
                                WDF_NO_OBJECT_ATTRIBUTES,
                                &WdfInterrupt);
#endif

EvtDeviceAddEnd:
    return Status;
}
Esempio n. 10
0
NTSTATUS
OnDeviceAdd(
    IN WDFDRIVER Driver,
    IN PWDFDEVICE_INIT DeviceInit
    )
/*++

Routine Description:

    OnDeviceAdd is called by the framework in response to AddDevice
    call from the PnP manager when a device is found. We create and 
    initialize a WDF device object to represent the new instance of 
    an touch device. Per-device objects are also instantiated.

Arguments:

    Driver - Handle to a framework driver object created in DriverEntry
    DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.

Return Value:

    NTSTATUS indicating success or failure

--*/
{
    WDF_OBJECT_ATTRIBUTES attributes;
    PDEVICE_EXTENSION devContext;
    WDFDEVICE fxDevice;
    WDF_INTERRUPT_CONFIG interruptConfig;  
    WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
    WDF_IO_QUEUE_CONFIG queueConfig;
    NTSTATUS status;
    
    UNREFERENCED_PARAMETER(Driver);
    PAGED_CODE();
    
    //
    // Relinquish power policy ownership because HIDCLASS acts a power
    // policy owner for ther HID stack.
    //
    WdfDeviceInitSetPowerPolicyOwnership(DeviceInit, FALSE);

    //
    // This driver handles D0 Entry and Exit to power on and off the
    // controller. It also handles prepare/release hardware so that it 
    // can acquire and free SPB resources needed to communicate with the  
    // touch controller.
    //
    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);

    pnpPowerCallbacks.EvtDeviceD0Entry = OnD0Entry;
    pnpPowerCallbacks.EvtDeviceD0Exit  = OnD0Exit;
    pnpPowerCallbacks.EvtDevicePrepareHardware = OnPrepareHardware;
    pnpPowerCallbacks.EvtDeviceReleaseHardware = OnReleaseHardware;

    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
    
    //
    // Create a framework device object. This call will in turn create
    // a WDM device object, attach to the lower stack, and set the
    // appropriate flags and attributes.
    //
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_EXTENSION);

    status = WdfDeviceCreate(&DeviceInit, &attributes, &fxDevice);

    if (!NT_SUCCESS(status)) 
    {
        Trace(
            TRACE_LEVEL_ERROR,
            TRACE_FLAG_INIT,
            "WdfDeviceCreate failed - %!STATUS!",
            status);

        goto exit;
    }

    devContext = GetDeviceContext(fxDevice);
    devContext->FxDevice = fxDevice;
    devContext->InputMode = MODE_MULTI_TOUCH;
  
    //
    // Create a parallel dispatch queue to handle requests from HID Class
    //
    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(
        &queueConfig, 
        WdfIoQueueDispatchParallel);

    queueConfig.EvtIoInternalDeviceControl = OnInternalDeviceControl;
    queueConfig.PowerManaged = WdfFalse;

    status = WdfIoQueueCreate(
        fxDevice,
        &queueConfig,
        WDF_NO_OBJECT_ATTRIBUTES,
        &devContext->DefaultQueue);

    if (!NT_SUCCESS (status)) 
    {
        Trace(
            TRACE_LEVEL_ERROR,
            TRACE_FLAG_INIT,
            "Error creating WDF default queue - %!STATUS!",
            status);

        goto exit;
    }

    //
    // Register a manual I/O queue for Read Requests. This queue will be used 
    // for storing HID read requests until touch data is available to 
    // complete them.
    //
    WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual);

    queueConfig.PowerManaged = WdfFalse;

    status = WdfIoQueueCreate(
        fxDevice,
        &queueConfig,
        WDF_NO_OBJECT_ATTRIBUTES,
        &devContext->PingPongQueue);

    if (!NT_SUCCESS(status)) 
    {
        Trace(
            TRACE_LEVEL_ERROR,
            TRACE_FLAG_INIT,
            "Error creating WDF read request queue - %!STATUS!",
            status);

        goto exit;
    }

    //
    // Register one last manual I/O queue for parking HIDClass's idle power
    // requests. This queue stores idle requests until they're cancelled,
    // and could be used to complete a wait/wake request.
    //

    WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual);

    queueConfig.PowerManaged = WdfFalse;

    status = WdfIoQueueCreate(
        fxDevice,
        &queueConfig,
        WDF_NO_OBJECT_ATTRIBUTES,
        &devContext->IdleQueue
        );

    if (!NT_SUCCESS(status))
    {
        Trace(
            TRACE_LEVEL_ERROR,
            TRACE_FLAG_INIT,
            "Error creating WDF idle request queue - %!STATUS!", 
            status);

        goto exit;
    }

    //
    // Create an interrupt object for hardware notifications
    //
    WDF_INTERRUPT_CONFIG_INIT(
        &interruptConfig,
        OnInterruptIsr,
        NULL);
    interruptConfig.PassiveHandling = TRUE;

    status = WdfInterruptCreate(
        fxDevice,
        &interruptConfig,
        WDF_NO_OBJECT_ATTRIBUTES,
        &devContext->InterruptObject);

    if (!NT_SUCCESS(status))
    {
        Trace(
            TRACE_LEVEL_ERROR,
            TRACE_FLAG_INIT,
            "Error creating WDF interrupt object - %!STATUS!",
            status);

        goto exit;
    }

exit:

    return status;
}
Esempio n. 11
0
File: Device.c Progetto: uri247/kmdf
NTSTATUS
SmplDeviceCreateDevice(
    _Inout_ PWDFDEVICE_INIT DeviceInit
    )
/*++

Routine Description:

    Worker routine called to create a device and its software resources.

Arguments:

    DeviceInit - Pointer to an opaque init structure. Memory for this
                    structure will be freed by the framework when the WdfDeviceCreate
                    succeeds. So don't access the structure after that point.

Return Value:

    NTSTATUS

--*/
{
    WDF_OBJECT_ATTRIBUTES deviceAttributes;
    PDEVICE_CONTEXT deviceContext;
    WDF_PNPPOWER_EVENT_CALLBACKS PnpPowerEventCallbacks;
    WDFDEVICE device;
    NTSTATUS status;

    PAGED_CODE();

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT);
    deviceAttributes.SynchronizationScope = WdfSynchronizationScopeQueue;

    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&PnpPowerEventCallbacks);
    PnpPowerEventCallbacks.EvtDevicePrepareHardware = SmplDeviceEvtPrepareHardware;
    PnpPowerEventCallbacks.EvtDeviceReleaseHardware = SmplDeviceEvtReleaseHardware;
    PnpPowerEventCallbacks.EvtDeviceD0Entry = SmplDeviceEvtD0Entry;
    PnpPowerEventCallbacks.EvtDeviceD0Exit = SmplDeviceEvtD0Exit;
    WdfDeviceInitSetPnpPowerEventCallbacks( DeviceInit, &PnpPowerEventCallbacks);

    status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device);
    if (NT_SUCCESS(status)) 
    {   //
        // Get the device context and initialize it. DeviceGetContext is an
        // inline function generated by WDF_DECLARE_CONTEXT_TYPE macro in the
        // device.h header file. This function will do the type checking and return
        // the device context. If you pass a wrong object  handle
        // it will return NULL and assert if run under framework verifier mode.
        //
        deviceContext = DeviceGetContext(device);

        //
        // Create a device interface so that applications can find and talk
        // to us.
        //
        status = WdfDeviceCreateDeviceInterface(device,
                                                &GUID_DEVINTERFACE_SMPLDEVICE,
                                                NULL);
        if (NT_SUCCESS(status)) 
        {   //
            // Initialize the I/O Package and any Queues
            //
            status = SmplDeviceQueueInitialize(device);
        }

        if (NT_SUCCESS(status)) {
            WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS PowerPolicyIdleSettings;
            WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&PowerPolicyIdleSettings, IdleCannotWakeFromS0);
            PowerPolicyIdleSettings.IdleTimeoutType = SystemManagedIdleTimeout;

            status = WdfDeviceAssignS0IdleSettings(device, &PowerPolicyIdleSettings);
            if (!NT_SUCCESS(status)) 
            {
                DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234,"WdfDeviceAssignS0IdleSettings failed! 0x%x\n", status);
            }
        }

        if (NT_SUCCESS(status)) {
            SmplPoFxSingleComponentInitialize(device);
        }

        if (NT_SUCCESS(status)) 
        {
            WDFINTERRUPT Interrupt;
            WDF_INTERRUPT_CONFIG Configuration;
            WDF_INTERRUPT_CONFIG_INIT(&Configuration, SmplInterruptEvtIsr, SmplInterruptEvtDpc);
            Configuration.EvtInterruptEnable = SmplInterruptEvtEnable;
            Configuration.EvtInterruptDisable = SmplInterruptEvtDisable;
            status = WdfInterruptCreate(device,
                                        &Configuration,
                                        WDF_NO_OBJECT_ATTRIBUTES,
                                        &Interrupt);
            if (!NT_SUCCESS(status)) 
            {
                DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234, "WdfInterruptCreate failed! 0x%x\n", status);
            }
        }

    }

    return status;
}
Esempio n. 12
0
NTSTATUS
I2CInitialize(
    _In_ PDEVICE_CONTEXT DeviceContext,
    _In_ WDFCMRESLIST ResourcesRaw,
    _In_ WDFCMRESLIST ResourcesTranslated
)
/*++

Routine Description:

    Initialize the I2C resource that provides a communications channel to the
    port controller hardware.

Arguments:

    DeviceContext - Context for a framework device.

    ResourcesRaw - A handle to a framework resource-list object that identifies the raw hardware
    resources that the Plug and Play manager has assigned to the device.

    ResourcesTranslated - A handle to a framework resource-list object that identifies the
    translated hardware resources that the Plug and Play manager has assigned to the device.

Return Value:

    NTSTATUS

--*/
{
    TRACE_FUNC_ENTRY(TRACE_I2C);

    UNREFERENCED_PARAMETER(ResourcesRaw);
    PAGED_CODE();

    NTSTATUS status = STATUS_SUCCESS;
    WDF_INTERRUPT_CONFIG interruptConfig;
    PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor = nullptr;
    ULONG interruptIndex = 0;
    BOOLEAN connFound = FALSE;
    BOOLEAN interruptFound = FALSE;
    ULONG resourceCount;

    // Check for I2C and Interrupt resources from the resources that PnP manager has
    // allocated to our device.
    resourceCount = WdfCmResourceListGetCount(ResourcesTranslated);

    for (ULONG i = 0; ((connFound == FALSE) || (interruptFound == FALSE)) && (i < resourceCount); i++)
    {
        descriptor = WdfCmResourceListGetDescriptor(ResourcesTranslated, i);

        switch (descriptor->Type)
        {
        case CmResourceTypeConnection:
            // Check for I2C resource
            if (descriptor->u.Connection.Class == CM_RESOURCE_CONNECTION_CLASS_SERIAL &&
                descriptor->u.Connection.Type == CM_RESOURCE_CONNECTION_TYPE_SERIAL_I2C)
            {
                DeviceContext->I2CConnectionId.LowPart = descriptor->u.Connection.IdLowPart;
                DeviceContext->I2CConnectionId.HighPart = descriptor->u.Connection.IdHighPart;

                connFound = TRUE;

                TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_I2C,
                    "I2C resource found with connection id: 0x%llx",
                    DeviceContext->I2CConnectionId.QuadPart);
            }
            break;

        case CmResourceTypeInterrupt:
            // We've found an interrupt resource.
            interruptFound = TRUE;
            interruptIndex = i;
            TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_I2C,
                "Interrupt resource found at index: %lu", interruptIndex);
            break;

        default:
            // We don't care about other descriptors.
            break;
        }
    }

    // Fail if either connection or interrupt resource was not found.
    if (!connFound)
    {
        status = STATUS_INSUFFICIENT_RESOURCES;
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_I2C,
            "Failed finding required I2C resource. Status: %!STATUS!", status);

        goto Exit;
    }

    if (!interruptFound)
    {
        status = STATUS_INSUFFICIENT_RESOURCES;
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_I2C,
            "Failed finding required interrupt resource. Status: %!STATUS!", status);

        goto Exit;
    }

    // The alerts from the port controller hardware will be handled in a passive ISR.
    // The ISR performs hardware read and write operations which block until the hardware access is complete.
    // Waiting is unacceptable at DIRQL, so we perform our ISR at PASSIVE_LEVEL.
    WDF_INTERRUPT_CONFIG_INIT(&interruptConfig, OnInterruptPassiveIsr, NULL);

    interruptConfig.PassiveHandling = TRUE;
    interruptConfig.InterruptTranslated = WdfCmResourceListGetDescriptor(ResourcesTranslated, interruptIndex);
    interruptConfig.InterruptRaw = WdfCmResourceListGetDescriptor(ResourcesRaw, interruptIndex);

    status = WdfInterruptCreate(
        DeviceContext->Device,
        &interruptConfig,
        WDF_NO_OBJECT_ATTRIBUTES,
        &DeviceContext->AlertInterrupt);
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_I2C,
            "WdfInterruptCreate failed. status: %!STATUS!", status);
        goto Exit;
    }

Exit:
    TRACE_FUNC_EXIT(TRACE_I2C);
    return status;
}
Esempio n. 13
0
_Use_decl_annotations_
NTSTATUS
OnDeviceAdd(
    WDFDRIVER       Driver,
    PWDFDEVICE_INIT DeviceInit
)
/*++

Routine Description:

    OnDeviceAdd is called by the framework in response to AddDevice
    call from the PnP manager. We create and initialize a device object to
    represent a new instance of the device.

Arguments:

    Driver - Handle to a framework driver object created in DriverEntry
    DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure

Return Value:

    Status

--*/
{
    PAGED_CODE();
    UNREFERENCED_PARAMETER(Driver);
    WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
    WDF_OBJECT_ATTRIBUTES   objectAttributes;
    PDEVICE_CONTEXT deviceContext;
    WDFDEVICE device;
    NTSTATUS status;
    DECLARE_UNICODE_STRING_SIZE(symbolicLinkName, 128);

    //
    // Set PnP callbacks.
    //

    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
    pnpPowerCallbacks.EvtDevicePrepareHardware = PrepareHardware;
    pnpPowerCallbacks.EvtDeviceReleaseHardware = ReleaseHardware;
    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

    //
    // PWM only allows exclusive access.
    //

    WdfDeviceInitSetExclusive(DeviceInit, TRUE);

    //
    // Create device object.
    //

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&objectAttributes, DEVICE_CONTEXT);
    objectAttributes.EvtCleanupCallback = OnDeviceContextCleanup;
    status = WdfDeviceCreate(&DeviceInit, &objectAttributes, &device);

    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Can not create device (0x%08x)", status);
        goto Exit;
    }

    deviceContext = GetContext(device);

    //
    // Prepare config spin lock.
    //

    WDF_OBJECT_ATTRIBUTES_INIT(&objectAttributes);
    status = WdfSpinLockCreate(&objectAttributes, &deviceContext->pwmLock);

    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Can not create config spin lock (0x%08x)", status);
        goto Exit;
    }

    //
    // Prepare notification list spin lock.
    //

    WDF_OBJECT_ATTRIBUTES_INIT(&objectAttributes);
    status = WdfSpinLockCreate(&objectAttributes, &deviceContext->notificationListLock);

    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Can not create notification list spin lock (0x%08x)", status);
        goto Exit;
    }

    //
    // Prepare interrupt object.
    //

    WDF_INTERRUPT_CONFIG interruptConfig;
    WDF_INTERRUPT_CONFIG_INIT(
        &interruptConfig,
        DmaIsr,
        DmaDpc
        );
    status = WdfInterruptCreate(
        device,
        &interruptConfig,
        WDF_NO_OBJECT_ATTRIBUTES,
        &deviceContext->interruptObj
        );

    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Can not create interrupt object (0x%08x)", status);
        goto Exit;
    }

    //
    // Create queues to handle IO.
    //

    WDF_IO_QUEUE_CONFIG queueConfig;

    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(
        &queueConfig,
        WdfIoQueueDispatchParallel);

    queueConfig.EvtIoDeviceControl = OnIoDeviceControl;
    queueConfig.PowerManaged = WdfFalse;

    status = WdfIoQueueCreate(
        device,
        &queueConfig,
        WDF_NO_OBJECT_ATTRIBUTES,
        &deviceContext->queueObj
        );

    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Can not create IO queue (0x%08x)", status);
        goto Exit;
    }

    //
    // Create a symbolic link.
    //

    status = RtlUnicodeStringInit(&symbolicLinkName, BCM_PWM_SYMBOLIC_NAME);

    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Can not process the symbolic name (0x%08x)", status);
        goto Exit;
    }

    status = WdfDeviceCreateSymbolicLink(
        device,
        &symbolicLinkName
        );

    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Can not create a symbolic name (0x%08x)", status);
        goto Exit;
    }
    
Exit:
    return status;
}
Esempio n. 14
0
NTSTATUS
InterruptCreate (
    _In_ WDFDEVICE Device,
    _In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR  InterruptResourceRaw,
    _In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR  InterruptResourceTranslated
    )
/*++

Routine Description:

    Helper function to create device's WDFINTERRUPT object and any other 
    needed WDF resources that the interrupt needs for proper functioning.

    It assumes the first interrupt resource with which this is invoked is 
    the device interrupt, and the second is the attach/detach interrupt.

Arguments:

    Device - Wdf device object corresponding to the FDO

    InterruptResourceRaw -  Raw resource for the interrupt

    InterruptResourceTranslated - Translated resource for the interrupt

Return Value:

    Appropriate NTSTATUS value

--*/
{
    NTSTATUS Status;
    WDF_INTERRUPT_CONFIG InterruptConfig;
    PCONTROLLER_CONTEXT ControllerContext;
    WDF_OBJECT_ATTRIBUTES Attributes;
    WDFINTERRUPT* InterruptToCreate;

    TraceEntry();

    PAGED_CODE();

    ControllerContext = DeviceGetControllerContext(Device);

    WDF_OBJECT_ATTRIBUTES_INIT(&Attributes);

    if (ControllerContext->DeviceInterrupt == NULL) {
        WDF_INTERRUPT_CONFIG_INIT(
            &InterruptConfig, 
            DeviceInterrupt_EvtInterruptIsr,
            DeviceInterrupt_EvtInterruptDpc);

        WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(
            &Attributes, 
            DEVICE_INTERRUPT_CONTEXT);

        InterruptToCreate = &ControllerContext->DeviceInterrupt;

    } else if (ControllerContext->AttachDetachInterrupt == NULL) {
        WDF_INTERRUPT_CONFIG_INIT(
            &InterruptConfig,
            DeviceInterrupt_EvtAttachDetachInterruptIsr,
            DeviceInterrupt_EvtInterruptDpc);
        InterruptConfig.CanWakeDevice = TRUE;
        InterruptConfig.PassiveHandling = TRUE;
        InterruptToCreate = &ControllerContext->AttachDetachInterrupt;

    } else {
        TraceWarning("Other interrupt resource [0X%X] is detected and is being"
                        " ignored", InterruptResourceRaw->u.Interrupt.Vector);
        Status = STATUS_SUCCESS;
        goto End;
    }
    
    InterruptConfig.InterruptRaw = InterruptResourceRaw;
    InterruptConfig.InterruptTranslated = InterruptResourceTranslated;

    Status = WdfInterruptCreate(
                 Device,
                 &InterruptConfig,
                 &Attributes,
                 InterruptToCreate);
    CHK_NT_MSG(Status, "Failed to create Device interrupt");

End:
    TraceExit();
    return Status;
}
Esempio n. 15
0
File: Device.c Progetto: uri247/kmdf
NTSTATUS
SmplDeviceCreateDevice(
    _Inout_ PWDFDEVICE_INIT DeviceInit
)
/*++

Routine Description:

    Worker routine called to create a device and its software resources.

Arguments:

    DeviceInit - Pointer to an opaque init structure. Memory for this
                    structure will be freed by the framework when the WdfDeviceCreate
                    succeeds. So don't access the structure after that point.

Return Value:

    NTSTATUS

--*/
{
    WDF_OBJECT_ATTRIBUTES   deviceAttributes;
    PDEVICE_CONTEXT deviceContext;
    WDFDEVICE device;
    NTSTATUS status;
    WDF_PNPPOWER_EVENT_CALLBACKS PnpPowerCallbacks;

    PAGED_CODE();

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT);



    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&PnpPowerCallbacks);
    PnpPowerCallbacks.EvtDevicePrepareHardware = SmplDeviceEvtPrepareHardware;
    PnpPowerCallbacks.EvtDeviceReleaseHardware = SmplDeviceEvtReleaseHardware;
    PnpPowerCallbacks.EvtDeviceD0Entry = SmplDeviceEvtD0Entry;
    PnpPowerCallbacks.EvtDeviceD0Exit = SmplDeviceEvtD0Exit;
    WdfDeviceInitSetPnpPowerEventCallbacks( DeviceInit, &PnpPowerCallbacks);


    status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device);

    if (NT_SUCCESS(status)) {
        WDF_INTERRUPT_CONFIG InterruptConfig;
        WDFINTERRUPT Interrupt;
        //
        // Get a pointer to the device context structure that we just associated
        // with the device object. We define this structure in the device.h
        // header file. DeviceGetContext is an inline function generated by
        // using the WDF_DECLARE_CONTEXT_TYPE_WITH_NAME macro in device.h.
        // This function will do the type checking and return the device context.
        // If you pass a wrong object handle it will return NULL and assert if
        // run under framework verifier mode.
        //
        deviceContext = DeviceGetContext(device);

        //
        // Initialize the context.
        //
        WDF_INTERRUPT_CONFIG_INIT(&InterruptConfig, SmplInterruptEvtIsr, NULL);

        InterruptConfig.EvtInterruptEnable = SmplInterruptEvtEnable;
        InterruptConfig.EvtInterruptDisable = SmplInterruptEvtDisable;

        status = WdfInterruptCreate( device,
                                     &InterruptConfig,
                                     WDF_NO_OBJECT_ATTRIBUTES,
                                     &Interrupt);
        if(!NT_SUCCESS(status))
        {
            DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234,"WdfInterruptCreate failed! 0x%x\n", status);
            return status;
        }


        //
        // Create a device interface so that applications can find and talk
        // to us.
        //
        status = WdfDeviceCreateDeviceInterface(
                     device,
                     &GUID_DEVINTERFACE_SMPLDEVICE,
                     NULL // ReferenceString
                 );

        if (NT_SUCCESS(status)) {
            //
            // Initialize the I/O Package and any Queues
            //
            status = SmplDeviceQueueInitialize(device);
        }
    }

    return status;
}
Esempio n. 16
0
NTSTATUS VioCryptDeviceAdd(IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit)
{
    NTSTATUS status;
    WDFDEVICE device;
    WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
    WDF_OBJECT_ATTRIBUTES attributes;
    WDFQUEUE queue;
    WDF_IO_QUEUE_CONFIG queueConfig;
    WDF_INTERRUPT_CONFIG interruptConfig;
    PDEVICE_CONTEXT context;

    UNREFERENCED_PARAMETER(Driver);

    Trace(TRACE_LEVEL_VERBOSE, "[%s] -->", __FUNCTION__);

    PAGED_CODE();

    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);

    pnpPowerCallbacks.EvtDevicePrepareHardware = VioCryptDevicePrepareHardware;
    pnpPowerCallbacks.EvtDeviceReleaseHardware = VioCryptDeviceReleaseHardware;
    pnpPowerCallbacks.EvtDeviceD0Entry = VioCryptDeviceD0Entry;
    pnpPowerCallbacks.EvtDeviceD0Exit = VioCryptDeviceD0Exit;

    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
    WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect);

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);
    attributes.EvtCleanupCallback = VioCryptDeviceContextCleanup;

    status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
    if (!NT_SUCCESS(status))
    {
        Trace(TRACE_LEVEL_ERROR, "[%s] WdfDeviceCreate failed: status %X", __FUNCTION__, status);
        return status;
    }

    context = GetDeviceContext(device);

    RtlZeroMemory(context, sizeof(*context));
    InitializeListHead(&context->PendingBuffers);

    WDF_INTERRUPT_CONFIG_INIT(&interruptConfig, VioCryptInterruptIsr, VioCryptInterruptDpc);

    interruptConfig.EvtInterruptEnable = VioCryptInterruptEnable;
    interruptConfig.EvtInterruptDisable = VioCryptInterruptDisable;

    status = WdfInterruptCreate(device, &interruptConfig,
        WDF_NO_OBJECT_ATTRIBUTES, &context->WdfInterrupt);

    if (!NT_SUCCESS(status))
    {
        Trace(TRACE_LEVEL_ERROR, "[%s] WdfInterruptCreate failed: status %X", __FUNCTION__, status);
        return status;
    }

    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    attributes.ParentObject = device;
    status = WdfSpinLockCreate(&attributes,
        &context->VirtQueueLock);

    if (!NT_SUCCESS(status))
    {
        Trace(TRACE_LEVEL_ERROR, "[%s] WdfSpinLockCreate failed: status %X", __FUNCTION__, status);
        return status;
    }

    status = WdfDeviceCreateDeviceInterface(device,
        &GUID_DEVINTERFACE_VIOCRYPT, NULL);

    if (!NT_SUCCESS(status))
    {
        Trace(TRACE_LEVEL_ERROR, "[%s] WdfDeviceCreateDeviceInterface failed: status %X", __FUNCTION__, status);
        return status;
    }

    WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchSequential);
    queueConfig.EvtIoDeviceControl = VioCryptIoControl;
    queueConfig.EvtIoStop = VioCryptIoStop;
    queueConfig.AllowZeroLengthRequests = FALSE;

    status = WdfIoQueueCreate(device, &queueConfig,
        WDF_NO_OBJECT_ATTRIBUTES, &queue);

    if (!NT_SUCCESS(status))
    {
        Trace(TRACE_LEVEL_ERROR, "[%s] WdfIoQueueCreate failed: status %X", __FUNCTION__, status);
        return status;
    }

    status = WdfDeviceConfigureRequestDispatching(device, queue, WdfRequestTypeDeviceControl);

    if (!NT_SUCCESS(status))
    {
        Trace(TRACE_LEVEL_ERROR, "[%s] WdfDeviceConfigureRequestDispatching failed: status %X", __FUNCTION__, status);
        return status;
    }

    Trace(TRACE_LEVEL_VERBOSE, "[%s] <--", __FUNCTION__);

    return status;
}