summaryrefslogtreecommitdiffstats
path: root/sys/dev/mlx
diff options
context:
space:
mode:
authormsmith <msmith@FreeBSD.org>1999-12-22 01:21:28 +0000
committermsmith <msmith@FreeBSD.org>1999-12-22 01:21:28 +0000
commit84a1c51a20fd7906da50daf7f340ba1008ec04e7 (patch)
tree4336a5b251cf220a7b17e9698b586c834b2448e4 /sys/dev/mlx
parentd55ac72ab6851d040ca79a49de956347c872ed78 (diff)
downloadFreeBSD-src-84a1c51a20fd7906da50daf7f340ba1008ec04e7.zip
FreeBSD-src-84a1c51a20fd7906da50daf7f340ba1008ec04e7.tar.gz
Updates resulting from new documentation from Mylex and some cleaning:
- Don't keep private copies of some of the data fields from the ENQUIRY and ENQUIRY2 commands. Instead, standardise on the ENQUIRY2 command for initial adapter information, and keep a copy of the entire structure. Refer to it where appropriate. - Move all of the controller description functionality into a new function. Print lots more controller data if bootverbose is set. Add knowledge of the DAC960 PR, PT, PTL0 and PRL controllers, rename the 960PTL -> PTL0 and 1100P -> 1100PVX. - Correctly terminate an error message. The controller interface procedures have been reviewed against the Mylex-supplied documentation; no changes appear necessary at this time.
Diffstat (limited to 'sys/dev/mlx')
-rw-r--r--sys/dev/mlx/mlx.c148
-rw-r--r--sys/dev/mlx/mlx_disk.c2
-rw-r--r--sys/dev/mlx/mlxreg.h4
-rw-r--r--sys/dev/mlx/mlxvar.h16
4 files changed, 95 insertions, 75 deletions
diff --git a/sys/dev/mlx/mlx.c b/sys/dev/mlx/mlx.c
index 6bf2d3f..8057e59 100644
--- a/sys/dev/mlx/mlx.c
+++ b/sys/dev/mlx/mlx.c
@@ -142,7 +142,7 @@ static void mlx_complete(struct mlx_softc *sc);
* Debugging.
*/
static char *mlx_diagnose_command(struct mlx_command *mc);
-static char *mlx_name_controller(u_int32_t hwid);
+static void mlx_describe_controller(struct mlx_softc *sc);
/*
@@ -201,6 +201,10 @@ mlx_free(struct mlx_softc *sc)
if (sc->mlx_mem != NULL)
bus_release_resource(sc->mlx_dev, SYS_RES_MEMORY,
(sc->mlx_iftype == MLX_IFTYPE_3) ? MLX_CFG_BASE1 : MLX_CFG_BASE0, sc->mlx_mem);
+
+ /* free controller enquiry data */
+ if (sc->mlx_enq2 != NULL)
+ free(sc->mlx_enq2, M_DEVBUF);
}
/********************************************************************************
@@ -273,9 +277,7 @@ mlx_sglist_map(struct mlx_softc *sc)
int
mlx_attach(struct mlx_softc *sc)
{
- struct mlx_enquiry *me;
- struct mlx_enquiry2 *me2;
- int rid, error;
+ int rid, error, fwminor;
debug("called");
@@ -350,69 +352,48 @@ mlx_attach(struct mlx_softc *sc)
/*
* Create an initial set of s/g mappings.
*/
- sc->mlx_maxiop = 2;
+ sc->mlx_maxiop = 8;
error = mlx_sglist_map(sc);
if (error != 0) {
device_printf(sc->mlx_dev, "couldn't make initial s/g list mapping\n");
return(error);
}
- /*
- * Probe the controller for more information.
- */
- /* send an ENQUIRY to the controller */
- if ((me = mlx_enquire(sc, MLX_CMD_ENQUIRY, sizeof(*me), NULL)) == NULL) {
- device_printf(sc->mlx_dev, "ENQUIRY failed\n");
- return(ENXIO);
- }
-
- /* pull information out of the ENQUIRY result */
- sc->mlx_fwminor = me->me_fwminor;
- sc->mlx_fwmajor = me->me_fwmajor;
- sc->mlx_maxiop = me->me_max_commands;
- sc->mlx_lastevent = sc->mlx_currevent = me->me_event_log_seq_num;
- free(me, M_DEVBUF);
-
/* send an ENQUIRY2 to the controller */
- if ((me2 = mlx_enquire(sc, MLX_CMD_ENQUIRY2, sizeof(*me2), NULL)) == NULL) {
+ if ((sc->mlx_enq2 = mlx_enquire(sc, MLX_CMD_ENQUIRY2, sizeof(struct mlx_enquiry2), NULL)) == NULL) {
device_printf(sc->mlx_dev, "ENQUIRY2 failed\n");
return(ENXIO);
}
- /* pull information out of the ENQUIRY2 result */
- sc->mlx_nchan = me2->me_configured_channels;
- sc->mlx_maxiosize = me2->me_maxblk;
- sc->mlx_maxtarg = me2->me_max_targets;
- sc->mlx_maxtags = me2->me_max_tags;
- sc->mlx_scsicap = me2->me_scsi_cap;
- sc->mlx_hwid = me2->me_hardware_id;
+ /*
+ * We don't (yet) know where the event log is up to.
+ */
+ sc->mlx_lastevent = -1;
- /* print a little information about the controller and ourselves */
- device_printf(sc->mlx_dev, "Mylex %s, firmware %d.%02d, %dMB RAM\n",
- mlx_name_controller(sc->mlx_hwid), sc->mlx_fwmajor, sc->mlx_fwminor,
- me2->me_mem_size / (1024 * 1024));
- free(me2, M_DEVBUF);
+ /* print a little information about the controller */
+ mlx_describe_controller(sc);
/*
* Do quirk/feature related things.
*/
+ fwminor = (sc->mlx_enq2->me_firmware_id >> 8) & 0xff;
switch(sc->mlx_iftype) {
case MLX_IFTYPE_3:
/* XXX certify 3.52? */
- if (sc->mlx_fwminor < 51) {
+ if (fwminor < 51) {
device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
device_printf(sc->mlx_dev, " *** WARNING *** Use revision 3.51 or later\n");
}
break;
case MLX_IFTYPE_4:
/* XXX certify firmware versions? */
- if (sc->mlx_fwminor < 6) {
+ if (fwminor < 6) {
device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
device_printf(sc->mlx_dev, " *** WARNING *** Use revision 4.06 or later\n");
}
break;
case MLX_IFTYPE_5:
- if (sc->mlx_fwminor < 7) {
+ if (fwminor < 7) {
device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
device_printf(sc->mlx_dev, " *** WARNING *** Use revision 5.07 or later\n");
}
@@ -426,6 +407,7 @@ mlx_attach(struct mlx_softc *sc)
* Create the final set of s/g mappings now that we know how many commands
* the controller actually supports.
*/
+ sc->mlx_maxiop = sc->mlx_enq2->me_max_commands;
error = mlx_sglist_map(sc);
if (error != 0) {
device_printf(sc->mlx_dev, "couldn't make initial s/g list mapping\n");
@@ -470,7 +452,7 @@ mlx_startup(struct mlx_softc *sc)
*/
mes = mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(*mes) * MLX_MAXDRIVES, NULL);
if (mes == NULL) {
- device_printf(sc->mlx_dev, "error fetching drive status");
+ device_printf(sc->mlx_dev, "error fetching drive status\n");
return;
}
@@ -798,7 +780,7 @@ mlx_ioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
sc->mlx_pause.mp_which = 0;
} else {
/* fix for legal channels */
- mp->mp_which &= ((1 << sc->mlx_nchan) -1);
+ mp->mp_which &= ((1 << sc->mlx_enq2->me_actual_channels) -1);
/* check time values */
if ((mp->mp_when < 0) || (mp->mp_when > 3600))
return(EINVAL);
@@ -1016,14 +998,16 @@ mlx_periodic_enquiry(struct mlx_command *mc)
{
struct mlx_enquiry *me = (struct mlx_enquiry *)mc->mc_data;
- /* New stuff in the event log? */
- if (me->me_event_log_seq_num != sc->mlx_lastevent) {
+ if (sc->mlx_lastevent == -1) {
+ /* initialise our view of the event log */
+ sc->mlx_currevent = sc->mlx_lastevent = me->me_event_log_seq_num;
+ } else if (me->me_event_log_seq_num != sc->mlx_lastevent) {
/* record where current events are up to */
sc->mlx_currevent = me->me_event_log_seq_num;
device_printf(sc->mlx_dev, "event log pointer was %d, now %d\n",
sc->mlx_lastevent, sc->mlx_currevent);
- /* start poll of event log */
+ /* drain new eventlog entries */
mlx_periodic_eventlog_poll(sc);
}
break;
@@ -1269,7 +1253,7 @@ mlx_pause_action(struct mlx_softc *sc)
}
/* build commands for every channel requested */
- for (i = 0; i < sc->mlx_nchan; i++) {
+ for (i = 0; i < sc->mlx_enq2->me_actual_channels; i++) {
if ((1 << i) & sc->mlx_pause.mp_which) {
/* get ourselves a command buffer */
@@ -1750,13 +1734,13 @@ static int
mlx_getslot(struct mlx_command *mc)
{
struct mlx_softc *sc = mc->mc_sc;
- int s, slot, limit;
+ int s, slot;
debug("called mc %p sc %p", mc, sc);
/* enforce slot-usage limit */
- limit = (mc->mc_flags & MLX_CMD_PRIORITY) ? sc->mlx_maxiop : sc->mlx_maxiop - 4;
- if (sc->mlx_busycmds > limit)
+ if (sc->mlx_busycmds >= ((mc->mc_flags & MLX_CMD_PRIORITY) ?
+ sc->mlx_maxiop : sc->mlx_maxiop - 4))
return(EBUSY);
/*
@@ -1977,10 +1961,6 @@ mlx_complete(struct mlx_softc *sc)
while (mc != NULL) {
nc = TAILQ_NEXT(mc, mc_link);
- /* XXX this is slightly bogus */
- if (count++ > (sc->mlx_maxiop * 2))
- panic("mlx_work list corrupt!");
-
/* Command has been completed in some fashion */
if (mc->mc_status != MLX_STATUS_BUSY) {
@@ -2421,31 +2401,79 @@ static struct
{0x02, "960PL"},
{0x10, "960PG"},
{0x11, "960PJ"},
- {0x16, "960PTL"},
- {0x20, "1164P"},
+ {0x12, "960PR"},
+ {0x13, "960PT"},
+ {0x14, "960PTL0"},
+ {0x15, "960PRL"},
+ {0x16, "960PTL1"},
+ {0x20, "1164PVX"},
{-1, NULL}
};
-static char *
-mlx_name_controller(u_int32_t hwid)
+static void
+mlx_describe_controller(struct mlx_softc *sc)
{
static char buf[80];
char *model;
- int nchn, i;
+ int i;
for (i = 0, model = NULL; mlx_controller_names[i].name != NULL; i++) {
- if ((hwid & 0xff) == mlx_controller_names[i].hwid) {
+ if ((sc->mlx_enq2->me_hardware_id & 0xff) == mlx_controller_names[i].hwid) {
model = mlx_controller_names[i].name;
break;
}
}
if (model == NULL) {
- sprintf(buf, " model 0x%x", hwid & 0xff);
+ sprintf(buf, " model 0x%x", sc->mlx_enq2->me_hardware_id & 0xff);
model = buf;
}
- nchn = (hwid >> 8) & 0xff;
- sprintf(buf, "DAC%s, %d channel%s", model, nchn, nchn > 1 ? "s" : "");
- return(buf);
+ device_printf(sc->mlx_dev, "DAC%s, %d channel%s, firmware %d.%02d-%c-%d, %dMB RAM\n",
+ model,
+ sc->mlx_enq2->me_actual_channels,
+ sc->mlx_enq2->me_actual_channels > 1 ? "s" : "",
+ sc->mlx_enq2->me_firmware_id & 0xff,
+ (sc->mlx_enq2->me_firmware_id >> 8) & 0xff,
+ (sc->mlx_enq2->me_firmware_id >> 16),
+ (sc->mlx_enq2->me_firmware_id >> 24) & 0xff,
+ sc->mlx_enq2->me_mem_size / (1024 * 1024));
+
+ if (bootverbose) {
+ device_printf(sc->mlx_dev, " Hardware ID 0x%08x\n", sc->mlx_enq2->me_hardware_id);
+ device_printf(sc->mlx_dev, " Firmware ID 0x%08x\n", sc->mlx_enq2->me_firmware_id);
+ device_printf(sc->mlx_dev, " Configured/Actual channels %d/%d\n", sc->mlx_enq2->me_configured_channels,
+ sc->mlx_enq2->me_actual_channels);
+ device_printf(sc->mlx_dev, " Max Targets %d\n", sc->mlx_enq2->me_max_targets);
+ device_printf(sc->mlx_dev, " Max Tags %d\n", sc->mlx_enq2->me_max_tags);
+ device_printf(sc->mlx_dev, " Max System Drives %d\n", sc->mlx_enq2->me_max_sys_drives);
+ device_printf(sc->mlx_dev, " Max Arms %d\n", sc->mlx_enq2->me_max_arms);
+ device_printf(sc->mlx_dev, " Max Spans %d\n", sc->mlx_enq2->me_max_spans);
+ device_printf(sc->mlx_dev, " DRAM/cache/flash/NVRAM size %d/%d/%d/%d\n", sc->mlx_enq2->me_mem_size,
+ sc->mlx_enq2->me_cache_size, sc->mlx_enq2->me_flash_size, sc->mlx_enq2->me_nvram_size);
+ device_printf(sc->mlx_dev, " DRAM type %d\n", sc->mlx_enq2->me_mem_type);
+ device_printf(sc->mlx_dev, " Clock Speed %dns\n", sc->mlx_enq2->me_clock_speed);
+ device_printf(sc->mlx_dev, " Hardware Speed %dns\n", sc->mlx_enq2->me_hardware_speed);
+ device_printf(sc->mlx_dev, " Max Commands %d\n", sc->mlx_enq2->me_max_commands);
+ device_printf(sc->mlx_dev, " Max SG Entries %d\n", sc->mlx_enq2->me_max_sg);
+ device_printf(sc->mlx_dev, " Max DP %d\n", sc->mlx_enq2->me_max_dp);
+ device_printf(sc->mlx_dev, " Max IOD %d\n", sc->mlx_enq2->me_max_iod);
+ device_printf(sc->mlx_dev, " Max Comb %d\n", sc->mlx_enq2->me_max_comb);
+ device_printf(sc->mlx_dev, " Latency %ds\n", sc->mlx_enq2->me_latency);
+ device_printf(sc->mlx_dev, " SCSI Timeout %ds\n", sc->mlx_enq2->me_scsi_timeout);
+ device_printf(sc->mlx_dev, " Min Free Lines %d\n", sc->mlx_enq2->me_min_freelines);
+ device_printf(sc->mlx_dev, " Rate Constant %d\n", sc->mlx_enq2->me_rate_const);
+ device_printf(sc->mlx_dev, " MAXBLK %d\n", sc->mlx_enq2->me_maxblk);
+ device_printf(sc->mlx_dev, " Blocking Factor %d sectors\n", sc->mlx_enq2->me_blocking_factor);
+ device_printf(sc->mlx_dev, " Cache Line Size %d blocks\n", sc->mlx_enq2->me_cacheline);
+ device_printf(sc->mlx_dev, " SCSI Capability %s%dMHz, %d bit\n",
+ sc->mlx_enq2->me_scsi_cap & (1<<4) ? "differential " : "",
+ (1 << ((sc->mlx_enq2->me_scsi_cap >> 2) & 3)) * 10,
+ 8 << (sc->mlx_enq2->me_scsi_cap & 0x3));
+ device_printf(sc->mlx_dev, " Firmware Build Number %d\n", sc->mlx_enq2->me_firmware_build);
+ device_printf(sc->mlx_dev, " Fault Management Type %d\n", sc->mlx_enq2->me_fault_mgmt_type);
+ device_printf(sc->mlx_dev, " Features %b\n", sc->mlx_enq2->me_firmware_features,
+ "\20\4Background Init\3Read Ahead\2MORE\1Cluster\n");
+
+ }
}
/********************************************************************************
diff --git a/sys/dev/mlx/mlx_disk.c b/sys/dev/mlx/mlx_disk.c
index 9624a9a..acd3d79 100644
--- a/sys/dev/mlx/mlx_disk.c
+++ b/sys/dev/mlx/mlx_disk.c
@@ -281,7 +281,7 @@ mlxd_attach(device_t dev)
disks_registered++;
/* set maximum I/O size */
- dsk->si_iosize_max = sc->mlxd_controller->mlx_maxiosize * MLX_BLKSIZE;
+ dsk->si_iosize_max = sc->mlxd_controller->mlx_enq2->me_maxblk * MLX_BLKSIZE;
return (0);
}
diff --git a/sys/dev/mlx/mlxreg.h b/sys/dev/mlx/mlxreg.h
index f50e202..d004a12c 100644
--- a/sys/dev/mlx/mlxreg.h
+++ b/sys/dev/mlx/mlxreg.h
@@ -214,7 +214,7 @@ struct mlx_enquiry2 /* MLX_CMD_ENQUIRY2 */
u_int16_t me_clock_speed;
u_int16_t me_mem_speed;
u_int16_t me_hardware_speed;
- u_int8_t res4[10];
+ u_int8_t res4[12];
u_int16_t me_max_commands;
u_int16_t me_max_sg;
u_int16_t me_max_dp;
@@ -235,7 +235,7 @@ struct mlx_enquiry2 /* MLX_CMD_ENQUIRY2 */
u_int16_t me_cacheline;
u_int8_t me_scsi_cap;
u_int8_t res9[5];
- u_int16_t me_fimware_build;
+ u_int16_t me_firmware_build;
u_int8_t me_fault_mgmt_type;
u_int8_t res10;
u_int32_t me_firmware_features;
diff --git a/sys/dev/mlx/mlxvar.h b/sys/dev/mlx/mlxvar.h
index 04c3246..3465358 100644
--- a/sys/dev/mlx/mlxvar.h
+++ b/sys/dev/mlx/mlxvar.h
@@ -105,13 +105,8 @@ struct mlx_softc
bus_dmamap_t mlx_sg_dmamap; /* map for s/g buffers */
/* controller limits and features */
- int mlx_hwid; /* hardware identifier */
- int mlx_maxiop; /* maximum number of I/O operations */
- int mlx_nchan; /* number of active channels */
- int mlx_maxiosize; /* largest I/O for this controller */
- int mlx_maxtarg; /* maximum number of targets per channel */
- int mlx_maxtags; /* maximum number of tags per device */
- int mlx_scsicap; /* SCSI capabilities */
+ struct mlx_enquiry2 *mlx_enq2;
+ int mlx_maxiop; /* hard maximum number of commands */
int mlx_feature; /* controller features/quirks */
#define MLX_FEAT_PAUSEWORKS (1<<0) /* channel pause works as expected */
@@ -125,8 +120,6 @@ struct mlx_softc
int mlx_waitbufs; /* number of bufs awaiting commands */
/* controller status */
- u_int8_t mlx_fwminor; /* firmware revision */
- u_int8_t mlx_fwmajor;
int mlx_geom;
#define MLX_GEOM_128_32 0 /* geoemetry translation modes */
#define MLX_GEOM_256_63 1
@@ -137,9 +130,8 @@ struct mlx_softc
#define MLX_STATE_SUSPEND (1<<3) /* controller is suspended */
struct callout_handle mlx_timeout; /* periodic status monitor */
time_t mlx_lastpoll; /* last time_second we polled for status */
- u_int16_t mlx_lastevent; /* sequence number of the last event we recorded */
- u_int16_t mlx_currevent; /* sequence number last time we looked */
- int mlx_polling; /* if > 0, polling operations still running */
+ int mlx_lastevent; /* sequence number of the last event we recorded */
+ int mlx_currevent; /* sequence number last time we looked */
int mlx_rebuild; /* if >= 0, drive is being rebuilt */
u_int32_t mlx_rebuildstat;/* blocks left to rebuild if active */
int mlx_check; /* if >= 0, drive is being checked */
OpenPOWER on IntegriCloud