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