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