diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2009-04-29 08:24:27 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2009-04-29 08:24:27 +0000 |
commit | b6386bc64158b986b64606b3027e51c591c9006b (patch) | |
tree | 7ff0f0c1e7dbb28595d233ca8559ed3ef74267e1 /sys/dev/ic | |
parent | 934c8447e8cb3f196b08c9659c19b106bb18a9c7 (diff) |
Implement the 64bit FIFO modes (based on the OpenCISS Specification
1.06). It is required to run ciss(4) with amd64 bigmem, even when
using the iommu.
Tested by many on 32bit and 64bit low- and bigmem systems
With feedback from mk@ deraadt@
Diffstat (limited to 'sys/dev/ic')
-rw-r--r-- | sys/dev/ic/ciss.c | 70 | ||||
-rw-r--r-- | sys/dev/ic/cissreg.h | 23 |
2 files changed, 78 insertions, 15 deletions
diff --git a/sys/dev/ic/ciss.c b/sys/dev/ic/ciss.c index 6fb9f8fd970..7fb0f4f6221 100644 --- a/sys/dev/ic/ciss.c +++ b/sys/dev/ic/ciss.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ciss.c,v 1.33 2009/02/16 21:19:06 miod Exp $ */ +/* $OpenBSD: ciss.c,v 1.34 2009/04/29 08:24:26 reyk Exp $ */ /* * Copyright (c) 2005,2006 Michael Shalayeff @@ -332,9 +332,14 @@ 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"); CISS_UNLOCK_SCRATCH(sc, lock); @@ -481,6 +486,7 @@ ciss_cmd(struct ciss_ccb *ccb, int flags, int wait) struct ciss_cmd *cmd = &ccb->ccb_cmd; struct ciss_ccb *ccb1; bus_dmamap_t dmap = ccb->ccb_dmamap; + u_int64_t addr; u_int32_t id; int i, tohz, error = 0; @@ -538,7 +544,18 @@ ciss_cmd(struct ciss_ccb *ccb, int flags, int wait) TAILQ_INSERT_TAIL(&sc->sc_ccbq, ccb, ccb_link); ccb->ccb_state = CISS_CCB_ONQ; CISS_DPRINTF(CISS_D_CMD, ("submit=0x%x ", cmd->id)); - bus_space_write_4(sc->iot, 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->iot, sc->ioh, CISS_INQ64_HI, + (addr >> 32) | 0x80000000); + bus_space_write_4(sc->iot, sc->ioh, CISS_INQ64_LO, + addr & 0x00000000ffffffffULL); + } else + bus_space_write_4(sc->iot, sc->ioh, CISS_INQ, ccb->ccb_cmdpa); if (wait & SCSI_POLL) { struct timeval tv; @@ -576,15 +593,37 @@ ciss_cmd(struct ciss_ccb *ccb, int flags, int wait) continue; } - if ((id = bus_space_read_4(sc->iot, 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->iot, sc->ioh, + CISS_OUTQ64_HI) == 0xffffffff) { + CISS_DPRINTF(CISS_D_CMD, ("Q")); + continue; + } + id = bus_space_read_4(sc->iot, sc->ioh, + CISS_OUTQ64_LO); + } else if (sc->cfg.methods & + CISS_METH_FIFO64_RRO) { + id = bus_space_read_4(sc->iot, sc->ioh, + CISS_OUTQ64_LO); + if (id == 0xffffffff) { + CISS_DPRINTF(CISS_D_CMD, ("Q")); + continue; + } + (void)bus_space_read_4(sc->iot, + sc->ioh, CISS_OUTQ64_HI); + } else { + id = bus_space_read_4(sc->iot, sc->ioh, + CISS_OUTQ); + if (id == 0xffffffff) { + CISS_DPRINTF(CISS_D_CMD, ("Q")); + continue; + } } CISS_DPRINTF(CISS_D_CMD, ("got=0x%x ", id)); ccb1 = sc->ccbs + (id >> 2) * sc->ccblen; ccb1->ccb_cmd.id = htole32(id); + ccb1->ccb_cmd.id_hi = htole32(0); } error = ciss_done(ccb1); @@ -940,6 +979,7 @@ ciss_intr(void *v) struct ciss_softc *sc = v; struct ciss_ccb *ccb; ciss_lock_t lock; + bus_size_t reg; u_int32_t id; int hit = 0; @@ -949,11 +989,23 @@ ciss_intr(void *v) return 0; lock = CISS_LOCK(sc); - while ((id = bus_space_read_4(sc->iot, sc->ioh, CISS_OUTQ)) != - 0xffffffff) { + 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->iot, sc->ioh, reg)) != 0xffffffff) { + if (reg == CISS_OUTQ64_HI) + id = bus_space_read_4(sc->iot, sc->ioh, + CISS_OUTQ64_LO); + else if (reg == CISS_OUTQ64_LO) + (void)bus_space_read_4(sc->iot, sc->ioh, + CISS_OUTQ64_HI); ccb = 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; wakeup(ccb); diff --git a/sys/dev/ic/cissreg.h b/sys/dev/ic/cissreg.h index 2ffe9dc4ee3..5f6a5e5c0b1 100644 --- a/sys/dev/ic/cissreg.h +++ b/sys/dev/ic/cissreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cissreg.h,v 1.9 2007/11/26 19:13:22 dlg Exp $ */ +/* $OpenBSD: cissreg.h,v 1.10 2009/04/29 08:24:26 reyk Exp $ */ /* * Copyright (c) 2005,2006 Michael Shalayeff @@ -30,6 +30,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 @@ -64,10 +70,15 @@ struct ciss_config { #define CISS_SIGNATURE (*(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; @@ -465,7 +476,7 @@ struct ciss_error { struct ciss_ccb { TAILQ_ENTRY(ciss_ccb) ccb_link; struct ciss_softc *ccb_sc; - paddr_t ccb_cmdpa; + u_int64_t ccb_cmdpa; enum { CISS_CCB_FREE = 0x01, CISS_CCB_READY = 0x02, |