Use <dev/ic/mc146818.h>. Change systemclock settings. Usable values for

HZ are now 48/64/96.  This reduces the interrupt overhead, because we
don't need the extra division by 4 in the interrupt handler.
This commit is contained in:
leo 1995-05-28 19:38:49 +00:00
parent 04246ac4f8
commit d66ffa3fe1
2 changed files with 67 additions and 134 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: clock.c,v 1.2 1995/05/05 16:31:46 leo Exp $ */
/* $NetBSD: clock.c,v 1.3 1995/05/28 19:38:49 leo Exp $ */
/*
* Copyright (c) 1988 University of Utah.
@ -105,18 +105,17 @@ struct device *pdp, *dp;
void *auxp;
{
/*
* Initialize Timer-A in the ST-MFP. An exact reduce to HZ is not
* possible by hardware. We use a divisor of 64 and reduce by software
* with a factor of 4. The MFP clock runs at 2457600Hz. Therefore the
* timer runs at an effective rate of: 2457600/(64*4) = 9600Hz. The
* following expression works for all 'normal' values of hz.
* Initialize Timer-A in the ST-MFP. We use a divisor of 200.
* The MFP clock runs at 2457600Hz. Therefore the timer runs
* at an effective rate of: 2457600/200 = 12288Hz. The
* following expression works for 48, 64 or 96 hz.
*/
divisor = 9600/hz;
divisor = 12288/hz;
MFP->mf_tacr = 0; /* Stop timer */
MFP->mf_iera &= ~IA_TIMA; /* Disable timer interrupts */
MFP->mf_tadr = divisor; /* Set divisor */
printf(": system hz %d timer-A divisor %d\n", hz, divisor);
printf(": system hz %d timer-A divisor 200/%d\n", hz, divisor);
/*
* Initialize Timer-B in the ST-MFP. This timer is used by the 'delay'
@ -132,7 +131,7 @@ void *auxp;
void cpu_initclocks()
{
MFP->mf_tacr = T_Q064; /* Start timer */
MFP->mf_tacr = T_Q200; /* Start timer */
MFP->mf_ipra &= ~IA_TIMA; /* Clear pending interrupts */
MFP->mf_iera |= IA_TIMA; /* Enable timer interrupts */
MFP->mf_imra |= IA_TIMA; /* ..... */
@ -149,12 +148,9 @@ setstatclockrate(hz)
*/
clkread()
{
extern short clk_div;
u_int delta, elapsed;
elapsed = (divisor - MFP->mf_tadr) + ((4 - clk_div) * divisor);
delta = (elapsed * tick) / (divisor << 2);
u_int delta;
delta = ((divisor - MFP->mf_tadr) * tick) / divisor;
/*
* Account for pending clock interrupts
*/
@ -377,68 +373,41 @@ static char ldmsize[12] =
31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
static __inline__ int rtc_getclkreg(regno)
int regno;
{
RTC->rtc_regno = RTC_REGA;
RTC->rtc_regno = regno;
return(RTC->rtc_data & 0377);
}
static __inline__ void rtc_setclkreg(regno, value)
int regno, value;
{
RTC->rtc_regno = regno;
RTC->rtc_data = value;
}
static u_long
gettod()
{
int i, year, mon, day, hour, min, sec;
u_long new_time = 0;
char *msize;
int i, sps;
u_long new_time = 0;
char *msize;
mc_todregs clkregs;
/*
* Hold clock
*/
rtc_setclkreg(RTC_REGB, rtc_getclkreg(RTC_REGB) | RTC_B_SET);
sps = splhigh();
MC146818_GETTOD(RTC, &clkregs);
splx(sps);
/*
* Read clock
*/
sec = rtc_getclkreg(RTC_SEC);
min = rtc_getclkreg(RTC_MIN);
hour = rtc_getclkreg(RTC_HOUR);
day = rtc_getclkreg(RTC_DAY) - 1;
mon = rtc_getclkreg(RTC_MONTH) - 1;
year = rtc_getclkreg(RTC_YEAR) + STARTOFTIME;
/*
* Let it run again..
*/
rtc_setclkreg(RTC_REGB, rtc_getclkreg(RTC_REGB) & ~RTC_B_SET);
if(range_test(hour, 0, 23))
if(range_test(clkregs[MC_HOUR], 0, 23))
return(0);
if(range_test(day, 0, 30))
if(range_test(clkregs[MC_DOM], 1, 31))
return(0);
if (range_test(mon, 0, 11))
if (range_test(clkregs[MC_MONTH], 1, 12))
return(0);
if(range_test(year, STARTOFTIME, 2000))
if(range_test(clkregs[MC_YEAR], 0, 2000 - GEMSTARTOFTIME))
return(0);
clkregs[MC_YEAR] += GEMSTARTOFTIME;
for(i = STARTOFTIME; i < year; i++) {
for(i = BSDSTARTOFTIME; i < clkregs[MC_YEAR]; i++) {
if(is_leap(i))
new_time += 366;
else new_time += 365;
}
msize = is_leap(year) ? ldmsize : dmsize;
for(i = 0; i < mon; i++)
msize = is_leap(clkregs[MC_YEAR]) ? ldmsize : dmsize;
for(i = 0; i < (clkregs[MC_MONTH] - 1); i++)
new_time += msize[i];
new_time += day;
return((new_time * SECS_DAY) + (hour * 3600) + (min * 60) + sec);
new_time += clkregs[MC_DOM] - 1;
new_time *= SECS_DAY;
new_time += (clkregs[MC_HOUR] * 3600) + (clkregs[MC_MIN] * 60);
return(new_time + clkregs[MC_SEC]);
}
static int
@ -447,9 +416,10 @@ u_long newtime;
{
register long days, rem, year;
register char *ml;
int sec, min, hour, month;
int sps, sec, min, hour, month;
mc_todregs clkregs;
/* Number of days since Jan. 1 1970 */
/* Number of days since Jan. 1 'BSDSTARTOFTIME' */
days = newtime / SECS_DAY;
rem = newtime % SECS_DAY;
@ -464,14 +434,10 @@ u_long newtime;
/*
* Figure out the year. Day in year is left in 'days'.
*/
year = STARTOFTIME;
year = BSDSTARTOFTIME;
while(days >= (rem = is_leap(year) ? 366 : 365)) {
++year;
days -= rem;
}
while(days < 0) {
--year;
days += is_leap(year) ? 366 : 365;
++year;
days -= rem;
}
/*
@ -484,16 +450,18 @@ u_long newtime;
/*
* Now that everything is calculated, program the RTC
*/
rtc_setclkreg(RTC_REGB, RTC_B_SET);
rtc_setclkreg(RTC_REGA, RTC_A_DV1|RTC_A_RS2|RTC_A_RS3);
rtc_setclkreg(RTC_REGB, RTC_B_SET|RTC_B_SQWE|RTC_B_DM|RTC_B_24_12);
rtc_setclkreg(RTC_SEC, sec);
rtc_setclkreg(RTC_MIN, min);
rtc_setclkreg(RTC_HOUR, hour);
rtc_setclkreg(RTC_DAY, days+1);
rtc_setclkreg(RTC_MONTH, month+1);
rtc_setclkreg(RTC_YEAR, year-1970);
rtc_setclkreg(RTC_REGB, RTC_B_SQWE|RTC_B_DM|RTC_B_24_12);
mc146818_write(RTC, MC_REGA, MC_BASE_32_KHz);
mc146818_write(RTC, MC_REGB, MC_REGB_24HR | MC_REGB_BINARY);
sps = splhigh();
MC146818_GETTOD(RTC, &clkregs);
clkregs[MC_SEC] = sec;
clkregs[MC_MIN] = min;
clkregs[MC_HOUR] = hour;
clkregs[MC_DOM] = days+1;
clkregs[MC_MONTH] = month+1;
clkregs[MC_YEAR] = year - GEMSTARTOFTIME;
MC146818_PUTTOD(RTC, &clkregs);
splx(sps);
return(1);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: clockreg.h,v 1.1.1.1 1995/03/26 07:12:15 leo Exp $ */
/* $NetBSD: clockreg.h,v 1.2 1995/05/28 19:38:51 leo Exp $ */
/*
* Copyright (c) 1995 Leo Weppelman.
@ -47,61 +47,25 @@ struct rtc {
#define rtc_data rtc_dat[3] /* data register */
/*
* Register number definitions
* Pull in general mc146818 definitions
*/
#define RTC_SEC 0
#define RTC_ASEC 1
#define RTC_MIN 2
#define RTC_A_MIN 3
#define RTC_HOUR 4
#define RTC_A_HOUR 5
#define RTC_WDAY 6
#define RTC_DAY 7
#define RTC_MONTH 8
#define RTC_YEAR 9
#define RTC_REGA 10
#define RTC_REGB 11
#define RTC_REGC 12
#define RTC_REGD 13
#define RTC_RAMBOT 14 /* Reg. offset of nv-RAM */
#define RTC_RAMSIZ 50 /* #bytes of nv-RAM available */
#include <dev/ic/mc146818.h>
/*
* Define fields for register A
*/
#define RTC_A_UIP 0x80 /* Update In Progress */
#define RTC_A_DV2 0x40 /* Divider select */
#define RTC_A_DV1 0x20 /* Divider select */
#define RTC_A_DV0 0x10 /* Divider select */
#define RTC_A_RS3 0x08 /* Rate Select */
#define RTC_A_RS2 0x04 /* Rate Select */
#define RTC_A_RS1 0x02 /* Rate Select */
#define RTC_A_RS0 0x01 /* Rate Select */
__inline__ u_int mc146818_read(rtc, regno)
void *rtc;
u_int regno;
{
((struct rtc *)rtc)->rtc_regno = regno;
return(((struct rtc *)rtc)->rtc_data & 0377);
}
/*
* Define fields for register B
*/
#define RTC_B_SET 0x80 /* SET date/time */
#define RTC_B_PIE 0x40 /* Periodic Int. Enable */
#define RTC_B_AIE 0x20 /* Alarm Int. Enable */
#define RTC_B_UIE 0x10 /* Update Ended Int. Enable */
#define RTC_B_SQWE 0x08 /* Square Wave Output Enable */
#define RTC_B_DM 0x04 /* Binary Data mode */
#define RTC_B_24_12 0x02 /* 24 Hour mode */
#define RTC_B_DSE 0x01 /* DST Enable */
/*
* Define fields for register C
*/
#define RTC_C_IRQF 0x80 /* IRQ flag */
#define RTC_C_PF 0x40 /* Periodic Int. flag */
#define RTC_C_AF 0x20 /* Alarm Int. flag */
#define RTC_C_UF 0x10 /* Update Ended Int. flag */
/*
* Define fields for register D
*/
#define RTC_D_VRT 0x80 /* Valid Ram and Time */
__inline__ void mc146818_write(rtc, regno, value)
void *rtc;
u_int regno, value;
{
((struct rtc *)rtc)->rtc_regno = regno;
((struct rtc *)rtc)->rtc_data = value;
}
/*
* Some useful constants/macros
@ -110,5 +74,6 @@ struct rtc {
#define range_test(n, l, h) ((n) < (l) || (n) > (h))
#define SECS_DAY 86400L
#define SECS_HOUR 3600L
#define STARTOFTIME 1970
#define GEMSTARTOFTIME ((machineid & ATARI_CLKBROKEN) ? 1970 : 1968)
#define BSDSTARTOFTIME 1970
#endif /* _CLOCKREG_H */