summaryrefslogtreecommitdiffstats
path: root/sys/pc98/cbus
diff options
context:
space:
mode:
authornyan <nyan@FreeBSD.org>2005-07-03 14:19:29 +0000
committernyan <nyan@FreeBSD.org>2005-07-03 14:19:29 +0000
commitdc79c6b0b0cc26d48f6154d90c41f7ee27d0e542 (patch)
tree7e1532070cb279afa5b9b268f0ad940c5593c575 /sys/pc98/cbus
parent13171c48a13db11e07de13a96b11cf642a7b8573 (diff)
downloadFreeBSD-src-dc79c6b0b0cc26d48f6154d90c41f7ee27d0e542.zip
FreeBSD-src-dc79c6b0b0cc26d48f6154d90c41f7ee27d0e542.tar.gz
MFi386: r1.221 (Use a simpler implementation for the i8254 timecounter).
Approved by: re (scottl)
Diffstat (limited to 'sys/pc98/cbus')
-rw-r--r--sys/pc98/cbus/clock.c47
-rw-r--r--sys/pc98/cbus/pcrtc.c47
2 files changed, 70 insertions, 24 deletions
diff --git a/sys/pc98/cbus/clock.c b/sys/pc98/cbus/clock.c
index ee75914..7f50c99 100644
--- a/sys/pc98/cbus/clock.c
+++ b/sys/pc98/cbus/clock.c
@@ -136,6 +136,7 @@ static int rtc_inb(void);
static void rtc_outb(int);
static unsigned i8254_get_timecount(struct timecounter *tc);
+static unsigned i8254_simple_get_timecount(struct timecounter *tc);
static void set_timer_freq(u_int freq, int intr_freq);
static struct timecounter i8254_timecounter = {
@@ -473,10 +474,15 @@ set_timer_freq(u_int freq, int intr_freq)
{
int new_timer0_max_count;
+ i8254_timecounter.tc_frequency = freq;
mtx_lock_spin(&clock_lock);
timer_freq = freq;
new_timer0_max_count = hardclock_max_count = TIMER_DIV(intr_freq);
- if (new_timer0_max_count != timer0_max_count) {
+ if (using_lapic_timer) {
+ outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
+ outb(TIMER_CNTR0, 0);
+ outb(TIMER_CNTR0, 0);
+ } else if (new_timer0_max_count != timer0_max_count) {
timer0_max_count = new_timer0_max_count;
outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
outb(TIMER_CNTR0, timer0_max_count & 0xff);
@@ -489,11 +495,7 @@ static void
i8254_restore(void)
{
- mtx_lock_spin(&clock_lock);
- outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
- outb(TIMER_CNTR0, timer0_max_count & 0xff);
- outb(TIMER_CNTR0, timer0_max_count >> 8);
- mtx_unlock_spin(&clock_lock);
+ set_timer_freq(timer_freq, hz);
}
@@ -559,7 +561,6 @@ startrtclock()
}
set_timer_freq(timer_freq, hz);
- i8254_timecounter.tc_frequency = timer_freq;
tc_init(&i8254_timecounter);
init_TSC();
@@ -761,15 +762,21 @@ cpu_initclocks()
/*
* If we aren't using the local APIC timer to drive the kernel
* clocks, setup the interrupt handler for the 8254 timer 0 so
- * that it can drive hardclock().
+ * that it can drive hardclock(). Otherwise, change the 8254
+ * timecounter to user a simpler algorithm.
*/
- if (!using_lapic_timer) {
+ if (!using_lapic_timer || 1) {
intr_add_handler("clk", 0, (driver_intr_t *)clkintr, NULL,
INTR_TYPE_CLK | INTR_FAST, NULL);
i8254_intsrc = intr_lookup_source(0);
if (i8254_intsrc != NULL)
i8254_pending =
i8254_intsrc->is_pic->pic_source_pending;
+ } else {
+ i8254_timecounter.tc_get_timecount =
+ i8254_simple_get_timecount;
+ i8254_timecounter.tc_counter_mask = 0xffff;
+ set_timer_freq(timer_freq, hz);
}
init_TSC_tc();
@@ -797,10 +804,8 @@ sysctl_machdep_i8254_freq(SYSCTL_HANDLER_ARGS)
*/
freq = timer_freq;
error = sysctl_handle_int(oidp, &freq, sizeof(freq), req);
- if (error == 0 && req->newptr != NULL) {
+ if (error == 0 && req->newptr != NULL)
set_timer_freq(freq, hz);
- i8254_timecounter.tc_frequency = freq;
- }
return (error);
}
@@ -808,6 +813,24 @@ SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW,
0, sizeof(u_int), sysctl_machdep_i8254_freq, "IU", "");
static unsigned
+i8254_simple_get_timecount(struct timecounter *tc)
+{
+ u_int count;
+ u_int high, low;
+
+ mtx_lock_spin(&clock_lock);
+
+ /* Select timer0 and latch counter value. */
+ outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
+
+ low = inb(TIMER_CNTR0);
+ high = inb(TIMER_CNTR0);
+ count = 0xffff - ((high << 8) | low);
+ mtx_unlock_spin(&clock_lock);
+ return (count);
+}
+
+static unsigned
i8254_get_timecount(struct timecounter *tc)
{
u_int count;
diff --git a/sys/pc98/cbus/pcrtc.c b/sys/pc98/cbus/pcrtc.c
index ee75914..7f50c99 100644
--- a/sys/pc98/cbus/pcrtc.c
+++ b/sys/pc98/cbus/pcrtc.c
@@ -136,6 +136,7 @@ static int rtc_inb(void);
static void rtc_outb(int);
static unsigned i8254_get_timecount(struct timecounter *tc);
+static unsigned i8254_simple_get_timecount(struct timecounter *tc);
static void set_timer_freq(u_int freq, int intr_freq);
static struct timecounter i8254_timecounter = {
@@ -473,10 +474,15 @@ set_timer_freq(u_int freq, int intr_freq)
{
int new_timer0_max_count;
+ i8254_timecounter.tc_frequency = freq;
mtx_lock_spin(&clock_lock);
timer_freq = freq;
new_timer0_max_count = hardclock_max_count = TIMER_DIV(intr_freq);
- if (new_timer0_max_count != timer0_max_count) {
+ if (using_lapic_timer) {
+ outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
+ outb(TIMER_CNTR0, 0);
+ outb(TIMER_CNTR0, 0);
+ } else if (new_timer0_max_count != timer0_max_count) {
timer0_max_count = new_timer0_max_count;
outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
outb(TIMER_CNTR0, timer0_max_count & 0xff);
@@ -489,11 +495,7 @@ static void
i8254_restore(void)
{
- mtx_lock_spin(&clock_lock);
- outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
- outb(TIMER_CNTR0, timer0_max_count & 0xff);
- outb(TIMER_CNTR0, timer0_max_count >> 8);
- mtx_unlock_spin(&clock_lock);
+ set_timer_freq(timer_freq, hz);
}
@@ -559,7 +561,6 @@ startrtclock()
}
set_timer_freq(timer_freq, hz);
- i8254_timecounter.tc_frequency = timer_freq;
tc_init(&i8254_timecounter);
init_TSC();
@@ -761,15 +762,21 @@ cpu_initclocks()
/*
* If we aren't using the local APIC timer to drive the kernel
* clocks, setup the interrupt handler for the 8254 timer 0 so
- * that it can drive hardclock().
+ * that it can drive hardclock(). Otherwise, change the 8254
+ * timecounter to user a simpler algorithm.
*/
- if (!using_lapic_timer) {
+ if (!using_lapic_timer || 1) {
intr_add_handler("clk", 0, (driver_intr_t *)clkintr, NULL,
INTR_TYPE_CLK | INTR_FAST, NULL);
i8254_intsrc = intr_lookup_source(0);
if (i8254_intsrc != NULL)
i8254_pending =
i8254_intsrc->is_pic->pic_source_pending;
+ } else {
+ i8254_timecounter.tc_get_timecount =
+ i8254_simple_get_timecount;
+ i8254_timecounter.tc_counter_mask = 0xffff;
+ set_timer_freq(timer_freq, hz);
}
init_TSC_tc();
@@ -797,10 +804,8 @@ sysctl_machdep_i8254_freq(SYSCTL_HANDLER_ARGS)
*/
freq = timer_freq;
error = sysctl_handle_int(oidp, &freq, sizeof(freq), req);
- if (error == 0 && req->newptr != NULL) {
+ if (error == 0 && req->newptr != NULL)
set_timer_freq(freq, hz);
- i8254_timecounter.tc_frequency = freq;
- }
return (error);
}
@@ -808,6 +813,24 @@ SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW,
0, sizeof(u_int), sysctl_machdep_i8254_freq, "IU", "");
static unsigned
+i8254_simple_get_timecount(struct timecounter *tc)
+{
+ u_int count;
+ u_int high, low;
+
+ mtx_lock_spin(&clock_lock);
+
+ /* Select timer0 and latch counter value. */
+ outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
+
+ low = inb(TIMER_CNTR0);
+ high = inb(TIMER_CNTR0);
+ count = 0xffff - ((high << 8) | low);
+ mtx_unlock_spin(&clock_lock);
+ return (count);
+}
+
+static unsigned
i8254_get_timecount(struct timecounter *tc)
{
u_int count;
OpenPOWER on IntegriCloud