Fix the endless stream of 7's problem on i8259-like interrupt controllers
once and for all. The i8259 does not like to be read in a loop, when an interrupt comes in, it will return a valid value, however, if you keep reading it until there are no outstanding interrupts, it will return 7 (which is the lpt interrupt). Change the pic handler to give an argument to the get_irq functions of mode, which indicates if this is the first time we are asking, or if we are just rechecking in a loop. Non-i8259 handlers can safely ignore this argument. Tested to fix the stream of 7's problem on prep and ofppc. Got rid of the nasty hack in ofppc with this too, and the prep machine seems to take less interrupts now, which is a good thing.
This commit is contained in:
parent
19e49bf314
commit
76a99a952a
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: pic_bebox.c,v 1.2 2007/10/17 19:53:59 garbled Exp $ */
|
||||
/* $NetBSD: pic_bebox.c,v 1.3 2007/12/11 18:04:18 garbled Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2007 The NetBSD Foundation, Inc.
|
||||
@ -37,7 +37,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: pic_bebox.c,v 1.2 2007/10/17 19:53:59 garbled Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: pic_bebox.c,v 1.3 2007/12/11 18:04:18 garbled Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/malloc.h>
|
||||
@ -60,7 +60,7 @@ extern paddr_t bebox_mb_reg;
|
||||
|
||||
static void bebox_enable_irq(struct pic_ops *, int, int);
|
||||
static void bebox_disable_irq(struct pic_ops *, int);
|
||||
static int bebox_get_irq(struct pic_ops *);
|
||||
static int bebox_get_irq(struct pic_ops *, int);
|
||||
static void bebox_ack_irq(struct pic_ops *, int);
|
||||
struct pic_ops * setup_bebox_intr(void);
|
||||
|
||||
@ -100,7 +100,7 @@ bebox_disable_irq(struct pic_ops *pic, int irq)
|
||||
}
|
||||
|
||||
static int
|
||||
bebox_get_irq(struct pic_ops *pic)
|
||||
bebox_get_irq(struct pic_ops *pic, int mode)
|
||||
{
|
||||
int irq;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: pic_heathrow.c,v 1.2 2007/10/17 19:55:34 garbled Exp $ */
|
||||
/* $NetBSD: pic_heathrow.c,v 1.3 2007/12/11 18:04:19 garbled Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2007 Michael Lorenz
|
||||
@ -30,7 +30,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: pic_heathrow.c,v 1.2 2007/10/17 19:55:34 garbled Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: pic_heathrow.c,v 1.3 2007/12/11 18:04:19 garbled Exp $");
|
||||
|
||||
#include "opt_interrupt.h"
|
||||
|
||||
@ -50,7 +50,7 @@ __KERNEL_RCSID(0, "$NetBSD: pic_heathrow.c,v 1.2 2007/10/17 19:55:34 garbled Exp
|
||||
static void heathrow_enable_irq(struct pic_ops *, int, int);
|
||||
static void heathrow_reenable_irq(struct pic_ops *, int, int);
|
||||
static void heathrow_disable_irq(struct pic_ops *, int);
|
||||
static int heathrow_get_irq(struct pic_ops *);
|
||||
static int heathrow_get_irq(struct pic_ops *, int);
|
||||
static void heathrow_ack_irq(struct pic_ops *, int);
|
||||
static void heathrow_establish_irq(struct pic_ops *, int, int, int);
|
||||
|
||||
@ -223,7 +223,7 @@ heathrow_read_events(struct heathrow_ops *heathrow)
|
||||
}
|
||||
|
||||
static int
|
||||
heathrow_get_irq(struct pic_ops *pic)
|
||||
heathrow_get_irq(struct pic_ops *pic, int mode)
|
||||
{
|
||||
struct heathrow_ops *heathrow = (struct heathrow_ops *)pic;
|
||||
int bit, mask;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: pic_ohare.c,v 1.2 2007/10/17 19:55:34 garbled Exp $ */
|
||||
/* $NetBSD: pic_ohare.c,v 1.3 2007/12/11 18:04:19 garbled Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2007 Michael Lorenz
|
||||
@ -30,7 +30,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: pic_ohare.c,v 1.2 2007/10/17 19:55:34 garbled Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: pic_ohare.c,v 1.3 2007/12/11 18:04:19 garbled Exp $");
|
||||
|
||||
#include "opt_interrupt.h"
|
||||
|
||||
@ -50,7 +50,7 @@ __KERNEL_RCSID(0, "$NetBSD: pic_ohare.c,v 1.2 2007/10/17 19:55:34 garbled Exp $"
|
||||
static void ohare_enable_irq(struct pic_ops *, int, int);
|
||||
static void ohare_reenable_irq(struct pic_ops *, int, int);
|
||||
static void ohare_disable_irq(struct pic_ops *, int);
|
||||
static int ohare_get_irq(struct pic_ops *);
|
||||
static int ohare_get_irq(struct pic_ops *, int);
|
||||
static void ohare_ack_irq(struct pic_ops *, int);
|
||||
static void ohare_establish_irq(struct pic_ops *, int, int, int);
|
||||
|
||||
@ -223,7 +223,7 @@ ohare_read_events(struct ohare_ops *ohare)
|
||||
}
|
||||
|
||||
static int
|
||||
ohare_get_irq(struct pic_ops *pic)
|
||||
ohare_get_irq(struct pic_ops *pic, int mode)
|
||||
{
|
||||
struct ohare_ops *ohare = (struct ohare_ops *)pic;
|
||||
uint32_t evt;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: mainbus.c,v 1.17 2007/11/07 19:31:10 garbled Exp $ */
|
||||
/* $NetBSD: mainbus.c,v 1.18 2007/12/11 18:04:19 garbled Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2007 The NetBSD Foundation, Inc.
|
||||
@ -37,7 +37,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.17 2007/11/07 19:31:10 garbled Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.18 2007/12/11 18:04:19 garbled Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/device.h>
|
||||
@ -57,8 +57,6 @@ __KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.17 2007/11/07 19:31:10 garbled Exp $")
|
||||
int mainbus_match(struct device *, struct cfdata *, void *);
|
||||
void mainbus_attach(struct device *, struct device *, void *);
|
||||
|
||||
static int pegasos_get_irq(struct pic_ops *);
|
||||
|
||||
CFATTACH_DECL(mainbus, sizeof(struct device),
|
||||
mainbus_match, mainbus_attach, NULL, NULL);
|
||||
|
||||
@ -164,7 +162,6 @@ void
|
||||
init_interrupt(void)
|
||||
{
|
||||
int node, i, isa_cascade = 0;
|
||||
char name[32];
|
||||
|
||||
/* Now setup the PIC's */
|
||||
node = OF_finddevice("/");
|
||||
@ -195,32 +192,4 @@ init_interrupt(void)
|
||||
intr_establish(16, IST_LEVEL, IPL_NONE, pic_handle_intr,
|
||||
isa_pic);
|
||||
}
|
||||
|
||||
/* The PegasosII is wierd (surprise!) and needs a prepivr style
|
||||
* get_irq routine. yay.
|
||||
*/
|
||||
memset(name, 0, sizeof(name));
|
||||
OF_getprop(node, "name", name, sizeof(name));
|
||||
if (strcmp(name, "bplan,Pegasos2") == 0)
|
||||
isa_pic->pic_get_irq = pegasos_get_irq;
|
||||
}
|
||||
|
||||
static int
|
||||
pegasos_get_irq(struct pic_ops *pic)
|
||||
{
|
||||
static int lirq;
|
||||
int irq;
|
||||
|
||||
irq = i8259_get_irq(pic);
|
||||
|
||||
if (lirq == 7 && irq == lirq) {
|
||||
lirq = -1;
|
||||
return 255;
|
||||
}
|
||||
|
||||
lirq = irq;
|
||||
if (irq == 0)
|
||||
return 255;
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: i8259_common.c,v 1.2 2007/10/17 19:56:45 garbled Exp $ */
|
||||
/* $NetBSD: i8259_common.c,v 1.3 2007/12/11 18:04:19 garbled Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2007 The NetBSD Foundation, Inc.
|
||||
@ -37,7 +37,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: i8259_common.c,v 1.2 2007/10/17 19:56:45 garbled Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: i8259_common.c,v 1.3 2007/12/11 18:04:19 garbled Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/malloc.h>
|
||||
@ -106,7 +106,7 @@ i8259_ack_irq(struct pic_ops *pic, int irq)
|
||||
}
|
||||
|
||||
int
|
||||
i8259_get_irq(struct pic_ops *pic)
|
||||
i8259_get_irq(struct pic_ops *pic, int mode)
|
||||
{
|
||||
int irq;
|
||||
|
||||
@ -117,7 +117,9 @@ i8259_get_irq(struct pic_ops *pic)
|
||||
irq = (isa_inb(IO_ICU2) & 0x07) + 8;
|
||||
}
|
||||
|
||||
if (irq == 0)
|
||||
if (irq == 0 && mode == PIC_GET_IRQ)
|
||||
return 255;
|
||||
if (irq == 7 && mode == PIC_GET_RECHECK)
|
||||
return 255;
|
||||
|
||||
return irq;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: intr.c,v 1.3 2007/12/03 15:34:14 ad Exp $ */
|
||||
/* $NetBSD: intr.c,v 1.4 2007/12/11 18:04:19 garbled Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2007 Michael Lorenz
|
||||
@ -30,7 +30,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.3 2007/12/03 15:34:14 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.4 2007/12/11 18:04:19 garbled Exp $");
|
||||
|
||||
#include "opt_multiprocessor.h"
|
||||
|
||||
@ -586,7 +586,7 @@ pic_handle_intr(void *cookie)
|
||||
int irq, realirq;
|
||||
int pcpl, msr, r_imen, bail;
|
||||
|
||||
realirq = pic->pic_get_irq(pic);
|
||||
realirq = pic->pic_get_irq(pic, PIC_GET_IRQ);
|
||||
if (realirq == 255)
|
||||
return 0;
|
||||
|
||||
@ -600,7 +600,7 @@ start:
|
||||
while (realirq == ipiops.ppc_ipi_vector) {
|
||||
ppcipi_intr(NULL);
|
||||
pic->pic_ack_irq(pic, realirq);
|
||||
realirq = pic->pic_get_irq(pic);
|
||||
realirq = pic->pic_get_irq(pic, PIC_GET_IRQ);
|
||||
}
|
||||
if (realirq == 255) {
|
||||
return 0;
|
||||
@ -657,7 +657,7 @@ start:
|
||||
boo:
|
||||
#endif /* PIC_DEBUG */
|
||||
pic->pic_ack_irq(pic, realirq);
|
||||
realirq = pic->pic_get_irq(pic);
|
||||
realirq = pic->pic_get_irq(pic, PIC_GET_RECHECK);
|
||||
if (realirq != 255)
|
||||
goto start;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: pic_openpic.c,v 1.2 2007/10/17 19:56:46 garbled Exp $ */
|
||||
/* $NetBSD: pic_openpic.c,v 1.3 2007/12/11 18:04:20 garbled Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2007 Michael Lorenz
|
||||
@ -30,7 +30,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: pic_openpic.c,v 1.2 2007/10/17 19:56:46 garbled Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: pic_openpic.c,v 1.3 2007/12/11 18:04:20 garbled Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/malloc.h>
|
||||
@ -48,7 +48,7 @@ __KERNEL_RCSID(0, "$NetBSD: pic_openpic.c,v 1.2 2007/10/17 19:56:46 garbled Exp
|
||||
void openpic_set_priority(int cpu, int pri);
|
||||
static void opic_enable_irq(struct pic_ops *, int, int);
|
||||
static void opic_disable_irq(struct pic_ops *, int);
|
||||
static int opic_get_irq(struct pic_ops *);
|
||||
static int opic_get_irq(struct pic_ops *, int);
|
||||
static void opic_ack_irq(struct pic_ops *, int);
|
||||
static void opic_establish_irq(struct pic_ops*, int, int, int);
|
||||
static void opic_finish_setup(struct pic_ops *);
|
||||
@ -203,7 +203,7 @@ opic_disable_irq(struct pic_ops *pic, int irq)
|
||||
}
|
||||
|
||||
static int
|
||||
opic_get_irq(struct pic_ops *pic)
|
||||
opic_get_irq(struct pic_ops *pic, int mode)
|
||||
{
|
||||
|
||||
return openpic_read_irq(cpu_number());
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: pic_prepivr.c,v 1.2 2007/10/17 19:56:46 garbled Exp $ */
|
||||
/* $NetBSD: pic_prepivr.c,v 1.3 2007/12/11 18:04:20 garbled Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2007 The NetBSD Foundation, Inc.
|
||||
@ -37,7 +37,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: pic_prepivr.c,v 1.2 2007/10/17 19:56:46 garbled Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: pic_prepivr.c,v 1.3 2007/12/11 18:04:20 garbled Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/malloc.h>
|
||||
@ -53,8 +53,8 @@ __KERNEL_RCSID(0, "$NetBSD: pic_prepivr.c,v 1.2 2007/10/17 19:56:46 garbled Exp
|
||||
#include <dev/isa/isareg.h>
|
||||
#include <dev/isa/isavar.h>
|
||||
|
||||
static int prepivr_get_irq(struct pic_ops *);
|
||||
static int motivr_get_irq(struct pic_ops *);
|
||||
static int prepivr_get_irq(struct pic_ops *, int);
|
||||
static int motivr_get_irq(struct pic_ops *, int);
|
||||
static void prepivr_establish_irq(struct pic_ops *, int, int, int);
|
||||
|
||||
vaddr_t prep_intr_reg; /* PReP interrupt vector register */
|
||||
@ -128,41 +128,28 @@ prepivr_establish_irq(struct pic_ops *pic, int irq, int type, int maxlevel)
|
||||
}
|
||||
|
||||
static int
|
||||
motivr_get_irq(struct pic_ops *pic)
|
||||
motivr_get_irq(struct pic_ops *pic, int mode)
|
||||
{
|
||||
static int lirq;
|
||||
int irq;
|
||||
|
||||
irq = i8259_get_irq(pic);
|
||||
irq = i8259_get_irq(pic, mode);
|
||||
/* read the IVR to ack it */
|
||||
(void)inb(pic->pic_cookie);
|
||||
|
||||
if (lirq == 7 && irq == lirq) {
|
||||
lirq = -1;
|
||||
return 255;
|
||||
}
|
||||
|
||||
lirq = irq;
|
||||
if (irq == 0)
|
||||
return 255;
|
||||
|
||||
/* i8259_get_irq will return 255 by itself, so just pass it on */
|
||||
return irq;
|
||||
}
|
||||
|
||||
static int
|
||||
prepivr_get_irq(struct pic_ops *pic)
|
||||
prepivr_get_irq(struct pic_ops *pic, int mode)
|
||||
{
|
||||
static int lirq;
|
||||
int irq;
|
||||
|
||||
irq = inb(pic->pic_cookie);
|
||||
if (lirq == 7 && irq == lirq) {
|
||||
lirq = -1;
|
||||
return 255;
|
||||
}
|
||||
|
||||
lirq = irq;
|
||||
if (irq == 0)
|
||||
if (irq == 0 && mode == PIC_GET_IRQ)
|
||||
return 255;
|
||||
if (irq == 7 && mode == PIC_GET_RECHECK)
|
||||
return 255;
|
||||
|
||||
return irq;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: picvar.h,v 1.2 2007/10/17 19:56:46 garbled Exp $ */
|
||||
/* $NetBSD: picvar.h,v 1.3 2007/12/11 18:04:20 garbled Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2007 Michael Lorenz
|
||||
@ -30,7 +30,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: picvar.h,v 1.2 2007/10/17 19:56:46 garbled Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: picvar.h,v 1.3 2007/12/11 18:04:20 garbled Exp $");
|
||||
|
||||
#ifndef PIC_VAR_H
|
||||
#define PIC_VAR_H
|
||||
@ -48,7 +48,7 @@ struct pic_ops {
|
||||
void (*pic_enable_irq)(struct pic_ops *, int, int);
|
||||
void (*pic_reenable_irq)(struct pic_ops *, int, int);
|
||||
void (*pic_disable_irq)(struct pic_ops *, int);
|
||||
int (*pic_get_irq)(struct pic_ops *);
|
||||
int (*pic_get_irq)(struct pic_ops *, int); /* PIC_GET_* */
|
||||
void (*pic_ack_irq)(struct pic_ops *, int); /* IRQ numbner */
|
||||
/* IRQ number, type, priority */
|
||||
void (*pic_establish_irq)(struct pic_ops *, int, int, int);
|
||||
@ -98,6 +98,8 @@ void pic_finish_setup(void);
|
||||
/* address, enable passthrough */
|
||||
#define PIC_IVR_IBM 0
|
||||
#define PIC_IVR_MOT 1
|
||||
#define PIC_GET_IRQ 0
|
||||
#define PIC_GET_RECHECK 1
|
||||
struct pic_ops *setup_openpic(void *, int);
|
||||
struct pic_ops *setup_prepivr(int);
|
||||
struct pic_ops *setup_i8259(void);
|
||||
@ -107,7 +109,7 @@ void i8259_initialize(void);
|
||||
void i8259_enable_irq(struct pic_ops *, int, int);
|
||||
void i8259_disable_irq(struct pic_ops *, int);
|
||||
void i8259_ack_irq(struct pic_ops *, int);
|
||||
int i8259_get_irq(struct pic_ops *);
|
||||
int i8259_get_irq(struct pic_ops *, int);
|
||||
|
||||
/* IPI handler */
|
||||
int cpuintr(void *);
|
||||
|
Loading…
Reference in New Issue
Block a user