Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpci.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/pci.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 BOOLEAN HalpPCIConfigInitialized; 00018 ULONG HalpMinPciBus, HalpMaxPciBus; 00019 KSPIN_LOCK HalpPCIConfigLock; 00020 PCI_CONFIG_HANDLER PCIConfigHandler; 00021 00022 /* PCI Operation Matrix */ 00023 UCHAR PCIDeref[4][4] = 00024 { 00025 {0, 1, 2, 2}, // ULONG-aligned offset 00026 {1, 1, 1, 1}, // UCHAR-aligned offset 00027 {2, 1, 2, 2}, // USHORT-aligned offset 00028 {1, 1, 1, 1} // UCHAR-aligned offset 00029 }; 00030 00031 /* Type 1 PCI Bus */ 00032 PCI_CONFIG_HANDLER PCIConfigHandlerType1 = 00033 { 00034 /* Synchronization */ 00035 (FncSync)HalpPCISynchronizeType1, 00036 (FncReleaseSync)HalpPCIReleaseSynchronzationType1, 00037 00038 /* Read */ 00039 { 00040 (FncConfigIO)HalpPCIReadUlongType1, 00041 (FncConfigIO)HalpPCIReadUcharType1, 00042 (FncConfigIO)HalpPCIReadUshortType1 00043 }, 00044 00045 /* Write */ 00046 { 00047 (FncConfigIO)HalpPCIWriteUlongType1, 00048 (FncConfigIO)HalpPCIWriteUcharType1, 00049 (FncConfigIO)HalpPCIWriteUshortType1 00050 } 00051 }; 00052 00053 /* Type 2 PCI Bus */ 00054 PCI_CONFIG_HANDLER PCIConfigHandlerType2 = 00055 { 00056 /* Synchronization */ 00057 (FncSync)HalpPCISynchronizeType2, 00058 (FncReleaseSync)HalpPCIReleaseSynchronzationType2, 00059 00060 /* Read */ 00061 { 00062 (FncConfigIO)HalpPCIReadUlongType2, 00063 (FncConfigIO)HalpPCIReadUcharType2, 00064 (FncConfigIO)HalpPCIReadUshortType2 00065 }, 00066 00067 /* Write */ 00068 { 00069 (FncConfigIO)HalpPCIWriteUlongType2, 00070 (FncConfigIO)HalpPCIWriteUcharType2, 00071 (FncConfigIO)HalpPCIWriteUshortType2 00072 } 00073 }; 00074 00075 PCIPBUSDATA HalpFakePciBusData = 00076 { 00077 { 00078 PCI_DATA_TAG, 00079 PCI_DATA_VERSION, 00080 HalpReadPCIConfig, 00081 HalpWritePCIConfig, 00082 NULL, 00083 NULL, 00084 {{{0}}}, 00085 {0, 0, 0, 0} 00086 }, 00087 {{0}}, 00088 32, 00089 }; 00090 00091 BUS_HANDLER HalpFakePciBusHandler = 00092 { 00093 1, 00094 PCIBus, 00095 PCIConfiguration, 00096 0, 00097 NULL, 00098 NULL, 00099 &HalpFakePciBusData, 00100 0, 00101 {0, 0, 0, 0}, 00102 HalpGetPCIData, 00103 HalpSetPCIData, 00104 NULL, 00105 HalpAssignPCISlotResources, 00106 NULL, 00107 NULL 00108 }; 00109 00110 /* TYPE 1 FUNCTIONS **********************************************************/ 00111 00112 VOID 00113 NTAPI 00114 HalpPCISynchronizeType1(IN PBUS_HANDLER BusHandler, 00115 IN PCI_SLOT_NUMBER Slot, 00116 IN PKIRQL Irql, 00117 IN PPCI_TYPE1_CFG_BITS PciCfg1) 00118 { 00119 /* Setup the PCI Configuration Register */ 00120 PciCfg1->u.AsULONG = 0; 00121 PciCfg1->u.bits.BusNumber = BusHandler->BusNumber; 00122 PciCfg1->u.bits.DeviceNumber = Slot.u.bits.DeviceNumber; 00123 PciCfg1->u.bits.FunctionNumber = Slot.u.bits.FunctionNumber; 00124 PciCfg1->u.bits.Enable = TRUE; 00125 00126 /* Acquire the lock */ 00127 KeRaiseIrql(HIGH_LEVEL, Irql); 00128 KiAcquireSpinLock(&HalpPCIConfigLock); 00129 } 00130 00131 VOID 00132 NTAPI 00133 HalpPCIReleaseSynchronzationType1(IN PBUS_HANDLER BusHandler, 00134 IN KIRQL Irql) 00135 { 00136 PCI_TYPE1_CFG_BITS PciCfg1; 00137 00138 /* Clear the PCI Configuration Register */ 00139 PciCfg1.u.AsULONG = 0; 00140 WRITE_PORT_ULONG(((PPCIPBUSDATA)BusHandler->BusData)->Config.Type1.Address, 00141 PciCfg1.u.AsULONG); 00142 00143 /* Release the lock */ 00144 KiReleaseSpinLock(&HalpPCIConfigLock); 00145 KeLowerIrql(Irql); 00146 } 00147 00148 TYPE1_READ(HalpPCIReadUcharType1, UCHAR) 00149 TYPE1_READ(HalpPCIReadUshortType1, USHORT) 00150 TYPE1_READ(HalpPCIReadUlongType1, ULONG) 00151 TYPE1_WRITE(HalpPCIWriteUcharType1, UCHAR) 00152 TYPE1_WRITE(HalpPCIWriteUshortType1, USHORT) 00153 TYPE1_WRITE(HalpPCIWriteUlongType1, ULONG) 00154 00155 /* TYPE 2 FUNCTIONS **********************************************************/ 00156 00157 VOID 00158 NTAPI 00159 HalpPCISynchronizeType2(IN PBUS_HANDLER BusHandler, 00160 IN PCI_SLOT_NUMBER Slot, 00161 IN PKIRQL Irql, 00162 IN PPCI_TYPE2_ADDRESS_BITS PciCfg) 00163 { 00164 PCI_TYPE2_CSE_BITS PciCfg2Cse; 00165 PPCIPBUSDATA BusData = (PPCIPBUSDATA)BusHandler->BusData; 00166 00167 /* Setup the configuration register */ 00168 PciCfg->u.AsUSHORT = 0; 00169 PciCfg->u.bits.Agent = (USHORT)Slot.u.bits.DeviceNumber; 00170 PciCfg->u.bits.AddressBase = (USHORT)BusData->Config.Type2.Base; 00171 00172 /* Acquire the lock */ 00173 KeRaiseIrql(HIGH_LEVEL, Irql); 00174 KiAcquireSpinLock(&HalpPCIConfigLock); 00175 00176 /* Setup the CSE Register */ 00177 PciCfg2Cse.u.AsUCHAR = 0; 00178 PciCfg2Cse.u.bits.Enable = TRUE; 00179 PciCfg2Cse.u.bits.FunctionNumber = (UCHAR)Slot.u.bits.FunctionNumber; 00180 PciCfg2Cse.u.bits.Key = -1; 00181 00182 /* Write the bus number and CSE */ 00183 WRITE_PORT_UCHAR(BusData->Config.Type2.Forward, 00184 (UCHAR)BusHandler->BusNumber); 00185 WRITE_PORT_UCHAR(BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR); 00186 } 00187 00188 VOID 00189 NTAPI 00190 HalpPCIReleaseSynchronzationType2(IN PBUS_HANDLER BusHandler, 00191 IN KIRQL Irql) 00192 { 00193 PCI_TYPE2_CSE_BITS PciCfg2Cse; 00194 PPCIPBUSDATA BusData = (PPCIPBUSDATA)BusHandler->BusData; 00195 00196 /* Clear CSE and bus number */ 00197 PciCfg2Cse.u.AsUCHAR = 0; 00198 WRITE_PORT_UCHAR(BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR); 00199 WRITE_PORT_UCHAR(BusData->Config.Type2.Forward, 0); 00200 00201 /* Release the lock */ 00202 KiReleaseSpinLock(&HalpPCIConfigLock); 00203 KeLowerIrql(Irql); 00204 } 00205 00206 TYPE2_READ(HalpPCIReadUcharType2, UCHAR) 00207 TYPE2_READ(HalpPCIReadUshortType2, USHORT) 00208 TYPE2_READ(HalpPCIReadUlongType2, ULONG) 00209 TYPE2_WRITE(HalpPCIWriteUcharType2, UCHAR) 00210 TYPE2_WRITE(HalpPCIWriteUshortType2, USHORT) 00211 TYPE2_WRITE(HalpPCIWriteUlongType2, ULONG) 00212 00213 /* PCI CONFIGURATION SPACE ***************************************************/ 00214 00215 VOID 00216 NTAPI 00217 HalpPCIConfig(IN PBUS_HANDLER BusHandler, 00218 IN PCI_SLOT_NUMBER Slot, 00219 IN PUCHAR Buffer, 00220 IN ULONG Offset, 00221 IN ULONG Length, 00222 IN FncConfigIO *ConfigIO) 00223 { 00224 KIRQL OldIrql; 00225 ULONG i; 00226 UCHAR State[20]; 00227 00228 /* Synchronize the operation */ 00229 PCIConfigHandler.Synchronize(BusHandler, Slot, &OldIrql, State); 00230 00231 /* Loop every increment */ 00232 while (Length) 00233 { 00234 /* Find out the type of read/write we need to do */ 00235 i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)]; 00236 00237 /* Do the read/write and return the number of bytes */ 00238 i = ConfigIO[i]((PPCIPBUSDATA)BusHandler->BusData, 00239 State, 00240 Buffer, 00241 Offset); 00242 00243 /* Increment the buffer position and offset, and decrease the length */ 00244 Offset += i; 00245 Buffer += i; 00246 Length -= i; 00247 } 00248 00249 /* Release the lock and PCI bus */ 00250 PCIConfigHandler.ReleaseSynchronzation(BusHandler, OldIrql); 00251 } 00252 00253 VOID 00254 NTAPI 00255 HalpReadPCIConfig(IN PBUS_HANDLER BusHandler, 00256 IN PCI_SLOT_NUMBER Slot, 00257 IN PVOID Buffer, 00258 IN ULONG Offset, 00259 IN ULONG Length) 00260 { 00261 /* Validate the PCI Slot */ 00262 if (!HalpValidPCISlot(BusHandler, Slot)) 00263 { 00264 /* Fill the buffer with invalid data */ 00265 RtlFillMemory(Buffer, Length, -1); 00266 } 00267 else 00268 { 00269 /* Send the request */ 00270 HalpPCIConfig(BusHandler, 00271 Slot, 00272 Buffer, 00273 Offset, 00274 Length, 00275 PCIConfigHandler.ConfigRead); 00276 } 00277 } 00278 00279 VOID 00280 NTAPI 00281 HalpWritePCIConfig(IN PBUS_HANDLER BusHandler, 00282 IN PCI_SLOT_NUMBER Slot, 00283 IN PVOID Buffer, 00284 IN ULONG Offset, 00285 IN ULONG Length) 00286 { 00287 /* Validate the PCI Slot */ 00288 if (HalpValidPCISlot(BusHandler, Slot)) 00289 { 00290 /* Send the request */ 00291 HalpPCIConfig(BusHandler, 00292 Slot, 00293 Buffer, 00294 Offset, 00295 Length, 00296 PCIConfigHandler.ConfigWrite); 00297 } 00298 } 00299 00300 BOOLEAN 00301 NTAPI 00302 HalpValidPCISlot(IN PBUS_HANDLER BusHandler, 00303 IN PCI_SLOT_NUMBER Slot) 00304 { 00305 PCI_SLOT_NUMBER MultiSlot; 00306 PPCIPBUSDATA BusData = (PPCIPBUSDATA)BusHandler->BusData; 00307 UCHAR HeaderType; 00308 ULONG Device; 00309 00310 /* Simple validation */ 00311 if (Slot.u.bits.Reserved) return FALSE; 00312 if (Slot.u.bits.DeviceNumber >= BusData->MaxDevice) return FALSE; 00313 00314 /* Function 0 doesn't need checking */ 00315 if (!Slot.u.bits.FunctionNumber) return TRUE; 00316 00317 /* Functions 0+ need Multi-Function support, so check the slot */ 00318 Device = Slot.u.bits.DeviceNumber; 00319 MultiSlot = Slot; 00320 MultiSlot.u.bits.FunctionNumber = 0; 00321 00322 /* Send function 0 request to get the header back */ 00323 HalpReadPCIConfig(BusHandler, 00324 MultiSlot, 00325 &HeaderType, 00326 FIELD_OFFSET(PCI_COMMON_CONFIG, HeaderType), 00327 sizeof(UCHAR)); 00328 00329 /* Now make sure the header is multi-function */ 00330 if (!(HeaderType & PCI_MULTIFUNCTION) || (HeaderType == 0xFF)) return FALSE; 00331 return TRUE; 00332 } 00333 00334 /* HAL PCI CALLBACKS *********************************************************/ 00335 00336 ULONG 00337 NTAPI 00338 HalpGetPCIData(IN PBUS_HANDLER BusHandler, 00339 IN PBUS_HANDLER RootHandler, 00340 IN PCI_SLOT_NUMBER Slot, 00341 IN PUCHAR Buffer, 00342 IN ULONG Offset, 00343 IN ULONG Length) 00344 { 00345 UCHAR PciBuffer[PCI_COMMON_HDR_LENGTH]; 00346 PPCI_COMMON_CONFIG PciConfig = (PPCI_COMMON_CONFIG)PciBuffer; 00347 ULONG Len = 0; 00348 00349 /* Normalize the length */ 00350 if (Length > sizeof(PCI_COMMON_CONFIG)) Length = sizeof(PCI_COMMON_CONFIG); 00351 00352 /* Check if this is a vendor-specific read */ 00353 if (Offset >= PCI_COMMON_HDR_LENGTH) 00354 { 00355 /* Read the header */ 00356 HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, sizeof(ULONG)); 00357 00358 /* Make sure the vendor is valid */ 00359 if (PciConfig->VendorID == PCI_INVALID_VENDORID) return 0; 00360 } 00361 else 00362 { 00363 /* Read the entire header */ 00364 Len = PCI_COMMON_HDR_LENGTH; 00365 HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, Len); 00366 00367 /* Validate the vendor ID */ 00368 if (PciConfig->VendorID == PCI_INVALID_VENDORID) 00369 { 00370 /* It's invalid, but we want to return this much */ 00371 PciConfig->VendorID = PCI_INVALID_VENDORID; 00372 Len = sizeof(USHORT); 00373 } 00374 00375 /* Now check if there's space left */ 00376 if (Len < Offset) return 0; 00377 00378 /* There is, so return what's after the offset and normalize */ 00379 Len -= Offset; 00380 if (Len > Length) Len = Length; 00381 00382 /* Copy the data into the caller's buffer */ 00383 RtlMoveMemory(Buffer, PciBuffer + Offset, Len); 00384 00385 /* Update buffer and offset, decrement total length */ 00386 Offset += Len; 00387 Buffer += Len; 00388 Length -= Len; 00389 } 00390 00391 /* Now we still have something to copy */ 00392 if (Length) 00393 { 00394 /* Check if it's vendor-specific data */ 00395 if (Offset >= PCI_COMMON_HDR_LENGTH) 00396 { 00397 /* Read it now */ 00398 HalpReadPCIConfig(BusHandler, Slot, Buffer, Offset, Length); 00399 Len += Length; 00400 } 00401 } 00402 00403 /* Update the total length read */ 00404 return Len; 00405 } 00406 00407 ULONG 00408 NTAPI 00409 HalpSetPCIData(IN PBUS_HANDLER BusHandler, 00410 IN PBUS_HANDLER RootHandler, 00411 IN PCI_SLOT_NUMBER Slot, 00412 IN PUCHAR Buffer, 00413 IN ULONG Offset, 00414 IN ULONG Length) 00415 { 00416 UCHAR PciBuffer[PCI_COMMON_HDR_LENGTH]; 00417 PPCI_COMMON_CONFIG PciConfig = (PPCI_COMMON_CONFIG)PciBuffer; 00418 ULONG Len = 0; 00419 00420 /* Normalize the length */ 00421 if (Length > sizeof(PCI_COMMON_CONFIG)) Length = sizeof(PCI_COMMON_CONFIG); 00422 00423 /* Check if this is a vendor-specific read */ 00424 if (Offset >= PCI_COMMON_HDR_LENGTH) 00425 { 00426 /* Read the header */ 00427 HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, sizeof(ULONG)); 00428 00429 /* Make sure the vendor is valid */ 00430 if (PciConfig->VendorID == PCI_INVALID_VENDORID) return 0; 00431 } 00432 else 00433 { 00434 /* Read the entire header and validate the vendor ID */ 00435 Len = PCI_COMMON_HDR_LENGTH; 00436 HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, Len); 00437 if (PciConfig->VendorID == PCI_INVALID_VENDORID) return 0; 00438 00439 /* Return what's after the offset and normalize */ 00440 Len -= Offset; 00441 if (Len > Length) Len = Length; 00442 00443 /* Copy the specific caller data */ 00444 RtlMoveMemory(PciBuffer + Offset, Buffer, Len); 00445 00446 /* Write the actual configuration data */ 00447 HalpWritePCIConfig(BusHandler, Slot, PciBuffer + Offset, Offset, Len); 00448 00449 /* Update buffer and offset, decrement total length */ 00450 Offset += Len; 00451 Buffer += Len; 00452 Length -= Len; 00453 } 00454 00455 /* Now we still have something to copy */ 00456 if (Length) 00457 { 00458 /* Check if it's vendor-specific data */ 00459 if (Offset >= PCI_COMMON_HDR_LENGTH) 00460 { 00461 /* Read it now */ 00462 HalpWritePCIConfig(BusHandler, Slot, Buffer, Offset, Length); 00463 Len += Length; 00464 } 00465 } 00466 00467 /* Update the total length read */ 00468 return Len; 00469 } 00470 00471 NTSTATUS 00472 NTAPI 00473 HalpSetupPciDeviceForDebugging(IN PVOID LoaderBlock, 00474 IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice) 00475 { 00476 DPRINT1("Unimplemented!\n"); 00477 return STATUS_NOT_IMPLEMENTED; 00478 } 00479 00480 NTSTATUS 00481 NTAPI 00482 HalpReleasePciDeviceForDebugging(IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice) 00483 { 00484 DPRINT1("Unimplemented!\n"); 00485 return STATUS_NOT_IMPLEMENTED; 00486 } 00487 00488 NTSTATUS 00489 NTAPI 00490 HalpAssignPCISlotResources(IN PBUS_HANDLER BusHandler, 00491 IN PBUS_HANDLER RootHandler, 00492 IN PUNICODE_STRING RegistryPath, 00493 IN PUNICODE_STRING DriverClassName OPTIONAL, 00494 IN PDRIVER_OBJECT DriverObject, 00495 IN PDEVICE_OBJECT DeviceObject OPTIONAL, 00496 IN ULONG Slot, 00497 IN OUT PCM_RESOURCE_LIST *pAllocatedResources) 00498 { 00499 KeBugCheck(0); 00500 return STATUS_SUCCESS; 00501 } 00502 00503 ULONG 00504 NTAPI 00505 HaliPciInterfaceReadConfig(IN PBUS_HANDLER RootBusHandler, 00506 IN ULONG BusNumber, 00507 IN PCI_SLOT_NUMBER SlotNumber, 00508 IN PVOID Buffer, 00509 IN ULONG Offset, 00510 IN ULONG Length) 00511 { 00512 BUS_HANDLER BusHandler; 00513 PPCI_COMMON_CONFIG PciData = (PPCI_COMMON_CONFIG)Buffer; 00514 00515 /* Setup fake PCI Bus handler */ 00516 RtlCopyMemory(&BusHandler, &HalpFakePciBusHandler, sizeof(BUS_HANDLER)); 00517 BusHandler.BusNumber = BusNumber; 00518 00519 /* Read configuration data */ 00520 HalpReadPCIConfig(&BusHandler, SlotNumber, Buffer, Offset, Length); 00521 00522 /* Check if caller only wanted at least Vendor ID */ 00523 if (Length >= 2) 00524 { 00525 /* Validate it */ 00526 if (PciData->VendorID != PCI_INVALID_VENDORID) 00527 { 00528 /* Check if this is the new maximum bus number */ 00529 if (HalpMaxPciBus < BusHandler.BusNumber) 00530 { 00531 /* Set it */ 00532 HalpMaxPciBus = BusHandler.BusNumber; 00533 } 00534 } 00535 } 00536 00537 /* Return length */ 00538 return Length; 00539 } 00540 00541 PPCI_REGISTRY_INFO_INTERNAL 00542 NTAPI 00543 HalpQueryPciRegistryInfo(VOID) 00544 { 00545 WCHAR NameBuffer[8]; 00546 OBJECT_ATTRIBUTES ObjectAttributes; 00547 UNICODE_STRING KeyName, ConfigName, IdentName; 00548 HANDLE KeyHandle, BusKeyHandle; 00549 NTSTATUS Status; 00550 UCHAR KeyBuffer[sizeof(PPCI_REGISTRY_INFO) + 100]; 00551 PKEY_VALUE_FULL_INFORMATION ValueInfo = (PVOID)KeyBuffer; 00552 ULONG ResultLength; 00553 PWSTR Tag; 00554 ULONG i; 00555 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor; 00556 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; 00557 PPCI_REGISTRY_INFO PciRegInfo; 00558 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo; 00559 00560 /* Setup the object attributes for the key */ 00561 RtlInitUnicodeString(&KeyName, 00562 L"\\Registry\\Machine\\Hardware\\Description\\" 00563 L"System\\MultiFunctionAdapter"); 00564 InitializeObjectAttributes(&ObjectAttributes, 00565 &KeyName, 00566 OBJ_CASE_INSENSITIVE, 00567 NULL, 00568 NULL); 00569 00570 /* Open the key */ 00571 Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes); 00572 if (!NT_SUCCESS(Status)) return NULL; 00573 00574 /* Setup the receiving string */ 00575 KeyName.Buffer = NameBuffer; 00576 KeyName.MaximumLength = sizeof(NameBuffer); 00577 00578 /* Setup the configuration and identifier key names */ 00579 RtlInitUnicodeString(&ConfigName, L"ConfigurationData"); 00580 RtlInitUnicodeString(&IdentName, L"Identifier"); 00581 00582 /* Keep looping for each ID */ 00583 for (i = 0; TRUE; i++) 00584 { 00585 /* Setup the key name */ 00586 RtlIntegerToUnicodeString(i, 10, &KeyName); 00587 InitializeObjectAttributes(&ObjectAttributes, 00588 &KeyName, 00589 OBJ_CASE_INSENSITIVE, 00590 KeyHandle, 00591 NULL); 00592 00593 /* Open it */ 00594 Status = ZwOpenKey(&BusKeyHandle, KEY_READ, &ObjectAttributes); 00595 if (!NT_SUCCESS(Status)) 00596 { 00597 /* None left, fail */ 00598 ZwClose(KeyHandle); 00599 return NULL; 00600 } 00601 00602 /* Read the registry data */ 00603 Status = ZwQueryValueKey(BusKeyHandle, 00604 &IdentName, 00605 KeyValueFullInformation, 00606 ValueInfo, 00607 sizeof(KeyBuffer), 00608 &ResultLength); 00609 if (!NT_SUCCESS(Status)) 00610 { 00611 /* Failed, try the next one */ 00612 ZwClose(BusKeyHandle); 00613 continue; 00614 } 00615 00616 /* Get the PCI Tag and validate it */ 00617 Tag = (PWSTR)((ULONG_PTR)ValueInfo + ValueInfo->DataOffset); 00618 if ((Tag[0] != L'P') || 00619 (Tag[1] != L'C') || 00620 (Tag[2] != L'I') || 00621 (Tag[3])) 00622 { 00623 /* Not a valid PCI entry, skip it */ 00624 ZwClose(BusKeyHandle); 00625 continue; 00626 } 00627 00628 /* Now read our PCI structure */ 00629 Status = ZwQueryValueKey(BusKeyHandle, 00630 &ConfigName, 00631 KeyValueFullInformation, 00632 ValueInfo, 00633 sizeof(KeyBuffer), 00634 &ResultLength); 00635 ZwClose(BusKeyHandle); 00636 if (!NT_SUCCESS(Status)) continue; 00637 00638 /* We read it OK! Get the actual resource descriptors */ 00639 FullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) 00640 ((ULONG_PTR)ValueInfo + ValueInfo->DataOffset); 00641 PartialDescriptor = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) 00642 ((ULONG_PTR)FullDescriptor-> 00643 PartialResourceList.PartialDescriptors); 00644 00645 /* Check if this is our PCI Registry Information */ 00646 if (PartialDescriptor->Type == CmResourceTypeDeviceSpecific) 00647 { 00648 /* Close the key */ 00649 ZwClose(KeyHandle); 00650 00651 /* FIXME: Check PnP\PCI\CardList */ 00652 00653 /* Get the PCI information */ 00654 PciRegInfo = (PPCI_REGISTRY_INFO)(PartialDescriptor + 1); 00655 00656 /* Allocate the return structure */ 00657 PciRegistryInfo = ExAllocatePoolWithTag(NonPagedPool, 00658 sizeof(PCI_REGISTRY_INFO_INTERNAL), 00659 ' laH'); 00660 if (!PciRegistryInfo) return NULL; 00661 00662 /* Fill it out */ 00663 PciRegistryInfo->HardwareMechanism = PciRegInfo->HardwareMechanism; 00664 PciRegistryInfo->NoBuses = PciRegInfo->NoBuses; 00665 PciRegistryInfo->MajorRevision = PciRegInfo->MajorRevision; 00666 PciRegistryInfo->MinorRevision = PciRegInfo->MinorRevision; 00667 PciRegistryInfo->ElementCount = 0; 00668 } 00669 } 00670 } 00671 00672 VOID 00673 NTAPI 00674 HalpInitializePciStubs(VOID) 00675 { 00676 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo; 00677 UCHAR PciType; 00678 PPCIPBUSDATA BusData = (PPCIPBUSDATA)HalpFakePciBusHandler.BusData; 00679 ULONG i; 00680 PCI_SLOT_NUMBER j; 00681 ULONG VendorId = 0; 00682 00683 /* Query registry information */ 00684 PciRegistryInfo = HalpQueryPciRegistryInfo(); 00685 if (!PciRegistryInfo) 00686 { 00687 /* Assume type 1 */ 00688 PciType = 1; 00689 } 00690 else 00691 { 00692 /* Get the type and free the info structure */ 00693 PciType = PciRegistryInfo->HardwareMechanism & 0xF; 00694 ExFreePool(PciRegistryInfo); 00695 } 00696 00697 /* Initialize the PCI lock */ 00698 KeInitializeSpinLock(&HalpPCIConfigLock); 00699 00700 /* Check the type of PCI bus */ 00701 switch (PciType) 00702 { 00703 /* Type 1 PCI Bus */ 00704 case 1: 00705 00706 /* Copy the Type 1 handler data */ 00707 RtlCopyMemory(&PCIConfigHandler, 00708 &PCIConfigHandlerType1, 00709 sizeof(PCIConfigHandler)); 00710 00711 /* Set correct I/O Ports */ 00712 BusData->Config.Type1.Address = PCI_TYPE1_ADDRESS_PORT; 00713 BusData->Config.Type1.Data = PCI_TYPE1_DATA_PORT; 00714 break; 00715 00716 /* Type 2 PCI Bus */ 00717 case 2: 00718 00719 /* Copy the Type 1 handler data */ 00720 RtlCopyMemory(&PCIConfigHandler, 00721 &PCIConfigHandlerType2, 00722 sizeof (PCIConfigHandler)); 00723 00724 /* Set correct I/O Ports */ 00725 BusData->Config.Type2.CSE = PCI_TYPE2_CSE_PORT; 00726 BusData->Config.Type2.Forward = PCI_TYPE2_FORWARD_PORT; 00727 BusData->Config.Type2.Base = PCI_TYPE2_ADDRESS_BASE; 00728 00729 /* Only 16 devices supported, not 32 */ 00730 BusData->MaxDevice = 16; 00731 break; 00732 00733 default: 00734 00735 /* Invalid type */ 00736 DbgPrint("HAL: Unnkown PCI type\n"); 00737 } 00738 00739 /* Loop all possible buses */ 00740 for (i = 0; i < 256; i++) 00741 { 00742 /* Loop all devices */ 00743 for (j.u.AsULONG = 0; j.u.AsULONG < 32; j.u.AsULONG++) 00744 { 00745 /* Query the interface */ 00746 if (HaliPciInterfaceReadConfig(NULL, 00747 i, 00748 j, 00749 &VendorId, 00750 0, 00751 sizeof(ULONG))) 00752 { 00753 /* Validate the vendor ID */ 00754 if ((USHORT)VendorId != PCI_INVALID_VENDORID) 00755 { 00756 /* Set this as the maximum ID */ 00757 HalpMaxPciBus = i; 00758 break; 00759 } 00760 } 00761 } 00762 } 00763 00764 /* We're done */ 00765 HalpPCIConfigInitialized = TRUE; 00766 } 00767 00768 VOID 00769 NTAPI 00770 HalpInitializePciBus(VOID) 00771 { 00772 /* Initialize the stubs */ 00773 HalpInitializePciStubs(); 00774 00775 /* FIXME: Initialize NMI Crash Flag */ 00776 } 00777 00778 /* EOF */ Generated on Sat May 26 2012 04:26:03 for ReactOS by
1.7.6.1
|