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, 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 } 984 } 985 } 986 #endif 987 988 INIT_FUNCTION 989 VOID 990 NTAPI 991 HalpInitializePciBus(VOID) 992 { 993 #ifndef _MINIHAL_ 994 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo; 995 UCHAR PciType; 996 PCI_SLOT_NUMBER PciSlot; 997 ULONG i, j, k; 998 UCHAR DataBuffer[PCI_COMMON_HDR_LENGTH]; 999 PPCI_COMMON_CONFIG PciData = (PPCI_COMMON_CONFIG)DataBuffer; 1000 PBUS_HANDLER BusHandler; 1001 ULONG HackFlags; 1002 BOOLEAN ExtendedAddressDecoding = FALSE; 1003 NTSTATUS Status; 1004 1005 /* Query registry information */ 1006 PciRegistryInfo = HalpQueryPciRegistryInfo(); 1007 if (!PciRegistryInfo) return; 1008 1009 /* Initialize the PCI configuration lock */ 1010 KeInitializeSpinLock(&HalpPCIConfigLock); 1011 1012 /* Get the type and free the info structure */ 1013 PciType = PciRegistryInfo->HardwareMechanism & 0xF; 1014 1015 /* Check if this is a type 2 PCI bus with at least one bus */ 1016 if ((PciRegistryInfo->NoBuses) && (PciType == 2)) 1017 { 1018 /* Setup the PCI slot */ 1019 PciSlot.u.bits.Reserved = 0; 1020 PciSlot.u.bits.FunctionNumber = 0; 1021 1022 /* Loop all slots */ 1023 for (i = 0; i < 32; i++) 1024 { 1025 /* Try to setup a Type 2 PCI slot */ 1026 PciType = 2; 1027 BusHandler = HalpAllocateAndInitPciBusHandler(2, 0, TRUE); 1028 if (!BusHandler) break; 1029 1030 /* Now check if it's valid */ 1031 if (HalpIsValidPCIDevice(BusHandler, PciSlot)) break; 1032 1033 /* Heh, the BIOS lied... try Type 1 */ 1034 PciType = 1; 1035 BusHandler = HalpAllocateAndInitPciBusHandler(1, 0, TRUE); 1036 if (!BusHandler) break; 1037 1038 /* Now check if it's valid */ 1039 if (HalpIsValidPCIDevice(BusHandler, PciSlot)) break; 1040 1041 /* Keep trying */ 1042 PciType = 2; 1043 } 1044 1045 /* Now allocate the correct kind of handler */ 1046 HalpAllocateAndInitPciBusHandler(PciType, 0, FALSE); 1047 } 1048 1049 /* Okay, now loop all PCI bridges */ 1050 do 1051 { 1052 /* Loop all PCI buses */ 1053 for (i = 0; i < PciRegistryInfo->NoBuses; i++) 1054 { 1055 /* Check if we have a handler for it */ 1056 if (!HalHandlerForBus(PCIBus, i)) 1057 { 1058 /* Allocate it */ 1059 HalpAllocateAndInitPciBusHandler(PciType, i, FALSE); 1060 } 1061 } 1062 /* Go to the next bridge */ 1063 } while (HalpGetPciBridgeConfig(PciType, &PciRegistryInfo->NoBuses)); 1064 1065 /* Now build correct address range informaiton */ 1066 HalpFixupPciSupportedRanges(PciRegistryInfo->NoBuses); 1067 1068 /* Loop every bus */ 1069 DbgPrint("\n====== PCI BUS HARDWARE DETECTION =======\n\n"); 1070 PciSlot.u.bits.Reserved = 0; 1071 for (i = 0; i < PciRegistryInfo->NoBuses; i++) 1072 { 1073 /* Get the bus handler */ 1074 BusHandler = HalHandlerForBus(PCIBus, i); 1075 1076 /* Loop every device */ 1077 for (j = 0; j < 32; j++) 1078 { 1079 /* Loop every function */ 1080 PciSlot.u.bits.DeviceNumber = j; 1081 for (k = 0; k < 8; k++) 1082 { 1083 /* Build the final slot structure */ 1084 PciSlot.u.bits.FunctionNumber = k; 1085 1086 /* Read the configuration information */ 1087 HalpReadPCIConfig(BusHandler, 1088 PciSlot, 1089 PciData, 1090 0, 1091 PCI_COMMON_HDR_LENGTH); 1092 1093 /* Skip if this is an invalid function */ 1094 if (PciData->VendorID == PCI_INVALID_VENDORID) continue; 1095 1096 /* Print out the entry */ 1097 HalpDebugPciDumpBus(i, j, k, PciData); 1098 1099 /* Check if this is a Cardbus bridge */ 1100 if (PCI_CONFIGURATION_TYPE(PciData) == PCI_CARDBUS_BRIDGE_TYPE) 1101 { 1102 /* Not supported */ 1103 DbgPrint("\tDevice is a PCI Cardbus Bridge. It will not work!\n"); 1104 continue; 1105 } 1106 1107 /* Check if this is a PCI device */ 1108 if (PCI_CONFIGURATION_TYPE(PciData) != PCI_BRIDGE_TYPE) 1109 { 1110 /* Check if it has an interrupt pin and line registered */ 1111 if ((PciData->u.type1.InterruptPin) && 1112 (PciData->u.type1.InterruptLine)) 1113 { 1114 /* Check if this interrupt line is connected to the bus */ 1115 if (PciData->u.type1.InterruptLine < 16) 1116 { 1117 /* Is this an IDE device? */ 1118 if (!HalpIsIdeDevice(PciData)) 1119 { 1120 /* We'll mask out this interrupt then */ 1121 DbgPrint("\tDevice is using IRQ %d! ISA Cards using that IRQ may fail!\n", 1122 PciData->u.type1.InterruptLine); 1123 HalpPciIrqMask |= (1 << PciData->u.type1.InterruptLine); 1124 } 1125 } 1126 } 1127 } 1128 1129 /* Check for broken Intel chips */ 1130 if (PciData->VendorID == 0x8086) 1131 { 1132 /* Check for broken 82830 PCI controller */ 1133 if ((PciData->DeviceID == 0x04A3) && 1134 (PciData->RevisionID < 0x11)) 1135 { 1136 /* Skip */ 1137 DbgPrint("\tDevice is a broken Intel 82430 PCI Controller. It will not work!\n\n"); 1138 continue; 1139 } 1140 1141 /* Check for broken 82378 PCI-to-ISA Bridge */ 1142 if ((PciData->DeviceID == 0x0484) && 1143 (PciData->RevisionID <= 3)) 1144 { 1145 /* Skip */ 1146 DbgPrint("\tDevice is a broken Intel 82378 PCI-to-ISA Bridge. It will not work!\n\n"); 1147 continue; 1148 } 1149 1150 /* Check for broken 82450 PCI Bridge */ 1151 if ((PciData->DeviceID == 0x84C4) && 1152 (PciData->RevisionID <= 4)) 1153 { 1154 DbgPrint("\tDevice is a Intel Orion 82450 PCI Bridge. It will not work!\n\n"); 1155 continue; 1156 } 1157 } 1158 1159 /* Do we know this card? */ 1160 if (!ExtendedAddressDecoding) 1161 { 1162 /* Check for it */ 1163 if (HalpIsRecognizedCard(PciRegistryInfo, 1164 PciData, 1165 HALP_CARD_FEATURE_FULL_DECODE)) 1166 { 1167 /* We'll do chipset checks later */ 1168 DbgPrint("\tDevice has Extended Address Decoding. It may fail to work on older BIOSes!\n"); 1169 ExtendedAddressDecoding = TRUE; 1170 } 1171 } 1172 1173 /* Now check the registry for chipset hacks */ 1174 Status = HalpGetChipHacks(PciData->VendorID, 1175 PciData->DeviceID, 1176 PciData->RevisionID, 1177 &HackFlags); 1178 if (NT_SUCCESS(Status)) 1179 { 1180 /* Check for broken ACPI routing */ 1181 if (HackFlags & HAL_PCI_CHIP_HACK_DISABLE_ACPI_IRQ_ROUTING) 1182 { 1183 DbgPrint("This chipset has broken ACPI IRQ Routing! Be aware!\n\n"); 1184 continue; 1185 } 1186 1187 /* Check for broken ACPI timer */ 1188 if (HackFlags & HAL_PCI_CHIP_HACK_BROKEN_ACPI_TIMER) 1189 { 1190 DbgPrint("This chipset has a broken ACPI timer! Be aware!\n\n"); 1191 continue; 1192 } 1193 1194 /* Check for hibernate-disable */ 1195 if (HackFlags & HAL_PCI_CHIP_HACK_DISABLE_HIBERNATE) 1196 { 1197 DbgPrint("This chipset has a broken PCI device which is incompatible with hibernation. Be aware!\n\n"); 1198 continue; 1199 } 1200 1201 /* Check for USB controllers that generate SMIs */ 1202 if (HackFlags & HAL_PCI_CHIP_HACK_USB_SMI_DISABLE) 1203 { 1204 DbgPrint("This chipset has a USB controller which generates SMIs. ReactOS will likely fail to boot!\n\n"); 1205 continue; 1206 } 1207 } 1208 1209 /* Terminate the entry */ 1210 DbgPrint("\n"); 1211 } 1212 } 1213 } 1214 1215 /* Initialize NMI Crash Flag */ 1216 HalpGetNMICrashFlag(); 1217 1218 /* Free the registry data */ 1219 ExFreePoolWithTag(PciRegistryInfo, TAG_HAL); 1220 1221 /* Tell PnP if this hard supports correct decoding */ 1222 HalpMarkChipsetDecode(ExtendedAddressDecoding); 1223 DbgPrint("====== PCI BUS DETECTION COMPLETE =======\n\n"); 1224 #endif 1225 } 1226 1227 INIT_FUNCTION 1228 VOID 1229 NTAPI 1230 HalpInitBusHandlers(VOID) 1231 { 1232 /* Register the HAL Bus Handler support */ 1233 HalpRegisterInternalBusHandlers(); 1234 } 1235 1236 INIT_FUNCTION 1237 VOID 1238 NTAPI 1239 HalpRegisterKdSupportFunctions(VOID) 1240 { 1241 /* Register PCI Device Functions */ 1242 KdSetupPciDeviceForDebugging = HalpSetupPciDeviceForDebugging; 1243 KdReleasePciDeviceforDebugging = HalpReleasePciDeviceForDebugging; 1244 1245 /* Register memory functions */ 1246 #ifndef _MINIHAL_ 1247 #if (NTDDI_VERSION >= NTDDI_VISTA) 1248 KdMapPhysicalMemory64 = HalpMapPhysicalMemory64Vista; 1249 KdUnmapVirtualAddress = HalpUnmapVirtualAddressVista; 1250 #else 1251 KdMapPhysicalMemory64 = HalpMapPhysicalMemory64; 1252 KdUnmapVirtualAddress = HalpUnmapVirtualAddress; 1253 #endif 1254 #endif 1255 1256 /* Register ACPI stub */ 1257 KdCheckPowerButton = HalpCheckPowerButton; 1258 } 1259 1260 NTSTATUS 1261 NTAPI 1262 HalpAssignSlotResources(IN PUNICODE_STRING RegistryPath, 1263 IN PUNICODE_STRING DriverClassName, 1264 IN PDRIVER_OBJECT DriverObject, 1265 IN PDEVICE_OBJECT DeviceObject, 1266 IN INTERFACE_TYPE BusType, 1267 IN ULONG BusNumber, 1268 IN ULONG SlotNumber, 1269 IN OUT PCM_RESOURCE_LIST *AllocatedResources) 1270 { 1271 PBUS_HANDLER Handler; 1272 NTSTATUS Status; 1273 PAGED_CODE(); 1274 DPRINT1("Slot assignment for %d on bus %u\n", BusType, BusNumber); 1275 1276 /* Find the handler */ 1277 Handler = HalReferenceHandlerForBus(BusType, BusNumber); 1278 if (!Handler) return STATUS_NOT_FOUND; 1279 1280 /* Do the assignment */ 1281 Status = Handler->AssignSlotResources(Handler, 1282 Handler, 1283 RegistryPath, 1284 DriverClassName, 1285 DriverObject, 1286 DeviceObject, 1287 SlotNumber, 1288 AllocatedResources); 1289 1290 /* Dereference the handler and return */ 1291 HalDereferenceBusHandler(Handler); 1292 return Status; 1293 } 1294 1295 BOOLEAN 1296 NTAPI 1297 HaliFindBusAddressTranslation(IN PHYSICAL_ADDRESS BusAddress, 1298 IN OUT PULONG AddressSpace, 1299 OUT PPHYSICAL_ADDRESS TranslatedAddress, 1300 IN OUT PULONG_PTR Context, 1301 IN BOOLEAN NextBus) 1302 { 1303 PHAL_BUS_HANDLER BusHandler; 1304 PBUS_HANDLER Handler; 1305 PLIST_ENTRY NextEntry; 1306 ULONG ContextValue; 1307 1308 /* Make sure we have a context */ 1309 if (!Context) return FALSE; 1310 ASSERT((*Context) || (NextBus == TRUE)); 1311 1312 /* Read the context */ 1313 ContextValue = *Context; 1314 1315 /* Find the bus handler */ 1316 Handler = HalpContextToBusHandler(ContextValue); 1317 if (!Handler) return FALSE; 1318 1319 /* Check if this is an ongoing lookup */ 1320 if (NextBus) 1321 { 1322 /* Get the HAL bus handler */ 1323 BusHandler = CONTAINING_RECORD(Handler, HAL_BUS_HANDLER, Handler); 1324 NextEntry = &BusHandler->AllHandlers; 1325 1326 /* Get the next one if we were already with one */ 1327 if (ContextValue) NextEntry = NextEntry->Flink; 1328 1329 /* Start scanning */ 1330 while (TRUE) 1331 { 1332 /* Check if this is the last one */ 1333 if (NextEntry == &HalpAllBusHandlers) 1334 { 1335 /* Quit */ 1336 *Context = 1; 1337 return FALSE; 1338 } 1339 1340 /* Call this translator */ 1341 BusHandler = CONTAINING_RECORD(NextEntry, HAL_BUS_HANDLER, AllHandlers); 1342 if (HalTranslateBusAddress(BusHandler->Handler.InterfaceType, 1343 BusHandler->Handler.BusNumber, 1344 BusAddress, 1345 AddressSpace, 1346 TranslatedAddress)) break; 1347 1348 /* Try the next one */ 1349 NextEntry = NextEntry->Flink; 1350 } 1351 1352 /* If we made it, we're done */ 1353 *Context = (ULONG_PTR)&BusHandler->Handler; 1354 return TRUE; 1355 } 1356 1357 /* Try the first one through */ 1358 if (!HalTranslateBusAddress(Handler->InterfaceType, 1359 Handler->BusNumber, 1360 BusAddress, 1361 AddressSpace, 1362 TranslatedAddress)) return FALSE; 1363 1364 /* Remember for next time */ 1365 *Context = (ULONG_PTR)Handler; 1366 return TRUE; 1367 } 1368 1369 BOOLEAN 1370 NTAPI 1371 HaliTranslateBusAddress(IN INTERFACE_TYPE InterfaceType, 1372 IN ULONG BusNumber, 1373 IN PHYSICAL_ADDRESS BusAddress, 1374 IN OUT PULONG AddressSpace, 1375 OUT PPHYSICAL_ADDRESS TranslatedAddress) 1376 { 1377 PBUS_HANDLER Handler; 1378 BOOLEAN Status; 1379 1380 /* Find the handler */ 1381 Handler = HalReferenceHandlerForBus(InterfaceType, BusNumber); 1382 if (!(Handler) || !(Handler->TranslateBusAddress)) 1383 { 1384 DPRINT1("No translator Interface: %x, Bus: %x, Handler: %p, BusAddress: %x!\n", InterfaceType, BusNumber, Handler, BusAddress); 1385 return FALSE; 1386 } 1387 1388 /* Do the assignment */ 1389 Status = Handler->TranslateBusAddress(Handler, 1390 Handler, 1391 BusAddress, 1392 AddressSpace, 1393 TranslatedAddress); 1394 1395 /* Dereference the handler and return */ 1396 HalDereferenceBusHandler(Handler); 1397 return Status; 1398 } 1399 1400 /* PUBLIC FUNCTIONS **********************************************************/ 1401 1402 /* 1403 * @implemented 1404 */ 1405 NTSTATUS 1406 NTAPI 1407 HalAdjustResourceList(IN PIO_RESOURCE_REQUIREMENTS_LIST *ResourceList) 1408 { 1409 PBUS_HANDLER Handler; 1410 ULONG Status; 1411 PAGED_CODE(); 1412 1413 /* Find the handler */ 1414 Handler = HalReferenceHandlerForBus((*ResourceList)->InterfaceType, 1415 (*ResourceList)->BusNumber); 1416 if (!Handler) return STATUS_SUCCESS; 1417 1418 /* Do the assignment */ 1419 Status = Handler->AdjustResourceList(Handler, 1420 Handler, 1421 ResourceList); 1422 1423 /* Dereference the handler and return */ 1424 HalDereferenceBusHandler(Handler); 1425 return Status; 1426 } 1427 1428 /* 1429 * @implemented 1430 */ 1431 NTSTATUS 1432 NTAPI 1433 HalAssignSlotResources(IN PUNICODE_STRING RegistryPath, 1434 IN PUNICODE_STRING DriverClassName, 1435 IN PDRIVER_OBJECT DriverObject, 1436 IN PDEVICE_OBJECT DeviceObject, 1437 IN INTERFACE_TYPE BusType, 1438 IN ULONG BusNumber, 1439 IN ULONG SlotNumber, 1440 IN OUT PCM_RESOURCE_LIST *AllocatedResources) 1441 { 1442 PAGED_CODE(); 1443 1444 /* Check the bus type */ 1445 if (BusType != PCIBus) 1446 { 1447 /* Call our internal handler */ 1448 return HalpAssignSlotResources(RegistryPath, 1449 DriverClassName, 1450 DriverObject, 1451 DeviceObject, 1452 BusType, 1453 BusNumber, 1454 SlotNumber, 1455 AllocatedResources); 1456 } 1457 else 1458 { 1459 /* Call the PCI registered function */ 1460 return HalPciAssignSlotResources(RegistryPath, 1461 DriverClassName, 1462 DriverObject, 1463 DeviceObject, 1464 PCIBus, 1465 BusNumber, 1466 SlotNumber, 1467 AllocatedResources); 1468 } 1469 } 1470 1471 /* 1472 * @implemented 1473 */ 1474 ULONG 1475 NTAPI 1476 HalGetBusData(IN BUS_DATA_TYPE BusDataType, 1477 IN ULONG BusNumber, 1478 IN ULONG SlotNumber, 1479 IN PVOID Buffer, 1480 IN ULONG Length) 1481 { 1482 /* Call the extended function */ 1483 return HalGetBusDataByOffset(BusDataType, 1484 BusNumber, 1485 SlotNumber, 1486 Buffer, 1487 0, 1488 Length); 1489 } 1490 1491 /* 1492 * @implemented 1493 */ 1494 ULONG 1495 NTAPI 1496 HalGetBusDataByOffset(IN BUS_DATA_TYPE BusDataType, 1497 IN ULONG BusNumber, 1498 IN ULONG SlotNumber, 1499 IN PVOID Buffer, 1500 IN ULONG Offset, 1501 IN ULONG Length) 1502 { 1503 PBUS_HANDLER Handler; 1504 ULONG Status; 1505 1506 /* Find the handler */ 1507 Handler = HaliReferenceHandlerForConfigSpace(BusDataType, BusNumber); 1508 if (!Handler) return 0; 1509 1510 /* Do the assignment */ 1511 Status = Handler->GetBusData(Handler, 1512 Handler, 1513 SlotNumber, 1514 Buffer, 1515 Offset, 1516 Length); 1517 1518 /* Dereference the handler and return */ 1519 HalDereferenceBusHandler(Handler); 1520 return Status; 1521 } 1522 1523 /* 1524 * @implemented 1525 */ 1526 ULONG 1527 NTAPI 1528 HalGetInterruptVector(IN INTERFACE_TYPE InterfaceType, 1529 IN ULONG BusNumber, 1530 IN ULONG BusInterruptLevel, 1531 IN ULONG BusInterruptVector, 1532 OUT PKIRQL Irql, 1533 OUT PKAFFINITY Affinity) 1534 { 1535 PBUS_HANDLER Handler; 1536 ULONG Vector; 1537 PAGED_CODE(); 1538 1539 /* Defaults */ 1540 *Irql = 0; 1541 *Affinity = 0; 1542 1543 /* Find the handler */ 1544 Handler = HalReferenceHandlerForBus(InterfaceType, BusNumber); 1545 if (!Handler) return 0; 1546 1547 /* Do the assignment */ 1548 Vector = Handler->GetInterruptVector(Handler, 1549 Handler, 1550 BusInterruptLevel, 1551 BusInterruptVector, 1552 Irql, 1553 Affinity); 1554 if ((Vector != IRQ2VECTOR(BusInterruptLevel)) || 1555 (*Irql != VECTOR2IRQL(IRQ2VECTOR(BusInterruptLevel)))) 1556 { 1557 DPRINT1("Returning IRQL %lx, Vector %lx for Level/Vector: %lx/%lx\n", 1558 *Irql, Vector, BusInterruptLevel, BusInterruptVector); 1559 DPRINT1("Old HAL would've returned IRQL %lx and Vector %lx\n", 1560 VECTOR2IRQL(IRQ2VECTOR(BusInterruptLevel)), 1561 IRQ2VECTOR(BusInterruptLevel)); 1562 } 1563 1564 /* Dereference the handler and return */ 1565 HalDereferenceBusHandler(Handler); 1566 return Vector; 1567 } 1568 1569 /* 1570 * @implemented 1571 */ 1572 ULONG 1573 NTAPI 1574 HalSetBusData(IN BUS_DATA_TYPE BusDataType, 1575 IN ULONG BusNumber, 1576 IN ULONG SlotNumber, 1577 IN PVOID Buffer, 1578 IN ULONG Length) 1579 { 1580 /* Call the extended function */ 1581 return HalSetBusDataByOffset(BusDataType, 1582 BusNumber, 1583 SlotNumber, 1584 Buffer, 1585 0, 1586 Length); 1587 } 1588 1589 /* 1590 * @implemented 1591 */ 1592 ULONG 1593 NTAPI 1594 HalSetBusDataByOffset(IN BUS_DATA_TYPE BusDataType, 1595 IN ULONG BusNumber, 1596 IN ULONG SlotNumber, 1597 IN PVOID Buffer, 1598 IN ULONG Offset, 1599 IN ULONG Length) 1600 { 1601 PBUS_HANDLER Handler; 1602 ULONG Status; 1603 1604 /* Find the handler */ 1605 Handler = HaliReferenceHandlerForConfigSpace(BusDataType, BusNumber); 1606 if (!Handler) return 0; 1607 1608 /* Do the assignment */ 1609 Status = Handler->SetBusData(Handler, 1610 Handler, 1611 SlotNumber, 1612 Buffer, 1613 Offset, 1614 Length); 1615 1616 /* Dereference the handler and return */ 1617 HalDereferenceBusHandler(Handler); 1618 return Status; 1619 } 1620 1621 /* 1622 * @implemented 1623 */ 1624 BOOLEAN 1625 NTAPI 1626 HalTranslateBusAddress(IN INTERFACE_TYPE InterfaceType, 1627 IN ULONG BusNumber, 1628 IN PHYSICAL_ADDRESS BusAddress, 1629 IN OUT PULONG AddressSpace, 1630 OUT PPHYSICAL_ADDRESS TranslatedAddress) 1631 { 1632 /* Look as the bus type */ 1633 if (InterfaceType == PCIBus) 1634 { 1635 /* Call the PCI registered function */ 1636 return HalPciTranslateBusAddress(PCIBus, 1637 BusNumber, 1638 BusAddress, 1639 AddressSpace, 1640 TranslatedAddress); 1641 } 1642 else 1643 { 1644 /* Call the bus handler */ 1645 return HaliTranslateBusAddress(InterfaceType, 1646 BusNumber, 1647 BusAddress, 1648 AddressSpace, 1649 TranslatedAddress); 1650 } 1651 } 1652 1653 /* EOF */ 1654