* Sync to trunk HEAD (r53318).
[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 != 0) &&
673 (PciConfig.u.type0.InterruptLine != 0xFF))
674 ResCount++;
675 }
676 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
677 {
678 for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
679 {
680 if (!PdoGetRangeLength(DeviceExtension,
681 0x10 + i * 4,
682 &Base,
683 &Length,
684 &Flags))
685 break;
686
687 if (Length != 0)
688 ResCount++;
689 }
690 if (DeviceExtension->PciDevice->PciConfig.BaseClass == PCI_CLASS_BRIDGE_DEV)
691 ResCount++;
692 }
693 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_CARDBUS_BRIDGE_TYPE)
694 {
695 /* FIXME: Count Cardbus bridge resources */
696 }
697 else
698 {
699 DPRINT1("Unsupported header type %u\n", PCI_CONFIGURATION_TYPE(&PciConfig));
700 }
701
702 if (ResCount == 0)
703 {
704 Irp->IoStatus.Information = 0;
705 return STATUS_SUCCESS;
706 }
707
708 /* Calculate the resource list size */
709 ListSize = FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.PartialDescriptors)
710 + ResCount * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
711
712 /* Allocate the resource list */
713 ResourceList = ExAllocatePoolWithTag(PagedPool,
714 ListSize, TAG_PCI);
715 if (ResourceList == NULL)
716 return STATUS_INSUFFICIENT_RESOURCES;
717
718 RtlZeroMemory(ResourceList, ListSize);
719 ResourceList->Count = 1;
720 ResourceList->List[0].InterfaceType = PCIBus;
721 ResourceList->List[0].BusNumber = DeviceExtension->PciDevice->BusNumber;
722
723 PartialList = &ResourceList->List[0].PartialResourceList;
724 PartialList->Version = 1;
725 PartialList->Revision = 1;
726 PartialList->Count = ResCount;
727
728 Descriptor = &PartialList->PartialDescriptors[0];
729 if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_DEVICE_TYPE)
730 {
731 for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
732 {
733 if (!PdoGetRangeLength(DeviceExtension,
734 0x10 + i * 4,
735 &Base,
736 &Length,
737 &Flags))
738 {
739 DPRINT1("PdoGetRangeLength() failed\n");
740 break;
741 }
742
743 if (Length == 0)
744 {
745 DPRINT("Unused address register\n");
746 continue;
747 }
748
749 if (Flags & PCI_ADDRESS_IO_SPACE)
750 {
751 Descriptor->Type = CmResourceTypePort;
752 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
753 Descriptor->Flags = CM_RESOURCE_PORT_IO;
754 Descriptor->u.Port.Start.QuadPart =
755 (ULONGLONG)Base;
756 Descriptor->u.Port.Length = Length;
757 }
758 else
759 {
760 Descriptor->Type = CmResourceTypeMemory;
761 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
762 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
763 Descriptor->u.Memory.Start.QuadPart =
764 (ULONGLONG)Base;
765 Descriptor->u.Memory.Length = Length;
766 }
767
768 Descriptor++;
769 }
770
771 /* Add interrupt resource */
772 if ((PciConfig.u.type0.InterruptPin != 0) &&
773 (PciConfig.u.type0.InterruptLine != 0) &&
774 (PciConfig.u.type0.InterruptLine != 0xFF))
775 {
776 Descriptor->Type = CmResourceTypeInterrupt;
777 Descriptor->ShareDisposition = CmResourceShareShared;
778 Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
779 Descriptor->u.Interrupt.Level = PciConfig.u.type0.InterruptLine;
780 Descriptor->u.Interrupt.Vector = PciConfig.u.type0.InterruptLine;
781 Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
782 }
783 }
784 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
785 {
786 for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
787 {
788 if (!PdoGetRangeLength(DeviceExtension,
789 0x10 + i * 4,
790 &Base,
791 &Length,
792 &Flags))
793 {
794 DPRINT1("PdoGetRangeLength() failed\n");
795 break;
796 }
797
798 if (Length == 0)
799 {
800 DPRINT("Unused address register\n");
801 continue;
802 }
803
804 if (Flags & PCI_ADDRESS_IO_SPACE)
805 {
806 Descriptor->Type = CmResourceTypePort;
807 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
808 Descriptor->Flags = CM_RESOURCE_PORT_IO;
809 Descriptor->u.Port.Start.QuadPart =
810 (ULONGLONG)Base;
811 Descriptor->u.Port.Length = Length;
812 }
813 else
814 {
815 Descriptor->Type = CmResourceTypeMemory;
816 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
817 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
818 Descriptor->u.Memory.Start.QuadPart =
819 (ULONGLONG)Base;
820 Descriptor->u.Memory.Length = Length;
821 }
822
823 Descriptor++;
824 }
825 if (DeviceExtension->PciDevice->PciConfig.BaseClass == PCI_CLASS_BRIDGE_DEV)
826 {
827 Descriptor->Type = CmResourceTypeBusNumber;
828 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
829
830 ResourceList->List[0].BusNumber =
831 Descriptor->u.BusNumber.Start = DeviceExtension->PciDevice->PciConfig.u.type1.SecondaryBus;
832 Descriptor->u.BusNumber.Length = 1;
833 Descriptor->u.BusNumber.Reserved = 0;
834 }
835 }
836 else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_CARDBUS_BRIDGE_TYPE)
837 {
838 /* FIXME: Add Cardbus bridge resources */
839 }
840
841 Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
842
843 return STATUS_SUCCESS;
844 }
845
846
847 static VOID NTAPI
848 InterfaceReference(
849 IN PVOID Context)
850 {
851 PPDO_DEVICE_EXTENSION DeviceExtension;
852
853 DPRINT("InterfaceReference(%p)\n", Context);
854
855 DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
856 InterlockedIncrement(&DeviceExtension->References);
857 }
858
859
860 static VOID NTAPI
861 InterfaceDereference(
862 IN PVOID Context)
863 {
864 PPDO_DEVICE_EXTENSION DeviceExtension;
865
866 DPRINT("InterfaceDereference(%p)\n", Context);
867
868 DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
869 InterlockedDecrement(&DeviceExtension->References);
870 }
871
872
873 static BOOLEAN NTAPI
874 InterfaceBusTranslateBusAddress(
875 IN PVOID Context,
876 IN PHYSICAL_ADDRESS BusAddress,
877 IN ULONG Length,
878 IN OUT PULONG AddressSpace,
879 OUT PPHYSICAL_ADDRESS TranslatedAddress)
880 {
881 PPDO_DEVICE_EXTENSION DeviceExtension;
882
883 DPRINT("InterfaceBusTranslateBusAddress(%p %p 0x%lx %p %p)\n",
884 Context, BusAddress, Length, AddressSpace, TranslatedAddress);
885
886 DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
887
888 return HalTranslateBusAddress(
889 PCIBus, DeviceExtension->PciDevice->BusNumber,
890 BusAddress, AddressSpace, TranslatedAddress);
891 }
892
893
894 static PDMA_ADAPTER NTAPI
895 InterfaceBusGetDmaAdapter(
896 IN PVOID Context,
897 IN PDEVICE_DESCRIPTION DeviceDescription,
898 OUT PULONG NumberOfMapRegisters)
899 {
900 DPRINT("InterfaceBusGetDmaAdapter(%p %p %p)\n",
901 Context, DeviceDescription, NumberOfMapRegisters);
902 return (PDMA_ADAPTER)HalGetAdapter(DeviceDescription, NumberOfMapRegisters);
903 }
904
905
906 static ULONG NTAPI
907 InterfaceBusSetBusData(
908 IN PVOID Context,
909 IN ULONG DataType,
910 IN PVOID Buffer,
911 IN ULONG Offset,
912 IN ULONG Length)
913 {
914 PPDO_DEVICE_EXTENSION DeviceExtension;
915 ULONG Size;
916
917 DPRINT("InterfaceBusSetBusData(%p 0x%lx %p 0x%lx 0x%lx)\n",
918 Context, DataType, Buffer, Offset, Length);
919
920 if (DataType != PCI_WHICHSPACE_CONFIG)
921 {
922 DPRINT("Unknown DataType %lu\n", DataType);
923 return 0;
924 }
925
926 DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
927
928 /* Get PCI configuration space */
929 Size = HalSetBusDataByOffset(PCIConfiguration,
930 DeviceExtension->PciDevice->BusNumber,
931 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
932 Buffer,
933 Offset,
934 Length);
935 return Size;
936 }
937
938
939 static ULONG NTAPI
940 InterfaceBusGetBusData(
941 IN PVOID Context,
942 IN ULONG DataType,
943 IN PVOID Buffer,
944 IN ULONG Offset,
945 IN ULONG Length)
946 {
947 PPDO_DEVICE_EXTENSION DeviceExtension;
948 ULONG Size;
949
950 DPRINT("InterfaceBusGetBusData(%p 0x%lx %p 0x%lx 0x%lx) called\n",
951 Context, DataType, Buffer, Offset, Length);
952
953 if (DataType != PCI_WHICHSPACE_CONFIG)
954 {
955 DPRINT("Unknown DataType %lu\n", DataType);
956 return 0;
957 }
958
959 DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
960
961 /* Get PCI configuration space */
962 Size = HalGetBusDataByOffset(PCIConfiguration,
963 DeviceExtension->PciDevice->BusNumber,
964 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
965 Buffer,
966 Offset,
967 Length);
968 return Size;
969 }
970
971
972 static BOOLEAN NTAPI
973 InterfacePciDevicePresent(
974 IN USHORT VendorID,
975 IN USHORT DeviceID,
976 IN UCHAR RevisionID,
977 IN USHORT SubVendorID,
978 IN USHORT SubSystemID,
979 IN ULONG Flags)
980 {
981 PFDO_DEVICE_EXTENSION FdoDeviceExtension;
982 PPCI_DEVICE PciDevice;
983 PLIST_ENTRY CurrentBus, CurrentEntry;
984 KIRQL OldIrql;
985 BOOLEAN Found = FALSE;
986
987 KeAcquireSpinLock(&DriverExtension->BusListLock, &OldIrql);
988 CurrentBus = DriverExtension->BusListHead.Flink;
989 while (!Found && CurrentBus != &DriverExtension->BusListHead)
990 {
991 FdoDeviceExtension = CONTAINING_RECORD(CurrentBus, FDO_DEVICE_EXTENSION, ListEntry);
992
993 KeAcquireSpinLockAtDpcLevel(&FdoDeviceExtension->DeviceListLock);
994 CurrentEntry = FdoDeviceExtension->DeviceListHead.Flink;
995 while (!Found && CurrentEntry != &FdoDeviceExtension->DeviceListHead)
996 {
997 PciDevice = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry);
998 if (PciDevice->PciConfig.VendorID == VendorID &&
999 PciDevice->PciConfig.DeviceID == DeviceID)
1000 {
1001 if (!(Flags & PCI_USE_SUBSYSTEM_IDS) || (
1002 PciDevice->PciConfig.u.type0.SubVendorID == SubVendorID &&
1003 PciDevice->PciConfig.u.type0.SubSystemID == SubSystemID))
1004 {
1005 if (!(Flags & PCI_USE_REVISION) ||
1006 PciDevice->PciConfig.RevisionID == RevisionID)
1007 {
1008 DPRINT("Found the PCI device\n");
1009 Found = TRUE;
1010 }
1011 }
1012 }
1013
1014 CurrentEntry = CurrentEntry->Flink;
1015 }
1016
1017 KeReleaseSpinLockFromDpcLevel(&FdoDeviceExtension->DeviceListLock);
1018 CurrentBus = CurrentBus->Flink;
1019 }
1020 KeReleaseSpinLock(&DriverExtension->BusListLock, OldIrql);
1021
1022 return Found;
1023 }
1024
1025
1026 static BOOLEAN
1027 CheckPciDevice(
1028 IN PPCI_COMMON_CONFIG PciConfig,
1029 IN PPCI_DEVICE_PRESENCE_PARAMETERS Parameters)
1030 {
1031 if ((Parameters->Flags & PCI_USE_VENDEV_IDS) && (
1032 PciConfig->VendorID != Parameters->VendorID ||
1033 PciConfig->DeviceID != Parameters->DeviceID))
1034 {
1035 return FALSE;
1036 }
1037 if ((Parameters->Flags & PCI_USE_CLASS_SUBCLASS) && (
1038 PciConfig->BaseClass != Parameters->BaseClass ||
1039 PciConfig->SubClass != Parameters->SubClass))
1040 {
1041 return FALSE;
1042 }
1043 if ((Parameters->Flags & PCI_USE_PROGIF) &&
1044 PciConfig->ProgIf != Parameters->ProgIf)
1045 {
1046 return FALSE;
1047 }
1048 if ((Parameters->Flags & PCI_USE_SUBSYSTEM_IDS) && (
1049 PciConfig->u.type0.SubVendorID != Parameters->SubVendorID ||
1050 PciConfig->u.type0.SubSystemID != Parameters->SubSystemID))
1051 {
1052 return FALSE;
1053 }
1054 if ((Parameters->Flags & PCI_USE_REVISION) &&
1055 PciConfig->RevisionID != Parameters->RevisionID)
1056 {
1057 return FALSE;
1058 }
1059 return TRUE;
1060 }
1061
1062
1063 static BOOLEAN NTAPI
1064 InterfacePciDevicePresentEx(
1065 IN PVOID Context,
1066 IN PPCI_DEVICE_PRESENCE_PARAMETERS Parameters)
1067 {
1068 PPDO_DEVICE_EXTENSION DeviceExtension;
1069 PFDO_DEVICE_EXTENSION MyFdoDeviceExtension;
1070 PFDO_DEVICE_EXTENSION FdoDeviceExtension;
1071 PPCI_DEVICE PciDevice;
1072 PLIST_ENTRY CurrentBus, CurrentEntry;
1073 KIRQL OldIrql;
1074 BOOLEAN Found = FALSE;
1075
1076 DPRINT("InterfacePciDevicePresentEx(%p %p) called\n",
1077 Context, Parameters);
1078
1079 if (!Parameters || Parameters->Size != sizeof(PCI_DEVICE_PRESENCE_PARAMETERS))
1080 return FALSE;
1081
1082 DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
1083 MyFdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceExtension->Fdo->DeviceExtension;
1084
1085 if (Parameters->Flags & PCI_USE_LOCAL_DEVICE)
1086 {
1087 return CheckPciDevice(&DeviceExtension->PciDevice->PciConfig, Parameters);
1088 }
1089
1090 KeAcquireSpinLock(&DriverExtension->BusListLock, &OldIrql);
1091 CurrentBus = DriverExtension->BusListHead.Flink;
1092 while (!Found && CurrentBus != &DriverExtension->BusListHead)
1093 {
1094 FdoDeviceExtension = CONTAINING_RECORD(CurrentBus, FDO_DEVICE_EXTENSION, ListEntry);
1095 if (!(Parameters->Flags & PCI_USE_LOCAL_BUS) || FdoDeviceExtension == MyFdoDeviceExtension)
1096 {
1097 KeAcquireSpinLockAtDpcLevel(&FdoDeviceExtension->DeviceListLock);
1098 CurrentEntry = FdoDeviceExtension->DeviceListHead.Flink;
1099 while (!Found && CurrentEntry != &FdoDeviceExtension->DeviceListHead)
1100 {
1101 PciDevice = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry);
1102
1103 if (CheckPciDevice(&PciDevice->PciConfig, Parameters))
1104 {
1105 DPRINT("Found the PCI device\n");
1106 Found = TRUE;
1107 }
1108
1109 CurrentEntry = CurrentEntry->Flink;
1110 }
1111
1112 KeReleaseSpinLockFromDpcLevel(&FdoDeviceExtension->DeviceListLock);
1113 }
1114 CurrentBus = CurrentBus->Flink;
1115 }
1116 KeReleaseSpinLock(&DriverExtension->BusListLock, OldIrql);
1117
1118 return Found;
1119 }
1120
1121
1122 static NTSTATUS
1123 PdoQueryInterface(
1124 IN PDEVICE_OBJECT DeviceObject,
1125 IN PIRP Irp,
1126 PIO_STACK_LOCATION IrpSp)
1127 {
1128 NTSTATUS Status;
1129
1130 UNREFERENCED_PARAMETER(Irp);
1131 if (RtlCompareMemory(IrpSp->Parameters.QueryInterface.InterfaceType,
1132 &GUID_BUS_INTERFACE_STANDARD, sizeof(GUID)) == sizeof(GUID))
1133 {
1134 /* BUS_INTERFACE_STANDARD */
1135 if (IrpSp->Parameters.QueryInterface.Version < 1)
1136 Status = STATUS_NOT_SUPPORTED;
1137 else if (IrpSp->Parameters.QueryInterface.Size < sizeof(BUS_INTERFACE_STANDARD))
1138 Status = STATUS_BUFFER_TOO_SMALL;
1139 else
1140 {
1141 PBUS_INTERFACE_STANDARD BusInterface;
1142 BusInterface = (PBUS_INTERFACE_STANDARD)IrpSp->Parameters.QueryInterface.Interface;
1143 BusInterface->Size = sizeof(BUS_INTERFACE_STANDARD);
1144 BusInterface->Version = 1;
1145 BusInterface->TranslateBusAddress = InterfaceBusTranslateBusAddress;
1146 BusInterface->GetDmaAdapter = InterfaceBusGetDmaAdapter;
1147 BusInterface->SetBusData = InterfaceBusSetBusData;
1148 BusInterface->GetBusData = InterfaceBusGetBusData;
1149 Status = STATUS_SUCCESS;
1150 }
1151 }
1152 else if (RtlCompareMemory(IrpSp->Parameters.QueryInterface.InterfaceType,
1153 &GUID_PCI_DEVICE_PRESENT_INTERFACE, sizeof(GUID)) == sizeof(GUID))
1154 {
1155 /* PCI_DEVICE_PRESENT_INTERFACE */
1156 if (IrpSp->Parameters.QueryInterface.Version < 1)
1157 Status = STATUS_NOT_SUPPORTED;
1158 else if (IrpSp->Parameters.QueryInterface.Size < sizeof(PCI_DEVICE_PRESENT_INTERFACE))
1159 Status = STATUS_BUFFER_TOO_SMALL;
1160 else
1161 {
1162 PPCI_DEVICE_PRESENT_INTERFACE PciDevicePresentInterface;
1163 PciDevicePresentInterface = (PPCI_DEVICE_PRESENT_INTERFACE)IrpSp->Parameters.QueryInterface.Interface;
1164 PciDevicePresentInterface->Size = sizeof(PCI_DEVICE_PRESENT_INTERFACE);
1165 PciDevicePresentInterface->Version = 1;
1166 PciDevicePresentInterface->IsDevicePresent = InterfacePciDevicePresent;
1167 PciDevicePresentInterface->IsDevicePresentEx = InterfacePciDevicePresentEx;
1168 Status = STATUS_SUCCESS;
1169 }
1170 }
1171 else
1172 {
1173 /* Not a supported interface */
1174 return STATUS_NOT_SUPPORTED;
1175 }
1176
1177 if (NT_SUCCESS(Status))
1178 {
1179 /* Add a reference for the returned interface */
1180 PINTERFACE Interface;
1181 Interface = (PINTERFACE)IrpSp->Parameters.QueryInterface.Interface;
1182 Interface->Context = DeviceObject;
1183 Interface->InterfaceReference = InterfaceReference;
1184 Interface->InterfaceDereference = InterfaceDereference;
1185 Interface->InterfaceReference(Interface->Context);
1186 }
1187
1188 return Status;
1189 }
1190
1191 static NTSTATUS
1192 PdoStartDevice(
1193 IN PDEVICE_OBJECT DeviceObject,
1194 IN PIRP Irp,
1195 PIO_STACK_LOCATION IrpSp)
1196 {
1197 PCM_RESOURCE_LIST RawResList = IrpSp->Parameters.StartDevice.AllocatedResources;
1198 PCM_FULL_RESOURCE_DESCRIPTOR RawFullDesc;
1199 PCM_PARTIAL_RESOURCE_DESCRIPTOR RawPartialDesc;
1200 ULONG i, ii;
1201 PPDO_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
1202 UCHAR Irq;
1203
1204 if (!RawResList)
1205 return STATUS_SUCCESS;
1206
1207 /* TODO: Assign the other resources we get to the card */
1208
1209 for (i = 0; i < RawResList->Count; i++)
1210 {
1211 RawFullDesc = &RawResList->List[i];
1212
1213 for (ii = 0; ii < RawFullDesc->PartialResourceList.Count; ii++)
1214 {
1215 RawPartialDesc = &RawFullDesc->PartialResourceList.PartialDescriptors[ii];
1216
1217 if (RawPartialDesc->Type == CmResourceTypeInterrupt)
1218 {
1219 DPRINT1("Assigning IRQ %x to PCI device (%x, %x)\n",
1220 RawPartialDesc->u.Interrupt.Vector,
1221 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
1222 DeviceExtension->PciDevice->BusNumber);
1223
1224 Irq = (UCHAR)RawPartialDesc->u.Interrupt.Vector;
1225 HalSetBusDataByOffset(PCIConfiguration,
1226 DeviceExtension->PciDevice->BusNumber,
1227 DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
1228 &Irq,
1229 0x3c /* PCI_INTERRUPT_LINE */,
1230 sizeof(UCHAR));
1231 }
1232 }
1233 }
1234
1235 return STATUS_SUCCESS;
1236 }
1237
1238 static NTSTATUS
1239 PdoReadConfig(
1240 IN PDEVICE_OBJECT DeviceObject,
1241 IN PIRP Irp,
1242 PIO_STACK_LOCATION IrpSp)
1243 {
1244 ULONG Size;
1245
1246 DPRINT("PdoReadConfig() called\n");
1247
1248 Size = InterfaceBusGetBusData(
1249 DeviceObject,
1250 IrpSp->Parameters.ReadWriteConfig.WhichSpace,
1251 IrpSp->Parameters.ReadWriteConfig.Buffer,
1252 IrpSp->Parameters.ReadWriteConfig.Offset,
1253 IrpSp->Parameters.ReadWriteConfig.Length);
1254
1255 if (Size != IrpSp->Parameters.ReadWriteConfig.Length)
1256 {
1257 DPRINT1("Size %lu Length %lu\n", Size, IrpSp->Parameters.ReadWriteConfig.Length);
1258 Irp->IoStatus.Information = 0;
1259 return STATUS_UNSUCCESSFUL;
1260 }
1261
1262 Irp->IoStatus.Information = Size;
1263
1264 return STATUS_SUCCESS;
1265 }
1266
1267
1268 static NTSTATUS
1269 PdoWriteConfig(
1270 IN PDEVICE_OBJECT DeviceObject,
1271 IN PIRP Irp,
1272 PIO_STACK_LOCATION IrpSp)
1273 {
1274 ULONG Size;
1275
1276 DPRINT1("PdoWriteConfig() called\n");
1277
1278 /* Get PCI configuration space */
1279 Size = InterfaceBusSetBusData(
1280 DeviceObject,
1281 IrpSp->Parameters.ReadWriteConfig.WhichSpace,
1282 IrpSp->Parameters.ReadWriteConfig.Buffer,
1283 IrpSp->Parameters.ReadWriteConfig.Offset,
1284 IrpSp->Parameters.ReadWriteConfig.Length);
1285
1286 if (Size != IrpSp->Parameters.ReadWriteConfig.Length)
1287 {
1288 DPRINT1("Size %lu Length %lu\n", Size, IrpSp->Parameters.ReadWriteConfig.Length);
1289 Irp->IoStatus.Information = 0;
1290 return STATUS_UNSUCCESSFUL;
1291 }
1292
1293 Irp->IoStatus.Information = Size;
1294
1295 return STATUS_SUCCESS;
1296 }
1297
1298 static NTSTATUS
1299 PdoQueryDeviceRelations(
1300 IN PDEVICE_OBJECT DeviceObject,
1301 IN PIRP Irp,
1302 PIO_STACK_LOCATION IrpSp)
1303 {
1304 PDEVICE_RELATIONS DeviceRelations;
1305
1306 /* We only support TargetDeviceRelation for child PDOs */
1307 if (IrpSp->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
1308 return Irp->IoStatus.Status;
1309
1310 /* We can do this because we only return 1 PDO for TargetDeviceRelation */
1311 DeviceRelations = ExAllocatePool(PagedPool, sizeof(*DeviceRelations));
1312 if (!DeviceRelations)
1313 return STATUS_INSUFFICIENT_RESOURCES;
1314
1315 DeviceRelations->Count = 1;
1316 DeviceRelations->Objects[0] = DeviceObject;
1317
1318 /* The PnP manager will remove this when it is done with the PDO */
1319 ObReferenceObject(DeviceObject);
1320
1321 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
1322
1323 return STATUS_SUCCESS;
1324 }
1325
1326 static NTSTATUS
1327 PdoSetPower(
1328 IN PDEVICE_OBJECT DeviceObject,
1329 IN PIRP Irp,
1330 PIO_STACK_LOCATION IrpSp)
1331 {
1332 PPDO_DEVICE_EXTENSION DeviceExtension;
1333 NTSTATUS Status;
1334
1335 UNREFERENCED_PARAMETER(Irp);
1336 DPRINT("Called\n");
1337
1338 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1339
1340 if (IrpSp->Parameters.Power.Type == DevicePowerState) {
1341 Status = STATUS_SUCCESS;
1342 switch (IrpSp->Parameters.Power.State.SystemState) {
1343 default:
1344 Status = STATUS_UNSUCCESSFUL;
1345 }
1346 } else {
1347 Status = STATUS_UNSUCCESSFUL;
1348 }
1349
1350 return Status;
1351 }
1352
1353
1354 /*** PUBLIC ******************************************************************/
1355
1356 NTSTATUS
1357 PdoPnpControl(
1358 PDEVICE_OBJECT DeviceObject,
1359 PIRP Irp)
1360 /*
1361 * FUNCTION: Handle Plug and Play IRPs for the child device
1362 * ARGUMENTS:
1363 * DeviceObject = Pointer to physical device object of the child device
1364 * Irp = Pointer to IRP that should be handled
1365 * RETURNS:
1366 * Status
1367 */
1368 {
1369 PIO_STACK_LOCATION IrpSp;
1370 NTSTATUS Status;
1371
1372 DPRINT("Called\n");
1373
1374 Status = Irp->IoStatus.Status;
1375
1376 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1377
1378 switch (IrpSp->MinorFunction) {
1379
1380 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
1381 DPRINT("Unimplemented IRP_MN_DEVICE_USAGE_NOTIFICATION received\n");
1382 break;
1383
1384 case IRP_MN_EJECT:
1385 DPRINT("Unimplemented IRP_MN_EJECT received\n");
1386 break;
1387
1388 case IRP_MN_QUERY_BUS_INFORMATION:
1389 Status = PdoQueryBusInformation(DeviceObject, Irp, IrpSp);
1390 break;
1391
1392 case IRP_MN_QUERY_CAPABILITIES:
1393 Status = PdoQueryCapabilities(DeviceObject, Irp, IrpSp);
1394 break;
1395
1396 case IRP_MN_QUERY_DEVICE_RELATIONS:
1397 Status = PdoQueryDeviceRelations(DeviceObject, Irp, IrpSp);
1398 break;
1399
1400 case IRP_MN_QUERY_DEVICE_TEXT:
1401 DPRINT("IRP_MN_QUERY_DEVICE_TEXT received\n");
1402 Status = PdoQueryDeviceText(DeviceObject, Irp, IrpSp);
1403 break;
1404
1405 case IRP_MN_QUERY_ID:
1406 DPRINT("IRP_MN_QUERY_ID received\n");
1407 Status = PdoQueryId(DeviceObject, Irp, IrpSp);
1408 break;
1409
1410 case IRP_MN_QUERY_PNP_DEVICE_STATE:
1411 DPRINT("Unimplemented IRP_MN_QUERY_ID received\n");
1412 break;
1413
1414 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
1415 DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS received\n");
1416 Status = PdoQueryResourceRequirements(DeviceObject, Irp, IrpSp);
1417 break;
1418
1419 case IRP_MN_QUERY_RESOURCES:
1420 DPRINT("IRP_MN_QUERY_RESOURCES received\n");
1421 Status = PdoQueryResources(DeviceObject, Irp, IrpSp);
1422 break;
1423
1424 case IRP_MN_SET_LOCK:
1425 DPRINT("Unimplemented IRP_MN_SET_LOCK received\n");
1426 break;
1427
1428 case IRP_MN_START_DEVICE:
1429 Status = PdoStartDevice(DeviceObject, Irp, IrpSp);
1430 break;
1431
1432 case IRP_MN_QUERY_STOP_DEVICE:
1433 case IRP_MN_CANCEL_STOP_DEVICE:
1434 case IRP_MN_STOP_DEVICE:
1435 case IRP_MN_QUERY_REMOVE_DEVICE:
1436 case IRP_MN_CANCEL_REMOVE_DEVICE:
1437 case IRP_MN_REMOVE_DEVICE:
1438 case IRP_MN_SURPRISE_REMOVAL:
1439 Status = STATUS_SUCCESS;
1440 break;
1441
1442 case IRP_MN_QUERY_INTERFACE:
1443 DPRINT("IRP_MN_QUERY_INTERFACE received\n");
1444 Status = PdoQueryInterface(DeviceObject, Irp, IrpSp);
1445 break;
1446
1447 case IRP_MN_READ_CONFIG:
1448 DPRINT("IRP_MN_READ_CONFIG received\n");
1449 Status = PdoReadConfig(DeviceObject, Irp, IrpSp);
1450 break;
1451
1452 case IRP_MN_WRITE_CONFIG:
1453 DPRINT("IRP_MN_WRITE_CONFIG received\n");
1454 Status = PdoWriteConfig(DeviceObject, Irp, IrpSp);
1455 break;
1456
1457 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
1458 DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS received\n");
1459 /* Nothing to do */
1460 Irp->IoStatus.Status = Status;
1461 break;
1462
1463 default:
1464 DPRINT1("Unknown IOCTL 0x%lx\n", IrpSp->MinorFunction);
1465 break;
1466 }
1467
1468 if (Status != STATUS_PENDING) {
1469 Irp->IoStatus.Status = Status;
1470 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1471 }
1472
1473 DPRINT("Leaving. Status 0x%X\n", Status);
1474
1475 return Status;
1476 }
1477
1478 NTSTATUS
1479 PdoPowerControl(
1480 PDEVICE_OBJECT DeviceObject,
1481 PIRP Irp)
1482 /*
1483 * FUNCTION: Handle power management IRPs for the child device
1484 * ARGUMENTS:
1485 * DeviceObject = Pointer to physical device object of the child device
1486 * Irp = Pointer to IRP that should be handled
1487 * RETURNS:
1488 * Status
1489 */
1490 {
1491 PIO_STACK_LOCATION IrpSp;
1492 NTSTATUS Status;
1493
1494 DPRINT("Called\n");
1495
1496 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1497
1498 switch (IrpSp->MinorFunction) {
1499 case IRP_MN_SET_POWER:
1500 Status = PdoSetPower(DeviceObject, Irp, IrpSp);
1501 break;
1502
1503 default:
1504 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
1505 Status = STATUS_NOT_IMPLEMENTED;
1506 break;
1507 }
1508
1509 if (Status != STATUS_PENDING) {
1510 Irp->IoStatus.Status = Status;
1511 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1512 }
1513
1514 DPRINT("Leaving. Status 0x%X\n", Status);
1515
1516 return Status;
1517 }
1518
1519 /* EOF */