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