Visual C++ backend for rbuild (for now just a hacked mingw backend) and related compi...
[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 DPRINT("Called\n");
136
137 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
138 FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceExtension->Fdo->DeviceExtension;
139 BusInformation = ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
140 Irp->IoStatus.Information = (ULONG_PTR)BusInformation;
141 if (BusInformation != NULL)
142 {
143 BusInformation->BusTypeGuid = GUID_BUS_TYPE_PCI;
144 BusInformation->LegacyBusType = PCIBus;
145 BusInformation->BusNumber = DeviceExtension->PciDevice->BusNumber;
146
147 return STATUS_SUCCESS;
148 }
149
150 return STATUS_INSUFFICIENT_RESOURCES;
151 }
152
153
154 static NTSTATUS
155 PdoQueryCapabilities(
156 IN PDEVICE_OBJECT DeviceObject,
157 IN PIRP Irp,
158 PIO_STACK_LOCATION IrpSp)
159 {
160 PPDO_DEVICE_EXTENSION DeviceExtension;
161 PDEVICE_CAPABILITIES DeviceCapabilities;
162 ULONG DeviceNumber, FunctionNumber;
163
164 DPRINT("Called\n");
165
166 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
167 DeviceCapabilities = IrpSp->Parameters.DeviceCapabilities.Capabilities;
168
169 if (DeviceCapabilities->Version != 1)
170 return STATUS_UNSUCCESSFUL;
171
172 DeviceNumber = DeviceExtension->PciDevice->SlotNumber.u.bits.DeviceNumber;
173 FunctionNumber = DeviceExtension->PciDevice->SlotNumber.u.bits.FunctionNumber;
174
175 DeviceCapabilities->UniqueID = FALSE;
176 DeviceCapabilities->Address = ((DeviceNumber << 16) & 0xFFFF0000) + (FunctionNumber & 0xFFFF);
177 DeviceCapabilities->UINumber = (ULONG)-1; /* FIXME */
178
179 return STATUS_SUCCESS;
180 }
181
182
183 static BOOLEAN
184 PdoGetRangeLength(PPDO_DEVICE_EXTENSION DeviceExtension,
185 ULONG Offset,
186 PULONG Base,
187 PULONG Length,
188 PULONG Flags)
189 {
190 ULONG OrigValue;
191 ULONG BaseValue;
192 ULONG NewValue;
193 ULONG Size;
194 ULONG XLength;
195
196 /* Save original value */
197 Size= HalGetBusDataByOffset(PCIConfiguration,
198 DeviceExtension->PciDevice->BusNumber,
199 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
200 &OrigValue,
201 Offset,
202 sizeof(ULONG));
203 if (Size != sizeof(ULONG))
204 {
205 DPRINT1("Wrong size %lu\n", Size);
206 return FALSE;
207 }
208
209 BaseValue = (OrigValue & 0x00000001) ? (OrigValue & ~0x3) : (OrigValue & ~0xF);
210
211 *Base = BaseValue;
212
213 /* Set magic value */
214 NewValue = (ULONG)-1;
215 Size= HalSetBusDataByOffset(PCIConfiguration,
216 DeviceExtension->PciDevice->BusNumber,
217 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
218 &NewValue,
219 Offset,
220 sizeof(ULONG));
221 if (Size != sizeof(ULONG))
222 {
223 DPRINT1("Wrong size %lu\n", Size);
224 return FALSE;
225 }
226
227 /* Get the range length */
228 Size= HalGetBusDataByOffset(PCIConfiguration,
229 DeviceExtension->PciDevice->BusNumber,
230 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
231 &NewValue,
232 Offset,
233 sizeof(ULONG));
234 if (Size != sizeof(ULONG))
235 {
236 DPRINT1("Wrong size %lu\n", Size);
237 return FALSE;
238 }
239
240 /* Restore original value */
241 Size= HalSetBusDataByOffset(PCIConfiguration,
242 DeviceExtension->PciDevice->BusNumber,
243 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
244 &OrigValue,
245 Offset,
246 sizeof(ULONG));
247 if (Size != sizeof(ULONG))
248 {
249 DPRINT1("Wrong size %lu\n", Size);
250 return FALSE;
251 }
252
253 if (NewValue == 0)
254 {
255 DPRINT("Unused address register\n");
256 *Base = 0;
257 *Length = 0;
258 *Flags = 0;
259 return TRUE;
260 }
261
262 XLength = ~((NewValue & 0x00000001) ? (NewValue & ~0x3) : (NewValue & ~0xF)) + 1;
263
264 #if 0
265 DbgPrint("BaseAddress 0x%08lx Length 0x%08lx",
266 BaseValue, XLength);
267
268 if (NewValue & 0x00000001)
269 {
270 DbgPrint(" IO range");
271 }
272 else
273 {
274 DbgPrint(" Memory range");
275 if ((NewValue & 0x00000006) == 0)
276 {
277 DbgPrint(" in 32-Bit address space");
278 }
279 else if ((NewValue & 0x00000006) == 2)
280 {
281 DbgPrint(" below 1BM ");
282 }
283 else if ((NewValue & 0x00000006) == 4)
284 {
285 DbgPrint(" in 64-Bit address space");
286 }
287
288 if (NewValue & 0x00000008)
289 {
290 DbgPrint(" prefetchable");
291 }
292 }
293
294 DbgPrint("\n");
295 #endif
296
297 *Length = XLength;
298 *Flags = (NewValue & 0x00000001) ? (NewValue & 0x3) : (NewValue & 0xF);
299
300 return TRUE;
301 }
302
303
304 static NTSTATUS
305 PdoQueryResourceRequirements(
306 IN PDEVICE_OBJECT DeviceObject,
307 IN PIRP Irp,
308 PIO_STACK_LOCATION IrpSp)
309 {
310 PPDO_DEVICE_EXTENSION DeviceExtension;
311 PCI_COMMON_CONFIG PciConfig;
312 PIO_RESOURCE_REQUIREMENTS_LIST ResourceList;
313 PIO_RESOURCE_DESCRIPTOR Descriptor;
314 ULONG Size;
315 ULONG ResCount = 0;
316 ULONG ListSize;
317 ULONG i;
318 ULONG Base;
319 ULONG Length;
320 ULONG Flags;
321
322 DPRINT("PdoQueryResourceRequirements() called\n");
323
324 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
325
326 /* Get PCI configuration space */
327 Size= HalGetBusData(PCIConfiguration,
328 DeviceExtension->PciDevice->BusNumber,
329 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
330 &PciConfig,
331 PCI_COMMON_HDR_LENGTH);
332 DPRINT("Size %lu\n", Size);
333 if (Size < PCI_COMMON_HDR_LENGTH)
334 {
335 Irp->IoStatus.Information = 0;
336 return STATUS_UNSUCCESSFUL;
337 }
338
339 DPRINT("Command register: 0x%04hx\n", PciConfig.Command);
340
341 /* Count required resource descriptors */
342 ResCount = 0;
343 if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_DEVICE_TYPE)
344 {
345 for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
346 {
347 if (!PdoGetRangeLength(DeviceExtension,
348 0x10 + i * 4,
349 &Base,
350 &Length,
351 &Flags))
352 break;
353
354 if (Length != 0)
355 ResCount += 2;
356 }
357
358 /* FIXME: Check ROM address */
359
360 if (PciConfig.u.type0.InterruptPin != 0)
361 ResCount++;
362 }
363 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
364 {
365 for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
366 {
367 if (!PdoGetRangeLength(DeviceExtension,
368 0x10 + i * 4,
369 &Base,
370 &Length,
371 &Flags))
372 break;
373
374 if (Length != 0)
375 ResCount += 2;
376 }
377 if (DeviceExtension->PciDevice->PciConfig.BaseClass == PCI_CLASS_BRIDGE_DEV)
378 ResCount++;
379 }
380 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_CARDBUS_BRIDGE_TYPE)
381 {
382 /* FIXME: Count Cardbus bridge resources */
383 }
384 else
385 {
386 DPRINT1("Unsupported header type %u\n", PCI_CONFIGURATION_TYPE(&PciConfig));
387 }
388
389 if (ResCount == 0)
390 {
391 Irp->IoStatus.Information = 0;
392 return STATUS_SUCCESS;
393 }
394
395 /* Calculate the resource list size */
396 ListSize = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List->Descriptors)
397 + ResCount * sizeof(IO_RESOURCE_DESCRIPTOR);
398
399 DPRINT("ListSize %lu (0x%lx)\n", ListSize, ListSize);
400
401 /* Allocate the resource requirements list */
402 ResourceList = ExAllocatePoolWithTag(PagedPool,
403 ListSize, TAG_PCI);
404 if (ResourceList == NULL)
405 {
406 Irp->IoStatus.Information = 0;
407 return STATUS_INSUFFICIENT_RESOURCES;
408 }
409
410 RtlZeroMemory(ResourceList, ListSize);
411 ResourceList->ListSize = ListSize;
412 ResourceList->InterfaceType = PCIBus;
413 ResourceList->BusNumber = 0;
414 ResourceList->SlotNumber = 0;
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 = CmResourceShareDeviceExclusive;
593
594 ResourceList->BusNumber =
595 Descriptor->u.BusNumber.MinBusNumber =
596 Descriptor->u.BusNumber.MaxBusNumber = DeviceExtension->PciDevice->PciConfig.u.type1.SecondaryBus;
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 if (DeviceExtension->PciDevice->PciConfig.BaseClass == PCI_CLASS_BRIDGE_DEV)
686 ResCount++;
687 }
688 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_CARDBUS_BRIDGE_TYPE)
689 {
690 /* FIXME: Count Cardbus bridge resources */
691 }
692 else
693 {
694 DPRINT1("Unsupported header type %u\n", PCI_CONFIGURATION_TYPE(&PciConfig));
695 }
696
697 if (ResCount == 0)
698 {
699 Irp->IoStatus.Information = 0;
700 return STATUS_SUCCESS;
701 }
702
703 /* Calculate the resource list size */
704 ListSize = FIELD_OFFSET(CM_RESOURCE_LIST, List->PartialResourceList.PartialDescriptors)
705 + ResCount * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
706
707 /* Allocate the resource list */
708 ResourceList = ExAllocatePoolWithTag(PagedPool,
709 ListSize, TAG_PCI);
710 if (ResourceList == NULL)
711 return STATUS_INSUFFICIENT_RESOURCES;
712
713 RtlZeroMemory(ResourceList, ListSize);
714 ResourceList->Count = 1;
715 ResourceList->List[0].InterfaceType = PCIBus;
716 ResourceList->List[0].BusNumber = 0;
717
718 PartialList = &ResourceList->List[0].PartialResourceList;
719 PartialList->Version = 1;
720 PartialList->Revision = 1;
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 = 0;
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 if (DeviceExtension->PciDevice->PciConfig.BaseClass == PCI_CLASS_BRIDGE_DEV)
820 {
821 Descriptor->Type = CmResourceTypeBusNumber;
822 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
823
824 ResourceList->List[0].BusNumber =
825 Descriptor->u.BusNumber.Start = DeviceExtension->PciDevice->PciConfig.u.type1.SecondaryBus;
826 Descriptor->u.BusNumber.Length = 1;
827 Descriptor->u.BusNumber.Reserved = 0;
828 }
829 }
830 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_CARDBUS_BRIDGE_TYPE)
831 {
832 /* FIXME: Add Cardbus bridge resources */
833 }
834
835 Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
836
837 return STATUS_SUCCESS;
838 }
839
840
841 static VOID NTAPI
842 InterfaceReference(
843 IN PVOID Context)
844 {
845 PPDO_DEVICE_EXTENSION DeviceExtension;
846
847 DPRINT("InterfaceReference(%p)\n", Context);
848
849 DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
850 InterlockedIncrement(&DeviceExtension->References);
851 }
852
853
854 static VOID NTAPI
855 InterfaceDereference(
856 IN PVOID Context)
857 {
858 PPDO_DEVICE_EXTENSION DeviceExtension;
859
860 DPRINT("InterfaceDereference(%p)\n", Context);
861
862 DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
863 InterlockedDecrement(&DeviceExtension->References);
864 }
865
866
867 static BOOLEAN NTAPI
868 InterfaceBusTranslateBusAddress(
869 IN PVOID Context,
870 IN PHYSICAL_ADDRESS BusAddress,
871 IN ULONG Length,
872 IN OUT PULONG AddressSpace,
873 OUT PPHYSICAL_ADDRESS TranslatedAddress)
874 {
875 PPDO_DEVICE_EXTENSION DeviceExtension;
876
877 DPRINT("InterfaceBusTranslateBusAddress(%p %p 0x%lx %p %p)\n",
878 Context, BusAddress, Length, AddressSpace, TranslatedAddress);
879
880 DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
881
882 return HalTranslateBusAddress(
883 PCIBus, DeviceExtension->PciDevice->BusNumber,
884 BusAddress, AddressSpace, TranslatedAddress);
885 }
886
887
888 static PDMA_ADAPTER NTAPI
889 InterfaceBusGetDmaAdapter(
890 IN PVOID Context,
891 IN PDEVICE_DESCRIPTION DeviceDescription,
892 OUT PULONG NumberOfMapRegisters)
893 {
894 DPRINT("InterfaceBusGetDmaAdapter(%p %p %p)\n",
895 Context, DeviceDescription, NumberOfMapRegisters);
896 return (PDMA_ADAPTER)HalGetAdapter(DeviceDescription, NumberOfMapRegisters);
897 }
898
899
900 static ULONG NTAPI
901 InterfaceBusSetBusData(
902 IN PVOID Context,
903 IN ULONG DataType,
904 IN PVOID Buffer,
905 IN ULONG Offset,
906 IN ULONG Length)
907 {
908 PPDO_DEVICE_EXTENSION DeviceExtension;
909 ULONG Size;
910
911 DPRINT("InterfaceBusSetBusData(%p 0x%lx %p 0x%lx 0x%lx)\n",
912 Context, DataType, Buffer, Offset, Length);
913
914 if (DataType != PCI_WHICHSPACE_CONFIG)
915 {
916 DPRINT("Unknown DataType %lu\n", DataType);
917 return 0;
918 }
919
920 DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
921
922 /* Get PCI configuration space */
923 Size = HalSetBusDataByOffset(PCIConfiguration,
924 DeviceExtension->PciDevice->BusNumber,
925 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
926 Buffer,
927 Offset,
928 Length);
929 return Size;
930 }
931
932
933 static ULONG NTAPI
934 InterfaceBusGetBusData(
935 IN PVOID Context,
936 IN ULONG DataType,
937 IN PVOID Buffer,
938 IN ULONG Offset,
939 IN ULONG Length)
940 {
941 PPDO_DEVICE_EXTENSION DeviceExtension;
942 ULONG Size;
943
944 DPRINT("InterfaceBusGetBusData(%p 0x%lx %p 0x%lx 0x%lx) called\n",
945 Context, DataType, Buffer, Offset, Length);
946
947 if (DataType != PCI_WHICHSPACE_CONFIG)
948 {
949 DPRINT("Unknown DataType %lu\n", DataType);
950 return 0;
951 }
952
953 DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
954
955 /* Get PCI configuration space */
956 Size = HalGetBusDataByOffset(PCIConfiguration,
957 DeviceExtension->PciDevice->BusNumber,
958 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
959 Buffer,
960 Offset,
961 Length);
962 return Size;
963 }
964
965
966 static BOOLEAN NTAPI
967 InterfacePciDevicePresent(
968 IN USHORT VendorID,
969 IN USHORT DeviceID,
970 IN UCHAR RevisionID,
971 IN USHORT SubVendorID,
972 IN USHORT SubSystemID,
973 IN ULONG Flags)
974 {
975 PFDO_DEVICE_EXTENSION FdoDeviceExtension;
976 PPCI_DEVICE PciDevice;
977 PLIST_ENTRY CurrentBus, CurrentEntry;
978 KIRQL OldIrql;
979 BOOLEAN Found = FALSE;
980
981 KeAcquireSpinLock(&DriverExtension->BusListLock, &OldIrql);
982 CurrentBus = DriverExtension->BusListHead.Flink;
983 while (!Found && CurrentBus != &DriverExtension->BusListHead)
984 {
985 FdoDeviceExtension = CONTAINING_RECORD(CurrentBus, FDO_DEVICE_EXTENSION, ListEntry);
986
987 KeAcquireSpinLockAtDpcLevel(&FdoDeviceExtension->DeviceListLock);
988 CurrentEntry = FdoDeviceExtension->DeviceListHead.Flink;
989 while (!Found && CurrentEntry != &FdoDeviceExtension->DeviceListHead)
990 {
991 PciDevice = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry);
992 if (PciDevice->PciConfig.VendorID == VendorID &&
993 PciDevice->PciConfig.DeviceID == DeviceID)
994 {
995 if (!(Flags & PCI_USE_SUBSYSTEM_IDS) || (
996 PciDevice->PciConfig.u.type0.SubVendorID == SubVendorID &&
997 PciDevice->PciConfig.u.type0.SubSystemID == SubSystemID))
998 {
999 if (!(Flags & PCI_USE_REVISION) ||
1000 PciDevice->PciConfig.RevisionID == RevisionID)
1001 {
1002 DPRINT("Found the PCI device\n");
1003 Found = TRUE;
1004 }
1005 }
1006 }
1007
1008 CurrentEntry = CurrentEntry->Flink;
1009 }
1010
1011 KeReleaseSpinLockFromDpcLevel(&FdoDeviceExtension->DeviceListLock);
1012 CurrentBus = CurrentBus->Flink;
1013 }
1014 KeReleaseSpinLock(&DriverExtension->BusListLock, OldIrql);
1015
1016 return Found;
1017 }
1018
1019
1020 static BOOLEAN
1021 CheckPciDevice(
1022 IN PPCI_COMMON_CONFIG PciConfig,
1023 IN PPCI_DEVICE_PRESENCE_PARAMETERS Parameters)
1024 {
1025 if ((Parameters->Flags & PCI_USE_VENDEV_IDS) && (
1026 PciConfig->VendorID != Parameters->VendorID ||
1027 PciConfig->DeviceID != Parameters->DeviceID))
1028 {
1029 return FALSE;
1030 }
1031 if ((Parameters->Flags & PCI_USE_CLASS_SUBCLASS) && (
1032 PciConfig->BaseClass != Parameters->BaseClass ||
1033 PciConfig->SubClass != Parameters->SubClass))
1034 {
1035 return FALSE;
1036 }
1037 if ((Parameters->Flags & PCI_USE_PROGIF) &&
1038 PciConfig->ProgIf != Parameters->ProgIf)
1039 {
1040 return FALSE;
1041 }
1042 if ((Parameters->Flags & PCI_USE_SUBSYSTEM_IDS) && (
1043 PciConfig->u.type0.SubVendorID != Parameters->SubVendorID ||
1044 PciConfig->u.type0.SubSystemID != Parameters->SubSystemID))
1045 {
1046 return FALSE;
1047 }
1048 if ((Parameters->Flags & PCI_USE_REVISION) &&
1049 PciConfig->RevisionID != Parameters->RevisionID)
1050 {
1051 return FALSE;
1052 }
1053 return TRUE;
1054 }
1055
1056
1057 static BOOLEAN NTAPI
1058 InterfacePciDevicePresentEx(
1059 IN PVOID Context,
1060 IN PPCI_DEVICE_PRESENCE_PARAMETERS Parameters)
1061 {
1062 PPDO_DEVICE_EXTENSION DeviceExtension;
1063 PFDO_DEVICE_EXTENSION MyFdoDeviceExtension;
1064 PFDO_DEVICE_EXTENSION FdoDeviceExtension;
1065 PPCI_DEVICE PciDevice;
1066 PLIST_ENTRY CurrentBus, CurrentEntry;
1067 KIRQL OldIrql;
1068 BOOLEAN Found = FALSE;
1069
1070 DPRINT("InterfacePciDevicePresentEx(%p %p) called\n",
1071 Context, Parameters);
1072
1073 if (!Parameters || Parameters->Size != sizeof(PCI_DEVICE_PRESENCE_PARAMETERS))
1074 return FALSE;
1075
1076 DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
1077 MyFdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceExtension->Fdo->DeviceExtension;
1078
1079 if (Parameters->Flags & PCI_USE_LOCAL_DEVICE)
1080 {
1081 return CheckPciDevice(&DeviceExtension->PciDevice->PciConfig, Parameters);
1082 }
1083
1084 KeAcquireSpinLock(&DriverExtension->BusListLock, &OldIrql);
1085 CurrentBus = DriverExtension->BusListHead.Flink;
1086 while (!Found && CurrentBus != &DriverExtension->BusListHead)
1087 {
1088 FdoDeviceExtension = CONTAINING_RECORD(CurrentBus, FDO_DEVICE_EXTENSION, ListEntry);
1089 if (!(Parameters->Flags & PCI_USE_LOCAL_BUS) || FdoDeviceExtension == MyFdoDeviceExtension)
1090 {
1091 KeAcquireSpinLockAtDpcLevel(&FdoDeviceExtension->DeviceListLock);
1092 CurrentEntry = FdoDeviceExtension->DeviceListHead.Flink;
1093 while (!Found && CurrentEntry != &FdoDeviceExtension->DeviceListHead)
1094 {
1095 PciDevice = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry);
1096
1097 if (CheckPciDevice(&PciDevice->PciConfig, Parameters))
1098 {
1099 DPRINT("Found the PCI device\n");
1100 Found = TRUE;
1101 }
1102
1103 CurrentEntry = CurrentEntry->Flink;
1104 }
1105
1106 KeReleaseSpinLockFromDpcLevel(&FdoDeviceExtension->DeviceListLock);
1107 }
1108 CurrentBus = CurrentBus->Flink;
1109 }
1110 KeReleaseSpinLock(&DriverExtension->BusListLock, OldIrql);
1111
1112 return Found;
1113 }
1114
1115
1116 static NTSTATUS
1117 PdoQueryInterface(
1118 IN PDEVICE_OBJECT DeviceObject,
1119 IN PIRP Irp,
1120 PIO_STACK_LOCATION IrpSp)
1121 {
1122 NTSTATUS Status;
1123
1124 if (RtlCompareMemory(IrpSp->Parameters.QueryInterface.InterfaceType,
1125 &GUID_BUS_INTERFACE_STANDARD, sizeof(GUID)) == sizeof(GUID))
1126 {
1127 /* BUS_INTERFACE_STANDARD */
1128 if (IrpSp->Parameters.QueryInterface.Version < 1)
1129 Status = STATUS_NOT_SUPPORTED;
1130 else if (IrpSp->Parameters.QueryInterface.Size < sizeof(BUS_INTERFACE_STANDARD))
1131 Status = STATUS_BUFFER_TOO_SMALL;
1132 else
1133 {
1134 PBUS_INTERFACE_STANDARD BusInterface;
1135 BusInterface = (PBUS_INTERFACE_STANDARD)IrpSp->Parameters.QueryInterface.Interface;
1136 BusInterface->Size = sizeof(BUS_INTERFACE_STANDARD);
1137 BusInterface->Version = 1;
1138 BusInterface->TranslateBusAddress = InterfaceBusTranslateBusAddress;
1139 BusInterface->GetDmaAdapter = InterfaceBusGetDmaAdapter;
1140 BusInterface->SetBusData = InterfaceBusSetBusData;
1141 BusInterface->GetBusData = InterfaceBusGetBusData;
1142 Status = STATUS_SUCCESS;
1143 }
1144 }
1145 else if (RtlCompareMemory(IrpSp->Parameters.QueryInterface.InterfaceType,
1146 &GUID_PCI_DEVICE_PRESENT_INTERFACE, sizeof(GUID)) == sizeof(GUID))
1147 {
1148 /* PCI_DEVICE_PRESENT_INTERFACE */
1149 if (IrpSp->Parameters.QueryInterface.Version < 1)
1150 Status = STATUS_NOT_SUPPORTED;
1151 else if (IrpSp->Parameters.QueryInterface.Size < sizeof(PCI_DEVICE_PRESENT_INTERFACE))
1152 Status = STATUS_BUFFER_TOO_SMALL;
1153 else
1154 {
1155 PPCI_DEVICE_PRESENT_INTERFACE PciDevicePresentInterface;
1156 PciDevicePresentInterface = (PPCI_DEVICE_PRESENT_INTERFACE)IrpSp->Parameters.QueryInterface.Interface;
1157 PciDevicePresentInterface->Size = sizeof(PCI_DEVICE_PRESENT_INTERFACE);
1158 PciDevicePresentInterface->Version = 1;
1159 PciDevicePresentInterface->IsDevicePresent = InterfacePciDevicePresent;
1160 PciDevicePresentInterface->IsDevicePresentEx = InterfacePciDevicePresentEx;
1161 Status = STATUS_SUCCESS;
1162 }
1163 }
1164 else
1165 {
1166 /* Not a supported interface */
1167 return STATUS_NOT_SUPPORTED;
1168 }
1169
1170 if (NT_SUCCESS(Status))
1171 {
1172 /* Add a reference for the returned interface */
1173 PINTERFACE Interface;
1174 Interface = (PINTERFACE)IrpSp->Parameters.QueryInterface.Interface;
1175 Interface->Context = DeviceObject;
1176 Interface->InterfaceReference = InterfaceReference;
1177 Interface->InterfaceDereference = InterfaceDereference;
1178 Interface->InterfaceReference(Interface->Context);
1179 }
1180
1181 return Status;
1182 }
1183
1184
1185 static NTSTATUS
1186 PdoReadConfig(
1187 IN PDEVICE_OBJECT DeviceObject,
1188 IN PIRP Irp,
1189 PIO_STACK_LOCATION IrpSp)
1190 {
1191 ULONG Size;
1192
1193 DPRINT("PdoReadConfig() called\n");
1194
1195 Size = InterfaceBusGetBusData(
1196 DeviceObject,
1197 IrpSp->Parameters.ReadWriteConfig.WhichSpace,
1198 IrpSp->Parameters.ReadWriteConfig.Buffer,
1199 IrpSp->Parameters.ReadWriteConfig.Offset,
1200 IrpSp->Parameters.ReadWriteConfig.Length);
1201
1202 if (Size != IrpSp->Parameters.ReadWriteConfig.Length)
1203 {
1204 DPRINT1("Size %lu Length %lu\n", Size, IrpSp->Parameters.ReadWriteConfig.Length);
1205 Irp->IoStatus.Information = 0;
1206 return STATUS_UNSUCCESSFUL;
1207 }
1208
1209 Irp->IoStatus.Information = Size;
1210
1211 return STATUS_SUCCESS;
1212 }
1213
1214
1215 static NTSTATUS
1216 PdoWriteConfig(
1217 IN PDEVICE_OBJECT DeviceObject,
1218 IN PIRP Irp,
1219 PIO_STACK_LOCATION IrpSp)
1220 {
1221 ULONG Size;
1222
1223 DPRINT1("PdoWriteConfig() called\n");
1224
1225 /* Get PCI configuration space */
1226 Size = InterfaceBusSetBusData(
1227 DeviceObject,
1228 IrpSp->Parameters.ReadWriteConfig.WhichSpace,
1229 IrpSp->Parameters.ReadWriteConfig.Buffer,
1230 IrpSp->Parameters.ReadWriteConfig.Offset,
1231 IrpSp->Parameters.ReadWriteConfig.Length);
1232
1233 if (Size != IrpSp->Parameters.ReadWriteConfig.Length)
1234 {
1235 DPRINT1("Size %lu Length %lu\n", Size, IrpSp->Parameters.ReadWriteConfig.Length);
1236 Irp->IoStatus.Information = 0;
1237 return STATUS_UNSUCCESSFUL;
1238 }
1239
1240 Irp->IoStatus.Information = Size;
1241
1242 return STATUS_SUCCESS;
1243 }
1244
1245
1246 static NTSTATUS
1247 PdoSetPower(
1248 IN PDEVICE_OBJECT DeviceObject,
1249 IN PIRP Irp,
1250 PIO_STACK_LOCATION IrpSp)
1251 {
1252 PPDO_DEVICE_EXTENSION DeviceExtension;
1253 NTSTATUS Status;
1254
1255 DPRINT("Called\n");
1256
1257 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1258
1259 if (IrpSp->Parameters.Power.Type == DevicePowerState) {
1260 Status = STATUS_SUCCESS;
1261 switch (IrpSp->Parameters.Power.State.SystemState) {
1262 default:
1263 Status = STATUS_UNSUCCESSFUL;
1264 }
1265 } else {
1266 Status = STATUS_UNSUCCESSFUL;
1267 }
1268
1269 return Status;
1270 }
1271
1272
1273 /*** PUBLIC ******************************************************************/
1274
1275 NTSTATUS
1276 PdoPnpControl(
1277 PDEVICE_OBJECT DeviceObject,
1278 PIRP Irp)
1279 /*
1280 * FUNCTION: Handle Plug and Play IRPs for the child device
1281 * ARGUMENTS:
1282 * DeviceObject = Pointer to physical device object of the child device
1283 * Irp = Pointer to IRP that should be handled
1284 * RETURNS:
1285 * Status
1286 */
1287 {
1288 PIO_STACK_LOCATION IrpSp;
1289 NTSTATUS Status;
1290
1291 DPRINT("Called\n");
1292
1293 Status = Irp->IoStatus.Status;
1294
1295 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1296
1297 switch (IrpSp->MinorFunction) {
1298 #if 0
1299 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
1300 break;
1301
1302 case IRP_MN_EJECT:
1303 break;
1304 #endif
1305
1306 case IRP_MN_QUERY_BUS_INFORMATION:
1307 Status = PdoQueryBusInformation(DeviceObject, Irp, IrpSp);
1308 break;
1309
1310 case IRP_MN_QUERY_CAPABILITIES:
1311 Status = PdoQueryCapabilities(DeviceObject, Irp, IrpSp);
1312 break;
1313
1314 #if 0
1315 case IRP_MN_QUERY_DEVICE_RELATIONS:
1316 /* FIXME: Possibly handle for RemovalRelations */
1317 break;
1318 #endif
1319
1320 case IRP_MN_QUERY_DEVICE_TEXT:
1321 DPRINT("IRP_MN_QUERY_DEVICE_TEXT received\n");
1322 Status = PdoQueryDeviceText(DeviceObject, Irp, IrpSp);
1323 break;
1324
1325 case IRP_MN_QUERY_ID:
1326 DPRINT("IRP_MN_QUERY_ID received\n");
1327 Status = PdoQueryId(DeviceObject, Irp, IrpSp);
1328 break;
1329
1330 #if 0
1331 case IRP_MN_QUERY_PNP_DEVICE_STATE:
1332 break;
1333 #endif
1334
1335 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
1336 DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS received\n");
1337 Status = PdoQueryResourceRequirements(DeviceObject, Irp, IrpSp);
1338 break;
1339
1340 case IRP_MN_QUERY_RESOURCES:
1341 DPRINT("IRP_MN_QUERY_RESOURCES received\n");
1342 Status = PdoQueryResources(DeviceObject, Irp, IrpSp);
1343 break;
1344
1345 #if 0
1346 case IRP_MN_SET_LOCK:
1347 break;
1348 #endif
1349
1350 case IRP_MN_START_DEVICE:
1351 case IRP_MN_QUERY_STOP_DEVICE:
1352 case IRP_MN_CANCEL_STOP_DEVICE:
1353 case IRP_MN_STOP_DEVICE:
1354 case IRP_MN_QUERY_REMOVE_DEVICE:
1355 case IRP_MN_CANCEL_REMOVE_DEVICE:
1356 case IRP_MN_REMOVE_DEVICE:
1357 case IRP_MN_SURPRISE_REMOVAL:
1358 Status = STATUS_SUCCESS;
1359 break;
1360
1361 case IRP_MN_QUERY_INTERFACE:
1362 DPRINT("IRP_MN_QUERY_INTERFACE received\n");
1363 Status = PdoQueryInterface(DeviceObject, Irp, IrpSp);
1364 break;
1365
1366 case IRP_MN_READ_CONFIG:
1367 DPRINT("IRP_MN_READ_CONFIG received\n");
1368 Status = PdoReadConfig(DeviceObject, Irp, IrpSp);
1369 break;
1370
1371 case IRP_MN_WRITE_CONFIG:
1372 DPRINT("IRP_MN_WRITE_CONFIG received\n");
1373 Status = PdoWriteConfig(DeviceObject, Irp, IrpSp);
1374 break;
1375
1376 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
1377 DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS received\n");
1378 /* Nothing to do */
1379 Irp->IoStatus.Status = Status;
1380 break;
1381
1382 default:
1383 DPRINT1("Unknown IOCTL 0x%lx\n", IrpSp->MinorFunction);
1384 break;
1385 }
1386
1387 if (Status != STATUS_PENDING) {
1388 Irp->IoStatus.Status = Status;
1389 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1390 }
1391
1392 DPRINT("Leaving. Status 0x%X\n", Status);
1393
1394 return Status;
1395 }
1396
1397 NTSTATUS
1398 PdoPowerControl(
1399 PDEVICE_OBJECT DeviceObject,
1400 PIRP Irp)
1401 /*
1402 * FUNCTION: Handle power management IRPs for the child device
1403 * ARGUMENTS:
1404 * DeviceObject = Pointer to physical device object of the child device
1405 * Irp = Pointer to IRP that should be handled
1406 * RETURNS:
1407 * Status
1408 */
1409 {
1410 PIO_STACK_LOCATION IrpSp;
1411 NTSTATUS Status;
1412
1413 DPRINT("Called\n");
1414
1415 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1416
1417 switch (IrpSp->MinorFunction) {
1418 case IRP_MN_SET_POWER:
1419 Status = PdoSetPower(DeviceObject, Irp, IrpSp);
1420 break;
1421
1422 default:
1423 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
1424 Status = STATUS_NOT_IMPLEMENTED;
1425 break;
1426 }
1427
1428 if (Status != STATUS_PENDING) {
1429 Irp->IoStatus.Status = Status;
1430 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1431 }
1432
1433 DPRINT("Leaving. Status 0x%X\n", Status);
1434
1435 return Status;
1436 }
1437
1438 /* EOF */