diff --git a/sys/dev/mlx/mlx.c b/sys/dev/mlx/mlx.c index d353ada28e9..95b83c9a216 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); @@ -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; diff --git a/sys/dev/mlx/mlx_disk.c b/sys/dev/mlx/mlx_disk.c index 85f8314cb67..9e2f571e406 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 7d791a8423b..8aa9e1a0032 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 713022334df..e287067c7cb 100644 --- a/sys/dev/mlx/mlxreg.h +++ b/sys/dev/mlx/mlxreg.h @@ -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. */ diff --git a/sys/dev/mlx/mlxvar.h b/sys/dev/mlx/mlxvar.h index 7679dbbce9b..ec69b25eebc 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 - }; /* @@ -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 */