2477a00ce16552b43250845c669c02173bf6db3b
[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
958 static BOOLEAN NTAPI
959 InterfacePciDevicePresent(
960 IN USHORT VendorID,
961 IN USHORT DeviceID,
962 IN UCHAR RevisionID,
963 IN USHORT SubVendorID,
964 IN USHORT SubSystemID,
965 IN ULONG Flags)
966 {
967 PFDO_DEVICE_EXTENSION FdoDeviceExtension;
968 PPCI_DEVICE PciDevice;
969 PLIST_ENTRY CurrentBus, CurrentEntry;
970 KIRQL OldIrql;
971 BOOLEAN Found = FALSE;
972
973 KeAcquireSpinLock(&DriverExtension->BusListLock, &OldIrql);
974 CurrentBus = DriverExtension->BusListHead.Flink;
975 while (!Found && CurrentBus != &DriverExtension->BusListHead)
976 {
977 FdoDeviceExtension = CONTAINING_RECORD(CurrentBus, FDO_DEVICE_EXTENSION, ListEntry);
978
979 KeAcquireSpinLockAtDpcLevel(&FdoDeviceExtension->DeviceListLock);
980 CurrentEntry = FdoDeviceExtension->DeviceListHead.Flink;
981 while (!Found && CurrentEntry != &FdoDeviceExtension->DeviceListHead)
982 {
983 PciDevice = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry);
984 if (PciDevice->PciConfig.VendorID == VendorID &&
985 PciDevice->PciConfig.DeviceID == DeviceID)
986 {
987 if (!(Flags & PCI_USE_SUBSYSTEM_IDS) || (
988 PciDevice->PciConfig.u.type0.SubVendorID == SubVendorID &&
989 PciDevice->PciConfig.u.type0.SubSystemID == SubSystemID))
990 {
991 if (!(Flags & PCI_USE_REVISION) ||
992 PciDevice->PciConfig.RevisionID == RevisionID)
993 {
994 DPRINT("Found the PCI device\n");
995 Found = TRUE;
996 }
997 }
998 }
999
1000 CurrentEntry = CurrentEntry->Flink;
1001 }
1002
1003 KeReleaseSpinLockFromDpcLevel(&FdoDeviceExtension->DeviceListLock);
1004 CurrentBus = CurrentBus->Flink;
1005 }
1006 KeReleaseSpinLock(&DriverExtension->BusListLock, OldIrql);
1007
1008 return Found;
1009 }
1010
1011
1012 static BOOLEAN
1013 CheckPciDevice(
1014 IN PPCI_COMMON_CONFIG PciConfig,
1015 IN PPCI_DEVICE_PRESENCE_PARAMETERS Parameters)
1016 {
1017 if ((Parameters->Flags & PCI_USE_VENDEV_IDS) && (
1018 PciConfig->VendorID != Parameters->VendorID ||
1019 PciConfig->DeviceID != Parameters->DeviceID))
1020 {
1021 return FALSE;
1022 }
1023 if ((Parameters->Flags && PCI_USE_CLASS_SUBCLASS) && (
1024 PciConfig->u.type0.SubVendorID != Parameters->SubVendorID ||
1025 PciConfig->u.type0.SubSystemID != Parameters->SubSystemID))
1026 {
1027 return FALSE;
1028 }
1029 if ((Parameters->Flags & PCI_USE_PROGIF) &&
1030 PciConfig->ProgIf != Parameters->ProgIf)
1031 {
1032 return FALSE;
1033 }
1034 if ((Parameters->Flags & PCI_USE_SUBSYSTEM_IDS) && (
1035 PciConfig->Command != Parameters->SubVendorID ||
1036 PciConfig->Status != Parameters->SubSystemID))
1037 {
1038 return FALSE;
1039 }
1040 if ((Parameters->Flags & PCI_USE_REVISION) &&
1041 PciConfig->RevisionID != Parameters->RevisionID)
1042 {
1043 return FALSE;
1044 }
1045 return TRUE;
1046 }
1047
1048
1049 static BOOLEAN NTAPI
1050 InterfacePciDevicePresentEx(
1051 IN PVOID Context,
1052 IN PPCI_DEVICE_PRESENCE_PARAMETERS Parameters)
1053 {
1054 PPDO_DEVICE_EXTENSION DeviceExtension;
1055 PFDO_DEVICE_EXTENSION MyFdoDeviceExtension;
1056 PFDO_DEVICE_EXTENSION FdoDeviceExtension;
1057 PPCI_DEVICE PciDevice;
1058 PLIST_ENTRY CurrentBus, CurrentEntry;
1059 KIRQL OldIrql;
1060 BOOLEAN Found = FALSE;
1061
1062 DPRINT("InterfacePciDevicePresentEx(%p %p) called\n",
1063 Context, Parameters);
1064
1065 if (!Parameters || Parameters->Size != sizeof(PCI_DEVICE_PRESENCE_PARAMETERS))
1066 return FALSE;
1067
1068 DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
1069 MyFdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceExtension->Fdo->DeviceExtension;
1070
1071 if (Parameters->Flags & PCI_USE_LOCAL_DEVICE)
1072 {
1073 return CheckPciDevice(&DeviceExtension->PciDevice->PciConfig, Parameters);
1074 }
1075
1076 KeAcquireSpinLock(&DriverExtension->BusListLock, &OldIrql);
1077 CurrentBus = DriverExtension->BusListHead.Flink;
1078 while (!Found && CurrentBus != &DriverExtension->BusListHead)
1079 {
1080 FdoDeviceExtension = CONTAINING_RECORD(CurrentBus, FDO_DEVICE_EXTENSION, ListEntry);
1081 if (!(Parameters->Flags & PCI_USE_LOCAL_BUS) || FdoDeviceExtension == MyFdoDeviceExtension)
1082 {
1083 KeAcquireSpinLockAtDpcLevel(&FdoDeviceExtension->DeviceListLock);
1084 CurrentEntry = FdoDeviceExtension->DeviceListHead.Flink;
1085 while (!Found && CurrentEntry != &FdoDeviceExtension->DeviceListHead)
1086 {
1087 PciDevice = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry);
1088
1089 if (CheckPciDevice(&PciDevice->PciConfig, Parameters))
1090 {
1091 DPRINT("Found the PCI device\n");
1092 Found = TRUE;
1093 }
1094
1095 CurrentEntry = CurrentEntry->Flink;
1096 }
1097
1098 KeReleaseSpinLockFromDpcLevel(&FdoDeviceExtension->DeviceListLock);
1099 }
1100 CurrentBus = CurrentBus->Flink;
1101 }
1102 KeReleaseSpinLock(&DriverExtension->BusListLock, OldIrql);
1103
1104 return Found;
1105 }
1106
1107
1108 static NTSTATUS
1109 PdoQueryInterface(
1110 IN PDEVICE_OBJECT DeviceObject,
1111 IN PIRP Irp,
1112 PIO_STACK_LOCATION IrpSp)
1113 {
1114 NTSTATUS Status;
1115
1116 if (RtlCompareMemory(IrpSp->Parameters.QueryInterface.InterfaceType,
1117 &GUID_BUS_INTERFACE_STANDARD, sizeof(GUID)) == sizeof(GUID))
1118 {
1119 /* BUS_INTERFACE_STANDARD */
1120 if (IrpSp->Parameters.QueryInterface.Version < 1)
1121 Status = STATUS_NOT_SUPPORTED;
1122 else if (IrpSp->Parameters.QueryInterface.Size < sizeof(BUS_INTERFACE_STANDARD))
1123 Status = STATUS_BUFFER_TOO_SMALL;
1124 else
1125 {
1126 PBUS_INTERFACE_STANDARD BusInterface;
1127 BusInterface = (PBUS_INTERFACE_STANDARD)IrpSp->Parameters.QueryInterface.Interface;
1128 BusInterface->Size = sizeof(BUS_INTERFACE_STANDARD);
1129 BusInterface->Version = 1;
1130 BusInterface->Context = DeviceObject;
1131 BusInterface->InterfaceReference = InterfaceReference;
1132 BusInterface->InterfaceDereference = InterfaceDereference;
1133 BusInterface->TranslateBusAddress = InterfaceBusTranslateBusAddress;
1134 BusInterface->GetDmaAdapter = InterfaceBusGetDmaAdapter;
1135 BusInterface->SetBusData = InterfaceBusSetBusData;
1136 BusInterface->GetBusData = InterfaceBusGetBusData;
1137 Status = STATUS_SUCCESS;
1138 }
1139 }
1140 else if (RtlCompareMemory(IrpSp->Parameters.QueryInterface.InterfaceType,
1141 &GUID_PCI_DEVICE_PRESENT_INTERFACE, sizeof(GUID)) == sizeof(GUID))
1142 {
1143 /* PCI_DEVICE_PRESENT_INTERFACE */
1144 if (IrpSp->Parameters.QueryInterface.Version < 1)
1145 Status = STATUS_NOT_SUPPORTED;
1146 else if (IrpSp->Parameters.QueryInterface.Size < sizeof(PCI_DEVICE_PRESENT_INTERFACE))
1147 Status = STATUS_BUFFER_TOO_SMALL;
1148 else
1149 {
1150 PPCI_DEVICE_PRESENT_INTERFACE PciDevicePresentInterface;
1151 PciDevicePresentInterface = (PPCI_DEVICE_PRESENT_INTERFACE)IrpSp->Parameters.QueryInterface.Interface;
1152 PciDevicePresentInterface->Size = sizeof(PCI_DEVICE_PRESENT_INTERFACE);
1153 PciDevicePresentInterface->Version = 1;
1154 PciDevicePresentInterface->Context = DeviceObject;
1155 PciDevicePresentInterface->InterfaceReference = InterfaceReference;
1156 PciDevicePresentInterface->InterfaceDereference = InterfaceDereference;
1157 PciDevicePresentInterface->IsDevicePresent = InterfacePciDevicePresent;
1158 PciDevicePresentInterface->IsDevicePresentEx = InterfacePciDevicePresentEx;
1159 Status = STATUS_SUCCESS;
1160 }
1161 }
1162 else
1163 {
1164 /* Not a supported interface */
1165 return STATUS_NOT_SUPPORTED;
1166 }
1167
1168 if (NT_SUCCESS(Status))
1169 {
1170 /* Add a reference for the returned interface */
1171 PINTERFACE Interface;
1172 Interface = (PINTERFACE)IrpSp->Parameters.QueryInterface.Interface;
1173 Interface->InterfaceReference(Interface->Context);
1174 }
1175
1176 return Status;
1177 }
1178
1179
1180 static NTSTATUS
1181 PdoReadConfig(
1182 IN PDEVICE_OBJECT DeviceObject,
1183 IN PIRP Irp,
1184 PIO_STACK_LOCATION IrpSp)
1185 {
1186 ULONG Size;
1187
1188 DPRINT("PdoReadConfig() called\n");
1189
1190 Size = InterfaceBusGetBusData(
1191 DeviceObject,
1192 IrpSp->Parameters.ReadWriteConfig.WhichSpace,
1193 IrpSp->Parameters.ReadWriteConfig.Buffer,
1194 IrpSp->Parameters.ReadWriteConfig.Offset,
1195 IrpSp->Parameters.ReadWriteConfig.Length);
1196
1197 if (Size != IrpSp->Parameters.ReadWriteConfig.Length)
1198 {
1199 DPRINT1("Size %lu Length %lu\n", Size, IrpSp->Parameters.ReadWriteConfig.Length);
1200 Irp->IoStatus.Information = 0;
1201 return STATUS_UNSUCCESSFUL;
1202 }
1203
1204 Irp->IoStatus.Information = Size;
1205
1206 return STATUS_SUCCESS;
1207 }
1208
1209
1210 static NTSTATUS
1211 PdoWriteConfig(
1212 IN PDEVICE_OBJECT DeviceObject,
1213 IN PIRP Irp,
1214 PIO_STACK_LOCATION IrpSp)
1215 {
1216 ULONG Size;
1217
1218 DPRINT1("PdoWriteConfig() called\n");
1219
1220 /* Get PCI configuration space */
1221 Size = InterfaceBusSetBusData(
1222 DeviceObject,
1223 IrpSp->Parameters.ReadWriteConfig.WhichSpace,
1224 IrpSp->Parameters.ReadWriteConfig.Buffer,
1225 IrpSp->Parameters.ReadWriteConfig.Offset,
1226 IrpSp->Parameters.ReadWriteConfig.Length);
1227
1228 if (Size != IrpSp->Parameters.ReadWriteConfig.Length)
1229 {
1230 DPRINT1("Size %lu Length %lu\n", Size, IrpSp->Parameters.ReadWriteConfig.Length);
1231 Irp->IoStatus.Information = 0;
1232 return STATUS_UNSUCCESSFUL;
1233 }
1234
1235 Irp->IoStatus.Information = Size;
1236
1237 return STATUS_SUCCESS;
1238 }
1239
1240
1241 static NTSTATUS
1242 PdoSetPower(
1243 IN PDEVICE_OBJECT DeviceObject,
1244 IN PIRP Irp,
1245 PIO_STACK_LOCATION IrpSp)
1246 {
1247 PPDO_DEVICE_EXTENSION DeviceExtension;
1248 NTSTATUS Status;
1249
1250 DPRINT("Called\n");
1251
1252 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1253
1254 if (IrpSp->Parameters.Power.Type == DevicePowerState) {
1255 Status = STATUS_SUCCESS;
1256 switch (IrpSp->Parameters.Power.State.SystemState) {
1257 default:
1258 Status = STATUS_UNSUCCESSFUL;
1259 }
1260 } else {
1261 Status = STATUS_UNSUCCESSFUL;
1262 }
1263
1264 return Status;
1265 }
1266
1267
1268 /*** PUBLIC ******************************************************************/
1269
1270 NTSTATUS
1271 PdoPnpControl(
1272 PDEVICE_OBJECT DeviceObject,
1273 PIRP Irp)
1274 /*
1275 * FUNCTION: Handle Plug and Play IRPs for the child device
1276 * ARGUMENTS:
1277 * DeviceObject = Pointer to physical device object of the child device
1278 * Irp = Pointer to IRP that should be handled
1279 * RETURNS:
1280 * Status
1281 */
1282 {
1283 PIO_STACK_LOCATION IrpSp;
1284 NTSTATUS Status;
1285
1286 DPRINT("Called\n");
1287
1288 Status = Irp->IoStatus.Status;
1289
1290 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1291
1292 switch (IrpSp->MinorFunction) {
1293 #if 0
1294 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
1295 break;
1296
1297 case IRP_MN_EJECT:
1298 break;
1299 #endif
1300
1301 case IRP_MN_QUERY_BUS_INFORMATION:
1302 Status = PdoQueryBusInformation(DeviceObject, Irp, IrpSp);
1303 break;
1304
1305 case IRP_MN_QUERY_CAPABILITIES:
1306 Status = PdoQueryCapabilities(DeviceObject, Irp, IrpSp);
1307 break;
1308
1309 #if 0
1310 case IRP_MN_QUERY_DEVICE_RELATIONS:
1311 /* FIXME: Possibly handle for RemovalRelations */
1312 break;
1313 #endif
1314
1315 case IRP_MN_QUERY_DEVICE_TEXT:
1316 DPRINT("IRP_MN_QUERY_DEVICE_TEXT received\n");
1317 Status = PdoQueryDeviceText(DeviceObject, Irp, IrpSp);
1318 break;
1319
1320 case IRP_MN_QUERY_ID:
1321 DPRINT("IRP_MN_QUERY_ID received\n");
1322 Status = PdoQueryId(DeviceObject, Irp, IrpSp);
1323 break;
1324
1325 #if 0
1326 case IRP_MN_QUERY_PNP_DEVICE_STATE:
1327 break;
1328 #endif
1329
1330 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
1331 DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS received\n");
1332 Status = PdoQueryResourceRequirements(DeviceObject, Irp, IrpSp);
1333 break;
1334
1335 case IRP_MN_QUERY_RESOURCES:
1336 DPRINT("IRP_MN_QUERY_RESOURCES received\n");
1337 Status = PdoQueryResources(DeviceObject, Irp, IrpSp);
1338 break;
1339
1340 #if 0
1341 case IRP_MN_SET_LOCK:
1342 break;
1343 #endif
1344
1345 case IRP_MN_START_DEVICE:
1346 case IRP_MN_QUERY_STOP_DEVICE:
1347 case IRP_MN_CANCEL_STOP_DEVICE:
1348 case IRP_MN_STOP_DEVICE:
1349 case IRP_MN_QUERY_REMOVE_DEVICE:
1350 case IRP_MN_CANCEL_REMOVE_DEVICE:
1351 case IRP_MN_REMOVE_DEVICE:
1352 case IRP_MN_SURPRISE_REMOVAL:
1353 Status = STATUS_SUCCESS;
1354 break;
1355
1356 case IRP_MN_QUERY_INTERFACE:
1357 DPRINT("IRP_MN_QUERY_INTERFACE received\n");
1358 Status = PdoQueryInterface(DeviceObject, Irp, IrpSp);
1359 break;
1360
1361 case IRP_MN_READ_CONFIG:
1362 DPRINT("IRP_MN_READ_CONFIG received\n");
1363 Status = PdoReadConfig(DeviceObject, Irp, IrpSp);
1364 break;
1365
1366 case IRP_MN_WRITE_CONFIG:
1367 DPRINT("IRP_MN_WRITE_CONFIG received\n");
1368 Status = PdoWriteConfig(DeviceObject, Irp, IrpSp);
1369 break;
1370
1371 default:
1372 DPRINT1("Unknown IOCTL 0x%lx\n", IrpSp->MinorFunction);
1373 break;
1374 }
1375
1376 if (Status != STATUS_PENDING) {
1377 Irp->IoStatus.Status = Status;
1378 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1379 }
1380
1381 DPRINT("Leaving. Status 0x%X\n", Status);
1382
1383 return Status;
1384 }
1385
1386 NTSTATUS
1387 PdoPowerControl(
1388 PDEVICE_OBJECT DeviceObject,
1389 PIRP Irp)
1390 /*
1391 * FUNCTION: Handle power management IRPs for the child device
1392 * ARGUMENTS:
1393 * DeviceObject = Pointer to physical device object of the child device
1394 * Irp = Pointer to IRP that should be handled
1395 * RETURNS:
1396 * Status
1397 */
1398 {
1399 PIO_STACK_LOCATION IrpSp;
1400 NTSTATUS Status;
1401
1402 DPRINT("Called\n");
1403
1404 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1405
1406 switch (IrpSp->MinorFunction) {
1407 case IRP_MN_SET_POWER:
1408 Status = PdoSetPower(DeviceObject, Irp, IrpSp);
1409 break;
1410
1411 default:
1412 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
1413 Status = STATUS_NOT_IMPLEMENTED;
1414 break;
1415 }
1416
1417 if (Status != STATUS_PENDING) {
1418 Irp->IoStatus.Status = Status;
1419 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1420 }
1421
1422 DPRINT("Leaving. Status 0x%X\n", Status);
1423
1424 return Status;
1425 }
1426
1427 /* EOF */