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