Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/ic - add 64 bit fifo support



details:   https://anonhg.NetBSD.org/src/rev/ef023cf5737e
branches:  trunk
changeset: 790454:ef023cf5737e
user:      christos <christos%NetBSD.org@localhost>
date:      Sat Oct 12 16:52:21 2013 +0000

description:
- add 64 bit fifo support
- handle fibrilation better

diffstat:

 sys/dev/ic/ciss.c    |  118 +++++++++++++++++++++++++++++++++++++++++---------
 sys/dev/ic/cissreg.h |   25 +++++++---
 sys/dev/ic/cissvar.h |    7 +-
 3 files changed, 118 insertions(+), 32 deletions(-)

diffs (truncated from 338 to 300 lines):

diff -r fc2e29884f5e -r ef023cf5737e sys/dev/ic/ciss.c
--- a/sys/dev/ic/ciss.c Sat Oct 12 16:49:00 2013 +0000
+++ b/sys/dev/ic/ciss.c Sat Oct 12 16:52:21 2013 +0000
@@ -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 <sys/cdefs.h>
-__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 @@
        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 @@
 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 @@
        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 @@
        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 @@
                                        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 @@
 
        switch ((rv = le16toh(err->cmd_stat))) {
        case CISS_ERR_OK:
+               rv = 0;
                break;
 
        case CISS_ERR_INVCMD:
@@ -657,10 +700,12 @@
                        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 @@
                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 @@
                                    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 @@
                                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 @@
                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 @@
                        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 @@
        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 @@
 
        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 -r fc2e29884f5e -r ef023cf5737e sys/dev/ic/cissreg.h
--- a/sys/dev/ic/cissreg.h      Sat Oct 12 16:49:00 2013 +0000
+++ b/sys/dev/ic/cissreg.h      Sat Oct 12 16:52:21 2013 +0000
@@ -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 @@
 #define        CISS_SIGNATURE  (*(const u_int32_t *)"CISS")
        u_int32_t       version;
        u_int32_t       methods;
-#define        CISS_METH_READY 0x0001



Home | Main Index | Thread Index | Old Index