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