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