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