summaryrefslogtreecommitdiffstats
path: root/sys/dev/mlx/mlx.c
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/mlx.c
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/mlx.c')
-rw-r--r--sys/dev/mlx/mlx.c120
1 files changed, 109 insertions, 11 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;
OpenPOWER on IntegriCloud