Module Name:    src
Committed By:   christos
Date:           Sat Oct 12 16:52:21 UTC 2013

Modified Files:
        src/sys/dev/ic: ciss.c cissreg.h cissvar.h

Log Message:
- add 64 bit fifo support
- handle fibrilation better


To generate a diff of this commit:
cvs rdiff -u -r1.29 -r1.30 src/sys/dev/ic/ciss.c
cvs rdiff -u -r1.3 -r1.4 src/sys/dev/ic/cissreg.h
cvs rdiff -u -r1.5 -r1.6 src/sys/dev/ic/cissvar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/ic/ciss.c
diff -u src/sys/dev/ic/ciss.c:1.29 src/sys/dev/ic/ciss.c:1.30
--- src/sys/dev/ic/ciss.c:1.29	Sat Oct 27 13:18:19 2012
+++ src/sys/dev/ic/ciss.c	Sat Oct 12 12:52:21 2013
@@ -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 @@ 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
 	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
 	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
 					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 *cha
 		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 *cha
 			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);
 }

Index: src/sys/dev/ic/cissreg.h
diff -u src/sys/dev/ic/cissreg.h:1.3 src/sys/dev/ic/cissreg.h:1.4
--- src/sys/dev/ic/cissreg.h:1.3	Sat Oct 18 14:53:20 2008
+++ src/sys/dev/ic/cissreg.h	Sat Oct 12 12:52:21 2013
@@ -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;

Index: src/sys/dev/ic/cissvar.h
diff -u src/sys/dev/ic/cissvar.h:1.5 src/sys/dev/ic/cissvar.h:1.6
--- src/sys/dev/ic/cissvar.h:1.5	Sat Oct 27 13:18:19 2012
+++ src/sys/dev/ic/cissvar.h	Sat Oct 12 12:52:21 2013
@@ -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;

Reply via email to