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