summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/ic/twe.c40
-rw-r--r--sys/dev/ic/twereg.h78
2 files changed, 94 insertions, 24 deletions
diff --git a/sys/dev/ic/twe.c b/sys/dev/ic/twe.c
index a10cbc03a8f..123434dcea0 100644
--- a/sys/dev/ic/twe.c
+++ b/sys/dev/ic/twe.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: twe.c,v 1.5 2000/11/08 20:44:56 mickey Exp $ */
+/* $OpenBSD: twe.c,v 1.6 2001/01/07 20:27:46 mickey Exp $ */
/*
* Copyright (c) 2000 Michael Shalayeff. All rights reserved.
@@ -86,7 +86,6 @@ static __inline void twe_put_ccb __P((struct twe_ccb *ccb));
void twe_dispose __P((struct twe_softc *sc));
int twe_cmd __P((struct twe_ccb *ccb, int flags, int wait));
int twe_start __P((struct twe_ccb *ccb, int wait));
-void twe_exec_cmd __P((void *v));
int twe_complete __P((struct twe_ccb *ccb));
int twe_done __P((struct twe_softc *sc, int idx));
void twe_copy_internal_data __P((struct scsi_xfer *xs, void *v, size_t size));
@@ -240,7 +239,7 @@ twe_attach(sc)
cmd = ccb->ccb_cmd;
cmd->cmd_unit_host = TWE_UNITHOST(0, 0);
cmd->cmd_op = TWE_CMD_GPARAM;
- cmd->cmd_count = 1;
+ cmd->cmd_param.count = 1;
pb->table_id = TWE_PARAM_AEN;
pb->param_id = 2;
@@ -308,7 +307,7 @@ twe_attach(sc)
cmd = ccb->ccb_cmd;
cmd->cmd_unit_host = TWE_UNITHOST(0, 0);
cmd->cmd_op = TWE_CMD_GPARAM;
- cmd->cmd_count = 1;
+ cmd->cmd_param.count = 1;
pb->table_id = TWE_PARAM_UC;
pb->param_id = TWE_PARAM_UC;
@@ -339,7 +338,7 @@ twe_attach(sc)
cmd = ccb->ccb_cmd;
cmd->cmd_unit_host = TWE_UNITHOST(0, 0);
cmd->cmd_op = TWE_CMD_GPARAM;
- cmd->cmd_count = 1;
+ cmd->cmd_param.count = 1;
cap->table_id = TWE_PARAM_UI + i;
cap->param_id = 4;
@@ -487,7 +486,6 @@ twe_start(ccb, wait)
int i;
cmd->cmd_op = htole16(cmd->cmd_op);
- cmd->cmd_count = htole16(cmd->cmd_count);
if (!wait) {
@@ -567,14 +565,13 @@ twe_done(sc, idx)
struct twe_softc *sc;
int idx;
{
- struct scsi_xfer *xs;
struct twe_ccb *ccb = &sc->sc_ccbs[idx];
struct twe_cmd *cmd = ccb->ccb_cmd;
+ struct scsi_xfer *xs = ccb->ccb_xs;
+ twe_lock_t lock;
TWE_DPRINTF(TWE_D_CMD, ("done(%d) ", idx));
- xs = ccb->ccb_xs;
-
if (ccb->ccb_state != TWE_CCB_QUEUED) {
printf("%s: unqueued ccb %d ready\n",
sc->sc_dev.dv_xname, idx);
@@ -616,8 +613,10 @@ twe_done(sc, idx)
ccb->ccb_realdata = NULL;
}
+ lock = TWE_LOCK_TWE(sc);
TAILQ_REMOVE(&sc->sc_ccbq, ccb, ccb_link);
twe_put_ccb(ccb);
+ TWE_UNLOCK_TWE(sc, lock);
if (xs) {
xs->resid = 0;
@@ -647,7 +646,7 @@ twe_copy_internal_data(xs, v, size)
TWE_DPRINTF(TWE_D_MISC, ("twe_copy_internal_data "));
if (!xs->datalen)
- printf("uio move not yet supported\n");
+ printf("uio move is not yet supported\n");
else {
copy_cnt = MIN(size, xs->datalen);
bcopy(v, xs->data, copy_cnt);
@@ -674,7 +673,7 @@ twe_scsi_cmd(xs)
u_int32_t blockno, blockcnt;
struct scsi_rw *rw;
struct scsi_rw_big *rwb;
- int error, op;
+ int error, op, flags;
twe_lock_t lock;
@@ -781,6 +780,7 @@ twe_scsi_cmd(xs)
case SYNCHRONIZE_CACHE:
lock = TWE_LOCK_TWE(sc);
+ flags = 0;
if (xs->cmd->opcode != SYNCHRONIZE_CACHE) {
/* A read or write operation. */
if (xs->cmdlen == 6) {
@@ -792,6 +792,10 @@ twe_scsi_cmd(xs)
rwb = (struct scsi_rw_big *)xs->cmd;
blockno = _4btol(rwb->addr);
blockcnt = _2btol(rwb->length);
+ /* reflect DPO & FUA flags */
+ if (xs->cmd->opcode == WRITE_BIG &&
+ rwb->byte2 & 0x18)
+ flags = TWE_FLAGS_CACHEDISABLE;
}
if (blockno >= sc->sc_hdr[target].hd_size ||
blockno + blockcnt > sc->sc_hdr[target].hd_size) {
@@ -799,8 +803,8 @@ twe_scsi_cmd(xs)
printf("%s: out of bounds %u-%u >= %u\n",
sc->sc_dev.dv_xname, blockno, blockcnt,
sc->sc_hdr[target].hd_size);
- scsi_done(xs);
xs->error = XS_DRIVER_STUFFUP;
+ scsi_done(xs);
return (COMPLETE);
}
}
@@ -814,8 +818,8 @@ twe_scsi_cmd(xs)
}
if ((ccb = twe_get_ccb(sc)) == NULL) {
- scsi_done(xs);
xs->error = XS_DRIVER_STUFFUP;
+ scsi_done(xs);
return (COMPLETE);
}
@@ -826,7 +830,8 @@ twe_scsi_cmd(xs)
cmd = ccb->ccb_cmd;
cmd->cmd_unit_host = TWE_UNITHOST(target, 0); /* XXX why 0? */
cmd->cmd_op = op;
- cmd->cmd_count = blockcnt;
+ cmd->cmd_flags = flags;
+ cmd->cmd_io.count = htole16(blockcnt);
cmd->cmd_io.lba = blockno;
if ((error = twe_cmd(ccb, ((xs->flags & SCSI_NOSLEEP)?
@@ -838,8 +843,8 @@ twe_scsi_cmd(xs)
xs->error = XS_TIMEOUT;
return (TRY_AGAIN_LATER);
} else {
- scsi_done(xs);
xs->error = XS_DRIVER_STUFFUP;
+ scsi_done(xs);
return (COMPLETE);
}
}
@@ -912,7 +917,6 @@ twe_intr(v)
if (status & TWE_STAT_RDYI) {
- lock = TWE_LOCK_TWE(sc);
while (!(status & TWE_STAT_RQE)) {
u_int32_t ready;
@@ -933,7 +937,6 @@ twe_intr(v)
TWE_DPRINTF(TWE_D_INTR, ("twe_intr stat=%b ",
status & TWE_STAT_FLAGS, TWE_STAT_BITS));
}
- TWE_UNLOCK_TWE(sc, lock);
}
if (status & TWE_STAT_ATTNI) {
@@ -963,7 +966,8 @@ twe_intr(v)
cmd = ccb->ccb_cmd;
cmd->cmd_unit_host = TWE_UNITHOST(0, 0);
cmd->cmd_op = TWE_CMD_GPARAM;
- cmd->cmd_count = 1;
+ cmd->cmd_flags = 0;
+ cmd->cmd_param.count = 1;
pb->table_id = TWE_PARAM_AEN;
pb->param_id = 2;
diff --git a/sys/dev/ic/twereg.h b/sys/dev/ic/twereg.h
index ba2968d85c6..8fc16a3cbfc 100644
--- a/sys/dev/ic/twereg.h
+++ b/sys/dev/ic/twereg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: twereg.h,v 1.3 2000/11/06 23:56:18 mickey Exp $ */
+/* $OpenBSD: twereg.h,v 1.4 2001/01/07 20:27:46 mickey Exp $ */
/*
* Copyright (c) 2000 Michael Shalayeff
@@ -78,6 +78,7 @@
#define TWE_STAT_FLAGS 0x00fff000 /* mask out other stuff */
#define TWE_STAT_BITS "\020\015cqr\016cpurdy\017rqe\20cqf" \
"\021rdyi\022cmdi\023attni\024hosti\025pciabr\026cpuerr\027queuee\030pcipar"
+
#define TWE_COMMANDQUEUE 0x08
/*
* the segs offset is encoded into upper 3 bits of the opcode.
@@ -88,18 +89,50 @@
#define TWE_CMD_INIT 0x0301
#define TWE_CMD_READ 0x0362
#define TWE_CMD_WRITE 0x0363
-#define TWE_CMD_VERIFY 0x0364
+#define TWE_CMD_RDVRFY 0x0364
+#define TWE_CMD_VERIFY 0x0365
+#define TWE_CMD_ZRFUNIT 0x0208
+#define TWE_CMD_RPLUNIT 0x0209
+#define TWE_CMD_HOTSWAP 0x020a
+#define TWE_CMD_SETATA 0x020c
+#define TWE_CMD_FLUSH 0x020e
+#define TWE_CMD_ABORT 0x020f
+#define TWE_CMD_QSTAT 0x0210
#define TWE_CMD_GPARAM 0x0252
#define TWE_CMD_SPARAM 0x0253
+#define TWE_CMD_NEWUNIT 0x0214
+#define TWE_CMD_DELUNIT 0x0215
+#define TWE_CMD_RBLUNIT 0x0217 /* rebuild */
#define TWE_CMD_SECINF 0x021a
#define TWE_CMD_AEN 0x021c
+#define TWE_CMD_CMDPK 0x021d
#define TWE_READYQUEUE 0x0c
#define TWE_READYID(u) (((u) >> 4) & 0xff)
+/*
+ * From 3ware's documentation:
+ *
+ * All parameters maintained by the controller are grouped into related
+ * tables. Tables are are accessed indirectly via get and set parameter
+ * commands. To access a specific parameter in a table, the table ID and
+ * parameter index are used to uniquely identify a parameter. Table
+ * 0xffff is the directory table and provides a list of the table IDs and
+ * sizes of all other tables. Index zero in each table specifies the
+ * entire table, and index one specifies the size of the table. An entire
+ * table can be read or set by using index zero.
+ */
+
/* get/set param table ids */
+#define TWE_PARAM_ALL 0x000 /* everything */
+#define TWE_PARAM_DSUM 0x002 /* drive summary */
#define TWE_PARAM_UC 0x003 /* unit config */
+#define TWE_PARAM_DC 0x200 /* + 15 -- drive config (doc says 0x100) */
#define TWE_PARAM_UI 0x300 /* + 16 -- unit information */
#define TWE_PARAM_AEN 0x401
+#define TWE_PARAM_VER 0x402 /* version info */
+#define TWE_PARAM_CTRL 0x403 /* controller info */
+#define TWE_PARAM_FTRS 0x404 /* features */
+#define TWE_PARAM_DIR 0xffff /* param table directory */
#define TWE_AEN_QEMPTY 0x0000
#define TWE_AEN_SRST 0x0001
@@ -111,13 +144,15 @@
#define TWE_AEN_QFULL 0x00ff
#define TWE_AEN_TUN 0x0015 /* table undefined */
+#pragma pack(1)
+
/* struct definitions */
struct twe_param {
u_int16_t table_id;
u_int8_t param_id;
u_int8_t param_size;
u_int8_t data[1];
-} __attribute__ ((packed));
+};
struct twe_segs {
u_int32_t twes_addr;
@@ -132,22 +167,53 @@ struct twe_cmd {
u_int8_t cmd_status;
u_int8_t cmd_flags;
#define TWE_FLAGS_CACHEDISABLE 0x01
- u_int16_t cmd_count;
union {
struct {
+ u_int16_t count;
u_int32_t lba;
struct twe_segs segs[TWE_MAXOFFSETS];
u_int32_t pad;
} _cmd_io;
#define cmd_io _._cmd_io
struct {
+ u_int16_t count;
struct twe_segs segs[TWE_MAXOFFSETS];
} _cmd_param;
#define cmd_param _._cmd_param
struct {
- u_int32_t rdy_q_ptr;
+ u_int16_t msgcr;
+ u_int32_t rdy_q_ptr;
} _cmd_init;
#define cmd_init _._cmd_init
+ struct {
+ u_int8_t action;
+#define TWE_HSWAP_REMOVE 0
+#define TWE_HSWAP_ADDCBOD 1
+#define TWE_HSWAP_ADDSPARE 2
+ u_int8_t port;
+ } _cmd_aport;
+#define cmd_hswap _._cmd_hswap
+ struct {
+ u_int8_t feature;
+#define TWE_ATA_WCE 0x02
+#define TWE_ATA_NWCE 0x82
+ u_int8_t mode;
+ u_int16_t units;
+ u_int16_t persist;
+ } _cmd_ata;
+#define cmd_ata _._cmd_ata
+ u_int16_t cmd_status;
+ struct {
+ u_int8_t action;
+#define TWE_REBUILD_NOP 0
+#define TWE_REBUILD_STOP 2
+#define TWE_REBUILD_START 4
+#define TWE_REBUILD_STARTU 5
+#define TWE_REBUILD_CS 0x80
+ u_int8_t subunit; /* raid10 lu rebuild */
+ } _cmd_rebuild;
+#define cmd_rebuild _._cmd_rebuild
} _;
-} __attribute__ ((packed)); /* 512 bytes */
+}; /* 512 bytes */
+#pragma pack()