141 lines
3.9 KiB
C
141 lines
3.9 KiB
C
/* readclock - read the AT real time clock Authors: T. Holm & E. Froese */
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* readclock.c */
|
|
/* */
|
|
/* Read the AT real time clock, write the time to */
|
|
/* standard output in a form usable by date(1). */
|
|
/* If the system is an AT then the time is read */
|
|
/* from the built-in clock, and written to standard */
|
|
/* output in the form: */
|
|
/* */
|
|
/* mmddyyhhmmss */
|
|
/* */
|
|
/* If the system is not an AT then ``-q'' is written */
|
|
/* to standard output. This is useful for placement in */
|
|
/* the ``/etc/rc'' script: */
|
|
/* */
|
|
/* /usr/bin/date `/usr/bin/readclock` </dev/tty */
|
|
/* */
|
|
/************************************************************************/
|
|
/* origination 1987-Dec-29 efth */
|
|
/************************************************************************/
|
|
|
|
|
|
|
|
#define CPU_TYPE_SEGMENT 0xFFFF /* BIOS segment for CPU type */
|
|
#define CPU_TYPE_OFFSET 0x000E /* BIOS offset for CPU type */
|
|
#define PC_AT 0xFC /* IBM code for PC-AT (0xFFFFE) */
|
|
#define PS_386 0xF8 /* IBM code for 386 PS/2's */
|
|
|
|
|
|
#define CLK_ELE 0x70 /* ptr corresponding to element of time to be*/
|
|
#define CLK_IO 0x71 /* read or written is written to port clk_ele*/
|
|
/* The element can then be read or written by */
|
|
/* Reading or writing port clk_io. */
|
|
|
|
#define YEAR 9 /* Clock register addresses */
|
|
#define MONTH 8
|
|
#define DAY 7
|
|
#define HOUR 4
|
|
#define MINUTE 2
|
|
#define SECOND 0
|
|
#define STATUS 0x0b
|
|
|
|
#define BCD_TO_DEC(x) ( (x>>4) * 10 + (x & 0x0f) )
|
|
|
|
|
|
struct time {
|
|
unsigned year;
|
|
unsigned month;
|
|
unsigned day;
|
|
unsigned hour;
|
|
unsigned minute;
|
|
unsigned second;
|
|
};
|
|
|
|
|
|
|
|
main()
|
|
{
|
|
struct time time1;
|
|
struct time time2;
|
|
int i;
|
|
int cpu_type;
|
|
|
|
cpu_type = peek(CPU_TYPE_SEGMENT, CPU_TYPE_OFFSET);
|
|
if (cpu_type != PS_386 && cpu_type != PC_AT) {
|
|
printf("-q\n");
|
|
exit(1);
|
|
}
|
|
for (i = 0; i < 10; i++) {
|
|
get_time(&time1);
|
|
get_time(&time2);
|
|
|
|
if (time1.year == time2.year &&
|
|
time1.month == time2.month &&
|
|
time1.day == time2.day &&
|
|
time1.hour == time2.hour &&
|
|
time1.minute == time2.minute &&
|
|
time1.second == time2.second) {
|
|
printf("%02d%02d%02d%02d%02d%02d\n",
|
|
time1.month, time1.day, time1.year,
|
|
time1.hour, time1.minute, time1.second);
|
|
exit(0);
|
|
}
|
|
}
|
|
|
|
printf("-q\n");
|
|
exit(1);
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
/* */
|
|
/* get_time( time ) */
|
|
/* */
|
|
/* Update the structure pointed to by time with the current time */
|
|
/* as read from the hardware real-time clock of the AT. */
|
|
/* If necessary, the time is converted into a binary format before */
|
|
/* being stored in the structure. */
|
|
/* */
|
|
/***********************************************************************/
|
|
|
|
get_time(t)
|
|
struct time *t;
|
|
{
|
|
t->year = read_register(YEAR);
|
|
t->month = read_register(MONTH);
|
|
t->day = read_register(DAY);
|
|
t->hour = read_register(HOUR);
|
|
t->minute = read_register(MINUTE);
|
|
t->second = read_register(SECOND);
|
|
|
|
|
|
|
|
if ((read_register(STATUS) & 0x04) == 0) {
|
|
/* Convert BCD to binary if necessary */
|
|
t->year = BCD_TO_DEC(t->year);
|
|
t->month = BCD_TO_DEC(t->month);
|
|
t->day = BCD_TO_DEC(t->day);
|
|
t->hour = BCD_TO_DEC(t->hour);
|
|
t->minute = BCD_TO_DEC(t->minute);
|
|
t->second = BCD_TO_DEC(t->second);
|
|
}
|
|
}
|
|
|
|
|
|
read_register(reg_addr)
|
|
char reg_addr;
|
|
{
|
|
int val;
|
|
|
|
if (port_out(CLK_ELE, reg_addr) < 0 || port_in(CLK_IO, &val) < 0) {
|
|
printf("-q\n");
|
|
exit(1);
|
|
}
|
|
return(val);
|
|
}
|