diff options
Diffstat (limited to 'sys/dev/ic')
-rw-r--r-- | sys/dev/ic/qla.c | 163 | ||||
-rw-r--r-- | sys/dev/ic/qlavar.h | 21 |
2 files changed, 87 insertions, 97 deletions
diff --git a/sys/dev/ic/qla.c b/sys/dev/ic/qla.c index 547121c8261..a1d808f20e2 100644 --- a/sys/dev/ic/qla.c +++ b/sys/dev/ic/qla.c @@ -1,4 +1,4 @@ -/* $OpenBSD: qla.c,v 1.22 2014/02/19 06:29:08 jmatthew Exp $ */ +/* $OpenBSD: qla.c,v 1.23 2014/02/19 13:41:23 dlg Exp $ */ /* * Copyright (c) 2011 David Gwynne <dlg@openbsd.org> @@ -70,10 +70,12 @@ void qla_scsi_cmd(struct scsi_xfer *); struct qla_ccb *qla_scsi_cmd_poll(struct qla_softc *); int qla_scsi_probe(struct scsi_link *); -u_int16_t qla_read(struct qla_softc *, int); -void qla_write(struct qla_softc *, int, u_int16_t); +u_int16_t qla_read(struct qla_softc *, bus_size_t); +void qla_write(struct qla_softc *, bus_size_t, u_int16_t); void qla_host_cmd(struct qla_softc *sc, u_int16_t); +u_int16_t qla_read_queue_2100(struct qla_softc *, bus_size_t); + int qla_mbox(struct qla_softc *, int, int); int qla_sns_req(struct qla_softc *, struct qla_dmamem *, int); void qla_mbox_putaddr(u_int16_t *, struct qla_dmamem *); @@ -85,10 +87,6 @@ void qla_set_ints(struct qla_softc *, int); int qla_read_isr(struct qla_softc *, u_int16_t *, u_int16_t *); void qla_clear_isr(struct qla_softc *, u_int16_t); -int qla_queue_reg(struct qla_softc *, enum qla_qptr); -u_int16_t qla_read_queue_ptr(struct qla_softc *, enum qla_qptr); -void qla_write_queue_ptr(struct qla_softc *, enum qla_qptr, - u_int16_t); void qla_update(struct qla_softc *, int); void qla_put_marker(struct qla_softc *, void *); void qla_put_cmd(struct qla_softc *, void *, struct scsi_xfer *, @@ -133,6 +131,33 @@ void qla_put_ccb(void *, void *); void qla_dump_iocb(struct qla_softc *, void *); void qla_dump_iocb_segs(struct qla_softc *, void *, int); +static const struct qla_queue_regs qla_queue_regs_2100 = { + qla_read_queue_2100, + QLA_MBOX_BASE_2100 + 0x8, + QLA_MBOX_BASE_2100 + 0x8, + QLA_MBOX_BASE_2100 + 0xa, + QLA_MBOX_BASE_2100 + 0xa +}; + +static const struct qla_queue_regs qla_queue_regs_2200 = { + qla_read, + QLA_MBOX_BASE_2200 + 0x8, + QLA_MBOX_BASE_2200 + 0x8, + QLA_MBOX_BASE_2200 + 0xa, + QLA_MBOX_BASE_2200 + 0xa +}; + +static const struct qla_queue_regs qla_queue_regs_23XX = { + qla_read, + QLA_REQ_IN, + QLA_REQ_OUT, + QLA_RESP_IN, + QLA_RESP_OUT +}; + +#define qla_queue_read(_sc, _r) ((*(_sc)->sc_q->read)((_sc), (_r))) +#define qla_queue_write(_sc, _r, _v) qla_write((_sc), (_r), (_v)) + struct scsi_adapter qla_switch = { qla_scsi_cmd, scsi_minphys, @@ -278,14 +303,17 @@ qla_attach(struct qla_softc *sc) switch (sc->sc_isp_gen) { case QLA_GEN_ISP2100: sc->sc_mbox_base = QLA_MBOX_BASE_2100; + sc->sc_q = &qla_queue_regs_2100; break; case QLA_GEN_ISP2200: sc->sc_mbox_base = QLA_MBOX_BASE_2200; + sc->sc_q = &qla_queue_regs_2200; break; case QLA_GEN_ISP23XX: sc->sc_mbox_base = QLA_MBOX_BASE_23XX; + sc->sc_q = &qla_queue_regs_23XX; break; default: @@ -723,7 +751,7 @@ qla_handle_intr(struct qla_softc *sc, u_int16_t isr, u_int16_t info) /* apparently can't read the out ptr with <2300 chips, * and apparently also need to debounce the in ptr reads */ - rspin = qla_read_queue_ptr(sc, QLA_RESP_QUEUE_IN); + rspin = qla_queue_read(sc, sc->sc_q->res_in); if (rspin == sc->sc_last_resp_id) { /* seems to happen a lot on 2200s when mbox commands * complete but it doesn't want to give us the register @@ -738,28 +766,25 @@ qla_handle_intr(struct qla_softc *sc, u_int16_t isr, u_int16_t info) return; } - /* isp(4) has some weird magic for this case */ - DPRINTF(QLA_D_INTR, "%s: nonsense interrupt (%x)\n", - DEVNAME(sc), rspin); - } else { - if (sc->sc_responses == NULL) - break; + break; + } - DPRINTF(QLA_D_IO, "%s: response queue %x=>%x\n", - DEVNAME(sc), sc->sc_last_resp_id, rspin); - while (sc->sc_last_resp_id != rspin) { - ccb = qla_handle_resp(sc, sc->sc_last_resp_id); - if (ccb) - scsi_done(ccb->ccb_xs); + if (sc->sc_responses == NULL) + break; - sc->sc_last_resp_id++; - if (sc->sc_last_resp_id == sc->sc_maxcmds) - sc->sc_last_resp_id = 0; - } + DPRINTF(QLA_D_IO, "%s: response queue %x=>%x\n", + DEVNAME(sc), sc->sc_last_resp_id, rspin); - qla_write_queue_ptr(sc, QLA_RESP_QUEUE_OUT, - sc->sc_last_resp_id); - } + do { + ccb = qla_handle_resp(sc, sc->sc_last_resp_id); + if (ccb) + scsi_done(ccb->ccb_xs); + + sc->sc_last_resp_id++; + sc->sc_last_resp_id %= sc->sc_maxcmds; + } while (sc->sc_last_resp_id != rspin); + + qla_queue_write(sc, sc->sc_q->res_out, rspin); break; case QLA_INT_TYPE_MBOX: @@ -878,7 +903,7 @@ qla_scsi_cmd(struct scsi_xfer *xs) bus_dmamap_sync(sc->sc_dmat, QLA_DMA_MAP(sc->sc_requests), offset, QLA_QUEUE_ENTRY_SIZE, BUS_DMASYNC_POSTWRITE); qla_put_marker(sc, iocb); - qla_write_queue_ptr(sc, QLA_REQ_QUEUE_IN, sc->sc_next_req_id); + qla_queue_write(sc, sc->sc_q->req_in, sc->sc_next_req_id); sc->sc_marker_required = 0; } @@ -896,7 +921,7 @@ qla_scsi_cmd(struct scsi_xfer *xs) DPRINTF(QLA_D_IO, "%s: writing cmd at request %d\n", DEVNAME(sc), req); qla_put_cmd(sc, iocb, xs, ccb); - qla_write_queue_ptr(sc, QLA_REQ_QUEUE_IN, sc->sc_next_req_id); + qla_queue_write(sc, sc->sc_q->req_in, sc->sc_next_req_id); if (!ISSET(xs->flags, SCSI_POLL)) { mtx_leave(&sc->sc_queue_mtx); @@ -937,7 +962,7 @@ qla_scsi_cmd_poll(struct qla_softc *sc) continue; } - rspin = qla_read_queue_ptr(sc, QLA_RESP_QUEUE_IN); + rspin = qla_queue_read(sc, sc->sc_q->res_in); if (rspin != sc->sc_last_resp_id) { ccb = qla_handle_resp(sc, sc->sc_last_resp_id); @@ -945,7 +970,7 @@ qla_scsi_cmd_poll(struct qla_softc *sc) if (sc->sc_last_resp_id == sc->sc_maxcmds) sc->sc_last_resp_id = 0; - qla_write_queue_ptr(sc, QLA_RESP_QUEUE_OUT, + qla_queue_write(sc, sc->sc_q->res_out, sc->sc_last_resp_id); } @@ -956,7 +981,7 @@ qla_scsi_cmd_poll(struct qla_softc *sc) } u_int16_t -qla_read(struct qla_softc *sc, int offset) +qla_read(struct qla_softc *sc, bus_size_t offset) { u_int16_t v; v = bus_space_read_2(sc->sc_iot, sc->sc_ioh, offset); @@ -966,7 +991,7 @@ qla_read(struct qla_softc *sc, int offset) } void -qla_write(struct qla_softc *sc, int offset, u_int16_t value) +qla_write(struct qla_softc *sc, bus_size_t offset, u_int16_t value) { bus_space_write_2(sc->sc_iot, sc->sc_ioh, offset, value); bus_space_barrier(sc->sc_iot, sc->sc_ioh, offset, 2, @@ -1176,64 +1201,24 @@ qla_clear_isr(struct qla_softc *sc, u_int16_t isr) } } -int -qla_queue_reg(struct qla_softc *sc, enum qla_qptr queue) +u_int16_t +qla_read_queue_2100(struct qla_softc *sc, bus_size_t queue) { - switch (sc->sc_isp_gen) { - case QLA_GEN_ISP2100: - case QLA_GEN_ISP2200: - switch (queue) { - case QLA_REQ_QUEUE_IN: - case QLA_REQ_QUEUE_OUT: - return (sc->sc_mbox_base + 8); - case QLA_RESP_QUEUE_IN: - case QLA_RESP_QUEUE_OUT: - return (sc->sc_mbox_base + 10); - } - break; + u_int16_t a, b, i; - case QLA_GEN_ISP23XX: - switch (queue) { - case QLA_REQ_QUEUE_IN: - return (QLA_REQ_IN); - case QLA_REQ_QUEUE_OUT: - return (QLA_REQ_OUT); - case QLA_RESP_QUEUE_IN: - return (QLA_RESP_IN); - case QLA_RESP_QUEUE_OUT: - return (QLA_RESP_OUT); - } - break; - } + do { + a = qla_read(sc, queue); + b = qla_read(sc, queue); - panic("unknown queue"); -} + if (a == b) + return (a); -u_int16_t -qla_read_queue_ptr(struct qla_softc *sc, enum qla_qptr queue) -{ - u_int16_t a, b, i; - switch (sc->sc_isp_gen) { - case QLA_GEN_ISP2100: - do { - a = qla_read(sc, qla_queue_reg(sc, queue)); - b = qla_read(sc, qla_queue_reg(sc, queue)); - } while (a != b && ++i < 1000); - if (i == 1000) - DPRINTF(QLA_D_INTR, "%s: queue ptr unstable\n", - DEVNAME(sc)); - return (a); + } while (++i < 1000); - default: - return (qla_read(sc, qla_queue_reg(sc, queue))); - } -} + DPRINTF(QLA_D_INTR, "%s: queue ptr unstable\n", + DEVNAME(sc)); -void -qla_write_queue_ptr(struct qla_softc *sc, enum qla_qptr queue, - u_int16_t value) -{ - qla_write(sc, qla_queue_reg(sc, queue), value); + return (a); } int @@ -1275,10 +1260,10 @@ qla_softreset(struct qla_softc *sc) qla_host_cmd(sc, QLA_HOST_CMD_RELEASE); /* reset queue pointers */ - qla_write_queue_ptr(sc, QLA_REQ_QUEUE_IN, 0); - qla_write_queue_ptr(sc, QLA_REQ_QUEUE_OUT, 0); - qla_write_queue_ptr(sc, QLA_RESP_QUEUE_IN, 0); - qla_write_queue_ptr(sc, QLA_RESP_QUEUE_OUT, 0); + qla_queue_write(sc, sc->sc_q->req_in, 0); + qla_queue_write(sc, sc->sc_q->req_out, 0); + qla_queue_write(sc, sc->sc_q->res_in, 0); + qla_queue_write(sc, sc->sc_q->res_out, 0); qla_set_ints(sc, 1); /* isp(4) sends QLA_HOST_CMD_BIOS here.. not documented? */ diff --git a/sys/dev/ic/qlavar.h b/sys/dev/ic/qlavar.h index 24ea2b14f7e..347abfea964 100644 --- a/sys/dev/ic/qlavar.h +++ b/sys/dev/ic/qlavar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: qlavar.h,v 1.3 2014/02/02 07:53:33 jmatthew Exp $ */ +/* $OpenBSD: qlavar.h,v 1.4 2014/02/19 13:41:23 dlg Exp $ */ /* * Copyright (c) 2013, 2014 Jonathan Matthew <jmatthew@openbsd.org> @@ -27,6 +27,8 @@ /* maximum number of segments allowed for in a single io */ #define QLA_MAX_SEGS 16 +struct qla_softc; + enum qla_isp_gen { QLA_GEN_ISP2100 = 1, QLA_GEN_ISP2200, @@ -41,12 +43,13 @@ enum qla_isp_type { QLA_ISP2322 }; -/* needed as <2300 use mailbox registers for queue pointers */ -enum qla_qptr { - QLA_REQ_QUEUE_IN, - QLA_REQ_QUEUE_OUT, - QLA_RESP_QUEUE_IN, - QLA_RESP_QUEUE_OUT +struct qla_queue_regs { + u_int16_t (*read)(struct qla_softc *, bus_size_t); + + bus_size_t req_in; + bus_size_t req_out; + bus_size_t res_in; + bus_size_t res_out; }; /* port database things */ @@ -125,7 +128,7 @@ struct qla_softc { bus_size_t sc_ios; bus_dma_tag_t sc_dmat; - struct scsi_link sc_link; + struct scsi_link sc_link; struct scsibus_softc *sc_scsibus; @@ -136,6 +139,8 @@ struct qla_softc { int sc_fabric; int sc_2k_logins; + const struct qla_queue_regs *sc_q; + int sc_mbox_base; u_int16_t sc_mbox[12]; int sc_mbox_pending; |