summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorArtur Grabowski <art@cvs.openbsd.org>2000-11-25 00:37:29 +0000
committerArtur Grabowski <art@cvs.openbsd.org>2000-11-25 00:37:29 +0000
commite6ec9082ebe20157d9d3de6941d758b89f4f998c (patch)
treebd3fc9c4de4e94d3c5e86fd742abb01ed42f7476 /sys
parent214a094a255867e71996b1cf6ca03fede69c93ba (diff)
Use the common cy82c693 access functions.
From NetBSD. Fixes pciide on 164sx.
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/alpha/pci/sio_pic.c361
1 files changed, 247 insertions, 114 deletions
diff --git a/sys/arch/alpha/pci/sio_pic.c b/sys/arch/alpha/pci/sio_pic.c
index 8a14f5ff969..c7ed7ffce66 100644
--- a/sys/arch/alpha/pci/sio_pic.c
+++ b/sys/arch/alpha/pci/sio_pic.c
@@ -1,5 +1,41 @@
-/* $OpenBSD: sio_pic.c,v 1.15 2000/11/08 16:01:22 art Exp $ */
-/* $NetBSD: sio_pic.c,v 1.16 1996/11/17 02:05:26 cgd Exp $ */
+/* $NetBSD: sio_pic.c,v 1.28 2000/06/06 03:10:13 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
/*
* Copyright (c) 1995, 1996 Carnegie-Mellon University.
@@ -41,14 +77,13 @@
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>
+#include <dev/pci/cy82c693reg.h>
+#include <dev/pci/cy82c693var.h>
+
#include <dev/isa/isareg.h>
#include <dev/isa/isavar.h>
#include <alpha/pci/siovar.h>
-#ifndef EVCNT_COUNTERS
-#include <machine/intrcnt.h>
-#endif
-
#include "sio.h"
/*
@@ -59,35 +94,23 @@
* what will happen if new interrupts (that the PROM console doesn't
* want) are turned on. I'll burn that bridge when I come to it.
*/
-#ifndef SANE_PROM
#define BROKEN_PROM_CONSOLE
-#endif /* SANE_PROM */
/*
* Private functions and variables.
*/
+
bus_space_tag_t sio_iot;
pci_chipset_tag_t sio_pc;
-bus_space_handle_t sio_ioh_icu1, sio_ioh_icu2, sio_ioh_elcr;
+bus_space_handle_t sio_ioh_icu1, sio_ioh_icu2;
#define ICU_LEN 16 /* number of ISA IRQs */
static struct alpha_shared_intr *sio_intr;
-#ifdef EVCNT_COUNTERS
-struct evcnt sio_intr_evcnt;
-#endif
#ifndef STRAY_MAX
-#ifdef BROKEN_PROM_CONSOLE
-/*
- * If prom console is broken, because initial interrupt settings
- * must be kept, there's no way to escape stray interrupts.
- */
-#define STRAY_MAX 0
-#else
#define STRAY_MAX 5
#endif
-#endif
#ifdef BROKEN_PROM_CONSOLE
/*
@@ -96,21 +119,16 @@ struct evcnt sio_intr_evcnt;
*/
u_int8_t initial_ocw1[2];
u_int8_t initial_elcr[2];
-#define INITIALLY_ENABLED(irq) \
- ((initial_ocw1[(irq) / 8] & (1 << ((irq) % 8))) == 0)
-#define INITIALLY_LEVEL_TRIGGERED(irq) \
- ((initial_elcr[(irq) / 8] & (1 << ((irq) % 8))) != 0)
-#else
-#define INITIALLY_ENABLED(irq) ((irq) == 2 ? 1 : 0)
-#define INITIALLY_LEVEL_TRIGGERED(irq) 0
#endif
-void sio_setirqstat __P((int, int, int));
-
-void sio_setirqstat __P((int, int, int));
+void sio_setirqstat __P((int, int, int));
u_int8_t (*sio_read_elcr) __P((int));
void (*sio_write_elcr) __P((int, u_int8_t));
+static void specific_eoi __P((int));
+#ifdef BROKEN_PROM_CONSOLE
+void sio_intr_shutdown __P((void *));
+#endif
/******************** i82378 SIO ELCR functions ********************/
@@ -118,6 +136,8 @@ int i82378_setup_elcr __P((void));
u_int8_t i82378_read_elcr __P((int));
void i82378_write_elcr __P((int, u_int8_t));
+bus_space_handle_t sio_ioh_elcr;
+
int
i82378_setup_elcr()
{
@@ -162,10 +182,13 @@ int cy82c693_setup_elcr __P((void));
u_int8_t cy82c693_read_elcr __P((int));
void cy82c693_write_elcr __P((int, u_int8_t));
+const struct cy82c693_handle *sio_cy82c693_handle;
+
int
cy82c693_setup_elcr()
{
int device, maxndevs;
+ pcitag_t tag;
pcireg_t id;
/*
@@ -183,8 +206,8 @@ cy82c693_setup_elcr()
maxndevs = pci_bus_maxdevs(sio_pc, 0);
for (device = 0; device < maxndevs; device++) {
- id = pci_conf_read(sio_pc, pci_make_tag(sio_pc, 0, device, 0),
- PCI_ID_REG);
+ tag = pci_make_tag(sio_pc, 0, device, 0);
+ id = pci_conf_read(sio_pc, tag, PCI_ID_REG);
/* Invalid vendor ID value? */
if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
@@ -203,15 +226,10 @@ cy82c693_setup_elcr()
#if 0
printf("cy82c693_setup_elcr: found 82C693 at device %d\n",
- device);
+ device);
#endif
- /*
- * The CY82C693's ELCR registers are accessed indirectly
- * via (IO_ICU1 + 2) (address) and (IO_ICU1 + 3) (data).
- */
- sio_ioh_elcr = sio_ioh_icu1;
-
+ sio_cy82c693_handle = cy82c693_init(sio_iot);
sio_read_elcr = cy82c693_read_elcr;
sio_write_elcr = cy82c693_write_elcr;
@@ -229,8 +247,7 @@ cy82c693_read_elcr(elcr)
int elcr;
{
- bus_space_write_1(sio_iot, sio_ioh_elcr, 0x02, 0x03 + elcr);
- return (bus_space_read_1(sio_iot, sio_ioh_elcr, 0x03));
+ return (cy82c693_read(sio_cy82c693_handle, CONFIG_ELCR1 + elcr));
}
void
@@ -239,8 +256,7 @@ cy82c693_write_elcr(elcr, val)
u_int8_t val;
{
- bus_space_write_1(sio_iot, sio_ioh_elcr, 0x02, 0x03 + elcr);
- bus_space_write_1(sio_iot, sio_ioh_elcr, 0x03, val);
+ cy82c693_write(sio_cy82c693_handle, CONFIG_ELCR1 + elcr, val);
}
/******************** ELCR access function configuration ********************/
@@ -259,6 +275,7 @@ int (*sio_elcr_setup_funcs[]) __P((void)) = {
};
/******************** Shared SIO/Cypress functions ********************/
+
void
sio_setirqstat(irq, enabled, type)
int irq, enabled;
@@ -277,8 +294,8 @@ sio_setirqstat(irq, enabled, type)
ocw1[0] = bus_space_read_1(sio_iot, sio_ioh_icu1, 1);
ocw1[1] = bus_space_read_1(sio_iot, sio_ioh_icu2, 1);
- elcr[0] = (*sio_read_elcr)(0); /* XXX */
- elcr[1] = (*sio_read_elcr)(1); /* XXX */
+ elcr[0] = (*sio_read_elcr)(0); /* XXX */
+ elcr[1] = (*sio_read_elcr)(1); /* XXX */
/*
* interrupt enable: set bit to mask (disable) interrupt.
@@ -303,65 +320,44 @@ sio_setirqstat(irq, enabled, type)
elcr[1] &= ~0x21; /* IRQ[13,8] must be edge-triggered */
#endif
-#ifdef BROKEN_PROM_CONSOLE
- /*
- * make sure that the initially clear bits (unmasked interrupts)
- * are never set, and that the initially-level-triggered
- * intrrupts always remain level-triggered, to keep the prom happy.
- */
- if ((ocw1[0] & ~initial_ocw1[0]) != 0 ||
- (ocw1[1] & ~initial_ocw1[1]) != 0 ||
- (elcr[0] & initial_elcr[0]) != initial_elcr[0] ||
- (elcr[1] & initial_elcr[1]) != initial_elcr[1]) {
- printf("sio_sis: initial: ocw = (%2x,%2x), elcr = (%2x,%2x)\n",
- initial_ocw1[0], initial_ocw1[1],
- initial_elcr[0], initial_elcr[1]);
- printf(" current: ocw = (%2x,%2x), elcr = (%2x,%2x)\n",
- ocw1[0], ocw1[1], elcr[0], elcr[1]);
- panic("sio_setirqstat: hosed");
- }
-#endif
-
bus_space_write_1(sio_iot, sio_ioh_icu1, 1, ocw1[0]);
bus_space_write_1(sio_iot, sio_ioh_icu2, 1, ocw1[1]);
- (*sio_write_elcr)(0, elcr[0]); /* XXX */
- (*sio_write_elcr)(1, elcr[1]); /* XXX */
+ (*sio_write_elcr)(0, elcr[0]); /* XXX */
+ (*sio_write_elcr)(1, elcr[1]); /* XXX */
}
void
sio_intr_setup(pc, iot)
- pci_chipset_tag_t pc;
+ pci_chipset_tag_t pc;
bus_space_tag_t iot;
{
+#ifdef notyet
+ char *cp;
+#endif
int i;
sio_iot = iot;
sio_pc = pc;
-
- if (bus_space_map(sio_iot, IO_ICU1, IO_ICUSIZE, 0, &sio_ioh_icu1) ||
- bus_space_map(sio_iot, IO_ICU2, IO_ICUSIZE, 0, &sio_ioh_icu2))
- panic("sio_intr_setup: can't map I/O ports");
- for (i = 0; sio_elcr_setup_funcs[i] != NULL; i++)
- if ((*sio_elcr_setup_funcs[i])() == 0)
- break;
- if (sio_elcr_setup_funcs[i] == NULL)
- panic("sio_intr_setup: can't map ELCR");
+ if (bus_space_map(sio_iot, IO_ICU1, 2, 0, &sio_ioh_icu1) ||
+ bus_space_map(sio_iot, IO_ICU2, 2, 0, &sio_ioh_icu2))
+ panic("sio_intr_setup: can't map ICU I/O ports");
+
+ for (i = 0; sio_elcr_setup_funcs[i] != NULL; i++)
+ if ((*sio_elcr_setup_funcs[i])() == 0)
+ break;
+ if (sio_elcr_setup_funcs[i] == NULL)
+ panic("sio_intr_setup: can't map ELCR");
#ifdef BROKEN_PROM_CONSOLE
/*
- * Remember the initial values, because the prom is stupid.
+ * Remember the initial values, so we can restore them later.
*/
initial_ocw1[0] = bus_space_read_1(sio_iot, sio_ioh_icu1, 1);
initial_ocw1[1] = bus_space_read_1(sio_iot, sio_ioh_icu2, 1);
- initial_elcr[0] = (*sio_read_elcr)(0); /* XXX */
- initial_elcr[1] = (*sio_read_elcr)(1); /* XXX */
-#if 0
- printf("initial_ocw1[0] = 0x%x\n", initial_ocw1[0]);
- printf("initial_ocw1[1] = 0x%x\n", initial_ocw1[1]);
- printf("initial_elcr[0] = 0x%x\n", initial_elcr[0]);
- printf("initial_elcr[1] = 0x%x\n", initial_elcr[1]);
-#endif
+ initial_elcr[0] = (*sio_read_elcr)(0); /* XXX */
+ initial_elcr[1] = (*sio_read_elcr)(1); /* XXX */
+ shutdownhook_establish(sio_intr_shutdown, 0);
#endif
sio_intr = alpha_shared_intr_alloc(ICU_LEN);
@@ -372,6 +368,13 @@ sio_intr_setup(pc, iot)
for (i = 0; i < ICU_LEN; i++) {
alpha_shared_intr_set_maxstrays(sio_intr, i, STRAY_MAX);
+#ifdef notyet
+ cp = alpha_shared_intr_string(sio_intr, i);
+ sprintf(cp, "irq %d", i);
+ evcnt_attach_dynamic(alpha_shared_intr_evcnt(sio_intr, i),
+ EVCNT_TYPE_INTR, NULL, "isa", cp);
+#endif
+
switch (i) {
case 0:
case 1:
@@ -381,11 +384,10 @@ sio_intr_setup(pc, iot)
* IRQs 0, 1, 8, and 13 must always be
* edge-triggered.
*/
- if (INITIALLY_LEVEL_TRIGGERED(i))
- printf("sio_intr_setup: %d LT!\n", i);
- sio_setirqstat(i, INITIALLY_ENABLED(i), IST_EDGE);
+ sio_setirqstat(i, 0, IST_EDGE);
alpha_shared_intr_set_dfltsharetype(sio_intr, i,
IST_EDGE);
+ specific_eoi(i);
break;
case 2:
@@ -393,10 +395,6 @@ sio_intr_setup(pc, iot)
* IRQ 2 must be edge-triggered, and should be
* enabled (otherwise IRQs 8-15 are ignored).
*/
- if (INITIALLY_LEVEL_TRIGGERED(i))
- printf("sio_intr_setup: %d LT!\n", i);
- if (!INITIALLY_ENABLED(i))
- printf("sio_intr_setup: %d not enabled!\n", i);
sio_setirqstat(i, 1, IST_EDGE);
alpha_shared_intr_set_dfltsharetype(sio_intr, i,
IST_UNUSABLE);
@@ -407,17 +405,30 @@ sio_intr_setup(pc, iot)
* Otherwise, disable the IRQ and set its
* type to (effectively) "unknown."
*/
- sio_setirqstat(i, INITIALLY_ENABLED(i),
- INITIALLY_LEVEL_TRIGGERED(i) ? IST_LEVEL :
- IST_NONE);
+ sio_setirqstat(i, 0, IST_NONE);
alpha_shared_intr_set_dfltsharetype(sio_intr, i,
- INITIALLY_LEVEL_TRIGGERED(i) ? IST_LEVEL :
- IST_NONE);
+ IST_NONE);
+ specific_eoi(i);
break;
}
}
}
+#ifdef BROKEN_PROM_CONSOLE
+void
+sio_intr_shutdown(arg)
+ void *arg;
+{
+ /*
+ * Restore the initial values, to make the PROM happy.
+ */
+ bus_space_write_1(sio_iot, sio_ioh_icu1, 1, initial_ocw1[0]);
+ bus_space_write_1(sio_iot, sio_ioh_icu2, 1, initial_ocw1[1]);
+ (*sio_write_elcr)(0, initial_elcr[0]); /* XXX */
+ (*sio_write_elcr)(1, initial_elcr[1]); /* XXX */
+}
+#endif
+
const char *
sio_intr_string(v, irq)
void *v;
@@ -426,12 +437,26 @@ sio_intr_string(v, irq)
static char irqstr[12]; /* 8 + 2 + NULL + sanity */
if (irq == 0 || irq >= ICU_LEN || irq == 2)
- panic("sio_intr_string: bogus isa irq 0x%x", irq);
+ panic("sio_intr_string: bogus isa irq 0x%x\n", irq);
sprintf(irqstr, "isa irq %d", irq);
return (irqstr);
}
+#ifdef notyet
+const struct evcnt *
+sio_intr_evcnt(v, irq)
+ void *v;
+ int irq;
+{
+
+ if (irq == 0 || irq >= ICU_LEN || irq == 2)
+ panic("sio_intr_evcnt: bogus isa irq 0x%x\n", irq);
+
+ return (alpha_shared_intr_evcnt(sio_intr, irq));
+}
+#endif
+
void *
sio_intr_establish(v, irq, type, level, fn, arg, name)
void *v, *arg;
@@ -461,12 +486,47 @@ sio_intr_disestablish(v, cookie)
void *v;
void *cookie;
{
+ struct alpha_shared_intrhand *ih = cookie;
+ int s, ist, irq = ih->ih_num;
+
+ s = splhigh();
- printf("sio_intr_disestablish(%p)\n", cookie);
- /* XXX */
+ /* Remove it from the link. */
+ alpha_shared_intr_disestablish(sio_intr, cookie, "isa irq");
- /* XXX NEVER ALLOW AN INITIALLY-ENABLED INTERRUPT TO BE DISABLED */
- /* XXX NEVER ALLOW AN INITIALLY-LT INTERRUPT TO BECOME UNTYPED */
+ /*
+ * Decide if we should disable the interrupt. We must ensure
+ * that:
+ *
+ * - An initially-enabled interrupt is never disabled.
+ * - An initially-LT interrupt is never untyped.
+ */
+ if (alpha_shared_intr_isactive(sio_intr, irq) == 0) {
+ /*
+ * IRQs 0, 1, 8, and 13 must always be edge-triggered
+ * (see setup).
+ */
+ switch (irq) {
+ case 0:
+ case 1:
+ case 8:
+ case 13:
+ /*
+ * If the interrupt was initially level-triggered
+ * a warning was printed in setup.
+ */
+ ist = IST_EDGE;
+ break;
+
+ default:
+ ist = IST_NONE;
+ break;
+ }
+ sio_setirqstat(irq, 0, ist);
+ alpha_shared_intr_set_dfltsharetype(sio_intr, irq, ist);
+ }
+
+ splx(s);
}
void
@@ -482,16 +542,6 @@ sio_iointr(framep, vec)
panic("sio_iointr: irq out of range (%d)", irq);
#endif
-#ifdef EVCNT_COUNTERS
- sio_intr_evcnt.ev_count++;
-#else
-#ifdef DEBUG
- if (ICU_LEN != INTRCNT_ISA_IRQ_LEN)
- panic("sio interrupt counter sizes inconsistent");
-#endif
- intrcnt[INTRCNT_ISA_IRQ + irq]++;
-#endif
-
if (!alpha_shared_intr_dispatch(sio_intr, irq))
alpha_shared_intr_stray(sio_intr, irq, "isa irq");
@@ -501,9 +551,92 @@ sio_iointr(framep, vec)
* require the non-specific EOI to be fed to the PIC(s)
* by the interrupt handler.
*/
+ specific_eoi(irq);
+}
+
+#define LEGAL_IRQ(x) ((x) >= 0 && (x) < ICU_LEN && (x) != 2)
+
+#ifdef notyet
+int
+sio_intr_alloc(v, mask, type, irq)
+ void *v;
+ int mask;
+ int type;
+ int *irq;
+{
+ int i, tmp, bestirq, count;
+ struct alpha_shared_intrhand **p, *q;
+
+ if (type == IST_NONE)
+ panic("intr_alloc: bogus type");
+
+ bestirq = -1;
+ count = -1;
+
+ /* some interrupts should never be dynamically allocated */
+ mask &= 0xdef8;
+
+ /*
+ * XXX some interrupts will be used later (6 for fdc, 12 for pms).
+ * the right answer is to do "breadth-first" searching of devices.
+ */
+ mask &= 0xefbf;
+
+ for (i = 0; i < ICU_LEN; i++) {
+ if (LEGAL_IRQ(i) == 0 || (mask & (1<<i)) == 0)
+ continue;
+
+ switch(sio_intr[i].intr_sharetype) {
+ case IST_NONE:
+ /*
+ * if nothing's using the irq, just return it
+ */
+ *irq = i;
+ return (0);
+
+ case IST_EDGE:
+ case IST_LEVEL:
+ if (type != sio_intr[i].intr_sharetype)
+ continue;
+ /*
+ * if the irq is shareable, count the number of other
+ * handlers, and if it's smaller than the last irq like
+ * this, remember it
+ *
+ * XXX We should probably also consider the
+ * interrupt level and stick IPL_TTY with other
+ * IPL_TTY, etc.
+ */
+ for (p = &TAILQ_FIRST(&sio_intr[i].intr_q), tmp = 0;
+ (q = *p) != NULL; p = &TAILQ_NEXT(q, ih_q), tmp++)
+ ;
+ if ((bestirq == -1) || (count > tmp)) {
+ bestirq = i;
+ count = tmp;
+ }
+ break;
+
+ case IST_PULSE:
+ /* this just isn't shareable */
+ continue;
+ }
+ }
+
+ if (bestirq == -1)
+ return (1);
+
+ *irq = bestirq;
+
+ return (0);
+}
+#endif
+
+static void
+specific_eoi(irq)
+ int irq;
+{
if (irq > 7)
bus_space_write_1(sio_iot,
sio_ioh_icu2, 0, 0x20 | (irq & 0x07)); /* XXX */
- bus_space_write_1(sio_iot,
- sio_ioh_icu1, 0, 0x20 | (irq > 7 ? 2 : irq)); /* XXX */
+ bus_space_write_1(sio_iot, sio_ioh_icu1, 0, 0x20 | (irq > 7 ? 2 : irq));
}