xref: /reactos/drivers/bus/acpi/buspdo.c (revision f69e2563)
19bcd8350SThomas Faber #ifndef UNIT_TEST
2c2c66affSColin Finck #include "precomp.h"
3c2c66affSColin Finck 
4c2c66affSColin Finck #include <initguid.h>
5c2c66affSColin Finck #include <poclass.h>
6c2c66affSColin Finck 
7c2c66affSColin Finck #define NDEBUG
8c2c66affSColin Finck #include <debug.h>
9c2c66affSColin Finck 
10c2c66affSColin Finck #ifdef ALLOC_PRAGMA
11c2c66affSColin Finck #pragma alloc_text (PAGE, Bus_PDO_PnP)
12c2c66affSColin Finck #pragma alloc_text (PAGE, Bus_PDO_QueryDeviceCaps)
13c2c66affSColin Finck #pragma alloc_text (PAGE, Bus_PDO_QueryDeviceId)
14c2c66affSColin Finck #pragma alloc_text (PAGE, Bus_PDO_QueryDeviceText)
15c2c66affSColin Finck #pragma alloc_text (PAGE, Bus_PDO_QueryResources)
16c2c66affSColin Finck #pragma alloc_text (PAGE, Bus_PDO_QueryResourceRequirements)
17c2c66affSColin Finck #pragma alloc_text (PAGE, Bus_PDO_QueryDeviceRelations)
18c2c66affSColin Finck #pragma alloc_text (PAGE, Bus_PDO_QueryBusInformation)
19c2c66affSColin Finck #pragma alloc_text (PAGE, Bus_GetDeviceCapabilities)
20c2c66affSColin Finck #endif
21c2c66affSColin Finck 
22c2c66affSColin Finck NTSTATUS
Bus_PDO_PnP(PDEVICE_OBJECT DeviceObject,PIRP Irp,PIO_STACK_LOCATION IrpStack,PPDO_DEVICE_DATA DeviceData)23c2c66affSColin Finck Bus_PDO_PnP (
24c2c66affSColin Finck      PDEVICE_OBJECT       DeviceObject,
25c2c66affSColin Finck      PIRP                 Irp,
26c2c66affSColin Finck      PIO_STACK_LOCATION   IrpStack,
27c2c66affSColin Finck      PPDO_DEVICE_DATA     DeviceData
28c2c66affSColin Finck     )
29c2c66affSColin Finck {
30c2c66affSColin Finck     NTSTATUS                status;
31c2c66affSColin Finck     POWER_STATE             state;
32c2c66affSColin Finck     struct acpi_device      *device = NULL;
33c2c66affSColin Finck 
34c2c66affSColin Finck     PAGED_CODE ();
35c2c66affSColin Finck 
36c2c66affSColin Finck     if (DeviceData->AcpiHandle)
37c2c66affSColin Finck         acpi_bus_get_device(DeviceData->AcpiHandle, &device);
38c2c66affSColin Finck 
39c2c66affSColin Finck     //
40c2c66affSColin Finck     // NB: Because we are a bus enumerator, we have no one to whom we could
41c2c66affSColin Finck     // defer these irps.  Therefore we do not pass them down but merely
42c2c66affSColin Finck     // return them.
43c2c66affSColin Finck     //
44c2c66affSColin Finck 
45c2c66affSColin Finck     switch (IrpStack->MinorFunction) {
46c2c66affSColin Finck 
47c2c66affSColin Finck     case IRP_MN_START_DEVICE:
48c2c66affSColin Finck         //
49c2c66affSColin Finck         // Here we do what ever initialization and ``turning on'' that is
50c2c66affSColin Finck         // required to allow others to access this device.
51c2c66affSColin Finck         // Power up the device.
52c2c66affSColin Finck         //
53c2c66affSColin Finck         if (DeviceData->AcpiHandle && acpi_bus_power_manageable(DeviceData->AcpiHandle) &&
54c2c66affSColin Finck             !ACPI_SUCCESS(acpi_bus_set_power(DeviceData->AcpiHandle, ACPI_STATE_D0)))
55c2c66affSColin Finck         {
56c2c66affSColin Finck             DPRINT1("Device %x failed to start!\n", DeviceData->AcpiHandle);
57c2c66affSColin Finck             status = STATUS_UNSUCCESSFUL;
58c2c66affSColin Finck             break;
59c2c66affSColin Finck         }
60c2c66affSColin Finck 
61c2c66affSColin Finck         DeviceData->InterfaceName.Length = 0;
62c2c66affSColin Finck         status = STATUS_SUCCESS;
63c2c66affSColin Finck 
64c2c66affSColin Finck         if (!device)
65c2c66affSColin Finck         {
66c2c66affSColin Finck             status = IoRegisterDeviceInterface(DeviceData->Common.Self,
67c2c66affSColin Finck                                                &GUID_DEVICE_SYS_BUTTON,
68c2c66affSColin Finck                                                NULL,
69c2c66affSColin Finck                                                &DeviceData->InterfaceName);
70c2c66affSColin Finck         }
71c2c66affSColin Finck         else if (device->flags.hardware_id &&
72c2c66affSColin Finck                  strstr(device->pnp.hardware_id, ACPI_THERMAL_HID))
73c2c66affSColin Finck         {
74c2c66affSColin Finck             status = IoRegisterDeviceInterface(DeviceData->Common.Self,
75c2c66affSColin Finck                                                &GUID_DEVICE_THERMAL_ZONE,
76c2c66affSColin Finck                                                NULL,
77c2c66affSColin Finck                                                &DeviceData->InterfaceName);
78c2c66affSColin Finck         }
79c2c66affSColin Finck         else if (device->flags.hardware_id &&
80*f69e2563SGeorge Bișoc                  strstr(device->pnp.hardware_id, ACPI_FAN_HID))
81*f69e2563SGeorge Bișoc         {
82*f69e2563SGeorge Bișoc             status = IoRegisterDeviceInterface(DeviceData->Common.Self,
83*f69e2563SGeorge Bișoc                                                &GUID_DEVICE_FAN,
84*f69e2563SGeorge Bișoc                                                NULL,
85*f69e2563SGeorge Bișoc                                                &DeviceData->InterfaceName);
86*f69e2563SGeorge Bișoc         }
87*f69e2563SGeorge Bișoc         else if (device->flags.hardware_id &&
88c2c66affSColin Finck                  strstr(device->pnp.hardware_id, ACPI_BUTTON_HID_LID))
89c2c66affSColin Finck         {
90c2c66affSColin Finck             status = IoRegisterDeviceInterface(DeviceData->Common.Self,
91c2c66affSColin Finck                                                &GUID_DEVICE_LID,
92c2c66affSColin Finck                                                NULL,
93c2c66affSColin Finck                                                &DeviceData->InterfaceName);
94c2c66affSColin Finck         }
95c2c66affSColin Finck         else if (device->flags.hardware_id &&
96c2c66affSColin Finck                  strstr(device->pnp.hardware_id, ACPI_PROCESSOR_HID))
97c2c66affSColin Finck         {
98c2c66affSColin Finck             status = IoRegisterDeviceInterface(DeviceData->Common.Self,
99c2c66affSColin Finck                                                &GUID_DEVICE_PROCESSOR,
100c2c66affSColin Finck                                                NULL,
101c2c66affSColin Finck                                                &DeviceData->InterfaceName);
102c2c66affSColin Finck         }
103c2c66affSColin Finck 
104c2c66affSColin Finck         /* Failure to register an interface is not a fatal failure so don't return a failure status */
105c2c66affSColin Finck         if (NT_SUCCESS(status) && DeviceData->InterfaceName.Length != 0)
106c2c66affSColin Finck             IoSetDeviceInterfaceState(&DeviceData->InterfaceName, TRUE);
107c2c66affSColin Finck 
108c2c66affSColin Finck         state.DeviceState = PowerDeviceD0;
109c2c66affSColin Finck         PoSetPowerState(DeviceData->Common.Self, DevicePowerState, state);
110c2c66affSColin Finck         DeviceData->Common.DevicePowerState = PowerDeviceD0;
111c2c66affSColin Finck         SET_NEW_PNP_STATE(DeviceData->Common, Started);
112c2c66affSColin Finck         status = STATUS_SUCCESS;
113c2c66affSColin Finck         break;
114c2c66affSColin Finck 
115c2c66affSColin Finck     case IRP_MN_STOP_DEVICE:
116c2c66affSColin Finck 
117c2c66affSColin Finck         if (DeviceData->InterfaceName.Length != 0)
118c2c66affSColin Finck             IoSetDeviceInterfaceState(&DeviceData->InterfaceName, FALSE);
119c2c66affSColin Finck 
120c2c66affSColin Finck         //
121c2c66affSColin Finck         // Here we shut down the device and give up and unmap any resources
122c2c66affSColin Finck         // we acquired for the device.
123c2c66affSColin Finck         //
124c2c66affSColin Finck         if (DeviceData->AcpiHandle && acpi_bus_power_manageable(DeviceData->AcpiHandle) &&
125c2c66affSColin Finck             !ACPI_SUCCESS(acpi_bus_set_power(DeviceData->AcpiHandle, ACPI_STATE_D3)))
126c2c66affSColin Finck         {
127c2c66affSColin Finck             DPRINT1("Device %x failed to stop!\n", DeviceData->AcpiHandle);
128c2c66affSColin Finck             status = STATUS_UNSUCCESSFUL;
129c2c66affSColin Finck             break;
130c2c66affSColin Finck         }
131c2c66affSColin Finck 
132c2c66affSColin Finck         state.DeviceState = PowerDeviceD3;
133c2c66affSColin Finck         PoSetPowerState(DeviceData->Common.Self, DevicePowerState, state);
134c2c66affSColin Finck         DeviceData->Common.DevicePowerState = PowerDeviceD3;
135c2c66affSColin Finck         SET_NEW_PNP_STATE(DeviceData->Common, Stopped);
136c2c66affSColin Finck         status = STATUS_SUCCESS;
137c2c66affSColin Finck         break;
138c2c66affSColin Finck 
139c2c66affSColin Finck 
140c2c66affSColin Finck     case IRP_MN_QUERY_STOP_DEVICE:
141c2c66affSColin Finck 
142c2c66affSColin Finck         //
143c2c66affSColin Finck         // No reason here why we can't stop the device.
144c2c66affSColin Finck         // If there were a reason we should speak now, because answering success
145c2c66affSColin Finck         // here may result in a stop device irp.
146c2c66affSColin Finck         //
147c2c66affSColin Finck 
148c2c66affSColin Finck         SET_NEW_PNP_STATE(DeviceData->Common, StopPending);
149c2c66affSColin Finck         status = STATUS_SUCCESS;
150c2c66affSColin Finck         break;
151c2c66affSColin Finck 
152c2c66affSColin Finck     case IRP_MN_CANCEL_STOP_DEVICE:
153c2c66affSColin Finck 
154c2c66affSColin Finck         //
155c2c66affSColin Finck         // The stop was canceled.  Whatever state we set, or resources we put
156c2c66affSColin Finck         // on hold in anticipation of the forthcoming STOP device IRP should be
157c2c66affSColin Finck         // put back to normal.  Someone, in the long list of concerned parties,
158c2c66affSColin Finck         // has failed the stop device query.
159c2c66affSColin Finck         //
160c2c66affSColin Finck 
161c2c66affSColin Finck         //
162c2c66affSColin Finck         // First check to see whether you have received cancel-stop
163c2c66affSColin Finck         // without first receiving a query-stop. This could happen if someone
164c2c66affSColin Finck         // above us fails a query-stop and passes down the subsequent
165c2c66affSColin Finck         // cancel-stop.
166c2c66affSColin Finck         //
167c2c66affSColin Finck 
168c2c66affSColin Finck         if (StopPending == DeviceData->Common.DevicePnPState)
169c2c66affSColin Finck         {
170c2c66affSColin Finck             //
171c2c66affSColin Finck             // We did receive a query-stop, so restore.
172c2c66affSColin Finck             //
173c2c66affSColin Finck             RESTORE_PREVIOUS_PNP_STATE(DeviceData->Common);
174c2c66affSColin Finck         }
175c2c66affSColin Finck         status = STATUS_SUCCESS;// We must not fail this IRP.
176c2c66affSColin Finck         break;
177c2c66affSColin Finck 
178c2c66affSColin Finck     case IRP_MN_REMOVE_DEVICE:
179c2c66affSColin Finck         //
180c2c66affSColin Finck         // We handle REMOVE_DEVICE just like STOP_DEVICE. This is because
181c2c66affSColin Finck         // the device is still physically present (or at least we don't know any better)
182c2c66affSColin Finck         // so we have to retain the PDO after stopping and removing power from it.
183c2c66affSColin Finck         //
184c2c66affSColin Finck         if (DeviceData->InterfaceName.Length != 0)
185c2c66affSColin Finck             IoSetDeviceInterfaceState(&DeviceData->InterfaceName, FALSE);
186c2c66affSColin Finck 
187c2c66affSColin Finck         if (DeviceData->AcpiHandle && acpi_bus_power_manageable(DeviceData->AcpiHandle) &&
188c2c66affSColin Finck             !ACPI_SUCCESS(acpi_bus_set_power(DeviceData->AcpiHandle, ACPI_STATE_D3)))
189c2c66affSColin Finck         {
190c2c66affSColin Finck             DPRINT1("Device %x failed to enter D3!\n", DeviceData->AcpiHandle);
191c2c66affSColin Finck             state.DeviceState = PowerDeviceD3;
192c2c66affSColin Finck             PoSetPowerState(DeviceData->Common.Self, DevicePowerState, state);
193c2c66affSColin Finck             DeviceData->Common.DevicePowerState = PowerDeviceD3;
194c2c66affSColin Finck         }
195c2c66affSColin Finck 
196c2c66affSColin Finck         SET_NEW_PNP_STATE(DeviceData->Common, Stopped);
197c2c66affSColin Finck         status = STATUS_SUCCESS;
198c2c66affSColin Finck         break;
199c2c66affSColin Finck 
200c2c66affSColin Finck     case IRP_MN_QUERY_REMOVE_DEVICE:
201c2c66affSColin Finck         SET_NEW_PNP_STATE(DeviceData->Common, RemovalPending);
202c2c66affSColin Finck         status = STATUS_SUCCESS;
203c2c66affSColin Finck         break;
204c2c66affSColin Finck 
205c2c66affSColin Finck     case IRP_MN_CANCEL_REMOVE_DEVICE:
206c2c66affSColin Finck         if (RemovalPending == DeviceData->Common.DevicePnPState)
207c2c66affSColin Finck         {
208c2c66affSColin Finck             RESTORE_PREVIOUS_PNP_STATE(DeviceData->Common);
209c2c66affSColin Finck         }
210c2c66affSColin Finck         status = STATUS_SUCCESS;
211c2c66affSColin Finck         break;
212c2c66affSColin Finck 
213c2c66affSColin Finck     case IRP_MN_QUERY_CAPABILITIES:
214c2c66affSColin Finck 
215c2c66affSColin Finck         //
216c2c66affSColin Finck         // Return the capabilities of a device, such as whether the device
217c2c66affSColin Finck         // can be locked or ejected..etc
218c2c66affSColin Finck         //
219c2c66affSColin Finck 
220c2c66affSColin Finck         status = Bus_PDO_QueryDeviceCaps(DeviceData, Irp);
221c2c66affSColin Finck 
222c2c66affSColin Finck         break;
223c2c66affSColin Finck 
224c2c66affSColin Finck     case IRP_MN_QUERY_ID:
225c2c66affSColin Finck 
226c2c66affSColin Finck         // Query the IDs of the device
227c2c66affSColin Finck         status = Bus_PDO_QueryDeviceId(DeviceData, Irp);
228c2c66affSColin Finck 
229c2c66affSColin Finck         break;
230c2c66affSColin Finck 
231c2c66affSColin Finck     case IRP_MN_QUERY_DEVICE_RELATIONS:
232c2c66affSColin Finck 
233c2c66affSColin Finck         DPRINT("\tQueryDeviceRelation Type: %s\n",DbgDeviceRelationString(\
234c2c66affSColin Finck                     IrpStack->Parameters.QueryDeviceRelations.Type));
235c2c66affSColin Finck 
236c2c66affSColin Finck         status = Bus_PDO_QueryDeviceRelations(DeviceData, Irp);
237c2c66affSColin Finck 
238c2c66affSColin Finck         break;
239c2c66affSColin Finck 
240c2c66affSColin Finck     case IRP_MN_QUERY_DEVICE_TEXT:
241c2c66affSColin Finck 
242c2c66affSColin Finck         status = Bus_PDO_QueryDeviceText(DeviceData, Irp);
243c2c66affSColin Finck 
244c2c66affSColin Finck         break;
245c2c66affSColin Finck 
246c2c66affSColin Finck     case IRP_MN_QUERY_RESOURCES:
247c2c66affSColin Finck 
248c2c66affSColin Finck         status = Bus_PDO_QueryResources(DeviceData, Irp);
249c2c66affSColin Finck 
250c2c66affSColin Finck         break;
251c2c66affSColin Finck 
252c2c66affSColin Finck     case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
253c2c66affSColin Finck 
254c2c66affSColin Finck         status = Bus_PDO_QueryResourceRequirements(DeviceData, Irp);
255c2c66affSColin Finck 
256c2c66affSColin Finck         break;
257c2c66affSColin Finck 
258c2c66affSColin Finck     case IRP_MN_QUERY_BUS_INFORMATION:
259c2c66affSColin Finck 
260c2c66affSColin Finck         status = Bus_PDO_QueryBusInformation(DeviceData, Irp);
261c2c66affSColin Finck 
262c2c66affSColin Finck         break;
263c2c66affSColin Finck 
264c2c66affSColin Finck     case IRP_MN_QUERY_INTERFACE:
265c2c66affSColin Finck 
266c2c66affSColin Finck         status = Bus_PDO_QueryInterface(DeviceData, Irp);
267c2c66affSColin Finck 
268c2c66affSColin Finck         break;
269c2c66affSColin Finck 
270c2c66affSColin Finck 
271c2c66affSColin Finck     case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
272c2c66affSColin Finck 
273c2c66affSColin Finck         //
274c2c66affSColin Finck         // OPTIONAL for bus drivers.
275c2c66affSColin Finck         // The PnP Manager sends this IRP to a device
276c2c66affSColin Finck         // stack so filter and function drivers can adjust the
277c2c66affSColin Finck         // resources required by the device, if appropriate.
278c2c66affSColin Finck         //
279c2c66affSColin Finck 
280c2c66affSColin Finck         //break;
281c2c66affSColin Finck 
282c2c66affSColin Finck     //case IRP_MN_QUERY_PNP_DEVICE_STATE:
283c2c66affSColin Finck 
284c2c66affSColin Finck         //
285c2c66affSColin Finck         // OPTIONAL for bus drivers.
286c2c66affSColin Finck         // The PnP Manager sends this IRP after the drivers for
287c2c66affSColin Finck         // a device return success from the IRP_MN_START_DEVICE
288c2c66affSColin Finck         // request. The PnP Manager also sends this IRP when a
289c2c66affSColin Finck         // driver for the device calls IoInvalidateDeviceState.
290c2c66affSColin Finck         //
291c2c66affSColin Finck 
292c2c66affSColin Finck         // break;
293c2c66affSColin Finck 
294c2c66affSColin Finck     //case IRP_MN_READ_CONFIG:
295c2c66affSColin Finck     //case IRP_MN_WRITE_CONFIG:
296c2c66affSColin Finck 
297c2c66affSColin Finck         //
298c2c66affSColin Finck         // Bus drivers for buses with configuration space must handle
299c2c66affSColin Finck         // this request for their child devices. Our devices don't
300c2c66affSColin Finck         // have a config space.
301c2c66affSColin Finck         //
302c2c66affSColin Finck 
303c2c66affSColin Finck         // break;
304c2c66affSColin Finck 
305c2c66affSColin Finck     //case IRP_MN_SET_LOCK:
306c2c66affSColin Finck 
307c2c66affSColin Finck         // break;
308c2c66affSColin Finck 
309c2c66affSColin Finck     default:
310c2c66affSColin Finck 
311c2c66affSColin Finck         //
312c2c66affSColin Finck         // For PnP requests to the PDO that we do not understand we should
313c2c66affSColin Finck         // return the IRP WITHOUT setting the status or information fields.
314c2c66affSColin Finck         // These fields may have already been set by a filter (eg acpi).
315c2c66affSColin Finck         status = Irp->IoStatus.Status;
316c2c66affSColin Finck 
317c2c66affSColin Finck         break;
318c2c66affSColin Finck     }
319c2c66affSColin Finck 
320c2c66affSColin Finck     Irp->IoStatus.Status = status;
321c2c66affSColin Finck     IoCompleteRequest (Irp, IO_NO_INCREMENT);
322c2c66affSColin Finck 
323c2c66affSColin Finck     return status;
324c2c66affSColin Finck }
325c2c66affSColin Finck 
326c2c66affSColin Finck NTSTATUS
Bus_PDO_QueryDeviceCaps(PPDO_DEVICE_DATA DeviceData,PIRP Irp)327c2c66affSColin Finck Bus_PDO_QueryDeviceCaps(
328c2c66affSColin Finck      PPDO_DEVICE_DATA     DeviceData,
329c2c66affSColin Finck       PIRP   Irp )
330c2c66affSColin Finck {
331c2c66affSColin Finck 
332c2c66affSColin Finck     PIO_STACK_LOCATION      stack;
333c2c66affSColin Finck     PDEVICE_CAPABILITIES    deviceCapabilities;
334c2c66affSColin Finck     struct acpi_device *device = NULL;
335c2c66affSColin Finck     ULONG i;
336c2c66affSColin Finck 
337c2c66affSColin Finck     PAGED_CODE ();
338c2c66affSColin Finck 
339c2c66affSColin Finck     if (DeviceData->AcpiHandle)
340c2c66affSColin Finck         acpi_bus_get_device(DeviceData->AcpiHandle, &device);
341c2c66affSColin Finck 
342c2c66affSColin Finck     stack = IoGetCurrentIrpStackLocation (Irp);
343c2c66affSColin Finck 
344c2c66affSColin Finck     //
345c2c66affSColin Finck     // Get the packet.
346c2c66affSColin Finck     //
347c2c66affSColin Finck     deviceCapabilities=stack->Parameters.DeviceCapabilities.Capabilities;
348c2c66affSColin Finck 
349c2c66affSColin Finck     //
350c2c66affSColin Finck     // Set the capabilities.
351c2c66affSColin Finck     //
352c2c66affSColin Finck 
353c2c66affSColin Finck     if (deviceCapabilities->Version != 1 ||
354c2c66affSColin Finck             deviceCapabilities->Size < sizeof(DEVICE_CAPABILITIES))
355c2c66affSColin Finck     {
356c2c66affSColin Finck        return STATUS_UNSUCCESSFUL;
357c2c66affSColin Finck     }
358c2c66affSColin Finck 
359c2c66affSColin Finck     deviceCapabilities->D1Latency = 0;
360c2c66affSColin Finck     deviceCapabilities->D2Latency = 0;
361c2c66affSColin Finck     deviceCapabilities->D3Latency = 0;
362c2c66affSColin Finck 
363c2c66affSColin Finck     deviceCapabilities->DeviceState[PowerSystemWorking] = PowerDeviceD0;
364c2c66affSColin Finck     deviceCapabilities->DeviceState[PowerSystemSleeping1] = PowerDeviceD3;
365c2c66affSColin Finck     deviceCapabilities->DeviceState[PowerSystemSleeping2] = PowerDeviceD3;
366c2c66affSColin Finck     deviceCapabilities->DeviceState[PowerSystemSleeping3] = PowerDeviceD3;
367c2c66affSColin Finck 
368c2c66affSColin Finck     for (i = 0; i < ACPI_D_STATE_COUNT && device; i++)
369c2c66affSColin Finck     {
370c2c66affSColin Finck         if (!device->power.states[i].flags.valid)
371c2c66affSColin Finck             continue;
372c2c66affSColin Finck 
373c2c66affSColin Finck         switch (i)
374c2c66affSColin Finck         {
375c2c66affSColin Finck            case ACPI_STATE_D0:
376c2c66affSColin Finck               deviceCapabilities->DeviceState[PowerSystemWorking] = PowerDeviceD0;
377c2c66affSColin Finck               break;
378c2c66affSColin Finck 
379c2c66affSColin Finck            case ACPI_STATE_D1:
380c2c66affSColin Finck               deviceCapabilities->DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
381c2c66affSColin Finck               deviceCapabilities->D1Latency = device->power.states[i].latency;
382c2c66affSColin Finck               break;
383c2c66affSColin Finck 
384c2c66affSColin Finck            case ACPI_STATE_D2:
385c2c66affSColin Finck               deviceCapabilities->DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
386c2c66affSColin Finck               deviceCapabilities->D2Latency = device->power.states[i].latency;
387c2c66affSColin Finck               break;
388c2c66affSColin Finck 
389c2c66affSColin Finck            case ACPI_STATE_D3:
390c2c66affSColin Finck               deviceCapabilities->DeviceState[PowerSystemSleeping3] = PowerDeviceD3;
391c2c66affSColin Finck               deviceCapabilities->D3Latency = device->power.states[i].latency;
392c2c66affSColin Finck               break;
393c2c66affSColin Finck         }
394c2c66affSColin Finck     }
395c2c66affSColin Finck 
396c2c66affSColin Finck     // We can wake the system from D1
397c2c66affSColin Finck     deviceCapabilities->DeviceWake = PowerDeviceD1;
398c2c66affSColin Finck 
399c2c66affSColin Finck 
400c2c66affSColin Finck     deviceCapabilities->DeviceD1 =
401c2c66affSColin Finck         (deviceCapabilities->DeviceState[PowerSystemSleeping1] == PowerDeviceD1) ? TRUE : FALSE;
402c2c66affSColin Finck     deviceCapabilities->DeviceD2 =
403c2c66affSColin Finck         (deviceCapabilities->DeviceState[PowerSystemSleeping2] == PowerDeviceD2) ? TRUE : FALSE;
404c2c66affSColin Finck 
405c2c66affSColin Finck     deviceCapabilities->WakeFromD0 = FALSE;
406c2c66affSColin Finck     deviceCapabilities->WakeFromD1 = TRUE; //Yes we can
407c2c66affSColin Finck     deviceCapabilities->WakeFromD2 = FALSE;
408c2c66affSColin Finck     deviceCapabilities->WakeFromD3 = FALSE;
409c2c66affSColin Finck 
410c2c66affSColin Finck     if (device)
411c2c66affSColin Finck     {
412c2c66affSColin Finck        deviceCapabilities->LockSupported = device->flags.lockable;
413c2c66affSColin Finck        deviceCapabilities->EjectSupported = device->flags.ejectable;
414c2c66affSColin Finck        deviceCapabilities->HardwareDisabled = !device->status.enabled && !device->status.functional;
415c2c66affSColin Finck        deviceCapabilities->Removable = device->flags.removable;
416c2c66affSColin Finck        deviceCapabilities->SurpriseRemovalOK = device->flags.surprise_removal_ok;
417c2c66affSColin Finck        deviceCapabilities->UniqueID = device->flags.unique_id;
418c2c66affSColin Finck        deviceCapabilities->NoDisplayInUI = !device->status.show_in_ui;
419c2c66affSColin Finck        deviceCapabilities->Address = device->pnp.bus_address;
420c2c66affSColin Finck     }
421c2c66affSColin Finck 
422c2c66affSColin Finck     if (!device ||
423c2c66affSColin Finck         (device->flags.hardware_id &&
424c2c66affSColin Finck          (strstr(device->pnp.hardware_id, ACPI_BUTTON_HID_LID) ||
425c2c66affSColin Finck           strstr(device->pnp.hardware_id, ACPI_THERMAL_HID) ||
426c2c66affSColin Finck           strstr(device->pnp.hardware_id, ACPI_PROCESSOR_HID))))
427c2c66affSColin Finck     {
428c2c66affSColin Finck         /* Allow ACPI to control the device if it is a lid button,
429c2c66affSColin Finck          * a thermal zone, a processor, or a fixed feature button */
430c2c66affSColin Finck         deviceCapabilities->RawDeviceOK = TRUE;
431c2c66affSColin Finck     }
432c2c66affSColin Finck 
433c2c66affSColin Finck     deviceCapabilities->SilentInstall = FALSE;
434c2c66affSColin Finck     deviceCapabilities->UINumber = (ULONG)-1;
435c2c66affSColin Finck 
436c2c66affSColin Finck     return STATUS_SUCCESS;
437c2c66affSColin Finck 
438c2c66affSColin Finck }
439c2c66affSColin Finck 
440c2c66affSColin Finck NTSTATUS
Bus_PDO_QueryDeviceId(PPDO_DEVICE_DATA DeviceData,PIRP Irp)441c2c66affSColin Finck Bus_PDO_QueryDeviceId(
442c2c66affSColin Finck      PPDO_DEVICE_DATA     DeviceData,
443c2c66affSColin Finck       PIRP   Irp )
444c2c66affSColin Finck {
445c2c66affSColin Finck     PIO_STACK_LOCATION      stack;
446c2c66affSColin Finck     PWCHAR                  buffer, src;
447c2c66affSColin Finck     WCHAR                   temp[256];
448c2c66affSColin Finck     ULONG                   length, i;
449c2c66affSColin Finck     NTSTATUS                status = STATUS_SUCCESS;
450c2c66affSColin Finck     struct acpi_device *Device;
451c2c66affSColin Finck 
452c2c66affSColin Finck     PAGED_CODE ();
453c2c66affSColin Finck 
454c2c66affSColin Finck     stack = IoGetCurrentIrpStackLocation (Irp);
455c2c66affSColin Finck 
456c2c66affSColin Finck     switch (stack->Parameters.QueryId.IdType) {
457c2c66affSColin Finck 
458c2c66affSColin Finck     case BusQueryDeviceID:
459c2c66affSColin Finck 
460c2c66affSColin Finck         /* This is a REG_SZ value */
461c2c66affSColin Finck 
462c2c66affSColin Finck         if (DeviceData->AcpiHandle)
463c2c66affSColin Finck         {
464c2c66affSColin Finck             acpi_bus_get_device(DeviceData->AcpiHandle, &Device);
465c2c66affSColin Finck 
466c2c66affSColin Finck             if (strcmp(Device->pnp.hardware_id, "Processor") == 0)
467c2c66affSColin Finck             {
468c2c66affSColin Finck                 length = wcslen(ProcessorIdString);
469c2c66affSColin Finck                 wcscpy(temp, ProcessorIdString);
470c2c66affSColin Finck             }
471c2c66affSColin Finck             else
472c2c66affSColin Finck             {
473c2c66affSColin Finck                 length = swprintf(temp,
474c2c66affSColin Finck                                   L"ACPI\\%hs",
475c2c66affSColin Finck                                   Device->pnp.hardware_id);
476c2c66affSColin Finck             }
477c2c66affSColin Finck         }
478c2c66affSColin Finck         else
479c2c66affSColin Finck         {
480c2c66affSColin Finck             /* We know it's a fixed feature button because
481c2c66affSColin Finck              * these are direct children of the ACPI root device
482c2c66affSColin Finck              * and therefore have no handle
483c2c66affSColin Finck              */
484c2c66affSColin Finck             length = swprintf(temp,
485c2c66affSColin Finck                               L"ACPI\\FixedButton");
486c2c66affSColin Finck         }
487c2c66affSColin Finck 
488c2c66affSColin Finck         temp[length++] = UNICODE_NULL;
489c2c66affSColin Finck 
490c2c66affSColin Finck         NT_ASSERT(length * sizeof(WCHAR) <= sizeof(temp));
491c2c66affSColin Finck 
492c2c66affSColin Finck         buffer = ExAllocatePoolWithTag(PagedPool, length * sizeof(WCHAR), 'IpcA');
493c2c66affSColin Finck 
494c2c66affSColin Finck         if (!buffer) {
495c2c66affSColin Finck            status = STATUS_INSUFFICIENT_RESOURCES;
496c2c66affSColin Finck            break;
497c2c66affSColin Finck         }
498c2c66affSColin Finck 
499c2c66affSColin Finck         RtlCopyMemory (buffer, temp, length * sizeof(WCHAR));
500c2c66affSColin Finck         Irp->IoStatus.Information = (ULONG_PTR) buffer;
501c2c66affSColin Finck         DPRINT("BusQueryDeviceID: %ls\n",buffer);
502c2c66affSColin Finck         break;
503c2c66affSColin Finck 
504c2c66affSColin Finck     case BusQueryInstanceID:
505c2c66affSColin Finck 
506c2c66affSColin Finck         /* This is a REG_SZ value */
507c2c66affSColin Finck 
508c2c66affSColin Finck         /* See comment in BusQueryDeviceID case */
509c2c66affSColin Finck         if(DeviceData->AcpiHandle)
510c2c66affSColin Finck         {
511c2c66affSColin Finck            acpi_bus_get_device(DeviceData->AcpiHandle, &Device);
512c2c66affSColin Finck 
513c2c66affSColin Finck            if (Device->flags.unique_id)
514c2c66affSColin Finck               length = swprintf(temp,
515c2c66affSColin Finck                                 L"%hs",
516c2c66affSColin Finck                                 Device->pnp.unique_id);
517c2c66affSColin Finck            else
518c2c66affSColin Finck               /* FIXME: Generate unique id! */
5192183e65cSHermès Bélusca-Maïto               length = swprintf(temp, L"%ls", L"0");
520c2c66affSColin Finck         }
521c2c66affSColin Finck         else
522c2c66affSColin Finck         {
523c2c66affSColin Finck            /* FIXME: Generate unique id! */
5242183e65cSHermès Bélusca-Maïto            length = swprintf(temp, L"%ls", L"0");
525c2c66affSColin Finck         }
526c2c66affSColin Finck 
527c2c66affSColin Finck         temp[length++] = UNICODE_NULL;
528c2c66affSColin Finck 
529c2c66affSColin Finck         NT_ASSERT(length * sizeof(WCHAR) <= sizeof(temp));
530c2c66affSColin Finck 
531c2c66affSColin Finck         buffer = ExAllocatePoolWithTag(PagedPool, length * sizeof(WCHAR), 'IpcA');
532c2c66affSColin Finck         if (!buffer) {
533c2c66affSColin Finck            status = STATUS_INSUFFICIENT_RESOURCES;
534c2c66affSColin Finck            break;
535c2c66affSColin Finck         }
536c2c66affSColin Finck 
537c2c66affSColin Finck         RtlCopyMemory (buffer, temp, length * sizeof (WCHAR));
538c2c66affSColin Finck         DPRINT("BusQueryInstanceID: %ls\n",buffer);
539c2c66affSColin Finck         Irp->IoStatus.Information = (ULONG_PTR) buffer;
540c2c66affSColin Finck         break;
541c2c66affSColin Finck 
542c2c66affSColin Finck     case BusQueryHardwareIDs:
543c2c66affSColin Finck 
544c2c66affSColin Finck         /* This is a REG_MULTI_SZ value */
545c2c66affSColin Finck         length = 0;
546c2c66affSColin Finck         status = STATUS_NOT_SUPPORTED;
547c2c66affSColin Finck 
548c2c66affSColin Finck         /* See comment in BusQueryDeviceID case */
549c2c66affSColin Finck         if (DeviceData->AcpiHandle)
550c2c66affSColin Finck         {
551c2c66affSColin Finck             acpi_bus_get_device(DeviceData->AcpiHandle, &Device);
552c2c66affSColin Finck 
553c2c66affSColin Finck             if (!Device->flags.hardware_id)
554c2c66affSColin Finck             {
555c2c66affSColin Finck                 /* We don't have the ID to satisfy this request */
556c2c66affSColin Finck                 break;
557c2c66affSColin Finck             }
558c2c66affSColin Finck 
559c2c66affSColin Finck             DPRINT("Device name: %s\n", Device->pnp.device_name);
560c2c66affSColin Finck             DPRINT("Hardware ID: %s\n", Device->pnp.hardware_id);
561c2c66affSColin Finck 
562c2c66affSColin Finck             if (strcmp(Device->pnp.hardware_id, "Processor") == 0)
563c2c66affSColin Finck             {
564c2c66affSColin Finck                 length = ProcessorHardwareIds.Length / sizeof(WCHAR);
565c2c66affSColin Finck                 src = ProcessorHardwareIds.Buffer;
566c2c66affSColin Finck             }
567c2c66affSColin Finck             else
568c2c66affSColin Finck             {
569c2c66affSColin Finck                 length += swprintf(&temp[length],
570c2c66affSColin Finck                                    L"ACPI\\%hs",
571c2c66affSColin Finck                                    Device->pnp.hardware_id);
572c2c66affSColin Finck                 temp[length++] = UNICODE_NULL;
573c2c66affSColin Finck 
574c2c66affSColin Finck                 length += swprintf(&temp[length],
575c2c66affSColin Finck                                    L"*%hs",
576c2c66affSColin Finck                                    Device->pnp.hardware_id);
577c2c66affSColin Finck                 temp[length++] = UNICODE_NULL;
578c2c66affSColin Finck                 temp[length++] = UNICODE_NULL;
579c2c66affSColin Finck                 src = temp;
580c2c66affSColin Finck             }
581c2c66affSColin Finck         }
582c2c66affSColin Finck         else
583c2c66affSColin Finck         {
584c2c66affSColin Finck             length += swprintf(&temp[length],
585c2c66affSColin Finck                                L"ACPI\\FixedButton");
586c2c66affSColin Finck             temp[length++] = UNICODE_NULL;
587c2c66affSColin Finck 
588c2c66affSColin Finck             length += swprintf(&temp[length],
589c2c66affSColin Finck                                L"*FixedButton");
590c2c66affSColin Finck             temp[length++] = UNICODE_NULL;
591c2c66affSColin Finck             temp[length++] = UNICODE_NULL;
592c2c66affSColin Finck             src = temp;
593c2c66affSColin Finck         }
594c2c66affSColin Finck 
595c2c66affSColin Finck         NT_ASSERT(length * sizeof(WCHAR) <= sizeof(temp));
596c2c66affSColin Finck 
597c2c66affSColin Finck         buffer = ExAllocatePoolWithTag(PagedPool, length * sizeof(WCHAR), 'IpcA');
598c2c66affSColin Finck 
599c2c66affSColin Finck         if (!buffer) {
600c2c66affSColin Finck            status = STATUS_INSUFFICIENT_RESOURCES;
601c2c66affSColin Finck            break;
602c2c66affSColin Finck         }
603c2c66affSColin Finck 
604c2c66affSColin Finck         RtlCopyMemory (buffer, src, length * sizeof(WCHAR));
605c2c66affSColin Finck         Irp->IoStatus.Information = (ULONG_PTR) buffer;
606c2c66affSColin Finck         DPRINT("BusQueryHardwareIDs: %ls\n",buffer);
607c2c66affSColin Finck         status = STATUS_SUCCESS;
608c2c66affSColin Finck         break;
609c2c66affSColin Finck 
610c2c66affSColin Finck     case BusQueryCompatibleIDs:
611c2c66affSColin Finck 
612c2c66affSColin Finck         /* This is a REG_MULTI_SZ value */
613c2c66affSColin Finck         length = 0;
614c2c66affSColin Finck         status = STATUS_NOT_SUPPORTED;
615c2c66affSColin Finck 
616c2c66affSColin Finck         /* See comment in BusQueryDeviceID case */
617c2c66affSColin Finck         if (DeviceData->AcpiHandle)
618c2c66affSColin Finck         {
619c2c66affSColin Finck             acpi_bus_get_device(DeviceData->AcpiHandle, &Device);
620c2c66affSColin Finck 
621c2c66affSColin Finck             if (!Device->flags.hardware_id)
622c2c66affSColin Finck             {
623c2c66affSColin Finck                 /* We don't have the ID to satisfy this request */
624c2c66affSColin Finck                 break;
625c2c66affSColin Finck             }
626c2c66affSColin Finck 
627c2c66affSColin Finck             DPRINT("Device name: %s\n", Device->pnp.device_name);
628c2c66affSColin Finck             DPRINT("Hardware ID: %s\n", Device->pnp.hardware_id);
629c2c66affSColin Finck 
630c2c66affSColin Finck             if (strcmp(Device->pnp.hardware_id, "Processor") == 0)
631c2c66affSColin Finck             {
632c2c66affSColin Finck                 length += swprintf(&temp[length],
633c2c66affSColin Finck                                    L"ACPI\\%hs",
634c2c66affSColin Finck                                    Device->pnp.hardware_id);
635c2c66affSColin Finck                 temp[length++] = UNICODE_NULL;
636c2c66affSColin Finck 
637c2c66affSColin Finck                 length += swprintf(&temp[length],
638c2c66affSColin Finck                                    L"*%hs",
639c2c66affSColin Finck                                    Device->pnp.hardware_id);
640c2c66affSColin Finck                 temp[length++] = UNICODE_NULL;
641c2c66affSColin Finck                 temp[length++] = UNICODE_NULL;
642c2c66affSColin Finck             }
643c2c66affSColin Finck             else if (Device->flags.compatible_ids)
644c2c66affSColin Finck             {
645c2c66affSColin Finck                 for (i = 0; i < Device->pnp.cid_list->Count; i++)
646c2c66affSColin Finck                 {
647c2c66affSColin Finck                     length += swprintf(&temp[length],
648c2c66affSColin Finck                                    L"ACPI\\%hs",
649c2c66affSColin Finck                                    Device->pnp.cid_list->Ids[i].String);
650c2c66affSColin Finck                     temp[length++] = UNICODE_NULL;
651c2c66affSColin Finck 
652c2c66affSColin Finck                     length += swprintf(&temp[length],
653c2c66affSColin Finck                                    L"*%hs",
654c2c66affSColin Finck                                    Device->pnp.cid_list->Ids[i].String);
655c2c66affSColin Finck                     temp[length++] = UNICODE_NULL;
656c2c66affSColin Finck                 }
657c2c66affSColin Finck 
658c2c66affSColin Finck                 temp[length++] = UNICODE_NULL;
659c2c66affSColin Finck             }
660c2c66affSColin Finck             else
661c2c66affSColin Finck             {
662c2c66affSColin Finck                 /* No compatible IDs */
663c2c66affSColin Finck                 break;
664c2c66affSColin Finck             }
665c2c66affSColin Finck 
666c2c66affSColin Finck             NT_ASSERT(length * sizeof(WCHAR) <= sizeof(temp));
667c2c66affSColin Finck 
668c2c66affSColin Finck             buffer = ExAllocatePoolWithTag(PagedPool, length * sizeof(WCHAR), 'IpcA');
669c2c66affSColin Finck             if (!buffer)
670c2c66affSColin Finck             {
671c2c66affSColin Finck                 status = STATUS_INSUFFICIENT_RESOURCES;
672c2c66affSColin Finck                 break;
673c2c66affSColin Finck             }
674c2c66affSColin Finck 
675c2c66affSColin Finck             RtlCopyMemory (buffer, temp, length * sizeof(WCHAR));
676c2c66affSColin Finck             Irp->IoStatus.Information = (ULONG_PTR) buffer;
677c2c66affSColin Finck             DPRINT("BusQueryCompatibleIDs: %ls\n",buffer);
678c2c66affSColin Finck             status = STATUS_SUCCESS;
679c2c66affSColin Finck         }
680c2c66affSColin Finck         break;
681c2c66affSColin Finck 
682c2c66affSColin Finck     default:
683c2c66affSColin Finck         status = Irp->IoStatus.Status;
684c2c66affSColin Finck     }
685c2c66affSColin Finck     return status;
686c2c66affSColin Finck }
687c2c66affSColin Finck 
688c2c66affSColin Finck NTSTATUS
Bus_PDO_QueryDeviceText(PPDO_DEVICE_DATA DeviceData,PIRP Irp)689c2c66affSColin Finck Bus_PDO_QueryDeviceText(
690c2c66affSColin Finck      PPDO_DEVICE_DATA     DeviceData,
691c2c66affSColin Finck       PIRP   Irp )
692c2c66affSColin Finck {
693c2c66affSColin Finck     PWCHAR  Buffer, Temp;
694c2c66affSColin Finck     PIO_STACK_LOCATION   stack;
695c2c66affSColin Finck     NTSTATUS    status = Irp->IoStatus.Status;
696c2c66affSColin Finck     PAGED_CODE ();
697c2c66affSColin Finck 
698c2c66affSColin Finck     stack = IoGetCurrentIrpStackLocation (Irp);
699c2c66affSColin Finck 
700c2c66affSColin Finck     switch (stack->Parameters.QueryDeviceText.DeviceTextType) {
701c2c66affSColin Finck 
702c2c66affSColin Finck     case DeviceTextDescription:
703c2c66affSColin Finck 
704c2c66affSColin Finck         if (!Irp->IoStatus.Information) {
705c2c66affSColin Finck             if (wcsstr (DeviceData->HardwareIDs, L"PNP000") != 0)
706c2c66affSColin Finck                 Temp = L"Programmable interrupt controller";
707c2c66affSColin Finck             else if (wcsstr(DeviceData->HardwareIDs, L"PNP010") != 0)
708c2c66affSColin Finck                 Temp = L"System timer";
709c2c66affSColin Finck             else if (wcsstr(DeviceData->HardwareIDs, L"PNP020") != 0)
710c2c66affSColin Finck                 Temp = L"DMA controller";
711c2c66affSColin Finck             else if (wcsstr(DeviceData->HardwareIDs, L"PNP03") != 0)
712c2c66affSColin Finck                 Temp = L"Keyboard";
713c2c66affSColin Finck             else if (wcsstr(DeviceData->HardwareIDs, L"PNP040") != 0)
714c2c66affSColin Finck                 Temp = L"Parallel port";
715c2c66affSColin Finck             else if (wcsstr(DeviceData->HardwareIDs, L"PNP05") != 0)
716c2c66affSColin Finck                 Temp = L"Serial port";
717c2c66affSColin Finck             else if (wcsstr(DeviceData->HardwareIDs, L"PNP06") != 0)
718c2c66affSColin Finck                 Temp = L"Disk controller";
719c2c66affSColin Finck             else if (wcsstr(DeviceData->HardwareIDs, L"PNP07") != 0)
720c2c66affSColin Finck                 Temp = L"Disk controller";
721c2c66affSColin Finck             else if (wcsstr(DeviceData->HardwareIDs, L"PNP09") != 0)
722c2c66affSColin Finck                 Temp = L"Display adapter";
723c2c66affSColin Finck             else if (wcsstr(DeviceData->HardwareIDs, L"PNP0A0") != 0)
724c2c66affSColin Finck                 Temp = L"Bus controller";
725c2c66affSColin Finck             else if (wcsstr(DeviceData->HardwareIDs, L"PNP0E0") != 0)
726c2c66affSColin Finck                 Temp = L"PCMCIA controller";
727c2c66affSColin Finck             else if (wcsstr(DeviceData->HardwareIDs, L"PNP0F") != 0)
728c2c66affSColin Finck                 Temp = L"Mouse device";
729c2c66affSColin Finck             else if (wcsstr(DeviceData->HardwareIDs, L"PNP8") != 0)
730c2c66affSColin Finck                 Temp = L"Network adapter";
731c2c66affSColin Finck             else if (wcsstr(DeviceData->HardwareIDs, L"PNPA0") != 0)
732c2c66affSColin Finck                 Temp = L"SCSI controller";
733c2c66affSColin Finck             else if (wcsstr(DeviceData->HardwareIDs, L"PNPB0") != 0)
734c2c66affSColin Finck                 Temp = L"Multimedia device";
735c2c66affSColin Finck             else if (wcsstr(DeviceData->HardwareIDs, L"PNPC00") != 0)
736c2c66affSColin Finck                 Temp = L"Modem";
737c2c66affSColin Finck             else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0C") != 0)
738c2c66affSColin Finck                 Temp = L"Power Button";
739c2c66affSColin Finck             else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0E") != 0)
740c2c66affSColin Finck                 Temp = L"Sleep Button";
741c2c66affSColin Finck             else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0D") != 0)
742c2c66affSColin Finck                 Temp = L"Lid Switch";
743c2c66affSColin Finck             else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C09") != 0)
744c2c66affSColin Finck                 Temp = L"ACPI Embedded Controller";
745c2c66affSColin Finck             else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0B") != 0)
746c2c66affSColin Finck                 Temp = L"ACPI Fan";
747c2c66affSColin Finck             else if (wcsstr(DeviceData->HardwareIDs, L"PNP0A03") != 0 ||
748c2c66affSColin Finck                      wcsstr(DeviceData->HardwareIDs, L"PNP0A08") != 0)
749c2c66affSColin Finck                 Temp = L"PCI Root Bridge";
750c2c66affSColin Finck             else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0A") != 0)
751c2c66affSColin Finck                 Temp = L"ACPI Battery";
752c2c66affSColin Finck             else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0F") != 0)
753c2c66affSColin Finck                 Temp = L"PCI Interrupt Link";
754c2c66affSColin Finck             else if (wcsstr(DeviceData->HardwareIDs, L"ACPI_PWR") != 0)
755c2c66affSColin Finck                 Temp = L"ACPI Power Resource";
756c2c66affSColin Finck             else if (wcsstr(DeviceData->HardwareIDs, L"Processor") != 0)
757c2c66affSColin Finck             {
758c2c66affSColin Finck                 if (ProcessorNameString != NULL)
759c2c66affSColin Finck                     Temp = ProcessorNameString;
760c2c66affSColin Finck                 else
761c2c66affSColin Finck                     Temp = L"Processor";
762c2c66affSColin Finck             }
763c2c66affSColin Finck             else if (wcsstr(DeviceData->HardwareIDs, L"ThermalZone") != 0)
764c2c66affSColin Finck                 Temp = L"ACPI Thermal Zone";
765c2c66affSColin Finck             else if (wcsstr(DeviceData->HardwareIDs, L"ACPI0002") != 0)
766c2c66affSColin Finck                 Temp = L"Smart Battery";
767c2c66affSColin Finck             else if (wcsstr(DeviceData->HardwareIDs, L"ACPI0003") != 0)
768c2c66affSColin Finck                 Temp = L"AC Adapter";
769c2c66affSColin Finck             /* Simply checking if AcpiHandle is NULL eliminates the need to check
770c2c66affSColin Finck              * for the 4 different names that ACPI knows the fixed feature button as internally
771c2c66affSColin Finck              */
772c2c66affSColin Finck             else if (!DeviceData->AcpiHandle)
773c2c66affSColin Finck                 Temp = L"ACPI Fixed Feature Button";
774c2c66affSColin Finck             else
775c2c66affSColin Finck                 Temp = L"Other ACPI device";
776c2c66affSColin Finck 
777c2c66affSColin Finck             Buffer = ExAllocatePoolWithTag(PagedPool, (wcslen(Temp) + 1) * sizeof(WCHAR), 'IpcA');
778c2c66affSColin Finck 
779c2c66affSColin Finck             if (!Buffer) {
780c2c66affSColin Finck                 status = STATUS_INSUFFICIENT_RESOURCES;
781c2c66affSColin Finck                 break;
782c2c66affSColin Finck             }
783c2c66affSColin Finck 
784c2c66affSColin Finck             RtlCopyMemory (Buffer, Temp, (wcslen(Temp) + 1) * sizeof(WCHAR));
785c2c66affSColin Finck 
786c2c66affSColin Finck             DPRINT("\tDeviceTextDescription :%ws\n", Buffer);
787c2c66affSColin Finck 
788c2c66affSColin Finck             Irp->IoStatus.Information = (ULONG_PTR) Buffer;
789c2c66affSColin Finck             status = STATUS_SUCCESS;
790c2c66affSColin Finck         }
791c2c66affSColin Finck         break;
792c2c66affSColin Finck 
793c2c66affSColin Finck     default:
794c2c66affSColin Finck         break;
795c2c66affSColin Finck     }
796c2c66affSColin Finck 
797c2c66affSColin Finck     return status;
798c2c66affSColin Finck 
799c2c66affSColin Finck }
800c2c66affSColin Finck 
801c2c66affSColin Finck NTSTATUS
Bus_PDO_QueryResources(PPDO_DEVICE_DATA DeviceData,PIRP Irp)802c2c66affSColin Finck Bus_PDO_QueryResources(
803c2c66affSColin Finck      PPDO_DEVICE_DATA     DeviceData,
804c2c66affSColin Finck       PIRP   Irp )
805c2c66affSColin Finck {
806c2c66affSColin Finck     ULONG NumberOfResources = 0;
807c2c66affSColin Finck     PCM_RESOURCE_LIST ResourceList;
808c2c66affSColin Finck     PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor;
809c2c66affSColin Finck     ACPI_STATUS AcpiStatus;
810c2c66affSColin Finck     ACPI_BUFFER Buffer;
811c2c66affSColin Finck     ACPI_RESOURCE* resource;
812c2c66affSColin Finck     ULONG ResourceListSize;
813c2c66affSColin Finck     ULONG i;
814c2c66affSColin Finck     ULONGLONG BusNumber;
815c2c66affSColin Finck     struct acpi_device *device;
816c2c66affSColin Finck 
817c2c66affSColin Finck     if (!DeviceData->AcpiHandle)
818c2c66affSColin Finck     {
819c2c66affSColin Finck         return Irp->IoStatus.Status;
820c2c66affSColin Finck     }
821c2c66affSColin Finck 
822c2c66affSColin Finck     /* A bus number resource is not included in the list of current resources
823c2c66affSColin Finck      * for the root PCI bus so we manually query one here and if we find it
824c2c66affSColin Finck      * we create a resource list and add a bus number descriptor to it */
825c2c66affSColin Finck     if (wcsstr(DeviceData->HardwareIDs, L"PNP0A03") != 0 ||
826c2c66affSColin Finck         wcsstr(DeviceData->HardwareIDs, L"PNP0A08") != 0)
827c2c66affSColin Finck     {
828c2c66affSColin Finck         acpi_bus_get_device(DeviceData->AcpiHandle, &device);
829c2c66affSColin Finck 
830c2c66affSColin Finck         AcpiStatus = acpi_evaluate_integer(DeviceData->AcpiHandle, "_BBN", NULL, &BusNumber);
831c2c66affSColin Finck         if (AcpiStatus != AE_OK)
832c2c66affSColin Finck         {
833c2c66affSColin Finck #if 0
834c2c66affSColin Finck             if (device->flags.unique_id)
835c2c66affSColin Finck             {
836c2c66affSColin Finck                 /* FIXME: Try the unique ID */
837c2c66affSColin Finck             }
838c2c66affSColin Finck             else
839c2c66affSColin Finck #endif
840c2c66affSColin Finck             {
841c2c66affSColin Finck                 BusNumber = 0;
842c2c66affSColin Finck                 DPRINT1("Failed to find a bus number\n");
843c2c66affSColin Finck             }
844c2c66affSColin Finck         }
845c2c66affSColin Finck         else
846c2c66affSColin Finck         {
847c2c66affSColin Finck             DPRINT("Using _BBN for bus number\n");
848c2c66affSColin Finck         }
849c2c66affSColin Finck 
850c2c66affSColin Finck         DPRINT("Found PCI root hub: %d\n", BusNumber);
851c2c66affSColin Finck 
852c2c66affSColin Finck         ResourceListSize = sizeof(CM_RESOURCE_LIST);
853c2c66affSColin Finck         ResourceList = ExAllocatePoolWithTag(PagedPool, ResourceListSize, 'RpcA');
854c2c66affSColin Finck         if (!ResourceList)
855c2c66affSColin Finck             return STATUS_INSUFFICIENT_RESOURCES;
856c2c66affSColin Finck 
857c2c66affSColin Finck         ResourceList->Count = 1;
858c2c66affSColin Finck         ResourceList->List[0].InterfaceType = Internal;
859c2c66affSColin Finck         ResourceList->List[0].BusNumber = 0;
860c2c66affSColin Finck         ResourceList->List[0].PartialResourceList.Version = 1;
861c2c66affSColin Finck         ResourceList->List[0].PartialResourceList.Revision = 1;
862c2c66affSColin Finck         ResourceList->List[0].PartialResourceList.Count = 1;
863c2c66affSColin Finck         ResourceDescriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
864c2c66affSColin Finck 
865c2c66affSColin Finck         ResourceDescriptor->Type = CmResourceTypeBusNumber;
866c2c66affSColin Finck         ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
867c2c66affSColin Finck         ResourceDescriptor->u.BusNumber.Start = BusNumber;
868c2c66affSColin Finck         ResourceDescriptor->u.BusNumber.Length = 1;
869c2c66affSColin Finck 
870c2c66affSColin Finck         Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
871c2c66affSColin Finck         return STATUS_SUCCESS;
872c2c66affSColin Finck     }
873c2c66affSColin Finck 
874c2c66affSColin Finck     /* Get current resources */
875c2c66affSColin Finck     Buffer.Length = 0;
876c2c66affSColin Finck     AcpiStatus = AcpiGetCurrentResources(DeviceData->AcpiHandle, &Buffer);
877c2c66affSColin Finck     if ((!ACPI_SUCCESS(AcpiStatus) && AcpiStatus != AE_BUFFER_OVERFLOW) ||
878c2c66affSColin Finck         Buffer.Length == 0)
879c2c66affSColin Finck     {
880c2c66affSColin Finck       return Irp->IoStatus.Status;
881c2c66affSColin Finck     }
882c2c66affSColin Finck 
883c2c66affSColin Finck     Buffer.Pointer = ExAllocatePoolWithTag(PagedPool, Buffer.Length, 'BpcA');
884c2c66affSColin Finck     if (!Buffer.Pointer)
885c2c66affSColin Finck       return STATUS_INSUFFICIENT_RESOURCES;
886c2c66affSColin Finck 
887c2c66affSColin Finck     AcpiStatus = AcpiGetCurrentResources(DeviceData->AcpiHandle, &Buffer);
888c2c66affSColin Finck     if (!ACPI_SUCCESS(AcpiStatus))
889c2c66affSColin Finck     {
890c2c66affSColin Finck       DPRINT1("AcpiGetCurrentResources #2 failed (0x%x)\n", AcpiStatus);
891c2c66affSColin Finck       ASSERT(FALSE);
892c2c66affSColin Finck       return STATUS_UNSUCCESSFUL;
893c2c66affSColin Finck     }
894c2c66affSColin Finck 
895c2c66affSColin Finck     resource= Buffer.Pointer;
896c2c66affSColin Finck     /* Count number of resources */
897c2c66affSColin Finck     while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG)
898c2c66affSColin Finck     {
899c2c66affSColin Finck         switch (resource->Type)
900c2c66affSColin Finck         {
901c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
902c2c66affSColin Finck             {
903c2c66affSColin Finck                 ACPI_RESOURCE_EXTENDED_IRQ *irq_data = (ACPI_RESOURCE_EXTENDED_IRQ*) &resource->Data;
904c2c66affSColin Finck                 if (irq_data->ProducerConsumer == ACPI_PRODUCER)
905c2c66affSColin Finck                     break;
906c2c66affSColin Finck                 NumberOfResources += irq_data->InterruptCount;
907c2c66affSColin Finck                 break;
908c2c66affSColin Finck             }
909c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_IRQ:
910c2c66affSColin Finck             {
911c2c66affSColin Finck                 ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
912c2c66affSColin Finck                 NumberOfResources += irq_data->InterruptCount;
913c2c66affSColin Finck                 break;
914c2c66affSColin Finck             }
915c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_DMA:
916c2c66affSColin Finck             {
917c2c66affSColin Finck                 ACPI_RESOURCE_DMA *dma_data = (ACPI_RESOURCE_DMA*) &resource->Data;
918c2c66affSColin Finck                 NumberOfResources += dma_data->ChannelCount;
919c2c66affSColin Finck                 break;
920c2c66affSColin Finck             }
921c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_ADDRESS16:
922c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_ADDRESS32:
923c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_ADDRESS64:
924c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
925c2c66affSColin Finck             {
926c2c66affSColin Finck                 ACPI_RESOURCE_ADDRESS *addr_res = (ACPI_RESOURCE_ADDRESS*) &resource->Data;
927c2c66affSColin Finck                 if (addr_res->ProducerConsumer == ACPI_PRODUCER)
928c2c66affSColin Finck                     break;
929c2c66affSColin Finck                 NumberOfResources++;
930c2c66affSColin Finck                 break;
931c2c66affSColin Finck             }
932c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_MEMORY24:
933c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_MEMORY32:
934c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
935c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_FIXED_IO:
936c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_IO:
937c2c66affSColin Finck             {
938c2c66affSColin Finck                 NumberOfResources++;
939c2c66affSColin Finck                 break;
940c2c66affSColin Finck             }
941c2c66affSColin Finck             default:
942c2c66affSColin Finck             {
943c2c66affSColin Finck                 DPRINT1("Unknown resource type: %d\n", resource->Type);
944c2c66affSColin Finck                 break;
945c2c66affSColin Finck             }
946c2c66affSColin Finck         }
947c2c66affSColin Finck         resource = ACPI_NEXT_RESOURCE(resource);
948c2c66affSColin Finck     }
949c2c66affSColin Finck 
950c2c66affSColin Finck     /* Allocate memory */
951c2c66affSColin Finck     ResourceListSize = sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * (NumberOfResources - 1);
952c2c66affSColin Finck     ResourceList = ExAllocatePoolWithTag(PagedPool, ResourceListSize, 'RpcA');
953c2c66affSColin Finck 
954c2c66affSColin Finck     if (!ResourceList)
955c2c66affSColin Finck     {
956c2c66affSColin Finck         ExFreePoolWithTag(Buffer.Pointer, 'BpcA');
957c2c66affSColin Finck         return STATUS_INSUFFICIENT_RESOURCES;
958c2c66affSColin Finck     }
959c2c66affSColin Finck     ResourceList->Count = 1;
960c2c66affSColin Finck     ResourceList->List[0].InterfaceType = Internal; /* FIXME */
961c2c66affSColin Finck     ResourceList->List[0].BusNumber = 0; /* We're the only ACPI bus device in the system */
962c2c66affSColin Finck     ResourceList->List[0].PartialResourceList.Version = 1;
963c2c66affSColin Finck     ResourceList->List[0].PartialResourceList.Revision = 1;
964c2c66affSColin Finck     ResourceList->List[0].PartialResourceList.Count = NumberOfResources;
965c2c66affSColin Finck     ResourceDescriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
966c2c66affSColin Finck 
967c2c66affSColin Finck     /* Fill resources list structure */
968c2c66affSColin Finck         resource = Buffer.Pointer;
969c2c66affSColin Finck     while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG)
970c2c66affSColin Finck     {
971c2c66affSColin Finck         switch (resource->Type)
972c2c66affSColin Finck         {
973c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
974c2c66affSColin Finck             {
975c2c66affSColin Finck                 ACPI_RESOURCE_EXTENDED_IRQ *irq_data = (ACPI_RESOURCE_EXTENDED_IRQ*) &resource->Data;
976c2c66affSColin Finck                 if (irq_data->ProducerConsumer == ACPI_PRODUCER)
977c2c66affSColin Finck                     break;
978c2c66affSColin Finck                 for (i = 0; i < irq_data->InterruptCount; i++)
979c2c66affSColin Finck                 {
980c2c66affSColin Finck                     ResourceDescriptor->Type = CmResourceTypeInterrupt;
981c2c66affSColin Finck 
982c2c66affSColin Finck                     ResourceDescriptor->ShareDisposition =
9839d53c935SThomas Faber                     (irq_data->Shareable == ACPI_SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
984c2c66affSColin Finck                     ResourceDescriptor->Flags =
985c2c66affSColin Finck                     (irq_data->Triggering == ACPI_LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
986c2c66affSColin Finck                     ResourceDescriptor->u.Interrupt.Level =
987c2c66affSColin Finck                     ResourceDescriptor->u.Interrupt.Vector = irq_data->Interrupts[i];
988c2c66affSColin Finck                     ResourceDescriptor->u.Interrupt.Affinity = (KAFFINITY)(-1);
989c2c66affSColin Finck 
990c2c66affSColin Finck                     ResourceDescriptor++;
991c2c66affSColin Finck                 }
992c2c66affSColin Finck                 break;
993c2c66affSColin Finck             }
994c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_IRQ:
995c2c66affSColin Finck             {
996c2c66affSColin Finck                 ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
997c2c66affSColin Finck                 for (i = 0; i < irq_data->InterruptCount; i++)
998c2c66affSColin Finck                 {
999c2c66affSColin Finck                     ResourceDescriptor->Type = CmResourceTypeInterrupt;
1000c2c66affSColin Finck 
1001c2c66affSColin Finck                     ResourceDescriptor->ShareDisposition =
10029d53c935SThomas Faber                     (irq_data->Shareable == ACPI_SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
1003c2c66affSColin Finck                     ResourceDescriptor->Flags =
1004c2c66affSColin Finck                     (irq_data->Triggering == ACPI_LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
1005c2c66affSColin Finck                     ResourceDescriptor->u.Interrupt.Level =
1006c2c66affSColin Finck                     ResourceDescriptor->u.Interrupt.Vector = irq_data->Interrupts[i];
1007c2c66affSColin Finck                     ResourceDescriptor->u.Interrupt.Affinity = (KAFFINITY)(-1);
1008c2c66affSColin Finck 
1009c2c66affSColin Finck                     ResourceDescriptor++;
1010c2c66affSColin Finck                 }
1011c2c66affSColin Finck                 break;
1012c2c66affSColin Finck             }
1013c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_DMA:
1014c2c66affSColin Finck             {
1015c2c66affSColin Finck                 ACPI_RESOURCE_DMA *dma_data = (ACPI_RESOURCE_DMA*) &resource->Data;
1016c2c66affSColin Finck                 for (i = 0; i < dma_data->ChannelCount; i++)
1017c2c66affSColin Finck                 {
1018c2c66affSColin Finck                     ResourceDescriptor->Type = CmResourceTypeDma;
1019c2c66affSColin Finck                     ResourceDescriptor->Flags = 0;
1020c2c66affSColin Finck                     switch (dma_data->Type)
1021c2c66affSColin Finck                     {
1022c2c66affSColin Finck                         case ACPI_TYPE_A: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_A; break;
1023c2c66affSColin Finck                         case ACPI_TYPE_B: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_B; break;
1024c2c66affSColin Finck                         case ACPI_TYPE_F: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_F; break;
1025c2c66affSColin Finck                     }
1026c2c66affSColin Finck                     if (dma_data->BusMaster == ACPI_BUS_MASTER)
1027c2c66affSColin Finck                         ResourceDescriptor->Flags |= CM_RESOURCE_DMA_BUS_MASTER;
1028c2c66affSColin Finck                     switch (dma_data->Transfer)
1029c2c66affSColin Finck                     {
1030c2c66affSColin Finck                         case ACPI_TRANSFER_8: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_8; break;
1031c2c66affSColin Finck                         case ACPI_TRANSFER_16: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_16; break;
1032c2c66affSColin Finck                         case ACPI_TRANSFER_8_16: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_8_AND_16; break;
1033c2c66affSColin Finck                     }
1034c2c66affSColin Finck                     ResourceDescriptor->u.Dma.Channel = dma_data->Channels[i];
1035c2c66affSColin Finck 
1036c2c66affSColin Finck                     ResourceDescriptor++;
1037c2c66affSColin Finck                 }
1038c2c66affSColin Finck                 break;
1039c2c66affSColin Finck             }
1040c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_IO:
1041c2c66affSColin Finck             {
1042c2c66affSColin Finck                 ACPI_RESOURCE_IO *io_data = (ACPI_RESOURCE_IO*) &resource->Data;
1043c2c66affSColin Finck                 ResourceDescriptor->Type = CmResourceTypePort;
1044c2c66affSColin Finck                 ResourceDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
1045c2c66affSColin Finck                 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
1046c2c66affSColin Finck                 if (io_data->IoDecode == ACPI_DECODE_16)
1047c2c66affSColin Finck                     ResourceDescriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
1048c2c66affSColin Finck                 else
1049c2c66affSColin Finck                     ResourceDescriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
1050c2c66affSColin Finck                 ResourceDescriptor->u.Port.Start.QuadPart = io_data->Minimum;
1051c2c66affSColin Finck                 ResourceDescriptor->u.Port.Length = io_data->AddressLength;
1052c2c66affSColin Finck 
1053c2c66affSColin Finck                 ResourceDescriptor++;
1054c2c66affSColin Finck                 break;
1055c2c66affSColin Finck             }
1056c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_FIXED_IO:
1057c2c66affSColin Finck             {
1058c2c66affSColin Finck                 ACPI_RESOURCE_FIXED_IO *io_data = (ACPI_RESOURCE_FIXED_IO*) &resource->Data;
1059c2c66affSColin Finck                 ResourceDescriptor->Type = CmResourceTypePort;
1060c2c66affSColin Finck                 ResourceDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
1061c2c66affSColin Finck                 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
1062c2c66affSColin Finck                 ResourceDescriptor->u.Port.Start.QuadPart = io_data->Address;
1063c2c66affSColin Finck                 ResourceDescriptor->u.Port.Length = io_data->AddressLength;
1064c2c66affSColin Finck 
1065c2c66affSColin Finck                 ResourceDescriptor++;
1066c2c66affSColin Finck                 break;
1067c2c66affSColin Finck             }
1068c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_ADDRESS16:
1069c2c66affSColin Finck             {
1070c2c66affSColin Finck                 ACPI_RESOURCE_ADDRESS16 *addr16_data = (ACPI_RESOURCE_ADDRESS16*) &resource->Data;
1071c2c66affSColin Finck                 if (addr16_data->ProducerConsumer == ACPI_PRODUCER)
1072c2c66affSColin Finck                     break;
1073c2c66affSColin Finck                 if (addr16_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1074c2c66affSColin Finck                 {
1075c2c66affSColin Finck                     ResourceDescriptor->Type = CmResourceTypeBusNumber;
1076c2c66affSColin Finck                     ResourceDescriptor->ShareDisposition = CmResourceShareShared;
1077c2c66affSColin Finck                     ResourceDescriptor->Flags = 0;
1078c2c66affSColin Finck                     ResourceDescriptor->u.BusNumber.Start = addr16_data->Address.Minimum;
1079c2c66affSColin Finck                     ResourceDescriptor->u.BusNumber.Length = addr16_data->Address.AddressLength;
1080c2c66affSColin Finck                 }
1081c2c66affSColin Finck                 else if (addr16_data->ResourceType == ACPI_IO_RANGE)
1082c2c66affSColin Finck                 {
1083c2c66affSColin Finck                     ResourceDescriptor->Type = CmResourceTypePort;
1084c2c66affSColin Finck                     ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1085c2c66affSColin Finck                     ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
1086c2c66affSColin Finck                     if (addr16_data->Decode == ACPI_POS_DECODE)
1087c2c66affSColin Finck                         ResourceDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1088c2c66affSColin Finck                     ResourceDescriptor->u.Port.Start.QuadPart = addr16_data->Address.Minimum;
1089c2c66affSColin Finck                     ResourceDescriptor->u.Port.Length = addr16_data->Address.AddressLength;
1090c2c66affSColin Finck                 }
1091c2c66affSColin Finck                 else
1092c2c66affSColin Finck                 {
1093c2c66affSColin Finck                     ResourceDescriptor->Type = CmResourceTypeMemory;
1094c2c66affSColin Finck                     ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1095c2c66affSColin Finck                     ResourceDescriptor->Flags = 0;
1096c2c66affSColin Finck                     if (addr16_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1097c2c66affSColin Finck                         ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1098c2c66affSColin Finck                     else
1099c2c66affSColin Finck                         ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1100c2c66affSColin Finck                     switch (addr16_data->Info.Mem.Caching)
1101c2c66affSColin Finck                     {
1102c2c66affSColin Finck                         case ACPI_CACHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1103c2c66affSColin Finck                         case ACPI_WRITE_COMBINING_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1104c2c66affSColin Finck                         case ACPI_PREFETCHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1105c2c66affSColin Finck                     }
1106c2c66affSColin Finck                     ResourceDescriptor->u.Memory.Start.QuadPart = addr16_data->Address.Minimum;
1107c2c66affSColin Finck                     ResourceDescriptor->u.Memory.Length = addr16_data->Address.AddressLength;
1108c2c66affSColin Finck                 }
1109c2c66affSColin Finck                 ResourceDescriptor++;
1110c2c66affSColin Finck                 break;
1111c2c66affSColin Finck             }
1112c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_ADDRESS32:
1113c2c66affSColin Finck             {
1114c2c66affSColin Finck                 ACPI_RESOURCE_ADDRESS32 *addr32_data = (ACPI_RESOURCE_ADDRESS32*) &resource->Data;
1115c2c66affSColin Finck                 if (addr32_data->ProducerConsumer == ACPI_PRODUCER)
1116c2c66affSColin Finck                     break;
1117c2c66affSColin Finck                 if (addr32_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1118c2c66affSColin Finck                 {
1119c2c66affSColin Finck                     ResourceDescriptor->Type = CmResourceTypeBusNumber;
1120c2c66affSColin Finck                     ResourceDescriptor->ShareDisposition = CmResourceShareShared;
1121c2c66affSColin Finck                     ResourceDescriptor->Flags = 0;
1122c2c66affSColin Finck                     ResourceDescriptor->u.BusNumber.Start = addr32_data->Address.Minimum;
1123c2c66affSColin Finck                     ResourceDescriptor->u.BusNumber.Length = addr32_data->Address.AddressLength;
1124c2c66affSColin Finck                 }
1125c2c66affSColin Finck                 else if (addr32_data->ResourceType == ACPI_IO_RANGE)
1126c2c66affSColin Finck                 {
1127c2c66affSColin Finck                     ResourceDescriptor->Type = CmResourceTypePort;
1128c2c66affSColin Finck                     ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1129c2c66affSColin Finck                     ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
1130c2c66affSColin Finck                     if (addr32_data->Decode == ACPI_POS_DECODE)
1131c2c66affSColin Finck                         ResourceDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1132c2c66affSColin Finck                     ResourceDescriptor->u.Port.Start.QuadPart = addr32_data->Address.Minimum;
1133c2c66affSColin Finck                     ResourceDescriptor->u.Port.Length = addr32_data->Address.AddressLength;
1134c2c66affSColin Finck                 }
1135c2c66affSColin Finck                 else
1136c2c66affSColin Finck                 {
1137c2c66affSColin Finck                     ResourceDescriptor->Type = CmResourceTypeMemory;
1138c2c66affSColin Finck                     ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1139c2c66affSColin Finck                     ResourceDescriptor->Flags = 0;
1140c2c66affSColin Finck                     if (addr32_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1141c2c66affSColin Finck                         ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1142c2c66affSColin Finck                     else
1143c2c66affSColin Finck                         ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1144c2c66affSColin Finck                     switch (addr32_data->Info.Mem.Caching)
1145c2c66affSColin Finck                     {
1146c2c66affSColin Finck                         case ACPI_CACHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1147c2c66affSColin Finck                         case ACPI_WRITE_COMBINING_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1148c2c66affSColin Finck                         case ACPI_PREFETCHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1149c2c66affSColin Finck                     }
1150c2c66affSColin Finck                     ResourceDescriptor->u.Memory.Start.QuadPart = addr32_data->Address.Minimum;
1151c2c66affSColin Finck                     ResourceDescriptor->u.Memory.Length = addr32_data->Address.AddressLength;
1152c2c66affSColin Finck                 }
1153c2c66affSColin Finck                 ResourceDescriptor++;
1154c2c66affSColin Finck                 break;
1155c2c66affSColin Finck             }
1156c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_ADDRESS64:
1157c2c66affSColin Finck             {
1158c2c66affSColin Finck                 ACPI_RESOURCE_ADDRESS64 *addr64_data = (ACPI_RESOURCE_ADDRESS64*) &resource->Data;
1159c2c66affSColin Finck                 if (addr64_data->ProducerConsumer == ACPI_PRODUCER)
1160c2c66affSColin Finck                     break;
1161c2c66affSColin Finck                 if (addr64_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1162c2c66affSColin Finck                 {
1163c2c66affSColin Finck                     DPRINT1("64-bit bus address is not supported!\n");
1164c2c66affSColin Finck                     ResourceDescriptor->Type = CmResourceTypeBusNumber;
1165c2c66affSColin Finck                     ResourceDescriptor->ShareDisposition = CmResourceShareShared;
1166c2c66affSColin Finck                     ResourceDescriptor->Flags = 0;
1167c2c66affSColin Finck                     ResourceDescriptor->u.BusNumber.Start = (ULONG)addr64_data->Address.Minimum;
1168c2c66affSColin Finck                     ResourceDescriptor->u.BusNumber.Length = addr64_data->Address.AddressLength;
1169c2c66affSColin Finck                 }
1170c2c66affSColin Finck                 else if (addr64_data->ResourceType == ACPI_IO_RANGE)
1171c2c66affSColin Finck                 {
1172c2c66affSColin Finck                     ResourceDescriptor->Type = CmResourceTypePort;
1173c2c66affSColin Finck                     ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1174c2c66affSColin Finck                     ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
1175c2c66affSColin Finck                     if (addr64_data->Decode == ACPI_POS_DECODE)
1176c2c66affSColin Finck                         ResourceDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1177c2c66affSColin Finck                     ResourceDescriptor->u.Port.Start.QuadPart = addr64_data->Address.Minimum;
1178c2c66affSColin Finck                     ResourceDescriptor->u.Port.Length = addr64_data->Address.AddressLength;
1179c2c66affSColin Finck                 }
1180c2c66affSColin Finck                 else
1181c2c66affSColin Finck                 {
1182c2c66affSColin Finck                     ResourceDescriptor->Type = CmResourceTypeMemory;
1183c2c66affSColin Finck                     ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1184c2c66affSColin Finck                     ResourceDescriptor->Flags = 0;
1185c2c66affSColin Finck                     if (addr64_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1186c2c66affSColin Finck                         ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1187c2c66affSColin Finck                     else
1188c2c66affSColin Finck                         ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1189c2c66affSColin Finck                     switch (addr64_data->Info.Mem.Caching)
1190c2c66affSColin Finck                     {
1191c2c66affSColin Finck                         case ACPI_CACHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1192c2c66affSColin Finck                         case ACPI_WRITE_COMBINING_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1193c2c66affSColin Finck                         case ACPI_PREFETCHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1194c2c66affSColin Finck                     }
1195c2c66affSColin Finck                     ResourceDescriptor->u.Memory.Start.QuadPart = addr64_data->Address.Minimum;
1196c2c66affSColin Finck                     ResourceDescriptor->u.Memory.Length = addr64_data->Address.AddressLength;
1197c2c66affSColin Finck                 }
1198c2c66affSColin Finck                 ResourceDescriptor++;
1199c2c66affSColin Finck                 break;
1200c2c66affSColin Finck             }
1201c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
1202c2c66affSColin Finck             {
1203c2c66affSColin Finck                 ACPI_RESOURCE_EXTENDED_ADDRESS64 *addr64_data = (ACPI_RESOURCE_EXTENDED_ADDRESS64*) &resource->Data;
1204c2c66affSColin Finck                 if (addr64_data->ProducerConsumer == ACPI_PRODUCER)
1205c2c66affSColin Finck                     break;
1206c2c66affSColin Finck                 if (addr64_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1207c2c66affSColin Finck                 {
1208c2c66affSColin Finck                     DPRINT1("64-bit bus address is not supported!\n");
1209c2c66affSColin Finck                     ResourceDescriptor->Type = CmResourceTypeBusNumber;
1210c2c66affSColin Finck                     ResourceDescriptor->ShareDisposition = CmResourceShareShared;
1211c2c66affSColin Finck                     ResourceDescriptor->Flags = 0;
1212c2c66affSColin Finck                     ResourceDescriptor->u.BusNumber.Start = (ULONG)addr64_data->Address.Minimum;
1213c2c66affSColin Finck                     ResourceDescriptor->u.BusNumber.Length = addr64_data->Address.AddressLength;
1214c2c66affSColin Finck                 }
1215c2c66affSColin Finck                 else if (addr64_data->ResourceType == ACPI_IO_RANGE)
1216c2c66affSColin Finck                 {
1217c2c66affSColin Finck                     ResourceDescriptor->Type = CmResourceTypePort;
1218c2c66affSColin Finck                     ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1219c2c66affSColin Finck                     ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
1220c2c66affSColin Finck                     if (addr64_data->Decode == ACPI_POS_DECODE)
1221c2c66affSColin Finck                         ResourceDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1222c2c66affSColin Finck                     ResourceDescriptor->u.Port.Start.QuadPart = addr64_data->Address.Minimum;
1223c2c66affSColin Finck                     ResourceDescriptor->u.Port.Length = addr64_data->Address.AddressLength;
1224c2c66affSColin Finck                 }
1225c2c66affSColin Finck                 else
1226c2c66affSColin Finck                 {
1227c2c66affSColin Finck                     ResourceDescriptor->Type = CmResourceTypeMemory;
1228c2c66affSColin Finck                     ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1229c2c66affSColin Finck                     ResourceDescriptor->Flags = 0;
1230c2c66affSColin Finck                     if (addr64_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1231c2c66affSColin Finck                         ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1232c2c66affSColin Finck                     else
1233c2c66affSColin Finck                         ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1234c2c66affSColin Finck                     switch (addr64_data->Info.Mem.Caching)
1235c2c66affSColin Finck                     {
1236c2c66affSColin Finck                         case ACPI_CACHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1237c2c66affSColin Finck                         case ACPI_WRITE_COMBINING_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1238c2c66affSColin Finck                         case ACPI_PREFETCHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1239c2c66affSColin Finck                     }
1240c2c66affSColin Finck                     ResourceDescriptor->u.Memory.Start.QuadPart = addr64_data->Address.Minimum;
1241c2c66affSColin Finck                     ResourceDescriptor->u.Memory.Length = addr64_data->Address.AddressLength;
1242c2c66affSColin Finck                 }
1243c2c66affSColin Finck                 ResourceDescriptor++;
1244c2c66affSColin Finck                 break;
1245c2c66affSColin Finck             }
1246c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_MEMORY24:
1247c2c66affSColin Finck             {
1248c2c66affSColin Finck                 ACPI_RESOURCE_MEMORY24 *mem24_data = (ACPI_RESOURCE_MEMORY24*) &resource->Data;
1249c2c66affSColin Finck                 ResourceDescriptor->Type = CmResourceTypeMemory;
1250c2c66affSColin Finck                 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1251c2c66affSColin Finck                 ResourceDescriptor->Flags = CM_RESOURCE_MEMORY_24;
1252c2c66affSColin Finck                 if (mem24_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
1253c2c66affSColin Finck                     ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1254c2c66affSColin Finck                 else
1255c2c66affSColin Finck                     ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1256c2c66affSColin Finck                 ResourceDescriptor->u.Memory.Start.QuadPart = mem24_data->Minimum;
1257c2c66affSColin Finck                 ResourceDescriptor->u.Memory.Length = mem24_data->AddressLength;
1258c2c66affSColin Finck 
1259c2c66affSColin Finck                 ResourceDescriptor++;
1260c2c66affSColin Finck                 break;
1261c2c66affSColin Finck             }
1262c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_MEMORY32:
1263c2c66affSColin Finck             {
1264c2c66affSColin Finck                 ACPI_RESOURCE_MEMORY32 *mem32_data = (ACPI_RESOURCE_MEMORY32*) &resource->Data;
1265c2c66affSColin Finck                 ResourceDescriptor->Type = CmResourceTypeMemory;
1266c2c66affSColin Finck                 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1267c2c66affSColin Finck                 ResourceDescriptor->Flags = 0;
1268c2c66affSColin Finck                 if (mem32_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
1269c2c66affSColin Finck                     ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1270c2c66affSColin Finck                 else
1271c2c66affSColin Finck                     ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1272c2c66affSColin Finck                 ResourceDescriptor->u.Memory.Start.QuadPart = mem32_data->Minimum;
1273c2c66affSColin Finck                 ResourceDescriptor->u.Memory.Length = mem32_data->AddressLength;
1274c2c66affSColin Finck 
1275c2c66affSColin Finck                 ResourceDescriptor++;
1276c2c66affSColin Finck                 break;
1277c2c66affSColin Finck             }
1278c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
1279c2c66affSColin Finck             {
1280c2c66affSColin Finck                 ACPI_RESOURCE_FIXED_MEMORY32 *memfixed32_data = (ACPI_RESOURCE_FIXED_MEMORY32*) &resource->Data;
1281c2c66affSColin Finck                 ResourceDescriptor->Type = CmResourceTypeMemory;
1282c2c66affSColin Finck                 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1283c2c66affSColin Finck                 ResourceDescriptor->Flags = 0;
1284c2c66affSColin Finck                 if (memfixed32_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
1285c2c66affSColin Finck                     ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1286c2c66affSColin Finck                 else
1287c2c66affSColin Finck                     ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1288c2c66affSColin Finck                 ResourceDescriptor->u.Memory.Start.QuadPart = memfixed32_data->Address;
1289c2c66affSColin Finck                 ResourceDescriptor->u.Memory.Length = memfixed32_data->AddressLength;
1290c2c66affSColin Finck 
1291c2c66affSColin Finck                 ResourceDescriptor++;
1292c2c66affSColin Finck                 break;
1293c2c66affSColin Finck             }
1294c2c66affSColin Finck             default:
1295c2c66affSColin Finck             {
1296c2c66affSColin Finck                 break;
1297c2c66affSColin Finck             }
1298c2c66affSColin Finck         }
1299c2c66affSColin Finck         resource = ACPI_NEXT_RESOURCE(resource);
1300c2c66affSColin Finck     }
1301c2c66affSColin Finck 
1302c2c66affSColin Finck     ExFreePoolWithTag(Buffer.Pointer, 'BpcA');
1303c2c66affSColin Finck     Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
1304c2c66affSColin Finck     return STATUS_SUCCESS;
1305c2c66affSColin Finck }
13069bcd8350SThomas Faber #endif /* UNIT_TEST */
1307c2c66affSColin Finck 
1308c2c66affSColin Finck NTSTATUS
Bus_PDO_QueryResourceRequirements(PPDO_DEVICE_DATA DeviceData,PIRP Irp)1309c2c66affSColin Finck Bus_PDO_QueryResourceRequirements(
1310c2c66affSColin Finck      PPDO_DEVICE_DATA     DeviceData,
1311c2c66affSColin Finck       PIRP   Irp )
1312c2c66affSColin Finck {
1313c2c66affSColin Finck     ULONG NumberOfResources = 0;
1314c2c66affSColin Finck     ACPI_STATUS AcpiStatus;
1315c2c66affSColin Finck     ACPI_BUFFER Buffer;
1316c2c66affSColin Finck     ACPI_RESOURCE* resource;
1317c2c66affSColin Finck     ULONG i, RequirementsListSize;
1318c2c66affSColin Finck     PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
1319c2c66affSColin Finck     PIO_RESOURCE_DESCRIPTOR RequirementDescriptor;
1320c2c66affSColin Finck     BOOLEAN CurrentRes = FALSE;
132115226572SThomas Faber     BOOLEAN SeenStartDependent;
1322c2c66affSColin Finck 
1323c2c66affSColin Finck     PAGED_CODE ();
1324c2c66affSColin Finck 
1325c2c66affSColin Finck     if (!DeviceData->AcpiHandle)
1326c2c66affSColin Finck     {
1327c2c66affSColin Finck         return Irp->IoStatus.Status;
1328c2c66affSColin Finck     }
1329c2c66affSColin Finck 
1330c2c66affSColin Finck     /* Handle the PCI root manually */
1331c2c66affSColin Finck     if (wcsstr(DeviceData->HardwareIDs, L"PNP0A03") != 0 ||
1332c2c66affSColin Finck         wcsstr(DeviceData->HardwareIDs, L"PNP0A08") != 0)
1333c2c66affSColin Finck     {
1334c2c66affSColin Finck         return Irp->IoStatus.Status;
1335c2c66affSColin Finck     }
1336c2c66affSColin Finck 
1337c2c66affSColin Finck     /* Get current resources */
1338c2c66affSColin Finck     while (TRUE)
1339c2c66affSColin Finck     {
1340c2c66affSColin Finck         Buffer.Length = 0;
1341c2c66affSColin Finck         if (CurrentRes)
1342c2c66affSColin Finck         AcpiStatus = AcpiGetCurrentResources(DeviceData->AcpiHandle, &Buffer);
1343c2c66affSColin Finck         else
1344c2c66affSColin Finck             AcpiStatus = AcpiGetPossibleResources(DeviceData->AcpiHandle, &Buffer);
1345c2c66affSColin Finck         if ((!ACPI_SUCCESS(AcpiStatus) && AcpiStatus != AE_BUFFER_OVERFLOW) ||
1346c2c66affSColin Finck             Buffer.Length == 0)
1347c2c66affSColin Finck         {
1348c2c66affSColin Finck             if (!CurrentRes)
1349c2c66affSColin Finck                 CurrentRes = TRUE;
1350c2c66affSColin Finck             else
1351c2c66affSColin Finck                 return Irp->IoStatus.Status;
1352c2c66affSColin Finck         }
1353c2c66affSColin Finck         else
1354c2c66affSColin Finck             break;
1355c2c66affSColin Finck     }
1356c2c66affSColin Finck 
1357c2c66affSColin Finck     Buffer.Pointer = ExAllocatePoolWithTag(PagedPool, Buffer.Length, 'BpcA');
1358c2c66affSColin Finck     if (!Buffer.Pointer)
1359c2c66affSColin Finck       return STATUS_INSUFFICIENT_RESOURCES;
1360c2c66affSColin Finck 
1361c2c66affSColin Finck     if (CurrentRes)
1362c2c66affSColin Finck         AcpiStatus = AcpiGetCurrentResources(DeviceData->AcpiHandle, &Buffer);
1363c2c66affSColin Finck     else
1364c2c66affSColin Finck         AcpiStatus = AcpiGetPossibleResources(DeviceData->AcpiHandle, &Buffer);
1365c2c66affSColin Finck     if (!ACPI_SUCCESS(AcpiStatus))
1366c2c66affSColin Finck     {
1367c2c66affSColin Finck       DPRINT1("AcpiGetCurrentResources #2 failed (0x%x)\n", AcpiStatus);
1368c2c66affSColin Finck       ASSERT(FALSE);
1369c2c66affSColin Finck       return STATUS_UNSUCCESSFUL;
1370c2c66affSColin Finck     }
1371c2c66affSColin Finck 
137215226572SThomas Faber     SeenStartDependent = FALSE;
1373c2c66affSColin Finck     resource = Buffer.Pointer;
1374c2c66affSColin Finck     /* Count number of resources */
137515226572SThomas Faber     while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG && resource->Type != ACPI_RESOURCE_TYPE_END_DEPENDENT)
1376c2c66affSColin Finck     {
137715226572SThomas Faber         if (resource->Type == ACPI_RESOURCE_TYPE_START_DEPENDENT)
137815226572SThomas Faber         {
137915226572SThomas Faber             if (SeenStartDependent)
138015226572SThomas Faber             {
138115226572SThomas Faber                 break;
138215226572SThomas Faber             }
138315226572SThomas Faber             SeenStartDependent = TRUE;
138415226572SThomas Faber         }
1385c2c66affSColin Finck         switch (resource->Type)
1386c2c66affSColin Finck         {
1387c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
1388c2c66affSColin Finck             {
1389c2c66affSColin Finck                 ACPI_RESOURCE_EXTENDED_IRQ *irq_data = (ACPI_RESOURCE_EXTENDED_IRQ*) &resource->Data;
1390c2c66affSColin Finck                 if (irq_data->ProducerConsumer == ACPI_PRODUCER)
1391c2c66affSColin Finck                     break;
1392c2c66affSColin Finck                 NumberOfResources += irq_data->InterruptCount;
1393c2c66affSColin Finck                 break;
1394c2c66affSColin Finck             }
1395c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_IRQ:
1396c2c66affSColin Finck             {
1397c2c66affSColin Finck                 ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
1398c2c66affSColin Finck                 NumberOfResources += irq_data->InterruptCount;
1399c2c66affSColin Finck                 break;
1400c2c66affSColin Finck             }
1401c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_DMA:
1402c2c66affSColin Finck             {
1403c2c66affSColin Finck                 ACPI_RESOURCE_DMA *dma_data = (ACPI_RESOURCE_DMA*) &resource->Data;
1404c2c66affSColin Finck                 NumberOfResources += dma_data->ChannelCount;
1405c2c66affSColin Finck                 break;
1406c2c66affSColin Finck             }
1407c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_ADDRESS16:
1408c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_ADDRESS32:
1409c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_ADDRESS64:
1410c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
1411c2c66affSColin Finck             {
1412c2c66affSColin Finck                 ACPI_RESOURCE_ADDRESS *res_addr = (ACPI_RESOURCE_ADDRESS*) &resource->Data;
1413c2c66affSColin Finck                 if (res_addr->ProducerConsumer == ACPI_PRODUCER)
1414c2c66affSColin Finck                     break;
1415c2c66affSColin Finck                 NumberOfResources++;
1416c2c66affSColin Finck                 break;
1417c2c66affSColin Finck             }
1418c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_MEMORY24:
1419c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_MEMORY32:
1420c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
1421c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_FIXED_IO:
1422c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_IO:
1423c2c66affSColin Finck             {
1424c2c66affSColin Finck                 NumberOfResources++;
1425c2c66affSColin Finck                 break;
1426c2c66affSColin Finck             }
1427c2c66affSColin Finck             default:
1428c2c66affSColin Finck             {
1429c2c66affSColin Finck                 break;
1430c2c66affSColin Finck             }
1431c2c66affSColin Finck         }
1432c2c66affSColin Finck         resource = ACPI_NEXT_RESOURCE(resource);
1433c2c66affSColin Finck     }
1434c2c66affSColin Finck 
1435c2c66affSColin Finck     RequirementsListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) + sizeof(IO_RESOURCE_DESCRIPTOR) * (NumberOfResources - 1);
1436c2c66affSColin Finck     RequirementsList = ExAllocatePoolWithTag(PagedPool, RequirementsListSize, 'RpcA');
1437c2c66affSColin Finck 
1438c2c66affSColin Finck     if (!RequirementsList)
1439c2c66affSColin Finck     {
1440c2c66affSColin Finck         ExFreePoolWithTag(Buffer.Pointer, 'BpcA');
1441c2c66affSColin Finck         return STATUS_INSUFFICIENT_RESOURCES;
1442c2c66affSColin Finck     }
1443c2c66affSColin Finck     RequirementsList->ListSize = RequirementsListSize;
1444c2c66affSColin Finck     RequirementsList->InterfaceType = Internal;
1445c2c66affSColin Finck     RequirementsList->BusNumber = 0;
1446c2c66affSColin Finck     RequirementsList->SlotNumber = 0; /* Not used by WDM drivers */
1447c2c66affSColin Finck     RequirementsList->AlternativeLists = 1;
1448c2c66affSColin Finck     RequirementsList->List[0].Version = 1;
1449c2c66affSColin Finck     RequirementsList->List[0].Revision = 1;
1450c2c66affSColin Finck     RequirementsList->List[0].Count = NumberOfResources;
1451c2c66affSColin Finck     RequirementDescriptor = RequirementsList->List[0].Descriptors;
1452c2c66affSColin Finck 
1453c2c66affSColin Finck     /* Fill resources list structure */
145415226572SThomas Faber     SeenStartDependent = FALSE;
1455c2c66affSColin Finck     resource = Buffer.Pointer;
1456c2c66affSColin Finck     while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG && resource->Type != ACPI_RESOURCE_TYPE_END_DEPENDENT)
1457c2c66affSColin Finck     {
145815226572SThomas Faber         if (resource->Type == ACPI_RESOURCE_TYPE_START_DEPENDENT)
145915226572SThomas Faber         {
146015226572SThomas Faber             if (SeenStartDependent)
146115226572SThomas Faber             {
146215226572SThomas Faber                 break;
146315226572SThomas Faber             }
146415226572SThomas Faber             SeenStartDependent = TRUE;
146515226572SThomas Faber         }
1466c2c66affSColin Finck         switch (resource->Type)
1467c2c66affSColin Finck         {
1468c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
1469c2c66affSColin Finck             {
147028be285dSThomas Faber                 ACPI_RESOURCE_EXTENDED_IRQ *irq_data = &resource->Data.ExtendedIrq;
1471c2c66affSColin Finck                 if (irq_data->ProducerConsumer == ACPI_PRODUCER)
1472c2c66affSColin Finck                     break;
1473c2c66affSColin Finck                 for (i = 0; i < irq_data->InterruptCount; i++)
1474c2c66affSColin Finck                 {
1475c2c66affSColin Finck                     RequirementDescriptor->Option = (i == 0) ? IO_RESOURCE_PREFERRED : IO_RESOURCE_ALTERNATIVE;
1476c2c66affSColin Finck                     RequirementDescriptor->Type = CmResourceTypeInterrupt;
14779d53c935SThomas Faber                     RequirementDescriptor->ShareDisposition = (irq_data->Shareable == ACPI_SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
1478c2c66affSColin Finck                     RequirementDescriptor->Flags =(irq_data->Triggering == ACPI_LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
1479c2c66affSColin Finck                     RequirementDescriptor->u.Interrupt.MinimumVector =
1480c2c66affSColin Finck                     RequirementDescriptor->u.Interrupt.MaximumVector = irq_data->Interrupts[i];
1481c2c66affSColin Finck 
1482c2c66affSColin Finck                     RequirementDescriptor++;
1483c2c66affSColin Finck                 }
1484c2c66affSColin Finck                 break;
1485c2c66affSColin Finck             }
1486c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_IRQ:
1487c2c66affSColin Finck             {
148828be285dSThomas Faber                 ACPI_RESOURCE_IRQ *irq_data = &resource->Data.Irq;
1489c2c66affSColin Finck                 for (i = 0; i < irq_data->InterruptCount; i++)
1490c2c66affSColin Finck                 {
1491c2c66affSColin Finck                     RequirementDescriptor->Option = (i == 0) ? IO_RESOURCE_PREFERRED : IO_RESOURCE_ALTERNATIVE;
1492c2c66affSColin Finck                     RequirementDescriptor->Type = CmResourceTypeInterrupt;
14939d53c935SThomas Faber                     RequirementDescriptor->ShareDisposition = (irq_data->Shareable == ACPI_SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
1494c2c66affSColin Finck                     RequirementDescriptor->Flags =(irq_data->Triggering == ACPI_LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
1495c2c66affSColin Finck                     RequirementDescriptor->u.Interrupt.MinimumVector =
1496c2c66affSColin Finck                     RequirementDescriptor->u.Interrupt.MaximumVector = irq_data->Interrupts[i];
1497c2c66affSColin Finck 
1498c2c66affSColin Finck                     RequirementDescriptor++;
1499c2c66affSColin Finck                 }
1500c2c66affSColin Finck                 break;
1501c2c66affSColin Finck             }
1502c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_DMA:
1503c2c66affSColin Finck             {
150428be285dSThomas Faber                 ACPI_RESOURCE_DMA *dma_data = &resource->Data.Dma;
1505c2c66affSColin Finck                 for (i = 0; i < dma_data->ChannelCount; i++)
1506c2c66affSColin Finck                 {
1507c2c66affSColin Finck                     RequirementDescriptor->Type = CmResourceTypeDma;
1508c2c66affSColin Finck                     RequirementDescriptor->Flags = 0;
1509c2c66affSColin Finck                     switch (dma_data->Type)
1510c2c66affSColin Finck                     {
1511c2c66affSColin Finck                         case ACPI_TYPE_A: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_A; break;
1512c2c66affSColin Finck                         case ACPI_TYPE_B: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_B; break;
1513c2c66affSColin Finck                         case ACPI_TYPE_F: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_F; break;
1514c2c66affSColin Finck                     }
1515c2c66affSColin Finck                     if (dma_data->BusMaster == ACPI_BUS_MASTER)
1516c2c66affSColin Finck                         RequirementDescriptor->Flags |= CM_RESOURCE_DMA_BUS_MASTER;
1517c2c66affSColin Finck                     switch (dma_data->Transfer)
1518c2c66affSColin Finck                     {
1519c2c66affSColin Finck                         case ACPI_TRANSFER_8: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_8; break;
1520c2c66affSColin Finck                         case ACPI_TRANSFER_16: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_16; break;
1521c2c66affSColin Finck                         case ACPI_TRANSFER_8_16: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_8_AND_16; break;
1522c2c66affSColin Finck                     }
1523c2c66affSColin Finck 
1524c2c66affSColin Finck                     RequirementDescriptor->Option = (i == 0) ? IO_RESOURCE_PREFERRED : IO_RESOURCE_ALTERNATIVE;
1525c2c66affSColin Finck                     RequirementDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
1526c2c66affSColin Finck                     RequirementDescriptor->u.Dma.MinimumChannel =
1527c2c66affSColin Finck                     RequirementDescriptor->u.Dma.MaximumChannel = dma_data->Channels[i];
1528c2c66affSColin Finck                     RequirementDescriptor++;
1529c2c66affSColin Finck                 }
1530c2c66affSColin Finck                 break;
1531c2c66affSColin Finck             }
1532c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_IO:
1533c2c66affSColin Finck             {
153428be285dSThomas Faber                 ACPI_RESOURCE_IO *io_data = &resource->Data.Io;
1535c2c66affSColin Finck                 RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
1536c2c66affSColin Finck                 if (io_data->IoDecode == ACPI_DECODE_16)
1537c2c66affSColin Finck                     RequirementDescriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
1538c2c66affSColin Finck                 else
1539c2c66affSColin Finck                     RequirementDescriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
1540c2c66affSColin Finck                 RequirementDescriptor->u.Port.Length = io_data->AddressLength;
1541c2c66affSColin Finck                 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1542c2c66affSColin Finck                 RequirementDescriptor->Type = CmResourceTypePort;
1543c2c66affSColin Finck                 RequirementDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
1544c2c66affSColin Finck                 RequirementDescriptor->u.Port.Alignment = io_data->Alignment;
1545c2c66affSColin Finck                 RequirementDescriptor->u.Port.MinimumAddress.QuadPart = io_data->Minimum;
1546c2c66affSColin Finck                 RequirementDescriptor->u.Port.MaximumAddress.QuadPart = io_data->Maximum + io_data->AddressLength - 1;
1547c2c66affSColin Finck 
1548c2c66affSColin Finck                 RequirementDescriptor++;
1549c2c66affSColin Finck                 break;
1550c2c66affSColin Finck             }
1551c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_FIXED_IO:
1552c2c66affSColin Finck             {
155328be285dSThomas Faber                 ACPI_RESOURCE_FIXED_IO *io_data = &resource->Data.FixedIo;
1554c2c66affSColin Finck                 RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
1555c2c66affSColin Finck                 RequirementDescriptor->u.Port.Length = io_data->AddressLength;
1556c2c66affSColin Finck                 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1557c2c66affSColin Finck                 RequirementDescriptor->Type = CmResourceTypePort;
1558c2c66affSColin Finck                 RequirementDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
1559c2c66affSColin Finck                 RequirementDescriptor->u.Port.Alignment = 1;
1560c2c66affSColin Finck                 RequirementDescriptor->u.Port.MinimumAddress.QuadPart = io_data->Address;
1561c2c66affSColin Finck                 RequirementDescriptor->u.Port.MaximumAddress.QuadPart = io_data->Address + io_data->AddressLength - 1;
1562c2c66affSColin Finck 
1563c2c66affSColin Finck                 RequirementDescriptor++;
1564c2c66affSColin Finck                 break;
1565c2c66affSColin Finck             }
1566c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_ADDRESS16:
1567c2c66affSColin Finck             {
156828be285dSThomas Faber                 ACPI_RESOURCE_ADDRESS16 *addr16_data = &resource->Data.Address16;
1569c2c66affSColin Finck                 if (addr16_data->ProducerConsumer == ACPI_PRODUCER)
1570c2c66affSColin Finck                     break;
1571c2c66affSColin Finck                 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1572c2c66affSColin Finck                 if (addr16_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1573c2c66affSColin Finck                 {
1574c2c66affSColin Finck                     RequirementDescriptor->Type = CmResourceTypeBusNumber;
1575c2c66affSColin Finck                     RequirementDescriptor->ShareDisposition = CmResourceShareShared;
1576c2c66affSColin Finck                     RequirementDescriptor->Flags = 0;
1577c2c66affSColin Finck                     RequirementDescriptor->u.BusNumber.MinBusNumber = addr16_data->Address.Minimum;
1578c2c66affSColin Finck                     RequirementDescriptor->u.BusNumber.MaxBusNumber = addr16_data->Address.Maximum + addr16_data->Address.AddressLength - 1;
1579c2c66affSColin Finck                     RequirementDescriptor->u.BusNumber.Length = addr16_data->Address.AddressLength;
1580c2c66affSColin Finck                 }
1581c2c66affSColin Finck                 else if (addr16_data->ResourceType == ACPI_IO_RANGE)
1582c2c66affSColin Finck                 {
1583c2c66affSColin Finck                     RequirementDescriptor->Type = CmResourceTypePort;
1584c2c66affSColin Finck                     RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1585c2c66affSColin Finck                     RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
1586c2c66affSColin Finck                     if (addr16_data->Decode == ACPI_POS_DECODE)
1587c2c66affSColin Finck                         RequirementDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1588c2c66affSColin Finck                     RequirementDescriptor->u.Port.MinimumAddress.QuadPart = addr16_data->Address.Minimum;
1589c2c66affSColin Finck                     RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr16_data->Address.Maximum + addr16_data->Address.AddressLength - 1;
1590c2c66affSColin Finck                     RequirementDescriptor->u.Port.Length = addr16_data->Address.AddressLength;
1591c2c66affSColin Finck                 }
1592c2c66affSColin Finck                 else
1593c2c66affSColin Finck                 {
1594c2c66affSColin Finck                     RequirementDescriptor->Type = CmResourceTypeMemory;
1595c2c66affSColin Finck                     RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1596c2c66affSColin Finck                     RequirementDescriptor->Flags = 0;
1597c2c66affSColin Finck                     if (addr16_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1598c2c66affSColin Finck                         RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1599c2c66affSColin Finck                     else
1600c2c66affSColin Finck                         RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1601c2c66affSColin Finck                     switch (addr16_data->Info.Mem.Caching)
1602c2c66affSColin Finck                     {
1603c2c66affSColin Finck                         case ACPI_CACHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1604c2c66affSColin Finck                         case ACPI_WRITE_COMBINING_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1605c2c66affSColin Finck                         case ACPI_PREFETCHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1606c2c66affSColin Finck                     }
1607c2c66affSColin Finck                     RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = addr16_data->Address.Minimum;
1608c2c66affSColin Finck                     RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr16_data->Address.Maximum + addr16_data->Address.AddressLength - 1;
1609c2c66affSColin Finck                     RequirementDescriptor->u.Memory.Length = addr16_data->Address.AddressLength;
1610c2c66affSColin Finck                 }
1611c2c66affSColin Finck                 RequirementDescriptor++;
1612c2c66affSColin Finck                 break;
1613c2c66affSColin Finck             }
1614c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_ADDRESS32:
1615c2c66affSColin Finck             {
161628be285dSThomas Faber                 ACPI_RESOURCE_ADDRESS32 *addr32_data = &resource->Data.Address32;
1617c2c66affSColin Finck                 if (addr32_data->ProducerConsumer == ACPI_PRODUCER)
1618c2c66affSColin Finck                     break;
1619c2c66affSColin Finck                 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1620c2c66affSColin Finck                 if (addr32_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1621c2c66affSColin Finck                 {
1622c2c66affSColin Finck                     RequirementDescriptor->Type = CmResourceTypeBusNumber;
1623c2c66affSColin Finck                     RequirementDescriptor->ShareDisposition = CmResourceShareShared;
1624c2c66affSColin Finck                     RequirementDescriptor->Flags = 0;
1625c2c66affSColin Finck                     RequirementDescriptor->u.BusNumber.MinBusNumber = addr32_data->Address.Minimum;
1626c2c66affSColin Finck                     RequirementDescriptor->u.BusNumber.MaxBusNumber = addr32_data->Address.Maximum + addr32_data->Address.AddressLength - 1;
1627c2c66affSColin Finck                     RequirementDescriptor->u.BusNumber.Length = addr32_data->Address.AddressLength;
1628c2c66affSColin Finck                 }
1629c2c66affSColin Finck                 else if (addr32_data->ResourceType == ACPI_IO_RANGE)
1630c2c66affSColin Finck                 {
1631c2c66affSColin Finck                     RequirementDescriptor->Type = CmResourceTypePort;
1632c2c66affSColin Finck                     RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1633c2c66affSColin Finck                     RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
1634c2c66affSColin Finck                     if (addr32_data->Decode == ACPI_POS_DECODE)
1635c2c66affSColin Finck                         RequirementDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1636c2c66affSColin Finck                     RequirementDescriptor->u.Port.MinimumAddress.QuadPart = addr32_data->Address.Minimum;
1637c2c66affSColin Finck                     RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr32_data->Address.Maximum + addr32_data->Address.AddressLength - 1;
1638c2c66affSColin Finck                     RequirementDescriptor->u.Port.Length = addr32_data->Address.AddressLength;
1639c2c66affSColin Finck                 }
1640c2c66affSColin Finck                 else
1641c2c66affSColin Finck                 {
1642c2c66affSColin Finck                     RequirementDescriptor->Type = CmResourceTypeMemory;
1643c2c66affSColin Finck                     RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1644c2c66affSColin Finck                     RequirementDescriptor->Flags = 0;
1645c2c66affSColin Finck                     if (addr32_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1646c2c66affSColin Finck                         RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1647c2c66affSColin Finck                     else
1648c2c66affSColin Finck                         RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1649c2c66affSColin Finck                     switch (addr32_data->Info.Mem.Caching)
1650c2c66affSColin Finck                     {
1651c2c66affSColin Finck                         case ACPI_CACHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1652c2c66affSColin Finck                         case ACPI_WRITE_COMBINING_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1653c2c66affSColin Finck                         case ACPI_PREFETCHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1654c2c66affSColin Finck                     }
1655c2c66affSColin Finck                     RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = addr32_data->Address.Minimum;
1656c2c66affSColin Finck                     RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr32_data->Address.Maximum + addr32_data->Address.AddressLength - 1;
1657c2c66affSColin Finck                     RequirementDescriptor->u.Memory.Length = addr32_data->Address.AddressLength;
1658c2c66affSColin Finck                 }
1659c2c66affSColin Finck                 RequirementDescriptor++;
1660c2c66affSColin Finck                 break;
1661c2c66affSColin Finck             }
1662c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_ADDRESS64:
1663c2c66affSColin Finck             {
166428be285dSThomas Faber                 ACPI_RESOURCE_ADDRESS64 *addr64_data = &resource->Data.Address64;
1665c2c66affSColin Finck                 if (addr64_data->ProducerConsumer == ACPI_PRODUCER)
1666c2c66affSColin Finck                     break;
1667c2c66affSColin Finck                 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1668c2c66affSColin Finck                 if (addr64_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1669c2c66affSColin Finck                 {
1670c2c66affSColin Finck                     DPRINT1("64-bit bus address is not supported!\n");
1671c2c66affSColin Finck                     RequirementDescriptor->Type = CmResourceTypeBusNumber;
1672c2c66affSColin Finck                     RequirementDescriptor->ShareDisposition = CmResourceShareShared;
1673c2c66affSColin Finck                     RequirementDescriptor->Flags = 0;
1674c2c66affSColin Finck                     RequirementDescriptor->u.BusNumber.MinBusNumber = (ULONG)addr64_data->Address.Minimum;
1675c2c66affSColin Finck                     RequirementDescriptor->u.BusNumber.MaxBusNumber = (ULONG)addr64_data->Address.Maximum + addr64_data->Address.AddressLength - 1;
1676c2c66affSColin Finck                     RequirementDescriptor->u.BusNumber.Length = addr64_data->Address.AddressLength;
1677c2c66affSColin Finck                 }
1678c2c66affSColin Finck                 else if (addr64_data->ResourceType == ACPI_IO_RANGE)
1679c2c66affSColin Finck                 {
1680c2c66affSColin Finck                     RequirementDescriptor->Type = CmResourceTypePort;
1681c2c66affSColin Finck                     RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1682c2c66affSColin Finck                     RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
1683c2c66affSColin Finck                     if (addr64_data->Decode == ACPI_POS_DECODE)
1684c2c66affSColin Finck                         RequirementDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1685c2c66affSColin Finck                     RequirementDescriptor->u.Port.MinimumAddress.QuadPart = addr64_data->Address.Minimum;
1686c2c66affSColin Finck                     RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr64_data->Address.Maximum + addr64_data->Address.AddressLength - 1;
1687c2c66affSColin Finck                     RequirementDescriptor->u.Port.Length = addr64_data->Address.AddressLength;
1688c2c66affSColin Finck                 }
1689c2c66affSColin Finck                 else
1690c2c66affSColin Finck                 {
1691c2c66affSColin Finck                     RequirementDescriptor->Type = CmResourceTypeMemory;
1692c2c66affSColin Finck                     RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1693c2c66affSColin Finck                     RequirementDescriptor->Flags = 0;
1694c2c66affSColin Finck                     if (addr64_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1695c2c66affSColin Finck                         RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1696c2c66affSColin Finck                     else
1697c2c66affSColin Finck                         RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1698c2c66affSColin Finck                     switch (addr64_data->Info.Mem.Caching)
1699c2c66affSColin Finck                     {
1700c2c66affSColin Finck                         case ACPI_CACHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1701c2c66affSColin Finck                         case ACPI_WRITE_COMBINING_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1702c2c66affSColin Finck                         case ACPI_PREFETCHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1703c2c66affSColin Finck                     }
1704c2c66affSColin Finck                     RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = addr64_data->Address.Minimum;
1705c2c66affSColin Finck                     RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr64_data->Address.Maximum + addr64_data->Address.AddressLength - 1;
1706c2c66affSColin Finck                     RequirementDescriptor->u.Memory.Length = addr64_data->Address.AddressLength;
1707c2c66affSColin Finck                 }
1708c2c66affSColin Finck                 RequirementDescriptor++;
1709c2c66affSColin Finck                 break;
1710c2c66affSColin Finck             }
1711c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
1712c2c66affSColin Finck             {
171328be285dSThomas Faber                 ACPI_RESOURCE_EXTENDED_ADDRESS64 *addr64_data = &resource->Data.ExtAddress64;
1714c2c66affSColin Finck                 if (addr64_data->ProducerConsumer == ACPI_PRODUCER)
1715c2c66affSColin Finck                     break;
1716c2c66affSColin Finck                 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1717c2c66affSColin Finck                 if (addr64_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1718c2c66affSColin Finck                 {
1719c2c66affSColin Finck                     DPRINT1("64-bit bus address is not supported!\n");
1720c2c66affSColin Finck                     RequirementDescriptor->Type = CmResourceTypeBusNumber;
1721c2c66affSColin Finck                     RequirementDescriptor->ShareDisposition = CmResourceShareShared;
1722c2c66affSColin Finck                     RequirementDescriptor->Flags = 0;
1723c2c66affSColin Finck                     RequirementDescriptor->u.BusNumber.MinBusNumber = (ULONG)addr64_data->Address.Minimum;
1724c2c66affSColin Finck                     RequirementDescriptor->u.BusNumber.MaxBusNumber = (ULONG)addr64_data->Address.Maximum + addr64_data->Address.AddressLength - 1;
1725c2c66affSColin Finck                     RequirementDescriptor->u.BusNumber.Length = addr64_data->Address.AddressLength;
1726c2c66affSColin Finck                 }
1727c2c66affSColin Finck                 else if (addr64_data->ResourceType == ACPI_IO_RANGE)
1728c2c66affSColin Finck                 {
1729c2c66affSColin Finck                     RequirementDescriptor->Type = CmResourceTypePort;
1730c2c66affSColin Finck                     RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1731c2c66affSColin Finck                     RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
1732c2c66affSColin Finck                     if (addr64_data->Decode == ACPI_POS_DECODE)
1733c2c66affSColin Finck                         RequirementDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1734c2c66affSColin Finck                     RequirementDescriptor->u.Port.MinimumAddress.QuadPart = addr64_data->Address.Minimum;
1735c2c66affSColin Finck                     RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr64_data->Address.Maximum + addr64_data->Address.AddressLength - 1;
1736c2c66affSColin Finck                     RequirementDescriptor->u.Port.Length = addr64_data->Address.AddressLength;
1737c2c66affSColin Finck                 }
1738c2c66affSColin Finck                 else
1739c2c66affSColin Finck                 {
1740c2c66affSColin Finck                     RequirementDescriptor->Type = CmResourceTypeMemory;
1741c2c66affSColin Finck                     RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1742c2c66affSColin Finck                     RequirementDescriptor->Flags = 0;
1743c2c66affSColin Finck                     if (addr64_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1744c2c66affSColin Finck                         RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1745c2c66affSColin Finck                     else
1746c2c66affSColin Finck                         RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1747c2c66affSColin Finck                     switch (addr64_data->Info.Mem.Caching)
1748c2c66affSColin Finck                     {
1749c2c66affSColin Finck                         case ACPI_CACHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1750c2c66affSColin Finck                         case ACPI_WRITE_COMBINING_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1751c2c66affSColin Finck                         case ACPI_PREFETCHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1752c2c66affSColin Finck                     }
1753c2c66affSColin Finck                     RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = addr64_data->Address.Minimum;
1754c2c66affSColin Finck                     RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr64_data->Address.Maximum + addr64_data->Address.AddressLength - 1;
1755c2c66affSColin Finck                     RequirementDescriptor->u.Memory.Length = addr64_data->Address.AddressLength;
1756c2c66affSColin Finck                 }
1757c2c66affSColin Finck                 RequirementDescriptor++;
1758c2c66affSColin Finck                 break;
1759c2c66affSColin Finck             }
1760c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_MEMORY24:
1761c2c66affSColin Finck             {
176228be285dSThomas Faber                 ACPI_RESOURCE_MEMORY24 *mem24_data = &resource->Data.Memory24;
1763c2c66affSColin Finck                 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1764c2c66affSColin Finck                 RequirementDescriptor->Type = CmResourceTypeMemory;
1765c2c66affSColin Finck                 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1766c2c66affSColin Finck                 RequirementDescriptor->Flags = CM_RESOURCE_MEMORY_24;
1767c2c66affSColin Finck                 if (mem24_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
1768c2c66affSColin Finck                     RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1769c2c66affSColin Finck                 else
1770c2c66affSColin Finck                     RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1771c2c66affSColin Finck                 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = mem24_data->Minimum;
1772c2c66affSColin Finck                 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = mem24_data->Maximum + mem24_data->AddressLength - 1;
1773c2c66affSColin Finck                 RequirementDescriptor->u.Memory.Length = mem24_data->AddressLength;
1774c2c66affSColin Finck 
1775c2c66affSColin Finck                 RequirementDescriptor++;
1776c2c66affSColin Finck                 break;
1777c2c66affSColin Finck             }
1778c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_MEMORY32:
1779c2c66affSColin Finck             {
178028be285dSThomas Faber                 ACPI_RESOURCE_MEMORY32 *mem32_data = &resource->Data.Memory32;
1781c2c66affSColin Finck                 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1782c2c66affSColin Finck                 RequirementDescriptor->Type = CmResourceTypeMemory;
1783c2c66affSColin Finck                 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1784c2c66affSColin Finck                 RequirementDescriptor->Flags = 0;
1785c2c66affSColin Finck                 if (mem32_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
1786c2c66affSColin Finck                     RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1787c2c66affSColin Finck                 else
1788c2c66affSColin Finck                     RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1789c2c66affSColin Finck                 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = mem32_data->Minimum;
1790c2c66affSColin Finck                 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = mem32_data->Maximum + mem32_data->AddressLength - 1;
1791c2c66affSColin Finck                 RequirementDescriptor->u.Memory.Length = mem32_data->AddressLength;
1792c2c66affSColin Finck 
1793c2c66affSColin Finck                 RequirementDescriptor++;
1794c2c66affSColin Finck                 break;
1795c2c66affSColin Finck             }
1796c2c66affSColin Finck             case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
1797c2c66affSColin Finck             {
179828be285dSThomas Faber                 ACPI_RESOURCE_FIXED_MEMORY32 *fixedmem32_data = &resource->Data.FixedMemory32;
1799c2c66affSColin Finck                 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1800c2c66affSColin Finck                 RequirementDescriptor->Type = CmResourceTypeMemory;
1801c2c66affSColin Finck                 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1802c2c66affSColin Finck                 RequirementDescriptor->Flags = 0;
1803c2c66affSColin Finck                 if (fixedmem32_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
1804c2c66affSColin Finck                     RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1805c2c66affSColin Finck                 else
1806c2c66affSColin Finck                     RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1807c2c66affSColin Finck                 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = fixedmem32_data->Address;
1808c2c66affSColin Finck                 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = fixedmem32_data->Address + fixedmem32_data->AddressLength - 1;
1809c2c66affSColin Finck                 RequirementDescriptor->u.Memory.Length = fixedmem32_data->AddressLength;
1810c2c66affSColin Finck 
1811c2c66affSColin Finck                 RequirementDescriptor++;
1812c2c66affSColin Finck                 break;
1813c2c66affSColin Finck             }
1814c2c66affSColin Finck             default:
1815c2c66affSColin Finck             {
1816c2c66affSColin Finck                 break;
1817c2c66affSColin Finck             }
1818c2c66affSColin Finck         }
1819c2c66affSColin Finck         resource = ACPI_NEXT_RESOURCE(resource);
1820c2c66affSColin Finck     }
1821c2c66affSColin Finck     ExFreePoolWithTag(Buffer.Pointer, 'BpcA');
1822c2c66affSColin Finck 
1823c2c66affSColin Finck     Irp->IoStatus.Information = (ULONG_PTR)RequirementsList;
1824c2c66affSColin Finck 
1825c2c66affSColin Finck     return STATUS_SUCCESS;
1826c2c66affSColin Finck }
1827c2c66affSColin Finck 
18289bcd8350SThomas Faber #ifndef UNIT_TEST
1829c2c66affSColin Finck NTSTATUS
Bus_PDO_QueryDeviceRelations(PPDO_DEVICE_DATA DeviceData,PIRP Irp)1830c2c66affSColin Finck Bus_PDO_QueryDeviceRelations(
1831c2c66affSColin Finck      PPDO_DEVICE_DATA     DeviceData,
1832c2c66affSColin Finck       PIRP   Irp )
1833c2c66affSColin Finck /*++
1834c2c66affSColin Finck 
1835c2c66affSColin Finck Routine Description:
1836c2c66affSColin Finck 
1837c2c66affSColin Finck     The PnP Manager sends this IRP to gather information about
1838c2c66affSColin Finck     devices with a relationship to the specified device.
1839c2c66affSColin Finck     Bus drivers must handle this request for TargetDeviceRelation
1840c2c66affSColin Finck     for their child devices (child PDOs).
1841c2c66affSColin Finck 
1842c2c66affSColin Finck     If a driver returns relations in response to this IRP,
1843c2c66affSColin Finck     it allocates a DEVICE_RELATIONS structure from paged
1844c2c66affSColin Finck     memory containing a count and the appropriate number of
1845c2c66affSColin Finck     device object pointers. The PnP Manager frees the structure
1846c2c66affSColin Finck     when it is no longer needed. If a driver replaces a
1847c2c66affSColin Finck     DEVICE_RELATIONS structure allocated by another driver,
1848c2c66affSColin Finck     it must free the previous structure.
1849c2c66affSColin Finck 
1850c2c66affSColin Finck     A driver must reference the PDO of any device that it
1851c2c66affSColin Finck     reports in this IRP (ObReferenceObject). The PnP Manager
1852c2c66affSColin Finck     removes the reference when appropriate.
1853c2c66affSColin Finck 
1854c2c66affSColin Finck Arguments:
1855c2c66affSColin Finck 
1856c2c66affSColin Finck     DeviceData - Pointer to the PDO's device extension.
1857c2c66affSColin Finck     Irp          - Pointer to the irp.
1858c2c66affSColin Finck 
1859c2c66affSColin Finck Return Value:
1860c2c66affSColin Finck 
1861c2c66affSColin Finck     NT STATUS
1862c2c66affSColin Finck 
1863c2c66affSColin Finck --*/
1864c2c66affSColin Finck {
1865c2c66affSColin Finck 
1866c2c66affSColin Finck     PIO_STACK_LOCATION   stack;
1867c2c66affSColin Finck     PDEVICE_RELATIONS deviceRelations;
1868c2c66affSColin Finck     NTSTATUS status;
1869c2c66affSColin Finck 
1870c2c66affSColin Finck     PAGED_CODE ();
1871c2c66affSColin Finck 
1872c2c66affSColin Finck     stack = IoGetCurrentIrpStackLocation (Irp);
1873c2c66affSColin Finck 
1874c2c66affSColin Finck     switch (stack->Parameters.QueryDeviceRelations.Type) {
1875c2c66affSColin Finck 
1876c2c66affSColin Finck     case TargetDeviceRelation:
1877c2c66affSColin Finck 
1878c2c66affSColin Finck         deviceRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information;
1879c2c66affSColin Finck         if (deviceRelations) {
1880c2c66affSColin Finck             //
1881c2c66affSColin Finck             // Only PDO can handle this request. Somebody above
1882c2c66affSColin Finck             // is not playing by rule.
1883c2c66affSColin Finck             //
18847d6bda16SSerge Gautherie             ASSERTMSG("Someone above is handling TargetDeviceRelation\n", !deviceRelations);
1885c2c66affSColin Finck         }
1886c2c66affSColin Finck 
1887c2c66affSColin Finck         deviceRelations = ExAllocatePoolWithTag(PagedPool,
1888c2c66affSColin Finck                                                 sizeof(DEVICE_RELATIONS),
1889c2c66affSColin Finck                                                 'IpcA');
1890c2c66affSColin Finck         if (!deviceRelations) {
1891c2c66affSColin Finck                 status = STATUS_INSUFFICIENT_RESOURCES;
1892c2c66affSColin Finck                 break;
1893c2c66affSColin Finck         }
1894c2c66affSColin Finck 
1895c2c66affSColin Finck         //
1896c2c66affSColin Finck         // There is only one PDO pointer in the structure
1897c2c66affSColin Finck         // for this relation type. The PnP Manager removes
1898c2c66affSColin Finck         // the reference to the PDO when the driver or application
1899c2c66affSColin Finck         // un-registers for notification on the device.
1900c2c66affSColin Finck         //
1901c2c66affSColin Finck 
1902c2c66affSColin Finck         deviceRelations->Count = 1;
1903c2c66affSColin Finck         deviceRelations->Objects[0] = DeviceData->Common.Self;
1904c2c66affSColin Finck         ObReferenceObject(DeviceData->Common.Self);
1905c2c66affSColin Finck 
1906c2c66affSColin Finck         status = STATUS_SUCCESS;
1907c2c66affSColin Finck         Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
1908c2c66affSColin Finck         break;
1909c2c66affSColin Finck 
1910c2c66affSColin Finck     case BusRelations: // Not handled by PDO
1911c2c66affSColin Finck     case EjectionRelations: // optional for PDO
1912c2c66affSColin Finck     case RemovalRelations: // // optional for PDO
1913c2c66affSColin Finck     default:
1914c2c66affSColin Finck         status = Irp->IoStatus.Status;
1915c2c66affSColin Finck     }
1916c2c66affSColin Finck 
1917c2c66affSColin Finck     return status;
1918c2c66affSColin Finck }
1919c2c66affSColin Finck 
1920c2c66affSColin Finck NTSTATUS
Bus_PDO_QueryBusInformation(PPDO_DEVICE_DATA DeviceData,PIRP Irp)1921c2c66affSColin Finck Bus_PDO_QueryBusInformation(
1922c2c66affSColin Finck      PPDO_DEVICE_DATA     DeviceData,
1923c2c66affSColin Finck       PIRP   Irp )
1924c2c66affSColin Finck /*++
1925c2c66affSColin Finck 
1926c2c66affSColin Finck Routine Description:
1927c2c66affSColin Finck 
1928c2c66affSColin Finck     The PnP Manager uses this IRP to request the type and
1929c2c66affSColin Finck     instance number of a device's parent bus. Bus drivers
1930c2c66affSColin Finck     should handle this request for their child devices (PDOs).
1931c2c66affSColin Finck 
1932c2c66affSColin Finck Arguments:
1933c2c66affSColin Finck 
1934c2c66affSColin Finck     DeviceData - Pointer to the PDO's device extension.
1935c2c66affSColin Finck     Irp          - Pointer to the irp.
1936c2c66affSColin Finck 
1937c2c66affSColin Finck Return Value:
1938c2c66affSColin Finck 
1939c2c66affSColin Finck     NT STATUS
1940c2c66affSColin Finck 
1941c2c66affSColin Finck --*/
1942c2c66affSColin Finck {
1943c2c66affSColin Finck 
1944c2c66affSColin Finck     PPNP_BUS_INFORMATION busInfo;
1945c2c66affSColin Finck 
1946c2c66affSColin Finck     PAGED_CODE ();
1947c2c66affSColin Finck 
1948c2c66affSColin Finck     busInfo = ExAllocatePoolWithTag(PagedPool,
1949c2c66affSColin Finck                                     sizeof(PNP_BUS_INFORMATION),
1950c2c66affSColin Finck                                     'IpcA');
1951c2c66affSColin Finck 
1952c2c66affSColin Finck     if (busInfo == NULL) {
1953c2c66affSColin Finck       return STATUS_INSUFFICIENT_RESOURCES;
1954c2c66affSColin Finck     }
1955c2c66affSColin Finck 
1956c2c66affSColin Finck     busInfo->BusTypeGuid = GUID_ACPI_INTERFACE_STANDARD;
1957c2c66affSColin Finck 
1958c2c66affSColin Finck     busInfo->LegacyBusType = InternalPowerBus;
1959c2c66affSColin Finck 
1960c2c66affSColin Finck     busInfo->BusNumber = 0; //fixme
1961c2c66affSColin Finck 
1962c2c66affSColin Finck     Irp->IoStatus.Information = (ULONG_PTR)busInfo;
1963c2c66affSColin Finck 
1964c2c66affSColin Finck     return STATUS_SUCCESS;
1965c2c66affSColin Finck }
1966c2c66affSColin Finck 
1967c2c66affSColin Finck 
1968c2c66affSColin Finck NTSTATUS
Bus_GetDeviceCapabilities(PDEVICE_OBJECT DeviceObject,PDEVICE_CAPABILITIES DeviceCapabilities)1969c2c66affSColin Finck Bus_GetDeviceCapabilities(
1970c2c66affSColin Finck       PDEVICE_OBJECT          DeviceObject,
1971c2c66affSColin Finck       PDEVICE_CAPABILITIES    DeviceCapabilities
1972c2c66affSColin Finck     )
1973c2c66affSColin Finck {
1974c2c66affSColin Finck     IO_STATUS_BLOCK     ioStatus;
1975c2c66affSColin Finck     KEVENT              pnpEvent;
1976c2c66affSColin Finck     NTSTATUS            status;
1977c2c66affSColin Finck     PDEVICE_OBJECT      targetObject;
1978c2c66affSColin Finck     PIO_STACK_LOCATION  irpStack;
1979c2c66affSColin Finck     PIRP                pnpIrp;
1980c2c66affSColin Finck 
1981c2c66affSColin Finck     PAGED_CODE();
1982c2c66affSColin Finck 
1983c2c66affSColin Finck     //
1984c2c66affSColin Finck     // Initialize the capabilities that we will send down
1985c2c66affSColin Finck     //
1986c2c66affSColin Finck     RtlZeroMemory( DeviceCapabilities, sizeof(DEVICE_CAPABILITIES) );
1987c2c66affSColin Finck     DeviceCapabilities->Size = sizeof(DEVICE_CAPABILITIES);
1988c2c66affSColin Finck     DeviceCapabilities->Version = 1;
1989c2c66affSColin Finck     DeviceCapabilities->Address = -1;
1990c2c66affSColin Finck     DeviceCapabilities->UINumber = -1;
1991c2c66affSColin Finck 
1992c2c66affSColin Finck     //
1993c2c66affSColin Finck     // Initialize the event
1994c2c66affSColin Finck     //
1995c2c66affSColin Finck     KeInitializeEvent( &pnpEvent, NotificationEvent, FALSE );
1996c2c66affSColin Finck 
1997c2c66affSColin Finck     targetObject = IoGetAttachedDeviceReference( DeviceObject );
1998c2c66affSColin Finck 
1999c2c66affSColin Finck     //
2000c2c66affSColin Finck     // Build an Irp
2001c2c66affSColin Finck     //
2002c2c66affSColin Finck     pnpIrp = IoBuildSynchronousFsdRequest(
2003c2c66affSColin Finck         IRP_MJ_PNP,
2004c2c66affSColin Finck         targetObject,
2005c2c66affSColin Finck         NULL,
2006c2c66affSColin Finck         0,
2007c2c66affSColin Finck         NULL,
2008c2c66affSColin Finck         &pnpEvent,
2009c2c66affSColin Finck         &ioStatus
2010c2c66affSColin Finck         );
2011c2c66affSColin Finck     if (pnpIrp == NULL) {
2012c2c66affSColin Finck 
2013c2c66affSColin Finck         status = STATUS_INSUFFICIENT_RESOURCES;
2014c2c66affSColin Finck         goto GetDeviceCapabilitiesExit;
2015c2c66affSColin Finck 
2016c2c66affSColin Finck     }
2017c2c66affSColin Finck 
2018c2c66affSColin Finck     //
2019c2c66affSColin Finck     // Pnp Irps all begin life as STATUS_NOT_SUPPORTED;
2020c2c66affSColin Finck     //
2021c2c66affSColin Finck     pnpIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
2022c2c66affSColin Finck 
2023c2c66affSColin Finck     //
2024c2c66affSColin Finck     // Get the top of stack
2025c2c66affSColin Finck     //
2026c2c66affSColin Finck     irpStack = IoGetNextIrpStackLocation( pnpIrp );
2027c2c66affSColin Finck 
2028c2c66affSColin Finck     //
2029c2c66affSColin Finck     // Set the top of stack
2030c2c66affSColin Finck     //
2031c2c66affSColin Finck     RtlZeroMemory( irpStack, sizeof(IO_STACK_LOCATION ) );
2032c2c66affSColin Finck     irpStack->MajorFunction = IRP_MJ_PNP;
2033c2c66affSColin Finck     irpStack->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
2034c2c66affSColin Finck     irpStack->Parameters.DeviceCapabilities.Capabilities = DeviceCapabilities;
2035c2c66affSColin Finck 
2036c2c66affSColin Finck     //
2037c2c66affSColin Finck     // Call the driver
2038c2c66affSColin Finck     //
2039c2c66affSColin Finck     status = IoCallDriver( targetObject, pnpIrp );
2040c2c66affSColin Finck     if (status == STATUS_PENDING) {
2041c2c66affSColin Finck 
2042c2c66affSColin Finck         //
2043c2c66affSColin Finck         // Block until the irp comes back.
2044c2c66affSColin Finck         // Important thing to note here is when you allocate
2045c2c66affSColin Finck         // the memory for an event in the stack you must do a
2046c2c66affSColin Finck         // KernelMode wait instead of UserMode to prevent
2047c2c66affSColin Finck         // the stack from getting paged out.
2048c2c66affSColin Finck         //
2049c2c66affSColin Finck 
2050c2c66affSColin Finck         KeWaitForSingleObject(
2051c2c66affSColin Finck             &pnpEvent,
2052c2c66affSColin Finck             Executive,
2053c2c66affSColin Finck             KernelMode,
2054c2c66affSColin Finck             FALSE,
2055c2c66affSColin Finck             NULL
2056c2c66affSColin Finck             );
2057c2c66affSColin Finck         status = ioStatus.Status;
2058c2c66affSColin Finck 
2059c2c66affSColin Finck     }
2060c2c66affSColin Finck 
2061c2c66affSColin Finck GetDeviceCapabilitiesExit:
2062c2c66affSColin Finck     //
2063c2c66affSColin Finck     // Done with reference
2064c2c66affSColin Finck     //
2065c2c66affSColin Finck     ObDereferenceObject( targetObject );
2066c2c66affSColin Finck 
2067c2c66affSColin Finck     //
2068c2c66affSColin Finck     // Done
2069c2c66affSColin Finck     //
2070c2c66affSColin Finck     return status;
2071c2c66affSColin Finck 
2072c2c66affSColin Finck }
20739bcd8350SThomas Faber #endif /* UNIT_TEST */
2074