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

init.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS PCI Bus Driver
00003  * LICENSE:         BSD - See COPYING.ARM in the top level directory
00004  * FILE:            drivers/bus/pci/init.c
00005  * PURPOSE:         Driver Initialization
00006  * PROGRAMMERS:     ReactOS Portable Systems Group
00007  */
00008 
00009 /* INCLUDES *******************************************************************/
00010 
00011 #include <pci.h>
00012 #define NDEBUG
00013 #include <debug.h>
00014 
00015 /* GLOBALS ********************************************************************/
00016 
00017 BOOLEAN PciRunningDatacenter;
00018 PDRIVER_OBJECT PciDriverObject;
00019 KEVENT PciGlobalLock;
00020 KEVENT PciBusLock;
00021 KEVENT PciLegacyDescriptionLock;
00022 BOOLEAN PciLockDeviceResources;
00023 BOOLEAN PciEnableNativeModeATA;
00024 ULONG PciSystemWideHackFlags;
00025 PPCI_IRQ_ROUTING_TABLE PciIrqRoutingTable;
00026 PWATCHDOG_TABLE WdTable;
00027 PPCI_HACK_ENTRY PciHackTable;
00028 
00029 /* FUNCTIONS ******************************************************************/
00030 
00031 NTSTATUS
00032 NTAPI
00033 PciAcpiFindRsdt(OUT PACPI_BIOS_MULTI_NODE *AcpiMultiNode)
00034 {
00035     BOOLEAN Result;
00036     NTSTATUS Status;
00037     HANDLE KeyHandle, SubKey;
00038     ULONG NumberOfBytes, i, Length;
00039     PKEY_FULL_INFORMATION FullInfo;
00040     PKEY_BASIC_INFORMATION KeyInfo;
00041     PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
00042     PACPI_BIOS_MULTI_NODE NodeData;
00043     UNICODE_STRING ValueName;
00044     struct
00045     {
00046         CM_FULL_RESOURCE_DESCRIPTOR Descriptor;
00047         ACPI_BIOS_MULTI_NODE Node;
00048     } *Package;
00049 
00050     /* So we know what to free at the end of the body */
00051     ValueInfo = NULL;
00052     KeyInfo = NULL;
00053     KeyHandle = NULL;
00054     FullInfo = NULL;
00055     Package = NULL;
00056     do
00057     {
00058         /* Open the ACPI BIOS key */
00059         Result = PciOpenKey(L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\"
00060                             L"System\\MultiFunctionAdapter",
00061                             NULL,
00062                             KEY_QUERY_VALUE,
00063                             &KeyHandle,
00064                             &Status);
00065         if (!Result) break;
00066 
00067         /* Query how much space should be allocated for the key information */
00068         Status = ZwQueryKey(KeyHandle,
00069                             KeyFullInformation,
00070                             NULL,
00071                             sizeof(ULONG),
00072                             &NumberOfBytes);
00073         if (Status != STATUS_BUFFER_TOO_SMALL) break;
00074 
00075         /* Allocate the space required */
00076         Status = STATUS_INSUFFICIENT_RESOURCES;
00077         FullInfo = ExAllocatePoolWithTag(PagedPool, NumberOfBytes, PCI_POOL_TAG);
00078         if ( !FullInfo ) break;
00079 
00080         /* Now query the key information that's needed */
00081         Status = ZwQueryKey(KeyHandle,
00082                             KeyFullInformation,
00083                             FullInfo,
00084                             NumberOfBytes,
00085                             &NumberOfBytes);
00086         if (!NT_SUCCESS(Status)) break;
00087 
00088         /* Allocate enough space to hold the value information plus the name */
00089         Status = STATUS_INSUFFICIENT_RESOURCES;
00090         Length = FullInfo->MaxNameLen + 26;
00091         KeyInfo = ExAllocatePoolWithTag(PagedPool, Length, PCI_POOL_TAG);
00092         if ( !KeyInfo ) break;
00093 
00094         /* Allocate the value information and name we expect to find */
00095         ValueInfo = ExAllocatePoolWithTag(PagedPool,
00096                                           sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
00097                                           sizeof(L"ACPI BIOS"),
00098                                           PCI_POOL_TAG);
00099         if (!ValueInfo) break;
00100 
00101         /* Loop each sub-key */
00102         i = 0;
00103         while (TRUE)
00104         {
00105             /* Query each sub-key */
00106             Status = ZwEnumerateKey(KeyHandle,
00107                                     i++,
00108                                     KeyBasicInformation,
00109                                     KeyInfo,
00110                                     Length,
00111                                     &NumberOfBytes);
00112             if (Status == STATUS_NO_MORE_ENTRIES) break;
00113 
00114             /* Null-terminate the keyname, because the kernel does not */
00115             KeyInfo->Name[KeyInfo->NameLength / sizeof(WCHAR)] = UNICODE_NULL;
00116 
00117             /* Open this subkey */
00118             Result = PciOpenKey(KeyInfo->Name,
00119                                 KeyHandle,
00120                                 KEY_QUERY_VALUE,
00121                                 &SubKey,
00122                                 &Status);
00123             if (Result)
00124             {
00125                 /* Query the identifier value for this subkey */
00126                 RtlInitUnicodeString(&ValueName, L"Identifier");
00127                 Status = ZwQueryValueKey(SubKey,
00128                                          &ValueName,
00129                                          KeyValuePartialInformation,
00130                                          ValueInfo,
00131                                          sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
00132                                          sizeof(L"ACPI BIOS"),
00133                                          &NumberOfBytes);
00134                 if (NT_SUCCESS(Status))
00135                 {
00136                     /* Check if this is the PCI BIOS subkey */
00137                     if (!wcsncmp((PWCHAR)ValueInfo->Data,
00138                                  L"ACPI BIOS",
00139                                  ValueInfo->DataLength))
00140                     {
00141                         /* It is, proceed to query the PCI IRQ routing table */
00142                         Status = PciGetRegistryValue(L"Configuration Data",
00143                                                      KeyInfo->Name,
00144                                                      KeyHandle,
00145                                                      REG_FULL_RESOURCE_DESCRIPTOR,
00146                                                      (PVOID*)&Package,
00147                                                      &NumberOfBytes);
00148                         ZwClose(SubKey);
00149                         break;
00150                     }
00151                 }
00152 
00153                 /* Close the subkey and try the next one */
00154                 ZwClose(SubKey);
00155             }
00156         }
00157 
00158         /* Check if we got here because the routing table was found */
00159         if (!NT_SUCCESS(Status))
00160         {
00161             /* This should only fail if we're out of entries */
00162             ASSERT(Status == STATUS_NO_MORE_ENTRIES);
00163             break;
00164         }
00165 
00166         /* Check if a descriptor was found */
00167         if (!Package) break;
00168 
00169         /* The configuration data is a resource list, and the BIOS node follows */
00170         NodeData = &Package->Node;
00171 
00172         /* How many E820 memory entries are there? */
00173         Length = sizeof(ACPI_BIOS_MULTI_NODE) +
00174                  (NodeData->Count - 1) * sizeof(ACPI_E820_ENTRY);
00175 
00176         /* Allocate the buffer needed to copy the information */
00177         Status = STATUS_INSUFFICIENT_RESOURCES;
00178         *AcpiMultiNode = ExAllocatePoolWithTag(NonPagedPool, Length, PCI_POOL_TAG);
00179         if (!*AcpiMultiNode) break;
00180 
00181         /* Copy the data */
00182         RtlCopyMemory(*AcpiMultiNode, NodeData, Length);
00183         Status = STATUS_SUCCESS;
00184     } while (FALSE);
00185 
00186     /* Close any opened keys, free temporary allocations, and return status */
00187     if (Package) ExFreePoolWithTag(Package, 0);
00188     if (ValueInfo) ExFreePoolWithTag(ValueInfo, 0);
00189     if (KeyInfo) ExFreePoolWithTag(KeyInfo, 0);
00190     if (FullInfo) ExFreePoolWithTag(FullInfo, 0);
00191     if (KeyHandle) ZwClose(KeyHandle);
00192     return Status;
00193 }
00194 
00195 PVOID
00196 NTAPI
00197 PciGetAcpiTable(IN ULONG TableCode)
00198 {
00199     PDESCRIPTION_HEADER Header;
00200     PACPI_BIOS_MULTI_NODE AcpiMultiNode;
00201     PRSDT Rsdt;
00202     PXSDT Xsdt;
00203     ULONG EntryCount, TableLength, Offset, CurrentEntry;
00204     PVOID TableBuffer, MappedAddress;
00205     PHYSICAL_ADDRESS PhysicalAddress;
00206     NTSTATUS Status;
00207 
00208     /* Try to find the RSDT or XSDT */
00209     Status = PciAcpiFindRsdt(&AcpiMultiNode);
00210     if (!NT_SUCCESS(Status))
00211     {
00212         /* No ACPI on the machine */
00213         DPRINT1("AcpiFindRsdt() Failed!\n");
00214         return NULL;
00215     }
00216 
00217     /* Map the RSDT with the minimum size allowed */
00218     MappedAddress = MmMapIoSpace(AcpiMultiNode->RsdtAddress,
00219                                  sizeof(DESCRIPTION_HEADER),
00220                                  MmNonCached);
00221     Header = MappedAddress;
00222     if (!Header) return NULL;
00223 
00224     /* Check how big the table really is and get rid of the temporary header */
00225     TableLength = Header->Length;
00226     MmUnmapIoSpace(Header, sizeof(DESCRIPTION_HEADER));
00227     Header = NULL;
00228 
00229     /* Map its true size */
00230     MappedAddress = MmMapIoSpace(AcpiMultiNode->RsdtAddress,
00231                                  TableLength,
00232                                  MmNonCached);
00233     Rsdt = MappedAddress;
00234     Xsdt = MappedAddress;
00235     ExFreePoolWithTag(AcpiMultiNode, 0);
00236     if (!Rsdt) return NULL;
00237 
00238     /* Validate the table's signature */
00239     if ((Rsdt->Header.Signature != RSDT_SIGNATURE) &&
00240         (Rsdt->Header.Signature != XSDT_SIGNATURE))
00241     {
00242         /* Very bad: crash */
00243         HalDisplayString("RSDT table contains invalid signature\n");
00244         MmUnmapIoSpace(Rsdt, TableLength);
00245         return NULL;
00246     }
00247 
00248     /* Smallest RSDT/XSDT is one without table entries */
00249     Offset = FIELD_OFFSET(RSDT, Tables);
00250     if (Rsdt->Header.Signature == XSDT_SIGNATURE)
00251     {
00252         /* Figure out total size of table and the offset */
00253         TableLength = Xsdt->Header.Length;
00254         if (TableLength < Offset) Offset = Xsdt->Header.Length;
00255 
00256         /* The entries are each 64-bits, so count them */
00257         EntryCount = (TableLength - Offset) / sizeof(PHYSICAL_ADDRESS);
00258     }
00259     else
00260     {
00261         /* Figure out total size of table and the offset */
00262         TableLength = Rsdt->Header.Length;
00263         if (TableLength < Offset) Offset = Rsdt->Header.Length;
00264 
00265         /* The entries are each 32-bits, so count them */
00266         EntryCount = (TableLength - Offset) / sizeof(ULONG);
00267     }
00268 
00269     /* Start at the beginning of the array and loop it */
00270     for (CurrentEntry = 0; CurrentEntry < EntryCount; CurrentEntry++)
00271     {
00272         /* Are we using the XSDT? */
00273         if (Rsdt->Header.Signature != XSDT_SIGNATURE)
00274         {
00275             /* Read the 32-bit physical address */
00276             PhysicalAddress.QuadPart = Rsdt->Tables[CurrentEntry];
00277         }
00278         else
00279         {
00280             /* Read the 64-bit physical address */
00281             PhysicalAddress = Xsdt->Tables[CurrentEntry];
00282         }
00283 
00284         /* Map this table */
00285         Header = MmMapIoSpace(PhysicalAddress,
00286                               sizeof(DESCRIPTION_HEADER),
00287                               MmNonCached);
00288         if (!Header) break;
00289 
00290         /* Check if this is the table that's being asked for */
00291         if (Header->Signature == TableCode)
00292         {
00293             /* Allocate a buffer for it */
00294             TableBuffer = ExAllocatePoolWithTag(PagedPool,
00295                                                 Header->Length,
00296                                                 PCI_POOL_TAG);
00297             if (!TableBuffer) break;
00298 
00299             /* Copy the table into the buffer */
00300             RtlCopyMemory(TableBuffer, Header, Header->Length);
00301         }
00302 
00303         /* Done with this table, keep going */
00304         MmUnmapIoSpace(Header, sizeof(DESCRIPTION_HEADER));
00305     }
00306 
00307     if (Header) MmUnmapIoSpace(Header, sizeof(DESCRIPTION_HEADER));
00308     return NULL;
00309 }
00310 
00311 NTSTATUS
00312 NTAPI
00313 PciGetIrqRoutingTableFromRegistry(OUT PPCI_IRQ_ROUTING_TABLE *PciRoutingTable)
00314 {
00315     BOOLEAN Result;
00316     NTSTATUS Status;
00317     HANDLE KeyHandle, SubKey;
00318     ULONG NumberOfBytes, i, Length;
00319     PKEY_FULL_INFORMATION FullInfo;
00320     PKEY_BASIC_INFORMATION KeyInfo;
00321     PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
00322     UNICODE_STRING ValueName;
00323     struct
00324     {
00325         CM_FULL_RESOURCE_DESCRIPTOR Descriptor;
00326         PCI_IRQ_ROUTING_TABLE Table;
00327     } *Package;
00328 
00329     /* So we know what to free at the end of the body */
00330     Package = NULL;
00331     ValueInfo = NULL;
00332     KeyInfo = NULL;
00333     KeyHandle = NULL;
00334     FullInfo = NULL;
00335     do
00336     {
00337         /* Open the BIOS key */
00338         Result = PciOpenKey(L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\"
00339                             L"System\\MultiFunctionAdapter",
00340                             NULL,
00341                             KEY_QUERY_VALUE,
00342                             &KeyHandle,
00343                             &Status);
00344         if (!Result) break;
00345 
00346         /* Query how much space should be allocated for the key information */
00347         Status = ZwQueryKey(KeyHandle,
00348                             KeyFullInformation,
00349                             NULL,
00350                             sizeof(ULONG),
00351                             &NumberOfBytes);
00352         if (Status != STATUS_BUFFER_TOO_SMALL) break;
00353 
00354         /* Allocate the space required */
00355         Status = STATUS_INSUFFICIENT_RESOURCES;
00356         FullInfo = ExAllocatePoolWithTag(PagedPool, NumberOfBytes, PCI_POOL_TAG);
00357         if ( !FullInfo ) break;
00358 
00359         /* Now query the key information that's needed */
00360         Status = ZwQueryKey(KeyHandle,
00361                             KeyFullInformation,
00362                             FullInfo,
00363                             NumberOfBytes,
00364                             &NumberOfBytes);
00365         if (!NT_SUCCESS(Status)) break;
00366 
00367         /* Allocate enough space to hold the value information plus the name */
00368         Status = STATUS_INSUFFICIENT_RESOURCES;
00369         Length = FullInfo->MaxNameLen + 26;
00370         KeyInfo = ExAllocatePoolWithTag(PagedPool, Length, PCI_POOL_TAG);
00371         if (!KeyInfo) break;
00372 
00373         /* Allocate the value information and name we expect to find */
00374         ValueInfo = ExAllocatePoolWithTag(PagedPool,
00375                                           sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
00376                                           sizeof(L"PCI BIOS"),
00377                                           PCI_POOL_TAG);
00378         if (!ValueInfo) break;
00379 
00380         /* Loop each sub-key */
00381         i = 0;
00382         while (TRUE)
00383         {
00384             /* Query each sub-key */
00385             Status = ZwEnumerateKey(KeyHandle,
00386                                     i++,
00387                                     KeyBasicInformation,
00388                                     KeyInfo,
00389                                     Length,
00390                                     &NumberOfBytes);
00391             if (Status == STATUS_NO_MORE_ENTRIES) break;
00392 
00393             /* Null-terminate the keyname, because the kernel does not */
00394             KeyInfo->Name[KeyInfo->NameLength / sizeof(WCHAR)] = UNICODE_NULL;
00395 
00396             /* Open this subkey */
00397             Result = PciOpenKey(KeyInfo->Name,
00398                                 KeyHandle,
00399                                 KEY_QUERY_VALUE,
00400                                 &SubKey,
00401                                 &Status);
00402             if (Result)
00403             {
00404                 /* Query the identifier value for this subkey */
00405                 RtlInitUnicodeString(&ValueName, L"Identifier");
00406                 Status = ZwQueryValueKey(SubKey,
00407                                          &ValueName,
00408                                          KeyValuePartialInformation,
00409                                          ValueInfo,
00410                                          sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
00411                                          sizeof(L"PCI BIOS"),
00412                                          &NumberOfBytes);
00413                 if (NT_SUCCESS(Status))
00414                 {
00415                     /* Check if this is the PCI BIOS subkey */
00416                     if (!wcsncmp((PWCHAR)ValueInfo->Data,
00417                                  L"PCI BIOS",
00418                                  ValueInfo->DataLength))
00419                     {
00420                         /* It is, proceed to query the PCI IRQ routing table */
00421                         Status = PciGetRegistryValue(L"Configuration Data",
00422                                                      L"RealModeIrqRoutingTable"
00423                                                      L"\\0",
00424                                                      SubKey,
00425                                                      REG_FULL_RESOURCE_DESCRIPTOR,
00426                                                      (PVOID*)&Package,
00427                                                      &NumberOfBytes);
00428                         ZwClose(SubKey);
00429                         break;
00430                     }
00431                 }
00432 
00433                 /* Close the subkey and try the next one */
00434                 ZwClose(SubKey);
00435             }
00436         }
00437 
00438         /* Check if we got here because the routing table was found */
00439         if (!NT_SUCCESS(Status)) break;
00440 
00441         /* Check if a descriptor was found */
00442         if (!Package) break;
00443 
00444         /* Make sure the buffer is large enough to hold the table */
00445         if ((NumberOfBytes < sizeof(*Package)) ||
00446             (Package->Table.TableSize >
00447              (NumberOfBytes - sizeof(CM_FULL_RESOURCE_DESCRIPTOR))))
00448         {
00449             /* Invalid package size */
00450             Status = STATUS_UNSUCCESSFUL;
00451             break;
00452         }
00453 
00454         /* Allocate space for the table */
00455         Status = STATUS_INSUFFICIENT_RESOURCES;
00456         *PciRoutingTable = ExAllocatePoolWithTag(PagedPool,
00457                                                  NumberOfBytes,
00458                                                  PCI_POOL_TAG);
00459         if (!*PciRoutingTable) break;
00460 
00461         /* Copy the registry data */
00462         RtlCopyMemory(*PciRoutingTable,
00463                       &Package->Table,
00464                       NumberOfBytes - sizeof(CM_FULL_RESOURCE_DESCRIPTOR));
00465         Status = STATUS_SUCCESS;
00466     } while (FALSE);
00467 
00468     /* Close any opened keys, free temporary allocations, and return status */
00469     if (Package) ExFreePoolWithTag(Package, 0);
00470     if (ValueInfo) ExFreePoolWithTag(ValueInfo, 0);
00471     if (KeyInfo) ExFreePoolWithTag(KeyInfo, 0);
00472     if (FullInfo) ExFreePoolWithTag(FullInfo, 0);
00473     if (KeyHandle) ZwClose(KeyHandle);
00474     return Status;
00475 }
00476 
00477 NTSTATUS
00478 NTAPI
00479 PciBuildHackTable(IN HANDLE KeyHandle)
00480 {
00481     PKEY_FULL_INFORMATION FullInfo;
00482     ULONG i, HackCount;
00483     PKEY_VALUE_FULL_INFORMATION ValueInfo;
00484     PPCI_HACK_ENTRY Entry;
00485     NTSTATUS Status;
00486     ULONG NameLength, ResultLength;
00487     ULONGLONG HackFlags;
00488 
00489     /* So we know what to free at the end of the body */
00490     FullInfo = NULL;
00491     ValueInfo = NULL;
00492     do
00493     {
00494         /* Query the size required for full key information */
00495         Status = ZwQueryKey(KeyHandle,
00496                             KeyFullInformation,
00497                             NULL,
00498                             0,
00499                             &ResultLength);
00500         if (Status != STATUS_BUFFER_TOO_SMALL) break;
00501 
00502         /* Allocate the space required to hold the full key information */
00503         Status = STATUS_INSUFFICIENT_RESOURCES;
00504         ASSERT(ResultLength > 0);
00505         FullInfo = ExAllocatePoolWithTag(PagedPool, ResultLength, PCI_POOL_TAG);
00506         if (!FullInfo) break;
00507 
00508         /* Go ahead and query the key information */
00509         Status = ZwQueryKey(KeyHandle,
00510                             KeyFullInformation,
00511                             FullInfo,
00512                             ResultLength,
00513                             &ResultLength);
00514         if (!NT_SUCCESS(Status)) break;
00515 
00516         /* The only piece of information that's needed is the count of values */
00517         HackCount = FullInfo->Values;
00518 
00519         /* Free the structure now */
00520         ExFreePoolWithTag(FullInfo, 0);
00521         FullInfo = NULL;
00522 
00523         /* Allocate the hack table, now that the number of entries is known */
00524         Status = STATUS_INSUFFICIENT_RESOURCES;
00525         ResultLength = sizeof(PCI_HACK_ENTRY) * HackCount;
00526         PciHackTable = ExAllocatePoolWithTag(NonPagedPool,
00527                                              ResultLength +
00528                                              sizeof(PCI_HACK_ENTRY),
00529                                              PCI_POOL_TAG);
00530         if (!PciHackTable) break;
00531 
00532         /* Allocate the space needed to hold the full value information */
00533         ValueInfo = ExAllocatePoolWithTag(NonPagedPool,
00534                                           sizeof(KEY_VALUE_FULL_INFORMATION) +
00535                                           PCI_HACK_ENTRY_FULL_SIZE,
00536                                           PCI_POOL_TAG);
00537         if (!PciHackTable) break;
00538 
00539         /* Loop each value in the registry */
00540         Entry = &PciHackTable[0];
00541         for (i = 0; i < HackCount; i++)
00542         {
00543             /* Get the entry for this value */
00544             Entry = &PciHackTable[i];
00545 
00546             /* Query the value in the key */
00547             Status = ZwEnumerateValueKey(KeyHandle,
00548                                          i,
00549                                          KeyValueFullInformation,
00550                                          ValueInfo,
00551                                          sizeof(KEY_VALUE_FULL_INFORMATION) +
00552                                          PCI_HACK_ENTRY_FULL_SIZE,
00553                                          &ResultLength);
00554             if (!NT_SUCCESS(Status))
00555             {
00556                 /* Check why the call failed */
00557                 if ((Status != STATUS_BUFFER_OVERFLOW) &&
00558                     (Status != STATUS_BUFFER_TOO_SMALL))
00559                 {
00560                     /* The call failed due to an unknown error, bail out */
00561                     break;
00562                 }
00563 
00564                 /* The data seems to mismatch, try the next key in the list */
00565                 continue;
00566             }
00567 
00568             /* Check if the value data matches what's expected */
00569             if ((ValueInfo->Type != REG_BINARY) ||
00570                 (ValueInfo->DataLength != sizeof(ULONGLONG)))
00571             {
00572                 /* It doesn't, try the next key in the list */
00573                 continue;
00574             }
00575 
00576             /* Read the actual hack flags */
00577             HackFlags = *(PULONGLONG)((ULONG_PTR)ValueInfo +
00578                                       ValueInfo->DataOffset);
00579 
00580             /* Check what kind of errata entry this is, based on the name */
00581             NameLength = ValueInfo->NameLength;
00582             if ((NameLength != PCI_HACK_ENTRY_SIZE) &&
00583                 (NameLength != PCI_HACK_ENTRY_REV_SIZE) &&
00584                 (NameLength != PCI_HACK_ENTRY_SUBSYS_SIZE) &&
00585                 (NameLength != PCI_HACK_ENTRY_FULL_SIZE))
00586             {
00587                 /* It's an invalid entry, skip it */
00588                 DPRINT1("Skipping hack entry with invalid length name\n");
00589                 continue;
00590             }
00591 
00592             /* Initialize the entry */
00593             RtlZeroMemory(Entry, sizeof(PCI_HACK_ENTRY));
00594 
00595             /* Get the vendor and device data */
00596             if (!(PciStringToUSHORT(ValueInfo->Name, &Entry->VendorID)) ||
00597                 !(PciStringToUSHORT(&ValueInfo->Name[4], &Entry->DeviceID)))
00598             {
00599                 /* This failed, try the next entry */
00600                 continue;
00601             }
00602 
00603             /* Check if the entry contains subsystem information */
00604             if ((NameLength == PCI_HACK_ENTRY_SUBSYS_SIZE) ||
00605                 (NameLength == PCI_HACK_ENTRY_FULL_SIZE))
00606             {
00607                 /* Get the data */
00608                 if (!(PciStringToUSHORT(&ValueInfo->Name[8],
00609                                         &Entry->SubVendorID)) ||
00610                     !(PciStringToUSHORT(&ValueInfo->Name[12],
00611                                         &Entry->SubSystemID)))
00612                   {
00613                       /* This failed, try the next entry */
00614                       continue;
00615                   }
00616 
00617                   /* Save the fact this entry has finer controls */
00618                   Entry->Flags |= PCI_HACK_HAS_SUBSYSTEM_INFO;
00619              }
00620 
00621              /* Check if the entry contains revision information */
00622              if ((NameLength == PCI_HACK_ENTRY_REV_SIZE) ||
00623                  (NameLength == PCI_HACK_ENTRY_FULL_SIZE))
00624              {
00625                  /* Get the data */
00626                  if (!PciStringToUSHORT(&ValueInfo->Name[16],
00627                                         &Entry->RevisionID))
00628                  {
00629                      /* This failed, try the next entry */
00630                      continue;
00631                  }
00632 
00633                  /* Save the fact this entry has finer controls */
00634                  Entry->Flags |= PCI_HACK_HAS_REVISION_INFO;
00635              }
00636 
00637             /* Only the last entry should have this set */
00638             ASSERT(Entry->VendorID != PCI_INVALID_VENDORID);
00639 
00640             /* Save the actual hack flags */
00641             Entry->HackFlags = HackFlags;
00642 
00643             /* Print out for the debugger's sake */
00644 #ifdef HACK_DEBUG
00645             DPRINT1("Adding Hack entry for Vendor:0x%04x Device:0x%04x ",
00646                     Entry->VendorID, Entry->DeviceID);
00647             if (Entry->Flags & PCI_HACK_HAS_SUBSYSTEM_INFO)
00648                 DbgPrint("SybSys:0x%04x SubVendor:0x%04x ",
00649                          Entry->SubSystemID, Entry->SubVendorID);
00650             if (Entry->Flags & PCI_HACK_HAS_REVISION_INFO)
00651                 DbgPrint("Revision:0x%02x", Entry->RevisionID);
00652             DbgPrint(" = 0x%I64x\n", Entry->HackFlags);
00653 #endif
00654         }
00655 
00656         /* Bail out in case of failure */
00657         if (!NT_SUCCESS(Status)) break;
00658 
00659         /* Terminate the table with an invalid entry */
00660         ASSERT(Entry < (PciHackTable + HackCount + 1));
00661         Entry->VendorID = PCI_INVALID_VENDORID;
00662 
00663         /* Success path, free the temporary registry data */
00664         ExFreePoolWithTag(ValueInfo, 0);
00665         return STATUS_SUCCESS;
00666     } while (TRUE);
00667 
00668     /* Failure path, free temporary allocations and return failure code */
00669     ASSERT(!NT_SUCCESS(Status));
00670     if (FullInfo) ExFreePool(FullInfo);
00671     if (ValueInfo) ExFreePool(ValueInfo);
00672     if (PciHackTable) ExFreePool(PciHackTable);
00673     return Status;
00674 }
00675 
00676 NTSTATUS
00677 NTAPI
00678 PciGetDebugPorts(IN HANDLE DebugKey)
00679 {
00680     /* This function is not yet implemented */
00681     UNIMPLEMENTED;
00682     while (TRUE);
00683     return STATUS_SUCCESS;
00684 }
00685 
00686 VOID
00687 NTAPI
00688 PciDriverUnload(IN PDRIVER_OBJECT DriverObject)
00689 {
00690     /* This function is not yet implemented */
00691     DPRINT1("PCI: Unload\n");
00692     UNIMPLEMENTED;
00693     while (TRUE);
00694 }
00695 
00696 NTSTATUS
00697 NTAPI
00698 DriverEntry(IN PDRIVER_OBJECT DriverObject,
00699             IN PUNICODE_STRING RegistryPath)
00700 {
00701     HANDLE KeyHandle, ParametersKey, DebugKey, ControlSetKey;
00702     BOOLEAN Result;
00703     OBJECT_ATTRIBUTES ObjectAttributes;
00704     ULONG ResultLength;
00705     PULONG Value;
00706     PWCHAR StartOptions;
00707     UNICODE_STRING OptionString, PciLockString;
00708     NTSTATUS Status;
00709     DPRINT1("PCI: DriverEntry!\n");
00710 
00711     /* Setup initial loop variables */
00712     KeyHandle = NULL;
00713     ParametersKey = NULL;
00714     DebugKey = NULL;
00715     ControlSetKey = NULL;
00716     do
00717     {
00718         /* Remember our object so we can get it to it later */
00719         PciDriverObject = DriverObject;
00720 
00721         /* Setup the IRP dispatcher */
00722         DriverObject->MajorFunction[IRP_MJ_POWER] = PciDispatchIrp;
00723         DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PciDispatchIrp;
00724         DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = PciDispatchIrp;
00725         DriverObject->MajorFunction[IRP_MJ_PNP] = PciDispatchIrp;
00726         DriverObject->DriverUnload = PciDriverUnload;
00727 
00728         /* This is how we'll detect a new PCI bus */
00729         DriverObject->DriverExtension->AddDevice = PciAddDevice;
00730 
00731         /* Open the PCI key */
00732         InitializeObjectAttributes(&ObjectAttributes,
00733                                    RegistryPath,
00734                                    OBJ_CASE_INSENSITIVE,
00735                                    NULL,
00736                                    NULL);
00737         Status = ZwOpenKey(&KeyHandle, KEY_QUERY_VALUE, &ObjectAttributes);
00738         if (!NT_SUCCESS(Status)) break;
00739 
00740         /* Open the Parameters subkey */
00741         Result = PciOpenKey(L"Parameters",
00742                             KeyHandle,
00743                             KEY_QUERY_VALUE,
00744                             &ParametersKey,
00745                             &Status);
00746         //if (!Result) break;
00747 
00748         /* Build the list of all known PCI erratas */
00749         Status = PciBuildHackTable(ParametersKey);
00750         //if (!NT_SUCCESS(Status)) break;
00751 
00752         /* Open the debug key, if it exists */
00753         Result = PciOpenKey(L"Debug",
00754                             KeyHandle,
00755                             KEY_QUERY_VALUE,
00756                             &DebugKey,
00757                             &Status);
00758         if (Result)
00759         {
00760             /* There are PCI debug devices, go discover them */
00761             Status = PciGetDebugPorts(DebugKey);
00762             if (!NT_SUCCESS(Status)) break;
00763         }
00764 
00765         /* Initialize the synchronization locks */
00766         KeInitializeEvent(&PciGlobalLock, SynchronizationEvent, TRUE);
00767         KeInitializeEvent(&PciBusLock, SynchronizationEvent, TRUE);
00768         KeInitializeEvent(&PciLegacyDescriptionLock, SynchronizationEvent, TRUE);
00769 
00770         /* Open the control set key */
00771         Result = PciOpenKey(L"\\Registry\\Machine\\System\\CurrentControlSet",
00772                             NULL,
00773                             KEY_QUERY_VALUE,
00774                             &ControlSetKey,
00775                             &Status);
00776         if (!Result) break;
00777 
00778         /* Read the command line */
00779         Status = PciGetRegistryValue(L"SystemStartOptions",
00780                                      L"Control",
00781                                      ControlSetKey,
00782                                      REG_SZ,
00783                                      (PVOID*)&StartOptions,
00784                                      &ResultLength);
00785         if (NT_SUCCESS(Status))
00786         {
00787             /* Initialize the command-line as a string */
00788             OptionString.Buffer = StartOptions;
00789             OptionString.MaximumLength = OptionString.Length = ResultLength;
00790 
00791             /* Check if the command-line has the PCILOCK argument */
00792             RtlInitUnicodeString(&PciLockString, L"PCILOCK");
00793             if (PciUnicodeStringStrStr(&OptionString, &PciLockString, TRUE))
00794             {
00795                 /* The PCI Bus driver will keep the BIOS-assigned resources */
00796                 PciLockDeviceResources = TRUE;
00797             }
00798 
00799             /* This data isn't needed anymore */
00800             ExFreePoolWithTag(StartOptions, 0);
00801         }
00802 
00803         /* The PCILOCK feature can also be enabled per-system in the registry */
00804         Status = PciGetRegistryValue(L"PCILock",
00805                                      L"Control\\BiosInfo\\PCI",
00806                                      ControlSetKey,
00807                                      REG_DWORD,
00808                                      (PVOID*)&Value,
00809                                      &ResultLength);
00810         if (NT_SUCCESS(Status))
00811         {
00812             /* Read the value it's been set to. This overrides /PCILOCK */
00813             if (ResultLength == sizeof(ULONG)) PciLockDeviceResources = *Value;
00814             ExFreePoolWithTag(Value, 0);
00815         }
00816 
00817         /* The system can have global PCI erratas in the registry */
00818         Status = PciGetRegistryValue(L"HackFlags",
00819                                      L"Control\\PnP\\PCI",
00820                                      ControlSetKey,
00821                                      REG_DWORD,
00822                                      (PVOID*)&Value,
00823                                      &ResultLength);
00824         if (NT_SUCCESS(Status))
00825         {
00826             /* Read them in */
00827             if (ResultLength == sizeof(ULONG)) PciSystemWideHackFlags = *Value;
00828             ExFreePoolWithTag(Value, 0);
00829         }
00830 
00831         /* Check if the system should allow native ATA support */
00832         Status = PciGetRegistryValue(L"EnableNativeModeATA",
00833                                      L"Control\\PnP\\PCI",
00834                                      ControlSetKey,
00835                                      REG_DWORD,
00836                                      (PVOID*)&Value,
00837                                      &ResultLength);
00838         if (NT_SUCCESS(Status))
00839         {
00840             /* This key is typically set by drivers, but users can force it */
00841             if (ResultLength == sizeof(ULONG)) PciEnableNativeModeATA = *Value;
00842             ExFreePoolWithTag(Value, 0);
00843         }
00844 
00845         /* Build the range lists for all the excluded resource areas */
00846         Status = PciBuildDefaultExclusionLists();
00847         if (!NT_SUCCESS(Status)) break;
00848 
00849         /* Read the PCI IRQ Routing Table that the loader put in the registry */
00850         PciGetIrqRoutingTableFromRegistry(&PciIrqRoutingTable);
00851 
00852         /* Take over the HAL's default PCI Bus Handler routines */
00853         PciHookHal();
00854 
00855         /* Initialize verification of PCI BIOS and devices, if requested */
00856         PciVerifierInit(DriverObject);
00857 
00858         /* Check if this is a Datacenter SKU, which impacts IRQ alignment */
00859         PciRunningDatacenter = PciIsDatacenter();
00860         if (PciRunningDatacenter) DPRINT1("PCI running on datacenter build\n");
00861 
00862         /* Check if the system has an ACPI Hardware Watchdog Timer */
00863         //WdTable = PciGetAcpiTable(WDRT_SIGNATURE);
00864         Status = STATUS_SUCCESS;
00865     } while (FALSE);
00866 
00867     /* Close all opened keys, return driver status to PnP Manager */
00868     if (KeyHandle) ZwClose(KeyHandle);
00869     if (ControlSetKey) ZwClose(ControlSetKey);
00870     if (ParametersKey) ZwClose(ParametersKey);
00871     if (DebugKey) ZwClose(DebugKey);
00872     return Status;
00873 }
00874 
00875 /* EOF */

Generated on Sat May 26 2012 04:22:06 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.