Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci support bus probes a la "badaddr" and VME interr...
details: https://anonhg.NetBSD.org/src/rev/00246e44165b
branches: trunk
changeset: 483537:00246e44165b
user: drochner <drochner%NetBSD.org@localhost>
date: Sun Mar 12 11:23:06 2000 +0000
description:
support bus probes a la "badaddr" and VME interrupts, fix error handling
after mapping problems
diffstat:
sys/dev/pci/btvmeii.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 165 insertions(+), 9 deletions(-)
diffs (288 lines):
diff -r 384f91308d44 -r 00246e44165b sys/dev/pci/btvmeii.c
--- a/sys/dev/pci/btvmeii.c Sun Mar 12 11:21:02 2000 +0000
+++ b/sys/dev/pci/btvmeii.c Sun Mar 12 11:23:06 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: btvmeii.c,v 1.1 2000/02/25 18:22:39 drochner Exp $ */
+/* $NetBSD: btvmeii.c,v 1.2 2000/03/12 11:23:06 drochner Exp $ */
/*
* Copyright (c) 1999
@@ -68,6 +68,7 @@
void *b3_2706_establish_vmeint __P((void *, vme_intr_handle_t, int,
int (*)(void *), void *));
void b3_2706_disestablish_vmeint __P((void *, void *));
+void b3_2706_vmeint __P((void *, int, int));
int b3_2706_dmamap_create __P((void *, vme_size_t,
vme_am_t, vme_datasize_t, vme_swap_t,
@@ -87,6 +88,16 @@
u_int32_t len;
};
+struct b3_2706_vmeintrhand {
+ TAILQ_ENTRY(b3_2706_vmeintrhand) ih_next;
+ int (*ih_fun) __P((void*));
+ void *ih_arg;
+ int ih_level;
+ int ih_vector;
+ int ih_prior;
+ u_long ih_count;
+};
+
struct b3_2706_softc {
struct device sc_dev;
struct univ_pci_data univdata;
@@ -100,6 +111,10 @@
char vmemap[EXTENT_FIXED_STORAGE_SIZE(8)];
struct vme_chipset_tag sc_vct;
+
+ /* list of VME interrupt handlers */
+ TAILQ_HEAD(, b3_2706_vmeintrhand) intrhdls;
+ int strayintrs;
};
struct cfattach btvmeii_ca = {
@@ -202,12 +217,17 @@
aa.pa_intrpin = ((1 + aa.pa_intrswiz - 1) % 4) + 1;
aa.pa_intrline = PCI_INTERRUPT_LINE(intr);
- if (univ_pci_attach(&sc->univdata, &aa)) {
+ if (univ_pci_attach(&sc->univdata, &aa, self->dv_xname,
+ b3_2706_vmeint, sc)) {
printf("%s: error initializing universe chip\n",
self->dv_xname);
return;
}
+ /*
+ * don't waste KVM - the byteswap register is aliased in
+ * a 512k window, we need it only once
+ */
tag = pci_make_tag(pc, secbus, 8, 0);
sc->swapt = pa->pa_memt;
if (pci_mapreg_info(pc, tag, 0x10,
@@ -217,6 +237,15 @@
printf("%s: can't map byteswap register\n", self->dv_xname);
return;
}
+ /*
+ * Set up cycle specific byteswap mode.
+ * XXX Readback yields "all-ones" for me, and it doesn't seem
+ * to matter what I write into the register - the data don't
+ * get swapped. Adapter fault or documentation bug?
+ */
+ bus_space_write_4(sc->swapt, sc->swaph, 0, 0x00000490);
+
+ /* VME space is mapped as needed */
sc->vmet = pa->pa_memt;
if (pci_mapreg_info(pc, tag, 0x14,
PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT,
@@ -224,13 +253,13 @@
printf("%s: VME range not assigned\n", self->dv_xname);
return;
}
+#ifdef BIT3DEBUG
printf("%s: VME window @%lx\n", self->dv_xname, (long)sc->vmepbase);
+#endif
for (i = 0; i < 8; i++) {
- univ_pci_unmapvme(&sc->univdata, i);
sc->windowused[i] = 0;
}
-
sc->vmeext = extent_create("pcivme", sc->vmepbase,
sc->vmepbase + 32*1024*1024 - 1, M_DEVBUF,
sc->vmemap, sizeof(sc->vmemap),
@@ -250,7 +279,7 @@
vaa.va_vct = &(sc->sc_vct);
vaa.va_bdt = pa->pa_dmat; /* XXX */
- vaa.va_slaveconfig = 0; /* XXX */
+ vaa.va_slaveconfig = 0; /* XXX CSR window? */
config_found(self, &vaa, 0);
}
@@ -300,13 +329,16 @@
/* bytes in outgoing window required */
maplen = vmeend - vmebase + boundary;
- if (extent_alloc(sc->vmeext, maplen, boundary, 0, EX_FAST, &pcibase))
+ if (extent_alloc(sc->vmeext, maplen, boundary, 0, EX_FAST, &pcibase)) {
+ sc->windowused[wnd] = 0;
return (ENOMEM);
+ }
res = univ_pci_mapvme(&sc->univdata, wnd, vmebase, maplen,
am, datasizes, pcibase);
if (res) {
extent_free(sc->vmeext, pcibase, maplen, 0);
+ sc->windowused[wnd] = 0;
return (res);
}
@@ -315,6 +347,7 @@
if (res) {
univ_pci_unmapvme(&sc->univdata, wnd);
extent_free(sc->vmeext, pcibase, maplen, 0);
+ sc->windowused[wnd] = 0;
return (res);
}
@@ -358,7 +391,54 @@
int (*callback) __P((void *, bus_space_tag_t, bus_space_handle_t));
void *cbarg;
{
- return (EINVAL);
+ bus_space_tag_t tag;
+ bus_space_handle_t handle;
+ vme_mapresc_t resc;
+ int res, i;
+ volatile u_int32_t dummy;
+
+ res = b3_2706_map_vme(vsc, addr, len, am, datasize, 0,
+ &tag, &handle, &resc);
+ if (res)
+ return (res);
+
+ if (univ_pci_vmebuserr(&sc->univdata, 1))
+ printf("b3_2706_vme_badaddr: TA bit not clean - reset\n");
+
+ if (callback)
+ res = (*callback)(cbarg, tag, handle);
+ else {
+ for (i = 0; i < len;) {
+ switch (datasize) {
+ case VME_D8:
+ dummy = bus_space_read_1(tag, handle, i);
+ i++;
+ break;
+ case VME_D16:
+ dummy = bus_space_read_2(tag, handle, i);
+ i += 2;
+ break;
+ case VME_D32:
+ dummy = bus_space_read_4(tag, handle, i);
+ i += 4;
+ break;
+ default:
+ panic("b3_2706_vme_probe: invalid datasize %x",
+ datasize);
+ }
+ }
+ }
+
+ if (univ_pci_vmebuserr(&sc->univdata, 0)) {
+#ifdef BIT3DEBUG
+ printf("b3_2706_vme_badaddr: caught TA\n");
+#endif
+ univ_pci_vmebuserr(&sc->univdata, 1);
+ res = EIO;
+ }
+
+ b3_2706_unmap_vme(vsc, resc);
+ return (res);
}
int
@@ -367,7 +447,9 @@
int level, vector;
vme_intr_handle_t *handlep;
{
- return (EINVAL);
+
+ *handlep = (void *)(long)((level << 8) | vector); /* XXX */
+ return (0);
}
void *
@@ -378,7 +460,30 @@
int (*func) __P((void *));
void *arg;
{
- return (NULL);
+ struct b3_2706_vmeintrhand *ih;
+ long lv;
+ int s;
+ extern int cold;
+
+ /* no point in sleeping unless someone can free memory. */
+ ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
+ if (ih == NULL)
+ panic("b3_2706_map_vmeint: can't malloc handler info");
+
+ lv = (long)handle; /* XXX */
+
+ ih->ih_fun = func;
+ ih->ih_arg = arg;
+ ih->ih_level = lv >> 8;
+ ih->ih_vector = lv & 0xff;
+ ih->ih_prior = prior;
+ ih->ih_count = 0;
+
+ s = splhigh();
+ TAILQ_INSERT_TAIL(&(sc->intrhdls), ih, ih_next);
+ splx(s);
+
+ return (ih);
}
void
@@ -386,6 +491,57 @@
void *vsc;
void *cookie;
{
+ struct b3_2706_vmeintrhand *ih = cookie;
+ int s;
+
+ if (!ih) {
+ printf("b3_2706_unmap_vmeint: NULL arg\n");
+ return;
+ }
+
+ s = splhigh();
+ TAILQ_REMOVE(&(sc->intrhdls), ih, ih_next);
+ splx(s);
+
+ free(ih, M_DEVBUF);
+}
+
+void
+b3_2706_vmeint(vsc, level, vector)
+ void *vsc;
+ int level, vector;
+{
+ struct b3_2706_vmeintrhand *ih;
+ int found;
+
+#ifdef BIT3DEBUG
+ printf("b3_2706_vmeint: VME IRQ %d, vec %x\n", level, vector);
+#endif
+ found = 0;
+
+ for (ih = sc->intrhdls.tqh_first; ih;
+ ih = ih->ih_next.tqe_next) {
+ if ((ih->ih_level == level) &&
+ ((ih->ih_vector == -1) ||
+ (ih->ih_vector == vector))) {
+ int s, res;
+ /*
+ * We should raise the interrupt level
+ * to ih->ih_prior here. How to do this
+ * machine-independantly?
+ * To be safe, raise to the maximum.
+ */
+ s = splhigh();
+ found |= (res = (*(ih->ih_fun))(ih->ih_arg));
+ splx(s);
+ if (res)
+ ih->ih_count++;
+ if (res == 1)
+ break;
+ }
+ }
+ if (!found)
+ sc->strayintrs++;
}
int
Home |
Main Index |
Thread Index |
Old Index