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/halraw/alpha/pcrtc.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/halraw/alpha/pcrtc.c')
-rw-r--r-- | private/ntos/nthals/halraw/alpha/pcrtc.c | 383 |
1 files changed, 383 insertions, 0 deletions
diff --git a/private/ntos/nthals/halraw/alpha/pcrtc.c b/private/ntos/nthals/halraw/alpha/pcrtc.c new file mode 100644 index 000000000..b5006ddf7 --- /dev/null +++ b/private/ntos/nthals/halraw/alpha/pcrtc.c @@ -0,0 +1,383 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation +Copyright (c) 1992, 1993 Digital Equipment Corporation + +Module Name: + + pcrtc.c + +Abstract: + + This module implements the HAL set/query realtime clock routines for + the standard pc-compatible real time clock use on Alpha AXP systems. + +Author: + + David N. Cutler (davec) 5-May-1991 + Jeff McLeman (mcleman) 3-Jun-1992 + +Environment: + + Kernel mode + +Revision History: + + 13-Jul-1992 Jeff McLeman + use VTI access routines to access clock + + 3-June-1992 Jeff McLeman + Adapt this module into a Jensen specific module + +--*/ + +#include "halp.h" +#include "pcrtc.h" + +// +// Local function prototypes. +// + +BOOLEAN +HalQueryRealTimeClock ( + OUT PTIME_FIELDS TimeFields + ); + +BOOLEAN +HalSetRealTimeClock ( + IN PTIME_FIELDS TimeFields + ); + +UCHAR +HalpReadClockRegister ( + UCHAR Register + ); + +VOID +HalpWriteClockRegister ( + UCHAR Register, + UCHAR Value + ); + +#ifdef AXP_FIRMWARE + +// +// Put these functions in the discardable text section. +// + +#pragma alloc_text(DISTEXT, HalQueryRealTimeClock ) +#pragma alloc_text(DISTEXT, HalSetRealTimeClock ) +#pragma alloc_text(DISTEXT, HalpReadClockRegister ) +#pragma alloc_text(DISTEXT, HalpWriteClockRegister ) + +#endif // AXP_FIRMWARE + +// +// Define globals used to map the realtime clock address and data ports. +// + +PVOID HalpRtcAddressPort = NULL; +PVOID HalpRtcDataPort = NULL; + + +BOOLEAN +HalQueryRealTimeClock ( + OUT PTIME_FIELDS TimeFields + ) + +/*++ + +Routine Description: + + This routine queries the realtime clock. + + N.B. This routine assumes that the caller has provided any required + synchronization to query the realtime clock information. + +Arguments: + + TimeFields - Supplies a pointer to a time structure that receives + the realtime clock information. + +Return Value: + + If the power to the realtime clock has not failed, then the time + values are read from the realtime clock and a value of TRUE is + returned. Otherwise, a value of FALSE is returned. + +--*/ + +{ + + UCHAR DataByte; + BOOLEAN Status; + KIRQL OldIrql; + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + // + // If the realtime clock battery is still functioning, then read + // the realtime clock values, and return a function value of TRUE. + // Otherwise, return a function value of FALSE. + // + + DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD); + if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) { + + // + // Wait until the realtime clock is not being updated. + // + + do { + DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERA); + } while (((PRTC_CONTROL_REGISTER_A)(&DataByte))->UpdateInProgress == 1); + + // + // Read the realtime clock values. + // + + TimeFields->Year = 1980 + (CSHORT)HalpReadClockRegister(RTC_YEAR); + TimeFields->Month = (CSHORT)HalpReadClockRegister(RTC_MONTH); + TimeFields->Day = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_MONTH); + TimeFields->Weekday = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_WEEK) - 1; + TimeFields->Hour = (CSHORT)HalpReadClockRegister(RTC_HOUR); + TimeFields->Minute = (CSHORT)HalpReadClockRegister(RTC_MINUTE); + TimeFields->Second = (CSHORT)HalpReadClockRegister(RTC_SECOND); + TimeFields->Milliseconds = 0; + Status = TRUE; + + } else { + Status = FALSE; + } + + KeLowerIrql(OldIrql); + return(Status); +} + +BOOLEAN +HalSetRealTimeClock ( + IN PTIME_FIELDS TimeFields + ) + +/*++ + +Routine Description: + + This routine sets the realtime clock. + + N.B. This routine is required to provide any synchronization necessary + to set the realtime clock information. + +Arguments: + + TimeFields - Supplies a pointer to a time structure that specifies the + realtime clock information. + +Return Value: + + If the power to the realtime clock has not failed, then the time + values are written to the realtime clock and a value of TRUE is + returned. Otherwise, a value of FALSE is returned. + +--*/ + +{ + KIRQL OldIrql; + + UCHAR DataByte; + + // + // If the realtime clock battery is still functioning, then write + // the realtime clock values, and return a function value of TRUE. + // Otherwise, return a function value of FALSE. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD); + if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) { + + // + // Set the realtime clock control to set the time. + // + + DataByte = 0; + ((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1; + ((PRTC_CONTROL_REGISTER_B)(&DataByte))->DataMode = 1; + ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 1; + +#ifdef RTC_SQE + + // + // If the platform requires it, make sure that the Square + // Wave output of the RTC is turned on. + // + + ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SquareWaveEnable = 1; + +#endif //RTC_SQE + + HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte); + + // + // Write the realtime clock values. + // + + HalpWriteClockRegister(RTC_YEAR, (UCHAR)(TimeFields->Year - 1980)); + HalpWriteClockRegister(RTC_MONTH, (UCHAR)TimeFields->Month); + HalpWriteClockRegister(RTC_DAY_OF_MONTH, (UCHAR)TimeFields->Day); + HalpWriteClockRegister(RTC_DAY_OF_WEEK, (UCHAR)(TimeFields->Weekday + 1)); + HalpWriteClockRegister(RTC_HOUR, (UCHAR)TimeFields->Hour); + HalpWriteClockRegister(RTC_MINUTE, (UCHAR)TimeFields->Minute); + HalpWriteClockRegister(RTC_SECOND, (UCHAR)TimeFields->Second); + + // + // Set the realtime clock control to update the time. + // (Make sure periodic interrupt is enabled) + // + + ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 0; + ((PRTC_CONTROL_REGISTER_B)(&DataByte))->TimerInterruptEnable = 1; + HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte); + KeLowerIrql(OldIrql); + return TRUE; + + } else { + KeLowerIrql(OldIrql); + return FALSE; + } +} + + +UCHAR +HalpReadClockRegister ( + UCHAR Register + ) + +/*++ + +Routine Description: + + This routine reads the specified realtime clock register. + +Arguments: + + Register - Supplies the number of the register whose value is read. + +Return Value: + + The value of the register is returned as the function value. + +--*/ + +{ + // + // Read the realtime clock register value. + // + + WRITE_PORT_UCHAR( HalpRtcAddressPort, Register ); + + return READ_PORT_UCHAR( HalpRtcDataPort ); +} + +VOID +HalpWriteClockRegister ( + UCHAR Register, + UCHAR Value + ) + +/*++ + +Routine Description: + + This routine writes the specified value to the specified realtime + clock register. + +Arguments: + + Register - Supplies the number of the register whose value is written. + + Value - Supplies the value that is written to the specified register. + +Return Value: + + None + +--*/ + +{ + // + // Write the realtime clock register value. + // + + WRITE_PORT_UCHAR( HalpRtcAddressPort, Register ); + + WRITE_PORT_UCHAR( HalpRtcDataPort, Value ); + + return; +} + + +#if 0 // ecrfix - should not be in this common routine!!!! +VOID +HalpProgramIntervalTimer( + IN ULONG RateSelect + ) + +/*++ + +Routine Description: + + This function is called to program the interval timer. It is used during + Phase 1 initialization to start the heartbeat timer. It also used by + the clock interrupt interrupt routine to change the hearbeat timer rate + when a call to HalSetTimeIncrement has been made in the previous time slice. + + On Sable the periodic interrupt comes from the square ware output of + the Dallas 1489A RTC on the Standard I/O board. Each processor + receives this clock phase shifted by at least 90 degrees from all + other processors. The periodic interrupt from the RTC is not used and + thus doesn't need to be enabled or acknowledged. Each processor has + its own clock interrupt latch that is cleared locally. This routine is + not used for Sable platforms. + + Because of the phase shifting among the processors, the clock is + half the rate given to the RTC. So, the RTC is programmed twice + as fast as on a system that takes the RTC periodic interrupt in + directly. + +Arguments: + + RateSelect - Supplies rate select to be placed in the clock. + +Return Value: + + None. + +--*/ + +{ + UCHAR DataByte; + + // + // Set the new rate + // + DataByte = 0; + ((PRTC_CONTROL_REGISTER_A)(&DataByte))->RateSelect = (UCHAR)RateSelect; + ((PRTC_CONTROL_REGISTER_A)(&DataByte))->TimebaseDivisor = RTC_TIMEBASE_DIVISOR; + HalpWriteClockRegister( RTC_CONTROL_REGISTERA, DataByte ); + + // + // Set the correct mode + // + DataByte = 0; +#if defined(RTC_SQE) + ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SquareWaveEnable = 1; +#else + ((PRTC_CONTROL_REGISTER_B)(&DataByte))->TimerInterruptEnable = 1; +#endif + + ((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1; + ((PRTC_CONTROL_REGISTER_B)(&DataByte))->DataMode = 1; + HalpWriteClockRegister( RTC_CONTROL_REGISTERB, DataByte ); +} +#endif |