Implement stubs for PCI_DEVICE_PRESENT_INTERFACE query-interface, plus fixes from...
[reactos.git] / reactos / drivers / bus / pci / pdo.c
1 /*
2 * PROJECT: ReactOS PCI bus driver
3 * FILE: pdo.c
4 * PURPOSE: Child device object dispatch routines
5 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
6 * UPDATE HISTORY:
7 * 10-09-2001 CSH Created
8 */
9
10 #include <ddk/ntddk.h>
11 #include <ddk/ntifs.h>
12 #include <initguid.h>
13 #include <ddk/wdmguid.h>
14 #include "pcidef.h"
15 #include "pci.h"
16
17 #define NDEBUG
18 #include <debug.h>
19
20 /*** PRIVATE *****************************************************************/
21
22 static NTSTATUS
23 PdoQueryDeviceText(
24 IN PDEVICE_OBJECT DeviceObject,
25 IN PIRP Irp,
26 PIO_STACK_LOCATION IrpSp)
27 {
28 PPDO_DEVICE_EXTENSION DeviceExtension;
29 NTSTATUS Status;
30
31 DPRINT("Called\n");
32
33 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
34
35 Status = STATUS_SUCCESS;
36
37 switch (IrpSp->Parameters.QueryDeviceText.DeviceTextType)
38 {
39 case DeviceTextDescription:
40 DPRINT("DeviceTextDescription\n");
41 Irp->IoStatus.Information = (ULONG_PTR)DeviceExtension->DeviceDescription.Buffer;
42 break;
43
44 case DeviceTextLocationInformation:
45 DPRINT("DeviceTextLocationInformation\n");
46 Irp->IoStatus.Information = (ULONG_PTR)DeviceExtension->DeviceLocation.Buffer;
47 break;
48
49 default:
50 Irp->IoStatus.Information = 0;
51 Status = STATUS_INVALID_PARAMETER;
52 }
53
54 return Status;
55 }
56
57
58 static NTSTATUS
59 PdoQueryId(
60 IN PDEVICE_OBJECT DeviceObject,
61 IN PIRP Irp,
62 PIO_STACK_LOCATION IrpSp)
63 {
64 PPDO_DEVICE_EXTENSION DeviceExtension;
65 UNICODE_STRING String;
66 NTSTATUS Status;
67
68 DPRINT("Called\n");
69
70 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
71
72 // Irp->IoStatus.Information = 0;
73
74 Status = STATUS_SUCCESS;
75
76 RtlInitUnicodeString(&String, NULL);
77
78 switch (IrpSp->Parameters.QueryId.IdType) {
79 case BusQueryDeviceID:
80 Status = RtlDuplicateUnicodeString(
81 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
82 &DeviceExtension->DeviceID,
83 &String);
84
85 DPRINT("DeviceID: %S\n", String.Buffer);
86
87 Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
88 break;
89
90 case BusQueryHardwareIDs:
91 Status = RtlDuplicateUnicodeString(
92 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
93 &DeviceExtension->HardwareIDs,
94 &String);
95
96 Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
97 break;
98
99 case BusQueryCompatibleIDs:
100 Status = RtlDuplicateUnicodeString(
101 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
102 &DeviceExtension->CompatibleIDs,
103 &String);
104
105 Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
106 break;
107
108 case BusQueryInstanceID:
109 Status = RtlDuplicateUnicodeString(
110 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
111 &DeviceExtension->InstanceID,
112 &String);
113
114 DPRINT("InstanceID: %S\n", String.Buffer);
115
116 Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
117 break;
118
119 case BusQueryDeviceSerialNumber:
120 default:
121 Status = STATUS_NOT_IMPLEMENTED;
122 }
123
124 return Status;
125 }
126
127
128 static NTSTATUS
129 PdoQueryBusInformation(
130 IN PDEVICE_OBJECT DeviceObject,
131 IN PIRP Irp,
132 PIO_STACK_LOCATION IrpSp)
133 {
134 PPDO_DEVICE_EXTENSION DeviceExtension;
135 PFDO_DEVICE_EXTENSION FdoDeviceExtension;
136 PPNP_BUS_INFORMATION BusInformation;
137
138 DPRINT("Called\n");
139
140 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
141 FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceExtension->Fdo->DeviceExtension;
142 BusInformation = ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
143 Irp->IoStatus.Information = (ULONG_PTR)BusInformation;
144 if (BusInformation != NULL)
145 {
146 BusInformation->BusTypeGuid = GUID_BUS_TYPE_PCI;
147 BusInformation->LegacyBusType = PCIBus;
148 BusInformation->BusNumber = DeviceExtension->PciDevice->BusNumber;
149
150 return STATUS_SUCCESS;
151 }
152
153 return STATUS_INSUFFICIENT_RESOURCES;
154 }
155
156
157 static NTSTATUS
158 PdoQueryCapabilities(
159 IN PDEVICE_OBJECT DeviceObject,
160 IN PIRP Irp,
161 PIO_STACK_LOCATION IrpSp)
162 {
163 PPDO_DEVICE_EXTENSION DeviceExtension;
164 PDEVICE_CAPABILITIES DeviceCapabilities;
165
166 DPRINT("Called\n");
167
168 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
169 DeviceCapabilities = IrpSp->Parameters.DeviceCapabilities.Capabilities;
170
171 if (DeviceCapabilities->Version != 1)
172 return STATUS_UNSUCCESSFUL;
173
174 DeviceCapabilities->UniqueID = FALSE;
175 DeviceCapabilities->Address = DeviceExtension->PciDevice->SlotNumber.u.AsULONG;
176 DeviceCapabilities->UINumber = (ULONG)-1; /* FIXME */
177
178 return STATUS_SUCCESS;
179 }
180
181
182 static BOOLEAN
183 PdoGetRangeLength(PPDO_DEVICE_EXTENSION DeviceExtension,
184 ULONG Offset,
185 PULONG Base,
186 PULONG Length,
187 PULONG Flags)
188 {
189 ULONG OrigValue;
190 ULONG BaseValue;
191 ULONG NewValue;
192 ULONG Size;
193 ULONG XLength;
194
195 /* Save original value */
196 Size= HalGetBusDataByOffset(PCIConfiguration,
197 DeviceExtension->PciDevice->BusNumber,
198 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
199 &OrigValue,
200 Offset,
201 sizeof(ULONG));
202 if (Size != sizeof(ULONG))
203 {
204 DPRINT1("Wrong size %lu\n", Size);
205 return FALSE;
206 }
207
208 BaseValue = (OrigValue & 0x00000001) ? (OrigValue & ~0x3) : (OrigValue & ~0xF);
209
210 *Base = BaseValue;
211
212 /* Set magic value */
213 NewValue = (ULONG)-1;
214 Size= HalSetBusDataByOffset(PCIConfiguration,
215 DeviceExtension->PciDevice->BusNumber,
216 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
217 &NewValue,
218 Offset,
219 sizeof(ULONG));
220 if (Size != sizeof(ULONG))
221 {
222 DPRINT1("Wrong size %lu\n", Size);
223 return FALSE;
224 }
225
226 /* Get the range length */
227 Size= HalGetBusDataByOffset(PCIConfiguration,
228 DeviceExtension->PciDevice->BusNumber,
229 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
230 &NewValue,
231 Offset,
232 sizeof(ULONG));
233 if (Size != sizeof(ULONG))
234 {
235 DPRINT1("Wrong size %lu\n", Size);
236 return FALSE;
237 }
238
239 /* Restore original value */
240 Size= HalSetBusDataByOffset(PCIConfiguration,
241 DeviceExtension->PciDevice->BusNumber,
242 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
243 &OrigValue,
244 Offset,
245 sizeof(ULONG));
246 if (Size != sizeof(ULONG))
247 {
248 DPRINT1("Wrong size %lu\n", Size);
249 return FALSE;
250 }
251
252 if (NewValue == 0)
253 {
254 DPRINT("Unused address register\n");
255 *Base = 0;
256 *Length = 0;
257 *Flags = 0;
258 return TRUE;
259 }
260
261 XLength = ~((NewValue & 0x00000001) ? (NewValue & ~0x3) : (NewValue & ~0xF)) + 1;
262
263 #if 0
264 DbgPrint("BaseAddress 0x%08lx Length 0x%08lx",
265 BaseValue, XLength);
266
267 if (NewValue & 0x00000001)
268 {
269 DbgPrint(" IO range");
270 }
271 else
272 {
273 DbgPrint(" Memory range");
274 if ((NewValue & 0x00000006) == 0)
275 {
276 DbgPrint(" in 32-Bit address space");
277 }
278 else if ((NewValue & 0x00000006) == 2)
279 {
280 DbgPrint(" below 1BM ");
281 }
282 else if ((NewValue & 0x00000006) == 4)
283 {
284 DbgPrint(" in 64-Bit address space");
285 }
286
287 if (NewValue & 0x00000008)
288 {
289 DbgPrint(" prefetchable");
290 }
291 }
292
293 DbgPrint("\n");
294 #endif
295
296 *Length = XLength;
297 *Flags = (NewValue & 0x00000001) ? (NewValue & 0x3) : (NewValue & 0xF);
298
299 return TRUE;
300 }
301
302
303 static NTSTATUS
304 PdoQueryResourceRequirements(
305 IN PDEVICE_OBJECT DeviceObject,
306 IN PIRP Irp,
307 PIO_STACK_LOCATION IrpSp)
308 {
309 PPDO_DEVICE_EXTENSION DeviceExtension;
310 PCI_COMMON_CONFIG PciConfig;
311 PIO_RESOURCE_REQUIREMENTS_LIST ResourceList;
312 PIO_RESOURCE_DESCRIPTOR Descriptor;
313 ULONG Size;
314 ULONG ResCount = 0;
315 ULONG ListSize;
316 ULONG i;
317 ULONG Base;
318 ULONG Length;
319 ULONG Flags;
320
321 DPRINT("PdoQueryResourceRequirements() called\n");
322
323 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
324
325 /* Get PCI configuration space */
326 Size= HalGetBusData(PCIConfiguration,
327 DeviceExtension->PciDevice->BusNumber,
328 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
329 &PciConfig,
330 PCI_COMMON_HDR_LENGTH);
331 DPRINT("Size %lu\n", Size);
332 if (Size < PCI_COMMON_HDR_LENGTH)
333 {
334 Irp->IoStatus.Information = 0;
335 return STATUS_UNSUCCESSFUL;
336 }
337
338 DPRINT("Command register: 0x%04hx\n", PciConfig.Command);
339
340 /* Count required resource descriptors */
341 ResCount = 0;
342 if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_DEVICE_TYPE)
343 {
344 for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
345 {
346 if (!PdoGetRangeLength(DeviceExtension,
347 0x10 + i * 4,
348 &Base,
349 &Length,
350 &Flags))
351 break;
352
353 if (Length != 0)
354 ResCount += 2;
355 }
356
357 /* FIXME: Check ROM address */
358
359 if (PciConfig.u.type0.InterruptPin != 0)
360 ResCount++;
361 }
362 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
363 {
364 for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
365 {
366 if (!PdoGetRangeLength(DeviceExtension,
367 0x10 + i * 4,
368 &Base,
369 &Length,
370 &Flags))
371 break;
372
373 if (Length != 0)
374 ResCount += 2;
375 }
376 if (DeviceExtension->PciDevice->PciConfig.BaseClass == PCI_CLASS_BRIDGE_DEV)
377 ResCount++;
378 }
379 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_CARDBUS_BRIDGE_TYPE)
380 {
381 }
382 else
383 {
384 DPRINT1("Unsupported header type %u\n", PCI_CONFIGURATION_TYPE(&PciConfig));
385 }
386
387 if (ResCount == 0)
388 {
389 Irp->IoStatus.Information = 0;
390 return STATUS_SUCCESS;
391 }
392
393 /* Calculate the resource list size */
394 ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
395 if (ResCount > 1)
396 {
397 ListSize += ((ResCount - 1) * sizeof(IO_RESOURCE_DESCRIPTOR));
398 }
399
400 DPRINT("ListSize %lu (0x%lx)\n", ListSize, ListSize);
401
402 /* Allocate the resource requirements list */
403 ResourceList = ExAllocatePool(PagedPool,
404 ListSize);
405 if (ResourceList == NULL)
406 {
407 Irp->IoStatus.Information = 0;
408 return STATUS_INSUFFICIENT_RESOURCES;
409 }
410
411 ResourceList->ListSize = ListSize;
412 ResourceList->InterfaceType = PCIBus;
413 ResourceList->BusNumber = DeviceExtension->PciDevice->BusNumber;
414 ResourceList->SlotNumber = DeviceExtension->PciDevice->SlotNumber.u.AsULONG;
415 ResourceList->AlternativeLists = 1;
416
417 ResourceList->List[0].Version = 1;
418 ResourceList->List[0].Revision = 1;
419 ResourceList->List[0].Count = ResCount;
420
421 Descriptor = &ResourceList->List[0].Descriptors[0];
422 if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_DEVICE_TYPE)
423 {
424 for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
425 {
426 if (!PdoGetRangeLength(DeviceExtension,
427 0x10 + i * 4,
428 &Base,
429 &Length,
430 &Flags))
431 {
432 DPRINT1("PdoGetRangeLength() failed\n");
433 break;
434 }
435
436 if (Length == 0)
437 {
438 DPRINT("Unused address register\n");
439 continue;
440 }
441
442 /* Set preferred descriptor */
443 Descriptor->Option = IO_RESOURCE_PREFERRED;
444 if (Flags & PCI_ADDRESS_IO_SPACE)
445 {
446 Descriptor->Type = CmResourceTypePort;
447 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
448 Descriptor->Flags = CM_RESOURCE_PORT_IO |
449 CM_RESOURCE_PORT_16_BIT_DECODE |
450 CM_RESOURCE_PORT_POSITIVE_DECODE;
451
452 Descriptor->u.Port.Length = Length;
453 Descriptor->u.Port.Alignment = 1;
454 Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)Base;
455 Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)(Base + Length - 1);
456 }
457 else
458 {
459 Descriptor->Type = CmResourceTypeMemory;
460 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
461 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
462
463 Descriptor->u.Memory.Length = Length;
464 Descriptor->u.Memory.Alignment = 1;
465 Descriptor->u.Memory.MinimumAddress.QuadPart = (ULONGLONG)Base;
466 Descriptor->u.Memory.MaximumAddress.QuadPart = (ULONGLONG)(Base + Length - 1);
467 }
468 Descriptor++;
469
470 /* Set alternative descriptor */
471 Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
472 if (Flags & PCI_ADDRESS_IO_SPACE)
473 {
474 Descriptor->Type = CmResourceTypePort;
475 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
476 Descriptor->Flags = CM_RESOURCE_PORT_IO |
477 CM_RESOURCE_PORT_16_BIT_DECODE |
478 CM_RESOURCE_PORT_POSITIVE_DECODE;
479
480 Descriptor->u.Port.Length = Length;
481 Descriptor->u.Port.Alignment = Length;
482 Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)0;
483 Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)0x00000000FFFFFFFF;
484 }
485 else
486 {
487 Descriptor->Type = CmResourceTypeMemory;
488 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
489 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
490
491 Descriptor->u.Memory.Length = Length;
492 Descriptor->u.Memory.Alignment = Length;
493 Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)0;
494 Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)0x00000000FFFFFFFF;
495 }
496 Descriptor++;
497 }
498
499 /* FIXME: Check ROM address */
500
501 if (PciConfig.u.type0.InterruptPin != 0)
502 {
503 Descriptor->Option = 0; /* Required */
504 Descriptor->Type = CmResourceTypeInterrupt;
505 Descriptor->ShareDisposition = CmResourceShareShared;
506 Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
507
508 Descriptor->u.Interrupt.MinimumVector = 0;
509 Descriptor->u.Interrupt.MaximumVector = 0xFF;
510 }
511 }
512 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
513 {
514 for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
515 {
516 if (!PdoGetRangeLength(DeviceExtension,
517 0x10 + i * 4,
518 &Base,
519 &Length,
520 &Flags))
521 {
522 DPRINT1("PdoGetRangeLength() failed\n");
523 break;
524 }
525
526 if (Length == 0)
527 {
528 DPRINT("Unused address register\n");
529 continue;
530 }
531
532 /* Set preferred descriptor */
533 Descriptor->Option = IO_RESOURCE_PREFERRED;
534 if (Flags & PCI_ADDRESS_IO_SPACE)
535 {
536 Descriptor->Type = CmResourceTypePort;
537 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
538 Descriptor->Flags = CM_RESOURCE_PORT_IO |
539 CM_RESOURCE_PORT_16_BIT_DECODE |
540 CM_RESOURCE_PORT_POSITIVE_DECODE;
541
542 Descriptor->u.Port.Length = Length;
543 Descriptor->u.Port.Alignment = 1;
544 Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)Base;
545 Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)(Base + Length - 1);
546 }
547 else
548 {
549 Descriptor->Type = CmResourceTypeMemory;
550 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
551 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
552
553 Descriptor->u.Memory.Length = Length;
554 Descriptor->u.Memory.Alignment = 1;
555 Descriptor->u.Memory.MinimumAddress.QuadPart = (ULONGLONG)Base;
556 Descriptor->u.Memory.MaximumAddress.QuadPart = (ULONGLONG)(Base + Length - 1);
557 }
558 Descriptor++;
559
560 /* Set alternative descriptor */
561 Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
562 if (Flags & PCI_ADDRESS_IO_SPACE)
563 {
564 Descriptor->Type = CmResourceTypePort;
565 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
566 Descriptor->Flags = CM_RESOURCE_PORT_IO |
567 CM_RESOURCE_PORT_16_BIT_DECODE |
568 CM_RESOURCE_PORT_POSITIVE_DECODE;
569
570 Descriptor->u.Port.Length = Length;
571 Descriptor->u.Port.Alignment = Length;
572 Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)0;
573 Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)0x00000000FFFFFFFF;
574 }
575 else
576 {
577 Descriptor->Type = CmResourceTypeMemory;
578 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
579 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
580
581 Descriptor->u.Memory.Length = Length;
582 Descriptor->u.Memory.Alignment = Length;
583 Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)0;
584 Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)0x00000000FFFFFFFF;
585 }
586 Descriptor++;
587 }
588 if (DeviceExtension->PciDevice->PciConfig.BaseClass == PCI_CLASS_BRIDGE_DEV)
589 {
590 Descriptor->Option = 0; /* Required */
591 Descriptor->Type = CmResourceTypeBusNumber;
592 Descriptor->ShareDisposition = CmResourceShareShared;
593 Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
594
595 Descriptor->u.BusNumber.MinBusNumber =
596 Descriptor->u.BusNumber.MaxBusNumber = DeviceExtension->PciDevice->PciConfig.u.type1.SubordinateBus;
597 Descriptor->u.BusNumber.Length = 1;
598 Descriptor->u.BusNumber.Reserved = 0;
599 }
600 }
601 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_CARDBUS_BRIDGE_TYPE)
602 {
603 /* FIXME: Add Cardbus bridge resources */
604 }
605
606 Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
607
608 return STATUS_SUCCESS;
609 }
610
611
612 static NTSTATUS
613 PdoQueryResources(
614 IN PDEVICE_OBJECT DeviceObject,
615 IN PIRP Irp,
616 PIO_STACK_LOCATION IrpSp)
617 {
618 PPDO_DEVICE_EXTENSION DeviceExtension;
619 PCI_COMMON_CONFIG PciConfig;
620 PCM_RESOURCE_LIST ResourceList;
621 PCM_PARTIAL_RESOURCE_LIST PartialList;
622 PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
623 ULONG Size;
624 ULONG ResCount = 0;
625 ULONG ListSize;
626 ULONG i;
627 ULONG Base;
628 ULONG Length;
629 ULONG Flags;
630
631 DPRINT("PdoQueryResources() called\n");
632
633 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
634
635 /* Get PCI configuration space */
636 Size= HalGetBusData(PCIConfiguration,
637 DeviceExtension->PciDevice->BusNumber,
638 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
639 &PciConfig,
640 PCI_COMMON_HDR_LENGTH);
641 DPRINT("Size %lu\n", Size);
642 if (Size < PCI_COMMON_HDR_LENGTH)
643 {
644 Irp->IoStatus.Information = 0;
645 return STATUS_UNSUCCESSFUL;
646 }
647
648 DPRINT("Command register: 0x%04hx\n", PciConfig.Command);
649
650 /* Count required resource descriptors */
651 ResCount = 0;
652 if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_DEVICE_TYPE)
653 {
654 for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
655 {
656 if (!PdoGetRangeLength(DeviceExtension,
657 0x10 + i * 4,
658 &Base,
659 &Length,
660 &Flags))
661 break;
662
663 if (Length)
664 ResCount++;
665 }
666
667 if ((PciConfig.u.type0.InterruptPin != 0) &&
668 (PciConfig.u.type0.InterruptLine != 0xFF))
669 ResCount++;
670 }
671 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
672 {
673 for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
674 {
675 if (!PdoGetRangeLength(DeviceExtension,
676 0x10 + i * 4,
677 &Base,
678 &Length,
679 &Flags))
680 break;
681
682 if (Length != 0)
683 ResCount++;
684 }
685 }
686 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_CARDBUS_BRIDGE_TYPE)
687 {
688
689 }
690 else
691 {
692 DPRINT1("Unsupported header type %u\n", PCI_CONFIGURATION_TYPE(&PciConfig));
693 }
694
695 if (ResCount == 0)
696 {
697 Irp->IoStatus.Information = 0;
698 return STATUS_SUCCESS;
699 }
700
701 /* Calculate the resource list size */
702 ListSize = sizeof(CM_RESOURCE_LIST);
703 if (ResCount > 1)
704 {
705 ListSize += ((ResCount - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
706 }
707
708 /* Allocate the resource list */
709 ResourceList = ExAllocatePool(PagedPool,
710 ListSize);
711 if (ResourceList == NULL)
712 return STATUS_INSUFFICIENT_RESOURCES;
713
714 ResourceList->Count = 1;
715 ResourceList->List[0].InterfaceType = PCIConfiguration;
716 ResourceList->List[0].BusNumber = DeviceExtension->PciDevice->BusNumber;
717
718 PartialList = &ResourceList->List[0].PartialResourceList;
719 PartialList->Version = 0;
720 PartialList->Revision = 0;
721 PartialList->Count = ResCount;
722
723 Descriptor = &PartialList->PartialDescriptors[0];
724 if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_DEVICE_TYPE)
725 {
726 for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
727 {
728 if (!PdoGetRangeLength(DeviceExtension,
729 0x10 + i * 4,
730 &Base,
731 &Length,
732 &Flags))
733 {
734 DPRINT1("PdoGetRangeLength() failed\n");
735 break;
736 }
737
738 if (Length == 0)
739 {
740 DPRINT("Unused address register\n");
741 continue;
742 }
743
744 if (Flags & PCI_ADDRESS_IO_SPACE)
745 {
746 Descriptor->Type = CmResourceTypePort;
747 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
748 Descriptor->Flags = CM_RESOURCE_PORT_IO;
749 Descriptor->u.Port.Start.QuadPart =
750 (ULONGLONG)Base;
751 Descriptor->u.Port.Length = Length;
752 }
753 else
754 {
755 Descriptor->Type = CmResourceTypeMemory;
756 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
757 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
758 Descriptor->u.Memory.Start.QuadPart =
759 (ULONGLONG)Base;
760 Descriptor->u.Memory.Length = Length;
761 }
762
763 Descriptor++;
764 }
765
766 /* Add interrupt resource */
767 if ((PciConfig.u.type0.InterruptPin != 0) &&
768 (PciConfig.u.type0.InterruptLine != 0xFF))
769 {
770 Descriptor->Type = CmResourceTypeInterrupt;
771 Descriptor->ShareDisposition = CmResourceShareShared;
772 Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
773 Descriptor->u.Interrupt.Level = PciConfig.u.type0.InterruptLine;
774 Descriptor->u.Interrupt.Vector = PciConfig.u.type0.InterruptLine;
775 Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
776 }
777 }
778 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
779 {
780 for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
781 {
782 if (!PdoGetRangeLength(DeviceExtension,
783 0x10 + i * 4,
784 &Base,
785 &Length,
786 &Flags))
787 {
788 DPRINT1("PdoGetRangeLength() failed\n");
789 break;
790 }
791
792 if (Length == 0)
793 {
794 DPRINT("Unused address register\n");
795 continue;
796 }
797
798 if (Flags & PCI_ADDRESS_IO_SPACE)
799 {
800 Descriptor->Type = CmResourceTypePort;
801 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
802 Descriptor->Flags = CM_RESOURCE_PORT_IO;
803 Descriptor->u.Port.Start.QuadPart =
804 (ULONGLONG)Base;
805 Descriptor->u.Port.Length = Length;
806 }
807 else
808 {
809 Descriptor->Type = CmResourceTypeMemory;
810 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
811 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
812 Descriptor->u.Memory.Start.QuadPart =
813 (ULONGLONG)Base;
814 Descriptor->u.Memory.Length = Length;
815 }
816
817 Descriptor++;
818 }
819 }
820 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_CARDBUS_BRIDGE_TYPE)
821 {
822 /* FIXME: Cardbus */
823 }
824
825 Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
826
827 return STATUS_SUCCESS;
828 }
829
830
831 static VOID NTAPI
832 InterfaceReference(
833 IN PVOID Context)
834 {
835 PPDO_DEVICE_EXTENSION DeviceExtension;
836
837 DPRINT("InterfaceReference(%p)\n", Context);
838
839 DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
840 InterlockedIncrement(&DeviceExtension->References);
841 }
842
843
844 static VOID NTAPI
845 InterfaceDereference(
846 IN PVOID Context)
847 {
848 PPDO_DEVICE_EXTENSION DeviceExtension;
849
850 DPRINT("InterfaceDereference(%p)\n", Context);
851
852 DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
853 InterlockedDecrement(&DeviceExtension->References);
854 }
855
856
857 static BOOLEAN NTAPI
858 InterfaceBusTranslateBusAddress(
859 IN PVOID Context,
860 IN PHYSICAL_ADDRESS BusAddress,
861 IN ULONG Length,
862 IN OUT PULONG AddressSpace,
863 OUT PPHYSICAL_ADDRESS TranslatedAddress)
864 {
865 PPDO_DEVICE_EXTENSION DeviceExtension;
866 PFDO_DEVICE_EXTENSION FdoDeviceExtension;
867
868 DPRINT("InterfaceBusTranslateBusAddress(%p %p 0x%lx %p %p)\n",
869 Context, BusAddress, Length, AddressSpace, TranslatedAddress);
870
871 DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
872 FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceExtension->Fdo->DeviceExtension;
873
874 return HalTranslateBusAddress(
875 PCIBus, FdoDeviceExtension->BusNumber,
876 BusAddress, AddressSpace, TranslatedAddress);
877 }
878
879
880 static PDMA_ADAPTER NTAPI
881 InterfaceBusGetDmaAdapter(
882 IN PVOID Context,
883 IN PDEVICE_DESCRIPTION DeviceDescription,
884 OUT PULONG NumberOfMapRegisters)
885 {
886 DPRINT("InterfaceBusGetDmaAdapter(%p %p %p)\n",
887 Context, DeviceDescription, NumberOfMapRegisters);
888 return (PDMA_ADAPTER)HalGetAdapter(DeviceDescription, NumberOfMapRegisters);
889 }
890
891
892 static ULONG NTAPI
893 InterfaceBusSetBusData(
894 IN PVOID Context,
895 IN ULONG DataType,
896 IN PVOID Buffer,
897 IN ULONG Offset,
898 IN ULONG Length)
899 {
900 PPDO_DEVICE_EXTENSION DeviceExtension;
901 ULONG Size;
902
903 DPRINT("InterfaceBusSetBusData(%p 0x%lx %p 0x%lx 0x%lx)\n",
904 Context, DataType, Buffer, Offset, Length);
905
906 if (DataType != PCI_WHICHSPACE_CONFIG)
907 {
908 DPRINT("Unknown DataType %lu\n", DataType);
909 return 0;
910 }
911
912 DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
913
914 /* Get PCI configuration space */
915 Size = HalSetBusDataByOffset(PCIConfiguration,
916 DeviceExtension->PciDevice->BusNumber,
917 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
918 Buffer,
919 Offset,
920 Length);
921 return Size;
922 }
923
924
925 static ULONG NTAPI
926 InterfaceBusGetBusData(
927 IN PVOID Context,
928 IN ULONG DataType,
929 IN PVOID Buffer,
930 IN ULONG Offset,
931 IN ULONG Length)
932 {
933 PPDO_DEVICE_EXTENSION DeviceExtension;
934 ULONG Size;
935
936 DPRINT("InterfaceBusGetBusData(%p 0x%lx %p 0x%lx 0x%lx) called\n",
937 Context, DataType, Buffer, Offset, Length);
938
939 if (DataType != PCI_WHICHSPACE_CONFIG)
940 {
941 DPRINT("Unknown DataType %lu\n", DataType);
942 return 0;
943 }
944
945 DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
946
947 /* Get PCI configuration space */
948 Size = HalGetBusDataByOffset(PCIConfiguration,
949 DeviceExtension->PciDevice->BusNumber,
950 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
951 Buffer,
952 Offset,
953 Length);
954 return Size;
955 }
956
957 static BOOLEAN NTAPI
958 InterfacePciDevicePresent(
959 IN USHORT VendorID,
960 IN USHORT DeviceID,
961 IN UCHAR RevisionID,
962 IN USHORT SubVendorID,
963 IN USHORT SubSystemID,
964 IN ULONG Flags
965 )
966 {
967 DPRINT1("Checking for PCI %04X:%04X not implemented\n",
968 VendorID, DeviceID);
969
970 return FALSE;
971 }
972
973 static BOOLEAN NTAPI
974 InterfacePciDevicePresentEx(
975 IN PVOID Context,
976 IN PPCI_DEVICE_PRESENCE_PARAMETERS Parameters)
977 {
978 PPDO_DEVICE_EXTENSION DeviceExtension;
979
980 DPRINT1("InterfacePciDevicePresentEx(%p %p) called\n",
981 Context, Parameters);
982
983 if (!Parameters || Parameters->Size != sizeof(PCI_DEVICE_PRESENCE_PARAMETERS))
984 return FALSE;
985
986 DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
987
988 DPRINT1("Checking for PCI %04X:%04X not implemented\n",
989 Parameters->VendorID, Parameters->DeviceID);
990
991 return FALSE;
992 }
993
994
995 static NTSTATUS
996 PdoQueryInterface(
997 IN PDEVICE_OBJECT DeviceObject,
998 IN PIRP Irp,
999 PIO_STACK_LOCATION IrpSp)
1000 {
1001 NTSTATUS Status;
1002
1003 if (RtlCompareMemory(IrpSp->Parameters.QueryInterface.InterfaceType,
1004 &GUID_BUS_INTERFACE_STANDARD, sizeof(GUID)) == sizeof(GUID))
1005 {
1006 /* BUS_INTERFACE_STANDARD */
1007 if (IrpSp->Parameters.QueryInterface.Version < 1)
1008 Status = STATUS_NOT_SUPPORTED;
1009 else if (IrpSp->Parameters.QueryInterface.Size < sizeof(BUS_INTERFACE_STANDARD))
1010 Status = STATUS_BUFFER_TOO_SMALL;
1011 else
1012 {
1013 PBUS_INTERFACE_STANDARD BusInterface;
1014 BusInterface = (PBUS_INTERFACE_STANDARD)IrpSp->Parameters.QueryInterface.Interface;
1015 BusInterface->Size = sizeof(BUS_INTERFACE_STANDARD);
1016 BusInterface->Version = 1;
1017 BusInterface->Context = DeviceObject;
1018 BusInterface->InterfaceReference = InterfaceReference;
1019 BusInterface->InterfaceDereference = InterfaceDereference;
1020 BusInterface->TranslateBusAddress = InterfaceBusTranslateBusAddress;
1021 BusInterface->GetDmaAdapter = InterfaceBusGetDmaAdapter;
1022 BusInterface->SetBusData = InterfaceBusSetBusData;
1023 BusInterface->GetBusData = InterfaceBusGetBusData;
1024 Status = STATUS_SUCCESS;
1025 }
1026 }
1027 else if (RtlCompareMemory(IrpSp->Parameters.QueryInterface.InterfaceType,
1028 &GUID_PCI_DEVICE_PRESENT_INTERFACE, sizeof(GUID)) == sizeof(GUID))
1029 {
1030 /* PCI_DEVICE_PRESENT_INTERFACE */
1031 if (IrpSp->Parameters.QueryInterface.Version < 1)
1032 Status = STATUS_NOT_SUPPORTED;
1033 else if (IrpSp->Parameters.QueryInterface.Size < sizeof(PCI_DEVICE_PRESENT_INTERFACE))
1034 Status = STATUS_BUFFER_TOO_SMALL;
1035 else
1036 {
1037 PPCI_DEVICE_PRESENT_INTERFACE BusInterface;
1038 BusInterface = (PPCI_DEVICE_PRESENT_INTERFACE)IrpSp->Parameters.QueryInterface.Interface;
1039 BusInterface->Size = sizeof(PCI_DEVICE_PRESENT_INTERFACE);
1040 BusInterface->Version = 1;
1041 BusInterface->Context = DeviceObject;
1042 BusInterface->InterfaceReference = InterfaceReference;
1043 BusInterface->InterfaceDereference = InterfaceDereference;
1044 BusInterface->IsDevicePresent = InterfacePciDevicePresent;
1045 BusInterface->IsDevicePresentEx = InterfacePciDevicePresentEx;
1046 Status = STATUS_SUCCESS;
1047 }
1048 }
1049 else
1050 {
1051 /* Not a supported interface */
1052 return STATUS_NOT_SUPPORTED;
1053 }
1054
1055 if (NT_SUCCESS(Status))
1056 {
1057 /* Add a reference for the returned interface */
1058 PINTERFACE Interface;
1059 Interface = (PINTERFACE)IrpSp->Parameters.QueryInterface.Interface;
1060 Interface->InterfaceReference(Interface->Context);
1061 }
1062
1063 return Status;
1064 }
1065
1066
1067 static NTSTATUS
1068 PdoReadConfig(
1069 IN PDEVICE_OBJECT DeviceObject,
1070 IN PIRP Irp,
1071 PIO_STACK_LOCATION IrpSp)
1072 {
1073 ULONG Size;
1074
1075 DPRINT("PdoReadConfig() called\n");
1076
1077 Size = InterfaceBusGetBusData(
1078 DeviceObject,
1079 IrpSp->Parameters.ReadWriteConfig.WhichSpace,
1080 IrpSp->Parameters.ReadWriteConfig.Buffer,
1081 IrpSp->Parameters.ReadWriteConfig.Offset,
1082 IrpSp->Parameters.ReadWriteConfig.Length);
1083
1084 if (Size != IrpSp->Parameters.ReadWriteConfig.Length)
1085 {
1086 DPRINT1("Size %lu Length %lu\n", Size, IrpSp->Parameters.ReadWriteConfig.Length);
1087 Irp->IoStatus.Information = 0;
1088 return STATUS_UNSUCCESSFUL;
1089 }
1090
1091 Irp->IoStatus.Information = Size;
1092
1093 return STATUS_SUCCESS;
1094 }
1095
1096
1097 static NTSTATUS
1098 PdoWriteConfig(
1099 IN PDEVICE_OBJECT DeviceObject,
1100 IN PIRP Irp,
1101 PIO_STACK_LOCATION IrpSp)
1102 {
1103 ULONG Size;
1104
1105 DPRINT1("PdoWriteConfig() called\n");
1106
1107 /* Get PCI configuration space */
1108 Size = InterfaceBusSetBusData(
1109 DeviceObject,
1110 IrpSp->Parameters.ReadWriteConfig.WhichSpace,
1111 IrpSp->Parameters.ReadWriteConfig.Buffer,
1112 IrpSp->Parameters.ReadWriteConfig.Offset,
1113 IrpSp->Parameters.ReadWriteConfig.Length);
1114
1115 if (Size != IrpSp->Parameters.ReadWriteConfig.Length)
1116 {
1117 DPRINT1("Size %lu Length %lu\n", Size, IrpSp->Parameters.ReadWriteConfig.Length);
1118 Irp->IoStatus.Information = 0;
1119 return STATUS_UNSUCCESSFUL;
1120 }
1121
1122 Irp->IoStatus.Information = Size;
1123
1124 return STATUS_SUCCESS;
1125 }
1126
1127
1128 static NTSTATUS
1129 PdoSetPower(
1130 IN PDEVICE_OBJECT DeviceObject,
1131 IN PIRP Irp,
1132 PIO_STACK_LOCATION IrpSp)
1133 {
1134 PPDO_DEVICE_EXTENSION DeviceExtension;
1135 NTSTATUS Status;
1136
1137 DPRINT("Called\n");
1138
1139 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1140
1141 if (IrpSp->Parameters.Power.Type == DevicePowerState) {
1142 Status = STATUS_SUCCESS;
1143 switch (IrpSp->Parameters.Power.State.SystemState) {
1144 default:
1145 Status = STATUS_UNSUCCESSFUL;
1146 }
1147 } else {
1148 Status = STATUS_UNSUCCESSFUL;
1149 }
1150
1151 return Status;
1152 }
1153
1154
1155 /*** PUBLIC ******************************************************************/
1156
1157 NTSTATUS
1158 PdoPnpControl(
1159 PDEVICE_OBJECT DeviceObject,
1160 PIRP Irp)
1161 /*
1162 * FUNCTION: Handle Plug and Play IRPs for the child device
1163 * ARGUMENTS:
1164 * DeviceObject = Pointer to physical device object of the child device
1165 * Irp = Pointer to IRP that should be handled
1166 * RETURNS:
1167 * Status
1168 */
1169 {
1170 PIO_STACK_LOCATION IrpSp;
1171 NTSTATUS Status;
1172
1173 DPRINT("Called\n");
1174
1175 Status = Irp->IoStatus.Status;
1176
1177 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1178
1179 switch (IrpSp->MinorFunction) {
1180 #if 0
1181 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
1182 break;
1183
1184 case IRP_MN_EJECT:
1185 break;
1186 #endif
1187
1188 case IRP_MN_QUERY_BUS_INFORMATION:
1189 Status = PdoQueryBusInformation(DeviceObject, Irp, IrpSp);
1190 break;
1191
1192 case IRP_MN_QUERY_CAPABILITIES:
1193 Status = PdoQueryCapabilities(DeviceObject, Irp, IrpSp);
1194 break;
1195
1196 #if 0
1197 case IRP_MN_QUERY_DEVICE_RELATIONS:
1198 /* FIXME: Possibly handle for RemovalRelations */
1199 break;
1200 #endif
1201
1202 case IRP_MN_QUERY_DEVICE_TEXT:
1203 DPRINT("IRP_MN_QUERY_DEVICE_TEXT received\n");
1204 Status = PdoQueryDeviceText(DeviceObject, Irp, IrpSp);
1205 break;
1206
1207 case IRP_MN_QUERY_ID:
1208 DPRINT("IRP_MN_QUERY_ID received\n");
1209 Status = PdoQueryId(DeviceObject, Irp, IrpSp);
1210 break;
1211
1212 #if 0
1213 case IRP_MN_QUERY_PNP_DEVICE_STATE:
1214 break;
1215 #endif
1216
1217 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
1218 DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS received\n");
1219 Status = PdoQueryResourceRequirements(DeviceObject, Irp, IrpSp);
1220 break;
1221
1222 case IRP_MN_QUERY_RESOURCES:
1223 DPRINT("IRP_MN_QUERY_RESOURCES received\n");
1224 Status = PdoQueryResources(DeviceObject, Irp, IrpSp);
1225 break;
1226
1227 #if 0
1228 case IRP_MN_SET_LOCK:
1229 break;
1230 #endif
1231
1232 case IRP_MN_START_DEVICE:
1233 case IRP_MN_QUERY_STOP_DEVICE:
1234 case IRP_MN_CANCEL_STOP_DEVICE:
1235 case IRP_MN_STOP_DEVICE:
1236 case IRP_MN_QUERY_REMOVE_DEVICE:
1237 case IRP_MN_CANCEL_REMOVE_DEVICE:
1238 case IRP_MN_REMOVE_DEVICE:
1239 case IRP_MN_SURPRISE_REMOVAL:
1240 Status = STATUS_SUCCESS;
1241 break;
1242
1243 case IRP_MN_QUERY_INTERFACE:
1244 DPRINT("IRP_MN_QUERY_INTERFACE received\n");
1245 Status = PdoQueryInterface(DeviceObject, Irp, IrpSp);
1246 break;
1247
1248 case IRP_MN_READ_CONFIG:
1249 DPRINT("IRP_MN_READ_CONFIG received\n");
1250 Status = PdoReadConfig(DeviceObject, Irp, IrpSp);
1251 break;
1252
1253 case IRP_MN_WRITE_CONFIG:
1254 DPRINT("IRP_MN_WRITE_CONFIG received\n");
1255 Status = PdoWriteConfig(DeviceObject, Irp, IrpSp);
1256 break;
1257
1258 default:
1259 DPRINT1("Unknown IOCTL 0x%lx\n", IrpSp->MinorFunction);
1260 break;
1261 }
1262
1263 if (Status != STATUS_PENDING) {
1264 Irp->IoStatus.Status = Status;
1265 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1266 }
1267
1268 DPRINT("Leaving. Status 0x%X\n", Status);
1269
1270 return Status;
1271 }
1272
1273 NTSTATUS
1274 PdoPowerControl(
1275 PDEVICE_OBJECT DeviceObject,
1276 PIRP Irp)
1277 /*
1278 * FUNCTION: Handle power management IRPs for the child device
1279 * ARGUMENTS:
1280 * DeviceObject = Pointer to physical device object of the child device
1281 * Irp = Pointer to IRP that should be handled
1282 * RETURNS:
1283 * Status
1284 */
1285 {
1286 PIO_STACK_LOCATION IrpSp;
1287 NTSTATUS Status;
1288
1289 DPRINT("Called\n");
1290
1291 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1292
1293 switch (IrpSp->MinorFunction) {
1294 case IRP_MN_SET_POWER:
1295 Status = PdoSetPower(DeviceObject, Irp, IrpSp);
1296 break;
1297
1298 default:
1299 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
1300 Status = STATUS_NOT_IMPLEMENTED;
1301 break;
1302 }
1303
1304 if (Status != STATUS_PENDING) {
1305 Irp->IoStatus.Status = Status;
1306 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1307 }
1308
1309 DPRINT("Leaving. Status 0x%X\n", Status);
1310
1311 return Status;
1312 }
1313
1314 /* EOF */