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