Implement IRP_MN_QUERY_RESOURCES (Irq, IO ports, DMA)

svn path=/trunk/; revision=14499
This commit is contained in:
Hervé Poussineau 2005-04-05 12:00:13 +00:00
parent f165c00432
commit 849f32b6b5
3 changed files with 209 additions and 0 deletions

View file

@ -4,6 +4,7 @@
* FILE: acpi/ospm/fdo.c
* PURPOSE: ACPI device object dispatch routines
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* Hervé Poussineau (hpoussin@reactos.com)
* UPDATE HISTORY:
* 08-08-2001 CSH Created
*/
@ -115,6 +116,149 @@ AcpiCreateInstanceIDString(PUNICODE_STRING InstanceID,
}
static BOOLEAN
AcpiCreateResourceList(PCM_RESOURCE_LIST* pResourceList,
PULONG ResourceListSize,
RESOURCE* resources)
{
BOOLEAN Done;
ULONG NumberOfResources = 0;
PCM_RESOURCE_LIST ResourceList;
PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor;
RESOURCE* resource;
ULONG i;
KIRQL Dirql;
/* Count number of resources */
Done = FALSE;
resource = resources;
while (!Done)
{
switch (resource->id)
{
case irq:
{
IRQ_RESOURCE *irq_data = (IRQ_RESOURCE*) &resource->data;
NumberOfResources += irq_data->number_of_interrupts;
break;
}
case dma:
{
DMA_RESOURCE *dma_data = (DMA_RESOURCE*) &resource->data;
NumberOfResources += dma_data->number_of_channels;
break;
}
case io:
{
NumberOfResources++;
break;
}
case end_tag:
{
Done = TRUE;
break;
}
}
resource = (RESOURCE *) ((NATIVE_UINT) resource + (NATIVE_UINT) resource->length);
}
/* Allocate memory */
*ResourceListSize = sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * (NumberOfResources - 1);
ResourceList = (PCM_RESOURCE_LIST)ExAllocatePool(PagedPool, *ResourceListSize);
*pResourceList = ResourceList;
if (!ResourceList)
return FALSE;
ResourceList->Count = 1;
ResourceList->List[0].InterfaceType = Internal; /* FIXME */
ResourceList->List[0].BusNumber = 0; /* We're the only ACPI bus device in the system */
ResourceList->List[0].PartialResourceList.Version = 1;
ResourceList->List[0].PartialResourceList.Revision = 1;
ResourceList->List[0].PartialResourceList.Count = NumberOfResources;
ResourceDescriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
/* Fill resources list structure */
Done = FALSE;
resource = resources;
while (!Done)
{
switch (resource->id)
{
case irq:
{
IRQ_RESOURCE *irq_data = (IRQ_RESOURCE*) &resource->data;
for (i = 0; i < irq_data->number_of_interrupts; i++)
{
ResourceDescriptor->Type = CmResourceTypeInterrupt;
ResourceDescriptor->ShareDisposition =
(irq_data->shared_exclusive == SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
ResourceDescriptor->Flags =
(irq_data->edge_level == LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
ResourceDescriptor->u.Interrupt.Vector = HalGetInterruptVector(
Internal, 0, 0, irq_data->interrupts[i],
&Dirql,
&ResourceDescriptor->u.Interrupt.Affinity);
ResourceDescriptor->u.Interrupt.Level = (ULONG)Dirql;
ResourceDescriptor++;
}
break;
}
case dma:
{
DMA_RESOURCE *dma_data = (DMA_RESOURCE*) &resource->data;
for (i = 0; i < dma_data->number_of_channels; i++)
{
ResourceDescriptor->Type = CmResourceTypeDma;
ResourceDescriptor->Flags = 0;
switch (dma_data->type)
{
case TYPE_A: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_A; break;
case TYPE_B: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_B; break;
case TYPE_F: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_F; break;
}
if (dma_data->bus_master == BUS_MASTER)
ResourceDescriptor->Flags |= CM_RESOURCE_DMA_BUS_MASTER;
switch (dma_data->transfer)
{
case TRANSFER_8: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_8; break;
case TRANSFER_16: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_16; break;
case TRANSFER_8_16: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_8_AND_16; break;
}
ResourceDescriptor->u.Dma.Channel = dma_data->channels[i];
ResourceDescriptor++;
}
break;
}
case io:
{
IO_RESOURCE *io_data = (IO_RESOURCE*) &resource->data;
ResourceDescriptor->Type = CmResourceTypePort;
ResourceDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
if (io_data->io_decode == DECODE_16)
ResourceDescriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
else
ResourceDescriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
ResourceDescriptor->u.Port.Start.u.HighPart = 0;
ResourceDescriptor->u.Port.Start.u.LowPart = io_data->min_base_address;
ResourceDescriptor->u.Port.Length = io_data->range_length;
ResourceDescriptor++;
break;
}
case end_tag:
{
Done = TRUE;
break;
}
}
resource = (RESOURCE *) ((NATIVE_UINT) resource + (NATIVE_UINT) resource->length);
}
acpi_rs_dump_resource_list(resource);
return TRUE;
}
static NTSTATUS
FdoQueryBusRelations(
IN PDEVICE_OBJECT DeviceObject,
@ -149,6 +293,7 @@ FdoQueryBusRelations(
CurrentEntry = DeviceExtension->DeviceListHead.Flink;
while (CurrentEntry != &DeviceExtension->DeviceListHead)
{
ACPI_BUFFER Buffer;
Device = CONTAINING_RECORD(CurrentEntry, ACPI_DEVICE, DeviceListEntry);
/* FIXME: For ACPI namespace devices on the motherboard create filter DOs
@ -200,6 +345,34 @@ FdoQueryBusRelations(
AcpiStatus = bm_get_node(Device->BmHandle, 0, &Node);
if (ACPI_SUCCESS(AcpiStatus))
{
/* Get current resources */
Buffer.length = 0;
Status = acpi_get_current_resources(Node->device.acpi_handle, &Buffer);
if ((Status & ACPI_OK) == 0)
{
ASSERT(FALSE);
}
if (Buffer.length > 0)
{
Buffer.pointer = ExAllocatePool(PagedPool, Buffer.length);
if (!Buffer.pointer)
{
ASSERT(FALSE);
}
Status = acpi_get_current_resources(Node->device.acpi_handle, &Buffer);
if (ACPI_FAILURE(Status))
{
ASSERT(FALSE);
}
if (!AcpiCreateResourceList(&PdoDeviceExtension->ResourceList,
&PdoDeviceExtension->ResourceListSize,
(RESOURCE*)Buffer.pointer))
{
ASSERT(FALSE);
}
ExFreePool(Buffer.pointer);
}
/* Add Device ID string */
if (!AcpiCreateDeviceIDString(&PdoDeviceExtension->DeviceID,
Node))

View file

@ -47,6 +47,9 @@ typedef struct _PDO_DEVICE_EXTENSION
UNICODE_STRING InstanceID;
// Hardware IDs
UNICODE_STRING HardwareIDs;
// Resource list
PCM_RESOURCE_LIST ResourceList;
ULONG ResourceListSize;
} PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;

View file

@ -107,6 +107,35 @@ PdoQueryId(
}
static NTSTATUS
PdoQueryResources(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
PIO_STACK_LOCATION IrpSp)
{
PPDO_DEVICE_EXTENSION DeviceExtension;
PCM_RESOURCE_LIST ResourceList;
DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
if (DeviceExtension->ResourceListSize == 0)
{
return Irp->IoStatus.Status;
}
ResourceList = ExAllocatePool(PagedPool, DeviceExtension->ResourceListSize);
if (!ResourceList)
{
Irp->IoStatus.Information = 0;
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyMemory(ResourceList, DeviceExtension->ResourceList, DeviceExtension->ResourceListSize);
Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
return STATUS_SUCCESS;
}
static NTSTATUS
PdoSetPower(
IN PDEVICE_OBJECT DeviceObject,
@ -201,6 +230,9 @@ PdoPnpControl(
break;
case IRP_MN_QUERY_RESOURCES:
Status = PdoQueryResources(DeviceObject,
Irp,
IrpSp);
break;
case IRP_MN_QUERY_STOP_DEVICE:
@ -213,6 +245,7 @@ PdoPnpControl(
break;
case IRP_MN_START_DEVICE:
Status = STATUS_SUCCESS;
break;
case IRP_MN_STOP_DEVICE: