Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenusage.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/usage.c 00005 * PURPOSE: HAL Resource Report Routines 00006 * PROGRAMMERS: Stefan Ginsberg (stefan.ginsberg@reactos.org) 00007 */ 00008 00009 /* INCLUDES *******************************************************************/ 00010 00011 #include <hal.h> 00012 #define NDEBUG 00013 #include <debug.h> 00014 00015 /* GLOBALS ********************************************************************/ 00016 00017 BOOLEAN HalpGetInfoFromACPI; 00018 BOOLEAN HalpNMIDumpFlag; 00019 PUCHAR KdComPortInUse; 00020 PADDRESS_USAGE HalpAddressUsageList; 00021 IDTUsageFlags HalpIDTUsageFlags[MAXIMUM_IDTVECTOR+1]; 00022 IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR+1]; 00023 00024 USHORT HalpComPortIrqMapping[5][2] = 00025 { 00026 {0x3F8, 4}, 00027 {0x2F8, 3}, 00028 {0x3E8, 4}, 00029 {0x2E8, 3}, 00030 {0, 0} 00031 }; 00032 00033 ADDRESS_USAGE HalpComIoSpace = 00034 { 00035 NULL, CmResourceTypePort, IDT_INTERNAL, 00036 { 00037 {0x2F8, 0x8}, /* COM 1 */ 00038 {0,0}, 00039 } 00040 }; 00041 00042 ADDRESS_USAGE HalpDefaultIoSpace = 00043 { 00044 NULL, CmResourceTypePort, IDT_INTERNAL, 00045 { 00046 {0x00, 0x20}, /* DMA 1 */ 00047 {0xC0, 0x20}, /* DMA 2 */ 00048 {0x80, 0x10}, /* DMA EPAR */ 00049 {0x20, 0x2}, /* PIC 1 */ 00050 {0xA0, 0x2}, /* PIC 2 */ 00051 {0x40, 0x4}, /* PIT 1 */ 00052 {0x48, 0x4}, /* PIT 2 */ 00053 {0x92, 0x1}, /* System Control Port A */ 00054 {0x70, 0x2}, /* CMOS */ 00055 {0xF0, 0x10}, /* x87 Coprocessor */ 00056 {0xCF8, 0x8}, /* PCI 0 */ 00057 {0,0}, 00058 } 00059 }; 00060 00061 /* FUNCTIONS ******************************************************************/ 00062 00063 #ifndef _MINIHAL_ 00064 VOID 00065 NTAPI 00066 INIT_FUNCTION 00067 HalpGetResourceSortValue(IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor, 00068 OUT PULONG Scale, 00069 OUT PLARGE_INTEGER Value) 00070 { 00071 /* Sorting depends on resource type */ 00072 switch (Descriptor->Type) 00073 { 00074 case CmResourceTypeInterrupt: 00075 00076 /* Interrupt goes by level */ 00077 *Scale = 0; 00078 *Value = RtlConvertUlongToLargeInteger(Descriptor->u.Interrupt.Level); 00079 break; 00080 00081 case CmResourceTypePort: 00082 00083 /* Port goes by port address */ 00084 *Scale = 1; 00085 *Value = Descriptor->u.Port.Start; 00086 break; 00087 00088 case CmResourceTypeMemory: 00089 00090 /* Memory goes by base address */ 00091 *Scale = 2; 00092 *Value = Descriptor->u.Memory.Start; 00093 break; 00094 00095 default: 00096 00097 /* Anything else */ 00098 *Scale = 4; 00099 *Value = RtlConvertUlongToLargeInteger(0); 00100 break; 00101 } 00102 } 00103 00104 VOID 00105 NTAPI 00106 INIT_FUNCTION 00107 HalpBuildPartialFromIdt(IN ULONG Entry, 00108 IN PCM_PARTIAL_RESOURCE_DESCRIPTOR RawDescriptor, 00109 IN PCM_PARTIAL_RESOURCE_DESCRIPTOR TranslatedDescriptor) 00110 { 00111 /* Exclusive interrupt entry */ 00112 RawDescriptor->Type = CmResourceTypeInterrupt; 00113 RawDescriptor->ShareDisposition = CmResourceShareDriverExclusive; 00114 00115 /* Check the interrupt type */ 00116 if (HalpIDTUsageFlags[Entry].Flags & IDT_LATCHED) 00117 { 00118 /* Latched */ 00119 RawDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; 00120 } 00121 else 00122 { 00123 /* Level */ 00124 RawDescriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; 00125 } 00126 00127 /* Get vector and level from IDT usage */ 00128 RawDescriptor->u.Interrupt.Vector = HalpIDTUsage[Entry].BusReleativeVector; 00129 RawDescriptor->u.Interrupt.Level = HalpIDTUsage[Entry].BusReleativeVector; 00130 00131 /* Affinity is all the CPUs */ 00132 RawDescriptor->u.Interrupt.Affinity = HalpActiveProcessors; 00133 00134 /* The translated copy is identical */ 00135 RtlCopyMemory(TranslatedDescriptor, RawDescriptor, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)); 00136 00137 /* But the vector and IRQL must be set correctly */ 00138 TranslatedDescriptor->u.Interrupt.Vector = Entry; 00139 TranslatedDescriptor->u.Interrupt.Level = HalpIDTUsage[Entry].Irql; 00140 } 00141 00142 VOID 00143 NTAPI 00144 INIT_FUNCTION 00145 HalpBuildPartialFromAddress(IN INTERFACE_TYPE Interface, 00146 IN PADDRESS_USAGE CurrentAddress, 00147 IN ULONG Element, 00148 IN PCM_PARTIAL_RESOURCE_DESCRIPTOR RawDescriptor, 00149 IN PCM_PARTIAL_RESOURCE_DESCRIPTOR TranslatedDescriptor) 00150 { 00151 ULONG AddressSpace; 00152 00153 /* Set the type and make it exclusive */ 00154 RawDescriptor->Type = CurrentAddress->Type; 00155 RawDescriptor->ShareDisposition = CmResourceShareDriverExclusive; 00156 00157 /* Check what this is */ 00158 if (RawDescriptor->Type == CmResourceTypePort) 00159 { 00160 /* Write out port data */ 00161 AddressSpace = 1; 00162 RawDescriptor->Flags = CM_RESOURCE_PORT_IO; 00163 RawDescriptor->u.Port.Start.HighPart = 0; 00164 RawDescriptor->u.Port.Start.LowPart = CurrentAddress->Element[Element].Start; 00165 RawDescriptor->u.Port.Length = CurrentAddress->Element[Element].Length; 00166 00167 /* Determine if 16-bit port addresses are allowed */ 00168 RawDescriptor->Flags |= HalpIs16BitPortDecodeSupported(); 00169 } 00170 else 00171 { 00172 /* Write out memory data */ 00173 AddressSpace = 0; 00174 RawDescriptor->Flags = (CurrentAddress->Flags & IDT_READ_ONLY) ? 00175 CM_RESOURCE_MEMORY_READ_ONLY : 00176 CM_RESOURCE_MEMORY_READ_WRITE; 00177 RawDescriptor->u.Memory.Start.HighPart = 0; 00178 RawDescriptor->u.Memory.Start.LowPart = CurrentAddress->Element[Element].Start; 00179 RawDescriptor->u.Memory.Length = CurrentAddress->Element[Element].Length; 00180 } 00181 00182 /* Make an identical copy to begin with */ 00183 RtlCopyMemory(TranslatedDescriptor, RawDescriptor, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)); 00184 00185 /* Check what this is */ 00186 if (RawDescriptor->Type == CmResourceTypePort) 00187 { 00188 /* Translate the port */ 00189 HalTranslateBusAddress(Interface, 00190 0, 00191 RawDescriptor->u.Port.Start, 00192 &AddressSpace, 00193 &TranslatedDescriptor->u.Port.Start); 00194 00195 /* If it turns out this is memory once translated, flag it */ 00196 if (AddressSpace == 0) TranslatedDescriptor->Flags = CM_RESOURCE_PORT_MEMORY; 00197 00198 } 00199 else 00200 { 00201 /* Translate the memory */ 00202 HalTranslateBusAddress(Interface, 00203 0, 00204 RawDescriptor->u.Memory.Start, 00205 &AddressSpace, 00206 &TranslatedDescriptor->u.Memory.Start); 00207 } 00208 } 00209 00210 VOID 00211 NTAPI 00212 INIT_FUNCTION 00213 HalpReportResourceUsage(IN PUNICODE_STRING HalName, 00214 IN INTERFACE_TYPE InterfaceType) 00215 { 00216 PCM_RESOURCE_LIST RawList, TranslatedList; 00217 PCM_FULL_RESOURCE_DESCRIPTOR RawFull, TranslatedFull; 00218 PCM_PARTIAL_RESOURCE_DESCRIPTOR CurrentRaw, CurrentTranslated, SortedRaw, SortedTranslated; 00219 CM_PARTIAL_RESOURCE_DESCRIPTOR RawPartial, TranslatedPartial; 00220 PCM_PARTIAL_RESOURCE_LIST RawPartialList = NULL, TranslatedPartialList = NULL; 00221 INTERFACE_TYPE Interface; 00222 ULONG i, j, k, ListSize, Count, Port, Element, CurrentScale, SortScale, ReportType, FlagMatch; 00223 ADDRESS_USAGE *CurrentAddress; 00224 LARGE_INTEGER CurrentSortValue, SortValue; 00225 DbgPrint("%wZ Detected\n", HalName); 00226 00227 /* Check if KD is using a COM port */ 00228 if (KdComPortInUse) 00229 { 00230 /* Enter it into the I/O space */ 00231 HalpComIoSpace.Element[0].Start = PtrToUlong(KdComPortInUse); 00232 HalpComIoSpace.Next = HalpAddressUsageList; 00233 HalpAddressUsageList = &HalpComIoSpace; 00234 00235 /* Use the debug port table if we have one */ 00236 HalpGetInfoFromACPI = HalpGetDebugPortTable(); 00237 00238 /* Check if we're using ACPI */ 00239 if (!HalpGetInfoFromACPI) 00240 { 00241 /* No, so use our local table */ 00242 for (i = 0, Port = HalpComPortIrqMapping[i][0]; 00243 Port; 00244 i++, Port = HalpComPortIrqMapping[i][0]) 00245 { 00246 /* Is this the port we want? */ 00247 if (Port == (ULONG_PTR)KdComPortInUse) 00248 { 00249 /* Register it */ 00250 HalpRegisterVector(IDT_DEVICE | IDT_LATCHED, 00251 HalpComPortIrqMapping[i][1], 00252 HalpComPortIrqMapping[i][1] + 00253 PRIMARY_VECTOR_BASE, 00254 HIGH_LEVEL); 00255 } 00256 } 00257 } 00258 } 00259 00260 /* On non-ACPI systems, we need to build an address map */ 00261 HalpBuildAddressMap(); 00262 00263 /* Allocate the master raw and translated lists */ 00264 RawList = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE * 2, ' laH'); 00265 TranslatedList = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE * 2, ' laH'); 00266 if (!(RawList) || !(TranslatedList)) 00267 { 00268 /* Bugcheck the system */ 00269 KeBugCheckEx(HAL_MEMORY_ALLOCATION, 00270 4 * PAGE_SIZE, 00271 1, 00272 (ULONG_PTR)__FILE__, 00273 __LINE__); 00274 } 00275 00276 /* Zero out the lists */ 00277 RtlZeroMemory(RawList, PAGE_SIZE * 2); 00278 RtlZeroMemory(TranslatedList, PAGE_SIZE * 2); 00279 00280 /* Set the interface type to begin with */ 00281 RawList->List[0].InterfaceType = InterfaceTypeUndefined; 00282 00283 /* Loop all IDT entries that are not IRQs */ 00284 for (i = 0; i < PRIMARY_VECTOR_BASE; i++) 00285 { 00286 /* Check if the IDT isn't owned */ 00287 if (!(HalpIDTUsageFlags[i].Flags & IDT_REGISTERED)) 00288 { 00289 /* Then register it for internal usage */ 00290 HalpIDTUsageFlags[i].Flags = IDT_INTERNAL; 00291 HalpIDTUsage[i].BusReleativeVector = (UCHAR)i; 00292 } 00293 } 00294 00295 /* Our full raw descriptors start here */ 00296 RawFull = RawList->List; 00297 00298 /* Keep track of the current partial raw and translated descriptors */ 00299 CurrentRaw = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)RawList->List; 00300 CurrentTranslated = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)TranslatedList->List; 00301 00302 /* Do two passes */ 00303 for (ReportType = 0; ReportType < 2; ReportType++) 00304 { 00305 /* Pass 0 is for device usage */ 00306 if (ReportType == 0) 00307 { 00308 FlagMatch = IDT_DEVICE & ~IDT_REGISTERED; 00309 Interface = InterfaceType; 00310 } 00311 else 00312 { 00313 /* Past 1 is for internal HAL usage */ 00314 FlagMatch = IDT_INTERNAL & ~IDT_REGISTERED; 00315 Interface = Internal; 00316 } 00317 00318 /* Reset loop variables */ 00319 i = Element = 0; 00320 00321 /* Start looping our address uage list and interrupts */ 00322 CurrentAddress = HalpAddressUsageList; 00323 while (TRUE) 00324 { 00325 /* Check for valid vector number */ 00326 if (i <= MAXIMUM_IDTVECTOR) 00327 { 00328 /* Check if this entry should be parsed */ 00329 if ((HalpIDTUsageFlags[i].Flags & FlagMatch)) 00330 { 00331 /* Parse it */ 00332 HalpBuildPartialFromIdt(i, &RawPartial, &TranslatedPartial); 00333 i++; 00334 } 00335 else 00336 { 00337 /* Skip this entry */ 00338 i++; 00339 continue; 00340 } 00341 } 00342 else 00343 { 00344 /* This is an address instead */ 00345 if (!CurrentAddress) break; 00346 00347 /* Check if the address should be reported */ 00348 if (!(CurrentAddress->Flags & FlagMatch) || 00349 !(CurrentAddress->Element[Element].Length)) 00350 { 00351 /* Nope, skip it */ 00352 Element = 0; 00353 CurrentAddress = CurrentAddress->Next; 00354 continue; 00355 } 00356 00357 /* Otherwise, parse the entry */ 00358 HalpBuildPartialFromAddress(Interface, 00359 CurrentAddress, 00360 Element, 00361 &RawPartial, 00362 &TranslatedPartial); 00363 Element++; 00364 } 00365 00366 /* Check for interface change */ 00367 if (RawFull->InterfaceType != Interface) 00368 { 00369 /* We need to add another full descriptor */ 00370 RawList->Count++; 00371 TranslatedList->Count++; 00372 00373 /* The full descriptor follows wherever we were */ 00374 RawFull = (PCM_FULL_RESOURCE_DESCRIPTOR)CurrentRaw; 00375 TranslatedFull = (PCM_FULL_RESOURCE_DESCRIPTOR)CurrentTranslated; 00376 00377 /* And it is of this new interface type */ 00378 RawFull->InterfaceType = Interface; 00379 TranslatedFull->InterfaceType = Interface; 00380 00381 /* And its partial descriptors begin here */ 00382 RawPartialList = &RawFull->PartialResourceList; 00383 TranslatedPartialList = &TranslatedFull->PartialResourceList; 00384 00385 /* And our next full descriptor should follow here */ 00386 CurrentRaw = RawFull->PartialResourceList.PartialDescriptors; 00387 CurrentTranslated = TranslatedFull->PartialResourceList.PartialDescriptors; 00388 } 00389 00390 /* We have written a new partial descriptor */ 00391 RawPartialList->Count++; 00392 TranslatedPartialList->Count++; 00393 00394 /* Copy our local descriptors into the actual list */ 00395 RtlCopyMemory(CurrentRaw, &RawPartial, sizeof(RawPartial)); 00396 RtlCopyMemory(CurrentTranslated, &TranslatedPartial, sizeof(TranslatedPartial)); 00397 00398 /* Move to the next partial descriptor */ 00399 CurrentRaw++; 00400 CurrentTranslated++; 00401 } 00402 } 00403 00404 /* Get the final list of the size for the kernel call later */ 00405 ListSize = (ULONG)((ULONG_PTR)CurrentRaw - (ULONG_PTR)RawList); 00406 00407 /* Now reset back to the first full descriptor */ 00408 RawFull = RawList->List; 00409 TranslatedFull = TranslatedList->List; 00410 00411 /* And loop all the full descriptors */ 00412 for (i = 0; i < RawList->Count; i++) 00413 { 00414 /* Get the first partial descriptor in this list */ 00415 CurrentRaw = RawFull->PartialResourceList.PartialDescriptors; 00416 CurrentTranslated = TranslatedFull->PartialResourceList.PartialDescriptors; 00417 00418 /* Get the count of partials in this list */ 00419 Count = RawFull->PartialResourceList.Count; 00420 00421 /* Loop all the partials in this list */ 00422 for (j = 0; j < Count; j++) 00423 { 00424 /* Get the sort value at this point */ 00425 HalpGetResourceSortValue(CurrentRaw, &CurrentScale, &CurrentSortValue); 00426 00427 /* Save the current sort pointer */ 00428 SortedRaw = CurrentRaw; 00429 SortedTranslated = CurrentTranslated; 00430 00431 /* Loop all descriptors starting from this one */ 00432 for (k = j; k < Count; k++) 00433 { 00434 /* Get the sort value at the sort point */ 00435 HalpGetResourceSortValue(SortedRaw, &SortScale, &SortValue); 00436 00437 /* Check if a swap needs to occur */ 00438 if ((SortScale < CurrentScale) || 00439 ((SortScale == CurrentScale) && 00440 (SortValue.QuadPart <= CurrentSortValue.QuadPart))) 00441 { 00442 /* Swap raw partial with the sort location partial */ 00443 RtlCopyMemory(&RawPartial, CurrentRaw, sizeof(RawPartial)); 00444 RtlCopyMemory(CurrentRaw, SortedRaw, sizeof(RawPartial)); 00445 RtlCopyMemory(SortedRaw, &RawPartial, sizeof(RawPartial)); 00446 00447 /* Swap translated partial in the same way */ 00448 RtlCopyMemory(&TranslatedPartial, CurrentTranslated, sizeof(TranslatedPartial)); 00449 RtlCopyMemory(CurrentTranslated, SortedTranslated, sizeof(TranslatedPartial)); 00450 RtlCopyMemory(SortedTranslated, &TranslatedPartial, sizeof(TranslatedPartial)); 00451 00452 /* Update the sort value at this point */ 00453 HalpGetResourceSortValue(CurrentRaw, &CurrentScale, &CurrentSortValue); 00454 } 00455 00456 /* The sort location has been updated */ 00457 SortedRaw++; 00458 SortedTranslated++; 00459 } 00460 00461 /* Move to the next partial */ 00462 CurrentRaw++; 00463 CurrentTranslated++; 00464 } 00465 00466 /* Move to the next full descriptor */ 00467 RawFull = (PCM_FULL_RESOURCE_DESCRIPTOR)CurrentRaw; 00468 TranslatedFull = (PCM_FULL_RESOURCE_DESCRIPTOR)CurrentTranslated; 00469 } 00470 00471 /* Mark this is an ACPI system, if it is */ 00472 HalpMarkAcpiHal(); 00473 00474 /* Tell the kernel about all this */ 00475 IoReportHalResourceUsage(HalName, 00476 RawList, 00477 TranslatedList, 00478 ListSize); 00479 00480 /* Free our lists */ 00481 ExFreePool(RawList); 00482 ExFreePool(TranslatedList); 00483 00484 /* Get the machine's serial number */ 00485 HalpReportSerialNumber(); 00486 } 00487 #endif 00488 00489 VOID 00490 NTAPI 00491 INIT_FUNCTION 00492 HalpRegisterVector(IN UCHAR Flags, 00493 IN ULONG BusVector, 00494 IN ULONG SystemVector, 00495 IN KIRQL Irql) 00496 { 00497 /* Save the vector flags */ 00498 HalpIDTUsageFlags[SystemVector].Flags = Flags; 00499 00500 /* Save the vector data */ 00501 HalpIDTUsage[SystemVector].Irql = Irql; 00502 HalpIDTUsage[SystemVector].BusReleativeVector = (UCHAR)BusVector; 00503 } 00504 00505 #ifndef _MINIHAL_ 00506 VOID 00507 NTAPI 00508 INIT_FUNCTION 00509 HalpEnableInterruptHandler(IN UCHAR Flags, 00510 IN ULONG BusVector, 00511 IN ULONG SystemVector, 00512 IN KIRQL Irql, 00513 IN PVOID Handler, 00514 IN KINTERRUPT_MODE Mode) 00515 { 00516 /* Set the IDT_LATCHED flag for latched interrupts */ 00517 if (Mode == Latched) Flags |= IDT_LATCHED; 00518 00519 /* Register the vector */ 00520 HalpRegisterVector(Flags, BusVector, SystemVector, Irql); 00521 00522 /* Connect the interrupt */ 00523 KeRegisterInterruptHandler(SystemVector, Handler); 00524 00525 /* Enable the interrupt */ 00526 HalEnableSystemInterrupt(SystemVector, Irql, Mode); 00527 } 00528 00529 VOID 00530 NTAPI 00531 INIT_FUNCTION 00532 HalpGetNMICrashFlag(VOID) 00533 { 00534 UNICODE_STRING ValueName; 00535 UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\CrashControl"); 00536 OBJECT_ATTRIBUTES ObjectAttributes; 00537 ULONG ResultLength; 00538 HANDLE Handle; 00539 NTSTATUS Status; 00540 KEY_VALUE_PARTIAL_INFORMATION KeyValueInformation; 00541 00542 /* Set default */ 00543 HalpNMIDumpFlag = 0; 00544 00545 /* Initialize attributes */ 00546 InitializeObjectAttributes(&ObjectAttributes, 00547 &KeyName, 00548 OBJ_CASE_INSENSITIVE, 00549 NULL, 00550 NULL); 00551 00552 /* Open crash key */ 00553 Status = ZwOpenKey(&Handle, KEY_READ, &ObjectAttributes); 00554 if (NT_SUCCESS(Status)) 00555 { 00556 /* Query key value */ 00557 RtlInitUnicodeString(&ValueName, L"NMICrashDump"); 00558 Status = ZwQueryValueKey(Handle, 00559 &ValueName, 00560 KeyValuePartialInformation, 00561 &KeyValueInformation, 00562 sizeof(KeyValueInformation), 00563 &ResultLength); 00564 if (NT_SUCCESS(Status)) 00565 { 00566 /* Check for valid data */ 00567 if (ResultLength == sizeof(KEY_VALUE_PARTIAL_INFORMATION)) 00568 { 00569 /* Read the flag */ 00570 HalpNMIDumpFlag = KeyValueInformation.Data[0]; 00571 } 00572 } 00573 00574 /* We're done */ 00575 ZwClose(Handle); 00576 } 00577 } 00578 #endif 00579 00580 /* EOF */ 00581 Generated on Sat May 26 2012 04:16:25 for ReactOS by
1.7.6.1
|