Restore pre-r212778 optimization, skipping timer reprogramming when it is

not neccessary. It allows to avoid time counter jump of up to 1/18s, when
base frequency slightly tuned via machdep.i8254_freq sysctl.
Fix few style things.

Suggested by:	bde
This commit is contained in:
Alexander Motin 2010-09-18 07:36:43 +00:00
parent 8e860de4bf
commit d3979248ac
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=212812

View File

@ -124,6 +124,8 @@ struct attimer_softc {
};
static struct attimer_softc *attimer_sc = NULL;
static int timer0_period = -2;
/* Values for timerX_state: */
#define RELEASED 0
#define RELEASE_PENDING 1
@ -367,36 +369,41 @@ DELAY(int n)
static void
set_i8254_freq(int mode, uint32_t period)
{
int val;
int new_count;
mtx_lock_spin(&clock_lock);
if (period == 0)
val = 0x10000;
else
val = min(((uint64_t)i8254_freq * period) >> 32, 0x10000);
if (val == 0x10000)
i8254_max_count = 0xffff;
else
i8254_max_count = val;
if (mode == MODE_STOP && i8254_timecounter)
mode = MODE_PERIODIC;
if (mode == MODE_STOP) {
if (i8254_timecounter) {
mode = MODE_PERIODIC;
new_count = 0x10000;
} else
new_count = -1;
} else {
new_count = min(((uint64_t)i8254_freq * period +
0x80000000LLU) >> 32, 0x10000);
}
if (new_count == timer0_period)
goto out;
i8254_max_count = ((new_count & ~0xffff) != 0) ? 0xffff : new_count;
timer0_period = (mode == MODE_PERIODIC) ? new_count : -1;
switch (mode) {
case MODE_STOP:
outb(TIMER_MODE, TIMER_SEL0 | TIMER_INTTC | TIMER_16BIT);
outb(TIMER_CNTR0, 0xff);
outb(TIMER_CNTR0, 0xff);
outb(TIMER_CNTR0, 0);
outb(TIMER_CNTR0, 0);
break;
case MODE_PERIODIC:
outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
outb(TIMER_CNTR0, val & 0xff);
outb(TIMER_CNTR0, val >> 8);
outb(TIMER_CNTR0, new_count & 0xff);
outb(TIMER_CNTR0, new_count >> 8);
break;
case MODE_ONESHOT:
outb(TIMER_MODE, TIMER_SEL0 | TIMER_INTTC | TIMER_16BIT);
outb(TIMER_CNTR0, val & 0xff);
outb(TIMER_CNTR0, val >> 8);
outb(TIMER_CNTR0, new_count & 0xff);
outb(TIMER_CNTR0, new_count >> 8);
break;
}
out:
mtx_unlock_spin(&clock_lock);
}
@ -404,7 +411,8 @@ static void
i8254_restore(void)
{
if (attimer_sc)
timer0_period = -2;
if (attimer_sc != NULL)
set_i8254_freq(attimer_sc->mode, attimer_sc->period);
else
set_i8254_freq(0, 0);
@ -473,7 +481,7 @@ sysctl_machdep_i8254_freq(SYSCTL_HANDLER_ARGS)
error = sysctl_handle_int(oidp, &freq, 0, req);
if (error == 0 && req->newptr != NULL) {
i8254_freq = freq;
if (attimer_sc) {
if (attimer_sc != NULL) {
set_i8254_freq(attimer_sc->mode, attimer_sc->period);
attimer_sc->tc.tc_frequency = freq;
} else {