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