2f1ff5a08f31458d1d16ce4b23d11535a528117f
[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 acpi_bus_get_device(DeviceData->AcpiHandle, &Device);
398
399 length = swprintf(temp,
400 L"ACPI\\%hs",
401 Device->pnp.hardware_id);
402
403 temp[++length] = UNICODE_NULL;
404
405 buffer = ExAllocatePoolWithTag (PagedPool, length * sizeof(WCHAR), 'IPCA');
406
407 if (!buffer) {
408 status = STATUS_INSUFFICIENT_RESOURCES;
409 break;
410 }
411
412 RtlCopyMemory (buffer, temp, length * sizeof(WCHAR));
413 Irp->IoStatus.Information = (ULONG_PTR) buffer;
414 DPRINT("BusQueryDeviceID: %ls\n",buffer);
415 break;
416
417 case BusQueryInstanceID:
418 acpi_bus_get_device(DeviceData->AcpiHandle, &Device);
419
420 if(Device->flags.unique_id)
421 length = swprintf(temp,
422 L"%hs",
423 Device->pnp.unique_id);
424 else
425 /* FIXME: Generate unique id! */
426 length = swprintf(temp, L"%ls", L"0000");
427
428 temp[++length] = UNICODE_NULL;
429
430 buffer = ExAllocatePoolWithTag (PagedPool, length * sizeof (WCHAR), 'IPCA');
431 if (!buffer) {
432 status = STATUS_INSUFFICIENT_RESOURCES;
433 break;
434 }
435
436 RtlCopyMemory (buffer, temp, length * sizeof (WCHAR));
437 DPRINT("BusQueryInstanceID: %ls\n",buffer);
438 Irp->IoStatus.Information = (ULONG_PTR) buffer;
439 break;
440
441 case BusQueryHardwareIDs:
442 acpi_bus_get_device(DeviceData->AcpiHandle, &Device);
443
444 length = 0;
445
446 length += swprintf(&temp[length],
447 L"ACPI\\%hs",
448 Device->pnp.hardware_id);
449 length++;
450
451 length += swprintf(&temp[length],
452 L"*%hs",
453 Device->pnp.hardware_id);
454 length++;
455
456 temp[length] = UNICODE_NULL;
457
458 length++;
459
460 temp[length] = UNICODE_NULL;
461
462 buffer = ExAllocatePoolWithTag (PagedPool, length * sizeof(WCHAR), 'IPCA');
463
464 if (!buffer) {
465 status = STATUS_INSUFFICIENT_RESOURCES;
466 break;
467 }
468
469 RtlCopyMemory (buffer, temp, length * sizeof(WCHAR));
470 Irp->IoStatus.Information = (ULONG_PTR) buffer;
471 DPRINT("BusQueryHardwareIDs: %ls\n",buffer);
472 break;
473
474 default:
475 status = Irp->IoStatus.Status;
476 }
477 return status;
478 }
479
480 NTSTATUS
481 Bus_PDO_QueryDeviceText(
482 PPDO_DEVICE_DATA DeviceData,
483 PIRP Irp )
484 {
485 PWCHAR Buffer;
486 PIO_STACK_LOCATION stack;
487 NTSTATUS status;
488 PAGED_CODE ();
489
490 stack = IoGetCurrentIrpStackLocation (Irp);
491
492 switch (stack->Parameters.QueryDeviceText.DeviceTextType) {
493
494 case DeviceTextDescription:
495
496 if (!Irp->IoStatus.Information) {
497 if (wcsstr (DeviceData->HardwareIDs, L"PNP000") != 0)
498 Buffer = L"Programmable interrupt controller";
499 else if (wcsstr(DeviceData->HardwareIDs, L"PNP010") != 0)
500 Buffer = L"System timer";
501 else if (wcsstr(DeviceData->HardwareIDs, L"PNP020") != 0)
502 Buffer = L"DMA controller";
503 else if (wcsstr(DeviceData->HardwareIDs, L"PNP03") != 0)
504 Buffer = L"Keyboard";
505 else if (wcsstr(DeviceData->HardwareIDs, L"PNP040") != 0)
506 Buffer = L"Parallel port";
507 else if (wcsstr(DeviceData->HardwareIDs, L"PNP05") != 0)
508 Buffer = L"Serial port";
509 else if (wcsstr(DeviceData->HardwareIDs, L"PNP06") != 0)
510 Buffer = L"Disk controller";
511 else if (wcsstr(DeviceData->HardwareIDs, L"PNP07") != 0)
512 Buffer = L"Disk controller";
513 else if (wcsstr(DeviceData->HardwareIDs, L"PNP09") != 0)
514 Buffer = L"Display adapter";
515 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0A0") != 0)
516 Buffer = L"Bus controller";
517 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0E0") != 0)
518 Buffer = L"PCMCIA controller";
519 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0F") != 0)
520 Buffer = L"Mouse device";
521 else if (wcsstr(DeviceData->HardwareIDs, L"PNP8") != 0)
522 Buffer = L"Network adapter";
523 else if (wcsstr(DeviceData->HardwareIDs, L"PNPA0") != 0)
524 Buffer = L"SCSI controller";
525 else if (wcsstr(DeviceData->HardwareIDs, L"PNPB0") != 0)
526 Buffer = L"Multimedia device";
527 else if (wcsstr(DeviceData->HardwareIDs, L"PNPC00") != 0)
528 Buffer = L"Modem";
529 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0C") != 0)
530 Buffer = L"Power Button";
531 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0E") != 0)
532 Buffer = L"Sleep Button";
533 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0D") != 0)
534 Buffer = L"Lid Switch";
535 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C09") != 0)
536 Buffer = L"ACPI Embedded Controller";
537 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0B") != 0)
538 Buffer = L"ACPI Fan";
539 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0A03") != 0)
540 Buffer = L"PCI Root Bridge";
541 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0A") != 0)
542 Buffer = L"ACPI Battery";
543 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0F") != 0)
544 Buffer = L"PCI Interrupt Link";
545 else if (wcsstr(DeviceData->HardwareIDs, L"ACPI_PWR") != 0)
546 Buffer = L"ACPI Power Resource";
547 else if (wcsstr(DeviceData->HardwareIDs, L"Processor") != 0)
548 Buffer = L"Processor";
549 else if (wcsstr(DeviceData->HardwareIDs, L"ACPI_SYS") != 0)
550 Buffer = L"ACPI System";
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 else
558 Buffer = L"Other ACPI device";
559
560 DPRINT("\tDeviceTextDescription :%ws\n", Buffer);
561
562 Irp->IoStatus.Information = (ULONG_PTR) Buffer;
563 }
564 status = STATUS_SUCCESS;
565 break;
566
567 default:
568 status = Irp->IoStatus.Status;
569 break;
570 }
571
572 return status;
573
574 }
575
576 NTSTATUS
577 Bus_PDO_QueryResources(
578 PPDO_DEVICE_DATA DeviceData,
579 PIRP Irp )
580 {
581 BOOLEAN Done;
582 ULONG NumberOfResources = 0;
583 PCM_RESOURCE_LIST ResourceList;
584 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor;
585 ACPI_STATUS AcpiStatus;
586 ACPI_BUFFER Buffer;
587 ACPI_RESOURCE* resource;
588 ULONG ResourceListSize;
589 ULONG i;
590
591 ULONG RequirementsListSize;
592 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
593 PIO_RESOURCE_DESCRIPTOR RequirementDescriptor;
594
595
596 /* Get current resources */
597 Buffer.Length = 0;
598 AcpiStatus = AcpiGetCurrentResources(DeviceData->AcpiHandle, &Buffer);
599 if (!ACPI_SUCCESS(AcpiStatus))
600 {
601 return STATUS_SUCCESS;
602 }
603 if (Buffer.Length > 0)
604 {
605 Buffer.Pointer = ExAllocatePool(PagedPool, Buffer.Length);
606 if (!Buffer.Pointer)
607 {
608 ASSERT(FALSE);
609 }
610 AcpiStatus = AcpiGetCurrentResources(DeviceData->AcpiHandle, &Buffer);
611 if (!ACPI_SUCCESS(AcpiStatus))
612 {
613 ASSERT(FALSE);
614 }
615 }
616
617 resource= Buffer.Pointer;
618 /* Count number of resources */
619 Done = FALSE;
620 while (!Done)
621 {
622 switch (resource->Type)
623 {
624 case ACPI_RESOURCE_TYPE_IRQ:
625 {
626 ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
627 NumberOfResources += irq_data->InterruptCount;
628 break;
629 }
630 case ACPI_RESOURCE_TYPE_DMA:
631 {
632 ACPI_RESOURCE_DMA *dma_data = (ACPI_RESOURCE_DMA*) &resource->Data;
633 NumberOfResources += dma_data->ChannelCount;
634 break;
635 }
636 case ACPI_RESOURCE_TYPE_IO:
637 {
638 NumberOfResources++;
639 break;
640 }
641 case ACPI_RESOURCE_TYPE_END_TAG:
642 {
643 Done = TRUE;
644 break;
645 }
646 default:
647 {
648 break;
649 }
650 }
651 resource = ACPI_NEXT_RESOURCE(resource);
652 }
653
654 /* Allocate memory */
655 ResourceListSize = sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * (NumberOfResources - 1);
656 ResourceList = (PCM_RESOURCE_LIST)ExAllocatePool(PagedPool, ResourceListSize);
657
658 if (!ResourceList)
659 return FALSE;
660 ResourceList->Count = 1;
661 ResourceList->List[0].InterfaceType = Internal; /* FIXME */
662 ResourceList->List[0].BusNumber = 0; /* We're the only ACPI bus device in the system */
663 ResourceList->List[0].PartialResourceList.Version = 1;
664 ResourceList->List[0].PartialResourceList.Revision = 1;
665 ResourceList->List[0].PartialResourceList.Count = NumberOfResources;
666 ResourceDescriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
667
668 RequirementsListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) + sizeof(IO_RESOURCE_DESCRIPTOR) * (NumberOfResources - 1);
669 RequirementsList = (PIO_RESOURCE_REQUIREMENTS_LIST)ExAllocatePool(PagedPool, RequirementsListSize);
670
671 if (!RequirementsList)
672 {
673 ExFreePool(ResourceList);
674 return STATUS_SUCCESS;
675 }
676 RequirementsList->ListSize = RequirementsListSize;
677 RequirementsList->InterfaceType = Internal;
678 RequirementsList->BusNumber = 0;
679 RequirementsList->SlotNumber = 0; /* Not used by WDM drivers */
680 RequirementsList->AlternativeLists = 1;
681 RequirementsList->List[0].Version = 1;
682 RequirementsList->List[0].Revision = 1;
683 RequirementsList->List[0].Count = NumberOfResources;
684 RequirementDescriptor = RequirementsList->List[0].Descriptors;
685
686 /* Fill resources list structure */
687 Done = FALSE;
688 while (!Done)
689 {
690 switch (resource->Type)
691 {
692 case ACPI_RESOURCE_TYPE_IRQ:
693 {
694 ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
695 for (i = 0; i < irq_data->InterruptCount; i++)
696 {
697 ResourceDescriptor->Type = CmResourceTypeInterrupt;
698
699 ResourceDescriptor->ShareDisposition =
700 (irq_data->Sharable == ACPI_SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
701 ResourceDescriptor->Flags =
702 (irq_data->Triggering == ACPI_LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
703 ResourceDescriptor->u.Interrupt.Level = irq_data->Interrupts[i];
704 ResourceDescriptor->u.Interrupt.Vector = 0;
705 ResourceDescriptor->u.Interrupt.Affinity = (KAFFINITY)(-1);
706
707 RequirementDescriptor->Option = 0; /* Required */
708 RequirementDescriptor->Type = ResourceDescriptor->Type;
709 RequirementDescriptor->ShareDisposition = ResourceDescriptor->ShareDisposition;
710 RequirementDescriptor->Flags = ResourceDescriptor->Flags;
711 RequirementDescriptor->u.Interrupt.MinimumVector = RequirementDescriptor->u.Interrupt.MaximumVector
712 = irq_data->Interrupts[i];
713
714 ResourceDescriptor++;
715 RequirementDescriptor++;
716 }
717 break;
718 }
719 case ACPI_RESOURCE_TYPE_DMA:
720 {
721 ACPI_RESOURCE_DMA *dma_data = (ACPI_RESOURCE_DMA*) &resource->Data;
722 for (i = 0; i < dma_data->ChannelCount; i++)
723 {
724 ResourceDescriptor->Type = CmResourceTypeDma;
725 ResourceDescriptor->Flags = 0;
726 switch (dma_data->Type)
727 {
728 case ACPI_TYPE_A: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_A; break;
729 case ACPI_TYPE_B: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_B; break;
730 case ACPI_TYPE_F: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_F; break;
731 }
732 if (dma_data->BusMaster == ACPI_BUS_MASTER)
733 ResourceDescriptor->Flags |= CM_RESOURCE_DMA_BUS_MASTER;
734 switch (dma_data->Transfer)
735 {
736 case ACPI_TRANSFER_8: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_8; break;
737 case ACPI_TRANSFER_16: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_16; break;
738 case ACPI_TRANSFER_8_16: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_8_AND_16; break;
739 }
740 ResourceDescriptor->u.Dma.Channel = dma_data->Channels[i];
741
742 RequirementDescriptor->Option = 0; /* Required */
743 RequirementDescriptor->Type = ResourceDescriptor->Type;
744 RequirementDescriptor->ShareDisposition = ResourceDescriptor->ShareDisposition;
745 RequirementDescriptor->Flags = ResourceDescriptor->Flags;
746 RequirementDescriptor->u.Dma.MinimumChannel = RequirementDescriptor->u.Dma.MaximumChannel
747 = ResourceDescriptor->u.Dma.Channel;
748
749 ResourceDescriptor++;
750 RequirementDescriptor++;
751 }
752 break;
753 }
754 case ACPI_RESOURCE_TYPE_IO:
755 {
756 ACPI_RESOURCE_IO *io_data = (ACPI_RESOURCE_IO*) &resource->Data;
757 ResourceDescriptor->Type = CmResourceTypePort;
758 ResourceDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
759 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
760 if (io_data->IoDecode == ACPI_DECODE_16)
761 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
762 else
763 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
764 ResourceDescriptor->u.Port.Start.u.HighPart = 0;
765 ResourceDescriptor->u.Port.Start.u.LowPart = io_data->Minimum;
766 ResourceDescriptor->u.Port.Length = io_data->AddressLength;
767
768 RequirementDescriptor->Option = 0; /* Required */
769 RequirementDescriptor->Type = ResourceDescriptor->Type;
770 RequirementDescriptor->ShareDisposition = ResourceDescriptor->ShareDisposition;
771 RequirementDescriptor->Flags = ResourceDescriptor->Flags;
772 RequirementDescriptor->u.Port.Length = ResourceDescriptor->u.Port.Length;
773 RequirementDescriptor->u.Port.Alignment = 1; /* Start address is specified, so it doesn't matter */
774 RequirementDescriptor->u.Port.MinimumAddress = RequirementDescriptor->u.Port.MaximumAddress
775 = ResourceDescriptor->u.Port.Start;
776
777 ResourceDescriptor++;
778 RequirementDescriptor++;
779 break;
780 }
781 case ACPI_RESOURCE_TYPE_END_TAG:
782 {
783 Done = TRUE;
784 break;
785 }
786 default:
787 {
788 DPRINT1("Unhandled resource type\n");
789 break;
790 }
791 }
792 resource = ACPI_NEXT_RESOURCE(resource);
793 }
794
795 ExFreePool(Buffer.Pointer);
796 Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
797 return STATUS_SUCCESS;
798 }
799
800 NTSTATUS
801 Bus_PDO_QueryResourceRequirements(
802 PPDO_DEVICE_DATA DeviceData,
803 PIRP Irp )
804 {
805 BOOLEAN Done;
806 ULONG NumberOfResources = 0;
807 ACPI_STATUS AcpiStatus;
808 ACPI_BUFFER Buffer;
809 ACPI_RESOURCE* resource;
810 ULONG i, RequirementsListSize;
811 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
812 PIO_RESOURCE_DESCRIPTOR RequirementDescriptor;
813
814 PAGED_CODE ();
815
816
817 /* Get current resources */
818 Buffer.Length = 0;
819 AcpiStatus = AcpiGetCurrentResources(DeviceData->AcpiHandle, &Buffer);
820 if (!ACPI_SUCCESS(AcpiStatus))
821 {
822 return STATUS_SUCCESS;
823 }
824 if (Buffer.Length > 0)
825 {
826 Buffer.Pointer = ExAllocatePool(PagedPool, Buffer.Length);
827 if (!Buffer.Pointer)
828 {
829 ASSERT(FALSE);
830 }
831 AcpiStatus = AcpiGetCurrentResources(DeviceData->AcpiHandle, &Buffer);
832 if (!ACPI_SUCCESS(AcpiStatus))
833 {
834 ASSERT(FALSE);
835 }
836 }
837
838 resource= Buffer.Pointer;
839 /* Count number of resources */
840 Done = FALSE;
841 while (!Done)
842 {
843 switch (resource->Type)
844 {
845 case ACPI_RESOURCE_TYPE_IRQ:
846 {
847 ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
848 NumberOfResources += irq_data->InterruptCount;
849 break;
850 }
851 case ACPI_RESOURCE_TYPE_DMA:
852 {
853 ACPI_RESOURCE_DMA *dma_data = (ACPI_RESOURCE_DMA*) &resource->Data;
854 NumberOfResources += dma_data->ChannelCount;
855 break;
856 }
857 case ACPI_RESOURCE_TYPE_IO:
858 {
859 NumberOfResources++;
860 break;
861 }
862 case ACPI_RESOURCE_TYPE_END_TAG:
863 {
864 Done = TRUE;
865 break;
866 }
867 default:
868 {
869 break;
870 }
871 }
872 resource = ACPI_NEXT_RESOURCE(resource);
873 }
874
875 RequirementsListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) + sizeof(IO_RESOURCE_DESCRIPTOR) * (NumberOfResources - 1);
876 RequirementsList = (PIO_RESOURCE_REQUIREMENTS_LIST)ExAllocatePool(PagedPool, RequirementsListSize);
877
878 if (!RequirementsList)
879 {
880 ExFreePool(Buffer.Pointer);
881 return STATUS_SUCCESS;
882 }
883 RequirementsList->ListSize = RequirementsListSize;
884 RequirementsList->InterfaceType = Internal;
885 RequirementsList->BusNumber = 0;
886 RequirementsList->SlotNumber = 0; /* Not used by WDM drivers */
887 RequirementsList->AlternativeLists = 1;
888 RequirementsList->List[0].Version = 1;
889 RequirementsList->List[0].Revision = 1;
890 RequirementsList->List[0].Count = NumberOfResources;
891 RequirementDescriptor = RequirementsList->List[0].Descriptors;
892
893 /* Fill resources list structure */
894 Done = FALSE;
895 while (!Done)
896 {
897 switch (resource->Type)
898 {
899 case ACPI_RESOURCE_TYPE_IRQ:
900 {
901 ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
902 for (i = 0; i < irq_data->InterruptCount; i++)
903 {
904 RequirementDescriptor->Option = 0; /* Required */
905 RequirementDescriptor->Type = CmResourceTypeInterrupt;
906 RequirementDescriptor->ShareDisposition = (irq_data->Sharable == ACPI_SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
907 RequirementDescriptor->Flags =(irq_data->Triggering == ACPI_LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
908 RequirementDescriptor->u.Interrupt.MinimumVector = irq_data->Interrupts[i];
909
910 RequirementDescriptor++;
911 }
912 break;
913 }
914 case ACPI_RESOURCE_TYPE_DMA:
915 {
916 ACPI_RESOURCE_DMA *dma_data = (ACPI_RESOURCE_DMA*) &resource->Data;
917 for (i = 0; i < dma_data->ChannelCount; i++)
918 {
919 RequirementDescriptor->Type = CmResourceTypeDma;
920 RequirementDescriptor->Flags = 0;
921 switch (dma_data->Type)
922 {
923 case ACPI_TYPE_A: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_A; break;
924 case ACPI_TYPE_B: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_B; break;
925 case ACPI_TYPE_F: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_F; break;
926 }
927 if (dma_data->BusMaster == ACPI_BUS_MASTER)
928 RequirementDescriptor->Flags |= CM_RESOURCE_DMA_BUS_MASTER;
929 switch (dma_data->Transfer)
930 {
931 case ACPI_TRANSFER_8: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_8; break;
932 case ACPI_TRANSFER_16: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_16; break;
933 case ACPI_TRANSFER_8_16: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_8_AND_16; break;
934 }
935
936 RequirementDescriptor->Option = 0; /* Required */
937 RequirementDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
938 RequirementDescriptor->u.Dma.MinimumChannel = dma_data->Channels[i];
939 RequirementDescriptor++;
940 }
941 break;
942 }
943 case ACPI_RESOURCE_TYPE_IO:
944 {
945 ACPI_RESOURCE_IO *io_data = (ACPI_RESOURCE_IO*) &resource->Data;
946 RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
947 if (io_data->IoDecode == ACPI_DECODE_16)
948 RequirementDescriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
949 else
950 RequirementDescriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
951
952 RequirementDescriptor->u.Port.Length = io_data->AddressLength;
953
954 RequirementDescriptor->Option = 0; /* Required */
955 RequirementDescriptor->Type = CmResourceTypePort;
956 RequirementDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
957 RequirementDescriptor->u.Port.Alignment = 1; /* Start address is specified, so it doesn't matter */
958 RequirementDescriptor->u.Port.MinimumAddress.QuadPart = io_data->Minimum;
959 RequirementDescriptor->u.Port.MaximumAddress.QuadPart = io_data->Maximum;
960
961 RequirementDescriptor++;
962 break;
963 }
964 case ACPI_RESOURCE_TYPE_END_TAG:
965 {
966 Done = TRUE;
967 break;
968 }
969 default:
970 {
971 DPRINT1("Unhandled resource type\n");
972 break;
973 }
974 }
975 resource = ACPI_NEXT_RESOURCE(resource);
976 }
977 ExFreePool(Buffer.Pointer);
978
979 return STATUS_SUCCESS;
980 }
981
982 NTSTATUS
983 Bus_PDO_QueryDeviceRelations(
984 PPDO_DEVICE_DATA DeviceData,
985 PIRP Irp )
986 /*++
987
988 Routine Description:
989
990 The PnP Manager sends this IRP to gather information about
991 devices with a relationship to the specified device.
992 Bus drivers must handle this request for TargetDeviceRelation
993 for their child devices (child PDOs).
994
995 If a driver returns relations in response to this IRP,
996 it allocates a DEVICE_RELATIONS structure from paged
997 memory containing a count and the appropriate number of
998 device object pointers. The PnP Manager frees the structure
999 when it is no longer needed. If a driver replaces a
1000 DEVICE_RELATIONS structure allocated by another driver,
1001 it must free the previous structure.
1002
1003 A driver must reference the PDO of any device that it
1004 reports in this IRP (ObReferenceObject). The PnP Manager
1005 removes the reference when appropriate.
1006
1007 Arguments:
1008
1009 DeviceData - Pointer to the PDO's device extension.
1010 Irp - Pointer to the irp.
1011
1012 Return Value:
1013
1014 NT STATUS
1015
1016 --*/
1017 {
1018
1019 PIO_STACK_LOCATION stack;
1020 PDEVICE_RELATIONS deviceRelations;
1021 NTSTATUS status;
1022
1023 PAGED_CODE ();
1024
1025 stack = IoGetCurrentIrpStackLocation (Irp);
1026
1027 switch (stack->Parameters.QueryDeviceRelations.Type) {
1028
1029 case TargetDeviceRelation:
1030
1031 deviceRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information;
1032 if (deviceRelations) {
1033 //
1034 // Only PDO can handle this request. Somebody above
1035 // is not playing by rule.
1036 //
1037 ASSERTMSG("Someone above is handling TargetDeviceRelation", !deviceRelations);
1038 }
1039
1040 deviceRelations = (PDEVICE_RELATIONS)
1041 ExAllocatePoolWithTag (PagedPool,
1042 sizeof(DEVICE_RELATIONS),
1043 'IPCA');
1044 if (!deviceRelations) {
1045 status = STATUS_INSUFFICIENT_RESOURCES;
1046 break;
1047 }
1048
1049 //
1050 // There is only one PDO pointer in the structure
1051 // for this relation type. The PnP Manager removes
1052 // the reference to the PDO when the driver or application
1053 // un-registers for notification on the device.
1054 //
1055
1056 deviceRelations->Count = 1;
1057 deviceRelations->Objects[0] = DeviceData->Common.Self;
1058 ObReferenceObject(DeviceData->Common.Self);
1059
1060 status = STATUS_SUCCESS;
1061 Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
1062 break;
1063
1064 case BusRelations: // Not handled by PDO
1065 case EjectionRelations: // optional for PDO
1066 case RemovalRelations: // // optional for PDO
1067 default:
1068 status = Irp->IoStatus.Status;
1069 }
1070
1071 return status;
1072 }
1073
1074 NTSTATUS
1075 Bus_PDO_QueryBusInformation(
1076 PPDO_DEVICE_DATA DeviceData,
1077 PIRP Irp )
1078 /*++
1079
1080 Routine Description:
1081
1082 The PnP Manager uses this IRP to request the type and
1083 instance number of a device's parent bus. Bus drivers
1084 should handle this request for their child devices (PDOs).
1085
1086 Arguments:
1087
1088 DeviceData - Pointer to the PDO's device extension.
1089 Irp - Pointer to the irp.
1090
1091 Return Value:
1092
1093 NT STATUS
1094
1095 --*/
1096 {
1097
1098 PPNP_BUS_INFORMATION busInfo;
1099
1100 PAGED_CODE ();
1101
1102 busInfo = ExAllocatePoolWithTag (PagedPool, sizeof(PNP_BUS_INFORMATION),
1103 'IPCA');
1104
1105 if (busInfo == NULL) {
1106 return STATUS_INSUFFICIENT_RESOURCES;
1107 }
1108
1109 busInfo->BusTypeGuid = GUID_ACPI_INTERFACE_STANDARD;
1110
1111 busInfo->LegacyBusType = InternalPowerBus;
1112
1113 busInfo->BusNumber = 0; //fixme
1114
1115 Irp->IoStatus.Information = (ULONG_PTR)busInfo;
1116
1117 return STATUS_SUCCESS;
1118 }
1119
1120
1121 NTSTATUS
1122 Bus_GetDeviceCapabilities(
1123 PDEVICE_OBJECT DeviceObject,
1124 PDEVICE_CAPABILITIES DeviceCapabilities
1125 )
1126 {
1127 IO_STATUS_BLOCK ioStatus;
1128 KEVENT pnpEvent;
1129 NTSTATUS status;
1130 PDEVICE_OBJECT targetObject;
1131 PIO_STACK_LOCATION irpStack;
1132 PIRP pnpIrp;
1133
1134 PAGED_CODE();
1135
1136 //
1137 // Initialize the capabilities that we will send down
1138 //
1139 RtlZeroMemory( DeviceCapabilities, sizeof(DEVICE_CAPABILITIES) );
1140 DeviceCapabilities->Size = sizeof(DEVICE_CAPABILITIES);
1141 DeviceCapabilities->Version = 1;
1142 DeviceCapabilities->Address = -1;
1143 DeviceCapabilities->UINumber = -1;
1144
1145 //
1146 // Initialize the event
1147 //
1148 KeInitializeEvent( &pnpEvent, NotificationEvent, FALSE );
1149
1150 targetObject = IoGetAttachedDeviceReference( DeviceObject );
1151
1152 //
1153 // Build an Irp
1154 //
1155 pnpIrp = IoBuildSynchronousFsdRequest(
1156 IRP_MJ_PNP,
1157 targetObject,
1158 NULL,
1159 0,
1160 NULL,
1161 &pnpEvent,
1162 &ioStatus
1163 );
1164 if (pnpIrp == NULL) {
1165
1166 status = STATUS_INSUFFICIENT_RESOURCES;
1167 goto GetDeviceCapabilitiesExit;
1168
1169 }
1170
1171 //
1172 // Pnp Irps all begin life as STATUS_NOT_SUPPORTED;
1173 //
1174 pnpIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
1175
1176 //
1177 // Get the top of stack
1178 //
1179 irpStack = IoGetNextIrpStackLocation( pnpIrp );
1180
1181 //
1182 // Set the top of stack
1183 //
1184 RtlZeroMemory( irpStack, sizeof(IO_STACK_LOCATION ) );
1185 irpStack->MajorFunction = IRP_MJ_PNP;
1186 irpStack->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
1187 irpStack->Parameters.DeviceCapabilities.Capabilities = DeviceCapabilities;
1188
1189 //
1190 // Call the driver
1191 //
1192 status = IoCallDriver( targetObject, pnpIrp );
1193 if (status == STATUS_PENDING) {
1194
1195 //
1196 // Block until the irp comes back.
1197 // Important thing to note here is when you allocate
1198 // the memory for an event in the stack you must do a
1199 // KernelMode wait instead of UserMode to prevent
1200 // the stack from getting paged out.
1201 //
1202
1203 KeWaitForSingleObject(
1204 &pnpEvent,
1205 Executive,
1206 KernelMode,
1207 FALSE,
1208 NULL
1209 );
1210 status = ioStatus.Status;
1211
1212 }
1213
1214 GetDeviceCapabilitiesExit:
1215 //
1216 // Done with reference
1217 //
1218 ObDereferenceObject( targetObject );
1219
1220 //
1221 // Done
1222 //
1223 return status;
1224
1225 }
1226
1227