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