- Return STATUS_SUCCESS for PCI bus PDO PnP IRPs so that function drivers can process...
[reactos.git] / reactos / drivers / bus / pci / pdo.c
1 /* $Id: pdo.c,v 1.11 2004/10/24 09:14:03 navaraf Exp $
2 *
3 * PROJECT: ReactOS PCI bus driver
4 * FILE: pdo.c
5 * PURPOSE: Child device object dispatch routines
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * UPDATE HISTORY:
8 * 10-09-2001 CSH Created
9 */
10
11 #include <ddk/ntddk.h>
12
13 #include "pcidef.h"
14 #include "pci.h"
15
16 #define NDEBUG
17 #include <debug.h>
18
19 DEFINE_GUID(GUID_BUS_TYPE_PCI, 0xc8ebdfb0L, 0xb510, 0x11d0, 0x80, 0xe5, 0x00, 0xa0, 0xc9, 0x25, 0x42, 0xe3);
20
21 /*** PRIVATE *****************************************************************/
22
23 static NTSTATUS
24 PdoQueryDeviceText(
25 IN PDEVICE_OBJECT DeviceObject,
26 IN PIRP Irp,
27 PIO_STACK_LOCATION IrpSp)
28 {
29 PPDO_DEVICE_EXTENSION DeviceExtension;
30 NTSTATUS Status;
31
32 DPRINT("Called\n");
33
34 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
35
36 Status = STATUS_SUCCESS;
37
38 switch (IrpSp->Parameters.QueryDeviceText.DeviceTextType)
39 {
40 case DeviceTextDescription:
41 DPRINT("DeviceTextDescription\n");
42 Irp->IoStatus.Information = (ULONG_PTR)DeviceExtension->DeviceDescription.Buffer;
43 break;
44
45 case DeviceTextLocationInformation:
46 DPRINT("DeviceTextLocationInformation\n");
47 Irp->IoStatus.Information = (ULONG_PTR)DeviceExtension->DeviceLocation.Buffer;
48 break;
49
50 default:
51 Irp->IoStatus.Information = 0;
52 Status = STATUS_INVALID_PARAMETER;
53 }
54
55 return Status;
56 }
57
58
59 static NTSTATUS
60 PdoQueryId(
61 IN PDEVICE_OBJECT DeviceObject,
62 IN PIRP Irp,
63 PIO_STACK_LOCATION IrpSp)
64 {
65 PPDO_DEVICE_EXTENSION DeviceExtension;
66 UNICODE_STRING String;
67 NTSTATUS Status;
68
69 DPRINT("Called\n");
70
71 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
72
73 // Irp->IoStatus.Information = 0;
74
75 Status = STATUS_SUCCESS;
76
77 RtlInitUnicodeString(&String, NULL);
78
79 switch (IrpSp->Parameters.QueryId.IdType) {
80 case BusQueryDeviceID:
81 Status = PciDuplicateUnicodeString(
82 &String,
83 &DeviceExtension->DeviceID,
84 PagedPool);
85
86 DPRINT("DeviceID: %S\n", String.Buffer);
87
88 Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
89 break;
90
91 case BusQueryHardwareIDs:
92 Status = PciDuplicateUnicodeString(
93 &String,
94 &DeviceExtension->HardwareIDs,
95 PagedPool);
96
97 Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
98 break;
99
100 case BusQueryCompatibleIDs:
101 Status = PciDuplicateUnicodeString(
102 &String,
103 &DeviceExtension->CompatibleIDs,
104 PagedPool);
105
106 Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
107 break;
108
109 case BusQueryInstanceID:
110 Status = PciDuplicateUnicodeString(
111 &String,
112 &DeviceExtension->InstanceID,
113 PagedPool);
114
115 DPRINT("InstanceID: %S\n", String.Buffer);
116
117 Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
118 break;
119
120 case BusQueryDeviceSerialNumber:
121 default:
122 Status = STATUS_NOT_IMPLEMENTED;
123 }
124
125 return Status;
126 }
127
128
129 static NTSTATUS
130 PdoQueryBusInformation(
131 IN PDEVICE_OBJECT DeviceObject,
132 IN PIRP Irp,
133 PIO_STACK_LOCATION IrpSp)
134 {
135 PPDO_DEVICE_EXTENSION DeviceExtension;
136 PFDO_DEVICE_EXTENSION FdoDeviceExtension;
137 PPNP_BUS_INFORMATION BusInformation;
138
139 DPRINT("Called\n");
140
141 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
142 FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceExtension->Fdo->DeviceExtension;
143 BusInformation = ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
144 Irp->IoStatus.Information = (ULONG_PTR)BusInformation;
145 if (BusInformation != NULL)
146 {
147 BusInformation->BusTypeGuid = GUID_BUS_TYPE_PCI;
148 BusInformation->LegacyBusType = PCIBus;
149 BusInformation->BusNumber = DeviceExtension->BusNumber;
150
151 return STATUS_SUCCESS;
152 }
153
154 return STATUS_INSUFFICIENT_RESOURCES;
155 }
156
157
158 static NTSTATUS
159 PdoQueryCapabilities(
160 IN PDEVICE_OBJECT DeviceObject,
161 IN PIRP Irp,
162 PIO_STACK_LOCATION IrpSp)
163 {
164 PPDO_DEVICE_EXTENSION DeviceExtension;
165 PDEVICE_CAPABILITIES DeviceCapabilities;
166
167 DPRINT("Called\n");
168
169 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
170 DeviceCapabilities = IrpSp->Parameters.DeviceCapabilities.Capabilities;
171
172 if (DeviceCapabilities->Version != 1)
173 return STATUS_UNSUCCESSFUL;
174
175 DeviceCapabilities->UniqueID = FALSE;
176 DeviceCapabilities->Address = DeviceExtension->SlotNumber.u.AsULONG;
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->BusNumber,
199 DeviceExtension->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->BusNumber,
217 DeviceExtension->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->BusNumber,
230 DeviceExtension->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->BusNumber,
243 DeviceExtension->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->BusNumber,
329 DeviceExtension->SlotNumber.u.AsULONG,
330 &PciConfig,
331 sizeof(PCI_COMMON_CONFIG));
332 DPRINT("Size %lu\n", Size);
333 if (Size < sizeof(PCI_COMMON_CONFIG))
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 ResCount += 2;
355 }
356
357 /* FIXME: Check ROM address */
358
359 if (PciConfig.u.type0.InterruptPin != 0)
360 ResCount++;
361 }
362 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
363 {
364 for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
365 {
366 if (!PdoGetRangeLength(DeviceExtension,
367 0x10 + i * 4,
368 &Base,
369 &Length,
370 &Flags))
371 break;
372
373 ResCount += 2;
374 }
375 }
376 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_CARDBUS_BRIDGE_TYPE)
377 {
378 }
379 else
380 {
381 DPRINT1("Unsupported header type %u\n", PCI_CONFIGURATION_TYPE(&PciConfig));
382 }
383
384 if (ResCount == 0)
385 {
386 Irp->IoStatus.Information = 0;
387 return STATUS_SUCCESS;
388 }
389
390 /* Calculate the resource list size */
391 ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
392 if (ResCount > 1)
393 {
394 ListSize += ((ResCount - 1) * sizeof(IO_RESOURCE_DESCRIPTOR));
395 }
396
397 DPRINT("ListSize %lu (0x%lx)\n", ListSize, ListSize);
398
399 /* Allocate the resource requirements list */
400 ResourceList = ExAllocatePool(PagedPool,
401 ListSize);
402 if (ResourceList == NULL)
403 {
404 Irp->IoStatus.Information = 0;
405 return STATUS_INSUFFICIENT_RESOURCES;
406 }
407
408 ResourceList->ListSize = ListSize;
409 ResourceList->InterfaceType = PCIBus;
410 ResourceList->AlternativeLists = 1;
411
412 ResourceList->List[0].Version = 1;
413 ResourceList->List[0].Revision = 1;
414 ResourceList->List[0].Count = ResCount;
415
416 Descriptor = &ResourceList->List[0].Descriptors[0];
417 if (PCI_CONFIGURATION_TYPE(&PciConfig) == 0)
418 {
419 for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
420 {
421 if (!PdoGetRangeLength(DeviceExtension,
422 0x10 + i * 4,
423 &Base,
424 &Length,
425 &Flags))
426 {
427 DPRINT1("PdoGetRangeLength() failed\n");
428 break;
429 }
430
431 if (Length == 0)
432 {
433 DPRINT("Unused address register\n");
434 break;
435 }
436
437 /* Set preferred descriptor */
438 Descriptor->Option = IO_RESOURCE_PREFERRED;
439 if (Flags & PCI_ADDRESS_IO_SPACE)
440 {
441 Descriptor->Type = CmResourceTypePort;
442 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
443 Descriptor->Flags = CM_RESOURCE_PORT_IO |
444 CM_RESOURCE_PORT_16_BIT_DECODE |
445 CM_RESOURCE_PORT_POSITIVE_DECODE;
446
447 Descriptor->u.Port.Length = Length;
448 Descriptor->u.Port.Alignment = 1;
449 Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)Base;
450 Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)(Base + Length - 1);
451 }
452 else
453 {
454 Descriptor->Type = CmResourceTypeMemory;
455 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
456 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
457
458 Descriptor->u.Memory.Length = Length;
459 Descriptor->u.Memory.Alignment = 1;
460 Descriptor->u.Memory.MinimumAddress.QuadPart = (ULONGLONG)Base;
461 Descriptor->u.Memory.MaximumAddress.QuadPart = (ULONGLONG)(Base + Length - 1);
462 }
463 Descriptor++;
464
465 /* Set alternative descriptor */
466 Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
467 if (Flags & PCI_ADDRESS_IO_SPACE)
468 {
469 Descriptor->Type = CmResourceTypePort;
470 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
471 Descriptor->Flags = CM_RESOURCE_PORT_IO |
472 CM_RESOURCE_PORT_16_BIT_DECODE |
473 CM_RESOURCE_PORT_POSITIVE_DECODE;
474
475 Descriptor->u.Port.Length = Length;
476 Descriptor->u.Port.Alignment = Length;
477 Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)0;
478 Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)0x00000000FFFFFFFF;
479 }
480 else
481 {
482 Descriptor->Type = CmResourceTypeMemory;
483 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
484 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
485
486 Descriptor->u.Memory.Length = Length;
487 Descriptor->u.Memory.Alignment = Length;
488 Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)0;
489 Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)0x00000000FFFFFFFF;
490 }
491 Descriptor++;
492 }
493
494 /* FIXME: Check ROM address */
495
496 if (PciConfig.u.type0.InterruptPin != 0)
497 {
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) == 1)
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 break;
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 }
583 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == 2)
584 {
585 /* FIXME: Add Cardbus bridge resources */
586 }
587
588 Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
589
590 return STATUS_SUCCESS;
591 }
592
593
594 static NTSTATUS
595 PdoQueryResources(
596 IN PDEVICE_OBJECT DeviceObject,
597 IN PIRP Irp,
598 PIO_STACK_LOCATION IrpSp)
599 {
600 PPDO_DEVICE_EXTENSION DeviceExtension;
601 PCI_COMMON_CONFIG PciConfig;
602 PCM_RESOURCE_LIST ResourceList;
603 PCM_PARTIAL_RESOURCE_LIST PartialList;
604 PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
605 ULONG Size;
606 ULONG ResCount = 0;
607 ULONG ListSize;
608 ULONG i;
609 ULONG Base;
610 ULONG Length;
611 ULONG Flags;
612
613 DPRINT("PdoQueryResources() called\n");
614
615 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
616
617 /* Get PCI configuration space */
618 Size= HalGetBusData(PCIConfiguration,
619 DeviceExtension->BusNumber,
620 DeviceExtension->SlotNumber.u.AsULONG,
621 &PciConfig,
622 sizeof(PCI_COMMON_CONFIG));
623 DPRINT("Size %lu\n", Size);
624 if (Size < sizeof(PCI_COMMON_CONFIG))
625 {
626 Irp->IoStatus.Information = 0;
627 return STATUS_UNSUCCESSFUL;
628 }
629
630 DPRINT("Command register: 0x%04hx\n", PciConfig.Command);
631
632 /* Count required resource descriptors */
633 ResCount = 0;
634 if (PCI_CONFIGURATION_TYPE(&PciConfig) == 0)
635 {
636 for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
637 {
638 if (!PdoGetRangeLength(DeviceExtension,
639 0x10 + i * 4,
640 &Base,
641 &Length,
642 &Flags))
643 break;
644
645 ResCount++;
646 }
647
648 if ((PciConfig.u.type0.InterruptPin != 0) &&
649 (PciConfig.u.type0.InterruptLine != 0xFF))
650 ResCount++;
651 }
652 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == 1)
653 {
654 for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
655 {
656 if (!PdoGetRangeLength(DeviceExtension,
657 0x10 + i * 4,
658 &Base,
659 &Length,
660 &Flags))
661 break;
662
663 ResCount++;
664 }
665 }
666 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == 2)
667 {
668
669 }
670 else
671 {
672 DPRINT1("Unsupported header type %u\n", PCI_CONFIGURATION_TYPE(&PciConfig));
673 }
674
675 if (ResCount == 0)
676 {
677 Irp->IoStatus.Information = 0;
678 return STATUS_SUCCESS;
679 }
680
681 /* Calculate the resource list size */
682 ListSize = sizeof(CM_RESOURCE_LIST);
683 if (ResCount > 1)
684 {
685 ListSize += ((ResCount - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
686 }
687
688 /* Allocate the resource list */
689 ResourceList = ExAllocatePool(PagedPool,
690 ListSize);
691 if (ResourceList == NULL)
692 return STATUS_INSUFFICIENT_RESOURCES;
693
694 ResourceList->Count = 1;
695 ResourceList->List[0].InterfaceType = PCIConfiguration;
696 ResourceList->List[0].BusNumber = DeviceExtension->BusNumber;
697
698 PartialList = &ResourceList->List[0].PartialResourceList;
699 PartialList->Version = 0;
700 PartialList->Revision = 0;
701 PartialList->Count = ResCount;
702
703 Descriptor = &PartialList->PartialDescriptors[0];
704 if (PCI_CONFIGURATION_TYPE(&PciConfig) == 0)
705 {
706 for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
707 {
708 if (!PdoGetRangeLength(DeviceExtension,
709 0x10 + i * 4,
710 &Base,
711 &Length,
712 &Flags))
713 {
714 DPRINT1("PdoGetRangeLength() failed\n");
715 break;
716 }
717
718 if (Length == 0)
719 {
720 DPRINT("Unused address register\n");
721 break;
722 }
723
724 if (Flags & PCI_ADDRESS_IO_SPACE)
725 {
726 Descriptor->Type = CmResourceTypePort;
727 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
728 Descriptor->Flags = CM_RESOURCE_PORT_IO;
729 Descriptor->u.Port.Start.QuadPart =
730 (ULONGLONG)Base;
731 Descriptor->u.Port.Length = Length;
732 }
733 else
734 {
735 Descriptor->Type = CmResourceTypeMemory;
736 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
737 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
738 Descriptor->u.Memory.Start.QuadPart =
739 (ULONGLONG)Base;
740 Descriptor->u.Memory.Length = Length;
741 }
742
743 Descriptor++;
744 }
745
746 /* Add interrupt resource */
747 if ((PciConfig.u.type0.InterruptPin != 0) &&
748 (PciConfig.u.type0.InterruptLine != 0xFF))
749 {
750 Descriptor->Type = CmResourceTypeInterrupt;
751 Descriptor->ShareDisposition = CmResourceShareShared;
752 Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
753 Descriptor->u.Interrupt.Level = PciConfig.u.type0.InterruptLine;
754 Descriptor->u.Interrupt.Vector = PciConfig.u.type0.InterruptLine;
755 Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
756 }
757 }
758 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == 1)
759 {
760 for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
761 {
762 if (!PdoGetRangeLength(DeviceExtension,
763 0x10 + i * 4,
764 &Base,
765 &Length,
766 &Flags))
767 {
768 DPRINT1("PdoGetRangeLength() failed\n");
769 break;
770 }
771
772 if (Length == 0)
773 {
774 DPRINT("Unused address register\n");
775 break;
776 }
777
778 if (Flags & PCI_ADDRESS_IO_SPACE)
779 {
780 Descriptor->Type = CmResourceTypePort;
781 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
782 Descriptor->Flags = CM_RESOURCE_PORT_IO;
783 Descriptor->u.Port.Start.QuadPart =
784 (ULONGLONG)Base;
785 Descriptor->u.Port.Length = Length;
786 }
787 else
788 {
789 Descriptor->Type = CmResourceTypeMemory;
790 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
791 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
792 Descriptor->u.Memory.Start.QuadPart =
793 (ULONGLONG)Base;
794 Descriptor->u.Memory.Length = Length;
795 }
796
797 Descriptor++;
798 }
799 }
800 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == 2)
801 {
802 /* FIXME: Cardbus */
803 }
804
805 Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
806
807 return STATUS_SUCCESS;
808 }
809
810
811 static NTSTATUS
812 PdoReadConfig(
813 IN PDEVICE_OBJECT DeviceObject,
814 IN PIRP Irp,
815 PIO_STACK_LOCATION IrpSp)
816 {
817 PPDO_DEVICE_EXTENSION DeviceExtension;
818 ULONG Size;
819
820 DPRINT1("PdoReadConfig() called\n");
821
822 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
823
824 #if 0
825 if (IrpSp->Parameters.ReadWriteConfig.WhichSpace != PCI_WHICHSPACE_CONFIG)
826 return STATUS_NOT_SUPPORTED;
827 #endif
828
829 /* Get PCI configuration space */
830 Size= HalGetBusDataByOffset(PCIConfiguration,
831 DeviceExtension->BusNumber,
832 DeviceExtension->SlotNumber.u.AsULONG,
833 IrpSp->Parameters.ReadWriteConfig.Buffer,
834 IrpSp->Parameters.ReadWriteConfig.Offset,
835 IrpSp->Parameters.ReadWriteConfig.Length);
836 if (Size != IrpSp->Parameters.ReadWriteConfig.Length)
837 {
838 DPRINT1("Size %lu Length %lu\n", Size, IrpSp->Parameters.ReadWriteConfig.Length);
839 Irp->IoStatus.Information = 0;
840 return STATUS_UNSUCCESSFUL;
841 }
842
843 Irp->IoStatus.Information = Size;
844
845 return STATUS_SUCCESS;
846 }
847
848
849 static NTSTATUS
850 PdoWriteConfig(
851 IN PDEVICE_OBJECT DeviceObject,
852 IN PIRP Irp,
853 PIO_STACK_LOCATION IrpSp)
854 {
855 PPDO_DEVICE_EXTENSION DeviceExtension;
856 ULONG Size;
857
858 DPRINT1("PdoWriteConfig() called\n");
859
860 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
861
862 #if 0
863 if (IrpSp->Parameters.ReadWriteConfig.WhichSpace != PCI_WHICHSPACE_CONFIG)
864 return STATUS_NOT_SUPPORTED;
865 #endif
866
867 /* Get PCI configuration space */
868 Size= HalSetBusDataByOffset(PCIConfiguration,
869 DeviceExtension->BusNumber,
870 DeviceExtension->SlotNumber.u.AsULONG,
871 IrpSp->Parameters.ReadWriteConfig.Buffer,
872 IrpSp->Parameters.ReadWriteConfig.Offset,
873 IrpSp->Parameters.ReadWriteConfig.Length);
874 if (Size != IrpSp->Parameters.ReadWriteConfig.Length)
875 {
876 DPRINT1("Size %lu Length %lu\n", Size, IrpSp->Parameters.ReadWriteConfig.Length);
877 Irp->IoStatus.Information = 0;
878 return STATUS_UNSUCCESSFUL;
879 }
880
881 Irp->IoStatus.Information = Size;
882
883 return STATUS_SUCCESS;
884 }
885
886
887 static NTSTATUS
888 PdoSetPower(
889 IN PDEVICE_OBJECT DeviceObject,
890 IN PIRP Irp,
891 PIO_STACK_LOCATION IrpSp)
892 {
893 PPDO_DEVICE_EXTENSION DeviceExtension;
894 NTSTATUS Status;
895
896 DPRINT("Called\n");
897
898 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
899
900 if (IrpSp->Parameters.Power.Type == DevicePowerState) {
901 Status = STATUS_SUCCESS;
902 switch (IrpSp->Parameters.Power.State.SystemState) {
903 default:
904 Status = STATUS_UNSUCCESSFUL;
905 }
906 } else {
907 Status = STATUS_UNSUCCESSFUL;
908 }
909
910 return Status;
911 }
912
913
914 /*** PUBLIC ******************************************************************/
915
916 NTSTATUS
917 PdoPnpControl(
918 PDEVICE_OBJECT DeviceObject,
919 PIRP Irp)
920 /*
921 * FUNCTION: Handle Plug and Play IRPs for the child device
922 * ARGUMENTS:
923 * DeviceObject = Pointer to physical device object of the child device
924 * Irp = Pointer to IRP that should be handled
925 * RETURNS:
926 * Status
927 */
928 {
929 PIO_STACK_LOCATION IrpSp;
930 NTSTATUS Status;
931
932 DPRINT("Called\n");
933
934 Status = Irp->IoStatus.Status;
935
936 IrpSp = IoGetCurrentIrpStackLocation(Irp);
937
938 switch (IrpSp->MinorFunction) {
939 #if 0
940 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
941 break;
942
943 case IRP_MN_EJECT:
944 break;
945 #endif
946
947 case IRP_MN_QUERY_BUS_INFORMATION:
948 Status = PdoQueryBusInformation(DeviceObject, Irp, IrpSp);
949 break;
950
951 case IRP_MN_QUERY_CAPABILITIES:
952 Status = PdoQueryCapabilities(DeviceObject, Irp, IrpSp);
953 break;
954
955 #if 0
956 case IRP_MN_QUERY_DEVICE_RELATIONS:
957 /* FIXME: Possibly handle for RemovalRelations */
958 break;
959 #endif
960
961 case IRP_MN_QUERY_DEVICE_TEXT:
962 DPRINT("IRP_MN_QUERY_DEVICE_TEXT received\n");
963 Status = PdoQueryDeviceText(DeviceObject, Irp, IrpSp);
964 break;
965
966 case IRP_MN_QUERY_ID:
967 DPRINT("IRP_MN_QUERY_ID received\n");
968 Status = PdoQueryId(DeviceObject, Irp, IrpSp);
969 break;
970
971 #if 0
972 case IRP_MN_QUERY_PNP_DEVICE_STATE:
973 break;
974 #endif
975
976 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
977 DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS received\n");
978 Status = PdoQueryResourceRequirements(DeviceObject, Irp, IrpSp);
979 break;
980
981 case IRP_MN_QUERY_RESOURCES:
982 DPRINT("IRP_MN_QUERY_RESOURCES received\n");
983 Status = PdoQueryResources(DeviceObject, Irp, IrpSp);
984 break;
985
986 #if 0
987 case IRP_MN_SET_LOCK:
988 break;
989 #endif
990
991 case IRP_MN_START_DEVICE:
992 case IRP_MN_QUERY_STOP_DEVICE:
993 case IRP_MN_CANCEL_STOP_DEVICE:
994 case IRP_MN_STOP_DEVICE:
995 case IRP_MN_QUERY_REMOVE_DEVICE:
996 case IRP_MN_CANCEL_REMOVE_DEVICE:
997 case IRP_MN_REMOVE_DEVICE:
998 case IRP_MN_SURPRISE_REMOVAL:
999 Status = STATUS_SUCCESS;
1000 break;
1001
1002 case IRP_MN_READ_CONFIG:
1003 DPRINT1("IRP_MN_READ_CONFIG received\n");
1004 Status = PdoReadConfig(DeviceObject, Irp, IrpSp);
1005 break;
1006
1007 case IRP_MN_WRITE_CONFIG:
1008 DPRINT1("IRP_MN_WRITE_CONFIG received\n");
1009 Status = PdoWriteConfig(DeviceObject, Irp, IrpSp);
1010 break;
1011
1012 default:
1013 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
1014 break;
1015 }
1016
1017 if (Status != STATUS_PENDING) {
1018 Irp->IoStatus.Status = Status;
1019 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1020 }
1021
1022 DPRINT("Leaving. Status 0x%X\n", Status);
1023
1024 return Status;
1025 }
1026
1027 NTSTATUS
1028 PdoPowerControl(
1029 PDEVICE_OBJECT DeviceObject,
1030 PIRP Irp)
1031 /*
1032 * FUNCTION: Handle power management IRPs for the child device
1033 * ARGUMENTS:
1034 * DeviceObject = Pointer to physical device object of the child device
1035 * Irp = Pointer to IRP that should be handled
1036 * RETURNS:
1037 * Status
1038 */
1039 {
1040 PIO_STACK_LOCATION IrpSp;
1041 NTSTATUS Status;
1042
1043 DPRINT("Called\n");
1044
1045 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1046
1047 switch (IrpSp->MinorFunction) {
1048 case IRP_MN_SET_POWER:
1049 Status = PdoSetPower(DeviceObject, Irp, IrpSp);
1050 break;
1051
1052 default:
1053 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
1054 Status = STATUS_NOT_IMPLEMENTED;
1055 break;
1056 }
1057
1058 if (Status != STATUS_PENDING) {
1059 Irp->IoStatus.Status = Status;
1060 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1061 }
1062
1063 DPRINT("Leaving. Status 0x%X\n", Status);
1064
1065 return Status;
1066 }
1067
1068 /* EOF */