ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

pci.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.