- Handle the special case of ACPI device, the fixed feature button, which is not...
[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
36 PAGED_CODE ();
37
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 DeviceData->Common.DevicePowerState = PowerDeviceD0;
55 SET_NEW_PNP_STATE(DeviceData->Common, Started);
56 status = STATUS_SUCCESS;
57 break;
58
59 case IRP_MN_STOP_DEVICE:
60
61 //
62 // Here we shut down the device and give up and unmap any resources
63 // we acquired for the device.
64 //
65
66 SET_NEW_PNP_STATE(DeviceData->Common, Stopped);
67 status = STATUS_SUCCESS;
68 break;
69
70
71 case IRP_MN_QUERY_STOP_DEVICE:
72
73 //
74 // No reason here why we can't stop the device.
75 // If there were a reason we should speak now, because answering success
76 // here may result in a stop device irp.
77 //
78
79 SET_NEW_PNP_STATE(DeviceData->Common, StopPending);
80 status = STATUS_SUCCESS;
81 break;
82
83 case IRP_MN_CANCEL_STOP_DEVICE:
84
85 //
86 // The stop was canceled. Whatever state we set, or resources we put
87 // on hold in anticipation of the forthcoming STOP device IRP should be
88 // put back to normal. Someone, in the long list of concerned parties,
89 // has failed the stop device query.
90 //
91
92 //
93 // First check to see whether you have received cancel-stop
94 // without first receiving a query-stop. This could happen if someone
95 // above us fails a query-stop and passes down the subsequent
96 // cancel-stop.
97 //
98
99 if (StopPending == DeviceData->Common.DevicePnPState)
100 {
101 //
102 // We did receive a query-stop, so restore.
103 //
104 RESTORE_PREVIOUS_PNP_STATE(DeviceData->Common);
105 }
106 status = STATUS_SUCCESS;// We must not fail this IRP.
107 break;
108 case IRP_MN_QUERY_CAPABILITIES:
109
110 //
111 // Return the capabilities of a device, such as whether the device
112 // can be locked or ejected..etc
113 //
114
115 status = Bus_PDO_QueryDeviceCaps(DeviceData, Irp);
116
117 break;
118
119 case IRP_MN_QUERY_ID:
120
121 // Query the IDs of the device
122 status = Bus_PDO_QueryDeviceId(DeviceData, Irp);
123
124 break;
125
126 case IRP_MN_QUERY_DEVICE_RELATIONS:
127
128 DPRINT("\tQueryDeviceRelation Type: %s\n",DbgDeviceRelationString(\
129 IrpStack->Parameters.QueryDeviceRelations.Type));
130
131 status = Bus_PDO_QueryDeviceRelations(DeviceData, Irp);
132
133 break;
134
135 case IRP_MN_QUERY_DEVICE_TEXT:
136
137 status = Bus_PDO_QueryDeviceText(DeviceData, Irp);
138
139 break;
140
141 case IRP_MN_QUERY_RESOURCES:
142
143 status = Bus_PDO_QueryResources(DeviceData, Irp);
144
145 break;
146
147 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
148
149 status = Bus_PDO_QueryResourceRequirements(DeviceData, Irp);
150
151 break;
152
153 case IRP_MN_QUERY_BUS_INFORMATION:
154
155 status = Bus_PDO_QueryBusInformation(DeviceData, Irp);
156
157 break;
158
159
160 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
161
162 //
163 // OPTIONAL for bus drivers.
164 // The PnP Manager sends this IRP to a device
165 // stack so filter and function drivers can adjust the
166 // resources required by the device, if appropriate.
167 //
168
169 //break;
170
171 //case IRP_MN_QUERY_PNP_DEVICE_STATE:
172
173 //
174 // OPTIONAL for bus drivers.
175 // The PnP Manager sends this IRP after the drivers for
176 // a device return success from the IRP_MN_START_DEVICE
177 // request. The PnP Manager also sends this IRP when a
178 // driver for the device calls IoInvalidateDeviceState.
179 //
180
181 // break;
182
183 //case IRP_MN_READ_CONFIG:
184 //case IRP_MN_WRITE_CONFIG:
185
186 //
187 // Bus drivers for buses with configuration space must handle
188 // this request for their child devices. Our devices don't
189 // have a config space.
190 //
191
192 // break;
193
194 //case IRP_MN_SET_LOCK:
195
196 // break;
197
198 default:
199
200 //
201 // For PnP requests to the PDO that we do not understand we should
202 // return the IRP WITHOUT setting the status or information fields.
203 // These fields may have already been set by a filter (eg acpi).
204 status = Irp->IoStatus.Status;
205
206 break;
207 }
208
209 Irp->IoStatus.Status = status;
210 IoCompleteRequest (Irp, IO_NO_INCREMENT);
211
212 return status;
213 }
214
215 //
216 // FIX ME FIX ME FIX ME !!!
217 //
218 NTSTATUS
219 Bus_PDO_QueryDeviceCaps(
220 PPDO_DEVICE_DATA DeviceData,
221 PIRP Irp )
222 {
223
224 PIO_STACK_LOCATION stack;
225 PDEVICE_CAPABILITIES deviceCapabilities;
226 DEVICE_CAPABILITIES parentCapabilities;
227 NTSTATUS status;
228
229 PAGED_CODE ();
230
231 stack = IoGetCurrentIrpStackLocation (Irp);
232
233 //
234 // Get the packet.
235 //
236 deviceCapabilities=stack->Parameters.DeviceCapabilities.Capabilities;
237
238 //
239 // Set the capabilities.
240 //
241
242 if (deviceCapabilities->Version != 1 ||
243 deviceCapabilities->Size < sizeof(DEVICE_CAPABILITIES))
244 {
245 return STATUS_UNSUCCESSFUL;
246 }
247
248 //
249 // Get the device capabilities of the parent
250 //
251 status = Bus_GetDeviceCapabilities(
252 FDO_FROM_PDO(DeviceData)->NextLowerDriver, &parentCapabilities);
253 if (!NT_SUCCESS(status)) {
254
255 DPRINT("\tQueryDeviceCaps failed\n");
256 return status;
257
258 }
259
260 //
261 // The entries in the DeviceState array are based on the capabilities
262 // of the parent devnode. These entries signify the highest-powered
263 // state that the device can support for the corresponding system
264 // state. A driver can specify a lower (less-powered) state than the
265 // bus driver. For eg: Suppose the acpi bus controller supports
266 // D0, D2, and D3; and the acpi Device supports D0, D1, D2, and D3.
267 // Following the above rule, the device cannot specify D1 as one of
268 // it's power state. A driver can make the rules more restrictive
269 // but cannot loosen them.
270 // First copy the parent's S to D state mapping
271 //
272
273 RtlCopyMemory(
274 deviceCapabilities->DeviceState,
275 parentCapabilities.DeviceState,
276 (PowerSystemShutdown + 1) * sizeof(DEVICE_POWER_STATE)
277 );
278
279 //
280 // Adjust the caps to what your device supports.
281 // Our device just supports D0 and D3.
282 //
283
284 deviceCapabilities->DeviceState[PowerSystemWorking] = PowerDeviceD0;
285
286 if (deviceCapabilities->DeviceState[PowerSystemSleeping1] != PowerDeviceD0)
287 deviceCapabilities->DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
288
289 if (deviceCapabilities->DeviceState[PowerSystemSleeping2] != PowerDeviceD0)
290 deviceCapabilities->DeviceState[PowerSystemSleeping2] = PowerDeviceD3;
291
292 if (deviceCapabilities->DeviceState[PowerSystemSleeping3] != PowerDeviceD0)
293 deviceCapabilities->DeviceState[PowerSystemSleeping3] = PowerDeviceD3;
294
295 // We can wake the system from D1
296 deviceCapabilities->DeviceWake = PowerDeviceD1;
297
298 //
299 // Specifies whether the device hardware supports the D1 and D2
300 // power state. Set these bits explicitly.
301 //
302
303 deviceCapabilities->DeviceD1 = TRUE; // Yes we can
304 deviceCapabilities->DeviceD2 = FALSE;
305
306 //
307 // Specifies whether the device can respond to an external wake
308 // signal while in the D0, D1, D2, and D3 state.
309 // Set these bits explicitly.
310 //
311
312 deviceCapabilities->WakeFromD0 = FALSE;
313 deviceCapabilities->WakeFromD1 = TRUE; //Yes we can
314 deviceCapabilities->WakeFromD2 = FALSE;
315 deviceCapabilities->WakeFromD3 = FALSE;
316
317
318 // We have no latencies
319
320 deviceCapabilities->D1Latency = 0;
321 deviceCapabilities->D2Latency = 0;
322 deviceCapabilities->D3Latency = 0;
323
324 // Ejection supported
325
326 deviceCapabilities->EjectSupported = TRUE;
327
328 //
329 // This flag specifies whether the device's hardware is disabled.
330 // The PnP Manager only checks this bit right after the device is
331 // enumerated. Once the device is started, this bit is ignored.
332 //
333 deviceCapabilities->HardwareDisabled = FALSE;
334
335 //
336 // Out simulated device can be physically removed.
337 //
338 deviceCapabilities->Removable = TRUE;
339 //
340 // Setting it to TURE prevents the warning dialog from appearing
341 // whenever the device is surprise removed.
342 //
343 deviceCapabilities->SurpriseRemovalOK = TRUE;
344
345 // We don't support system-wide unique IDs.
346
347 deviceCapabilities->UniqueID = FALSE;
348
349 //
350 // Specify whether the Device Manager should suppress all
351 // installation pop-ups except required pop-ups such as
352 // "no compatible drivers found."
353 //
354
355 deviceCapabilities->SilentInstall = FALSE;
356
357 //
358 // Specifies an address indicating where the device is located
359 // on its underlying bus. The interpretation of this number is
360 // bus-specific. If the address is unknown or the bus driver
361 // does not support an address, the bus driver leaves this
362 // member at its default value of 0xFFFFFFFF. In this example
363 // the location address is same as instance id.
364 //
365
366 //deviceCapabilities->Address = DeviceData->SerialNo;
367
368 //
369 // UINumber specifies a number associated with the device that can
370 // be displayed in the user interface.
371 //
372 //deviceCapabilities->UINumber = DeviceData->SerialNo;
373
374 return STATUS_SUCCESS;
375
376 }
377
378 NTSTATUS
379 Bus_PDO_QueryDeviceId(
380 PPDO_DEVICE_DATA DeviceData,
381 PIRP Irp )
382 {
383 PIO_STACK_LOCATION stack;
384 PWCHAR buffer;
385 WCHAR temp[256];
386 ULONG length;
387 NTSTATUS status = STATUS_SUCCESS;
388 struct acpi_device *Device;
389
390 PAGED_CODE ();
391
392 stack = IoGetCurrentIrpStackLocation (Irp);
393
394 switch (stack->Parameters.QueryId.IdType) {
395
396 case BusQueryDeviceID:
397 if (DeviceData->AcpiHandle)
398 {
399 acpi_bus_get_device(DeviceData->AcpiHandle, &Device);
400
401 length = swprintf(temp,
402 L"ACPI\\%hs",
403 Device->pnp.hardware_id);
404 }
405 else
406 {
407 /* We know it's a fixed feature button because
408 * these are direct children of the ACPI root device
409 * and therefore have no handle
410 */
411 length = swprintf(temp,
412 L"ACPI\\FixedButton");
413 }
414
415 temp[++length] = UNICODE_NULL;
416
417 buffer = ExAllocatePoolWithTag (PagedPool, length * sizeof(WCHAR), 'IPCA');
418
419 if (!buffer) {
420 status = STATUS_INSUFFICIENT_RESOURCES;
421 break;
422 }
423
424 RtlCopyMemory (buffer, temp, length * sizeof(WCHAR));
425 Irp->IoStatus.Information = (ULONG_PTR) buffer;
426 DPRINT("BusQueryDeviceID: %ls\n",buffer);
427 break;
428
429 case BusQueryInstanceID:
430 /* See comment in BusQueryDeviceID case */
431 if(DeviceData->AcpiHandle)
432 {
433 acpi_bus_get_device(DeviceData->AcpiHandle, &Device);
434
435 if (Device->flags.unique_id)
436 length = swprintf(temp,
437 L"%hs",
438 Device->pnp.unique_id);
439 else
440 /* FIXME: Generate unique id! */
441 length = swprintf(temp, L"%ls", L"0000");
442 }
443 else
444 /* FIXME: Generate unique id! */
445 length = swprintf(temp, L"%ls", L"0000");
446
447 temp[++length] = UNICODE_NULL;
448
449 buffer = ExAllocatePoolWithTag (PagedPool, length * sizeof (WCHAR), 'IPCA');
450 if (!buffer) {
451 status = STATUS_INSUFFICIENT_RESOURCES;
452 break;
453 }
454
455 RtlCopyMemory (buffer, temp, length * sizeof (WCHAR));
456 DPRINT("BusQueryInstanceID: %ls\n",buffer);
457 Irp->IoStatus.Information = (ULONG_PTR) buffer;
458 break;
459
460 case BusQueryHardwareIDs:
461 length = 0;
462
463 /* See comment in BusQueryDeviceID case */
464 if (DeviceData->AcpiHandle)
465 {
466 acpi_bus_get_device(DeviceData->AcpiHandle, &Device);
467
468 length += swprintf(&temp[length],
469 L"ACPI\\%hs",
470 Device->pnp.hardware_id);
471 length++;
472
473 length += swprintf(&temp[length],
474 L"*%hs",
475 Device->pnp.hardware_id);
476 length++;
477 }
478 else
479 {
480 length += swprintf(&temp[length],
481 L"ACPI\\FixedButton");
482 length++;
483
484 length += swprintf(&temp[length],
485 L"*FixedButton");
486 length++;
487 }
488
489 temp[length] = UNICODE_NULL;
490
491 length++;
492
493 temp[length] = UNICODE_NULL;
494
495 buffer = ExAllocatePoolWithTag (PagedPool, length * sizeof(WCHAR), 'IPCA');
496
497 if (!buffer) {
498 status = STATUS_INSUFFICIENT_RESOURCES;
499 break;
500 }
501
502 RtlCopyMemory (buffer, temp, length * sizeof(WCHAR));
503 Irp->IoStatus.Information = (ULONG_PTR) buffer;
504 DPRINT("BusQueryHardwareIDs: %ls\n",buffer);
505 break;
506
507 default:
508 status = Irp->IoStatus.Status;
509 }
510 return status;
511 }
512
513 NTSTATUS
514 Bus_PDO_QueryDeviceText(
515 PPDO_DEVICE_DATA DeviceData,
516 PIRP Irp )
517 {
518 PWCHAR Buffer;
519 PIO_STACK_LOCATION stack;
520 NTSTATUS status;
521 PAGED_CODE ();
522
523 stack = IoGetCurrentIrpStackLocation (Irp);
524
525 switch (stack->Parameters.QueryDeviceText.DeviceTextType) {
526
527 case DeviceTextDescription:
528
529 if (!Irp->IoStatus.Information) {
530 if (wcsstr (DeviceData->HardwareIDs, L"PNP000") != 0)
531 Buffer = L"Programmable interrupt controller";
532 else if (wcsstr(DeviceData->HardwareIDs, L"PNP010") != 0)
533 Buffer = L"System timer";
534 else if (wcsstr(DeviceData->HardwareIDs, L"PNP020") != 0)
535 Buffer = L"DMA controller";
536 else if (wcsstr(DeviceData->HardwareIDs, L"PNP03") != 0)
537 Buffer = L"Keyboard";
538 else if (wcsstr(DeviceData->HardwareIDs, L"PNP040") != 0)
539 Buffer = L"Parallel port";
540 else if (wcsstr(DeviceData->HardwareIDs, L"PNP05") != 0)
541 Buffer = L"Serial port";
542 else if (wcsstr(DeviceData->HardwareIDs, L"PNP06") != 0)
543 Buffer = L"Disk controller";
544 else if (wcsstr(DeviceData->HardwareIDs, L"PNP07") != 0)
545 Buffer = L"Disk controller";
546 else if (wcsstr(DeviceData->HardwareIDs, L"PNP09") != 0)
547 Buffer = L"Display adapter";
548 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0A0") != 0)
549 Buffer = L"Bus controller";
550 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0E0") != 0)
551 Buffer = L"PCMCIA controller";
552 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0F") != 0)
553 Buffer = L"Mouse device";
554 else if (wcsstr(DeviceData->HardwareIDs, L"PNP8") != 0)
555 Buffer = L"Network adapter";
556 else if (wcsstr(DeviceData->HardwareIDs, L"PNPA0") != 0)
557 Buffer = L"SCSI controller";
558 else if (wcsstr(DeviceData->HardwareIDs, L"PNPB0") != 0)
559 Buffer = L"Multimedia device";
560 else if (wcsstr(DeviceData->HardwareIDs, L"PNPC00") != 0)
561 Buffer = L"Modem";
562 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0C") != 0)
563 Buffer = L"Power Button";
564 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0E") != 0)
565 Buffer = L"Sleep Button";
566 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0D") != 0)
567 Buffer = L"Lid Switch";
568 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C09") != 0)
569 Buffer = L"ACPI Embedded Controller";
570 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0B") != 0)
571 Buffer = L"ACPI Fan";
572 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0A03") != 0)
573 Buffer = L"PCI Root Bridge";
574 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0A") != 0)
575 Buffer = L"ACPI Battery";
576 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0F") != 0)
577 Buffer = L"PCI Interrupt Link";
578 else if (wcsstr(DeviceData->HardwareIDs, L"ACPI_PWR") != 0)
579 Buffer = L"ACPI Power Resource";
580 else if (wcsstr(DeviceData->HardwareIDs, L"Processor") != 0)
581 Buffer = L"Processor";
582 else if (wcsstr(DeviceData->HardwareIDs, L"ACPI_SYS") != 0)
583 Buffer = L"ACPI System";
584 else if (wcsstr(DeviceData->HardwareIDs, L"ThermalZone") != 0)
585 Buffer = L"ACPI Thermal Zone";
586 else if (wcsstr(DeviceData->HardwareIDs, L"ACPI0002") != 0)
587 Buffer = L"Smart Battery";
588 else if (wcsstr(DeviceData->HardwareIDs, L"ACPI0003") != 0)
589 Buffer = L"AC Adapter";
590 /* Simply checking if AcpiHandle is NULL eliminates the need to check
591 * for the 4 different names that ACPI knows the fixed feature button as internally
592 */
593 else if (!DeviceData->AcpiHandle)
594 Buffer = L"ACPI Fixed Feature Button";
595 else
596 Buffer = L"Other ACPI device";
597
598 DPRINT("\tDeviceTextDescription :%ws\n", Buffer);
599
600 Irp->IoStatus.Information = (ULONG_PTR) Buffer;
601 }
602 status = STATUS_SUCCESS;
603 break;
604
605 default:
606 status = Irp->IoStatus.Status;
607 break;
608 }
609
610 return status;
611
612 }
613
614 NTSTATUS
615 Bus_PDO_QueryResources(
616 PPDO_DEVICE_DATA DeviceData,
617 PIRP Irp )
618 {
619 BOOLEAN Done;
620 ULONG NumberOfResources = 0;
621 PCM_RESOURCE_LIST ResourceList;
622 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor;
623 ACPI_STATUS AcpiStatus;
624 ACPI_BUFFER Buffer;
625 ACPI_RESOURCE* resource;
626 ULONG ResourceListSize;
627 ULONG i;
628
629 ULONG RequirementsListSize;
630 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
631 PIO_RESOURCE_DESCRIPTOR RequirementDescriptor;
632
633
634 /* Get current resources */
635 Buffer.Length = 0;
636 AcpiStatus = AcpiGetCurrentResources(DeviceData->AcpiHandle, &Buffer);
637 if (!ACPI_SUCCESS(AcpiStatus))
638 {
639 return STATUS_SUCCESS;
640 }
641 if (Buffer.Length > 0)
642 {
643 Buffer.Pointer = ExAllocatePool(PagedPool, Buffer.Length);
644 if (!Buffer.Pointer)
645 {
646 ASSERT(FALSE);
647 }
648 AcpiStatus = AcpiGetCurrentResources(DeviceData->AcpiHandle, &Buffer);
649 if (!ACPI_SUCCESS(AcpiStatus))
650 {
651 ASSERT(FALSE);
652 }
653 }
654
655 resource= Buffer.Pointer;
656 /* Count number of resources */
657 Done = FALSE;
658 while (!Done)
659 {
660 switch (resource->Type)
661 {
662 case ACPI_RESOURCE_TYPE_IRQ:
663 {
664 ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
665 NumberOfResources += irq_data->InterruptCount;
666 break;
667 }
668 case ACPI_RESOURCE_TYPE_DMA:
669 {
670 ACPI_RESOURCE_DMA *dma_data = (ACPI_RESOURCE_DMA*) &resource->Data;
671 NumberOfResources += dma_data->ChannelCount;
672 break;
673 }
674 case ACPI_RESOURCE_TYPE_IO:
675 {
676 NumberOfResources++;
677 break;
678 }
679 case ACPI_RESOURCE_TYPE_END_TAG:
680 {
681 Done = TRUE;
682 break;
683 }
684 default:
685 {
686 break;
687 }
688 }
689 resource = ACPI_NEXT_RESOURCE(resource);
690 }
691
692 /* Allocate memory */
693 ResourceListSize = sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * (NumberOfResources - 1);
694 ResourceList = (PCM_RESOURCE_LIST)ExAllocatePool(PagedPool, ResourceListSize);
695
696 if (!ResourceList)
697 return FALSE;
698 ResourceList->Count = 1;
699 ResourceList->List[0].InterfaceType = Internal; /* FIXME */
700 ResourceList->List[0].BusNumber = 0; /* We're the only ACPI bus device in the system */
701 ResourceList->List[0].PartialResourceList.Version = 1;
702 ResourceList->List[0].PartialResourceList.Revision = 1;
703 ResourceList->List[0].PartialResourceList.Count = NumberOfResources;
704 ResourceDescriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
705
706 RequirementsListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) + sizeof(IO_RESOURCE_DESCRIPTOR) * (NumberOfResources - 1);
707 RequirementsList = (PIO_RESOURCE_REQUIREMENTS_LIST)ExAllocatePool(PagedPool, RequirementsListSize);
708
709 if (!RequirementsList)
710 {
711 ExFreePool(ResourceList);
712 return STATUS_SUCCESS;
713 }
714 RequirementsList->ListSize = RequirementsListSize;
715 RequirementsList->InterfaceType = Internal;
716 RequirementsList->BusNumber = 0;
717 RequirementsList->SlotNumber = 0; /* Not used by WDM drivers */
718 RequirementsList->AlternativeLists = 1;
719 RequirementsList->List[0].Version = 1;
720 RequirementsList->List[0].Revision = 1;
721 RequirementsList->List[0].Count = NumberOfResources;
722 RequirementDescriptor = RequirementsList->List[0].Descriptors;
723
724 /* Fill resources list structure */
725 Done = FALSE;
726 while (!Done)
727 {
728 switch (resource->Type)
729 {
730 case ACPI_RESOURCE_TYPE_IRQ:
731 {
732 ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
733 for (i = 0; i < irq_data->InterruptCount; i++)
734 {
735 ResourceDescriptor->Type = CmResourceTypeInterrupt;
736
737 ResourceDescriptor->ShareDisposition =
738 (irq_data->Sharable == ACPI_SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
739 ResourceDescriptor->Flags =
740 (irq_data->Triggering == ACPI_LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
741 ResourceDescriptor->u.Interrupt.Level = irq_data->Interrupts[i];
742 ResourceDescriptor->u.Interrupt.Vector = 0;
743 ResourceDescriptor->u.Interrupt.Affinity = (KAFFINITY)(-1);
744
745 RequirementDescriptor->Option = 0; /* Required */
746 RequirementDescriptor->Type = ResourceDescriptor->Type;
747 RequirementDescriptor->ShareDisposition = ResourceDescriptor->ShareDisposition;
748 RequirementDescriptor->Flags = ResourceDescriptor->Flags;
749 RequirementDescriptor->u.Interrupt.MinimumVector = RequirementDescriptor->u.Interrupt.MaximumVector
750 = irq_data->Interrupts[i];
751
752 ResourceDescriptor++;
753 RequirementDescriptor++;
754 }
755 break;
756 }
757 case ACPI_RESOURCE_TYPE_DMA:
758 {
759 ACPI_RESOURCE_DMA *dma_data = (ACPI_RESOURCE_DMA*) &resource->Data;
760 for (i = 0; i < dma_data->ChannelCount; i++)
761 {
762 ResourceDescriptor->Type = CmResourceTypeDma;
763 ResourceDescriptor->Flags = 0;
764 switch (dma_data->Type)
765 {
766 case ACPI_TYPE_A: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_A; break;
767 case ACPI_TYPE_B: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_B; break;
768 case ACPI_TYPE_F: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_F; break;
769 }
770 if (dma_data->BusMaster == ACPI_BUS_MASTER)
771 ResourceDescriptor->Flags |= CM_RESOURCE_DMA_BUS_MASTER;
772 switch (dma_data->Transfer)
773 {
774 case ACPI_TRANSFER_8: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_8; break;
775 case ACPI_TRANSFER_16: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_16; break;
776 case ACPI_TRANSFER_8_16: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_8_AND_16; break;
777 }
778 ResourceDescriptor->u.Dma.Channel = dma_data->Channels[i];
779
780 RequirementDescriptor->Option = 0; /* Required */
781 RequirementDescriptor->Type = ResourceDescriptor->Type;
782 RequirementDescriptor->ShareDisposition = ResourceDescriptor->ShareDisposition;
783 RequirementDescriptor->Flags = ResourceDescriptor->Flags;
784 RequirementDescriptor->u.Dma.MinimumChannel = RequirementDescriptor->u.Dma.MaximumChannel
785 = ResourceDescriptor->u.Dma.Channel;
786
787 ResourceDescriptor++;
788 RequirementDescriptor++;
789 }
790 break;
791 }
792 case ACPI_RESOURCE_TYPE_IO:
793 {
794 ACPI_RESOURCE_IO *io_data = (ACPI_RESOURCE_IO*) &resource->Data;
795 ResourceDescriptor->Type = CmResourceTypePort;
796 ResourceDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
797 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
798 if (io_data->IoDecode == ACPI_DECODE_16)
799 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
800 else
801 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
802 ResourceDescriptor->u.Port.Start.u.HighPart = 0;
803 ResourceDescriptor->u.Port.Start.u.LowPart = io_data->Minimum;
804 ResourceDescriptor->u.Port.Length = io_data->AddressLength;
805
806 RequirementDescriptor->Option = 0; /* Required */
807 RequirementDescriptor->Type = ResourceDescriptor->Type;
808 RequirementDescriptor->ShareDisposition = ResourceDescriptor->ShareDisposition;
809 RequirementDescriptor->Flags = ResourceDescriptor->Flags;
810 RequirementDescriptor->u.Port.Length = ResourceDescriptor->u.Port.Length;
811 RequirementDescriptor->u.Port.Alignment = 1; /* Start address is specified, so it doesn't matter */
812 RequirementDescriptor->u.Port.MinimumAddress = RequirementDescriptor->u.Port.MaximumAddress
813 = ResourceDescriptor->u.Port.Start;
814
815 ResourceDescriptor++;
816 RequirementDescriptor++;
817 break;
818 }
819 case ACPI_RESOURCE_TYPE_END_TAG:
820 {
821 Done = TRUE;
822 break;
823 }
824 default:
825 {
826 DPRINT1("Unhandled resource type\n");
827 break;
828 }
829 }
830 resource = ACPI_NEXT_RESOURCE(resource);
831 }
832
833 ExFreePool(Buffer.Pointer);
834 Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
835 return STATUS_SUCCESS;
836 }
837
838 NTSTATUS
839 Bus_PDO_QueryResourceRequirements(
840 PPDO_DEVICE_DATA DeviceData,
841 PIRP Irp )
842 {
843 BOOLEAN Done;
844 ULONG NumberOfResources = 0;
845 ACPI_STATUS AcpiStatus;
846 ACPI_BUFFER Buffer;
847 ACPI_RESOURCE* resource;
848 ULONG i, RequirementsListSize;
849 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
850 PIO_RESOURCE_DESCRIPTOR RequirementDescriptor;
851
852 PAGED_CODE ();
853
854
855 /* Get current resources */
856 Buffer.Length = 0;
857 AcpiStatus = AcpiGetCurrentResources(DeviceData->AcpiHandle, &Buffer);
858 if (!ACPI_SUCCESS(AcpiStatus))
859 {
860 return STATUS_SUCCESS;
861 }
862 if (Buffer.Length > 0)
863 {
864 Buffer.Pointer = ExAllocatePool(PagedPool, Buffer.Length);
865 if (!Buffer.Pointer)
866 {
867 ASSERT(FALSE);
868 }
869 AcpiStatus = AcpiGetCurrentResources(DeviceData->AcpiHandle, &Buffer);
870 if (!ACPI_SUCCESS(AcpiStatus))
871 {
872 ASSERT(FALSE);
873 }
874 }
875
876 resource= Buffer.Pointer;
877 /* Count number of resources */
878 Done = FALSE;
879 while (!Done)
880 {
881 switch (resource->Type)
882 {
883 case ACPI_RESOURCE_TYPE_IRQ:
884 {
885 ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
886 NumberOfResources += irq_data->InterruptCount;
887 break;
888 }
889 case ACPI_RESOURCE_TYPE_DMA:
890 {
891 ACPI_RESOURCE_DMA *dma_data = (ACPI_RESOURCE_DMA*) &resource->Data;
892 NumberOfResources += dma_data->ChannelCount;
893 break;
894 }
895 case ACPI_RESOURCE_TYPE_IO:
896 {
897 NumberOfResources++;
898 break;
899 }
900 case ACPI_RESOURCE_TYPE_END_TAG:
901 {
902 Done = TRUE;
903 break;
904 }
905 default:
906 {
907 break;
908 }
909 }
910 resource = ACPI_NEXT_RESOURCE(resource);
911 }
912
913 RequirementsListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) + sizeof(IO_RESOURCE_DESCRIPTOR) * (NumberOfResources - 1);
914 RequirementsList = (PIO_RESOURCE_REQUIREMENTS_LIST)ExAllocatePool(PagedPool, RequirementsListSize);
915
916 if (!RequirementsList)
917 {
918 ExFreePool(Buffer.Pointer);
919 return STATUS_SUCCESS;
920 }
921 RequirementsList->ListSize = RequirementsListSize;
922 RequirementsList->InterfaceType = Internal;
923 RequirementsList->BusNumber = 0;
924 RequirementsList->SlotNumber = 0; /* Not used by WDM drivers */
925 RequirementsList->AlternativeLists = 1;
926 RequirementsList->List[0].Version = 1;
927 RequirementsList->List[0].Revision = 1;
928 RequirementsList->List[0].Count = NumberOfResources;
929 RequirementDescriptor = RequirementsList->List[0].Descriptors;
930
931 /* Fill resources list structure */
932 Done = FALSE;
933 while (!Done)
934 {
935 switch (resource->Type)
936 {
937 case ACPI_RESOURCE_TYPE_IRQ:
938 {
939 ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
940 for (i = 0; i < irq_data->InterruptCount; i++)
941 {
942 RequirementDescriptor->Option = 0; /* Required */
943 RequirementDescriptor->Type = CmResourceTypeInterrupt;
944 RequirementDescriptor->ShareDisposition = (irq_data->Sharable == ACPI_SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
945 RequirementDescriptor->Flags =(irq_data->Triggering == ACPI_LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
946 RequirementDescriptor->u.Interrupt.MinimumVector = irq_data->Interrupts[i];
947
948 RequirementDescriptor++;
949 }
950 break;
951 }
952 case ACPI_RESOURCE_TYPE_DMA:
953 {
954 ACPI_RESOURCE_DMA *dma_data = (ACPI_RESOURCE_DMA*) &resource->Data;
955 for (i = 0; i < dma_data->ChannelCount; i++)
956 {
957 RequirementDescriptor->Type = CmResourceTypeDma;
958 RequirementDescriptor->Flags = 0;
959 switch (dma_data->Type)
960 {
961 case ACPI_TYPE_A: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_A; break;
962 case ACPI_TYPE_B: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_B; break;
963 case ACPI_TYPE_F: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_F; break;
964 }
965 if (dma_data->BusMaster == ACPI_BUS_MASTER)
966 RequirementDescriptor->Flags |= CM_RESOURCE_DMA_BUS_MASTER;
967 switch (dma_data->Transfer)
968 {
969 case ACPI_TRANSFER_8: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_8; break;
970 case ACPI_TRANSFER_16: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_16; break;
971 case ACPI_TRANSFER_8_16: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_8_AND_16; break;
972 }
973
974 RequirementDescriptor->Option = 0; /* Required */
975 RequirementDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
976 RequirementDescriptor->u.Dma.MinimumChannel = dma_data->Channels[i];
977 RequirementDescriptor++;
978 }
979 break;
980 }
981 case ACPI_RESOURCE_TYPE_IO:
982 {
983 ACPI_RESOURCE_IO *io_data = (ACPI_RESOURCE_IO*) &resource->Data;
984 RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
985 if (io_data->IoDecode == ACPI_DECODE_16)
986 RequirementDescriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
987 else
988 RequirementDescriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
989
990 RequirementDescriptor->u.Port.Length = io_data->AddressLength;
991
992 RequirementDescriptor->Option = 0; /* Required */
993 RequirementDescriptor->Type = CmResourceTypePort;
994 RequirementDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
995 RequirementDescriptor->u.Port.Alignment = 1; /* Start address is specified, so it doesn't matter */
996 RequirementDescriptor->u.Port.MinimumAddress.QuadPart = io_data->Minimum;
997 RequirementDescriptor->u.Port.MaximumAddress.QuadPart = io_data->Maximum;
998
999 RequirementDescriptor++;
1000 break;
1001 }
1002 case ACPI_RESOURCE_TYPE_END_TAG:
1003 {
1004 Done = TRUE;
1005 break;
1006 }
1007 default:
1008 {
1009 DPRINT1("Unhandled resource type\n");
1010 break;
1011 }
1012 }
1013 resource = ACPI_NEXT_RESOURCE(resource);
1014 }
1015 ExFreePool(Buffer.Pointer);
1016
1017 return STATUS_SUCCESS;
1018 }
1019
1020 NTSTATUS
1021 Bus_PDO_QueryDeviceRelations(
1022 PPDO_DEVICE_DATA DeviceData,
1023 PIRP Irp )
1024 /*++
1025
1026 Routine Description:
1027
1028 The PnP Manager sends this IRP to gather information about
1029 devices with a relationship to the specified device.
1030 Bus drivers must handle this request for TargetDeviceRelation
1031 for their child devices (child PDOs).
1032
1033 If a driver returns relations in response to this IRP,
1034 it allocates a DEVICE_RELATIONS structure from paged
1035 memory containing a count and the appropriate number of
1036 device object pointers. The PnP Manager frees the structure
1037 when it is no longer needed. If a driver replaces a
1038 DEVICE_RELATIONS structure allocated by another driver,
1039 it must free the previous structure.
1040
1041 A driver must reference the PDO of any device that it
1042 reports in this IRP (ObReferenceObject). The PnP Manager
1043 removes the reference when appropriate.
1044
1045 Arguments:
1046
1047 DeviceData - Pointer to the PDO's device extension.
1048 Irp - Pointer to the irp.
1049
1050 Return Value:
1051
1052 NT STATUS
1053
1054 --*/
1055 {
1056
1057 PIO_STACK_LOCATION stack;
1058 PDEVICE_RELATIONS deviceRelations;
1059 NTSTATUS status;
1060
1061 PAGED_CODE ();
1062
1063 stack = IoGetCurrentIrpStackLocation (Irp);
1064
1065 switch (stack->Parameters.QueryDeviceRelations.Type) {
1066
1067 case TargetDeviceRelation:
1068
1069 deviceRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information;
1070 if (deviceRelations) {
1071 //
1072 // Only PDO can handle this request. Somebody above
1073 // is not playing by rule.
1074 //
1075 ASSERTMSG("Someone above is handling TargetDeviceRelation", !deviceRelations);
1076 }
1077
1078 deviceRelations = (PDEVICE_RELATIONS)
1079 ExAllocatePoolWithTag (PagedPool,
1080 sizeof(DEVICE_RELATIONS),
1081 'IPCA');
1082 if (!deviceRelations) {
1083 status = STATUS_INSUFFICIENT_RESOURCES;
1084 break;
1085 }
1086
1087 //
1088 // There is only one PDO pointer in the structure
1089 // for this relation type. The PnP Manager removes
1090 // the reference to the PDO when the driver or application
1091 // un-registers for notification on the device.
1092 //
1093
1094 deviceRelations->Count = 1;
1095 deviceRelations->Objects[0] = DeviceData->Common.Self;
1096 ObReferenceObject(DeviceData->Common.Self);
1097
1098 status = STATUS_SUCCESS;
1099 Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
1100 break;
1101
1102 case BusRelations: // Not handled by PDO
1103 case EjectionRelations: // optional for PDO
1104 case RemovalRelations: // // optional for PDO
1105 default:
1106 status = Irp->IoStatus.Status;
1107 }
1108
1109 return status;
1110 }
1111
1112 NTSTATUS
1113 Bus_PDO_QueryBusInformation(
1114 PPDO_DEVICE_DATA DeviceData,
1115 PIRP Irp )
1116 /*++
1117
1118 Routine Description:
1119
1120 The PnP Manager uses this IRP to request the type and
1121 instance number of a device's parent bus. Bus drivers
1122 should handle this request for their child devices (PDOs).
1123
1124 Arguments:
1125
1126 DeviceData - Pointer to the PDO's device extension.
1127 Irp - Pointer to the irp.
1128
1129 Return Value:
1130
1131 NT STATUS
1132
1133 --*/
1134 {
1135
1136 PPNP_BUS_INFORMATION busInfo;
1137
1138 PAGED_CODE ();
1139
1140 busInfo = ExAllocatePoolWithTag (PagedPool, sizeof(PNP_BUS_INFORMATION),
1141 'IPCA');
1142
1143 if (busInfo == NULL) {
1144 return STATUS_INSUFFICIENT_RESOURCES;
1145 }
1146
1147 busInfo->BusTypeGuid = GUID_ACPI_INTERFACE_STANDARD;
1148
1149 busInfo->LegacyBusType = InternalPowerBus;
1150
1151 busInfo->BusNumber = 0; //fixme
1152
1153 Irp->IoStatus.Information = (ULONG_PTR)busInfo;
1154
1155 return STATUS_SUCCESS;
1156 }
1157
1158
1159 NTSTATUS
1160 Bus_GetDeviceCapabilities(
1161 PDEVICE_OBJECT DeviceObject,
1162 PDEVICE_CAPABILITIES DeviceCapabilities
1163 )
1164 {
1165 IO_STATUS_BLOCK ioStatus;
1166 KEVENT pnpEvent;
1167 NTSTATUS status;
1168 PDEVICE_OBJECT targetObject;
1169 PIO_STACK_LOCATION irpStack;
1170 PIRP pnpIrp;
1171
1172 PAGED_CODE();
1173
1174 //
1175 // Initialize the capabilities that we will send down
1176 //
1177 RtlZeroMemory( DeviceCapabilities, sizeof(DEVICE_CAPABILITIES) );
1178 DeviceCapabilities->Size = sizeof(DEVICE_CAPABILITIES);
1179 DeviceCapabilities->Version = 1;
1180 DeviceCapabilities->Address = -1;
1181 DeviceCapabilities->UINumber = -1;
1182
1183 //
1184 // Initialize the event
1185 //
1186 KeInitializeEvent( &pnpEvent, NotificationEvent, FALSE );
1187
1188 targetObject = IoGetAttachedDeviceReference( DeviceObject );
1189
1190 //
1191 // Build an Irp
1192 //
1193 pnpIrp = IoBuildSynchronousFsdRequest(
1194 IRP_MJ_PNP,
1195 targetObject,
1196 NULL,
1197 0,
1198 NULL,
1199 &pnpEvent,
1200 &ioStatus
1201 );
1202 if (pnpIrp == NULL) {
1203
1204 status = STATUS_INSUFFICIENT_RESOURCES;
1205 goto GetDeviceCapabilitiesExit;
1206
1207 }
1208
1209 //
1210 // Pnp Irps all begin life as STATUS_NOT_SUPPORTED;
1211 //
1212 pnpIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
1213
1214 //
1215 // Get the top of stack
1216 //
1217 irpStack = IoGetNextIrpStackLocation( pnpIrp );
1218
1219 //
1220 // Set the top of stack
1221 //
1222 RtlZeroMemory( irpStack, sizeof(IO_STACK_LOCATION ) );
1223 irpStack->MajorFunction = IRP_MJ_PNP;
1224 irpStack->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
1225 irpStack->Parameters.DeviceCapabilities.Capabilities = DeviceCapabilities;
1226
1227 //
1228 // Call the driver
1229 //
1230 status = IoCallDriver( targetObject, pnpIrp );
1231 if (status == STATUS_PENDING) {
1232
1233 //
1234 // Block until the irp comes back.
1235 // Important thing to note here is when you allocate
1236 // the memory for an event in the stack you must do a
1237 // KernelMode wait instead of UserMode to prevent
1238 // the stack from getting paged out.
1239 //
1240
1241 KeWaitForSingleObject(
1242 &pnpEvent,
1243 Executive,
1244 KernelMode,
1245 FALSE,
1246 NULL
1247 );
1248 status = ioStatus.Status;
1249
1250 }
1251
1252 GetDeviceCapabilitiesExit:
1253 //
1254 // Done with reference
1255 //
1256 ObDereferenceObject( targetObject );
1257
1258 //
1259 // Done
1260 //
1261 return status;
1262
1263 }
1264
1265