c6893138c1456a980566286314aa9720639972ef
[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 wcsstr(DeviceData->HardwareIDs, L"PNP0A08") != 0 )
599 Temp = L"PCI Root Bridge";
600 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0A") != 0)
601 Temp = L"ACPI Battery";
602 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0F") != 0)
603 Temp = L"PCI Interrupt Link";
604 else if (wcsstr(DeviceData->HardwareIDs, L"ACPI_PWR") != 0)
605 Temp = L"ACPI Power Resource";
606 else if (wcsstr(DeviceData->HardwareIDs, L"Processor") != 0)
607 Temp = L"Processor";
608 else if (wcsstr(DeviceData->HardwareIDs, L"ThermalZone") != 0)
609 Temp = L"ACPI Thermal Zone";
610 else if (wcsstr(DeviceData->HardwareIDs, L"ACPI0002") != 0)
611 Temp = L"Smart Battery";
612 else if (wcsstr(DeviceData->HardwareIDs, L"ACPI0003") != 0)
613 Temp = L"AC Adapter";
614 /* Simply checking if AcpiHandle is NULL eliminates the need to check
615 * for the 4 different names that ACPI knows the fixed feature button as internally
616 */
617 else if (!DeviceData->AcpiHandle)
618 Temp = L"ACPI Fixed Feature Button";
619 else
620 Temp = L"Other ACPI device";
621
622 Buffer = ExAllocatePoolWithTag (PagedPool, (wcslen(Temp) + 1) * sizeof(WCHAR), 'IPCA');
623
624 if (!Buffer) {
625 status = STATUS_INSUFFICIENT_RESOURCES;
626 break;
627 }
628
629 RtlCopyMemory (Buffer, Temp, (wcslen(Temp) + 1) * sizeof(WCHAR));
630
631 DPRINT("\tDeviceTextDescription :%ws\n", Buffer);
632
633 Irp->IoStatus.Information = (ULONG_PTR) Buffer;
634 status = STATUS_SUCCESS;
635 }
636 break;
637
638 default:
639 break;
640 }
641
642 return status;
643
644 }
645
646 NTSTATUS
647 Bus_PDO_QueryResources(
648 PPDO_DEVICE_DATA DeviceData,
649 PIRP Irp )
650 {
651 ULONG NumberOfResources = 0;
652 PCM_RESOURCE_LIST ResourceList;
653 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor;
654 ACPI_STATUS AcpiStatus;
655 ACPI_BUFFER Buffer;
656 ACPI_RESOURCE* resource;
657 ULONG ResourceListSize;
658 ULONG i;
659 ULONGLONG BusNumber;
660 struct acpi_device *device;
661
662 if (!DeviceData->AcpiHandle)
663 {
664 return Irp->IoStatus.Status;
665 }
666
667 /* A bus number resource is not included in the list of current resources
668 * for the root PCI bus so we manually query one here and if we find it
669 * we create a resource list and add a bus number descriptor to it */
670 if (wcsstr(DeviceData->HardwareIDs, L"PNP0A03") != 0 ||
671 wcsstr(DeviceData->HardwareIDs, L"PNP0A08") != 0)
672 {
673 acpi_bus_get_device(DeviceData->AcpiHandle, &device);
674
675 AcpiStatus = acpi_evaluate_integer(DeviceData->AcpiHandle, "_BBN", NULL, &BusNumber);
676 if (AcpiStatus != AE_OK)
677 {
678 #if 0
679 if (device->flags.unique_id)
680 {
681 /* FIXME: Try the unique ID */
682 }
683 else
684 #endif
685 {
686 BusNumber = 0;
687 DPRINT1("Failed to find a bus number\n");
688 }
689 }
690 else
691 {
692 DPRINT1("Using _BBN for bus number\n");
693 }
694
695 DPRINT1("Found PCI root hub: %d\n", BusNumber);
696
697 ResourceListSize = sizeof(CM_RESOURCE_LIST);
698 ResourceList = (PCM_RESOURCE_LIST)ExAllocatePoolWithTag(PagedPool, ResourceListSize, 'IPCA');
699 if (!ResourceList)
700 return STATUS_INSUFFICIENT_RESOURCES;
701
702 ResourceList->Count = 1;
703 ResourceList->List[0].InterfaceType = Internal;
704 ResourceList->List[0].BusNumber = 0;
705 ResourceList->List[0].PartialResourceList.Version = 1;
706 ResourceList->List[0].PartialResourceList.Revision = 1;
707 ResourceList->List[0].PartialResourceList.Count = 1;
708 ResourceDescriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
709
710 ResourceDescriptor->Type = CmResourceTypeBusNumber;
711 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
712 ResourceDescriptor->u.BusNumber.Start = BusNumber;
713 ResourceDescriptor->u.BusNumber.Length = 1;
714
715 Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
716 return STATUS_SUCCESS;
717 }
718
719 /* Get current resources */
720 Buffer.Length = 0;
721 AcpiStatus = AcpiGetCurrentResources(DeviceData->AcpiHandle, &Buffer);
722 if ((!ACPI_SUCCESS(AcpiStatus) && AcpiStatus != AE_BUFFER_OVERFLOW) ||
723 Buffer.Length == 0)
724 {
725 return Irp->IoStatus.Status;
726 }
727
728 Buffer.Pointer = ExAllocatePoolWithTag(PagedPool, Buffer.Length, 'IPCA');
729 if (!Buffer.Pointer)
730 return STATUS_INSUFFICIENT_RESOURCES;
731
732 AcpiStatus = AcpiGetCurrentResources(DeviceData->AcpiHandle, &Buffer);
733 if (!ACPI_SUCCESS(AcpiStatus))
734 {
735 DPRINT1("AcpiGetCurrentResources #2 failed (0x%x)\n", AcpiStatus);
736 ASSERT(FALSE);
737 return STATUS_UNSUCCESSFUL;
738 }
739
740 resource= Buffer.Pointer;
741 /* Count number of resources */
742 while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG)
743 {
744 switch (resource->Type)
745 {
746 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
747 {
748 ACPI_RESOURCE_EXTENDED_IRQ *irq_data = (ACPI_RESOURCE_EXTENDED_IRQ*) &resource->Data;
749 if (irq_data->ProducerConsumer == ACPI_PRODUCER)
750 break;
751 NumberOfResources += irq_data->InterruptCount;
752 break;
753 }
754 case ACPI_RESOURCE_TYPE_IRQ:
755 {
756 ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
757 NumberOfResources += irq_data->InterruptCount;
758 break;
759 }
760 case ACPI_RESOURCE_TYPE_DMA:
761 {
762 ACPI_RESOURCE_DMA *dma_data = (ACPI_RESOURCE_DMA*) &resource->Data;
763 NumberOfResources += dma_data->ChannelCount;
764 break;
765 }
766 case ACPI_RESOURCE_TYPE_ADDRESS16:
767 case ACPI_RESOURCE_TYPE_ADDRESS32:
768 case ACPI_RESOURCE_TYPE_ADDRESS64:
769 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
770 {
771 ACPI_RESOURCE_ADDRESS *addr_res = (ACPI_RESOURCE_ADDRESS*) &resource->Data;
772 if (addr_res->ProducerConsumer == ACPI_PRODUCER)
773 break;
774 NumberOfResources++;
775 break;
776 }
777 case ACPI_RESOURCE_TYPE_MEMORY24:
778 case ACPI_RESOURCE_TYPE_MEMORY32:
779 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
780 case ACPI_RESOURCE_TYPE_FIXED_IO:
781 case ACPI_RESOURCE_TYPE_IO:
782 {
783 NumberOfResources++;
784 break;
785 }
786 default:
787 {
788 DPRINT1("Unknown resource type: %d\n", resource->Type);
789 break;
790 }
791 }
792 resource = ACPI_NEXT_RESOURCE(resource);
793 }
794
795 /* Allocate memory */
796 ResourceListSize = sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * (NumberOfResources - 1);
797 ResourceList = (PCM_RESOURCE_LIST)ExAllocatePoolWithTag(PagedPool, ResourceListSize, 'IPCA');
798
799 if (!ResourceList)
800 {
801 ExFreePoolWithTag(Buffer.Pointer, 'IPCA');
802 return STATUS_INSUFFICIENT_RESOURCES;
803 }
804 ResourceList->Count = 1;
805 ResourceList->List[0].InterfaceType = Internal; /* FIXME */
806 ResourceList->List[0].BusNumber = 0; /* We're the only ACPI bus device in the system */
807 ResourceList->List[0].PartialResourceList.Version = 1;
808 ResourceList->List[0].PartialResourceList.Revision = 1;
809 ResourceList->List[0].PartialResourceList.Count = NumberOfResources;
810 ResourceDescriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
811
812 /* Fill resources list structure */
813 resource = Buffer.Pointer;
814 while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG)
815 {
816 switch (resource->Type)
817 {
818 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
819 {
820 ACPI_RESOURCE_EXTENDED_IRQ *irq_data = (ACPI_RESOURCE_EXTENDED_IRQ*) &resource->Data;
821 if (irq_data->ProducerConsumer == ACPI_PRODUCER)
822 break;
823 for (i = 0; i < irq_data->InterruptCount; i++)
824 {
825 ResourceDescriptor->Type = CmResourceTypeInterrupt;
826
827 ResourceDescriptor->ShareDisposition =
828 (irq_data->Sharable == ACPI_SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
829 ResourceDescriptor->Flags =
830 (irq_data->Triggering == ACPI_LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
831 ResourceDescriptor->u.Interrupt.Level =
832 ResourceDescriptor->u.Interrupt.Vector = irq_data->Interrupts[i];
833 ResourceDescriptor->u.Interrupt.Affinity = (KAFFINITY)(-1);
834
835 ResourceDescriptor++;
836 }
837 break;
838 }
839 case ACPI_RESOURCE_TYPE_IRQ:
840 {
841 ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
842 for (i = 0; i < irq_data->InterruptCount; i++)
843 {
844 ResourceDescriptor->Type = CmResourceTypeInterrupt;
845
846 ResourceDescriptor->ShareDisposition =
847 (irq_data->Sharable == ACPI_SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
848 ResourceDescriptor->Flags =
849 (irq_data->Triggering == ACPI_LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
850 ResourceDescriptor->u.Interrupt.Level =
851 ResourceDescriptor->u.Interrupt.Vector = irq_data->Interrupts[i];
852 ResourceDescriptor->u.Interrupt.Affinity = (KAFFINITY)(-1);
853
854 ResourceDescriptor++;
855 }
856 break;
857 }
858 case ACPI_RESOURCE_TYPE_DMA:
859 {
860 ACPI_RESOURCE_DMA *dma_data = (ACPI_RESOURCE_DMA*) &resource->Data;
861 for (i = 0; i < dma_data->ChannelCount; i++)
862 {
863 ResourceDescriptor->Type = CmResourceTypeDma;
864 ResourceDescriptor->Flags = 0;
865 switch (dma_data->Type)
866 {
867 case ACPI_TYPE_A: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_A; break;
868 case ACPI_TYPE_B: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_B; break;
869 case ACPI_TYPE_F: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_F; break;
870 }
871 if (dma_data->BusMaster == ACPI_BUS_MASTER)
872 ResourceDescriptor->Flags |= CM_RESOURCE_DMA_BUS_MASTER;
873 switch (dma_data->Transfer)
874 {
875 case ACPI_TRANSFER_8: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_8; break;
876 case ACPI_TRANSFER_16: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_16; break;
877 case ACPI_TRANSFER_8_16: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_8_AND_16; break;
878 }
879 ResourceDescriptor->u.Dma.Channel = dma_data->Channels[i];
880
881 ResourceDescriptor++;
882 }
883 break;
884 }
885 case ACPI_RESOURCE_TYPE_IO:
886 {
887 ACPI_RESOURCE_IO *io_data = (ACPI_RESOURCE_IO*) &resource->Data;
888 ResourceDescriptor->Type = CmResourceTypePort;
889 ResourceDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
890 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
891 if (io_data->IoDecode == ACPI_DECODE_16)
892 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
893 else
894 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
895 ResourceDescriptor->u.Port.Start.QuadPart = io_data->Minimum;
896 ResourceDescriptor->u.Port.Length = io_data->AddressLength;
897
898 ResourceDescriptor++;
899 break;
900 }
901 case ACPI_RESOURCE_TYPE_FIXED_IO:
902 {
903 ACPI_RESOURCE_FIXED_IO *io_data = (ACPI_RESOURCE_FIXED_IO*) &resource->Data;
904 ResourceDescriptor->Type = CmResourceTypePort;
905 ResourceDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
906 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
907 ResourceDescriptor->u.Port.Start.QuadPart = io_data->Address;
908 ResourceDescriptor->u.Port.Length = io_data->AddressLength;
909
910 ResourceDescriptor++;
911 break;
912 }
913 case ACPI_RESOURCE_TYPE_ADDRESS16:
914 {
915 ACPI_RESOURCE_ADDRESS16 *addr16_data = (ACPI_RESOURCE_ADDRESS16*) &resource->Data;
916 if (addr16_data->ProducerConsumer == ACPI_PRODUCER)
917 break;
918 if (addr16_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
919 {
920 ResourceDescriptor->Type = CmResourceTypeBusNumber;
921 ResourceDescriptor->ShareDisposition = CmResourceShareShared;
922 ResourceDescriptor->Flags = 0;
923 ResourceDescriptor->u.BusNumber.Start = addr16_data->Minimum;
924 ResourceDescriptor->u.BusNumber.Length = addr16_data->AddressLength;
925 }
926 else if (addr16_data->ResourceType == ACPI_IO_RANGE)
927 {
928 ResourceDescriptor->Type = CmResourceTypePort;
929 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
930 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
931 if (addr16_data->Decode == ACPI_POS_DECODE)
932 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
933 ResourceDescriptor->u.Port.Start.QuadPart = addr16_data->Minimum;
934 ResourceDescriptor->u.Port.Length = addr16_data->AddressLength;
935 }
936 else
937 {
938 ResourceDescriptor->Type = CmResourceTypeMemory;
939 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
940 ResourceDescriptor->Flags = 0;
941 if (addr16_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
942 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
943 else
944 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
945 switch (addr16_data->Info.Mem.Caching)
946 {
947 case ACPI_CACHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
948 case ACPI_WRITE_COMBINING_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
949 case ACPI_PREFETCHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
950 }
951 ResourceDescriptor->u.Memory.Start.QuadPart = addr16_data->Minimum;
952 ResourceDescriptor->u.Memory.Length = addr16_data->AddressLength;
953 }
954 ResourceDescriptor++;
955 break;
956 }
957 case ACPI_RESOURCE_TYPE_ADDRESS32:
958 {
959 ACPI_RESOURCE_ADDRESS32 *addr32_data = (ACPI_RESOURCE_ADDRESS32*) &resource->Data;
960 if (addr32_data->ProducerConsumer == ACPI_PRODUCER)
961 break;
962 if (addr32_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
963 {
964 ResourceDescriptor->Type = CmResourceTypeBusNumber;
965 ResourceDescriptor->ShareDisposition = CmResourceShareShared;
966 ResourceDescriptor->Flags = 0;
967 ResourceDescriptor->u.BusNumber.Start = addr32_data->Minimum;
968 ResourceDescriptor->u.BusNumber.Length = addr32_data->AddressLength;
969 }
970 else if (addr32_data->ResourceType == ACPI_IO_RANGE)
971 {
972 ResourceDescriptor->Type = CmResourceTypePort;
973 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
974 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
975 if (addr32_data->Decode == ACPI_POS_DECODE)
976 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
977 ResourceDescriptor->u.Port.Start.QuadPart = addr32_data->Minimum;
978 ResourceDescriptor->u.Port.Length = addr32_data->AddressLength;
979 }
980 else
981 {
982 ResourceDescriptor->Type = CmResourceTypeMemory;
983 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
984 ResourceDescriptor->Flags = 0;
985 if (addr32_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
986 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
987 else
988 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
989 switch (addr32_data->Info.Mem.Caching)
990 {
991 case ACPI_CACHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
992 case ACPI_WRITE_COMBINING_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
993 case ACPI_PREFETCHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
994 }
995 ResourceDescriptor->u.Memory.Start.QuadPart = addr32_data->Minimum;
996 ResourceDescriptor->u.Memory.Length = addr32_data->AddressLength;
997 }
998 ResourceDescriptor++;
999 break;
1000 }
1001 case ACPI_RESOURCE_TYPE_ADDRESS64:
1002 {
1003 ACPI_RESOURCE_ADDRESS64 *addr64_data = (ACPI_RESOURCE_ADDRESS64*) &resource->Data;
1004 if (addr64_data->ProducerConsumer == ACPI_PRODUCER)
1005 break;
1006 if (addr64_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1007 {
1008 DPRINT1("64-bit bus address is not supported!\n");
1009 ResourceDescriptor->Type = CmResourceTypeBusNumber;
1010 ResourceDescriptor->ShareDisposition = CmResourceShareShared;
1011 ResourceDescriptor->Flags = 0;
1012 ResourceDescriptor->u.BusNumber.Start = (ULONG)addr64_data->Minimum;
1013 ResourceDescriptor->u.BusNumber.Length = addr64_data->AddressLength;
1014 }
1015 else if (addr64_data->ResourceType == ACPI_IO_RANGE)
1016 {
1017 ResourceDescriptor->Type = CmResourceTypePort;
1018 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1019 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
1020 if (addr64_data->Decode == ACPI_POS_DECODE)
1021 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1022 ResourceDescriptor->u.Port.Start.QuadPart = addr64_data->Minimum;
1023 ResourceDescriptor->u.Port.Length = addr64_data->AddressLength;
1024 }
1025 else
1026 {
1027 ResourceDescriptor->Type = CmResourceTypeMemory;
1028 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1029 ResourceDescriptor->Flags = 0;
1030 if (addr64_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1031 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1032 else
1033 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1034 switch (addr64_data->Info.Mem.Caching)
1035 {
1036 case ACPI_CACHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1037 case ACPI_WRITE_COMBINING_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1038 case ACPI_PREFETCHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1039 }
1040 ResourceDescriptor->u.Memory.Start.QuadPart = addr64_data->Minimum;
1041 ResourceDescriptor->u.Memory.Length = addr64_data->AddressLength;
1042 }
1043 ResourceDescriptor++;
1044 break;
1045 }
1046 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
1047 {
1048 ACPI_RESOURCE_EXTENDED_ADDRESS64 *addr64_data = (ACPI_RESOURCE_EXTENDED_ADDRESS64*) &resource->Data;
1049 if (addr64_data->ProducerConsumer == ACPI_PRODUCER)
1050 break;
1051 if (addr64_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1052 {
1053 DPRINT1("64-bit bus address is not supported!\n");
1054 ResourceDescriptor->Type = CmResourceTypeBusNumber;
1055 ResourceDescriptor->ShareDisposition = CmResourceShareShared;
1056 ResourceDescriptor->Flags = 0;
1057 ResourceDescriptor->u.BusNumber.Start = (ULONG)addr64_data->Minimum;
1058 ResourceDescriptor->u.BusNumber.Length = addr64_data->AddressLength;
1059 }
1060 else if (addr64_data->ResourceType == ACPI_IO_RANGE)
1061 {
1062 ResourceDescriptor->Type = CmResourceTypePort;
1063 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1064 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
1065 if (addr64_data->Decode == ACPI_POS_DECODE)
1066 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1067 ResourceDescriptor->u.Port.Start.QuadPart = addr64_data->Minimum;
1068 ResourceDescriptor->u.Port.Length = addr64_data->AddressLength;
1069 }
1070 else
1071 {
1072 ResourceDescriptor->Type = CmResourceTypeMemory;
1073 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1074 ResourceDescriptor->Flags = 0;
1075 if (addr64_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1076 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1077 else
1078 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1079 switch (addr64_data->Info.Mem.Caching)
1080 {
1081 case ACPI_CACHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1082 case ACPI_WRITE_COMBINING_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1083 case ACPI_PREFETCHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1084 }
1085 ResourceDescriptor->u.Memory.Start.QuadPart = addr64_data->Minimum;
1086 ResourceDescriptor->u.Memory.Length = addr64_data->AddressLength;
1087 }
1088 ResourceDescriptor++;
1089 break;
1090 }
1091 case ACPI_RESOURCE_TYPE_MEMORY24:
1092 {
1093 ACPI_RESOURCE_MEMORY24 *mem24_data = (ACPI_RESOURCE_MEMORY24*) &resource->Data;
1094 ResourceDescriptor->Type = CmResourceTypeMemory;
1095 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1096 ResourceDescriptor->Flags = CM_RESOURCE_MEMORY_24;
1097 if (mem24_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
1098 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1099 else
1100 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1101 ResourceDescriptor->u.Memory.Start.QuadPart = mem24_data->Minimum;
1102 ResourceDescriptor->u.Memory.Length = mem24_data->AddressLength;
1103
1104 ResourceDescriptor++;
1105 break;
1106 }
1107 case ACPI_RESOURCE_TYPE_MEMORY32:
1108 {
1109 ACPI_RESOURCE_MEMORY32 *mem32_data = (ACPI_RESOURCE_MEMORY32*) &resource->Data;
1110 ResourceDescriptor->Type = CmResourceTypeMemory;
1111 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1112 ResourceDescriptor->Flags = 0;
1113 if (mem32_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
1114 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1115 else
1116 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1117 ResourceDescriptor->u.Memory.Start.QuadPart = mem32_data->Minimum;
1118 ResourceDescriptor->u.Memory.Length = mem32_data->AddressLength;
1119
1120 ResourceDescriptor++;
1121 break;
1122 }
1123 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
1124 {
1125 ACPI_RESOURCE_FIXED_MEMORY32 *memfixed32_data = (ACPI_RESOURCE_FIXED_MEMORY32*) &resource->Data;
1126 ResourceDescriptor->Type = CmResourceTypeMemory;
1127 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1128 ResourceDescriptor->Flags = 0;
1129 if (memfixed32_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
1130 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1131 else
1132 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1133 ResourceDescriptor->u.Memory.Start.QuadPart = memfixed32_data->Address;
1134 ResourceDescriptor->u.Memory.Length = memfixed32_data->AddressLength;
1135
1136 ResourceDescriptor++;
1137 break;
1138 }
1139 default:
1140 {
1141 break;
1142 }
1143 }
1144 resource = ACPI_NEXT_RESOURCE(resource);
1145 }
1146
1147 ExFreePoolWithTag(Buffer.Pointer, 'IPCA');
1148 Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
1149 return STATUS_SUCCESS;
1150 }
1151
1152 NTSTATUS
1153 Bus_PDO_QueryResourceRequirements(
1154 PPDO_DEVICE_DATA DeviceData,
1155 PIRP Irp )
1156 {
1157 ULONG NumberOfResources = 0;
1158 ACPI_STATUS AcpiStatus;
1159 ACPI_BUFFER Buffer;
1160 ACPI_RESOURCE* resource;
1161 ULONG i, RequirementsListSize;
1162 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
1163 PIO_RESOURCE_DESCRIPTOR RequirementDescriptor;
1164 BOOLEAN CurrentRes = FALSE;
1165
1166 PAGED_CODE ();
1167
1168 if (!DeviceData->AcpiHandle)
1169 {
1170 return Irp->IoStatus.Status;
1171 }
1172
1173 /* Handle the PCI root manually */
1174 if (wcsstr(DeviceData->HardwareIDs, L"PNP0A03") != 0 ||
1175 wcsstr(DeviceData->HardwareIDs, L"PNP0A08") != 0)
1176 {
1177 return Irp->IoStatus.Status;
1178 }
1179
1180 /* Get current resources */
1181 while (TRUE)
1182 {
1183 Buffer.Length = 0;
1184 if (CurrentRes)
1185 AcpiStatus = AcpiGetCurrentResources(DeviceData->AcpiHandle, &Buffer);
1186 else
1187 AcpiStatus = AcpiGetPossibleResources(DeviceData->AcpiHandle, &Buffer);
1188 if ((!ACPI_SUCCESS(AcpiStatus) && AcpiStatus != AE_BUFFER_OVERFLOW) ||
1189 Buffer.Length == 0)
1190 {
1191 if (!CurrentRes)
1192 CurrentRes = TRUE;
1193 else
1194 return Irp->IoStatus.Status;
1195 }
1196 else
1197 break;
1198 }
1199
1200 Buffer.Pointer = ExAllocatePoolWithTag(PagedPool, Buffer.Length, 'IPCA');
1201 if (!Buffer.Pointer)
1202 return STATUS_INSUFFICIENT_RESOURCES;
1203
1204 if (CurrentRes)
1205 AcpiStatus = AcpiGetCurrentResources(DeviceData->AcpiHandle, &Buffer);
1206 else
1207 AcpiStatus = AcpiGetPossibleResources(DeviceData->AcpiHandle, &Buffer);
1208 if (!ACPI_SUCCESS(AcpiStatus))
1209 {
1210 DPRINT1("AcpiGetCurrentResources #2 failed (0x%x)\n", AcpiStatus);
1211 ASSERT(FALSE);
1212 return STATUS_UNSUCCESSFUL;
1213 }
1214
1215 resource= Buffer.Pointer;
1216 /* Count number of resources */
1217 while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG)
1218 {
1219 switch (resource->Type)
1220 {
1221 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
1222 {
1223 ACPI_RESOURCE_EXTENDED_IRQ *irq_data = (ACPI_RESOURCE_EXTENDED_IRQ*) &resource->Data;
1224 if (irq_data->ProducerConsumer == ACPI_PRODUCER)
1225 break;
1226 NumberOfResources += irq_data->InterruptCount;
1227 break;
1228 }
1229 case ACPI_RESOURCE_TYPE_IRQ:
1230 {
1231 ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
1232 NumberOfResources += irq_data->InterruptCount;
1233 break;
1234 }
1235 case ACPI_RESOURCE_TYPE_DMA:
1236 {
1237 ACPI_RESOURCE_DMA *dma_data = (ACPI_RESOURCE_DMA*) &resource->Data;
1238 NumberOfResources += dma_data->ChannelCount;
1239 break;
1240 }
1241 case ACPI_RESOURCE_TYPE_ADDRESS16:
1242 case ACPI_RESOURCE_TYPE_ADDRESS32:
1243 case ACPI_RESOURCE_TYPE_ADDRESS64:
1244 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
1245 {
1246 ACPI_RESOURCE_ADDRESS *res_addr = (ACPI_RESOURCE_ADDRESS*) &resource->Data;
1247 if (res_addr->ProducerConsumer == ACPI_PRODUCER)
1248 break;
1249 NumberOfResources++;
1250 break;
1251 }
1252 case ACPI_RESOURCE_TYPE_MEMORY24:
1253 case ACPI_RESOURCE_TYPE_MEMORY32:
1254 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
1255 case ACPI_RESOURCE_TYPE_FIXED_IO:
1256 case ACPI_RESOURCE_TYPE_IO:
1257 {
1258 NumberOfResources++;
1259 break;
1260 }
1261 default:
1262 {
1263 break;
1264 }
1265 }
1266 resource = ACPI_NEXT_RESOURCE(resource);
1267 }
1268
1269 RequirementsListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) + sizeof(IO_RESOURCE_DESCRIPTOR) * (NumberOfResources - 1);
1270 RequirementsList = (PIO_RESOURCE_REQUIREMENTS_LIST)ExAllocatePoolWithTag(PagedPool, RequirementsListSize, 'IPCA');
1271
1272 if (!RequirementsList)
1273 {
1274 ExFreePoolWithTag(Buffer.Pointer, 'IPCA');
1275 return STATUS_INSUFFICIENT_RESOURCES;
1276 }
1277 RequirementsList->ListSize = RequirementsListSize;
1278 RequirementsList->InterfaceType = Internal;
1279 RequirementsList->BusNumber = 0;
1280 RequirementsList->SlotNumber = 0; /* Not used by WDM drivers */
1281 RequirementsList->AlternativeLists = 1;
1282 RequirementsList->List[0].Version = 1;
1283 RequirementsList->List[0].Revision = 1;
1284 RequirementsList->List[0].Count = NumberOfResources;
1285 RequirementDescriptor = RequirementsList->List[0].Descriptors;
1286
1287 /* Fill resources list structure */
1288 resource = Buffer.Pointer;
1289 while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG && resource->Type != ACPI_RESOURCE_TYPE_END_DEPENDENT)
1290 {
1291 switch (resource->Type)
1292 {
1293 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
1294 {
1295 ACPI_RESOURCE_EXTENDED_IRQ *irq_data = (ACPI_RESOURCE_EXTENDED_IRQ*) &resource->Data;
1296 if (irq_data->ProducerConsumer == ACPI_PRODUCER)
1297 break;
1298 for (i = 0; i < irq_data->InterruptCount; i++)
1299 {
1300 RequirementDescriptor->Option = (i == 0) ? IO_RESOURCE_PREFERRED : IO_RESOURCE_ALTERNATIVE;
1301 RequirementDescriptor->Type = CmResourceTypeInterrupt;
1302 RequirementDescriptor->ShareDisposition = (irq_data->Sharable == ACPI_SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
1303 RequirementDescriptor->Flags =(irq_data->Triggering == ACPI_LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
1304 RequirementDescriptor->u.Interrupt.MinimumVector =
1305 RequirementDescriptor->u.Interrupt.MaximumVector = irq_data->Interrupts[i];
1306
1307 RequirementDescriptor++;
1308 }
1309 break;
1310 }
1311 case ACPI_RESOURCE_TYPE_IRQ:
1312 {
1313 ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
1314 for (i = 0; i < irq_data->InterruptCount; i++)
1315 {
1316 RequirementDescriptor->Option = (i == 0) ? IO_RESOURCE_PREFERRED : IO_RESOURCE_ALTERNATIVE;
1317 RequirementDescriptor->Type = CmResourceTypeInterrupt;
1318 RequirementDescriptor->ShareDisposition = (irq_data->Sharable == ACPI_SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
1319 RequirementDescriptor->Flags =(irq_data->Triggering == ACPI_LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
1320 RequirementDescriptor->u.Interrupt.MinimumVector =
1321 RequirementDescriptor->u.Interrupt.MaximumVector = irq_data->Interrupts[i];
1322
1323 RequirementDescriptor++;
1324 }
1325 break;
1326 }
1327 case ACPI_RESOURCE_TYPE_DMA:
1328 {
1329 ACPI_RESOURCE_DMA *dma_data = (ACPI_RESOURCE_DMA*) &resource->Data;
1330 for (i = 0; i < dma_data->ChannelCount; i++)
1331 {
1332 RequirementDescriptor->Type = CmResourceTypeDma;
1333 RequirementDescriptor->Flags = 0;
1334 switch (dma_data->Type)
1335 {
1336 case ACPI_TYPE_A: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_A; break;
1337 case ACPI_TYPE_B: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_B; break;
1338 case ACPI_TYPE_F: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_F; break;
1339 }
1340 if (dma_data->BusMaster == ACPI_BUS_MASTER)
1341 RequirementDescriptor->Flags |= CM_RESOURCE_DMA_BUS_MASTER;
1342 switch (dma_data->Transfer)
1343 {
1344 case ACPI_TRANSFER_8: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_8; break;
1345 case ACPI_TRANSFER_16: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_16; break;
1346 case ACPI_TRANSFER_8_16: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_8_AND_16; break;
1347 }
1348
1349 RequirementDescriptor->Option = (i == 0) ? IO_RESOURCE_PREFERRED : IO_RESOURCE_ALTERNATIVE;
1350 RequirementDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
1351 RequirementDescriptor->u.Dma.MinimumChannel =
1352 RequirementDescriptor->u.Dma.MaximumChannel = dma_data->Channels[i];
1353 RequirementDescriptor++;
1354 }
1355 break;
1356 }
1357 case ACPI_RESOURCE_TYPE_IO:
1358 {
1359 ACPI_RESOURCE_IO *io_data = (ACPI_RESOURCE_IO*) &resource->Data;
1360 RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
1361 if (io_data->IoDecode == ACPI_DECODE_16)
1362 RequirementDescriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
1363 else
1364 RequirementDescriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
1365 RequirementDescriptor->u.Port.Length = io_data->AddressLength;
1366 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1367 RequirementDescriptor->Type = CmResourceTypePort;
1368 RequirementDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
1369 RequirementDescriptor->u.Port.Alignment = io_data->Alignment;
1370 RequirementDescriptor->u.Port.MinimumAddress.QuadPart = io_data->Minimum;
1371 RequirementDescriptor->u.Port.MaximumAddress.QuadPart = io_data->Maximum + io_data->AddressLength - 1;
1372
1373 RequirementDescriptor++;
1374 break;
1375 }
1376 case ACPI_RESOURCE_TYPE_FIXED_IO:
1377 {
1378 ACPI_RESOURCE_FIXED_IO *io_data = (ACPI_RESOURCE_FIXED_IO*) &resource->Data;
1379 RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
1380 RequirementDescriptor->u.Port.Length = io_data->AddressLength;
1381 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1382 RequirementDescriptor->Type = CmResourceTypePort;
1383 RequirementDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
1384 RequirementDescriptor->u.Port.Alignment = 1;
1385 RequirementDescriptor->u.Port.MinimumAddress.QuadPart = io_data->Address;
1386 RequirementDescriptor->u.Port.MaximumAddress.QuadPart = io_data->Address + io_data->AddressLength - 1;
1387
1388 RequirementDescriptor++;
1389 break;
1390 }
1391 case ACPI_RESOURCE_TYPE_ADDRESS16:
1392 {
1393 ACPI_RESOURCE_ADDRESS16 *addr16_data = (ACPI_RESOURCE_ADDRESS16*) &resource->Data;
1394 if (addr16_data->ProducerConsumer == ACPI_PRODUCER)
1395 break;
1396 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1397 if (addr16_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1398 {
1399 RequirementDescriptor->Type = CmResourceTypeBusNumber;
1400 RequirementDescriptor->ShareDisposition = CmResourceShareShared;
1401 RequirementDescriptor->Flags = 0;
1402 RequirementDescriptor->u.BusNumber.MinBusNumber = addr16_data->Minimum;
1403 RequirementDescriptor->u.BusNumber.MaxBusNumber = addr16_data->Maximum + addr16_data->AddressLength - 1;
1404 RequirementDescriptor->u.BusNumber.Length = addr16_data->AddressLength;
1405 }
1406 else if (addr16_data->ResourceType == ACPI_IO_RANGE)
1407 {
1408 RequirementDescriptor->Type = CmResourceTypePort;
1409 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1410 RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
1411 if (addr16_data->Decode == ACPI_POS_DECODE)
1412 RequirementDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1413 RequirementDescriptor->u.Port.MinimumAddress.QuadPart = addr16_data->Minimum;
1414 RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr16_data->Maximum + addr16_data->AddressLength - 1;
1415 RequirementDescriptor->u.Port.Length = addr16_data->AddressLength;
1416 }
1417 else
1418 {
1419 RequirementDescriptor->Type = CmResourceTypeMemory;
1420 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1421 RequirementDescriptor->Flags = 0;
1422 if (addr16_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1423 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1424 else
1425 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1426 switch (addr16_data->Info.Mem.Caching)
1427 {
1428 case ACPI_CACHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1429 case ACPI_WRITE_COMBINING_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1430 case ACPI_PREFETCHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1431 }
1432 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = addr16_data->Minimum;
1433 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr16_data->Maximum + addr16_data->AddressLength - 1;
1434 RequirementDescriptor->u.Memory.Length = addr16_data->AddressLength;
1435 }
1436 RequirementDescriptor++;
1437 break;
1438 }
1439 case ACPI_RESOURCE_TYPE_ADDRESS32:
1440 {
1441 ACPI_RESOURCE_ADDRESS32 *addr32_data = (ACPI_RESOURCE_ADDRESS32*) &resource->Data;
1442 if (addr32_data->ProducerConsumer == ACPI_PRODUCER)
1443 break;
1444 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1445 if (addr32_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1446 {
1447 RequirementDescriptor->Type = CmResourceTypeBusNumber;
1448 RequirementDescriptor->ShareDisposition = CmResourceShareShared;
1449 RequirementDescriptor->Flags = 0;
1450 RequirementDescriptor->u.BusNumber.MinBusNumber = addr32_data->Minimum;
1451 RequirementDescriptor->u.BusNumber.MaxBusNumber = addr32_data->Maximum + addr32_data->AddressLength - 1;
1452 RequirementDescriptor->u.BusNumber.Length = addr32_data->AddressLength;
1453 }
1454 else if (addr32_data->ResourceType == ACPI_IO_RANGE)
1455 {
1456 RequirementDescriptor->Type = CmResourceTypePort;
1457 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1458 RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
1459 if (addr32_data->Decode == ACPI_POS_DECODE)
1460 RequirementDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1461 RequirementDescriptor->u.Port.MinimumAddress.QuadPart = addr32_data->Minimum;
1462 RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr32_data->Maximum + addr32_data->AddressLength - 1;
1463 RequirementDescriptor->u.Port.Length = addr32_data->AddressLength;
1464 }
1465 else
1466 {
1467 RequirementDescriptor->Type = CmResourceTypeMemory;
1468 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1469 RequirementDescriptor->Flags = 0;
1470 if (addr32_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1471 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1472 else
1473 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1474 switch (addr32_data->Info.Mem.Caching)
1475 {
1476 case ACPI_CACHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1477 case ACPI_WRITE_COMBINING_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1478 case ACPI_PREFETCHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1479 }
1480 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = addr32_data->Minimum;
1481 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr32_data->Maximum + addr32_data->AddressLength - 1;
1482 RequirementDescriptor->u.Memory.Length = addr32_data->AddressLength;
1483 }
1484 RequirementDescriptor++;
1485 break;
1486 }
1487 case ACPI_RESOURCE_TYPE_ADDRESS64:
1488 {
1489 ACPI_RESOURCE_ADDRESS64 *addr64_data = (ACPI_RESOURCE_ADDRESS64*) &resource->Data;
1490 if (addr64_data->ProducerConsumer == ACPI_PRODUCER)
1491 break;
1492 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1493 if (addr64_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1494 {
1495 DPRINT1("64-bit bus address is not supported!\n");
1496 RequirementDescriptor->Type = CmResourceTypeBusNumber;
1497 RequirementDescriptor->ShareDisposition = CmResourceShareShared;
1498 RequirementDescriptor->Flags = 0;
1499 RequirementDescriptor->u.BusNumber.MinBusNumber = (ULONG)addr64_data->Minimum;
1500 RequirementDescriptor->u.BusNumber.MaxBusNumber = (ULONG)addr64_data->Maximum + addr64_data->AddressLength - 1;
1501 RequirementDescriptor->u.BusNumber.Length = addr64_data->AddressLength;
1502 }
1503 else if (addr64_data->ResourceType == ACPI_IO_RANGE)
1504 {
1505 RequirementDescriptor->Type = CmResourceTypePort;
1506 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1507 RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
1508 if (addr64_data->Decode == ACPI_POS_DECODE)
1509 RequirementDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1510 RequirementDescriptor->u.Port.MinimumAddress.QuadPart = addr64_data->Minimum;
1511 RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr64_data->Maximum + addr64_data->AddressLength - 1;
1512 RequirementDescriptor->u.Port.Length = addr64_data->AddressLength;
1513 }
1514 else
1515 {
1516 RequirementDescriptor->Type = CmResourceTypeMemory;
1517 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1518 RequirementDescriptor->Flags = 0;
1519 if (addr64_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1520 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1521 else
1522 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1523 switch (addr64_data->Info.Mem.Caching)
1524 {
1525 case ACPI_CACHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1526 case ACPI_WRITE_COMBINING_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1527 case ACPI_PREFETCHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1528 }
1529 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = addr64_data->Minimum;
1530 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr64_data->Maximum + addr64_data->AddressLength - 1;
1531 RequirementDescriptor->u.Memory.Length = addr64_data->AddressLength;
1532 }
1533 RequirementDescriptor++;
1534 break;
1535 }
1536 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
1537 {
1538 ACPI_RESOURCE_EXTENDED_ADDRESS64 *addr64_data = (ACPI_RESOURCE_EXTENDED_ADDRESS64*) &resource->Data;
1539 if (addr64_data->ProducerConsumer == ACPI_PRODUCER)
1540 break;
1541 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1542 if (addr64_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1543 {
1544 DPRINT1("64-bit bus address is not supported!\n");
1545 RequirementDescriptor->Type = CmResourceTypeBusNumber;
1546 RequirementDescriptor->ShareDisposition = CmResourceShareShared;
1547 RequirementDescriptor->Flags = 0;
1548 RequirementDescriptor->u.BusNumber.MinBusNumber = (ULONG)addr64_data->Minimum;
1549 RequirementDescriptor->u.BusNumber.MaxBusNumber = (ULONG)addr64_data->Maximum + addr64_data->AddressLength - 1;
1550 RequirementDescriptor->u.BusNumber.Length = addr64_data->AddressLength;
1551 }
1552 else if (addr64_data->ResourceType == ACPI_IO_RANGE)
1553 {
1554 RequirementDescriptor->Type = CmResourceTypePort;
1555 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1556 RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
1557 if (addr64_data->Decode == ACPI_POS_DECODE)
1558 RequirementDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1559 RequirementDescriptor->u.Port.MinimumAddress.QuadPart = addr64_data->Minimum;
1560 RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr64_data->Maximum + addr64_data->AddressLength - 1;
1561 RequirementDescriptor->u.Port.Length = addr64_data->AddressLength;
1562 }
1563 else
1564 {
1565 RequirementDescriptor->Type = CmResourceTypeMemory;
1566 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1567 RequirementDescriptor->Flags = 0;
1568 if (addr64_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1569 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1570 else
1571 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1572 switch (addr64_data->Info.Mem.Caching)
1573 {
1574 case ACPI_CACHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1575 case ACPI_WRITE_COMBINING_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1576 case ACPI_PREFETCHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1577 }
1578 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = addr64_data->Minimum;
1579 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr64_data->Maximum + addr64_data->AddressLength - 1;
1580 RequirementDescriptor->u.Memory.Length = addr64_data->AddressLength;
1581 }
1582 RequirementDescriptor++;
1583 break;
1584 }
1585 case ACPI_RESOURCE_TYPE_MEMORY24:
1586 {
1587 ACPI_RESOURCE_MEMORY24 *mem24_data = (ACPI_RESOURCE_MEMORY24*) &resource->Data;
1588 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1589 RequirementDescriptor->Type = CmResourceTypeMemory;
1590 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1591 RequirementDescriptor->Flags = CM_RESOURCE_MEMORY_24;
1592 if (mem24_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
1593 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1594 else
1595 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1596 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = mem24_data->Minimum;
1597 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = mem24_data->Maximum + mem24_data->AddressLength - 1;
1598 RequirementDescriptor->u.Memory.Length = mem24_data->AddressLength;
1599
1600 RequirementDescriptor++;
1601 break;
1602 }
1603 case ACPI_RESOURCE_TYPE_MEMORY32:
1604 {
1605 ACPI_RESOURCE_MEMORY32 *mem32_data = (ACPI_RESOURCE_MEMORY32*) &resource->Data;
1606 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1607 RequirementDescriptor->Type = CmResourceTypeMemory;
1608 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1609 RequirementDescriptor->Flags = 0;
1610 if (mem32_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
1611 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1612 else
1613 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1614 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = mem32_data->Minimum;
1615 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = mem32_data->Maximum + mem32_data->AddressLength - 1;
1616 RequirementDescriptor->u.Memory.Length = mem32_data->AddressLength;
1617
1618 RequirementDescriptor++;
1619 break;
1620 }
1621 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
1622 {
1623 ACPI_RESOURCE_FIXED_MEMORY32 *fixedmem32_data = (ACPI_RESOURCE_FIXED_MEMORY32*) &resource->Data;
1624 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1625 RequirementDescriptor->Type = CmResourceTypeMemory;
1626 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1627 RequirementDescriptor->Flags = 0;
1628 if (fixedmem32_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
1629 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1630 else
1631 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1632 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = fixedmem32_data->Address;
1633 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = fixedmem32_data->Address + fixedmem32_data->AddressLength - 1;
1634 RequirementDescriptor->u.Memory.Length = fixedmem32_data->AddressLength;
1635
1636 RequirementDescriptor++;
1637 break;
1638 }
1639 default:
1640 {
1641 break;
1642 }
1643 }
1644 resource = ACPI_NEXT_RESOURCE(resource);
1645 }
1646 ExFreePoolWithTag(Buffer.Pointer, 'IPCA');
1647
1648 Irp->IoStatus.Information = (ULONG_PTR)RequirementsList;
1649
1650 return STATUS_SUCCESS;
1651 }
1652
1653 NTSTATUS
1654 Bus_PDO_QueryDeviceRelations(
1655 PPDO_DEVICE_DATA DeviceData,
1656 PIRP Irp )
1657 /*++
1658
1659 Routine Description:
1660
1661 The PnP Manager sends this IRP to gather information about
1662 devices with a relationship to the specified device.
1663 Bus drivers must handle this request for TargetDeviceRelation
1664 for their child devices (child PDOs).
1665
1666 If a driver returns relations in response to this IRP,
1667 it allocates a DEVICE_RELATIONS structure from paged
1668 memory containing a count and the appropriate number of
1669 device object pointers. The PnP Manager frees the structure
1670 when it is no longer needed. If a driver replaces a
1671 DEVICE_RELATIONS structure allocated by another driver,
1672 it must free the previous structure.
1673
1674 A driver must reference the PDO of any device that it
1675 reports in this IRP (ObReferenceObject). The PnP Manager
1676 removes the reference when appropriate.
1677
1678 Arguments:
1679
1680 DeviceData - Pointer to the PDO's device extension.
1681 Irp - Pointer to the irp.
1682
1683 Return Value:
1684
1685 NT STATUS
1686
1687 --*/
1688 {
1689
1690 PIO_STACK_LOCATION stack;
1691 PDEVICE_RELATIONS deviceRelations;
1692 NTSTATUS status;
1693
1694 PAGED_CODE ();
1695
1696 stack = IoGetCurrentIrpStackLocation (Irp);
1697
1698 switch (stack->Parameters.QueryDeviceRelations.Type) {
1699
1700 case TargetDeviceRelation:
1701
1702 deviceRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information;
1703 if (deviceRelations) {
1704 //
1705 // Only PDO can handle this request. Somebody above
1706 // is not playing by rule.
1707 //
1708 ASSERTMSG("Someone above is handling TargetDeviceRelation", !deviceRelations);
1709 }
1710
1711 deviceRelations = (PDEVICE_RELATIONS)
1712 ExAllocatePoolWithTag (PagedPool,
1713 sizeof(DEVICE_RELATIONS),
1714 'IPCA');
1715 if (!deviceRelations) {
1716 status = STATUS_INSUFFICIENT_RESOURCES;
1717 break;
1718 }
1719
1720 //
1721 // There is only one PDO pointer in the structure
1722 // for this relation type. The PnP Manager removes
1723 // the reference to the PDO when the driver or application
1724 // un-registers for notification on the device.
1725 //
1726
1727 deviceRelations->Count = 1;
1728 deviceRelations->Objects[0] = DeviceData->Common.Self;
1729 ObReferenceObject(DeviceData->Common.Self);
1730
1731 status = STATUS_SUCCESS;
1732 Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
1733 break;
1734
1735 case BusRelations: // Not handled by PDO
1736 case EjectionRelations: // optional for PDO
1737 case RemovalRelations: // // optional for PDO
1738 default:
1739 status = Irp->IoStatus.Status;
1740 }
1741
1742 return status;
1743 }
1744
1745 NTSTATUS
1746 Bus_PDO_QueryBusInformation(
1747 PPDO_DEVICE_DATA DeviceData,
1748 PIRP Irp )
1749 /*++
1750
1751 Routine Description:
1752
1753 The PnP Manager uses this IRP to request the type and
1754 instance number of a device's parent bus. Bus drivers
1755 should handle this request for their child devices (PDOs).
1756
1757 Arguments:
1758
1759 DeviceData - Pointer to the PDO's device extension.
1760 Irp - Pointer to the irp.
1761
1762 Return Value:
1763
1764 NT STATUS
1765
1766 --*/
1767 {
1768
1769 PPNP_BUS_INFORMATION busInfo;
1770
1771 PAGED_CODE ();
1772
1773 busInfo = ExAllocatePoolWithTag (PagedPool, sizeof(PNP_BUS_INFORMATION),
1774 'IPCA');
1775
1776 if (busInfo == NULL) {
1777 return STATUS_INSUFFICIENT_RESOURCES;
1778 }
1779
1780 busInfo->BusTypeGuid = GUID_ACPI_INTERFACE_STANDARD;
1781
1782 busInfo->LegacyBusType = InternalPowerBus;
1783
1784 busInfo->BusNumber = 0; //fixme
1785
1786 Irp->IoStatus.Information = (ULONG_PTR)busInfo;
1787
1788 return STATUS_SUCCESS;
1789 }
1790
1791
1792 NTSTATUS
1793 Bus_GetDeviceCapabilities(
1794 PDEVICE_OBJECT DeviceObject,
1795 PDEVICE_CAPABILITIES DeviceCapabilities
1796 )
1797 {
1798 IO_STATUS_BLOCK ioStatus;
1799 KEVENT pnpEvent;
1800 NTSTATUS status;
1801 PDEVICE_OBJECT targetObject;
1802 PIO_STACK_LOCATION irpStack;
1803 PIRP pnpIrp;
1804
1805 PAGED_CODE();
1806
1807 //
1808 // Initialize the capabilities that we will send down
1809 //
1810 RtlZeroMemory( DeviceCapabilities, sizeof(DEVICE_CAPABILITIES) );
1811 DeviceCapabilities->Size = sizeof(DEVICE_CAPABILITIES);
1812 DeviceCapabilities->Version = 1;
1813 DeviceCapabilities->Address = -1;
1814 DeviceCapabilities->UINumber = -1;
1815
1816 //
1817 // Initialize the event
1818 //
1819 KeInitializeEvent( &pnpEvent, NotificationEvent, FALSE );
1820
1821 targetObject = IoGetAttachedDeviceReference( DeviceObject );
1822
1823 //
1824 // Build an Irp
1825 //
1826 pnpIrp = IoBuildSynchronousFsdRequest(
1827 IRP_MJ_PNP,
1828 targetObject,
1829 NULL,
1830 0,
1831 NULL,
1832 &pnpEvent,
1833 &ioStatus
1834 );
1835 if (pnpIrp == NULL) {
1836
1837 status = STATUS_INSUFFICIENT_RESOURCES;
1838 goto GetDeviceCapabilitiesExit;
1839
1840 }
1841
1842 //
1843 // Pnp Irps all begin life as STATUS_NOT_SUPPORTED;
1844 //
1845 pnpIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
1846
1847 //
1848 // Get the top of stack
1849 //
1850 irpStack = IoGetNextIrpStackLocation( pnpIrp );
1851
1852 //
1853 // Set the top of stack
1854 //
1855 RtlZeroMemory( irpStack, sizeof(IO_STACK_LOCATION ) );
1856 irpStack->MajorFunction = IRP_MJ_PNP;
1857 irpStack->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
1858 irpStack->Parameters.DeviceCapabilities.Capabilities = DeviceCapabilities;
1859
1860 //
1861 // Call the driver
1862 //
1863 status = IoCallDriver( targetObject, pnpIrp );
1864 if (status == STATUS_PENDING) {
1865
1866 //
1867 // Block until the irp comes back.
1868 // Important thing to note here is when you allocate
1869 // the memory for an event in the stack you must do a
1870 // KernelMode wait instead of UserMode to prevent
1871 // the stack from getting paged out.
1872 //
1873
1874 KeWaitForSingleObject(
1875 &pnpEvent,
1876 Executive,
1877 KernelMode,
1878 FALSE,
1879 NULL
1880 );
1881 status = ioStatus.Status;
1882
1883 }
1884
1885 GetDeviceCapabilitiesExit:
1886 //
1887 // Done with reference
1888 //
1889 ObDereferenceObject( targetObject );
1890
1891 //
1892 // Done
1893 //
1894 return status;
1895
1896 }
1897
1898