Enable use of the RTC chip for the statistical clock. While this does
not provide the full accuracy of a randomized statistical clock, it does provide greater accuracy than the previous method, while not significantly increasing overhead. It also provides profiling support at 1024 Hz. You must re-compile config before making a new kernel, or you will end up with unresolved symbols. Reviewed uy: Bruce evans said it worked for him.
This commit is contained in:
parent
99ca219150
commit
8ea838500f
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
|
||||
* $Id: clock.c,v 1.12 1994/08/11 00:28:24 wollman Exp $
|
||||
* $Id: clock.c,v 1.13 1994/08/13 03:49:56 wollman Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -60,6 +60,7 @@
|
||||
#define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x))
|
||||
|
||||
void hardclock();
|
||||
void statclock();
|
||||
static int beeping;
|
||||
int timer0_divisor = TIMER_DIV(100); /* XXX should be hz */
|
||||
u_int timer0_prescale;
|
||||
@ -102,6 +103,44 @@ clkintr(frame)
|
||||
hardclock(&frame);
|
||||
}
|
||||
|
||||
static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
|
||||
|
||||
/*
|
||||
* This routine receives statistical clock interrupts from the RTC.
|
||||
* As explained above, these occur at 128 interrupts per second.
|
||||
* When profiling, we receive interrupts at a rate of 1024 Hz.
|
||||
*
|
||||
* This does not actually add as much overhead as it sounds, because
|
||||
* when the statistical clock is active, the hardclock driver no longer
|
||||
* needs to keep (inaccurate) statistics on its own. This decouples
|
||||
* statistics gathering from scheduling interrupts.
|
||||
*
|
||||
* The RTC chip requires that we read status register C (RTC_INTR)
|
||||
* to acknowledge an interrupt, before it will generate the next one.
|
||||
*/
|
||||
void
|
||||
rtcintr(struct clockframe frame)
|
||||
{
|
||||
u_char stat;
|
||||
stat = rtcin(RTC_INTR);
|
||||
if(stat & RTCIR_PERIOD) {
|
||||
statclock(&frame);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
printrtc(void)
|
||||
{
|
||||
outb(IO_RTC, RTC_STATUSA);
|
||||
printf("RTC status A = %x", inb(IO_RTC+1));
|
||||
outb(IO_RTC, RTC_STATUSB);
|
||||
printf(", B = %x", inb(IO_RTC+1));
|
||||
outb(IO_RTC, RTC_INTR);
|
||||
printf(", C = %x\n", inb(IO_RTC+1));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
void
|
||||
timerintr(struct clockframe frame)
|
||||
@ -338,9 +377,9 @@ startrtclock()
|
||||
|
||||
/* initialize brain-dead battery powered clock */
|
||||
outb (IO_RTC, RTC_STATUSA);
|
||||
outb (IO_RTC+1, 0x26);
|
||||
outb (IO_RTC+1, rtc_statusa);
|
||||
outb (IO_RTC, RTC_STATUSB);
|
||||
outb (IO_RTC+1, 2);
|
||||
outb (IO_RTC+1, RTCSB_24HR);
|
||||
|
||||
outb (IO_RTC, RTC_DIAG);
|
||||
if (s = inb (IO_RTC+1))
|
||||
@ -460,13 +499,17 @@ test_inittodr(time_t base)
|
||||
*/
|
||||
#define V(s) __CONCAT(V, s)
|
||||
extern void V(clk)();
|
||||
|
||||
extern void V(rtc)();
|
||||
|
||||
void
|
||||
enablertclock()
|
||||
{
|
||||
setidt(ICU_OFFSET+0, &V(clk), SDT_SYS386IGT, SEL_KPL);
|
||||
INTREN(IRQ0);
|
||||
setidt(ICU_OFFSET+8, &V(rtc), SDT_SYS386IGT, SEL_KPL);
|
||||
INTREN(IRQ8);
|
||||
outb(IO_RTC, RTC_STATUSB);
|
||||
outb(IO_RTC+1, RTCSB_PINTR | RTCSB_24HR);
|
||||
}
|
||||
|
||||
|
||||
@ -482,10 +525,19 @@ spinwait(int millisecs)
|
||||
void
|
||||
cpu_initclocks()
|
||||
{
|
||||
stathz = RTC_NOPROFRATE;
|
||||
profhz = RTC_PROFRATE;
|
||||
enablertclock();
|
||||
}
|
||||
|
||||
void
|
||||
setstatclockrate(int newhz)
|
||||
{
|
||||
if(newhz == RTC_PROFRATE) {
|
||||
rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF;
|
||||
} else {
|
||||
rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
|
||||
}
|
||||
outb(IO_RTC, RTC_STATUSA);
|
||||
outb(IO_RTC+1, rtc_statusa);
|
||||
}
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
|
||||
* $Id: clock.c,v 1.12 1994/08/11 00:28:24 wollman Exp $
|
||||
* $Id: clock.c,v 1.13 1994/08/13 03:49:56 wollman Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -60,6 +60,7 @@
|
||||
#define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x))
|
||||
|
||||
void hardclock();
|
||||
void statclock();
|
||||
static int beeping;
|
||||
int timer0_divisor = TIMER_DIV(100); /* XXX should be hz */
|
||||
u_int timer0_prescale;
|
||||
@ -102,6 +103,44 @@ clkintr(frame)
|
||||
hardclock(&frame);
|
||||
}
|
||||
|
||||
static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
|
||||
|
||||
/*
|
||||
* This routine receives statistical clock interrupts from the RTC.
|
||||
* As explained above, these occur at 128 interrupts per second.
|
||||
* When profiling, we receive interrupts at a rate of 1024 Hz.
|
||||
*
|
||||
* This does not actually add as much overhead as it sounds, because
|
||||
* when the statistical clock is active, the hardclock driver no longer
|
||||
* needs to keep (inaccurate) statistics on its own. This decouples
|
||||
* statistics gathering from scheduling interrupts.
|
||||
*
|
||||
* The RTC chip requires that we read status register C (RTC_INTR)
|
||||
* to acknowledge an interrupt, before it will generate the next one.
|
||||
*/
|
||||
void
|
||||
rtcintr(struct clockframe frame)
|
||||
{
|
||||
u_char stat;
|
||||
stat = rtcin(RTC_INTR);
|
||||
if(stat & RTCIR_PERIOD) {
|
||||
statclock(&frame);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
printrtc(void)
|
||||
{
|
||||
outb(IO_RTC, RTC_STATUSA);
|
||||
printf("RTC status A = %x", inb(IO_RTC+1));
|
||||
outb(IO_RTC, RTC_STATUSB);
|
||||
printf(", B = %x", inb(IO_RTC+1));
|
||||
outb(IO_RTC, RTC_INTR);
|
||||
printf(", C = %x\n", inb(IO_RTC+1));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
void
|
||||
timerintr(struct clockframe frame)
|
||||
@ -338,9 +377,9 @@ startrtclock()
|
||||
|
||||
/* initialize brain-dead battery powered clock */
|
||||
outb (IO_RTC, RTC_STATUSA);
|
||||
outb (IO_RTC+1, 0x26);
|
||||
outb (IO_RTC+1, rtc_statusa);
|
||||
outb (IO_RTC, RTC_STATUSB);
|
||||
outb (IO_RTC+1, 2);
|
||||
outb (IO_RTC+1, RTCSB_24HR);
|
||||
|
||||
outb (IO_RTC, RTC_DIAG);
|
||||
if (s = inb (IO_RTC+1))
|
||||
@ -460,13 +499,17 @@ test_inittodr(time_t base)
|
||||
*/
|
||||
#define V(s) __CONCAT(V, s)
|
||||
extern void V(clk)();
|
||||
|
||||
extern void V(rtc)();
|
||||
|
||||
void
|
||||
enablertclock()
|
||||
{
|
||||
setidt(ICU_OFFSET+0, &V(clk), SDT_SYS386IGT, SEL_KPL);
|
||||
INTREN(IRQ0);
|
||||
setidt(ICU_OFFSET+8, &V(rtc), SDT_SYS386IGT, SEL_KPL);
|
||||
INTREN(IRQ8);
|
||||
outb(IO_RTC, RTC_STATUSB);
|
||||
outb(IO_RTC+1, RTCSB_PINTR | RTCSB_24HR);
|
||||
}
|
||||
|
||||
|
||||
@ -482,10 +525,19 @@ spinwait(int millisecs)
|
||||
void
|
||||
cpu_initclocks()
|
||||
{
|
||||
stathz = RTC_NOPROFRATE;
|
||||
profhz = RTC_PROFRATE;
|
||||
enablertclock();
|
||||
}
|
||||
|
||||
void
|
||||
setstatclockrate(int newhz)
|
||||
{
|
||||
if(newhz == RTC_PROFRATE) {
|
||||
rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF;
|
||||
} else {
|
||||
rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
|
||||
}
|
||||
outb(IO_RTC, RTC_STATUSA);
|
||||
outb(IO_RTC+1, rtc_statusa);
|
||||
}
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
|
||||
* $Id: clock.c,v 1.12 1994/08/11 00:28:24 wollman Exp $
|
||||
* $Id: clock.c,v 1.13 1994/08/13 03:49:56 wollman Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -60,6 +60,7 @@
|
||||
#define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x))
|
||||
|
||||
void hardclock();
|
||||
void statclock();
|
||||
static int beeping;
|
||||
int timer0_divisor = TIMER_DIV(100); /* XXX should be hz */
|
||||
u_int timer0_prescale;
|
||||
@ -102,6 +103,44 @@ clkintr(frame)
|
||||
hardclock(&frame);
|
||||
}
|
||||
|
||||
static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
|
||||
|
||||
/*
|
||||
* This routine receives statistical clock interrupts from the RTC.
|
||||
* As explained above, these occur at 128 interrupts per second.
|
||||
* When profiling, we receive interrupts at a rate of 1024 Hz.
|
||||
*
|
||||
* This does not actually add as much overhead as it sounds, because
|
||||
* when the statistical clock is active, the hardclock driver no longer
|
||||
* needs to keep (inaccurate) statistics on its own. This decouples
|
||||
* statistics gathering from scheduling interrupts.
|
||||
*
|
||||
* The RTC chip requires that we read status register C (RTC_INTR)
|
||||
* to acknowledge an interrupt, before it will generate the next one.
|
||||
*/
|
||||
void
|
||||
rtcintr(struct clockframe frame)
|
||||
{
|
||||
u_char stat;
|
||||
stat = rtcin(RTC_INTR);
|
||||
if(stat & RTCIR_PERIOD) {
|
||||
statclock(&frame);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
printrtc(void)
|
||||
{
|
||||
outb(IO_RTC, RTC_STATUSA);
|
||||
printf("RTC status A = %x", inb(IO_RTC+1));
|
||||
outb(IO_RTC, RTC_STATUSB);
|
||||
printf(", B = %x", inb(IO_RTC+1));
|
||||
outb(IO_RTC, RTC_INTR);
|
||||
printf(", C = %x\n", inb(IO_RTC+1));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
void
|
||||
timerintr(struct clockframe frame)
|
||||
@ -338,9 +377,9 @@ startrtclock()
|
||||
|
||||
/* initialize brain-dead battery powered clock */
|
||||
outb (IO_RTC, RTC_STATUSA);
|
||||
outb (IO_RTC+1, 0x26);
|
||||
outb (IO_RTC+1, rtc_statusa);
|
||||
outb (IO_RTC, RTC_STATUSB);
|
||||
outb (IO_RTC+1, 2);
|
||||
outb (IO_RTC+1, RTCSB_24HR);
|
||||
|
||||
outb (IO_RTC, RTC_DIAG);
|
||||
if (s = inb (IO_RTC+1))
|
||||
@ -460,13 +499,17 @@ test_inittodr(time_t base)
|
||||
*/
|
||||
#define V(s) __CONCAT(V, s)
|
||||
extern void V(clk)();
|
||||
|
||||
extern void V(rtc)();
|
||||
|
||||
void
|
||||
enablertclock()
|
||||
{
|
||||
setidt(ICU_OFFSET+0, &V(clk), SDT_SYS386IGT, SEL_KPL);
|
||||
INTREN(IRQ0);
|
||||
setidt(ICU_OFFSET+8, &V(rtc), SDT_SYS386IGT, SEL_KPL);
|
||||
INTREN(IRQ8);
|
||||
outb(IO_RTC, RTC_STATUSB);
|
||||
outb(IO_RTC+1, RTCSB_PINTR | RTCSB_24HR);
|
||||
}
|
||||
|
||||
|
||||
@ -482,10 +525,19 @@ spinwait(int millisecs)
|
||||
void
|
||||
cpu_initclocks()
|
||||
{
|
||||
stathz = RTC_NOPROFRATE;
|
||||
profhz = RTC_PROFRATE;
|
||||
enablertclock();
|
||||
}
|
||||
|
||||
void
|
||||
setstatclockrate(int newhz)
|
||||
{
|
||||
if(newhz == RTC_PROFRATE) {
|
||||
rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF;
|
||||
} else {
|
||||
rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
|
||||
}
|
||||
outb(IO_RTC, RTC_STATUSA);
|
||||
outb(IO_RTC+1, rtc_statusa);
|
||||
}
|
||||
|
@ -30,7 +30,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
* $Id: spl.h,v 1.3 1994/08/02 07:39:06 davidg Exp $
|
||||
*/
|
||||
|
||||
#ifndef _MACHINE_IPL_H_
|
||||
@ -79,6 +79,7 @@ extern unsigned net_imask; /* group of interrupts masked with splimp() */
|
||||
extern volatile unsigned ipending; /* active interrupts masked by cpl */
|
||||
extern volatile unsigned netisr;
|
||||
extern unsigned tty_imask; /* group of interrupts masked with spltty() */
|
||||
extern unsigned stat_imask; /* interrupts masked with splstatclock() */
|
||||
|
||||
/*
|
||||
* ipending has to be volatile so that it is read every time it is accessed
|
||||
@ -110,7 +111,7 @@ static __inline int name(void) \
|
||||
GENSPL(splbio, cpl |= bio_imask)
|
||||
GENSPL(splclock, cpl = HWI_MASK | SWI_MASK)
|
||||
GENSPL(splhigh, cpl = HWI_MASK | SWI_MASK)
|
||||
GENSPL(splstatclock, cpl = HWI_MASK | SWI_MASK)
|
||||
GENSPL(splstatclock, cpl |= stat_imask | SWI_CLOCK_MASK)
|
||||
GENSPL(splimp, cpl |= net_imask)
|
||||
GENSPL(splnet, cpl |= SWI_NET_MASK)
|
||||
GENSPL(splsoftclock, cpl = SWI_CLOCK_MASK)
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
|
||||
* $Id: clock.c,v 1.12 1994/08/11 00:28:24 wollman Exp $
|
||||
* $Id: clock.c,v 1.13 1994/08/13 03:49:56 wollman Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -60,6 +60,7 @@
|
||||
#define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x))
|
||||
|
||||
void hardclock();
|
||||
void statclock();
|
||||
static int beeping;
|
||||
int timer0_divisor = TIMER_DIV(100); /* XXX should be hz */
|
||||
u_int timer0_prescale;
|
||||
@ -102,6 +103,44 @@ clkintr(frame)
|
||||
hardclock(&frame);
|
||||
}
|
||||
|
||||
static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
|
||||
|
||||
/*
|
||||
* This routine receives statistical clock interrupts from the RTC.
|
||||
* As explained above, these occur at 128 interrupts per second.
|
||||
* When profiling, we receive interrupts at a rate of 1024 Hz.
|
||||
*
|
||||
* This does not actually add as much overhead as it sounds, because
|
||||
* when the statistical clock is active, the hardclock driver no longer
|
||||
* needs to keep (inaccurate) statistics on its own. This decouples
|
||||
* statistics gathering from scheduling interrupts.
|
||||
*
|
||||
* The RTC chip requires that we read status register C (RTC_INTR)
|
||||
* to acknowledge an interrupt, before it will generate the next one.
|
||||
*/
|
||||
void
|
||||
rtcintr(struct clockframe frame)
|
||||
{
|
||||
u_char stat;
|
||||
stat = rtcin(RTC_INTR);
|
||||
if(stat & RTCIR_PERIOD) {
|
||||
statclock(&frame);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
printrtc(void)
|
||||
{
|
||||
outb(IO_RTC, RTC_STATUSA);
|
||||
printf("RTC status A = %x", inb(IO_RTC+1));
|
||||
outb(IO_RTC, RTC_STATUSB);
|
||||
printf(", B = %x", inb(IO_RTC+1));
|
||||
outb(IO_RTC, RTC_INTR);
|
||||
printf(", C = %x\n", inb(IO_RTC+1));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
void
|
||||
timerintr(struct clockframe frame)
|
||||
@ -338,9 +377,9 @@ startrtclock()
|
||||
|
||||
/* initialize brain-dead battery powered clock */
|
||||
outb (IO_RTC, RTC_STATUSA);
|
||||
outb (IO_RTC+1, 0x26);
|
||||
outb (IO_RTC+1, rtc_statusa);
|
||||
outb (IO_RTC, RTC_STATUSB);
|
||||
outb (IO_RTC+1, 2);
|
||||
outb (IO_RTC+1, RTCSB_24HR);
|
||||
|
||||
outb (IO_RTC, RTC_DIAG);
|
||||
if (s = inb (IO_RTC+1))
|
||||
@ -460,13 +499,17 @@ test_inittodr(time_t base)
|
||||
*/
|
||||
#define V(s) __CONCAT(V, s)
|
||||
extern void V(clk)();
|
||||
|
||||
extern void V(rtc)();
|
||||
|
||||
void
|
||||
enablertclock()
|
||||
{
|
||||
setidt(ICU_OFFSET+0, &V(clk), SDT_SYS386IGT, SEL_KPL);
|
||||
INTREN(IRQ0);
|
||||
setidt(ICU_OFFSET+8, &V(rtc), SDT_SYS386IGT, SEL_KPL);
|
||||
INTREN(IRQ8);
|
||||
outb(IO_RTC, RTC_STATUSB);
|
||||
outb(IO_RTC+1, RTCSB_PINTR | RTCSB_24HR);
|
||||
}
|
||||
|
||||
|
||||
@ -482,10 +525,19 @@ spinwait(int millisecs)
|
||||
void
|
||||
cpu_initclocks()
|
||||
{
|
||||
stathz = RTC_NOPROFRATE;
|
||||
profhz = RTC_PROFRATE;
|
||||
enablertclock();
|
||||
}
|
||||
|
||||
void
|
||||
setstatclockrate(int newhz)
|
||||
{
|
||||
if(newhz == RTC_PROFRATE) {
|
||||
rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF;
|
||||
} else {
|
||||
rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
|
||||
}
|
||||
outb(IO_RTC, RTC_STATUSA);
|
||||
outb(IO_RTC+1, rtc_statusa);
|
||||
}
|
||||
|
@ -36,7 +36,7 @@
|
||||
*
|
||||
* @(#)icu.s 7.2 (Berkeley) 5/21/91
|
||||
*
|
||||
* $Id: icu.s,v 1.9 1994/05/25 08:58:55 rgrimes Exp $
|
||||
* $Id: icu.s,v 1.10 1994/08/13 03:50:01 wollman Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -58,6 +58,8 @@ _cpl: .long HWI_MASK | SWI_MASK /* current priority (all off) */
|
||||
.globl _imen
|
||||
_imen: .long HWI_MASK /* interrupt mask enable (all h/w off) */
|
||||
_high_imask: .long HWI_MASK | SWI_MASK
|
||||
.globl _stat_imask
|
||||
_stat_imask: .long (1 << 8)
|
||||
.globl _tty_imask
|
||||
_tty_imask: .long 0
|
||||
.globl _bio_imask
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)rtc.h 7.1 (Berkeley) 5/12/91
|
||||
* $Id: rtc.h,v 1.3 1993/11/07 17:44:34 wollman Exp $
|
||||
* $Id: rtc.h,v 1.4 1993/12/18 01:12:47 ache Exp $
|
||||
*/
|
||||
|
||||
#ifndef _I386_ISA_RTC_H_
|
||||
@ -54,10 +54,28 @@
|
||||
#define RTC_DAY 0x07 /* day of month */
|
||||
#define RTC_MONTH 0x08 /* month of year */
|
||||
#define RTC_YEAR 0x09 /* month of year */
|
||||
|
||||
#define RTC_STATUSA 0x0a /* status register A */
|
||||
#define RTCSA_TUP 0x80 /* time update, don't look now */
|
||||
#define RTCSA_DIVIDER 0x20 /* divider correct for 32768 Hz */
|
||||
#define RTCSA_8192 0x03
|
||||
#define RTCSA_4096 0x04
|
||||
#define RTCSA_2048 0x05
|
||||
#define RTCSA_1024 0x06 /* default for profiling */
|
||||
#define RTCSA_PROF RTCSA_1024
|
||||
#define RTC_PROFRATE 1024
|
||||
#define RTCSA_512 0x07
|
||||
#define RTCSA_256 0x08
|
||||
#define RTCSA_128 0x09
|
||||
#define RTCSA_NOPROF RTCSA_128
|
||||
#define RTC_NOPROFRATE 128
|
||||
#define RTCSA_64 0x0a
|
||||
#define RTCSA_32 0x0b
|
||||
|
||||
#define RTC_STATUSB 0x0b /* status register B */
|
||||
#define RTCSB_HALT 0x80 /* stop clock updates */
|
||||
#define RTCSB_PINTR 0x40 /* periodic clock interrupt */
|
||||
#define RTCSB_24HR 0x02 /* 24-hour mode */
|
||||
|
||||
#define RTC_INTR 0x0c /* status register C (R) interrupt source */
|
||||
#define RTCIR_UPDATE 0x10 /* update intr */
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
|
||||
* $Id: clock.c,v 1.12 1994/08/11 00:28:24 wollman Exp $
|
||||
* $Id: clock.c,v 1.13 1994/08/13 03:49:56 wollman Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -60,6 +60,7 @@
|
||||
#define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x))
|
||||
|
||||
void hardclock();
|
||||
void statclock();
|
||||
static int beeping;
|
||||
int timer0_divisor = TIMER_DIV(100); /* XXX should be hz */
|
||||
u_int timer0_prescale;
|
||||
@ -102,6 +103,44 @@ clkintr(frame)
|
||||
hardclock(&frame);
|
||||
}
|
||||
|
||||
static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
|
||||
|
||||
/*
|
||||
* This routine receives statistical clock interrupts from the RTC.
|
||||
* As explained above, these occur at 128 interrupts per second.
|
||||
* When profiling, we receive interrupts at a rate of 1024 Hz.
|
||||
*
|
||||
* This does not actually add as much overhead as it sounds, because
|
||||
* when the statistical clock is active, the hardclock driver no longer
|
||||
* needs to keep (inaccurate) statistics on its own. This decouples
|
||||
* statistics gathering from scheduling interrupts.
|
||||
*
|
||||
* The RTC chip requires that we read status register C (RTC_INTR)
|
||||
* to acknowledge an interrupt, before it will generate the next one.
|
||||
*/
|
||||
void
|
||||
rtcintr(struct clockframe frame)
|
||||
{
|
||||
u_char stat;
|
||||
stat = rtcin(RTC_INTR);
|
||||
if(stat & RTCIR_PERIOD) {
|
||||
statclock(&frame);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
printrtc(void)
|
||||
{
|
||||
outb(IO_RTC, RTC_STATUSA);
|
||||
printf("RTC status A = %x", inb(IO_RTC+1));
|
||||
outb(IO_RTC, RTC_STATUSB);
|
||||
printf(", B = %x", inb(IO_RTC+1));
|
||||
outb(IO_RTC, RTC_INTR);
|
||||
printf(", C = %x\n", inb(IO_RTC+1));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
void
|
||||
timerintr(struct clockframe frame)
|
||||
@ -338,9 +377,9 @@ startrtclock()
|
||||
|
||||
/* initialize brain-dead battery powered clock */
|
||||
outb (IO_RTC, RTC_STATUSA);
|
||||
outb (IO_RTC+1, 0x26);
|
||||
outb (IO_RTC+1, rtc_statusa);
|
||||
outb (IO_RTC, RTC_STATUSB);
|
||||
outb (IO_RTC+1, 2);
|
||||
outb (IO_RTC+1, RTCSB_24HR);
|
||||
|
||||
outb (IO_RTC, RTC_DIAG);
|
||||
if (s = inb (IO_RTC+1))
|
||||
@ -460,13 +499,17 @@ test_inittodr(time_t base)
|
||||
*/
|
||||
#define V(s) __CONCAT(V, s)
|
||||
extern void V(clk)();
|
||||
|
||||
extern void V(rtc)();
|
||||
|
||||
void
|
||||
enablertclock()
|
||||
{
|
||||
setidt(ICU_OFFSET+0, &V(clk), SDT_SYS386IGT, SEL_KPL);
|
||||
INTREN(IRQ0);
|
||||
setidt(ICU_OFFSET+8, &V(rtc), SDT_SYS386IGT, SEL_KPL);
|
||||
INTREN(IRQ8);
|
||||
outb(IO_RTC, RTC_STATUSB);
|
||||
outb(IO_RTC+1, RTCSB_PINTR | RTCSB_24HR);
|
||||
}
|
||||
|
||||
|
||||
@ -482,10 +525,19 @@ spinwait(int millisecs)
|
||||
void
|
||||
cpu_initclocks()
|
||||
{
|
||||
stathz = RTC_NOPROFRATE;
|
||||
profhz = RTC_PROFRATE;
|
||||
enablertclock();
|
||||
}
|
||||
|
||||
void
|
||||
setstatclockrate(int newhz)
|
||||
{
|
||||
if(newhz == RTC_PROFRATE) {
|
||||
rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF;
|
||||
} else {
|
||||
rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
|
||||
}
|
||||
outb(IO_RTC, RTC_STATUSA);
|
||||
outb(IO_RTC+1, rtc_statusa);
|
||||
}
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)rtc.h 7.1 (Berkeley) 5/12/91
|
||||
* $Id: rtc.h,v 1.3 1993/11/07 17:44:34 wollman Exp $
|
||||
* $Id: rtc.h,v 1.4 1993/12/18 01:12:47 ache Exp $
|
||||
*/
|
||||
|
||||
#ifndef _I386_ISA_RTC_H_
|
||||
@ -54,10 +54,28 @@
|
||||
#define RTC_DAY 0x07 /* day of month */
|
||||
#define RTC_MONTH 0x08 /* month of year */
|
||||
#define RTC_YEAR 0x09 /* month of year */
|
||||
|
||||
#define RTC_STATUSA 0x0a /* status register A */
|
||||
#define RTCSA_TUP 0x80 /* time update, don't look now */
|
||||
#define RTCSA_DIVIDER 0x20 /* divider correct for 32768 Hz */
|
||||
#define RTCSA_8192 0x03
|
||||
#define RTCSA_4096 0x04
|
||||
#define RTCSA_2048 0x05
|
||||
#define RTCSA_1024 0x06 /* default for profiling */
|
||||
#define RTCSA_PROF RTCSA_1024
|
||||
#define RTC_PROFRATE 1024
|
||||
#define RTCSA_512 0x07
|
||||
#define RTCSA_256 0x08
|
||||
#define RTCSA_128 0x09
|
||||
#define RTCSA_NOPROF RTCSA_128
|
||||
#define RTC_NOPROFRATE 128
|
||||
#define RTCSA_64 0x0a
|
||||
#define RTCSA_32 0x0b
|
||||
|
||||
#define RTC_STATUSB 0x0b /* status register B */
|
||||
#define RTCSB_HALT 0x80 /* stop clock updates */
|
||||
#define RTCSB_PINTR 0x40 /* periodic clock interrupt */
|
||||
#define RTCSB_24HR 0x02 /* 24-hour mode */
|
||||
|
||||
#define RTC_INTR 0x0c /* status register C (R) interrupt source */
|
||||
#define RTCIR_UPDATE 0x10 /* update intr */
|
||||
|
Loading…
Reference in New Issue
Block a user