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("]\n"); 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, SubClassName, VendorName, ProductName, SubVendorName; 813 ULONG Length; 814 CHAR LookupString[16] = ""; 815 CHAR bSubClassName[64] = ""; 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 += 6; 828 sprintf(LookupString, "\t%02x ", PciData->SubClass); 829 SubClassName = strstr(ClassName, LookupString); 830 if (SubClassName) 831 { 832 /* Copy the subclass into our buffer */ 833 SubClassName += 5; 834 p = strpbrk(SubClassName, "\r\n"); 835 Length = p - SubClassName; 836 if (Length >= sizeof(bSubClassName)) Length = sizeof(bSubClassName) - 1; 837 strncpy(bSubClassName, SubClassName, Length); 838 bSubClassName[Length] = '\0'; 839 } 840 } 841 842 /* Isolate the vendor name */ 843 sprintf(LookupString, "\r\n%04x ", PciData->VendorID); 844 VendorName = strstr((PCHAR)VendorTable, LookupString); 845 if (VendorName) 846 { 847 /* Copy the vendor name into our buffer */ 848 VendorName += 8; 849 p = strpbrk(VendorName, "\r\n"); 850 Length = p - VendorName; 851 if (Length >= sizeof(bVendorName)) Length = sizeof(bVendorName) - 1; 852 strncpy(bVendorName, VendorName, Length); 853 bVendorName[Length] = '\0'; 854 855 /* Isolate the product name */ 856 sprintf(LookupString, "\t%04x ", PciData->DeviceID); 857 ProductName = strstr(VendorName, LookupString); 858 if (ProductName) 859 { 860 /* Copy the product name into our buffer */ 861 ProductName += 7; 862 p = strpbrk(ProductName, "\r\n"); 863 Length = p - ProductName; 864 if (Length >= sizeof(bProductName)) Length = sizeof(bProductName) - 1; 865 strncpy(bProductName, ProductName, Length); 866 bProductName[Length] = '\0'; 867 868 /* Isolate the subvendor and subsystem name */ 869 sprintf(LookupString, 870 "\t\t%04x %04x ", 871 PciData->u.type0.SubVendorID, 872 PciData->u.type0.SubSystemID); 873 SubVendorName = strstr(ProductName, LookupString); 874 if (SubVendorName) 875 { 876 /* Copy the subvendor name into our buffer */ 877 SubVendorName += 13; 878 p = strpbrk(SubVendorName, "\r\n"); 879 Length = p - SubVendorName; 880 if (Length >= sizeof(bSubVendorName)) Length = sizeof(bSubVendorName) - 1; 881 strncpy(bSubVendorName, SubVendorName, Length); 882 bSubVendorName[Length] = '\0'; 883 } 884 } 885 } 886 887 /* Print out the data */ 888 DbgPrint("%02x:%02x.%x %s [%02x%02x]: %s %s [%04x:%04x] (rev %02x)\n" 889 "\tSubsystem: %s [%04x:%04x]\n", 890 i, 891 j, 892 k, 893 bSubClassName, 894 PciData->BaseClass, 895 PciData->SubClass, 896 bVendorName, 897 bProductName, 898 PciData->VendorID, 899 PciData->DeviceID, 900 PciData->RevisionID, 901 bSubVendorName, 902 PciData->u.type0.SubVendorID, 903 PciData->u.type0.SubSystemID); 904 905 /* Print out and decode flags */ 906 DbgPrint("\tFlags:"); 907 if (PciData->Command & PCI_ENABLE_BUS_MASTER) DbgPrint(" bus master,"); 908 if (PciData->Status & PCI_STATUS_66MHZ_CAPABLE) DbgPrint(" 66MHz,"); 909 if ((PciData->Status & PCI_STATUS_DEVSEL) == 0x000) DbgPrint(" fast devsel,"); 910 if ((PciData->Status & PCI_STATUS_DEVSEL) == 0x200) DbgPrint(" medium devsel,"); 911 if ((PciData->Status & PCI_STATUS_DEVSEL) == 0x400) DbgPrint(" slow devsel,"); 912 if ((PciData->Status & PCI_STATUS_DEVSEL) == 0x600) DbgPrint(" unknown devsel,"); 913 DbgPrint(" latency %d", PciData->LatencyTimer); 914 if (PciData->u.type0.InterruptPin != 0 && 915 PciData->u.type0.InterruptLine != 0 && 916 PciData->u.type0.InterruptLine != 0xFF) DbgPrint(", IRQ %02d", PciData->u.type0.InterruptLine); 917 else if (PciData->u.type0.InterruptPin != 0) DbgPrint(", IRQ assignment required"); 918 DbgPrint("\n"); 919 920 /* Scan addresses */ 921 Size = 0; 922 for (b = 0; b < PCI_TYPE0_ADDRESSES; b++) 923 { 924 /* Check for a BAR */ 925 Mem = PciData->u.type0.BaseAddresses[b]; 926 if (Mem) 927 { 928 /* Decode the address type */ 929 if (Mem & PCI_ADDRESS_IO_SPACE) 930 { 931 /* Guess the size */ 932 Size = 1 << 2; 933 while (!(Mem & Size) && (Size)) Size <<= 1; 934 935 /* Print it out */ 936 DbgPrint("\tI/O ports at %04lx", Mem & PCI_ADDRESS_IO_ADDRESS_MASK); 937 ShowSize(Size); 938 } 939 else 940 { 941 /* Guess the size */ 942 Size = 1 << 8; 943 while (!(Mem & Size) && (Size)) Size <<= 1; 944 945 /* Print it out */ 946 DbgPrint("\tMemory at %08lx (%d-bit, %sprefetchable)", 947 Mem & PCI_ADDRESS_MEMORY_ADDRESS_MASK, 948 (Mem & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_32BIT ? 32 : 64, 949 (Mem & PCI_ADDRESS_MEMORY_PREFETCHABLE) ? "" : "non-"); 950 ShowSize(Size); 951 } 952 } 953 } 954 } 955 #endif 956 957 INIT_FUNCTION 958 VOID 959 NTAPI 960 HalpInitializePciBus(VOID) 961 { 962 #ifndef _MINIHAL_ 963 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo; 964 UCHAR PciType; 965 PCI_SLOT_NUMBER PciSlot; 966 ULONG i, j, k; 967 UCHAR DataBuffer[PCI_COMMON_HDR_LENGTH]; 968 PPCI_COMMON_CONFIG PciData = (PPCI_COMMON_CONFIG)DataBuffer; 969 PBUS_HANDLER BusHandler; 970 ULONG HackFlags; 971 BOOLEAN ExtendedAddressDecoding = FALSE; 972 NTSTATUS Status; 973 974 /* Query registry information */ 975 PciRegistryInfo = HalpQueryPciRegistryInfo(); 976 if (!PciRegistryInfo) return; 977 978 /* Initialize the PCI configuration lock */ 979 KeInitializeSpinLock(&HalpPCIConfigLock); 980 981 /* Get the type and free the info structure */ 982 PciType = PciRegistryInfo->HardwareMechanism & 0xF; 983 984 /* Check if this is a type 2 PCI bus with at least one bus */ 985 if ((PciRegistryInfo->NoBuses) && (PciType == 2)) 986 { 987 /* Setup the PCI slot */ 988 PciSlot.u.bits.Reserved = 0; 989 PciSlot.u.bits.FunctionNumber = 0; 990 991 /* Loop all slots */ 992 for (i = 0; i < 32; i++) 993 { 994 /* Try to setup a Type 2 PCI slot */ 995 PciType = 2; 996 BusHandler = HalpAllocateAndInitPciBusHandler(2, 0, TRUE); 997 if (!BusHandler) break; 998 999 /* Now check if it's valid */ 1000 if (HalpIsValidPCIDevice(BusHandler, PciSlot)) break; 1001 1002 /* Heh, the BIOS lied... try Type 1 */ 1003 PciType = 1; 1004 BusHandler = HalpAllocateAndInitPciBusHandler(1, 0, TRUE); 1005 if (!BusHandler) break; 1006 1007 /* Now check if it's valid */ 1008 if (HalpIsValidPCIDevice(BusHandler, PciSlot)) break; 1009 1010 /* Keep trying */ 1011 PciType = 2; 1012 } 1013 1014 /* Now allocate the correct kind of handler */ 1015 HalpAllocateAndInitPciBusHandler(PciType, 0, FALSE); 1016 } 1017 1018 /* Okay, now loop all PCI bridges */ 1019 do 1020 { 1021 /* Loop all PCI buses */ 1022 for (i = 0; i < PciRegistryInfo->NoBuses; i++) 1023 { 1024 /* Check if we have a handler for it */ 1025 if (!HalHandlerForBus(PCIBus, i)) 1026 { 1027 /* Allocate it */ 1028 HalpAllocateAndInitPciBusHandler(PciType, i, FALSE); 1029 } 1030 } 1031 /* Go to the next bridge */ 1032 } while (HalpGetPciBridgeConfig(PciType, &PciRegistryInfo->NoBuses)); 1033 1034 /* Now build correct address range informaiton */ 1035 HalpFixupPciSupportedRanges(PciRegistryInfo->NoBuses); 1036 1037 /* Loop every bus */ 1038 DbgPrint("\n====== PCI BUS HARDWARE DETECTION =======\n\n"); 1039 PciSlot.u.bits.Reserved = 0; 1040 for (i = 0; i < PciRegistryInfo->NoBuses; i++) 1041 { 1042 /* Get the bus handler */ 1043 BusHandler = HalHandlerForBus(PCIBus, i); 1044 1045 /* Loop every device */ 1046 for (j = 0; j < 32; j++) 1047 { 1048 /* Loop every function */ 1049 PciSlot.u.bits.DeviceNumber = j; 1050 for (k = 0; k < 8; k++) 1051 { 1052 /* Build the final slot structure */ 1053 PciSlot.u.bits.FunctionNumber = k; 1054 1055 /* Read the configuration information */ 1056 HalpReadPCIConfig(BusHandler, 1057 PciSlot, 1058 PciData, 1059 0, 1060 PCI_COMMON_HDR_LENGTH); 1061 1062 /* Skip if this is an invalid function */ 1063 if (PciData->VendorID == PCI_INVALID_VENDORID) continue; 1064 1065 /* Print out the entry */ 1066 HalpDebugPciDumpBus(i, j, k, PciData); 1067 1068 /* Check if this is a Cardbus bridge */ 1069 if (PCI_CONFIGURATION_TYPE(PciData) == PCI_CARDBUS_BRIDGE_TYPE) 1070 { 1071 /* Not supported */ 1072 DbgPrint("\tDevice is a PCI Cardbus Bridge. It will not work!\n"); 1073 continue; 1074 } 1075 1076 /* Check if this is a PCI device */ 1077 if (PCI_CONFIGURATION_TYPE(PciData) != PCI_BRIDGE_TYPE) 1078 { 1079 /* Check if it has an interrupt pin and line registered */ 1080 if ((PciData->u.type1.InterruptPin) && 1081 (PciData->u.type1.InterruptLine)) 1082 { 1083 /* Check if this interrupt line is connected to the bus */ 1084 if (PciData->u.type1.InterruptLine < 16) 1085 { 1086 /* Is this an IDE device? */ 1087 if (!HalpIsIdeDevice(PciData)) 1088 { 1089 /* We'll mask out this interrupt then */ 1090 DbgPrint("\tDevice is using IRQ %d! ISA Cards using that IRQ may fail!\n", 1091 PciData->u.type1.InterruptLine); 1092 HalpPciIrqMask |= (1 << PciData->u.type1.InterruptLine); 1093 } 1094 } 1095 } 1096 } 1097 1098 /* Check for broken Intel chips */ 1099 if (PciData->VendorID == 0x8086) 1100 { 1101 /* Check for broken 82830 PCI controller */ 1102 if ((PciData->DeviceID == 0x04A3) && 1103 (PciData->RevisionID < 0x11)) 1104 { 1105 /* Skip */ 1106 DbgPrint("\tDevice is a broken Intel 82430 PCI Controller. It will not work!\n\n"); 1107 continue; 1108 } 1109 1110 /* Check for broken 82378 PCI-to-ISA Bridge */ 1111 if ((PciData->DeviceID == 0x0484) && 1112 (PciData->RevisionID <= 3)) 1113 { 1114 /* Skip */ 1115 DbgPrint("\tDevice is a broken Intel 82378 PCI-to-ISA Bridge. It will not work!\n\n"); 1116 continue; 1117 } 1118 1119 /* Check for broken 82450 PCI Bridge */ 1120 if ((PciData->DeviceID == 0x84C4) && 1121 (PciData->RevisionID <= 4)) 1122 { 1123 DbgPrint("\tDevice is a Intel Orion 82450 PCI Bridge. It will not work!\n\n"); 1124 continue; 1125 } 1126 } 1127 1128 /* Do we know this card? */ 1129 if (!ExtendedAddressDecoding) 1130 { 1131 /* Check for it */ 1132 if (HalpIsRecognizedCard(PciRegistryInfo, 1133 PciData, 1134 HALP_CARD_FEATURE_FULL_DECODE)) 1135 { 1136 /* We'll do chipset checks later */ 1137 DbgPrint("\tDevice has Extended Address Decoding. It may fail to work on older BIOSes!\n"); 1138 ExtendedAddressDecoding = TRUE; 1139 } 1140 } 1141 1142 /* Now check the registry for chipset hacks */ 1143 Status = HalpGetChipHacks(PciData->VendorID, 1144 PciData->DeviceID, 1145 PciData->RevisionID, 1146 &HackFlags); 1147 if (NT_SUCCESS(Status)) 1148 { 1149 /* Check for broken ACPI routing */ 1150 if (HackFlags & HAL_PCI_CHIP_HACK_DISABLE_ACPI_IRQ_ROUTING) 1151 { 1152 DbgPrint("This chipset has broken ACPI IRQ Routing! Be aware!\n\n"); 1153 continue; 1154 } 1155 1156 /* Check for broken ACPI timer */ 1157 if (HackFlags & HAL_PCI_CHIP_HACK_BROKEN_ACPI_TIMER) 1158 { 1159 DbgPrint("This chipset has a broken ACPI timer! Be aware!\n\n"); 1160 continue; 1161 } 1162 1163 /* Check for hibernate-disable */ 1164 if (HackFlags & HAL_PCI_CHIP_HACK_DISABLE_HIBERNATE) 1165 { 1166 DbgPrint("This chipset has a broken PCI device which is incompatible with hibernation. Be aware!\n\n"); 1167 continue; 1168 } 1169 1170 /* Check for USB controllers that generate SMIs */ 1171 if (HackFlags & HAL_PCI_CHIP_HACK_USB_SMI_DISABLE) 1172 { 1173 DbgPrint("This chipset has a USB controller which generates SMIs. ReactOS will likely fail to boot!\n\n"); 1174 continue; 1175 } 1176 } 1177 1178 /* Terminate the entry */ 1179 DbgPrint("\n"); 1180 } 1181 } 1182 } 1183 1184 /* Initialize NMI Crash Flag */ 1185 HalpGetNMICrashFlag(); 1186 1187 /* Free the registry data */ 1188 ExFreePoolWithTag(PciRegistryInfo, TAG_HAL); 1189 1190 /* Tell PnP if this hard supports correct decoding */ 1191 HalpMarkChipsetDecode(ExtendedAddressDecoding); 1192 DbgPrint("====== PCI BUS DETECTION COMPLETE =======\n\n"); 1193 #endif 1194 } 1195 1196 INIT_FUNCTION 1197 VOID 1198 NTAPI 1199 HalpInitBusHandlers(VOID) 1200 { 1201 /* Register the HAL Bus Handler support */ 1202 HalpRegisterInternalBusHandlers(); 1203 } 1204 1205 INIT_FUNCTION 1206 VOID 1207 NTAPI 1208 HalpRegisterKdSupportFunctions(VOID) 1209 { 1210 /* Register PCI Device Functions */ 1211 KdSetupPciDeviceForDebugging = HalpSetupPciDeviceForDebugging; 1212 KdReleasePciDeviceforDebugging = HalpReleasePciDeviceForDebugging; 1213 1214 /* Register memory functions */ 1215 #ifndef _MINIHAL_ 1216 #if (NTDDI_VERSION >= NTDDI_VISTA) 1217 KdMapPhysicalMemory64 = HalpMapPhysicalMemory64Vista; 1218 KdUnmapVirtualAddress = HalpUnmapVirtualAddressVista; 1219 #else 1220 KdMapPhysicalMemory64 = HalpMapPhysicalMemory64; 1221 KdUnmapVirtualAddress = HalpUnmapVirtualAddress; 1222 #endif 1223 #endif 1224 1225 /* Register ACPI stub */ 1226 KdCheckPowerButton = HalpCheckPowerButton; 1227 } 1228 1229 NTSTATUS 1230 NTAPI 1231 HalpAssignSlotResources(IN PUNICODE_STRING RegistryPath, 1232 IN PUNICODE_STRING DriverClassName, 1233 IN PDRIVER_OBJECT DriverObject, 1234 IN PDEVICE_OBJECT DeviceObject, 1235 IN INTERFACE_TYPE BusType, 1236 IN ULONG BusNumber, 1237 IN ULONG SlotNumber, 1238 IN OUT PCM_RESOURCE_LIST *AllocatedResources) 1239 { 1240 PBUS_HANDLER Handler; 1241 NTSTATUS Status; 1242 PAGED_CODE(); 1243 DPRINT1("Slot assignment for %d on bus %u\n", BusType, BusNumber); 1244 1245 /* Find the handler */ 1246 Handler = HalReferenceHandlerForBus(BusType, BusNumber); 1247 if (!Handler) return STATUS_NOT_FOUND; 1248 1249 /* Do the assignment */ 1250 Status = Handler->AssignSlotResources(Handler, 1251 Handler, 1252 RegistryPath, 1253 DriverClassName, 1254 DriverObject, 1255 DeviceObject, 1256 SlotNumber, 1257 AllocatedResources); 1258 1259 /* Dereference the handler and return */ 1260 HalDereferenceBusHandler(Handler); 1261 return Status; 1262 } 1263 1264 BOOLEAN 1265 NTAPI 1266 HaliFindBusAddressTranslation(IN PHYSICAL_ADDRESS BusAddress, 1267 IN OUT PULONG AddressSpace, 1268 OUT PPHYSICAL_ADDRESS TranslatedAddress, 1269 IN OUT PULONG_PTR Context, 1270 IN BOOLEAN NextBus) 1271 { 1272 PHAL_BUS_HANDLER BusHandler; 1273 PBUS_HANDLER Handler; 1274 PLIST_ENTRY NextEntry; 1275 ULONG ContextValue; 1276 1277 /* Make sure we have a context */ 1278 if (!Context) return FALSE; 1279 ASSERT((*Context) || (NextBus == TRUE)); 1280 1281 /* Read the context */ 1282 ContextValue = *Context; 1283 1284 /* Find the bus handler */ 1285 Handler = HalpContextToBusHandler(ContextValue); 1286 if (!Handler) return FALSE; 1287 1288 /* Check if this is an ongoing lookup */ 1289 if (NextBus) 1290 { 1291 /* Get the HAL bus handler */ 1292 BusHandler = CONTAINING_RECORD(Handler, HAL_BUS_HANDLER, Handler); 1293 NextEntry = &BusHandler->AllHandlers; 1294 1295 /* Get the next one if we were already with one */ 1296 if (ContextValue) NextEntry = NextEntry->Flink; 1297 1298 /* Start scanning */ 1299 while (TRUE) 1300 { 1301 /* Check if this is the last one */ 1302 if (NextEntry == &HalpAllBusHandlers) 1303 { 1304 /* Quit */ 1305 *Context = 1; 1306 return FALSE; 1307 } 1308 1309 /* Call this translator */ 1310 BusHandler = CONTAINING_RECORD(NextEntry, HAL_BUS_HANDLER, AllHandlers); 1311 if (HalTranslateBusAddress(BusHandler->Handler.InterfaceType, 1312 BusHandler->Handler.BusNumber, 1313 BusAddress, 1314 AddressSpace, 1315 TranslatedAddress)) break; 1316 1317 /* Try the next one */ 1318 NextEntry = NextEntry->Flink; 1319 } 1320 1321 /* If we made it, we're done */ 1322 *Context = (ULONG_PTR)Handler; 1323 return TRUE; 1324 } 1325 1326 /* Try the first one through */ 1327 if (!HalTranslateBusAddress(Handler->InterfaceType, 1328 Handler->BusNumber, 1329 BusAddress, 1330 AddressSpace, 1331 TranslatedAddress)) return FALSE; 1332 1333 /* Remember for next time */ 1334 *Context = (ULONG_PTR)Handler; 1335 return TRUE; 1336 } 1337 1338 BOOLEAN 1339 NTAPI 1340 HaliTranslateBusAddress(IN INTERFACE_TYPE InterfaceType, 1341 IN ULONG BusNumber, 1342 IN PHYSICAL_ADDRESS BusAddress, 1343 IN OUT PULONG AddressSpace, 1344 OUT PPHYSICAL_ADDRESS TranslatedAddress) 1345 { 1346 PBUS_HANDLER Handler; 1347 BOOLEAN Status; 1348 1349 /* Find the handler */ 1350 Handler = HalReferenceHandlerForBus(InterfaceType, BusNumber); 1351 if (!(Handler) || !(Handler->TranslateBusAddress)) 1352 { 1353 DPRINT1("No translator Interface: %x, Bus: %x, Handler: %p, BusAddress: %x!\n", InterfaceType, BusNumber, Handler, BusAddress); 1354 return FALSE; 1355 } 1356 1357 /* Do the assignment */ 1358 Status = Handler->TranslateBusAddress(Handler, 1359 Handler, 1360 BusAddress, 1361 AddressSpace, 1362 TranslatedAddress); 1363 1364 /* Dereference the handler and return */ 1365 HalDereferenceBusHandler(Handler); 1366 return Status; 1367 } 1368 1369 /* PUBLIC FUNCTIONS **********************************************************/ 1370 1371 /* 1372 * @implemented 1373 */ 1374 NTSTATUS 1375 NTAPI 1376 HalAdjustResourceList(IN PIO_RESOURCE_REQUIREMENTS_LIST *ResourceList) 1377 { 1378 PBUS_HANDLER Handler; 1379 ULONG Status; 1380 PAGED_CODE(); 1381 1382 /* Find the handler */ 1383 Handler = HalReferenceHandlerForBus((*ResourceList)->InterfaceType, 1384 (*ResourceList)->BusNumber); 1385 if (!Handler) return STATUS_SUCCESS; 1386 1387 /* Do the assignment */ 1388 Status = Handler->AdjustResourceList(Handler, 1389 Handler, 1390 ResourceList); 1391 1392 /* Dereference the handler and return */ 1393 HalDereferenceBusHandler(Handler); 1394 return Status; 1395 } 1396 1397 /* 1398 * @implemented 1399 */ 1400 NTSTATUS 1401 NTAPI 1402 HalAssignSlotResources(IN PUNICODE_STRING RegistryPath, 1403 IN PUNICODE_STRING DriverClassName, 1404 IN PDRIVER_OBJECT DriverObject, 1405 IN PDEVICE_OBJECT DeviceObject, 1406 IN INTERFACE_TYPE BusType, 1407 IN ULONG BusNumber, 1408 IN ULONG SlotNumber, 1409 IN OUT PCM_RESOURCE_LIST *AllocatedResources) 1410 { 1411 PAGED_CODE(); 1412 1413 /* Check the bus type */ 1414 if (BusType != PCIBus) 1415 { 1416 /* Call our internal handler */ 1417 return HalpAssignSlotResources(RegistryPath, 1418 DriverClassName, 1419 DriverObject, 1420 DeviceObject, 1421 BusType, 1422 BusNumber, 1423 SlotNumber, 1424 AllocatedResources); 1425 } 1426 else 1427 { 1428 /* Call the PCI registered function */ 1429 return HalPciAssignSlotResources(RegistryPath, 1430 DriverClassName, 1431 DriverObject, 1432 DeviceObject, 1433 PCIBus, 1434 BusNumber, 1435 SlotNumber, 1436 AllocatedResources); 1437 } 1438 } 1439 1440 /* 1441 * @implemented 1442 */ 1443 ULONG 1444 NTAPI 1445 HalGetBusData(IN BUS_DATA_TYPE BusDataType, 1446 IN ULONG BusNumber, 1447 IN ULONG SlotNumber, 1448 IN PVOID Buffer, 1449 IN ULONG Length) 1450 { 1451 /* Call the extended function */ 1452 return HalGetBusDataByOffset(BusDataType, 1453 BusNumber, 1454 SlotNumber, 1455 Buffer, 1456 0, 1457 Length); 1458 } 1459 1460 /* 1461 * @implemented 1462 */ 1463 ULONG 1464 NTAPI 1465 HalGetBusDataByOffset(IN BUS_DATA_TYPE BusDataType, 1466 IN ULONG BusNumber, 1467 IN ULONG SlotNumber, 1468 IN PVOID Buffer, 1469 IN ULONG Offset, 1470 IN ULONG Length) 1471 { 1472 PBUS_HANDLER Handler; 1473 ULONG Status; 1474 1475 /* Find the handler */ 1476 Handler = HaliReferenceHandlerForConfigSpace(BusDataType, BusNumber); 1477 if (!Handler) return 0; 1478 1479 /* Do the assignment */ 1480 Status = Handler->GetBusData(Handler, 1481 Handler, 1482 SlotNumber, 1483 Buffer, 1484 Offset, 1485 Length); 1486 1487 /* Dereference the handler and return */ 1488 HalDereferenceBusHandler(Handler); 1489 return Status; 1490 } 1491 1492 /* 1493 * @implemented 1494 */ 1495 ULONG 1496 NTAPI 1497 HalGetInterruptVector(IN INTERFACE_TYPE InterfaceType, 1498 IN ULONG BusNumber, 1499 IN ULONG BusInterruptLevel, 1500 IN ULONG BusInterruptVector, 1501 OUT PKIRQL Irql, 1502 OUT PKAFFINITY Affinity) 1503 { 1504 PBUS_HANDLER Handler; 1505 ULONG Vector; 1506 PAGED_CODE(); 1507 1508 /* Defaults */ 1509 *Irql = 0; 1510 *Affinity = 0; 1511 1512 /* Find the handler */ 1513 Handler = HalReferenceHandlerForBus(InterfaceType, BusNumber); 1514 if (!Handler) return 0; 1515 1516 /* Do the assignment */ 1517 Vector = Handler->GetInterruptVector(Handler, 1518 Handler, 1519 BusInterruptLevel, 1520 BusInterruptVector, 1521 Irql, 1522 Affinity); 1523 if ((Vector != IRQ2VECTOR(BusInterruptLevel)) || 1524 (*Irql != VECTOR2IRQL(IRQ2VECTOR(BusInterruptLevel)))) 1525 { 1526 DPRINT1("Returning IRQL %lx, Vector %lx for Level/Vector: %lx/%lx\n", 1527 *Irql, Vector, BusInterruptLevel, BusInterruptVector); 1528 DPRINT1("Old HAL would've returned IRQL %lx and Vector %lx\n", 1529 VECTOR2IRQL(IRQ2VECTOR(BusInterruptLevel)), 1530 IRQ2VECTOR(BusInterruptLevel)); 1531 } 1532 1533 /* Dereference the handler and return */ 1534 HalDereferenceBusHandler(Handler); 1535 return Vector; 1536 } 1537 1538 /* 1539 * @implemented 1540 */ 1541 ULONG 1542 NTAPI 1543 HalSetBusData(IN BUS_DATA_TYPE BusDataType, 1544 IN ULONG BusNumber, 1545 IN ULONG SlotNumber, 1546 IN PVOID Buffer, 1547 IN ULONG Length) 1548 { 1549 /* Call the extended function */ 1550 return HalSetBusDataByOffset(BusDataType, 1551 BusNumber, 1552 SlotNumber, 1553 Buffer, 1554 0, 1555 Length); 1556 } 1557 1558 /* 1559 * @implemented 1560 */ 1561 ULONG 1562 NTAPI 1563 HalSetBusDataByOffset(IN BUS_DATA_TYPE BusDataType, 1564 IN ULONG BusNumber, 1565 IN ULONG SlotNumber, 1566 IN PVOID Buffer, 1567 IN ULONG Offset, 1568 IN ULONG Length) 1569 { 1570 PBUS_HANDLER Handler; 1571 ULONG Status; 1572 1573 /* Find the handler */ 1574 Handler = HaliReferenceHandlerForConfigSpace(BusDataType, BusNumber); 1575 if (!Handler) return 0; 1576 1577 /* Do the assignment */ 1578 Status = Handler->SetBusData(Handler, 1579 Handler, 1580 SlotNumber, 1581 Buffer, 1582 Offset, 1583 Length); 1584 1585 /* Dereference the handler and return */ 1586 HalDereferenceBusHandler(Handler); 1587 return Status; 1588 } 1589 1590 /* 1591 * @implemented 1592 */ 1593 BOOLEAN 1594 NTAPI 1595 HalTranslateBusAddress(IN INTERFACE_TYPE InterfaceType, 1596 IN ULONG BusNumber, 1597 IN PHYSICAL_ADDRESS BusAddress, 1598 IN OUT PULONG AddressSpace, 1599 OUT PPHYSICAL_ADDRESS TranslatedAddress) 1600 { 1601 /* Look as the bus type */ 1602 if (InterfaceType == PCIBus) 1603 { 1604 /* Call the PCI registered function */ 1605 return HalPciTranslateBusAddress(PCIBus, 1606 BusNumber, 1607 BusAddress, 1608 AddressSpace, 1609 TranslatedAddress); 1610 } 1611 else 1612 { 1613 /* Call the bus handler */ 1614 return HaliTranslateBusAddress(InterfaceType, 1615 BusNumber, 1616 BusAddress, 1617 AddressSpace, 1618 TranslatedAddress); 1619 } 1620 } 1621 1622 /* EOF */ 1623