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