Sync with trunk r47129
[reactos.git] / drivers / bus / pci / pdo.c
1 /*
2 * PROJECT: ReactOS PCI bus driver
3 * FILE: pdo.c
4 * PURPOSE: Child device object dispatch routines
5 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
6 * UPDATE HISTORY:
7 * 10-09-2001 CSH Created
8 */
9
10 #include "pci.h"
11
12 #ifndef NDEBUG
13 #define NDEBUG
14 #endif
15 #include <debug.h>
16
17 /*** PRIVATE *****************************************************************/
18
19 static NTSTATUS
20 PdoQueryDeviceText(
21 IN PDEVICE_OBJECT DeviceObject,
22 IN PIRP Irp,
23 PIO_STACK_LOCATION IrpSp)
24 {
25 PPDO_DEVICE_EXTENSION DeviceExtension;
26 NTSTATUS Status;
27
28 DPRINT("Called\n");
29
30 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
31
32 Status = STATUS_SUCCESS;
33
34 switch (IrpSp->Parameters.QueryDeviceText.DeviceTextType)
35 {
36 case DeviceTextDescription:
37 DPRINT("DeviceTextDescription\n");
38 Irp->IoStatus.Information = (ULONG_PTR)DeviceExtension->DeviceDescription.Buffer;
39 break;
40
41 case DeviceTextLocationInformation:
42 DPRINT("DeviceTextLocationInformation\n");
43 Irp->IoStatus.Information = (ULONG_PTR)DeviceExtension->DeviceLocation.Buffer;
44 break;
45
46 default:
47 Irp->IoStatus.Information = 0;
48 Status = STATUS_INVALID_PARAMETER;
49 }
50
51 return Status;
52 }
53
54
55 static NTSTATUS
56 PdoQueryId(
57 IN PDEVICE_OBJECT DeviceObject,
58 IN PIRP Irp,
59 PIO_STACK_LOCATION IrpSp)
60 {
61 PPDO_DEVICE_EXTENSION DeviceExtension;
62 UNICODE_STRING String;
63 NTSTATUS Status;
64
65 DPRINT("Called\n");
66
67 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
68
69 // Irp->IoStatus.Information = 0;
70
71 Status = STATUS_SUCCESS;
72
73 RtlInitUnicodeString(&String, NULL);
74
75 switch (IrpSp->Parameters.QueryId.IdType) {
76 case BusQueryDeviceID:
77 Status = PciDuplicateUnicodeString(
78 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
79 &DeviceExtension->DeviceID,
80 &String);
81
82 DPRINT("DeviceID: %S\n", String.Buffer);
83
84 Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
85 break;
86
87 case BusQueryHardwareIDs:
88 Status = PciDuplicateUnicodeString(
89 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
90 &DeviceExtension->HardwareIDs,
91 &String);
92
93 Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
94 break;
95
96 case BusQueryCompatibleIDs:
97 Status = PciDuplicateUnicodeString(
98 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
99 &DeviceExtension->CompatibleIDs,
100 &String);
101
102 Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
103 break;
104
105 case BusQueryInstanceID:
106 Status = PciDuplicateUnicodeString(
107 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
108 &DeviceExtension->InstanceID,
109 &String);
110
111 DPRINT("InstanceID: %S\n", String.Buffer);
112
113 Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
114 break;
115
116 case BusQueryDeviceSerialNumber:
117 default:
118 Status = STATUS_NOT_IMPLEMENTED;
119 }
120
121 return Status;
122 }
123
124
125 static NTSTATUS
126 PdoQueryBusInformation(
127 IN PDEVICE_OBJECT DeviceObject,
128 IN PIRP Irp,
129 PIO_STACK_LOCATION IrpSp)
130 {
131 PPDO_DEVICE_EXTENSION DeviceExtension;
132 PFDO_DEVICE_EXTENSION FdoDeviceExtension;
133 PPNP_BUS_INFORMATION BusInformation;
134
135 UNREFERENCED_PARAMETER(IrpSp);
136 DPRINT("Called\n");
137
138 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
139 FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceExtension->Fdo->DeviceExtension;
140 BusInformation = ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
141 Irp->IoStatus.Information = (ULONG_PTR)BusInformation;
142 if (BusInformation != NULL)
143 {
144 BusInformation->BusTypeGuid = GUID_BUS_TYPE_PCI;
145 BusInformation->LegacyBusType = PCIBus;
146 BusInformation->BusNumber = DeviceExtension->PciDevice->BusNumber;
147
148 return STATUS_SUCCESS;
149 }
150
151 return STATUS_INSUFFICIENT_RESOURCES;
152 }
153
154
155 static NTSTATUS
156 PdoQueryCapabilities(
157 IN PDEVICE_OBJECT DeviceObject,
158 IN PIRP Irp,
159 PIO_STACK_LOCATION IrpSp)
160 {
161 PPDO_DEVICE_EXTENSION DeviceExtension;
162 PDEVICE_CAPABILITIES DeviceCapabilities;
163 ULONG DeviceNumber, FunctionNumber;
164
165 UNREFERENCED_PARAMETER(Irp);
166 DPRINT("Called\n");
167
168 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
169 DeviceCapabilities = IrpSp->Parameters.DeviceCapabilities.Capabilities;
170
171 if (DeviceCapabilities->Version != 1)
172 return STATUS_UNSUCCESSFUL;
173
174 DeviceNumber = DeviceExtension->PciDevice->SlotNumber.u.bits.DeviceNumber;
175 FunctionNumber = DeviceExtension->PciDevice->SlotNumber.u.bits.FunctionNumber;
176
177 DeviceCapabilities->UniqueID = FALSE;
178 DeviceCapabilities->Address = ((DeviceNumber << 16) & 0xFFFF0000) + (FunctionNumber & 0xFFFF);
179 DeviceCapabilities->UINumber = MAXULONG; /* FIXME */
180
181 return STATUS_SUCCESS;
182 }
183
184
185 static BOOLEAN
186 PdoGetRangeLength(PPDO_DEVICE_EXTENSION DeviceExtension,
187 ULONG Offset,
188 PULONG Base,
189 PULONG Length,
190 PULONG Flags)
191 {
192 ULONG OrigValue;
193 ULONG BaseValue;
194 ULONG NewValue;
195 ULONG Size;
196 ULONG XLength;
197
198 /* Save original value */
199 Size= HalGetBusDataByOffset(PCIConfiguration,
200 DeviceExtension->PciDevice->BusNumber,
201 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
202 &OrigValue,
203 Offset,
204 sizeof(ULONG));
205 if (Size != sizeof(ULONG))
206 {
207 DPRINT1("Wrong size %lu\n", Size);
208 return FALSE;
209 }
210
211 BaseValue = (OrigValue & 0x00000001) ? (OrigValue & ~0x3) : (OrigValue & ~0xF);
212
213 *Base = BaseValue;
214
215 /* Set magic value */
216 NewValue = MAXULONG;
217 Size= HalSetBusDataByOffset(PCIConfiguration,
218 DeviceExtension->PciDevice->BusNumber,
219 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
220 &NewValue,
221 Offset,
222 sizeof(ULONG));
223 if (Size != sizeof(ULONG))
224 {
225 DPRINT1("Wrong size %lu\n", Size);
226 return FALSE;
227 }
228
229 /* Get the range length */
230 Size= HalGetBusDataByOffset(PCIConfiguration,
231 DeviceExtension->PciDevice->BusNumber,
232 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
233 &NewValue,
234 Offset,
235 sizeof(ULONG));
236 if (Size != sizeof(ULONG))
237 {
238 DPRINT1("Wrong size %lu\n", Size);
239 return FALSE;
240 }
241
242 /* Restore original value */
243 Size= HalSetBusDataByOffset(PCIConfiguration,
244 DeviceExtension->PciDevice->BusNumber,
245 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
246 &OrigValue,
247 Offset,
248 sizeof(ULONG));
249 if (Size != sizeof(ULONG))
250 {
251 DPRINT1("Wrong size %lu\n", Size);
252 return FALSE;
253 }
254
255 if (NewValue == 0)
256 {
257 DPRINT("Unused address register\n");
258 *Base = 0;
259 *Length = 0;
260 *Flags = 0;
261 return TRUE;
262 }
263
264 XLength = ~((NewValue & 0x00000001) ? (NewValue & ~0x3) : (NewValue & ~0xF)) + 1;
265
266 #if 0
267 DbgPrint("BaseAddress 0x%08lx Length 0x%08lx",
268 BaseValue, XLength);
269
270 if (NewValue & 0x00000001)
271 {
272 DbgPrint(" IO range");
273 }
274 else
275 {
276 DbgPrint(" Memory range");
277 if ((NewValue & 0x00000006) == 0)
278 {
279 DbgPrint(" in 32-Bit address space");
280 }
281 else if ((NewValue & 0x00000006) == 2)
282 {
283 DbgPrint(" below 1BM ");
284 }
285 else if ((NewValue & 0x00000006) == 4)
286 {
287 DbgPrint(" in 64-Bit address space");
288 }
289
290 if (NewValue & 0x00000008)
291 {
292 DbgPrint(" prefetchable");
293 }
294 }
295
296 DbgPrint("\n");
297 #endif
298
299 *Length = XLength;
300 *Flags = (NewValue & 0x00000001) ? (NewValue & 0x3) : (NewValue & 0xF);
301
302 return TRUE;
303 }
304
305
306 static NTSTATUS
307 PdoQueryResourceRequirements(
308 IN PDEVICE_OBJECT DeviceObject,
309 IN PIRP Irp,
310 PIO_STACK_LOCATION IrpSp)
311 {
312 PPDO_DEVICE_EXTENSION DeviceExtension;
313 PCI_COMMON_CONFIG PciConfig;
314 PIO_RESOURCE_REQUIREMENTS_LIST ResourceList;
315 PIO_RESOURCE_DESCRIPTOR Descriptor;
316 ULONG Size;
317 ULONG ResCount = 0;
318 ULONG ListSize;
319 ULONG i;
320 ULONG Base;
321 ULONG Length;
322 ULONG Flags;
323
324 UNREFERENCED_PARAMETER(IrpSp);
325 DPRINT("PdoQueryResourceRequirements() called\n");
326
327 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
328
329 /* Get PCI configuration space */
330 Size= HalGetBusData(PCIConfiguration,
331 DeviceExtension->PciDevice->BusNumber,
332 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
333 &PciConfig,
334 PCI_COMMON_HDR_LENGTH);
335 DPRINT("Size %lu\n", Size);
336 if (Size < PCI_COMMON_HDR_LENGTH)
337 {
338 Irp->IoStatus.Information = 0;
339 return STATUS_UNSUCCESSFUL;
340 }
341
342 DPRINT("Command register: 0x%04hx\n", PciConfig.Command);
343
344 /* Count required resource descriptors */
345 ResCount = 0;
346 if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_DEVICE_TYPE)
347 {
348 for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
349 {
350 if (!PdoGetRangeLength(DeviceExtension,
351 0x10 + i * 4,
352 &Base,
353 &Length,
354 &Flags))
355 break;
356
357 if (Length != 0)
358 ResCount += 2;
359 }
360
361 /* FIXME: Check ROM address */
362
363 if (PciConfig.u.type0.InterruptPin != 0)
364 ResCount++;
365 }
366 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
367 {
368 for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
369 {
370 if (!PdoGetRangeLength(DeviceExtension,
371 0x10 + i * 4,
372 &Base,
373 &Length,
374 &Flags))
375 break;
376
377 if (Length != 0)
378 ResCount += 2;
379 }
380 if (DeviceExtension->PciDevice->PciConfig.BaseClass == PCI_CLASS_BRIDGE_DEV)
381 ResCount++;
382 }
383 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_CARDBUS_BRIDGE_TYPE)
384 {
385 /* FIXME: Count Cardbus bridge resources */
386 }
387 else
388 {
389 DPRINT1("Unsupported header type %u\n", PCI_CONFIGURATION_TYPE(&PciConfig));
390 }
391
392 if (ResCount == 0)
393 {
394 Irp->IoStatus.Information = 0;
395 return STATUS_SUCCESS;
396 }
397
398 /* Calculate the resource list size */
399 ListSize = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List[0].Descriptors)
400 + ResCount * sizeof(IO_RESOURCE_DESCRIPTOR);
401
402 DPRINT("ListSize %lu (0x%lx)\n", ListSize, ListSize);
403
404 /* Allocate the resource requirements list */
405 ResourceList = ExAllocatePoolWithTag(PagedPool,
406 ListSize, TAG_PCI);
407 if (ResourceList == NULL)
408 {
409 Irp->IoStatus.Information = 0;
410 return STATUS_INSUFFICIENT_RESOURCES;
411 }
412
413 RtlZeroMemory(ResourceList, ListSize);
414 ResourceList->ListSize = ListSize;
415 ResourceList->InterfaceType = PCIBus;
416 ResourceList->BusNumber = DeviceExtension->PciDevice->BusNumber;
417 ResourceList->SlotNumber = DeviceExtension->PciDevice->SlotNumber.u.AsULONG;
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 = DeviceExtension->PciDevice->BusNumber;
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 if (!RawResList)
1203 return STATUS_SUCCESS;
1204
1205 /* TODO: Assign the other resources we get to the card */
1206
1207 for (i = 0; i < RawResList->Count; i++)
1208 {
1209 RawFullDesc = &RawResList->List[i];
1210
1211 for (ii = 0; ii < RawFullDesc->PartialResourceList.Count; ii++)
1212 {
1213 RawPartialDesc = &RawFullDesc->PartialResourceList.PartialDescriptors[ii];
1214
1215 if (RawPartialDesc->Type == CmResourceTypeInterrupt)
1216 {
1217 DPRINT1("Assigning IRQ %x to PCI device (%x, %x)\n",
1218 RawPartialDesc->u.Interrupt.Vector,
1219 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
1220 DeviceExtension->PciDevice->BusNumber);
1221
1222 Irq = (UCHAR)RawPartialDesc->u.Interrupt.Vector;
1223 HalSetBusDataByOffset(PCIConfiguration,
1224 DeviceExtension->PciDevice->BusNumber,
1225 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
1226 &Irq,
1227 0x3c /* PCI_INTERRUPT_LINE */,
1228 sizeof(UCHAR));
1229 }
1230 }
1231 }
1232
1233 return STATUS_SUCCESS;
1234 }
1235
1236 static NTSTATUS
1237 PdoReadConfig(
1238 IN PDEVICE_OBJECT DeviceObject,
1239 IN PIRP Irp,
1240 PIO_STACK_LOCATION IrpSp)
1241 {
1242 ULONG Size;
1243
1244 DPRINT("PdoReadConfig() called\n");
1245
1246 Size = InterfaceBusGetBusData(
1247 DeviceObject,
1248 IrpSp->Parameters.ReadWriteConfig.WhichSpace,
1249 IrpSp->Parameters.ReadWriteConfig.Buffer,
1250 IrpSp->Parameters.ReadWriteConfig.Offset,
1251 IrpSp->Parameters.ReadWriteConfig.Length);
1252
1253 if (Size != IrpSp->Parameters.ReadWriteConfig.Length)
1254 {
1255 DPRINT1("Size %lu Length %lu\n", Size, IrpSp->Parameters.ReadWriteConfig.Length);
1256 Irp->IoStatus.Information = 0;
1257 return STATUS_UNSUCCESSFUL;
1258 }
1259
1260 Irp->IoStatus.Information = Size;
1261
1262 return STATUS_SUCCESS;
1263 }
1264
1265
1266 static NTSTATUS
1267 PdoWriteConfig(
1268 IN PDEVICE_OBJECT DeviceObject,
1269 IN PIRP Irp,
1270 PIO_STACK_LOCATION IrpSp)
1271 {
1272 ULONG Size;
1273
1274 DPRINT1("PdoWriteConfig() called\n");
1275
1276 /* Get PCI configuration space */
1277 Size = InterfaceBusSetBusData(
1278 DeviceObject,
1279 IrpSp->Parameters.ReadWriteConfig.WhichSpace,
1280 IrpSp->Parameters.ReadWriteConfig.Buffer,
1281 IrpSp->Parameters.ReadWriteConfig.Offset,
1282 IrpSp->Parameters.ReadWriteConfig.Length);
1283
1284 if (Size != IrpSp->Parameters.ReadWriteConfig.Length)
1285 {
1286 DPRINT1("Size %lu Length %lu\n", Size, IrpSp->Parameters.ReadWriteConfig.Length);
1287 Irp->IoStatus.Information = 0;
1288 return STATUS_UNSUCCESSFUL;
1289 }
1290
1291 Irp->IoStatus.Information = Size;
1292
1293 return STATUS_SUCCESS;
1294 }
1295
1296 static NTSTATUS
1297 PdoQueryDeviceRelations(
1298 IN PDEVICE_OBJECT DeviceObject,
1299 IN PIRP Irp,
1300 PIO_STACK_LOCATION IrpSp)
1301 {
1302 PDEVICE_RELATIONS DeviceRelations;
1303
1304 /* We only support TargetDeviceRelation for child PDOs */
1305 if (IrpSp->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
1306 return Irp->IoStatus.Status;
1307
1308 /* We can do this because we only return 1 PDO for TargetDeviceRelation */
1309 DeviceRelations = ExAllocatePool(PagedPool, sizeof(*DeviceRelations));
1310 if (!DeviceRelations)
1311 return STATUS_INSUFFICIENT_RESOURCES;
1312
1313 DeviceRelations->Count = 1;
1314 DeviceRelations->Objects[0] = DeviceObject;
1315
1316 /* The PnP manager will remove this when it is done with the PDO */
1317 ObReferenceObject(DeviceObject);
1318
1319 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
1320
1321 return STATUS_SUCCESS;
1322 }
1323
1324 static NTSTATUS
1325 PdoSetPower(
1326 IN PDEVICE_OBJECT DeviceObject,
1327 IN PIRP Irp,
1328 PIO_STACK_LOCATION IrpSp)
1329 {
1330 PPDO_DEVICE_EXTENSION DeviceExtension;
1331 NTSTATUS Status;
1332
1333 UNREFERENCED_PARAMETER(Irp);
1334 DPRINT("Called\n");
1335
1336 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1337
1338 if (IrpSp->Parameters.Power.Type == DevicePowerState) {
1339 Status = STATUS_SUCCESS;
1340 switch (IrpSp->Parameters.Power.State.SystemState) {
1341 default:
1342 Status = STATUS_UNSUCCESSFUL;
1343 }
1344 } else {
1345 Status = STATUS_UNSUCCESSFUL;
1346 }
1347
1348 return Status;
1349 }
1350
1351
1352 /*** PUBLIC ******************************************************************/
1353
1354 NTSTATUS
1355 PdoPnpControl(
1356 PDEVICE_OBJECT DeviceObject,
1357 PIRP Irp)
1358 /*
1359 * FUNCTION: Handle Plug and Play IRPs for the child device
1360 * ARGUMENTS:
1361 * DeviceObject = Pointer to physical device object of the child device
1362 * Irp = Pointer to IRP that should be handled
1363 * RETURNS:
1364 * Status
1365 */
1366 {
1367 PIO_STACK_LOCATION IrpSp;
1368 NTSTATUS Status;
1369
1370 DPRINT("Called\n");
1371
1372 Status = Irp->IoStatus.Status;
1373
1374 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1375
1376 switch (IrpSp->MinorFunction) {
1377
1378 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
1379 DPRINT("Unimplemented IRP_MN_DEVICE_USAGE_NOTIFICATION received\n");
1380 break;
1381
1382 case IRP_MN_EJECT:
1383 DPRINT("Unimplemented IRP_MN_EJECT received\n");
1384 break;
1385
1386 case IRP_MN_QUERY_BUS_INFORMATION:
1387 Status = PdoQueryBusInformation(DeviceObject, Irp, IrpSp);
1388 break;
1389
1390 case IRP_MN_QUERY_CAPABILITIES:
1391 Status = PdoQueryCapabilities(DeviceObject, Irp, IrpSp);
1392 break;
1393
1394 case IRP_MN_QUERY_DEVICE_RELATIONS:
1395 Status = PdoQueryDeviceRelations(DeviceObject, Irp, IrpSp);
1396 break;
1397
1398 case IRP_MN_QUERY_DEVICE_TEXT:
1399 DPRINT("IRP_MN_QUERY_DEVICE_TEXT received\n");
1400 Status = PdoQueryDeviceText(DeviceObject, Irp, IrpSp);
1401 break;
1402
1403 case IRP_MN_QUERY_ID:
1404 DPRINT("IRP_MN_QUERY_ID received\n");
1405 Status = PdoQueryId(DeviceObject, Irp, IrpSp);
1406 break;
1407
1408 case IRP_MN_QUERY_PNP_DEVICE_STATE:
1409 DPRINT("Unimplemented IRP_MN_QUERY_ID received\n");
1410 break;
1411
1412 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
1413 DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS received\n");
1414 Status = PdoQueryResourceRequirements(DeviceObject, Irp, IrpSp);
1415 break;
1416
1417 case IRP_MN_QUERY_RESOURCES:
1418 DPRINT("IRP_MN_QUERY_RESOURCES received\n");
1419 Status = PdoQueryResources(DeviceObject, Irp, IrpSp);
1420 break;
1421
1422 case IRP_MN_SET_LOCK:
1423 DPRINT("Unimplemented IRP_MN_SET_LOCK received\n");
1424 break;
1425
1426 case IRP_MN_START_DEVICE:
1427 Status = PdoStartDevice(DeviceObject, Irp, IrpSp);
1428 break;
1429
1430 case IRP_MN_QUERY_STOP_DEVICE:
1431 case IRP_MN_CANCEL_STOP_DEVICE:
1432 case IRP_MN_STOP_DEVICE:
1433 case IRP_MN_QUERY_REMOVE_DEVICE:
1434 case IRP_MN_CANCEL_REMOVE_DEVICE:
1435 case IRP_MN_REMOVE_DEVICE:
1436 case IRP_MN_SURPRISE_REMOVAL:
1437 Status = STATUS_SUCCESS;
1438 break;
1439
1440 case IRP_MN_QUERY_INTERFACE:
1441 DPRINT("IRP_MN_QUERY_INTERFACE received\n");
1442 Status = PdoQueryInterface(DeviceObject, Irp, IrpSp);
1443 break;
1444
1445 case IRP_MN_READ_CONFIG:
1446 DPRINT("IRP_MN_READ_CONFIG received\n");
1447 Status = PdoReadConfig(DeviceObject, Irp, IrpSp);
1448 break;
1449
1450 case IRP_MN_WRITE_CONFIG:
1451 DPRINT("IRP_MN_WRITE_CONFIG received\n");
1452 Status = PdoWriteConfig(DeviceObject, Irp, IrpSp);
1453 break;
1454
1455 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
1456 DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS received\n");
1457 /* Nothing to do */
1458 Irp->IoStatus.Status = Status;
1459 break;
1460
1461 default:
1462 DPRINT1("Unknown IOCTL 0x%lx\n", IrpSp->MinorFunction);
1463 break;
1464 }
1465
1466 if (Status != STATUS_PENDING) {
1467 Irp->IoStatus.Status = Status;
1468 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1469 }
1470
1471 DPRINT("Leaving. Status 0x%X\n", Status);
1472
1473 return Status;
1474 }
1475
1476 NTSTATUS
1477 PdoPowerControl(
1478 PDEVICE_OBJECT DeviceObject,
1479 PIRP Irp)
1480 /*
1481 * FUNCTION: Handle power management IRPs for the child device
1482 * ARGUMENTS:
1483 * DeviceObject = Pointer to physical device object of the child device
1484 * Irp = Pointer to IRP that should be handled
1485 * RETURNS:
1486 * Status
1487 */
1488 {
1489 PIO_STACK_LOCATION IrpSp;
1490 NTSTATUS Status;
1491
1492 DPRINT("Called\n");
1493
1494 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1495
1496 switch (IrpSp->MinorFunction) {
1497 case IRP_MN_SET_POWER:
1498 Status = PdoSetPower(DeviceObject, Irp, IrpSp);
1499 break;
1500
1501 default:
1502 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
1503 Status = STATUS_NOT_IMPLEMENTED;
1504 break;
1505 }
1506
1507 if (Status != STATUS_PENDING) {
1508 Irp->IoStatus.Status = Status;
1509 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1510 }
1511
1512 DPRINT("Leaving. Status 0x%X\n", Status);
1513
1514 return Status;
1515 }
1516
1517 /* EOF */