1
0
Files
irix-657m-src/stand/arcs/ide/EVEREST/lib/rtc_access.c
2022-09-29 17:59:04 +03:00

325 lines
7.8 KiB
C

/**************************************************************************
* *
* Copyright (C) 1992, Silicon Graphics, Inc. *
* *
* These coded instructions, statements, and computer programs contain *
* unpublished proprietary information of Silicon Graphics, Inc., and *
* are protected by Federal copyright law. They may not be disclosed *
* to third parties or copied or duplicated in any form, in whole or *
* in part, without the prior written consent of Silicon Graphics, Inc. *
* *
**************************************************************************/
/************************************************************************
* *
* rtc_access.c - read/write routines for the RTC/NVRAM *
* *
************************************************************************/
#include <sys/types.h>
#include <sys/sbd.h>
#include <sys/EVEREST/everest.h>
#include <sys/EVEREST/addrs.h>
#include <sys/EVEREST/evmp.h>
#include <sys/EVEREST/io4.h>
#include <sys/EVEREST/epc.h>
#include <sys/EVEREST/nvram.h>
#include <sys/EVEREST/evconfig.h>
#include <rtc_access.h>
#ident "arcs/ide/EVEREST/pbus/rtc_access.c $Revision: 1.4 $"
/*
* Get NVRAM values. These routines are endian-independent.
*/
#define NVRAM_ADDR(_region, _adap, _x) \
(SWIN_BASE(_region, _adap) + EPC_NVRTC + (_x) + BYTE_SELECT)
#define NVRAM_GET(_region, _adap, _reg) \
( *((unsigned char *) NVRAM_ADDR(_region,_adap, _reg)))
#define NVRAM_SET(_region, _adap, _reg, _value) \
NVRAM_GET(_region, _adap, _reg) = (_value);
#define EPC_PRST_RTC 0x8 /* PRST bit for Pbus device 3 (RTC) */
#define DEL_100_MS 100000 /* 100 Ms delay for us_delay */
/*
* rtc_reset()
* Resets the RTC chip
*/
void rtc_reset(int region, int adap)
{
/*
* resets the RTC chip, holds it reset for 100 ms, then relases it
* and waits 500 ms for chip to recover before returning
*/
EPC_SET(region, adap, EPC_PRSTSET, EPC_PRST_RTC);
us_delay(DEL_100_MS);
EPC_SET(region, adap, EPC_PRSTCLR, EPC_PRST_RTC);
us_delay(5*DEL_100_MS);
}
/*
* ide_get_nvreg()
* Read a byte from the NVRAM.
*/
uint
ide_get_nvreg(int region, int adap, uint offset)
{
uint value;
/* First set up the XRAM Page register */
NVRAM_SET(region, adap, NVR_XRAMPAGE, XRAM_PAGE(offset));
value = (uint) NVRAM_GET(region, adap, XRAM_REG(offset));
return value;
}
/*
* ide_set_nvreg()
* Writes a byte into the NVRAM
*/
int
ide_set_nvreg(int region, int adap, uint offset, char byte)
{
uint value;
/* First set up the XRAM Page register */
NVRAM_SET(region, adap, NVR_XRAMPAGE, XRAM_PAGE(offset));
NVRAM_SET(region, adap, XRAM_REG(offset), byte);
value = NVRAM_GET(region, adap, XRAM_REG(offset));
if (value == byte)
return 0;
else
return -1;
}
/*
* get_rtcreg()
* Read a byte from a RTC register
*/
uint
get_rtcreg(int region, int adap, uint offset)
{
uint value;
/* First set up the RTC address register */
NVRAM_SET(region, adap, (NVR_RTC + NVR_RTC_ADDR), offset);
/*
* just an experiment to see if we have timing problems
*/
us_delay(50);
/* Now read the correct value from the RTC data register */
value = (uint) NVRAM_GET(region, adap, (NVR_RTC + NVR_RTC_DATA));
return value;
}
/*
* set_rtcreg()
* Writes a byte into a RTC register
*/
int
set_rtcreg(int region, int adap, uint offset, char byte)
{
uint value;
/* First set up the RTC address register */
NVRAM_SET(region, adap, (NVR_RTC + NVR_RTC_ADDR), offset);
/*
* just an experiment to see if we have timing problems
*/
us_delay(50);
/* write the value to the RTC data register */
NVRAM_SET(region, adap, (NVR_RTC + NVR_RTC_DATA), byte);
/*
* just an experiment to see if we have timing problems
*/
us_delay(50);
/* check to make sure we can read the value we set back */
value = (uint) NVRAM_GET(region, adap, (NVR_RTC + NVR_RTC_DATA));
if (value == byte)
return 0;
else
return -1;
}
/*
* get_rtcvals()
* Saves current RTC values into an array of chars of size RTCSIZE
* since it saves the registers in order, the calling routine can
* modify the saved contents at will.
*/
void
get_rtcvals(int region, int adap, char *savearr)
{
int regnum;
char savloc;
/*
* disable updates while reading
*/
savloc = get_rtcreg(region, adap, NVR_RTCB);
set_rtcreg(region, adap, NVR_RTCB, savloc|NVR_SET);
for(regnum = 0; regnum < RTCSIZE; regnum++)
*savearr++ = get_rtcreg(region, adap, regnum);
/*
* restore previous operating values
*/
set_rtcreg(region, adap, NVR_RTCB, savloc);
}
/*
* set_rtcvals()
* Sets RTC to parameters passed via an array of chars of size RTCSIZE
* This routine presumes that the contents of the array are in the same
* order as the registers in the RTC chip, and does *no* bounds or error
* checking - ie, garbage in, garbage out
*/
void
set_rtcvals(int region, int adap, char *savearr)
{
int regnum;
char *savep;
/*
* hold off updates, but set up rest of format to match the value to be
* written
*/
set_rtcreg(region, adap, NVR_RTCB, NVR_SET|savearr[NVR_RTCB]);
set_rtcreg(region, adap, NVR_RTCA, savearr[NVR_RTCA]);
/*
* write the time info into the timer registers
*/
for(regnum = 0, savep = savearr; regnum <= NVR_YEAR; regnum++, savep++)
set_rtcreg(region, adap, regnum, *savep);
/*
* restore reg B (especially the SET bit) to the currect value. If the
* set bit is clear, this should restart the clock
*/
set_rtcreg(region, adap, NVR_RTCB, savearr[NVR_RTCB]);
}
/*
* used by add_time
*/
static int month_days[12] = {
31, /* January */
28, /* February */
31, /* March */
30, /* April */
31, /* May */
30, /* June */
31, /* July */
31, /* August */
30, /* September */
31, /* October */
30, /* November */
31 /* December */
};
/*
* add_time(timearr, secs) - adds "secs" seconds to the values in "timearr"
*
* This routine assumes that the time is stored in an array of chars in
* the same order as the registers in the RTC. It also assumes that the
* times given are in binary, 24 hour, format.
*
* Vastly simplified - it ignores leap years, daylight savings, etc. It
* also skips bounds checking for ridiculously large values of "secs".
*/
void
add_time(char *timearr, int secs)
{
int sec, min, hour, day, dayw, month, year;
sec = timearr[NVR_SEC];
min = timearr[NVR_MIN];
hour = timearr[NVR_HOUR];
day = timearr[NVR_DAY];
dayw = timearr[NVR_WEEKDAY];
month = timearr[NVR_MONTH];
year = timearr[NVR_YEAR];
sec += secs;
while (sec > 59) {
min++;
sec -= 60;
}
while (min > 59) {
hour++;
min -= 60;
}
while (hour > 23) {
day++;
dayw++;
hour -= 24;
}
while (dayw > 7) {
dayw -= 7;
}
while (day > month_days[year]) {
day -= month_days[year];
month++;
if (month > 12) {
year++;
month -= 12;
}
}
}
static char *month[] = {
"",
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
};
void
date_stamp(void)
{
int sec, min, hour, day, mon, year;
sec = get_rtcreg(EPC_REGION, EPC_ADAPTER, NVR_SEC);
min = get_rtcreg(EPC_REGION, EPC_ADAPTER, NVR_MIN);
hour = get_rtcreg(EPC_REGION, EPC_ADAPTER, NVR_HOUR);
day = get_rtcreg(EPC_REGION, EPC_ADAPTER, NVR_DAY);
mon= get_rtcreg(EPC_REGION, EPC_ADAPTER, NVR_MONTH);
year = get_rtcreg(EPC_REGION, EPC_ADAPTER, NVR_YEAR);
/* date from the epoch */
year += 1970;
printf("%s %u %u, %02u:%02u:%02u GMT\n",
month[mon], day, year, hour, min, sec);
}