summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2014-03-15 21:49:48 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2014-03-15 21:49:48 +0000
commitf39b4ef058b8673a7bbdd44c530626bff37d2664 (patch)
treee543a44da1f0c814f74b6f4fcf1ab6113f1a795d /sys/dev
parentabf1b580c65c2435367d4cb233afd06d59175bd1 (diff)
ISP1000 SBus support for qlw(4).
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/qlw.c174
-rw-r--r--sys/dev/ic/qlwreg.h60
-rw-r--r--sys/dev/sbus/files.sbus5
-rw-r--r--sys/dev/sbus/qlw_sbus.c147
4 files changed, 297 insertions, 89 deletions
diff --git a/sys/dev/ic/qlw.c b/sys/dev/ic/qlw.c
index 35d5eabd78c..e6e0df29832 100644
--- a/sys/dev/ic/qlw.c
+++ b/sys/dev/ic/qlw.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: qlw.c,v 1.16 2014/03/15 13:08:52 kettenis Exp $ */
+/* $OpenBSD: qlw.c,v 1.17 2014/03/15 21:49:47 kettenis Exp $ */
/*
* Copyright (c) 2011 David Gwynne <dlg@openbsd.org>
@@ -91,7 +91,12 @@ void qlw_put_cmd(struct qlw_softc *, void *, struct scsi_xfer *,
void qlw_put_cont(struct qlw_softc *, void *, struct scsi_xfer *,
struct qlw_ccb *, int);
struct qlw_ccb *qlw_handle_resp(struct qlw_softc *, u_int16_t);
-void qlw_put_data_seg(struct qlw_iocb_seg *, bus_dmamap_t, int);
+void qlw_get_header(struct qlw_softc *, struct qlw_iocb_hdr *,
+ int *, int *);
+void qlw_put_header(struct qlw_softc *, struct qlw_iocb_hdr *,
+ int, int);
+void qlw_put_data_seg(struct qlw_softc *, struct qlw_iocb_seg *,
+ bus_dmamap_t, int);
int qlw_softreset(struct qlw_softc *);
void qlw_dma_burst_enable(struct qlw_softc *);
@@ -124,6 +129,24 @@ qlw_xs_bus(struct qlw_softc *sc, struct scsi_xfer *xs)
}
static inline u_int16_t
+qlw_swap16(struct qlw_softc *sc, u_int16_t value)
+{
+ if (sc->sc_isp_gen == QLW_GEN_ISP1000)
+ return htobe16(value);
+ else
+ return htole16(value);
+}
+
+static inline u_int32_t
+qlw_swap32(struct qlw_softc *sc, u_int32_t value)
+{
+ if (sc->sc_isp_gen == QLW_GEN_ISP1000)
+ return htobe32(value);
+ else
+ return htole32(value);
+}
+
+static inline u_int16_t
qlw_queue_read(struct qlw_softc *sc, bus_size_t offset)
{
return qlw_read(sc, sc->sc_mbox_base + offset);
@@ -522,24 +545,28 @@ struct qlw_ccb *
qlw_handle_resp(struct qlw_softc *sc, u_int16_t id)
{
struct qlw_ccb *ccb;
- struct qla_iocb_status *status;
+ struct qlw_iocb_hdr *hdr;
+ struct qlw_iocb_status *status;
struct scsi_xfer *xs;
u_int32_t handle;
- u_int8_t *entry;
+ int entry_type;
+ int flags;
int bus;
ccb = NULL;
- entry = QLW_DMA_KVA(sc->sc_responses) + (id * QLW_QUEUE_ENTRY_SIZE);
+ hdr = QLW_DMA_KVA(sc->sc_responses) + (id * QLW_QUEUE_ENTRY_SIZE);
bus_dmamap_sync(sc->sc_dmat,
QLW_DMA_MAP(sc->sc_responses), id * QLW_QUEUE_ENTRY_SIZE,
QLW_QUEUE_ENTRY_SIZE, BUS_DMASYNC_POSTREAD);
- qlw_dump_iocb(sc, entry);
- switch (entry[0]) {
+ qlw_dump_iocb(sc, hdr);
+
+ qlw_get_header(sc, hdr, &entry_type, &flags);
+ switch (entry_type) {
case QLW_IOCB_STATUS:
- status = (struct qla_iocb_status *)entry;
- handle = letoh32(status->handle);
+ status = (struct qlw_iocb_status *)hdr;
+ handle = qlw_swap32(sc, status->handle);
if (handle > sc->sc_maxccbs) {
panic("bad completed command handle: %d (> %d)",
handle, sc->sc_maxccbs);
@@ -568,10 +595,10 @@ qlw_handle_resp(struct qlw_softc *sc, u_int16_t id)
}
bus = qlw_xs_bus(sc, xs);
- xs->status = letoh16(status->scsi_status);
- switch (letoh16(status->completion)) {
+ xs->status = qlw_swap16(sc, status->scsi_status);
+ switch (qlw_swap16(sc, status->completion)) {
case QLW_IOCB_STATUS_COMPLETE:
- if (letoh16(status->scsi_status) &
+ if (qlw_swap16(sc, status->scsi_status) &
QLW_SCSI_STATUS_SENSE_VALID) {
memcpy(&xs->sense, status->sense_data,
sizeof(xs->sense));
@@ -583,8 +610,7 @@ qlw_handle_resp(struct qlw_softc *sc, u_int16_t id)
break;
case QLW_IOCB_STATUS_INCOMPLETE:
- if (letoh16(status->flags) &
- QLW_STATE_GOT_TARGET) {
+ if (flags & QLW_STATE_GOT_TARGET) {
xs->error = XS_DRIVER_STUFFUP;
} else {
xs->error = XS_SELTIMEOUT;
@@ -617,7 +643,7 @@ qlw_handle_resp(struct qlw_softc *sc, u_int16_t id)
case QLW_IOCB_STATUS_DATA_OVERRUN:
case QLW_IOCB_STATUS_DATA_UNDERRUN:
- xs->resid = letoh32(status->resid);
+ xs->resid = qlw_swap32(sc, status->resid);
xs->error = XS_NOERROR;
break;
@@ -632,7 +658,7 @@ qlw_handle_resp(struct qlw_softc *sc, u_int16_t id)
atomic_setbits_int(&sc->sc_update_required[bus],
1 << xs->sc_link->target);
task_add(systq, &sc->sc_update_task);
- xs->resid = letoh32(status->resid);
+ xs->resid = qlw_swap32(sc, status->resid);
xs->error = XS_NOERROR;
break;
@@ -642,14 +668,14 @@ qlw_handle_resp(struct qlw_softc *sc, u_int16_t id)
atomic_setbits_int(&sc->sc_update_required[bus],
1 << xs->sc_link->target);
task_add(systq, &sc->sc_update_task);
- xs->resid = letoh32(status->resid);
+ xs->resid = qlw_swap32(sc, status->resid);
xs->error = XS_NOERROR;
break;
default:
DPRINTF(QLW_D_INTR, "%s: unexpected completion"
" status %x\n", DEVNAME(sc),
- letoh16(status->completion));
+ qlw_swap16(sc, status->completion));
xs->error = XS_DRIVER_STUFFUP;
break;
}
@@ -657,7 +683,7 @@ qlw_handle_resp(struct qlw_softc *sc, u_int16_t id)
default:
DPRINTF(QLW_D_INTR, "%s: unexpected response entry type %x\n",
- DEVNAME(sc), entry[0]);
+ DEVNAME(sc), entry_type);
break;
}
@@ -774,7 +800,7 @@ qlw_scsi_cmd(struct scsi_xfer *xs)
int bus;
int seg;
- if (xs->cmdlen > sizeof(iocb->req_cdb)) {
+ if (xs->cmdlen > sizeof(iocb->cdb)) {
DPRINTF(QLW_D_IO, "%s: cdb too big (%d)\n", DEVNAME(sc),
xs->cmdlen);
memset(&xs->sense, 0, sizeof(xs->sense));
@@ -1252,27 +1278,63 @@ qlw_dump_iocb_segs(struct qlw_softc *sc, void *segs, int n)
#endif
}
+/*
+ * The PCI bus is little-endian whereas SBus is big-endian. This
+ * leads to some differences in byte twisting of DMA transfers of
+ * request and response queue entries. Most fields can be treated as
+ * 16-bit or 32-bit with the endianness of the bus, but the header
+ * fields end up being swapped by the ISP1000's SBus interface.
+ */
+
void
-qlw_put_marker(struct qlw_softc *sc, int bus, void *buf)
+qlw_get_header(struct qlw_softc *sc, struct qlw_iocb_hdr *hdr,
+ int *type, int *flags)
{
- struct qlw_iocb_marker *marker = buf;
+ if (sc->sc_isp_gen == QLW_GEN_ISP1000) {
+ *type = hdr->entry_count;
+ *flags = hdr->seqno;
+ } else {
+ *type = hdr->entry_type;
+ *flags = hdr->flags;
+ }
+}
- marker->entry_type = QLW_IOCB_MARKER;
- marker->entry_count = 1;
- marker->seqno = 0;
- marker->flags = 0;
+void
+qlw_put_header(struct qlw_softc *sc, struct qlw_iocb_hdr *hdr,
+ int type, int count)
+{
+ if (sc->sc_isp_gen == QLW_GEN_ISP1000) {
+ hdr->entry_type = count;
+ hdr->entry_count = type;
+ hdr->seqno = 0;
+ hdr->flags = 0;
+ } else {
+ hdr->entry_type = type;
+ hdr->entry_count = count;
+ hdr->seqno = 0;
+ hdr->flags = 0;
+ }
+}
- /* could be more specific here; isp(4) isn't */
- marker->target = (bus << 7);
- marker->modifier = QLW_IOCB_MARKER_SYNC_ALL;
- qlw_dump_iocb(sc, buf);
+void
+qlw_put_data_seg(struct qlw_softc *sc, struct qlw_iocb_seg *seg,
+ bus_dmamap_t dmap, int num)
+{
+ seg->seg_addr = qlw_swap32(sc, dmap->dm_segs[num].ds_addr);
+ seg->seg_len = qlw_swap32(sc, dmap->dm_segs[num].ds_len);
}
void
-qlw_put_data_seg(struct qlw_iocb_seg *seg, bus_dmamap_t dmap, int num)
+qlw_put_marker(struct qlw_softc *sc, int bus, void *buf)
{
- seg->seg_addr = htole32(dmap->dm_segs[num].ds_addr);
- seg->seg_len = htole32(dmap->dm_segs[num].ds_len);
+ struct qlw_iocb_marker *marker = buf;
+
+ qlw_put_header(sc, &marker->hdr, QLW_IOCB_MARKER, 1);
+
+ /* could be more specific here; isp(4) isn't */
+ marker->device = qlw_swap16(sc, (bus << 7) << 8);
+ marker->modifier = qlw_swap16(sc, QLW_IOCB_MARKER_SYNC_ALL);
+ qlw_dump_iocb(sc, buf);
}
void
@@ -1280,30 +1342,29 @@ qlw_put_cmd(struct qlw_softc *sc, void *buf, struct scsi_xfer *xs,
struct qlw_ccb *ccb)
{
struct qlw_iocb_req0 *req = buf;
+ int entry_count = 1;
u_int16_t dir;
int seg, nsegs;
-
- req->entry_type = QLW_IOCB_CMD_TYPE_0;
- req->entry_count = 1;
- req->seqno = 0;
- req->flags = 0;
+ int seg_count;
+ int timeout = 0;
+ int bus, target, lun;
if (xs->datalen == 0) {
dir = QLW_IOCB_CMD_NO_DATA;
- req->req_seg_count = htole16(1);
+ seg_count = 1;
} else {
dir = xs->flags & SCSI_DATA_IN ? QLW_IOCB_CMD_READ_DATA :
QLW_IOCB_CMD_WRITE_DATA;
- req->req_seg_count = htole16(ccb->ccb_dmamap->dm_nsegs);
+ seg_count = ccb->ccb_dmamap->dm_nsegs;
nsegs = ccb->ccb_dmamap->dm_nsegs - QLW_IOCB_SEGS_PER_CMD;
while (nsegs > 0) {
- req->entry_count++;
+ entry_count++;
nsegs -= QLW_IOCB_SEGS_PER_CONT;
}
for (seg = 0; seg < ccb->ccb_dmamap->dm_nsegs; seg++) {
if (seg >= QLW_IOCB_SEGS_PER_CMD)
break;
- qlw_put_data_seg(&req->req0_segs[seg],
+ qlw_put_data_seg(sc, &req->segs[seg],
ccb->ccb_dmamap, seg);
}
}
@@ -1311,42 +1372,45 @@ qlw_put_cmd(struct qlw_softc *sc, void *buf, struct scsi_xfer *xs,
if (sc->sc_running && (xs->sc_link->quirks & SDEV_NOTAGS) == 0)
dir |= QLW_IOCB_CMD_SIMPLE_QUEUE;
- req->req_flags = htole16(dir);
+ qlw_put_header(sc, &req->hdr, QLW_IOCB_CMD_TYPE_0, entry_count);
/*
* timeout is in seconds. make sure it's at least 1 if a timeout
* was specified in xs
*/
if (xs->timeout != 0)
- req->req_time = htole16(MAX(1, xs->timeout/1000));
+ timeout = MAX(1, xs->timeout/1000);
- req->req_target = (qlw_xs_bus(sc, xs) << 7) | xs->sc_link->target;
- req->req_lun_trn = xs->sc_link->lun;
+ req->flags = qlw_swap16(sc, dir);
+ req->seg_count = qlw_swap16(sc, seg_count);
+ req->timeout = qlw_swap16(sc, timeout);
+
+ bus = qlw_xs_bus(sc, xs);
+ target = xs->sc_link->target;
+ lun = xs->sc_link->lun;
+ req->device = qlw_swap16(sc, (((bus << 7) | target) << 8) | lun);
- memcpy(req->req_cdb, xs->cmd, xs->cmdlen);
- req->req_ccblen = htole16(xs->cmdlen);
+ memcpy(req->cdb, xs->cmd, xs->cmdlen);
+ req->ccblen = qlw_swap16(sc, xs->cmdlen);
- req->req_handle = htole32(ccb->ccb_id);
+ req->handle = qlw_swap32(sc, ccb->ccb_id);
qlw_dump_iocb(sc, buf);
}
void
qlw_put_cont(struct qlw_softc *sc, void *buf, struct scsi_xfer *xs,
- struct qlw_ccb *ccb, int seg0)
+ struct qlw_ccb *ccb, int seg0)
{
struct qlw_iocb_cont0 *cont = buf;
int seg;
- cont->entry_type = QLW_IOCB_CONT_TYPE_0;
- cont->entry_count = 1;
- cont->seqno = 0;
- cont->flags = 0;
+ qlw_put_header(sc, &cont->hdr, QLW_IOCB_CONT_TYPE_0, 1);
for (seg = seg0; seg < ccb->ccb_dmamap->dm_nsegs; seg++) {
if ((seg - seg0) >= QLW_IOCB_SEGS_PER_CONT)
break;
- qlw_put_data_seg(&cont->segs[seg - seg0],
+ qlw_put_data_seg(sc, &cont->segs[seg - seg0],
ccb->ccb_dmamap, seg);
}
}
diff --git a/sys/dev/ic/qlwreg.h b/sys/dev/ic/qlwreg.h
index b3602dbb139..65f761565a5 100644
--- a/sys/dev/ic/qlwreg.h
+++ b/sys/dev/ic/qlwreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: qlwreg.h,v 1.6 2014/03/15 13:08:52 kettenis Exp $ */
+/* $OpenBSD: qlwreg.h,v 1.7 2014/03/15 21:49:47 kettenis Exp $ */
/*
* Copyright (c) 2013, 2014 Jonathan Matthew <jmatthew@openbsd.org>
@@ -245,7 +245,12 @@ struct qlw_nvram {
#define QLW_IOCB_CMD_WRITE_DATA 0x0040
#define QLW_IOCB_CMD_NO_FAST_POST 0x0080
-#define QLW_IOCB_MARKER_SYNC_ALL 2
+struct qlw_iocb_hdr {
+ u_int8_t entry_type;
+ u_int8_t entry_count;
+ u_int8_t seqno;
+ u_int8_t flags;
+} __packed;
#define QLW_IOCB_SEGS_PER_CMD 4
#define QLW_IOCB_SEGS_PER_CONT 7
@@ -262,38 +267,28 @@ struct qlw_iocb_seg {
#define QLW_IOCB_MARKER 0x04
struct qlw_iocb_req0 {
- u_int8_t entry_type; /* QLW_IOCB_CMD_TYPE_0 */
- u_int8_t entry_count;
- u_int8_t seqno;
- u_int8_t flags;
+ struct qlw_iocb_hdr hdr; /* QLW_IOCB_REQ_TYPE0 */
- u_int32_t req_handle;
- u_int8_t req_lun_trn;
- u_int8_t req_target;
- u_int16_t req_ccblen;
- u_int16_t req_flags;
- u_int16_t req_reserved;
- u_int16_t req_time;
- u_int16_t req_seg_count;
- u_int8_t req_cdb[12];
- struct qlw_iocb_seg req0_segs[4];
+ u_int32_t handle;
+ u_int16_t device;
+ u_int16_t ccblen;
+ u_int16_t flags;
+ u_int16_t reserved;
+ u_int16_t timeout;
+ u_int16_t seg_count;
+ u_int8_t cdb[12];
+ struct qlw_iocb_seg segs[4];
} __packed;
struct qlw_iocb_cont0 {
- u_int8_t entry_type; /* QLA_IOCB_CONT_TYPE_0 */
- u_int8_t entry_count;
- u_int8_t seqno;
- u_int8_t flags;
+ struct qlw_iocb_hdr hdr; /* QLW_IOCB_CONT_TYPE_0 */
u_int32_t reserved;
struct qlw_iocb_seg segs[7];
} __packed;
-struct qla_iocb_status {
- u_int8_t entry_type; /* QLA_IOCB_STATUS */
- u_int8_t entry_count;
- u_int8_t seqno;
- u_int8_t flags;
+struct qlw_iocb_status {
+ struct qlw_iocb_hdr hdr;
u_int32_t handle;
u_int16_t scsi_status;
@@ -326,14 +321,13 @@ struct qla_iocb_status {
#define QLW_SCSI_STATUS_SENSE_VALID 0x0200
struct qlw_iocb_marker {
- u_int8_t entry_type; /* QLW_IOCB_MARKER */
- u_int8_t entry_count;
- u_int8_t seqno;
- u_int8_t flags;
+ struct qlw_iocb_hdr hdr; /* QLW_IOCB_MARKER */
u_int32_t handle;
- u_int8_t lun;
- u_int8_t target;
- u_int8_t modifier;
- u_int8_t reserved2[53];
+ u_int16_t device;
+ u_int16_t modifier;
+ u_int8_t reserved2[52];
+
} __packed;
+
+#define QLW_IOCB_MARKER_SYNC_ALL 2
diff --git a/sys/dev/sbus/files.sbus b/sys/dev/sbus/files.sbus
index 1a12d6e7905..e5e767759ae 100644
--- a/sys/dev/sbus/files.sbus
+++ b/sys/dev/sbus/files.sbus
@@ -1,4 +1,4 @@
-# $OpenBSD: files.sbus,v 1.40 2014/02/02 13:01:58 kettenis Exp $
+# $OpenBSD: files.sbus,v 1.41 2014/03/15 21:49:47 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 qlw at sbus with qlw_sbus
+file dev/sbus/qlw_sbus.c qlw_sbus
+
attach qla at sbus with qla_sbus
file dev/sbus/qla_sbus.c qla_sbus
diff --git a/sys/dev/sbus/qlw_sbus.c b/sys/dev/sbus/qlw_sbus.c
new file mode 100644
index 00000000000..c1e6a6a832d
--- /dev/null
+++ b/sys/dev/sbus/qlw_sbus.c
@@ -0,0 +1,147 @@
+/* $OpenBSD: qlw_sbus.c,v 1.1 2014/03/15 21:49:47 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 <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+
+#include <dev/ic/qlwreg.h>
+#include <dev/ic/qlwvar.h>
+
+#ifndef ISP_NOFIRMWARE
+#include <dev/microcode/isp/asm_sbus.h>
+#endif
+
+int qlw_sbus_match(struct device *, void *, void *);
+void qlw_sbus_attach(struct device *, struct device *, void *);
+
+struct cfattach qlw_sbus_ca = {
+ sizeof(struct qlw_softc),
+ qlw_sbus_match,
+ qlw_sbus_attach
+};
+
+int
+qlw_sbus_match(struct device *parent, void *cf, void *aux)
+{
+ struct sbus_attach_args *sa = aux;
+
+ if (strcmp("ptisp", sa->sa_name) == 0 ||
+ strcmp("PTI,ptisp", sa->sa_name) == 0 ||
+ strcmp("SUNW,isp", sa->sa_name) == 0 ||
+ strcmp("QLGC,isp", sa->sa_name) == 0)
+ return 2;
+
+ return 0;
+}
+
+void
+qlw_sbus_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct qlw_softc *sc = (void *)self;
+ struct sbus_attach_args *sa = aux;
+ u_int32_t sbusburst, burst;
+ int freq;
+
+ if (sa->sa_nintr < 1) {
+ printf(": no interrupt\n");
+ return;
+ }
+
+ if (sa->sa_nreg < 1) {
+ printf(": no registers\n");
+ return;
+ }
+
+ if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset,
+ sa->sa_size, 0, 0, &sc->sc_ioh) != 0) {
+ printf(": can't map registers\n");
+ return;
+ }
+
+ printf(": %s\n", sa->sa_name);
+
+ if (bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_BIO, 0,
+ qlw_intr, sc, sc->sc_dev.dv_xname) == NULL) {
+ printf("%s: can't establish interrupt\n", DEVNAME(sc));
+ goto unmap;
+ }
+
+ /*
+ * Get transfer burst size from PROM
+ */
+ sbusburst = ((struct sbus_softc *)parent)->sc_burst;
+ if (sbusburst == 0)
+ sbusburst = SBUS_BURST_32 - 1; /* 1->16 */
+
+ burst = getpropint(sa->sa_node, "burst-sizes", -1);
+ if (burst == -1)
+ burst = sbusburst;
+
+ /* Clamp at parent's burst sizes */
+ burst &= sbusburst;
+
+ if ((burst & SBUS_BURST_32))
+ sc->sc_isp_config = QLW_BURST_ENABLE | QLW_SBUS_FIFO_32;
+ else if ((burst & SBUS_BURST_16))
+ sc->sc_isp_config = QLW_BURST_ENABLE | QLW_SBUS_FIFO_16;
+ else if ((burst & SBUS_BURST_8))
+ sc->sc_isp_config = QLW_BURST_ENABLE | QLW_SBUS_BURST_8;
+
+ sc->sc_iot = sa->sa_bustag;
+ sc->sc_ios = sa->sa_size;
+ sc->sc_dmat = sa->sa_dmatag;
+
+ sc->sc_isp_gen = QLW_GEN_ISP1000;
+ sc->sc_isp_type = QLW_ISP1000;
+ sc->sc_numbusses = 1;
+
+ freq = getpropint(sa->sa_node, "clock-frequency", 40000000);
+ sc->sc_clock = (freq + 500000) / 1000000;
+
+#ifndef ISP_NOFIRMWARE
+ /*
+ * Some early versions of the PTI cards don't support loading
+ * a new firmware, so only do this in the Sun or QLogic
+ * branded ones.
+ */
+ if (strcmp("SUNW,isp", sa->sa_name) == 0 ||
+ strcmp("QLGC,isp", sa->sa_name) == 0)
+ sc->sc_firmware = isp_1000_risc_code;
+#endif
+
+ sc->sc_initiator[0] = getpropint(sa->sa_node, "scsi-initiator-id", 6);
+
+ sc->sc_host_cmd_ctrl = QLW_HOST_CMD_CTRL_SBUS;
+ sc->sc_mbox_base = QLW_MBOX_BASE_SBUS;
+
+ qlw_attach(sc);
+ return;
+
+unmap:
+ bus_space_unmap(sa->sa_bustag, sc->sc_ioh, sa->sa_size);
+}