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