diff --git a/sys/dev/ic/ciss.c b/sys/dev/ic/ciss.c index e10295793ba3..bd7141eb0a06 100644 --- a/sys/dev/ic/ciss.c +++ b/sys/dev/ic/ciss.c @@ -1,8 +1,8 @@ -/* $NetBSD: ciss.c,v 1.29 2012/10/27 17:18:19 chs Exp $ */ -/* $OpenBSD: ciss.c,v 1.14 2006/03/13 16:02:23 mickey Exp $ */ +/* $NetBSD: ciss.c,v 1.30 2013/10/12 16:52:21 christos Exp $ */ +/* $OpenBSD: ciss.c,v 1.68 2013/05/30 16:15:02 deraadt Exp $ */ /* - * Copyright (c) 2005 Michael Shalayeff + * Copyright (c) 2005,2006 Michael Shalayeff * All rights reserved. * * Permission to use, copy, modify, and distribute this software for any @@ -19,7 +19,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ciss.c,v 1.29 2012/10/27 17:18:19 chs Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ciss.c,v 1.30 2013/10/12 16:52:21 christos Exp $"); #include "bio.h" @@ -323,10 +323,16 @@ ciss_attach(struct ciss_softc *sc) sc->maxunits = inq->numld; sc->nbus = inq->nscsi_bus; sc->ndrives = inq->buswidth ? inq->buswidth : 256; - printf(": %d LD%s, HW rev %d, FW %4.4s/%4.4s\n", + printf(": %d LD%s, HW rev %d, FW %4.4s/%4.4s", inq->numld, inq->numld == 1? "" : "s", inq->hw_rev, inq->fw_running, inq->fw_stored); + if (sc->cfg.methods & CISS_METH_FIFO64) + printf(", 64bit fifo"); + else if (sc->cfg.methods & CISS_METH_FIFO64_RRO) + printf(", 64bit fifo rro"); + printf("\n"); + mutex_exit(&sc->sc_mutex_scratch); callout_init(&sc->sc_hb, 0); @@ -423,7 +429,7 @@ ciss_shutdown(void *v) static void cissminphys(struct buf *bp) { -#if 0 /* TOSO */ +#if 0 /* TODO */ #define CISS_MAXFER (PAGE_SIZE * (sc->maxsg + 1)) if (bp->b_bcount > CISS_MAXFER) bp->b_bcount = CISS_MAXFER; @@ -445,6 +451,7 @@ ciss_cmd(struct ciss_ccb *ccb, int flags, int wait) struct ciss_ccb *ccb1; bus_dmamap_t dmap = ccb->ccb_dmamap; u_int32_t id; + u_int64_t addr; int i, tohz, error = 0; if (ccb->ccb_state != CISS_CCB_READY) { @@ -505,7 +512,19 @@ ciss_cmd(struct ciss_ccb *ccb, int flags, int wait) mutex_exit(&sc->sc_mutex); ccb->ccb_state = CISS_CCB_ONQ; CISS_DPRINTF(CISS_D_CMD, ("submit=0x%x ", cmd->id)); - bus_space_write_4(sc->sc_iot, sc->sc_ioh, CISS_INQ, ccb->ccb_cmdpa); + if (sc->cfg.methods & (CISS_METH_FIFO64|CISS_METH_FIFO64_RRO)) { + /* + * Write the upper 32bits immediately before the lower + * 32bits and set bit 63 to indicate 64bit FIFO mode. + */ + addr = (u_int64_t)ccb->ccb_cmdpa; + bus_space_write_4(sc->sc_iot, sc->sc_ioh, CISS_INQ64_HI, + (addr >> 32) | 0x80000000); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, CISS_INQ64_LO, + addr & 0x00000000ffffffffULL); + } else + bus_space_write_4(sc->sc_iot, sc->sc_ioh, CISS_INQ, + ccb->ccb_cmdpa); if (wait & XS_CTL_POLL) { int etick; @@ -543,21 +562,44 @@ ciss_cmd(struct ciss_ccb *ccb, int flags, int wait) continue; } - if ((id = bus_space_read_4(sc->sc_iot, sc->sc_ioh, - CISS_OUTQ)) == 0xffffffff) { - CISS_DPRINTF(CISS_D_CMD, ("Q")); - continue; + if (sc->cfg.methods & CISS_METH_FIFO64) { + if (bus_space_read_4(sc->sc_iot, + sc->sc_ioh, + CISS_OUTQ64_HI) == 0xffffffff) { + CISS_DPRINTF(CISS_D_CMD, ("Q")); + continue; + } + id = bus_space_read_4(sc->sc_iot, + sc->sc_ioh, CISS_OUTQ64_LO); + } else if (sc->cfg.methods & + CISS_METH_FIFO64_RRO) { + id = bus_space_read_4(sc->sc_iot, + sc->sc_ioh, CISS_OUTQ64_LO); + if (id == 0xffffffff) { + CISS_DPRINTF(CISS_D_CMD, ("Q")); + continue; + } + (void)bus_space_read_4(sc->sc_iot, + sc->sc_ioh, CISS_OUTQ64_HI); + } else { + id = bus_space_read_4(sc->sc_iot, + sc->sc_ioh, CISS_OUTQ); + if (id == 0xffffffff) { + CISS_DPRINTF(CISS_D_CMD, ("Q")); + continue; + } } CISS_DPRINTF(CISS_D_CMD, ("got=0x%x ", id)); ccb1 = (struct ciss_ccb *) ((char *)sc->ccbs + (id >> 2) * sc->ccblen); ccb1->ccb_cmd.id = htole32(id); + ccb1->ccb_cmd.id_hi = htole32(0); } error = ciss_done(ccb1); if (ccb1 == ccb) - break; + return error; } /* if never got a chance to be done above... */ @@ -640,6 +682,7 @@ ciss_error(struct ciss_ccb *ccb) switch ((rv = le16toh(err->cmd_stat))) { case CISS_ERR_OK: + rv = 0; break; case CISS_ERR_INVCMD: @@ -657,10 +700,12 @@ ciss_error(struct ciss_ccb *ccb) xs->sense.scsi_sense.ascq = 0x0; xs->error = XS_SENSE; } + rv = EIO; break; case CISS_ERR_TMO: xs->error = XS_TIMEOUT; + rv = ETIMEDOUT; break; case CISS_ERR_UNRUN: @@ -668,6 +713,7 @@ ciss_error(struct ciss_ccb *ccb) xs->resid = le32toh(err->resid); CISS_DPRINTF(CISS_D_CMD, (" underrun resid=0x%x ", xs->resid)); + rv = EIO; break; default: if (xs) { @@ -679,10 +725,12 @@ ciss_error(struct ciss_ccb *ccb) sizeof(xs->sense)); CISS_DPRINTF(CISS_D_CMD, (" sense=%02x %02x %02x %02x ", err->sense[0], err->sense[1], err->sense[2], err->sense[3])); + rv = EIO; break; case XS_BUSY: xs->error = XS_BUSY; + rv = EBUSY; break; default: @@ -693,10 +741,12 @@ ciss_error(struct ciss_ccb *ccb) printf("ciss driver stuffup in %s:%d: %s()\n", __FILE__, __LINE__, __func__); xs->error = XS_DRIVER_STUFFUP; + rv = EIO; break; } xs->resid = le32toh(err->resid); - } + } else + rv = EIO; } ccb->ccb_cmd.id &= htole32(~3); @@ -1031,9 +1081,9 @@ ciss_scsi_cmd(struct scsipi_channel *chan, scsipi_adapter_req_t req, if (xs->cmdlen > CISS_MAX_CDB) { CISS_DPRINTF(CISS_D_CMD, ("CDB too big %p ", xs)); memset(&xs->sense, 0, sizeof(xs->sense)); + xs->error = XS_SENSE; printf("ciss driver stuffup in %s:%d: %s()\n", __FILE__, __LINE__, __func__); - xs->error = XS_DRIVER_STUFFUP; scsipi_done(xs); break; } @@ -1056,7 +1106,7 @@ ciss_scsi_cmd(struct scsipi_channel *chan, scsipi_adapter_req_t req, cmd->flags |= CISS_CDB_IN; else if (xs->xs_control & XS_CTL_DATA_OUT) cmd->flags |= CISS_CDB_OUT; - cmd->tmo = xs->timeout < 1000? 1 : xs->timeout / 1000; + cmd->tmo = htole16(xs->timeout < 1000? 1 : xs->timeout / 1000); memset(&cmd->cdb[0], 0, sizeof(cmd->cdb)); memcpy(&cmd->cdb[0], xs->cmd, CISS_MAX_CDB); CISS_DPRINTF(CISS_D_CMD, ("cmd=%02x %02x %02x %02x %02x %02x ", @@ -1096,18 +1146,29 @@ ciss_intr(void *v) struct ciss_softc *sc = v; struct ciss_ccb *ccb; u_int32_t id; + bus_size_t reg; int hit = 0; CISS_DPRINTF(CISS_D_INTR, ("intr ")); - if (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_ISR) & sc->iem)) - return 0; - - while ((id = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_OUTQ)) != + if (sc->cfg.methods & CISS_METH_FIFO64) + reg = CISS_OUTQ64_HI; + else if (sc->cfg.methods & CISS_METH_FIFO64_RRO) + reg = CISS_OUTQ64_LO; + else + reg = CISS_OUTQ; + while ((id = bus_space_read_4(sc->sc_iot, sc->sc_ioh, reg)) != 0xffffffff) { + if (reg == CISS_OUTQ64_HI) + id = bus_space_read_4(sc->sc_iot, sc->sc_ioh, + CISS_OUTQ64_LO); + else if (reg == CISS_OUTQ64_LO) + (void)bus_space_read_4(sc->sc_iot, sc->sc_ioh, + CISS_OUTQ64_HI); ccb = (struct ciss_ccb *) ((char *)sc->ccbs + (id >> 2) * sc->ccblen); ccb->ccb_cmd.id = htole32(id); + ccb->ccb_cmd.id_hi = htole32(0); /* ignore the upper 32bits */ if (ccb->ccb_state == CISS_CCB_POLL) { ccb->ccb_state = CISS_CCB_ONQ; mutex_enter(&sc->sc_mutex); @@ -1131,10 +1192,23 @@ ciss_heartbeat(void *v) hb = bus_space_read_4(sc->sc_iot, sc->cfg_ioh, sc->cfgoff + offsetof(struct ciss_config, heartbeat)); - if (hb == sc->heartbeat) - panic("ciss: dead"); /* XX reset! */ - else + if (hb == sc->heartbeat) { + sc->fibrillation++; + CISS_DPRINTF(CISS_D_ERR, ("%s: fibrillation #%d (value=%d)\n", + device_xname(sc->sc_dev), sc->fibrillation, hb)); + if (sc->fibrillation >= 11) { + /* No heartbeat for 33 seconds */ + panic("%s: dead", device_xname(sc->sc_dev)); /* XXX reset! */ + } + } else { sc->heartbeat = hb; + if (sc->fibrillation) { + CISS_DPRINTF(CISS_D_ERR, ("%s: " + "fibrillation ended (value=%d)\n", + device_xname(sc->sc_dev), hb)); + } + sc->fibrillation = 0; + } callout_schedule(&sc->sc_hb, hz * 3); } diff --git a/sys/dev/ic/cissreg.h b/sys/dev/ic/cissreg.h index 04b91ff4fa91..df2e49df72e4 100644 --- a/sys/dev/ic/cissreg.h +++ b/sys/dev/ic/cissreg.h @@ -1,8 +1,8 @@ -/* $NetBSD: cissreg.h,v 1.3 2008/10/18 18:53:20 bouyer Exp $ */ -/* $OpenBSD: cissreg.h,v 1.4 2005/12/13 15:55:59 brad Exp $ */ +/* $NetBSD: cissreg.h,v 1.4 2013/10/12 16:52:21 christos Exp $ */ +/* $OpenBSD: cissreg.h,v 1.11 2010/06/03 01:02:13 dlg Exp $ */ /* - * Copyright (c) 2005 Michael Shalayeff + * Copyright (c) 2005,2006 Michael Shalayeff * All rights reserved. * * Permission to use, copy, modify, and distribute this software for any @@ -31,6 +31,12 @@ #define CISS_CFG_BAR 0xb4 #define CISS_CFG_OFF 0xb8 +/* 64bit FIFO mode input/output post queues */ +#define CISS_INQ64_LO 0xc0 +#define CISS_INQ64_HI 0xc4 +#define CISS_OUTQ64_LO 0xc8 +#define CISS_OUTQ64_HI 0xcc + #define CISS_DRVMAP_SIZE (128 / 8) #define CISS_CMD_CTRL_GET 0x26 @@ -65,10 +71,15 @@ struct ciss_config { #define CISS_SIGNATURE (*(const u_int32_t *)"CISS") u_int32_t version; u_int32_t methods; -#define CISS_METH_READY 0x0001 -#define CISS_METH_SIMPL 0x0002 -#define CISS_METH_PERF 0x0004 -#define CISS_METH_EMQ 0x0008 +#define CISS_METH_READY 0x00000001 /* indicate to accept commands */ +#define CISS_METH_SIMPL 0x00000002 /* simple mode */ +#define CISS_METH_PERF 0x00000004 /* performant mode */ +#define CISS_METH_EMQ 0x00000008 /* MEMQ method */ +#define CISS_METH_BIT63 0x08000000 /* address bit 63 is valid */ +#define CISS_METH_FIFO64_RRO 0x10000000 /* 64bit FIFO reverse read order */ +#define CISS_METH_SHORT_TAG 0x20000000 /* short 4 byte tag support */ +#define CISS_METH_MSIX 0x40000000 /* directed MSI-X support */ +#define CISS_METH_FIFO64 0x80000000 /* 64bit FIFO support */ u_int32_t amethod; u_int32_t rmethod; u_int32_t paddr_lim; diff --git a/sys/dev/ic/cissvar.h b/sys/dev/ic/cissvar.h index 868e78adccde..fefebc80a0c6 100644 --- a/sys/dev/ic/cissvar.h +++ b/sys/dev/ic/cissvar.h @@ -1,8 +1,8 @@ -/* $NetBSD: cissvar.h,v 1.5 2012/10/27 17:18:19 chs Exp $ */ -/* $OpenBSD: cissvar.h,v 1.2 2005/09/07 04:00:16 mickey Exp $ */ +/* $NetBSD: cissvar.h,v 1.6 2013/10/12 16:52:21 christos Exp $ */ +/* $OpenBSD: cissvar.h,v 1.15 2013/05/30 16:15:02 deraadt Exp $ */ /* - * Copyright (c) 2005 Michael Shalayeff + * Copyright (c) 2005,2006 Michael Shalayeff * All rights reserved. * * Permission to use, copy, modify, and distribute this software for any @@ -63,6 +63,7 @@ struct ciss_softc { bus_space_handle_t cfg_ioh; + int fibrillation; struct ciss_config cfg; int cfgoff; u_int32_t iem;