/*++ Copyright (c) 1991 Microsoft Corporation Module Name: iousage.c Abstract: Author: Ken Reneris (kenr) Environment: Kernel mode only. Revision History: Added to Alpha (Avanti Hals) (Sameer Dekate) 5-4-94 --*/ #include "halp.h" #include "iousage.h" // // Define constants for system IDTs // #define MAXIMUM_IDTVECTOR 0xff #define MAXIMUM_PRIMARY_VECTOR 0xff #define PRIMARY_VECTOR_BASE 0x30 // 0-2f are x86 trap vectors // // Array to remember hal's IDT usage // KAFFINITY HalpActiveProcessors; // // From usage.c // ADDRESS_USAGE *HalpAddressUsageList; // // IDT vector usage info // IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR]; VOID HalpGetResourceSortValue ( IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, OUT PULONG sortscale, OUT PLARGE_INTEGER sortvalue ); #ifdef ALLOC_PRAGMA #pragma alloc_text(INIT,HalpEnableInterruptHandler) #pragma alloc_text(INIT,HalpRegisterVector) #pragma alloc_text(INIT,HalpGetResourceSortValue) #pragma alloc_text(INIT,HalpReportResourceUsage) #endif VOID HalpEnableInterruptHandler ( IN UCHAR ReportFlags, IN ULONG BusInterruptVector, IN ULONG SystemInterruptVector, IN KIRQL SystemIrql, IN VOID (*HalInterruptServiceRoutine)(VOID), IN KINTERRUPT_MODE InterruptMode ) /*++ Routine Description: This function connects & registers an IDT vectors usage by the HAL. Arguments: Return Value: --*/ { // // Remember which vector the hal is connecting so it can be reported // later on // HalpRegisterVector (ReportFlags, BusInterruptVector, SystemInterruptVector, SystemIrql); // // Connect the IDT and enable the vector now // #if 0 KiSetHandlerAddressToIDT(SystemInterruptVector, HalInterruptServiceRoutine); #endif //0 HalEnableSystemInterrupt(SystemInterruptVector, SystemIrql, InterruptMode); } VOID HalpRegisterVector ( IN UCHAR ReportFlags, IN ULONG BusInterruptVector, IN ULONG SystemInterruptVector, IN KIRQL SystemIrql ) /*++ Routine Description: This registers an IDT vectors usage by the HAL. Arguments: Return Value: --*/ { #if DBG // There are only 0ff IDT entries... ASSERT (SystemInterruptVector <= MAXIMUM_IDTVECTOR && BusInterruptVector <= MAXIMUM_IDTVECTOR); #endif // // Remember which vector the hal is connecting so it can be reported // later on // HalpIDTUsage[SystemInterruptVector].Flags = ReportFlags; HalpIDTUsage[SystemInterruptVector].Irql = SystemIrql; HalpIDTUsage[SystemInterruptVector].BusReleativeVector = (UCHAR) BusInterruptVector; } VOID HalpGetResourceSortValue ( IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, OUT PULONG sortscale, OUT PLARGE_INTEGER sortvalue ) /*++ Routine Description: Used by HalpReportResourceUsage in order to properly sort partial_resource_descriptors. Arguments: pRCurLoc - resource descriptor Return Value: sortscale - scaling of resource descriptor for sorting sortvalue - value to sort on --*/ { switch (pRCurLoc->Type) { case CmResourceTypeInterrupt: *sortscale = 0; sortvalue->QuadPart = pRCurLoc->u.Interrupt.Level; break; case CmResourceTypePort: *sortscale = 1; *sortvalue = pRCurLoc->u.Port.Start; break; case CmResourceTypeMemory: *sortscale = 2; *sortvalue = pRCurLoc->u.Memory.Start; break; default: *sortscale = 4; sortvalue->QuadPart = 0; break; } } VOID HalpReportResourceUsage ( IN PUNICODE_STRING HalName, IN INTERFACE_TYPE DeviceInterfaceToUse ) /*++ Routine Description: Arguments: Return Value: --*/ { PCM_RESOURCE_LIST RawResourceList, TranslatedResourceList; PCM_FULL_RESOURCE_DESCRIPTOR pRFullDesc, pTFullDesc; PCM_PARTIAL_RESOURCE_LIST pRPartList, pTPartList; PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, pTCurLoc; PCM_PARTIAL_RESOURCE_DESCRIPTOR pRSortLoc, pTSortLoc; CM_PARTIAL_RESOURCE_DESCRIPTOR RPartialDesc, TPartialDesc; ULONG i, j, k, ListSize, Count; ULONG curscale, sortscale; UCHAR pass, reporton; INTERFACE_TYPE interfacetype; ULONG CurrentIDT, CurrentElement; ADDRESS_USAGE *CurrentAddress; LARGE_INTEGER curvalue, sortvalue; PHYSICAL_ADDRESS TempAddress; // // Allocate some space to build the resource structure // RawResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2); TranslatedResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2); // This functions assumes unset fields are zero RtlZeroMemory (RawResourceList, PAGE_SIZE*2); RtlZeroMemory (TranslatedResourceList, PAGE_SIZE*2); // // Initialize the lists // RawResourceList->List[0].InterfaceType = (INTERFACE_TYPE) -1; pRFullDesc = RawResourceList->List; pRCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) RawResourceList->List; pTCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) TranslatedResourceList->List; // // Make sure all vectors 00-2f are reserved // 00-1E reserved by Intel // 1F reserved by Intel for APIC (apc priority level) // 20-2e reserved by Microsoft // 2f reserved by Microsoft for APIC (dpc priority level) // for(i=0; i < PRIMARY_VECTOR_BASE; i++) { if (!(HalpIDTUsage[i].Flags & IDTOwned)) { HalpIDTUsage[i].Flags = InternalUsage; HalpIDTUsage[i].BusReleativeVector = (UCHAR) i; } } for(pass=0; pass < 3; pass++) { switch(pass) { case 0: { #if DBG DbgPrint("Device LIST...\n"); #endif // DBG // // First pass - build resource lists for resources reported // reported against device usage. // reporton = DeviceUsage & ~IDTOwned; interfacetype = DeviceInterfaceToUse; break; } case 1: { #if DBG DbgPrint("Internal LIST...\n"); #endif // DBG // // Second pass = build reousce lists for resources reported // as internal usage. // reporton = InternalUsage & ~IDTOwned; interfacetype = Internal; break; } case 2: { #if DBG DbgPrint("PCI LIST...\n"); #endif // DBG // // Third pass = build reousce lists for resources reported // as PCI usage. // reporton = PCIUsage & ~IDTOwned; interfacetype = PCIBus; break; } } CurrentIDT = 0; CurrentElement = 0; CurrentAddress = HalpAddressUsageList; for (; ;) { if (CurrentIDT <= MAXIMUM_IDTVECTOR) { // // Check to see if CurrentIDT needs to be reported // if (!(HalpIDTUsage[CurrentIDT].Flags & reporton)) { // Don't report on this one CurrentIDT++; continue; } // // Report CurrentIDT resource // RPartialDesc.Type = CmResourceTypeInterrupt; RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive; RPartialDesc.Flags = HalpIDTUsage[CurrentIDT].Flags & InterruptLatched ? CM_RESOURCE_INTERRUPT_LATCHED : CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; RPartialDesc.u.Interrupt.Vector = HalpIDTUsage[CurrentIDT].BusReleativeVector; RPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].BusReleativeVector; RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors; RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc); TPartialDesc.u.Interrupt.Vector = CurrentIDT; TPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].Irql; CurrentIDT++; } else { // // Check to see if CurrentAddress needs to be reported // if (!CurrentAddress) { break; // No addresses left } if (!(CurrentAddress->Flags & reporton)) { // Don't report on this list CurrentElement = 0; CurrentAddress = CurrentAddress->Next; continue; } if (!CurrentAddress->Element[CurrentElement].Length) { // End of current list, go to next list CurrentElement = 0; CurrentAddress = CurrentAddress->Next; continue; } // // Report CurrentAddress // RPartialDesc.Type = (UCHAR) CurrentAddress->Type; RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive; if (RPartialDesc.Type == CmResourceTypePort) { i = 1; // address space port RPartialDesc.Flags = CM_RESOURCE_PORT_IO; } else { i = 0; // address space memory RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE; } // Notice: assuming u.Memory and u.Port have the same layout RPartialDesc.u.Memory.Start.HighPart = 0; RPartialDesc.u.Memory.Start.LowPart = CurrentAddress->Element[CurrentElement].Start; RPartialDesc.u.Memory.Length = CurrentAddress->Element[CurrentElement].Length; #if DBG DbgPrint("Start=0x%x Lenght=0x%x\n", RPartialDesc.u.Memory.Start.LowPart, RPartialDesc.u.Memory.Length); #endif // DBG // translated address = Raw address RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc); HalTranslateBusAddress ( interfacetype, // device bus or internal 0, // bus number RPartialDesc.u.Memory.Start, // source address &i, // address space &TempAddress ); // aligned translated address TPartialDesc.u.Memory.Start = TempAddress; // TPartialDesc is pack(4) #if DBG DbgPrint("TRANSLATED ADDRESS Start=0x%x Lenght=0x%x\n", TPartialDesc.u.Memory.Start.LowPart, TPartialDesc.u.Memory.Length); #endif // DBG if (RPartialDesc.Type == CmResourceTypePort && i == 0) { TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY; } CurrentElement++; } // // Include the current resource in the HALs list // if (pRFullDesc->InterfaceType != interfacetype) { // // Interface type changed, add another full section // RawResourceList->Count++; TranslatedResourceList->Count++; pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc; pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc; pRFullDesc->InterfaceType = interfacetype; pTFullDesc->InterfaceType = interfacetype; pRPartList = &pRFullDesc->PartialResourceList; pTPartList = &pTFullDesc->PartialResourceList; // // Bump current location pointers up // pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors; pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors; } pRPartList->Count++; pTPartList->Count++; RtlCopyMemory (pRCurLoc, &RPartialDesc, sizeof RPartialDesc); RtlCopyMemory (pTCurLoc, &TPartialDesc, sizeof TPartialDesc); pRCurLoc++; pTCurLoc++; } } ListSize = (ULONG) ( ((PUCHAR) pRCurLoc) - ((PUCHAR) RawResourceList) ); // // The HAL's resource usage structures have been built // Sort the partial lists based on the Raw resource values // pRFullDesc = RawResourceList->List; pTFullDesc = TranslatedResourceList->List; for (i=0; i < RawResourceList->Count; i++) { pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors; pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors; Count = pRFullDesc->PartialResourceList.Count; for (j=0; j < Count; j++) { HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue); pRSortLoc = pRCurLoc; pTSortLoc = pTCurLoc; for (k=j; k < Count; k++) { HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue); if (sortscale < curscale || (sortscale == curscale && (sortvalue.QuadPart < curvalue.QuadPart)) ) { // // Swap the elements.. // RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc); RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc); RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc); // swap translated descriptor as well RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc); RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc); RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc); // get new curscale & curvalue HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue); } pRSortLoc++; pTSortLoc++; } pRCurLoc++; pTCurLoc++; } pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc; pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc; } // // Inform the IO system of our resources.. // IoReportHalResourceUsage ( HalName, RawResourceList, TranslatedResourceList, ListSize ); ExFreePool (RawResourceList); ExFreePool (TranslatedResourceList); }