1 /*
2 * PROJECT: ReactOS HAL
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: hal/halx86/acpi/halpnpdd.c
5 * PURPOSE: HAL Plug and Play Device Driver
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <hal.h>
12
13 #include <initguid.h>
14 #include <wdmguid.h>
15
16 #define NDEBUG
17 #include <debug.h>
18
19 typedef enum _EXTENSION_TYPE
20 {
21 PdoExtensionType = 0xC0,
22 FdoExtensionType
23 } EXTENSION_TYPE;
24
25 typedef enum _PDO_TYPE
26 {
27 AcpiPdo = 0x80,
28 WdPdo
29 } PDO_TYPE;
30
31 typedef struct _FDO_EXTENSION
32 {
33 EXTENSION_TYPE ExtensionType;
34 struct _PDO_EXTENSION* ChildPdoList;
35 PDEVICE_OBJECT PhysicalDeviceObject;
36 PDEVICE_OBJECT FunctionalDeviceObject;
37 PDEVICE_OBJECT AttachedDeviceObject;
38 } FDO_EXTENSION, *PFDO_EXTENSION;
39
40 typedef struct _PDO_EXTENSION
41 {
42 EXTENSION_TYPE ExtensionType;
43 struct _PDO_EXTENSION* Next;
44 PDEVICE_OBJECT PhysicalDeviceObject;
45 PFDO_EXTENSION ParentFdoExtension;
46 PDO_TYPE PdoType;
47 PDESCRIPTION_HEADER WdTable;
48 LONG InterfaceReferenceCount;
49 } PDO_EXTENSION, *PPDO_EXTENSION;
50
51 /* GLOBALS ********************************************************************/
52
53 PDRIVER_OBJECT HalpDriverObject;
54
55 /* PRIVATE FUNCTIONS **********************************************************/
56
57 NTSTATUS
58 NTAPI
HalpAddDevice(IN PDRIVER_OBJECT DriverObject,IN PDEVICE_OBJECT TargetDevice)59 HalpAddDevice(IN PDRIVER_OBJECT DriverObject,
60 IN PDEVICE_OBJECT TargetDevice)
61 {
62 NTSTATUS Status;
63 PFDO_EXTENSION FdoExtension;
64 PPDO_EXTENSION PdoExtension;
65 PDEVICE_OBJECT DeviceObject, AttachedDevice;
66 PDEVICE_OBJECT PdoDeviceObject;
67 PDESCRIPTION_HEADER Wdrt;
68
69 DPRINT("HAL: PnP Driver ADD!\n");
70
71 /* Create the FDO */
72 Status = IoCreateDevice(DriverObject,
73 sizeof(FDO_EXTENSION),
74 NULL,
75 FILE_DEVICE_BUS_EXTENDER,
76 0,
77 FALSE,
78 &DeviceObject);
79 if (!NT_SUCCESS(Status))
80 {
81 /* Should not happen */
82 DbgBreakPoint();
83 return Status;
84 }
85
86 /* Setup the FDO extension */
87 FdoExtension = DeviceObject->DeviceExtension;
88 FdoExtension->ExtensionType = FdoExtensionType;
89 FdoExtension->PhysicalDeviceObject = TargetDevice;
90 FdoExtension->FunctionalDeviceObject = DeviceObject;
91 FdoExtension->ChildPdoList = NULL;
92
93 /* FDO is done initializing */
94 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
95
96 /* Attach to the physical device object (the bus) */
97 AttachedDevice = IoAttachDeviceToDeviceStack(DeviceObject, TargetDevice);
98 if (!AttachedDevice)
99 {
100 /* Failed, undo everything */
101 IoDeleteDevice(DeviceObject);
102 return STATUS_NO_SUCH_DEVICE;
103 }
104
105 /* Save the attachment */
106 FdoExtension->AttachedDeviceObject = AttachedDevice;
107
108 /* Create the PDO */
109 Status = IoCreateDevice(DriverObject,
110 sizeof(PDO_EXTENSION),
111 NULL,
112 FILE_DEVICE_BUS_EXTENDER,
113 FILE_AUTOGENERATED_DEVICE_NAME,
114 FALSE,
115 &PdoDeviceObject);
116 if (!NT_SUCCESS(Status))
117 {
118 /* Fail */
119 DPRINT1("HAL: Could not create ACPI device object status=0x%08x\n", Status);
120 return Status;
121 }
122
123 /* Setup the PDO device extension */
124 PdoExtension = PdoDeviceObject->DeviceExtension;
125 PdoExtension->ExtensionType = PdoExtensionType;
126 PdoExtension->PhysicalDeviceObject = PdoDeviceObject;
127 PdoExtension->ParentFdoExtension = FdoExtension;
128 PdoExtension->PdoType = AcpiPdo;
129
130 /* Add the PDO to the head of the list */
131 PdoExtension->Next = FdoExtension->ChildPdoList;
132 FdoExtension->ChildPdoList = PdoExtension;
133
134 /* Initialization is finished */
135 PdoDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
136
137 /* Find the ACPI watchdog table */
138 Wdrt = HalAcpiGetTable(0, 'TRDW');
139 if (Wdrt)
140 {
141 /* FIXME: TODO */
142 DPRINT1("You have an ACPI Watchdog. That's great! You should be proud ;-)\n");
143 }
144
145 /* Return status */
146 DPRINT("Device added %lx\n", Status);
147 return Status;
148 }
149
150 NTSTATUS
151 NTAPI
HalpQueryInterface(IN PDEVICE_OBJECT DeviceObject,IN CONST GUID * InterfaceType,IN USHORT Version,IN PVOID InterfaceSpecificData,IN ULONG InterfaceBufferSize,IN PINTERFACE Interface,OUT PULONG Length)152 HalpQueryInterface(IN PDEVICE_OBJECT DeviceObject,
153 IN CONST GUID* InterfaceType,
154 IN USHORT Version,
155 IN PVOID InterfaceSpecificData,
156 IN ULONG InterfaceBufferSize,
157 IN PINTERFACE Interface,
158 OUT PULONG Length)
159 {
160 if (IsEqualIID(InterfaceType, &GUID_ACPI_REGS_INTERFACE_STANDARD))
161 {
162 DPRINT1("HalpQueryInterface(GUID_ACPI_REGS_INTERFACE_STANDARD) is UNIMPLEMENTED\n");
163 }
164 else if (IsEqualIID(InterfaceType, &GUID_ACPI_PORT_RANGES_INTERFACE_STANDARD))
165 {
166 DPRINT1("HalpQueryInterface(GUID_ACPI_PORT_RANGES_INTERFACE_STANDARD) is UNIMPLEMENTED\n");
167 }
168 else
169 {
170 DPRINT1("HalpQueryInterface({%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}) is UNIMPLEMENTED\n",
171 InterfaceType->Data1, InterfaceType->Data2, InterfaceType->Data3,
172 InterfaceType->Data4[0], InterfaceType->Data4[1],
173 InterfaceType->Data4[2], InterfaceType->Data4[3],
174 InterfaceType->Data4[4], InterfaceType->Data4[5],
175 InterfaceType->Data4[6], InterfaceType->Data4[7]);
176 }
177 return STATUS_NOT_SUPPORTED;
178 }
179
180 NTSTATUS
181 NTAPI
HalpQueryDeviceRelations(IN PDEVICE_OBJECT DeviceObject,IN DEVICE_RELATION_TYPE RelationType,OUT PDEVICE_RELATIONS * DeviceRelations)182 HalpQueryDeviceRelations(IN PDEVICE_OBJECT DeviceObject,
183 IN DEVICE_RELATION_TYPE RelationType,
184 OUT PDEVICE_RELATIONS* DeviceRelations)
185 {
186 EXTENSION_TYPE ExtensionType;
187 PPDO_EXTENSION PdoExtension;
188 PFDO_EXTENSION FdoExtension;
189 PDEVICE_RELATIONS PdoRelations, FdoRelations;
190 PDEVICE_OBJECT* ObjectEntry;
191 ULONG i = 0, PdoCount = 0;
192
193 /* Get FDO device extension and PDO count */
194 FdoExtension = DeviceObject->DeviceExtension;
195 ExtensionType = FdoExtension->ExtensionType;
196
197 /* What do they want? */
198 if (RelationType == BusRelations)
199 {
200 /* This better be an FDO */
201 if (ExtensionType == FdoExtensionType)
202 {
203 /* Count how many PDOs we have */
204 PdoExtension = FdoExtension->ChildPdoList;
205 while (PdoExtension)
206 {
207 /* Next one */
208 PdoExtension = PdoExtension->Next;
209 PdoCount++;
210 }
211
212 /* Add the PDOs that already exist in the device relations */
213 if (*DeviceRelations)
214 {
215 PdoCount += (*DeviceRelations)->Count;
216 }
217
218 /* Allocate our structure */
219 FdoRelations = ExAllocatePoolWithTag(PagedPool,
220 FIELD_OFFSET(DEVICE_RELATIONS,
221 Objects) +
222 sizeof(PDEVICE_OBJECT) * PdoCount,
223 TAG_HAL);
224 if (!FdoRelations) return STATUS_INSUFFICIENT_RESOURCES;
225
226 /* Save our count */
227 FdoRelations->Count = PdoCount;
228
229 /* Query existing relations */
230 ObjectEntry = FdoRelations->Objects;
231 if (*DeviceRelations)
232 {
233 /* Check if there were any */
234 if ((*DeviceRelations)->Count)
235 {
236 /* Loop them all */
237 do
238 {
239 /* Copy into our structure */
240 *ObjectEntry++ = (*DeviceRelations)->Objects[i];
241 }
242 while (++i < (*DeviceRelations)->Count);
243 }
244
245 /* Free existing structure */
246 ExFreePool(*DeviceRelations);
247 }
248
249 /* Now check if we have a PDO list */
250 PdoExtension = FdoExtension->ChildPdoList;
251 if (PdoExtension)
252 {
253 /* Loop the PDOs */
254 do
255 {
256 /* Save our own PDO and reference it */
257 *ObjectEntry++ = PdoExtension->PhysicalDeviceObject;
258 ObReferenceObject(PdoExtension->PhysicalDeviceObject);
259
260 /* Go to our next PDO */
261 PdoExtension = PdoExtension->Next;
262 }
263 while (PdoExtension);
264 }
265
266 /* Return the new structure */
267 *DeviceRelations = FdoRelations;
268 return STATUS_SUCCESS;
269 }
270 }
271 else
272 {
273 /* The only other thing we support is a target relation for the PDO */
274 if ((RelationType == TargetDeviceRelation) &&
275 (ExtensionType == PdoExtensionType))
276 {
277 /* Only one entry */
278 PdoRelations = ExAllocatePoolWithTag(PagedPool,
279 sizeof(DEVICE_RELATIONS),
280 TAG_HAL);
281 if (!PdoRelations) return STATUS_INSUFFICIENT_RESOURCES;
282
283 /* Fill it out and reference us */
284 PdoRelations->Count = 1;
285 PdoRelations->Objects[0] = DeviceObject;
286 ObReferenceObject(DeviceObject);
287
288 /* Return it */
289 *DeviceRelations = PdoRelations;
290 return STATUS_SUCCESS;
291 }
292 }
293
294 /* We don't support anything else */
295 return STATUS_NOT_SUPPORTED;
296 }
297
298 NTSTATUS
299 NTAPI
HalpQueryCapabilities(IN PDEVICE_OBJECT DeviceObject,OUT PDEVICE_CAPABILITIES Capabilities)300 HalpQueryCapabilities(IN PDEVICE_OBJECT DeviceObject,
301 OUT PDEVICE_CAPABILITIES Capabilities)
302 {
303 //PPDO_EXTENSION PdoExtension;
304 NTSTATUS Status;
305 PAGED_CODE();
306
307 /* Get the extension and check for valid version */
308 //PdoExtension = DeviceObject->DeviceExtension;
309 ASSERT(Capabilities->Version == 1);
310 if (Capabilities->Version == 1)
311 {
312 /* Can't lock or eject us */
313 Capabilities->LockSupported = FALSE;
314 Capabilities->EjectSupported = FALSE;
315
316 /* Can't remove or dock us */
317 Capabilities->Removable = FALSE;
318 Capabilities->DockDevice = FALSE;
319
320 /* Can't access us raw */
321 Capabilities->RawDeviceOK = FALSE;
322
323 /* We have a unique ID, and don't bother the user */
324 Capabilities->UniqueID = TRUE;
325 Capabilities->SilentInstall = TRUE;
326
327 /* Fill out the address */
328 Capabilities->Address = InterfaceTypeUndefined;
329 Capabilities->UINumber = InterfaceTypeUndefined;
330
331 /* Fill out latencies */
332 Capabilities->D1Latency = 0;
333 Capabilities->D2Latency = 0;
334 Capabilities->D3Latency = 0;
335
336 /* Fill out supported device states */
337 Capabilities->DeviceState[PowerSystemWorking] = PowerDeviceD0;
338 Capabilities->DeviceState[PowerSystemHibernate] = PowerDeviceD3;
339 Capabilities->DeviceState[PowerSystemShutdown] = PowerDeviceD3;
340 Capabilities->DeviceState[PowerSystemSleeping3] = PowerDeviceD3;
341
342 /* Done */
343 Status = STATUS_SUCCESS;
344 }
345 else
346 {
347 /* Fail */
348 Status = STATUS_NOT_SUPPORTED;
349 }
350
351 /* Return status */
352 return Status;
353 }
354
355 NTSTATUS
356 NTAPI
HalpQueryResources(IN PDEVICE_OBJECT DeviceObject,OUT PCM_RESOURCE_LIST * Resources)357 HalpQueryResources(IN PDEVICE_OBJECT DeviceObject,
358 OUT PCM_RESOURCE_LIST *Resources)
359 {
360 PPDO_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
361 NTSTATUS Status;
362 PCM_RESOURCE_LIST ResourceList;
363 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
364 PIO_RESOURCE_DESCRIPTOR Descriptor;
365 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDesc;
366 ULONG i;
367 PAGED_CODE();
368
369 /* Only the ACPI PDO has requirements */
370 if (DeviceExtension->PdoType == AcpiPdo)
371 {
372 /* Query ACPI requirements */
373 Status = HalpQueryAcpiResourceRequirements(&RequirementsList);
374 if (!NT_SUCCESS(Status)) return Status;
375
376 ASSERT(RequirementsList->AlternativeLists == 1);
377
378 /* Allocate the resourcel ist */
379 ResourceList = ExAllocatePoolWithTag(PagedPool,
380 sizeof(CM_RESOURCE_LIST),
381 TAG_HAL);
382 if (!ResourceList )
383 {
384 /* Fail, no memory */
385 Status = STATUS_INSUFFICIENT_RESOURCES;
386 ExFreePoolWithTag(RequirementsList, TAG_HAL);
387 return Status;
388 }
389
390 /* Initialize it */
391 RtlZeroMemory(ResourceList, sizeof(CM_RESOURCE_LIST));
392 ResourceList->Count = 1;
393
394 /* Setup the list fields */
395 ResourceList->List[0].BusNumber = -1;
396 ResourceList->List[0].InterfaceType = PNPBus;
397 ResourceList->List[0].PartialResourceList.Version = 1;
398 ResourceList->List[0].PartialResourceList.Revision = 1;
399 ResourceList->List[0].PartialResourceList.Count = 0;
400
401 /* Setup the first descriptor */
402 PartialDesc = ResourceList->List[0].PartialResourceList.PartialDescriptors;
403
404 /* Find the requirement descriptor for the SCI */
405 for (i = 0; i < RequirementsList->List[0].Count; i++)
406 {
407 /* Get this descriptor */
408 Descriptor = &RequirementsList->List[0].Descriptors[i];
409 if (Descriptor->Type == CmResourceTypeInterrupt)
410 {
411 /* Copy requirements descriptor into resource descriptor */
412 PartialDesc->Type = CmResourceTypeInterrupt;
413 PartialDesc->ShareDisposition = Descriptor->ShareDisposition;
414 PartialDesc->Flags = Descriptor->Flags;
415 ASSERT(Descriptor->u.Interrupt.MinimumVector ==
416 Descriptor->u.Interrupt.MaximumVector);
417 PartialDesc->u.Interrupt.Vector = Descriptor->u.Interrupt.MinimumVector;
418 PartialDesc->u.Interrupt.Level = Descriptor->u.Interrupt.MinimumVector;
419 PartialDesc->u.Interrupt.Affinity = 0xFFFFFFFF;
420
421 ResourceList->List[0].PartialResourceList.Count++;
422
423 break;
424 }
425 }
426
427 /* Return resources and success */
428 *Resources = ResourceList;
429
430 ExFreePoolWithTag(RequirementsList, TAG_HAL);
431
432 return STATUS_SUCCESS;
433 }
434 else if (DeviceExtension->PdoType == WdPdo)
435 {
436 /* Watchdog doesn't */
437 return STATUS_NOT_SUPPORTED;
438 }
439 else
440 {
441 /* This shouldn't happen */
442 return STATUS_UNSUCCESSFUL;
443 }
444 }
445
446 NTSTATUS
447 NTAPI
HalpQueryResourceRequirements(IN PDEVICE_OBJECT DeviceObject,OUT PIO_RESOURCE_REQUIREMENTS_LIST * Requirements)448 HalpQueryResourceRequirements(IN PDEVICE_OBJECT DeviceObject,
449 OUT PIO_RESOURCE_REQUIREMENTS_LIST *Requirements)
450 {
451 PPDO_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
452 PAGED_CODE();
453
454 /* Only the ACPI PDO has requirements */
455 if (DeviceExtension->PdoType == AcpiPdo)
456 {
457 /* Query ACPI requirements */
458 return HalpQueryAcpiResourceRequirements(Requirements);
459 }
460 else if (DeviceExtension->PdoType == WdPdo)
461 {
462 /* Watchdog doesn't */
463 return STATUS_NOT_SUPPORTED;
464 }
465 else
466 {
467 /* This shouldn't happen */
468 return STATUS_UNSUCCESSFUL;
469 }
470 }
471
472 NTSTATUS
473 NTAPI
HalpQueryIdPdo(IN PDEVICE_OBJECT DeviceObject,IN BUS_QUERY_ID_TYPE IdType,OUT PUSHORT * BusQueryId)474 HalpQueryIdPdo(IN PDEVICE_OBJECT DeviceObject,
475 IN BUS_QUERY_ID_TYPE IdType,
476 OUT PUSHORT *BusQueryId)
477 {
478 PPDO_EXTENSION PdoExtension;
479 PDO_TYPE PdoType;
480 PWCHAR CurrentId;
481 WCHAR Id[100];
482 NTSTATUS Status;
483 SIZE_T Length = 0;
484 PWCHAR Buffer;
485
486 /* Get the PDO type */
487 PdoExtension = DeviceObject->DeviceExtension;
488 PdoType = PdoExtension->PdoType;
489
490 /* What kind of ID is being requested? */
491 DPRINT("ID: %d\n", IdType);
492 switch (IdType)
493 {
494 case BusQueryDeviceID:
495 case BusQueryHardwareIDs:
496
497 /* What kind of PDO is this? */
498 if (PdoType == AcpiPdo)
499 {
500 /* ACPI ID */
501 CurrentId = L"ACPI_HAL\\PNP0C08";
502 RtlCopyMemory(Id, CurrentId, (wcslen(CurrentId) * sizeof(WCHAR)) + sizeof(UNICODE_NULL));
503 Length += (wcslen(CurrentId) * sizeof(WCHAR)) + sizeof(UNICODE_NULL);
504
505 CurrentId = L"*PNP0C08";
506 RtlCopyMemory(&Id[wcslen(Id) + 1], CurrentId, (wcslen(CurrentId) * sizeof(WCHAR)) + sizeof(UNICODE_NULL));
507 Length += (wcslen(CurrentId) * sizeof(WCHAR)) + sizeof(UNICODE_NULL);
508 }
509 else if (PdoType == WdPdo)
510 {
511 /* WatchDog ID */
512 CurrentId = L"ACPI_HAL\\PNP0C18";
513 RtlCopyMemory(Id, CurrentId, (wcslen(CurrentId) * sizeof(WCHAR)) + sizeof(UNICODE_NULL));
514 Length += (wcslen(CurrentId) * sizeof(WCHAR)) + sizeof(UNICODE_NULL);
515
516 CurrentId = L"*PNP0C18";
517 RtlCopyMemory(&Id[wcslen(Id) + 1], CurrentId, (wcslen(CurrentId) * sizeof(WCHAR)) + sizeof(UNICODE_NULL));
518 Length += (wcslen(CurrentId) * sizeof(WCHAR)) + sizeof(UNICODE_NULL);
519 }
520 else
521 {
522 /* Unknown */
523 return STATUS_NOT_SUPPORTED;
524 }
525 break;
526
527 case BusQueryInstanceID:
528
529 /* Instance ID */
530 CurrentId = L"0";
531 RtlCopyMemory(Id, CurrentId, (wcslen(CurrentId) * sizeof(WCHAR)) + sizeof(UNICODE_NULL));
532 Length += (wcslen(CurrentId) * sizeof(WCHAR)) + sizeof(UNICODE_NULL);
533 break;
534
535 case BusQueryCompatibleIDs:
536 default:
537
538 /* We don't support anything else */
539 return STATUS_NOT_SUPPORTED;
540 }
541
542
543 /* Allocate the buffer */
544 Buffer = ExAllocatePoolWithTag(PagedPool,
545 Length + sizeof(UNICODE_NULL),
546 TAG_HAL);
547 if (Buffer)
548 {
549 /* Copy the string and null-terminate it */
550 RtlCopyMemory(Buffer, Id, Length);
551 Buffer[Length / sizeof(WCHAR)] = UNICODE_NULL;
552
553 /* Return string */
554 *BusQueryId = Buffer;
555 Status = STATUS_SUCCESS;
556 DPRINT("Returning: %S\n", *BusQueryId);
557 }
558 else
559 {
560 /* Fail */
561 Status = STATUS_INSUFFICIENT_RESOURCES;
562 }
563
564 /* Return status */
565 return Status;
566 }
567
568 NTSTATUS
569 NTAPI
HalpQueryIdFdo(IN PDEVICE_OBJECT DeviceObject,IN BUS_QUERY_ID_TYPE IdType,OUT PUSHORT * BusQueryId)570 HalpQueryIdFdo(IN PDEVICE_OBJECT DeviceObject,
571 IN BUS_QUERY_ID_TYPE IdType,
572 OUT PUSHORT *BusQueryId)
573 {
574 NTSTATUS Status;
575 SIZE_T Length;
576 PWCHAR Id;
577 PWCHAR Buffer;
578
579 /* What kind of ID is being requested? */
580 DPRINT("ID: %d\n", IdType);
581 switch (IdType)
582 {
583 case BusQueryDeviceID:
584 case BusQueryHardwareIDs:
585
586 /* This is our hardware ID */
587 Id = HalHardwareIdString;
588 break;
589
590 case BusQueryInstanceID:
591
592 /* And our instance ID */
593 Id = L"0";
594 break;
595
596 default:
597
598 /* We don't support anything else */
599 return STATUS_NOT_SUPPORTED;
600 }
601
602 /* Calculate the length */
603 Length = (wcslen(Id) * sizeof(WCHAR)) + sizeof(UNICODE_NULL);
604
605 /* Allocate the buffer */
606 Buffer = ExAllocatePoolWithTag(PagedPool,
607 Length + sizeof(UNICODE_NULL),
608 TAG_HAL);
609 if (Buffer)
610 {
611 /* Copy the string and null-terminate it */
612 RtlCopyMemory(Buffer, Id, Length);
613 Buffer[Length / sizeof(WCHAR)] = UNICODE_NULL;
614
615 /* Return string */
616 *BusQueryId = Buffer;
617 Status = STATUS_SUCCESS;
618 DPRINT("Returning: %S\n", *BusQueryId);
619 }
620 else
621 {
622 /* Fail */
623 Status = STATUS_INSUFFICIENT_RESOURCES;
624 }
625
626 /* Return status */
627 return Status;
628 }
629
630 NTSTATUS
631 NTAPI
HalpDispatchPnp(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)632 HalpDispatchPnp(IN PDEVICE_OBJECT DeviceObject,
633 IN PIRP Irp)
634 {
635 PIO_STACK_LOCATION IoStackLocation;
636 //PPDO_EXTENSION PdoExtension;
637 PFDO_EXTENSION FdoExtension;
638 NTSTATUS Status;
639 UCHAR Minor;
640
641 /* Get the device extension and stack location */
642 FdoExtension = DeviceObject->DeviceExtension;
643 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
644 Minor = IoStackLocation->MinorFunction;
645
646 /* FDO? */
647 if (FdoExtension->ExtensionType == FdoExtensionType)
648 {
649 /* Query the IRP type */
650 switch (Minor)
651 {
652 case IRP_MN_QUERY_DEVICE_RELATIONS:
653
654 /* Call the worker */
655 DPRINT("Querying device relations for FDO\n");
656 Status = HalpQueryDeviceRelations(DeviceObject,
657 IoStackLocation->Parameters.QueryDeviceRelations.Type,
658 (PVOID)&Irp->IoStatus.Information);
659 break;
660
661 case IRP_MN_QUERY_INTERFACE:
662
663 /* Call the worker */
664 DPRINT("Querying interface for FDO\n");
665 Status = HalpQueryInterface(DeviceObject,
666 IoStackLocation->Parameters.QueryInterface.InterfaceType,
667 IoStackLocation->Parameters.QueryInterface.Size,
668 IoStackLocation->Parameters.QueryInterface.InterfaceSpecificData,
669 IoStackLocation->Parameters.QueryInterface.Version,
670 IoStackLocation->Parameters.QueryInterface.Interface,
671 (PVOID)&Irp->IoStatus.Information);
672 break;
673
674
675 case IRP_MN_QUERY_ID:
676
677 /* Call the worker */
678 DPRINT("Querying ID for FDO\n");
679 Status = HalpQueryIdFdo(DeviceObject,
680 IoStackLocation->Parameters.QueryId.IdType,
681 (PVOID)&Irp->IoStatus.Information);
682 break;
683
684 case IRP_MN_QUERY_CAPABILITIES:
685
686 /* Call the worker */
687 DPRINT("Querying the capabilities for the FDO\n");
688 Status = HalpQueryCapabilities(DeviceObject,
689 IoStackLocation->Parameters.DeviceCapabilities.Capabilities);
690 break;
691
692 default:
693
694 DPRINT("Other IRP: %lx\n", Minor);
695 Status = STATUS_NOT_SUPPORTED;
696 break;
697 }
698
699 /* What happpened? */
700 if ((NT_SUCCESS(Status)) || (Status == STATUS_NOT_SUPPORTED))
701 {
702 /* Set the IRP status, unless this isn't understood */
703 if (Status != STATUS_NOT_SUPPORTED)
704 {
705 Irp->IoStatus.Status = Status;
706 }
707
708 /* Pass it on */
709 IoSkipCurrentIrpStackLocation(Irp);
710 return IoCallDriver(FdoExtension->AttachedDeviceObject, Irp);
711 }
712
713 /* Otherwise, we failed, so set the status and complete the request */
714 DPRINT1("IRP failed with status: %lx\n", Status);
715 Irp->IoStatus.Status = Status;
716 IoCompleteRequest(Irp, IO_NO_INCREMENT);
717 return Status;
718 }
719 else
720 {
721 /* This is a PDO instead */
722 ASSERT(FdoExtension->ExtensionType == PdoExtensionType);
723 //PdoExtension = (PPDO_EXTENSION)FdoExtension;
724 /* Query the IRP type */
725 Status = STATUS_SUCCESS;
726 switch (Minor)
727 {
728 case IRP_MN_START_DEVICE:
729
730 /* We only care about a PCI PDO */
731 DPRINT1("Start device received\n");
732 /* Complete the IRP normally */
733 break;
734
735 case IRP_MN_REMOVE_DEVICE:
736
737 /* Check if this is a PCI device */
738 DPRINT1("Remove device received\n");
739
740 /* We're done */
741 Status = STATUS_SUCCESS;
742 break;
743
744 case IRP_MN_SURPRISE_REMOVAL:
745
746 /* Inherit whatever status we had */
747 DPRINT1("Surprise removal IRP\n");
748 Status = Irp->IoStatus.Status;
749 break;
750
751 case IRP_MN_QUERY_DEVICE_RELATIONS:
752
753 /* Query the device relations */
754 DPRINT("Querying PDO relations\n");
755 Status = HalpQueryDeviceRelations(DeviceObject,
756 IoStackLocation->Parameters.QueryDeviceRelations.Type,
757 (PVOID)&Irp->IoStatus.Information);
758 break;
759
760 case IRP_MN_QUERY_INTERFACE:
761
762 /* Call the worker */
763 DPRINT("Querying interface for PDO\n");
764 Status = HalpQueryInterface(DeviceObject,
765 IoStackLocation->Parameters.QueryInterface.InterfaceType,
766 IoStackLocation->Parameters.QueryInterface.Size,
767 IoStackLocation->Parameters.QueryInterface.InterfaceSpecificData,
768 IoStackLocation->Parameters.QueryInterface.Version,
769 IoStackLocation->Parameters.QueryInterface.Interface,
770 (PVOID)&Irp->IoStatus.Information);
771 break;
772
773 case IRP_MN_QUERY_CAPABILITIES:
774
775 /* Call the worker */
776 DPRINT("Querying the capabilities for the PDO\n");
777 Status = HalpQueryCapabilities(DeviceObject,
778 IoStackLocation->Parameters.DeviceCapabilities.Capabilities);
779 break;
780
781 case IRP_MN_QUERY_RESOURCES:
782
783 /* Call the worker */
784 DPRINT("Querying the resources for the PDO\n");
785 Status = HalpQueryResources(DeviceObject, (PVOID)&Irp->IoStatus.Information);
786 break;
787
788 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
789
790 /* Call the worker */
791 DPRINT("Querying the resource requirements for the PDO\n");
792 Status = HalpQueryResourceRequirements(DeviceObject,
793 (PVOID)&Irp->IoStatus.Information);
794 break;
795
796 case IRP_MN_QUERY_ID:
797
798 /* Call the worker */
799 DPRINT("Query the ID for the PDO\n");
800 Status = HalpQueryIdPdo(DeviceObject,
801 IoStackLocation->Parameters.QueryId.IdType,
802 (PVOID)&Irp->IoStatus.Information);
803 break;
804
805 default:
806
807 /* We don't handle anything else, so inherit the old state */
808 DPRINT("Illegal IRP: %lx\n", Minor);
809 Status = Irp->IoStatus.Status;
810 break;
811 }
812
813 /* If it's not supported, inherit the old status */
814 if (Status == STATUS_NOT_SUPPORTED) Status = Irp->IoStatus.Status;
815
816 /* Complete the IRP */
817 DPRINT("IRP completed with status: %lx\n", Status);
818 Irp->IoStatus.Status = Status;
819 IoCompleteRequest(Irp, IO_NO_INCREMENT);
820 return Status;
821 }
822 }
823
824 NTSTATUS
825 NTAPI
HalpDispatchWmi(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)826 HalpDispatchWmi(IN PDEVICE_OBJECT DeviceObject,
827 IN PIRP Irp)
828 {
829 UNIMPLEMENTED_DBGBREAK("HAL: PnP Driver WMI!\n");
830 return STATUS_SUCCESS;
831 }
832
833 NTSTATUS
834 NTAPI
HalpDispatchPower(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)835 HalpDispatchPower(IN PDEVICE_OBJECT DeviceObject,
836 IN PIRP Irp)
837 {
838 PFDO_EXTENSION FdoExtension;
839
840 DPRINT("HAL: PnP Driver Power!\n");
841 FdoExtension = DeviceObject->DeviceExtension;
842 if (FdoExtension->ExtensionType == FdoExtensionType)
843 {
844 PoStartNextPowerIrp(Irp);
845 IoSkipCurrentIrpStackLocation(Irp);
846 return PoCallDriver(FdoExtension->AttachedDeviceObject, Irp);
847 }
848 else
849 {
850 PoStartNextPowerIrp(Irp);
851 Irp->IoStatus.Status = STATUS_SUCCESS;
852 IoCompleteRequest(Irp, IO_NO_INCREMENT);
853 return STATUS_SUCCESS;
854 }
855 }
856
857 NTSTATUS
858 NTAPI
HalpDriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)859 HalpDriverEntry(IN PDRIVER_OBJECT DriverObject,
860 IN PUNICODE_STRING RegistryPath)
861 {
862 NTSTATUS Status;
863 PDEVICE_OBJECT TargetDevice = NULL;
864
865 DPRINT("HAL: PnP Driver ENTRY!\n");
866
867 /* This is us */
868 HalpDriverObject = DriverObject;
869
870 /* Set up add device */
871 DriverObject->DriverExtension->AddDevice = HalpAddDevice;
872
873 /* Set up the callouts */
874 DriverObject->MajorFunction[IRP_MJ_PNP] = HalpDispatchPnp;
875 DriverObject->MajorFunction[IRP_MJ_POWER] = HalpDispatchPower;
876 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = HalpDispatchWmi;
877
878 /* Create the PDO and tell the PnP manager about us*/
879 Status = IoReportDetectedDevice(DriverObject,
880 InterfaceTypeUndefined,
881 -1,
882 -1,
883 NULL,
884 NULL,
885 FALSE,
886 &TargetDevice);
887 if (!NT_SUCCESS(Status))
888 return Status;
889
890 TargetDevice->Flags &= ~DO_DEVICE_INITIALIZING;
891
892 /* Set up the device stack */
893 Status = HalpAddDevice(DriverObject, TargetDevice);
894 if (!NT_SUCCESS(Status))
895 {
896 IoDeleteDevice(TargetDevice);
897 return Status;
898 }
899
900 /* Return to kernel */
901 return Status;
902 }
903
904 NTSTATUS
905 NTAPI
HaliInitPnpDriver(VOID)906 HaliInitPnpDriver(VOID)
907 {
908 NTSTATUS Status;
909 UNICODE_STRING DriverString;
910 PAGED_CODE();
911
912 /* Create the driver */
913 RtlInitUnicodeString(&DriverString, L"\\Driver\\ACPI_HAL");
914 Status = IoCreateDriver(&DriverString, HalpDriverEntry);
915
916 /* Return status */
917 return Status;
918 }
919
920 /* EOF */
921