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

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

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