Fixed glitches (jumps) of about 1/HZ seconds for the i8254 timecounter.
The old version only worked right when the time was read strictly more often than every 1/HZ seconds, but we only guarantee reading it every (1/HZ + epsilon) seconds. Part of rev.1.126-1.127 attempted to fix this but didn't succeed. Detect counter rollover using the heuristic from the old version of microtime() with additional complications for supporting calls from fast interrupt handlers. This works provided i8254 interrupts are not delayed by more than 1/(2*HZ) seconds. This needs more comments, and cleanups for the SMP case, and more testing of the SMP case before it is merged into RELENG_3. Tested by: jhay
This commit is contained in:
parent
2c39f0fd7d
commit
639d459251
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* from: vector.s, 386BSD 0.1 unknown origin
|
||||
* $Id: apic_vector.s,v 1.36 1999/04/14 14:26:35 bde Exp $
|
||||
* $Id: apic_vector.s,v 1.37 1999/04/28 01:04:12 luoqi Exp $
|
||||
*/
|
||||
|
||||
|
||||
@ -324,7 +324,7 @@ log_intr_event:
|
||||
|
||||
#ifdef CPL_AND_CML
|
||||
|
||||
#define INTR(irq_num, vec_name) \
|
||||
#define INTR(irq_num, vec_name, maybe_extra_ipending) \
|
||||
.text ; \
|
||||
SUPERALIGN_TEXT ; \
|
||||
/* _XintrNN: entry point used by IDT/HWIs & splz_unpend via _vec[]. */ \
|
||||
@ -335,6 +335,8 @@ IDTVEC(vec_name) ; \
|
||||
movl %ax, %es ; \
|
||||
movl $KPSEL, %eax ; \
|
||||
movl %ax, %fs ; \
|
||||
; \
|
||||
maybe_extra_ipending ; \
|
||||
; \
|
||||
APIC_ITRACE(apic_itrace_enter, irq_num, APIC_ITRACE_ENTER) ; \
|
||||
lock ; /* MP-safe */ \
|
||||
@ -436,7 +438,7 @@ __CONCAT(Xresume,irq_num): ; \
|
||||
#else /* CPL_AND_CML */
|
||||
|
||||
|
||||
#define INTR(irq_num, vec_name) \
|
||||
#define INTR(irq_num, vec_name, maybe_extra_ipending) \
|
||||
.text ; \
|
||||
SUPERALIGN_TEXT ; \
|
||||
/* _XintrNN: entry point used by IDT/HWIs & splz_unpend via _vec[]. */ \
|
||||
@ -447,6 +449,8 @@ IDTVEC(vec_name) ; \
|
||||
movl %ax, %es ; \
|
||||
movl $KPSEL, %eax ; \
|
||||
movl %ax, %fs ; \
|
||||
; \
|
||||
maybe_extra_ipending ; \
|
||||
; \
|
||||
APIC_ITRACE(apic_itrace_enter, irq_num, APIC_ITRACE_ENTER) ; \
|
||||
lock ; /* MP-safe */ \
|
||||
@ -916,30 +920,31 @@ MCOUNT_LABEL(bintr)
|
||||
FAST_INTR(21,fastintr21)
|
||||
FAST_INTR(22,fastintr22)
|
||||
FAST_INTR(23,fastintr23)
|
||||
INTR(0,intr0)
|
||||
INTR(1,intr1)
|
||||
INTR(2,intr2)
|
||||
INTR(3,intr3)
|
||||
INTR(4,intr4)
|
||||
INTR(5,intr5)
|
||||
INTR(6,intr6)
|
||||
INTR(7,intr7)
|
||||
INTR(8,intr8)
|
||||
INTR(9,intr9)
|
||||
INTR(10,intr10)
|
||||
INTR(11,intr11)
|
||||
INTR(12,intr12)
|
||||
INTR(13,intr13)
|
||||
INTR(14,intr14)
|
||||
INTR(15,intr15)
|
||||
INTR(16,intr16)
|
||||
INTR(17,intr17)
|
||||
INTR(18,intr18)
|
||||
INTR(19,intr19)
|
||||
INTR(20,intr20)
|
||||
INTR(21,intr21)
|
||||
INTR(22,intr22)
|
||||
INTR(23,intr23)
|
||||
#define CLKINTR_PENDING movl $1,CNAME(clkintr_pending)
|
||||
INTR(0,intr0, CLKINTR_PENDING)
|
||||
INTR(1,intr1,)
|
||||
INTR(2,intr2,)
|
||||
INTR(3,intr3,)
|
||||
INTR(4,intr4,)
|
||||
INTR(5,intr5,)
|
||||
INTR(6,intr6,)
|
||||
INTR(7,intr7,)
|
||||
INTR(8,intr8,)
|
||||
INTR(9,intr9,)
|
||||
INTR(10,intr10,)
|
||||
INTR(11,intr11,)
|
||||
INTR(12,intr12,)
|
||||
INTR(13,intr13,)
|
||||
INTR(14,intr14,)
|
||||
INTR(15,intr15,)
|
||||
INTR(16,intr16,)
|
||||
INTR(17,intr17,)
|
||||
INTR(18,intr18,)
|
||||
INTR(19,intr19,)
|
||||
INTR(20,intr20,)
|
||||
INTR(21,intr21,)
|
||||
INTR(22,intr22,)
|
||||
INTR(23,intr23,)
|
||||
MCOUNT_LABEL(eintr)
|
||||
|
||||
.data
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
|
||||
* $Id: clock.c,v 1.132 1999/04/25 09:00:00 phk Exp $
|
||||
* $Id: clock.c,v 1.133 1999/05/09 23:32:29 peter Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -69,6 +69,7 @@
|
||||
#include <machine/ipl.h>
|
||||
#include <machine/limits.h>
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/psl.h>
|
||||
#if NAPM > 0
|
||||
#include <machine/apm_bios.h>
|
||||
#include <i386/apm/apm_setup.h>
|
||||
@ -127,6 +128,7 @@ static void setup_8254_mixed_mode __P((void));
|
||||
#define TIMER0_MAX_FREQ 20000
|
||||
|
||||
int adjkerntz; /* local offset from GMT in seconds */
|
||||
int clkintr_pending;
|
||||
int disable_rtc_set; /* disable resettodr() if != 0 */
|
||||
volatile u_int idelayed;
|
||||
int statclock_disable;
|
||||
@ -199,24 +201,15 @@ static void
|
||||
clkintr(struct clockframe frame)
|
||||
{
|
||||
if (timecounter->tc_get_timecount == i8254_get_timecount) {
|
||||
/*
|
||||
* Maintain i8254_offset and related variables. Optimize
|
||||
* the usual case where i8254 counter rollover has not been
|
||||
* detected in i8254_get_timecount() by pretending that we
|
||||
* read the counter when it rolled over. Otherwise, call
|
||||
* i8254_get_timecount() to do most of the work. The
|
||||
* hardware counter must be read to ensure monotonicity
|
||||
* despite multiple rollovers and misbehaving hardware.
|
||||
*/
|
||||
(disable_intr)(); /* XXX avoid clock locking */
|
||||
if (i8254_ticked) {
|
||||
i8254_get_timecount(NULL);
|
||||
disable_intr();
|
||||
if (i8254_ticked)
|
||||
i8254_ticked = 0;
|
||||
} else {
|
||||
else {
|
||||
i8254_offset += timer0_max_count;
|
||||
i8254_lastcount = 0;
|
||||
}
|
||||
(enable_intr)(); /* XXX avoid clock locking */
|
||||
clkintr_pending = 0;
|
||||
enable_intr();
|
||||
}
|
||||
timer_func(&frame);
|
||||
switch (timer0_state) {
|
||||
@ -1159,13 +1152,21 @@ i8254_get_timecount(struct timecounter *tc)
|
||||
|
||||
low = inb(TIMER_CNTR0);
|
||||
high = inb(TIMER_CNTR0);
|
||||
|
||||
count = hardclock_max_count - ((high << 8) | low);
|
||||
if (count < i8254_lastcount) {
|
||||
count = timer0_max_count - ((high << 8) | low);
|
||||
if (count < i8254_lastcount ||
|
||||
(!i8254_ticked && (clkintr_pending ||
|
||||
((count < 20 || (!(ef & PSL_I) && count < timer0_max_count / 2u)) &&
|
||||
#ifdef APIC_IO
|
||||
#define lapic_irr1 ((volatile u_int *)&lapic)[0x210 / 4] /* XXX XXX */
|
||||
/* XXX this assumes that apic_8254_intr is < 24. */
|
||||
(lapic_irr1 & (1 << apic_8254_intr))))
|
||||
#else
|
||||
(inb(IO_ICU1) & 1)))
|
||||
#endif
|
||||
)) {
|
||||
i8254_ticked = 1;
|
||||
i8254_offset += hardclock_max_count;
|
||||
i8254_offset += timer0_max_count;
|
||||
}
|
||||
|
||||
i8254_lastcount = count;
|
||||
count += i8254_offset;
|
||||
CLOCK_UNLOCK();
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* from: vector.s, 386BSD 0.1 unknown origin
|
||||
* $Id: icu_vector.s,v 1.10 1999/04/14 14:26:36 bde Exp $
|
||||
* $Id: icu_vector.s,v 1.11 1999/04/28 01:04:13 luoqi Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -106,7 +106,7 @@ IDTVEC(vec_name) ; \
|
||||
MEXITCOUNT ; \
|
||||
jmp _doreti
|
||||
|
||||
#define INTR(irq_num, vec_name, icu, enable_icus, reg) \
|
||||
#define INTR(irq_num, vec_name, icu, enable_icus, reg, maybe_extra_ipending) \
|
||||
.text ; \
|
||||
SUPERALIGN_TEXT ; \
|
||||
IDTVEC(vec_name) ; \
|
||||
@ -120,6 +120,7 @@ IDTVEC(vec_name) ; \
|
||||
movl %ax,%ds ; /* ... early for obsolete reasons */ \
|
||||
movl %ax,%es ; \
|
||||
movl %ax,%fs ; \
|
||||
maybe_extra_ipending ; \
|
||||
movb _imen + IRQ_BYTE(irq_num),%al ; \
|
||||
orb $IRQ_BIT(irq_num),%al ; \
|
||||
movb %al,_imen + IRQ_BYTE(irq_num) ; \
|
||||
@ -180,22 +181,23 @@ MCOUNT_LABEL(bintr)
|
||||
FAST_INTR(13,fastintr13, ENABLE_ICU1_AND_2)
|
||||
FAST_INTR(14,fastintr14, ENABLE_ICU1_AND_2)
|
||||
FAST_INTR(15,fastintr15, ENABLE_ICU1_AND_2)
|
||||
INTR(0,intr0, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(1,intr1, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(2,intr2, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(3,intr3, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(4,intr4, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(5,intr5, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(6,intr6, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(7,intr7, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(8,intr8, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(9,intr9, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(10,intr10, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(11,intr11, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(12,intr12, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(13,intr13, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(14,intr14, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(15,intr15, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
#define CLKINTR_PENDING movl $1,CNAME(clkintr_pending)
|
||||
INTR(0,intr0, IO_ICU1, ENABLE_ICU1, al, CLKINTR_PENDING)
|
||||
INTR(1,intr1, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(2,intr2, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(3,intr3, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(4,intr4, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(5,intr5, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(6,intr6, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(7,intr7, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(8,intr8, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(9,intr9, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(10,intr10, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(11,intr11, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(12,intr12, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(13,intr13, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(14,intr14, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(15,intr15, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
MCOUNT_LABEL(eintr)
|
||||
|
||||
.data
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
|
||||
* $Id: clock.c,v 1.132 1999/04/25 09:00:00 phk Exp $
|
||||
* $Id: clock.c,v 1.133 1999/05/09 23:32:29 peter Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -69,6 +69,7 @@
|
||||
#include <machine/ipl.h>
|
||||
#include <machine/limits.h>
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/psl.h>
|
||||
#if NAPM > 0
|
||||
#include <machine/apm_bios.h>
|
||||
#include <i386/apm/apm_setup.h>
|
||||
@ -127,6 +128,7 @@ static void setup_8254_mixed_mode __P((void));
|
||||
#define TIMER0_MAX_FREQ 20000
|
||||
|
||||
int adjkerntz; /* local offset from GMT in seconds */
|
||||
int clkintr_pending;
|
||||
int disable_rtc_set; /* disable resettodr() if != 0 */
|
||||
volatile u_int idelayed;
|
||||
int statclock_disable;
|
||||
@ -199,24 +201,15 @@ static void
|
||||
clkintr(struct clockframe frame)
|
||||
{
|
||||
if (timecounter->tc_get_timecount == i8254_get_timecount) {
|
||||
/*
|
||||
* Maintain i8254_offset and related variables. Optimize
|
||||
* the usual case where i8254 counter rollover has not been
|
||||
* detected in i8254_get_timecount() by pretending that we
|
||||
* read the counter when it rolled over. Otherwise, call
|
||||
* i8254_get_timecount() to do most of the work. The
|
||||
* hardware counter must be read to ensure monotonicity
|
||||
* despite multiple rollovers and misbehaving hardware.
|
||||
*/
|
||||
(disable_intr)(); /* XXX avoid clock locking */
|
||||
if (i8254_ticked) {
|
||||
i8254_get_timecount(NULL);
|
||||
disable_intr();
|
||||
if (i8254_ticked)
|
||||
i8254_ticked = 0;
|
||||
} else {
|
||||
else {
|
||||
i8254_offset += timer0_max_count;
|
||||
i8254_lastcount = 0;
|
||||
}
|
||||
(enable_intr)(); /* XXX avoid clock locking */
|
||||
clkintr_pending = 0;
|
||||
enable_intr();
|
||||
}
|
||||
timer_func(&frame);
|
||||
switch (timer0_state) {
|
||||
@ -1159,13 +1152,21 @@ i8254_get_timecount(struct timecounter *tc)
|
||||
|
||||
low = inb(TIMER_CNTR0);
|
||||
high = inb(TIMER_CNTR0);
|
||||
|
||||
count = hardclock_max_count - ((high << 8) | low);
|
||||
if (count < i8254_lastcount) {
|
||||
count = timer0_max_count - ((high << 8) | low);
|
||||
if (count < i8254_lastcount ||
|
||||
(!i8254_ticked && (clkintr_pending ||
|
||||
((count < 20 || (!(ef & PSL_I) && count < timer0_max_count / 2u)) &&
|
||||
#ifdef APIC_IO
|
||||
#define lapic_irr1 ((volatile u_int *)&lapic)[0x210 / 4] /* XXX XXX */
|
||||
/* XXX this assumes that apic_8254_intr is < 24. */
|
||||
(lapic_irr1 & (1 << apic_8254_intr))))
|
||||
#else
|
||||
(inb(IO_ICU1) & 1)))
|
||||
#endif
|
||||
)) {
|
||||
i8254_ticked = 1;
|
||||
i8254_offset += hardclock_max_count;
|
||||
i8254_offset += timer0_max_count;
|
||||
}
|
||||
|
||||
i8254_lastcount = count;
|
||||
count += i8254_offset;
|
||||
CLOCK_UNLOCK();
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* from: vector.s, 386BSD 0.1 unknown origin
|
||||
* $Id: icu_vector.s,v 1.10 1999/04/14 14:26:36 bde Exp $
|
||||
* $Id: icu_vector.s,v 1.11 1999/04/28 01:04:13 luoqi Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -106,7 +106,7 @@ IDTVEC(vec_name) ; \
|
||||
MEXITCOUNT ; \
|
||||
jmp _doreti
|
||||
|
||||
#define INTR(irq_num, vec_name, icu, enable_icus, reg) \
|
||||
#define INTR(irq_num, vec_name, icu, enable_icus, reg, maybe_extra_ipending) \
|
||||
.text ; \
|
||||
SUPERALIGN_TEXT ; \
|
||||
IDTVEC(vec_name) ; \
|
||||
@ -120,6 +120,7 @@ IDTVEC(vec_name) ; \
|
||||
movl %ax,%ds ; /* ... early for obsolete reasons */ \
|
||||
movl %ax,%es ; \
|
||||
movl %ax,%fs ; \
|
||||
maybe_extra_ipending ; \
|
||||
movb _imen + IRQ_BYTE(irq_num),%al ; \
|
||||
orb $IRQ_BIT(irq_num),%al ; \
|
||||
movb %al,_imen + IRQ_BYTE(irq_num) ; \
|
||||
@ -180,22 +181,23 @@ MCOUNT_LABEL(bintr)
|
||||
FAST_INTR(13,fastintr13, ENABLE_ICU1_AND_2)
|
||||
FAST_INTR(14,fastintr14, ENABLE_ICU1_AND_2)
|
||||
FAST_INTR(15,fastintr15, ENABLE_ICU1_AND_2)
|
||||
INTR(0,intr0, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(1,intr1, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(2,intr2, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(3,intr3, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(4,intr4, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(5,intr5, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(6,intr6, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(7,intr7, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(8,intr8, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(9,intr9, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(10,intr10, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(11,intr11, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(12,intr12, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(13,intr13, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(14,intr14, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(15,intr15, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
#define CLKINTR_PENDING movl $1,CNAME(clkintr_pending)
|
||||
INTR(0,intr0, IO_ICU1, ENABLE_ICU1, al, CLKINTR_PENDING)
|
||||
INTR(1,intr1, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(2,intr2, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(3,intr3, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(4,intr4, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(5,intr5, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(6,intr6, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(7,intr7, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(8,intr8, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(9,intr9, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(10,intr10, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(11,intr11, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(12,intr12, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(13,intr13, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(14,intr14, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(15,intr15, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
MCOUNT_LABEL(eintr)
|
||||
|
||||
.data
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* from: vector.s, 386BSD 0.1 unknown origin
|
||||
* $Id: icu_vector.s,v 1.10 1999/04/14 14:26:36 bde Exp $
|
||||
* $Id: icu_vector.s,v 1.11 1999/04/28 01:04:13 luoqi Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -106,7 +106,7 @@ IDTVEC(vec_name) ; \
|
||||
MEXITCOUNT ; \
|
||||
jmp _doreti
|
||||
|
||||
#define INTR(irq_num, vec_name, icu, enable_icus, reg) \
|
||||
#define INTR(irq_num, vec_name, icu, enable_icus, reg, maybe_extra_ipending) \
|
||||
.text ; \
|
||||
SUPERALIGN_TEXT ; \
|
||||
IDTVEC(vec_name) ; \
|
||||
@ -120,6 +120,7 @@ IDTVEC(vec_name) ; \
|
||||
movl %ax,%ds ; /* ... early for obsolete reasons */ \
|
||||
movl %ax,%es ; \
|
||||
movl %ax,%fs ; \
|
||||
maybe_extra_ipending ; \
|
||||
movb _imen + IRQ_BYTE(irq_num),%al ; \
|
||||
orb $IRQ_BIT(irq_num),%al ; \
|
||||
movb %al,_imen + IRQ_BYTE(irq_num) ; \
|
||||
@ -180,22 +181,23 @@ MCOUNT_LABEL(bintr)
|
||||
FAST_INTR(13,fastintr13, ENABLE_ICU1_AND_2)
|
||||
FAST_INTR(14,fastintr14, ENABLE_ICU1_AND_2)
|
||||
FAST_INTR(15,fastintr15, ENABLE_ICU1_AND_2)
|
||||
INTR(0,intr0, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(1,intr1, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(2,intr2, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(3,intr3, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(4,intr4, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(5,intr5, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(6,intr6, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(7,intr7, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(8,intr8, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(9,intr9, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(10,intr10, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(11,intr11, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(12,intr12, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(13,intr13, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(14,intr14, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(15,intr15, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
#define CLKINTR_PENDING movl $1,CNAME(clkintr_pending)
|
||||
INTR(0,intr0, IO_ICU1, ENABLE_ICU1, al, CLKINTR_PENDING)
|
||||
INTR(1,intr1, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(2,intr2, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(3,intr3, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(4,intr4, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(5,intr5, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(6,intr6, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(7,intr7, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(8,intr8, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(9,intr9, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(10,intr10, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(11,intr11, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(12,intr12, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(13,intr13, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(14,intr14, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(15,intr15, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
MCOUNT_LABEL(eintr)
|
||||
|
||||
.data
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* from: vector.s, 386BSD 0.1 unknown origin
|
||||
* $Id: apic_vector.s,v 1.36 1999/04/14 14:26:35 bde Exp $
|
||||
* $Id: apic_vector.s,v 1.37 1999/04/28 01:04:12 luoqi Exp $
|
||||
*/
|
||||
|
||||
|
||||
@ -324,7 +324,7 @@ log_intr_event:
|
||||
|
||||
#ifdef CPL_AND_CML
|
||||
|
||||
#define INTR(irq_num, vec_name) \
|
||||
#define INTR(irq_num, vec_name, maybe_extra_ipending) \
|
||||
.text ; \
|
||||
SUPERALIGN_TEXT ; \
|
||||
/* _XintrNN: entry point used by IDT/HWIs & splz_unpend via _vec[]. */ \
|
||||
@ -335,6 +335,8 @@ IDTVEC(vec_name) ; \
|
||||
movl %ax, %es ; \
|
||||
movl $KPSEL, %eax ; \
|
||||
movl %ax, %fs ; \
|
||||
; \
|
||||
maybe_extra_ipending ; \
|
||||
; \
|
||||
APIC_ITRACE(apic_itrace_enter, irq_num, APIC_ITRACE_ENTER) ; \
|
||||
lock ; /* MP-safe */ \
|
||||
@ -436,7 +438,7 @@ __CONCAT(Xresume,irq_num): ; \
|
||||
#else /* CPL_AND_CML */
|
||||
|
||||
|
||||
#define INTR(irq_num, vec_name) \
|
||||
#define INTR(irq_num, vec_name, maybe_extra_ipending) \
|
||||
.text ; \
|
||||
SUPERALIGN_TEXT ; \
|
||||
/* _XintrNN: entry point used by IDT/HWIs & splz_unpend via _vec[]. */ \
|
||||
@ -447,6 +449,8 @@ IDTVEC(vec_name) ; \
|
||||
movl %ax, %es ; \
|
||||
movl $KPSEL, %eax ; \
|
||||
movl %ax, %fs ; \
|
||||
; \
|
||||
maybe_extra_ipending ; \
|
||||
; \
|
||||
APIC_ITRACE(apic_itrace_enter, irq_num, APIC_ITRACE_ENTER) ; \
|
||||
lock ; /* MP-safe */ \
|
||||
@ -916,30 +920,31 @@ MCOUNT_LABEL(bintr)
|
||||
FAST_INTR(21,fastintr21)
|
||||
FAST_INTR(22,fastintr22)
|
||||
FAST_INTR(23,fastintr23)
|
||||
INTR(0,intr0)
|
||||
INTR(1,intr1)
|
||||
INTR(2,intr2)
|
||||
INTR(3,intr3)
|
||||
INTR(4,intr4)
|
||||
INTR(5,intr5)
|
||||
INTR(6,intr6)
|
||||
INTR(7,intr7)
|
||||
INTR(8,intr8)
|
||||
INTR(9,intr9)
|
||||
INTR(10,intr10)
|
||||
INTR(11,intr11)
|
||||
INTR(12,intr12)
|
||||
INTR(13,intr13)
|
||||
INTR(14,intr14)
|
||||
INTR(15,intr15)
|
||||
INTR(16,intr16)
|
||||
INTR(17,intr17)
|
||||
INTR(18,intr18)
|
||||
INTR(19,intr19)
|
||||
INTR(20,intr20)
|
||||
INTR(21,intr21)
|
||||
INTR(22,intr22)
|
||||
INTR(23,intr23)
|
||||
#define CLKINTR_PENDING movl $1,CNAME(clkintr_pending)
|
||||
INTR(0,intr0, CLKINTR_PENDING)
|
||||
INTR(1,intr1,)
|
||||
INTR(2,intr2,)
|
||||
INTR(3,intr3,)
|
||||
INTR(4,intr4,)
|
||||
INTR(5,intr5,)
|
||||
INTR(6,intr6,)
|
||||
INTR(7,intr7,)
|
||||
INTR(8,intr8,)
|
||||
INTR(9,intr9,)
|
||||
INTR(10,intr10,)
|
||||
INTR(11,intr11,)
|
||||
INTR(12,intr12,)
|
||||
INTR(13,intr13,)
|
||||
INTR(14,intr14,)
|
||||
INTR(15,intr15,)
|
||||
INTR(16,intr16,)
|
||||
INTR(17,intr17,)
|
||||
INTR(18,intr18,)
|
||||
INTR(19,intr19,)
|
||||
INTR(20,intr20,)
|
||||
INTR(21,intr21,)
|
||||
INTR(22,intr22,)
|
||||
INTR(23,intr23,)
|
||||
MCOUNT_LABEL(eintr)
|
||||
|
||||
.data
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
|
||||
* $Id: clock.c,v 1.132 1999/04/25 09:00:00 phk Exp $
|
||||
* $Id: clock.c,v 1.133 1999/05/09 23:32:29 peter Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -69,6 +69,7 @@
|
||||
#include <machine/ipl.h>
|
||||
#include <machine/limits.h>
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/psl.h>
|
||||
#if NAPM > 0
|
||||
#include <machine/apm_bios.h>
|
||||
#include <i386/apm/apm_setup.h>
|
||||
@ -127,6 +128,7 @@ static void setup_8254_mixed_mode __P((void));
|
||||
#define TIMER0_MAX_FREQ 20000
|
||||
|
||||
int adjkerntz; /* local offset from GMT in seconds */
|
||||
int clkintr_pending;
|
||||
int disable_rtc_set; /* disable resettodr() if != 0 */
|
||||
volatile u_int idelayed;
|
||||
int statclock_disable;
|
||||
@ -199,24 +201,15 @@ static void
|
||||
clkintr(struct clockframe frame)
|
||||
{
|
||||
if (timecounter->tc_get_timecount == i8254_get_timecount) {
|
||||
/*
|
||||
* Maintain i8254_offset and related variables. Optimize
|
||||
* the usual case where i8254 counter rollover has not been
|
||||
* detected in i8254_get_timecount() by pretending that we
|
||||
* read the counter when it rolled over. Otherwise, call
|
||||
* i8254_get_timecount() to do most of the work. The
|
||||
* hardware counter must be read to ensure monotonicity
|
||||
* despite multiple rollovers and misbehaving hardware.
|
||||
*/
|
||||
(disable_intr)(); /* XXX avoid clock locking */
|
||||
if (i8254_ticked) {
|
||||
i8254_get_timecount(NULL);
|
||||
disable_intr();
|
||||
if (i8254_ticked)
|
||||
i8254_ticked = 0;
|
||||
} else {
|
||||
else {
|
||||
i8254_offset += timer0_max_count;
|
||||
i8254_lastcount = 0;
|
||||
}
|
||||
(enable_intr)(); /* XXX avoid clock locking */
|
||||
clkintr_pending = 0;
|
||||
enable_intr();
|
||||
}
|
||||
timer_func(&frame);
|
||||
switch (timer0_state) {
|
||||
@ -1159,13 +1152,21 @@ i8254_get_timecount(struct timecounter *tc)
|
||||
|
||||
low = inb(TIMER_CNTR0);
|
||||
high = inb(TIMER_CNTR0);
|
||||
|
||||
count = hardclock_max_count - ((high << 8) | low);
|
||||
if (count < i8254_lastcount) {
|
||||
count = timer0_max_count - ((high << 8) | low);
|
||||
if (count < i8254_lastcount ||
|
||||
(!i8254_ticked && (clkintr_pending ||
|
||||
((count < 20 || (!(ef & PSL_I) && count < timer0_max_count / 2u)) &&
|
||||
#ifdef APIC_IO
|
||||
#define lapic_irr1 ((volatile u_int *)&lapic)[0x210 / 4] /* XXX XXX */
|
||||
/* XXX this assumes that apic_8254_intr is < 24. */
|
||||
(lapic_irr1 & (1 << apic_8254_intr))))
|
||||
#else
|
||||
(inb(IO_ICU1) & 1)))
|
||||
#endif
|
||||
)) {
|
||||
i8254_ticked = 1;
|
||||
i8254_offset += hardclock_max_count;
|
||||
i8254_offset += timer0_max_count;
|
||||
}
|
||||
|
||||
i8254_lastcount = count;
|
||||
count += i8254_offset;
|
||||
CLOCK_UNLOCK();
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* from: vector.s, 386BSD 0.1 unknown origin
|
||||
* $Id: apic_vector.s,v 1.36 1999/04/14 14:26:35 bde Exp $
|
||||
* $Id: apic_vector.s,v 1.37 1999/04/28 01:04:12 luoqi Exp $
|
||||
*/
|
||||
|
||||
|
||||
@ -324,7 +324,7 @@ log_intr_event:
|
||||
|
||||
#ifdef CPL_AND_CML
|
||||
|
||||
#define INTR(irq_num, vec_name) \
|
||||
#define INTR(irq_num, vec_name, maybe_extra_ipending) \
|
||||
.text ; \
|
||||
SUPERALIGN_TEXT ; \
|
||||
/* _XintrNN: entry point used by IDT/HWIs & splz_unpend via _vec[]. */ \
|
||||
@ -335,6 +335,8 @@ IDTVEC(vec_name) ; \
|
||||
movl %ax, %es ; \
|
||||
movl $KPSEL, %eax ; \
|
||||
movl %ax, %fs ; \
|
||||
; \
|
||||
maybe_extra_ipending ; \
|
||||
; \
|
||||
APIC_ITRACE(apic_itrace_enter, irq_num, APIC_ITRACE_ENTER) ; \
|
||||
lock ; /* MP-safe */ \
|
||||
@ -436,7 +438,7 @@ __CONCAT(Xresume,irq_num): ; \
|
||||
#else /* CPL_AND_CML */
|
||||
|
||||
|
||||
#define INTR(irq_num, vec_name) \
|
||||
#define INTR(irq_num, vec_name, maybe_extra_ipending) \
|
||||
.text ; \
|
||||
SUPERALIGN_TEXT ; \
|
||||
/* _XintrNN: entry point used by IDT/HWIs & splz_unpend via _vec[]. */ \
|
||||
@ -447,6 +449,8 @@ IDTVEC(vec_name) ; \
|
||||
movl %ax, %es ; \
|
||||
movl $KPSEL, %eax ; \
|
||||
movl %ax, %fs ; \
|
||||
; \
|
||||
maybe_extra_ipending ; \
|
||||
; \
|
||||
APIC_ITRACE(apic_itrace_enter, irq_num, APIC_ITRACE_ENTER) ; \
|
||||
lock ; /* MP-safe */ \
|
||||
@ -916,30 +920,31 @@ MCOUNT_LABEL(bintr)
|
||||
FAST_INTR(21,fastintr21)
|
||||
FAST_INTR(22,fastintr22)
|
||||
FAST_INTR(23,fastintr23)
|
||||
INTR(0,intr0)
|
||||
INTR(1,intr1)
|
||||
INTR(2,intr2)
|
||||
INTR(3,intr3)
|
||||
INTR(4,intr4)
|
||||
INTR(5,intr5)
|
||||
INTR(6,intr6)
|
||||
INTR(7,intr7)
|
||||
INTR(8,intr8)
|
||||
INTR(9,intr9)
|
||||
INTR(10,intr10)
|
||||
INTR(11,intr11)
|
||||
INTR(12,intr12)
|
||||
INTR(13,intr13)
|
||||
INTR(14,intr14)
|
||||
INTR(15,intr15)
|
||||
INTR(16,intr16)
|
||||
INTR(17,intr17)
|
||||
INTR(18,intr18)
|
||||
INTR(19,intr19)
|
||||
INTR(20,intr20)
|
||||
INTR(21,intr21)
|
||||
INTR(22,intr22)
|
||||
INTR(23,intr23)
|
||||
#define CLKINTR_PENDING movl $1,CNAME(clkintr_pending)
|
||||
INTR(0,intr0, CLKINTR_PENDING)
|
||||
INTR(1,intr1,)
|
||||
INTR(2,intr2,)
|
||||
INTR(3,intr3,)
|
||||
INTR(4,intr4,)
|
||||
INTR(5,intr5,)
|
||||
INTR(6,intr6,)
|
||||
INTR(7,intr7,)
|
||||
INTR(8,intr8,)
|
||||
INTR(9,intr9,)
|
||||
INTR(10,intr10,)
|
||||
INTR(11,intr11,)
|
||||
INTR(12,intr12,)
|
||||
INTR(13,intr13,)
|
||||
INTR(14,intr14,)
|
||||
INTR(15,intr15,)
|
||||
INTR(16,intr16,)
|
||||
INTR(17,intr17,)
|
||||
INTR(18,intr18,)
|
||||
INTR(19,intr19,)
|
||||
INTR(20,intr20,)
|
||||
INTR(21,intr21,)
|
||||
INTR(22,intr22,)
|
||||
INTR(23,intr23,)
|
||||
MCOUNT_LABEL(eintr)
|
||||
|
||||
.data
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* from: vector.s, 386BSD 0.1 unknown origin
|
||||
* $Id: icu_vector.s,v 1.10 1999/04/14 14:26:36 bde Exp $
|
||||
* $Id: icu_vector.s,v 1.11 1999/04/28 01:04:13 luoqi Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -106,7 +106,7 @@ IDTVEC(vec_name) ; \
|
||||
MEXITCOUNT ; \
|
||||
jmp _doreti
|
||||
|
||||
#define INTR(irq_num, vec_name, icu, enable_icus, reg) \
|
||||
#define INTR(irq_num, vec_name, icu, enable_icus, reg, maybe_extra_ipending) \
|
||||
.text ; \
|
||||
SUPERALIGN_TEXT ; \
|
||||
IDTVEC(vec_name) ; \
|
||||
@ -120,6 +120,7 @@ IDTVEC(vec_name) ; \
|
||||
movl %ax,%ds ; /* ... early for obsolete reasons */ \
|
||||
movl %ax,%es ; \
|
||||
movl %ax,%fs ; \
|
||||
maybe_extra_ipending ; \
|
||||
movb _imen + IRQ_BYTE(irq_num),%al ; \
|
||||
orb $IRQ_BIT(irq_num),%al ; \
|
||||
movb %al,_imen + IRQ_BYTE(irq_num) ; \
|
||||
@ -180,22 +181,23 @@ MCOUNT_LABEL(bintr)
|
||||
FAST_INTR(13,fastintr13, ENABLE_ICU1_AND_2)
|
||||
FAST_INTR(14,fastintr14, ENABLE_ICU1_AND_2)
|
||||
FAST_INTR(15,fastintr15, ENABLE_ICU1_AND_2)
|
||||
INTR(0,intr0, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(1,intr1, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(2,intr2, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(3,intr3, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(4,intr4, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(5,intr5, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(6,intr6, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(7,intr7, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(8,intr8, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(9,intr9, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(10,intr10, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(11,intr11, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(12,intr12, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(13,intr13, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(14,intr14, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(15,intr15, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
#define CLKINTR_PENDING movl $1,CNAME(clkintr_pending)
|
||||
INTR(0,intr0, IO_ICU1, ENABLE_ICU1, al, CLKINTR_PENDING)
|
||||
INTR(1,intr1, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(2,intr2, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(3,intr3, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(4,intr4, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(5,intr5, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(6,intr6, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(7,intr7, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(8,intr8, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(9,intr9, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(10,intr10, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(11,intr11, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(12,intr12, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(13,intr13, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(14,intr14, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(15,intr15, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
MCOUNT_LABEL(eintr)
|
||||
|
||||
.data
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
|
||||
* $Id: clock.c,v 1.132 1999/04/25 09:00:00 phk Exp $
|
||||
* $Id: clock.c,v 1.133 1999/05/09 23:32:29 peter Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -69,6 +69,7 @@
|
||||
#include <machine/ipl.h>
|
||||
#include <machine/limits.h>
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/psl.h>
|
||||
#if NAPM > 0
|
||||
#include <machine/apm_bios.h>
|
||||
#include <i386/apm/apm_setup.h>
|
||||
@ -127,6 +128,7 @@ static void setup_8254_mixed_mode __P((void));
|
||||
#define TIMER0_MAX_FREQ 20000
|
||||
|
||||
int adjkerntz; /* local offset from GMT in seconds */
|
||||
int clkintr_pending;
|
||||
int disable_rtc_set; /* disable resettodr() if != 0 */
|
||||
volatile u_int idelayed;
|
||||
int statclock_disable;
|
||||
@ -199,24 +201,15 @@ static void
|
||||
clkintr(struct clockframe frame)
|
||||
{
|
||||
if (timecounter->tc_get_timecount == i8254_get_timecount) {
|
||||
/*
|
||||
* Maintain i8254_offset and related variables. Optimize
|
||||
* the usual case where i8254 counter rollover has not been
|
||||
* detected in i8254_get_timecount() by pretending that we
|
||||
* read the counter when it rolled over. Otherwise, call
|
||||
* i8254_get_timecount() to do most of the work. The
|
||||
* hardware counter must be read to ensure monotonicity
|
||||
* despite multiple rollovers and misbehaving hardware.
|
||||
*/
|
||||
(disable_intr)(); /* XXX avoid clock locking */
|
||||
if (i8254_ticked) {
|
||||
i8254_get_timecount(NULL);
|
||||
disable_intr();
|
||||
if (i8254_ticked)
|
||||
i8254_ticked = 0;
|
||||
} else {
|
||||
else {
|
||||
i8254_offset += timer0_max_count;
|
||||
i8254_lastcount = 0;
|
||||
}
|
||||
(enable_intr)(); /* XXX avoid clock locking */
|
||||
clkintr_pending = 0;
|
||||
enable_intr();
|
||||
}
|
||||
timer_func(&frame);
|
||||
switch (timer0_state) {
|
||||
@ -1159,13 +1152,21 @@ i8254_get_timecount(struct timecounter *tc)
|
||||
|
||||
low = inb(TIMER_CNTR0);
|
||||
high = inb(TIMER_CNTR0);
|
||||
|
||||
count = hardclock_max_count - ((high << 8) | low);
|
||||
if (count < i8254_lastcount) {
|
||||
count = timer0_max_count - ((high << 8) | low);
|
||||
if (count < i8254_lastcount ||
|
||||
(!i8254_ticked && (clkintr_pending ||
|
||||
((count < 20 || (!(ef & PSL_I) && count < timer0_max_count / 2u)) &&
|
||||
#ifdef APIC_IO
|
||||
#define lapic_irr1 ((volatile u_int *)&lapic)[0x210 / 4] /* XXX XXX */
|
||||
/* XXX this assumes that apic_8254_intr is < 24. */
|
||||
(lapic_irr1 & (1 << apic_8254_intr))))
|
||||
#else
|
||||
(inb(IO_ICU1) & 1)))
|
||||
#endif
|
||||
)) {
|
||||
i8254_ticked = 1;
|
||||
i8254_offset += hardclock_max_count;
|
||||
i8254_offset += timer0_max_count;
|
||||
}
|
||||
|
||||
i8254_lastcount = count;
|
||||
count += i8254_offset;
|
||||
CLOCK_UNLOCK();
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* from: vector.s, 386BSD 0.1 unknown origin
|
||||
* $Id: icu_vector.s,v 1.10 1999/04/14 14:26:36 bde Exp $
|
||||
* $Id: icu_vector.s,v 1.11 1999/04/28 01:04:13 luoqi Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -106,7 +106,7 @@ IDTVEC(vec_name) ; \
|
||||
MEXITCOUNT ; \
|
||||
jmp _doreti
|
||||
|
||||
#define INTR(irq_num, vec_name, icu, enable_icus, reg) \
|
||||
#define INTR(irq_num, vec_name, icu, enable_icus, reg, maybe_extra_ipending) \
|
||||
.text ; \
|
||||
SUPERALIGN_TEXT ; \
|
||||
IDTVEC(vec_name) ; \
|
||||
@ -120,6 +120,7 @@ IDTVEC(vec_name) ; \
|
||||
movl %ax,%ds ; /* ... early for obsolete reasons */ \
|
||||
movl %ax,%es ; \
|
||||
movl %ax,%fs ; \
|
||||
maybe_extra_ipending ; \
|
||||
movb _imen + IRQ_BYTE(irq_num),%al ; \
|
||||
orb $IRQ_BIT(irq_num),%al ; \
|
||||
movb %al,_imen + IRQ_BYTE(irq_num) ; \
|
||||
@ -180,22 +181,23 @@ MCOUNT_LABEL(bintr)
|
||||
FAST_INTR(13,fastintr13, ENABLE_ICU1_AND_2)
|
||||
FAST_INTR(14,fastintr14, ENABLE_ICU1_AND_2)
|
||||
FAST_INTR(15,fastintr15, ENABLE_ICU1_AND_2)
|
||||
INTR(0,intr0, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(1,intr1, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(2,intr2, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(3,intr3, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(4,intr4, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(5,intr5, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(6,intr6, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(7,intr7, IO_ICU1, ENABLE_ICU1, al)
|
||||
INTR(8,intr8, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(9,intr9, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(10,intr10, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(11,intr11, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(12,intr12, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(13,intr13, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(14,intr14, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
INTR(15,intr15, IO_ICU2, ENABLE_ICU1_AND_2, ah)
|
||||
#define CLKINTR_PENDING movl $1,CNAME(clkintr_pending)
|
||||
INTR(0,intr0, IO_ICU1, ENABLE_ICU1, al, CLKINTR_PENDING)
|
||||
INTR(1,intr1, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(2,intr2, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(3,intr3, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(4,intr4, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(5,intr5, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(6,intr6, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(7,intr7, IO_ICU1, ENABLE_ICU1, al,)
|
||||
INTR(8,intr8, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(9,intr9, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(10,intr10, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(11,intr11, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(12,intr12, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(13,intr13, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(14,intr14, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
INTR(15,intr15, IO_ICU2, ENABLE_ICU1_AND_2, ah,)
|
||||
MCOUNT_LABEL(eintr)
|
||||
|
||||
.data
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
|
||||
* $Id: clock.c,v 1.132 1999/04/25 09:00:00 phk Exp $
|
||||
* $Id: clock.c,v 1.133 1999/05/09 23:32:29 peter Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -69,6 +69,7 @@
|
||||
#include <machine/ipl.h>
|
||||
#include <machine/limits.h>
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/psl.h>
|
||||
#if NAPM > 0
|
||||
#include <machine/apm_bios.h>
|
||||
#include <i386/apm/apm_setup.h>
|
||||
@ -127,6 +128,7 @@ static void setup_8254_mixed_mode __P((void));
|
||||
#define TIMER0_MAX_FREQ 20000
|
||||
|
||||
int adjkerntz; /* local offset from GMT in seconds */
|
||||
int clkintr_pending;
|
||||
int disable_rtc_set; /* disable resettodr() if != 0 */
|
||||
volatile u_int idelayed;
|
||||
int statclock_disable;
|
||||
@ -199,24 +201,15 @@ static void
|
||||
clkintr(struct clockframe frame)
|
||||
{
|
||||
if (timecounter->tc_get_timecount == i8254_get_timecount) {
|
||||
/*
|
||||
* Maintain i8254_offset and related variables. Optimize
|
||||
* the usual case where i8254 counter rollover has not been
|
||||
* detected in i8254_get_timecount() by pretending that we
|
||||
* read the counter when it rolled over. Otherwise, call
|
||||
* i8254_get_timecount() to do most of the work. The
|
||||
* hardware counter must be read to ensure monotonicity
|
||||
* despite multiple rollovers and misbehaving hardware.
|
||||
*/
|
||||
(disable_intr)(); /* XXX avoid clock locking */
|
||||
if (i8254_ticked) {
|
||||
i8254_get_timecount(NULL);
|
||||
disable_intr();
|
||||
if (i8254_ticked)
|
||||
i8254_ticked = 0;
|
||||
} else {
|
||||
else {
|
||||
i8254_offset += timer0_max_count;
|
||||
i8254_lastcount = 0;
|
||||
}
|
||||
(enable_intr)(); /* XXX avoid clock locking */
|
||||
clkintr_pending = 0;
|
||||
enable_intr();
|
||||
}
|
||||
timer_func(&frame);
|
||||
switch (timer0_state) {
|
||||
@ -1159,13 +1152,21 @@ i8254_get_timecount(struct timecounter *tc)
|
||||
|
||||
low = inb(TIMER_CNTR0);
|
||||
high = inb(TIMER_CNTR0);
|
||||
|
||||
count = hardclock_max_count - ((high << 8) | low);
|
||||
if (count < i8254_lastcount) {
|
||||
count = timer0_max_count - ((high << 8) | low);
|
||||
if (count < i8254_lastcount ||
|
||||
(!i8254_ticked && (clkintr_pending ||
|
||||
((count < 20 || (!(ef & PSL_I) && count < timer0_max_count / 2u)) &&
|
||||
#ifdef APIC_IO
|
||||
#define lapic_irr1 ((volatile u_int *)&lapic)[0x210 / 4] /* XXX XXX */
|
||||
/* XXX this assumes that apic_8254_intr is < 24. */
|
||||
(lapic_irr1 & (1 << apic_8254_intr))))
|
||||
#else
|
||||
(inb(IO_ICU1) & 1)))
|
||||
#endif
|
||||
)) {
|
||||
i8254_ticked = 1;
|
||||
i8254_offset += hardclock_max_count;
|
||||
i8254_offset += timer0_max_count;
|
||||
}
|
||||
|
||||
i8254_lastcount = count;
|
||||
count += i8254_offset;
|
||||
CLOCK_UNLOCK();
|
||||
|
Loading…
Reference in New Issue
Block a user