- Assign a proper InterfaceType to the resource descriptor. Fixes assert when using...
[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 "pci.h"
11
12 #define NDEBUG
13 #include <debug.h>
14
15 /*** PRIVATE *****************************************************************/
16
17 static NTSTATUS
18 PdoQueryDeviceText(
19 IN PDEVICE_OBJECT DeviceObject,
20 IN PIRP Irp,
21 PIO_STACK_LOCATION IrpSp)
22 {
23 PPDO_DEVICE_EXTENSION DeviceExtension;
24 NTSTATUS Status;
25
26 DPRINT("Called\n");
27
28 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
29
30 Status = STATUS_SUCCESS;
31
32 switch (IrpSp->Parameters.QueryDeviceText.DeviceTextType)
33 {
34 case DeviceTextDescription:
35 DPRINT("DeviceTextDescription\n");
36 Irp->IoStatus.Information = (ULONG_PTR)DeviceExtension->DeviceDescription.Buffer;
37 break;
38
39 case DeviceTextLocationInformation:
40 DPRINT("DeviceTextLocationInformation\n");
41 Irp->IoStatus.Information = (ULONG_PTR)DeviceExtension->DeviceLocation.Buffer;
42 break;
43
44 default:
45 Irp->IoStatus.Information = 0;
46 Status = STATUS_INVALID_PARAMETER;
47 }
48
49 return Status;
50 }
51
52
53 static NTSTATUS
54 PdoQueryId(
55 IN PDEVICE_OBJECT DeviceObject,
56 IN PIRP Irp,
57 PIO_STACK_LOCATION IrpSp)
58 {
59 PPDO_DEVICE_EXTENSION DeviceExtension;
60 UNICODE_STRING String;
61 NTSTATUS Status;
62
63 DPRINT("Called\n");
64
65 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
66
67 // Irp->IoStatus.Information = 0;
68
69 Status = STATUS_SUCCESS;
70
71 RtlInitUnicodeString(&String, NULL);
72
73 switch (IrpSp->Parameters.QueryId.IdType) {
74 case BusQueryDeviceID:
75 Status = RtlDuplicateUnicodeString(
76 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
77 &DeviceExtension->DeviceID,
78 &String);
79
80 DPRINT("DeviceID: %S\n", String.Buffer);
81
82 Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
83 break;
84
85 case BusQueryHardwareIDs:
86 Status = RtlDuplicateUnicodeString(
87 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
88 &DeviceExtension->HardwareIDs,
89 &String);
90
91 Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
92 break;
93
94 case BusQueryCompatibleIDs:
95 Status = RtlDuplicateUnicodeString(
96 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
97 &DeviceExtension->CompatibleIDs,
98 &String);
99
100 Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
101 break;
102
103 case BusQueryInstanceID:
104 Status = RtlDuplicateUnicodeString(
105 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
106 &DeviceExtension->InstanceID,
107 &String);
108
109 DPRINT("InstanceID: %S\n", String.Buffer);
110
111 Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
112 break;
113
114 case BusQueryDeviceSerialNumber:
115 default:
116 Status = STATUS_NOT_IMPLEMENTED;
117 }
118
119 return Status;
120 }
121
122
123 static NTSTATUS
124 PdoQueryBusInformation(
125 IN PDEVICE_OBJECT DeviceObject,
126 IN PIRP Irp,
127 PIO_STACK_LOCATION IrpSp)
128 {
129 PPDO_DEVICE_EXTENSION DeviceExtension;
130 PFDO_DEVICE_EXTENSION FdoDeviceExtension;
131 PPNP_BUS_INFORMATION BusInformation;
132
133 DPRINT("Called\n");
134
135 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
136 FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceExtension->Fdo->DeviceExtension;
137 BusInformation = ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
138 Irp->IoStatus.Information = (ULONG_PTR)BusInformation;
139 if (BusInformation != NULL)
140 {
141 BusInformation->BusTypeGuid = GUID_BUS_TYPE_PCI;
142 BusInformation->LegacyBusType = PCIBus;
143 BusInformation->BusNumber = DeviceExtension->PciDevice->BusNumber;
144
145 return STATUS_SUCCESS;
146 }
147
148 return STATUS_INSUFFICIENT_RESOURCES;
149 }
150
151
152 static NTSTATUS
153 PdoQueryCapabilities(
154 IN PDEVICE_OBJECT DeviceObject,
155 IN PIRP Irp,
156 PIO_STACK_LOCATION IrpSp)
157 {
158 PPDO_DEVICE_EXTENSION DeviceExtension;
159 PDEVICE_CAPABILITIES DeviceCapabilities;
160
161 DPRINT("Called\n");
162
163 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
164 DeviceCapabilities = IrpSp->Parameters.DeviceCapabilities.Capabilities;
165
166 if (DeviceCapabilities->Version != 1)
167 return STATUS_UNSUCCESSFUL;
168
169 DeviceCapabilities->UniqueID = FALSE;
170 DeviceCapabilities->Address = DeviceExtension->PciDevice->SlotNumber.u.AsULONG;
171 DeviceCapabilities->UINumber = (ULONG)-1; /* FIXME */
172
173 return STATUS_SUCCESS;
174 }
175
176
177 static BOOLEAN
178 PdoGetRangeLength(PPDO_DEVICE_EXTENSION DeviceExtension,
179 ULONG Offset,
180 PULONG Base,
181 PULONG Length,
182 PULONG Flags)
183 {
184 ULONG OrigValue;
185 ULONG BaseValue;
186 ULONG NewValue;
187 ULONG Size;
188 ULONG XLength;
189
190 /* Save original value */
191 Size= HalGetBusDataByOffset(PCIConfiguration,
192 DeviceExtension->PciDevice->BusNumber,
193 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
194 &OrigValue,
195 Offset,
196 sizeof(ULONG));
197 if (Size != sizeof(ULONG))
198 {
199 DPRINT1("Wrong size %lu\n", Size);
200 return FALSE;
201 }
202
203 BaseValue = (OrigValue & 0x00000001) ? (OrigValue & ~0x3) : (OrigValue & ~0xF);
204
205 *Base = BaseValue;
206
207 /* Set magic value */
208 NewValue = (ULONG)-1;
209 Size= HalSetBusDataByOffset(PCIConfiguration,
210 DeviceExtension->PciDevice->BusNumber,
211 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
212 &NewValue,
213 Offset,
214 sizeof(ULONG));
215 if (Size != sizeof(ULONG))
216 {
217 DPRINT1("Wrong size %lu\n", Size);
218 return FALSE;
219 }
220
221 /* Get the range length */
222 Size= HalGetBusDataByOffset(PCIConfiguration,
223 DeviceExtension->PciDevice->BusNumber,
224 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
225 &NewValue,
226 Offset,
227 sizeof(ULONG));
228 if (Size != sizeof(ULONG))
229 {
230 DPRINT1("Wrong size %lu\n", Size);
231 return FALSE;
232 }
233
234 /* Restore original value */
235 Size= HalSetBusDataByOffset(PCIConfiguration,
236 DeviceExtension->PciDevice->BusNumber,
237 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
238 &OrigValue,
239 Offset,
240 sizeof(ULONG));
241 if (Size != sizeof(ULONG))
242 {
243 DPRINT1("Wrong size %lu\n", Size);
244 return FALSE;
245 }
246
247 if (NewValue == 0)
248 {
249 DPRINT("Unused address register\n");
250 *Base = 0;
251 *Length = 0;
252 *Flags = 0;
253 return TRUE;
254 }
255
256 XLength = ~((NewValue & 0x00000001) ? (NewValue & ~0x3) : (NewValue & ~0xF)) + 1;
257
258 #if 0
259 DbgPrint("BaseAddress 0x%08lx Length 0x%08lx",
260 BaseValue, XLength);
261
262 if (NewValue & 0x00000001)
263 {
264 DbgPrint(" IO range");
265 }
266 else
267 {
268 DbgPrint(" Memory range");
269 if ((NewValue & 0x00000006) == 0)
270 {
271 DbgPrint(" in 32-Bit address space");
272 }
273 else if ((NewValue & 0x00000006) == 2)
274 {
275 DbgPrint(" below 1BM ");
276 }
277 else if ((NewValue & 0x00000006) == 4)
278 {
279 DbgPrint(" in 64-Bit address space");
280 }
281
282 if (NewValue & 0x00000008)
283 {
284 DbgPrint(" prefetchable");
285 }
286 }
287
288 DbgPrint("\n");
289 #endif
290
291 *Length = XLength;
292 *Flags = (NewValue & 0x00000001) ? (NewValue & 0x3) : (NewValue & 0xF);
293
294 return TRUE;
295 }
296
297
298 static NTSTATUS
299 PdoQueryResourceRequirements(
300 IN PDEVICE_OBJECT DeviceObject,
301 IN PIRP Irp,
302 PIO_STACK_LOCATION IrpSp)
303 {
304 PPDO_DEVICE_EXTENSION DeviceExtension;
305 PCI_COMMON_CONFIG PciConfig;
306 PIO_RESOURCE_REQUIREMENTS_LIST ResourceList;
307 PIO_RESOURCE_DESCRIPTOR Descriptor;
308 ULONG Size;
309 ULONG ResCount = 0;
310 ULONG ListSize;
311 ULONG i;
312 ULONG Base;
313 ULONG Length;
314 ULONG Flags;
315
316 DPRINT("PdoQueryResourceRequirements() called\n");
317
318 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
319
320 /* Get PCI configuration space */
321 Size= HalGetBusData(PCIConfiguration,
322 DeviceExtension->PciDevice->BusNumber,
323 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
324 &PciConfig,
325 PCI_COMMON_HDR_LENGTH);
326 DPRINT("Size %lu\n", Size);
327 if (Size < PCI_COMMON_HDR_LENGTH)
328 {
329 Irp->IoStatus.Information = 0;
330 return STATUS_UNSUCCESSFUL;
331 }
332
333 DPRINT("Command register: 0x%04hx\n", PciConfig.Command);
334
335 /* Count required resource descriptors */
336 ResCount = 0;
337 if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_DEVICE_TYPE)
338 {
339 for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
340 {
341 if (!PdoGetRangeLength(DeviceExtension,
342 0x10 + i * 4,
343 &Base,
344 &Length,
345 &Flags))
346 break;
347
348 if (Length != 0)
349 ResCount += 2;
350 }
351
352 /* FIXME: Check ROM address */
353
354 if (PciConfig.u.type0.InterruptPin != 0)
355 ResCount++;
356 }
357 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
358 {
359 for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
360 {
361 if (!PdoGetRangeLength(DeviceExtension,
362 0x10 + i * 4,
363 &Base,
364 &Length,
365 &Flags))
366 break;
367
368 if (Length != 0)
369 ResCount += 2;
370 }
371 if (DeviceExtension->PciDevice->PciConfig.BaseClass == PCI_CLASS_BRIDGE_DEV)
372 ResCount++;
373 }
374 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_CARDBUS_BRIDGE_TYPE)
375 {
376 /* FIXME: Count Cardbus bridge resources */
377 }
378 else
379 {
380 DPRINT1("Unsupported header type %u\n", PCI_CONFIGURATION_TYPE(&PciConfig));
381 }
382
383 if (ResCount == 0)
384 {
385 Irp->IoStatus.Information = 0;
386 return STATUS_SUCCESS;
387 }
388
389 /* Calculate the resource list size */
390 ListSize = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List->Descriptors)
391 + ResCount * sizeof(IO_RESOURCE_DESCRIPTOR);
392
393 DPRINT("ListSize %lu (0x%lx)\n", ListSize, ListSize);
394
395 /* Allocate the resource requirements list */
396 ResourceList = ExAllocatePool(PagedPool,
397 ListSize);
398 if (ResourceList == NULL)
399 {
400 Irp->IoStatus.Information = 0;
401 return STATUS_INSUFFICIENT_RESOURCES;
402 }
403
404 RtlZeroMemory(ResourceList, ListSize);
405 ResourceList->ListSize = ListSize;
406 ResourceList->InterfaceType = PCIBus;
407 ResourceList->BusNumber = DeviceExtension->PciDevice->BusNumber;
408 ResourceList->SlotNumber = DeviceExtension->PciDevice->SlotNumber.u.AsULONG;
409 ResourceList->AlternativeLists = 1;
410
411 ResourceList->List[0].Version = 1;
412 ResourceList->List[0].Revision = 1;
413 ResourceList->List[0].Count = ResCount;
414
415 Descriptor = &ResourceList->List[0].Descriptors[0];
416 if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_DEVICE_TYPE)
417 {
418 for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
419 {
420 if (!PdoGetRangeLength(DeviceExtension,
421 0x10 + i * 4,
422 &Base,
423 &Length,
424 &Flags))
425 {
426 DPRINT1("PdoGetRangeLength() failed\n");
427 break;
428 }
429
430 if (Length == 0)
431 {
432 DPRINT("Unused address register\n");
433 continue;
434 }
435
436 /* Set preferred descriptor */
437 Descriptor->Option = IO_RESOURCE_PREFERRED;
438 if (Flags & PCI_ADDRESS_IO_SPACE)
439 {
440 Descriptor->Type = CmResourceTypePort;
441 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
442 Descriptor->Flags = CM_RESOURCE_PORT_IO |
443 CM_RESOURCE_PORT_16_BIT_DECODE |
444 CM_RESOURCE_PORT_POSITIVE_DECODE;
445
446 Descriptor->u.Port.Length = Length;
447 Descriptor->u.Port.Alignment = 1;
448 Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)Base;
449 Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)(Base + Length - 1);
450 }
451 else
452 {
453 Descriptor->Type = CmResourceTypeMemory;
454 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
455 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
456
457 Descriptor->u.Memory.Length = Length;
458 Descriptor->u.Memory.Alignment = 1;
459 Descriptor->u.Memory.MinimumAddress.QuadPart = (ULONGLONG)Base;
460 Descriptor->u.Memory.MaximumAddress.QuadPart = (ULONGLONG)(Base + Length - 1);
461 }
462 Descriptor++;
463
464 /* Set alternative descriptor */
465 Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
466 if (Flags & PCI_ADDRESS_IO_SPACE)
467 {
468 Descriptor->Type = CmResourceTypePort;
469 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
470 Descriptor->Flags = CM_RESOURCE_PORT_IO |
471 CM_RESOURCE_PORT_16_BIT_DECODE |
472 CM_RESOURCE_PORT_POSITIVE_DECODE;
473
474 Descriptor->u.Port.Length = Length;
475 Descriptor->u.Port.Alignment = Length;
476 Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)0;
477 Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)0x00000000FFFFFFFF;
478 }
479 else
480 {
481 Descriptor->Type = CmResourceTypeMemory;
482 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
483 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
484
485 Descriptor->u.Memory.Length = Length;
486 Descriptor->u.Memory.Alignment = Length;
487 Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)0;
488 Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)0x00000000FFFFFFFF;
489 }
490 Descriptor++;
491 }
492
493 /* FIXME: Check ROM address */
494
495 if (PciConfig.u.type0.InterruptPin != 0)
496 {
497 Descriptor->Option = 0; /* Required */
498 Descriptor->Type = CmResourceTypeInterrupt;
499 Descriptor->ShareDisposition = CmResourceShareShared;
500 Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
501
502 Descriptor->u.Interrupt.MinimumVector = 0;
503 Descriptor->u.Interrupt.MaximumVector = 0xFF;
504 }
505 }
506 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
507 {
508 for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
509 {
510 if (!PdoGetRangeLength(DeviceExtension,
511 0x10 + i * 4,
512 &Base,
513 &Length,
514 &Flags))
515 {
516 DPRINT1("PdoGetRangeLength() failed\n");
517 break;
518 }
519
520 if (Length == 0)
521 {
522 DPRINT("Unused address register\n");
523 continue;
524 }
525
526 /* Set preferred descriptor */
527 Descriptor->Option = IO_RESOURCE_PREFERRED;
528 if (Flags & PCI_ADDRESS_IO_SPACE)
529 {
530 Descriptor->Type = CmResourceTypePort;
531 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
532 Descriptor->Flags = CM_RESOURCE_PORT_IO |
533 CM_RESOURCE_PORT_16_BIT_DECODE |
534 CM_RESOURCE_PORT_POSITIVE_DECODE;
535
536 Descriptor->u.Port.Length = Length;
537 Descriptor->u.Port.Alignment = 1;
538 Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)Base;
539 Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)(Base + Length - 1);
540 }
541 else
542 {
543 Descriptor->Type = CmResourceTypeMemory;
544 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
545 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
546
547 Descriptor->u.Memory.Length = Length;
548 Descriptor->u.Memory.Alignment = 1;
549 Descriptor->u.Memory.MinimumAddress.QuadPart = (ULONGLONG)Base;
550 Descriptor->u.Memory.MaximumAddress.QuadPart = (ULONGLONG)(Base + Length - 1);
551 }
552 Descriptor++;
553
554 /* Set alternative descriptor */
555 Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
556 if (Flags & PCI_ADDRESS_IO_SPACE)
557 {
558 Descriptor->Type = CmResourceTypePort;
559 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
560 Descriptor->Flags = CM_RESOURCE_PORT_IO |
561 CM_RESOURCE_PORT_16_BIT_DECODE |
562 CM_RESOURCE_PORT_POSITIVE_DECODE;
563
564 Descriptor->u.Port.Length = Length;
565 Descriptor->u.Port.Alignment = Length;
566 Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)0;
567 Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)0x00000000FFFFFFFF;
568 }
569 else
570 {
571 Descriptor->Type = CmResourceTypeMemory;
572 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
573 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
574
575 Descriptor->u.Memory.Length = Length;
576 Descriptor->u.Memory.Alignment = Length;
577 Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)0;
578 Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)0x00000000FFFFFFFF;
579 }
580 Descriptor++;
581 }
582 if (DeviceExtension->PciDevice->PciConfig.BaseClass == PCI_CLASS_BRIDGE_DEV)
583 {
584 Descriptor->Option = 0; /* Required */
585 Descriptor->Type = CmResourceTypeBusNumber;
586 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
587
588 Descriptor->u.BusNumber.MinBusNumber =
589 Descriptor->u.BusNumber.MaxBusNumber = DeviceExtension->PciDevice->PciConfig.u.type1.SecondaryBus;
590 Descriptor->u.BusNumber.Length = 1;
591 Descriptor->u.BusNumber.Reserved = 0;
592 }
593 }
594 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_CARDBUS_BRIDGE_TYPE)
595 {
596 /* FIXME: Add Cardbus bridge resources */
597 }
598
599 Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
600
601 return STATUS_SUCCESS;
602 }
603
604
605 static NTSTATUS
606 PdoQueryResources(
607 IN PDEVICE_OBJECT DeviceObject,
608 IN PIRP Irp,
609 PIO_STACK_LOCATION IrpSp)
610 {
611 PPDO_DEVICE_EXTENSION DeviceExtension;
612 PCI_COMMON_CONFIG PciConfig;
613 PCM_RESOURCE_LIST ResourceList;
614 PCM_PARTIAL_RESOURCE_LIST PartialList;
615 PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
616 ULONG Size;
617 ULONG ResCount = 0;
618 ULONG ListSize;
619 ULONG i;
620 ULONG Base;
621 ULONG Length;
622 ULONG Flags;
623
624 DPRINT("PdoQueryResources() called\n");
625
626 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
627
628 /* Get PCI configuration space */
629 Size= HalGetBusData(PCIConfiguration,
630 DeviceExtension->PciDevice->BusNumber,
631 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
632 &PciConfig,
633 PCI_COMMON_HDR_LENGTH);
634 DPRINT("Size %lu\n", Size);
635 if (Size < PCI_COMMON_HDR_LENGTH)
636 {
637 Irp->IoStatus.Information = 0;
638 return STATUS_UNSUCCESSFUL;
639 }
640
641 DPRINT("Command register: 0x%04hx\n", PciConfig.Command);
642
643 /* Count required resource descriptors */
644 ResCount = 0;
645 if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_DEVICE_TYPE)
646 {
647 for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
648 {
649 if (!PdoGetRangeLength(DeviceExtension,
650 0x10 + i * 4,
651 &Base,
652 &Length,
653 &Flags))
654 break;
655
656 if (Length)
657 ResCount++;
658 }
659
660 if ((PciConfig.u.type0.InterruptPin != 0) &&
661 (PciConfig.u.type0.InterruptLine != 0xFF))
662 ResCount++;
663 }
664 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
665 {
666 for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
667 {
668 if (!PdoGetRangeLength(DeviceExtension,
669 0x10 + i * 4,
670 &Base,
671 &Length,
672 &Flags))
673 break;
674
675 if (Length != 0)
676 ResCount++;
677 }
678 if (DeviceExtension->PciDevice->PciConfig.BaseClass == PCI_CLASS_BRIDGE_DEV)
679 ResCount++;
680 }
681 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_CARDBUS_BRIDGE_TYPE)
682 {
683 /* FIXME: Count Cardbus bridge resources */
684 }
685 else
686 {
687 DPRINT1("Unsupported header type %u\n", PCI_CONFIGURATION_TYPE(&PciConfig));
688 }
689
690 if (ResCount == 0)
691 {
692 Irp->IoStatus.Information = 0;
693 return STATUS_SUCCESS;
694 }
695
696 /* Calculate the resource list size */
697 ListSize = FIELD_OFFSET(CM_RESOURCE_LIST, List->PartialResourceList.PartialDescriptors)
698 + ResCount * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
699
700 /* Allocate the resource list */
701 ResourceList = ExAllocatePool(PagedPool,
702 ListSize);
703 if (ResourceList == NULL)
704 return STATUS_INSUFFICIENT_RESOURCES;
705
706 RtlZeroMemory(ResourceList, ListSize);
707 ResourceList->Count = 1;
708 ResourceList->List[0].InterfaceType = PCIBus;
709 ResourceList->List[0].BusNumber = DeviceExtension->PciDevice->BusNumber;
710
711 PartialList = &ResourceList->List[0].PartialResourceList;
712 PartialList->Version = 1;
713 PartialList->Revision = 1;
714 PartialList->Count = ResCount;
715
716 Descriptor = &PartialList->PartialDescriptors[0];
717 if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_DEVICE_TYPE)
718 {
719 for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
720 {
721 if (!PdoGetRangeLength(DeviceExtension,
722 0x10 + i * 4,
723 &Base,
724 &Length,
725 &Flags))
726 {
727 DPRINT1("PdoGetRangeLength() failed\n");
728 break;
729 }
730
731 if (Length == 0)
732 {
733 DPRINT("Unused address register\n");
734 continue;
735 }
736
737 if (Flags & PCI_ADDRESS_IO_SPACE)
738 {
739 Descriptor->Type = CmResourceTypePort;
740 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
741 Descriptor->Flags = CM_RESOURCE_PORT_IO;
742 Descriptor->u.Port.Start.QuadPart =
743 (ULONGLONG)Base;
744 Descriptor->u.Port.Length = Length;
745 }
746 else
747 {
748 Descriptor->Type = CmResourceTypeMemory;
749 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
750 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
751 Descriptor->u.Memory.Start.QuadPart =
752 (ULONGLONG)Base;
753 Descriptor->u.Memory.Length = Length;
754 }
755
756 Descriptor++;
757 }
758
759 /* Add interrupt resource */
760 if ((PciConfig.u.type0.InterruptPin != 0) &&
761 (PciConfig.u.type0.InterruptLine != 0xFF))
762 {
763 Descriptor->Type = CmResourceTypeInterrupt;
764 Descriptor->ShareDisposition = CmResourceShareShared;
765 Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
766 Descriptor->u.Interrupt.Level = PciConfig.u.type0.InterruptLine;
767 Descriptor->u.Interrupt.Vector = PciConfig.u.type0.InterruptLine;
768 Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
769 }
770 }
771 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
772 {
773 for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
774 {
775 if (!PdoGetRangeLength(DeviceExtension,
776 0x10 + i * 4,
777 &Base,
778 &Length,
779 &Flags))
780 {
781 DPRINT1("PdoGetRangeLength() failed\n");
782 break;
783 }
784
785 if (Length == 0)
786 {
787 DPRINT("Unused address register\n");
788 continue;
789 }
790
791 if (Flags & PCI_ADDRESS_IO_SPACE)
792 {
793 Descriptor->Type = CmResourceTypePort;
794 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
795 Descriptor->Flags = CM_RESOURCE_PORT_IO;
796 Descriptor->u.Port.Start.QuadPart =
797 (ULONGLONG)Base;
798 Descriptor->u.Port.Length = Length;
799 }
800 else
801 {
802 Descriptor->Type = CmResourceTypeMemory;
803 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
804 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
805 Descriptor->u.Memory.Start.QuadPart =
806 (ULONGLONG)Base;
807 Descriptor->u.Memory.Length = Length;
808 }
809
810 Descriptor++;
811 }
812 if (DeviceExtension->PciDevice->PciConfig.BaseClass == PCI_CLASS_BRIDGE_DEV)
813 {
814 Descriptor->Type = CmResourceTypeBusNumber;
815 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
816
817 Descriptor->u.BusNumber.Start = DeviceExtension->PciDevice->PciConfig.u.type1.SecondaryBus;
818 Descriptor->u.BusNumber.Length = 1;
819 Descriptor->u.BusNumber.Reserved = 0;
820 }
821 }
822 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_CARDBUS_BRIDGE_TYPE)
823 {
824 /* FIXME: Add Cardbus bridge resources */
825 }
826
827 Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
828
829 return STATUS_SUCCESS;
830 }
831
832
833 static VOID NTAPI
834 InterfaceReference(
835 IN PVOID Context)
836 {
837 PPDO_DEVICE_EXTENSION DeviceExtension;
838
839 DPRINT("InterfaceReference(%p)\n", Context);
840
841 DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
842 InterlockedIncrement(&DeviceExtension->References);
843 }
844
845
846 static VOID NTAPI
847 InterfaceDereference(
848 IN PVOID Context)
849 {
850 PPDO_DEVICE_EXTENSION DeviceExtension;
851
852 DPRINT("InterfaceDereference(%p)\n", Context);
853
854 DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
855 InterlockedDecrement(&DeviceExtension->References);
856 }
857
858
859 static BOOLEAN NTAPI
860 InterfaceBusTranslateBusAddress(
861 IN PVOID Context,
862 IN PHYSICAL_ADDRESS BusAddress,
863 IN ULONG Length,
864 IN OUT PULONG AddressSpace,
865 OUT PPHYSICAL_ADDRESS TranslatedAddress)
866 {
867 PPDO_DEVICE_EXTENSION DeviceExtension;
868
869 DPRINT("InterfaceBusTranslateBusAddress(%p %p 0x%lx %p %p)\n",
870 Context, BusAddress, Length, AddressSpace, TranslatedAddress);
871
872 DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
873
874 return HalTranslateBusAddress(
875 PCIBus, DeviceExtension->PciDevice->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->BaseClass != Parameters->BaseClass ||
1025 PciConfig->SubClass != Parameters->SubClass))
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->u.type0.SubVendorID != Parameters->SubVendorID ||
1036 PciConfig->u.type0.SubSystemID != 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->TranslateBusAddress = InterfaceBusTranslateBusAddress;
1131 BusInterface->GetDmaAdapter = InterfaceBusGetDmaAdapter;
1132 BusInterface->SetBusData = InterfaceBusSetBusData;
1133 BusInterface->GetBusData = InterfaceBusGetBusData;
1134 Status = STATUS_SUCCESS;
1135 }
1136 }
1137 else if (RtlCompareMemory(IrpSp->Parameters.QueryInterface.InterfaceType,
1138 &GUID_PCI_DEVICE_PRESENT_INTERFACE, sizeof(GUID)) == sizeof(GUID))
1139 {
1140 /* PCI_DEVICE_PRESENT_INTERFACE */
1141 if (IrpSp->Parameters.QueryInterface.Version < 1)
1142 Status = STATUS_NOT_SUPPORTED;
1143 else if (IrpSp->Parameters.QueryInterface.Size < sizeof(PCI_DEVICE_PRESENT_INTERFACE))
1144 Status = STATUS_BUFFER_TOO_SMALL;
1145 else
1146 {
1147 PPCI_DEVICE_PRESENT_INTERFACE PciDevicePresentInterface;
1148 PciDevicePresentInterface = (PPCI_DEVICE_PRESENT_INTERFACE)IrpSp->Parameters.QueryInterface.Interface;
1149 PciDevicePresentInterface->Size = sizeof(PCI_DEVICE_PRESENT_INTERFACE);
1150 PciDevicePresentInterface->Version = 1;
1151 PciDevicePresentInterface->IsDevicePresent = InterfacePciDevicePresent;
1152 PciDevicePresentInterface->IsDevicePresentEx = InterfacePciDevicePresentEx;
1153 Status = STATUS_SUCCESS;
1154 }
1155 }
1156 else
1157 {
1158 /* Not a supported interface */
1159 return STATUS_NOT_SUPPORTED;
1160 }
1161
1162 if (NT_SUCCESS(Status))
1163 {
1164 /* Add a reference for the returned interface */
1165 PINTERFACE Interface;
1166 Interface = (PINTERFACE)IrpSp->Parameters.QueryInterface.Interface;
1167 Interface->Context = DeviceObject;
1168 Interface->InterfaceReference = InterfaceReference;
1169 Interface->InterfaceDereference = InterfaceDereference;
1170 Interface->InterfaceReference(Interface->Context);
1171 }
1172
1173 return Status;
1174 }
1175
1176
1177 static NTSTATUS
1178 PdoReadConfig(
1179 IN PDEVICE_OBJECT DeviceObject,
1180 IN PIRP Irp,
1181 PIO_STACK_LOCATION IrpSp)
1182 {
1183 ULONG Size;
1184
1185 DPRINT("PdoReadConfig() called\n");
1186
1187 Size = InterfaceBusGetBusData(
1188 DeviceObject,
1189 IrpSp->Parameters.ReadWriteConfig.WhichSpace,
1190 IrpSp->Parameters.ReadWriteConfig.Buffer,
1191 IrpSp->Parameters.ReadWriteConfig.Offset,
1192 IrpSp->Parameters.ReadWriteConfig.Length);
1193
1194 if (Size != IrpSp->Parameters.ReadWriteConfig.Length)
1195 {
1196 DPRINT1("Size %lu Length %lu\n", Size, IrpSp->Parameters.ReadWriteConfig.Length);
1197 Irp->IoStatus.Information = 0;
1198 return STATUS_UNSUCCESSFUL;
1199 }
1200
1201 Irp->IoStatus.Information = Size;
1202
1203 return STATUS_SUCCESS;
1204 }
1205
1206
1207 static NTSTATUS
1208 PdoWriteConfig(
1209 IN PDEVICE_OBJECT DeviceObject,
1210 IN PIRP Irp,
1211 PIO_STACK_LOCATION IrpSp)
1212 {
1213 ULONG Size;
1214
1215 DPRINT1("PdoWriteConfig() called\n");
1216
1217 /* Get PCI configuration space */
1218 Size = InterfaceBusSetBusData(
1219 DeviceObject,
1220 IrpSp->Parameters.ReadWriteConfig.WhichSpace,
1221 IrpSp->Parameters.ReadWriteConfig.Buffer,
1222 IrpSp->Parameters.ReadWriteConfig.Offset,
1223 IrpSp->Parameters.ReadWriteConfig.Length);
1224
1225 if (Size != IrpSp->Parameters.ReadWriteConfig.Length)
1226 {
1227 DPRINT1("Size %lu Length %lu\n", Size, IrpSp->Parameters.ReadWriteConfig.Length);
1228 Irp->IoStatus.Information = 0;
1229 return STATUS_UNSUCCESSFUL;
1230 }
1231
1232 Irp->IoStatus.Information = Size;
1233
1234 return STATUS_SUCCESS;
1235 }
1236
1237
1238 static NTSTATUS
1239 PdoSetPower(
1240 IN PDEVICE_OBJECT DeviceObject,
1241 IN PIRP Irp,
1242 PIO_STACK_LOCATION IrpSp)
1243 {
1244 PPDO_DEVICE_EXTENSION DeviceExtension;
1245 NTSTATUS Status;
1246
1247 DPRINT("Called\n");
1248
1249 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1250
1251 if (IrpSp->Parameters.Power.Type == DevicePowerState) {
1252 Status = STATUS_SUCCESS;
1253 switch (IrpSp->Parameters.Power.State.SystemState) {
1254 default:
1255 Status = STATUS_UNSUCCESSFUL;
1256 }
1257 } else {
1258 Status = STATUS_UNSUCCESSFUL;
1259 }
1260
1261 return Status;
1262 }
1263
1264
1265 /*** PUBLIC ******************************************************************/
1266
1267 NTSTATUS
1268 PdoPnpControl(
1269 PDEVICE_OBJECT DeviceObject,
1270 PIRP Irp)
1271 /*
1272 * FUNCTION: Handle Plug and Play IRPs for the child device
1273 * ARGUMENTS:
1274 * DeviceObject = Pointer to physical device object of the child device
1275 * Irp = Pointer to IRP that should be handled
1276 * RETURNS:
1277 * Status
1278 */
1279 {
1280 PIO_STACK_LOCATION IrpSp;
1281 NTSTATUS Status;
1282
1283 DPRINT("Called\n");
1284
1285 Status = Irp->IoStatus.Status;
1286
1287 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1288
1289 switch (IrpSp->MinorFunction) {
1290 #if 0
1291 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
1292 break;
1293
1294 case IRP_MN_EJECT:
1295 break;
1296 #endif
1297
1298 case IRP_MN_QUERY_BUS_INFORMATION:
1299 Status = PdoQueryBusInformation(DeviceObject, Irp, IrpSp);
1300 break;
1301
1302 case IRP_MN_QUERY_CAPABILITIES:
1303 Status = PdoQueryCapabilities(DeviceObject, Irp, IrpSp);
1304 break;
1305
1306 #if 0
1307 case IRP_MN_QUERY_DEVICE_RELATIONS:
1308 /* FIXME: Possibly handle for RemovalRelations */
1309 break;
1310 #endif
1311
1312 case IRP_MN_QUERY_DEVICE_TEXT:
1313 DPRINT("IRP_MN_QUERY_DEVICE_TEXT received\n");
1314 Status = PdoQueryDeviceText(DeviceObject, Irp, IrpSp);
1315 break;
1316
1317 case IRP_MN_QUERY_ID:
1318 DPRINT("IRP_MN_QUERY_ID received\n");
1319 Status = PdoQueryId(DeviceObject, Irp, IrpSp);
1320 break;
1321
1322 #if 0
1323 case IRP_MN_QUERY_PNP_DEVICE_STATE:
1324 break;
1325 #endif
1326
1327 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
1328 DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS received\n");
1329 Status = PdoQueryResourceRequirements(DeviceObject, Irp, IrpSp);
1330 break;
1331
1332 case IRP_MN_QUERY_RESOURCES:
1333 DPRINT("IRP_MN_QUERY_RESOURCES received\n");
1334 Status = PdoQueryResources(DeviceObject, Irp, IrpSp);
1335 break;
1336
1337 #if 0
1338 case IRP_MN_SET_LOCK:
1339 break;
1340 #endif
1341
1342 case IRP_MN_START_DEVICE:
1343 case IRP_MN_QUERY_STOP_DEVICE:
1344 case IRP_MN_CANCEL_STOP_DEVICE:
1345 case IRP_MN_STOP_DEVICE:
1346 case IRP_MN_QUERY_REMOVE_DEVICE:
1347 case IRP_MN_CANCEL_REMOVE_DEVICE:
1348 case IRP_MN_REMOVE_DEVICE:
1349 case IRP_MN_SURPRISE_REMOVAL:
1350 Status = STATUS_SUCCESS;
1351 break;
1352
1353 case IRP_MN_QUERY_INTERFACE:
1354 DPRINT("IRP_MN_QUERY_INTERFACE received\n");
1355 Status = PdoQueryInterface(DeviceObject, Irp, IrpSp);
1356 break;
1357
1358 case IRP_MN_READ_CONFIG:
1359 DPRINT("IRP_MN_READ_CONFIG received\n");
1360 Status = PdoReadConfig(DeviceObject, Irp, IrpSp);
1361 break;
1362
1363 case IRP_MN_WRITE_CONFIG:
1364 DPRINT("IRP_MN_WRITE_CONFIG received\n");
1365 Status = PdoWriteConfig(DeviceObject, Irp, IrpSp);
1366 break;
1367
1368 default:
1369 DPRINT1("Unknown IOCTL 0x%lx\n", IrpSp->MinorFunction);
1370 break;
1371 }
1372
1373 if (Status != STATUS_PENDING) {
1374 Irp->IoStatus.Status = Status;
1375 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1376 }
1377
1378 DPRINT("Leaving. Status 0x%X\n", Status);
1379
1380 return Status;
1381 }
1382
1383 NTSTATUS
1384 PdoPowerControl(
1385 PDEVICE_OBJECT DeviceObject,
1386 PIRP Irp)
1387 /*
1388 * FUNCTION: Handle power management IRPs for the child device
1389 * ARGUMENTS:
1390 * DeviceObject = Pointer to physical device object of the child device
1391 * Irp = Pointer to IRP that should be handled
1392 * RETURNS:
1393 * Status
1394 */
1395 {
1396 PIO_STACK_LOCATION IrpSp;
1397 NTSTATUS Status;
1398
1399 DPRINT("Called\n");
1400
1401 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1402
1403 switch (IrpSp->MinorFunction) {
1404 case IRP_MN_SET_POWER:
1405 Status = PdoSetPower(DeviceObject, Irp, IrpSp);
1406 break;
1407
1408 default:
1409 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
1410 Status = STATUS_NOT_IMPLEMENTED;
1411 break;
1412 }
1413
1414 if (Status != STATUS_PENDING) {
1415 Irp->IoStatus.Status = Status;
1416 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1417 }
1418
1419 DPRINT("Leaving. Status 0x%X\n", Status);
1420
1421 return Status;
1422 }
1423
1424 /* EOF */