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.
This commit is contained in:
Mike Smith 1999-10-14 02:54:06 +00:00
parent bdf5faebaf
commit f6b84b08c9
5 changed files with 180 additions and 58 deletions

View File

@ -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);
@ -2167,6 +2182,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;

View File

@ -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);
}

View File

@ -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}
};

View File

@ -50,6 +50,65 @@
#define MLX_STATUS_WEDGED 0xdead /* controller not listening */
#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.
*/

View File

@ -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
};
/*
@ -204,31 +202,6 @@ extern int mlx_submit_ioctl(struct mlx_softc *sc, struct mlx_sysdrive *drive, u_
caddr_t addr, int32_t flag, struct proc *p);
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
*/