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