Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygeninit.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
1.7.6.1
|