Rototill ISA interrupt code. In particular, I have remembered most

of the horror that is the 8259 PIC.

PCMCIA interrupts still not working yet, but getting closer.
This commit is contained in:
thorpej 2001-06-21 05:20:54 +00:00
parent bddb038898
commit f341043437
3 changed files with 125 additions and 95 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: algor_p5064_intr.c,v 1.4 2001/06/15 04:01:40 thorpej Exp $ */
/* $NetBSD: algor_p5064_intr.c,v 1.5 2001/06/21 05:20:54 thorpej Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@ -706,6 +706,7 @@ void *
algor_p5064_isa_intr_establish(void *v, int iirq, int type, int level,
int (*func)(void *), void *arg)
{
struct algor_intrhand *ih;
int irqidx;
if (iirq > 15 || type == IST_NONE)
@ -714,14 +715,23 @@ algor_p5064_isa_intr_establish(void *v, int iirq, int type, int level,
if ((irqidx = p5064_isa_to_irqmap[iirq]) == -1)
return (NULL);
return (algor_p5064_intr_establish(irqidx, func, arg));
ih = algor_p5064_intr_establish(irqidx, func, arg);
if (ih != NULL) {
/* Translate it to an ISA IRQ. */
ih->ih_irq = iirq;
}
return (ih);
}
void
algor_p5064_isa_intr_disestablish(void *v, void *cookie)
{
struct algor_intrhand *ih = cookie;
algor_p5064_intr_disestablish(cookie);
/* Translate the IRQ back to our domain. */
ih->ih_irq = p5064_isa_to_irqmap[ih->ih_irq];
algor_p5064_intr_disestablish(ih);
}
int

View File

@ -1,4 +1,4 @@
/* $NetBSD: algor_p5064var.h,v 1.4 2001/06/15 04:01:40 thorpej Exp $ */
/* $NetBSD: algor_p5064var.h,v 1.5 2001/06/21 05:20:54 thorpej Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@ -73,6 +73,7 @@ struct p5064_config {
#define P5064_IRQ_IDE1 15
extern struct p5064_config p5064_configuration;
extern const int p5064_isa_to_irqmap[];
void algor_p5064_bus_io_init(bus_space_tag_t, void *);
void algor_p5064_bus_mem_init(bus_space_tag_t, void *);

View File

@ -1,4 +1,4 @@
/* $NetBSD: pcib.c,v 1.5 2001/06/15 04:01:41 thorpej Exp $ */
/* $NetBSD: pcib.c,v 1.6 2001/06/21 05:20:54 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.5 2001/06/15 04:01:41 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: pcib.c,v 1.6 2001/06/21 05:20:54 thorpej Exp $");
#include "opt_algor_p5064.h"
#include "opt_algor_p6032.h"
@ -59,6 +59,8 @@ __KERNEL_RCSID(0, "$NetBSD: pcib.c,v 1.5 2001/06/15 04:01:41 thorpej Exp $");
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>
#include <dev/ic/i8259reg.h>
#ifdef ALGOR_P5064
#include <algor/algor/algor_p5064var.h>
#endif
@ -104,14 +106,15 @@ struct pcib_softc {
struct pcib_intrhead sc_intrtab[16];
u_int16_t sc_inten;
u_int16_t sc_imask;
u_int16_t sc_elcr;
#if defined(ALGOR_P5064)
isa_chipset_tag_t sc_parent_ic;
u_int16_t sc_reserved;
#endif
u_int16_t sc_reserved;
void *sc_ih;
};
@ -177,54 +180,60 @@ pcib_attach(struct device *parent, struct device *self, void *aux)
printf("%s: unable to map ICU2 registers\n",
sc->sc_dev.dv_xname);
/* All interrupts default to "masked off". */
sc->sc_imask = 0xffff;
/* All interrupts default to edge-triggered. */
sc->sc_elcr = 0;
/*
* Initialize the 8259s.
*/
/* ICW1: reset; program device, 4 bytes */
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, 0, 0x11);
/* reset, program device, 4 bytes */
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_ICW1,
ICW_SELECT(1) | ICW1_IC4);
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_ICW2,
ICW2_VECTOR(32)/*XXX*/);
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_ICW3,
ICW3_CASCADE);
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_ICW4,
ICW4_8086);
/* ICW2: vector base address */
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, 1, 32/*XXX*/);
/* mask all interrupts */
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW1,
sc->sc_imask & 0xff);
/* ICW3: cascade mode */
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, 1, 0x04);
/* enable special mask mode */
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW3,
OCW3_SELECT | OCW3_ESMM | OCW3_SMM);
/* 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);
/* read IRR by default */
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW3,
OCW3_SELECT | OCW3_RR_CMD(OCW3_RR_CMD_READ_IRQ));
/* ICW1: reset; program device, 4 bytes */
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, 0, 0x11);
/* reset; program device, 4 bytes */
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_ICW1,
ICW_SELECT(1) | ICW1_IC4);
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_ICW2,
ICW2_VECTOR(32 + 8)/*XXX*/);
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_ICW3,
ICW3_SIC(2));
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_ICW4,
ICW4_8086);
/* ICW2: vector base address */
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, 1, 32+8/*XXX*/);
/* mask all interrupts */
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_OCW1,
(sc->sc_imask >> 8) & 0xff);
/* ICW3: slave ID code */
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, 1, 0x02);
/* enable special mask mode */
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_OCW3,
OCW3_SELECT | OCW3_ESMM | OCW3_SMM);
/* 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);
/* read IRR by default */
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_OCW3,
OCW3_SELECT | OCW3_RR_CMD(OCW3_RR_CMD_READ_IRQ));
/*
* Default all interrupts to edge-triggered.
@ -234,22 +243,27 @@ pcib_attach(struct device *parent, struct device *self, void *aux)
bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 1,
(sc->sc_elcr >> 8) & 0xff);
/*
* Some ISA interrupts are reserved for devices that
* we know are hard-wired to certain IRQs.
*/
sc->sc_reserved =
(1U << 0) | /* timer */
(1U << 1) | /* keyboard controller */
(1U << 3) | /* COM 2 */
(1U << 4) | /* COM 1 */
(1U << 6) | /* floppy */
(1U << 7) | /* centronics */
(1U << 8) | /* RTC */
(1U << 12) | /* keyboard controller */
(1U << 14) | /* IDE 0 */
(1U << 15); /* IDE 1 */
#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 */
@ -300,7 +314,6 @@ pcib_bridge_callback(self)
iba.iba_iot = &acp->ac_iot;
iba.iba_memt = &acp->ac_memt;
iba.iba_dmat = &acp->ac_isa_dmat;
iba.iba_ic = &acp->ac_ic;
}
#elif defined(ALGOR_P6032)
{
@ -308,6 +321,7 @@ pcib_bridge_callback(self)
}
#endif
iba.iba_ic = &sc->sc_ic;
iba.iba_ic->ic_attach_hook = pcib_isa_attach_hook;
(void) config_found(&sc->sc_dev, &iba, pcib_print);
@ -336,15 +350,15 @@ 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);
if ((sc->sc_imask & 0xff00) != 0xff00)
sc->sc_imask &= ~(1U << 2);
else
sc->sc_inten &= ~(1 << 2);
sc->sc_imask |= (1U << 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_icu1, PIC_OCW1,
sc->sc_imask & 0xff);
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_OCW1,
(sc->sc_imask >> 8) & 0xff);
bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 0,
sc->sc_elcr & 0xff);
@ -357,32 +371,36 @@ pcib_intr(void *v)
{
struct pcib_softc *sc = v;
struct algor_intrhand *ih;
u_int16_t ipending;
int i;
int irq;
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);
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW3,
OCW3_SELECT | OCW3_POLL);
irq = bus_space_read_1(sc->sc_iot, sc->sc_ioh_icu1,
PIC_OCW3) & 0x7f;
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));
if (irq == 2) {
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_OCW3,
OCW3_SELECT | OCW3_POLL);
irq = (bus_space_read_1(sc->sc_iot, sc->sc_ioh_icu2,
PIC_OCW3) & 0x7f) + 8;
}
sc->sc_intrtab[irq].intr_count.ev_count++;
for (ih = LIST_FIRST(&sc->sc_intrtab[irq].intr_q);
ih != NULL; ih = LIST_NEXT(ih, ih_q)) {
(*ih->ih_func)(ih->ih_arg);
}
/* Send a specific EOI to the 8259. */
if (irq > 7)
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2,
PIC_OCW2, OCW2_SELECT | OCW2_OP(OCW2_OP_SPECIFIC_EOI_CMD) |
OCW2_ILS(irq & 7));
bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW2,
OCW2_SELECT | OCW2_OP(OCW2_OP_SPECIFIC_EOI_CMD) |
(irq > 7 ? OCW2_ILS(2) : OCW2_ILS(irq)));
return (1);
}
@ -392,7 +410,7 @@ pcib_isa_intr_evcnt(void *v, int irq)
struct pcib_softc *sc = v;
#if defined(ALGOR_P5064)
if (sc->sc_reserved & (1 << irq))
if (p5064_isa_to_irqmap[irq] != -1)
return (isa_intr_evcnt(sc->sc_parent_ic, irq));
#endif
@ -411,12 +429,9 @@ pcib_isa_intr_establish(void *v, int irq, int type, int level,
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;
}
if (p5064_isa_to_irqmap[irq] != -1)
return (isa_intr_establish(sc->sc_parent_ic, irq, type,
level, func, arg));
#endif
switch (sc->sc_intrtab[irq].intr_type) {
@ -452,7 +467,7 @@ pcib_isa_intr_establish(void *v, int irq, int type, int level,
sc->sc_intrtab[irq].intr_type = type;
/* Enable it, set trigger mode. */
sc->sc_inten |= (1 << irq);
sc->sc_imask &= ~(1 << irq);
if (sc->sc_intrtab[irq].intr_type == IST_LEVEL)
sc->sc_elcr |= (1 << irq);
else
@ -473,7 +488,7 @@ pcib_isa_intr_disestablish(void *v, void *arg)
int s;
#if defined(ALGOR_P5064)
if (sc->sc_reserved & (1 << ih->ih_irq)) {
if (p5064_isa_to_irqmap[ih->ih_irq] != -1) {
isa_intr_disestablish(sc->sc_parent_ic, ih);
return;
}
@ -485,7 +500,7 @@ pcib_isa_intr_disestablish(void *v, void *arg)
/* 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);
sc->sc_imask |= (1 << ih->ih_irq);
pcib_set_icus(sc);
}
@ -511,6 +526,10 @@ pcib_isa_intr_alloc(void *v, int mask, int type, int *irq)
mask &= ~sc->sc_reserved;
#endif
#if 0
printf("pcib_intr_alloc: mask = 0x%04x\n", mask);
#endif
for (i = 0; i < 16; i++) {
if (i == 2 || (mask & (1 << i)) == 0)
continue;