Check in work-in-progress of generic ISA interrupt support. The
goal here is to get the P-5064 PCMCIA slots working, and serve as the basis for P-6032 interrupt support. PCMCIA interrupt auto-detection not working -- more work to be done here.
This commit is contained in:
parent
82418a77b0
commit
7c074dc806
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: algor_p4032_intr.c,v 1.2 2001/06/10 05:26:58 thorpej Exp $ */
|
||||
/* $NetBSD: algor_p4032_intr.c,v 1.3 2001/06/10 09:13:06 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
|
@ -186,13 +186,6 @@ const struct p4032_irqmap p4032_irqmap[NIRQMAPS] = {
|
|||
1, 6 },
|
||||
};
|
||||
|
||||
struct p4032_intrhand {
|
||||
LIST_ENTRY(p4032_intrhand) ih_q;
|
||||
int (*ih_func)(void *);
|
||||
void *ih_arg;
|
||||
const struct p4032_irqmap *ih_irqmap;
|
||||
};
|
||||
|
||||
struct p4032_intrhead {
|
||||
struct evcnt intr_count;
|
||||
int intr_refcnt;
|
||||
|
@ -202,7 +195,7 @@ struct p4032_intrhead p4032_intrtab[NIRQMAPS];
|
|||
#define NINTRS 2 /* MIPS INT0 - INT1 */
|
||||
|
||||
struct p4032_cpuintr {
|
||||
LIST_HEAD(, p4032_intrhand) cintr_list;
|
||||
LIST_HEAD(, algor_intrhand) cintr_list;
|
||||
struct evcnt cintr_count;
|
||||
};
|
||||
|
||||
|
@ -338,7 +331,7 @@ void *
|
|||
algor_p4032_intr_establish(const struct p4032_irqmap *irqmap,
|
||||
int (*func)(void *), void *arg)
|
||||
{
|
||||
struct p4032_intrhand *ih;
|
||||
struct algor_intrhand *ih;
|
||||
int s;
|
||||
|
||||
ih = malloc(sizeof(*ih), M_DEVBUF, M_NOWAIT);
|
||||
|
@ -347,6 +340,7 @@ algor_p4032_intr_establish(const struct p4032_irqmap *irqmap,
|
|||
|
||||
ih->ih_func = func;
|
||||
ih->ih_arg = arg;
|
||||
ih->ih_irq = 0;
|
||||
ih->ih_irqmap = irqmap;
|
||||
|
||||
s = splhigh();
|
||||
|
@ -375,7 +369,7 @@ void
|
|||
algor_p4032_intr_disestablish(void *v, void *cookie)
|
||||
{
|
||||
const struct p4032_irqmap *irqmap;
|
||||
struct p4032_intrhand *ih = v;
|
||||
struct algor_intrhand *ih = v;
|
||||
int s;
|
||||
|
||||
s = splhigh();
|
||||
|
@ -404,7 +398,8 @@ void
|
|||
algor_p4032_iointr(u_int32_t status, u_int32_t cause, u_int32_t pc,
|
||||
u_int32_t ipending)
|
||||
{
|
||||
struct p4032_intrhand *ih;
|
||||
const struct p4032_irqmap *irqmap;
|
||||
struct algor_intrhand *ih;
|
||||
int level, i;
|
||||
u_int32_t irr[NIRQREG];
|
||||
|
||||
|
@ -460,10 +455,10 @@ algor_p4032_iointr(u_int32_t status, u_int32_t cause, u_int32_t pc,
|
|||
p4032_cpuintrs[level].cintr_count.ev_count++;
|
||||
for (ih = LIST_FIRST(&p4032_cpuintrs[level].cintr_list);
|
||||
ih != NULL; ih = LIST_NEXT(ih, ih_q)) {
|
||||
if (irr[ih->ih_irqmap->irqreg] &
|
||||
ih->ih_irqmap->irqbit) {
|
||||
irqmap = ih->ih_irqmap;
|
||||
if (irr[irqmap->irqreg] & irqmap->irqbit) {
|
||||
p4032_intrtab[
|
||||
ih->ih_irqmap->irqidx].intr_count.ev_count++;
|
||||
irqmap->irqidx].intr_count.ev_count++;
|
||||
(*ih->ih_func)(ih->ih_arg);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: algor_p5064_intr.c,v 1.2 2001/06/10 05:26:58 thorpej Exp $ */
|
||||
/* $NetBSD: algor_p5064_intr.c,v 1.3 2001/06/10 09:13:07 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
|
@ -80,15 +80,6 @@ struct p5064_irqreg {
|
|||
u_int32_t val;
|
||||
};
|
||||
|
||||
struct p5064_irqmap {
|
||||
int irqidx;
|
||||
int cpuintr;
|
||||
int irqreg;
|
||||
int irqbit;
|
||||
int xbarreg;
|
||||
int xbarshift;
|
||||
};
|
||||
|
||||
#define IRQREG_LOCINT 0
|
||||
#define IRQREG_PANIC 1
|
||||
#define IRQREG_PCIINT 2
|
||||
|
@ -114,22 +105,10 @@ struct p5064_irqreg p5064_irqsteer[NSTEERREG] = {
|
|||
{ P5064_XBAR4, 0 },
|
||||
};
|
||||
|
||||
#define IRQ_ETHERNET 4
|
||||
#define IRQ_SCSI 5
|
||||
#define IRQ_USB 6
|
||||
#define NPCIIRQS 7
|
||||
|
||||
#define IRQ_MKBD 7
|
||||
#define IRQ_COM1 8
|
||||
#define IRQ_COM2 9
|
||||
#define IRQ_FLOPPY 10
|
||||
#define IRQ_CENTRONICS 11
|
||||
#define IRQ_RTC 12
|
||||
#define NLOCIRQS 6
|
||||
|
||||
#define IRQ_ISABRIDGE 13
|
||||
#define IRQ_IDE0 14
|
||||
#define IRQ_IDE1 15
|
||||
#define NISAIRQS 3
|
||||
|
||||
#define IRQMAP_PCIBASE 0
|
||||
|
@ -260,28 +239,21 @@ const struct p5064_irqmap p5064_irqmap[NIRQMAPS] = {
|
|||
|
||||
const int p5064_isa_to_irqmap[16] = {
|
||||
-1, /* 0 */
|
||||
IRQ_MKBD, /* 1 */
|
||||
P5064_IRQ_MKBD, /* 1 */
|
||||
-1, /* 2 */
|
||||
IRQ_COM2, /* 3 */
|
||||
IRQ_COM1, /* 4 */
|
||||
P5064_IRQ_COM2, /* 3 */
|
||||
P5064_IRQ_COM1, /* 4 */
|
||||
-1, /* 5 */
|
||||
IRQ_FLOPPY, /* 6 */
|
||||
IRQ_CENTRONICS, /* 7 */
|
||||
IRQ_RTC, /* 8 */
|
||||
P5064_IRQ_FLOPPY, /* 6 */
|
||||
P5064_IRQ_CENTRONICS, /* 7 */
|
||||
P5064_IRQ_RTC, /* 8 */
|
||||
-1, /* 9 */
|
||||
-1, /* 10 */
|
||||
-1, /* 11 */
|
||||
IRQ_MKBD, /* 12 */
|
||||
P5064_IRQ_MKBD, /* 12 */
|
||||
-1, /* 13 */
|
||||
IRQ_IDE0, /* 14 */
|
||||
IRQ_IDE1, /* 15 */
|
||||
};
|
||||
|
||||
struct p5064_intrhand {
|
||||
LIST_ENTRY(p5064_intrhand) ih_q;
|
||||
int (*ih_func)(void *);
|
||||
void *ih_arg;
|
||||
const struct p5064_irqmap *ih_irqmap;
|
||||
P5064_IRQ_IDE0, /* 14 */
|
||||
P5064_IRQ_IDE1, /* 15 */
|
||||
};
|
||||
|
||||
struct p5064_intrhead {
|
||||
|
@ -293,7 +265,7 @@ struct p5064_intrhead p5064_intrtab[NIRQMAPS];
|
|||
#define NINTRS 3 /* MIPS INT0 - INT2 */
|
||||
|
||||
struct p5064_cpuintr {
|
||||
LIST_HEAD(, p5064_intrhand) cintr_list;
|
||||
LIST_HEAD(, algor_intrhand) cintr_list;
|
||||
struct evcnt cintr_count;
|
||||
};
|
||||
|
||||
|
@ -310,10 +282,6 @@ const char *p5064_intrgroups[NINTRS] = {
|
|||
"local",
|
||||
};
|
||||
|
||||
void algor_p5064_intr_disestablish(void *, void *);
|
||||
void *algor_p5064_intr_establish(const struct p5064_irqmap *,
|
||||
int (*)(void *), void *);
|
||||
|
||||
int algor_p5064_pci_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
|
||||
const char *algor_p5064_pci_intr_string(void *, pci_intr_handle_t);
|
||||
const struct evcnt *algor_p5064_pci_intr_evcnt(void *, pci_intr_handle_t);
|
||||
|
@ -448,7 +416,7 @@ void *
|
|||
algor_p5064_intr_establish(const struct p5064_irqmap *irqmap,
|
||||
int (*func)(void *), void *arg)
|
||||
{
|
||||
struct p5064_intrhand *ih;
|
||||
struct algor_intrhand *ih;
|
||||
int s;
|
||||
|
||||
ih = malloc(sizeof(*ih), M_DEVBUF, M_NOWAIT);
|
||||
|
@ -457,6 +425,7 @@ algor_p5064_intr_establish(const struct p5064_irqmap *irqmap,
|
|||
|
||||
ih->ih_func = func;
|
||||
ih->ih_arg = arg;
|
||||
ih->ih_irq = 0;
|
||||
ih->ih_irqmap = irqmap;
|
||||
|
||||
s = splhigh();
|
||||
|
@ -485,7 +454,7 @@ void
|
|||
algor_p5064_intr_disestablish(void *v, void *cookie)
|
||||
{
|
||||
const struct p5064_irqmap *irqmap;
|
||||
struct p5064_intrhand *ih = v;
|
||||
struct algor_intrhand *ih = v;
|
||||
int s;
|
||||
|
||||
s = splhigh();
|
||||
|
@ -514,7 +483,8 @@ void
|
|||
algor_p5064_iointr(u_int32_t status, u_int32_t cause, u_int32_t pc,
|
||||
u_int32_t ipending)
|
||||
{
|
||||
struct p5064_intrhand *ih;
|
||||
const struct p5064_irqmap *irqmap;
|
||||
struct algor_intrhand *ih;
|
||||
int level, i;
|
||||
u_int32_t irr[NIRQREG];
|
||||
|
||||
|
@ -562,10 +532,10 @@ algor_p5064_iointr(u_int32_t status, u_int32_t cause, u_int32_t pc,
|
|||
p5064_cpuintrs[level].cintr_count.ev_count++;
|
||||
for (ih = LIST_FIRST(&p5064_cpuintrs[level].cintr_list);
|
||||
ih != NULL; ih = LIST_NEXT(ih, ih_q)) {
|
||||
if (irr[ih->ih_irqmap->irqreg] &
|
||||
ih->ih_irqmap->irqbit) {
|
||||
irqmap = ih->ih_irqmap;
|
||||
if (irr[irqmap->irqreg] & irqmap->irqbit) {
|
||||
p5064_intrtab[
|
||||
ih->ih_irqmap->irqidx].intr_count.ev_count++;
|
||||
irqmap->irqidx].intr_count.ev_count++;
|
||||
(*ih->ih_func)(ih->ih_arg);
|
||||
}
|
||||
}
|
||||
|
@ -585,12 +555,12 @@ algor_p5064_pci_intr_map(struct pci_attach_args *pa,
|
|||
pci_intr_handle_t *ihp)
|
||||
{
|
||||
static const int pciirqmap[6/*device*/][4/*pin*/] = {
|
||||
{ IRQ_ETHERNET, -1, -1, -1 }, /* 0: Ethernet */
|
||||
{ IRQ_SCSI, -1, -1, -1 }, /* 1: SCSI */
|
||||
{ -1, -1, -1, IRQ_USB }, /* 2: PCI-ISA bridge */
|
||||
{ 0, 1, 2, 3 }, /* 3: PCI slot 3 */
|
||||
{ 3, 0, 1, 2 }, /* 4: PCI slot 2 */
|
||||
{ 2, 3, 0, 1 }, /* 5: PCI slot 1 */
|
||||
{ P5064_IRQ_ETHERNET, -1, -1, -1 }, /* 0: Ethernet */
|
||||
{ P5064_IRQ_SCSI, -1, -1, -1 }, /* 1: SCSI */
|
||||
{ -1, -1, -1, P5064_IRQ_USB }, /* 2: PCI-ISA bridge */
|
||||
{ 0, 1, 2, 3 }, /* 3: PCI slot 3 */
|
||||
{ 3, 0, 1, 2 }, /* 4: PCI slot 2 */
|
||||
{ 2, 3, 0, 1 }, /* 5: PCI slot 1 */
|
||||
};
|
||||
pcitag_t bustag = pa->pa_intrtag;
|
||||
int buspin = pa->pa_intrpin;
|
||||
|
@ -683,7 +653,7 @@ algor_p5064_pciide_compat_intr_establish(void *v, struct device *dev,
|
|||
if (bus != 0)
|
||||
return (NULL);
|
||||
|
||||
irqmap = &p5064_irqmap[IRQ_IDE0 + chan];
|
||||
irqmap = &p5064_irqmap[P5064_IRQ_IDE0 + chan];
|
||||
|
||||
cookie = algor_p5064_intr_establish(irqmap, func, arg);
|
||||
if (cookie == NULL)
|
||||
|
@ -715,10 +685,6 @@ algor_p5064_isa_intr_establish(void *v, int iirq, int type, int level,
|
|||
if (iirq > 15 || type == IST_NONE)
|
||||
panic("algor_p5064_isa_intr_establish: bad irq or type");
|
||||
|
||||
/*
|
||||
* XXX WE CURRENTLY DO NOT DO ANYTHING USEFUL AT ALL WITH
|
||||
* XXX REGULAR ISA INTERRUPTS.
|
||||
*/
|
||||
if ((irqidx = p5064_isa_to_irqmap[iirq]) == -1)
|
||||
return (NULL);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: algor_p5064var.h,v 1.2 2001/06/10 05:26:58 thorpej Exp $ */
|
||||
/* $NetBSD: algor_p5064var.h,v 1.3 2001/06/10 09:13:07 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
|
@ -57,7 +57,36 @@ struct p5064_config {
|
|||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
#define P5064_IRQ_ETHERNET 4
|
||||
#define P5064_IRQ_SCSI 5
|
||||
#define P5064_IRQ_USB 6
|
||||
|
||||
#define P5064_IRQ_MKBD 7
|
||||
#define P5064_IRQ_COM1 8
|
||||
#define P5064_IRQ_COM2 9
|
||||
#define P5064_IRQ_FLOPPY 10
|
||||
#define P5064_IRQ_CENTRONICS 11
|
||||
#define P5064_IRQ_RTC 12
|
||||
|
||||
#define P5064_IRQ_ISABRIDGE 13
|
||||
#define P5064_IRQ_IDE0 14
|
||||
#define P5064_IRQ_IDE1 15
|
||||
|
||||
struct p5064_irqmap {
|
||||
int irqidx;
|
||||
int cpuintr;
|
||||
int irqreg;
|
||||
int irqbit;
|
||||
int xbarreg;
|
||||
int xbarshift;
|
||||
};
|
||||
|
||||
void algor_p5064_intr_disestablish(void *, void *);
|
||||
void *algor_p5064_intr_establish(const struct p5064_irqmap *,
|
||||
int (*)(void *), void *);
|
||||
|
||||
extern struct p5064_config p5064_configuration;
|
||||
extern const struct p5064_irqmap p5064_irqmap[];
|
||||
|
||||
void algor_p5064_bus_io_init(bus_space_tag_t, void *);
|
||||
void algor_p5064_bus_mem_init(bus_space_tag_t, void *);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: intr.h,v 1.2 2001/06/10 05:26:59 thorpej Exp $ */
|
||||
/* $NetBSD: intr.h,v 1.3 2001/06/10 09:13:07 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
|
||||
|
@ -114,6 +114,14 @@ extern int _clrsoftintr(int);
|
|||
|
||||
#define spllowersoftclock() _spllower(ipl_sr_bits[IPL_SOFTCLOCK])
|
||||
|
||||
struct algor_intrhand {
|
||||
LIST_ENTRY(algor_intrhand) ih_q;
|
||||
int (*ih_func)(void *);
|
||||
void *ih_arg;
|
||||
int ih_irq; /* mostly for ISA */
|
||||
const void *ih_irqmap;
|
||||
};
|
||||
|
||||
#define setsoft(x) \
|
||||
do { \
|
||||
_setsoftintr(ipl_si_to_sr[(x) - IPL_SOFT]); \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pcib.c,v 1.2 2001/06/01 15:20:06 thorpej Exp $ */
|
||||
/* $NetBSD: pcib.c,v 1.3 2001/06/10 09:13:07 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
|
||||
|
@ -38,7 +38,7 @@
|
|||
|
||||
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
|
||||
|
||||
__KERNEL_RCSID(0, "$NetBSD: pcib.c,v 1.2 2001/06/01 15:20:06 thorpej Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: pcib.c,v 1.3 2001/06/10 09:13:07 thorpej Exp $");
|
||||
|
||||
#include "opt_algor_p5064.h"
|
||||
#include "opt_algor_p6032.h"
|
||||
|
@ -52,6 +52,7 @@ __KERNEL_RCSID(0, "$NetBSD: pcib.c,v 1.2 2001/06/01 15:20:06 thorpej Exp $");
|
|||
#include <machine/intr.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/isa/isareg.h>
|
||||
#include <dev/isa/isavar.h>
|
||||
|
||||
#include <dev/pci/pcireg.h>
|
||||
|
@ -66,9 +67,52 @@ __KERNEL_RCSID(0, "$NetBSD: pcib.c,v 1.2 2001/06/01 15:20:06 thorpej Exp $");
|
|||
#include <algor/algor/algor_p6032var.h>
|
||||
#endif
|
||||
|
||||
const char *pcib_intrnames[16] = {
|
||||
"irq 0",
|
||||
"irq 1",
|
||||
"irq 2",
|
||||
"irq 3",
|
||||
"irq 4",
|
||||
"irq 5",
|
||||
"irq 6",
|
||||
"irq 7",
|
||||
"irq 8",
|
||||
"irq 9",
|
||||
"irq 10",
|
||||
"irq 11",
|
||||
"irq 12",
|
||||
"irq 13",
|
||||
"irq 14",
|
||||
"irq 15",
|
||||
};
|
||||
|
||||
struct pcib_intrhead {
|
||||
LIST_HEAD(, algor_intrhand) intr_q;
|
||||
struct evcnt intr_count;
|
||||
int intr_type;
|
||||
};
|
||||
|
||||
struct pcib_softc {
|
||||
struct device sc_dev;
|
||||
|
||||
bus_space_tag_t sc_iot;
|
||||
bus_space_handle_t sc_ioh_icu1;
|
||||
bus_space_handle_t sc_ioh_icu2;
|
||||
bus_space_handle_t sc_ioh_elcr;
|
||||
|
||||
struct algor_isa_chipset sc_ic;
|
||||
|
||||
struct pcib_intrhead sc_intrtab[16];
|
||||
|
||||
u_int16_t sc_inten;
|
||||
u_int16_t sc_elcr;
|
||||
|
||||
#if defined(ALGOR_P5064)
|
||||
isa_chipset_tag_t sc_parent_ic;
|
||||
u_int16_t sc_reserved;
|
||||
#endif
|
||||
|
||||
void *sc_ih;
|
||||
};
|
||||
|
||||
int pcib_match(struct device *, struct cfdata *, void *);
|
||||
|
@ -82,8 +126,18 @@ int pcib_print(void *, const char *pnp);
|
|||
void pcib_isa_attach_hook(struct device *, struct device *,
|
||||
struct isabus_attach_args *);
|
||||
|
||||
int pcib_intr(void *);
|
||||
|
||||
void pcib_bridge_callback(struct device *);
|
||||
|
||||
const struct evcnt *pcib_isa_intr_evcnt(void *, int);
|
||||
void *pcib_isa_intr_establish(void *, int, int, int,
|
||||
int (*)(void *), void *);
|
||||
void pcib_isa_intr_disestablish(void *, void *);
|
||||
int pcib_isa_intr_alloc(void *, int, int, int *);
|
||||
|
||||
void pcib_set_icus(struct pcib_softc *);
|
||||
|
||||
int
|
||||
pcib_match(struct device *parent, struct cfdata *match, void *aux)
|
||||
{
|
||||
|
@ -99,13 +153,133 @@ pcib_match(struct device *parent, struct cfdata *match, void *aux)
|
|||
void
|
||||
pcib_attach(struct device *parent, struct device *self, void *aux)
|
||||
{
|
||||
struct pcib_softc *sc = (void *) self;
|
||||
struct pci_attach_args *pa = aux;
|
||||
char devinfo[256];
|
||||
int i;
|
||||
|
||||
pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo);
|
||||
printf(": %s (rev. 0x%02x)\n", devinfo,
|
||||
PCI_REVISION(pa->pa_class));
|
||||
|
||||
sc->sc_iot = pa->pa_iot;
|
||||
|
||||
/*
|
||||
* Map the PIC/ELCR registers.
|
||||
*/
|
||||
if (bus_space_map(sc->sc_iot, 0x4d0, 2, 0, &sc->sc_ioh_elcr) != 0)
|
||||
printf("%s: unable to map ELCR registers\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
if (bus_space_map(sc->sc_iot, IO_ICU1, 2, 0, &sc->sc_ioh_icu1) != 0)
|
||||
printf("%s: unable to map ICU1 registers\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
if (bus_space_map(sc->sc_iot, IO_ICU2, 2, 0, &sc->sc_ioh_icu2) != 0)
|
||||
printf("%s: unable to map ICU2 registers\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
|
||||
/*
|
||||
* Initialize the 8259s.
|
||||
*/
|
||||
|
||||
/* ICW1: reset; program device, 4 bytes */
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, 0, 0x11);
|
||||
|
||||
/* ICW2: vector base address */
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, 1, 32/*XXX*/);
|
||||
|
||||
/* ICW3: cascade mode */
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, 1, 0x04);
|
||||
|
||||
/* ICW4: 8086 mode */
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, 1, 0x01);
|
||||
|
||||
/* OCW1: mask all interrupts */
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, 1,
|
||||
~sc->sc_inten & 0xff);
|
||||
|
||||
/* OCW3: enable special mask mode */
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, 0, 0x68);
|
||||
|
||||
/* OCW3: read IRR by default */
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, 0, 0x0a);
|
||||
|
||||
|
||||
/* ICW1: reset; program device, 4 bytes */
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, 0, 0x11);
|
||||
|
||||
/* ICW2: vector base address */
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, 1, 32+8/*XXX*/);
|
||||
|
||||
/* ICW3: slave ID code */
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, 1, 0x02);
|
||||
|
||||
/* ICW4: 8086 mode */
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, 1, 0x01);
|
||||
|
||||
/* OCW1: mask all interrupts */
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, 1,
|
||||
(~sc->sc_inten >> 8) & 0xff);
|
||||
|
||||
/* OCW3: enable special mask mode */
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, 0, 0x68);
|
||||
|
||||
/* OCW3: read IRR by default */
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, 0, 0x0a);
|
||||
|
||||
/*
|
||||
* Default all interrupts to edge-triggered.
|
||||
*/
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 0,
|
||||
sc->sc_elcr & 0xff);
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 1,
|
||||
(sc->sc_elcr >> 8) & 0xff);
|
||||
|
||||
#if defined(ALGOR_P5064)
|
||||
/*
|
||||
* Some "ISA" interrupts are a little wacky, wired up directly
|
||||
* to the P-5064 interrupt controller.
|
||||
*/
|
||||
sc->sc_reserved =
|
||||
(1 << 1) |
|
||||
(1 << 3) |
|
||||
(1 << 4) |
|
||||
(1 << 6) |
|
||||
(1 << 7) |
|
||||
(1 << 8) |
|
||||
(1 << 12) |
|
||||
(1 << 14) |
|
||||
(1 << 15);
|
||||
|
||||
sc->sc_parent_ic = &p5064_configuration.ac_ic;
|
||||
#endif /* ALGOR_P5064 */
|
||||
|
||||
/* Set up our ISA chipset. */
|
||||
sc->sc_ic.ic_v = sc;
|
||||
sc->sc_ic.ic_intr_evcnt = pcib_isa_intr_evcnt;
|
||||
sc->sc_ic.ic_intr_establish = pcib_isa_intr_establish;
|
||||
sc->sc_ic.ic_intr_disestablish = pcib_isa_intr_disestablish;
|
||||
sc->sc_ic.ic_intr_alloc = pcib_isa_intr_alloc;
|
||||
|
||||
/* Initialize our interrupt table. */
|
||||
for (i = 0; i < 16; i++) {
|
||||
LIST_INIT(&sc->sc_intrtab[i].intr_q);
|
||||
evcnt_attach_dynamic(&sc->sc_intrtab[i].intr_count,
|
||||
EVCNT_TYPE_INTR, NULL, "pcib", pcib_intrnames[i]);
|
||||
sc->sc_intrtab[i].intr_type = IST_NONE;
|
||||
}
|
||||
|
||||
/* Hook up our interrupt handler. */
|
||||
#if defined(ALGOR_P5064)
|
||||
sc->sc_ih = algor_p5064_intr_establish(&p5064_irqmap[
|
||||
P5064_IRQ_ISABRIDGE], pcib_intr, sc);
|
||||
#elif defined(ALGOR_P6032)
|
||||
sc->sc_ih = algor_p6032_intr_establish(&p6032_irqmap[XXX],
|
||||
pcib_intr, sc);
|
||||
#endif
|
||||
if (sc->sc_ih == NULL)
|
||||
printf("%s: WARNING: unable to register interrupt handler\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
|
||||
config_defer(self, pcib_bridge_callback);
|
||||
}
|
||||
|
||||
|
@ -156,3 +330,222 @@ pcib_isa_attach_hook(struct device *parent, struct device *self,
|
|||
|
||||
/* Nothing to do. */
|
||||
}
|
||||
|
||||
void
|
||||
pcib_set_icus(struct pcib_softc *sc)
|
||||
{
|
||||
|
||||
/* Enable the cascade IRQ (2) if 8-15 is enabled. */
|
||||
if (sc->sc_inten & 0xff00)
|
||||
sc->sc_inten |= (1 << 2);
|
||||
else
|
||||
sc->sc_inten &= ~(1 << 2);
|
||||
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, 1,
|
||||
~sc->sc_inten & 0xff);
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, 1,
|
||||
(~sc->sc_inten >> 8) & 0xff);
|
||||
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 0,
|
||||
sc->sc_elcr & 0xff);
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 1,
|
||||
(sc->sc_elcr >> 8) & 0xff);
|
||||
}
|
||||
|
||||
int
|
||||
pcib_intr(void *v)
|
||||
{
|
||||
struct pcib_softc *sc = v;
|
||||
struct algor_intrhand *ih;
|
||||
u_int16_t ipending;
|
||||
int i;
|
||||
|
||||
ipending = bus_space_read_1(sc->sc_iot, sc->sc_ioh_icu1, 0) |
|
||||
(bus_space_read_1(sc->sc_iot, sc->sc_ioh_icu2, 0) << 8);
|
||||
ipending &= (sc->sc_inten & ~0x02);
|
||||
if (ipending == 0)
|
||||
return (0);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
if ((ipending & (1 << i)) == 0)
|
||||
continue;
|
||||
sc->sc_intrtab[i].intr_count.ev_count++;
|
||||
for (ih = LIST_FIRST(&sc->sc_intrtab[i].intr_q);
|
||||
ih != NULL; ih = LIST_NEXT(ih, ih_q)) {
|
||||
(*ih->ih_func)(ih->ih_arg);
|
||||
}
|
||||
|
||||
/* Send a specific EOI to the 8259. */
|
||||
if (i > 7)
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2,
|
||||
0, 0x20 | (i & 0x07));
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, 0,
|
||||
0x20 | (i > 7 ? 2 : i));
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
const struct evcnt *
|
||||
pcib_isa_intr_evcnt(void *v, int irq)
|
||||
{
|
||||
struct pcib_softc *sc = v;
|
||||
|
||||
return (&sc->sc_intrtab[irq].intr_count);
|
||||
}
|
||||
|
||||
void *
|
||||
pcib_isa_intr_establish(void *v, int irq, int type, int level,
|
||||
int (*func)(void *), void *arg)
|
||||
{
|
||||
struct pcib_softc *sc = v;
|
||||
struct algor_intrhand *ih;
|
||||
int s;
|
||||
|
||||
if (irq > 15 || irq == 2 || type == IST_NONE)
|
||||
panic("pcib_isa_intr_establish: bad irq or type");
|
||||
|
||||
#if defined(ALGOR_P5064)
|
||||
if (sc->sc_reserved & (1 << irq)) {
|
||||
ih = isa_intr_establish(sc->sc_parent_ic, irq, type,
|
||||
level, func, arg);
|
||||
if (ih != NULL)
|
||||
ih->ih_irq = irq;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (sc->sc_intrtab[irq].intr_type) {
|
||||
case IST_NONE:
|
||||
sc->sc_intrtab[irq].intr_type = type;
|
||||
break;
|
||||
|
||||
case IST_EDGE:
|
||||
case IST_LEVEL:
|
||||
if (type == sc->sc_intrtab[irq].intr_type)
|
||||
break;
|
||||
/* FALLTHROUGH */
|
||||
case IST_PULSE:
|
||||
/*
|
||||
* We can't share interrupts in this case.
|
||||
*/
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
ih = malloc(sizeof(*ih), M_DEVBUF, M_NOWAIT);
|
||||
if (ih == NULL)
|
||||
return (NULL);
|
||||
|
||||
ih->ih_func = func;
|
||||
ih->ih_arg = arg;
|
||||
ih->ih_irq = irq;
|
||||
ih->ih_irqmap = NULL;
|
||||
|
||||
s = splhigh();
|
||||
|
||||
/* Insert the handler into the table. */
|
||||
LIST_INSERT_HEAD(&sc->sc_intrtab[irq].intr_q, ih, ih_q);
|
||||
sc->sc_intrtab[irq].intr_type = type;
|
||||
|
||||
/* Enable it, set trigger mode. */
|
||||
sc->sc_inten |= (1 << irq);
|
||||
if (sc->sc_intrtab[irq].intr_type == IST_LEVEL)
|
||||
sc->sc_elcr |= (1 << irq);
|
||||
else
|
||||
sc->sc_elcr &= ~(1 << irq);
|
||||
|
||||
pcib_set_icus(sc);
|
||||
|
||||
splx(s);
|
||||
|
||||
return (ih);
|
||||
}
|
||||
|
||||
void
|
||||
pcib_isa_intr_disestablish(void *v, void *arg)
|
||||
{
|
||||
struct pcib_softc *sc = v;
|
||||
struct algor_intrhand *ih = arg;
|
||||
int s;
|
||||
|
||||
#if defined(ALGOR_P5064)
|
||||
if (sc->sc_reserved & (1 << ih->ih_irq)) {
|
||||
isa_intr_disestablish(sc->sc_parent_ic, ih);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
s = splhigh();
|
||||
|
||||
LIST_REMOVE(ih, ih_q);
|
||||
|
||||
/* If there are no more handlers on this IRQ, disable it. */
|
||||
if (LIST_FIRST(&sc->sc_intrtab[ih->ih_irq].intr_q) == NULL) {
|
||||
sc->sc_inten &= ~(1 << ih->ih_irq);
|
||||
pcib_set_icus(sc);
|
||||
}
|
||||
|
||||
splx(s);
|
||||
|
||||
free(ih, M_DEVBUF);
|
||||
}
|
||||
|
||||
int
|
||||
pcib_isa_intr_alloc(void *v, int mask, int type, int *irq)
|
||||
{
|
||||
struct pcib_softc *sc = v;
|
||||
int i, tmp, bestirq, count;
|
||||
struct algor_intrhand *ih;
|
||||
|
||||
if (type == IST_NONE)
|
||||
panic("pcib_intr_alloc: bogus type");
|
||||
|
||||
bestirq = -1;
|
||||
count = -1;
|
||||
|
||||
#if defined(ALGOR_P5064)
|
||||
mask &= ~sc->sc_reserved;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (i == 2 || (mask & (1 << i)) == 0)
|
||||
continue;
|
||||
|
||||
switch (sc->sc_intrtab[i].intr_type) {
|
||||
case IST_NONE:
|
||||
/*
|
||||
* If nothing's using the IRQ, just return it.
|
||||
*/
|
||||
*irq = i;
|
||||
return (0);
|
||||
|
||||
case IST_EDGE:
|
||||
case IST_LEVEL:
|
||||
if (type != sc->sc_intrtab[i].intr_type)
|
||||
continue;
|
||||
/*
|
||||
* If the IRQ is sharable, count the number of
|
||||
* other handlers, and if it's smaller than the
|
||||
* last IRQ like this, remember it.
|
||||
*/
|
||||
tmp = 0;
|
||||
for (ih = LIST_FIRST(&sc->sc_intrtab[i].intr_q);
|
||||
ih != NULL; ih = LIST_NEXT(ih, ih_q))
|
||||
tmp++;
|
||||
if (bestirq == -1 || count > tmp) {
|
||||
bestirq = i;
|
||||
count = tmp;
|
||||
}
|
||||
break;
|
||||
|
||||
case IST_PULSE:
|
||||
/* This just isn't sharable. */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestirq == -1)
|
||||
return (1);
|
||||
|
||||
*irq = bestirq;
|
||||
return (0);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue