387 lines
8.9 KiB
C
387 lines
8.9 KiB
C
/*++
|
||
|
||
Copyright (c) 1991 Microsoft Corporation
|
||
|
||
Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
|
||
contains copyrighted material. Use of this file is restricted
|
||
by the provisions of a Motorola Software License Agreement.
|
||
|
||
Module Name:
|
||
|
||
pxtime.c
|
||
|
||
Abstract:
|
||
|
||
This module implements the HAL set/query realtime clock routines for
|
||
a PowerPC system.
|
||
|
||
Author:
|
||
|
||
David N. Cutler (davec) 5-May-1991
|
||
|
||
Environment:
|
||
|
||
Kernel mode
|
||
|
||
Revision History:
|
||
|
||
Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial Power PC port
|
||
|
||
Change real time clock mapping to port 71.
|
||
Code assumes the DS1385S chip is compatible with existing
|
||
PC/AT type RTC's. The only known exception to PC/AT
|
||
compatibility on S-FOOT is the use of ports 810 and 812.
|
||
These ports provide password security for the RTC's NVRAM,
|
||
and are currently unused in this port since this address space
|
||
is available from kernel mode only in NT.
|
||
|
||
Steve Johns (sjohns@pets.sps.mot.com)
|
||
Changed to support years > 1999
|
||
|
||
--*/
|
||
|
||
#include "halp.h"
|
||
#include "pxds1585.h"
|
||
#include "eisa.h"
|
||
|
||
|
||
//
|
||
// Define forward referenced procedure prototypes.
|
||
//
|
||
|
||
static UCHAR
|
||
HalpReadRawClockRegister (
|
||
UCHAR Register
|
||
);
|
||
|
||
static VOID
|
||
HalpWriteRawClockRegister (
|
||
UCHAR Register,
|
||
UCHAR Value
|
||
);
|
||
|
||
static UCHAR
|
||
HalpReadClockRegister (
|
||
UCHAR Register
|
||
);
|
||
|
||
static VOID
|
||
HalpWriteClockRegister (
|
||
UCHAR Register,
|
||
UCHAR Value
|
||
);
|
||
|
||
BOOLEAN
|
||
HalQueryRealTimeClockDs (
|
||
OUT PTIME_FIELDS TimeFields
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine queries the realtime clock.
|
||
|
||
N.B. This routine is required to provide any synchronization necessary
|
||
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;
|
||
KIRQL 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.
|
||
//
|
||
|
||
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||
DataByte = HalpReadRawClockRegister(RTC_CONTROL_REGISTERD);
|
||
if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
|
||
|
||
//
|
||
// Wait until the realtime clock is not being updated.
|
||
//
|
||
|
||
do {
|
||
DataByte = HalpReadRawClockRegister(RTC_CONTROL_REGISTERA);
|
||
} while (((PRTC_CONTROL_REGISTER_A)(&DataByte))->UpdateInProgress == 1);
|
||
|
||
//
|
||
// Read the realtime clock values.
|
||
//
|
||
|
||
TimeFields->Year = 1900 + (CSHORT)HalpReadClockRegister(RTC_YEAR);
|
||
if (TimeFields->Year < 1980) TimeFields->Year += 100;
|
||
|
||
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;
|
||
KeLowerIrql(OldIrql);
|
||
return TRUE;
|
||
|
||
} else {
|
||
KeLowerIrql(OldIrql);
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
BOOLEAN
|
||
HalSetRealTimeClockDs (
|
||
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.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
UCHAR DataByte;
|
||
KIRQL OldIrql;
|
||
|
||
//
|
||
// 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 = HalpReadRawClockRegister(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))->SetTime = 1;
|
||
HalpWriteRawClockRegister(RTC_CONTROL_REGISTERB, DataByte);
|
||
|
||
//
|
||
// Write the realtime clock values.
|
||
//
|
||
|
||
if (TimeFields->Year > 1999)
|
||
HalpWriteClockRegister(RTC_YEAR, (UCHAR)(TimeFields->Year - 2000));
|
||
else
|
||
HalpWriteClockRegister(RTC_YEAR, (UCHAR)(TimeFields->Year - 1900));
|
||
|
||
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.
|
||
//
|
||
|
||
((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 0;
|
||
HalpWriteRawClockRegister(RTC_CONTROL_REGISTERB, DataByte);
|
||
KeLowerIrql(OldIrql);
|
||
return TRUE;
|
||
|
||
} else {
|
||
KeLowerIrql(OldIrql);
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
static UCHAR
|
||
HalpReadRawClockRegister (
|
||
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.
|
||
|
||
--*/
|
||
|
||
{
|
||
//
|
||
// Insert the realtime clock register number, and write the value back
|
||
// to the SIO NMI enable register. This selects the realtime clock register
|
||
// that is read. Note this is a write only register and the EISA NMI
|
||
// is always enabled.
|
||
//
|
||
|
||
//
|
||
// TEMPTEMP Disable NMI's for now because this is causing machines in the
|
||
// build lab to get NMI's during boot.
|
||
//
|
||
|
||
|
||
|
||
WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpIoControlBase)->NmiEnable,
|
||
Register);
|
||
|
||
//
|
||
// Read the realtime clock register value.
|
||
//
|
||
|
||
return READ_REGISTER_UCHAR(&((PRTC_CONTROL)HalpIoControlBase)->RtcData);
|
||
}
|
||
|
||
static UCHAR
|
||
HalpReadClockRegister (
|
||
UCHAR Register
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine reads the specified realtime clock register.
|
||
change return value from BCD to binary integer. I think the chip
|
||
can be configured to do this,... but as a quick fix I am doing it
|
||
here. (plj)
|
||
|
||
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.
|
||
|
||
--*/
|
||
|
||
{
|
||
UCHAR BcdValue;
|
||
|
||
|
||
BcdValue = HalpReadRawClockRegister(Register);
|
||
return (BcdValue >> 4) * 10 + (BcdValue & 0x0f);
|
||
}
|
||
|
||
static VOID
|
||
HalpWriteRawClockRegister (
|
||
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:
|
||
|
||
The value of the register is returned as the function value.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
//
|
||
// Insert the realtime clock register number, and write the value back
|
||
// to the SIO NMI enable register. This selects the realtime clock
|
||
// register that is written. Note this is a write only register and
|
||
// the SIO NMI is always enabled.
|
||
//
|
||
|
||
|
||
WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpIoControlBase)->NmiEnable,
|
||
Register);
|
||
|
||
//
|
||
// Write the realtime clock register value.
|
||
//
|
||
|
||
WRITE_REGISTER_UCHAR(&((PRTC_CONTROL)HalpIoControlBase)->RtcData, Value);
|
||
return;
|
||
}
|
||
|
||
static 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:
|
||
|
||
The value of the register is returned as the function value.
|
||
|
||
--*/
|
||
|
||
{
|
||
UCHAR BcdValue;
|
||
|
||
BcdValue = ((Value / 10) << 4) | (Value % 10);
|
||
HalpWriteRawClockRegister(Register, BcdValue);
|
||
return;
|
||
}
|