Пример #1
0
// Typically on IRP_MN_START_DEVICE
NTSTATUS
RoboDeviceEvtDevicePrepareHardware(
    WDFDEVICE      Device,
    WDFCMRESLIST   ResourcesRaw,
    WDFCMRESLIST   ResourcesTranslated
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    ULONG i;

    // pCtx

    UNREFERENCED_PARAMETER(Device);
    UNREFERENCED_PARAMETER(ResourcesRaw);
    DbgPrint( "RoboDeviceEvtDevicePrepareHardware called" );
    PAGED_CODE();

    //
    // Get the number item that are currently in Resources collection and
    // iterate thru as many times to get more information about the each items
    //

    for (i=0; i < WdfCmResourceListGetCount(ResourcesTranslated); i++)
    {
        PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor;

        descriptor = WdfCmResourceListGetDescriptor(ResourcesTranslated, i);

        switch(descriptor->Type)
        {

        case CmResourceTypePort:
            DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "I/O Port: (%x) Lenth: (%d)\n", 
                    descriptor->u.Port.Start.LowPart,
                    descriptor->u.Port.Length );
            break;

        case CmResourceTypeMemory:
            DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Memory: (%x) Lenth: (%d)\n", 
                    descriptor->u.Memory.Start.LowPart,
                    descriptor->u.Memory.Length );
            break;

        case CmResourceTypeInterrupt:
            DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, 
                "Interrupt level: 0x%0x, Vector: 0x%0x, Affinity: 0x%0Ix\n",
                descriptor->u.Interrupt.Level,
                descriptor->u.Interrupt.Vector,
                descriptor->u.Interrupt.Affinity );
            break;

        default:
            break;
        }

    }

    return status;

}
Пример #2
0
NTSTATUS fscc_card_delete(struct fscc_card *card,
                          WDFCMRESLIST ResourcesTranslated)
{	
    unsigned bar_counter = 0;
    unsigned i = 0;

    for (i = 0; i < WdfCmResourceListGetCount(ResourcesTranslated); i++) {		
        PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor;

        descriptor = WdfCmResourceListGetDescriptor(ResourcesTranslated, i);

        if (!descriptor)
            return STATUS_DEVICE_CONFIGURATION_ERROR;

        switch (descriptor->Type) {
        case CmResourceTypePort:
            bar_counter++;
            break;

        case CmResourceTypeMemory:
            MmUnmapIoSpace(card->bar[bar_counter].address,
                descriptor->u.Memory.Length);

            bar_counter++;
            break;
        }
    }

    return STATUS_SUCCESS;
}
Пример #3
0
NTSTATUS
AmccPciEvtDevicePrepareHardware(
    _In_ WDFDEVICE       Device,
    _In_ WDFCMRESLIST   Resources,
    _In_ WDFCMRESLIST   ResourcesTranslated
    )
/*++

Routine Description:

    EvtDevicePrepareHardware event callback performs operations that are necessary
    to use the device's control registers.

Arguments:

    Device - Handle to a framework device object.

    Resources - Handle to a collection of framework resource objects.
                This collection identifies the raw (bus-relative) hardware
                resources that have been assigned to the device.

    ResourcesTranslated - Handle to a collection of framework resource objects.
                This collection identifies the translated (system-physical)
                hardware resources that have been assigned to the device.
                The resources appear from the CPU's point of view.
                Use this list of resources to map I/O space and
                device-accessible memory into virtual address space

Return Value:

    WDF status code.

    Let us not worry about cleaning up the resources here if we fail start,
    because the PNP manager will send a remove-request and we will free all
    the allocated resources in AmccPciEvtDeviceReleaseHardware.

--*/
{
    ULONG                               i;
    NTSTATUS                            status = STATUS_SUCCESS;
    PAMCC_DEVICE_EXTENSION                   devExt = NULL;
    BOOLEAN                             foundPort      = FALSE;
    PHYSICAL_ADDRESS                    portBasePA     = {0};
    ULONG                               portCount      = 0;
    WDF_DMA_ENABLER_CONFIG              dmaConfig;
    PCM_PARTIAL_RESOURCE_DESCRIPTOR     desc;

    PAGED_CODE();

    //
    // The Resources collection is not used for PCI devices, since the PCI
    // bus driver manages the device's PCI Base Address Registers.
    //

    UNREFERENCED_PARAMETER( Resources );


    devExt = AmccPciGetDevExt(Device);

    //
    // Parse the resource list and save the resource information.
    //
    for (i=0; i < WdfCmResourceListGetCount(ResourcesTranslated); i++) {

        desc = WdfCmResourceListGetDescriptor(ResourcesTranslated, i);

        if(!desc) {
            TraceEvents(TRACE_LEVEL_ERROR, AMCC_TRACE_INIT,
                            "WdfResourceCmGetDescriptor failed");
            return STATUS_DEVICE_CONFIGURATION_ERROR;
        }

        switch (desc->Type) {

        case CmResourceTypePort:

            portBasePA = desc->u.Port.Start;
            portCount  = desc->u.Port.Length;

            devExt->PortMapped =
                (desc->Flags & CM_RESOURCE_PORT_IO) ? FALSE : TRUE;

            foundPort = TRUE;

            //
            // Map in the single IO Space resource.
            //
            if (devExt->PortMapped) {

                devExt->PortBase =
                    (PUCHAR) MmMapIoSpace( portBasePA, portCount, MmNonCached );

                if (!devExt->PortBase) {

                    TraceEvents(TRACE_LEVEL_ERROR, AMCC_TRACE_INIT,
                                    "Unable to map port range 0x%p, length %d",
                                        devExt->PortBase, devExt->PortCount);

                    return STATUS_INSUFFICIENT_RESOURCES;
                }

                devExt->PortCount = portCount;

            } else {

                devExt->PortBase  = (PUCHAR)(ULONG_PTR) portBasePA.QuadPart;
                devExt->PortCount = portCount;
            }

            devExt->Regs = (PREG5933) devExt->PortBase;

            break;

        default:
            TraceEvents(TRACE_LEVEL_WARNING, AMCC_TRACE_INIT,
                                "Unknown resource type %d", desc->Type);
            break;
        }

    }

    if (!foundPort) {
        TraceEvents(TRACE_LEVEL_ERROR, AMCC_TRACE_INIT,
                            "Missing hardware resources");
        return STATUS_DEVICE_CONFIGURATION_ERROR;
    }


    //
    // Configure the DMA  object
    //

    WDF_DMA_ENABLER_CONFIG_INIT( &dmaConfig,
                                 WdfDmaProfilePacket,
                                 devExt->MaximumTransferLength );

    status = WdfDmaEnablerCreate( devExt->Device,
                                  &dmaConfig,
                                  WDF_NO_OBJECT_ATTRIBUTES,
                                  &devExt->DmaEnabler );

    if (!NT_SUCCESS (status)) {
        TraceEvents(TRACE_LEVEL_ERROR, AMCC_TRACE_INIT,
                       "WdfDmaEnablerCreate failed %08X", status);
        return status;
    }

    return STATUS_SUCCESS;
}
Пример #4
0
///////////////////////////////////////////////////////////////////////////////
// Private local helper function that parses the translated resource list 
// and extracts the data needed for the port address.
///////////////////////////////////////////////////////////////////////////////
NTSTATUS
SmplDeviceHwResourcesGet(
    IN WDFDEVICE Device,
    IN WDFCMRESLIST ResourceListTranslated
    )
{
    NTSTATUS Status = STATUS_SUCCESS;
    ULONG index = 0;
    PCM_PARTIAL_RESOURCE_DESCRIPTOR  pCMResourceDescPartial;
    PDEVICE_CONTEXT pSmplDeviceContext = NULL;

    pSmplDeviceContext = DeviceGetContext(Device);

    DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234,"SmplDeviceHwResourcesGet >>\n");

    if (NULL != pSmplDeviceContext)
    {
        for (index = 0; index < WdfCmResourceListGetCount(ResourceListTranslated); index++)
        {
            pCMResourceDescPartial = WdfCmResourceListGetDescriptor(ResourceListTranslated, index);
            
            if (NULL == pCMResourceDescPartial)
            {
                DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234,"pCMResourceDescPartial is NULL!!!\n");
                return STATUS_DEVICE_CONFIGURATION_ERROR;
            }

            switch (pCMResourceDescPartial->Type) 
            {
                case CmResourceTypePort:
                    //
                    // Handle port resources here.
                    //
                    DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234,"CmResourceTypePort 0x%x %d\n", pCMResourceDescPartial->u.Port.Start.LowPart, pCMResourceDescPartial->u.Port.Length);
                    pSmplDeviceContext->pPortAddress = (PUCHAR) pCMResourceDescPartial->u.Port.Start.LowPart;
                    pSmplDeviceContext->PortAddressLength = pCMResourceDescPartial->u.Port.Length;
                    break;

                case CmResourceTypeMemory:
                    //
                    // Handle memory resources here.
                    //
                    DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234,"CmResourceTypeMemory Desc\n");
                    break;

                case CmResourceTypeInterrupt:
                    //
                    // Handle interrupt resources here.
                    //
                    DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234,"CmResourceTypeInterrupt\n");
                    break;
                default:
                    //
                    // Ignore all other descriptors.
                    //
                    DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234,"CmResourceType unknown\n");
                    break;
            } // end switch
        } // end for loop
    } // end if

    return Status;

} // end SmplDeviceHwResourcesGet
Пример #5
0
NTSTATUS
PortIOEvtDevicePrepareHardware(
    _In_ WDFDEVICE  Device,    
    _In_ WDFCMRESLIST  ResourcesRaw,    
    _In_ WDFCMRESLIST  ResourcesTranslated    
    )
/*++

Routine Description:

    This event is called by the Framework when the device is started
    or restarted after a suspend operation.

Arguments:

    Device - Handle to a framework device object.

Return Value:

    NTSTATUS - Failures will result in the device stack being torn down.

--*/
{
    ULONG  i;
    PCM_PARTIAL_RESOURCE_DESCRIPTOR  desc;
    PCM_PARTIAL_RESOURCE_DESCRIPTOR  descTranslated;
    PDEVICE_CONTEXT deviceContext = NULL;
    NTSTATUS status = STATUS_SUCCESS;

    PAGED_CODE();
    
    if ((NULL == ResourcesRaw) || 
        (NULL == ResourcesTranslated)){
        return STATUS_DEVICE_CONFIGURATION_ERROR;        
    }
        
    deviceContext = PortIOGetDeviceContext(Device);
    
    for (i=0; i < WdfCmResourceListGetCount(ResourcesRaw); i++) {
        
        desc = WdfCmResourceListGetDescriptor(ResourcesRaw, i);
        descTranslated =  WdfCmResourceListGetDescriptor(ResourcesTranslated, i);
        
        switch(desc ->Type) {
        case CmResourceTypePort:

            switch(descTranslated -> Type) {
            case CmResourceTypePort:
                deviceContext -> PortWasMapped = FALSE;
                deviceContext -> PortBase = ULongToPtr(descTranslated->u.Port.Start.LowPart);
                deviceContext -> PortCount = descTranslated ->u.Port.Length;
                KdPrint(("Resource Translated Port: (%x) Length: (%d)\n",
                         descTranslated->u.Port.Start.LowPart,
                         descTranslated->u.Port.Length));                        
                break;
            case CmResourceTypeMemory:
                //
                // Map the memory
                //
                deviceContext-> PortBase = (PVOID)
                                    MmMapIoSpace(descTranslated->u.Memory.Start,
                                                 descTranslated->u.Memory.Length,
                                                 MmNonCached);
                deviceContext-> PortCount = descTranslated->u.Memory.Length;

                deviceContext-> PortWasMapped = TRUE;
                
                KdPrint(("Resource Translated Memory: (%x) Length: (%d)\n",
                         descTranslated->u.Memory.Start.LowPart,
                         descTranslated->u.Memory.Length));                        
                break;
            default:
                KdPrint(("Unhandled resource_type (0x%x)\n", descTranslated->Type));
                status = STATUS_UNSUCCESSFUL;
                ASSERTMSG("Unhandled resource_type in start request\n", FALSE);                        
            }
            break;

        case CmResourceTypeMemory:
            deviceContext-> PortBase = (PVOID)
                                    MmMapIoSpace (descTranslated->u.Memory.Start,
                                    descTranslated->u.Memory.Length,
                                    MmNonCached);
            deviceContext-> PortCount = descTranslated->u.Memory.Length;

            deviceContext-> PortWasMapped = TRUE;
                    
            KdPrint(("Resource Translated Memory: (%x) Length: (%d)\n",
                    descTranslated->u.Memory.Start.LowPart,
                    descTranslated->u.Memory.Length));                        
            
            break;
        case CmResourceTypeInterrupt:
        default:
        KdPrint(("Unhandled resource type (0x%x)\n", desc->Type));
        status = STATUS_UNSUCCESSFUL;
        break;
        }

    }

    return status;
}
Пример #6
0
NTSTATUS fscc_card_init(struct fscc_card *card,
                        WDFCMRESLIST ResourcesTranslated,
                        WDFDEVICE port_device)
{	
    unsigned bar_num = 0;
    unsigned i = 0;
    PDEVICE_OBJECT pdo;

    card->device_id = 0;

    for (i = 0; i < WdfCmResourceListGetCount(ResourcesTranslated); i++) {
        PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor;

        descriptor = WdfCmResourceListGetDescriptor(ResourcesTranslated, i);

        if (!descriptor)
            return STATUS_DEVICE_CONFIGURATION_ERROR;

        switch (descriptor->Type) {
        case CmResourceTypePort:
            switch (i) {
            case 0:
                bar_num = 2;
                break;

            case 2:
                bar_num = 0;
                break;
            }

            card->bar[bar_num].address =
                ULongToPtr(descriptor->u.Port.Start.LowPart);

            card->bar[bar_num].memory_mapped = FALSE;
            break;

        case CmResourceTypeMemory:
            switch (i) {
            case 0:
                bar_num = 2;
                break;

            case 2:
                bar_num = 0;
                break;
            }

            card->bar[bar_num].address =
                MmMapIoSpace(descriptor->u.Memory.Start,
                             descriptor->u.Memory.Length,
                             MmNonCached);

            card->bar[bar_num].memory_mapped = TRUE;
            break;
        }
    }

    pdo = WdfDeviceWdmGetDeviceObject(port_device);

    PCIReadConfigWord(pdo, 0x02, &card->device_id);

    return STATUS_SUCCESS;
}
Пример #7
0
_Use_decl_annotations_
NTSTATUS
PrepareHardware(
    WDFDEVICE Device,
    WDFCMRESLIST ResourceList,
    WDFCMRESLIST ResourceListTranslated
)
/*++

Routine Description:

    PrepareHardware parses the device resource description and assigns default values
    in device context.

Arguments:

    Device - Pointer to the device object
    ResourceList - Pointer to the devices resource list
    ResourceListTranslated - Ponter to the translated resource list of the device

Return Value:

    Status

--*/
{
    PAGED_CODE();
    UNREFERENCED_PARAMETER(ResourceList);

    PDEVICE_CONTEXT deviceContext;
    NTSTATUS status = STATUS_SUCCESS;
    ULONG resourceCount;
    ULONG memoryResources = 0;
    ULONG interruptResources = 0;
    ULONG dmaResources = 0;

    deviceContext = GetContext(Device);

    resourceCount = WdfCmResourceListGetCount(ResourceListTranslated);
    for (ULONG i = 0; i < resourceCount && NT_SUCCESS(status); ++i)
    {
        PCM_PARTIAL_RESOURCE_DESCRIPTOR res;

        res = WdfCmResourceListGetDescriptor(ResourceListTranslated, i);

        switch (res->Type)
        {

            case CmResourceTypeMemory:
                if (memoryResources == 0)
                {
                    //
                    // DMA channel registers
                    //

                    if (res->u.Memory.Length < sizeof(DMA_CHANNEL_REGS))
                    {
                        TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "DMA channel memory region too small (start:0x%llX, length:0x%X)",
                            res->u.Memory.Start.QuadPart,
                            res->u.Memory.Length
                            );
                        status = STATUS_DEVICE_CONFIGURATION_ERROR;
                        break;
                    }

                    deviceContext->dmaChannelRegs = (PDMA_CHANNEL_REGS)MmMapIoSpaceEx(
                        res->u.Memory.Start,
                        res->u.Memory.Length,
                        PAGE_READWRITE | PAGE_NOCACHE
                        );

                    if (deviceContext->dmaChannelRegs == NULL)
                    {
                        TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Unable to map DMA channel registers.");
                        status = STATUS_INSUFFICIENT_RESOURCES;
                        break;
                    }
                    deviceContext->dmaChannelRegsPa = res->u.Memory.Start;
                }
                else if (memoryResources == 1)
                {
                    //
                    // PWM registers
                    //

                    if (res->u.Memory.Length < sizeof(PWM_REGS))
                    {
                        TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "PWM control register memory region too small (start:0x%llX, length:0x%X)",
                            res->u.Memory.Start.QuadPart,
                            res->u.Memory.Length
                            );
                        status = STATUS_DEVICE_CONFIGURATION_ERROR;
                        break;
                    }

                    deviceContext->pwmRegs = (PPWM_REGS)MmMapIoSpaceEx(
                        res->u.Memory.Start,
                        res->u.Memory.Length,
                        PAGE_READWRITE | PAGE_NOCACHE
                        );

                    if (deviceContext->pwmRegs == NULL)
                    {
                        TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Unable to map PWM control registers.");
                        status = STATUS_INSUFFICIENT_RESOURCES;
                        break;
                    }
                    deviceContext->pwmRegsPa = res->u.Memory.Start;
                }
                else if (memoryResources == 2)
                {
                    //
                    // PWM control registers bus address
                    //

                    deviceContext->pwmRegsBusPa = res->u.Memory.Start;
                }
                else if (memoryResources == 3)
                {
                    //
                    // PWM control registers uncached address
                    //

                    PHYSICAL_ADDRESS pa = res->u.Memory.Start;
                    deviceContext->memUncachedOffset = pa.LowPart - deviceContext->pwmRegsPa.LowPart;
                }
                else if (memoryResources == 4)
                {
                    //
                    // PWM clock registers
                    //

                    if (res->u.Memory.Length < sizeof(CM_PWM_REGS))
                    {
                        TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "PWM clock register memory region too small (start:0x%llX, length:0x%X)",
                            res->u.Memory.Start.QuadPart,
                            res->u.Memory.Length
                            );
                        status = STATUS_DEVICE_CONFIGURATION_ERROR;
                        break;
                    }

                    deviceContext->cmPwmRegs = (PCM_PWM_REGS)MmMapIoSpaceEx(
                        res->u.Memory.Start,
                        res->u.Memory.Length,
                        PAGE_READWRITE | PAGE_NOCACHE
                        );

                    if (deviceContext->cmPwmRegs == NULL)
                    {
                        TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Unable to map PWM clock registers.");
                        status = STATUS_INSUFFICIENT_RESOURCES;
                        break;
                    }
                    deviceContext->cmPwmRegsPa = res->u.Memory.Start;
                }
                else
                {
                    TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Too many ACPI memory entries. Only 5 memory entries are allowed. Please verify ACPI configuration.");
                    status = STATUS_DEVICE_CONFIGURATION_ERROR;
                    break;
                }
                memoryResources++;
                break;

            case CmResourceTypeInterrupt:

                //
                // Interrupt for used DMA channel. No setup required.
                //

                interruptResources++;
                break;

            case CmResourceTypeDma:

                //
                // Get the used DMA channel.
                //

                deviceContext->dmaChannel = res->u.DmaV3.Channel;
                deviceContext->dmaDreq = res->u.DmaV3.RequestLine;
                deviceContext->dmaTransferWidth = (DMA_WIDTH)res->u.DmaV3.TransferWidth;

                //
                // Sanity check DREQ, transfer width.
                //

                if (deviceContext->dmaDreq != DMA_DREQ_PWM)
                {
                    TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "PWM DREQ configuration invalid (DREQ:%d)", res->u.DmaV3.RequestLine);
                    status = STATUS_DEVICE_CONFIGURATION_ERROR;
                    break;
                }
                if (deviceContext->dmaTransferWidth != Width32Bits)
                {
                    TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "PWM DMA transfer width setting (width setting:%d)", (ULONG)res->u.DmaV3.TransferWidth);
                    status = STATUS_DEVICE_CONFIGURATION_ERROR;
                    break;
                }

                //
                // Allocate and initialize contiguous DMA buffer logic.
                //

                status = AllocateDmaBuffer(deviceContext);
                if (NT_ERROR(status))
                {
                    TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Error allocating DMA buffer (0x%08x)", status);
                }

                dmaResources++;
                break;

            default:
                TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Resource type not allowed for PWM. Please verify ACPI configuration.");
                status = STATUS_DEVICE_CONFIGURATION_ERROR;
                break;
        }
    }
    
    //
    // Sanity check ACPI resources.
    //
    if (memoryResources != 5)
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Too less ACPI memory entries. 5 memory entries are required. Please verify ACPI configuration.");
        status = STATUS_DEVICE_CONFIGURATION_ERROR;
    }
    if (interruptResources != 1)
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Exactly 1 interrupt entry is required and allowed. Please verify ACPI configuration.");
        status = STATUS_DEVICE_CONFIGURATION_ERROR;
    }
    if (dmaResources != 1)
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Exactly 1 DMA entry is required and allowed. Please verify ACPI configuration.");
        status = STATUS_DEVICE_CONFIGURATION_ERROR;
    }

    if (NT_SUCCESS(status))
    {
        //
        // Initialize device context and set default values.
        //

        deviceContext->pwmClockConfig.ClockSource = BCM_PWM_CLOCKSOURCE_PLLC;
        deviceContext->pwmClockConfig.Divisor = CM_PWMCTL_DIVI_PLLC_1MHZ;

        deviceContext->pwmChannel1Config.Channel = BCM_PWM_CHANNEL_CHANNEL1;
        deviceContext->pwmChannel1Config.Range = 0x20;
        deviceContext->pwmChannel1Config.DutyMode = BCM_PWM_DUTYMODE_PWM;
        deviceContext->pwmChannel1Config.Mode = BCM_PWM_MODE_PWM;
        deviceContext->pwmChannel1Config.Polarity = BCM_PWM_POLARITY_NORMAL;
        deviceContext->pwmChannel1Config.Repeat = BCM_PWM_REPEATMODE_OFF;
        deviceContext->pwmChannel1Config.Silence = BCM_PWM_SILENCELEVEL_LOW;
        deviceContext->pwmDuty1 = 0;

        deviceContext->pwmChannel2Config.Channel = BCM_PWM_CHANNEL_CHANNEL2;
        deviceContext->pwmChannel2Config.Range = 0x20;
        deviceContext->pwmChannel2Config.DutyMode = BCM_PWM_DUTYMODE_PWM;
        deviceContext->pwmChannel2Config.Mode = BCM_PWM_MODE_PWM;
        deviceContext->pwmChannel2Config.Polarity = BCM_PWM_POLARITY_NORMAL;
        deviceContext->pwmChannel2Config.Repeat = BCM_PWM_REPEATMODE_OFF;
        deviceContext->pwmChannel2Config.Silence = BCM_PWM_SILENCELEVEL_LOW;
        deviceContext->pwmDuty2 = 0;
        deviceContext->pwmMode = PWM_MODE_REGISTER;
        InitializeListHead(&deviceContext->notificationList);
        deviceContext->dmaDpcForIsrErrorCount = 0;
        deviceContext->dmaUnderflowErrorCount = 0;
        deviceContext->dmaLastKnownCompletedPacket = NO_LAST_COMPLETED_PACKET;
        deviceContext->dmaPacketsInUse = 0;
        deviceContext->dmaPacketsToPrime = 0;
        deviceContext->dmaPacketsToPrimePreset = 0;
        deviceContext->dmaPacketsProcessed = 0;
        deviceContext->dmaAudioNotifcationCount = 0;
        deviceContext->dmaRestartRequired = FALSE;
    }
    else
    {
        ReleaseHardware(Device, ResourceListTranslated);
    }

    return status;
}
NTSTATUS
BalloonEvtDevicePrepareHardware(
    IN WDFDEVICE    Device,
    IN WDFCMRESLIST ResourceList,
    IN WDFCMRESLIST ResourceListTranslated
    )
{
    NTSTATUS            status         = STATUS_SUCCESS;
    BOOLEAN             foundPort      = FALSE;
    PHYSICAL_ADDRESS    PortBasePA     = {0};
    ULONG               PortLength     = 0;
    ULONG               i;
    WDF_INTERRUPT_INFO  interruptInfo;
    PDEVICE_CONTEXT     devCtx = NULL;

    PCM_PARTIAL_RESOURCE_DESCRIPTOR  desc;

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

    UNREFERENCED_PARAMETER(ResourceList);

    PAGED_CODE();

    devCtx = GetDeviceContext(Device);

    for (i=0; i < WdfCmResourceListGetCount(ResourceListTranslated); i++) {

        desc = WdfCmResourceListGetDescriptor( ResourceListTranslated, i );

        if(!desc) {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                        "WdfResourceCmGetDescriptor failed\n");
            return STATUS_DEVICE_CONFIGURATION_ERROR;
        }

        switch (desc->Type) {

            case CmResourceTypePort:
                if (!foundPort &&
                     desc->u.Port.Length >= 0x20) {

                    devCtx->PortMapped =
                         (desc->Flags & CM_RESOURCE_PORT_IO) ? FALSE : TRUE;

                    PortBasePA = desc->u.Port.Start;
                    PortLength = desc->u.Port.Length;
                    foundPort = TRUE;

                    if (devCtx->PortMapped) {
                         devCtx->PortBase =
                             (PUCHAR) MmMapIoSpace( PortBasePA, PortLength, MmNonCached );

                      if (!devCtx->PortBase) {
                         TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, " Unable to map port range %08I64X, length %d\n",
                                        PortBasePA.QuadPart, PortLength);

                         return STATUS_INSUFFICIENT_RESOURCES;
                      }
                      devCtx->PortCount = PortLength;

                    } else {
                         devCtx->PortBase  = (PUCHAR)(ULONG_PTR) PortBasePA.QuadPart;
                         devCtx->PortCount = PortLength;
                    }
                }

                TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-> Port   Resource [%08I64X-%08I64X]\n",
                            desc->u.Port.Start.QuadPart,
                            desc->u.Port.Start.QuadPart +
                            desc->u.Port.Length);
                break;

            default:
                break;
        }
    }

    if (!foundPort) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, " Missing resources\n");
        return STATUS_DEVICE_CONFIGURATION_ERROR;
    }

    WDF_INTERRUPT_INFO_INIT(&interruptInfo);
    WdfInterruptGetInfo(devCtx->WdfInterrupt, &interruptInfo);

    VirtIODeviceInitialize(&devCtx->VDevice, (ULONG_PTR)devCtx->PortBase, sizeof(devCtx->VDevice));
    VirtIODeviceSetMSIXUsed(&devCtx->VDevice, interruptInfo.MessageSignaled);

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- %s\n", __FUNCTION__);
    return status;
}
Пример #9
0
NTSTATUS
OnEvtDevicePrepareHardware (
    _In_ WDFDEVICE Device,
    _In_ WDFCMRESLIST ResourcesRaw,
    _In_ WDFCMRESLIST ResourcesTranslated
    )
/*++

Routine Description:

    EvtDevicePrepareHardware callback handler for the controller FDO.
    It expects Register memory and two interrupts - Device and Wake.

Arguments:

    Device - WDFDEVICE object representing the controller.

    ResourcesRaw - Raw resources relative to the parent bus driver.

    ResourcesTranslated - Translated resources available for the controller.

Return Value:

    Appropriate NTSTATUS value

--*/
{
    NTSTATUS Status;
    ULONG ResCount;
    ULONG ResIndex;
    PCONTROLLER_CONTEXT ControllerContext;
    BOOLEAN MemoryResourceMapped;

    PAGED_CODE();

    TraceEntry();

    ControllerContext = DeviceGetControllerContext(Device);
    MemoryResourceMapped = FALSE;

    ResCount = WdfCmResourceListGetCount(ResourcesRaw);

    Status = STATUS_SUCCESS;

    for (ResIndex = 0; ResIndex < ResCount; ResIndex++) {

        PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptorRaw;
        PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptorTranslated;

        ResourceDescriptorRaw = WdfCmResourceListGetDescriptor(
                                                        ResourcesRaw,
                                                        ResIndex);
        switch (ResourceDescriptorRaw->Type) {

        case CmResourceTypeMemory:
            if (MemoryResourceMapped == FALSE) {
                MemoryResourceMapped = TRUE;
                Status = RegistersCreate(Device, ResourceDescriptorRaw);
                CHK_NT_MSG(Status, "Failed to read the HW registers");
            }
            break;

        case CmResourceTypeInterrupt:
            ResourceDescriptorTranslated = WdfCmResourceListGetDescriptor(
                                                            ResourcesTranslated,
                                                            ResIndex);
            Status = InterruptCreate(
                                Device,
                                ResourceDescriptorRaw,
                                ResourceDescriptorTranslated);
            CHK_NT_MSG(Status, "Failed to create WDFINTERRUPT object");
            break;

        default:
            break;
        }
    }

    NT_ASSERT(ControllerContext->DeviceInterrupt != NULL);

End:
    TraceExit();
    return STATUS_SUCCESS;
}
Пример #10
0
NTSTATUS
SampleDrvEvtDevicePrepareHardware (
    _In_ WDFDEVICE Device,
    _In_ WDFCMRESLIST ResourcesRaw,
    _In_ WDFCMRESLIST ResourcesTranslated
    )

/*++

Routine Description:

    This routine is called by the framework when the PnP manager sends an
    IRP_MN_START_DEVICE request to the driver stack.

Arguments:

    Device - Supplies a handle to a framework device object.

    ResourcesRaw - Supplies a handle to a collection of framework resource
        objects. This collection identifies the raw (bus-relative) hardware
        resources that have been assigned to the device.

    ResourcesTranslated - Supplies a handle to a collection of framework
        resource objects. This collection identifies the translated
        (system-physical) hardware resources that have been assigned to the
        device. The resources appear from the CPU's point of view.

Return Value:

    NT status code.

--*/

{

    PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
    PSAMPLE_DRV_DEVICE_EXTENSION SampleDrvExtension;
    ULONG Index;
    ULONG ResourceCount;
    NTSTATUS Status;
    ULONG IoResourceIndex;

    UNREFERENCED_PARAMETER(Device);
    UNREFERENCED_PARAMETER(ResourcesRaw);

    PAGED_CODE();

    SampleDrvExtension = SampleDrvGetDeviceExtension(Device);
    Status = STATUS_SUCCESS;
    IoResourceIndex = 0;

    SampleDrvExtension->InterruptCount = 0;

    //
    // Walk through the resource list and map all the resources. Only one
    // memory resource and one interrupt is expected.
    //

    ResourceCount = WdfCmResourceListGetCount(ResourcesTranslated);
    for (Index = 0; Index < ResourceCount; Index += 1) {
        Descriptor = WdfCmResourceListGetDescriptor(ResourcesTranslated, Index);
        switch(Descriptor->Type) {

        //
        // This memory resource supplies the base of the device registers.
        //

        case CmResourceTypeConnection:

            //
            //  Check against expected connection type
            //

            if ((Descriptor->u.Connection.Class ==
                 CM_RESOURCE_CONNECTION_CLASS_GPIO) &&
                (Descriptor->u.Connection.Type ==
                 CM_RESOURCE_CONNECTION_TYPE_GPIO_IO)) {

                SampleDrvExtension->ConnectionIds[IoResourceIndex].LowPart =
                    Descriptor->u.Connection.IdLowPart;
                SampleDrvExtension->ConnectionIds[IoResourceIndex].HighPart =
                      Descriptor->u.Connection.IdHighPart;
                IoResourceIndex++;
            } else {

                Status = STATUS_UNSUCCESSFUL;
            }

            break;

        //
        //  Interrupt resource
        //

        case CmResourceTypeInterrupt:
            SampleDrvExtension->InterruptCount++;

        default:
            break;
        }

        if (!NT_SUCCESS(Status)) {
            goto DevicePrepareHardwareEnd;
        }
    }

    //
    //  Ensure that at least two interrupt resources are defined. One for DIRQL
    //  and another for the passive level ISR
    //

    NT_ASSERT(SampleDrvExtension->InterruptCount > 0);

    if (SampleDrvExtension->InterruptCount < 1) {
        Status = STATUS_UNSUCCESSFUL;
        goto DevicePrepareHardwareEnd;
    }

    //
    //  Store the number of GPIO IO connection strings
    //

    SampleDrvExtension->IoResourceCount = IoResourceIndex;

DevicePrepareHardwareEnd:
    return Status;
}
Пример #11
0
// 此函数类似于WDM中的PNP_MN_START_DEVICE函数,紧接着PnpAdd之后被调用。
// 此时PNP管理器经过甄别之后,已经决定将那些系统资源分配给当前设备。
// 参数ResourceList和ResourceListTranslated代表了这些系统资源。
// 当个函数被调用时候,设备已经进入了D0电源状态;函数完成后,设备即正式进入工作状态。
NTSTATUS DrvClass::PnpPrepareHardware(IN WDFCMRESLIST ResourceList, IN WDFCMRESLIST ResourceListTranslated)
{
	NTSTATUS status;
	PDEVICE_CONTEXT pContext = NULL; 
	ULONG ulNumRes = 0;
	ULONG ulIndex;
	CM_PARTIAL_RESOURCE_DESCRIPTOR*  pResDes = NULL;

	KDBG(DPFLTR_INFO_LEVEL, "[PnpPrepareHardware]");

	pContext = GetDeviceContext(m_hDevice);

	// 配置设备
	status = ConfigureUsbDevice();
	if(!NT_SUCCESS(status))
		return status;

	// 获取Pipe句柄
	status = GetUsbPipes();
	if(!NT_SUCCESS(status))
		return status;

	// 初始电源策略,
	status = InitPowerManagement();

	// 获取USB总线驱动接口。总线接口中包含总线驱动提供的回调函数和其他信息。
	// 总线接口由系统共用GUID标识。
	status = WdfFdoQueryForInterface(
		m_hDevice,
		&USB_BUS_INTERFACE_USBDI_GUID1,		// 总线接口ID
		(PINTERFACE)&m_busInterface,		// 保存在设备环境块中
		sizeof(USB_BUS_INTERFACE_USBDI_V1),
		1, NULL);

	// 调用接口函数,判断USB版本。
	if(NT_SUCCESS(status) && m_busInterface.IsDeviceHighSpeed){
		if(m_busInterface.IsDeviceHighSpeed(m_busInterface.BusContext))
			KDBG(DPFLTR_INFO_LEVEL, "USB 2.0");
		else
			KDBG(DPFLTR_INFO_LEVEL, "USB 1.1");
	}

	// 对系统资源列表,我们不做实质性的操作,仅仅打印一些信息。
	// 读者完全可以把下面的这些代码都注释掉。
	ulNumRes = WdfCmResourceListGetCount(ResourceList);
	KDBG(DPFLTR_INFO_LEVEL, "ResourceListCount:%d\n", ulNumRes);

	// 下面我们饶有兴致地枚举这些系统资源,并打印出它们的相关名称信息。
	for(ulIndex = 0; ulIndex < ulNumRes; ulIndex++)
	{
		pResDes = WdfCmResourceListGetDescriptor(ResourceList, ulIndex);		
		if(!pResDes)continue; // 取得失败,则跳到下一个

		switch (pResDes->Type) 
		{
		case CmResourceTypeMemory:
			KDBG(DPFLTR_INFO_LEVEL, "System Resource:CmResourceTypeMemory\n");
			break;

		case CmResourceTypePort:
			KDBG(DPFLTR_INFO_LEVEL, "System Resource:CmResourceTypePort\n");
			break;

		case CmResourceTypeInterrupt:
			KDBG(DPFLTR_INFO_LEVEL, "System Resource:CmResourceTypeInterrupt\n");
			break;

		default:
			KDBG(DPFLTR_INFO_LEVEL, "System Resource:Others %d\n", pResDes->Type);
			break;
		}
	}

	return STATUS_SUCCESS;
}
Пример #12
0
NTSTATUS
VIOSerialEvtDevicePrepareHardware(
    IN WDFDEVICE Device,
    IN WDFCMRESLIST ResourcesRaw,
    IN WDFCMRESLIST ResourcesTranslated)
{
    int nListSize = 0;
    PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDescriptor;
    WDF_INTERRUPT_INFO interruptInfo;
    int i = 0;
    PPORTS_DEVICE pContext = GetPortsDevice(Device);
    bool bPortFound = FALSE;
    NTSTATUS status = STATUS_SUCCESS;
    UINT nr_ports, max_queues, size_to_allocate;

    UNREFERENCED_PARAMETER(ResourcesRaw);
    PAGED_CODE();

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

    max_queues = 64; // 2 for each of max 32 ports
    size_to_allocate = VirtIODeviceSizeRequired((USHORT)max_queues);

    pContext->pIODevice = (VirtIODevice *)ExAllocatePoolWithTag(
                                 NonPagedPool,
                                 size_to_allocate,
                                 VIOSERIAL_DRIVER_MEMORY_TAG);
    if (NULL == pContext->pIODevice)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    nListSize = WdfCmResourceListGetCount(ResourcesTranslated);

    for (i = 0; i < nListSize; i++)
    {
        if(pResDescriptor = WdfCmResourceListGetDescriptor(ResourcesTranslated, i))
        {
            switch(pResDescriptor->Type)
            {
                case CmResourceTypePort :
                    pContext->bPortMapped = (pResDescriptor->Flags & CM_RESOURCE_PORT_IO) ? FALSE : TRUE;
                    pContext->PortBasePA = pResDescriptor->u.Port.Start;
                    pContext->uPortLength = pResDescriptor->u.Port.Length;
                    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "IO Port Info  [%08I64X-%08I64X]\n",
                                 pResDescriptor->u.Port.Start.QuadPart,
                                 pResDescriptor->u.Port.Start.QuadPart +
                                 pResDescriptor->u.Port.Length);

                    if (pContext->bPortMapped )
                    {
                        pContext->pPortBase = MmMapIoSpace(pContext->PortBasePA,
                                                           pContext->uPortLength,
                                                           MmNonCached);

                        if (!pContext->pPortBase) {
                            TraceEvents(TRACE_LEVEL_ERROR, DBG_HW_ACCESS, "%s>>> Failed to map IO port!\n", __FUNCTION__);
                            return STATUS_INSUFFICIENT_RESOURCES;
                        }
                    }
                    else
                    {
                        pContext->pPortBase = (PVOID)(ULONG_PTR)pContext->PortBasePA.QuadPart;
                    }

                    bPortFound = TRUE;

                    break;
                case CmResourceTypeInterrupt:
                    break;
            }
        }
    }

    if(!bPortFound)
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_HW_ACCESS, "%s>>> %s", __FUNCTION__, "IO port wasn't found!\n");
        return STATUS_DEVICE_CONFIGURATION_ERROR;
    }
    WDF_INTERRUPT_INFO_INIT(&interruptInfo);
    WdfInterruptGetInfo(pContext->WdfInterrupt, &interruptInfo);

    VirtIODeviceInitialize(pContext->pIODevice, (ULONG_PTR)pContext->pPortBase, size_to_allocate);
    VirtIODeviceSetMSIXUsed(pContext->pIODevice, interruptInfo.MessageSignaled);

    VirtIODeviceReset(pContext->pIODevice);

    VirtIODeviceAddStatus(pContext->pIODevice, VIRTIO_CONFIG_S_ACKNOWLEDGE);

    pContext->consoleConfig.max_nr_ports = 1;
    if(pContext->isHostMultiport = VirtIODeviceGetHostFeature(pContext->pIODevice, VIRTIO_CONSOLE_F_MULTIPORT))
    {
        TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "We have multiport host\n");
        VirtIODeviceEnableGuestFeature(pContext->pIODevice, VIRTIO_CONSOLE_F_MULTIPORT);
        VirtIODeviceGet(pContext->pIODevice,
                                 FIELD_OFFSET(CONSOLE_CONFIG, max_nr_ports),
                                 &pContext->consoleConfig.max_nr_ports,
                                 sizeof(pContext->consoleConfig.max_nr_ports));
        TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
                                "VirtIOConsoleConfig->max_nr_ports %d\n", pContext->consoleConfig.max_nr_ports);
        if (pContext->consoleConfig.max_nr_ports > pContext->pIODevice->maxQueues / 2)
        {
           pContext->consoleConfig.max_nr_ports = pContext->pIODevice->maxQueues / 2;
           TraceEvents(TRACE_LEVEL_WARNING, DBG_PNP,
                                "VirtIOConsoleConfig->max_nr_ports limited to %d\n", pContext->consoleConfig.max_nr_ports);
        }
    }

    if(pContext->isHostMultiport)
    {
        WDF_OBJECT_ATTRIBUTES  attributes;
        WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
        attributes.ParentObject = Device;
        status = WdfSpinLockCreate(
                                &attributes,
                                &pContext->CVqLock
                                );
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT,
                "WdfSpinLockCreate failed 0x%x\n", status);
           return status;
        }
    }
    else
    {
//FIXME
//        VIOSerialAddPort(Device, 0);
    }

    nr_ports = pContext->consoleConfig.max_nr_ports;
    pContext->in_vqs = (struct virtqueue**)ExAllocatePoolWithTag(
                                 NonPagedPool,
                                 nr_ports * sizeof(struct virtqueue*),
                                 VIOSERIAL_DRIVER_MEMORY_TAG);

    if(pContext->in_vqs == NULL)
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT,"ExAllocatePoolWithTag failed\n");
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    memset(pContext->in_vqs, 0, nr_ports * sizeof(struct virtqueue*));
    pContext->out_vqs = (struct virtqueue**)ExAllocatePoolWithTag(
                                 NonPagedPool,
                                 nr_ports * sizeof(struct virtqueue*),
                                 VIOSERIAL_DRIVER_MEMORY_TAG
                                 );

    if(pContext->out_vqs == NULL)
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "ExAllocatePoolWithTag failed\n");
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    memset(pContext->out_vqs, 0, nr_ports * sizeof(struct virtqueue*));

    pContext->DeviceOK = TRUE;
    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_HW_ACCESS, "<-- %s\n", __FUNCTION__);
    return status;
}
Пример #13
0
NTSTATUS
TpmEvtDevicePrepareHardware (
							 WDFDEVICE      Device,
							 WDFCMRESLIST   Resources,
							 WDFCMRESLIST   ResourcesTranslated
    )
{
    NTSTATUS                    status;
    ULONG                       ListCount = 0;
    ULONG                       MemLen = 0;
//    ULONG                       NumberOfBytes;
    PTPM_CONTEXT                TpmContext;
    PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDesc;
    ULONG                       ListIndex;
    PHYSICAL_ADDRESS            MemoryAddr;
    BOOLEAN                     bMemAddr = FALSE;

	PAGED_CODE();

    TpmContext = GetTpmContext(Device);

    KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL,
                "TpmEvtDevicePrepareHardware (raw count = %u, trans count = %u)\n",
                WdfCmResourceListGetCount(Resources),
                WdfCmResourceListGetCount(ResourcesTranslated)));

    ListIndex = 0;

    ListCount = WdfCmResourceListGetCount(ResourcesTranslated);

    if(ListCount)
    {
        while(ListIndex < ListCount)
        {
            ResourceDesc = WdfCmResourceListGetDescriptor(ResourcesTranslated,ListIndex);

            if(!ResourceDesc) break;

            if(ResourceDesc->Type == CmResourceTypePort)
            {
                if(TpmContext->UsePortBasedIO)
                {
                    TpmContext->PortAddr = (PUCHAR)ResourceDesc->u.Port.Start.u.LowPart;
                }
            }
            else if(ResourceDesc->Type == CmResourceTypeMemory && TpmContext->UsePortBasedIO == 0)
            {
                MemoryAddr.u.LowPart = ResourceDesc->u.Memory.Start.u.LowPart;
                MemoryAddr.u.HighPart = ResourceDesc->u.Memory.Start.u.HighPart;
                MemLen = ResourceDesc->u.Memory.Length;
                bMemAddr = TRUE;
            }
            ListIndex++;
        }

        do
        {
            if(ListIndex < WdfCmResourceListGetCount( ResourcesTranslated))
            {
                KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL,
                    "WdfCmResourceListGetDescriptor failed.\n"));
                status = STATUS_DEVICE_CONFIGURATION_ERROR; // 0xC0000182;
                break;
            }

            if(TpmContext->UsePortBasedIO)
            {
                if(!TpmContext->PortAddr)
                {
                    if(TpmContext->UsePortBasedIO != TRUE)
                    {
                        KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_WARNING_LEVEL,
                                  "Port I/O resources required but not allocated for Vendor index %u",
                                  TpmContext->UsePortBasedIO));
                        status = STATUS_DEVICE_CONFIGURATION_ERROR; // 0xC0000182;
                        goto Exit;
                    }

                    KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_WARNING_LEVEL,
                            "No resources allocated for Port-based I/O."));

					status = STATUS_DEVICE_CONFIGURATION_ERROR;
					break;
                }
            }
            else
            {
                if(!bMemAddr)
                {
                    KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL,
                            "Physical address resource not provided via ACPI; using default address and size.\n"));
                    MemLen = 1024;
                    MemoryAddr.u.LowPart    = TPM_DEFAULT_ADDRESS;
                    MemoryAddr.u.HighPart   = 0;
                }

                if(MemLen < 1024)
                {
                    KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL,
                            "Physical address length provided is too small (%d)\n",MemLen));
                    status = STATUS_DEVICE_CONFIGURATION_ERROR; //0xC0000182;
                    break;
                }

                if(MemoryAddr.u.LowPart != TPM_DEFAULT_ADDRESS || MemoryAddr.u.HighPart)
                {
                    KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL,
                                "Physical address provided is incorrect: 0x%08x`%08x\n",MemoryAddr.u.HighPart,MemoryAddr.u.LowPart));
                    status = STATUS_DEVICE_CONFIGURATION_ERROR; //0xC0000182;
                    break;
                }

                TpmContext->MemAddr = MmMapIoSpace(MemoryAddr,MemLen,MmNonCached);
                if(!TpmContext->MemAddr)
                {
                    KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL,
                            "MmMapIoSpace couldn't map the TPM device: 0x%x.\n", MemoryAddr.u.LowPart));
                    status = STATUS_INSUFFICIENT_RESOURCES; //0xC000009A;
                    break;
                }

                TpmContext->MemLen = MemLen;

            }

            status = TpmSetDefaultTimingValues(TpmContext);
            if(!NT_SUCCESS(status))
            {
                KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL,
                    "TpmSetDefaultTimingValues failed with status 0x%x",status));
                break;
            }

            if(TpmContext->SkipInitCommands)
            {
                KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL,
                    "Skipping initialization commands\n"));
            }
            else
            {
                TpmGetTimeoutInfo(TpmContext);
                TpmGetDurations(TpmContext);
				// 获取硬件厂商信息
				TpmGetManufacturer(TpmContext);
            }

            status = TpmVerifyAccessRegister(TpmContext,TpmINB(TpmContext,0),0);
            if(!NT_SUCCESS(status))
            {
                break;
            }

#if _NT_TARGET_VERSION >= 0x601
            status = TpmEntropyInit(TpmContext);
#endif

        } while(FALSE);
    }
    else
    {
         KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL,
            "Physical address resource not provided via ACPI; using default address and size.\n"));
    }

Exit:
    KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL,
        "TpmEvtDevicePrepareHardware exited with Status code 0x%x\n",status));

    return status;
}
Пример #14
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;
}
Пример #15
0
NTSTATUS
OnPrepareHardware(
    _In_  WDFDEVICE     FxDevice,
    _In_  WDFCMRESLIST  FxResourcesRaw,
    _In_  WDFCMRESLIST  FxResourcesTranslated
    )
/*++
 
  Routine Description:

    This routine caches the SPB resource connection ID.

  Arguments:

    FxDevice - a handle to the framework device object
    FxResourcesRaw - list of translated hardware resources that 
        the PnP manager has assigned to the device
    FxResourcesTranslated - list of raw hardware resources that 
        the PnP manager has assigned to the device

  Return Value:

    Status

--*/
{
    FuncEntry(TRACE_FLAG_WDFLOADING);

    PDEVICE_CONTEXT pDevice = GetDeviceContext(FxDevice);
    BOOLEAN fSpbResourceFound = FALSE;
    NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES;

    UNREFERENCED_PARAMETER(FxResourcesRaw);

    //
    // Parse the peripheral's resources.
    //

    ULONG resourceCount = WdfCmResourceListGetCount(FxResourcesTranslated);

    for(ULONG i = 0; i < resourceCount; i++)
    {
        PCM_PARTIAL_RESOURCE_DESCRIPTOR pDescriptor;
        UCHAR Class;
        UCHAR Type;

        pDescriptor = WdfCmResourceListGetDescriptor(
            FxResourcesTranslated, i);

        switch (pDescriptor->Type)
        {
            case CmResourceTypeConnection:
                //
                // Look for I2C or SPI resource and save connection ID.
                //
                Class = pDescriptor->u.Connection.Class;
                Type = pDescriptor->u.Connection.Type;
                if (Class == CM_RESOURCE_CONNECTION_CLASS_SERIAL &&
                    Type == CM_RESOURCE_CONNECTION_TYPE_SERIAL_I2C)
                {
                    if (fSpbResourceFound == FALSE)
                    {
						status = STATUS_SUCCESS;
						pDevice->I2CContext.I2cResHubId.LowPart = pDescriptor->u.Connection.IdLowPart;
						pDevice->I2CContext.I2cResHubId.HighPart = pDescriptor->u.Connection.IdHighPart;
                        fSpbResourceFound = TRUE;
                        Trace(
                            TRACE_LEVEL_INFORMATION,
                            TRACE_FLAG_WDFLOADING,
                            "SPB resource found with ID=0x%llx",
							pDevice->I2CContext.I2cResHubId.QuadPart);
                    }
                    else
                    {
                        Trace(
                            TRACE_LEVEL_WARNING,
                            TRACE_FLAG_WDFLOADING,
                            "Duplicate SPB resource found with ID=0x%llx",
							pDevice->I2CContext.I2cResHubId.QuadPart);
                    }
                }
                break;
            default:
                //
                // Ignoring all other resource types.
                //
                break;
        }
    }

    //
    // An SPB resource is required.
    //

    if (fSpbResourceFound == FALSE)
    {
        status = STATUS_NOT_FOUND;
        Trace(
            TRACE_LEVEL_ERROR,
            TRACE_FLAG_WDFLOADING,
            "SPB resource not found - %!STATUS!", 
            status);
    }

	status = SpbTargetInitialize(FxDevice, &pDevice->I2CContext);
	if (!NT_SUCCESS(status))
	{
		Trace(
			TRACE_LEVEL_ERROR,
			TRACE_FLAG_WDFLOADING,
			"Error in Spb initialization - %!STATUS!",
			status);

		return status;
	}

    FuncExit(TRACE_FLAG_WDFLOADING);

    return status;
}
Пример #16
0
NTSTATUS
PLxPrepareHardware(
    IN PDEVICE_EXTENSION DevExt,
    IN WDFCMRESLIST     ResourcesTranslated
    )
/*++
Routine Description:

    Gets the HW resources assigned by the bus driver from the start-irp
    and maps it to system address space.

Arguments:

    DevExt      Pointer to our DEVICE_EXTENSION

Return Value:

     None

--*/
{
    ULONG               i;
    NTSTATUS            status = STATUS_SUCCESS;
    CHAR              * bar;

    BOOLEAN             foundRegs      = FALSE;
    PHYSICAL_ADDRESS    regsBasePA     = {0};
    ULONG               regsLength     = 0;

    BOOLEAN             foundSRAM      = FALSE;
    PHYSICAL_ADDRESS    SRAMBasePA     = {0};
    ULONG               SRAMLength     = 0;

    BOOLEAN             foundSRAM2     = FALSE;
    //PHYSICAL_ADDRESS    SRAM2BasePA    = {0};
    //ULONG               SRAM2Length    = 0;

    BOOLEAN             foundPort      = FALSE;

    PCM_PARTIAL_RESOURCE_DESCRIPTOR  desc;

    PAGED_CODE();

    //
    // Parse the resource list and save the resource information.
    //
    for (i=0; i < WdfCmResourceListGetCount(ResourcesTranslated); i++) {

        desc = WdfCmResourceListGetDescriptor( ResourcesTranslated, i );

        if(!desc) {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                        "WdfResourceCmGetDescriptor failed");
            return STATUS_DEVICE_CONFIGURATION_ERROR;
        }

        switch (desc->Type) {

            case CmResourceTypeMemory:

                bar = NULL;

                if (foundSRAM && !foundSRAM2 &&
                    desc->u.Memory.Length == PCI9656_SRAM_SIZE) {

                    //SRAM2BasePA = desc->u.Memory.Start;
                    //SRAM2Length = desc->u.Memory.Length;
                    foundSRAM2 = TRUE;
                    bar = "BAR3";
                }

                if (foundRegs && !foundSRAM &&
                    desc->u.Memory.Length == PCI9656_SRAM_SIZE) {

                    SRAMBasePA = desc->u.Memory.Start;
                    SRAMLength = desc->u.Memory.Length;
                    foundSRAM = TRUE;
                    bar = "BAR2";
                }

                if (!foundRegs &&
                    desc->u.Memory.Length == 0x200) {

                    regsBasePA = desc->u.Memory.Start;
                    regsLength = desc->u.Memory.Length;
                    foundRegs = TRUE;
                    bar = "BAR0";
                }

                TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
                            " - Memory Resource [%I64X-%I64X] %s",
                            desc->u.Memory.Start.QuadPart,
                            desc->u.Memory.Start.QuadPart +
                            desc->u.Memory.Length,
                            (bar) ? bar : "<unrecognized>" );
                break;

            case CmResourceTypePort:

                bar = NULL;

                if (!foundPort &&
                    desc->u.Port.Length >= 0x100) {
                    foundPort = TRUE;
                    bar = "BAR1";
                }

                TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
                            " - Port   Resource [%08I64X-%08I64X] %s",
                            desc->u.Port.Start.QuadPart,
                            desc->u.Port.Start.QuadPart +
                            desc->u.Port.Length,
                            (bar) ? bar : "<unrecognized>" );
                break;

            default:
                //
                // Ignore all other descriptors
                //
                break;
        }
    }

    if (!(foundRegs && foundSRAM)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "PLxMapResources: Missing resources");
        return STATUS_DEVICE_CONFIGURATION_ERROR;
    }

    //
    // Map in the Registers Memory resource: BAR0
    //
    DevExt->RegsBase = (PUCHAR) MmMapIoSpace( regsBasePA,
                                              regsLength,
                                              MmNonCached );

    if (!DevExt->RegsBase) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    " - Unable to map Registers memory %08I64X, length %d",
                    regsBasePA.QuadPart, regsLength);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    DevExt->RegsLength = regsLength;

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
                " - Registers %p, length %d",
                DevExt->RegsBase, DevExt->RegsLength );

    //
    // Set seperated pointer to PCI9656_REGS structure.
    //
    DevExt->Regs = (PPCI9656_REGS) DevExt->RegsBase;

    //
    // Map in the SRAM Memory Space resource: BAR2
    //
    DevExt->SRAMBase = (PUCHAR) MmMapIoSpace( SRAMBasePA,
                                              SRAMLength,
                                              MmNonCached );

    if (!DevExt->SRAMBase) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    " - Unable to map SRAM memory %08I64X, length %d",
                    SRAMBasePA.QuadPart,  SRAMLength);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    DevExt->SRAMLength = SRAMLength;

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
                " - SRAM      %p, length %d",
                DevExt->SRAMBase, DevExt->SRAMLength );

    return status;
}
Пример #17
0
/*++

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;
}
Пример #18
0
NTSTATUS PCIAllocBars(WDFCMRESLIST ResourcesTranslated,
                      PVIRTIO_WDF_DRIVER pWdfDriver)
{
    PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDescriptor;
    ULONG nInterrupts = 0, nMSIInterrupts = 0;
    int nListSize = WdfCmResourceListGetCount(ResourcesTranslated);
    int i;
    PVIRTIO_WDF_BAR pBar;
    PCI_COMMON_HEADER PCIHeader;

    /* read the PCI config header */
    if (pWdfDriver->PCIBus.GetBusData(
        pWdfDriver->PCIBus.Context,
        PCI_WHICHSPACE_CONFIG,
        &PCIHeader,
        0,
        sizeof(PCIHeader)) != sizeof(PCIHeader)) {
        return STATUS_DEVICE_CONFIGURATION_ERROR;
    }
    
    for (i = 0; i < nListSize; i++) {
        pResDescriptor = WdfCmResourceListGetDescriptor(ResourcesTranslated, i);
        if (pResDescriptor) {
            switch (pResDescriptor->Type) {
                case CmResourceTypePort:
                case CmResourceTypeMemory:
                    pBar = (PVIRTIO_WDF_BAR)ExAllocatePoolWithTag(
                        NonPagedPool,
                        sizeof(VIRTIO_WDF_BAR),
                        pWdfDriver->MemoryTag);
                    if (pBar == NULL) {
                        /* undo what we've done so far */
                        PCIFreeBars(pWdfDriver);
                        return STATUS_INSUFFICIENT_RESOURCES;
                    }

                    /* unfortunately WDF doesn't tell us BAR indices */
                    pBar->iBar = virtio_get_bar_index(&PCIHeader, pResDescriptor->u.Memory.Start);
                    if (pBar->iBar < 0) {
                        /* undo what we've done so far */
                        PCIFreeBars(pWdfDriver);
                        return STATUS_NOT_FOUND;
                    }

                    pBar->bPortSpace = !!(pResDescriptor->Flags & CM_RESOURCE_PORT_IO);
                    pBar->BasePA = pResDescriptor->u.Memory.Start;
                    pBar->uLength = pResDescriptor->u.Memory.Length;

                    if (pBar->bPortSpace) {
                        pBar->pBase = (PVOID)(ULONG_PTR)pBar->BasePA.QuadPart;
                    } else {
                        /* memory regions are mapped into the virtual memory space on demand */
                        pBar->pBase = NULL;
                    }
                    PushEntryList(&pWdfDriver->PCIBars, &pBar->ListEntry);
                    break;

                case CmResourceTypeInterrupt:
                    nInterrupts++;
                    if (pResDescriptor->Flags &
                        (CM_RESOURCE_INTERRUPT_LATCHED | CM_RESOURCE_INTERRUPT_MESSAGE)) {
                        nMSIInterrupts++;
                    }
                    break;
            }
        }
    }

    pWdfDriver->nInterrupts = nInterrupts;
    pWdfDriver->nMSIInterrupts = nMSIInterrupts;

    return STATUS_SUCCESS;
}