diff options
author | nyan <nyan@FreeBSD.org> | 2005-07-03 14:19:29 +0000 |
---|---|---|
committer | nyan <nyan@FreeBSD.org> | 2005-07-03 14:19:29 +0000 |
commit | dc79c6b0b0cc26d48f6154d90c41f7ee27d0e542 (patch) | |
tree | 7e1532070cb279afa5b9b268f0ad940c5593c575 /sys/pc98/cbus | |
parent | 13171c48a13db11e07de13a96b11cf642a7b8573 (diff) | |
download | FreeBSD-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.c | 47 | ||||
-rw-r--r-- | sys/pc98/cbus/pcrtc.c | 47 |
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; |