1 /* 2 * PROJECT: ReactOS HAL 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: hal/halx86/legacy/bus/pcibus.c 5 * PURPOSE: PCI Bus Support (Configuration Space, Resource Allocation) 6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 7 */ 8 9 /* INCLUDES ******************************************************************/ 10 11 #include <hal.h> 12 #define NDEBUG 13 #include <debug.h> 14 15 /* GLOBALS *******************************************************************/ 16 17 extern BOOLEAN HalpPciLockSettings; 18 ULONG HalpBusType; 19 20 BOOLEAN HalpPCIConfigInitialized; 21 ULONG HalpMinPciBus, HalpMaxPciBus; 22 KSPIN_LOCK HalpPCIConfigLock; 23 PCI_CONFIG_HANDLER PCIConfigHandler; 24 25 /* PCI Operation Matrix */ 26 UCHAR PCIDeref[4][4] = 27 { 28 {0, 1, 2, 2}, // ULONG-aligned offset 29 {1, 1, 1, 1}, // UCHAR-aligned offset 30 {2, 1, 2, 2}, // USHORT-aligned offset 31 {1, 1, 1, 1} // UCHAR-aligned offset 32 }; 33 34 /* Type 1 PCI Bus */ 35 PCI_CONFIG_HANDLER PCIConfigHandlerType1 = 36 { 37 /* Synchronization */ 38 (FncSync)HalpPCISynchronizeType1, 39 (FncReleaseSync)HalpPCIReleaseSynchronzationType1, 40 41 /* Read */ 42 { 43 (FncConfigIO)HalpPCIReadUlongType1, 44 (FncConfigIO)HalpPCIReadUcharType1, 45 (FncConfigIO)HalpPCIReadUshortType1 46 }, 47 48 /* Write */ 49 { 50 (FncConfigIO)HalpPCIWriteUlongType1, 51 (FncConfigIO)HalpPCIWriteUcharType1, 52 (FncConfigIO)HalpPCIWriteUshortType1 53 } 54 }; 55 56 /* Type 2 PCI Bus */ 57 PCI_CONFIG_HANDLER PCIConfigHandlerType2 = 58 { 59 /* Synchronization */ 60 (FncSync)HalpPCISynchronizeType2, 61 (FncReleaseSync)HalpPCIReleaseSynchronizationType2, 62 63 /* Read */ 64 { 65 (FncConfigIO)HalpPCIReadUlongType2, 66 (FncConfigIO)HalpPCIReadUcharType2, 67 (FncConfigIO)HalpPCIReadUshortType2 68 }, 69 70 /* Write */ 71 { 72 (FncConfigIO)HalpPCIWriteUlongType2, 73 (FncConfigIO)HalpPCIWriteUcharType2, 74 (FncConfigIO)HalpPCIWriteUshortType2 75 } 76 }; 77 78 PCIPBUSDATA HalpFakePciBusData = 79 { 80 { 81 PCI_DATA_TAG, 82 PCI_DATA_VERSION, 83 HalpReadPCIConfig, 84 HalpWritePCIConfig, 85 NULL, 86 NULL, 87 {{{0, 0, 0}}}, 88 {0, 0, 0, 0} 89 }, 90 {{0, 0}}, 91 32, 92 }; 93 94 BUS_HANDLER HalpFakePciBusHandler = 95 { 96 1, 97 PCIBus, 98 PCIConfiguration, 99 0, 100 NULL, 101 NULL, 102 &HalpFakePciBusData, 103 0, 104 NULL, 105 {0, 0, 0, 0}, 106 (PGETSETBUSDATA)HalpGetPCIData, 107 (PGETSETBUSDATA)HalpSetPCIData, 108 NULL, 109 HalpAssignPCISlotResources, 110 NULL, 111 NULL 112 }; 113 114 /* TYPE 1 FUNCTIONS **********************************************************/ 115 116 VOID 117 NTAPI 118 HalpPCISynchronizeType1(IN PBUS_HANDLER BusHandler, 119 IN PCI_SLOT_NUMBER Slot, 120 OUT PKIRQL OldIrql, 121 OUT PPCI_TYPE1_CFG_BITS PciCfg1) 122 { 123 /* Setup the PCI Configuration Register */ 124 PciCfg1->u.AsULONG = 0; 125 PciCfg1->u.bits.BusNumber = BusHandler->BusNumber; 126 PciCfg1->u.bits.DeviceNumber = Slot.u.bits.DeviceNumber; 127 PciCfg1->u.bits.FunctionNumber = Slot.u.bits.FunctionNumber; 128 PciCfg1->u.bits.Enable = TRUE; 129 130 /* Acquire the lock */ 131 KeRaiseIrql(HIGH_LEVEL, OldIrql); 132 KeAcquireSpinLockAtDpcLevel(&HalpPCIConfigLock); 133 } 134 135 VOID 136 NTAPI 137 HalpPCIReleaseSynchronzationType1(IN PBUS_HANDLER BusHandler, 138 IN KIRQL OldIrql) 139 { 140 PCI_TYPE1_CFG_BITS PciCfg1; 141 142 /* Clear the PCI Configuration Register */ 143 PciCfg1.u.AsULONG = 0; 144 WRITE_PORT_ULONG(((PPCIPBUSDATA)BusHandler->BusData)->Config.Type1.Address, 145 PciCfg1.u.AsULONG); 146 147 /* Release the lock */ 148 KeReleaseSpinLock(&HalpPCIConfigLock, OldIrql); 149 } 150 151 TYPE1_READ(HalpPCIReadUcharType1, UCHAR) 152 TYPE1_READ(HalpPCIReadUshortType1, USHORT) 153 TYPE1_READ(HalpPCIReadUlongType1, ULONG) 154 TYPE1_WRITE(HalpPCIWriteUcharType1, UCHAR) 155 TYPE1_WRITE(HalpPCIWriteUshortType1, USHORT) 156 TYPE1_WRITE(HalpPCIWriteUlongType1, ULONG) 157 158 /* TYPE 2 FUNCTIONS **********************************************************/ 159 160 VOID 161 NTAPI 162 HalpPCISynchronizeType2(IN PBUS_HANDLER BusHandler, 163 IN PCI_SLOT_NUMBER Slot, 164 OUT PKIRQL OldIrql, 165 OUT PPCI_TYPE2_ADDRESS_BITS PciCfg) 166 { 167 PCI_TYPE2_CSE_BITS PciCfg2Cse; 168 PPCIPBUSDATA BusData = (PPCIPBUSDATA)BusHandler->BusData; 169 170 /* Setup the configuration register */ 171 PciCfg->u.AsUSHORT = 0; 172 PciCfg->u.bits.Agent = (USHORT)Slot.u.bits.DeviceNumber; 173 PciCfg->u.bits.AddressBase = (USHORT)BusData->Config.Type2.Base; 174 175 /* Acquire the lock */ 176 KeRaiseIrql(HIGH_LEVEL, OldIrql); 177 KeAcquireSpinLockAtDpcLevel(&HalpPCIConfigLock); 178 179 /* Setup the CSE Register */ 180 PciCfg2Cse.u.AsUCHAR = 0; 181 PciCfg2Cse.u.bits.Enable = TRUE; 182 PciCfg2Cse.u.bits.FunctionNumber = (UCHAR)Slot.u.bits.FunctionNumber; 183 PciCfg2Cse.u.bits.Key = -1; 184 185 /* Write the bus number and CSE */ 186 WRITE_PORT_UCHAR(BusData->Config.Type2.Forward, 187 (UCHAR)BusHandler->BusNumber); 188 WRITE_PORT_UCHAR(BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR); 189 } 190 191 VOID 192 NTAPI 193 HalpPCIReleaseSynchronizationType2(IN PBUS_HANDLER BusHandler, 194 IN KIRQL OldIrql) 195 { 196 PCI_TYPE2_CSE_BITS PciCfg2Cse; 197 PPCIPBUSDATA BusData = (PPCIPBUSDATA)BusHandler->BusData; 198 199 /* Clear CSE and bus number */ 200 PciCfg2Cse.u.AsUCHAR = 0; 201 WRITE_PORT_UCHAR(BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR); 202 WRITE_PORT_UCHAR(BusData->Config.Type2.Forward, 0); 203 204 /* Release the lock */ 205 KeReleaseSpinLock(&HalpPCIConfigLock, OldIrql); 206 } 207 208 TYPE2_READ(HalpPCIReadUcharType2, UCHAR) 209 TYPE2_READ(HalpPCIReadUshortType2, USHORT) 210 TYPE2_READ(HalpPCIReadUlongType2, ULONG) 211 TYPE2_WRITE(HalpPCIWriteUcharType2, UCHAR) 212 TYPE2_WRITE(HalpPCIWriteUshortType2, USHORT) 213 TYPE2_WRITE(HalpPCIWriteUlongType2, ULONG) 214 215 /* PCI CONFIGURATION SPACE ***************************************************/ 216 217 VOID 218 NTAPI 219 HalpPCIConfig(IN PBUS_HANDLER BusHandler, 220 IN PCI_SLOT_NUMBER Slot, 221 IN PUCHAR Buffer, 222 IN ULONG Offset, 223 IN ULONG Length, 224 IN FncConfigIO *ConfigIO) 225 { 226 KIRQL OldIrql; 227 ULONG i; 228 UCHAR State[20]; 229 230 /* Synchronize the operation */ 231 PCIConfigHandler.Synchronize(BusHandler, Slot, &OldIrql, State); 232 233 /* Loop every increment */ 234 while (Length) 235 { 236 /* Find out the type of read/write we need to do */ 237 i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)]; 238 239 /* Do the read/write and return the number of bytes */ 240 i = ConfigIO[i]((PPCIPBUSDATA)BusHandler->BusData, 241 State, 242 Buffer, 243 Offset); 244 245 /* Increment the buffer position and offset, and decrease the length */ 246 Offset += i; 247 Buffer += i; 248 Length -= i; 249 } 250 251 /* Release the lock and PCI bus */ 252 PCIConfigHandler.ReleaseSynchronzation(BusHandler, OldIrql); 253 } 254 255 VOID 256 NTAPI 257 HalpReadPCIConfig(IN PBUS_HANDLER BusHandler, 258 IN PCI_SLOT_NUMBER Slot, 259 IN PVOID Buffer, 260 IN ULONG Offset, 261 IN ULONG Length) 262 { 263 /* Validate the PCI Slot */ 264 if (!HalpValidPCISlot(BusHandler, Slot)) 265 { 266 /* Fill the buffer with invalid data */ 267 RtlFillMemory(Buffer, Length, -1); 268 } 269 else 270 { 271 /* Send the request */ 272 HalpPCIConfig(BusHandler, 273 Slot, 274 Buffer, 275 Offset, 276 Length, 277 PCIConfigHandler.ConfigRead); 278 } 279 } 280 281 VOID 282 NTAPI 283 HalpWritePCIConfig(IN PBUS_HANDLER BusHandler, 284 IN PCI_SLOT_NUMBER Slot, 285 IN PVOID Buffer, 286 IN ULONG Offset, 287 IN ULONG Length) 288 { 289 /* Validate the PCI Slot */ 290 if (HalpValidPCISlot(BusHandler, Slot)) 291 { 292 /* Send the request */ 293 HalpPCIConfig(BusHandler, 294 Slot, 295 Buffer, 296 Offset, 297 Length, 298 PCIConfigHandler.ConfigWrite); 299 } 300 } 301 302 #ifdef SARCH_XBOX 303 static 304 BOOLEAN 305 HalpXboxBlacklistedPCISlot( 306 _In_ ULONG BusNumber, 307 _In_ PCI_SLOT_NUMBER Slot) 308 { 309 /* Trying to get PCI config data from devices 0:0:1 and 0:0:2 will completely 310 * hang the Xbox. Also, the device number doesn't seem to be decoded for the 311 * video card, so it appears to be present on 1:0:0 - 1:31:0. 312 * We hack around these problems by indicating "device not present" for devices 313 * 0:0:1, 0:0:2, 1:1:0, 1:2:0, 1:3:0, ...., 1:31:0 */ 314 if ((BusNumber == 0 && Slot.u.bits.DeviceNumber == 0 && 315 (Slot.u.bits.FunctionNumber == 1 || Slot.u.bits.FunctionNumber == 2)) || 316 (BusNumber == 1 && Slot.u.bits.DeviceNumber != 0)) 317 { 318 DPRINT("Blacklisted PCI slot (%d:%d:%d)\n", 319 BusNumber, Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber); 320 return TRUE; 321 } 322 323 return FALSE; 324 } 325 #endif 326 327 BOOLEAN 328 NTAPI 329 HalpValidPCISlot(IN PBUS_HANDLER BusHandler, 330 IN PCI_SLOT_NUMBER Slot) 331 { 332 PCI_SLOT_NUMBER MultiSlot; 333 PPCIPBUSDATA BusData = (PPCIPBUSDATA)BusHandler->BusData; 334 UCHAR HeaderType; 335 //ULONG Device; 336 337 /* Simple validation */ 338 if (Slot.u.bits.Reserved) return FALSE; 339 if (Slot.u.bits.DeviceNumber >= BusData->MaxDevice) return FALSE; 340 341 #ifdef SARCH_XBOX 342 if (HalpXboxBlacklistedPCISlot(BusHandler->BusNumber, Slot)) 343 return FALSE; 344 #endif 345 346 /* Function 0 doesn't need checking */ 347 if (!Slot.u.bits.FunctionNumber) return TRUE; 348 349 /* Functions 0+ need Multi-Function support, so check the slot */ 350 //Device = Slot.u.bits.DeviceNumber; 351 MultiSlot = Slot; 352 MultiSlot.u.bits.FunctionNumber = 0; 353 354 /* Send function 0 request to get the header back */ 355 HalpReadPCIConfig(BusHandler, 356 MultiSlot, 357 &HeaderType, 358 FIELD_OFFSET(PCI_COMMON_CONFIG, HeaderType), 359 sizeof(UCHAR)); 360 361 /* Now make sure the header is multi-function */ 362 if (!(HeaderType & PCI_MULTIFUNCTION) || (HeaderType == 0xFF)) return FALSE; 363 return TRUE; 364 } 365 366 CODE_SEG("INIT") 367 ULONG 368 HalpPhase0GetPciDataByOffset( 369 _In_ ULONG Bus, 370 _In_ PCI_SLOT_NUMBER PciSlot, 371 _Out_writes_bytes_all_(Length) PVOID Buffer, 372 _In_ ULONG Offset, 373 _In_ ULONG Length) 374 { 375 ULONG BytesLeft = Length; 376 PUCHAR BufferPtr = Buffer; 377 PCI_TYPE1_CFG_BITS PciCfg; 378 379 #ifdef SARCH_XBOX 380 if (HalpXboxBlacklistedPCISlot(Bus, PciSlot)) 381 { 382 RtlFillMemory(Buffer, Length, 0xFF); 383 return Length; 384 } 385 #endif 386 387 PciCfg.u.AsULONG = 0; 388 PciCfg.u.bits.BusNumber = Bus; 389 PciCfg.u.bits.DeviceNumber = PciSlot.u.bits.DeviceNumber; 390 PciCfg.u.bits.FunctionNumber = PciSlot.u.bits.FunctionNumber; 391 PciCfg.u.bits.Enable = TRUE; 392 393 while (BytesLeft) 394 { 395 ULONG i; 396 397 PciCfg.u.bits.RegisterNumber = Offset / sizeof(ULONG); 398 WRITE_PORT_ULONG((PULONG)PCI_TYPE1_ADDRESS_PORT, PciCfg.u.AsULONG); 399 400 i = PCIDeref[Offset % sizeof(ULONG)][BytesLeft % sizeof(ULONG)]; 401 switch (i) 402 { 403 case 0: 404 { 405 *(PULONG)BufferPtr = READ_PORT_ULONG((PULONG)PCI_TYPE1_DATA_PORT); 406 407 /* Number of bytes read */ 408 i = sizeof(ULONG); 409 break; 410 } 411 case 1: 412 { 413 *BufferPtr = READ_PORT_UCHAR((PUCHAR)(PCI_TYPE1_DATA_PORT + 414 Offset % sizeof(ULONG))); 415 break; 416 } 417 case 2: 418 { 419 *(PUSHORT)BufferPtr = READ_PORT_USHORT((PUSHORT)(PCI_TYPE1_DATA_PORT + 420 Offset % sizeof(ULONG))); 421 break; 422 } 423 424 DEFAULT_UNREACHABLE; 425 } 426 427 Offset += i; 428 BufferPtr += i; 429 BytesLeft -= i; 430 } 431 432 return Length; 433 } 434 435 CODE_SEG("INIT") 436 ULONG 437 HalpPhase0SetPciDataByOffset( 438 _In_ ULONG Bus, 439 _In_ PCI_SLOT_NUMBER PciSlot, 440 _In_reads_bytes_(Length) PVOID Buffer, 441 _In_ ULONG Offset, 442 _In_ ULONG Length) 443 { 444 ULONG BytesLeft = Length; 445 PUCHAR BufferPtr = Buffer; 446 PCI_TYPE1_CFG_BITS PciCfg; 447 448 #ifdef SARCH_XBOX 449 if (HalpXboxBlacklistedPCISlot(Bus, PciSlot)) 450 { 451 return 0; 452 } 453 #endif 454 455 PciCfg.u.AsULONG = 0; 456 PciCfg.u.bits.BusNumber = Bus; 457 PciCfg.u.bits.DeviceNumber = PciSlot.u.bits.DeviceNumber; 458 PciCfg.u.bits.FunctionNumber = PciSlot.u.bits.FunctionNumber; 459 PciCfg.u.bits.Enable = TRUE; 460 461 while (BytesLeft) 462 { 463 ULONG i; 464 465 PciCfg.u.bits.RegisterNumber = Offset / sizeof(ULONG); 466 WRITE_PORT_ULONG((PULONG)PCI_TYPE1_ADDRESS_PORT, PciCfg.u.AsULONG); 467 468 i = PCIDeref[Offset % sizeof(ULONG)][BytesLeft % sizeof(ULONG)]; 469 switch (i) 470 { 471 case 0: 472 { 473 WRITE_PORT_ULONG((PULONG)PCI_TYPE1_DATA_PORT, *(PULONG)BufferPtr); 474 475 /* Number of bytes written */ 476 i = sizeof(ULONG); 477 break; 478 } 479 case 1: 480 { 481 WRITE_PORT_UCHAR((PUCHAR)(PCI_TYPE1_DATA_PORT + Offset % sizeof(ULONG)), 482 *BufferPtr); 483 break; 484 } 485 case 2: 486 { 487 WRITE_PORT_USHORT((PUSHORT)(PCI_TYPE1_DATA_PORT + Offset % sizeof(ULONG)), 488 *(PUSHORT)BufferPtr); 489 break; 490 } 491 492 DEFAULT_UNREACHABLE; 493 } 494 495 Offset += i; 496 BufferPtr += i; 497 BytesLeft -= i; 498 } 499 500 return Length; 501 } 502 503 /* HAL PCI CALLBACKS *********************************************************/ 504 505 ULONG 506 NTAPI 507 HalpGetPCIData(IN PBUS_HANDLER BusHandler, 508 IN PBUS_HANDLER RootHandler, 509 IN ULONG SlotNumber, 510 IN PVOID Buffer, 511 IN ULONG Offset, 512 IN ULONG Length) 513 { 514 PCI_SLOT_NUMBER Slot; 515 UCHAR PciBuffer[PCI_COMMON_HDR_LENGTH]; 516 PPCI_COMMON_CONFIG PciConfig = (PPCI_COMMON_CONFIG)PciBuffer; 517 ULONG Len = 0; 518 519 Slot.u.AsULONG = SlotNumber; 520 #ifdef SARCH_XBOX 521 if (HalpXboxBlacklistedPCISlot(BusHandler->BusNumber, Slot)) 522 { 523 RtlFillMemory(Buffer, Length, 0xFF); 524 return Length; 525 } 526 #endif 527 528 /* Normalize the length */ 529 if (Length > sizeof(PCI_COMMON_CONFIG)) Length = sizeof(PCI_COMMON_CONFIG); 530 531 /* Check if this is a vendor-specific read */ 532 if (Offset >= PCI_COMMON_HDR_LENGTH) 533 { 534 /* Read the header */ 535 HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, sizeof(ULONG)); 536 537 /* Make sure the vendor is valid */ 538 if (PciConfig->VendorID == PCI_INVALID_VENDORID) return 0; 539 } 540 else 541 { 542 /* Read the entire header */ 543 Len = PCI_COMMON_HDR_LENGTH; 544 HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, Len); 545 546 /* Validate the vendor ID */ 547 if (PciConfig->VendorID == PCI_INVALID_VENDORID) 548 { 549 /* It's invalid, but we want to return this much */ 550 Len = sizeof(USHORT); 551 } 552 553 /* Now check if there's space left */ 554 if (Len < Offset) return 0; 555 556 /* There is, so return what's after the offset and normalize */ 557 Len -= Offset; 558 if (Len > Length) Len = Length; 559 560 /* Copy the data into the caller's buffer */ 561 RtlMoveMemory(Buffer, PciBuffer + Offset, Len); 562 563 /* Update buffer and offset, decrement total length */ 564 Offset += Len; 565 Buffer = (PVOID)((ULONG_PTR)Buffer + Len); 566 Length -= Len; 567 } 568 569 /* Now we still have something to copy */ 570 if (Length) 571 { 572 /* Check if it's vendor-specific data */ 573 if (Offset >= PCI_COMMON_HDR_LENGTH) 574 { 575 /* Read it now */ 576 HalpReadPCIConfig(BusHandler, Slot, Buffer, Offset, Length); 577 Len += Length; 578 } 579 } 580 581 /* Update the total length read */ 582 return Len; 583 } 584 585 ULONG 586 NTAPI 587 HalpSetPCIData(IN PBUS_HANDLER BusHandler, 588 IN PBUS_HANDLER RootHandler, 589 IN ULONG SlotNumber, 590 IN PVOID Buffer, 591 IN ULONG Offset, 592 IN ULONG Length) 593 { 594 PCI_SLOT_NUMBER Slot; 595 UCHAR PciBuffer[PCI_COMMON_HDR_LENGTH]; 596 PPCI_COMMON_CONFIG PciConfig = (PPCI_COMMON_CONFIG)PciBuffer; 597 ULONG Len = 0; 598 599 Slot.u.AsULONG = SlotNumber; 600 #ifdef SARCH_XBOX 601 if (HalpXboxBlacklistedPCISlot(BusHandler->BusNumber, Slot)) 602 return 0; 603 #endif 604 605 /* Normalize the length */ 606 if (Length > sizeof(PCI_COMMON_CONFIG)) Length = sizeof(PCI_COMMON_CONFIG); 607 608 /* Check if this is a vendor-specific read */ 609 if (Offset >= PCI_COMMON_HDR_LENGTH) 610 { 611 /* Read the header */ 612 HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, sizeof(ULONG)); 613 614 /* Make sure the vendor is valid */ 615 if (PciConfig->VendorID == PCI_INVALID_VENDORID) return 0; 616 } 617 else 618 { 619 /* Read the entire header and validate the vendor ID */ 620 Len = PCI_COMMON_HDR_LENGTH; 621 HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, Len); 622 if (PciConfig->VendorID == PCI_INVALID_VENDORID) return 0; 623 624 /* Return what's after the offset and normalize */ 625 Len -= Offset; 626 if (Len > Length) Len = Length; 627 628 /* Copy the specific caller data */ 629 RtlMoveMemory(PciBuffer + Offset, Buffer, Len); 630 631 /* Write the actual configuration data */ 632 HalpWritePCIConfig(BusHandler, Slot, PciBuffer + Offset, Offset, Len); 633 634 /* Update buffer and offset, decrement total length */ 635 Offset += Len; 636 Buffer = (PVOID)((ULONG_PTR)Buffer + Len); 637 Length -= Len; 638 } 639 640 /* Now we still have something to copy */ 641 if (Length) 642 { 643 /* Check if it's vendor-specific data */ 644 if (Offset >= PCI_COMMON_HDR_LENGTH) 645 { 646 /* Read it now */ 647 HalpWritePCIConfig(BusHandler, Slot, Buffer, Offset, Length); 648 Len += Length; 649 } 650 } 651 652 /* Update the total length read */ 653 return Len; 654 } 655 #ifndef _MINIHAL_ 656 ULONG 657 NTAPI 658 HalpGetPCIIntOnISABus(IN PBUS_HANDLER BusHandler, 659 IN PBUS_HANDLER RootHandler, 660 IN ULONG BusInterruptLevel, 661 IN ULONG BusInterruptVector, 662 OUT PKIRQL Irql, 663 OUT PKAFFINITY Affinity) 664 { 665 /* Validate the level first */ 666 if (BusInterruptLevel < 1) return 0; 667 668 /* PCI has its IRQs on top of ISA IRQs, so pass it on to the ISA handler */ 669 return HalGetInterruptVector(Isa, 670 0, 671 BusInterruptLevel, 672 0, 673 Irql, 674 Affinity); 675 } 676 #endif // _MINIHAL_ 677 678 VOID 679 NTAPI 680 HalpPCIPin2ISALine(IN PBUS_HANDLER BusHandler, 681 IN PBUS_HANDLER RootHandler, 682 IN PCI_SLOT_NUMBER SlotNumber, 683 IN PPCI_COMMON_CONFIG PciData) 684 { 685 UNIMPLEMENTED_DBGBREAK(); 686 } 687 688 VOID 689 NTAPI 690 HalpPCIISALine2Pin(IN PBUS_HANDLER BusHandler, 691 IN PBUS_HANDLER RootHandler, 692 IN PCI_SLOT_NUMBER SlotNumber, 693 IN PPCI_COMMON_CONFIG PciNewData, 694 IN PPCI_COMMON_CONFIG PciOldData) 695 { 696 UNIMPLEMENTED_DBGBREAK(); 697 } 698 699 #ifndef _MINIHAL_ 700 NTSTATUS 701 NTAPI 702 HalpGetISAFixedPCIIrq(IN PBUS_HANDLER BusHandler, 703 IN PBUS_HANDLER RootHandler, 704 IN PCI_SLOT_NUMBER PciSlot, 705 OUT PSUPPORTED_RANGE *Range) 706 { 707 PCI_COMMON_HEADER PciData; 708 709 /* Read PCI configuration data */ 710 HalGetBusData(PCIConfiguration, 711 BusHandler->BusNumber, 712 PciSlot.u.AsULONG, 713 &PciData, 714 PCI_COMMON_HDR_LENGTH); 715 716 /* Make sure it's a real device */ 717 if (PciData.VendorID == PCI_INVALID_VENDORID) return STATUS_UNSUCCESSFUL; 718 719 /* Allocate the supported range structure */ 720 *Range = ExAllocatePoolWithTag(PagedPool, sizeof(SUPPORTED_RANGE), TAG_HAL); 721 if (!*Range) return STATUS_INSUFFICIENT_RESOURCES; 722 723 /* Set it up */ 724 RtlZeroMemory(*Range, sizeof(SUPPORTED_RANGE)); 725 (*Range)->Base = 1; 726 727 /* If the PCI device has no IRQ, nothing to do */ 728 if (!PciData.u.type0.InterruptPin) return STATUS_SUCCESS; 729 730 /* FIXME: The PCI IRQ Routing Miniport should be called */ 731 732 /* Also if the INT# seems bogus, nothing to do either */ 733 if ((PciData.u.type0.InterruptLine == 0) || 734 (PciData.u.type0.InterruptLine == 255)) 735 { 736 /* Fake success */ 737 return STATUS_SUCCESS; 738 } 739 740 /* Otherwise, the INT# should be valid, return it to the caller */ 741 (*Range)->Base = PciData.u.type0.InterruptLine; 742 (*Range)->Limit = PciData.u.type0.InterruptLine; 743 return STATUS_SUCCESS; 744 } 745 #endif // _MINIHAL_ 746 747 static ULONG NTAPI 748 PciSize(ULONG Base, ULONG Mask) 749 { 750 ULONG Size = Mask & Base; /* Find the significant bits */ 751 Size = Size & ~(Size - 1); /* Get the lowest of them to find the decode size */ 752 return Size; 753 } 754 755 NTSTATUS 756 NTAPI 757 HalpAdjustPCIResourceList(IN PBUS_HANDLER BusHandler, 758 IN PBUS_HANDLER RootHandler, 759 IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList) 760 { 761 PPCIPBUSDATA BusData; 762 PCI_SLOT_NUMBER SlotNumber; 763 PSUPPORTED_RANGE Interrupt; 764 NTSTATUS Status; 765 766 /* Get PCI bus data */ 767 BusData = BusHandler->BusData; 768 SlotNumber.u.AsULONG = (*pResourceList)->SlotNumber; 769 770 /* Get the IRQ supported range */ 771 Status = BusData->GetIrqRange(BusHandler, RootHandler, SlotNumber, &Interrupt); 772 if (!NT_SUCCESS(Status)) return Status; 773 #ifndef _MINIHAL_ 774 /* Handle the /PCILOCK feature */ 775 if (HalpPciLockSettings) 776 { 777 /* /PCILOCK is not yet supported */ 778 UNIMPLEMENTED_DBGBREAK("/PCILOCK boot switch is not yet supported."); 779 } 780 #endif 781 /* Now create the correct resource list based on the supported bus ranges */ 782 #if 0 783 Status = HaliAdjustResourceListRange(BusHandler->BusAddresses, 784 Interrupt, 785 pResourceList); 786 #else 787 DPRINT1("HAL: No PCI Resource Adjustment done! Hardware may malfunction\n"); 788 Status = STATUS_SUCCESS; 789 #endif 790 791 /* Return to caller */ 792 ExFreePool(Interrupt); 793 return Status; 794 } 795 796 NTSTATUS 797 NTAPI 798 HalpAssignPCISlotResources(IN PBUS_HANDLER BusHandler, 799 IN PBUS_HANDLER RootHandler, 800 IN PUNICODE_STRING RegistryPath, 801 IN PUNICODE_STRING DriverClassName OPTIONAL, 802 IN PDRIVER_OBJECT DriverObject, 803 IN PDEVICE_OBJECT DeviceObject OPTIONAL, 804 IN ULONG Slot, 805 IN OUT PCM_RESOURCE_LIST *AllocatedResources) 806 { 807 PCI_COMMON_CONFIG PciConfig; 808 SIZE_T Address; 809 ULONG ResourceCount; 810 ULONG Size[PCI_TYPE0_ADDRESSES]; 811 NTSTATUS Status = STATUS_SUCCESS; 812 UCHAR Offset; 813 PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor; 814 PCI_SLOT_NUMBER SlotNumber; 815 ULONG WriteBuffer; 816 DPRINT1("WARNING: PCI Slot Resource Assignment is FOOBAR\n"); 817 818 /* FIXME: Should handle 64-bit addresses */ 819 820 /* Read configuration data */ 821 SlotNumber.u.AsULONG = Slot; 822 HalpReadPCIConfig(BusHandler, SlotNumber, &PciConfig, 0, PCI_COMMON_HDR_LENGTH); 823 824 /* Check if we read it correctly */ 825 if (PciConfig.VendorID == PCI_INVALID_VENDORID) 826 return STATUS_NO_SUCH_DEVICE; 827 828 /* Read the PCI configuration space for the device and store base address and 829 size information in temporary storage. Count the number of valid base addresses */ 830 ResourceCount = 0; 831 for (Address = 0; Address < PCI_TYPE0_ADDRESSES; Address++) 832 { 833 if (0xffffffff == PciConfig.u.type0.BaseAddresses[Address]) 834 PciConfig.u.type0.BaseAddresses[Address] = 0; 835 836 /* Memory resource */ 837 if (0 != PciConfig.u.type0.BaseAddresses[Address]) 838 { 839 ResourceCount++; 840 841 Offset = (UCHAR)FIELD_OFFSET(PCI_COMMON_CONFIG, u.type0.BaseAddresses[Address]); 842 843 /* Write 0xFFFFFFFF there */ 844 WriteBuffer = 0xffffffff; 845 HalpWritePCIConfig(BusHandler, SlotNumber, &WriteBuffer, Offset, sizeof(ULONG)); 846 847 /* Read that figure back from the config space */ 848 HalpReadPCIConfig(BusHandler, SlotNumber, &Size[Address], Offset, sizeof(ULONG)); 849 850 /* Write back initial value */ 851 HalpWritePCIConfig(BusHandler, SlotNumber, &PciConfig.u.type0.BaseAddresses[Address], Offset, sizeof(ULONG)); 852 } 853 } 854 855 /* Interrupt resource */ 856 if (0 != PciConfig.u.type0.InterruptPin && 857 0 != PciConfig.u.type0.InterruptLine && 858 0xFF != PciConfig.u.type0.InterruptLine) 859 ResourceCount++; 860 861 /* Allocate output buffer and initialize */ 862 *AllocatedResources = ExAllocatePoolWithTag( 863 PagedPool, 864 sizeof(CM_RESOURCE_LIST) + 865 (ResourceCount - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR), 866 TAG_HAL); 867 868 if (NULL == *AllocatedResources) 869 return STATUS_NO_MEMORY; 870 871 (*AllocatedResources)->Count = 1; 872 (*AllocatedResources)->List[0].InterfaceType = PCIBus; 873 (*AllocatedResources)->List[0].BusNumber = BusHandler->BusNumber; 874 (*AllocatedResources)->List[0].PartialResourceList.Version = 1; 875 (*AllocatedResources)->List[0].PartialResourceList.Revision = 1; 876 (*AllocatedResources)->List[0].PartialResourceList.Count = ResourceCount; 877 Descriptor = (*AllocatedResources)->List[0].PartialResourceList.PartialDescriptors; 878 879 /* Store configuration information */ 880 for (Address = 0; Address < PCI_TYPE0_ADDRESSES; Address++) 881 { 882 if (0 != PciConfig.u.type0.BaseAddresses[Address]) 883 { 884 if (PCI_ADDRESS_MEMORY_SPACE == 885 (PciConfig.u.type0.BaseAddresses[Address] & 0x1)) 886 { 887 Descriptor->Type = CmResourceTypeMemory; 888 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; /* FIXME I have no idea... */ 889 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE; /* FIXME Just a guess */ 890 Descriptor->u.Memory.Start.QuadPart = (PciConfig.u.type0.BaseAddresses[Address] & PCI_ADDRESS_MEMORY_ADDRESS_MASK); 891 Descriptor->u.Memory.Length = PciSize(Size[Address], PCI_ADDRESS_MEMORY_ADDRESS_MASK); 892 } 893 else if (PCI_ADDRESS_IO_SPACE == 894 (PciConfig.u.type0.BaseAddresses[Address] & 0x1)) 895 { 896 Descriptor->Type = CmResourceTypePort; 897 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; /* FIXME I have no idea... */ 898 Descriptor->Flags = CM_RESOURCE_PORT_IO; /* FIXME Just a guess */ 899 Descriptor->u.Port.Start.QuadPart = PciConfig.u.type0.BaseAddresses[Address] &= PCI_ADDRESS_IO_ADDRESS_MASK; 900 Descriptor->u.Port.Length = PciSize(Size[Address], PCI_ADDRESS_IO_ADDRESS_MASK & 0xffff); 901 } 902 else 903 { 904 ASSERT(FALSE); 905 return STATUS_UNSUCCESSFUL; 906 } 907 Descriptor++; 908 } 909 } 910 911 if (0 != PciConfig.u.type0.InterruptPin && 912 0 != PciConfig.u.type0.InterruptLine && 913 0xFF != PciConfig.u.type0.InterruptLine) 914 { 915 Descriptor->Type = CmResourceTypeInterrupt; 916 Descriptor->ShareDisposition = CmResourceShareShared; /* FIXME Just a guess */ 917 Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; /* FIXME Just a guess */ 918 Descriptor->u.Interrupt.Level = PciConfig.u.type0.InterruptLine; 919 Descriptor->u.Interrupt.Vector = PciConfig.u.type0.InterruptLine; 920 Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF; 921 922 Descriptor++; 923 } 924 925 ASSERT(Descriptor == (*AllocatedResources)->List[0].PartialResourceList.PartialDescriptors + ResourceCount); 926 927 /* FIXME: Should store the resources in the registry resource map */ 928 929 return Status; 930 } 931 932 ULONG 933 NTAPI 934 HaliPciInterfaceReadConfig(IN PBUS_HANDLER RootBusHandler, 935 IN ULONG BusNumber, 936 IN PCI_SLOT_NUMBER SlotNumber, 937 IN PVOID Buffer, 938 IN ULONG Offset, 939 IN ULONG Length) 940 { 941 BUS_HANDLER BusHandler; 942 943 /* Setup fake PCI Bus handler */ 944 RtlCopyMemory(&BusHandler, &HalpFakePciBusHandler, sizeof(BUS_HANDLER)); 945 BusHandler.BusNumber = BusNumber; 946 947 /* Read configuration data */ 948 HalpReadPCIConfig(&BusHandler, SlotNumber, Buffer, Offset, Length); 949 950 /* Return length */ 951 return Length; 952 } 953 954 CODE_SEG("INIT") 955 PPCI_REGISTRY_INFO_INTERNAL 956 NTAPI 957 HalpQueryPciRegistryInfo(VOID) 958 { 959 #ifndef _MINIHAL_ 960 WCHAR NameBuffer[8]; 961 OBJECT_ATTRIBUTES ObjectAttributes; 962 UNICODE_STRING KeyName, ConfigName, IdentName; 963 HANDLE KeyHandle, BusKeyHandle, CardListHandle; 964 NTSTATUS Status; 965 UCHAR KeyBuffer[sizeof(CM_FULL_RESOURCE_DESCRIPTOR) + 100]; 966 PKEY_VALUE_FULL_INFORMATION ValueInfo = (PVOID)KeyBuffer; 967 UCHAR PartialKeyBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 968 sizeof(PCI_CARD_DESCRIPTOR)]; 969 PKEY_VALUE_PARTIAL_INFORMATION PartialValueInfo = (PVOID)PartialKeyBuffer; 970 KEY_FULL_INFORMATION KeyInformation; 971 ULONG ResultLength; 972 PWSTR Tag; 973 ULONG i, ElementCount; 974 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor; 975 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; 976 PPCI_REGISTRY_INFO PciRegInfo; 977 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo; 978 PPCI_CARD_DESCRIPTOR CardDescriptor; 979 980 /* Setup the object attributes for the key */ 981 RtlInitUnicodeString(&KeyName, 982 L"\\Registry\\Machine\\Hardware\\Description\\" 983 L"System\\MultiFunctionAdapter"); 984 InitializeObjectAttributes(&ObjectAttributes, 985 &KeyName, 986 OBJ_CASE_INSENSITIVE, 987 NULL, 988 NULL); 989 990 /* Open the key */ 991 Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes); 992 if (!NT_SUCCESS(Status)) return NULL; 993 994 /* Setup the receiving string */ 995 KeyName.Buffer = NameBuffer; 996 KeyName.MaximumLength = sizeof(NameBuffer); 997 998 /* Setup the configuration and identifier key names */ 999 RtlInitUnicodeString(&ConfigName, L"Configuration Data"); 1000 RtlInitUnicodeString(&IdentName, L"Identifier"); 1001 1002 /* Keep looping for each ID */ 1003 for (i = 0; TRUE; i++) 1004 { 1005 /* Setup the key name */ 1006 RtlIntegerToUnicodeString(i, 10, &KeyName); 1007 InitializeObjectAttributes(&ObjectAttributes, 1008 &KeyName, 1009 OBJ_CASE_INSENSITIVE, 1010 KeyHandle, 1011 NULL); 1012 1013 /* Open it */ 1014 Status = ZwOpenKey(&BusKeyHandle, KEY_READ, &ObjectAttributes); 1015 if (!NT_SUCCESS(Status)) 1016 { 1017 /* None left, fail */ 1018 ZwClose(KeyHandle); 1019 return NULL; 1020 } 1021 1022 /* Read the registry data */ 1023 Status = ZwQueryValueKey(BusKeyHandle, 1024 &IdentName, 1025 KeyValueFullInformation, 1026 ValueInfo, 1027 sizeof(KeyBuffer), 1028 &ResultLength); 1029 if (!NT_SUCCESS(Status)) 1030 { 1031 /* Failed, try the next one */ 1032 ZwClose(BusKeyHandle); 1033 continue; 1034 } 1035 1036 /* Get the PCI Tag and validate it */ 1037 Tag = (PWSTR)((ULONG_PTR)ValueInfo + ValueInfo->DataOffset); 1038 if ((Tag[0] != L'P') || 1039 (Tag[1] != L'C') || 1040 (Tag[2] != L'I') || 1041 (Tag[3])) 1042 { 1043 /* Not a valid PCI entry, skip it */ 1044 ZwClose(BusKeyHandle); 1045 continue; 1046 } 1047 1048 /* Now read our PCI structure */ 1049 Status = ZwQueryValueKey(BusKeyHandle, 1050 &ConfigName, 1051 KeyValueFullInformation, 1052 ValueInfo, 1053 sizeof(KeyBuffer), 1054 &ResultLength); 1055 ZwClose(BusKeyHandle); 1056 if (!NT_SUCCESS(Status)) continue; 1057 1058 /* We read it OK! Get the actual resource descriptors */ 1059 FullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) 1060 ((ULONG_PTR)ValueInfo + ValueInfo->DataOffset); 1061 PartialDescriptor = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) 1062 ((ULONG_PTR)FullDescriptor-> 1063 PartialResourceList.PartialDescriptors); 1064 1065 /* Check if this is our PCI Registry Information */ 1066 if (PartialDescriptor->Type == CmResourceTypeDeviceSpecific) 1067 { 1068 /* It is, stop searching */ 1069 break; 1070 } 1071 } 1072 1073 /* Close the key */ 1074 ZwClose(KeyHandle); 1075 1076 /* Save the PCI information for later */ 1077 PciRegInfo = (PPCI_REGISTRY_INFO)(PartialDescriptor + 1); 1078 1079 /* Assume no Card List entries */ 1080 ElementCount = 0; 1081 1082 /* Set up for checking the PCI Card List key */ 1083 RtlInitUnicodeString(&KeyName, 1084 L"\\Registry\\Machine\\System\\CurrentControlSet\\" 1085 L"Control\\PnP\\PCI\\CardList"); 1086 InitializeObjectAttributes(&ObjectAttributes, 1087 &KeyName, 1088 OBJ_CASE_INSENSITIVE, 1089 NULL, 1090 NULL); 1091 1092 /* Attempt to open it */ 1093 Status = ZwOpenKey(&CardListHandle, KEY_READ, &ObjectAttributes); 1094 if (NT_SUCCESS(Status)) 1095 { 1096 /* It exists, so let's query it */ 1097 Status = ZwQueryKey(CardListHandle, 1098 KeyFullInformation, 1099 &KeyInformation, 1100 sizeof(KEY_FULL_INFORMATION), 1101 &ResultLength); 1102 if (!NT_SUCCESS(Status)) 1103 { 1104 /* Failed to query, so no info */ 1105 PciRegistryInfo = NULL; 1106 } 1107 else 1108 { 1109 /* Allocate the full structure */ 1110 PciRegistryInfo = 1111 ExAllocatePoolWithTag(NonPagedPool, 1112 sizeof(PCI_REGISTRY_INFO_INTERNAL) + 1113 (KeyInformation.Values * 1114 sizeof(PCI_CARD_DESCRIPTOR)), 1115 TAG_HAL); 1116 if (PciRegistryInfo) 1117 { 1118 /* Get the first card descriptor entry */ 1119 CardDescriptor = (PPCI_CARD_DESCRIPTOR)(PciRegistryInfo + 1); 1120 1121 /* Loop all the values */ 1122 for (i = 0; i < KeyInformation.Values; i++) 1123 { 1124 /* Attempt to get the value */ 1125 Status = ZwEnumerateValueKey(CardListHandle, 1126 i, 1127 KeyValuePartialInformation, 1128 PartialValueInfo, 1129 sizeof(PartialKeyBuffer), 1130 &ResultLength); 1131 if (!NT_SUCCESS(Status)) 1132 { 1133 /* Something went wrong, stop the search */ 1134 break; 1135 } 1136 1137 /* Make sure it is correctly sized */ 1138 if (PartialValueInfo->DataLength == sizeof(PCI_CARD_DESCRIPTOR)) 1139 { 1140 /* Sure is, copy it over */ 1141 *CardDescriptor = *(PPCI_CARD_DESCRIPTOR) 1142 PartialValueInfo->Data; 1143 1144 /* One more Card List entry */ 1145 ElementCount++; 1146 1147 /* Move to the next descriptor */ 1148 CardDescriptor = (CardDescriptor + 1); 1149 } 1150 } 1151 } 1152 } 1153 1154 /* Close the Card List key */ 1155 ZwClose(CardListHandle); 1156 } 1157 else 1158 { 1159 /* No key, no Card List */ 1160 PciRegistryInfo = NULL; 1161 } 1162 1163 /* Check if we failed to get the full structure */ 1164 if (!PciRegistryInfo) 1165 { 1166 /* Just allocate the basic structure then */ 1167 PciRegistryInfo = ExAllocatePoolWithTag(NonPagedPool, 1168 sizeof(PCI_REGISTRY_INFO_INTERNAL), 1169 TAG_HAL); 1170 if (!PciRegistryInfo) return NULL; 1171 } 1172 1173 /* Save the info we got */ 1174 PciRegistryInfo->MajorRevision = PciRegInfo->MajorRevision; 1175 PciRegistryInfo->MinorRevision = PciRegInfo->MinorRevision; 1176 PciRegistryInfo->NoBuses = PciRegInfo->NoBuses; 1177 PciRegistryInfo->HardwareMechanism = PciRegInfo->HardwareMechanism; 1178 PciRegistryInfo->ElementCount = ElementCount; 1179 1180 /* Return it */ 1181 return PciRegistryInfo; 1182 #else 1183 return NULL; 1184 #endif 1185 } 1186 1187 CODE_SEG("INIT") 1188 VOID 1189 NTAPI 1190 HalpInitializePciStubs(VOID) 1191 { 1192 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo; 1193 UCHAR PciType; 1194 PPCIPBUSDATA BusData = (PPCIPBUSDATA)HalpFakePciBusHandler.BusData; 1195 ULONG i; 1196 PCI_SLOT_NUMBER j; 1197 ULONG VendorId = 0; 1198 ULONG MaxPciBusNumber; 1199 1200 /* Query registry information */ 1201 PciRegistryInfo = HalpQueryPciRegistryInfo(); 1202 if (!PciRegistryInfo) 1203 { 1204 /* Assume type 1 */ 1205 PciType = 1; 1206 1207 /* Force a manual bus scan later */ 1208 MaxPciBusNumber = MAXULONG; 1209 } 1210 else 1211 { 1212 /* Get the PCI type */ 1213 PciType = PciRegistryInfo->HardwareMechanism & 0xF; 1214 1215 /* Get MaxPciBusNumber and make it 0-based */ 1216 MaxPciBusNumber = PciRegistryInfo->NoBuses - 1; 1217 1218 /* Free the info structure */ 1219 ExFreePoolWithTag(PciRegistryInfo, TAG_HAL); 1220 } 1221 1222 /* Initialize the PCI lock */ 1223 KeInitializeSpinLock(&HalpPCIConfigLock); 1224 1225 /* Check the type of PCI bus */ 1226 switch (PciType) 1227 { 1228 /* Type 1 PCI Bus */ 1229 case 1: 1230 1231 /* Copy the Type 1 handler data */ 1232 RtlCopyMemory(&PCIConfigHandler, 1233 &PCIConfigHandlerType1, 1234 sizeof(PCIConfigHandler)); 1235 1236 /* Set correct I/O Ports */ 1237 BusData->Config.Type1.Address = PCI_TYPE1_ADDRESS_PORT; 1238 BusData->Config.Type1.Data = PCI_TYPE1_DATA_PORT; 1239 break; 1240 1241 /* Type 2 PCI Bus */ 1242 case 2: 1243 1244 /* Copy the Type 2 handler data */ 1245 RtlCopyMemory(&PCIConfigHandler, 1246 &PCIConfigHandlerType2, 1247 sizeof (PCIConfigHandler)); 1248 1249 /* Set correct I/O Ports */ 1250 BusData->Config.Type2.CSE = PCI_TYPE2_CSE_PORT; 1251 BusData->Config.Type2.Forward = PCI_TYPE2_FORWARD_PORT; 1252 BusData->Config.Type2.Base = PCI_TYPE2_ADDRESS_BASE; 1253 1254 /* Only 16 devices supported, not 32 */ 1255 BusData->MaxDevice = 16; 1256 break; 1257 1258 default: 1259 1260 /* Invalid type */ 1261 DbgPrint("HAL: Unknown PCI type\n"); 1262 } 1263 1264 /* Run a forced bus scan if needed */ 1265 if (MaxPciBusNumber == MAXULONG) 1266 { 1267 /* Initialize the max bus number to 0xFF */ 1268 HalpMaxPciBus = 0xFF; 1269 1270 /* Initialize the counter */ 1271 MaxPciBusNumber = 0; 1272 1273 /* Loop all possible buses */ 1274 for (i = 0; i < HalpMaxPciBus; i++) 1275 { 1276 /* Loop all devices */ 1277 for (j.u.AsULONG = 0; j.u.AsULONG < BusData->MaxDevice; j.u.AsULONG++) 1278 { 1279 /* Query the interface */ 1280 if (HaliPciInterfaceReadConfig(NULL, 1281 i, 1282 j, 1283 &VendorId, 1284 0, 1285 sizeof(ULONG))) 1286 { 1287 /* Validate the vendor ID */ 1288 if ((VendorId & 0xFFFF) != PCI_INVALID_VENDORID) 1289 { 1290 /* Set this as the maximum ID */ 1291 MaxPciBusNumber = i; 1292 break; 1293 } 1294 } 1295 } 1296 } 1297 } 1298 1299 /* Set the real max bus number */ 1300 HalpMaxPciBus = MaxPciBusNumber; 1301 1302 /* We're done */ 1303 HalpPCIConfigInitialized = TRUE; 1304 } 1305 1306 /* EOF */ 1307 1308