wee@iris (Chris Wee) (05/09/88)
Does anyone have a program/tool to read the date and time from a standard IBM PC-AT? I'm tired of responding to MINIX's date query. Also, I would like to incorporate some history mechanism into the current shell. If such a product already exists, please e-mail its location to me immediately - my OS classmates are weary with typing. chris wee (wee@iris.ucdavis.edu)
Leisner.Henr@xerox.com (marty) (05/09/88)
Chris,
The answer is to get the time when you boot from the pc-at. I have the
following code in kernel/clock.c
#ifdef i286
#define CMOS_SECONDS 0
#define CMOS_MINUTES 2
#define CMOS_HOURS 4
#define CMOS_DATE 7
#define CMOS_MONTH 8
#define CMOS_YEAR 9
#define SECS_PER_DAY (24L*60L*60L)
#define SECS_PER_YEAR (365L*SECS_PER_DAY)
/* get the cmos time off the battery backed up clock (6845) */
static real_time get_cmos_time()
{
extern unsigned char read_cmos_ram();
real_time temp;
static int month_to_days[12] =
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
int year;
int month;
int day;
year = convert_bcd(read_cmos_ram(CMOS_YEAR));
month = convert_bcd(read_cmos_ram(CMOS_MONTH));
if(month > 2 && !(year % 4))
month_to_days[month - 1]++; /* leap year */
year -= 70; /* only want years since 1970 */
day = month_to_days[month - 1];
day += convert_bcd(read_cmos_ram(CMOS_DATE)) -1;
day += (year + 1)/4; /* take into account leap years */
temp = (real_time) year * SECS_PER_YEAR;
temp += (real_time) day*SECS_PER_DAY;
temp += (real_time) convert_bcd(read_cmos_ram(CMOS_HOURS))*3600L;
temp += (real_time) convert_bcd(read_cmos_ram(CMOS_MINUTES))*60L;
temp += (real_time) convert_bcd(read_cmos_ram(CMOS_SECONDS));
return temp;
}
#endif
And in init_clock:
#ifdef i286
real_time get_cmos_time();
/* get time off cmos battery backed up ram */
ps = disable();
lost_ticks = 0;
realtime = 0;
boot_time = get_cmos_time();
#endif
And stick the following in assembler somewhere:
CMOS_ADDR = 070H
CMOS_DATA = 071H
procdef read_cmos_ram,<<in_address,word>>
pushf
cli
mov ax,in_address
out CMOS_ADDR,al
xor ah,ah
in al,CMOS_DATA
popf
pret
pend read_cmos_ram
procdef convert_bcd,<<to_convert, byte>>
mov al,to_convert
; convert from bcd to decimal
mov bl,al
shr al,4
mov cl,10
mul cl
and bl,0fH
add al,bl
pret
pend convert_bcd
Please note the above code is quick and dirty. It seems to work fine. If
anyone sees any bugs, please let me know. Telling time is not one of my strong
points ;-). I'm only dealing with local time, no GMT stuff.
It is definitely a bad idea to let applications play with hardware ports
directly. I believe Xenix/Microport systems have some sortta clock device to
let setuid applications set the hardware real-time clock. Non-protected mode
Minix systems will allow you to do the above in user code, if you want to.
As for a history mechanism, I'm planning on bringing up the Alan Holub shell
written up in Dr. Dobb's Journal a couple of years ago. I use it under Ms/Dos
and it supplies reasonable capability. It should run nicely on Minix.
marty
ARPA: leisner.henr@xerox.com
GV: leisner.henr
NS: martin leisner:henr801c:xerox
UUCP: nsc!nscimg!amps!marty