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