9 #include <acpi_drivers.h>
15 #pragma alloc_text (PAGE, Bus_PDO_PnP)
16 #pragma alloc_text (PAGE, Bus_PDO_QueryDeviceCaps)
17 #pragma alloc_text (PAGE, Bus_PDO_QueryDeviceId)
18 #pragma alloc_text (PAGE, Bus_PDO_QueryDeviceText)
19 #pragma alloc_text (PAGE, Bus_PDO_QueryResources)
20 #pragma alloc_text (PAGE, Bus_PDO_QueryResourceRequirements)
21 #pragma alloc_text (PAGE, Bus_PDO_QueryDeviceRelations)
22 #pragma alloc_text (PAGE, Bus_PDO_QueryBusInformation)
23 #pragma alloc_text (PAGE, Bus_GetDeviceCapabilities)
28 PDEVICE_OBJECT DeviceObject
,
30 PIO_STACK_LOCATION IrpStack
,
31 PPDO_DEVICE_DATA DeviceData
40 // NB: Because we are a bus enumerator, we have no one to whom we could
41 // defer these irps. Therefore we do not pass them down but merely
45 switch (IrpStack
->MinorFunction
) {
47 case IRP_MN_START_DEVICE
:
50 // Here we do what ever initialization and ``turning on'' that is
51 // required to allow others to access this device.
52 // Power up the device.
54 DeviceData
->Common
.DevicePowerState
= PowerDeviceD0
;
55 SET_NEW_PNP_STATE(DeviceData
->Common
, Started
);
56 status
= STATUS_SUCCESS
;
59 case IRP_MN_STOP_DEVICE
:
62 // Here we shut down the device and give up and unmap any resources
63 // we acquired for the device.
66 SET_NEW_PNP_STATE(DeviceData
->Common
, Stopped
);
67 status
= STATUS_SUCCESS
;
71 case IRP_MN_QUERY_STOP_DEVICE
:
74 // No reason here why we can't stop the device.
75 // If there were a reason we should speak now, because answering success
76 // here may result in a stop device irp.
79 SET_NEW_PNP_STATE(DeviceData
->Common
, StopPending
);
80 status
= STATUS_SUCCESS
;
83 case IRP_MN_CANCEL_STOP_DEVICE
:
86 // The stop was canceled. Whatever state we set, or resources we put
87 // on hold in anticipation of the forthcoming STOP device IRP should be
88 // put back to normal. Someone, in the long list of concerned parties,
89 // has failed the stop device query.
93 // First check to see whether you have received cancel-stop
94 // without first receiving a query-stop. This could happen if someone
95 // above us fails a query-stop and passes down the subsequent
99 if (StopPending
== DeviceData
->Common
.DevicePnPState
)
102 // We did receive a query-stop, so restore.
104 RESTORE_PREVIOUS_PNP_STATE(DeviceData
->Common
);
106 status
= STATUS_SUCCESS
;// We must not fail this IRP.
108 case IRP_MN_QUERY_CAPABILITIES
:
111 // Return the capabilities of a device, such as whether the device
112 // can be locked or ejected..etc
115 status
= Bus_PDO_QueryDeviceCaps(DeviceData
, Irp
);
119 case IRP_MN_QUERY_ID
:
121 // Query the IDs of the device
122 status
= Bus_PDO_QueryDeviceId(DeviceData
, Irp
);
126 case IRP_MN_QUERY_DEVICE_RELATIONS
:
128 DPRINT("\tQueryDeviceRelation Type: %s\n",DbgDeviceRelationString(\
129 IrpStack
->Parameters
.QueryDeviceRelations
.Type
));
131 status
= Bus_PDO_QueryDeviceRelations(DeviceData
, Irp
);
135 case IRP_MN_QUERY_DEVICE_TEXT
:
137 status
= Bus_PDO_QueryDeviceText(DeviceData
, Irp
);
141 case IRP_MN_QUERY_RESOURCES
:
143 status
= Bus_PDO_QueryResources(DeviceData
, Irp
);
147 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
:
149 status
= Bus_PDO_QueryResourceRequirements(DeviceData
, Irp
);
153 case IRP_MN_QUERY_BUS_INFORMATION
:
155 status
= Bus_PDO_QueryBusInformation(DeviceData
, Irp
);
160 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS
:
163 // OPTIONAL for bus drivers.
164 // The PnP Manager sends this IRP to a device
165 // stack so filter and function drivers can adjust the
166 // resources required by the device, if appropriate.
171 //case IRP_MN_QUERY_PNP_DEVICE_STATE:
174 // OPTIONAL for bus drivers.
175 // The PnP Manager sends this IRP after the drivers for
176 // a device return success from the IRP_MN_START_DEVICE
177 // request. The PnP Manager also sends this IRP when a
178 // driver for the device calls IoInvalidateDeviceState.
183 //case IRP_MN_READ_CONFIG:
184 //case IRP_MN_WRITE_CONFIG:
187 // Bus drivers for buses with configuration space must handle
188 // this request for their child devices. Our devices don't
189 // have a config space.
194 //case IRP_MN_SET_LOCK:
201 // For PnP requests to the PDO that we do not understand we should
202 // return the IRP WITHOUT setting the status or information fields.
203 // These fields may have already been set by a filter (eg acpi).
204 status
= Irp
->IoStatus
.Status
;
209 Irp
->IoStatus
.Status
= status
;
210 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
216 // FIX ME FIX ME FIX ME !!!
219 Bus_PDO_QueryDeviceCaps(
220 PPDO_DEVICE_DATA DeviceData
,
224 PIO_STACK_LOCATION stack
;
225 PDEVICE_CAPABILITIES deviceCapabilities
;
226 DEVICE_CAPABILITIES parentCapabilities
;
231 stack
= IoGetCurrentIrpStackLocation (Irp
);
236 deviceCapabilities
=stack
->Parameters
.DeviceCapabilities
.Capabilities
;
239 // Set the capabilities.
242 if (deviceCapabilities
->Version
!= 1 ||
243 deviceCapabilities
->Size
< sizeof(DEVICE_CAPABILITIES
))
245 return STATUS_UNSUCCESSFUL
;
249 // Get the device capabilities of the parent
251 status
= Bus_GetDeviceCapabilities(
252 FDO_FROM_PDO(DeviceData
)->NextLowerDriver
, &parentCapabilities
);
253 if (!NT_SUCCESS(status
)) {
255 DPRINT("\tQueryDeviceCaps failed\n");
261 // The entries in the DeviceState array are based on the capabilities
262 // of the parent devnode. These entries signify the highest-powered
263 // state that the device can support for the corresponding system
264 // state. A driver can specify a lower (less-powered) state than the
265 // bus driver. For eg: Suppose the acpi bus controller supports
266 // D0, D2, and D3; and the acpi Device supports D0, D1, D2, and D3.
267 // Following the above rule, the device cannot specify D1 as one of
268 // it's power state. A driver can make the rules more restrictive
269 // but cannot loosen them.
270 // First copy the parent's S to D state mapping
274 deviceCapabilities
->DeviceState
,
275 parentCapabilities
.DeviceState
,
276 (PowerSystemShutdown
+ 1) * sizeof(DEVICE_POWER_STATE
)
280 // Adjust the caps to what your device supports.
281 // Our device just supports D0 and D3.
284 deviceCapabilities
->DeviceState
[PowerSystemWorking
] = PowerDeviceD0
;
286 if (deviceCapabilities
->DeviceState
[PowerSystemSleeping1
] != PowerDeviceD0
)
287 deviceCapabilities
->DeviceState
[PowerSystemSleeping1
] = PowerDeviceD1
;
289 if (deviceCapabilities
->DeviceState
[PowerSystemSleeping2
] != PowerDeviceD0
)
290 deviceCapabilities
->DeviceState
[PowerSystemSleeping2
] = PowerDeviceD3
;
292 if (deviceCapabilities
->DeviceState
[PowerSystemSleeping3
] != PowerDeviceD0
)
293 deviceCapabilities
->DeviceState
[PowerSystemSleeping3
] = PowerDeviceD3
;
295 // We can wake the system from D1
296 deviceCapabilities
->DeviceWake
= PowerDeviceD1
;
299 // Specifies whether the device hardware supports the D1 and D2
300 // power state. Set these bits explicitly.
303 deviceCapabilities
->DeviceD1
= TRUE
; // Yes we can
304 deviceCapabilities
->DeviceD2
= FALSE
;
307 // Specifies whether the device can respond to an external wake
308 // signal while in the D0, D1, D2, and D3 state.
309 // Set these bits explicitly.
312 deviceCapabilities
->WakeFromD0
= FALSE
;
313 deviceCapabilities
->WakeFromD1
= TRUE
; //Yes we can
314 deviceCapabilities
->WakeFromD2
= FALSE
;
315 deviceCapabilities
->WakeFromD3
= FALSE
;
318 // We have no latencies
320 deviceCapabilities
->D1Latency
= 0;
321 deviceCapabilities
->D2Latency
= 0;
322 deviceCapabilities
->D3Latency
= 0;
324 // Ejection supported
326 deviceCapabilities
->EjectSupported
= TRUE
;
329 // This flag specifies whether the device's hardware is disabled.
330 // The PnP Manager only checks this bit right after the device is
331 // enumerated. Once the device is started, this bit is ignored.
333 deviceCapabilities
->HardwareDisabled
= FALSE
;
336 // Out simulated device can be physically removed.
338 deviceCapabilities
->Removable
= TRUE
;
340 // Setting it to TURE prevents the warning dialog from appearing
341 // whenever the device is surprise removed.
343 deviceCapabilities
->SurpriseRemovalOK
= TRUE
;
345 // We don't support system-wide unique IDs.
347 deviceCapabilities
->UniqueID
= FALSE
;
350 // Specify whether the Device Manager should suppress all
351 // installation pop-ups except required pop-ups such as
352 // "no compatible drivers found."
355 deviceCapabilities
->SilentInstall
= FALSE
;
358 // Specifies an address indicating where the device is located
359 // on its underlying bus. The interpretation of this number is
360 // bus-specific. If the address is unknown or the bus driver
361 // does not support an address, the bus driver leaves this
362 // member at its default value of 0xFFFFFFFF. In this example
363 // the location address is same as instance id.
366 //deviceCapabilities->Address = DeviceData->SerialNo;
369 // UINumber specifies a number associated with the device that can
370 // be displayed in the user interface.
372 //deviceCapabilities->UINumber = DeviceData->SerialNo;
374 return STATUS_SUCCESS
;
379 Bus_PDO_QueryDeviceId(
380 PPDO_DEVICE_DATA DeviceData
,
383 PIO_STACK_LOCATION stack
;
387 NTSTATUS status
= STATUS_SUCCESS
;
388 struct acpi_device
*Device
;
392 stack
= IoGetCurrentIrpStackLocation (Irp
);
394 switch (stack
->Parameters
.QueryId
.IdType
) {
396 case BusQueryDeviceID
:
397 acpi_bus_get_device(DeviceData
->AcpiHandle
, &Device
);
399 length
= swprintf(temp
,
401 Device
->pnp
.hardware_id
);
403 temp
[++length
] = UNICODE_NULL
;
405 buffer
= ExAllocatePoolWithTag (PagedPool
, length
* sizeof(WCHAR
), 'IPCA');
408 status
= STATUS_INSUFFICIENT_RESOURCES
;
412 RtlCopyMemory (buffer
, temp
, length
* sizeof(WCHAR
));
413 Irp
->IoStatus
.Information
= (ULONG_PTR
) buffer
;
414 DPRINT("BusQueryDeviceID: %ls\n",buffer
);
417 case BusQueryInstanceID
:
418 acpi_bus_get_device(DeviceData
->AcpiHandle
, &Device
);
420 if(Device
->flags
.unique_id
)
421 length
= swprintf(temp
,
423 Device
->pnp
.unique_id
);
425 /* FIXME: Generate unique id! */
426 length
= swprintf(temp
, L
"%ls", L
"0000");
428 temp
[++length
] = UNICODE_NULL
;
430 buffer
= ExAllocatePoolWithTag (PagedPool
, length
* sizeof (WCHAR
), 'IPCA');
432 status
= STATUS_INSUFFICIENT_RESOURCES
;
436 RtlCopyMemory (buffer
, temp
, length
* sizeof (WCHAR
));
437 DPRINT("BusQueryInstanceID: %ls\n",buffer
);
438 Irp
->IoStatus
.Information
= (ULONG_PTR
) buffer
;
441 case BusQueryHardwareIDs
:
442 acpi_bus_get_device(DeviceData
->AcpiHandle
, &Device
);
446 length
+= swprintf(&temp
[length
],
448 Device
->pnp
.hardware_id
);
451 length
+= swprintf(&temp
[length
],
453 Device
->pnp
.hardware_id
);
456 temp
[length
] = UNICODE_NULL
;
460 temp
[length
] = UNICODE_NULL
;
462 buffer
= ExAllocatePoolWithTag (PagedPool
, length
* sizeof(WCHAR
), 'IPCA');
465 status
= STATUS_INSUFFICIENT_RESOURCES
;
469 RtlCopyMemory (buffer
, temp
, length
* sizeof(WCHAR
));
470 Irp
->IoStatus
.Information
= (ULONG_PTR
) buffer
;
471 DPRINT("BusQueryHardwareIDs: %ls\n",buffer
);
475 status
= Irp
->IoStatus
.Status
;
481 Bus_PDO_QueryDeviceText(
482 PPDO_DEVICE_DATA DeviceData
,
486 PIO_STACK_LOCATION stack
;
490 stack
= IoGetCurrentIrpStackLocation (Irp
);
492 switch (stack
->Parameters
.QueryDeviceText
.DeviceTextType
) {
494 case DeviceTextDescription
:
496 if (!Irp
->IoStatus
.Information
) {
497 if (wcsstr (DeviceData
->HardwareIDs
, L
"PNP000") != 0)
498 Buffer
= L
"Programmable interrupt controller";
499 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP010") != 0)
500 Buffer
= L
"System timer";
501 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP020") != 0)
502 Buffer
= L
"DMA controller";
503 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP03") != 0)
504 Buffer
= L
"Keyboard";
505 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP040") != 0)
506 Buffer
= L
"Parallel port";
507 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP05") != 0)
508 Buffer
= L
"Serial port";
509 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP06") != 0)
510 Buffer
= L
"Disk controller";
511 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP07") != 0)
512 Buffer
= L
"Disk controller";
513 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP09") != 0)
514 Buffer
= L
"Display adapter";
515 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0A0") != 0)
516 Buffer
= L
"Bus controller";
517 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0E0") != 0)
518 Buffer
= L
"PCMCIA controller";
519 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0F") != 0)
520 Buffer
= L
"Mouse device";
521 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP8") != 0)
522 Buffer
= L
"Network adapter";
523 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNPA0") != 0)
524 Buffer
= L
"SCSI controller";
525 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNPB0") != 0)
526 Buffer
= L
"Multimedia device";
527 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNPC00") != 0)
529 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0C0C") != 0)
530 Buffer
= L
"Power Button";
531 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0C0E") != 0)
532 Buffer
= L
"Sleep Button";
533 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0C0D") != 0)
534 Buffer
= L
"Lid Switch";
535 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0C09") != 0)
536 Buffer
= L
"ACPI Embedded Controller";
537 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0C0B") != 0)
538 Buffer
= L
"ACPI Fan";
539 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0A03") != 0)
540 Buffer
= L
"PCI Root Bridge";
541 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0C0A") != 0)
542 Buffer
= L
"ACPI Battery";
543 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0C0F") != 0)
544 Buffer
= L
"PCI Interrupt Link";
545 else if (wcsstr(DeviceData
->HardwareIDs
, L
"ACPI_PWR") != 0)
546 Buffer
= L
"ACPI Power Resource";
547 else if (wcsstr(DeviceData
->HardwareIDs
, L
"Processor") != 0)
548 Buffer
= L
"Processor";
549 else if (wcsstr(DeviceData
->HardwareIDs
, L
"ACPI_SYS") != 0)
550 Buffer
= L
"ACPI System";
551 else if (wcsstr(DeviceData
->HardwareIDs
, L
"ThermalZone") != 0)
552 Buffer
= L
"ACPI Thermal Zone";
553 else if (wcsstr(DeviceData
->HardwareIDs
, L
"ACPI0002") != 0)
554 Buffer
= L
"Smart Battery";
555 else if (wcsstr(DeviceData
->HardwareIDs
, L
"ACPI0003") != 0)
556 Buffer
= L
"AC Adapter";
558 Buffer
= L
"Other ACPI device";
560 DPRINT("\tDeviceTextDescription :%ws\n", Buffer
);
562 Irp
->IoStatus
.Information
= (ULONG_PTR
) Buffer
;
564 status
= STATUS_SUCCESS
;
568 status
= Irp
->IoStatus
.Status
;
577 Bus_PDO_QueryResources(
578 PPDO_DEVICE_DATA DeviceData
,
582 ULONG NumberOfResources
= 0;
583 PCM_RESOURCE_LIST ResourceList
;
584 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor
;
585 ACPI_STATUS AcpiStatus
;
587 ACPI_RESOURCE
* resource
;
588 ULONG ResourceListSize
;
591 ULONG RequirementsListSize
;
592 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList
;
593 PIO_RESOURCE_DESCRIPTOR RequirementDescriptor
;
596 /* Get current resources */
598 AcpiStatus
= AcpiGetCurrentResources(DeviceData
->AcpiHandle
, &Buffer
);
599 if (!ACPI_SUCCESS(AcpiStatus
))
601 return STATUS_SUCCESS
;
603 if (Buffer
.Length
> 0)
605 Buffer
.Pointer
= ExAllocatePool(PagedPool
, Buffer
.Length
);
610 AcpiStatus
= AcpiGetCurrentResources(DeviceData
->AcpiHandle
, &Buffer
);
611 if (!ACPI_SUCCESS(AcpiStatus
))
617 resource
= Buffer
.Pointer
;
618 /* Count number of resources */
622 switch (resource
->Type
)
624 case ACPI_RESOURCE_TYPE_IRQ
:
626 ACPI_RESOURCE_IRQ
*irq_data
= (ACPI_RESOURCE_IRQ
*) &resource
->Data
;
627 NumberOfResources
+= irq_data
->InterruptCount
;
630 case ACPI_RESOURCE_TYPE_DMA
:
632 ACPI_RESOURCE_DMA
*dma_data
= (ACPI_RESOURCE_DMA
*) &resource
->Data
;
633 NumberOfResources
+= dma_data
->ChannelCount
;
636 case ACPI_RESOURCE_TYPE_IO
:
641 case ACPI_RESOURCE_TYPE_END_TAG
:
651 resource
= ACPI_NEXT_RESOURCE(resource
);
654 /* Allocate memory */
655 ResourceListSize
= sizeof(CM_RESOURCE_LIST
) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) * (NumberOfResources
- 1);
656 ResourceList
= (PCM_RESOURCE_LIST
)ExAllocatePool(PagedPool
, ResourceListSize
);
660 ResourceList
->Count
= 1;
661 ResourceList
->List
[0].InterfaceType
= Internal
; /* FIXME */
662 ResourceList
->List
[0].BusNumber
= 0; /* We're the only ACPI bus device in the system */
663 ResourceList
->List
[0].PartialResourceList
.Version
= 1;
664 ResourceList
->List
[0].PartialResourceList
.Revision
= 1;
665 ResourceList
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
666 ResourceDescriptor
= ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
;
668 RequirementsListSize
= sizeof(IO_RESOURCE_REQUIREMENTS_LIST
) + sizeof(IO_RESOURCE_DESCRIPTOR
) * (NumberOfResources
- 1);
669 RequirementsList
= (PIO_RESOURCE_REQUIREMENTS_LIST
)ExAllocatePool(PagedPool
, RequirementsListSize
);
671 if (!RequirementsList
)
673 ExFreePool(ResourceList
);
674 return STATUS_SUCCESS
;
676 RequirementsList
->ListSize
= RequirementsListSize
;
677 RequirementsList
->InterfaceType
= Internal
;
678 RequirementsList
->BusNumber
= 0;
679 RequirementsList
->SlotNumber
= 0; /* Not used by WDM drivers */
680 RequirementsList
->AlternativeLists
= 1;
681 RequirementsList
->List
[0].Version
= 1;
682 RequirementsList
->List
[0].Revision
= 1;
683 RequirementsList
->List
[0].Count
= NumberOfResources
;
684 RequirementDescriptor
= RequirementsList
->List
[0].Descriptors
;
686 /* Fill resources list structure */
690 switch (resource
->Type
)
692 case ACPI_RESOURCE_TYPE_IRQ
:
694 ACPI_RESOURCE_IRQ
*irq_data
= (ACPI_RESOURCE_IRQ
*) &resource
->Data
;
695 for (i
= 0; i
< irq_data
->InterruptCount
; i
++)
697 ResourceDescriptor
->Type
= CmResourceTypeInterrupt
;
699 ResourceDescriptor
->ShareDisposition
=
700 (irq_data
->Sharable
== ACPI_SHARED
? CmResourceShareShared
: CmResourceShareDeviceExclusive
);
701 ResourceDescriptor
->Flags
=
702 (irq_data
->Triggering
== ACPI_LEVEL_SENSITIVE
? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE
: CM_RESOURCE_INTERRUPT_LATCHED
);
703 ResourceDescriptor
->u
.Interrupt
.Level
= irq_data
->Interrupts
[i
];
704 ResourceDescriptor
->u
.Interrupt
.Vector
= 0;
705 ResourceDescriptor
->u
.Interrupt
.Affinity
= (KAFFINITY
)(-1);
707 RequirementDescriptor
->Option
= 0; /* Required */
708 RequirementDescriptor
->Type
= ResourceDescriptor
->Type
;
709 RequirementDescriptor
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
710 RequirementDescriptor
->Flags
= ResourceDescriptor
->Flags
;
711 RequirementDescriptor
->u
.Interrupt
.MinimumVector
= RequirementDescriptor
->u
.Interrupt
.MaximumVector
712 = irq_data
->Interrupts
[i
];
714 ResourceDescriptor
++;
715 RequirementDescriptor
++;
719 case ACPI_RESOURCE_TYPE_DMA
:
721 ACPI_RESOURCE_DMA
*dma_data
= (ACPI_RESOURCE_DMA
*) &resource
->Data
;
722 for (i
= 0; i
< dma_data
->ChannelCount
; i
++)
724 ResourceDescriptor
->Type
= CmResourceTypeDma
;
725 ResourceDescriptor
->Flags
= 0;
726 switch (dma_data
->Type
)
728 case ACPI_TYPE_A
: ResourceDescriptor
->Flags
|= CM_RESOURCE_DMA_TYPE_A
; break;
729 case ACPI_TYPE_B
: ResourceDescriptor
->Flags
|= CM_RESOURCE_DMA_TYPE_B
; break;
730 case ACPI_TYPE_F
: ResourceDescriptor
->Flags
|= CM_RESOURCE_DMA_TYPE_F
; break;
732 if (dma_data
->BusMaster
== ACPI_BUS_MASTER
)
733 ResourceDescriptor
->Flags
|= CM_RESOURCE_DMA_BUS_MASTER
;
734 switch (dma_data
->Transfer
)
736 case ACPI_TRANSFER_8
: ResourceDescriptor
->Flags
|= CM_RESOURCE_DMA_8
; break;
737 case ACPI_TRANSFER_16
: ResourceDescriptor
->Flags
|= CM_RESOURCE_DMA_16
; break;
738 case ACPI_TRANSFER_8_16
: ResourceDescriptor
->Flags
|= CM_RESOURCE_DMA_8_AND_16
; break;
740 ResourceDescriptor
->u
.Dma
.Channel
= dma_data
->Channels
[i
];
742 RequirementDescriptor
->Option
= 0; /* Required */
743 RequirementDescriptor
->Type
= ResourceDescriptor
->Type
;
744 RequirementDescriptor
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
745 RequirementDescriptor
->Flags
= ResourceDescriptor
->Flags
;
746 RequirementDescriptor
->u
.Dma
.MinimumChannel
= RequirementDescriptor
->u
.Dma
.MaximumChannel
747 = ResourceDescriptor
->u
.Dma
.Channel
;
749 ResourceDescriptor
++;
750 RequirementDescriptor
++;
754 case ACPI_RESOURCE_TYPE_IO
:
756 ACPI_RESOURCE_IO
*io_data
= (ACPI_RESOURCE_IO
*) &resource
->Data
;
757 ResourceDescriptor
->Type
= CmResourceTypePort
;
758 ResourceDescriptor
->ShareDisposition
= CmResourceShareDriverExclusive
;
759 ResourceDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
760 if (io_data
->IoDecode
== ACPI_DECODE_16
)
761 ResourceDescriptor
->Flags
|= CM_RESOURCE_PORT_16_BIT_DECODE
;
763 ResourceDescriptor
->Flags
|= CM_RESOURCE_PORT_10_BIT_DECODE
;
764 ResourceDescriptor
->u
.Port
.Start
.u
.HighPart
= 0;
765 ResourceDescriptor
->u
.Port
.Start
.u
.LowPart
= io_data
->Minimum
;
766 ResourceDescriptor
->u
.Port
.Length
= io_data
->AddressLength
;
768 RequirementDescriptor
->Option
= 0; /* Required */
769 RequirementDescriptor
->Type
= ResourceDescriptor
->Type
;
770 RequirementDescriptor
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
771 RequirementDescriptor
->Flags
= ResourceDescriptor
->Flags
;
772 RequirementDescriptor
->u
.Port
.Length
= ResourceDescriptor
->u
.Port
.Length
;
773 RequirementDescriptor
->u
.Port
.Alignment
= 1; /* Start address is specified, so it doesn't matter */
774 RequirementDescriptor
->u
.Port
.MinimumAddress
= RequirementDescriptor
->u
.Port
.MaximumAddress
775 = ResourceDescriptor
->u
.Port
.Start
;
777 ResourceDescriptor
++;
778 RequirementDescriptor
++;
781 case ACPI_RESOURCE_TYPE_END_TAG
:
788 DPRINT1("Unhandled resource type\n");
792 resource
= ACPI_NEXT_RESOURCE(resource
);
795 ExFreePool(Buffer
.Pointer
);
796 Irp
->IoStatus
.Information
= (ULONG_PTR
)ResourceList
;
797 return STATUS_SUCCESS
;
801 Bus_PDO_QueryResourceRequirements(
802 PPDO_DEVICE_DATA DeviceData
,
806 ULONG NumberOfResources
= 0;
807 ACPI_STATUS AcpiStatus
;
809 ACPI_RESOURCE
* resource
;
810 ULONG i
, RequirementsListSize
;
811 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList
;
812 PIO_RESOURCE_DESCRIPTOR RequirementDescriptor
;
817 /* Get current resources */
819 AcpiStatus
= AcpiGetCurrentResources(DeviceData
->AcpiHandle
, &Buffer
);
820 if (!ACPI_SUCCESS(AcpiStatus
))
822 return STATUS_SUCCESS
;
824 if (Buffer
.Length
> 0)
826 Buffer
.Pointer
= ExAllocatePool(PagedPool
, Buffer
.Length
);
831 AcpiStatus
= AcpiGetCurrentResources(DeviceData
->AcpiHandle
, &Buffer
);
832 if (!ACPI_SUCCESS(AcpiStatus
))
838 resource
= Buffer
.Pointer
;
839 /* Count number of resources */
843 switch (resource
->Type
)
845 case ACPI_RESOURCE_TYPE_IRQ
:
847 ACPI_RESOURCE_IRQ
*irq_data
= (ACPI_RESOURCE_IRQ
*) &resource
->Data
;
848 NumberOfResources
+= irq_data
->InterruptCount
;
851 case ACPI_RESOURCE_TYPE_DMA
:
853 ACPI_RESOURCE_DMA
*dma_data
= (ACPI_RESOURCE_DMA
*) &resource
->Data
;
854 NumberOfResources
+= dma_data
->ChannelCount
;
857 case ACPI_RESOURCE_TYPE_IO
:
862 case ACPI_RESOURCE_TYPE_END_TAG
:
872 resource
= ACPI_NEXT_RESOURCE(resource
);
875 RequirementsListSize
= sizeof(IO_RESOURCE_REQUIREMENTS_LIST
) + sizeof(IO_RESOURCE_DESCRIPTOR
) * (NumberOfResources
- 1);
876 RequirementsList
= (PIO_RESOURCE_REQUIREMENTS_LIST
)ExAllocatePool(PagedPool
, RequirementsListSize
);
878 if (!RequirementsList
)
880 ExFreePool(Buffer
.Pointer
);
881 return STATUS_SUCCESS
;
883 RequirementsList
->ListSize
= RequirementsListSize
;
884 RequirementsList
->InterfaceType
= Internal
;
885 RequirementsList
->BusNumber
= 0;
886 RequirementsList
->SlotNumber
= 0; /* Not used by WDM drivers */
887 RequirementsList
->AlternativeLists
= 1;
888 RequirementsList
->List
[0].Version
= 1;
889 RequirementsList
->List
[0].Revision
= 1;
890 RequirementsList
->List
[0].Count
= NumberOfResources
;
891 RequirementDescriptor
= RequirementsList
->List
[0].Descriptors
;
893 /* Fill resources list structure */
897 switch (resource
->Type
)
899 case ACPI_RESOURCE_TYPE_IRQ
:
901 ACPI_RESOURCE_IRQ
*irq_data
= (ACPI_RESOURCE_IRQ
*) &resource
->Data
;
902 for (i
= 0; i
< irq_data
->InterruptCount
; i
++)
904 RequirementDescriptor
->Option
= 0; /* Required */
905 RequirementDescriptor
->Type
= CmResourceTypeInterrupt
;
906 RequirementDescriptor
->ShareDisposition
= (irq_data
->Sharable
== ACPI_SHARED
? CmResourceShareShared
: CmResourceShareDeviceExclusive
);
907 RequirementDescriptor
->Flags
=(irq_data
->Triggering
== ACPI_LEVEL_SENSITIVE
? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE
: CM_RESOURCE_INTERRUPT_LATCHED
);
908 RequirementDescriptor
->u
.Interrupt
.MinimumVector
= irq_data
->Interrupts
[i
];
910 RequirementDescriptor
++;
914 case ACPI_RESOURCE_TYPE_DMA
:
916 ACPI_RESOURCE_DMA
*dma_data
= (ACPI_RESOURCE_DMA
*) &resource
->Data
;
917 for (i
= 0; i
< dma_data
->ChannelCount
; i
++)
919 RequirementDescriptor
->Type
= CmResourceTypeDma
;
920 RequirementDescriptor
->Flags
= 0;
921 switch (dma_data
->Type
)
923 case ACPI_TYPE_A
: RequirementDescriptor
->Flags
|= CM_RESOURCE_DMA_TYPE_A
; break;
924 case ACPI_TYPE_B
: RequirementDescriptor
->Flags
|= CM_RESOURCE_DMA_TYPE_B
; break;
925 case ACPI_TYPE_F
: RequirementDescriptor
->Flags
|= CM_RESOURCE_DMA_TYPE_F
; break;
927 if (dma_data
->BusMaster
== ACPI_BUS_MASTER
)
928 RequirementDescriptor
->Flags
|= CM_RESOURCE_DMA_BUS_MASTER
;
929 switch (dma_data
->Transfer
)
931 case ACPI_TRANSFER_8
: RequirementDescriptor
->Flags
|= CM_RESOURCE_DMA_8
; break;
932 case ACPI_TRANSFER_16
: RequirementDescriptor
->Flags
|= CM_RESOURCE_DMA_16
; break;
933 case ACPI_TRANSFER_8_16
: RequirementDescriptor
->Flags
|= CM_RESOURCE_DMA_8_AND_16
; break;
936 RequirementDescriptor
->Option
= 0; /* Required */
937 RequirementDescriptor
->ShareDisposition
= CmResourceShareDriverExclusive
;
938 RequirementDescriptor
->u
.Dma
.MinimumChannel
= dma_data
->Channels
[i
];
939 RequirementDescriptor
++;
943 case ACPI_RESOURCE_TYPE_IO
:
945 ACPI_RESOURCE_IO
*io_data
= (ACPI_RESOURCE_IO
*) &resource
->Data
;
946 RequirementDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
947 if (io_data
->IoDecode
== ACPI_DECODE_16
)
948 RequirementDescriptor
->Flags
|= CM_RESOURCE_PORT_16_BIT_DECODE
;
950 RequirementDescriptor
->Flags
|= CM_RESOURCE_PORT_10_BIT_DECODE
;
952 RequirementDescriptor
->u
.Port
.Length
= io_data
->AddressLength
;
954 RequirementDescriptor
->Option
= 0; /* Required */
955 RequirementDescriptor
->Type
= CmResourceTypePort
;
956 RequirementDescriptor
->ShareDisposition
= CmResourceShareDriverExclusive
;
957 RequirementDescriptor
->u
.Port
.Alignment
= 1; /* Start address is specified, so it doesn't matter */
958 RequirementDescriptor
->u
.Port
.MinimumAddress
.QuadPart
= io_data
->Minimum
;
959 RequirementDescriptor
->u
.Port
.MaximumAddress
.QuadPart
= io_data
->Maximum
;
961 RequirementDescriptor
++;
964 case ACPI_RESOURCE_TYPE_END_TAG
:
971 DPRINT1("Unhandled resource type\n");
975 resource
= ACPI_NEXT_RESOURCE(resource
);
977 ExFreePool(Buffer
.Pointer
);
979 return STATUS_SUCCESS
;
983 Bus_PDO_QueryDeviceRelations(
984 PPDO_DEVICE_DATA DeviceData
,
990 The PnP Manager sends this IRP to gather information about
991 devices with a relationship to the specified device.
992 Bus drivers must handle this request for TargetDeviceRelation
993 for their child devices (child PDOs).
995 If a driver returns relations in response to this IRP,
996 it allocates a DEVICE_RELATIONS structure from paged
997 memory containing a count and the appropriate number of
998 device object pointers. The PnP Manager frees the structure
999 when it is no longer needed. If a driver replaces a
1000 DEVICE_RELATIONS structure allocated by another driver,
1001 it must free the previous structure.
1003 A driver must reference the PDO of any device that it
1004 reports in this IRP (ObReferenceObject). The PnP Manager
1005 removes the reference when appropriate.
1009 DeviceData - Pointer to the PDO's device extension.
1010 Irp - Pointer to the irp.
1019 PIO_STACK_LOCATION stack
;
1020 PDEVICE_RELATIONS deviceRelations
;
1025 stack
= IoGetCurrentIrpStackLocation (Irp
);
1027 switch (stack
->Parameters
.QueryDeviceRelations
.Type
) {
1029 case TargetDeviceRelation
:
1031 deviceRelations
= (PDEVICE_RELATIONS
) Irp
->IoStatus
.Information
;
1032 if (deviceRelations
) {
1034 // Only PDO can handle this request. Somebody above
1035 // is not playing by rule.
1037 ASSERTMSG("Someone above is handling TargetDeviceRelation", !deviceRelations
);
1040 deviceRelations
= (PDEVICE_RELATIONS
)
1041 ExAllocatePoolWithTag (PagedPool
,
1042 sizeof(DEVICE_RELATIONS
),
1044 if (!deviceRelations
) {
1045 status
= STATUS_INSUFFICIENT_RESOURCES
;
1050 // There is only one PDO pointer in the structure
1051 // for this relation type. The PnP Manager removes
1052 // the reference to the PDO when the driver or application
1053 // un-registers for notification on the device.
1056 deviceRelations
->Count
= 1;
1057 deviceRelations
->Objects
[0] = DeviceData
->Common
.Self
;
1058 ObReferenceObject(DeviceData
->Common
.Self
);
1060 status
= STATUS_SUCCESS
;
1061 Irp
->IoStatus
.Information
= (ULONG_PTR
) deviceRelations
;
1064 case BusRelations
: // Not handled by PDO
1065 case EjectionRelations
: // optional for PDO
1066 case RemovalRelations
: // // optional for PDO
1068 status
= Irp
->IoStatus
.Status
;
1075 Bus_PDO_QueryBusInformation(
1076 PPDO_DEVICE_DATA DeviceData
,
1080 Routine Description:
1082 The PnP Manager uses this IRP to request the type and
1083 instance number of a device's parent bus. Bus drivers
1084 should handle this request for their child devices (PDOs).
1088 DeviceData - Pointer to the PDO's device extension.
1089 Irp - Pointer to the irp.
1098 PPNP_BUS_INFORMATION busInfo
;
1102 busInfo
= ExAllocatePoolWithTag (PagedPool
, sizeof(PNP_BUS_INFORMATION
),
1105 if (busInfo
== NULL
) {
1106 return STATUS_INSUFFICIENT_RESOURCES
;
1109 busInfo
->BusTypeGuid
= GUID_ACPI_INTERFACE_STANDARD
;
1111 busInfo
->LegacyBusType
= InternalPowerBus
;
1113 busInfo
->BusNumber
= 0; //fixme
1115 Irp
->IoStatus
.Information
= (ULONG_PTR
)busInfo
;
1117 return STATUS_SUCCESS
;
1122 Bus_GetDeviceCapabilities(
1123 PDEVICE_OBJECT DeviceObject
,
1124 PDEVICE_CAPABILITIES DeviceCapabilities
1127 IO_STATUS_BLOCK ioStatus
;
1130 PDEVICE_OBJECT targetObject
;
1131 PIO_STACK_LOCATION irpStack
;
1137 // Initialize the capabilities that we will send down
1139 RtlZeroMemory( DeviceCapabilities
, sizeof(DEVICE_CAPABILITIES
) );
1140 DeviceCapabilities
->Size
= sizeof(DEVICE_CAPABILITIES
);
1141 DeviceCapabilities
->Version
= 1;
1142 DeviceCapabilities
->Address
= -1;
1143 DeviceCapabilities
->UINumber
= -1;
1146 // Initialize the event
1148 KeInitializeEvent( &pnpEvent
, NotificationEvent
, FALSE
);
1150 targetObject
= IoGetAttachedDeviceReference( DeviceObject
);
1155 pnpIrp
= IoBuildSynchronousFsdRequest(
1164 if (pnpIrp
== NULL
) {
1166 status
= STATUS_INSUFFICIENT_RESOURCES
;
1167 goto GetDeviceCapabilitiesExit
;
1172 // Pnp Irps all begin life as STATUS_NOT_SUPPORTED;
1174 pnpIrp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
1177 // Get the top of stack
1179 irpStack
= IoGetNextIrpStackLocation( pnpIrp
);
1182 // Set the top of stack
1184 RtlZeroMemory( irpStack
, sizeof(IO_STACK_LOCATION
) );
1185 irpStack
->MajorFunction
= IRP_MJ_PNP
;
1186 irpStack
->MinorFunction
= IRP_MN_QUERY_CAPABILITIES
;
1187 irpStack
->Parameters
.DeviceCapabilities
.Capabilities
= DeviceCapabilities
;
1192 status
= IoCallDriver( targetObject
, pnpIrp
);
1193 if (status
== STATUS_PENDING
) {
1196 // Block until the irp comes back.
1197 // Important thing to note here is when you allocate
1198 // the memory for an event in the stack you must do a
1199 // KernelMode wait instead of UserMode to prevent
1200 // the stack from getting paged out.
1203 KeWaitForSingleObject(
1210 status
= ioStatus
.Status
;
1214 GetDeviceCapabilitiesExit
:
1216 // Done with reference
1218 ObDereferenceObject( targetObject
);