Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpcibus.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS HAL 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: hal/halx86/generic/bus/pcibus.c 00005 * PURPOSE: PCI Bus Support (Configuration Space, Resource Allocation) 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 */ 00008 00009 /* INCLUDES ******************************************************************/ 00010 00011 #include <hal.h> 00012 #define NDEBUG 00013 #include <debug.h> 00014 00015 /* GLOBALS *******************************************************************/ 00016 00017 extern BOOLEAN HalpPciLockSettings; 00018 ULONG HalpBusType; 00019 00020 PCI_TYPE1_CFG_CYCLE_BITS HalpPciDebuggingDevice[2] = {{{{0}}}}; 00021 00022 BOOLEAN HalpPCIConfigInitialized; 00023 ULONG HalpMinPciBus, HalpMaxPciBus; 00024 KSPIN_LOCK HalpPCIConfigLock; 00025 PCI_CONFIG_HANDLER PCIConfigHandler; 00026 00027 /* PCI Operation Matrix */ 00028 UCHAR PCIDeref[4][4] = 00029 { 00030 {0, 1, 2, 2}, // ULONG-aligned offset 00031 {1, 1, 1, 1}, // UCHAR-aligned offset 00032 {2, 1, 2, 2}, // USHORT-aligned offset 00033 {1, 1, 1, 1} // UCHAR-aligned offset 00034 }; 00035 00036 /* Type 1 PCI Bus */ 00037 PCI_CONFIG_HANDLER PCIConfigHandlerType1 = 00038 { 00039 /* Synchronization */ 00040 (FncSync)HalpPCISynchronizeType1, 00041 (FncReleaseSync)HalpPCIReleaseSynchronzationType1, 00042 00043 /* Read */ 00044 { 00045 (FncConfigIO)HalpPCIReadUlongType1, 00046 (FncConfigIO)HalpPCIReadUcharType1, 00047 (FncConfigIO)HalpPCIReadUshortType1 00048 }, 00049 00050 /* Write */ 00051 { 00052 (FncConfigIO)HalpPCIWriteUlongType1, 00053 (FncConfigIO)HalpPCIWriteUcharType1, 00054 (FncConfigIO)HalpPCIWriteUshortType1 00055 } 00056 }; 00057 00058 /* Type 2 PCI Bus */ 00059 PCI_CONFIG_HANDLER PCIConfigHandlerType2 = 00060 { 00061 /* Synchronization */ 00062 (FncSync)HalpPCISynchronizeType2, 00063 (FncReleaseSync)HalpPCIReleaseSynchronizationType2, 00064 00065 /* Read */ 00066 { 00067 (FncConfigIO)HalpPCIReadUlongType2, 00068 (FncConfigIO)HalpPCIReadUcharType2, 00069 (FncConfigIO)HalpPCIReadUshortType2 00070 }, 00071 00072 /* Write */ 00073 { 00074 (FncConfigIO)HalpPCIWriteUlongType2, 00075 (FncConfigIO)HalpPCIWriteUcharType2, 00076 (FncConfigIO)HalpPCIWriteUshortType2 00077 } 00078 }; 00079 00080 PCIPBUSDATA HalpFakePciBusData = 00081 { 00082 { 00083 PCI_DATA_TAG, 00084 PCI_DATA_VERSION, 00085 HalpReadPCIConfig, 00086 HalpWritePCIConfig, 00087 NULL, 00088 NULL, 00089 {{{0, 0, 0}}}, 00090 {0, 0, 0, 0} 00091 }, 00092 {{0, 0}}, 00093 32, 00094 }; 00095 00096 BUS_HANDLER HalpFakePciBusHandler = 00097 { 00098 1, 00099 PCIBus, 00100 PCIConfiguration, 00101 0, 00102 NULL, 00103 NULL, 00104 &HalpFakePciBusData, 00105 0, 00106 NULL, 00107 {0, 0, 0, 0}, 00108 (PGETSETBUSDATA)HalpGetPCIData, 00109 (PGETSETBUSDATA)HalpSetPCIData, 00110 NULL, 00111 HalpAssignPCISlotResources, 00112 NULL, 00113 NULL 00114 }; 00115 00116 /* TYPE 1 FUNCTIONS **********************************************************/ 00117 00118 VOID 00119 NTAPI 00120 HalpPCISynchronizeType1(IN PBUS_HANDLER BusHandler, 00121 IN PCI_SLOT_NUMBER Slot, 00122 IN PKIRQL Irql, 00123 IN PPCI_TYPE1_CFG_BITS PciCfg1) 00124 { 00125 /* Setup the PCI Configuration Register */ 00126 PciCfg1->u.AsULONG = 0; 00127 PciCfg1->u.bits.BusNumber = BusHandler->BusNumber; 00128 PciCfg1->u.bits.DeviceNumber = Slot.u.bits.DeviceNumber; 00129 PciCfg1->u.bits.FunctionNumber = Slot.u.bits.FunctionNumber; 00130 PciCfg1->u.bits.Enable = TRUE; 00131 00132 /* Acquire the lock */ 00133 KeRaiseIrql(HIGH_LEVEL, Irql); 00134 KiAcquireSpinLock(&HalpPCIConfigLock); 00135 } 00136 00137 VOID 00138 NTAPI 00139 HalpPCIReleaseSynchronzationType1(IN PBUS_HANDLER BusHandler, 00140 IN KIRQL Irql) 00141 { 00142 PCI_TYPE1_CFG_BITS PciCfg1; 00143 00144 /* Clear the PCI Configuration Register */ 00145 PciCfg1.u.AsULONG = 0; 00146 WRITE_PORT_ULONG(((PPCIPBUSDATA)BusHandler->BusData)->Config.Type1.Address, 00147 PciCfg1.u.AsULONG); 00148 00149 /* Release the lock */ 00150 KiReleaseSpinLock(&HalpPCIConfigLock); 00151 KeLowerIrql(Irql); 00152 } 00153 00154 TYPE1_READ(HalpPCIReadUcharType1, UCHAR) 00155 TYPE1_READ(HalpPCIReadUshortType1, USHORT) 00156 TYPE1_READ(HalpPCIReadUlongType1, ULONG) 00157 TYPE1_WRITE(HalpPCIWriteUcharType1, UCHAR) 00158 TYPE1_WRITE(HalpPCIWriteUshortType1, USHORT) 00159 TYPE1_WRITE(HalpPCIWriteUlongType1, ULONG) 00160 00161 /* TYPE 2 FUNCTIONS **********************************************************/ 00162 00163 VOID 00164 NTAPI 00165 HalpPCISynchronizeType2(IN PBUS_HANDLER BusHandler, 00166 IN PCI_SLOT_NUMBER Slot, 00167 IN PKIRQL Irql, 00168 IN PPCI_TYPE2_ADDRESS_BITS PciCfg) 00169 { 00170 PCI_TYPE2_CSE_BITS PciCfg2Cse; 00171 PPCIPBUSDATA BusData = (PPCIPBUSDATA)BusHandler->BusData; 00172 00173 /* Setup the configuration register */ 00174 PciCfg->u.AsUSHORT = 0; 00175 PciCfg->u.bits.Agent = (USHORT)Slot.u.bits.DeviceNumber; 00176 PciCfg->u.bits.AddressBase = (USHORT)BusData->Config.Type2.Base; 00177 00178 /* Acquire the lock */ 00179 KeRaiseIrql(HIGH_LEVEL, Irql); 00180 KiAcquireSpinLock(&HalpPCIConfigLock); 00181 00182 /* Setup the CSE Register */ 00183 PciCfg2Cse.u.AsUCHAR = 0; 00184 PciCfg2Cse.u.bits.Enable = TRUE; 00185 PciCfg2Cse.u.bits.FunctionNumber = (UCHAR)Slot.u.bits.FunctionNumber; 00186 PciCfg2Cse.u.bits.Key = -1; 00187 00188 /* Write the bus number and CSE */ 00189 WRITE_PORT_UCHAR(BusData->Config.Type2.Forward, 00190 (UCHAR)BusHandler->BusNumber); 00191 WRITE_PORT_UCHAR(BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR); 00192 } 00193 00194 VOID 00195 NTAPI 00196 HalpPCIReleaseSynchronizationType2(IN PBUS_HANDLER BusHandler, 00197 IN KIRQL Irql) 00198 { 00199 PCI_TYPE2_CSE_BITS PciCfg2Cse; 00200 PPCIPBUSDATA BusData = (PPCIPBUSDATA)BusHandler->BusData; 00201 00202 /* Clear CSE and bus number */ 00203 PciCfg2Cse.u.AsUCHAR = 0; 00204 WRITE_PORT_UCHAR(BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR); 00205 WRITE_PORT_UCHAR(BusData->Config.Type2.Forward, 0); 00206 00207 /* Release the lock */ 00208 KiReleaseSpinLock(&HalpPCIConfigLock); 00209 KeLowerIrql(Irql); 00210 } 00211 00212 TYPE2_READ(HalpPCIReadUcharType2, UCHAR) 00213 TYPE2_READ(HalpPCIReadUshortType2, USHORT) 00214 TYPE2_READ(HalpPCIReadUlongType2, ULONG) 00215 TYPE2_WRITE(HalpPCIWriteUcharType2, UCHAR) 00216 TYPE2_WRITE(HalpPCIWriteUshortType2, USHORT) 00217 TYPE2_WRITE(HalpPCIWriteUlongType2, ULONG) 00218 00219 /* PCI CONFIGURATION SPACE ***************************************************/ 00220 00221 VOID 00222 NTAPI 00223 HalpPCIConfig(IN PBUS_HANDLER BusHandler, 00224 IN PCI_SLOT_NUMBER Slot, 00225 IN PUCHAR Buffer, 00226 IN ULONG Offset, 00227 IN ULONG Length, 00228 IN FncConfigIO *ConfigIO) 00229 { 00230 KIRQL OldIrql; 00231 ULONG i; 00232 UCHAR State[20]; 00233 00234 /* Synchronize the operation */ 00235 PCIConfigHandler.Synchronize(BusHandler, Slot, &OldIrql, State); 00236 00237 /* Loop every increment */ 00238 while (Length) 00239 { 00240 /* Find out the type of read/write we need to do */ 00241 i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)]; 00242 00243 /* Do the read/write and return the number of bytes */ 00244 i = ConfigIO[i]((PPCIPBUSDATA)BusHandler->BusData, 00245 State, 00246 Buffer, 00247 Offset); 00248 00249 /* Increment the buffer position and offset, and decrease the length */ 00250 Offset += i; 00251 Buffer += i; 00252 Length -= i; 00253 } 00254 00255 /* Release the lock and PCI bus */ 00256 PCIConfigHandler.ReleaseSynchronzation(BusHandler, OldIrql); 00257 } 00258 00259 VOID 00260 NTAPI 00261 HalpReadPCIConfig(IN PBUS_HANDLER BusHandler, 00262 IN PCI_SLOT_NUMBER Slot, 00263 IN PVOID Buffer, 00264 IN ULONG Offset, 00265 IN ULONG Length) 00266 { 00267 /* Validate the PCI Slot */ 00268 if (!HalpValidPCISlot(BusHandler, Slot)) 00269 { 00270 /* Fill the buffer with invalid data */ 00271 RtlFillMemory(Buffer, Length, -1); 00272 } 00273 else 00274 { 00275 /* Send the request */ 00276 HalpPCIConfig(BusHandler, 00277 Slot, 00278 Buffer, 00279 Offset, 00280 Length, 00281 PCIConfigHandler.ConfigRead); 00282 } 00283 } 00284 00285 VOID 00286 NTAPI 00287 HalpWritePCIConfig(IN PBUS_HANDLER BusHandler, 00288 IN PCI_SLOT_NUMBER Slot, 00289 IN PVOID Buffer, 00290 IN ULONG Offset, 00291 IN ULONG Length) 00292 { 00293 /* Validate the PCI Slot */ 00294 if (HalpValidPCISlot(BusHandler, Slot)) 00295 { 00296 /* Send the request */ 00297 HalpPCIConfig(BusHandler, 00298 Slot, 00299 Buffer, 00300 Offset, 00301 Length, 00302 PCIConfigHandler.ConfigWrite); 00303 } 00304 } 00305 00306 BOOLEAN 00307 NTAPI 00308 HalpValidPCISlot(IN PBUS_HANDLER BusHandler, 00309 IN PCI_SLOT_NUMBER Slot) 00310 { 00311 PCI_SLOT_NUMBER MultiSlot; 00312 PPCIPBUSDATA BusData = (PPCIPBUSDATA)BusHandler->BusData; 00313 UCHAR HeaderType; 00314 //ULONG Device; 00315 00316 /* Simple validation */ 00317 if (Slot.u.bits.Reserved) return FALSE; 00318 if (Slot.u.bits.DeviceNumber >= BusData->MaxDevice) return FALSE; 00319 00320 /* Function 0 doesn't need checking */ 00321 if (!Slot.u.bits.FunctionNumber) return TRUE; 00322 00323 /* Functions 0+ need Multi-Function support, so check the slot */ 00324 //Device = Slot.u.bits.DeviceNumber; 00325 MultiSlot = Slot; 00326 MultiSlot.u.bits.FunctionNumber = 0; 00327 00328 /* Send function 0 request to get the header back */ 00329 HalpReadPCIConfig(BusHandler, 00330 MultiSlot, 00331 &HeaderType, 00332 FIELD_OFFSET(PCI_COMMON_CONFIG, HeaderType), 00333 sizeof(UCHAR)); 00334 00335 /* Now make sure the header is multi-function */ 00336 if (!(HeaderType & PCI_MULTIFUNCTION) || (HeaderType == 0xFF)) return FALSE; 00337 return TRUE; 00338 } 00339 00340 /* HAL PCI CALLBACKS *********************************************************/ 00341 00342 ULONG 00343 NTAPI 00344 HalpGetPCIData(IN PBUS_HANDLER BusHandler, 00345 IN PBUS_HANDLER RootHandler, 00346 IN PCI_SLOT_NUMBER Slot, 00347 IN PVOID Buffer, 00348 IN ULONG Offset, 00349 IN ULONG Length) 00350 { 00351 UCHAR PciBuffer[PCI_COMMON_HDR_LENGTH]; 00352 PPCI_COMMON_CONFIG PciConfig = (PPCI_COMMON_CONFIG)PciBuffer; 00353 ULONG Len = 0; 00354 00355 #ifdef SARCH_XBOX 00356 /* Trying to get PCI config data from devices 0:0:1 and 0:0:2 will completely 00357 * hang the Xbox. Also, the device number doesn't seem to be decoded for the 00358 * video card, so it appears to be present on 1:0:0 - 1:31:0. 00359 * We hack around these problems by indicating "device not present" for devices 00360 * 0:0:1, 0:0:2, 1:1:0, 1:2:0, 1:3:0, ...., 1:31:0 */ 00361 if ((0 == BusHandler->BusNumber && 0 == Slot.u.bits.DeviceNumber && 00362 (1 == Slot.u.bits.FunctionNumber || 2 == Slot.u.bits.FunctionNumber)) || 00363 (1 == BusHandler->BusNumber && 0 != Slot.u.bits.DeviceNumber)) 00364 { 00365 DPRINT("Blacklisted PCI slot\n"); 00366 if (0 == Offset && sizeof(USHORT) <= Length) 00367 { 00368 *(PUSHORT)Buffer = PCI_INVALID_VENDORID; 00369 return sizeof(USHORT); 00370 } 00371 return 0; 00372 } 00373 #endif 00374 00375 /* Normalize the length */ 00376 if (Length > sizeof(PCI_COMMON_CONFIG)) Length = sizeof(PCI_COMMON_CONFIG); 00377 00378 /* Check if this is a vendor-specific read */ 00379 if (Offset >= PCI_COMMON_HDR_LENGTH) 00380 { 00381 /* Read the header */ 00382 HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, sizeof(ULONG)); 00383 00384 /* Make sure the vendor is valid */ 00385 if (PciConfig->VendorID == PCI_INVALID_VENDORID) return 0; 00386 } 00387 else 00388 { 00389 /* Read the entire header */ 00390 Len = PCI_COMMON_HDR_LENGTH; 00391 HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, Len); 00392 00393 /* Validate the vendor ID */ 00394 if (PciConfig->VendorID == PCI_INVALID_VENDORID) 00395 { 00396 /* It's invalid, but we want to return this much */ 00397 Len = sizeof(USHORT); 00398 } 00399 00400 /* Now check if there's space left */ 00401 if (Len < Offset) return 0; 00402 00403 /* There is, so return what's after the offset and normalize */ 00404 Len -= Offset; 00405 if (Len > Length) Len = Length; 00406 00407 /* Copy the data into the caller's buffer */ 00408 RtlMoveMemory(Buffer, PciBuffer + Offset, Len); 00409 00410 /* Update buffer and offset, decrement total length */ 00411 Offset += Len; 00412 Buffer = (PVOID)((ULONG_PTR)Buffer + Len); 00413 Length -= Len; 00414 } 00415 00416 /* Now we still have something to copy */ 00417 if (Length) 00418 { 00419 /* Check if it's vendor-specific data */ 00420 if (Offset >= PCI_COMMON_HDR_LENGTH) 00421 { 00422 /* Read it now */ 00423 HalpReadPCIConfig(BusHandler, Slot, Buffer, Offset, Length); 00424 Len += Length; 00425 } 00426 } 00427 00428 /* Update the total length read */ 00429 return Len; 00430 } 00431 00432 ULONG 00433 NTAPI 00434 HalpSetPCIData(IN PBUS_HANDLER BusHandler, 00435 IN PBUS_HANDLER RootHandler, 00436 IN PCI_SLOT_NUMBER Slot, 00437 IN PVOID Buffer, 00438 IN ULONG Offset, 00439 IN ULONG Length) 00440 { 00441 UCHAR PciBuffer[PCI_COMMON_HDR_LENGTH]; 00442 PPCI_COMMON_CONFIG PciConfig = (PPCI_COMMON_CONFIG)PciBuffer; 00443 ULONG Len = 0; 00444 00445 #ifdef SARCH_XBOX 00446 /* Trying to get PCI config data from devices 0:0:1 and 0:0:2 will completely 00447 * hang the Xbox. Also, the device number doesn't seem to be decoded for the 00448 * video card, so it appears to be present on 1:0:0 - 1:31:0. 00449 * We hack around these problems by indicating "device not present" for devices 00450 * 0:0:1, 0:0:2, 1:1:0, 1:2:0, 1:3:0, ...., 1:31:0 */ 00451 if ((0 == BusHandler->BusNumber && 0 == Slot.u.bits.DeviceNumber && 00452 (1 == Slot.u.bits.FunctionNumber || 2 == Slot.u.bits.FunctionNumber)) || 00453 (1 == BusHandler->BusNumber && 0 != Slot.u.bits.DeviceNumber)) 00454 { 00455 DPRINT1("Trying to set data on blacklisted PCI slot\n"); 00456 return 0; 00457 } 00458 #endif 00459 00460 /* Normalize the length */ 00461 if (Length > sizeof(PCI_COMMON_CONFIG)) Length = sizeof(PCI_COMMON_CONFIG); 00462 00463 /* Check if this is a vendor-specific read */ 00464 if (Offset >= PCI_COMMON_HDR_LENGTH) 00465 { 00466 /* Read the header */ 00467 HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, sizeof(ULONG)); 00468 00469 /* Make sure the vendor is valid */ 00470 if (PciConfig->VendorID == PCI_INVALID_VENDORID) return 0; 00471 } 00472 else 00473 { 00474 /* Read the entire header and validate the vendor ID */ 00475 Len = PCI_COMMON_HDR_LENGTH; 00476 HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, Len); 00477 if (PciConfig->VendorID == PCI_INVALID_VENDORID) return 0; 00478 00479 /* Return what's after the offset and normalize */ 00480 Len -= Offset; 00481 if (Len > Length) Len = Length; 00482 00483 /* Copy the specific caller data */ 00484 RtlMoveMemory(PciBuffer + Offset, Buffer, Len); 00485 00486 /* Write the actual configuration data */ 00487 HalpWritePCIConfig(BusHandler, Slot, PciBuffer + Offset, Offset, Len); 00488 00489 /* Update buffer and offset, decrement total length */ 00490 Offset += Len; 00491 Buffer = (PVOID)((ULONG_PTR)Buffer + Len); 00492 Length -= Len; 00493 } 00494 00495 /* Now we still have something to copy */ 00496 if (Length) 00497 { 00498 /* Check if it's vendor-specific data */ 00499 if (Offset >= PCI_COMMON_HDR_LENGTH) 00500 { 00501 /* Read it now */ 00502 HalpWritePCIConfig(BusHandler, Slot, Buffer, Offset, Length); 00503 Len += Length; 00504 } 00505 } 00506 00507 /* Update the total length read */ 00508 return Len; 00509 } 00510 00511 ULONG 00512 NTAPI 00513 HalpGetPCIIntOnISABus(IN PBUS_HANDLER BusHandler, 00514 IN PBUS_HANDLER RootHandler, 00515 IN ULONG BusInterruptLevel, 00516 IN ULONG BusInterruptVector, 00517 OUT PKIRQL Irql, 00518 OUT PKAFFINITY Affinity) 00519 { 00520 /* Validate the level first */ 00521 if (BusInterruptLevel < 1) return 0; 00522 00523 /* PCI has its IRQs on top of ISA IRQs, so pass it on to the ISA handler */ 00524 return HalGetInterruptVector(Isa, 00525 0, 00526 BusInterruptLevel, 00527 0, 00528 Irql, 00529 Affinity); 00530 } 00531 00532 VOID 00533 NTAPI 00534 HalpPCIPin2ISALine(IN PBUS_HANDLER BusHandler, 00535 IN PBUS_HANDLER RootHandler, 00536 IN PCI_SLOT_NUMBER SlotNumber, 00537 IN PPCI_COMMON_CONFIG PciData) 00538 { 00539 UNIMPLEMENTED; 00540 while (TRUE); 00541 } 00542 00543 VOID 00544 NTAPI 00545 HalpPCIISALine2Pin(IN PBUS_HANDLER BusHandler, 00546 IN PBUS_HANDLER RootHandler, 00547 IN PCI_SLOT_NUMBER SlotNumber, 00548 IN PPCI_COMMON_CONFIG PciNewData, 00549 IN PPCI_COMMON_CONFIG PciOldData) 00550 { 00551 UNIMPLEMENTED; 00552 while (TRUE); 00553 } 00554 00555 NTSTATUS 00556 NTAPI 00557 HalpGetISAFixedPCIIrq(IN PBUS_HANDLER BusHandler, 00558 IN PBUS_HANDLER RootHandler, 00559 IN PCI_SLOT_NUMBER PciSlot, 00560 OUT PSUPPORTED_RANGE *Range) 00561 { 00562 PCI_COMMON_HEADER PciData; 00563 00564 /* Read PCI configuration data */ 00565 HalGetBusData(PCIConfiguration, 00566 BusHandler->BusNumber, 00567 PciSlot.u.AsULONG, 00568 &PciData, 00569 PCI_COMMON_HDR_LENGTH); 00570 00571 /* Make sure it's a real device */ 00572 if (PciData.VendorID == PCI_INVALID_VENDORID) return STATUS_UNSUCCESSFUL; 00573 00574 /* Allocate the supported range structure */ 00575 *Range = ExAllocatePoolWithTag(PagedPool, sizeof(SUPPORTED_RANGE), TAG_HAL); 00576 if (!*Range) return STATUS_INSUFFICIENT_RESOURCES; 00577 00578 /* Set it up */ 00579 RtlZeroMemory(*Range, sizeof(SUPPORTED_RANGE)); 00580 (*Range)->Base = 1; 00581 00582 /* If the PCI device has no IRQ, nothing to do */ 00583 if (!PciData.u.type0.InterruptPin) return STATUS_SUCCESS; 00584 00585 /* FIXME: The PCI IRQ Routing Miniport should be called */ 00586 00587 /* Also if the INT# seems bogus, nothing to do either */ 00588 if ((PciData.u.type0.InterruptLine == 0) || 00589 (PciData.u.type0.InterruptLine == 255)) 00590 { 00591 /* Fake success */ 00592 return STATUS_SUCCESS; 00593 } 00594 00595 /* Otherwise, the INT# should be valid, return it to the caller */ 00596 (*Range)->Base = PciData.u.type0.InterruptLine; 00597 (*Range)->Limit = PciData.u.type0.InterruptLine; 00598 return STATUS_SUCCESS; 00599 } 00600 00601 NTSTATUS 00602 NTAPI 00603 INIT_FUNCTION 00604 HalpSetupPciDeviceForDebugging(IN PVOID LoaderBlock, 00605 IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice) 00606 { 00607 DPRINT1("Unimplemented!\n"); 00608 return STATUS_NOT_IMPLEMENTED; 00609 } 00610 00611 NTSTATUS 00612 NTAPI 00613 INIT_FUNCTION 00614 HalpReleasePciDeviceForDebugging(IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice) 00615 { 00616 DPRINT1("Unimplemented!\n"); 00617 return STATUS_NOT_IMPLEMENTED; 00618 } 00619 00620 VOID 00621 NTAPI 00622 INIT_FUNCTION 00623 HalpRegisterPciDebuggingDeviceInfo(VOID) 00624 { 00625 BOOLEAN Found = FALSE; 00626 ULONG i; 00627 PAGED_CODE(); 00628 00629 /* Loop PCI debugging devices */ 00630 for (i = 0; i < 2; i++) 00631 { 00632 /* Reserved bit is set if we found one */ 00633 if (HalpPciDebuggingDevice[i].u.bits.Reserved1) 00634 { 00635 Found = TRUE; 00636 break; 00637 } 00638 } 00639 00640 /* Bail out if there aren't any */ 00641 if (!Found) return; 00642 00643 /* FIXME: TODO */ 00644 DPRINT1("You have implemented the KD routines for searching PCI debugger" 00645 "devices, but you have forgotten to implement this routine\n"); 00646 while (TRUE); 00647 } 00648 00649 static ULONG NTAPI 00650 PciSize(ULONG Base, ULONG Mask) 00651 { 00652 ULONG Size = Mask & Base; /* Find the significant bits */ 00653 Size = Size & ~(Size - 1); /* Get the lowest of them to find the decode size */ 00654 return Size; 00655 } 00656 00657 NTSTATUS 00658 NTAPI 00659 HalpAdjustPCIResourceList(IN PBUS_HANDLER BusHandler, 00660 IN PBUS_HANDLER RootHandler, 00661 IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList) 00662 { 00663 PPCIPBUSDATA BusData; 00664 PCI_SLOT_NUMBER SlotNumber; 00665 PSUPPORTED_RANGE Interrupt; 00666 NTSTATUS Status; 00667 00668 /* Get PCI bus data */ 00669 BusData = BusHandler->BusData; 00670 SlotNumber.u.AsULONG = (*pResourceList)->SlotNumber; 00671 00672 /* Get the IRQ supported range */ 00673 Status = BusData->GetIrqRange(BusHandler, RootHandler, SlotNumber, &Interrupt); 00674 if (!NT_SUCCESS(Status)) return Status; 00675 #ifndef _MINIHAL_ 00676 /* Handle the /PCILOCK feature */ 00677 if (HalpPciLockSettings) 00678 { 00679 /* /PCILOCK is not yet supported */ 00680 UNIMPLEMENTED; 00681 while (TRUE); 00682 } 00683 #endif 00684 /* Now create the correct resource list based on the supported bus ranges */ 00685 #if 0 00686 Status = HaliAdjustResourceListRange(BusHandler->BusAddresses, 00687 Interrupt, 00688 pResourceList); 00689 #else 00690 DPRINT1("HAL: No PCI Resource Adjustment done! Hardware may malfunction\n"); 00691 Status = STATUS_SUCCESS; 00692 #endif 00693 00694 /* Return to caller */ 00695 ExFreePool(Interrupt); 00696 return Status; 00697 } 00698 00699 NTSTATUS 00700 NTAPI 00701 HalpAssignPCISlotResources(IN PBUS_HANDLER BusHandler, 00702 IN PBUS_HANDLER RootHandler, 00703 IN PUNICODE_STRING RegistryPath, 00704 IN PUNICODE_STRING DriverClassName OPTIONAL, 00705 IN PDRIVER_OBJECT DriverObject, 00706 IN PDEVICE_OBJECT DeviceObject OPTIONAL, 00707 IN ULONG Slot, 00708 IN OUT PCM_RESOURCE_LIST *AllocatedResources) 00709 { 00710 PCI_COMMON_CONFIG PciConfig; 00711 SIZE_T Address; 00712 ULONG ResourceCount; 00713 ULONG Size[PCI_TYPE0_ADDRESSES]; 00714 NTSTATUS Status = STATUS_SUCCESS; 00715 UCHAR Offset; 00716 PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor; 00717 PCI_SLOT_NUMBER SlotNumber; 00718 ULONG WriteBuffer; 00719 DPRINT1("WARNING: PCI Slot Resource Assignment is FOOBAR\n"); 00720 00721 /* FIXME: Should handle 64-bit addresses */ 00722 00723 /* Read configuration data */ 00724 SlotNumber.u.AsULONG = Slot; 00725 HalpReadPCIConfig(BusHandler, SlotNumber, &PciConfig, 0, PCI_COMMON_HDR_LENGTH); 00726 00727 /* Check if we read it correctly */ 00728 if (PciConfig.VendorID == PCI_INVALID_VENDORID) 00729 return STATUS_NO_SUCH_DEVICE; 00730 00731 /* Read the PCI configuration space for the device and store base address and 00732 size information in temporary storage. Count the number of valid base addresses */ 00733 ResourceCount = 0; 00734 for (Address = 0; Address < PCI_TYPE0_ADDRESSES; Address++) 00735 { 00736 if (0xffffffff == PciConfig.u.type0.BaseAddresses[Address]) 00737 PciConfig.u.type0.BaseAddresses[Address] = 0; 00738 00739 /* Memory resource */ 00740 if (0 != PciConfig.u.type0.BaseAddresses[Address]) 00741 { 00742 ResourceCount++; 00743 00744 Offset = (UCHAR)FIELD_OFFSET(PCI_COMMON_CONFIG, u.type0.BaseAddresses[Address]); 00745 00746 /* Write 0xFFFFFFFF there */ 00747 WriteBuffer = 0xffffffff; 00748 HalpWritePCIConfig(BusHandler, SlotNumber, &WriteBuffer, Offset, sizeof(ULONG)); 00749 00750 /* Read that figure back from the config space */ 00751 HalpReadPCIConfig(BusHandler, SlotNumber, &Size[Address], Offset, sizeof(ULONG)); 00752 00753 /* Write back initial value */ 00754 HalpWritePCIConfig(BusHandler, SlotNumber, &PciConfig.u.type0.BaseAddresses[Address], Offset, sizeof(ULONG)); 00755 } 00756 } 00757 00758 /* Interrupt resource */ 00759 if (0 != PciConfig.u.type0.InterruptPin && 00760 0 != PciConfig.u.type0.InterruptLine && 00761 0xFF != PciConfig.u.type0.InterruptLine) 00762 ResourceCount++; 00763 00764 /* Allocate output buffer and initialize */ 00765 *AllocatedResources = ExAllocatePoolWithTag( 00766 PagedPool, 00767 sizeof(CM_RESOURCE_LIST) + 00768 (ResourceCount - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR), 00769 TAG_HAL); 00770 00771 if (NULL == *AllocatedResources) 00772 return STATUS_NO_MEMORY; 00773 00774 (*AllocatedResources)->Count = 1; 00775 (*AllocatedResources)->List[0].InterfaceType = PCIBus; 00776 (*AllocatedResources)->List[0].BusNumber = BusHandler->BusNumber; 00777 (*AllocatedResources)->List[0].PartialResourceList.Version = 1; 00778 (*AllocatedResources)->List[0].PartialResourceList.Revision = 1; 00779 (*AllocatedResources)->List[0].PartialResourceList.Count = ResourceCount; 00780 Descriptor = (*AllocatedResources)->List[0].PartialResourceList.PartialDescriptors; 00781 00782 /* Store configuration information */ 00783 for (Address = 0; Address < PCI_TYPE0_ADDRESSES; Address++) 00784 { 00785 if (0 != PciConfig.u.type0.BaseAddresses[Address]) 00786 { 00787 if (PCI_ADDRESS_MEMORY_SPACE == 00788 (PciConfig.u.type0.BaseAddresses[Address] & 0x1)) 00789 { 00790 Descriptor->Type = CmResourceTypeMemory; 00791 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; /* FIXME I have no idea... */ 00792 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE; /* FIXME Just a guess */ 00793 Descriptor->u.Memory.Start.QuadPart = (PciConfig.u.type0.BaseAddresses[Address] & PCI_ADDRESS_MEMORY_ADDRESS_MASK); 00794 Descriptor->u.Memory.Length = PciSize(Size[Address], PCI_ADDRESS_MEMORY_ADDRESS_MASK); 00795 } 00796 else if (PCI_ADDRESS_IO_SPACE == 00797 (PciConfig.u.type0.BaseAddresses[Address] & 0x1)) 00798 { 00799 Descriptor->Type = CmResourceTypePort; 00800 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; /* FIXME I have no idea... */ 00801 Descriptor->Flags = CM_RESOURCE_PORT_IO; /* FIXME Just a guess */ 00802 Descriptor->u.Port.Start.QuadPart = PciConfig.u.type0.BaseAddresses[Address] &= PCI_ADDRESS_IO_ADDRESS_MASK; 00803 Descriptor->u.Port.Length = PciSize(Size[Address], PCI_ADDRESS_IO_ADDRESS_MASK & 0xffff); 00804 } 00805 else 00806 { 00807 ASSERT(FALSE); 00808 return STATUS_UNSUCCESSFUL; 00809 } 00810 Descriptor++; 00811 } 00812 } 00813 00814 if (0 != PciConfig.u.type0.InterruptPin && 00815 0 != PciConfig.u.type0.InterruptLine && 00816 0xFF != PciConfig.u.type0.InterruptLine) 00817 { 00818 Descriptor->Type = CmResourceTypeInterrupt; 00819 Descriptor->ShareDisposition = CmResourceShareShared; /* FIXME Just a guess */ 00820 Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; /* FIXME Just a guess */ 00821 Descriptor->u.Interrupt.Level = PciConfig.u.type0.InterruptLine; 00822 Descriptor->u.Interrupt.Vector = PciConfig.u.type0.InterruptLine; 00823 Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF; 00824 00825 Descriptor++; 00826 } 00827 00828 ASSERT(Descriptor == (*AllocatedResources)->List[0].PartialResourceList.PartialDescriptors + ResourceCount); 00829 00830 /* FIXME: Should store the resources in the registry resource map */ 00831 00832 return Status; 00833 } 00834 00835 ULONG 00836 NTAPI 00837 HaliPciInterfaceReadConfig(IN PBUS_HANDLER RootBusHandler, 00838 IN ULONG BusNumber, 00839 IN PCI_SLOT_NUMBER SlotNumber, 00840 IN PVOID Buffer, 00841 IN ULONG Offset, 00842 IN ULONG Length) 00843 { 00844 BUS_HANDLER BusHandler; 00845 00846 /* Setup fake PCI Bus handler */ 00847 RtlCopyMemory(&BusHandler, &HalpFakePciBusHandler, sizeof(BUS_HANDLER)); 00848 BusHandler.BusNumber = BusNumber; 00849 00850 /* Read configuration data */ 00851 HalpReadPCIConfig(&BusHandler, SlotNumber, Buffer, Offset, Length); 00852 00853 /* Return length */ 00854 return Length; 00855 } 00856 00857 PPCI_REGISTRY_INFO_INTERNAL 00858 NTAPI 00859 INIT_FUNCTION 00860 HalpQueryPciRegistryInfo(VOID) 00861 { 00862 #ifndef _MINIHAL_ 00863 WCHAR NameBuffer[8]; 00864 OBJECT_ATTRIBUTES ObjectAttributes; 00865 UNICODE_STRING KeyName, ConfigName, IdentName; 00866 HANDLE KeyHandle, BusKeyHandle, CardListHandle; 00867 NTSTATUS Status; 00868 UCHAR KeyBuffer[sizeof(CM_FULL_RESOURCE_DESCRIPTOR) + 100]; 00869 PKEY_VALUE_FULL_INFORMATION ValueInfo = (PVOID)KeyBuffer; 00870 UCHAR PartialKeyBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 00871 sizeof(PCI_CARD_DESCRIPTOR)]; 00872 PKEY_VALUE_PARTIAL_INFORMATION PartialValueInfo = (PVOID)PartialKeyBuffer; 00873 KEY_FULL_INFORMATION KeyInformation; 00874 ULONG ResultLength; 00875 PWSTR Tag; 00876 ULONG i, ElementCount; 00877 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor; 00878 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; 00879 PPCI_REGISTRY_INFO PciRegInfo; 00880 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo; 00881 PPCI_CARD_DESCRIPTOR CardDescriptor; 00882 00883 /* Setup the object attributes for the key */ 00884 RtlInitUnicodeString(&KeyName, 00885 L"\\Registry\\Machine\\Hardware\\Description\\" 00886 L"System\\MultiFunctionAdapter"); 00887 InitializeObjectAttributes(&ObjectAttributes, 00888 &KeyName, 00889 OBJ_CASE_INSENSITIVE, 00890 NULL, 00891 NULL); 00892 00893 /* Open the key */ 00894 Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes); 00895 if (!NT_SUCCESS(Status)) return NULL; 00896 00897 /* Setup the receiving string */ 00898 KeyName.Buffer = NameBuffer; 00899 KeyName.MaximumLength = sizeof(NameBuffer); 00900 00901 /* Setup the configuration and identifier key names */ 00902 RtlInitUnicodeString(&ConfigName, L"Configuration Data"); 00903 RtlInitUnicodeString(&IdentName, L"Identifier"); 00904 00905 /* Keep looping for each ID */ 00906 for (i = 0; TRUE; i++) 00907 { 00908 /* Setup the key name */ 00909 RtlIntegerToUnicodeString(i, 10, &KeyName); 00910 InitializeObjectAttributes(&ObjectAttributes, 00911 &KeyName, 00912 OBJ_CASE_INSENSITIVE, 00913 KeyHandle, 00914 NULL); 00915 00916 /* Open it */ 00917 Status = ZwOpenKey(&BusKeyHandle, KEY_READ, &ObjectAttributes); 00918 if (!NT_SUCCESS(Status)) 00919 { 00920 /* None left, fail */ 00921 ZwClose(KeyHandle); 00922 return NULL; 00923 } 00924 00925 /* Read the registry data */ 00926 Status = ZwQueryValueKey(BusKeyHandle, 00927 &IdentName, 00928 KeyValueFullInformation, 00929 ValueInfo, 00930 sizeof(KeyBuffer), 00931 &ResultLength); 00932 if (!NT_SUCCESS(Status)) 00933 { 00934 /* Failed, try the next one */ 00935 ZwClose(BusKeyHandle); 00936 continue; 00937 } 00938 00939 /* Get the PCI Tag and validate it */ 00940 Tag = (PWSTR)((ULONG_PTR)ValueInfo + ValueInfo->DataOffset); 00941 if ((Tag[0] != L'P') || 00942 (Tag[1] != L'C') || 00943 (Tag[2] != L'I') || 00944 (Tag[3])) 00945 { 00946 /* Not a valid PCI entry, skip it */ 00947 ZwClose(BusKeyHandle); 00948 continue; 00949 } 00950 00951 /* Now read our PCI structure */ 00952 Status = ZwQueryValueKey(BusKeyHandle, 00953 &ConfigName, 00954 KeyValueFullInformation, 00955 ValueInfo, 00956 sizeof(KeyBuffer), 00957 &ResultLength); 00958 ZwClose(BusKeyHandle); 00959 if (!NT_SUCCESS(Status)) continue; 00960 00961 /* We read it OK! Get the actual resource descriptors */ 00962 FullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) 00963 ((ULONG_PTR)ValueInfo + ValueInfo->DataOffset); 00964 PartialDescriptor = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) 00965 ((ULONG_PTR)FullDescriptor-> 00966 PartialResourceList.PartialDescriptors); 00967 00968 /* Check if this is our PCI Registry Information */ 00969 if (PartialDescriptor->Type == CmResourceTypeDeviceSpecific) 00970 { 00971 /* It is, stop searching */ 00972 break; 00973 } 00974 } 00975 00976 /* Close the key */ 00977 ZwClose(KeyHandle); 00978 00979 /* Save the PCI information for later */ 00980 PciRegInfo = (PPCI_REGISTRY_INFO)(PartialDescriptor + 1); 00981 00982 /* Assume no Card List entries */ 00983 ElementCount = 0; 00984 00985 /* Set up for checking the PCI Card List key */ 00986 RtlInitUnicodeString(&KeyName, 00987 L"\\Registry\\Machine\\System\\CurrentControlSet\\" 00988 L"Control\\PnP\\PCI\\CardList"); 00989 InitializeObjectAttributes(&ObjectAttributes, 00990 &KeyName, 00991 OBJ_CASE_INSENSITIVE, 00992 NULL, 00993 NULL); 00994 00995 /* Attempt to open it */ 00996 Status = ZwOpenKey(&CardListHandle, KEY_READ, &ObjectAttributes); 00997 if (NT_SUCCESS(Status)) 00998 { 00999 /* It exists, so let's query it */ 01000 Status = ZwQueryKey(CardListHandle, 01001 KeyFullInformation, 01002 &KeyInformation, 01003 sizeof(KEY_FULL_INFORMATION), 01004 &ResultLength); 01005 if (!NT_SUCCESS(Status)) 01006 { 01007 /* Failed to query, so no info */ 01008 PciRegistryInfo = NULL; 01009 } 01010 else 01011 { 01012 /* Allocate the full structure */ 01013 PciRegistryInfo = 01014 ExAllocatePoolWithTag(NonPagedPool, 01015 sizeof(PCI_REGISTRY_INFO_INTERNAL) + 01016 (KeyInformation.Values * 01017 sizeof(PCI_CARD_DESCRIPTOR)), 01018 TAG_HAL); 01019 if (PciRegistryInfo) 01020 { 01021 /* Get the first card descriptor entry */ 01022 CardDescriptor = (PPCI_CARD_DESCRIPTOR)(PciRegistryInfo + 1); 01023 01024 /* Loop all the values */ 01025 for (i = 0; i < KeyInformation.Values; i++) 01026 { 01027 /* Attempt to get the value */ 01028 Status = ZwEnumerateValueKey(CardListHandle, 01029 i, 01030 KeyValuePartialInformation, 01031 PartialValueInfo, 01032 sizeof(PartialKeyBuffer), 01033 &ResultLength); 01034 if (!NT_SUCCESS(Status)) 01035 { 01036 /* Something went wrong, stop the search */ 01037 break; 01038 } 01039 01040 /* Make sure it is correctly sized */ 01041 if (PartialValueInfo->DataLength == sizeof(PCI_CARD_DESCRIPTOR)) 01042 { 01043 /* Sure is, copy it over */ 01044 *CardDescriptor = *(PPCI_CARD_DESCRIPTOR) 01045 PartialValueInfo->Data; 01046 01047 /* One more Card List entry */ 01048 ElementCount++; 01049 01050 /* Move to the next descriptor */ 01051 CardDescriptor = (CardDescriptor + 1); 01052 } 01053 } 01054 } 01055 } 01056 01057 /* Close the Card List key */ 01058 ZwClose(CardListHandle); 01059 } 01060 else 01061 { 01062 /* No key, no Card List */ 01063 PciRegistryInfo = NULL; 01064 } 01065 01066 /* Check if we failed to get the full structure */ 01067 if (!PciRegistryInfo) 01068 { 01069 /* Just allocate the basic structure then */ 01070 PciRegistryInfo = ExAllocatePoolWithTag(NonPagedPool, 01071 sizeof(PCI_REGISTRY_INFO_INTERNAL), 01072 TAG_HAL); 01073 if (!PciRegistryInfo) return NULL; 01074 } 01075 01076 /* Save the info we got */ 01077 PciRegistryInfo->MajorRevision = PciRegInfo->MajorRevision; 01078 PciRegistryInfo->MinorRevision = PciRegInfo->MinorRevision; 01079 PciRegistryInfo->NoBuses = PciRegInfo->NoBuses; 01080 PciRegistryInfo->HardwareMechanism = PciRegInfo->HardwareMechanism; 01081 PciRegistryInfo->ElementCount = ElementCount; 01082 01083 /* Return it */ 01084 return PciRegistryInfo; 01085 #else 01086 return NULL; 01087 #endif 01088 } 01089 01090 VOID 01091 NTAPI 01092 INIT_FUNCTION 01093 HalpInitializePciStubs(VOID) 01094 { 01095 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo; 01096 UCHAR PciType; 01097 PPCIPBUSDATA BusData = (PPCIPBUSDATA)HalpFakePciBusHandler.BusData; 01098 ULONG i; 01099 PCI_SLOT_NUMBER j; 01100 ULONG VendorId = 0; 01101 ULONG MaxPciBusNumber; 01102 01103 /* Query registry information */ 01104 PciRegistryInfo = HalpQueryPciRegistryInfo(); 01105 if (!PciRegistryInfo) 01106 { 01107 /* Assume type 1 */ 01108 PciType = 1; 01109 01110 /* Force a manual bus scan later */ 01111 MaxPciBusNumber = MAXULONG; 01112 } 01113 else 01114 { 01115 /* Get the PCI type */ 01116 PciType = PciRegistryInfo->HardwareMechanism & 0xF; 01117 01118 /* Get MaxPciBusNumber and make it 0-based */ 01119 MaxPciBusNumber = PciRegistryInfo->NoBuses - 1; 01120 01121 /* Free the info structure */ 01122 ExFreePoolWithTag(PciRegistryInfo, TAG_HAL); 01123 } 01124 01125 /* Initialize the PCI lock */ 01126 KeInitializeSpinLock(&HalpPCIConfigLock); 01127 01128 /* Check the type of PCI bus */ 01129 switch (PciType) 01130 { 01131 /* Type 1 PCI Bus */ 01132 case 1: 01133 01134 /* Copy the Type 1 handler data */ 01135 RtlCopyMemory(&PCIConfigHandler, 01136 &PCIConfigHandlerType1, 01137 sizeof(PCIConfigHandler)); 01138 01139 /* Set correct I/O Ports */ 01140 BusData->Config.Type1.Address = PCI_TYPE1_ADDRESS_PORT; 01141 BusData->Config.Type1.Data = PCI_TYPE1_DATA_PORT; 01142 break; 01143 01144 /* Type 2 PCI Bus */ 01145 case 2: 01146 01147 /* Copy the Type 2 handler data */ 01148 RtlCopyMemory(&PCIConfigHandler, 01149 &PCIConfigHandlerType2, 01150 sizeof (PCIConfigHandler)); 01151 01152 /* Set correct I/O Ports */ 01153 BusData->Config.Type2.CSE = PCI_TYPE2_CSE_PORT; 01154 BusData->Config.Type2.Forward = PCI_TYPE2_FORWARD_PORT; 01155 BusData->Config.Type2.Base = PCI_TYPE2_ADDRESS_BASE; 01156 01157 /* Only 16 devices supported, not 32 */ 01158 BusData->MaxDevice = 16; 01159 break; 01160 01161 default: 01162 01163 /* Invalid type */ 01164 DbgPrint("HAL: Unknown PCI type\n"); 01165 } 01166 01167 /* Run a forced bus scan if needed */ 01168 if (MaxPciBusNumber == MAXULONG) 01169 { 01170 /* Initialize the max bus number to 0xFF */ 01171 HalpMaxPciBus = 0xFF; 01172 01173 /* Initialize the counter */ 01174 MaxPciBusNumber = 0; 01175 01176 /* Loop all possible buses */ 01177 for (i = 0; i < HalpMaxPciBus; i++) 01178 { 01179 /* Loop all devices */ 01180 for (j.u.AsULONG = 0; j.u.AsULONG < BusData->MaxDevice; j.u.AsULONG++) 01181 { 01182 /* Query the interface */ 01183 if (HaliPciInterfaceReadConfig(NULL, 01184 i, 01185 j, 01186 &VendorId, 01187 0, 01188 sizeof(ULONG))) 01189 { 01190 /* Validate the vendor ID */ 01191 if ((VendorId & 0xFFFF) != PCI_INVALID_VENDORID) 01192 { 01193 /* Set this as the maximum ID */ 01194 MaxPciBusNumber = i; 01195 break; 01196 } 01197 } 01198 } 01199 } 01200 } 01201 01202 /* Set the real max bus number */ 01203 HalpMaxPciBus = MaxPciBusNumber; 01204 01205 /* We're done */ 01206 HalpPCIConfigInitialized = TRUE; 01207 } 01208 01209 /* EOF */ 01210 Generated on Thu May 24 2012 04:29:22 for ReactOS by
1.7.6.1
|