- Make ACPI use PCH. Cuts down compile time to 9 seconds on gcc.
[reactos.git] / reactos / drivers / bus / acpi / ospm / fdo.c
1 /* $Id$
2 *
3 * PROJECT: ReactOS ACPI bus driver
4 * FILE: acpi/ospm/fdo.c
5 * PURPOSE: ACPI device object dispatch routines
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Hervé Poussineau (hpoussin@reactos.com)
8 * UPDATE HISTORY:
9 * 08-08-2001 CSH Created
10 */
11 #include <acpi.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16 FADT_DESCRIPTOR_REV2 acpi_fadt;
17
18 /*** PRIVATE *****************************************************************/
19
20
21 BOOLEAN
22 AcpiCreateUnicodeString(
23 PUNICODE_STRING Destination,
24 PWSTR Source,
25 POOL_TYPE PoolType)
26 {
27 ULONG Length;
28
29 if (!Source)
30 {
31 RtlInitUnicodeString(Destination, NULL);
32 return TRUE;
33 }
34
35 Length = (wcslen(Source) + 1) * sizeof(WCHAR);
36
37 Destination->Buffer = ExAllocatePool(PoolType, Length);
38 if (Destination->Buffer == NULL)
39 {
40 return FALSE;
41 }
42
43 RtlCopyMemory(Destination->Buffer, Source, Length);
44
45 Destination->MaximumLength = Length;
46
47 Destination->Length = Length - sizeof(WCHAR);
48
49 return TRUE;
50 }
51
52 BOOLEAN
53 AcpiCreateDeviceIDString(PUNICODE_STRING DeviceID,
54 BM_NODE *Node)
55 {
56 WCHAR Buffer[256];
57
58 swprintf(Buffer,
59 L"ACPI\\%S",
60 Node->device.id.hid);
61
62 return AcpiCreateUnicodeString(DeviceID, Buffer, PagedPool);
63 }
64
65
66 BOOLEAN
67 AcpiCreateHardwareIDsString(PUNICODE_STRING HardwareIDs,
68 BM_NODE *Node)
69 {
70 WCHAR Buffer[256];
71 ULONG Length;
72 ULONG Index;
73
74 Index = 0;
75 Index += swprintf(&Buffer[Index],
76 L"ACPI\\%S",
77 Node->device.id.hid);
78 Index++;
79
80 Index += swprintf(&Buffer[Index],
81 L"*%S",
82 Node->device.id.hid);
83 Index++;
84 Buffer[Index] = UNICODE_NULL;
85
86 Length = (Index + 1) * sizeof(WCHAR);
87 HardwareIDs->Buffer = ExAllocatePool(PagedPool, Length);
88 if (HardwareIDs->Buffer == NULL)
89 {
90 return FALSE;
91 }
92
93 HardwareIDs->Length = Length - sizeof(WCHAR);
94 HardwareIDs->MaximumLength = Length;
95 RtlCopyMemory(HardwareIDs->Buffer, Buffer, Length);
96
97 return TRUE;
98 }
99
100
101 BOOLEAN
102 AcpiCreateInstanceIDString(PUNICODE_STRING InstanceID,
103 BM_NODE *Node)
104 {
105 WCHAR Buffer[10];
106
107 if (Node->device.id.uid[0])
108 swprintf(Buffer, L"%S", Node->device.id.uid);
109 else
110 /* FIXME: Generate unique id! */
111 swprintf(Buffer, L"0000");
112
113 return AcpiCreateUnicodeString(InstanceID, Buffer, PagedPool);
114 }
115
116
117 BOOLEAN
118 AcpiCreateDeviceDescriptionString(PUNICODE_STRING DeviceDescription,
119 BM_NODE *Node)
120 {
121 PWSTR Buffer;
122
123 if (RtlCompareMemory(Node->device.id.hid, "PNP000", 6) == 6)
124 Buffer = L"Programmable interrupt controller";
125 else if (RtlCompareMemory(Node->device.id.hid, "PNP010", 6) == 6)
126 Buffer = L"System timer";
127 else if (RtlCompareMemory(Node->device.id.hid, "PNP020", 6) == 6)
128 Buffer = L"DMA controller";
129 else if (RtlCompareMemory(Node->device.id.hid, "PNP03", 5) == 5)
130 Buffer = L"Keyboard";
131 else if (RtlCompareMemory(Node->device.id.hid, "PNP040", 6) == 6)
132 Buffer = L"Parallel port";
133 else if (RtlCompareMemory(Node->device.id.hid, "PNP05", 5) == 5)
134 Buffer = L"Serial port";
135 else if (RtlCompareMemory(Node->device.id.hid, "PNP06", 5) ==5)
136 Buffer = L"Disk controller";
137 else if (RtlCompareMemory(Node->device.id.hid, "PNP07", 5) == 5)
138 Buffer = L"Disk controller";
139 else if (RtlCompareMemory(Node->device.id.hid, "PNP09", 5) == 5)
140 Buffer = L"Display adapter";
141 else if (RtlCompareMemory(Node->device.id.hid, "PNP0A0", 6) == 6)
142 Buffer = L"Bus controller";
143 else if (RtlCompareMemory(Node->device.id.hid, "PNP0E0", 6) == 6)
144 Buffer = L"PCMCIA controller";
145 else if (RtlCompareMemory(Node->device.id.hid, "PNP0F", 5) == 5)
146 Buffer = L"Mouse device";
147 else if (RtlCompareMemory(Node->device.id.hid, "PNP8", 4) == 4)
148 Buffer = L"Network adapter";
149 else if (RtlCompareMemory(Node->device.id.hid, "PNPA0", 5) == 5)
150 Buffer = L"SCSI controller";
151 else if (RtlCompareMemory(Node->device.id.hid, "PNPB0", 5) == 5)
152 Buffer = L"Multimedia device";
153 else if (RtlCompareMemory(Node->device.id.hid, "PNPC00", 6) == 6)
154 Buffer = L"Modem";
155 else
156 Buffer = L"Other ACPI device";
157
158 return AcpiCreateUnicodeString(DeviceDescription, Buffer, PagedPool);
159 }
160
161
162 static BOOLEAN
163 AcpiCreateResourceList(PCM_RESOURCE_LIST* pResourceList,
164 PULONG ResourceListSize,
165 PIO_RESOURCE_REQUIREMENTS_LIST* pRequirementsList,
166 PULONG RequirementsListSize,
167 RESOURCE* resources)
168 {
169 BOOLEAN Done;
170 ULONG NumberOfResources = 0;
171 PCM_RESOURCE_LIST ResourceList;
172 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
173 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor;
174 PIO_RESOURCE_DESCRIPTOR RequirementDescriptor;
175 RESOURCE* resource;
176 ULONG i;
177 KIRQL Dirql;
178
179 /* Count number of resources */
180 Done = FALSE;
181 resource = resources;
182 while (!Done)
183 {
184 switch (resource->id)
185 {
186 case irq:
187 {
188 IRQ_RESOURCE *irq_data = (IRQ_RESOURCE*) &resource->data;
189 NumberOfResources += irq_data->number_of_interrupts;
190 break;
191 }
192 case dma:
193 {
194 DMA_RESOURCE *dma_data = (DMA_RESOURCE*) &resource->data;
195 NumberOfResources += dma_data->number_of_channels;
196 break;
197 }
198 case io:
199 {
200 NumberOfResources++;
201 break;
202 }
203 case end_tag:
204 {
205 Done = TRUE;
206 break;
207 }
208 default:
209 {
210 break;
211 }
212 }
213 resource = (RESOURCE *) ((NATIVE_UINT) resource + (NATIVE_UINT) resource->length);
214 }
215
216 /* Allocate memory */
217 *ResourceListSize = sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * (NumberOfResources - 1);
218 ResourceList = (PCM_RESOURCE_LIST)ExAllocatePool(PagedPool, *ResourceListSize);
219 *pResourceList = ResourceList;
220 if (!ResourceList)
221 return FALSE;
222 ResourceList->Count = 1;
223 ResourceList->List[0].InterfaceType = Internal; /* FIXME */
224 ResourceList->List[0].BusNumber = 0; /* We're the only ACPI bus device in the system */
225 ResourceList->List[0].PartialResourceList.Version = 1;
226 ResourceList->List[0].PartialResourceList.Revision = 1;
227 ResourceList->List[0].PartialResourceList.Count = NumberOfResources;
228 ResourceDescriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
229
230 *RequirementsListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) + sizeof(IO_RESOURCE_DESCRIPTOR) * (NumberOfResources - 1);
231 RequirementsList = (PIO_RESOURCE_REQUIREMENTS_LIST)ExAllocatePool(PagedPool, *RequirementsListSize);
232 *pRequirementsList = RequirementsList;
233 if (!RequirementsList)
234 {
235 ExFreePool(ResourceList);
236 return FALSE;
237 }
238 RequirementsList->ListSize = *RequirementsListSize;
239 RequirementsList->InterfaceType = ResourceList->List[0].InterfaceType;
240 RequirementsList->BusNumber = ResourceList->List[0].BusNumber;
241 RequirementsList->SlotNumber = 0; /* Not used by WDM drivers */
242 RequirementsList->AlternativeLists = 1;
243 RequirementsList->List[0].Version = 1;
244 RequirementsList->List[0].Revision = 1;
245 RequirementsList->List[0].Count = NumberOfResources;
246 RequirementDescriptor = RequirementsList->List[0].Descriptors;
247
248 /* Fill resources list structure */
249 Done = FALSE;
250 resource = resources;
251 while (!Done)
252 {
253 switch (resource->id)
254 {
255 case irq:
256 {
257 IRQ_RESOURCE *irq_data = (IRQ_RESOURCE*) &resource->data;
258 for (i = 0; i < irq_data->number_of_interrupts; i++)
259 {
260 ResourceDescriptor->Type = CmResourceTypeInterrupt;
261
262 ResourceDescriptor->ShareDisposition =
263 (irq_data->shared_exclusive == SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
264 ResourceDescriptor->Flags =
265 (irq_data->edge_level == LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
266 ResourceDescriptor->u.Interrupt.Vector = HalGetInterruptVector(
267 Internal, 0, 0, irq_data->interrupts[i],
268 &Dirql,
269 &ResourceDescriptor->u.Interrupt.Affinity);
270 ResourceDescriptor->u.Interrupt.Level = (ULONG)Dirql;
271
272 RequirementDescriptor->Option = 0; /* Required */
273 RequirementDescriptor->Type = ResourceDescriptor->Type;
274 RequirementDescriptor->ShareDisposition = ResourceDescriptor->ShareDisposition;
275 RequirementDescriptor->Flags = ResourceDescriptor->Flags;
276 RequirementDescriptor->u.Interrupt.MinimumVector = RequirementDescriptor->u.Interrupt.MaximumVector
277 = irq_data->interrupts[i];
278
279 ResourceDescriptor++;
280 RequirementDescriptor++;
281 }
282 break;
283 }
284 case dma:
285 {
286 DMA_RESOURCE *dma_data = (DMA_RESOURCE*) &resource->data;
287 for (i = 0; i < dma_data->number_of_channels; i++)
288 {
289 ResourceDescriptor->Type = CmResourceTypeDma;
290 ResourceDescriptor->Flags = 0;
291 switch (dma_data->type)
292 {
293 case TYPE_A: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_A; break;
294 case TYPE_B: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_B; break;
295 case TYPE_F: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_F; break;
296 }
297 if (dma_data->bus_master == BUS_MASTER)
298 ResourceDescriptor->Flags |= CM_RESOURCE_DMA_BUS_MASTER;
299 switch (dma_data->transfer)
300 {
301 case TRANSFER_8: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_8; break;
302 case TRANSFER_16: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_16; break;
303 case TRANSFER_8_16: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_8_AND_16; break;
304 }
305 ResourceDescriptor->u.Dma.Channel = dma_data->channels[i];
306
307 RequirementDescriptor->Option = 0; /* Required */
308 RequirementDescriptor->Type = ResourceDescriptor->Type;
309 RequirementDescriptor->ShareDisposition = ResourceDescriptor->ShareDisposition;
310 RequirementDescriptor->Flags = ResourceDescriptor->Flags;
311 RequirementDescriptor->u.Dma.MinimumChannel = RequirementDescriptor->u.Dma.MaximumChannel
312 = ResourceDescriptor->u.Dma.Channel;
313
314 ResourceDescriptor++;
315 RequirementDescriptor++;
316 }
317 break;
318 }
319 case io:
320 {
321 IO_RESOURCE *io_data = (IO_RESOURCE*) &resource->data;
322 ResourceDescriptor->Type = CmResourceTypePort;
323 ResourceDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
324 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
325 if (io_data->io_decode == DECODE_16)
326 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
327 else
328 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
329 ResourceDescriptor->u.Port.Start.u.HighPart = 0;
330 ResourceDescriptor->u.Port.Start.u.LowPart = io_data->min_base_address;
331 ResourceDescriptor->u.Port.Length = io_data->range_length;
332
333 RequirementDescriptor->Option = 0; /* Required */
334 RequirementDescriptor->Type = ResourceDescriptor->Type;
335 RequirementDescriptor->ShareDisposition = ResourceDescriptor->ShareDisposition;
336 RequirementDescriptor->Flags = ResourceDescriptor->Flags;
337 RequirementDescriptor->u.Port.Length = ResourceDescriptor->u.Port.Length;
338 RequirementDescriptor->u.Port.Alignment = 1; /* Start address is specified, so it doesn't matter */
339 RequirementDescriptor->u.Port.MinimumAddress = RequirementDescriptor->u.Port.MaximumAddress
340 = ResourceDescriptor->u.Port.Start;
341
342 ResourceDescriptor++;
343 RequirementDescriptor++;
344 break;
345 }
346 case end_tag:
347 {
348 Done = TRUE;
349 break;
350 }
351 default:
352 {
353 break;
354 }
355 }
356 resource = (RESOURCE *) ((NATIVE_UINT) resource + (NATIVE_UINT) resource->length);
357 }
358
359 acpi_rs_dump_resource_list(resource);
360 return TRUE;
361 }
362
363
364 static NTSTATUS
365 FdoQueryBusRelations(
366 IN PDEVICE_OBJECT DeviceObject,
367 IN PIRP Irp,
368 PIO_STACK_LOCATION IrpSp)
369 {
370 PPDO_DEVICE_EXTENSION PdoDeviceExtension;
371 PFDO_DEVICE_EXTENSION DeviceExtension;
372 PDEVICE_RELATIONS Relations;
373 PLIST_ENTRY CurrentEntry;
374 ACPI_STATUS AcpiStatus;
375 PACPI_DEVICE Device;
376 NTSTATUS Status = STATUS_SUCCESS;
377 BM_NODE *Node;
378 ULONG Size;
379 ULONG i;
380
381 DPRINT("Called\n");
382
383 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
384
385 Size = sizeof(DEVICE_RELATIONS) + sizeof(Relations->Objects) *
386 (DeviceExtension->DeviceListCount - 1);
387 Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, Size);
388 if (!Relations)
389 return STATUS_INSUFFICIENT_RESOURCES;
390
391 Relations->Count = DeviceExtension->DeviceListCount;
392
393 i = 0;
394 CurrentEntry = DeviceExtension->DeviceListHead.Flink;
395 while (CurrentEntry != &DeviceExtension->DeviceListHead)
396 {
397 ACPI_BUFFER Buffer;
398 Device = CONTAINING_RECORD(CurrentEntry, ACPI_DEVICE, DeviceListEntry);
399
400 /* FIXME: For ACPI namespace devices on the motherboard create filter DOs
401 and attach them just above the ACPI bus device object (PDO) */
402
403 /* FIXME: For other devices in ACPI namespace, but not on motherboard,
404 create PDOs */
405
406 if (!Device->Pdo)
407 {
408 /* Create a physical device object for the
409 device as it does not already have one */
410 Status = IoCreateDevice(DeviceObject->DriverObject,
411 sizeof(PDO_DEVICE_EXTENSION),
412 NULL,
413 FILE_DEVICE_CONTROLLER,
414 FILE_AUTOGENERATED_DEVICE_NAME,
415 FALSE,
416 &Device->Pdo);
417 if (!NT_SUCCESS(Status))
418 {
419 DPRINT("IoCreateDevice() failed with status 0x%X\n", Status);
420 /* FIXME: Cleanup all new PDOs created in this call */
421 ExFreePool(Relations);
422 return Status;
423 }
424
425 PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension;
426
427 RtlZeroMemory(PdoDeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
428
429 Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
430
431 Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
432
433 //Device->Pdo->Flags |= DO_POWER_PAGABLE;
434
435 PdoDeviceExtension->Common.DeviceObject = Device->Pdo;
436
437 PdoDeviceExtension->Common.DevicePowerState = PowerDeviceD0;
438
439 // PdoDeviceExtension->Common.Ldo = IoAttachDeviceToDeviceStack(DeviceObject,
440 // Device->Pdo);
441
442 RtlInitUnicodeString(&PdoDeviceExtension->DeviceID, NULL);
443 RtlInitUnicodeString(&PdoDeviceExtension->InstanceID, NULL);
444 RtlInitUnicodeString(&PdoDeviceExtension->HardwareIDs, NULL);
445
446 AcpiStatus = bm_get_node(Device->BmHandle, 0, &Node);
447 if (ACPI_SUCCESS(AcpiStatus))
448 {
449 /* Get current resources */
450 Buffer.length = 0;
451 Status = acpi_get_current_resources(Node->device.acpi_handle, &Buffer);
452 if ((Status & ACPI_OK) == 0)
453 {
454 ASSERT(FALSE);
455 }
456 if (Buffer.length > 0)
457 {
458 Buffer.pointer = ExAllocatePool(PagedPool, Buffer.length);
459 if (!Buffer.pointer)
460 {
461 ASSERT(FALSE);
462 }
463 Status = acpi_get_current_resources(Node->device.acpi_handle, &Buffer);
464 if (ACPI_FAILURE(Status))
465 {
466 ASSERT(FALSE);
467 }
468 if (!AcpiCreateResourceList(&PdoDeviceExtension->ResourceList,
469 &PdoDeviceExtension->ResourceListSize,
470 &PdoDeviceExtension->ResourceRequirementsList,
471 &PdoDeviceExtension->ResourceRequirementsListSize,
472 (RESOURCE*)Buffer.pointer))
473 {
474 ASSERT(FALSE);
475 }
476 ExFreePool(Buffer.pointer);
477 }
478
479 /* Add Device ID string */
480 if (!AcpiCreateDeviceIDString(&PdoDeviceExtension->DeviceID,
481 Node))
482 {
483 ASSERT(FALSE);
484 // ErrorStatus = STATUS_INSUFFICIENT_RESOURCES;
485 // ErrorOccurred = TRUE;
486 // break;
487 }
488
489 if (!AcpiCreateInstanceIDString(&PdoDeviceExtension->InstanceID,
490 Node))
491 {
492 ASSERT(FALSE);
493 // ErrorStatus = STATUS_INSUFFICIENT_RESOURCES;
494 // ErrorOccurred = TRUE;
495 // break;
496 }
497
498 if (!AcpiCreateHardwareIDsString(&PdoDeviceExtension->HardwareIDs,
499 Node))
500 {
501 ASSERT(FALSE);
502 // ErrorStatus = STATUS_INSUFFICIENT_RESOURCES;
503 // ErrorOccurred = TRUE;
504 // break;
505 }
506
507 if (!AcpiCreateDeviceDescriptionString(&PdoDeviceExtension->DeviceDescription,
508 Node))
509 {
510 ASSERT(FALSE);
511 // ErrorStatus = STATUS_INSUFFICIENT_RESOURCES;
512 // ErrorOccurred = TRUE;
513 // break;
514 }
515 }
516 }
517
518 /* Reference the physical device object. The PnP manager
519 will dereference it again when it is no longer needed */
520 ObReferenceObject(Device->Pdo);
521
522 Relations->Objects[i] = Device->Pdo;
523
524 i++;
525
526 CurrentEntry = CurrentEntry->Flink;
527 }
528
529 Irp->IoStatus.Information = (ULONG)Relations;
530
531 return Status;
532 }
533
534 #ifndef NDEBUG
535 static VOID
536 ACPIPrintInfo(
537 PFDO_DEVICE_EXTENSION DeviceExtension)
538 {
539 DbgPrint("ACPI: System firmware supports:\n");
540
541 /*
542 * Print out basic system information
543 */
544 DbgPrint("+------------------------------------------------------------\n");
545 DbgPrint("| Sx states: %cS0 %cS1 %cS2 %cS3 %cS4 %cS5\n",
546 (DeviceExtension->SystemStates[0]?'+':'-'),
547 (DeviceExtension->SystemStates[1]?'+':'-'),
548 (DeviceExtension->SystemStates[2]?'+':'-'),
549 (DeviceExtension->SystemStates[3]?'+':'-'),
550 (DeviceExtension->SystemStates[4]?'+':'-'),
551 (DeviceExtension->SystemStates[5]?'+':'-'));
552 DbgPrint("+------------------------------------------------------------\n");
553 }
554 #endif
555
556 static NTSTATUS
557 ACPIInitializeInternalDriver(
558 PFDO_DEVICE_EXTENSION DeviceExtension,
559 ACPI_DRIVER_FUNCTION Initialize,
560 ACPI_DRIVER_FUNCTION Terminate)
561 {
562 ACPI_STATUS AcpiStatus;
563
564 AcpiStatus = Initialize();
565 if (!ACPI_SUCCESS(AcpiStatus)) {
566 DPRINT("BN init status 0x%X\n", AcpiStatus);
567 return STATUS_UNSUCCESSFUL;
568 }
569 #if 0
570 AcpiDevice = (PACPI_DEVICE)ExAllocatePool(
571 NonPagedPool, sizeof(ACPI_DEVICE));
572 if (!AcpiDevice) {
573 return STATUS_INSUFFICIENT_RESOURCES;
574 }
575
576 AcpiDevice->Initialize = Initialize;
577 AcpiDevice->Terminate = Terminate;
578
579 /* FIXME: Create PDO */
580
581 AcpiDevice->Pdo = NULL;
582 //AcpiDevice->BmHandle = HandleList.handles[i];
583
584 ExInterlockedInsertHeadList(&DeviceExtension->DeviceListHead,
585 &AcpiDevice->ListEntry, &DeviceExtension->DeviceListLock);
586 #endif
587 return STATUS_SUCCESS;
588 }
589
590
591 static NTSTATUS
592 ACPIInitializeInternalDrivers(
593 PFDO_DEVICE_EXTENSION DeviceExtension)
594 {
595 NTSTATUS Status;
596
597 Status = ACPIInitializeInternalDriver(DeviceExtension,
598 bn_initialize, bn_terminate);
599
600 return STATUS_SUCCESS;
601 }
602
603
604 static NTSTATUS
605 FdoStartDevice(
606 IN PDEVICE_OBJECT DeviceObject,
607 IN PIRP Irp)
608 {
609 PFDO_DEVICE_EXTENSION DeviceExtension;
610 ACPI_PHYSICAL_ADDRESS rsdp;
611 ACPI_SYSTEM_INFO SysInfo;
612 ACPI_STATUS AcpiStatus;
613 ACPI_BUFFER Buffer;
614 UCHAR TypeA, TypeB;
615 ULONG i;
616
617 DPRINT("Called\n");
618
619 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
620
621 ASSERT(DeviceExtension->State == dsStopped);
622
623 AcpiStatus = acpi_initialize_subsystem();
624 if (!ACPI_SUCCESS(AcpiStatus)) {
625 DPRINT("acpi_initialize_subsystem() failed with status 0x%X\n", AcpiStatus);
626 return STATUS_UNSUCCESSFUL;
627 }
628
629 AcpiStatus = acpi_find_root_pointer(&rsdp);
630 if (!ACPI_SUCCESS(AcpiStatus)) {
631 DPRINT("acpi_find_root_pointer() failed with status 0x%X\n", AcpiStatus);
632 return STATUS_UNSUCCESSFUL;
633 }
634
635 /* From this point on, on error we must call acpi_terminate() */
636
637 AcpiStatus = acpi_load_tables(rsdp);
638 if (!ACPI_SUCCESS(AcpiStatus)) {
639 DPRINT("acpi_load_tables() failed with status 0x%X\n", AcpiStatus);
640 acpi_terminate();
641 return STATUS_UNSUCCESSFUL;
642 }
643
644 Buffer.length = sizeof(SysInfo);
645 Buffer.pointer = &SysInfo;
646
647 AcpiStatus = acpi_get_system_info(&Buffer);
648 if (!ACPI_SUCCESS(AcpiStatus)) {
649 DPRINT("acpi_get_system_info() failed with status 0x%X\n", AcpiStatus);
650 acpi_terminate();
651 return STATUS_UNSUCCESSFUL;
652 }
653
654 DPRINT("ACPI CA Core Subsystem version 0x%X\n", SysInfo.acpi_ca_version);
655
656 ASSERT(SysInfo.num_table_types > ACPI_TABLE_FADT);
657
658 RtlMoveMemory(&acpi_fadt,
659 &SysInfo.table_info[ACPI_TABLE_FADT],
660 sizeof(FADT_DESCRIPTOR_REV2));
661
662 AcpiStatus = acpi_enable_subsystem(ACPI_FULL_INITIALIZATION);
663 if (!ACPI_SUCCESS(AcpiStatus)) {
664 DPRINT("acpi_enable_subsystem() failed with status 0x%X\n", AcpiStatus);
665 acpi_terminate();
666 return STATUS_UNSUCCESSFUL;
667 }
668
669 DPRINT("ACPI CA Core Subsystem enabled\n");
670
671 /*
672 * Sx States:
673 * ----------
674 * Figure out which Sx states are supported
675 */
676 for (i=0; i<=ACPI_S_STATES_MAX; i++) {
677 AcpiStatus = acpi_hw_obtain_sleep_type_register_data(
678 i,
679 &TypeA,
680 &TypeB);
681 DPRINT("acpi_hw_obtain_sleep_type_register_data (%d) status 0x%X\n",
682 i, AcpiStatus);
683 if (ACPI_SUCCESS(AcpiStatus)) {
684 DeviceExtension->SystemStates[i] = TRUE;
685 }
686 }
687
688 #ifndef NDEBUG
689 ACPIPrintInfo(DeviceExtension);
690 #endif
691
692 /* Initialize ACPI bus manager */
693 AcpiStatus = bm_initialize();
694 if (!ACPI_SUCCESS(AcpiStatus)) {
695 DPRINT("bm_initialize() failed with status 0x%X\n", AcpiStatus);
696 acpi_terminate();
697 return STATUS_UNSUCCESSFUL;
698 }
699
700 InitializeListHead(&DeviceExtension->DeviceListHead);
701 KeInitializeSpinLock(&DeviceExtension->DeviceListLock);
702 DeviceExtension->DeviceListCount = 0;
703
704 ACPIEnumerateDevices(DeviceExtension);
705
706 ACPIInitializeInternalDrivers(DeviceExtension);
707
708 DeviceExtension->State = dsStarted;
709
710 return STATUS_SUCCESS;
711 }
712
713
714 static NTSTATUS
715 FdoSetPower(
716 IN PDEVICE_OBJECT DeviceObject,
717 IN PIRP Irp,
718 PIO_STACK_LOCATION IrpSp)
719 {
720 PFDO_DEVICE_EXTENSION DeviceExtension;
721 ACPI_STATUS AcpiStatus;
722 NTSTATUS Status;
723 ULONG AcpiState;
724
725 DPRINT("Called\n");
726
727 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
728
729 if (IrpSp->Parameters.Power.Type == SystemPowerState) {
730 Status = STATUS_SUCCESS;
731 switch (IrpSp->Parameters.Power.State.SystemState) {
732 case PowerSystemSleeping1:
733 AcpiState = ACPI_STATE_S1;
734 break;
735 case PowerSystemSleeping2:
736 AcpiState = ACPI_STATE_S2;
737 break;
738 case PowerSystemSleeping3:
739 AcpiState = ACPI_STATE_S3;
740 break;
741 case PowerSystemHibernate:
742 AcpiState = ACPI_STATE_S4;
743 break;
744 case PowerSystemShutdown:
745 AcpiState = ACPI_STATE_S5;
746 break;
747 default:
748 Status = STATUS_UNSUCCESSFUL;
749 return Status;
750 }
751 if (!DeviceExtension->SystemStates[AcpiState]) {
752 DPRINT("System sleep state S%d is not supported by hardware\n", AcpiState);
753 Status = STATUS_UNSUCCESSFUL;
754 }
755
756 if (NT_SUCCESS(Status)) {
757 DPRINT("Trying to enter sleep state %d\n", AcpiState);
758
759 AcpiStatus = acpi_enter_sleep_state(AcpiState);
760 if (!ACPI_SUCCESS(AcpiStatus)) {
761 DPRINT("Failed to enter sleep state %d (Status 0x%X)\n",
762 AcpiState, AcpiStatus);
763 Status = STATUS_UNSUCCESSFUL;
764 }
765 }
766 } else {
767 Status = STATUS_UNSUCCESSFUL;
768 }
769
770 return Status;
771 }
772
773
774 /*** PUBLIC ******************************************************************/
775
776 NTSTATUS
777 STDCALL
778 FdoPnpControl(
779 PDEVICE_OBJECT DeviceObject,
780 PIRP Irp)
781 /*
782 * FUNCTION: Handle Plug and Play IRPs for the ACPI device
783 * ARGUMENTS:
784 * DeviceObject = Pointer to functional device object of the ACPI driver
785 * Irp = Pointer to IRP that should be handled
786 * RETURNS:
787 * Status
788 */
789 {
790 PIO_STACK_LOCATION IrpSp;
791 NTSTATUS Status;
792
793 DPRINT("Called\n");
794
795 IrpSp = IoGetCurrentIrpStackLocation(Irp);
796 switch (IrpSp->MinorFunction) {
797 case IRP_MN_CANCEL_REMOVE_DEVICE:
798 Status = STATUS_NOT_IMPLEMENTED;
799 break;
800
801 case IRP_MN_CANCEL_STOP_DEVICE:
802 Status = STATUS_NOT_IMPLEMENTED;
803 break;
804
805 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
806 Status = STATUS_NOT_IMPLEMENTED;
807 break;
808
809 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
810 Status = STATUS_NOT_IMPLEMENTED;
811 break;
812
813 case IRP_MN_QUERY_DEVICE_RELATIONS:
814 Status = FdoQueryBusRelations(DeviceObject, Irp, IrpSp);
815 break;
816
817 case IRP_MN_QUERY_PNP_DEVICE_STATE:
818 Status = STATUS_NOT_IMPLEMENTED;
819 break;
820
821 case IRP_MN_QUERY_REMOVE_DEVICE:
822 Status = STATUS_NOT_IMPLEMENTED;
823 break;
824
825 case IRP_MN_QUERY_STOP_DEVICE:
826 Status = STATUS_NOT_IMPLEMENTED;
827 break;
828
829 case IRP_MN_REMOVE_DEVICE:
830 Status = STATUS_NOT_IMPLEMENTED;
831 break;
832
833 case IRP_MN_START_DEVICE:
834 DPRINT("IRP_MN_START_DEVICE received\n");
835 Status = FdoStartDevice(DeviceObject, Irp);
836 break;
837
838 case IRP_MN_STOP_DEVICE:
839 /* Currently not supported */
840 //bm_terminate();
841 Status = STATUS_UNSUCCESSFUL;
842 break;
843
844 case IRP_MN_SURPRISE_REMOVAL:
845 Status = STATUS_NOT_IMPLEMENTED;
846 break;
847
848 default:
849 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
850 Status = STATUS_NOT_IMPLEMENTED;
851 break;
852 }
853
854 if (Status != STATUS_PENDING) {
855 Irp->IoStatus.Status = Status;
856 IoCompleteRequest(Irp, IO_NO_INCREMENT);
857 }
858
859 DPRINT("Leaving. Status 0x%X\n", Status);
860
861 return Status;
862 }
863
864
865 NTSTATUS
866 STDCALL
867 FdoPowerControl(
868 PDEVICE_OBJECT DeviceObject,
869 PIRP Irp)
870 /*
871 * FUNCTION: Handle power management IRPs for the ACPI device
872 * ARGUMENTS:
873 * DeviceObject = Pointer to functional device object of the ACPI driver
874 * Irp = Pointer to IRP that should be handled
875 * RETURNS:
876 * Status
877 */
878 {
879 PIO_STACK_LOCATION IrpSp;
880 NTSTATUS Status;
881
882 DPRINT("Called\n");
883
884 IrpSp = IoGetCurrentIrpStackLocation(Irp);
885
886 switch (IrpSp->MinorFunction) {
887 case IRP_MN_SET_POWER:
888 Status = FdoSetPower(DeviceObject, Irp, IrpSp);
889 break;
890
891 default:
892 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
893 Status = STATUS_NOT_IMPLEMENTED;
894 break;
895 }
896
897 if (Status != STATUS_PENDING) {
898 Irp->IoStatus.Status = Status;
899 IoCompleteRequest(Irp, IO_NO_INCREMENT);
900 }
901
902 DPRINT("Leaving. Status 0x%X\n", Status);
903
904 return Status;
905 }
906
907 /* EOF */