summaryrefslogtreecommitdiffstats
path: root/sys/dev/mlx
diff options
context:
space:
mode:
authormsmith <msmith@FreeBSD.org>1999-10-14 02:54:06 +0000
committermsmith <msmith@FreeBSD.org>1999-10-14 02:54:06 +0000
commit23b1a2234e799a3404b63d76dc2b5c549533c1e9 (patch)
tree4e9b3943aae84bc20e5074d80ee1f299ed15a0fa /sys/dev/mlx
parent3274954f706557bb6eb3a421fd5029764b1cd2f3 (diff)
downloadFreeBSD-src-23b1a2234e799a3404b63d76dc2b5c549533c1e9.zip
FreeBSD-src-23b1a2234e799a3404b63d76dc2b5c549533c1e9.tar.gz
Add support for the version 4 firmware interface and the DAC960 PG and
PJ cards. This will probably also support the AcceleRAID and eXtremeRAID cards, but nobody has volunteered one for testing, so I haven't enabled their PCI device IDs. Slightly clean up communication between the disk devices and the controller device as per new practice, and move some more register- related items int mlxreg.h from mlxvar.h. Remove some unnecessary read-modify-write operations to the card control registers; they don't behave like that. Increase the status polling interval to 10 seconds. It's still possible to load the card up to the point where a status poll will find the previous poll still running, but this will reduce the incidence of complaints.
Diffstat (limited to 'sys/dev/mlx')
-rw-r--r--sys/dev/mlx/mlx.c120
-rw-r--r--sys/dev/mlx/mlx_disk.c31
-rw-r--r--sys/dev/mlx/mlx_pci.c1
-rw-r--r--sys/dev/mlx/mlxreg.h59
-rw-r--r--sys/dev/mlx/mlxvar.h27
5 files changed, 180 insertions, 58 deletions
diff --git a/sys/dev/mlx/mlx.c b/sys/dev/mlx/mlx.c
index d353ada..95b83c9 100644
--- a/sys/dev/mlx/mlx.c
+++ b/sys/dev/mlx/mlx.c
@@ -72,7 +72,7 @@ static struct cdevsw mlx_cdevsw = {
/* dump */ nodump,
/* psize */ nopsize,
/* flags */ 0,
- /* bmaj */ 254 /* XXX magic no-bdev */
+ /* bmaj */ -1
};
static int cdev_registered = 0;
@@ -85,6 +85,10 @@ static int mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
static int mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
static void mlx_v3_intaction(struct mlx_softc *sc, int action);
+static int mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
+static int mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
+static void mlx_v4_intaction(struct mlx_softc *sc, int action);
+
/*
* Status monitoring
*/
@@ -287,6 +291,11 @@ mlx_attach(struct mlx_softc *sc)
sc->mlx_findcomplete = mlx_v3_findcomplete;
sc->mlx_intaction = mlx_v3_intaction;
break;
+ case MLX_IFTYPE_4:
+ sc->mlx_tryqueue = mlx_v4_tryqueue;
+ sc->mlx_findcomplete = mlx_v4_findcomplete;
+ sc->mlx_intaction = mlx_v4_intaction;
+ break;
default:
device_printf(sc->mlx_dev, "attaching unsupported interface version %d\n", sc->mlx_iftype);
return(ENXIO); /* should never happen */
@@ -380,11 +389,19 @@ mlx_attach(struct mlx_softc *sc)
*/
switch(sc->mlx_iftype) {
case MLX_IFTYPE_3:
+ /* XXX certify 3.52? */
if (sc->mlx_fwminor != 51) {
device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is NOT SUPPORTED\n");
device_printf(sc->mlx_dev, " *** WARNING *** Use revision 3.51 only\n");
}
break;
+ case MLX_IFTYPE_4:
+ /* XXX certify firmware versions? */
+ if (sc->mlx_fwminor != 6) {
+ device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is NOT SUPPORTED\n");
+ device_printf(sc->mlx_dev, " *** WARNING *** Use revision 4.6 only\n");
+ }
+ break;
default:
device_printf(sc->mlx_dev, "interface version corrupted to %d\n", sc->mlx_iftype);
return(ENXIO); /* should never happen */
@@ -450,7 +467,7 @@ mlx_startup(struct mlx_softc *sc)
if (dr->ms_disk == 0) {
/* pick up drive information */
dr->ms_size = mes[i].sd_size;
- dr->ms_raidlevel = mes[i].sd_raidlevel;
+ dr->ms_raidlevel = mes[i].sd_raidlevel & 0xf;
dr->ms_state = mes[i].sd_state;
/* generate geometry information */
@@ -619,9 +636,6 @@ mlx_intr(void *arg)
debug("called");
- /* ack the interrupt */
- sc->mlx_intaction(sc, MLX_INTACTION_ACKNOWLEDGE);
-
/* spin collecting finished commands */
worked = 0;
while (mlx_done(sc))
@@ -937,7 +951,7 @@ mlx_periodic(void *data)
} else if (MLX_PERIODIC_ISBUSY(sc)) {
/* time to perform a periodic status poll? XXX tuneable interval? */
- if (time_second > (sc->mlx_lastpoll + 5)) {
+ if (time_second > (sc->mlx_lastpoll + 10)) {
sc->mlx_lastpoll = time_second;
/* for caution's sake */
@@ -1602,7 +1616,7 @@ mlx_startio(struct mlx_softc *sc)
mlx_mapcmd(mc);
/* build a suitable I/O command (assumes 512-byte rounded transfers) */
- mlxd = (struct mlxd_softc *)bp->b_driver1;
+ mlxd = (struct mlxd_softc *)bp->b_dev->si_drv1;
driveno = mlxd->mlxd_drive - &sc->mlx_sysdrive[0];
blkcount = bp->b_bcount / MLX_BLKSIZE;
@@ -1639,7 +1653,7 @@ mlx_completeio(struct mlx_command *mc)
{
struct mlx_softc *sc = mc->mc_sc;
struct buf *bp = (struct buf *)mc->mc_private;
- struct mlxd_softc *mlxd = (struct mlxd_softc *)bp->b_driver1;
+ struct mlxd_softc *mlxd = (struct mlxd_softc *)bp->b_dev->si_drv1;
if (mc->mc_status != MLX_STATUS_OK) { /* could be more verbose here? */
bp->b_error = EIO;
@@ -1649,6 +1663,7 @@ mlx_completeio(struct mlx_command *mc)
case MLX_STATUS_RDWROFFLINE: /* system drive has gone offline */
device_printf(mlxd->mlxd_dev, "drive offline\n");
device_printf(sc->mlx_dev, "drive offline\n");
+ /* should signal this with a return code */
mlxd->mlxd_drive->ms_state = MLX_SYSD_OFFLINE;
break;
@@ -2113,7 +2128,7 @@ mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
MLX_V3_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
/* post command */
- MLX_V3_PUT_IDBR(sc, MLX_V3_GET_IDBR(sc) | MLX_V3_IDB_FULL);
+ MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_FULL);
return(1);
}
return(0);
@@ -2137,8 +2152,8 @@ mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
*status = MLX_V3_GET_STATUS(sc); /* get status */
/* acknowledge completion */
- MLX_V3_PUT_ODBR(sc, MLX_V3_GET_ODBR(sc) | MLX_V3_ODB_SAVAIL);
- MLX_V3_PUT_IDBR(sc, MLX_V3_GET_IDBR(sc) | MLX_V3_IDB_SACK);
+ MLX_V3_PUT_ODBR(sc, MLX_V3_ODB_SAVAIL);
+ MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_SACK);
return(1);
}
return(0);
@@ -2169,6 +2184,86 @@ mlx_v3_intaction(struct mlx_softc *sc, int action)
/********************************************************************************
********************************************************************************
+ Type 4 interface accessor methods
+ ********************************************************************************
+ ********************************************************************************/
+
+/********************************************************************************
+ * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure
+ * (the controller is not ready to take a command).
+ *
+ * Must be called at splbio or in a fashion that prevents reentry.
+ */
+static int
+mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
+{
+ int i;
+
+ debug("called");
+
+ /* ready for our command? */
+ if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_FULL)) {
+ /* copy mailbox data to window */
+ for (i = 0; i < 13; i++)
+ MLX_V4_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
+
+ /* post command */
+ MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_HWMBOX_CMD);
+ return(1);
+ }
+ return(0);
+}
+
+/********************************************************************************
+ * See if a command has been completed, if so acknowledge its completion
+ * and recover the slot number and status code.
+ *
+ * Must be called at splbio or in a fashion that prevents reentry.
+ */
+static int
+mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
+{
+
+ debug("called");
+
+ /* status available? */
+ if (MLX_V4_GET_ODBR(sc) & MLX_V4_ODB_HWSAVAIL) {
+ *slot = MLX_V4_GET_STATUS_IDENT(sc); /* get command identifier */
+ *status = MLX_V4_GET_STATUS(sc); /* get status */
+
+ /* acknowledge completion */
+ MLX_V4_PUT_ODBR(sc, MLX_V4_ODB_HWMBOX_ACK);
+ MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_SACK);
+ return(1);
+ }
+ return(0);
+}
+
+/********************************************************************************
+ * Enable/disable interrupts as requested.
+ *
+ * Must be called at splbio or in a fashion that prevents reentry.
+ */
+static void
+mlx_v4_intaction(struct mlx_softc *sc, int action)
+{
+ debug("called");
+
+ switch(action) {
+ case MLX_INTACTION_DISABLE:
+ MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK | MLX_V4_IER_DISINT);
+ sc->mlx_state &= ~MLX_STATE_INTEN;
+ break;
+ case MLX_INTACTION_ENABLE:
+ MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK & ~MLX_V4_IER_DISINT);
+ sc->mlx_state |= MLX_STATE_INTEN;
+ break;
+ }
+}
+
+
+/********************************************************************************
+ ********************************************************************************
Debugging
********************************************************************************
********************************************************************************/
@@ -2258,6 +2353,9 @@ mlx_name_controller(u_int32_t hwid)
case 0x10:
submodel = "PG";
break;
+ case 0x11:
+ submodel = "PJ";
+ break;
default:
sprintf(smbuf, " model 0x%x", hwid & 0xff);
submodel = smbuf;
diff --git a/sys/dev/mlx/mlx_disk.c b/sys/dev/mlx/mlx_disk.c
index 85f8314..9e2f571 100644
--- a/sys/dev/mlx/mlx_disk.c
+++ b/sys/dev/mlx/mlx_disk.c
@@ -104,19 +104,10 @@ static driver_t mlxd_driver = {
DRIVER_MODULE(mlxd, mlx, mlxd_driver, mlxd_devclass, 0, 0);
-static __inline struct mlxd_softc *
-mlxd_getsoftc(dev_t dev)
-{
- int unit;
-
- unit = dkunit(dev);
- return ((struct mlxd_softc *)devclass_get_softc(mlxd_devclass, unit));
-}
-
static int
mlxd_open(dev_t dev, int flags, int fmt, struct proc *p)
{
- struct mlxd_softc *sc = mlxd_getsoftc(dev);
+ struct mlxd_softc *sc = (struct mlxd_softc *)dev->si_drv1;
struct disklabel *label;
debug("called");
@@ -138,9 +129,6 @@ mlxd_open(dev_t dev, int flags, int fmt, struct proc *p)
label->d_secpercyl = sc->mlxd_drive->ms_sectors * sc->mlxd_drive->ms_heads;
label->d_secperunit = sc->mlxd_drive->ms_size;
- /* set maximum I/O size */
- dev->si_iosize_max = sc->mlxd_controller->mlx_maxiosize;
-
sc->mlxd_flags |= MLXD_OPEN;
return (0);
}
@@ -148,7 +136,7 @@ mlxd_open(dev_t dev, int flags, int fmt, struct proc *p)
static int
mlxd_close(dev_t dev, int flags, int fmt, struct proc *p)
{
- struct mlxd_softc *sc = mlxd_getsoftc(dev);
+ struct mlxd_softc *sc = (struct mlxd_softc *)dev->si_drv1;
debug("called");
@@ -161,7 +149,7 @@ mlxd_close(dev_t dev, int flags, int fmt, struct proc *p)
static int
mlxd_ioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
{
- struct mlxd_softc *sc = mlxd_getsoftc(dev);
+ struct mlxd_softc *sc = (struct mlxd_softc *)dev->si_drv1;
int error;
debug("called");
@@ -185,7 +173,7 @@ mlxd_ioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
static void
mlxd_strategy(struct buf *bp)
{
- struct mlxd_softc *sc = mlxd_getsoftc(bp->b_dev);
+ struct mlxd_softc *sc = (struct mlxd_softc *)bp->b_dev->si_drv1;
int s;
debug("called");
@@ -206,8 +194,6 @@ mlxd_strategy(struct buf *bp)
if (bp->b_bcount == 0)
goto done;
- /* pass reference to us */
- bp->b_driver1 = sc;
s = splbio();
devstat_start_transaction(&sc->mlxd_stats);
mlx_submit_buf(sc->mlxd_controller, bp);
@@ -230,7 +216,7 @@ void
mlxd_intr(void *data)
{
struct buf *bp = (struct buf *)data;
- struct mlxd_softc *sc = (struct mlxd_softc *)bp->b_driver1;
+ struct mlxd_softc *sc = (struct mlxd_softc *)bp->b_dev->si_drv1;
debug("called");
@@ -259,6 +245,7 @@ mlxd_attach(device_t dev)
struct mlxd_softc *sc = (struct mlxd_softc *)device_get_softc(dev);
device_t parent;
char *state;
+ dev_t dsk;
debug("called");
@@ -290,9 +277,13 @@ mlxd_attach(device_t dev)
DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_OTHER,
DEVSTAT_PRIORITY_DA);
- disk_create(sc->mlxd_unit, &sc->mlxd_disk, 0, &mlxd_cdevsw, &mlxddisk_cdevsw);
+ dsk = disk_create(sc->mlxd_unit, &sc->mlxd_disk, 0, &mlxd_cdevsw, &mlxddisk_cdevsw);
disks_registered++;
+ /* set maximum I/O size */
+ dsk->si_iosize_max = sc->mlxd_controller->mlx_maxiosize * MLX_BLKSIZE;
+ dsk->si_drv1 = sc;
+
return (0);
}
diff --git a/sys/dev/mlx/mlx_pci.c b/sys/dev/mlx/mlx_pci.c
index 7d791a8..8aa9e1a 100644
--- a/sys/dev/mlx/mlx_pci.c
+++ b/sys/dev/mlx/mlx_pci.c
@@ -88,6 +88,7 @@ struct
char *desc;
} mlx_identifiers[] = {
{0x1069, 0x0002, MLX_IFTYPE_3, "Mylex version 3 RAID interface"}, /* Mylex v3 software interface */
+ {0x1069, 0x0010, MLX_IFTYPE_4, "Mylex version 4 RAID interface"}, /* Mylex v4 software interface */
{0, 0, 0, 0}
};
diff --git a/sys/dev/mlx/mlxreg.h b/sys/dev/mlx/mlxreg.h
index 7130223..e287067 100644
--- a/sys/dev/mlx/mlxreg.h
+++ b/sys/dev/mlx/mlxreg.h
@@ -51,6 +51,65 @@
#define MLX_STATUS_BUSY 0xffff /* command is in controller */
/*
+ * Accessor defines for the V3 interface.
+ */
+#define MLX_V3_MAILBOX 0x00
+#define MLX_V3_STATUS_IDENT 0x0d
+#define MLX_V3_STATUS 0x0e
+#define MLX_V3_IDBR 0x40
+#define MLX_V3_ODBR 0x41
+#define MLX_V3_IER 0x43
+
+#define MLX_V3_PUT_MAILBOX(sc, idx, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V3_MAILBOX + idx, val)
+#define MLX_V3_GET_STATUS_IDENT(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_STATUS_IDENT)
+#define MLX_V3_GET_STATUS(sc) bus_space_read_2 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_STATUS)
+#define MLX_V3_GET_IDBR(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_IDBR)
+#define MLX_V3_PUT_IDBR(sc, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V3_IDBR, val)
+#define MLX_V3_GET_ODBR(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_ODBR)
+#define MLX_V3_PUT_ODBR(sc, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V3_ODBR, val)
+#define MLX_V3_PUT_IER(sc, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V3_IER, val)
+
+#define MLX_V3_IDB_FULL (1<<0) /* mailbox is full */
+#define MLX_V3_IDB_SACK (1<<1) /* acknowledge status read */
+
+#define MLX_V3_ODB_SAVAIL (1<<0) /* status is available */
+
+/*
+ * Accessor defines for the V4 interface.
+ */
+#define MLX_V4_MAILBOX 0x1000
+#define MLX_V4_STATUS_IDENT 0x1018
+#define MLX_V4_STATUS 0x101a
+#define MLX_V4_IDBR 0x0020
+#define MLX_V4_ODBR 0x002c
+#define MLX_V4_IER 0x0034
+
+/* use longword access? */
+#define MLX_V4_PUT_MAILBOX(sc, idx, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_MAILBOX + idx, val)
+#define MLX_V4_GET_STATUS_IDENT(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V4_STATUS_IDENT)
+#define MLX_V4_GET_STATUS(sc) bus_space_read_2 (sc->mlx_btag, sc->mlx_bhandle, MLX_V4_STATUS)
+#define MLX_V4_GET_IDBR(sc) bus_space_read_4 (sc->mlx_btag, sc->mlx_bhandle, MLX_V4_IDBR)
+#define MLX_V4_PUT_IDBR(sc, val) bus_space_write_4(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_IDBR, val)
+#define MLX_V4_GET_ODBR(sc) bus_space_read_4 (sc->mlx_btag, sc->mlx_bhandle, MLX_V4_ODBR)
+#define MLX_V4_PUT_ODBR(sc, val) bus_space_write_4(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_ODBR, val)
+#define MLX_V4_PUT_IER(sc, val) bus_space_write_4(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_IER, val)
+
+#define MLX_V4_IDB_FULL (1<<0) /* mailbox is full */
+
+#define MLX_V4_IDB_HWMBOX_CMD (1<<0) /* posted hardware mailbox command */
+#define MLX_V4_IDB_SACK (1<<1) /* acknowledge status read */
+#define MLX_V4_IDB_MEMMBOX_CMD (1<<4) /* posted memory mailbox command */
+
+#define MLX_V4_ODB_HWSAVAIL (1<<0) /* status is available for hardware mailbox */
+#define MLX_V4_ODB_MEMSAVAIL (1<<1) /* status is available for memory mailbox */
+
+#define MLX_V4_ODB_HWMBOX_ACK (1<<0) /* ack status read from hardware mailbox */
+#define MLX_V4_ODB_MEMMBOX_ACK (1<<1) /* ack status read from memory mailbox */
+
+#define MLX_V4_IER_MASK 0xfb /* message unit interrupt mask */
+#define MLX_V4_IER_DISINT (1<<2) /* interrupt disable bit */
+
+/*
* Scatter-gather list format, type 1, kind 00.
*/
struct mlx_sgentry
diff --git a/sys/dev/mlx/mlxvar.h b/sys/dev/mlx/mlxvar.h
index 7679dbb..ec69b25 100644
--- a/sys/dev/mlx/mlxvar.h
+++ b/sys/dev/mlx/mlxvar.h
@@ -159,8 +159,6 @@ struct mlx_softc
void (* mlx_intaction)(struct mlx_softc *sc, int action);
#define MLX_INTACTION_DISABLE 0
#define MLX_INTACTION_ENABLE 1
-#define MLX_INTACTION_ACKNOWLEDGE 2
-
};
/*
@@ -205,31 +203,6 @@ extern int mlx_submit_ioctl(struct mlx_softc *sc, struct mlx_sysdrive *drive, u_
extern void mlxd_intr(void *data);
/*
- * Accessor defines for the V3 interface.
- */
-#define MLX_V3_MAILBOX 0x00
-#define MLX_V3_STATUS_IDENT 0x0d
-#define MLX_V3_STATUS 0x0e
-#define MLX_V3_IDBR 0x40
-#define MLX_V3_ODBR 0x41
-#define MLX_V3_IER 0x43
-
-#define MLX_V3_PUT_MAILBOX(sc, idx, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V3_MAILBOX + idx, val)
-#define MLX_V3_GET_STATUS_IDENT(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_STATUS_IDENT)
-#define MLX_V3_GET_STATUS(sc) bus_space_read_2 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_STATUS)
-#define MLX_V3_GET_IDBR(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_IDBR)
-#define MLX_V3_PUT_IDBR(sc, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V3_IDBR, val)
-#define MLX_V3_GET_ODBR(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_ODBR)
-#define MLX_V3_PUT_ODBR(sc, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V3_ODBR, val)
-#define MLX_V3_PUT_IER(sc, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V3_IER, val)
-
-#define MLX_V3_IDB_FULL (1<<0) /* mailbox is full */
-#define MLX_V3_IDB_SACK (1<<1) /* acknowledge status read */
-#define MLX_V3_IDB_RESET (1<<3) /* request soft reset */
-
-#define MLX_V3_ODB_SAVAIL (1<<0) /* status is available */
-
-/*
* Inlines to build various command structures
*/
static __inline void
OpenPOWER on IntegriCloud