Date: Thu, 09 Mar 2000 23:08:33 -0800 From: Mike Smith <msmith@freebsd.org> To: alpha@freebsd.org Cc: Vladimir Kravchuk <adm@smr.ru> Subject: Mylex controllers and Alpha systems Message-ID: <200003100708.XAA00710@mass.cdrom.com>
next in thread | raw e-mail | index | archive | help
[-- Attachment #1 --]
The attached patch _should_ fix (amongst other things) the operation of
Mylex RAID controllers on Alpha systems. I've been running this code
here for a while now, and apart from a problem unloading the driver if
it's a module, it's been quite stable.
I'd _like_ to get this into 4.x so that we can claim support for these
controllers on Alpha as well, but I'd really like at least one other
success story first.
Thanks for any feedback.
(Note that this patch doesn't address the Digital-branded Mylex
controllers yet.)
[-- Attachment #2 --]
Index: mlx.c
===================================================================
RCS file: /local0/src/src/sys/dev/mlx/mlx.c,v
retrieving revision 1.14
diff -u -r1.14 mlx.c
--- mlx.c 1999/12/25 01:45:22 1.14
+++ mlx.c 2000/03/10 07:03:46
@@ -40,6 +40,7 @@
#include <sys/conf.h>
#include <sys/devicestat.h>
#include <sys/disk.h>
+#include <sys/stat.h>
#include <machine/resource.h>
#include <machine/bus.h>
@@ -50,12 +51,6 @@
#include <dev/mlx/mlxvar.h>
#include <dev/mlx/mlxreg.h>
-#if 0
-#define debug(fmt, args...) printf("%s: " fmt "\n", __FUNCTION__ , ##args)
-#else
-#define debug(fmt, args...)
-#endif
-
#define MLX_CDEV_MAJOR 130
static struct cdevsw mlx_cdevsw = {
@@ -75,7 +70,6 @@
/* bmaj */ -1
};
-static int cdev_registered = 0;
devclass_t mlx_devclass;
/*
@@ -84,14 +78,18 @@
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_v3_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2);
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);
+static int mlx_v4_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2);
static int mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
static int mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
static void mlx_v5_intaction(struct mlx_softc *sc, int action);
+static int mlx_v5_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2);
+static int mlx_v5_reset(struct mlx_softc *sc);
/*
* Status monitoring
@@ -143,7 +141,7 @@
*/
static char *mlx_diagnose_command(struct mlx_command *mc);
static void mlx_describe_controller(struct mlx_softc *sc);
-
+static int mlx_fw_message(struct mlx_softc *sc, int status, int param1, int param2);
/*
* Utility functions.
@@ -166,7 +164,7 @@
{
struct mlx_command *mc;
- debug("called");
+ debug_called(1);
/* cancel status timeout */
untimeout(mlx_periodic, sc, sc->mlx_timeout);
@@ -176,7 +174,6 @@
TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link);
mlx_freecmd(mc);
}
-
/* destroy data-transfer DMA tag */
if (sc->mlx_buffer_dmat)
bus_dma_tag_destroy(sc->mlx_buffer_dmat);
@@ -205,6 +202,10 @@
/* free controller enquiry data */
if (sc->mlx_enq2 != NULL)
free(sc->mlx_enq2, M_DEVBUF);
+
+ /* destroy control device */
+ if (sc->mlx_dev_t != (dev_t)NULL)
+ destroy_dev(sc->mlx_dev_t);
}
/********************************************************************************
@@ -215,7 +216,7 @@
{
struct mlx_softc *sc = (struct mlx_softc *)arg;
- debug("called");
+ debug_called(1);
/* save base of s/g table's address in bus space */
sc->mlx_sgbusaddr = segs->ds_addr;
@@ -227,7 +228,7 @@
size_t segsize;
int error;
- debug("called");
+ debug_called(1);
/* destroy any existing mappings */
if (sc->mlx_sgtable)
@@ -239,7 +240,7 @@
* Create a single tag describing a region large enough to hold all of
* the s/g lists we will need.
*/
- segsize = sizeof(struct mlx_sgentry) * MLX_NSEG * sc->mlx_maxiop;
+ segsize = sizeof(struct mlx_sgentry) * sc->mlx_sg_nseg * sc->mlx_maxiop;
error = bus_dma_tag_create(sc->mlx_parent_dmat, /* parent */
1, 0, /* alignment, boundary */
BUS_SPACE_MAXADDR, /* lowaddr */
@@ -277,9 +278,9 @@
int
mlx_attach(struct mlx_softc *sc)
{
- int rid, error, fwminor;
+ int rid, error, fwminor, hscode, hserror, hsparam1, hsparam2, hsmsg;
- debug("called");
+ debug_called(1);
/*
* Initialise per-controller queues.
@@ -292,20 +293,28 @@
* Select accessor methods based on controller interface type.
*/
switch(sc->mlx_iftype) {
+ case MLX_IFTYPE_2:
case MLX_IFTYPE_3:
sc->mlx_tryqueue = mlx_v3_tryqueue;
sc->mlx_findcomplete = mlx_v3_findcomplete;
sc->mlx_intaction = mlx_v3_intaction;
+ sc->mlx_fw_handshake = mlx_v3_fw_handshake;
+ sc->mlx_sg_nseg = MLX_NSEG_OLD;
break;
case MLX_IFTYPE_4:
sc->mlx_tryqueue = mlx_v4_tryqueue;
sc->mlx_findcomplete = mlx_v4_findcomplete;
sc->mlx_intaction = mlx_v4_intaction;
+ sc->mlx_fw_handshake = mlx_v4_fw_handshake;
+ sc->mlx_sg_nseg = MLX_NSEG_NEW;
break;
case MLX_IFTYPE_5:
sc->mlx_tryqueue = mlx_v5_tryqueue;
sc->mlx_findcomplete = mlx_v5_findcomplete;
sc->mlx_intaction = mlx_v5_intaction;
+ sc->mlx_fw_handshake = mlx_v5_fw_handshake;
+ sc->mlx_sg_nseg = MLX_NSEG_NEW;
+/* mlx_v5_reset(sc); */
break;
default:
device_printf(sc->mlx_dev, "attaching unsupported interface version %d\n", sc->mlx_iftype);
@@ -315,6 +324,28 @@
/* disable interrupts before we start talking to the controller */
sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
+ /* wait for the controller to come ready, handshake with the firmware if required */
+ hsmsg = 0;
+ DELAY(1000);
+ while ((hscode = sc->mlx_fw_handshake(sc, &hserror, &hsparam1, &hsparam2)) != 0) {
+ /* report first time around... */
+ if (hsmsg == 0) {
+ device_printf(sc->mlx_dev, "controller initialisation in progress...\n");
+ hsmsg = 1;
+ }
+ /* did we get a real message? */
+ if (hscode == 2) {
+ hscode = mlx_fw_message(sc, hserror, hsparam1, hsparam2);
+ /* fatal initialisation error? */
+ if (hscode != 0) {
+ mlx_free(sc);
+ return(ENXIO);
+ }
+ }
+ }
+ if (hsmsg == 1)
+ device_printf(sc->mlx_dev, "initialisation complete.\n");
+
/*
* Allocate and connect our interrupt.
*/
@@ -335,14 +366,14 @@
/*
* Create DMA tag for mapping buffers into controller-addressable space.
*/
- error = bus_dma_tag_create(sc->mlx_parent_dmat, /* parent */
- 1, 0, /* alignment, boundary */
- BUS_SPACE_MAXADDR, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- MAXBSIZE, MLX_NSEG, /* maxsize, nsegments */
- BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
- 0, /* flags */
+ error = bus_dma_tag_create(sc->mlx_parent_dmat, /* parent */
+ 1, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ MAXBSIZE, sc->mlx_sg_nseg, /* maxsize, nsegments */
+ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
+ 0, /* flags */
&sc->mlx_buffer_dmat);
if (error != 0) {
device_printf(sc->mlx_dev, "can't allocate buffer DMA tag\n");
@@ -378,6 +409,14 @@
*/
fwminor = (sc->mlx_enq2->me_firmware_id >> 8) & 0xff;
switch(sc->mlx_iftype) {
+ case MLX_IFTYPE_2:
+ /* XXX require 2.42 or better (PCI) or 2.14 or better (EISA) */
+ if (fwminor < 42) {
+ device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
+ device_printf(sc->mlx_dev, " *** WARNING *** Use revision 2.42 or later\n");
+ }
+ break;
+ break;
case MLX_IFTYPE_3:
/* XXX certify 3.52? */
if (fwminor < 51) {
@@ -421,10 +460,10 @@
sc->mlx_check = -1;
/*
- * Register the control device on first attach.
+ * Create the control device.
*/
- if (cdev_registered++ == 0)
- cdevsw_add(&mlx_cdevsw);
+ sc->mlx_dev_t = make_dev(&mlx_cdevsw, device_get_unit(sc->mlx_dev), UID_ROOT, GID_OPERATOR,
+ S_IRUSR | S_IWUSR, "mlx%d", device_get_unit(sc->mlx_dev));
/*
* Start the timeout routine.
@@ -444,7 +483,7 @@
struct mlx_sysdrive *dr;
int i, error;
- debug("called");
+ debug_called(1);
/*
* Scan all the system drives and attach children for those that
@@ -504,7 +543,7 @@
struct mlxd_softc *mlxd;
int i, s, error;
- debug("called");
+ debug_called(1);
error = EBUSY;
s = splbio();
@@ -525,11 +564,6 @@
mlx_free(sc);
- /*
- * Deregister the control device on last detach.
- */
- if (--cdev_registered == 0)
- cdevsw_remove(&mlx_cdevsw);
error = 0;
out:
splx(s);
@@ -552,7 +586,7 @@
struct mlx_softc *sc = device_get_softc(dev);
int i, s, error;
- debug("called");
+ debug_called(1);
s = splbio();
error = 0;
@@ -591,7 +625,7 @@
struct mlx_softc *sc = device_get_softc(dev);
int s;
- debug("called");
+ debug_called(1);
s = splbio();
sc->mlx_state |= MLX_STATE_SUSPEND;
@@ -614,7 +648,7 @@
{
struct mlx_softc *sc = device_get_softc(dev);
- debug("called");
+ debug_called(1);
sc->mlx_state &= ~MLX_STATE_SUSPEND;
sc->mlx_intaction(sc, MLX_INTACTION_ENABLE);
@@ -631,7 +665,7 @@
{
struct mlx_softc *sc = (struct mlx_softc *)arg;
- debug("called");
+ debug_called(1);
/* collect finished commands, queue anything waiting */
mlx_done(sc);
@@ -646,7 +680,7 @@
{
int s;
- debug("called");
+ debug_called(1);
s = splbio();
bufq_insert_tail(&sc->mlx_bufq, bp);
@@ -907,7 +941,7 @@
{
struct mlx_softc *sc = (struct mlx_softc *)data;
- debug("called");
+ debug_called(1);
/*
* Run a bus pause?
@@ -980,11 +1014,11 @@
{
struct mlx_softc *sc = mc->mc_sc;
- debug("called");
+ debug_called(1);
/* Command completed OK? */
if (mc->mc_status != 0) {
- device_printf(sc->mlx_dev, "periodic enquiry failed\n");
+ device_printf(sc->mlx_dev, "periodic enquiry failed - %s\n", mlx_diagnose_command(mc));
goto out;
}
@@ -1065,7 +1099,7 @@
void *result = NULL;
int error;
- debug("called");
+ debug_called(1);
/* get ourselves a command buffer */
error = 1;
@@ -1129,7 +1163,7 @@
struct mlx_eventlog_entry *el = (struct mlx_eventlog_entry *)mc->mc_data;
char *reason;
- debug("called");
+ debug_called(1);
sc->mlx_lastevent++; /* next message... */
if (mc->mc_status == 0) {
@@ -1321,7 +1355,7 @@
void *result;
int error;
- debug("called");
+ debug_called(1);
/* get ourselves a command buffer */
error = 1;
@@ -1387,7 +1421,7 @@
struct mlx_command *mc;
int error;
- debug("called");
+ debug_called(1);
/* get ourselves a command buffer */
error = 1;
@@ -1429,7 +1463,7 @@
struct mlx_command *mc;
int error;
- debug("called");
+ debug_called(1);
/* get ourselves a command buffer */
error = 0x10000;
@@ -1471,7 +1505,7 @@
struct mlx_softc *sc = mc->mc_sc;
int error, count;
- debug("called");
+ debug_called(1);
mc->mc_complete = NULL;
mc->mc_private = mc; /* wake us when you're done */
@@ -1495,7 +1529,7 @@
/********************************************************************************
* Start the command (mc) and busy-wait for it to complete.
*
- * Should only be used when interrupts are not available. Returns 0 on
+ * Should only be used when interrupts can't be relied upon. Returns 0 on
* success, nonzero on error.
* Successfully completed commands are dequeued.
*/
@@ -1505,7 +1539,7 @@
struct mlx_softc *sc = mc->mc_sc;
int error, count, s;
- debug("called");
+ debug_called(1);
mc->mc_complete = NULL;
mc->mc_private = NULL; /* we will poll for it */
@@ -1516,7 +1550,8 @@
do {
/* poll for completion */
mlx_done(mc->mc_sc);
- } while ((mc->mc_status == MLX_STATUS_BUSY) && (count < 10000));
+
+ } while ((mc->mc_status == MLX_STATUS_BUSY) && (count++ < 15000000));
if (mc->mc_status != MLX_STATUS_BUSY) {
s = splbio();
TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
@@ -1532,7 +1567,7 @@
* controller. Leave a couple of slots free for emergencies.
*
* Must be called at splbio or in an equivalent fashion that prevents
- * reentry or activity on the bufq..
+ * reentry or activity on the bufq.
*/
static void
mlx_startio(struct mlx_softc *sc)
@@ -1663,6 +1698,8 @@
void *kbuf;
int error;
+ debug_called(0);
+
kbuf = NULL;
mc = NULL;
error = ENOMEM;
@@ -1670,28 +1707,34 @@
if (mu->mu_datasize > 0) {
if ((kbuf = malloc(mu->mu_datasize, M_DEVBUF, M_WAITOK)) == NULL)
goto out;
- if ((mu->mu_bufptr < 0) || (mu->mu_bufptr > (sizeof(mu->mu_command) < sizeof(u_int32_t)))) {
+ if ((mu->mu_bufptr < 0) || (mu->mu_bufptr > (sizeof(mu->mu_command) - sizeof(u_int32_t)))) {
error = EINVAL;
goto out;
}
}
+ debug(0, "got kernel buffer");
+
/* get ourselves a command buffer */
if ((mc = mlx_alloccmd(sc)) == NULL)
goto out;
+ debug(0, "got command buffer");
/* copy the command and data */
bcopy(mu->mu_command, mc->mc_mailbox, sizeof(mc->mc_mailbox));
if ((mu->mu_datasize > 0) && ((error = copyin(mu->mu_buf, kbuf, mu->mu_datasize))))
goto out;
-
+ debug(0, "got command and data");
+
/* get a command slot */
if (mlx_getslot(mc))
goto out;
-
+ debug(0, "got a slot");
+
/* map the command so the controller can see it */
mc->mc_data = kbuf;
mc->mc_length = mu->mu_datasize;
mlx_mapcmd(mc);
+ debug(0, "mapped");
/* if there's a data buffer, fix up the command */
if (mu->mu_datasize > 0) {
@@ -1700,6 +1743,7 @@
mc->mc_mailbox[mu->mu_bufptr + 2] = (mc->mc_length >> 16) & 0xff;
mc->mc_mailbox[mu->mu_bufptr + 3] = (mc->mc_length >> 24) & 0xff;
}
+ debug(0, "command fixup");
/* submit the command and wait */
if ((error = mlx_wait_command(mc)) != 0)
@@ -1736,7 +1780,7 @@
struct mlx_softc *sc = mc->mc_sc;
int s, slot;
- debug("called mc %p sc %p", mc, sc);
+ debug_called(1);
/* enforce slot-usage limit */
if (sc->mlx_busycmds >= ((mc->mc_flags & MLX_CMD_PRIORITY) ?
@@ -1750,7 +1794,7 @@
*/
s = splbio();
for (slot = 0; slot < sc->mlx_maxiop; slot++) {
- debug("try slot %d", slot);
+ debug(2, "try slot %d", slot);
if (sc->mlx_busycmd[slot] == NULL)
break;
}
@@ -1764,7 +1808,7 @@
if (slot >= sc->mlx_maxiop)
return(EBUSY);
- debug("got slot %d", slot);
+ debug(2, "got slot %d", slot);
mc->mc_slot = slot;
return(0);
}
@@ -1780,14 +1824,14 @@
struct mlx_sgentry *sg;
int i;
- debug("called");
+ debug_called(1);
/* get base address of s/g table */
- sg = sc->mlx_sgtable + (mc->mc_slot * MLX_NSEG);
+ sg = sc->mlx_sgtable + (mc->mc_slot * sc->mlx_sg_nseg);
/* save s/g table information in command */
mc->mc_nsgent = nsegments;
- mc->mc_sgphys = sc->mlx_sgbusaddr + (mc->mc_slot * MLX_NSEG * sizeof(struct mlx_sgentry));
+ mc->mc_sgphys = sc->mlx_sgbusaddr + (mc->mc_slot * sc->mlx_sg_nseg * sizeof(struct mlx_sgentry));
mc->mc_dataphys = segs[0].ds_addr;
/* populate s/g table */
@@ -1802,7 +1846,7 @@
{
struct mlx_softc *sc = mc->mc_sc;
- debug("called");
+ debug_called(1);
/* if the command involves data at all */
if (mc->mc_data != NULL) {
@@ -1822,7 +1866,7 @@
{
struct mlx_softc *sc = mc->mc_sc;
- debug("called");
+ debug_called(1);
/* if the command involved data at all */
if (mc->mc_data != NULL) {
@@ -1847,7 +1891,7 @@
struct mlx_softc *sc = mc->mc_sc;
int i, s, done;
- debug("called");
+ debug_called(1);
/* save the slot number as ident so we can handle this command when complete */
mc->mc_mailbox[0x1] = mc->mc_slot;
@@ -1899,7 +1943,7 @@
u_int8_t slot;
u_int16_t status;
- debug("called");
+ debug_called(2);
result = 0;
@@ -1947,7 +1991,7 @@
struct mlx_command *mc, *nc;
int s, count;
- debug("called");
+ debug_called(2);
/* avoid reentrancy XXX might want to signal and request a restart */
if (mlx_lock_tas(sc, MLX_LOCK_COMPLETING))
@@ -2023,7 +2067,7 @@
int error;
int s;
- debug("called");
+ debug_called(1);
s = splbio();
if ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL)
@@ -2057,7 +2101,7 @@
{
int s;
- debug("called");
+ debug_called(1);
s = splbio();
TAILQ_INSERT_HEAD(&mc->mc_sc->mlx_freecmds, mc, mc_link);
@@ -2072,8 +2116,7 @@
{
struct mlx_softc *sc = mc->mc_sc;
- debug("called");
-
+ debug_called(1);
bus_dmamap_destroy(sc->mlx_buffer_dmat, mc->mc_dmamap);
free(mc, M_DEVBUF);
}
@@ -2096,7 +2139,7 @@
{
int i;
- debug("called");
+ debug_called(2);
/* ready for our command? */
if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_FULL)) {
@@ -2121,7 +2164,7 @@
mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
{
- debug("called");
+ debug_called(2);
/* status available? */
if (MLX_V3_GET_ODBR(sc) & MLX_V3_ODB_SAVAIL) {
@@ -2144,7 +2187,7 @@
static void
mlx_v3_intaction(struct mlx_softc *sc, int action)
{
- debug("called");
+ debug_called(1);
switch(action) {
case MLX_INTACTION_DISABLE:
@@ -2158,7 +2201,36 @@
}
}
+/********************************************************************************
+ * Poll for firmware error codes during controller initialisation.
+ * Returns 0 if initialisation is complete, 1 if still in progress but no
+ * error has been fetched, 2 if an error has been retrieved.
+ */
+static int
+mlx_v3_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2)
+{
+ u_int8_t fwerror;
+
+ /* init in progress? */
+ if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_INIT_BUSY))
+ return(0);
+
+ /* test error value */
+ fwerror = MLX_V3_GET_FWERROR(sc);
+ if (!(fwerror & MLX_V3_FWERROR_PEND))
+ return(1);
+ /* mask status pending bit, fetch status */
+ *error = fwerror & ~MLX_V3_FWERROR_PEND;
+ *param1 = MLX_V3_GET_FWERROR_PARAM1(sc);
+ *param2 = MLX_V3_GET_FWERROR_PARAM2(sc);
+
+ /* acknowledge */
+ MLX_V3_PUT_FWERROR(sc, 0);
+
+ return(2);
+}
+
/********************************************************************************
********************************************************************************
Type 4 interface accessor methods
@@ -2176,7 +2248,7 @@
{
int i;
- debug("called");
+ debug_called(2);
/* ready for our command? */
if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_FULL)) {
@@ -2184,6 +2256,10 @@
for (i = 0; i < 13; i++)
MLX_V4_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
+ /* memory-mapped controller, so issue a write barrier to ensure the mailbox is filled */
+ bus_space_barrier(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_MAILBOX, MLX_V4_MAILBOX_LENGTH,
+ BUS_SPACE_BARRIER_WRITE);
+
/* post command */
MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_HWMBOX_CMD);
return(1);
@@ -2201,7 +2277,7 @@
mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
{
- debug("called");
+ debug_called(2);
/* status available? */
if (MLX_V4_GET_ODBR(sc) & MLX_V4_ODB_HWSAVAIL) {
@@ -2224,7 +2300,7 @@
static void
mlx_v4_intaction(struct mlx_softc *sc, int action)
{
- debug("called");
+ debug_called(1);
switch(action) {
case MLX_INTACTION_DISABLE:
@@ -2238,7 +2314,38 @@
}
}
+/********************************************************************************
+ * Poll for firmware error codes during controller initialisation.
+ * Returns 0 if initialisation is complete, 1 if still in progress but no
+ * error has been fetched, 2 if an error has been retrieved.
+ */
+static int
+mlx_v4_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2)
+{
+ u_int8_t fwerror;
+
+ debug_called(2);
+
+ /* init in progress? */
+ if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_INIT_BUSY))
+ return(0);
+
+ /* test error value */
+ fwerror = MLX_V4_GET_FWERROR(sc);
+ if (!(fwerror & MLX_V4_FWERROR_PEND))
+ return(1);
+
+ /* mask status pending bit, fetch status */
+ *error = fwerror & ~MLX_V4_FWERROR_PEND;
+ *param1 = MLX_V4_GET_FWERROR_PARAM1(sc);
+ *param2 = MLX_V4_GET_FWERROR_PARAM2(sc);
+
+ /* acknowledge */
+ MLX_V4_PUT_FWERROR(sc, 0);
+ return(2);
+}
+
/********************************************************************************
********************************************************************************
Type 5 interface accessor methods
@@ -2255,19 +2362,20 @@
mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
{
int i;
-
- debug("called");
+
+ debug_called(2);
/* ready for our command? */
if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_EMPTY) {
- /* copy mailbox data to window */
- for (i = 0; i < 13; i++)
- MLX_V5_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
-
- /* post command */
- MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_HWMBOX_CMD);
- return(1);
+ /* copy mailbox data to window */
+ for (i = 0; i < 13; i++)
+ MLX_V5_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
+
+ /* post command */
+ MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_HWMBOX_CMD);
+ return(1);
}
+
return(0);
}
@@ -2281,7 +2389,7 @@
mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
{
- debug("called");
+ debug_called(2);
/* status available? */
if (MLX_V5_GET_ODBR(sc) & MLX_V5_ODB_HWSAVAIL) {
@@ -2304,22 +2412,108 @@
static void
mlx_v5_intaction(struct mlx_softc *sc, int action)
{
- debug("called");
+ debug_called(1);
switch(action) {
case MLX_INTACTION_DISABLE:
- MLX_V5_PUT_IER(sc, MLX_V5_IER_DISINT);
+ MLX_V5_PUT_IER(sc, 0xff & MLX_V5_IER_DISINT);
sc->mlx_state &= ~MLX_STATE_INTEN;
break;
case MLX_INTACTION_ENABLE:
- MLX_V5_PUT_IER(sc, 0);
+ MLX_V5_PUT_IER(sc, 0xff & ~MLX_V5_IER_DISINT);
sc->mlx_state |= MLX_STATE_INTEN;
break;
}
}
+/********************************************************************************
+ * Poll for firmware error codes during controller initialisation.
+ * Returns 0 if initialisation is complete, 1 if still in progress but no
+ * error has been fetched, 2 if an error has been retrieved.
+ */
+static int
+mlx_v5_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2)
+{
+ u_int8_t fwerror;
+ static int initted = 0;
+
+ debug_called(2);
+
+ /* first time around, clear any hardware completion status */
+ if (!initted) {
+ MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_SACK);
+ DELAY(1000);
+ initted = 1;
+ }
+
+ /* init in progress? */
+ if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_INIT_DONE)
+ return(0);
+
+ /* test for error value */
+ fwerror = MLX_V5_GET_FWERROR(sc);
+ if (!(fwerror & MLX_V5_FWERROR_PEND))
+ return(1);
+
+ /* mask status pending bit, fetch status */
+ *error = fwerror & ~MLX_V5_FWERROR_PEND;
+ *param1 = MLX_V5_GET_FWERROR_PARAM1(sc);
+ *param2 = MLX_V5_GET_FWERROR_PARAM2(sc);
+ /* acknowledge */
+ MLX_V5_PUT_FWERROR(sc, 0xff);
+
+ return(2);
+}
+
/********************************************************************************
+ * Reset the controller
+ *
+ * Note that if time is not advancing, the timeouts here may not be accurate.
+ */
+static int
+mlx_v5_reset(struct mlx_softc *sc)
+{
+ time_t t;
+ int count;
+
+ t = time_second;
+ count = 0;
+ MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_RESET); /* request a reset */
+ bus_space_barrier(sc->mlx_btag, sc->mlx_bhandle, MLX_V5_IDBR, 1, BUS_SPACE_BARRIER_READ);
+
+ while (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_RESET) {
+ count++;
+ if ((t == time_second) && (count > 10000000)) {
+ debug(0, "reset approximately timed out, IDB 0x%x", MLX_V5_GET_IDBR(sc));
+ return(1);
+ }
+ if ((time_second - t) > 5) {
+ debug(0, "reset timed out after 5 seconds, IDB 0x%x (%d polls)", MLX_V5_GET_IDBR(sc), count);
+ return(1);
+ }
+ }
+ debug(0, "reset acknowledged after %d polls", count);
+ MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_SACK); /* acknowledge reset */
+ bus_space_barrier(sc->mlx_btag, sc->mlx_bhandle, MLX_V5_IDBR, 1, BUS_SPACE_BARRIER_READ);
+
+ while (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_SACK) {
+ count++;
+ if ((t == time_second) && (count > 10000000)) {
+ debug(0, "init approximately timed out, IDB 0x%x", MLX_V5_GET_IDBR(sc));
+ return(1);
+ }
+ if ((time_second - t) > 120) {
+ debug(0, "reset timed out after 2 minutes, IDB 0x%x (%d polls)", MLX_V5_GET_IDBR(sc), count);
+ return(1);
+ }
+ }
+ debug(0, "ack cleared after %d polls", count);
+ return(0);
+}
+
+
+/********************************************************************************
********************************************************************************
Debugging
********************************************************************************
@@ -2343,6 +2537,8 @@
"invalid or non-redundant drive", /* 11 */
"channel is busy", /* 12 */
"channel is not stopped", /* 13 */
+ "rebuild successfully terminated", /* 14 */
+ ""
};
static struct
@@ -2363,6 +2559,7 @@
{MLX_CMD_REBUILDASYNC, 0x0004, 7},
{MLX_CMD_REBUILDASYNC, 0x0105, 8},
{MLX_CMD_REBUILDASYNC, 0x0106, 9},
+ {MLX_CMD_REBUILDASYNC, 0x0107, 14},
{MLX_CMD_CHECKASYNC, 0x0002, 10},
{MLX_CMD_CHECKASYNC, 0x0105, 11},
{MLX_CMD_CHECKASYNC, 0x0106, 9},
@@ -2390,7 +2587,7 @@
}
/*******************************************************************************
- * Return a string describing the controller (hwid)
+ * Print a string describing the controller (sc)
*/
static struct
{
@@ -2427,7 +2624,7 @@
sprintf(buf, " model 0x%x", sc->mlx_enq2->me_hardware_id & 0xff);
model = buf;
}
- device_printf(sc->mlx_dev, "DAC%s, %d channel%s, firmware %d.%02d-%c-%d, %dMB RAM\n",
+ device_printf(sc->mlx_dev, "DAC%s, %d channel%s, firmware %d.%02d-%c-%02d, %dMB RAM\n",
model,
sc->mlx_enq2->me_actual_channels,
sc->mlx_enq2->me_actual_channels > 1 ? "s" : "",
@@ -2474,6 +2671,59 @@
"\20\4Background Init\3Read Ahead\2MORE\1Cluster\n");
}
+}
+
+/*******************************************************************************
+ * Emit a string describing the firmware handshake status code, and return a flag
+ * indicating whether the code represents a fatal error.
+ *
+ * Error code interpretations are from the Linux driver, and don't directly match
+ * the messages printed by Mylex's BIOS. This may change if documentation on the
+ * codes is forthcoming.
+ */
+static int
+mlx_fw_message(struct mlx_softc *sc, int error, int param1, int param2)
+{
+ switch(error) {
+ case 0x00:
+ device_printf(sc->mlx_dev, "physical drive %d:%d not responding\n", param2, param1);
+ break;
+ case 0x08:
+ /* we could be neater about this and give some indication when we receive more of them */
+ if (!(sc->mlx_flags & MLX_SPINUP_REPORTED)) {
+ device_printf(sc->mlx_dev, "spinning up drives...\n");
+ sc->mlx_flags |= MLX_SPINUP_REPORTED;
+ }
+ break;
+ case 0x30:
+ device_printf(sc->mlx_dev, "configuration checksum error\n");
+ break;
+ case 0x60:
+ device_printf(sc->mlx_dev, "mirror race recovery failed\n");
+ break;
+ case 0x70:
+ device_printf(sc->mlx_dev, "mirror race recovery in progress\n");
+ break;
+ case 0x90:
+ device_printf(sc->mlx_dev, "physical drive %d:%d COD mismatch\n", param2, param1);
+ break;
+ case 0xa0:
+ device_printf(sc->mlx_dev, "logical drive installation aborted\n");
+ break;
+ case 0xb0:
+ device_printf(sc->mlx_dev, "mirror race on a critical system drive\n");
+ break;
+ case 0xd0:
+ device_printf(sc->mlx_dev, "new controller configuration found\n");
+ break;
+ case 0xf0:
+ device_printf(sc->mlx_dev, "FATAL MEMORY PARITY ERROR\n");
+ return(1);
+ default:
+ device_printf(sc->mlx_dev, "unknown firmware initialisation error %02x:%02x:%02x\n", error, param1, param2);
+ break;
+ }
+ return(0);
}
/********************************************************************************
Index: mlx_disk.c
===================================================================
RCS file: /local0/src/src/sys/dev/mlx/mlx_disk.c,v
retrieving revision 1.8
diff -u -r1.8 mlx_disk.c
--- mlx_disk.c 1999/12/22 01:21:27 1.8
+++ mlx_disk.c 2000/03/10 07:02:45
@@ -50,12 +50,6 @@
#include <dev/mlx/mlxvar.h>
#include <dev/mlx/mlxreg.h>
-#if 0
-#define debug(fmt, args...) printf("%s: " fmt "\n", __FUNCTION__ , ##args)
-#else
-#define debug(fmt, args...)
-#endif
-
/* prototypes */
static int mlxd_probe(device_t dev);
static int mlxd_attach(device_t dev);
@@ -111,7 +105,7 @@
struct mlxd_softc *sc = (struct mlxd_softc *)dev->si_drv1;
struct disklabel *label;
- debug("called");
+ debug_called(1);
if (sc == NULL)
return (ENXIO);
@@ -139,7 +133,7 @@
{
struct mlxd_softc *sc = (struct mlxd_softc *)dev->si_drv1;
- debug("called");
+ debug_called(1);
if (sc == NULL)
return (ENXIO);
@@ -153,13 +147,13 @@
struct mlxd_softc *sc = (struct mlxd_softc *)dev->si_drv1;
int error;
- debug("called");
+ debug_called(1);
if (sc == NULL)
return (ENXIO);
if ((error = mlx_submit_ioctl(sc->mlxd_controller, sc->mlxd_drive, cmd, addr, flag, p)) != ENOIOCTL) {
- debug("mlx_submit_ioctl returned %d\n", error);
+ debug(0, "mlx_submit_ioctl returned %d\n", error);
return(error);
}
return (ENOTTY);
@@ -176,7 +170,7 @@
{
struct mlxd_softc *sc = (struct mlxd_softc *)bp->b_dev->si_drv1;
- debug("called");
+ debug_called(1);
/* bogus disk? */
if (sc == NULL) {
@@ -216,7 +210,7 @@
struct buf *bp = (struct buf *)data;
struct mlxd_softc *sc = (struct mlxd_softc *)bp->b_dev->si_drv1;
- debug("called");
+ debug_called(1);
if (bp->b_flags & B_ERROR)
bp->b_error = EIO;
@@ -231,7 +225,7 @@
mlxd_probe(device_t dev)
{
- debug("called");
+ debug_called(1);
device_set_desc(dev, "Mylex System Drive");
return (0);
@@ -245,7 +239,7 @@
char *state;
dev_t dsk;
- debug("called");
+ debug_called(1);
parent = device_get_parent(dev);
sc->mlxd_controller = (struct mlx_softc *)device_get_softc(parent);
@@ -291,7 +285,7 @@
{
struct mlxd_softc *sc = (struct mlxd_softc *)device_get_softc(dev);
- debug("called");
+ debug_called(1);
devstat_remove_entry(&sc->mlxd_stats);
Index: mlx_pci.c
===================================================================
RCS file: /local0/src/src/sys/dev/mlx/mlx_pci.c,v
retrieving revision 1.4
diff -u -r1.4 mlx_pci.c
--- mlx_pci.c 1999/12/11 00:00:12 1.4
+++ mlx_pci.c 2000/03/10 07:02:45
@@ -50,12 +50,6 @@
#include <dev/mlx/mlxvar.h>
#include <dev/mlx/mlxreg.h>
-#if 0
-#define debug(fmt, args...) printf("%s: " fmt "\n", __FUNCTION__ , ##args)
-#else
-#define debug(fmt, args...)
-#endif
-
static int mlx_pci_probe(device_t dev);
static int mlx_pci_attach(device_t dev);
@@ -90,7 +84,7 @@
int iftype;
char *desc;
} mlx_identifiers[] = {
-/* {0x1069, 0x0001, 0x0000, 0x0000, MLX_IFTYPE_2, "Mylex version 2 RAID interface"}, */
+ {0x1069, 0x0001, 0x0000, 0x0000, MLX_IFTYPE_2, "Mylex version 2 RAID interface"},
{0x1069, 0x0002, 0x0000, 0x0000, MLX_IFTYPE_3, "Mylex version 3 RAID interface"},
{0x1069, 0x0010, 0x0000, 0x0000, MLX_IFTYPE_4, "Mylex version 4 RAID interface"},
{0x1011, 0x1065, 0x1069, 0x0020, MLX_IFTYPE_5, "Mylex version 5 RAID interface"},
@@ -102,7 +96,7 @@
{
struct mlx_ident *m;
- debug("called");
+ debug_called(1);
for (m = mlx_identifiers; m->vendor != 0; m++) {
if ((m->vendor == pci_get_vendor(dev)) &&
@@ -124,16 +118,19 @@
int i, rid, error;
u_int32_t command;
- debug("called");
+ debug_called(1);
/*
* Make sure we are going to be able to talk to this board.
*/
- command = pci_read_config(dev, PCIR_COMMAND, 1);
+ command = pci_read_config(dev, PCIR_COMMAND, 2);
if ((command & PCIM_CMD_MEMEN) == 0) {
device_printf(dev, "memory window not available\n");
return(ENXIO);
}
+ /* force the busmaster enable bit on */
+ command |= PCIM_CMD_BUSMASTEREN;
+ pci_write_config(dev, PCIR_COMMAND, command, 2);
/*
* Initialise softc.
@@ -162,7 +159,16 @@
*/
/* type 3 adapters have an I/O region we don't use at base 0 */
- rid = (sc->mlx_iftype == MLX_IFTYPE_3) ? MLX_CFG_BASE1 : MLX_CFG_BASE0;
+ switch(sc->mlx_iftype) {
+ case MLX_IFTYPE_2:
+ case MLX_IFTYPE_3:
+ rid = MLX_CFG_BASE1;
+ break;
+ case MLX_IFTYPE_4:
+ case MLX_IFTYPE_5:
+ rid = MLX_CFG_BASE0;
+ break;
+ }
sc->mlx_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, 1, RF_ACTIVE);
if (sc->mlx_mem == NULL) {
device_printf(sc->mlx_dev, "couldn't allocate mailbox window\n");
@@ -180,7 +186,7 @@
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
- MAXBSIZE, MLX_NSEG, /* maxsize, nsegments */
+ MAXBSIZE, MLX_NSEG_NEW, /* maxsize, nsegments */
BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
BUS_DMA_ALLOCNOW, /* flags */
&sc->mlx_parent_dmat);
Index: mlxio.h
===================================================================
RCS file: /local0/src/src/sys/dev/mlx/mlxio.h,v
retrieving revision 1.1
diff -u -r1.1 mlxio.h
--- mlxio.h 1999/10/07 02:20:32 1.1
+++ mlxio.h 2000/03/10 07:02:45
@@ -79,6 +79,9 @@
/* command */
u_int16_t mu_status; /* command status returned */
u_int8_t mu_command[16]; /* command mailbox contents */
+
+ /* wrapper */
+ int mu_error; /* result of submission to driver */
};
#define MLX_NEXT_CHILD _IOWR('M', 0, int)
@@ -86,3 +89,4 @@
#define MLX_DETACH_DRIVE _IOW ('M', 2, int)
#define MLX_PAUSE_CHANNEL _IOW ('M', 3, struct mlx_pause)
#define MLX_COMMAND _IOWR('M', 4, struct mlx_usercommand)
+
Index: mlxreg.h
===================================================================
RCS file: /local0/src/src/sys/dev/mlx/mlxreg.h,v
retrieving revision 1.5
diff -u -r1.5 mlxreg.h
--- mlxreg.h 1999/12/22 01:21:27 1.5
+++ mlxreg.h 2000/03/10 07:02:45
@@ -26,9 +26,6 @@
* $FreeBSD: src/sys/dev/mlx/mlxreg.h,v 1.5 1999/12/22 01:21:27 msmith Exp $
*/
-#define MLX_CFG_BASE0 0x10 /* first region */
-#define MLX_CFG_BASE1 0x14 /* second region (type 3 only) */
-
#define MLX_BLKSIZE 512 /* fixed feature */
/*
@@ -47,6 +44,11 @@
#define MLX_CMD_STOPCHANNEL 0x13
#define MLX_CMD_STARTCHANNEL 0x12
+#ifdef _KERNEL
+
+#define MLX_CFG_BASE0 0x10 /* first region */
+#define MLX_CFG_BASE1 0x14 /* second region (type 3 only) */
+
/*
* Status values.
*/
@@ -65,6 +67,9 @@
#define MLX_V3_IDBR 0x40
#define MLX_V3_ODBR 0x41
#define MLX_V3_IER 0x43
+#define MLX_V3_FWERROR 0x3f
+#define MLX_V3_FWERROR_PARAM1 0x00
+#define MLX_V3_FWERROR_PARAM2 0x01
#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)
@@ -74,21 +79,33 @@
#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_GET_FWERROR(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_FWERROR)
+#define MLX_V3_PUT_FWERROR(sc, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V3_FWERROR, val)
+#define MLX_V3_GET_FWERROR_PARAM1(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_FWERROR_PARAM1)
+#define MLX_V3_GET_FWERROR_PARAM2(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_FWERROR_PARAM2)
#define MLX_V3_IDB_FULL (1<<0) /* mailbox is full */
+#define MLX_V3_IDB_INIT_BUSY (1<<1) /* initialisation in progress */
+
#define MLX_V3_IDB_SACK (1<<1) /* acknowledge status read */
#define MLX_V3_ODB_SAVAIL (1<<0) /* status is available */
+#define MLX_V3_FWERROR_PEND (1<<2) /* firmware error pending */
+
/*
* Accessor defines for the V4 interface.
*/
#define MLX_V4_MAILBOX 0x1000
+#define MLX_V4_MAILBOX_LENGTH 16
#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
+#define MLX_V4_FWERROR 0x103f
+#define MLX_V4_FWERROR_PARAM1 0x1000
+#define MLX_V4_FWERROR_PARAM2 0x1001
/* 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)
@@ -99,8 +116,13 @@
#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_GET_FWERROR(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V4_FWERROR)
+#define MLX_V4_PUT_FWERROR(sc, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_FWERROR, val)
+#define MLX_V4_GET_FWERROR_PARAM1(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V4_FWERROR_PARAM1)
+#define MLX_V4_GET_FWERROR_PARAM2(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V4_FWERROR_PARAM2)
#define MLX_V4_IDB_FULL (1<<0) /* mailbox is full */
+#define MLX_V4_IDB_INIT_BUSY (1<<1) /* initialisation in progress */
#define MLX_V4_IDB_HWMBOX_CMD (1<<0) /* posted hardware mailbox command */
#define MLX_V4_IDB_SACK (1<<1) /* acknowledge status read */
@@ -115,15 +137,21 @@
#define MLX_V4_IER_MASK 0xfb /* message unit interrupt mask */
#define MLX_V4_IER_DISINT (1<<2) /* interrupt disable bit */
+#define MLX_V4_FWERROR_PEND (1<<2) /* firmware error pending */
+
/*
* Accessor defines for the V5 interface
*/
#define MLX_V5_MAILBOX 0x50
+#define MLX_V5_MAILBOX_LENGTH 16
#define MLX_V5_STATUS_IDENT 0x5d
#define MLX_V5_STATUS 0x5e
#define MLX_V5_IDBR 0x60
#define MLX_V5_ODBR 0x61
#define MLX_V5_IER 0x34
+#define MLX_V5_FWERROR 0x63
+#define MLX_V5_FWERROR_PARAM1 0x50
+#define MLX_V5_FWERROR_PARAM2 0x51
#define MLX_V5_PUT_MAILBOX(sc, idx, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V5_MAILBOX + idx, val)
#define MLX_V5_GET_STATUS_IDENT(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V5_STATUS_IDENT)
@@ -133,11 +161,17 @@
#define MLX_V5_GET_ODBR(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V5_ODBR)
#define MLX_V5_PUT_ODBR(sc, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V5_ODBR, val)
#define MLX_V5_PUT_IER(sc, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V5_IER, val)
+#define MLX_V5_GET_FWERROR(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V5_FWERROR)
+#define MLX_V5_PUT_FWERROR(sc, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V5_FWERROR, val)
+#define MLX_V5_GET_FWERROR_PARAM1(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V5_FWERROR_PARAM1)
+#define MLX_V5_GET_FWERROR_PARAM2(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V5_FWERROR_PARAM2)
#define MLX_V5_IDB_EMPTY (1<<0) /* mailbox is empty */
+#define MLX_V5_IDB_INIT_DONE (1<<1) /* initialisation has completed */
#define MLX_V5_IDB_HWMBOX_CMD (1<<0) /* posted hardware mailbox command */
#define MLX_V5_IDB_SACK (1<<1) /* acknowledge status read */
+#define MLX_V5_IDB_RESET (1<<3) /* reset request */
#define MLX_V5_IDB_MEMMBOX_CMD (1<<4) /* posted memory mailbox command */
#define MLX_V5_ODB_HWSAVAIL (1<<0) /* status is available for hardware mailbox */
@@ -148,6 +182,9 @@
#define MLX_V5_IER_DISINT (1<<2) /* interrupt disable bit */
+#define MLX_V5_FWERROR_PEND (1<<2) /* firmware error pending */
+
+#endif /* _KERNEL */
/*
* Scatter-gather list format, type 1, kind 00.
@@ -285,6 +322,108 @@
u_int32_t rb_remaining;
} __attribute__ ((packed));
+struct mlx_config2
+{
+ u_int16_t cf_flags1;
+#define MLX_CF2_ACTV_NEG (1<<1)
+#define MLX_CF2_NORSTRTRY (1<<7)
+#define MLX_CF2_STRGWRK (1<<8)
+#define MLX_CF2_HPSUPP (1<<9)
+#define MLX_CF2_NODISCN (1<<10)
+#define MLX_CF2_ARM (1<<13)
+#define MLX_CF2_OFM (1<<15)
+#define MLX_CF2_AEMI (MLX_CF2_ARM | MLX_CF2_OFM)
+ u_int8_t cf_oemid;
+ u_int8_t cf_oem_model;
+ u_int8_t cf_physical_sector;
+ u_int8_t cf_logical_sector;
+ u_int8_t cf_blockfactor;
+ u_int8_t cf_flags2;
+#define MLX_CF2_READAH (1<<0)
+#define MLX_CF2_BIOSDLY (1<<1)
+#define MLX_CF2_REASS1S (1<<4)
+#define MLX_CF2_FUAENABL (1<<6)
+#define MLX_CF2_R5ALLS (1<<7)
+ u_int8_t cf_rcrate;
+ u_int8_t cf_res1;
+ u_int8_t cf_blocks_per_cache_line;
+ u_int8_t cf_blocks_per_stripe;
+ u_int8_t cf_scsi_param_0;
+ u_int8_t cf_scsi_param_1;
+ u_int8_t cf_scsi_param_2;
+ u_int8_t cf_scsi_param_3;
+ u_int8_t cf_scsi_param_4;
+ u_int8_t cf_scsi_param_5;
+ u_int8_t cf_scsi_initiator_id;
+ u_int8_t cf_res2;
+ u_int8_t cf_startup_mode;
+ u_int8_t cf_simultaneous_spinup_devices;
+ u_int8_t cf_delay_between_spinups;
+ u_int8_t cf_res3;
+ u_int16_t cf_checksum;
+} __attribute__ ((packed));
+
+struct mlx_sys_drv_span
+{
+ u_int32_t sp_start_lba;
+ u_int32_t sp_nblks;
+ u_int8_t sp_arm[8];
+} __attribute__ ((packed));
+
+struct mlx_sys_drv
+{
+ u_int8_t sd_status;
+ u_int8_t sd_ext_status;
+ u_int8_t sd_mod1;
+ u_int8_t sd_mod2;
+ u_int8_t sd_raidlevel;
+#define MLX_SYS_DRV_WRITEBACK (1<<7)
+#define MLX_SYS_DRV_RAID0 0
+#define MLX_SYS_DRV_RAID1 1
+#define MLX_SYS_DRV_RAID3 3
+#define MLX_SYS_DRV_RAID5 5
+#define MLX_SYS_DRV_RAID6 6
+#define MLX_SYS_DRV_JBOD 7
+ u_int8_t sd_valid_arms;
+ u_int8_t sd_valid_spans;
+ u_int8_t sd_init_state;
+#define MLX_SYS_DRV_INITTED 0x81;
+ struct mlx_sys_drv_span span[4];
+} __attribute__ ((packed));
+
+struct mlx_phys_drv
+{
+ u_int16_t pd_flags;
+#define MLX_PHYS_DRV_PRESENT (1<<0)
+#define MLX_PHYS_DRV_OTHER 0x0000
+#define MLX_PHYS_DRV_DISK 0x0100
+#define MLX_PHYS_DRV_SEQUENTIAL 0x0200
+#define MLX_PHYS_DRV_CDROM 0x0300
+#define MLX_PHYS_DRV_FAST20 (1<<11)
+#define MLX_PHYS_DRV_SYNC (1<<12)
+#define MLX_PHYS_DRV_FAST (1<<13)
+#define MLX_PHYS_DRV_WIDE (1<<14)
+#define MLX_PHYS_DRV_TAG (1<<15)
+ u_int8_t pd_status;
+#define MLX_PHYS_DRV_DEAD 0x00
+#define MLX_PHYS_DRV_WRONLY 0x02
+#define MLX_PHYS_DRV_ONLINE 0x03
+#define MLX_PHYS_DRV_STANDBY 0x10
+ u_int8_t pd_period;
+ u_int8_t pd_offset;
+ u_int32_t pd_config_size;
+} __attribute__ ((packed));
+
+struct mlx_core_cfg
+{
+ u_int8_t cc_num_sys_drives;
+ u_int8_t cc_res1[3];
+ struct mlx_sys_drv cc_sys_drives[32];
+ struct mlx_phys_drv cc_phys_drives[64];
+} __attribute__ ((packed));
+
+
+#ifdef _KERNEL
/*
* Inlines to build various command structures
*/
@@ -406,3 +545,5 @@
mc->mc_mailbox[0xb] = (f4 >> 24) & 0xff;
mc->mc_mailbox[0xc] = f5;
}
+
+#endif /* _KERNEL */
Index: mlxvar.h
===================================================================
RCS file: /local0/src/src/sys/dev/mlx/mlxvar.h,v
retrieving revision 1.5
diff -u -r1.5 mlxvar.h
--- mlxvar.h 1999/12/22 01:21:28 1.5
+++ mlxvar.h 2000/03/10 07:02:45
@@ -27,14 +27,30 @@
*/
/*
- * We could actually use all 33 segments, but using only 32 means that
- * each scatter/gather map is 256 bytes in size, and thus we don't have to worry about
+ * Debugging levels:
+ * 0 - quiet, only emit warnings
+ * 1 - noisy, emit major function points and things done
+ * 2 - extremely noisy, emit trace items in loops, etc.
+ */
+#ifdef MLX_DEBUG
+#define debug(level, fmt, args...) do { if (level <= MLX_DEBUG) printf("%s: " fmt "\n", __FUNCTION__ , ##args); } while(0)
+#define debug_called(level) do { if (level <= MLX_DEBUG) printf(__FUNCTION__ ": called\n"); } while(0)
+#else
+#define debug(level, fmt, args...)
+#define debug_called(level)
+#endif
+
+
+/*
+ * We could actually use all 17/33 segments, but using only 16/32 means that
+ * each scatter/gather map is 128/256 bytes in size, and thus we don't have to worry about
* maps crossing page boundaries.
*/
-#define MLX_NSEG 32 /* max scatter/gather segments we use */
+#define MLX_NSEG_OLD 16 /* max scatter/gather segments we use 3.x and earlier */
+#define MLX_NSEG_NEW 32 /* max scatter/gather segments we use 4.x and later */
#define MLX_NSLOTS 256 /* max number of command slots */
-#define MLX_MAXDRIVES 32
+#define MLX_MAXDRIVES 32 /* max number of system drives */
/*
* Structure describing a System Drive as attached to the controller.
@@ -90,6 +106,7 @@
{
/* bus connections */
device_t mlx_dev;
+ dev_t mlx_dev_t;
struct resource *mlx_mem; /* mailbox interface window */
bus_space_handle_t mlx_bhandle; /* bus space handle */
bus_space_tag_t mlx_btag; /* bus space tag */
@@ -103,6 +120,7 @@
u_int32_t mlx_sgbusaddr; /* s/g table base address in bus space */
bus_dma_tag_t mlx_sg_dmat; /* s/g buffer DMA tag */
bus_dmamap_t mlx_sg_dmamap; /* map for s/g buffers */
+ int mlx_sg_nseg; /* max number of s/g entries */
/* controller limits and features */
struct mlx_enquiry2 *mlx_enq2;
@@ -138,15 +156,19 @@
struct mlx_pause mlx_pause; /* pending pause operation details */
int mlx_locks; /* reentrancy avoidance */
+ int mlx_flags;
+#define MLX_SPINUP_REPORTED (1<<0) /* "spinning up drives" message displayed */
/* interface-specific accessor functions */
int mlx_iftype; /* interface protocol */
+#define MLX_IFTYPE_2 2
#define MLX_IFTYPE_3 3
#define MLX_IFTYPE_4 4
#define MLX_IFTYPE_5 5
int (* mlx_tryqueue)(struct mlx_softc *sc, struct mlx_command *mc);
int (* mlx_findcomplete)(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
void (* mlx_intaction)(struct mlx_softc *sc, int action);
+ int (* mlx_fw_handshake)(struct mlx_softc *sc, int *error, int *param1, int *param2);
#define MLX_INTACTION_DISABLE 0
#define MLX_INTACTION_ENABLE 1
};
[-- Attachment #3 --]
\\ Give a man a fish, and you feed him for a day. \\ Mike Smith
\\ Tell him he should learn how to fish himself, \\ msmith@freebsd.org
\\ and he'll hate you for a lifetime. \\ msmith@cdrom.com
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200003100708.XAA00710>
