summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2014-02-02 13:01:59 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2014-02-02 13:01:59 +0000
commitc2cebc16383f29a4d3ead1ca6d6529cc0dd9cd46 (patch)
treeb049b7fe4a4d4b62a6fe6b2ba57e4d7a1cd3f451
parent7ac263196f1d6b2caddacfbe0af7eeef4060136b (diff)
sbus(4) glue for qla(4)
-rw-r--r--sys/dev/sbus/files.sbus5
-rw-r--r--sys/dev/sbus/qla_sbus.c156
2 files changed, 160 insertions, 1 deletions
diff --git a/sys/dev/sbus/files.sbus b/sys/dev/sbus/files.sbus
index 7184d70ca0f..1a12d6e7905 100644
--- a/sys/dev/sbus/files.sbus
+++ b/sys/dev/sbus/files.sbus
@@ -1,4 +1,4 @@
-# $OpenBSD: files.sbus,v 1.39 2013/09/24 20:11:02 miod Exp $
+# $OpenBSD: files.sbus,v 1.40 2014/02/02 13:01:58 kettenis Exp $
# $NetBSD: files.sbus,v 1.16 2000/12/08 17:29:12 martin Exp $
#
# Config file and device description for machine-independent SBUS code.
@@ -58,6 +58,9 @@ file dev/sbus/cs4231.c audiocs
attach isp at sbus with isp_sbus
file dev/sbus/isp_sbus.c isp_sbus
+attach qla at sbus with qla_sbus
+file dev/sbus/qla_sbus.c qla_sbus
+
device agten: wsemuldisplaydev, rasops8
attach agten at sbus
file dev/sbus/agten.c agten
diff --git a/sys/dev/sbus/qla_sbus.c b/sys/dev/sbus/qla_sbus.c
new file mode 100644
index 00000000000..4f2904de902
--- /dev/null
+++ b/sys/dev/sbus/qla_sbus.c
@@ -0,0 +1,156 @@
+/* $OpenBSD: qla_sbus.c,v 1.1 2014/02/02 13:01:58 kettenis Exp $ */
+/*
+ * Copyright (c) 2014 Mark Kettenis
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/systm.h>
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+#include <machine/autoconf.h>
+
+#include <dev/sbus/sbusvar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+
+#include <dev/ic/qlareg.h>
+#include <dev/ic/qlavar.h>
+
+#define QLA_SBUS_REG_OFFSET 0x100
+#define QLA_SBUS_REG_SIZE 0x300
+
+int qla_sbus_match(struct device *, void *, void *);
+void qla_sbus_attach(struct device *, struct device *, void *);
+
+struct cfattach qla_sbus_ca = {
+ sizeof(struct qla_softc),
+ qla_sbus_match,
+ qla_sbus_attach
+};
+
+int
+qla_sbus_match(struct device *parent, void *cf, void *aux)
+{
+ struct sbus_attach_args *sa = aux;
+
+ if (strcmp("SUNW,qlc", sa->sa_name) == 0 ||
+ strcmp("QLGC,qla", sa->sa_name) == 0)
+ return 2;
+
+ return 0;
+}
+
+void
+qla_sbus_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct qla_softc *sc = (void *)self;
+ struct sbus_attach_args *sa = aux;
+ struct sparc_bus_space_tag *iot;
+ bus_space_handle_t ioh;
+ pcireg_t id, class;
+ char devinfo[256];
+
+ if (sa->sa_nintr < 1) {
+ printf(": no interrupt\n");
+ return;
+ }
+
+ if (sa->sa_nreg < 1) {
+ printf(": no registers\n");
+ return;
+ }
+
+ /*
+ * These cards have a standard PCI chips that sit behind an
+ * FPGA with some bridging logic. Since the PCI bus is
+ * little-endian, we need a little-endian bus tag. So we
+ * build one here.
+ */
+ iot = malloc(sizeof(*iot), M_DEVBUF, M_NOWAIT);
+ if (iot == NULL) {
+ printf(": can't allocate bus tag\n");
+ return;
+ }
+ *iot = *sa->sa_bustag;
+ iot->asi = ASI_PRIMARY_LITTLE;
+
+ if (sbus_bus_map(iot, sa->sa_slot, sa->sa_offset,
+ sa->sa_size, 0, 0, &ioh) != 0) {
+ printf(": can't map registers\n");
+ goto free;
+ }
+
+ /*
+ * PCI config space is mapped at the start of the SBus
+ * register space. We use it to identify the ISP chip.
+ */
+ id = bus_space_read_4(iot, ioh, PCI_ID_REG);
+ class = bus_space_read_4(iot, ioh, PCI_CLASS_REG);
+
+ pci_devinfo(id, class, 0, devinfo, sizeof(devinfo));
+ printf(": %s\n", devinfo);
+
+ switch (PCI_PRODUCT(id)) {
+ case PCI_PRODUCT_QLOGIC_ISP2200:
+ sc->sc_isp_gen = QLA_GEN_ISP2200;
+ sc->sc_isp_type = QLA_ISP2200;
+ break;
+
+ case PCI_PRODUCT_QLOGIC_ISP2300:
+ sc->sc_isp_gen = QLA_GEN_ISP23XX;
+ sc->sc_isp_type = QLA_ISP2300;
+ break;
+
+ case PCI_PRODUCT_QLOGIC_ISP2312:
+ sc->sc_isp_gen = QLA_GEN_ISP23XX;
+ sc->sc_isp_type = QLA_ISP2312;
+ break;
+
+ default:
+ printf("%s: unsupported ISP chip\n", DEVNAME(sc));
+ goto unmap;
+ }
+
+ if (bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_BIO, 0,
+ qla_intr, sc, sc->sc_dev.dv_xname) == NULL) {
+ printf("%s: can't establish interrupt\n", DEVNAME(sc));
+ goto unmap;
+ }
+
+ if (bus_space_subregion(iot, ioh, QLA_SBUS_REG_OFFSET,
+ QLA_SBUS_REG_SIZE, &sc->sc_ioh) != 0) {
+ printf("%s: can't submap registers\n", DEVNAME(sc));
+ goto unmap;
+ }
+
+ sc->sc_iot = iot;
+ sc->sc_ios = QLA_SBUS_REG_SIZE;
+ sc->sc_dmat = sa->sa_dmatag;
+
+ qla_attach(sc);
+ return;
+
+unmap:
+ bus_space_unmap(iot, ioh, sa->sa_size);
+free:
+ free(iot, M_DEVBUF);
+}