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