diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/nthals/halalpha/eisaprof.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/ntos/nthals/halalpha/eisaprof.c')
-rw-r--r-- | private/ntos/nthals/halalpha/eisaprof.c | 517 |
1 files changed, 517 insertions, 0 deletions
diff --git a/private/ntos/nthals/halalpha/eisaprof.c b/private/ntos/nthals/halalpha/eisaprof.c new file mode 100644 index 000000000..71350f4f6 --- /dev/null +++ b/private/ntos/nthals/halalpha/eisaprof.c @@ -0,0 +1,517 @@ +/*++ + +Copyright (c) 1992, 1993 Digital Equipment Corporation + +Module Name: + + eisaprof.c + +Abstract: + + This module handles the Profile Counter and all Profile counter functions + for the standard EISA interval timer. + +Author: + + Jeff McLeman (mcleman) 05-June-1992 + +Environment: + + Kernel mode + +Revision History: + + + Rod Gamache [DEC] 9-Mar-1993 + Fix profile clock. + + +--*/ + +#include "halp.h" +#include "eisa.h" +#include "halprof.h" + +// +// Define global data. +// + +// +// Values used for Profile Clock +// + +// Convert the interval to rollover count for 8254 timer. Since +// the 8254 counts down a 16 bit value at the clock rate of 1.193 MHZ, +// the computation is: +// +// RolloverCount = (Interval * 0.0000001) * (1193 * 1000000) +// = Interval * .1193 +// = Interval * 1193 / 10000 + +#define PROFILE_INTERVAL 1193 +#define PROFILE_INTERVALS_PER_100NS 10000/1193 +#define MIN_PROFILE_TICKS 4 +#define MAX_PROFILE_TICKS 0x10000 // 16 bit counter (zero is max) + +// +// Since the profile timer interrupts at a frequency of 1.193 MHZ, we +// have .1193 intervals each 100ns. So we need a more reasonable value. +// If we compute the timer based on 1600ns intervals, we get 16 * .1193 or +// about 1.9 ticks per 16 intervals. +// +// We round this to 2 ticks per 1600ns intervals. +// + +#define PROFILE_TIMER_1600NS_TICKS 2 + +// +// Default Profile Interval to be about 1ms. +// + +ULONG HalpProfileInterval = PROFILE_TIMER_1600NS_TICKS * PROFILE_INTERVALS_PER_100NS * 10000 / 16; // ~1ms + +// +// Default Number of Profile Clock Ticks per sample +// + +ULONG HalpNumberOfTicks = 1; + +// +// Define the profile interrupt object. +// + +PKINTERRUPT HalpProfileInterruptObject; + +// +// Declare profile interrupt handler. +// + +BOOLEAN +HalpProfileInterrupt( + PKSERVICE_ROUTINE InterruptRoutine, + PVOID ServiceContext, + PKTRAP_FRAME TrapFrame + ); + +// +// Function prototypes. +// + +BOOLEAN +HalQueryProfileInterval( + IN KPROFILE_SOURCE Source + ); + +NTSTATUS +HalSetProfileSourceInterval( + IN KPROFILE_SOURCE ProfileSource, + IN OUT ULONG *Interval + ); + +// +// Function definitions. +// + + +NTSTATUS +HalpProfileSourceInformation ( + OUT PVOID Buffer, + IN ULONG BufferLength, + OUT PULONG ReturnedLength + ) +/*++ + +Routine Description: + + Returns the HAL_PROFILE_SOURCE_INFORMATION for this processor. + +Arguments: + + Buffer - output buffer + BufferLength - length of buffer on input + ReturnedLength - The length of data returned + +Return Value: + + STATUS_SUCCESS + STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize + currently needed. + +--*/ +{ + PHAL_PROFILE_SOURCE_INFORMATION SourceInfo; + NTSTATUS Status; + + + if (BufferLength != sizeof(HAL_PROFILE_SOURCE_INFORMATION)) { + Status = STATUS_INFO_LENGTH_MISMATCH; + return Status; + } + + SourceInfo = (PHAL_PROFILE_SOURCE_INFORMATION)Buffer; + SourceInfo->Supported = HalQueryProfileInterval(SourceInfo->Source); + + if (SourceInfo->Supported) { + SourceInfo->Interval = HalpProfileInterval * HalpNumberOfTicks; + } + + Status = STATUS_SUCCESS; + return Status; +} + + +NTSTATUS +HalpProfileSourceInterval ( + OUT PVOID Buffer, + IN ULONG BufferLength + ) +/*++ + +Routine Description: + + Returns the HAL_PROFILE_SOURCE_INTERVAL for this processor. + +Arguments: + + Buffer - output buffer + BufferLength - length of buffer on input + +Return Value: + + STATUS_SUCCESS + STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize + currently needed. + +--*/ +{ + PHAL_PROFILE_SOURCE_INTERVAL Interval; + NTSTATUS Status; + + + if (BufferLength != sizeof(HAL_PROFILE_SOURCE_INTERVAL)) { + Status = STATUS_INFO_LENGTH_MISMATCH; + return Status; + } + + Interval = (PHAL_PROFILE_SOURCE_INTERVAL)Buffer; + Status = HalSetProfileSourceInterval(Interval->Source, + &Interval->Interval); + return Status; +} + + +VOID +HalpInitializeProfiler( + VOID + ) +/*++ + +Routine Description: + + Initialize the profiler by setting initial values and connecting + the profile interrupt. + +Arguments: + + InterfaceType - Supplies the interface type of the bus on which the + profiler will be connected. + + BusNumber - Supplies the number of the bus on which the profiler will + be connected. + + BusInterruptLevel - Supplies the bus interrupt level to connect the + profile interrupt. + +Return Value: + + None. + +--*/ +{ + KAFFINITY Affinity; + KIRQL Irql; + ULONG Vector; + + // + // Get the interrupt vector and synchronization Irql. + // + + Vector = HalGetInterruptVector( Eisa, + 0, + 0, + 0, + &Irql, + &Affinity ); + + IoConnectInterrupt( &HalpProfileInterruptObject, + (PKSERVICE_ROUTINE)HalpProfileInterrupt, + NULL, + NULL, + Vector, + Irql, + Irql, + Latched, + FALSE, + Affinity, + FALSE ); + + return; +} + + +BOOLEAN +HalpProfileInterrupt( + PKSERVICE_ROUTINE InterruptRoutine, + PVOID ServiceContext, + PKTRAP_FRAME TrapFrame + ) +/*++ + +Routine Description: + + This routine is entered as a result of an interrupt generated by + the profile timer. Its function is to acknowlege the interrupt and + transfer control to the standard system routine to update the + system profile time. + +Arguments: + + InterruptRoutine - not used. + + ServiceContext - not used. + + TrapFrame - Supplies a pointer to the trap frame for the profile interrupt. + +Returned Value: + + None + +--*/ +{ + + // + // See if profiling is active + // + + if ( HAL_PCR->ProfileCount ) { + + // + // Check to see if the interval has expired + // If it has then call the kernel routine for profile + // and reset the count, else return. + + + if ( !(--HAL_PCR->ProfileCount) ) { + + KeProfileInterrupt( TrapFrame ); + HAL_PCR->ProfileCount = HalpNumberOfTicks; + + } + } + + return TRUE; + +} + + +BOOLEAN +HalQueryProfileInterval( + IN KPROFILE_SOURCE ProfileSource + ) + +/*++ + +Routine Description: + + Given a profile source, returns whether or not that source is + supported. + +Arguments: + + Source - Supplies the profile source + +Return Value: + + TRUE - Profile source is supported + + FALSE - Profile source is not supported + +--*/ + +{ + if (ProfileSource == ProfileTime) + return(TRUE); + else + return(FALSE); +} + + +NTSTATUS +HalSetProfileSourceInterval( + IN KPROFILE_SOURCE ProfileSource, + IN OUT ULONG *Interval + ) + +/*++ + +Routine Description: + + Sets the profile interval for a specified profile source + +Arguments: + + ProfileSource - Supplies the profile source + + Interval - Supplies the specified profile interval + Returns the actual profile interval + +Return Value: + + NTSTATUS + +--*/ + +{ + if (ProfileSource != ProfileTime) + return(STATUS_NOT_IMPLEMENTED); + + // + // Set the interval. + // + + *Interval = HalSetProfileInterval(*Interval); + + // + // We're done. + // + + return(STATUS_SUCCESS); +} + + +ULONG +HalSetProfileInterval ( + IN ULONG Interval + ) + +/*++ + +Routine Description: + + This routine sets the profile interrupt interval. + +Arguments: + + Interval - Supplies the desired profile interval in 100ns units. + +Return Value: + + The actual profile interval. + +--*/ + +{ + + HalpProfileInterval = (Interval/16) * PROFILE_TIMER_1600NS_TICKS; + + HalpProfileInterval = ( HalpProfileInterval < MIN_PROFILE_TICKS ) ? + MIN_PROFILE_TICKS : HalpProfileInterval; + + return HalpProfileInterval * PROFILE_INTERVALS_PER_100NS; +} + + +VOID +HalStartProfileInterrupt ( + KPROFILE_SOURCE ProfileSource + ) + +/*++ + +Routine Description: + + This routine turns on the profile interrupt. + + N.B. This routine must be called at PROCLK_LEVEL while holding the + profile lock. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + + if (ProfileSource != ProfileTime) + return; + + // + // Assume that we only need 1 clock tick before we collect data + // + + HalpNumberOfTicks = 1; + + if ( HalpProfileInterval > MAX_PROFILE_TICKS ) { + + HalpNumberOfTicks = HalpProfileInterval / (MAX_PROFILE_TICKS / 4); + HalpNumberOfTicks = 4 * HalpNumberOfTicks; + HalpProfileInterval = MAX_PROFILE_TICKS / 4; + + } + + // + // Set current profile count and interval. + // + + HAL_PCR->ProfileCount = HalpNumberOfTicks; + + PIC_PROFILER_ON(HalpProfileInterval); + + return; +} + + +VOID +HalStopProfileInterrupt ( + KPROFILE_SOURCE ProfileSource + ) + +/*++ + +Routine Description: + + This routine turns off the profile interrupt. + + N.B. This routine must be called at PROCLK_LEVEL while holding the + profile lock. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + + if (ProfileSource != ProfileTime) + return; + + // + // Clear the current profile count and turn off the profiler timer. + // + + HAL_PCR->ProfileCount = 0; + + PIC_PROFILER_OFF(); + + return; +} |