1 /* 2 * PROJECT: ReactOS HAL 3 * LICENSE: BSD - See COPYING.ARM in the top level directory 4 * FILE: hal/halx86/legacy/bussupp.c 5 * PURPOSE: HAL Legacy Bus Support Code 6 * PROGRAMMERS: ReactOS Portable Systems Group 7 */ 8 9 /* INCLUDES *******************************************************************/ 10 11 #include <hal.h> 12 #define NDEBUG 13 #include <debug.h> 14 15 CODE_SEG("INIT") 16 PBUS_HANDLER 17 NTAPI 18 HalpAllocateAndInitPciBusHandler( 19 IN ULONG PciType, 20 IN ULONG BusNo, 21 IN BOOLEAN TestAllocation 22 ); 23 24 CODE_SEG("INIT") 25 VOID 26 NTAPI 27 HalpFixupPciSupportedRanges( 28 IN ULONG BusCount 29 ); 30 31 CODE_SEG("INIT") 32 NTSTATUS 33 NTAPI 34 HalpGetChipHacks( 35 IN USHORT VendorId, 36 IN USHORT DeviceId, 37 IN UCHAR RevisionId, 38 IN PULONG HackFlags 39 ); 40 41 CODE_SEG("INIT") 42 BOOLEAN 43 NTAPI 44 HalpGetPciBridgeConfig( 45 IN ULONG PciType, 46 IN PUCHAR BusCount 47 ); 48 49 CODE_SEG("INIT") 50 BOOLEAN 51 NTAPI 52 HalpIsBridgeDevice( 53 IN PPCI_COMMON_CONFIG PciData 54 ); 55 56 CODE_SEG("INIT") 57 BOOLEAN 58 NTAPI 59 HalpIsIdeDevice( 60 IN PPCI_COMMON_CONFIG PciData 61 ); 62 63 CODE_SEG("INIT") 64 BOOLEAN 65 NTAPI 66 HalpIsRecognizedCard( 67 IN PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo, 68 IN PPCI_COMMON_CONFIG PciData, 69 IN ULONG Flags 70 ); 71 72 CODE_SEG("INIT") 73 BOOLEAN 74 NTAPI 75 HalpIsValidPCIDevice( 76 IN PBUS_HANDLER BusHandler, 77 IN PCI_SLOT_NUMBER Slot 78 ); 79 80 CODE_SEG("INIT") 81 NTSTATUS 82 NTAPI 83 HalpMarkChipsetDecode( 84 IN BOOLEAN OverrideEnable 85 ); 86 87 CODE_SEG("INIT") 88 VOID 89 NTAPI 90 HalpRegisterInternalBusHandlers( 91 VOID 92 ); 93 94 CODE_SEG("INIT") 95 VOID 96 NTAPI 97 ShowSize( 98 IN ULONG Size 99 ); 100 101 /* GLOBALS ********************************************************************/ 102 103 extern KSPIN_LOCK HalpPCIConfigLock; 104 ULONG HalpPciIrqMask; 105 106 /* PRIVATE FUNCTIONS **********************************************************/ 107 108 PBUS_HANDLER 109 NTAPI 110 HalpAllocateBusHandler(IN INTERFACE_TYPE InterfaceType, 111 IN BUS_DATA_TYPE BusDataType, 112 IN ULONG BusNumber, 113 IN INTERFACE_TYPE ParentBusInterfaceType, 114 IN ULONG ParentBusNumber, 115 IN ULONG BusSpecificData) 116 { 117 PBUS_HANDLER Bus; 118 119 /* Register the bus handler */ 120 HalRegisterBusHandler(InterfaceType, 121 BusDataType, 122 BusNumber, 123 ParentBusInterfaceType, 124 ParentBusNumber, 125 BusSpecificData, 126 NULL, 127 &Bus); 128 if (!Bus) 129 { 130 return NULL; 131 } 132 133 /* Check for a valid interface */ 134 if (InterfaceType != InterfaceTypeUndefined) 135 { 136 /* Allocate address ranges and zero them out */ 137 Bus->BusAddresses = ExAllocatePoolWithTag(NonPagedPoolMustSucceed, 138 sizeof(SUPPORTED_RANGES), 139 TAG_HAL); 140 RtlZeroMemory(Bus->BusAddresses, sizeof(SUPPORTED_RANGES)); 141 142 /* Build the data structure */ 143 Bus->BusAddresses->Version = HAL_SUPPORTED_RANGE_VERSION; 144 Bus->BusAddresses->Dma.Limit = 7; 145 Bus->BusAddresses->Memory.Limit = 0xFFFFFFFF; 146 Bus->BusAddresses->IO.Limit = 0xFFFF; 147 Bus->BusAddresses->IO.SystemAddressSpace = 1; 148 Bus->BusAddresses->PrefetchMemory.Base = 1; 149 } 150 151 /* Return the bus address */ 152 return Bus; 153 } 154 155 #ifndef _MINIHAL_ 156 CODE_SEG("INIT") 157 VOID 158 NTAPI 159 HalpRegisterInternalBusHandlers(VOID) 160 { 161 PBUS_HANDLER Bus; 162 163 /* Only do processor 1 */ 164 if (KeGetCurrentPrcb()->Number) return; 165 166 /* Register root support */ 167 HalpInitBusHandler(); 168 169 /* Allocate the system bus */ 170 Bus = HalpAllocateBusHandler(Internal, 171 ConfigurationSpaceUndefined, 172 0, 173 InterfaceTypeUndefined, 174 0, 175 0); 176 if (Bus) 177 { 178 /* Set it up */ 179 Bus->GetInterruptVector = HalpGetSystemInterruptVector; 180 Bus->TranslateBusAddress = HalpTranslateSystemBusAddress; 181 } 182 183 /* Allocate the CMOS bus */ 184 Bus = HalpAllocateBusHandler(InterfaceTypeUndefined, 185 Cmos, 186 0, 187 InterfaceTypeUndefined, 188 0, 189 0); 190 if (Bus) 191 { 192 /* Set it up */ 193 Bus->GetBusData = HalpcGetCmosData; 194 Bus->SetBusData = HalpcSetCmosData; 195 } 196 197 /* Allocate the CMOS bus */ 198 Bus = HalpAllocateBusHandler(InterfaceTypeUndefined, 199 Cmos, 200 1, 201 InterfaceTypeUndefined, 202 0, 203 0); 204 if (Bus) 205 { 206 /* Set it up */ 207 Bus->GetBusData = HalpcGetCmosData; 208 Bus->SetBusData = HalpcSetCmosData; 209 } 210 211 /* Allocate ISA bus */ 212 Bus = HalpAllocateBusHandler(Isa, 213 ConfigurationSpaceUndefined, 214 0, 215 Internal, 216 0, 217 0); 218 if (Bus) 219 { 220 /* Set it up */ 221 Bus->GetBusData = HalpNoBusData; 222 Bus->BusAddresses->Memory.Limit = 0xFFFFFF; 223 Bus->TranslateBusAddress = HalpTranslateIsaBusAddress; 224 } 225 226 /* No support for EISA or MCA */ 227 ASSERT(HalpBusType == MACHINE_TYPE_ISA); 228 } 229 #endif // _MINIHAL_ 230 231 #ifndef _MINIHAL_ 232 CODE_SEG("INIT") 233 NTSTATUS 234 NTAPI 235 HalpMarkChipsetDecode(BOOLEAN OverrideEnable) 236 { 237 NTSTATUS Status; 238 UNICODE_STRING KeyString; 239 ULONG Data = OverrideEnable; 240 HANDLE KeyHandle, Handle; 241 242 /* Open CCS key */ 243 RtlInitUnicodeString(&KeyString, 244 L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET"); 245 Status = HalpOpenRegistryKey(&Handle, 0, &KeyString, KEY_ALL_ACCESS, FALSE); 246 if (NT_SUCCESS(Status)) 247 { 248 /* Open PNP Bios key */ 249 RtlInitUnicodeString(&KeyString, L"Control\\Biosinfo\\PNPBios"); 250 Status = HalpOpenRegistryKey(&KeyHandle, 251 Handle, 252 &KeyString, 253 KEY_ALL_ACCESS, 254 TRUE); 255 256 /* Close root key */ 257 ZwClose(Handle); 258 259 /* Check if PNP BIOS key exists */ 260 if (NT_SUCCESS(Status)) 261 { 262 /* Set the override value */ 263 RtlInitUnicodeString(&KeyString, L"FullDecodeChipsetOverride"); 264 Status = ZwSetValueKey(KeyHandle, 265 &KeyString, 266 0, 267 REG_DWORD, 268 &Data, 269 sizeof(Data)); 270 271 /* Close subkey */ 272 ZwClose(KeyHandle); 273 } 274 } 275 276 /* Return status */ 277 return Status; 278 } 279 280 CODE_SEG("INIT") 281 PBUS_HANDLER 282 NTAPI 283 HalpAllocateAndInitPciBusHandler(IN ULONG PciType, 284 IN ULONG BusNo, 285 IN BOOLEAN TestAllocation) 286 { 287 PBUS_HANDLER Bus; 288 PPCIPBUSDATA BusData; 289 290 /* Allocate the bus handler */ 291 Bus = HalpAllocateBusHandler(PCIBus, 292 PCIConfiguration, 293 BusNo, 294 Internal, 295 0, 296 sizeof(PCIPBUSDATA)); 297 298 /* Set it up */ 299 Bus->GetBusData = HalpGetPCIData; 300 Bus->SetBusData = HalpSetPCIData; 301 Bus->GetInterruptVector = HalpGetPCIIntOnISABus; 302 Bus->AdjustResourceList = HalpAdjustPCIResourceList; 303 Bus->AssignSlotResources = HalpAssignPCISlotResources; 304 Bus->BusAddresses->Dma.Limit = 0; 305 306 /* Get our custom bus data */ 307 BusData = (PPCIPBUSDATA)Bus->BusData; 308 309 /* Setup custom bus data */ 310 BusData->CommonData.Tag = PCI_DATA_TAG; 311 BusData->CommonData.Version = PCI_DATA_VERSION; 312 BusData->CommonData.ReadConfig = HalpReadPCIConfig; 313 BusData->CommonData.WriteConfig = HalpWritePCIConfig; 314 BusData->CommonData.Pin2Line = HalpPCIPin2ISALine; 315 BusData->CommonData.Line2Pin = HalpPCIISALine2Pin; 316 BusData->MaxDevice = PCI_MAX_DEVICES; 317 BusData->GetIrqRange = HalpGetISAFixedPCIIrq; 318 319 /* Initialize the bitmap */ 320 RtlInitializeBitMap(&BusData->DeviceConfigured, BusData->ConfiguredBits, 256); 321 322 /* Check the type of PCI bus */ 323 switch (PciType) 324 { 325 /* Type 1 PCI Bus */ 326 case 1: 327 328 /* Copy the Type 1 handler data */ 329 RtlCopyMemory(&PCIConfigHandler, 330 &PCIConfigHandlerType1, 331 sizeof(PCIConfigHandler)); 332 333 /* Set correct I/O Ports */ 334 BusData->Config.Type1.Address = PCI_TYPE1_ADDRESS_PORT; 335 BusData->Config.Type1.Data = PCI_TYPE1_DATA_PORT; 336 break; 337 338 /* Type 2 PCI Bus */ 339 case 2: 340 341 /* Copy the Type 1 handler data */ 342 RtlCopyMemory(&PCIConfigHandler, 343 &PCIConfigHandlerType2, 344 sizeof (PCIConfigHandler)); 345 346 /* Set correct I/O Ports */ 347 BusData->Config.Type2.CSE = PCI_TYPE2_CSE_PORT; 348 BusData->Config.Type2.Forward = PCI_TYPE2_FORWARD_PORT; 349 BusData->Config.Type2.Base = PCI_TYPE2_ADDRESS_BASE; 350 351 /* Only 16 devices supported, not 32 */ 352 BusData->MaxDevice = 16; 353 break; 354 355 default: 356 357 /* Invalid type */ 358 DbgPrint("HAL: Unknown PCI type\n"); 359 } 360 361 /* Return the bus handler */ 362 return Bus; 363 } 364 365 CODE_SEG("INIT") 366 BOOLEAN 367 NTAPI 368 HalpIsValidPCIDevice(IN PBUS_HANDLER BusHandler, 369 IN PCI_SLOT_NUMBER Slot) 370 { 371 UCHAR DataBuffer[PCI_COMMON_HDR_LENGTH]; 372 PPCI_COMMON_CONFIG PciHeader = (PVOID)DataBuffer; 373 ULONG i; 374 ULONG_PTR Address; 375 376 /* Read the PCI header */ 377 HalpReadPCIConfig(BusHandler, Slot, PciHeader, 0, PCI_COMMON_HDR_LENGTH); 378 379 /* Make sure it's a valid device */ 380 if ((PciHeader->VendorID == PCI_INVALID_VENDORID) || 381 (PCI_CONFIGURATION_TYPE(PciHeader) != PCI_DEVICE_TYPE)) 382 { 383 /* Bail out */ 384 return FALSE; 385 } 386 387 /* Make sure interrupt numbers make sense */ 388 if (((PciHeader->u.type0.InterruptPin) && 389 (PciHeader->u.type0.InterruptPin > 4)) || 390 (PciHeader->u.type0.InterruptLine & 0x70)) 391 { 392 /* Bail out */ 393 return FALSE; 394 } 395 396 /* Now scan PCI BARs */ 397 for (i = 0; i < PCI_TYPE0_ADDRESSES; i++) 398 { 399 /* Check what kind of address it is */ 400 Address = PciHeader->u.type0.BaseAddresses[i]; 401 if (Address & PCI_ADDRESS_IO_SPACE) 402 { 403 /* Highest I/O port is 65535 */ 404 if (Address > 0xFFFF) return FALSE; 405 } 406 else 407 { 408 /* MMIO should be higher than 0x80000 */ 409 if ((Address > 0xF) && (Address < 0x80000)) return FALSE; 410 } 411 412 /* Is this a 64-bit address? */ 413 if (!(Address & PCI_ADDRESS_IO_SPACE) && 414 ((Address & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT)) 415 { 416 /* Check the next-next entry, since this one 64-bits wide */ 417 i++; 418 } 419 } 420 421 /* Header, interrupt and address data all make sense */ 422 return TRUE; 423 } 424 425 static BOOLEAN WarningsGiven[5]; 426 427 CODE_SEG("INIT") 428 NTSTATUS 429 NTAPI 430 HalpGetChipHacks(IN USHORT VendorId, 431 IN USHORT DeviceId, 432 IN UCHAR RevisionId, 433 IN PULONG HackFlags) 434 { 435 UNICODE_STRING KeyName, ValueName; 436 NTSTATUS Status; 437 OBJECT_ATTRIBUTES ObjectAttributes; 438 HANDLE KeyHandle; 439 WCHAR Buffer[32]; 440 KEY_VALUE_PARTIAL_INFORMATION PartialInfo; 441 ULONG ResultLength; 442 443 /* Setup the object attributes for the key */ 444 RtlInitUnicodeString(&KeyName, 445 L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\" 446 L"Control\\HAL"); 447 InitializeObjectAttributes(&ObjectAttributes, 448 &KeyName, 449 OBJ_CASE_INSENSITIVE, 450 NULL, 451 NULL); 452 453 /* Open the key */ 454 Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes); 455 if (!NT_SUCCESS(Status)) return Status; 456 457 /* Query value */ 458 swprintf(Buffer, L"%04X%04X", VendorId, DeviceId); 459 RtlInitUnicodeString(&ValueName, Buffer); 460 Status = ZwQueryValueKey(KeyHandle, 461 &ValueName, 462 KeyValuePartialInformation, 463 &PartialInfo, 464 sizeof(PartialInfo), 465 &ResultLength); 466 if (NT_SUCCESS(Status)) 467 { 468 /* Return the flags */ 469 DbgPrint("\tFound HackFlags for your chipset\n"); 470 *HackFlags = *(PULONG)PartialInfo.Data; 471 DbgPrint("\t\tHack Flags: %lx (Hack Revision: %lx-Your Revision: %lx)\n", 472 *HackFlags, HALP_REVISION_FROM_HACK_FLAGS(*HackFlags), RevisionId); 473 474 /* Does it apply to this revision? */ 475 if ((RevisionId) && (RevisionId >= (HALP_REVISION_FROM_HACK_FLAGS(*HackFlags)))) 476 { 477 /* Read the revision flags */ 478 *HackFlags = HALP_REVISION_HACK_FLAGS(*HackFlags); 479 } 480 481 /* Throw out revision data */ 482 *HackFlags = HALP_HACK_FLAGS(*HackFlags); 483 if (!*HackFlags) DbgPrint("\tNo HackFlags for your chipset's revision!\n"); 484 } 485 486 /* Close the handle and return */ 487 ZwClose(KeyHandle); 488 return Status; 489 } 490 491 CODE_SEG("INIT") 492 BOOLEAN 493 NTAPI 494 HalpIsRecognizedCard(IN PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo, 495 IN PPCI_COMMON_CONFIG PciData, 496 IN ULONG Flags) 497 { 498 ULONG ElementCount, i; 499 PPCI_CARD_DESCRIPTOR CardDescriptor; 500 501 /* How many PCI Cards that we know about? */ 502 ElementCount = PciRegistryInfo->ElementCount; 503 if (!ElementCount) return FALSE; 504 505 /* Loop all descriptors */ 506 CardDescriptor = &PciRegistryInfo->CardList[0]; 507 for (i = 0; i < ElementCount; i++, CardDescriptor++) 508 { 509 /* Check for flag match */ 510 if (CardDescriptor->Flags != Flags) continue; 511 512 /* Check for VID-PID match */ 513 if ((CardDescriptor->VendorID != PciData->VendorID) || 514 (CardDescriptor->DeviceID != PciData->DeviceID)) 515 { 516 /* Skip */ 517 continue; 518 } 519 520 /* Check for revision match, if requested */ 521 if ((CardDescriptor->Flags & HALP_CHECK_CARD_REVISION_ID) && 522 (CardDescriptor->RevisionID != PciData->RevisionID)) 523 { 524 /* Skip */ 525 continue; 526 } 527 528 /* Check what kind of device this is */ 529 switch (PCI_CONFIGURATION_TYPE(PciData)) 530 { 531 /* CardBUS Bridge */ 532 case PCI_CARDBUS_BRIDGE_TYPE: 533 534 /* This means the real device header is in the device-specific data */ 535 PciData = (PPCI_COMMON_CONFIG)PciData->DeviceSpecific; 536 537 /* Normal PCI device */ 538 case PCI_DEVICE_TYPE: 539 540 /* Check for subvendor match, if requested */ 541 if ((CardDescriptor->Flags & HALP_CHECK_CARD_SUBVENDOR_ID) && 542 (CardDescriptor->SubsystemVendorID != PciData->u.type0.SubVendorID)) 543 { 544 /* Skip */ 545 continue; 546 } 547 548 /* Check for subsystem match, if requested */ 549 if ((CardDescriptor->Flags & HALP_CHECK_CARD_SUBSYSTEM_ID) && 550 (CardDescriptor->SubsystemID != PciData->u.type0.SubSystemID)) 551 { 552 /* Skip */ 553 continue; 554 } 555 556 /* You made it! */ 557 return TRUE; 558 559 /* PCI Bridge -- don't bother */ 560 case PCI_BRIDGE_TYPE: 561 default: 562 563 /* Recognize it */ 564 return TRUE; 565 } 566 } 567 568 /* This means the card isn't recognized */ 569 return FALSE; 570 } 571 572 CODE_SEG("INIT") 573 BOOLEAN 574 NTAPI 575 HalpIsIdeDevice(IN PPCI_COMMON_CONFIG PciData) 576 { 577 /* Simple test first */ 578 if ((PciData->BaseClass == PCI_CLASS_MASS_STORAGE_CTLR) && 579 (PciData->SubClass == PCI_SUBCLASS_MSC_IDE_CTLR)) 580 { 581 /* The device is nice enough to admit it */ 582 return TRUE; 583 } 584 585 /* Symphony 82C101 */ 586 if (PciData->VendorID == 0x1C1C) return TRUE; 587 588 /* ALi MS4803 or M5219 */ 589 if ((PciData->VendorID == 0x10B9) && 590 ((PciData->DeviceID == 0x5215) || (PciData->DeviceID == 0x5219))) 591 { 592 return TRUE; 593 } 594 595 /* Appian Technology */ 596 if ((PciData->VendorID == 0x1097) && (PciData->DeviceID == 0x38)) return TRUE; 597 598 /* Compaq Triflex Dual EIDE Controller */ 599 if ((PciData->VendorID == 0xE11) && (PciData->DeviceID == 0xAE33)) return TRUE; 600 601 /* Micron PC Tech RZ1000 */ 602 if ((PciData->VendorID == 0x1042) && (PciData->DeviceID == 0x1000)) return TRUE; 603 604 /* SiS 85C601 or 5513 [IDE] */ 605 if ((PciData->VendorID == 0x1039) && 606 ((PciData->DeviceID == 0x601) || (PciData->DeviceID == 0x5513))) 607 { 608 return TRUE; 609 } 610 611 /* Symphony Labs W83769F */ 612 if ((PciData->VendorID == 0x10AD) && 613 ((PciData->DeviceID == 0x1) || (PciData->DeviceID == 0x150))) 614 { 615 return TRUE; 616 } 617 618 /* UMC UM8673F */ 619 if ((PciData->VendorID == 0x1060) && (PciData->DeviceID == 0x101)) return TRUE; 620 621 /* You've survived */ 622 return FALSE; 623 } 624 625 CODE_SEG("INIT") 626 BOOLEAN 627 NTAPI 628 HalpIsBridgeDevice(IN PPCI_COMMON_CONFIG PciData) 629 { 630 /* Either this is a PCI-to-PCI Bridge, or a CardBUS Bridge */ 631 return (((PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE) && 632 (PciData->BaseClass == PCI_CLASS_BRIDGE_DEV) && 633 (PciData->SubClass == PCI_SUBCLASS_BR_PCI_TO_PCI)) || 634 ((PCI_CONFIGURATION_TYPE(PciData) == PCI_CARDBUS_BRIDGE_TYPE) && 635 (PciData->BaseClass == PCI_CLASS_BRIDGE_DEV) && 636 (PciData->SubClass == PCI_SUBCLASS_BR_CARDBUS))); 637 } 638 639 CODE_SEG("INIT") 640 BOOLEAN 641 NTAPI 642 HalpGetPciBridgeConfig(IN ULONG PciType, 643 IN PUCHAR BusCount) 644 { 645 PCI_SLOT_NUMBER PciSlot; 646 ULONG i, j, k; 647 UCHAR DataBuffer[PCI_COMMON_HDR_LENGTH]; 648 PPCI_COMMON_CONFIG PciData = (PPCI_COMMON_CONFIG)DataBuffer; 649 PBUS_HANDLER BusHandler; 650 651 /* Loop PCI buses */ 652 PciSlot.u.bits.Reserved = 0; 653 for (i = 0; i < *BusCount; i++) 654 { 655 /* Get the bus handler */ 656 BusHandler = HalHandlerForBus(PCIBus, i); 657 658 /* Loop every device */ 659 for (j = 0; j < PCI_MAX_DEVICES; j++) 660 { 661 /* Loop every function */ 662 PciSlot.u.bits.DeviceNumber = j; 663 for (k = 0; k < PCI_MAX_FUNCTION; k++) 664 { 665 /* Build the final slot structure */ 666 PciSlot.u.bits.FunctionNumber = k; 667 668 /* Read the configuration information */ 669 HalpReadPCIConfig(BusHandler, 670 PciSlot, 671 PciData, 672 0, 673 PCI_COMMON_HDR_LENGTH); 674 675 /* Skip if this is an invalid function */ 676 if (PciData->VendorID == PCI_INVALID_VENDORID) continue; 677 678 /* Make sure that this is a PCI bridge or a cardbus bridge */ 679 if (!HalpIsBridgeDevice(PciData)) continue; 680 681 /* Not supported */ 682 if (!WarningsGiven[2]++) 683 DPRINT1("Your machine has a PCI-to-PCI or CardBUS Bridge. PCI devices may fail!\n"); 684 continue; 685 } 686 } 687 } 688 689 /* If we exited the loop, then there's no bridge to worry about */ 690 return FALSE; 691 } 692 693 CODE_SEG("INIT") 694 VOID 695 NTAPI 696 HalpFixupPciSupportedRanges(IN ULONG BusCount) 697 { 698 ULONG i; 699 PBUS_HANDLER Bus, ParentBus; 700 701 /* Loop all buses */ 702 for (i = 0; i < BusCount; i++) 703 { 704 /* Get PCI bus handler */ 705 Bus = HalHandlerForBus(PCIBus, i); 706 707 /* Loop all parent buses */ 708 ParentBus = Bus->ParentHandler; 709 while (ParentBus) 710 { 711 /* Should merge addresses */ 712 if (!WarningsGiven[0]++) 713 DPRINT1("Found parent bus (indicating PCI Bridge). PCI devices may fail!\n"); 714 715 /* Check the next parent */ 716 ParentBus = ParentBus->ParentHandler; 717 } 718 } 719 720 /* Loop all buses again */ 721 for (i = 0; i < BusCount; i++) 722 { 723 /* Get PCI bus handler */ 724 Bus = HalHandlerForBus(PCIBus, i); 725 726 /* Check if this is a PCI 2.2 Bus with Subtractive Decode */ 727 if (!((PPCIPBUSDATA)Bus->BusData)->Subtractive) 728 { 729 /* Loop all parent buses */ 730 ParentBus = Bus->ParentHandler; 731 while (ParentBus) 732 { 733 /* But check only PCI parent buses specifically */ 734 if (ParentBus->InterfaceType == PCIBus) 735 { 736 /* Should trim addresses */ 737 if (!WarningsGiven[1]++) 738 DPRINT1("Found parent PCI Bus (indicating PCI-to-PCI Bridge). PCI devices may fail!\n"); 739 } 740 741 /* Check the next parent */ 742 ParentBus = ParentBus->ParentHandler; 743 } 744 } 745 } 746 747 /* Loop buses one last time */ 748 for (i = 0; i < BusCount; i++) 749 { 750 /* Get the PCI bus handler */ 751 Bus = HalHandlerForBus(PCIBus, i); 752 753 /* Sort and combine (trim) bus address range information */ 754 DPRINT("Warning: Bus addresses not being optimized!\n"); 755 } 756 } 757 758 CODE_SEG("INIT") 759 VOID 760 NTAPI 761 ShowSize(ULONG x) 762 { 763 if (!x) return; 764 DbgPrint(" [size="); 765 if (x < 1024) 766 { 767 DbgPrint("%d", (int) x); 768 } 769 else if (x < 1048576) 770 { 771 DbgPrint("%dK", (int)(x / 1024)); 772 } 773 else if (x < 0x80000000) 774 { 775 DbgPrint("%dM", (int)(x / 1048576)); 776 } 777 else 778 { 779 DbgPrint("%d", x); 780 } 781 DbgPrint("]"); 782 } 783 784 /* 785 * These includes are required to define 786 * the ClassTable and VendorTable arrays. 787 */ 788 #define NEWLINE "\n" // "\r\n" 789 #include "pci_classes.h" 790 #include "pci_vendors.h" 791 CODE_SEG("INIT") 792 VOID 793 NTAPI 794 HalpDebugPciDumpBus(IN PBUS_HANDLER BusHandler, 795 IN PCI_SLOT_NUMBER PciSlot, 796 IN ULONG i, 797 IN ULONG j, 798 IN ULONG k, 799 IN PPCI_COMMON_CONFIG PciData) 800 { 801 PCHAR p, ClassName, Boundary, SubClassName, VendorName, ProductName, SubVendorName; 802 UCHAR HeaderType; 803 ULONG Length; 804 CHAR LookupString[16] = ""; 805 CHAR bSubClassName[64] = "Unknown"; 806 CHAR bVendorName[64] = ""; 807 CHAR bProductName[128] = "Unknown device"; 808 CHAR bSubVendorName[128] = "Unknown"; 809 ULONG Size, Mem, b; 810 811 HeaderType = (PciData->HeaderType & ~PCI_MULTIFUNCTION); 812 813 /* Isolate the class name */ 814 sprintf(LookupString, "C %02x ", PciData->BaseClass); 815 ClassName = strstr((PCHAR)ClassTable, LookupString); 816 if (ClassName) 817 { 818 /* Isolate the subclass name */ 819 ClassName += strlen("C 00 "); 820 Boundary = strstr(ClassName, NEWLINE "C "); 821 sprintf(LookupString, NEWLINE "\t%02x ", PciData->SubClass); 822 SubClassName = strstr(ClassName, LookupString); 823 if (Boundary && SubClassName > Boundary) 824 { 825 SubClassName = NULL; 826 } 827 if (!SubClassName) 828 { 829 SubClassName = ClassName; 830 } 831 else 832 { 833 SubClassName += strlen(NEWLINE "\t00 "); 834 } 835 /* Copy the subclass into our buffer */ 836 p = strpbrk(SubClassName, NEWLINE); 837 Length = p - SubClassName; 838 Length = min(Length, sizeof(bSubClassName) - 1); 839 strncpy(bSubClassName, SubClassName, Length); 840 bSubClassName[Length] = '\0'; 841 } 842 843 /* Isolate the vendor name */ 844 sprintf(LookupString, NEWLINE "%04x ", PciData->VendorID); 845 VendorName = strstr((PCHAR)VendorTable, LookupString); 846 if (VendorName) 847 { 848 /* Copy the vendor name into our buffer */ 849 VendorName += strlen(NEWLINE "0000 "); 850 p = strpbrk(VendorName, NEWLINE); 851 Length = p - VendorName; 852 Length = min(Length, sizeof(bVendorName) - 1); 853 strncpy(bVendorName, VendorName, Length); 854 bVendorName[Length] = '\0'; 855 p += strlen(NEWLINE); 856 while (*p == '\t' || *p == '#') 857 { 858 p = strpbrk(p, NEWLINE); 859 p += strlen(NEWLINE); 860 } 861 Boundary = p; 862 863 /* Isolate the product name */ 864 sprintf(LookupString, "\t%04x ", PciData->DeviceID); 865 ProductName = strstr(VendorName, LookupString); 866 if (Boundary && ProductName >= Boundary) 867 { 868 ProductName = NULL; 869 } 870 if (ProductName) 871 { 872 /* Copy the product name into our buffer */ 873 ProductName += strlen("\t0000 "); 874 p = strpbrk(ProductName, NEWLINE); 875 Length = p - ProductName; 876 Length = min(Length, sizeof(bProductName) - 1); 877 strncpy(bProductName, ProductName, Length); 878 bProductName[Length] = '\0'; 879 p += strlen(NEWLINE); 880 while ((*p == '\t' && *(p + 1) == '\t') || *p == '#') 881 { 882 p = strpbrk(p, NEWLINE); 883 p += strlen(NEWLINE); 884 } 885 Boundary = p; 886 SubVendorName = NULL; 887 888 if (HeaderType == PCI_DEVICE_TYPE) 889 { 890 /* Isolate the subvendor and subsystem name */ 891 sprintf(LookupString, 892 "\t\t%04x %04x ", 893 PciData->u.type0.SubVendorID, 894 PciData->u.type0.SubSystemID); 895 SubVendorName = strstr(ProductName, LookupString); 896 if (Boundary && SubVendorName >= Boundary) 897 { 898 SubVendorName = NULL; 899 } 900 } 901 if (SubVendorName) 902 { 903 /* Copy the subvendor name into our buffer */ 904 SubVendorName += strlen("\t\t0000 0000 "); 905 p = strpbrk(SubVendorName, NEWLINE); 906 Length = p - SubVendorName; 907 Length = min(Length, sizeof(bSubVendorName) - 1); 908 strncpy(bSubVendorName, SubVendorName, Length); 909 bSubVendorName[Length] = '\0'; 910 } 911 } 912 } 913 914 /* Print out the data */ 915 DbgPrint("%02x:%02x.%x %s [%02x%02x]: %s %s [%04x:%04x] (rev %02x)\n", 916 i, 917 j, 918 k, 919 bSubClassName, 920 PciData->BaseClass, 921 PciData->SubClass, 922 bVendorName, 923 bProductName, 924 PciData->VendorID, 925 PciData->DeviceID, 926 PciData->RevisionID); 927 928 if (HeaderType == PCI_DEVICE_TYPE) 929 { 930 DbgPrint("\tSubsystem: %s [%04x:%04x]\n", 931 bSubVendorName, 932 PciData->u.type0.SubVendorID, 933 PciData->u.type0.SubSystemID); 934 } 935 936 /* Print out and decode flags */ 937 DbgPrint("\tFlags:"); 938 if (PciData->Command & PCI_ENABLE_BUS_MASTER) DbgPrint(" bus master,"); 939 if (PciData->Status & PCI_STATUS_66MHZ_CAPABLE) DbgPrint(" 66MHz,"); 940 if ((PciData->Status & PCI_STATUS_DEVSEL) == 0x000) DbgPrint(" fast devsel,"); 941 if ((PciData->Status & PCI_STATUS_DEVSEL) == 0x200) DbgPrint(" medium devsel,"); 942 if ((PciData->Status & PCI_STATUS_DEVSEL) == 0x400) DbgPrint(" slow devsel,"); 943 if ((PciData->Status & PCI_STATUS_DEVSEL) == 0x600) DbgPrint(" unknown devsel,"); 944 DbgPrint(" latency %d", PciData->LatencyTimer); 945 if (PciData->u.type0.InterruptPin != 0 && 946 PciData->u.type0.InterruptLine != 0 && 947 PciData->u.type0.InterruptLine != 0xFF) DbgPrint(", IRQ %02d", PciData->u.type0.InterruptLine); 948 else if (PciData->u.type0.InterruptPin != 0) DbgPrint(", IRQ assignment required"); 949 DbgPrint("\n"); 950 951 if (HeaderType == PCI_BRIDGE_TYPE) 952 { 953 DbgPrint("\tBridge:"); 954 DbgPrint(" primary bus %d,", PciData->u.type1.PrimaryBus); 955 DbgPrint(" secondary bus %d,", PciData->u.type1.SecondaryBus); 956 DbgPrint(" subordinate bus %d,", PciData->u.type1.SubordinateBus); 957 DbgPrint(" secondary latency %d", PciData->u.type1.SecondaryLatency); 958 DbgPrint("\n"); 959 } 960 961 /* Scan addresses */ 962 Size = 0; 963 for (b = 0; b < (HeaderType == PCI_DEVICE_TYPE ? PCI_TYPE0_ADDRESSES : PCI_TYPE1_ADDRESSES); b++) 964 { 965 /* Check for a BAR */ 966 if (HeaderType != PCI_CARDBUS_BRIDGE_TYPE) 967 Mem = PciData->u.type0.BaseAddresses[b]; 968 else 969 Mem = 0; 970 if (Mem) 971 { 972 ULONG PciBar = 0xFFFFFFFF; 973 974 HalpWritePCIConfig(BusHandler, 975 PciSlot, 976 &PciBar, 977 FIELD_OFFSET(PCI_COMMON_HEADER, u.type0.BaseAddresses[b]), 978 sizeof(ULONG)); 979 HalpReadPCIConfig(BusHandler, 980 PciSlot, 981 &PciBar, 982 FIELD_OFFSET(PCI_COMMON_HEADER, u.type0.BaseAddresses[b]), 983 sizeof(ULONG)); 984 HalpWritePCIConfig(BusHandler, 985 PciSlot, 986 &Mem, 987 FIELD_OFFSET(PCI_COMMON_HEADER, u.type0.BaseAddresses[b]), 988 sizeof(ULONG)); 989 990 /* Decode the address type */ 991 if (PciBar & PCI_ADDRESS_IO_SPACE) 992 { 993 /* Guess the size */ 994 Size = 1 << 2; 995 while (!(PciBar & Size) && (Size)) Size <<= 1; 996 997 /* Print it out */ 998 DbgPrint("\tI/O ports at %04lx", Mem & PCI_ADDRESS_IO_ADDRESS_MASK); 999 ShowSize(Size); 1000 } 1001 else 1002 { 1003 /* Guess the size */ 1004 Size = 1 << 4; 1005 while (!(PciBar & Size) && (Size)) Size <<= 1; 1006 1007 /* Print it out */ 1008 DbgPrint("\tMemory at %08lx (%d-bit, %sprefetchable)", 1009 Mem & PCI_ADDRESS_MEMORY_ADDRESS_MASK, 1010 (Mem & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_32BIT ? 32 : 64, 1011 (Mem & PCI_ADDRESS_MEMORY_PREFETCHABLE) ? "" : "non-"); 1012 ShowSize(Size); 1013 } 1014 DbgPrint("\n"); 1015 } 1016 } 1017 } 1018 #endif 1019 1020 CODE_SEG("INIT") 1021 VOID 1022 NTAPI 1023 HalpInitializePciBus(VOID) 1024 { 1025 #ifndef _MINIHAL_ 1026 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo; 1027 UCHAR PciType; 1028 PCI_SLOT_NUMBER PciSlot; 1029 ULONG i, j, k; 1030 UCHAR DataBuffer[PCI_COMMON_HDR_LENGTH]; 1031 PPCI_COMMON_CONFIG PciData = (PPCI_COMMON_CONFIG)DataBuffer; 1032 PBUS_HANDLER BusHandler; 1033 ULONG HackFlags; 1034 BOOLEAN ExtendedAddressDecoding = FALSE; 1035 NTSTATUS Status; 1036 1037 /* Query registry information */ 1038 PciRegistryInfo = HalpQueryPciRegistryInfo(); 1039 if (!PciRegistryInfo) return; 1040 1041 /* Initialize the PCI configuration lock */ 1042 KeInitializeSpinLock(&HalpPCIConfigLock); 1043 1044 /* Get the type and free the info structure */ 1045 PciType = PciRegistryInfo->HardwareMechanism & 0xF; 1046 1047 /* Check if this is a type 2 PCI bus with at least one bus */ 1048 if ((PciRegistryInfo->NoBuses) && (PciType == 2)) 1049 { 1050 /* Setup the PCI slot */ 1051 PciSlot.u.bits.Reserved = 0; 1052 PciSlot.u.bits.FunctionNumber = 0; 1053 1054 /* Loop all slots */ 1055 for (i = 0; i < 32; i++) 1056 { 1057 /* Try to setup a Type 2 PCI slot */ 1058 PciType = 2; 1059 BusHandler = HalpAllocateAndInitPciBusHandler(2, 0, TRUE); 1060 if (!BusHandler) break; 1061 1062 /* Now check if it's valid */ 1063 if (HalpIsValidPCIDevice(BusHandler, PciSlot)) break; 1064 1065 /* Heh, the BIOS lied... try Type 1 */ 1066 PciType = 1; 1067 BusHandler = HalpAllocateAndInitPciBusHandler(1, 0, TRUE); 1068 if (!BusHandler) break; 1069 1070 /* Now check if it's valid */ 1071 if (HalpIsValidPCIDevice(BusHandler, PciSlot)) break; 1072 1073 /* Keep trying */ 1074 PciType = 2; 1075 } 1076 1077 /* Now allocate the correct kind of handler */ 1078 HalpAllocateAndInitPciBusHandler(PciType, 0, FALSE); 1079 } 1080 1081 /* Okay, now loop all PCI bridges */ 1082 do 1083 { 1084 /* Loop all PCI buses */ 1085 for (i = 0; i < PciRegistryInfo->NoBuses; i++) 1086 { 1087 /* Check if we have a handler for it */ 1088 if (!HalHandlerForBus(PCIBus, i)) 1089 { 1090 /* Allocate it */ 1091 HalpAllocateAndInitPciBusHandler(PciType, i, FALSE); 1092 } 1093 } 1094 /* Go to the next bridge */ 1095 } while (HalpGetPciBridgeConfig(PciType, &PciRegistryInfo->NoBuses)); 1096 1097 /* Now build correct address range informaiton */ 1098 HalpFixupPciSupportedRanges(PciRegistryInfo->NoBuses); 1099 1100 /* Loop every bus */ 1101 DbgPrint("\n====== PCI BUS HARDWARE DETECTION =======\n\n"); 1102 PciSlot.u.bits.Reserved = 0; 1103 for (i = 0; i < PciRegistryInfo->NoBuses; i++) 1104 { 1105 /* Get the bus handler */ 1106 BusHandler = HalHandlerForBus(PCIBus, i); 1107 1108 /* Loop every device */ 1109 for (j = 0; j < 32; j++) 1110 { 1111 /* Loop every function */ 1112 PciSlot.u.bits.DeviceNumber = j; 1113 for (k = 0; k < 8; k++) 1114 { 1115 /* Build the final slot structure */ 1116 PciSlot.u.bits.FunctionNumber = k; 1117 1118 /* Read the configuration information */ 1119 HalpReadPCIConfig(BusHandler, 1120 PciSlot, 1121 PciData, 1122 0, 1123 PCI_COMMON_HDR_LENGTH); 1124 1125 /* Skip if this is an invalid function */ 1126 if (PciData->VendorID == PCI_INVALID_VENDORID) continue; 1127 1128 /* Print out the entry */ 1129 HalpDebugPciDumpBus(BusHandler, PciSlot, i, j, k, PciData); 1130 1131 /* Check if this is a Cardbus bridge */ 1132 if (PCI_CONFIGURATION_TYPE(PciData) == PCI_CARDBUS_BRIDGE_TYPE) 1133 { 1134 /* Not supported */ 1135 DbgPrint("\tDevice is a PCI Cardbus Bridge. It will not work!\n"); 1136 continue; 1137 } 1138 1139 /* Check if this is a PCI device */ 1140 if (PCI_CONFIGURATION_TYPE(PciData) != PCI_BRIDGE_TYPE) 1141 { 1142 /* Check if it has an interrupt pin and line registered */ 1143 if ((PciData->u.type1.InterruptPin) && 1144 (PciData->u.type1.InterruptLine)) 1145 { 1146 /* Check if this interrupt line is connected to the bus */ 1147 if (PciData->u.type1.InterruptLine < 16) 1148 { 1149 /* Is this an IDE device? */ 1150 if (!HalpIsIdeDevice(PciData)) 1151 { 1152 /* We'll mask out this interrupt then */ 1153 DbgPrint("\tDevice is using IRQ %d! ISA Cards using that IRQ may fail!\n", 1154 PciData->u.type1.InterruptLine); 1155 HalpPciIrqMask |= (1 << PciData->u.type1.InterruptLine); 1156 } 1157 } 1158 } 1159 } 1160 1161 /* Check for broken Intel chips */ 1162 if (PciData->VendorID == 0x8086) 1163 { 1164 /* Check for broken 82830 PCI controller */ 1165 if ((PciData->DeviceID == 0x04A3) && 1166 (PciData->RevisionID < 0x11)) 1167 { 1168 /* Skip */ 1169 DbgPrint("\tDevice is a broken Intel 82430 PCI Controller. It will not work!\n\n"); 1170 continue; 1171 } 1172 1173 /* Check for broken 82378 PCI-to-ISA Bridge */ 1174 if ((PciData->DeviceID == 0x0484) && 1175 (PciData->RevisionID <= 3)) 1176 { 1177 /* Skip */ 1178 DbgPrint("\tDevice is a broken Intel 82378 PCI-to-ISA Bridge. It will not work!\n\n"); 1179 continue; 1180 } 1181 1182 /* Check for broken 82450 PCI Bridge */ 1183 if ((PciData->DeviceID == 0x84C4) && 1184 (PciData->RevisionID <= 4)) 1185 { 1186 DbgPrint("\tDevice is a Intel Orion 82450 PCI Bridge. It will not work!\n\n"); 1187 continue; 1188 } 1189 } 1190 1191 /* Do we know this card? */ 1192 if (!ExtendedAddressDecoding) 1193 { 1194 /* Check for it */ 1195 if (HalpIsRecognizedCard(PciRegistryInfo, 1196 PciData, 1197 HALP_CARD_FEATURE_FULL_DECODE)) 1198 { 1199 /* We'll do chipset checks later */ 1200 DbgPrint("\tDevice has Extended Address Decoding. It may fail to work on older BIOSes!\n"); 1201 ExtendedAddressDecoding = TRUE; 1202 } 1203 } 1204 1205 /* Now check the registry for chipset hacks */ 1206 Status = HalpGetChipHacks(PciData->VendorID, 1207 PciData->DeviceID, 1208 PciData->RevisionID, 1209 &HackFlags); 1210 if (NT_SUCCESS(Status)) 1211 { 1212 /* Check for broken ACPI routing */ 1213 if (HackFlags & HAL_PCI_CHIP_HACK_DISABLE_ACPI_IRQ_ROUTING) 1214 { 1215 DbgPrint("This chipset has broken ACPI IRQ Routing! Be aware!\n\n"); 1216 continue; 1217 } 1218 1219 /* Check for broken ACPI timer */ 1220 if (HackFlags & HAL_PCI_CHIP_HACK_BROKEN_ACPI_TIMER) 1221 { 1222 DbgPrint("This chipset has a broken ACPI timer! Be aware!\n\n"); 1223 continue; 1224 } 1225 1226 /* Check for hibernate-disable */ 1227 if (HackFlags & HAL_PCI_CHIP_HACK_DISABLE_HIBERNATE) 1228 { 1229 DbgPrint("This chipset has a broken PCI device which is incompatible with hibernation. Be aware!\n\n"); 1230 continue; 1231 } 1232 1233 /* Check for USB controllers that generate SMIs */ 1234 if (HackFlags & HAL_PCI_CHIP_HACK_USB_SMI_DISABLE) 1235 { 1236 DbgPrint("This chipset has a USB controller which generates SMIs. ReactOS will likely fail to boot!\n\n"); 1237 continue; 1238 } 1239 } 1240 1241 /* Terminate the entry */ 1242 DbgPrint("\n"); 1243 } 1244 } 1245 } 1246 1247 /* Initialize NMI Crash Flag */ 1248 HalpGetNMICrashFlag(); 1249 1250 /* Free the registry data */ 1251 ExFreePoolWithTag(PciRegistryInfo, TAG_HAL); 1252 1253 /* Tell PnP if this hard supports correct decoding */ 1254 HalpMarkChipsetDecode(ExtendedAddressDecoding); 1255 DbgPrint("====== PCI BUS DETECTION COMPLETE =======\n\n"); 1256 #endif 1257 } 1258 1259 #ifndef _MINIHAL_ 1260 CODE_SEG("INIT") 1261 VOID 1262 NTAPI 1263 HalpInitBusHandlers(VOID) 1264 { 1265 /* Register the HAL Bus Handler support */ 1266 HalpRegisterInternalBusHandlers(); 1267 } 1268 1269 CODE_SEG("INIT") 1270 VOID 1271 NTAPI 1272 HalpRegisterKdSupportFunctions(VOID) 1273 { 1274 /* Register PCI Device Functions */ 1275 KdSetupPciDeviceForDebugging = HalpSetupPciDeviceForDebugging; 1276 KdReleasePciDeviceforDebugging = HalpReleasePciDeviceForDebugging; 1277 1278 /* Register memory functions */ 1279 #ifndef _MINIHAL_ 1280 #if (NTDDI_VERSION >= NTDDI_VISTA) 1281 KdMapPhysicalMemory64 = HalpMapPhysicalMemory64Vista; 1282 KdUnmapVirtualAddress = HalpUnmapVirtualAddressVista; 1283 #else 1284 KdMapPhysicalMemory64 = HalpMapPhysicalMemory64; 1285 KdUnmapVirtualAddress = HalpUnmapVirtualAddress; 1286 #endif 1287 #endif 1288 1289 /* Register ACPI stub */ 1290 KdCheckPowerButton = HalpCheckPowerButton; 1291 } 1292 #endif // _MINIHAL_ 1293 1294 NTSTATUS 1295 NTAPI 1296 HalpAssignSlotResources(IN PUNICODE_STRING RegistryPath, 1297 IN PUNICODE_STRING DriverClassName, 1298 IN PDRIVER_OBJECT DriverObject, 1299 IN PDEVICE_OBJECT DeviceObject, 1300 IN INTERFACE_TYPE BusType, 1301 IN ULONG BusNumber, 1302 IN ULONG SlotNumber, 1303 IN OUT PCM_RESOURCE_LIST *AllocatedResources) 1304 { 1305 PBUS_HANDLER Handler; 1306 NTSTATUS Status; 1307 PAGED_CODE(); 1308 DPRINT1("Slot assignment for %d on bus %u\n", BusType, BusNumber); 1309 1310 /* Find the handler */ 1311 Handler = HalReferenceHandlerForBus(BusType, BusNumber); 1312 if (!Handler) return STATUS_NOT_FOUND; 1313 1314 /* Do the assignment */ 1315 Status = Handler->AssignSlotResources(Handler, 1316 Handler, 1317 RegistryPath, 1318 DriverClassName, 1319 DriverObject, 1320 DeviceObject, 1321 SlotNumber, 1322 AllocatedResources); 1323 1324 /* Dereference the handler and return */ 1325 HalDereferenceBusHandler(Handler); 1326 return Status; 1327 } 1328 1329 BOOLEAN 1330 NTAPI 1331 HaliFindBusAddressTranslation(IN PHYSICAL_ADDRESS BusAddress, 1332 IN OUT PULONG AddressSpace, 1333 OUT PPHYSICAL_ADDRESS TranslatedAddress, 1334 IN OUT PULONG_PTR Context, 1335 IN BOOLEAN NextBus) 1336 { 1337 PHAL_BUS_HANDLER BusHandler; 1338 PBUS_HANDLER Handler; 1339 PLIST_ENTRY NextEntry; 1340 1341 /* Make sure we have a context */ 1342 if (!Context) 1343 return FALSE; 1344 1345 /* If we have data in the context, then this shouldn't be a new lookup */ 1346 if ((*Context != 0) && (NextBus != FALSE)) 1347 return FALSE; 1348 1349 /* Find the bus handler */ 1350 Handler = HalpContextToBusHandler(*Context); 1351 if (!Handler) 1352 return FALSE; 1353 1354 /* Check if this is an ongoing lookup */ 1355 if (NextBus) 1356 { 1357 /* Get the HAL bus handler */ 1358 BusHandler = CONTAINING_RECORD(Handler, HAL_BUS_HANDLER, Handler); 1359 NextEntry = &BusHandler->AllHandlers; 1360 1361 /* Get the next one if we were already with one */ 1362 if (*Context) 1363 NextEntry = NextEntry->Flink; 1364 1365 /* Start scanning */ 1366 while (TRUE) 1367 { 1368 /* Check if this is the last one */ 1369 if (NextEntry == &HalpAllBusHandlers) 1370 { 1371 /* Quit */ 1372 *Context = 1; 1373 return FALSE; 1374 } 1375 1376 /* Call this translator */ 1377 BusHandler = CONTAINING_RECORD(NextEntry, HAL_BUS_HANDLER, AllHandlers); 1378 if (HalTranslateBusAddress(BusHandler->Handler.InterfaceType, 1379 BusHandler->Handler.BusNumber, 1380 BusAddress, 1381 AddressSpace, 1382 TranslatedAddress)) 1383 { 1384 break; 1385 } 1386 1387 /* Try the next one */ 1388 NextEntry = NextEntry->Flink; 1389 } 1390 1391 /* If we made it, we're done */ 1392 *Context = (ULONG_PTR)&BusHandler->Handler; 1393 return TRUE; 1394 } 1395 1396 /* Try the first one through */ 1397 if (!HalTranslateBusAddress(Handler->InterfaceType, 1398 Handler->BusNumber, 1399 BusAddress, 1400 AddressSpace, 1401 TranslatedAddress)) 1402 { 1403 return FALSE; 1404 } 1405 1406 /* Remember for next time */ 1407 *Context = (ULONG_PTR)Handler; 1408 return TRUE; 1409 } 1410 1411 BOOLEAN 1412 NTAPI 1413 HaliTranslateBusAddress(IN INTERFACE_TYPE InterfaceType, 1414 IN ULONG BusNumber, 1415 IN PHYSICAL_ADDRESS BusAddress, 1416 IN OUT PULONG AddressSpace, 1417 OUT PPHYSICAL_ADDRESS TranslatedAddress) 1418 { 1419 PBUS_HANDLER Handler; 1420 BOOLEAN Status; 1421 1422 /* Find the handler */ 1423 Handler = HalReferenceHandlerForBus(InterfaceType, BusNumber); 1424 if (!(Handler) || !(Handler->TranslateBusAddress)) 1425 { 1426 DPRINT1("No translator Interface: %x, Bus: %x, Handler: %p, BusAddress: %x!\n", InterfaceType, BusNumber, Handler, BusAddress); 1427 return FALSE; 1428 } 1429 1430 /* Do the assignment */ 1431 Status = Handler->TranslateBusAddress(Handler, 1432 Handler, 1433 BusAddress, 1434 AddressSpace, 1435 TranslatedAddress); 1436 1437 /* Dereference the handler and return */ 1438 HalDereferenceBusHandler(Handler); 1439 return Status; 1440 } 1441 1442 /* PUBLIC FUNCTIONS **********************************************************/ 1443 1444 #ifndef _MINIHAL_ 1445 /* 1446 * @implemented 1447 */ 1448 NTSTATUS 1449 NTAPI 1450 HalAdjustResourceList(IN PIO_RESOURCE_REQUIREMENTS_LIST *ResourceList) 1451 { 1452 PBUS_HANDLER Handler; 1453 ULONG Status; 1454 PAGED_CODE(); 1455 1456 /* Find the handler */ 1457 Handler = HalReferenceHandlerForBus((*ResourceList)->InterfaceType, 1458 (*ResourceList)->BusNumber); 1459 if (!Handler) return STATUS_SUCCESS; 1460 1461 /* Do the assignment */ 1462 Status = Handler->AdjustResourceList(Handler, 1463 Handler, 1464 ResourceList); 1465 1466 /* Dereference the handler and return */ 1467 HalDereferenceBusHandler(Handler); 1468 return Status; 1469 } 1470 #endif // _MINIHAL_ 1471 1472 /* 1473 * @implemented 1474 */ 1475 NTSTATUS 1476 NTAPI 1477 HalAssignSlotResources(IN PUNICODE_STRING RegistryPath, 1478 IN PUNICODE_STRING DriverClassName, 1479 IN PDRIVER_OBJECT DriverObject, 1480 IN PDEVICE_OBJECT DeviceObject, 1481 IN INTERFACE_TYPE BusType, 1482 IN ULONG BusNumber, 1483 IN ULONG SlotNumber, 1484 IN OUT PCM_RESOURCE_LIST *AllocatedResources) 1485 { 1486 PAGED_CODE(); 1487 1488 /* Check the bus type */ 1489 if (BusType != PCIBus) 1490 { 1491 /* Call our internal handler */ 1492 return HalpAssignSlotResources(RegistryPath, 1493 DriverClassName, 1494 DriverObject, 1495 DeviceObject, 1496 BusType, 1497 BusNumber, 1498 SlotNumber, 1499 AllocatedResources); 1500 } 1501 else 1502 { 1503 /* Call the PCI registered function */ 1504 return HalPciAssignSlotResources(RegistryPath, 1505 DriverClassName, 1506 DriverObject, 1507 DeviceObject, 1508 PCIBus, 1509 BusNumber, 1510 SlotNumber, 1511 AllocatedResources); 1512 } 1513 } 1514 1515 #ifndef _MINIHAL_ 1516 /* 1517 * @implemented 1518 */ 1519 ULONG 1520 NTAPI 1521 HalGetBusData(IN BUS_DATA_TYPE BusDataType, 1522 IN ULONG BusNumber, 1523 IN ULONG SlotNumber, 1524 IN PVOID Buffer, 1525 IN ULONG Length) 1526 { 1527 /* Call the extended function */ 1528 return HalGetBusDataByOffset(BusDataType, 1529 BusNumber, 1530 SlotNumber, 1531 Buffer, 1532 0, 1533 Length); 1534 } 1535 #endif // _MINIHAL_ 1536 1537 /* 1538 * @implemented 1539 */ 1540 ULONG 1541 NTAPI 1542 HalGetBusDataByOffset(IN BUS_DATA_TYPE BusDataType, 1543 IN ULONG BusNumber, 1544 IN ULONG SlotNumber, 1545 IN PVOID Buffer, 1546 IN ULONG Offset, 1547 IN ULONG Length) 1548 { 1549 PBUS_HANDLER Handler; 1550 ULONG Status; 1551 1552 /* Find the handler */ 1553 Handler = HaliReferenceHandlerForConfigSpace(BusDataType, BusNumber); 1554 if (!Handler) return 0; 1555 1556 /* Do the assignment */ 1557 Status = Handler->GetBusData(Handler, 1558 Handler, 1559 SlotNumber, 1560 Buffer, 1561 Offset, 1562 Length); 1563 1564 /* Dereference the handler and return */ 1565 HalDereferenceBusHandler(Handler); 1566 return Status; 1567 } 1568 1569 #ifndef _MINIHAL_ 1570 /* 1571 * @implemented 1572 */ 1573 ULONG 1574 NTAPI 1575 HalGetInterruptVector(IN INTERFACE_TYPE InterfaceType, 1576 IN ULONG BusNumber, 1577 IN ULONG BusInterruptLevel, 1578 IN ULONG BusInterruptVector, 1579 OUT PKIRQL Irql, 1580 OUT PKAFFINITY Affinity) 1581 { 1582 PBUS_HANDLER Handler; 1583 ULONG Vector; 1584 PAGED_CODE(); 1585 1586 /* Defaults */ 1587 *Irql = 0; 1588 *Affinity = 0; 1589 1590 /* Find the handler */ 1591 Handler = HalReferenceHandlerForBus(InterfaceType, BusNumber); 1592 if (!Handler) return 0; 1593 1594 /* Do the assignment */ 1595 Vector = Handler->GetInterruptVector(Handler, 1596 Handler, 1597 BusInterruptLevel, 1598 BusInterruptVector, 1599 Irql, 1600 Affinity); 1601 if ((Vector != IRQ2VECTOR(BusInterruptLevel)) || 1602 (*Irql != VECTOR2IRQL(IRQ2VECTOR(BusInterruptLevel)))) 1603 { 1604 DPRINT1("Returning IRQL %lx, Vector %lx for Level/Vector: %lx/%lx\n", 1605 *Irql, Vector, BusInterruptLevel, BusInterruptVector); 1606 DPRINT1("Old HAL would've returned IRQL %lx and Vector %lx\n", 1607 VECTOR2IRQL(IRQ2VECTOR(BusInterruptLevel)), 1608 IRQ2VECTOR(BusInterruptLevel)); 1609 } 1610 1611 /* Dereference the handler and return */ 1612 HalDereferenceBusHandler(Handler); 1613 return Vector; 1614 } 1615 1616 /* 1617 * @implemented 1618 */ 1619 ULONG 1620 NTAPI 1621 HalSetBusData(IN BUS_DATA_TYPE BusDataType, 1622 IN ULONG BusNumber, 1623 IN ULONG SlotNumber, 1624 IN PVOID Buffer, 1625 IN ULONG Length) 1626 { 1627 /* Call the extended function */ 1628 return HalSetBusDataByOffset(BusDataType, 1629 BusNumber, 1630 SlotNumber, 1631 Buffer, 1632 0, 1633 Length); 1634 } 1635 1636 /* 1637 * @implemented 1638 */ 1639 ULONG 1640 NTAPI 1641 HalSetBusDataByOffset(IN BUS_DATA_TYPE BusDataType, 1642 IN ULONG BusNumber, 1643 IN ULONG SlotNumber, 1644 IN PVOID Buffer, 1645 IN ULONG Offset, 1646 IN ULONG Length) 1647 { 1648 PBUS_HANDLER Handler; 1649 ULONG Status; 1650 1651 /* Find the handler */ 1652 Handler = HaliReferenceHandlerForConfigSpace(BusDataType, BusNumber); 1653 if (!Handler) return 0; 1654 1655 /* Do the assignment */ 1656 Status = Handler->SetBusData(Handler, 1657 Handler, 1658 SlotNumber, 1659 Buffer, 1660 Offset, 1661 Length); 1662 1663 /* Dereference the handler and return */ 1664 HalDereferenceBusHandler(Handler); 1665 return Status; 1666 } 1667 #endif // _MINIHAL_ 1668 1669 /* 1670 * @implemented 1671 */ 1672 BOOLEAN 1673 NTAPI 1674 HalTranslateBusAddress(IN INTERFACE_TYPE InterfaceType, 1675 IN ULONG BusNumber, 1676 IN PHYSICAL_ADDRESS BusAddress, 1677 IN OUT PULONG AddressSpace, 1678 OUT PPHYSICAL_ADDRESS TranslatedAddress) 1679 { 1680 /* Look as the bus type */ 1681 if (InterfaceType == PCIBus) 1682 { 1683 /* Call the PCI registered function */ 1684 return HalPciTranslateBusAddress(PCIBus, 1685 BusNumber, 1686 BusAddress, 1687 AddressSpace, 1688 TranslatedAddress); 1689 } 1690 else 1691 { 1692 /* Call the bus handler */ 1693 return HaliTranslateBusAddress(InterfaceType, 1694 BusNumber, 1695 BusAddress, 1696 AddressSpace, 1697 TranslatedAddress); 1698 } 1699 } 1700 1701 /* EOF */ 1702