Example #1
0
NTSTATUS
NTAPI
CmBattQueryTag(IN PCMBATT_DEVICE_EXTENSION DeviceExtension,
               OUT PULONG Tag)
{
    PDEVICE_OBJECT PdoDevice;
    ULONG StaData;
    ULONG NewTag;
    NTSTATUS Status;
    PAGED_CODE();
    if (CmBattDebug & (CMBATT_ACPI_WARNING | CMBATT_GENERIC_INFO))
      DbgPrint("CmBattQueryTag - Tag (%d), Battery %x, Device %d\n",
                *Tag, DeviceExtension, DeviceExtension->DeviceId);
    
    /* Get PDO and clear notification flag */  
    PdoDevice = DeviceExtension->PdoDeviceObject;
    DeviceExtension->NotifySent = 0;
    
    /* Get _STA from PDO (we need the machine status, not the battery status) */
    Status = CmBattGetStaData(PdoDevice, &StaData);
    if (NT_SUCCESS(Status))
    {
        /* Is a battery present? */
        if (StaData & ACPI_STA_BATTERY_PRESENT)
        {
            /* Do we not have a tag yet? */
            if (!DeviceExtension->Tag)
            {
                /* Set the new tag value, reset tags if we reached the maximum */
                NewTag = DeviceExtension->TagData;
                if (DeviceExtension->TagData++ == 0xFFFFFFFF) NewTag = 1;
                DeviceExtension->Tag = NewTag;
                if (CmBattDebug & CMBATT_GENERIC_INFO)
                    DbgPrint("CmBattQueryTag - New Tag: (%d)\n", DeviceExtension->Tag);
                
                /* Reset trip point data */
                DeviceExtension->TripPointOld = 0;
                DeviceExtension->TripPointValue = BATTERY_UNKNOWN_CAPACITY;
                                
                /* Clear AR lock and set new interrupt time */
                InterlockedExchange(&DeviceExtension->ArLockValue, 0);
                DeviceExtension->InterruptTime = KeQueryInterruptTime();
            }
        }
        else
        {
            /* No battery, so no tag */
            DeviceExtension->Tag = 0;
            Status = STATUS_NO_SUCH_DEVICE;
        }
    }
    
    /* Return the tag and status result */
    *Tag = DeviceExtension->Tag;
    if (CmBattDebug & CMBATT_ACPI_WARNING)
      DbgPrint("CmBattQueryTag: Returning Tag: 0x%x, status 0x%x\n", *Tag, Status);
    return Status;
}
Example #2
0
//=============================================================================
STDMETHODIMP CMiniportWaveCyclicStream::GetPosition(
    OUT PULONG                  Position
)
/*++
Routine Description:
  The GetPosition function gets the current position of the DMA read or write
  pointer for the stream. Callers of GetPosition should run at
  IRQL <= DISPATCH_LEVEL.

Arguments:
  Position - Position of the DMA pointer

Return Value:
  NT status code.
--*/
{
    if (m_fDmaActive) {
        // Get the current time
        ULONGLONG CurrentTime = KeQueryInterruptTime();

        // Calculate the time elapsed since the last call to GetPosition() or since the
        // DMA engine started.  Note that the division by 10000 to convert to milliseconds
        // may cause us to lose some of the time, so we will carry the remainder forward 
        // to the next GetPosition() call.
        ULONG TimeElapsedInMS = ((ULONG) (CurrentTime - m_ullDmaTimeStamp + m_ullElapsedTimeCarryForward)) / 10000;

        // Carry forward the remainder of this division so we don't fall behind with our position.
        m_ullElapsedTimeCarryForward = (CurrentTime - m_ullDmaTimeStamp + m_ullElapsedTimeCarryForward) % 10000;

        // Calculate how many bytes in the DMA buffer would have been processed in the elapsed
        // time.  Note that the division by 1000 to convert to milliseconds may cause us to 
        // lose some bytes, so we will carry the remainder forward to the next GetPosition() call.
        ULONG ByteDisplacement = ((m_ulDmaMovementRate * TimeElapsedInMS) + m_ulByteDisplacementCarryForward) / 1000;

        // Carry forward the remainder of this division so we don't fall behind with our position.
        m_ulByteDisplacementCarryForward = ((m_ulDmaMovementRate * TimeElapsedInMS) + m_ulByteDisplacementCarryForward) % 1000;

        // Increment the DMA position by the number of bytes displaced since the last
        // call to GetPosition() and ensure we properly wrap at buffer length.
        m_ulDmaPosition = (m_ulDmaPosition + ByteDisplacement) % m_ulDmaBufferSize;

        // Return the new DMA position
        *Position = m_ulDmaPosition;

        // Update the DMA time stamp for the next call to GetPosition()
        m_ullDmaTimeStamp = CurrentTime;
    } else {
        // DMA is inactive so just return the current DMA position.
        *Position = m_ulDmaPosition;
    }

    return STATUS_SUCCESS;
} // GetPosition
Example #3
0
BOOLEAN
FASTCALL
KiInsertTimerTable(IN PKTIMER Timer,
                   IN ULONG Hand)
{
    LARGE_INTEGER InterruptTime;
    LONGLONG DueTime = Timer->DueTime.QuadPart;
    BOOLEAN Expired = FALSE;
    PLIST_ENTRY ListHead, NextEntry;
    PKTIMER CurrentTimer;
    DPRINT("KiInsertTimerTable(): Timer %p, Hand: %lu\n", Timer, Hand);

    /* Check if the period is zero */
    if (!Timer->Period) Timer->Header.SignalState = FALSE;

    /* Sanity check */
    ASSERT(Hand == KiComputeTimerTableIndex(DueTime));

    /* Loop the timer list backwards */
    ListHead = &KiTimerTableListHead[Hand].Entry;
    NextEntry = ListHead->Blink;
    while (NextEntry != ListHead)
    {
        /* Get the timer */
        CurrentTimer = CONTAINING_RECORD(NextEntry, KTIMER, TimerListEntry);

        /* Now check if we can fit it before */
        if ((ULONGLONG)DueTime >= CurrentTimer->DueTime.QuadPart) break;

        /* Keep looping */
        NextEntry = NextEntry->Blink;
    }

    /* Looped all the list, insert it here and get the interrupt time again */
    InsertHeadList(NextEntry, &Timer->TimerListEntry);

    /* Check if we didn't find it in the list */
    if (NextEntry == ListHead)
    {
        /* Set the time */
        KiTimerTableListHead[Hand].Time.QuadPart = DueTime;

        /* Make sure it hasn't expired already */
        InterruptTime.QuadPart = KeQueryInterruptTime();
        if (DueTime <= InterruptTime.QuadPart) Expired = TRUE;
    }

    /* Return expired state */
    return Expired;
}
Example #4
0
/*----------------------------------------------------------------------------*/
int zrtp_add_system_state(zrtp_global_t* zrtp, MD_CTX *ctx)
{
    LARGE_INTEGER li1;
    LARGE_INTEGER li2;
    ULONG ul1;
    ULONG ul2;
    ULONGLONG ull;
    PKTHREAD thread;
    static int tsc_ok = 1;
	/* 
	 * WARNING! 
	 * Of course it's not a real size of entropy added to the context. It's very
	 * difficult to compute the size of real random data and estimate its quality.
	 * This value means: size of maximum possible random data which this function can provide.
	 */
	static int entropy_length = sizeof(LARGE_INTEGER)*2 + sizeof(PKTHREAD) +
								sizeof(ULONG)*2 + sizeof(LARGE_INTEGER)*2 + sizeof(ULONG)*2;

    li2 = KeQueryPerformanceCounter(&li1);
    MD_Update(ctx, &li1, sizeof(LARGE_INTEGER));
    MD_Update(ctx, &li2, sizeof(LARGE_INTEGER));

    ull = KeQueryInterruptTime();
    MD_Update(ctx, &ull, sizeof(ULONGLONG));

    thread = KeGetCurrentThread();
    MD_Update(ctx, &thread, sizeof(PKTHREAD));
    ul2 = KeQueryRuntimeThread(thread, &ul1);
    MD_Update(ctx, &ul1, sizeof(ULONG));
    MD_Update(ctx, &ul2, sizeof(ULONG));

    KeQuerySystemTime(&li1);
    MD_Update(ctx, &li1, sizeof(LARGE_INTEGER));

    KeQueryTickCount(&li1);
    MD_Update(ctx, &li1, sizeof(LARGE_INTEGER));

    if (tsc_ok) {
		__try {			
			ull = _RDTSC();
			MD_Update(ctx, &ull, sizeof(ULONGLONG));
		} __except(EXCEPTION_EXECUTE_HANDLER) {
			tsc_ok = 0;
		}
    }
    
    return entropy_length;
}
/**
 * Get current NT interrupt time.
 * @return NT interrupt time
 */
static uint64_t rtTimerNtQueryInterruptTime(void)
{
# ifdef RT_ARCH_AMD64
    return KeQueryInterruptTime(); /* macro */
# else
    if (g_pfnrtKeQueryInterruptTime)
        return g_pfnrtKeQueryInterruptTime();

    /* NT4 */
    ULARGE_INTEGER InterruptTime;
    do
    {
        InterruptTime.HighPart = ((KUSER_SHARED_DATA volatile *)SharedUserData)->InterruptTime.High1Time;
        InterruptTime.LowPart  = ((KUSER_SHARED_DATA volatile *)SharedUserData)->InterruptTime.LowPart;
    } while (((KUSER_SHARED_DATA volatile *)SharedUserData)->InterruptTime.High2Time != InterruptTime.HighPart);
    return InterruptTime.QuadPart;
# endif
}
Example #6
0
void rnd_reseed_now()
{
	seed_data seed;

	KeQuerySystemTime(&seed.seed20);
	
	seed.seed1  = PsGetCurrentProcess();
	seed.seed2  = PsGetCurrentProcessId();
	seed.seed3  = KeGetCurrentThread();
	seed.seed4  = PsGetCurrentThreadId();
	seed.seed5  = KeGetCurrentProcessorNumber();
	seed.seed6  = KeQueryInterruptTime();
	seed.seed10 = KeQueryPerformanceCounter(NULL);
	seed.seed11 = __rdtsc();
	seed.seed12 = ExGetPreviousMode();	
	seed.seed14 = IoGetTopLevelIrp();
	seed.seed15 = MmQuerySystemSize();
	seed.seed24 = KeGetCurrentIrql();
	
	if (KeGetCurrentIrql() == PASSIVE_LEVEL) {
		seed.seed7  = KeQueryPriorityThread(seed.seed3);
		seed.seed17 = ExUuidCreate(&seed.seed18);
		seed.seed19 = RtlRandom(&seed.seed8);
	}
	if (KeGetCurrentIrql() <= APC_LEVEL) {
		seed.seed13 = IoGetInitialStack();
		seed.seed16 = PsGetProcessExitTime();
		IoGetStackLimits(&seed.seed22, &seed.seed23);
	}	
	KeQueryTickCount(&seed.seed21);
	
	rnd_add_buff(&seed, sizeof(seed));
	
	/* Prevent leaks */	
	zeroauto(&seed, sizeof(seed));
}
Example #7
0
VOID
NTAPI
KiTimerExpiration(IN PKDPC Dpc,
                  IN PVOID DeferredContext,
                  IN PVOID SystemArgument1,
                  IN PVOID SystemArgument2)
{
    ULARGE_INTEGER SystemTime, InterruptTime;
    LARGE_INTEGER Interval;
    LONG Limit, Index, i;
    ULONG Timers, ActiveTimers, DpcCalls;
    PLIST_ENTRY ListHead, NextEntry;
    KIRQL OldIrql;
    PKTIMER Timer;
    PKDPC TimerDpc;
    ULONG Period;
    DPC_QUEUE_ENTRY DpcEntry[MAX_TIMER_DPCS];
    PKSPIN_LOCK_QUEUE LockQueue;
#ifdef CONFIG_SMP
    PKPRCB Prcb = KeGetCurrentPrcb();
#endif

    /* Disable interrupts */
    _disable();

    /* Query system and interrupt time */
    KeQuerySystemTime((PLARGE_INTEGER)&SystemTime);
    InterruptTime.QuadPart = KeQueryInterruptTime();
    Limit = KeTickCount.LowPart;

    /* Bring interrupts back */
    _enable();

    /* Get the index of the timer and normalize it */
    Index = PtrToLong(SystemArgument1);
    if ((Limit - Index) >= TIMER_TABLE_SIZE)
    {
        /* Normalize it */
        Limit = Index + TIMER_TABLE_SIZE - 1;
    }

    /* Setup index and actual limit */
    Index--;
    Limit &= (TIMER_TABLE_SIZE - 1);

    /* Setup accounting data */
    DpcCalls = 0;
    Timers = 24;
    ActiveTimers = 4;

    /* Lock the Database and Raise IRQL */
    OldIrql = KiAcquireDispatcherLock();

    /* Start expiration loop */
    do
    {
        /* Get the current index */
        Index = (Index + 1) & (TIMER_TABLE_SIZE - 1);

        /* Get list pointers and loop the list */
        ListHead = &KiTimerTableListHead[Index].Entry;
        while (ListHead != ListHead->Flink)
        {
            /* Lock the timer and go to the next entry */
            LockQueue = KiAcquireTimerLock(Index);
            NextEntry = ListHead->Flink;

            /* Get the current timer and check its due time */
            Timers--;
            Timer = CONTAINING_RECORD(NextEntry, KTIMER, TimerListEntry);
            if ((NextEntry != ListHead) &&
                (Timer->DueTime.QuadPart <= InterruptTime.QuadPart))
            {
                /* It's expired, remove it */
                ActiveTimers--;
                KiRemoveEntryTimer(Timer);

                /* Make it non-inserted, unlock it, and signal it */
                Timer->Header.Inserted = FALSE;
                KiReleaseTimerLock(LockQueue);
                Timer->Header.SignalState = 1;

                /* Get the DPC and period */
                TimerDpc = Timer->Dpc;
                Period = Timer->Period;

                /* Check if there's any waiters */
                if (!IsListEmpty(&Timer->Header.WaitListHead))
                {
                    /* Check the type of event */
                    if (Timer->Header.Type == TimerNotificationObject)
                    {
                        /* Unwait the thread */
                        KxUnwaitThread(&Timer->Header, IO_NO_INCREMENT);
                    }
                    else
                    {
                        /* Otherwise unwait the thread and signal the timer */
                        KxUnwaitThreadForEvent((PKEVENT)Timer, IO_NO_INCREMENT);
                    }
                }

                /* Check if we have a period */
                if (Period)
                {
                    /* Calculate the interval and insert the timer */
                    Interval.QuadPart = Int32x32To64(Period, -10000);
                    while (!KiInsertTreeTimer(Timer, Interval));
                }

                /* Check if we have a DPC */
                if (TimerDpc)
                {
#ifdef CONFIG_SMP
                    /* 
                     * If the DPC is targeted to another processor,
                     * then insert it into that processor's DPC queue
                     * instead of delivering it now.
                     * If the DPC is a threaded DPC, and the current CPU
                     * has threaded DPCs enabled (KiExecuteDpc is actively parsing DPCs),
                     * then also insert it into the DPC queue for threaded delivery,
                     * instead of doing it here.
                     */
                    if (((TimerDpc->Number >= MAXIMUM_PROCESSORS) &&
                        ((TimerDpc->Number - MAXIMUM_PROCESSORS) != Prcb->Number)) ||
                        ((TimerDpc->Type == ThreadedDpcObject) && (Prcb->ThreadDpcEnable)))
                    {
                        /* Queue it */
                        KeInsertQueueDpc(TimerDpc,
                                         UlongToPtr(SystemTime.LowPart),
                                         UlongToPtr(SystemTime.HighPart));
                    }
                    else
#endif
                    {
                        /* Setup the DPC Entry */
                        DpcEntry[DpcCalls].Dpc = TimerDpc;
                        DpcEntry[DpcCalls].Routine = TimerDpc->DeferredRoutine;
                        DpcEntry[DpcCalls].Context = TimerDpc->DeferredContext;
                        DpcCalls++;
                        ASSERT(DpcCalls < MAX_TIMER_DPCS);
                    }
                }

                /* Check if we're done processing */
                if (!(ActiveTimers) || !(Timers))
                {
                    /* Release the dispatcher while doing DPCs */
                    KiReleaseDispatcherLock(DISPATCH_LEVEL);

                    /* Start looping all DPC Entries */
                    for (i = 0; DpcCalls; DpcCalls--, i++)
                    {
                        /* Call the DPC */
                        DpcEntry[i].Routine(DpcEntry[i].Dpc,
                                            DpcEntry[i].Context,
                                            UlongToPtr(SystemTime.LowPart),
                                            UlongToPtr(SystemTime.HighPart));
                    }

                    /* Reset accounting */
                    Timers = 24;
                    ActiveTimers = 4;

                    /* Lock the dispatcher database */
                    KiAcquireDispatcherLock();
                }
            }
            else
            {
                /* Check if the timer list is empty */
                if (NextEntry != ListHead)
                {
                    /* Sanity check */
                    ASSERT(KiTimerTableListHead[Index].Time.QuadPart <=
                           Timer->DueTime.QuadPart);

                    /* Update the time */
                    _disable();
                    KiTimerTableListHead[Index].Time.QuadPart =
                        Timer->DueTime.QuadPart;
                    _enable();
                }

                /* Release the lock */
                KiReleaseTimerLock(LockQueue);

                /* Check if we've scanned all the timers we could */
                if (!Timers)
                {
                    /* Release the dispatcher while doing DPCs */
                    KiReleaseDispatcherLock(DISPATCH_LEVEL);

                    /* Start looping all DPC Entries */
                    for (i = 0; DpcCalls; DpcCalls--, i++)
                    {
                        /* Call the DPC */
                        DpcEntry[i].Routine(DpcEntry[i].Dpc,
                                            DpcEntry[i].Context,
                                            UlongToPtr(SystemTime.LowPart),
                                            UlongToPtr(SystemTime.HighPart));
                    }

                    /* Reset accounting */
                    Timers = 24;
                    ActiveTimers = 4;

                    /* Lock the dispatcher database */
                    KiAcquireDispatcherLock();
                }

                /* Done looping */
                break;
            }
        }
    } while (Index != Limit);

    /* Verify the timer table, on debug builds */
    if (KeNumberProcessors == 1) KiCheckTimerTable(InterruptTime);

    /* Check if we still have DPC entries */
    if (DpcCalls)
    {
        /* Release the dispatcher while doing DPCs */
        KiReleaseDispatcherLock(DISPATCH_LEVEL);

        /* Start looping all DPC Entries */
        for (i = 0; DpcCalls; DpcCalls--, i++)
        {
            /* Call the DPC */
            DpcEntry[i].Routine(DpcEntry[i].Dpc,
                                DpcEntry[i].Context,
                                UlongToPtr(SystemTime.LowPart),
                                UlongToPtr(SystemTime.HighPart));
        }

        /* Lower IRQL if we need to */
        if (OldIrql != DISPATCH_LEVEL) KeLowerIrql(OldIrql);
    }
    else
    {
        /* Unlock the dispatcher */
        KiReleaseDispatcherLock(OldIrql);
    }
}
Example #8
0
VOID
ExGetNextWakeTime (
    OUT PULONGLONG      DueTime,
    OUT PTIME_FIELDS    TimeFields,
    OUT PVOID           *TimerObject
    )
{
    PLIST_ENTRY     Link;
    PETIMER         ExTimer;
    PETIMER         BestTimer;
    KIRQL           OldIrql;
    ULONGLONG       TimerDueTime;
    ULONGLONG       BestDueTime;
    ULONGLONG       InterruptTime;
    LARGE_INTEGER   SystemTime;
    LARGE_INTEGER   CmosTime;

    ExAcquireSpinLock(&ExpWakeTimerListLock, &OldIrql);
    BestDueTime = 0;
    BestTimer = NULL;
    Link = ExpWakeTimerList.Flink;
    while (Link != &ExpWakeTimerList) {
        ExTimer = CONTAINING_RECORD(Link, ETIMER, WakeTimerListEntry);
        Link = Link->Flink;

        if (ExTimer->WakeTimer) {

            TimerDueTime = KeQueryTimerDueTime(&ExTimer->KeTimer);
            TimerDueTime = 0 - TimerDueTime;

            //
            // Is this timers due time closer?
            //

            if (TimerDueTime > BestDueTime) {
                BestDueTime = TimerDueTime;
                BestTimer = ExTimer;
            }

        } else {

            //
            // Timer is not an active wake timer, remove it
            //

            RemoveEntryList(&ExTimer->WakeTimerListEntry);
            ExTimer->WakeTimerListEntry.Flink = NULL;
        }
    }

    ExReleaseSpinLock(&ExpWakeTimerListLock, OldIrql);

    if (BestDueTime) {
        //
        // Convert time to timefields
        //

        KeQuerySystemTime (&SystemTime);
        InterruptTime = KeQueryInterruptTime ();
        BestDueTime = 0 - BestDueTime;

        SystemTime.QuadPart += BestDueTime - InterruptTime;

        //
        // Many system alarms are only good to 1 second resolution.
        // Add one sceond to the target time so that the timer is really
        // elasped if this is the wake event.
        //

        SystemTime.QuadPart += 10000000;

        ExSystemTimeToLocalTime(&SystemTime,&CmosTime);
        RtlTimeToTimeFields(&CmosTime, TimeFields);
    }

    *DueTime = BestDueTime;
    *TimerObject = BestTimer;
}
Example #9
0
VOID
KiCalibrateTimeAdjustment (
    PADJUST_INTERRUPT_TIME_CONTEXT Adjust
    )

/*++

Routine Description:

    This function calibrates the adjustment of time on all processors.

Arguments:

    Adjust - Supplies the operation context.

Return Value:

    None.

--*/

{

    ULONG cl;
    ULONG divisor;
    BOOLEAN Enable;
    LARGE_INTEGER InterruptTime;
    ULARGE_INTEGER li;
    PERFINFO_PO_CALIBRATED_PERFCOUNTER LogEntry;
    LARGE_INTEGER NewTickCount;
    ULONG NewTickOffset;
    LARGE_INTEGER PerfCount;
    LARGE_INTEGER PerfFreq;
    LARGE_INTEGER SetTime;

    //
    // As each processor arrives, decrement the remaining processor count. If
    // this is the last processor to arrive, then compute the time change, and
    // signal all processor when to apply the performance counter change.
    //

    if (InterlockedDecrement((PLONG)&Adjust->KiNumber)) {
        Enable = KeDisableInterrupts();

        //
        // It is possible to deadlock if one or more of the other processors
        // receives and processes a freeze request while this processor has
        // interrupts disabled. Poll for a freeze request until all processors
        // are known to be in this code.
        //

        do {
            KiPollFreezeExecution();
        } while (Adjust->KiNumber != (ULONG)-1);

        //
        // Wait to perform the time set.
        //

        while (Adjust->Barrier);

    } else {

        //
        // Set timer expiration dpc to scan the timer queues once for any
        // expired timers.
        //

        KeRemoveQueueDpc(&KiTimerExpireDpc);
        KeInsertQueueDpc(&KiTimerExpireDpc,
                         ULongToPtr(KiQueryLowTickCount() - TIMER_TABLE_SIZE),
                         NULL);

        //
        // Disable interrupts and indicate that this processor is now
        // in final portion of this code.
        //

        Enable = KeDisableInterrupts();
        InterlockedDecrement((PLONG) &Adjust->KiNumber);

        //
        // Adjust Interrupt Time.
        //

        InterruptTime.QuadPart = KeQueryInterruptTime() + Adjust->Adjustment;
        SetTime.QuadPart = Adjust->Adjustment;

        //
        // Get the current times
        //

        PerfCount = KeQueryPerformanceCounter(&PerfFreq);

        //
        // Compute performance counter for current time.
        //
        // Multiply SetTime * PerfCount and obtain 96-bit result in cl,
        // li.LowPart, li.HighPart.  Then divide the 96-bit result by
        // 10,000,000 to get new performance counter value.
        //

        li.QuadPart = RtlEnlargedUnsignedMultiply((ULONG)SetTime.LowPart,
                                                  (ULONG)PerfFreq.LowPart).QuadPart;

        cl = li.LowPart;
        li.QuadPart =
            li.HighPart + RtlEnlargedUnsignedMultiply((ULONG)SetTime.LowPart,
                                                      (ULONG)PerfFreq.HighPart).QuadPart;

        li.QuadPart =
            li.QuadPart + RtlEnlargedUnsignedMultiply((ULONG)SetTime.HighPart,
                                                      (ULONG)PerfFreq.LowPart).QuadPart;

        li.HighPart = li.HighPart + SetTime.HighPart * PerfFreq.HighPart;
        divisor = 10000000;
        Adjust->NewCount.HighPart = RtlEnlargedUnsignedDivide(li,
                                                              divisor,
                                                              &li.HighPart);

        li.LowPart = cl;
        Adjust->NewCount.LowPart = RtlEnlargedUnsignedDivide(li,
                                                             divisor,
                                                             NULL);

        Adjust->NewCount.QuadPart += PerfCount.QuadPart;

        //
        // Compute tick count and tick offset for current interrupt time.
        //

        NewTickCount = RtlExtendedLargeIntegerDivide(InterruptTime,
                                                     KeMaximumIncrement,
                                                     &NewTickOffset);

        //
        // Apply changes to interrupt time, tick count, tick offset, and the
        // performance counter.
        //

        KiTickOffset = KeMaximumIncrement - NewTickOffset;
        KeInterruptTimeBias += Adjust->Adjustment;
        SharedUserData->TickCount.High2Time = NewTickCount.HighPart;

#if defined(_WIN64)

        SharedUserData->TickCountQuad = NewTickCount.QuadPart;

#else

        SharedUserData->TickCount.LowPart   = NewTickCount.LowPart;
        SharedUserData->TickCount.High1Time = NewTickCount.HighPart;

#endif

        //
        // N.B. There is no global tick count variable on AMD64.
        //

#if defined(_X86_)

        KeTickCount.High2Time = NewTickCount.HighPart;
        KeTickCount.LowPart   = NewTickCount.LowPart;
        KeTickCount.High1Time = NewTickCount.HighPart;

#endif

#if defined(_AMD64_)

        SharedUserData->InterruptTime.High2Time = InterruptTime.HighPart;
        *((volatile ULONG64 *)&SharedUserData->InterruptTime) = InterruptTime.QuadPart;

#else

        SharedUserData->InterruptTime.High2Time = InterruptTime.HighPart;
        SharedUserData->InterruptTime.LowPart   = InterruptTime.LowPart;
        SharedUserData->InterruptTime.High1Time = InterruptTime.HighPart;

#endif

        //
        // Apply the performance counter change.
        //

        Adjust->Barrier = 0;
    }

    KeGetCurrentPrcb()->TickOffset = KiTickOffset;

#if defined(_AMD64_)

    KeGetCurrentPrcb()->MasterOffset = KiTickOffset;

#endif

    HalCalibratePerformanceCounter((LONG volatile *)&Adjust->HalNumber,
                                   (ULONGLONG)Adjust->NewCount.QuadPart);

    //
    // Log an event that the performance counter has been calibrated
    // properly and indicate the new performance counter value.
    //

    if (PERFINFO_IS_GROUP_ON(PERF_POWER)) {
        LogEntry.PerformanceCounter = KeQueryPerformanceCounter(NULL);
        PerfInfoLogBytes(PERFINFO_LOG_TYPE_PO_CALIBRATED_PERFCOUNTER,
                         &LogEntry,
                         sizeof(LogEntry));
    }

    KeEnableInterrupts(Enable);
    return;
}
Example #10
0
NTSTATUS
NTAPI
CmBattQueryInformation(IN PCMBATT_DEVICE_EXTENSION FdoExtension,
                       IN ULONG Tag,
                       IN BATTERY_QUERY_INFORMATION_LEVEL InfoLevel,
                       IN OPTIONAL LONG AtRate,
                       IN PVOID Buffer,
                       IN ULONG BufferLength,
                       OUT PULONG ReturnedLength)
{
    NTSTATUS Status;
    PVOID QueryData = NULL;
    ULONG QueryLength = 0;
    ULONG RemainingTime = 0;
    ANSI_STRING TempString;
    UNICODE_STRING TempString2;
    WCHAR InfoBuffer[256];
    WCHAR TempBuffer[256];
    UNICODE_STRING InfoString;
    ULONG RemainingCapacity;
    BATTERY_REPORTING_SCALE BatteryReportingScale[2];
    LONG Rate;
    PAGED_CODE();
    if (CmBattDebug & (CMBATT_ACPI_WARNING | CMBATT_GENERIC_INFO))
        DbgPrint("CmBattQueryInformation - Tag (%d) Device %d, Informationlevel %d\n",
                 Tag,
                 FdoExtension->DeviceId,
                 InfoLevel);

    /* Check ACPI Data */
    Status = CmBattVerifyStaticInfo(FdoExtension, Tag);
    if (!NT_SUCCESS(Status)) return Status;

    /* Check what caller wants */
    switch (InfoLevel)
    {
        case BatteryInformation:
            /* Just return our static information */
            QueryData = &FdoExtension->BatteryInformation;
            QueryLength = sizeof(BATTERY_INFORMATION);
            break;
        
        case BatteryGranularityInformation:
        
            /* Return our static information, we have two scales */
            BatteryReportingScale[0].Granularity = FdoExtension->BatteryCapacityGranularity1;
            BatteryReportingScale[0].Capacity = FdoExtension->BatteryInformation.DefaultAlert1;
            BatteryReportingScale[1].Granularity = FdoExtension->BatteryCapacityGranularity2;
            BatteryReportingScale[1].Capacity = FdoExtension->BatteryInformation.DesignedCapacity;
            QueryData = BatteryReportingScale;
            QueryLength = sizeof(BATTERY_REPORTING_SCALE) * 2;
            break;
            
        case BatteryEstimatedTime:
        
            /* Check if it's been more than 2 1/2 minutes since the last change */
            if ((KeQueryInterruptTime() - 150000000) > (FdoExtension->InterruptTime))
            {
                /* Get new battery status */
                CmBattGetBatteryStatus(FdoExtension, FdoExtension->Tag);
                
                /* If the caller didn't specify a rate, use our static one */
                Rate = AtRate;
                if (!Rate) Rate = FdoExtension->Rate;
                
                /* If we don't have a valid negative rate, use unknown value */
                if (Rate >= 0) Rate = BATTERY_UNKNOWN_RATE;
                
                /* Grab the remaining capacity */
                RemainingCapacity = FdoExtension->RemainingCapacity;
                
                /* See if we don't know one or the other */
                if ((Rate == BATTERY_UNKNOWN_RATE) ||
                    (RemainingCapacity == BATTERY_UNKNOWN_CAPACITY))
                {
                    /* If the battery is discharging, we can't give out a time */
                    if ((FdoExtension->BstData.State & ACPI_BATT_STAT_DISCHARG) &&
                        (CmBattDebug & CMBATT_GENERIC_WARNING))
                            DbgPrint("CmBattQueryInformation: Can't calculate EstimatedTime.\n");
                    
                    /* Check if we don't have a rate and capacity is going down */
                    if ((FdoExtension->Rate == BATTERY_UNKNOWN_RATE) &&
                        (FdoExtension->BstData.State & ACPI_BATT_STAT_DISCHARG))
                    {
                        /* We have to fail, since we lack data */
                        Status = STATUS_INVALID_DEVICE_REQUEST;
                        if (CmBattDebug & CMBATT_GENERIC_WARNING)
                            DbgPrint("----------------------   PresentRate = BATTERY_UNKNOWN_RATE\n");
                    }
                    
                    /* If we don't have capacity, the rate is useless */
                    if (RemainingCapacity == BATTERY_UNKNOWN_CAPACITY)
                    {
                        /* We have to fail the request */
                        Status = STATUS_INVALID_DEVICE_REQUEST;
                        if (CmBattDebug & CMBATT_GENERIC_WARNING)
                            DbgPrint("----------------------   RemainingCapacity = BATTERY_UNKNOWN_CAPACITY\n");
                    }
                }
                else
                {
                    /* We have data, but is it valid? */
                    if (RemainingCapacity > 0x123456)
                    {
                        /* The capacity seems bogus, so don't use it */
                        if (CmBattDebug & CMBATT_ACPI_WARNING)
                            DbgPrint("CmBattQueryInformation: Data Overflow in calculating Remaining Capacity.\n");
                    }
                    else
                    {
                        /* Compute the remaining time in seconds, based on rate */
                        RemainingTime = (RemainingCapacity * 3600) / -Rate;
                    }
                }
            }
            
            /* Return the remaining time */
            QueryData = &RemainingTime;
            QueryLength = sizeof(ULONG);
            break;
            
        case BatteryDeviceName:
        
            /* Build the model number string */
            RtlInitAnsiString(&TempString, FdoExtension->ModelNumber);

            /* Convert it to Unicode */
            InfoString.Buffer = InfoBuffer;
            InfoString.MaximumLength = sizeof(InfoBuffer);            
            Status = RtlAnsiStringToUnicodeString(&InfoString, &TempString, 0);
            
            /* Return the unicode buffer */
            QueryData = InfoString.Buffer;
            QueryLength = InfoString.Length;
            break;
            
        case BatteryTemperature:
        case BatteryManufactureDate:
        
            /* We don't support these */
            Status = STATUS_INVALID_DEVICE_REQUEST;
            break;
            
        case BatteryManufactureName:
            
            /* Build the OEM info string */
            RtlInitAnsiString(&TempString, FdoExtension->OemInfo);
            
            /* Convert it to Unicode */
            InfoString.Buffer = InfoBuffer;
            InfoString.MaximumLength = sizeof(InfoBuffer);
            Status = RtlAnsiStringToUnicodeString(&InfoString, &TempString, 0);
            
            /* Return the unicode buffer */
            QueryData = InfoString.Buffer;
            QueryLength = InfoString.Length;
            break;
            
        case BatteryUniqueID:

            /* Build the serial number string */
            RtlInitAnsiString(&TempString, FdoExtension->SerialNumber);

            /* Convert it to Unicode */
            InfoString.Buffer = InfoBuffer;
            InfoString.MaximumLength = sizeof(InfoBuffer);
            RtlAnsiStringToUnicodeString(&InfoString, &TempString, 0);

            /* Setup a temporary string for concatenation */
            TempString2.Buffer = TempBuffer;
            TempString2.MaximumLength = sizeof(TempBuffer);
            
            /* Check if there's an OEM string */
            if (FdoExtension->OemInfo[0])
            {
                /* Build the OEM info string */
                RtlInitAnsiString(&TempString, FdoExtension->OemInfo);
              
                /* Convert it to Unicode and append it */
                RtlAnsiStringToUnicodeString(&TempString2, &TempString, 0);
                RtlAppendUnicodeStringToString(&InfoString, &TempString2);
            }
            
            /* Build the model number string */
            RtlInitAnsiString(&TempString, FdoExtension->ModelNumber);
            
            /* Convert it to Unicode and append it */
            RtlAnsiStringToUnicodeString(&TempString2, &TempString, 0);
            RtlAppendUnicodeStringToString(&InfoString, &TempString2);
            
            /* Return the final appended string */
            QueryData = InfoString.Buffer;
            QueryLength = InfoString.Length;
            break;
            
        default:
        
            /* Everything else is unknown */
            Status = STATUS_INVALID_PARAMETER;
            break;
    }

    /* Return the required length and check if the caller supplied enough */
    *ReturnedLength = QueryLength;
    if (BufferLength < QueryLength) Status = STATUS_BUFFER_TOO_SMALL;

    /* Copy the data if there's enough space and it exists */
    if ((NT_SUCCESS(Status)) && (QueryData)) RtlCopyMemory(Buffer, QueryData, QueryLength);
      
    /* Return function result */
    return Status;
}
Example #11
0
NTSTATUS
NTAPI
CmBattGetBatteryStatus(IN PCMBATT_DEVICE_EXTENSION DeviceExtension,
                       IN ULONG Tag)
{
    ULONG PsrData = 0;
    NTSTATUS Status;
    ULONG BstState;
    ULONG DesignVoltage, PresentRate, RemainingCapacity;
    PAGED_CODE();
    if (CmBattDebug & CMBATT_GENERIC_INFO)
        DbgPrint("CmBattGetBatteryStatus - CmBatt (%08x) Tag (%d)\n", DeviceExtension, Tag);
    
    /* Validate ACPI data */    
    Status = CmBattVerifyStaticInfo(DeviceExtension, Tag);
    if (!NT_SUCCESS(Status)) return Status;

    /* Check for delayed status notifications */
    if (DeviceExtension->DelayNotification)
    {
        /* Process them now and don't do any other work */
        CmBattNotifyHandler(DeviceExtension, ACPI_BATT_NOTIFY_STATUS);
        return Status;
    }

    /* Get _BST from ACPI */
    Status = CmBattGetBstData(DeviceExtension, &DeviceExtension->BstData);
    if (!NT_SUCCESS(Status))
    {
        /* Fail */
        InterlockedExchange(&DeviceExtension->ArLockValue, 0);
        return Status;
    }
    
    /* Clear current BST information */ 
    DeviceExtension->State = 0;
    DeviceExtension->RemainingCapacity = 0;
    DeviceExtension->PresentVoltage = 0;
    DeviceExtension->Rate = 0;

    /* Get battery state */
    BstState = DeviceExtension->BstData.State;
    
    /* Is the battery both charging and discharging? */
    if ((BstState & ACPI_BATT_STAT_DISCHARG) && (BstState & ACPI_BATT_STAT_CHARGING) &&
        (CmBattDebug & (CMBATT_ACPI_WARNING | CMBATT_GENERIC_WARNING)))
            DbgPrint("************************ ACPI BIOS BUG ********************\n* "
                     "CmBattGetBatteryStatus: Invalid state: _BST method returned 0x%08x for Battery State.\n"
                     "* One battery cannot be charging and discharging at the same time.\n",
                     BstState);
    
    /* Is the battery discharging? */   
    if (BstState & ACPI_BATT_STAT_DISCHARG)
    {
        /* Set power state and check if it just started discharging now */
        DeviceExtension->State |= BATTERY_DISCHARGING;
        if (!(DeviceExtension->State & ACPI_BATT_STAT_DISCHARG))
        {
            /* Remember the time when the state changed */
            DeviceExtension->InterruptTime = KeQueryInterruptTime();
        }
    }
    else if (BstState & ACPI_BATT_STAT_CHARGING)
    {
        /* Battery is charging, update power state */
        DeviceExtension->State |= (BATTERY_CHARGING | BATTERY_POWER_ON_LINE);
    }
    
    /* Is the battery in a critical state? */
    if (BstState & ACPI_BATT_STAT_CRITICAL) DeviceExtension->State |= BATTERY_CRITICAL;
    
    /* Read the voltage data */  
    DeviceExtension->PresentVoltage = DeviceExtension->BstData.PresentVoltage;
    
    /* Check if we have an A/C adapter */
    if (AcAdapterPdo)
    {
        /* Query information on it */
        CmBattGetPsrData(AcAdapterPdo, &PsrData);
    }
    else
    {
        /* Otherwise, check if the battery is charging */
        if (BstState & ACPI_BATT_STAT_CHARGING)
        {
            /* Then we'll assume there's a charger */
            PsrData = 1;
        }
        else
        {
            /* Assume no charger */
            PsrData = 0;        
        }
    }
    
    /* Is there a charger? */
    if (PsrData)
    {
        /* Set the power state flag to reflect this */
        DeviceExtension->State |= BATTERY_POWER_ON_LINE;
        if (CmBattDebug & (CMBATT_GENERIC_INFO | CMBATT_GENERIC_STATUS))
            DbgPrint("CmBattGetBatteryStatus: AC adapter is connected\n");
    }
    else if (CmBattDebug & (CMBATT_GENERIC_INFO | CMBATT_GENERIC_STATUS))
    {
        DbgPrint("CmBattGetBatteryStatus: AC adapter is NOT connected\n");        
    }
    
    /* Get some data we'll need */
    DesignVoltage = DeviceExtension->BifData.DesignVoltage;
    PresentRate = DeviceExtension->BstData.PresentRate;
    RemainingCapacity = DeviceExtension->BstData.RemainingCapacity;
    
    /* Check if we have battery data in Watts instead of Amps */
    if (DeviceExtension->BifData.PowerUnit == ACPI_BATT_POWER_UNIT_WATTS)
    {
        /* Get the data from the BST */
        DeviceExtension->RemainingCapacity = RemainingCapacity;
        DeviceExtension->Rate = PresentRate;
        
        /* Check if the rate is invalid */
        if (PresentRate > CM_MAX_VALUE)
        {
            /* Set an unknown rate and don't touch the old value */
            DeviceExtension->Rate = BATTERY_UNKNOWN_RATE;
            if ((PresentRate != CM_UNKNOWN_VALUE) && (CmBattDebug & CMBATT_ACPI_WARNING))
            {
                DbgPrint("CmBattGetBatteryStatus - Rate is greater than CM_MAX_VALUE\n");
                DbgPrint("----------------------   PresentRate = 0x%08x\n", PresentRate);
            }
        }
    }
    else if ((DesignVoltage != CM_UNKNOWN_VALUE) && (DesignVoltage))
    {
        /* We have voltage data, what about capacity? */
        if (RemainingCapacity == CM_UNKNOWN_VALUE)
        {
            /* Unable to calculate it */
            DeviceExtension->RemainingCapacity = BATTERY_UNKNOWN_CAPACITY;
            if (CmBattDebug & CMBATT_ACPI_WARNING)
            {
                DbgPrint("CmBattGetBatteryStatus - Can't calculate RemainingCapacity \n");
                DbgPrint("----------------------   RemainingCapacity = CM_UNKNOWN_VALUE\n");
            }
        }
        else
        {
            /* Compute the capacity with the information we have */
            DeviceExtension->RemainingCapacity = (DesignVoltage * RemainingCapacity + 500) / 1000;
        }
        
        /* Check if we have a rate */
        if (PresentRate != CM_UNKNOWN_VALUE)
        {
            /* Make sure the rate isn't too large */
            if (PresentRate > (-500 / DesignVoltage))
            {
                /* It is, so set unknown state */
                DeviceExtension->Rate = BATTERY_UNKNOWN_RATE;
                if (CmBattDebug & CMBATT_ACPI_WARNING)
                {
                    DbgPrint("CmBattGetBatteryStatus - Can't calculate Rate \n");
                    DbgPrint("----------------------   Overflow: PresentRate = 0x%08x\n", PresentRate);
                }
            }
            
            /* Compute the rate */
            DeviceExtension->Rate = (PresentRate * DesignVoltage + 500) / 1000;
        }
        else
        {
            /* We don't have a rate, so set unknown value */
            DeviceExtension->Rate = BATTERY_UNKNOWN_RATE;        
            if (CmBattDebug & CMBATT_ACPI_WARNING)
            {
                DbgPrint("CmBattGetBatteryStatus - Can't calculate Rate \n");
                DbgPrint("----------------------   Present Rate = CM_UNKNOWN_VALUE\n");
            }
        }
    }
    else
    {
        /* We have no rate, and no capacity, set unknown values */
        DeviceExtension->Rate = BATTERY_UNKNOWN_RATE;
        DeviceExtension->RemainingCapacity = BATTERY_UNKNOWN_CAPACITY;
        if (CmBattDebug & CMBATT_ACPI_WARNING)
        {
            DbgPrint("CmBattGetBatteryStatus - Can't calculate RemainingCapacity and Rate \n");
            DbgPrint("----------------------   DesignVoltage = 0x%08x\n", DesignVoltage);
        }
    }
    
    /* Check if we have an unknown rate */
    if (DeviceExtension->Rate == BATTERY_UNKNOWN_RATE)
    {
        /* The battery is discharging but we don't know by how much... this is bad! */
        if ((BstState & ACPI_BATT_STAT_DISCHARG) &&
            (CmBattDebug & (CMBATT_ACPI_WARNING | CMBATT_GENERIC_WARNING)))
            DbgPrint("CmBattGetBatteryStatus: battery rate is unkown when battery is not charging!\n");
    }
    else if (DeviceExtension->State & BATTERY_DISCHARGING)
    {
        /* The battery is discharging, so treat the rate as a negative rate */
        DeviceExtension->Rate = -DeviceExtension->Rate;
    }
    else if (!(DeviceExtension->State & BATTERY_CHARGING) && (DeviceExtension->Rate))
    {
        /* We are not charging, not discharging, but have a rate? Ignore it! */
        if (CmBattDebug & CMBATT_GENERIC_WARNING)
            DbgPrint("CmBattGetBatteryStatus: battery is not charging or discharging, but rate = %x\n",
                     DeviceExtension->Rate);
        DeviceExtension->Rate = 0;
    }
     
    /* Done */
    return STATUS_SUCCESS;
}
Example #12
0
//=============================================================================
STDMETHODIMP CMiniportWaveCyclicStream::SetState(
    IN  KSSTATE                 NewState
)
/*++
Routine Description:
  The SetState function sets the new state of playback or recording for the
  stream. SetState should run at IRQL PASSIVE_LEVEL

Arguments:
  NewState - KSSTATE indicating the new state for the stream.

Return Value:
  NT status code.
--*/
{
    PAGED_CODE();

    DPF_ENTER(("[CMiniportWaveCyclicStream::SetState]"));

    NTSTATUS ntStatus = STATUS_SUCCESS;

    // The acquire state is not distinguishable from the stop state for our
    // purposes.
    if (NewState == KSSTATE_ACQUIRE) {
        NewState = KSSTATE_STOP;
    }

    if (m_ksState != NewState) {
        switch(NewState) {
            case KSSTATE_PAUSE:
                DPF(D_TERSE, ("KSSTATE_PAUSE"));
                
                m_fDmaActive = FALSE;
                break;

            case KSSTATE_RUN:
                DPF(D_TERSE, ("KSSTATE_RUN"));

                LARGE_INTEGER   delay;

                // Set the timer for DPC.
                m_ullDmaTimeStamp             = KeQueryInterruptTime();
                m_ullElapsedTimeCarryForward  = 0;
                m_fDmaActive                  = TRUE;
                delay.HighPart                = 0;
                delay.LowPart                 = m_pMiniport->m_NotificationInterval;

                KeSetTimerEx(m_pTimer, delay, m_pMiniport->m_NotificationInterval, m_pDpc);
                break;

            case KSSTATE_STOP:
                DPF(D_TERSE, ("KSSTATE_STOP"));
    
                m_fDmaActive                      = FALSE;
                m_ulDmaPosition                   = 0;
                m_ullElapsedTimeCarryForward      = 0;
                m_ulByteDisplacementCarryForward  = 0;
    
                KeCancelTimer(m_pTimer);
    
                // Wait until all work items are completed.
                if (!m_fCapture) {
                    m_SaveData.WaitAllWorkItems();
                }
                break;
        }

        m_ksState = NewState;
    }

    return ntStatus;
} // SetState