Merge from amd64-branch:
[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"%S", 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
178 /* Count number of resources */
179 Done = FALSE;
180 resource = resources;
181 while (!Done)
182 {
183 switch (resource->id)
184 {
185 case irq:
186 {
187 IRQ_RESOURCE *irq_data = (IRQ_RESOURCE*) &resource->data;
188 NumberOfResources += irq_data->number_of_interrupts;
189 break;
190 }
191 case dma:
192 {
193 DMA_RESOURCE *dma_data = (DMA_RESOURCE*) &resource->data;
194 NumberOfResources += dma_data->number_of_channels;
195 break;
196 }
197 case io:
198 {
199 NumberOfResources++;
200 break;
201 }
202 case end_tag:
203 {
204 Done = TRUE;
205 break;
206 }
207 default:
208 {
209 break;
210 }
211 }
212 resource = NEXT_RESOURCE(resource);
213 }
214
215 /* Allocate memory */
216 *ResourceListSize = sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * (NumberOfResources - 1);
217 ResourceList = (PCM_RESOURCE_LIST)ExAllocatePool(PagedPool, *ResourceListSize);
218 *pResourceList = ResourceList;
219 if (!ResourceList)
220 return FALSE;
221 ResourceList->Count = 1;
222 ResourceList->List[0].InterfaceType = Internal; /* FIXME */
223 ResourceList->List[0].BusNumber = 0; /* We're the only ACPI bus device in the system */
224 ResourceList->List[0].PartialResourceList.Version = 1;
225 ResourceList->List[0].PartialResourceList.Revision = 1;
226 ResourceList->List[0].PartialResourceList.Count = NumberOfResources;
227 ResourceDescriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
228
229 *RequirementsListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) + sizeof(IO_RESOURCE_DESCRIPTOR) * (NumberOfResources - 1);
230 RequirementsList = (PIO_RESOURCE_REQUIREMENTS_LIST)ExAllocatePool(PagedPool, *RequirementsListSize);
231 *pRequirementsList = RequirementsList;
232 if (!RequirementsList)
233 {
234 ExFreePool(ResourceList);
235 return FALSE;
236 }
237 RequirementsList->ListSize = *RequirementsListSize;
238 RequirementsList->InterfaceType = ResourceList->List[0].InterfaceType;
239 RequirementsList->BusNumber = ResourceList->List[0].BusNumber;
240 RequirementsList->SlotNumber = 0; /* Not used by WDM drivers */
241 RequirementsList->AlternativeLists = 1;
242 RequirementsList->List[0].Version = 1;
243 RequirementsList->List[0].Revision = 1;
244 RequirementsList->List[0].Count = NumberOfResources;
245 RequirementDescriptor = RequirementsList->List[0].Descriptors;
246
247 /* Fill resources list structure */
248 Done = FALSE;
249 resource = resources;
250 while (!Done)
251 {
252 switch (resource->id)
253 {
254 case irq:
255 {
256 IRQ_RESOURCE *irq_data = (IRQ_RESOURCE*) &resource->data;
257 for (i = 0; i < irq_data->number_of_interrupts; i++)
258 {
259 ResourceDescriptor->Type = CmResourceTypeInterrupt;
260
261 ResourceDescriptor->ShareDisposition =
262 (irq_data->shared_exclusive == SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
263 ResourceDescriptor->Flags =
264 (irq_data->edge_level == LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
265 ResourceDescriptor->u.Interrupt.Level = irq_data->interrupts[i];
266 ResourceDescriptor->u.Interrupt.Vector = 0;
267 ResourceDescriptor->u.Interrupt.Affinity = (KAFFINITY)(-1);
268
269 RequirementDescriptor->Option = 0; /* Required */
270 RequirementDescriptor->Type = ResourceDescriptor->Type;
271 RequirementDescriptor->ShareDisposition = ResourceDescriptor->ShareDisposition;
272 RequirementDescriptor->Flags = ResourceDescriptor->Flags;
273 RequirementDescriptor->u.Interrupt.MinimumVector = RequirementDescriptor->u.Interrupt.MaximumVector
274 = irq_data->interrupts[i];
275
276 ResourceDescriptor++;
277 RequirementDescriptor++;
278 }
279 break;
280 }
281 case dma:
282 {
283 DMA_RESOURCE *dma_data = (DMA_RESOURCE*) &resource->data;
284 for (i = 0; i < dma_data->number_of_channels; i++)
285 {
286 ResourceDescriptor->Type = CmResourceTypeDma;
287 ResourceDescriptor->Flags = 0;
288 switch (dma_data->type)
289 {
290 case TYPE_A: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_A; break;
291 case TYPE_B: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_B; break;
292 case TYPE_F: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_F; break;
293 }
294 if (dma_data->bus_master == BUS_MASTER)
295 ResourceDescriptor->Flags |= CM_RESOURCE_DMA_BUS_MASTER;
296 switch (dma_data->transfer)
297 {
298 case TRANSFER_8: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_8; break;
299 case TRANSFER_16: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_16; break;
300 case TRANSFER_8_16: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_8_AND_16; break;
301 }
302 ResourceDescriptor->u.Dma.Channel = dma_data->channels[i];
303
304 RequirementDescriptor->Option = 0; /* Required */
305 RequirementDescriptor->Type = ResourceDescriptor->Type;
306 RequirementDescriptor->ShareDisposition = ResourceDescriptor->ShareDisposition;
307 RequirementDescriptor->Flags = ResourceDescriptor->Flags;
308 RequirementDescriptor->u.Dma.MinimumChannel = RequirementDescriptor->u.Dma.MaximumChannel
309 = ResourceDescriptor->u.Dma.Channel;
310
311 ResourceDescriptor++;
312 RequirementDescriptor++;
313 }
314 break;
315 }
316 case io:
317 {
318 IO_RESOURCE *io_data = (IO_RESOURCE*) &resource->data;
319 ResourceDescriptor->Type = CmResourceTypePort;
320 ResourceDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
321 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
322 if (io_data->io_decode == DECODE_16)
323 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
324 else
325 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
326 ResourceDescriptor->u.Port.Start.u.HighPart = 0;
327 ResourceDescriptor->u.Port.Start.u.LowPart = io_data->min_base_address;
328 ResourceDescriptor->u.Port.Length = io_data->range_length;
329
330 RequirementDescriptor->Option = 0; /* Required */
331 RequirementDescriptor->Type = ResourceDescriptor->Type;
332 RequirementDescriptor->ShareDisposition = ResourceDescriptor->ShareDisposition;
333 RequirementDescriptor->Flags = ResourceDescriptor->Flags;
334 RequirementDescriptor->u.Port.Length = ResourceDescriptor->u.Port.Length;
335 RequirementDescriptor->u.Port.Alignment = 1; /* Start address is specified, so it doesn't matter */
336 RequirementDescriptor->u.Port.MinimumAddress = RequirementDescriptor->u.Port.MaximumAddress
337 = ResourceDescriptor->u.Port.Start;
338
339 ResourceDescriptor++;
340 RequirementDescriptor++;
341 break;
342 }
343 case end_tag:
344 {
345 Done = TRUE;
346 break;
347 }
348 default:
349 {
350 break;
351 }
352 }
353 resource = NEXT_RESOURCE(resource);
354 }
355
356 acpi_rs_dump_resource_list(resource);
357 return TRUE;
358 }
359
360
361 static BOOLEAN
362 AcpiCheckIfIsSerialDebugPort(
363 IN PACPI_DEVICE Device)
364 {
365 ACPI_STATUS AcpiStatus;
366 BM_NODE *Node;
367 ACPI_BUFFER Buffer;
368 BOOLEAN Done;
369 RESOURCE* resource;
370
371 AcpiStatus = bm_get_node(Device->BmHandle, 0, &Node);
372 if (!ACPI_SUCCESS(AcpiStatus))
373 return FALSE;
374
375 /* Get current resources */
376 Buffer.length = 0;
377 AcpiStatus = acpi_get_current_resources(Node->device.acpi_handle, &Buffer);
378 if ((AcpiStatus & ACPI_OK) == 0)
379 return FALSE;
380 if (Buffer.length == 0)
381 return FALSE;
382
383 Buffer.pointer = ExAllocatePool(PagedPool, Buffer.length);
384 if (!Buffer.pointer)
385 return FALSE;
386 AcpiStatus = acpi_get_current_resources(Node->device.acpi_handle, &Buffer);
387 if (!ACPI_SUCCESS(AcpiStatus))
388 {
389 ExFreePool(Buffer.pointer);
390 return FALSE;
391 }
392
393 /* Loop through the list of resources to see if the
394 * device is using the serial port address
395 */
396 Done = FALSE;
397 resource = (RESOURCE*)Buffer.pointer;
398 while (!Done)
399 {
400 switch (resource->id)
401 {
402 case io:
403 {
404 IO_RESOURCE *io_data = (IO_RESOURCE*) &resource->data;
405 if (KdComPortInUse == (PUCHAR)io_data->min_base_address)
406 {
407 ExFreePool(Buffer.pointer);
408 return TRUE;
409 }
410 break;
411 }
412 case end_tag:
413 {
414 Done = TRUE;
415 break;
416 }
417 default:
418 {
419 break;
420 }
421 }
422 resource = (RESOURCE *) ((NATIVE_UINT) resource + (NATIVE_UINT) resource->length);
423 }
424
425 ExFreePool(Buffer.pointer);
426 return FALSE;
427 }
428
429 static NTSTATUS
430 FdoQueryBusRelations(
431 IN PDEVICE_OBJECT DeviceObject,
432 IN PIRP Irp,
433 PIO_STACK_LOCATION IrpSp)
434 {
435 PPDO_DEVICE_EXTENSION PdoDeviceExtension;
436 PFDO_DEVICE_EXTENSION DeviceExtension;
437 PDEVICE_RELATIONS Relations;
438 PLIST_ENTRY CurrentEntry;
439 ACPI_STATUS AcpiStatus;
440 PACPI_DEVICE Device;
441 NTSTATUS Status = STATUS_SUCCESS;
442 BM_NODE *Node;
443 ULONG Size;
444 ULONG i;
445
446 DPRINT("Called\n");
447
448 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
449
450 Size = sizeof(DEVICE_RELATIONS) + sizeof(Relations->Objects) *
451 (DeviceExtension->DeviceListCount - 1);
452 Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, Size);
453 if (!Relations)
454 return STATUS_INSUFFICIENT_RESOURCES;
455
456 Relations->Count = DeviceExtension->DeviceListCount;
457
458 i = 0;
459 CurrentEntry = DeviceExtension->DeviceListHead.Flink;
460 while (CurrentEntry != &DeviceExtension->DeviceListHead)
461 {
462 ACPI_BUFFER Buffer;
463 Device = CONTAINING_RECORD(CurrentEntry, ACPI_DEVICE, DeviceListEntry);
464
465 if (AcpiCheckIfIsSerialDebugPort(Device))
466 {
467 /* Skip this device */
468 DPRINT("Found debug serial port ; skipping it\n");
469 Relations->Count--;
470 CurrentEntry = CurrentEntry->Flink;
471 continue;
472 }
473
474 /* FIXME: For ACPI namespace devices on the motherboard create filter DOs
475 and attach them just above the ACPI bus device object (PDO) */
476
477 /* FIXME: For other devices in ACPI namespace, but not on motherboard,
478 create PDOs */
479
480 if (!Device->Pdo)
481 {
482 /* Create a physical device object for the
483 device as it does not already have one */
484 Status = IoCreateDevice(DeviceObject->DriverObject,
485 sizeof(PDO_DEVICE_EXTENSION),
486 NULL,
487 FILE_DEVICE_CONTROLLER,
488 FILE_AUTOGENERATED_DEVICE_NAME,
489 FALSE,
490 &Device->Pdo);
491 if (!NT_SUCCESS(Status))
492 {
493 DPRINT("IoCreateDevice() failed with status 0x%X\n", Status);
494 /* FIXME: Cleanup all new PDOs created in this call */
495 ExFreePool(Relations);
496 return Status;
497 }
498
499 PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension;
500
501 RtlZeroMemory(PdoDeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
502
503 Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
504
505 Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
506
507 //Device->Pdo->Flags |= DO_POWER_PAGABLE;
508
509 PdoDeviceExtension->Common.DeviceObject = Device->Pdo;
510
511 PdoDeviceExtension->Common.DevicePowerState = PowerDeviceD0;
512
513 // PdoDeviceExtension->Common.Ldo = IoAttachDeviceToDeviceStack(DeviceObject,
514 // Device->Pdo);
515
516 RtlInitUnicodeString(&PdoDeviceExtension->DeviceID, NULL);
517 RtlInitUnicodeString(&PdoDeviceExtension->InstanceID, NULL);
518 RtlInitUnicodeString(&PdoDeviceExtension->HardwareIDs, NULL);
519
520 AcpiStatus = bm_get_node(Device->BmHandle, 0, &Node);
521 if (ACPI_SUCCESS(AcpiStatus))
522 {
523 /* Get current resources */
524 Buffer.length = 0;
525 Status = acpi_get_current_resources(Node->device.acpi_handle, &Buffer);
526 if ((Status & ACPI_OK) == 0)
527 {
528 ASSERT(FALSE);
529 }
530 if (Buffer.length > 0)
531 {
532 Buffer.pointer = ExAllocatePool(PagedPool, Buffer.length);
533 if (!Buffer.pointer)
534 {
535 ASSERT(FALSE);
536 }
537 Status = acpi_get_current_resources(Node->device.acpi_handle, &Buffer);
538 if (ACPI_FAILURE(Status))
539 {
540 ASSERT(FALSE);
541 }
542 if (!AcpiCreateResourceList(&PdoDeviceExtension->ResourceList,
543 &PdoDeviceExtension->ResourceListSize,
544 &PdoDeviceExtension->ResourceRequirementsList,
545 &PdoDeviceExtension->ResourceRequirementsListSize,
546 (RESOURCE*)Buffer.pointer))
547 {
548 ASSERT(FALSE);
549 }
550 ExFreePool(Buffer.pointer);
551 }
552
553 /* Add Device ID string */
554 if (!AcpiCreateDeviceIDString(&PdoDeviceExtension->DeviceID,
555 Node))
556 {
557 ASSERT(FALSE);
558 // ErrorStatus = STATUS_INSUFFICIENT_RESOURCES;
559 // ErrorOccurred = TRUE;
560 // break;
561 }
562
563 if (!AcpiCreateInstanceIDString(&PdoDeviceExtension->InstanceID,
564 Node))
565 {
566 ASSERT(FALSE);
567 // ErrorStatus = STATUS_INSUFFICIENT_RESOURCES;
568 // ErrorOccurred = TRUE;
569 // break;
570 }
571
572 if (!AcpiCreateHardwareIDsString(&PdoDeviceExtension->HardwareIDs,
573 Node))
574 {
575 ASSERT(FALSE);
576 // ErrorStatus = STATUS_INSUFFICIENT_RESOURCES;
577 // ErrorOccurred = TRUE;
578 // break;
579 }
580
581 if (!AcpiCreateDeviceDescriptionString(&PdoDeviceExtension->DeviceDescription,
582 Node))
583 {
584 ASSERT(FALSE);
585 // ErrorStatus = STATUS_INSUFFICIENT_RESOURCES;
586 // ErrorOccurred = TRUE;
587 // break;
588 }
589 }
590 }
591
592 /* Reference the physical device object. The PnP manager
593 will dereference it again when it is no longer needed */
594 ObReferenceObject(Device->Pdo);
595
596 Relations->Objects[i] = Device->Pdo;
597
598 i++;
599
600 CurrentEntry = CurrentEntry->Flink;
601 }
602
603 Irp->IoStatus.Information = (ULONG)Relations;
604
605 return Status;
606 }
607
608 #ifndef NDEBUG
609 static VOID
610 ACPIPrintInfo(
611 PFDO_DEVICE_EXTENSION DeviceExtension)
612 {
613 DbgPrint("ACPI: System firmware supports:\n");
614
615 /*
616 * Print out basic system information
617 */
618 DbgPrint("+------------------------------------------------------------\n");
619 DbgPrint("| Sx states: %cS0 %cS1 %cS2 %cS3 %cS4 %cS5\n",
620 (DeviceExtension->SystemStates[0]?'+':'-'),
621 (DeviceExtension->SystemStates[1]?'+':'-'),
622 (DeviceExtension->SystemStates[2]?'+':'-'),
623 (DeviceExtension->SystemStates[3]?'+':'-'),
624 (DeviceExtension->SystemStates[4]?'+':'-'),
625 (DeviceExtension->SystemStates[5]?'+':'-'));
626 DbgPrint("+------------------------------------------------------------\n");
627 }
628 #endif
629
630 static NTSTATUS
631 ACPIInitializeInternalDriver(
632 PFDO_DEVICE_EXTENSION DeviceExtension,
633 ACPI_DRIVER_FUNCTION Initialize,
634 ACPI_DRIVER_FUNCTION Terminate)
635 {
636 ACPI_STATUS AcpiStatus;
637
638 AcpiStatus = Initialize();
639 if (!ACPI_SUCCESS(AcpiStatus)) {
640 DPRINT("BN init status 0x%X\n", AcpiStatus);
641 return STATUS_UNSUCCESSFUL;
642 }
643 #if 0
644 AcpiDevice = (PACPI_DEVICE)ExAllocatePool(
645 NonPagedPool, sizeof(ACPI_DEVICE));
646 if (!AcpiDevice) {
647 return STATUS_INSUFFICIENT_RESOURCES;
648 }
649
650 AcpiDevice->Initialize = Initialize;
651 AcpiDevice->Terminate = Terminate;
652
653 /* FIXME: Create PDO */
654
655 AcpiDevice->Pdo = NULL;
656 //AcpiDevice->BmHandle = HandleList.handles[i];
657
658 ExInterlockedInsertHeadList(&DeviceExtension->DeviceListHead,
659 &AcpiDevice->ListEntry, &DeviceExtension->DeviceListLock);
660 #endif
661 return STATUS_SUCCESS;
662 }
663
664
665 static NTSTATUS
666 ACPIInitializeInternalDrivers(
667 PFDO_DEVICE_EXTENSION DeviceExtension)
668 {
669 NTSTATUS Status;
670
671 Status = ACPIInitializeInternalDriver(DeviceExtension,
672 bn_initialize, bn_terminate);
673
674 return STATUS_SUCCESS;
675 }
676
677
678 static NTSTATUS
679 FdoStartDevice(
680 IN PDEVICE_OBJECT DeviceObject,
681 IN PIRP Irp)
682 {
683 PFDO_DEVICE_EXTENSION DeviceExtension;
684 ACPI_PHYSICAL_ADDRESS rsdp;
685 ACPI_SYSTEM_INFO SysInfo;
686 ACPI_STATUS AcpiStatus;
687 ACPI_BUFFER Buffer;
688 UCHAR TypeA, TypeB;
689 ULONG i;
690
691 DPRINT("Called\n");
692
693 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
694
695 ASSERT(DeviceExtension->State == dsStopped);
696
697 AcpiStatus = acpi_initialize_subsystem();
698 if (!ACPI_SUCCESS(AcpiStatus)) {
699 DPRINT("acpi_initialize_subsystem() failed with status 0x%X\n", AcpiStatus);
700 return STATUS_UNSUCCESSFUL;
701 }
702
703 AcpiStatus = acpi_find_root_pointer(&rsdp);
704 if (!ACPI_SUCCESS(AcpiStatus)) {
705 DPRINT("acpi_find_root_pointer() failed with status 0x%X\n", AcpiStatus);
706 return STATUS_UNSUCCESSFUL;
707 }
708
709 /* From this point on, on error we must call acpi_terminate() */
710
711 AcpiStatus = acpi_load_tables(rsdp);
712 if (!ACPI_SUCCESS(AcpiStatus)) {
713 DPRINT("acpi_load_tables() failed with status 0x%X\n", AcpiStatus);
714 acpi_terminate();
715 return STATUS_UNSUCCESSFUL;
716 }
717
718 Buffer.length = sizeof(SysInfo);
719 Buffer.pointer = &SysInfo;
720
721 AcpiStatus = acpi_get_system_info(&Buffer);
722 if (!ACPI_SUCCESS(AcpiStatus)) {
723 DPRINT("acpi_get_system_info() failed with status 0x%X\n", AcpiStatus);
724 acpi_terminate();
725 return STATUS_UNSUCCESSFUL;
726 }
727
728 DPRINT("ACPI CA Core Subsystem version 0x%X\n", SysInfo.acpi_ca_version);
729
730 ASSERT(SysInfo.num_table_types > ACPI_TABLE_FADT);
731
732 RtlMoveMemory(&acpi_fadt,
733 &SysInfo.table_info[ACPI_TABLE_FADT],
734 sizeof(FADT_DESCRIPTOR_REV2));
735
736 AcpiStatus = acpi_enable_subsystem(ACPI_FULL_INITIALIZATION);
737 if (!ACPI_SUCCESS(AcpiStatus)) {
738 DPRINT("acpi_enable_subsystem() failed with status 0x%X\n", AcpiStatus);
739 acpi_terminate();
740 return STATUS_UNSUCCESSFUL;
741 }
742
743 DPRINT("ACPI CA Core Subsystem enabled\n");
744
745 /*
746 * Sx States:
747 * ----------
748 * Figure out which Sx states are supported
749 */
750 for (i=0; i<=ACPI_S_STATES_MAX; i++) {
751 AcpiStatus = acpi_hw_obtain_sleep_type_register_data(
752 i,
753 &TypeA,
754 &TypeB);
755 DPRINT("acpi_hw_obtain_sleep_type_register_data (%d) status 0x%X\n",
756 i, AcpiStatus);
757 if (ACPI_SUCCESS(AcpiStatus)) {
758 DeviceExtension->SystemStates[i] = TRUE;
759 }
760 }
761
762 #ifndef NDEBUG
763 ACPIPrintInfo(DeviceExtension);
764 #endif
765
766 /* Initialize ACPI bus manager */
767 AcpiStatus = bm_initialize();
768 if (!ACPI_SUCCESS(AcpiStatus)) {
769 DPRINT("bm_initialize() failed with status 0x%X\n", AcpiStatus);
770 acpi_terminate();
771 return STATUS_UNSUCCESSFUL;
772 }
773
774 InitializeListHead(&DeviceExtension->DeviceListHead);
775 KeInitializeSpinLock(&DeviceExtension->DeviceListLock);
776 DeviceExtension->DeviceListCount = 0;
777
778 #if 0
779 ACPIEnumerateDevices(DeviceExtension);
780 #endif
781
782 ACPIInitializeInternalDrivers(DeviceExtension);
783
784 DeviceExtension->State = dsStarted;
785
786 return STATUS_SUCCESS;
787 }
788
789
790 static NTSTATUS
791 FdoSetPower(
792 IN PDEVICE_OBJECT DeviceObject,
793 IN PIRP Irp,
794 PIO_STACK_LOCATION IrpSp)
795 {
796 PFDO_DEVICE_EXTENSION DeviceExtension;
797 ACPI_STATUS AcpiStatus;
798 NTSTATUS Status;
799 ULONG AcpiState;
800
801 DPRINT("Called\n");
802
803 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
804
805 if (IrpSp->Parameters.Power.Type == SystemPowerState) {
806 Status = STATUS_SUCCESS;
807 switch (IrpSp->Parameters.Power.State.SystemState) {
808 case PowerSystemSleeping1:
809 AcpiState = ACPI_STATE_S1;
810 break;
811 case PowerSystemSleeping2:
812 AcpiState = ACPI_STATE_S2;
813 break;
814 case PowerSystemSleeping3:
815 AcpiState = ACPI_STATE_S3;
816 break;
817 case PowerSystemHibernate:
818 AcpiState = ACPI_STATE_S4;
819 break;
820 case PowerSystemShutdown:
821 AcpiState = ACPI_STATE_S5;
822 break;
823 default:
824 Status = STATUS_UNSUCCESSFUL;
825 return Status;
826 }
827 if (!DeviceExtension->SystemStates[AcpiState]) {
828 DPRINT("System sleep state S%d is not supported by hardware\n", AcpiState);
829 Status = STATUS_UNSUCCESSFUL;
830 }
831
832 if (NT_SUCCESS(Status)) {
833 DPRINT("Trying to enter sleep state %d\n", AcpiState);
834
835 AcpiStatus = acpi_enter_sleep_state(AcpiState);
836 if (!ACPI_SUCCESS(AcpiStatus)) {
837 DPRINT("Failed to enter sleep state %d (Status 0x%X)\n",
838 AcpiState, AcpiStatus);
839 Status = STATUS_UNSUCCESSFUL;
840 }
841 }
842 } else {
843 Status = STATUS_UNSUCCESSFUL;
844 }
845
846 return Status;
847 }
848
849
850 /*** PUBLIC ******************************************************************/
851
852 NTSTATUS
853 NTAPI
854 FdoPnpControl(
855 PDEVICE_OBJECT DeviceObject,
856 PIRP Irp)
857 /*
858 * FUNCTION: Handle Plug and Play IRPs for the ACPI device
859 * ARGUMENTS:
860 * DeviceObject = Pointer to functional device object of the ACPI driver
861 * Irp = Pointer to IRP that should be handled
862 * RETURNS:
863 * Status
864 */
865 {
866 PIO_STACK_LOCATION IrpSp;
867 NTSTATUS Status;
868
869 DPRINT("Called\n");
870
871 IrpSp = IoGetCurrentIrpStackLocation(Irp);
872 switch (IrpSp->MinorFunction) {
873 //case IRP_MN_CANCEL_REMOVE_DEVICE:
874 // Status = STATUS_NOT_IMPLEMENTED;
875 // break;
876
877 //case IRP_MN_CANCEL_STOP_DEVICE:
878 // Status = STATUS_NOT_IMPLEMENTED;
879 // break;
880
881 //case IRP_MN_DEVICE_USAGE_NOTIFICATION:
882 // Status = STATUS_NOT_IMPLEMENTED;
883 // break;
884
885 //case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
886 // Status = STATUS_NOT_IMPLEMENTED;
887 // break;
888
889 case IRP_MN_QUERY_DEVICE_RELATIONS:
890 Status = FdoQueryBusRelations(DeviceObject, Irp, IrpSp);
891 break;
892
893 //case IRP_MN_QUERY_PNP_DEVICE_STATE:
894 // Status = STATUS_NOT_IMPLEMENTED;
895 // break;
896
897 //case IRP_MN_QUERY_REMOVE_DEVICE:
898 // Status = STATUS_NOT_IMPLEMENTED;
899 // break;
900
901 //case IRP_MN_QUERY_STOP_DEVICE:
902 // Status = STATUS_NOT_IMPLEMENTED;
903 // break;
904
905 //case IRP_MN_REMOVE_DEVICE:
906 // Status = STATUS_NOT_IMPLEMENTED;
907 // break;
908
909 case IRP_MN_START_DEVICE:
910 DPRINT("IRP_MN_START_DEVICE received\n");
911 Status = FdoStartDevice(DeviceObject, Irp);
912 break;
913
914 case IRP_MN_STOP_DEVICE:
915 /* Currently not supported */
916 //bm_terminate();
917 Status = STATUS_UNSUCCESSFUL;
918 break;
919
920 //case IRP_MN_SURPRISE_REMOVAL:
921 // Status = STATUS_NOT_IMPLEMENTED;
922 // break;
923
924 default:
925 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
926 Status = Irp->IoStatus.Status;
927 break;
928 }
929
930 if (Status != STATUS_PENDING) {
931 Irp->IoStatus.Status = Status;
932 IoCompleteRequest(Irp, IO_NO_INCREMENT);
933 }
934
935 DPRINT("Leaving. Status 0x%X\n", Status);
936
937 return Status;
938 }
939
940
941 NTSTATUS
942 NTAPI
943 FdoPowerControl(
944 PDEVICE_OBJECT DeviceObject,
945 PIRP Irp)
946 /*
947 * FUNCTION: Handle power management IRPs for the ACPI device
948 * ARGUMENTS:
949 * DeviceObject = Pointer to functional device object of the ACPI driver
950 * Irp = Pointer to IRP that should be handled
951 * RETURNS:
952 * Status
953 */
954 {
955 PIO_STACK_LOCATION IrpSp;
956 NTSTATUS Status;
957
958 DPRINT("Called\n");
959
960 IrpSp = IoGetCurrentIrpStackLocation(Irp);
961
962 switch (IrpSp->MinorFunction) {
963 case IRP_MN_SET_POWER:
964 Status = FdoSetPower(DeviceObject, Irp, IrpSp);
965 break;
966
967 default:
968 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
969 Status = STATUS_NOT_IMPLEMENTED;
970 break;
971 }
972
973 if (Status != STATUS_PENDING) {
974 Irp->IoStatus.Status = Status;
975 IoCompleteRequest(Irp, IO_NO_INCREMENT);
976 }
977
978 DPRINT("Leaving. Status 0x%X\n", Status);
979
980 return Status;
981 }
982
983 /* EOF */