ULONG NTAPI HalpSetCmosData(IN ULONG BusNumber, IN ULONG SlotNumber, IN PVOID Buffer, IN ULONG Length) { PUCHAR Ptr = (PUCHAR)Buffer; ULONG Address = SlotNumber; ULONG Len = Length; /* FIXME: Acquire CMOS Lock */ /* Do nothing if we don't have a length */ if (!Length) return 0; /* Check if this is simple CMOS */ if (!BusNumber) { /* Loop the buffer up to 0xFF */ while ((Len > 0) && (Address < 0x100)) { /* Write the data */ HalpWriteCmos((UCHAR)Address, *Ptr); /* Update position and length */ Ptr++; Address++; Len--; } } else if (BusNumber == 1) { /* Loop the buffer up to 0xFFFF */ while ((Len > 0) && (Address < 0x10000)) { /* Write the data */ HalpWriteCmos((UCHAR)Address, *Ptr); /* Update position and length */ Ptr++; Address++; Len--; } } /* FIXME: Release the CMOS Lock */ /* Return length read */ return Length - Len; }
/* * @implemented */ BOOLEAN NTAPI HalSetRealTimeClock(IN PTIME_FIELDS Time) { /* FIXME: Acquire CMOS Lock */ /* Loop while update is in progress */ while ((HalpReadCmos(RTC_REGISTER_A)) & RTC_REG_A_UIP); /* Write time fields to CMOS RTC */ HalpWriteCmos(0, INT_BCD(Time->Second)); HalpWriteCmos(2, INT_BCD(Time->Minute)); HalpWriteCmos(4, INT_BCD(Time->Hour)); HalpWriteCmos(6, INT_BCD(Time->Weekday)); HalpWriteCmos(7, INT_BCD(Time->Day)); HalpWriteCmos(8, INT_BCD(Time->Month)); HalpWriteCmos(9, INT_BCD(Time->Year % 100)); /* FIXME: Set the century byte */ /* FIXME: Release the CMOS Lock */ /* Always return TRUE */ return TRUE; }
/* * @implemented */ VOID NTAPI HalStopProfileInterrupt(IN KPROFILE_SOURCE ProfileSource) { UCHAR StatusB; /* Acquire the CMOS lock */ HalpAcquireCmosSpinLock(); /* Read Status Register B */ StatusB = HalpReadCmos(RTC_REGISTER_B); /* Disable periodic interrupts */ StatusB = StatusB & ~RTC_REG_B_PI; /* Write new value into Status Register B */ HalpWriteCmos(RTC_REGISTER_B, StatusB); /* Release the CMOS lock */ HalpReleaseCmosSpinLock(); }
/* * @implemented */ ARC_STATUS NTAPI HalSetEnvironmentVariable(IN PCH Name, IN PCH Value) { UCHAR Val; /* Only variable supported on x86 */ if (_stricmp(Name, "LastKnownGood")) return ENOMEM; /* Check if this is true or false */ if (!_stricmp(Value, "TRUE")) { /* It's true, acquire CMOS lock (FIXME) */ /* Read the current value and add the flag */ Val = HalpReadCmos(RTC_REGISTER_B) | 1; } else if (!_stricmp(Value, "FALSE")) { /* It's false, acquire CMOS lock (FIXME) */ /* Read the current value and mask out the flag */ Val = HalpReadCmos(RTC_REGISTER_B) & ~1; } else { /* Fail */ return ENOMEM; } /* Write new value */ HalpWriteCmos(RTC_REGISTER_B, Val); /* Release the lock and return success */ return ESUCCESS; }
VOID NTAPI HalpInitializeTsc(VOID) { ULONG_PTR Flags; KIDTENTRY OldIdtEntry, *IdtPointer; PKPCR Pcr = KeGetPcr(); UCHAR RegisterA, RegisterB; /* Check if the CPU supports RDTSC */ if (!(KeGetCurrentPrcb()->FeatureBits & KF_RDTSC)) { KeBugCheck(HAL_INITIALIZATION_FAILED); } /* Save flags and disable interrupts */ Flags = __readeflags(); _disable(); /* Enable the periodic interrupt in the CMOS */ RegisterB = HalpReadCmos(RTC_REGISTER_B); HalpWriteCmos(RTC_REGISTER_B, RegisterB | RTC_REG_B_PI); /* Modify register A to RTC_MODE to get SAMPLE_FREQENCY */ RegisterA = HalpReadCmos(RTC_REGISTER_A); RegisterA = (RegisterA & 0xF0) | RTC_MODE; HalpWriteCmos(RTC_REGISTER_A, RegisterA); /* Save old IDT entry */ IdtPointer = KiGetIdtEntry(Pcr, HalpRtcClockVector); OldIdtEntry = *IdtPointer; /* Set the calibration ISR */ KeRegisterInterruptHandler(HalpRtcClockVector, TscCalibrationISR); /* Reset TSC value to 0 */ __writemsr(MSR_RDTSC, 0); /* Enable the timer interupt */ HalEnableSystemInterrupt(HalpRtcClockVector, CLOCK_LEVEL, Latched); /* Read register C, so that the next interrupt can happen */ HalpReadCmos(RTC_REGISTER_C);; /* Wait for completion */ _enable(); while (TscCalibrationPhase < NUM_SAMPLES) _ReadWriteBarrier(); _disable(); /* Disable the periodic interrupt in the CMOS */ HalpWriteCmos(RTC_REGISTER_B, RegisterB & ~RTC_REG_B_PI); /* Disable the timer interupt */ HalDisableSystemInterrupt(HalpRtcClockVector, CLOCK_LEVEL); /* Restore old IDT entry */ *IdtPointer = OldIdtEntry; /* Calculate an average, using simplified linear regression */ HalpCpuClockFrequency.QuadPart = DoLinearRegression(NUM_SAMPLES - 1, TscCalibrationArray); /* Restore flags */ __writeeflags(Flags); }