Cleanup the clock code. This includes:

o  Remove alpha specific timer code (mc146818A) and compiled-out
   calibration of said timer.
o  Remove i386 inherited timer code (i8253) and related acquire and
   release functions.
o  Move sysbeep() from clock.c to machdep.c and have it return
   ENODEV. Console beeps should be implemented using ACPI or if no
   such device is described, using the sound driver.
o  Move the sysctls related to adjkerntz, disable_rtc_set and
   wall_cmos_clock from machdep.c to clock.c, where the variables
   are.
o  Don't hardcode a hz value of 1024 in cpu_initclocks() and don't
   bother faking a stathz that's 1/8 of that. Keep it simple: hz
   defaults to HZ and stathz equals hz. This is also how it's done
   for sparc64.
o  Keep a per-CPU ITC counter (pc_clock) and adjustment (pc_clockadj)
   to calculate ITC skew and corrections. On average, we adjust the
   ITC match register once every ~1500 interrupts for a duration of
   2 consequtive interruprs. This is to correct the non-deterministic
   behaviour of the ITC interrupt (there's a delay between the match
   and the raising of the interrupt).
o  Add 4 debugging sysctls to monitor clock behaviour. Those are
   debug.clock_adjust_edges, debug.clock_adjust_excess,
   debug.clock_adjust_lost and debug.clock_adjust_ticks. The first
   counts the individual adjustment cycles (when the skew first
   crosses the threshold), the second counts the number of times the
   adjustment was excessive (any non-zero value is to be considered
   a bug), the third counts lost clock interrupts and the last counts
   the number of interrupts for which we applied an adjustment
   (debug.clock_adjust_ticks / debug.clock_adjust_edges gives the
   avarage duration of an individual adjustment -- should be ~2).

While here, remove some nearby (trivial) left-overs from alpha and
other cleanups.
This commit is contained in:
marcel 2003-08-04 05:13:18 +00:00
parent 0c6d0d5962
commit a9b84efaa9
8 changed files with 177 additions and 462 deletions

View File

@ -1,6 +1,3 @@
/* $FreeBSD$ */
/* $NetBSD: clock.c,v 1.20 1998/01/31 10:32:47 ross Exp $ */
/*
* Copyright (c) 1988 University of Utah.
* Copyright (c) 1992, 1993
@ -42,8 +39,10 @@
*
* @(#)clock.c 8.1 (Berkeley) 6/10/93
*/
/* $NetBSD: clock.c,v 1.20 1998/01/31 10:32:47 ross Exp $ */
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
@ -52,13 +51,11 @@
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/timetc.h>
#include <sys/pcpu.h>
#include <machine/pal.h>
#include <machine/sal.h>
#include <machine/clock.h>
#include <machine/clockvar.h>
#include <isa/isareg.h>
#include <ia64/ia64/timerreg.h>
#include <machine/cpu.h>
#define SECMIN ((unsigned)60) /* seconds per minute */
#define SECHOUR ((unsigned)(60*SECMIN)) /* seconds per hour */
@ -68,198 +65,107 @@
/*
* 32-bit time_t's can't reach leap years before 1904 or after 2036, so we
* can use a simple formula for leap years.
* XXX time_t is 64-bits on ia64.
*/
#define LEAPYEAR(y) (((y) % 4) == 0)
kobj_t clockdev;
int clockinitted;
int tickfix;
int tickfixinterval;
static int sysctl_machdep_adjkerntz(SYSCTL_HANDLER_ARGS);
int disable_rtc_set; /* disable resettodr() if != 0 */
SYSCTL_INT(_machdep, CPU_DISRTCSET, disable_rtc_set,
CTLFLAG_RW, &disable_rtc_set, 0, "");
int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */
SYSCTL_INT(_machdep, CPU_WALLCLOCK, wall_cmos_clock,
CTLFLAG_RW, &wall_cmos_clock, 0, "");
int adjkerntz; /* local offset from GMT in seconds */
int disable_rtc_set; /* disable resettodr() if != 0 */
int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */
u_int64_t itm_reload; /* reload ticks for clock */
static int beeping = 0;
SYSCTL_PROC(_machdep, CPU_ADJKERNTZ, adjkerntz, CTLTYPE_INT|CTLFLAG_RW,
&adjkerntz, 0, sysctl_machdep_adjkerntz, "I", "");
kobj_t clockdev;
int todr_initialized;
uint64_t ia64_clock_reload;
#ifndef SMP
static timecounter_get_t ia64_get_timecount;
static timecounter_get_t ia64_get_timecount;
static struct timecounter ia64_timecounter = {
ia64_get_timecount, /* get_timecount */
0, /* no poll_pps */
~0u, /* counter_mask */
~0u, /* counter_mask */
0, /* frequency */
"ITC" /* name */
};
static unsigned
ia64_get_timecount(struct timecounter* tc)
{
return ia64_get_itc();
}
#endif
/* Values for timerX_state: */
#define RELEASED 0
#define RELEASE_PENDING 1
#define ACQUIRED 2
#define ACQUIRE_PENDING 3
static int
sysctl_machdep_adjkerntz(SYSCTL_HANDLER_ARGS)
{
int error;
/* static u_char timer0_state; */
static u_char timer2_state;
/*
* Algorithm for missed clock ticks from Linux/alpha.
*/
/*
* Shift amount by which scaled_ticks_per_cycle is scaled. Shifting
* by 48 gives us 16 bits for HZ while keeping the accuracy good even
* for large CPU clock rates.
*/
#define FIX_SHIFT 48
static u_int64_t scaled_ticks_per_cycle;
static u_int32_t max_cycles_per_tick;
static u_int32_t last_time;
#if 0 /* not used yet */
static u_int32_t calibrate_clocks(u_int32_t firmware_freq);
#endif
error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
if (!error && req->newptr)
resettodr();
return (error);
}
void
clockattach(kobj_t dev)
{
/*
* Just bookkeeping.
*/
if (clockdev)
panic("clockattach: multiple clocks");
clockdev = dev;
#ifdef EVCNT_COUNTERS
evcnt_attach(dev, "intr", &clock_intr_evcnt);
#endif
/*
* Get the clock started.
*/
/* Get the clock started. */
CLOCK_INIT(clockdev);
}
/*
* Machine-dependent clock routines.
*
* Startrtclock restarts the real-time clock, which provides
* hardclock interrupts to kern_clock.c.
*
* Inittodr initializes the time of day hardware which provides
* date functions. Its primary function is to use some file
* system information in case the hardare clock lost state.
*
* Resettodr restores the time of day hardware after a time change.
*/
void
pcpu_initclock(void)
{
PCPU_SET(clockadj, 0);
PCPU_SET(clock, ia64_get_itc());
ia64_set_itm(PCPU_GET(clock) + ia64_clock_reload);
ia64_set_itv(CLOCK_VECTOR); /* highest priority class */
}
/*
* Start the real-time and statistics clocks. Leave stathz 0 since there
* are no other timers available.
* Start the real-time and statistics clocks. We use cr.itc and cr.itm
* to implement a 1000hz clock.
*/
void
cpu_initclocks()
{
u_int32_t freq;
/*
* We use cr.itc and cr.itm to implement a 1024hz clock.
*/
hz = 1024;
tick = 1000000 / hz; /* number of microseconds between interrupts */
tickfix = 1000000 - (hz * tick);
if (tickfix) {
int ftp;
ftp = min(ffs(tickfix), ffs(hz));
tickfix >>= (ftp - 1);
tickfixinterval = hz >> (ftp - 1);
}
if (!itc_frequency)
if (itc_frequency == 0)
panic("Unknown clock frequency");
freq = itc_frequency;
last_time = ia64_get_itc();
scaled_ticks_per_cycle = ((u_int64_t)hz << FIX_SHIFT) / freq;
max_cycles_per_tick = 2*freq / hz;
stathz = hz;
ia64_clock_reload = (itc_frequency + hz/2) / hz;
#ifndef SMP
ia64_timecounter.tc_frequency = freq;
ia64_timecounter.tc_frequency = itc_frequency;
tc_init(&ia64_timecounter);
#endif
itm_reload = (itc_frequency + hz/2) / hz;
ia64_set_itm(ia64_get_itc() + itm_reload);
ia64_set_itv(CLOCK_VECTOR); /* highest priority class */
stathz = 128;
pcpu_initclock();
}
#if 0 /* not used yet */
static u_int32_t
calibrate_clocks(u_int32_t firmware_freq)
{
u_int32_t start_pcc, stop_pcc;
int sec, start_sec;
if (bootverbose)
printf("Calibrating clock(s) ... ");
/* Read the mc146818A seconds counter. */
if (CLOCK_GETSECS(clockdev, &sec))
goto fail;
/* Wait for the mC146818A seconds counter to change. */
start_sec = sec;
for (;;) {
if (CLOCK_GETSECS(clockdev, &sec))
goto fail;
if (sec != start_sec)
break;
}
/* Start keeping track of the PCC. */
start_pcc = ia64_get_itc();
/*
* Wait for the mc146818A seconds counter to change.
*/
start_sec = sec;
for (;;) {
if (CLOCK_GETSECS(clockdev, &sec))
goto fail;
if (sec != start_sec)
break;
}
/*
* Read the PCC again to work out frequency.
*/
stop_pcc = ia64_get_itc();
if (bootverbose) {
printf("PCC clock: %u Hz (firmware %u Hz)\n",
stop_pcc - start_pcc, firmware_freq);
}
return (stop_pcc - start_pcc);
fail:
if (bootverbose)
printf("failed, using firmware default of %u Hz\n",
firmware_freq);
return (firmware_freq);
}
#endif
/*
* We assume newhz is either stathz or profhz, and that neither will
* change after being set up above. Could recalculate intervals here
* but that would be a drag.
*/
void
cpu_startprofclock(void)
{
@ -283,20 +189,17 @@ static short dayyr[12] = {
};
/*
* Initialze the time of day register, based on the time base which is, e.g.
* from a filesystem. Base provides the time to within six months,
* Initialize the time of day register, based on the time base which is,
* e.g. from a filesystem. Base provides the time to within six months,
* and the time of year clock (if any) provides the rest.
*/
void
inittodr(base)
time_t base;
inittodr(time_t base)
{
register int days, yr;
struct clocktime ct;
time_t deltat;
int badbase;
int s;
struct timespec ts;
time_t deltat;
int badbase, days, s, yr;
if (base < 5*SECYR) {
printf("WARNING: preposterous time in filesystem");
@ -307,7 +210,7 @@ inittodr(base)
badbase = 0;
CLOCK_GET(clockdev, base, &ct);
clockinitted = 1;
todr_initialized = 1;
/* simple sanity checks */
if (ct.year < 70 || ct.mon < 1 || ct.mon > 12 || ct.day < 1 ||
@ -333,12 +236,13 @@ inittodr(base)
days += dayyr[ct.mon - 1] + ct.day - 1;
if (LEAPYEAR(yr) && ct.mon > 2)
days++;
/* now have days since Jan 1, 1970; the rest is easy... */
s = splclock();
ts.tv_sec =
ts.tv_sec =
days * SECDAY + ct.hour * SECHOUR + ct.min * SECMIN + ct.sec;
if (wall_cmos_clock)
ts.tv_sec += adjkerntz;
ts.tv_sec += adjkerntz;
ts.tv_nsec = 0;
tc_setclock(&ts);
splx(s);
@ -361,29 +265,26 @@ inittodr(base)
}
/*
* Reset the TODR based on the time value; used when the TODR
* has a preposterous value and also when the time is reset
* by the stime system call. Also called when the TODR goes past
* Reset the TODR based on the time value; used when the TODR has a
* preposterous value and also when the time is reset by the stime
* system call. Also called when the TODR goes past
* TODRZERO + 100*(SECYEAR+2*SECDAY) (e.g. on Jan 2 just after midnight)
* to wrap the TODR around.
*/
void
resettodr()
{
register int t, t2, s;
struct clocktime ct;
unsigned long tm;
unsigned long tm;
int s, t, t2;
if (disable_rtc_set)
if (!todr_initialized || disable_rtc_set)
return;
s = splclock();
tm = time_second;
splx(s);
if (!clockinitted)
return;
/* Calculate local time to put in RTC */
tm -= (wall_cmos_clock ? adjkerntz : 0);
@ -419,86 +320,3 @@ resettodr()
CLOCK_SET(clockdev, &ct);
}
#ifndef SMP
static unsigned
ia64_get_timecount(struct timecounter* tc)
{
return ia64_get_itc();
}
#endif
int
acquire_timer2(int mode)
{
if (timer2_state != RELEASED)
return (-1);
timer2_state = ACQUIRED;
/*
* This access to the timer registers is as atomic as possible
* because it is a single instruction. We could do better if we
* knew the rate. Use of splclock() limits glitches to 10-100us,
* and this is probably good enough for timer2, so we aren't as
* careful with it as with timer0.
*/
outb(TIMER_MODE, TIMER_SEL2 | (mode & 0x3f));
return (0);
}
int
release_timer2()
{
if (timer2_state != ACQUIRED)
return (-1);
timer2_state = RELEASED;
outb(TIMER_MODE, TIMER_SEL2 | TIMER_SQWAVE | TIMER_16BIT);
return (0);
}
static void
sysbeepstop(void *chan)
{
outb(IO_PPI, inb(IO_PPI)&0xFC); /* disable counter2 output to speaker */
release_timer2();
beeping = 0;
}
/*
* Frequency of all three count-down timers; (TIMER_FREQ/freq) is the
* appropriate count to generate a frequency of freq hz.
*/
#ifndef TIMER_FREQ
#define TIMER_FREQ 1193182
#endif
#define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x))
int
sysbeep(int pitch, int period)
{
int x = splhigh();
if (acquire_timer2(TIMER_SQWAVE|TIMER_16BIT))
if (!beeping) {
/* Something else owns it. */
splx(x);
return (-1); /* XXX Should be EBUSY, but nobody cares anyway. */
}
if (pitch) pitch = TIMER_DIV(pitch);
outb(TIMER_CNTR2, pitch);
outb(TIMER_CNTR2, (pitch>>8));
if (!beeping) {
/* enable counter2 output to speaker */
if (pitch) outb(IO_PPI, inb(IO_PPI) | 3);
beeping = period;
timeout(sysbeepstop, (void *)NULL, period);
}
splx(x);
return (0);
}

View File

@ -85,21 +85,51 @@ dummy_perf(unsigned long vector, struct trapframe *framep)
void (*perf_irq)(unsigned long, struct trapframe *) = dummy_perf;
static unsigned int ints[MAXCPU];
static unsigned int clks[MAXCPU];
static unsigned int asts[MAXCPU];
static unsigned int rdvs[MAXCPU];
SYSCTL_OPAQUE(_debug, OID_AUTO, ints, CTLFLAG_RW, &ints, sizeof(ints), "IU","");
SYSCTL_OPAQUE(_debug, OID_AUTO, clks, CTLFLAG_RW, &clks, sizeof(clks), "IU","");
SYSCTL_OPAQUE(_debug, OID_AUTO, asts, CTLFLAG_RW, &asts, sizeof(asts), "IU","");
SYSCTL_OPAQUE(_debug, OID_AUTO, rdvs, CTLFLAG_RW, &rdvs, sizeof(rdvs), "IU","");
SYSCTL_OPAQUE(_debug, OID_AUTO, ints, CTLFLAG_RW, &ints, sizeof(ints), "IU",
"");
static u_int schedclk2;
static unsigned int clks[MAXCPU];
#ifdef SMP
SYSCTL_OPAQUE(_debug, OID_AUTO, clks, CTLFLAG_RW, &clks, sizeof(clks), "IU",
"");
#else
SYSCTL_INT(_debug, OID_AUTO, clks, CTLFLAG_RW, clks, 0, "");
#endif
#ifdef SMP
static unsigned int asts[MAXCPU];
SYSCTL_OPAQUE(_debug, OID_AUTO, asts, CTLFLAG_RW, &asts, sizeof(asts), "IU",
"");
static unsigned int rdvs[MAXCPU];
SYSCTL_OPAQUE(_debug, OID_AUTO, rdvs, CTLFLAG_RW, &rdvs, sizeof(rdvs), "IU",
"");
#endif
static int adjust_edges = 0;
SYSCTL_INT(_debug, OID_AUTO, clock_adjust_edges, CTLFLAG_RW,
&adjust_edges, 0, "Number of times ITC got more than 12.5% behind");
static int adjust_excess = 0;
SYSCTL_INT(_debug, OID_AUTO, clock_adjust_excess, CTLFLAG_RW,
&adjust_excess, 0, "Total number of ignored ITC interrupts");
static int adjust_lost = 0;
SYSCTL_INT(_debug, OID_AUTO, clock_adjust_lost, CTLFLAG_RW,
&adjust_lost, 0, "Total number of lost ITC interrupts");
static int adjust_ticks = 0;
SYSCTL_INT(_debug, OID_AUTO, clock_adjust_ticks, CTLFLAG_RW,
&adjust_ticks, 0, "Total number of ITC interrupts with adjustment");
void
interrupt(u_int64_t vector, struct trapframe *framep)
{
struct thread *td;
volatile struct ia64_interrupt_block *ib = IA64_INTERRUPT_BLOCK;
uint64_t adj, clk, itc;
int64_t delta;
int count;
td = curthread;
atomic_add_int(&td->td_intr_nesting_level, 1);
@ -115,39 +145,55 @@ interrupt(u_int64_t vector, struct trapframe *framep)
if (vector == CLOCK_VECTOR) {/* clock interrupt */
/* CTR0(KTR_INTR, "clock interrupt"); */
cnt.v_intr++;
#ifdef EVCNT_COUNTERS
clock_intr_evcnt.ev_count++;
#else
intrcnt[INTRCNT_CLOCK]++;
#endif
critical_enter();
/* Rearm so we get the next clock interrupt */
ia64_set_itm(ia64_get_itc() + itm_reload);
#ifdef SMP
clks[PCPU_GET(cpuid)]++;
/* Only the BSP runs the real clock */
if (PCPU_GET(cpuid) == 0) {
#endif
hardclock((struct clockframe *)framep);
/* divide hz (1024) by 8 to get stathz (128) */
if ((++schedclk2 & 0x7) == 0) {
if (profprocs != 0)
profclock((struct clockframe *)framep);
statclock((struct clockframe *)framep);
}
#ifdef SMP
} else {
hardclock_process((struct clockframe *)framep);
if ((schedclk2 & 0x7) == 0) {
if (profprocs != 0)
profclock((struct clockframe *)framep);
statclock((struct clockframe *)framep);
}
critical_enter();
adj = PCPU_GET(clockadj);
itc = ia64_get_itc();
ia64_set_itm(itc + ia64_clock_reload - adj);
clk = PCPU_GET(clock);
delta = itc - clk;
count = 0;
while (delta >= ia64_clock_reload) {
/* Only the BSP runs the real clock */
if (PCPU_GET(cpuid) == 0)
hardclock((struct clockframe *)framep);
else
hardclock_process((struct clockframe *)framep);
if (profprocs != 0)
profclock((struct clockframe *)framep);
statclock((struct clockframe *)framep);
delta -= ia64_clock_reload;
clk += ia64_clock_reload;
if (adj != 0)
adjust_ticks++;
count++;
}
#endif
if (count > 0) {
adjust_lost += count - 1;
if (delta > (ia64_clock_reload >> 3)) {
if (adj == 0)
adjust_edges++;
adj = ia64_clock_reload >> 4;
} else if (delta < (ia64_clock_reload >> 3))
adj = 0;
} else {
adj = 0;
adjust_excess++;
}
PCPU_SET(clock, clk);
PCPU_SET(clockadj, adj);
critical_exit();
#ifdef SMP
} else if (vector == ipi_vector[IPI_AST]) {
asts[PCPU_GET(cpuid)]++;
@ -186,23 +232,6 @@ interrupt(u_int64_t vector, struct trapframe *framep)
atomic_subtract_int(&td->td_intr_nesting_level, 1);
}
int
badaddr(addr, size)
void *addr;
size_t size;
{
return(badaddr_read(addr, size, NULL));
}
int
badaddr_read(addr, size, rptr)
void *addr;
size_t size;
void *rptr;
{
return (1); /* XXX implement */
}
/*
* Hardware irqs have vectors starting at this offset.
*/

View File

@ -1357,26 +1357,6 @@ Debugger(const char *msg)
}
#endif /* no DDB */
static int
sysctl_machdep_adjkerntz(SYSCTL_HANDLER_ARGS)
{
int error;
error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2,
req);
if (!error && req->newptr)
resettodr();
return (error);
}
SYSCTL_PROC(_machdep, CPU_ADJKERNTZ, adjkerntz, CTLTYPE_INT|CTLFLAG_RW,
&adjkerntz, 0, sysctl_machdep_adjkerntz, "I", "");
SYSCTL_INT(_machdep, CPU_DISRTCSET, disable_rtc_set,
CTLFLAG_RW, &disable_rtc_set, 0, "");
SYSCTL_INT(_machdep, CPU_WALLCLOCK, wall_cmos_clock,
CTLFLAG_RW, &wall_cmos_clock, 0, "");
/*
* Utility functions for manipulating instruction bundles.
*/
@ -1400,3 +1380,9 @@ ia64_pack_bundle(u_int64_t *lowp, u_int64_t *highp,
*lowp = low;
*highp = high;
}
int
sysbeep(int pitch, int period)
{
return (ENODEV);
}

View File

@ -123,10 +123,11 @@ ia64_ap_startup(void)
mtx_lock_spin(&sched_lock);
/* kick off the clock on this AP */
ia64_set_itm(ia64_get_itc() + itm_reload);
ia64_set_itv(CLOCK_VECTOR);
ia64_set_tpr(0);
/* kick off the clock on this AP */
pcpu_initclock();
cpu_throw(NULL, choosethread());
/* NOTREACHED */
}

View File

@ -1,110 +0,0 @@
/*-
* Copyright (c) 1993 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: Header: timerreg.h,v 1.2 93/02/28 15:08:58 mccanne Exp
* $FreeBSD$
*/
/*
*
* Register definitions for the Intel 8253 Programmable Interval Timer.
*
* This chip has three independent 16-bit down counters that can be
* read on the fly. There are three mode registers and three countdown
* registers. The countdown registers are addressed directly, via the
* first three I/O ports. The three mode registers are accessed via
* the fourth I/O port, with two bits in the mode byte indicating the
* register. (Why are hardware interfaces always so braindead?).
*
* To write a value into the countdown register, the mode register
* is first programmed with a command indicating the which byte of
* the two byte register is to be modified. The three possibilities
* are load msb (TMR_MR_MSB), load lsb (TMR_MR_LSB), or load lsb then
* msb (TMR_MR_BOTH).
*
* To read the current value ("on the fly") from the countdown register,
* you write a "latch" command into the mode register, then read the stable
* value from the corresponding I/O port. For example, you write
* TMR_MR_LATCH into the corresponding mode register. Presumably,
* after doing this, a write operation to the I/O port would result
* in undefined behavior (but hopefully not fry the chip).
* Reading in this manner has no side effects.
*
* [IBM-PC]
* The outputs of the three timers are connected as follows:
*
* timer 0 -> irq 0
* timer 1 -> dma chan 0 (for dram refresh)
* timer 2 -> speaker (via keyboard controller)
*
* Timer 0 is used to call hardclock.
* Timer 2 is used to generate console beeps.
*
* [PC-9801]
* The outputs of the three timers are connected as follows:
*
* timer 0 -> irq 0
* timer 1 -> speaker (via keyboard controller)
* timer 2 -> RS232C
*
* Timer 0 is used to call hardclock.
* Timer 1 is used to generate console beeps.
*/
/*
* Macros for specifying values to be written into a mode register.
*/
#define TIMER_CNTR0 (IO_TIMER1 + 0) /* timer 0 counter port */
#ifdef PC98
#define TIMER_CNTR1 0x3fdb /* timer 1 counter port */
#define TIMER_CNTR2 (IO_TIMER1 + 4) /* timer 2 counter port */
#define TIMER_MODE (IO_TIMER1 + 6) /* timer mode port */
#else
#define TIMER_CNTR1 (IO_TIMER1 + 1) /* timer 1 counter port */
#define TIMER_CNTR2 (IO_TIMER1 + 2) /* timer 2 counter port */
#define TIMER_MODE (IO_TIMER1 + 3) /* timer mode port */
#endif
#define TIMER_SEL0 0x00 /* select counter 0 */
#define TIMER_SEL1 0x40 /* select counter 1 */
#define TIMER_SEL2 0x80 /* select counter 2 */
#define TIMER_INTTC 0x00 /* mode 0, intr on terminal cnt */
#define TIMER_ONESHOT 0x02 /* mode 1, one shot */
#define TIMER_RATEGEN 0x04 /* mode 2, rate generator */
#define TIMER_SQWAVE 0x06 /* mode 3, square wave */
#define TIMER_SWSTROBE 0x08 /* mode 4, s/w triggered strobe */
#define TIMER_HWSTROBE 0x0a /* mode 5, h/w triggered strobe */
#define TIMER_LATCH 0x00 /* latch counter for reading */
#define TIMER_LSB 0x10 /* r/w counter LSB */
#define TIMER_MSB 0x20 /* r/w counter MSB */
#define TIMER_16BIT 0x30 /* r/w counter 16 bits, LSB first */
#define TIMER_BCD 0x01 /* count in BCD */

View File

@ -13,16 +13,14 @@
#define CLOCK_VECTOR 254
extern int disable_rtc_set;
extern int wall_cmos_clock;
extern int adjkerntz;
extern int adjkerntz;
extern int disable_rtc_set;
extern int wall_cmos_clock;
extern u_int64_t itc_frequency;
extern u_int64_t itm_reload;
extern uint64_t ia64_clock_reload;
extern uint64_t itc_frequency;
int sysbeep(int pitch, int period);
int acquire_timer2(int mode);
int release_timer2(void);
int sysbeep(int pitch, int period);
#endif

View File

@ -75,18 +75,14 @@ struct clockframe {
* CTL_MACHDEP definitions.
*/
#define CPU_CONSDEV 1 /* dev_t: console terminal device */
#define CPU_ROOT_DEVICE 2 /* string: root device name */
#define CPU_BOOTED_KERNEL 3 /* string: booted kernel name */
#define CPU_ADJKERNTZ 4 /* int: timezone offset (seconds) */
#define CPU_DISRTCSET 5 /* int: disable resettodr() call */
#define CPU_WALLCLOCK 6 /* int: indicates wall CMOS clock */
#define CPU_MAXID 7 /* valid machdep IDs */
#define CPU_ADJKERNTZ 2 /* int: timezone offset (seconds) */
#define CPU_DISRTCSET 3 /* int: disable resettodr() call */
#define CPU_WALLCLOCK 4 /* int: indicates wall CMOS clock */
#define CPU_MAXID 5 /* valid machdep IDs */
#define CTL_MACHDEP_NAMES { \
{ 0, 0 }, \
{ "console_device", CTLTYPE_STRUCT }, \
{ "root_device", CTLTYPE_STRING }, \
{ "booted_kernel", CTLTYPE_STRING }, \
{ "adjkerntz", CTLTYPE_INT }, \
{ "disable_rtc_set", CTLTYPE_INT }, \
{ "wall_cmos_clock", CTLTYPE_INT }, \
@ -100,11 +96,6 @@ struct reg;
struct rpb;
struct trapframe;
extern struct rpb *hwrpb;
extern volatile int mc_expected, mc_received;
int badaddr(void *, size_t);
int badaddr_read(void *, size_t, void *);
u_int64_t console_restart(u_int64_t, u_int64_t, u_int64_t);
int do_ast(struct trapframe *);
void dumpconf(void);
@ -118,8 +109,6 @@ void init_prom_interface(struct rpb*);
void interrupt(u_int64_t, struct trapframe *);
void machine_check(unsigned long, struct trapframe *, unsigned long,
unsigned long);
u_int64_t hwrpb_checksum(void);
void hwrpb_restart_setup(void);
void regdump(struct trapframe *);
void regtoframe(struct reg *, struct trapframe *);
void set_iointr(void (*)(void *, unsigned long));

View File

@ -35,8 +35,10 @@
#define PCPU_MD_FIELDS \
struct pcb *pc_pcb; /* Used by IPI_STOP */ \
struct pmap *pc_current_pmap; /* active pmap */ \
u_int64_t pc_lid; /* local CPU ID */ \
u_int32_t pc_awake:1; /* CPU is awake? */
uint64_t pc_lid; /* local CPU ID */ \
uint32_t pc_awake:1; /* CPU is awake? */ \
uint64_t pc_clock; /* Clock counter. */ \
uint64_t pc_clockadj; /* Clock adjust. */
struct pcpu;
@ -46,6 +48,8 @@ register struct pcpu *pcpup __asm__("r13");
#define PCPU_PTR(member) (&pcpup->pc_ ## member)
#define PCPU_SET(member,value) (pcpup->pc_ ## member = (value))
void pcpu_initclock(void);
#endif /* _KERNEL */
#endif /* !_MACHINE_PCPU_H_ */