Define interrupt resource as required
[reactos.git] / reactos / drivers / bus / pci / pdo.c
1 /* $Id$
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 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 }
378 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_CARDBUS_BRIDGE_TYPE)
379 {
380 }
381 else
382 {
383 DPRINT1("Unsupported header type %u\n", PCI_CONFIGURATION_TYPE(&PciConfig));
384 }
385
386 if (ResCount == 0)
387 {
388 Irp->IoStatus.Information = 0;
389 return STATUS_SUCCESS;
390 }
391
392 /* Calculate the resource list size */
393 ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
394 if (ResCount > 1)
395 {
396 ListSize += ((ResCount - 1) * sizeof(IO_RESOURCE_DESCRIPTOR));
397 }
398
399 DPRINT("ListSize %lu (0x%lx)\n", ListSize, ListSize);
400
401 /* Allocate the resource requirements list */
402 ResourceList = ExAllocatePool(PagedPool,
403 ListSize);
404 if (ResourceList == NULL)
405 {
406 Irp->IoStatus.Information = 0;
407 return STATUS_INSUFFICIENT_RESOURCES;
408 }
409
410 ResourceList->ListSize = ListSize;
411 ResourceList->InterfaceType = PCIBus;
412 ResourceList->AlternativeLists = 1;
413
414 ResourceList->List[0].Version = 1;
415 ResourceList->List[0].Revision = 1;
416 ResourceList->List[0].Count = ResCount;
417
418 Descriptor = &ResourceList->List[0].Descriptors[0];
419 if (PCI_CONFIGURATION_TYPE(&PciConfig) == 0)
420 {
421 for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
422 {
423 if (!PdoGetRangeLength(DeviceExtension,
424 0x10 + i * 4,
425 &Base,
426 &Length,
427 &Flags))
428 {
429 DPRINT1("PdoGetRangeLength() failed\n");
430 break;
431 }
432
433 if (Length == 0)
434 {
435 DPRINT("Unused address register\n");
436 continue;
437 }
438
439 /* Set preferred descriptor */
440 Descriptor->Option = IO_RESOURCE_PREFERRED;
441 if (Flags & PCI_ADDRESS_IO_SPACE)
442 {
443 Descriptor->Type = CmResourceTypePort;
444 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
445 Descriptor->Flags = CM_RESOURCE_PORT_IO |
446 CM_RESOURCE_PORT_16_BIT_DECODE |
447 CM_RESOURCE_PORT_POSITIVE_DECODE;
448
449 Descriptor->u.Port.Length = Length;
450 Descriptor->u.Port.Alignment = 1;
451 Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)Base;
452 Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)(Base + Length - 1);
453 }
454 else
455 {
456 Descriptor->Type = CmResourceTypeMemory;
457 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
458 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
459
460 Descriptor->u.Memory.Length = Length;
461 Descriptor->u.Memory.Alignment = 1;
462 Descriptor->u.Memory.MinimumAddress.QuadPart = (ULONGLONG)Base;
463 Descriptor->u.Memory.MaximumAddress.QuadPart = (ULONGLONG)(Base + Length - 1);
464 }
465 Descriptor++;
466
467 /* Set alternative descriptor */
468 Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
469 if (Flags & PCI_ADDRESS_IO_SPACE)
470 {
471 Descriptor->Type = CmResourceTypePort;
472 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
473 Descriptor->Flags = CM_RESOURCE_PORT_IO |
474 CM_RESOURCE_PORT_16_BIT_DECODE |
475 CM_RESOURCE_PORT_POSITIVE_DECODE;
476
477 Descriptor->u.Port.Length = Length;
478 Descriptor->u.Port.Alignment = Length;
479 Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)0;
480 Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)0x00000000FFFFFFFF;
481 }
482 else
483 {
484 Descriptor->Type = CmResourceTypeMemory;
485 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
486 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
487
488 Descriptor->u.Memory.Length = Length;
489 Descriptor->u.Memory.Alignment = Length;
490 Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)0;
491 Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)0x00000000FFFFFFFF;
492 }
493 Descriptor++;
494 }
495
496 /* FIXME: Check ROM address */
497
498 if (PciConfig.u.type0.InterruptPin != 0)
499 {
500 Descriptor->Option = 0; /* Required */
501 Descriptor->Type = CmResourceTypeInterrupt;
502 Descriptor->ShareDisposition = CmResourceShareShared;
503 Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
504
505 Descriptor->u.Interrupt.MinimumVector = 0;
506 Descriptor->u.Interrupt.MaximumVector = 0xFF;
507 }
508 }
509 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == 1)
510 {
511 for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
512 {
513 if (!PdoGetRangeLength(DeviceExtension,
514 0x10 + i * 4,
515 &Base,
516 &Length,
517 &Flags))
518 {
519 DPRINT1("PdoGetRangeLength() failed\n");
520 break;
521 }
522
523 if (Length == 0)
524 {
525 DPRINT("Unused address register\n");
526 continue;
527 }
528
529 /* Set preferred descriptor */
530 Descriptor->Option = IO_RESOURCE_PREFERRED;
531 if (Flags & PCI_ADDRESS_IO_SPACE)
532 {
533 Descriptor->Type = CmResourceTypePort;
534 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
535 Descriptor->Flags = CM_RESOURCE_PORT_IO |
536 CM_RESOURCE_PORT_16_BIT_DECODE |
537 CM_RESOURCE_PORT_POSITIVE_DECODE;
538
539 Descriptor->u.Port.Length = Length;
540 Descriptor->u.Port.Alignment = 1;
541 Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)Base;
542 Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)(Base + Length - 1);
543 }
544 else
545 {
546 Descriptor->Type = CmResourceTypeMemory;
547 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
548 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
549
550 Descriptor->u.Memory.Length = Length;
551 Descriptor->u.Memory.Alignment = 1;
552 Descriptor->u.Memory.MinimumAddress.QuadPart = (ULONGLONG)Base;
553 Descriptor->u.Memory.MaximumAddress.QuadPart = (ULONGLONG)(Base + Length - 1);
554 }
555 Descriptor++;
556
557 /* Set alternative descriptor */
558 Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
559 if (Flags & PCI_ADDRESS_IO_SPACE)
560 {
561 Descriptor->Type = CmResourceTypePort;
562 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
563 Descriptor->Flags = CM_RESOURCE_PORT_IO |
564 CM_RESOURCE_PORT_16_BIT_DECODE |
565 CM_RESOURCE_PORT_POSITIVE_DECODE;
566
567 Descriptor->u.Port.Length = Length;
568 Descriptor->u.Port.Alignment = Length;
569 Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)0;
570 Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)0x00000000FFFFFFFF;
571 }
572 else
573 {
574 Descriptor->Type = CmResourceTypeMemory;
575 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
576 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
577
578 Descriptor->u.Memory.Length = Length;
579 Descriptor->u.Memory.Alignment = Length;
580 Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)0;
581 Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)0x00000000FFFFFFFF;
582 }
583 Descriptor++;
584 }
585 }
586 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == 2)
587 {
588 /* FIXME: Add Cardbus bridge resources */
589 }
590
591 Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
592
593 return STATUS_SUCCESS;
594 }
595
596
597 static NTSTATUS
598 PdoQueryResources(
599 IN PDEVICE_OBJECT DeviceObject,
600 IN PIRP Irp,
601 PIO_STACK_LOCATION IrpSp)
602 {
603 PPDO_DEVICE_EXTENSION DeviceExtension;
604 PCI_COMMON_CONFIG PciConfig;
605 PCM_RESOURCE_LIST ResourceList;
606 PCM_PARTIAL_RESOURCE_LIST PartialList;
607 PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
608 ULONG Size;
609 ULONG ResCount = 0;
610 ULONG ListSize;
611 ULONG i;
612 ULONG Base;
613 ULONG Length;
614 ULONG Flags;
615
616 DPRINT("PdoQueryResources() called\n");
617
618 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
619
620 /* Get PCI configuration space */
621 Size= HalGetBusData(PCIConfiguration,
622 DeviceExtension->BusNumber,
623 DeviceExtension->SlotNumber.u.AsULONG,
624 &PciConfig,
625 sizeof(PCI_COMMON_CONFIG));
626 DPRINT("Size %lu\n", Size);
627 if (Size < sizeof(PCI_COMMON_CONFIG))
628 {
629 Irp->IoStatus.Information = 0;
630 return STATUS_UNSUCCESSFUL;
631 }
632
633 DPRINT("Command register: 0x%04hx\n", PciConfig.Command);
634
635 /* Count required resource descriptors */
636 ResCount = 0;
637 if (PCI_CONFIGURATION_TYPE(&PciConfig) == 0)
638 {
639 for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
640 {
641 if (!PdoGetRangeLength(DeviceExtension,
642 0x10 + i * 4,
643 &Base,
644 &Length,
645 &Flags))
646 break;
647
648 if (Length)
649 ResCount++;
650 }
651
652 if ((PciConfig.u.type0.InterruptPin != 0) &&
653 (PciConfig.u.type0.InterruptLine != 0xFF))
654 ResCount++;
655 }
656 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == 1)
657 {
658 for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
659 {
660 if (!PdoGetRangeLength(DeviceExtension,
661 0x10 + i * 4,
662 &Base,
663 &Length,
664 &Flags))
665 break;
666
667 if (Length != 0)
668 ResCount++;
669 }
670 }
671 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == 2)
672 {
673
674 }
675 else
676 {
677 DPRINT1("Unsupported header type %u\n", PCI_CONFIGURATION_TYPE(&PciConfig));
678 }
679
680 if (ResCount == 0)
681 {
682 Irp->IoStatus.Information = 0;
683 return STATUS_SUCCESS;
684 }
685
686 /* Calculate the resource list size */
687 ListSize = sizeof(CM_RESOURCE_LIST);
688 if (ResCount > 1)
689 {
690 ListSize += ((ResCount - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
691 }
692
693 /* Allocate the resource list */
694 ResourceList = ExAllocatePool(PagedPool,
695 ListSize);
696 if (ResourceList == NULL)
697 return STATUS_INSUFFICIENT_RESOURCES;
698
699 ResourceList->Count = 1;
700 ResourceList->List[0].InterfaceType = PCIConfiguration;
701 ResourceList->List[0].BusNumber = DeviceExtension->BusNumber;
702
703 PartialList = &ResourceList->List[0].PartialResourceList;
704 PartialList->Version = 0;
705 PartialList->Revision = 0;
706 PartialList->Count = ResCount;
707
708 Descriptor = &PartialList->PartialDescriptors[0];
709 if (PCI_CONFIGURATION_TYPE(&PciConfig) == 0)
710 {
711 for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
712 {
713 if (!PdoGetRangeLength(DeviceExtension,
714 0x10 + i * 4,
715 &Base,
716 &Length,
717 &Flags))
718 {
719 DPRINT1("PdoGetRangeLength() failed\n");
720 break;
721 }
722
723 if (Length == 0)
724 {
725 DPRINT("Unused address register\n");
726 continue;
727 }
728
729 if (Flags & PCI_ADDRESS_IO_SPACE)
730 {
731 Descriptor->Type = CmResourceTypePort;
732 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
733 Descriptor->Flags = CM_RESOURCE_PORT_IO;
734 Descriptor->u.Port.Start.QuadPart =
735 (ULONGLONG)Base;
736 Descriptor->u.Port.Length = Length;
737 }
738 else
739 {
740 Descriptor->Type = CmResourceTypeMemory;
741 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
742 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
743 Descriptor->u.Memory.Start.QuadPart =
744 (ULONGLONG)Base;
745 Descriptor->u.Memory.Length = Length;
746 }
747
748 Descriptor++;
749 }
750
751 /* Add interrupt resource */
752 if ((PciConfig.u.type0.InterruptPin != 0) &&
753 (PciConfig.u.type0.InterruptLine != 0xFF))
754 {
755 Descriptor->Type = CmResourceTypeInterrupt;
756 Descriptor->ShareDisposition = CmResourceShareShared;
757 Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
758 Descriptor->u.Interrupt.Level = PciConfig.u.type0.InterruptLine;
759 Descriptor->u.Interrupt.Vector = PciConfig.u.type0.InterruptLine;
760 Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
761 }
762 }
763 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == 1)
764 {
765 for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
766 {
767 if (!PdoGetRangeLength(DeviceExtension,
768 0x10 + i * 4,
769 &Base,
770 &Length,
771 &Flags))
772 {
773 DPRINT1("PdoGetRangeLength() failed\n");
774 break;
775 }
776
777 if (Length == 0)
778 {
779 DPRINT("Unused address register\n");
780 continue;
781 }
782
783 if (Flags & PCI_ADDRESS_IO_SPACE)
784 {
785 Descriptor->Type = CmResourceTypePort;
786 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
787 Descriptor->Flags = CM_RESOURCE_PORT_IO;
788 Descriptor->u.Port.Start.QuadPart =
789 (ULONGLONG)Base;
790 Descriptor->u.Port.Length = Length;
791 }
792 else
793 {
794 Descriptor->Type = CmResourceTypeMemory;
795 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
796 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
797 Descriptor->u.Memory.Start.QuadPart =
798 (ULONGLONG)Base;
799 Descriptor->u.Memory.Length = Length;
800 }
801
802 Descriptor++;
803 }
804 }
805 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == 2)
806 {
807 /* FIXME: Cardbus */
808 }
809
810 Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
811
812 return STATUS_SUCCESS;
813 }
814
815
816 static NTSTATUS
817 PdoReadConfig(
818 IN PDEVICE_OBJECT DeviceObject,
819 IN PIRP Irp,
820 PIO_STACK_LOCATION IrpSp)
821 {
822 PPDO_DEVICE_EXTENSION DeviceExtension;
823 ULONG Size;
824
825 DPRINT1("PdoReadConfig() called\n");
826
827 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
828
829 #if 0
830 if (IrpSp->Parameters.ReadWriteConfig.WhichSpace != PCI_WHICHSPACE_CONFIG)
831 return STATUS_NOT_SUPPORTED;
832 #endif
833
834 /* Get PCI configuration space */
835 Size= HalGetBusDataByOffset(PCIConfiguration,
836 DeviceExtension->BusNumber,
837 DeviceExtension->SlotNumber.u.AsULONG,
838 IrpSp->Parameters.ReadWriteConfig.Buffer,
839 IrpSp->Parameters.ReadWriteConfig.Offset,
840 IrpSp->Parameters.ReadWriteConfig.Length);
841 if (Size != IrpSp->Parameters.ReadWriteConfig.Length)
842 {
843 DPRINT1("Size %lu Length %lu\n", Size, IrpSp->Parameters.ReadWriteConfig.Length);
844 Irp->IoStatus.Information = 0;
845 return STATUS_UNSUCCESSFUL;
846 }
847
848 Irp->IoStatus.Information = Size;
849
850 return STATUS_SUCCESS;
851 }
852
853
854 static NTSTATUS
855 PdoWriteConfig(
856 IN PDEVICE_OBJECT DeviceObject,
857 IN PIRP Irp,
858 PIO_STACK_LOCATION IrpSp)
859 {
860 PPDO_DEVICE_EXTENSION DeviceExtension;
861 ULONG Size;
862
863 DPRINT1("PdoWriteConfig() called\n");
864
865 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
866
867 #if 0
868 if (IrpSp->Parameters.ReadWriteConfig.WhichSpace != PCI_WHICHSPACE_CONFIG)
869 return STATUS_NOT_SUPPORTED;
870 #endif
871
872 /* Get PCI configuration space */
873 Size= HalSetBusDataByOffset(PCIConfiguration,
874 DeviceExtension->BusNumber,
875 DeviceExtension->SlotNumber.u.AsULONG,
876 IrpSp->Parameters.ReadWriteConfig.Buffer,
877 IrpSp->Parameters.ReadWriteConfig.Offset,
878 IrpSp->Parameters.ReadWriteConfig.Length);
879 if (Size != IrpSp->Parameters.ReadWriteConfig.Length)
880 {
881 DPRINT1("Size %lu Length %lu\n", Size, IrpSp->Parameters.ReadWriteConfig.Length);
882 Irp->IoStatus.Information = 0;
883 return STATUS_UNSUCCESSFUL;
884 }
885
886 Irp->IoStatus.Information = Size;
887
888 return STATUS_SUCCESS;
889 }
890
891
892 static NTSTATUS
893 PdoSetPower(
894 IN PDEVICE_OBJECT DeviceObject,
895 IN PIRP Irp,
896 PIO_STACK_LOCATION IrpSp)
897 {
898 PPDO_DEVICE_EXTENSION DeviceExtension;
899 NTSTATUS Status;
900
901 DPRINT("Called\n");
902
903 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
904
905 if (IrpSp->Parameters.Power.Type == DevicePowerState) {
906 Status = STATUS_SUCCESS;
907 switch (IrpSp->Parameters.Power.State.SystemState) {
908 default:
909 Status = STATUS_UNSUCCESSFUL;
910 }
911 } else {
912 Status = STATUS_UNSUCCESSFUL;
913 }
914
915 return Status;
916 }
917
918
919 /*** PUBLIC ******************************************************************/
920
921 NTSTATUS
922 PdoPnpControl(
923 PDEVICE_OBJECT DeviceObject,
924 PIRP Irp)
925 /*
926 * FUNCTION: Handle Plug and Play IRPs for the child device
927 * ARGUMENTS:
928 * DeviceObject = Pointer to physical device object of the child device
929 * Irp = Pointer to IRP that should be handled
930 * RETURNS:
931 * Status
932 */
933 {
934 PIO_STACK_LOCATION IrpSp;
935 NTSTATUS Status;
936
937 DPRINT("Called\n");
938
939 Status = Irp->IoStatus.Status;
940
941 IrpSp = IoGetCurrentIrpStackLocation(Irp);
942
943 switch (IrpSp->MinorFunction) {
944 #if 0
945 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
946 break;
947
948 case IRP_MN_EJECT:
949 break;
950 #endif
951
952 case IRP_MN_QUERY_BUS_INFORMATION:
953 Status = PdoQueryBusInformation(DeviceObject, Irp, IrpSp);
954 break;
955
956 case IRP_MN_QUERY_CAPABILITIES:
957 Status = PdoQueryCapabilities(DeviceObject, Irp, IrpSp);
958 break;
959
960 #if 0
961 case IRP_MN_QUERY_DEVICE_RELATIONS:
962 /* FIXME: Possibly handle for RemovalRelations */
963 break;
964 #endif
965
966 case IRP_MN_QUERY_DEVICE_TEXT:
967 DPRINT("IRP_MN_QUERY_DEVICE_TEXT received\n");
968 Status = PdoQueryDeviceText(DeviceObject, Irp, IrpSp);
969 break;
970
971 case IRP_MN_QUERY_ID:
972 DPRINT("IRP_MN_QUERY_ID received\n");
973 Status = PdoQueryId(DeviceObject, Irp, IrpSp);
974 break;
975
976 #if 0
977 case IRP_MN_QUERY_PNP_DEVICE_STATE:
978 break;
979 #endif
980
981 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
982 DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS received\n");
983 Status = PdoQueryResourceRequirements(DeviceObject, Irp, IrpSp);
984 break;
985
986 case IRP_MN_QUERY_RESOURCES:
987 DPRINT("IRP_MN_QUERY_RESOURCES received\n");
988 Status = PdoQueryResources(DeviceObject, Irp, IrpSp);
989 break;
990
991 #if 0
992 case IRP_MN_SET_LOCK:
993 break;
994 #endif
995
996 case IRP_MN_START_DEVICE:
997 case IRP_MN_QUERY_STOP_DEVICE:
998 case IRP_MN_CANCEL_STOP_DEVICE:
999 case IRP_MN_STOP_DEVICE:
1000 case IRP_MN_QUERY_REMOVE_DEVICE:
1001 case IRP_MN_CANCEL_REMOVE_DEVICE:
1002 case IRP_MN_REMOVE_DEVICE:
1003 case IRP_MN_SURPRISE_REMOVAL:
1004 Status = STATUS_SUCCESS;
1005 break;
1006
1007 case IRP_MN_READ_CONFIG:
1008 DPRINT1("IRP_MN_READ_CONFIG received\n");
1009 Status = PdoReadConfig(DeviceObject, Irp, IrpSp);
1010 break;
1011
1012 case IRP_MN_WRITE_CONFIG:
1013 DPRINT1("IRP_MN_WRITE_CONFIG received\n");
1014 Status = PdoWriteConfig(DeviceObject, Irp, IrpSp);
1015 break;
1016
1017 default:
1018 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
1019 break;
1020 }
1021
1022 if (Status != STATUS_PENDING) {
1023 Irp->IoStatus.Status = Status;
1024 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1025 }
1026
1027 DPRINT("Leaving. Status 0x%X\n", Status);
1028
1029 return Status;
1030 }
1031
1032 NTSTATUS
1033 PdoPowerControl(
1034 PDEVICE_OBJECT DeviceObject,
1035 PIRP Irp)
1036 /*
1037 * FUNCTION: Handle power management IRPs for the child device
1038 * ARGUMENTS:
1039 * DeviceObject = Pointer to physical device object of the child device
1040 * Irp = Pointer to IRP that should be handled
1041 * RETURNS:
1042 * Status
1043 */
1044 {
1045 PIO_STACK_LOCATION IrpSp;
1046 NTSTATUS Status;
1047
1048 DPRINT("Called\n");
1049
1050 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1051
1052 switch (IrpSp->MinorFunction) {
1053 case IRP_MN_SET_POWER:
1054 Status = PdoSetPower(DeviceObject, Irp, IrpSp);
1055 break;
1056
1057 default:
1058 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
1059 Status = STATUS_NOT_IMPLEMENTED;
1060 break;
1061 }
1062
1063 if (Status != STATUS_PENDING) {
1064 Irp->IoStatus.Status = Status;
1065 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1066 }
1067
1068 DPRINT("Leaving. Status 0x%X\n", Status);
1069
1070 return Status;
1071 }
1072
1073 /* EOF */