mlx.c revision 166901
1/*-
2 * Copyright (c) 1999 Michael Smith
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 *	$FreeBSD: head/sys/dev/mlx/mlx.c 166901 2007-02-23 12:19:07Z piso $
27 */
28
29/*
30 * Driver for the Mylex DAC960 family of RAID controllers.
31 */
32
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/malloc.h>
36#include <sys/kernel.h>
37
38#include <sys/bus.h>
39#include <sys/conf.h>
40#include <sys/stat.h>
41
42#include <machine/resource.h>
43#include <machine/bus.h>
44#include <machine/clock.h>
45#include <sys/rman.h>
46
47#include <geom/geom_disk.h>
48
49#include <dev/mlx/mlx_compat.h>
50#include <dev/mlx/mlxio.h>
51#include <dev/mlx/mlxvar.h>
52#include <dev/mlx/mlxreg.h>
53
54static struct cdevsw mlx_cdevsw = {
55	.d_version =	D_VERSION,
56	.d_flags =	D_NEEDGIANT,
57	.d_open =	mlx_open,
58	.d_close =	mlx_close,
59	.d_ioctl =	mlx_ioctl,
60	.d_name =	"mlx",
61};
62
63devclass_t	mlx_devclass;
64
65/*
66 * Per-interface accessor methods
67 */
68static int			mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
69static int			mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
70static void			mlx_v3_intaction(struct mlx_softc *sc, int action);
71static int			mlx_v3_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2);
72
73static int			mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
74static int			mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
75static void			mlx_v4_intaction(struct mlx_softc *sc, int action);
76static int			mlx_v4_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2);
77
78static int			mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
79static int			mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
80static void			mlx_v5_intaction(struct mlx_softc *sc, int action);
81static int			mlx_v5_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2);
82
83/*
84 * Status monitoring
85 */
86static void			mlx_periodic(void *data);
87static void			mlx_periodic_enquiry(struct mlx_command *mc);
88static void			mlx_periodic_eventlog_poll(struct mlx_softc *sc);
89static void			mlx_periodic_eventlog_respond(struct mlx_command *mc);
90static void			mlx_periodic_rebuild(struct mlx_command *mc);
91
92/*
93 * Channel Pause
94 */
95static void			mlx_pause_action(struct mlx_softc *sc);
96static void			mlx_pause_done(struct mlx_command *mc);
97
98/*
99 * Command submission.
100 */
101static void			*mlx_enquire(struct mlx_softc *sc, int command, size_t bufsize,
102					     void (*complete)(struct mlx_command *mc));
103static int			mlx_flush(struct mlx_softc *sc);
104static int			mlx_check(struct mlx_softc *sc, int drive);
105static int			mlx_rebuild(struct mlx_softc *sc, int channel, int target);
106static int			mlx_wait_command(struct mlx_command *mc);
107static int			mlx_poll_command(struct mlx_command *mc);
108void				mlx_startio_cb(void *arg,
109					       bus_dma_segment_t *segs,
110					       int nsegments, int error);
111static void			mlx_startio(struct mlx_softc *sc);
112static void			mlx_completeio(struct mlx_command *mc);
113static int			mlx_user_command(struct mlx_softc *sc,
114						 struct mlx_usercommand *mu);
115void				mlx_user_cb(void *arg, bus_dma_segment_t *segs,
116					    int nsegments, int error);
117
118/*
119 * Command buffer allocation.
120 */
121static struct mlx_command	*mlx_alloccmd(struct mlx_softc *sc);
122static void			mlx_releasecmd(struct mlx_command *mc);
123static void			mlx_freecmd(struct mlx_command *mc);
124
125/*
126 * Command management.
127 */
128static int			mlx_getslot(struct mlx_command *mc);
129static void			mlx_setup_dmamap(struct mlx_command *mc,
130						 bus_dma_segment_t *segs,
131						 int nsegments, int error);
132static void			mlx_unmapcmd(struct mlx_command *mc);
133static int			mlx_start(struct mlx_command *mc);
134static int			mlx_done(struct mlx_softc *sc);
135static void			mlx_complete(struct mlx_softc *sc);
136
137/*
138 * Debugging.
139 */
140static char			*mlx_diagnose_command(struct mlx_command *mc);
141static void			mlx_describe_controller(struct mlx_softc *sc);
142static int			mlx_fw_message(struct mlx_softc *sc, int status, int param1, int param2);
143
144/*
145 * Utility functions.
146 */
147static struct mlx_sysdrive	*mlx_findunit(struct mlx_softc *sc, int unit);
148
149/********************************************************************************
150 ********************************************************************************
151                                                                Public Interfaces
152 ********************************************************************************
153 ********************************************************************************/
154
155/********************************************************************************
156 * Free all of the resources associated with (sc)
157 *
158 * Should not be called if the controller is active.
159 */
160void
161mlx_free(struct mlx_softc *sc)
162{
163    struct mlx_command	*mc;
164
165    debug_called(1);
166
167    /* cancel status timeout */
168    untimeout(mlx_periodic, sc, sc->mlx_timeout);
169
170    /* throw away any command buffers */
171    while ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL) {
172	TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link);
173	mlx_freecmd(mc);
174    }
175
176    /* destroy data-transfer DMA tag */
177    if (sc->mlx_buffer_dmat)
178	bus_dma_tag_destroy(sc->mlx_buffer_dmat);
179
180    /* free and destroy DMA memory and tag for s/g lists */
181    if (sc->mlx_sgtable)
182	bus_dmamem_free(sc->mlx_sg_dmat, sc->mlx_sgtable, sc->mlx_sg_dmamap);
183    if (sc->mlx_sg_dmat)
184	bus_dma_tag_destroy(sc->mlx_sg_dmat);
185
186    /* disconnect the interrupt handler */
187    if (sc->mlx_intr)
188	bus_teardown_intr(sc->mlx_dev, sc->mlx_irq, sc->mlx_intr);
189    if (sc->mlx_irq != NULL)
190	bus_release_resource(sc->mlx_dev, SYS_RES_IRQ, 0, sc->mlx_irq);
191
192    /* destroy the parent DMA tag */
193    if (sc->mlx_parent_dmat)
194	bus_dma_tag_destroy(sc->mlx_parent_dmat);
195
196    /* release the register window mapping */
197    if (sc->mlx_mem != NULL)
198	bus_release_resource(sc->mlx_dev, sc->mlx_mem_type, sc->mlx_mem_rid, sc->mlx_mem);
199
200    /* free controller enquiry data */
201    if (sc->mlx_enq2 != NULL)
202	free(sc->mlx_enq2, M_DEVBUF);
203
204    /* destroy control device */
205    if (sc->mlx_dev_t != (struct cdev *)NULL)
206	destroy_dev(sc->mlx_dev_t);
207}
208
209/********************************************************************************
210 * Map the scatter/gather table into bus space
211 */
212static void
213mlx_dma_map_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error)
214{
215    struct mlx_softc	*sc = (struct mlx_softc *)arg;
216
217    debug_called(1);
218
219    /* save base of s/g table's address in bus space */
220    sc->mlx_sgbusaddr = segs->ds_addr;
221}
222
223static int
224mlx_sglist_map(struct mlx_softc *sc)
225{
226    size_t	segsize;
227    int		error, ncmd;
228
229    debug_called(1);
230
231    /* destroy any existing mappings */
232    if (sc->mlx_sgtable)
233	bus_dmamem_free(sc->mlx_sg_dmat, sc->mlx_sgtable, sc->mlx_sg_dmamap);
234    if (sc->mlx_sg_dmat)
235	bus_dma_tag_destroy(sc->mlx_sg_dmat);
236
237    /*
238     * Create a single tag describing a region large enough to hold all of
239     * the s/g lists we will need.  If we're called early on, we don't know how
240     * many commands we're going to be asked to support, so only allocate enough
241     * for a couple.
242     */
243    if (sc->mlx_enq2 == NULL) {
244	ncmd = 2;
245    } else {
246	ncmd = sc->mlx_enq2->me_max_commands;
247    }
248    segsize = sizeof(struct mlx_sgentry) * MLX_NSEG * ncmd;
249    error = bus_dma_tag_create(sc->mlx_parent_dmat, 	/* parent */
250			       1, 0, 			/* alignment,boundary */
251			       BUS_SPACE_MAXADDR,	/* lowaddr */
252			       BUS_SPACE_MAXADDR, 	/* highaddr */
253			       NULL, NULL, 		/* filter, filterarg */
254			       segsize, 1,		/* maxsize, nsegments */
255			       BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
256			       0,			/* flags */
257			       NULL, NULL,		/* lockfunc, lockarg */
258			       &sc->mlx_sg_dmat);
259    if (error != 0) {
260	device_printf(sc->mlx_dev, "can't allocate scatter/gather DMA tag\n");
261	return(ENOMEM);
262    }
263
264    /*
265     * Allocate enough s/g maps for all commands and permanently map them into
266     * controller-visible space.
267     *
268     * XXX this assumes we can get enough space for all the s/g maps in one
269     * contiguous slab.  We may need to switch to a more complex arrangement
270     * where we allocate in smaller chunks and keep a lookup table from slot
271     * to bus address.
272     */
273    error = bus_dmamem_alloc(sc->mlx_sg_dmat, (void **)&sc->mlx_sgtable,
274			     BUS_DMA_NOWAIT, &sc->mlx_sg_dmamap);
275    if (error) {
276	device_printf(sc->mlx_dev, "can't allocate s/g table\n");
277	return(ENOMEM);
278    }
279    (void)bus_dmamap_load(sc->mlx_sg_dmat, sc->mlx_sg_dmamap, sc->mlx_sgtable,
280			  segsize, mlx_dma_map_sg, sc, 0);
281    return(0);
282}
283
284/********************************************************************************
285 * Initialise the controller and softc
286 */
287int
288mlx_attach(struct mlx_softc *sc)
289{
290    struct mlx_enquiry_old	*meo;
291    int				rid, error, fwminor, hscode, hserror, hsparam1, hsparam2, hsmsg;
292
293    debug_called(1);
294
295    /*
296     * Initialise per-controller queues.
297     */
298    TAILQ_INIT(&sc->mlx_work);
299    TAILQ_INIT(&sc->mlx_freecmds);
300    MLX_BIO_QINIT(sc->mlx_bioq);
301
302    /*
303     * Select accessor methods based on controller interface type.
304     */
305    switch(sc->mlx_iftype) {
306    case MLX_IFTYPE_2:
307    case MLX_IFTYPE_3:
308	sc->mlx_tryqueue	= mlx_v3_tryqueue;
309	sc->mlx_findcomplete	= mlx_v3_findcomplete;
310	sc->mlx_intaction	= mlx_v3_intaction;
311	sc->mlx_fw_handshake	= mlx_v3_fw_handshake;
312	break;
313    case MLX_IFTYPE_4:
314	sc->mlx_tryqueue	= mlx_v4_tryqueue;
315	sc->mlx_findcomplete	= mlx_v4_findcomplete;
316	sc->mlx_intaction	= mlx_v4_intaction;
317	sc->mlx_fw_handshake	= mlx_v4_fw_handshake;
318	break;
319    case MLX_IFTYPE_5:
320	sc->mlx_tryqueue	= mlx_v5_tryqueue;
321	sc->mlx_findcomplete	= mlx_v5_findcomplete;
322	sc->mlx_intaction	= mlx_v5_intaction;
323	sc->mlx_fw_handshake	= mlx_v5_fw_handshake;
324	break;
325    default:
326	return(ENXIO);		/* should never happen */
327    }
328
329    /* disable interrupts before we start talking to the controller */
330    sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
331
332    /*
333     * Wait for the controller to come ready, handshake with the firmware if required.
334     * This is typically only necessary on platforms where the controller BIOS does not
335     * run.
336     */
337    hsmsg = 0;
338    DELAY(1000);
339    while ((hscode = sc->mlx_fw_handshake(sc, &hserror, &hsparam1, &hsparam2)) != 0) {
340	/* report first time around... */
341	if (hsmsg == 0) {
342	    device_printf(sc->mlx_dev, "controller initialisation in progress...\n");
343	    hsmsg = 1;
344	}
345	/* did we get a real message? */
346	if (hscode == 2) {
347	    hscode = mlx_fw_message(sc, hserror, hsparam1, hsparam2);
348	    /* fatal initialisation error? */
349	    if (hscode != 0) {
350		return(ENXIO);
351	    }
352	}
353    }
354    if (hsmsg == 1)
355	device_printf(sc->mlx_dev, "initialisation complete.\n");
356
357    /*
358     * Allocate and connect our interrupt.
359     */
360    rid = 0;
361    sc->mlx_irq = bus_alloc_resource_any(sc->mlx_dev, SYS_RES_IRQ, &rid,
362        RF_SHAREABLE | RF_ACTIVE);
363    if (sc->mlx_irq == NULL) {
364	device_printf(sc->mlx_dev, "can't allocate interrupt\n");
365	return(ENXIO);
366    }
367    error = bus_setup_intr(sc->mlx_dev, sc->mlx_irq, INTR_TYPE_BIO | INTR_ENTROPY, NULL, mlx_intr, sc, &sc->mlx_intr);
368    if (error) {
369	device_printf(sc->mlx_dev, "can't set up interrupt\n");
370	return(ENXIO);
371    }
372
373    /*
374     * Create DMA tag for mapping buffers into controller-addressable space.
375     */
376    error = bus_dma_tag_create(sc->mlx_parent_dmat, 	/* parent */
377			       1, 0, 			/* align, boundary */
378			       BUS_SPACE_MAXADDR,	/* lowaddr */
379			       BUS_SPACE_MAXADDR, 	/* highaddr */
380			       NULL, NULL, 		/* filter, filterarg */
381			       MAXBSIZE, MLX_NSEG,	/* maxsize, nsegments */
382			       BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
383			       0,			/* flags */
384			       busdma_lock_mutex,	/* lockfunc */
385			       &Giant,			/* lockarg */
386			       &sc->mlx_buffer_dmat);
387    if (error != 0) {
388	device_printf(sc->mlx_dev, "can't allocate buffer DMA tag\n");
389	return(ENOMEM);
390    }
391
392    /*
393     * Create some initial scatter/gather mappings so we can run the probe
394     * commands.
395     */
396    error = mlx_sglist_map(sc);
397    if (error != 0) {
398	device_printf(sc->mlx_dev, "can't make initial s/g list mapping\n");
399	return(error);
400    }
401
402    /*
403     * We don't (yet) know where the event log is up to.
404     */
405    sc->mlx_currevent = -1;
406
407    /*
408     * Obtain controller feature information
409     */
410    if ((sc->mlx_enq2 = mlx_enquire(sc, MLX_CMD_ENQUIRY2, sizeof(struct mlx_enquiry2), NULL)) == NULL) {
411	device_printf(sc->mlx_dev, "ENQUIRY2 failed\n");
412	return(ENXIO);
413    }
414
415    /*
416     * Do quirk/feature related things.
417     */
418    fwminor = (sc->mlx_enq2->me_firmware_id >> 8) & 0xff;
419    switch(sc->mlx_iftype) {
420    case MLX_IFTYPE_2:
421	/* These controllers don't report the firmware version in the ENQUIRY2 response */
422	if ((meo = mlx_enquire(sc, MLX_CMD_ENQUIRY_OLD, sizeof(struct mlx_enquiry_old), NULL)) == NULL) {
423	    device_printf(sc->mlx_dev, "ENQUIRY_OLD failed\n");
424	    return(ENXIO);
425	}
426	sc->mlx_enq2->me_firmware_id = ('0' << 24) | (0 << 16) | (meo->me_fwminor << 8) | meo->me_fwmajor;
427
428	/* XXX require 2.42 or better (PCI) or 2.14 or better (EISA) */
429	if (meo->me_fwminor < 42) {
430	    device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
431	    device_printf(sc->mlx_dev, " *** WARNING *** Use revision 2.42 or later\n");
432	}
433	free(meo, M_DEVBUF);
434	break;
435    case MLX_IFTYPE_3:
436	/* XXX certify 3.52? */
437	if (fwminor < 51) {
438	    device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
439	    device_printf(sc->mlx_dev, " *** WARNING *** Use revision 3.51 or later\n");
440	}
441	break;
442    case MLX_IFTYPE_4:
443	/* XXX certify firmware versions? */
444	if (fwminor < 6) {
445	    device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
446	    device_printf(sc->mlx_dev, " *** WARNING *** Use revision 4.06 or later\n");
447	}
448	break;
449    case MLX_IFTYPE_5:
450	if (fwminor < 7) {
451	    device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
452	    device_printf(sc->mlx_dev, " *** WARNING *** Use revision 5.07 or later\n");
453	}
454	break;
455    default:
456	return(ENXIO);		/* should never happen */
457    }
458
459    /*
460     * Create the final scatter/gather mappings now that we have characterised the controller.
461     */
462    error = mlx_sglist_map(sc);
463    if (error != 0) {
464	device_printf(sc->mlx_dev, "can't make final s/g list mapping\n");
465	return(error);
466    }
467
468    /*
469     * No user-requested background operation is in progress.
470     */
471    sc->mlx_background = 0;
472    sc->mlx_rebuildstat.rs_code = MLX_REBUILDSTAT_IDLE;
473
474    /*
475     * Create the control device.
476     */
477    sc->mlx_dev_t = make_dev(&mlx_cdevsw, device_get_unit(sc->mlx_dev), UID_ROOT, GID_OPERATOR,
478			     S_IRUSR | S_IWUSR, "mlx%d", device_get_unit(sc->mlx_dev));
479
480    /*
481     * Start the timeout routine.
482     */
483    sc->mlx_timeout = timeout(mlx_periodic, sc, hz);
484
485    /* print a little information about the controller */
486    mlx_describe_controller(sc);
487
488    return(0);
489}
490
491/********************************************************************************
492 * Locate disk resources and attach children to them.
493 */
494void
495mlx_startup(struct mlx_softc *sc)
496{
497    struct mlx_enq_sys_drive	*mes;
498    struct mlx_sysdrive		*dr;
499    int				i, error;
500
501    debug_called(1);
502
503    /*
504     * Scan all the system drives and attach children for those that
505     * don't currently have them.
506     */
507    mes = mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(*mes) * MLX_MAXDRIVES, NULL);
508    if (mes == NULL) {
509	device_printf(sc->mlx_dev, "error fetching drive status\n");
510	return;
511    }
512
513    /* iterate over drives returned */
514    for (i = 0, dr = &sc->mlx_sysdrive[0];
515	 (i < MLX_MAXDRIVES) && (mes[i].sd_size != 0xffffffff);
516	 i++, dr++) {
517	/* are we already attached to this drive? */
518    	if (dr->ms_disk == 0) {
519	    /* pick up drive information */
520	    dr->ms_size = mes[i].sd_size;
521	    dr->ms_raidlevel = mes[i].sd_raidlevel & 0xf;
522	    dr->ms_state = mes[i].sd_state;
523
524	    /* generate geometry information */
525	    if (sc->mlx_geom == MLX_GEOM_128_32) {
526		dr->ms_heads = 128;
527		dr->ms_sectors = 32;
528		dr->ms_cylinders = dr->ms_size / (128 * 32);
529	    } else {        /* MLX_GEOM_255/63 */
530		dr->ms_heads = 255;
531		dr->ms_sectors = 63;
532		dr->ms_cylinders = dr->ms_size / (255 * 63);
533	    }
534	    dr->ms_disk =  device_add_child(sc->mlx_dev, /*"mlxd"*/NULL, -1);
535	    if (dr->ms_disk == 0)
536		device_printf(sc->mlx_dev, "device_add_child failed\n");
537	    device_set_ivars(dr->ms_disk, dr);
538	}
539    }
540    free(mes, M_DEVBUF);
541    if ((error = bus_generic_attach(sc->mlx_dev)) != 0)
542	device_printf(sc->mlx_dev, "bus_generic_attach returned %d", error);
543
544    /* mark controller back up */
545    sc->mlx_state &= ~MLX_STATE_SHUTDOWN;
546
547    /* enable interrupts */
548    sc->mlx_intaction(sc, MLX_INTACTION_ENABLE);
549}
550
551/********************************************************************************
552 * Disconnect from the controller completely, in preparation for unload.
553 */
554int
555mlx_detach(device_t dev)
556{
557    struct mlx_softc	*sc = device_get_softc(dev);
558    struct mlxd_softc	*mlxd;
559    int			i, s, error;
560
561    debug_called(1);
562
563    error = EBUSY;
564    s = splbio();
565    if (sc->mlx_state & MLX_STATE_OPEN)
566	goto out;
567
568    for (i = 0; i < MLX_MAXDRIVES; i++) {
569	if (sc->mlx_sysdrive[i].ms_disk != 0) {
570	    mlxd = device_get_softc(sc->mlx_sysdrive[i].ms_disk);
571	    if (mlxd->mlxd_flags & MLXD_OPEN) {		/* drive is mounted, abort detach */
572		device_printf(sc->mlx_sysdrive[i].ms_disk, "still open, can't detach\n");
573		goto out;
574	    }
575	}
576    }
577    if ((error = mlx_shutdown(dev)))
578	goto out;
579
580    mlx_free(sc);
581
582    error = 0;
583 out:
584    splx(s);
585    return(error);
586}
587
588/********************************************************************************
589 * Bring the controller down to a dormant state and detach all child devices.
590 *
591 * This function is called before detach, system shutdown, or before performing
592 * an operation which may add or delete system disks.  (Call mlx_startup to
593 * resume normal operation.)
594 *
595 * Note that we can assume that the bioq on the controller is empty, as we won't
596 * allow shutdown if any device is open.
597 */
598int
599mlx_shutdown(device_t dev)
600{
601    struct mlx_softc	*sc = device_get_softc(dev);
602    int			i, s, error;
603
604    debug_called(1);
605
606    s = splbio();
607    error = 0;
608
609    sc->mlx_state |= MLX_STATE_SHUTDOWN;
610    sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
611
612    /* flush controller */
613    device_printf(sc->mlx_dev, "flushing cache...");
614    if (mlx_flush(sc)) {
615	printf("failed\n");
616    } else {
617	printf("done\n");
618    }
619
620    /* delete all our child devices */
621    for (i = 0; i < MLX_MAXDRIVES; i++) {
622	if (sc->mlx_sysdrive[i].ms_disk != 0) {
623	    if ((error = device_delete_child(sc->mlx_dev, sc->mlx_sysdrive[i].ms_disk)) != 0)
624		goto out;
625	    sc->mlx_sysdrive[i].ms_disk = 0;
626	}
627    }
628
629 out:
630    splx(s);
631    return(error);
632}
633
634/********************************************************************************
635 * Bring the controller to a quiescent state, ready for system suspend.
636 */
637int
638mlx_suspend(device_t dev)
639{
640    struct mlx_softc	*sc = device_get_softc(dev);
641    int			s;
642
643    debug_called(1);
644
645    s = splbio();
646    sc->mlx_state |= MLX_STATE_SUSPEND;
647
648    /* flush controller */
649    device_printf(sc->mlx_dev, "flushing cache...");
650    printf("%s\n", mlx_flush(sc) ? "failed" : "done");
651
652    sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
653    splx(s);
654
655    return(0);
656}
657
658/********************************************************************************
659 * Bring the controller back to a state ready for operation.
660 */
661int
662mlx_resume(device_t dev)
663{
664    struct mlx_softc	*sc = device_get_softc(dev);
665
666    debug_called(1);
667
668    sc->mlx_state &= ~MLX_STATE_SUSPEND;
669    sc->mlx_intaction(sc, MLX_INTACTION_ENABLE);
670
671    return(0);
672}
673
674/*******************************************************************************
675 * Take an interrupt, or be poked by other code to look for interrupt-worthy
676 * status.
677 */
678void
679mlx_intr(void *arg)
680{
681    struct mlx_softc	*sc = (struct mlx_softc *)arg;
682
683    debug_called(1);
684
685    /* collect finished commands, queue anything waiting */
686    mlx_done(sc);
687};
688
689/*******************************************************************************
690 * Receive a buf structure from a child device and queue it on a particular
691 * disk resource, then poke the disk resource to start as much work as it can.
692 */
693int
694mlx_submit_buf(struct mlx_softc *sc, mlx_bio *bp)
695{
696    int		s;
697
698    debug_called(1);
699
700    s = splbio();
701    MLX_BIO_QINSERT(sc->mlx_bioq, bp);
702    sc->mlx_waitbufs++;
703    splx(s);
704    mlx_startio(sc);
705    return(0);
706}
707
708/********************************************************************************
709 * Accept an open operation on the control device.
710 */
711int
712mlx_open(struct cdev *dev, int flags, int fmt, struct thread *td)
713{
714    int			unit = minor(dev);
715    struct mlx_softc	*sc = devclass_get_softc(mlx_devclass, unit);
716
717    sc->mlx_state |= MLX_STATE_OPEN;
718    return(0);
719}
720
721/********************************************************************************
722 * Accept the last close on the control device.
723 */
724int
725mlx_close(struct cdev *dev, int flags, int fmt, struct thread *td)
726{
727    int			unit = minor(dev);
728    struct mlx_softc	*sc = devclass_get_softc(mlx_devclass, unit);
729
730    sc->mlx_state &= ~MLX_STATE_OPEN;
731    return (0);
732}
733
734/********************************************************************************
735 * Handle controller-specific control operations.
736 */
737int
738mlx_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td)
739{
740    int				unit = minor(dev);
741    struct mlx_softc		*sc = devclass_get_softc(mlx_devclass, unit);
742    struct mlx_rebuild_request	*rb = (struct mlx_rebuild_request *)addr;
743    struct mlx_rebuild_status	*rs = (struct mlx_rebuild_status *)addr;
744    int				*arg = (int *)addr;
745    struct mlx_pause		*mp;
746    struct mlx_sysdrive		*dr;
747    struct mlxd_softc		*mlxd;
748    int				i, error;
749
750    switch(cmd) {
751	/*
752	 * Enumerate connected system drives; returns the first system drive's
753	 * unit number if *arg is -1, or the next unit after *arg if it's
754	 * a valid unit on this controller.
755	 */
756    case MLX_NEXT_CHILD:
757	/* search system drives */
758	for (i = 0; i < MLX_MAXDRIVES; i++) {
759	    /* is this one attached? */
760	    if (sc->mlx_sysdrive[i].ms_disk != 0) {
761		/* looking for the next one we come across? */
762		if (*arg == -1) {
763		    *arg = device_get_unit(sc->mlx_sysdrive[0].ms_disk);
764		    return(0);
765		}
766		/* we want the one after this one */
767		if (*arg == device_get_unit(sc->mlx_sysdrive[i].ms_disk))
768		    *arg = -1;
769	    }
770	}
771	return(ENOENT);
772
773	/*
774	 * Scan the controller to see whether new drives have appeared.
775	 */
776    case MLX_RESCAN_DRIVES:
777	mlx_startup(sc);
778	return(0);
779
780	/*
781	 * Disconnect from the specified drive; it may be about to go
782	 * away.
783	 */
784    case MLX_DETACH_DRIVE:			/* detach one drive */
785
786	if (((dr = mlx_findunit(sc, *arg)) == NULL) ||
787	    ((mlxd = device_get_softc(dr->ms_disk)) == NULL))
788	    return(ENOENT);
789
790	device_printf(dr->ms_disk, "detaching...");
791	error = 0;
792	if (mlxd->mlxd_flags & MLXD_OPEN) {
793	    error = EBUSY;
794	    goto detach_out;
795	}
796
797	/* flush controller */
798	if (mlx_flush(sc)) {
799	    error = EBUSY;
800	    goto detach_out;
801	}
802
803	/* nuke drive */
804	if ((error = device_delete_child(sc->mlx_dev, dr->ms_disk)) != 0)
805	    goto detach_out;
806	dr->ms_disk = 0;
807
808    detach_out:
809	if (error) {
810	    printf("failed\n");
811	} else {
812	    printf("done\n");
813	}
814	return(error);
815
816	/*
817	 * Pause one or more SCSI channels for a period of time, to assist
818	 * in the process of hot-swapping devices.
819	 *
820	 * Note that at least the 3.51 firmware on the DAC960PL doesn't seem
821	 * to do this right.
822	 */
823    case MLX_PAUSE_CHANNEL:			/* schedule a channel pause */
824	/* Does this command work on this firmware? */
825	if (!(sc->mlx_feature & MLX_FEAT_PAUSEWORKS))
826	    return(EOPNOTSUPP);
827
828	mp = (struct mlx_pause *)addr;
829	if ((mp->mp_which == MLX_PAUSE_CANCEL) && (sc->mlx_pause.mp_when != 0)) {
830	    /* cancel a pending pause operation */
831	    sc->mlx_pause.mp_which = 0;
832	} else {
833	    /* fix for legal channels */
834	    mp->mp_which &= ((1 << sc->mlx_enq2->me_actual_channels) -1);
835	    /* check time values */
836	    if ((mp->mp_when < 0) || (mp->mp_when > 3600))
837		return(EINVAL);
838	    if ((mp->mp_howlong < 1) || (mp->mp_howlong > (0xf * 30)))
839		return(EINVAL);
840
841	    /* check for a pause currently running */
842	    if ((sc->mlx_pause.mp_which != 0) && (sc->mlx_pause.mp_when == 0))
843		return(EBUSY);
844
845	    /* looks ok, go with it */
846	    sc->mlx_pause.mp_which = mp->mp_which;
847	    sc->mlx_pause.mp_when = time_second + mp->mp_when;
848	    sc->mlx_pause.mp_howlong = sc->mlx_pause.mp_when + mp->mp_howlong;
849	}
850	return(0);
851
852	/*
853	 * Accept a command passthrough-style.
854	 */
855    case MLX_COMMAND:
856	return(mlx_user_command(sc, (struct mlx_usercommand *)addr));
857
858	/*
859	 * Start a rebuild on a given SCSI disk
860	 */
861    case MLX_REBUILDASYNC:
862	if (sc->mlx_background != 0) {
863	    rb->rr_status = 0x0106;
864	    return(EBUSY);
865	}
866	rb->rr_status = mlx_rebuild(sc, rb->rr_channel, rb->rr_target);
867	switch (rb->rr_status) {
868	case 0:
869	    error = 0;
870	    break;
871	case 0x10000:
872	    error = ENOMEM;		/* couldn't set up the command */
873	    break;
874	case 0x0002:
875	    error = EBUSY;
876	    break;
877	case 0x0104:
878	    error = EIO;
879	    break;
880	case 0x0105:
881	    error = ERANGE;
882	    break;
883	case 0x0106:
884	    error = EBUSY;
885	    break;
886	default:
887	    error = EINVAL;
888	    break;
889	}
890	if (error == 0)
891	    sc->mlx_background = MLX_BACKGROUND_REBUILD;
892	return(error);
893
894	/*
895	 * Get the status of the current rebuild or consistency check.
896	 */
897    case MLX_REBUILDSTAT:
898	*rs = sc->mlx_rebuildstat;
899	return(0);
900
901	/*
902	 * Return the per-controller system drive number matching the
903	 * disk device number in (arg), if it happens to belong to us.
904	 */
905    case MLX_GET_SYSDRIVE:
906	error = ENOENT;
907	mlxd = (struct mlxd_softc *)devclass_get_softc(mlxd_devclass, *arg);
908	if ((mlxd != NULL) && (mlxd->mlxd_drive >= sc->mlx_sysdrive) &&
909	    (mlxd->mlxd_drive < (sc->mlx_sysdrive + MLX_MAXDRIVES))) {
910	    error = 0;
911	    *arg = mlxd->mlxd_drive - sc->mlx_sysdrive;
912	}
913	return(error);
914
915    default:
916	return(ENOTTY);
917    }
918}
919
920/********************************************************************************
921 * Handle operations requested by a System Drive connected to this controller.
922 */
923int
924mlx_submit_ioctl(struct mlx_softc *sc, struct mlx_sysdrive *drive, u_long cmd,
925		caddr_t addr, int32_t flag, struct thread *td)
926{
927    int				*arg = (int *)addr;
928    int				error, result;
929
930    switch(cmd) {
931	/*
932	 * Return the current status of this drive.
933	 */
934    case MLXD_STATUS:
935	*arg = drive->ms_state;
936	return(0);
937
938	/*
939	 * Start a background consistency check on this drive.
940	 */
941    case MLXD_CHECKASYNC:		/* start a background consistency check */
942	if (sc->mlx_background != 0) {
943	    *arg = 0x0106;
944	    return(EBUSY);
945	}
946	result = mlx_check(sc, drive - &sc->mlx_sysdrive[0]);
947	switch (result) {
948	case 0:
949	    error = 0;
950	    break;
951	case 0x10000:
952	    error = ENOMEM;		/* couldn't set up the command */
953	    break;
954	case 0x0002:
955	    error = EIO;
956	    break;
957	case 0x0105:
958	    error = ERANGE;
959	    break;
960	case 0x0106:
961	    error = EBUSY;
962	    break;
963	default:
964	    error = EINVAL;
965	    break;
966	}
967	if (error == 0)
968	    sc->mlx_background = MLX_BACKGROUND_CHECK;
969	*arg = result;
970	return(error);
971
972    }
973    return(ENOIOCTL);
974}
975
976
977/********************************************************************************
978 ********************************************************************************
979                                                                Status Monitoring
980 ********************************************************************************
981 ********************************************************************************/
982
983/********************************************************************************
984 * Fire off commands to periodically check the status of connected drives.
985 */
986static void
987mlx_periodic(void *data)
988{
989    struct mlx_softc *sc = (struct mlx_softc *)data;
990
991    debug_called(1);
992
993    /*
994     * Run a bus pause?
995     */
996    if ((sc->mlx_pause.mp_which != 0) &&
997	(sc->mlx_pause.mp_when > 0) &&
998	(time_second >= sc->mlx_pause.mp_when)){
999
1000	mlx_pause_action(sc);		/* pause is running */
1001	sc->mlx_pause.mp_when = 0;
1002	sysbeep(500, hz);
1003
1004	/*
1005	 * Bus pause still running?
1006	 */
1007    } else if ((sc->mlx_pause.mp_which != 0) &&
1008	       (sc->mlx_pause.mp_when == 0)) {
1009
1010	/* time to stop bus pause? */
1011	if (time_second >= sc->mlx_pause.mp_howlong) {
1012	    mlx_pause_action(sc);
1013	    sc->mlx_pause.mp_which = 0;	/* pause is complete */
1014	    sysbeep(500, hz);
1015	} else {
1016	    sysbeep((time_second % 5) * 100 + 500, hz/8);
1017	}
1018
1019	/*
1020	 * Run normal periodic activities?
1021	 */
1022    } else if (time_second > (sc->mlx_lastpoll + 10)) {
1023	sc->mlx_lastpoll = time_second;
1024
1025	/*
1026	 * Check controller status.
1027	 *
1028	 * XXX Note that this may not actually launch a command in situations of high load.
1029	 */
1030	mlx_enquire(sc, (sc->mlx_iftype == MLX_IFTYPE_2) ? MLX_CMD_ENQUIRY_OLD : MLX_CMD_ENQUIRY,
1031		    imax(sizeof(struct mlx_enquiry), sizeof(struct mlx_enquiry_old)), mlx_periodic_enquiry);
1032
1033	/*
1034	 * Check system drive status.
1035	 *
1036	 * XXX This might be better left to event-driven detection, eg. I/O to an offline
1037	 *     drive will detect it's offline, rebuilds etc. should detect the drive is back
1038	 *     online.
1039	 */
1040	mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(struct mlx_enq_sys_drive) * MLX_MAXDRIVES,
1041			mlx_periodic_enquiry);
1042
1043    }
1044
1045    /* get drive rebuild/check status */
1046    /* XXX should check sc->mlx_background if this is only valid while in progress */
1047    mlx_enquire(sc, MLX_CMD_REBUILDSTAT, sizeof(struct mlx_rebuild_stat), mlx_periodic_rebuild);
1048
1049    /* deal with possibly-missed interrupts and timed-out commands */
1050    mlx_done(sc);
1051
1052    /* reschedule another poll next second or so */
1053    sc->mlx_timeout = timeout(mlx_periodic, sc, hz);
1054}
1055
1056/********************************************************************************
1057 * Handle the result of an ENQUIRY command instigated by periodic status polling.
1058 */
1059static void
1060mlx_periodic_enquiry(struct mlx_command *mc)
1061{
1062    struct mlx_softc		*sc = mc->mc_sc;
1063
1064    debug_called(1);
1065
1066    /* Command completed OK? */
1067    if (mc->mc_status != 0) {
1068	device_printf(sc->mlx_dev, "periodic enquiry failed - %s\n", mlx_diagnose_command(mc));
1069	goto out;
1070    }
1071
1072    /* respond to command */
1073    switch(mc->mc_mailbox[0]) {
1074	/*
1075	 * This is currently a bit fruitless, as we don't know how to extract the eventlog
1076	 * pointer yet.
1077	 */
1078    case MLX_CMD_ENQUIRY_OLD:
1079    {
1080	struct mlx_enquiry		*me = (struct mlx_enquiry *)mc->mc_data;
1081	struct mlx_enquiry_old		*meo = (struct mlx_enquiry_old *)mc->mc_data;
1082	int				i;
1083
1084	/* convert data in-place to new format */
1085	for (i = (sizeof(me->me_dead) / sizeof(me->me_dead[0])) - 1; i >= 0; i--) {
1086	    me->me_dead[i].dd_chan = meo->me_dead[i].dd_chan;
1087	    me->me_dead[i].dd_targ = meo->me_dead[i].dd_targ;
1088	}
1089	me->me_misc_flags        = 0;
1090	me->me_rebuild_count     = meo->me_rebuild_count;
1091	me->me_dead_count        = meo->me_dead_count;
1092	me->me_critical_sd_count = meo->me_critical_sd_count;
1093	me->me_event_log_seq_num = 0;
1094	me->me_offline_sd_count  = meo->me_offline_sd_count;
1095	me->me_max_commands      = meo->me_max_commands;
1096	me->me_rebuild_flag      = meo->me_rebuild_flag;
1097	me->me_fwmajor           = meo->me_fwmajor;
1098	me->me_fwminor           = meo->me_fwminor;
1099	me->me_status_flags      = meo->me_status_flags;
1100	me->me_flash_age         = meo->me_flash_age;
1101	for (i = (sizeof(me->me_drvsize) / sizeof(me->me_drvsize[0])) - 1; i >= 0; i--) {
1102	    if (i > ((sizeof(meo->me_drvsize) / sizeof(meo->me_drvsize[0])) - 1)) {
1103		me->me_drvsize[i] = 0;		/* drive beyond supported range */
1104	    } else {
1105		me->me_drvsize[i] = meo->me_drvsize[i];
1106	    }
1107	}
1108	me->me_num_sys_drvs = meo->me_num_sys_drvs;
1109    }
1110    /* FALLTHROUGH */
1111
1112	/*
1113	 * Generic controller status update.  We could do more with this than just
1114	 * checking the event log.
1115	 */
1116    case MLX_CMD_ENQUIRY:
1117    {
1118	struct mlx_enquiry		*me = (struct mlx_enquiry *)mc->mc_data;
1119
1120	if (sc->mlx_currevent == -1) {
1121	    /* initialise our view of the event log */
1122	    sc->mlx_currevent = sc->mlx_lastevent = me->me_event_log_seq_num;
1123	} else if ((me->me_event_log_seq_num != sc->mlx_lastevent) && !(sc->mlx_flags & MLX_EVENTLOG_BUSY)) {
1124	    /* record where current events are up to */
1125	    sc->mlx_currevent = me->me_event_log_seq_num;
1126	    debug(1, "event log pointer was %d, now %d\n", sc->mlx_lastevent, sc->mlx_currevent);
1127
1128	    /* mark the event log as busy */
1129	    atomic_set_int(&sc->mlx_flags, MLX_EVENTLOG_BUSY);
1130
1131	    /* drain new eventlog entries */
1132	    mlx_periodic_eventlog_poll(sc);
1133	}
1134	break;
1135    }
1136    case MLX_CMD_ENQSYSDRIVE:
1137    {
1138	struct mlx_enq_sys_drive	*mes = (struct mlx_enq_sys_drive *)mc->mc_data;
1139	struct mlx_sysdrive		*dr;
1140	int				i;
1141
1142	for (i = 0, dr = &sc->mlx_sysdrive[0];
1143	     (i < MLX_MAXDRIVES) && (mes[i].sd_size != 0xffffffff);
1144	     i++) {
1145
1146	    /* has state been changed by controller? */
1147	    if (dr->ms_state != mes[i].sd_state) {
1148		switch(mes[i].sd_state) {
1149		case MLX_SYSD_OFFLINE:
1150		    device_printf(dr->ms_disk, "drive offline\n");
1151		    break;
1152		case MLX_SYSD_ONLINE:
1153		    device_printf(dr->ms_disk, "drive online\n");
1154		    break;
1155		case MLX_SYSD_CRITICAL:
1156		    device_printf(dr->ms_disk, "drive critical\n");
1157		    break;
1158		}
1159		/* save new state */
1160		dr->ms_state = mes[i].sd_state;
1161	    }
1162	}
1163	break;
1164    }
1165    default:
1166	device_printf(sc->mlx_dev, "%s: unknown command 0x%x", __func__, mc->mc_mailbox[0]);
1167	break;
1168    }
1169
1170 out:
1171    free(mc->mc_data, M_DEVBUF);
1172    mlx_releasecmd(mc);
1173}
1174
1175static void
1176mlx_eventlog_cb(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
1177{
1178    struct mlx_command *mc;
1179
1180    mc = (struct mlx_command *)arg;
1181    mlx_setup_dmamap(mc, segs, nsegments, error);
1182
1183    /* build the command to get one entry */
1184    mlx_make_type3(mc, MLX_CMD_LOGOP, MLX_LOGOP_GET, 1,
1185		   mc->mc_sc->mlx_lastevent, 0, 0, mc->mc_dataphys, 0);
1186    mc->mc_complete = mlx_periodic_eventlog_respond;
1187    mc->mc_private = mc;
1188
1189    /* start the command */
1190    if (mlx_start(mc) != 0) {
1191	mlx_releasecmd(mc);
1192	free(mc->mc_data, M_DEVBUF);
1193	mc->mc_data = NULL;
1194    }
1195
1196}
1197
1198/********************************************************************************
1199 * Instigate a poll for one event log message on (sc).
1200 * We only poll for one message at a time, to keep our command usage down.
1201 */
1202static void
1203mlx_periodic_eventlog_poll(struct mlx_softc *sc)
1204{
1205    struct mlx_command	*mc;
1206    void		*result = NULL;
1207    int			error = 0;
1208
1209    debug_called(1);
1210
1211    /* get ourselves a command buffer */
1212    error = 1;
1213    if ((mc = mlx_alloccmd(sc)) == NULL)
1214	goto out;
1215
1216    /* allocate the response structure */
1217    if ((result = malloc(/*sizeof(struct mlx_eventlog_entry)*/1024, M_DEVBUF,
1218			 M_NOWAIT)) == NULL)
1219	goto out;
1220
1221    /* get a command slot */
1222    if (mlx_getslot(mc))
1223	goto out;
1224
1225    /* map the command so the controller can see it */
1226    mc->mc_data = result;
1227    mc->mc_length = /*sizeof(struct mlx_eventlog_entry)*/1024;
1228    error = bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data,
1229			    mc->mc_length, mlx_eventlog_cb, mc, BUS_DMA_NOWAIT);
1230
1231 out:
1232    if (error != 0) {
1233	if (mc != NULL)
1234	    mlx_releasecmd(mc);
1235	if ((result != NULL) && (mc->mc_data != NULL))
1236	    free(result, M_DEVBUF);
1237    }
1238}
1239
1240/********************************************************************************
1241 * Handle the result of polling for a log message, generate diagnostic output.
1242 * If this wasn't the last message waiting for us, we'll go collect another.
1243 */
1244static char *mlx_sense_messages[] = {
1245    "because write recovery failed",
1246    "because of SCSI bus reset failure",
1247    "because of double check condition",
1248    "because it was removed",
1249    "because of gross error on SCSI chip",
1250    "because of bad tag returned from drive",
1251    "because of timeout on SCSI command",
1252    "because of reset SCSI command issued from system",
1253    "because busy or parity error count exceeded limit",
1254    "because of 'kill drive' command from system",
1255    "because of selection timeout",
1256    "due to SCSI phase sequence error",
1257    "due to unknown status"
1258};
1259
1260static void
1261mlx_periodic_eventlog_respond(struct mlx_command *mc)
1262{
1263    struct mlx_softc		*sc = mc->mc_sc;
1264    struct mlx_eventlog_entry	*el = (struct mlx_eventlog_entry *)mc->mc_data;
1265    char			*reason;
1266
1267    debug_called(1);
1268
1269    sc->mlx_lastevent++;		/* next message... */
1270    if (mc->mc_status == 0) {
1271
1272	/* handle event log message */
1273	switch(el->el_type) {
1274	    /*
1275	     * This is the only sort of message we understand at the moment.
1276	     * The tests here are probably incomplete.
1277	     */
1278	case MLX_LOGMSG_SENSE:	/* sense data */
1279	    /* Mylex vendor-specific message indicating a drive was killed? */
1280	    if ((el->el_sensekey == 9) &&
1281		(el->el_asc == 0x80)) {
1282		if (el->el_asq < (sizeof(mlx_sense_messages) / sizeof(mlx_sense_messages[0]))) {
1283		    reason = mlx_sense_messages[el->el_asq];
1284		} else {
1285		    reason = "for unknown reason";
1286		}
1287		device_printf(sc->mlx_dev, "physical drive %d:%d killed %s\n",
1288			      el->el_channel, el->el_target, reason);
1289	    }
1290	    /* SCSI drive was reset? */
1291	    if ((el->el_sensekey == 6) && (el->el_asc == 0x29)) {
1292		device_printf(sc->mlx_dev, "physical drive %d:%d reset\n",
1293			      el->el_channel, el->el_target);
1294	    }
1295	    /* SCSI drive error? */
1296	    if (!((el->el_sensekey == 0) ||
1297		  ((el->el_sensekey == 2) &&
1298		   (el->el_asc == 0x04) &&
1299		   ((el->el_asq == 0x01) ||
1300		    (el->el_asq == 0x02))))) {
1301		device_printf(sc->mlx_dev, "physical drive %d:%d error log: sense = %d asc = %x asq = %x\n",
1302			      el->el_channel, el->el_target, el->el_sensekey, el->el_asc, el->el_asq);
1303		device_printf(sc->mlx_dev, "  info %4D csi %4D\n", el->el_information, ":", el->el_csi, ":");
1304	    }
1305	    break;
1306
1307	default:
1308	    device_printf(sc->mlx_dev, "unknown log message type 0x%x\n", el->el_type);
1309	    break;
1310	}
1311    } else {
1312	device_printf(sc->mlx_dev, "error reading message log - %s\n", mlx_diagnose_command(mc));
1313	/* give up on all the outstanding messages, as we may have come unsynched */
1314	sc->mlx_lastevent = sc->mlx_currevent;
1315    }
1316
1317    /* dispose of command and data */
1318    free(mc->mc_data, M_DEVBUF);
1319    mlx_releasecmd(mc);
1320
1321    /* is there another message to obtain? */
1322    if (sc->mlx_lastevent != sc->mlx_currevent) {
1323	mlx_periodic_eventlog_poll(sc);
1324    } else {
1325	/* clear log-busy status */
1326	atomic_clear_int(&sc->mlx_flags, MLX_EVENTLOG_BUSY);
1327    }
1328}
1329
1330/********************************************************************************
1331 * Handle check/rebuild operations in progress.
1332 */
1333static void
1334mlx_periodic_rebuild(struct mlx_command *mc)
1335{
1336    struct mlx_softc		*sc = mc->mc_sc;
1337    struct mlx_rebuild_status	*mr = (struct mlx_rebuild_status *)mc->mc_data;
1338
1339    switch(mc->mc_status) {
1340    case 0:				/* operation running, update stats */
1341	sc->mlx_rebuildstat = *mr;
1342
1343	/* spontaneous rebuild/check? */
1344	if (sc->mlx_background == 0) {
1345	    sc->mlx_background = MLX_BACKGROUND_SPONTANEOUS;
1346	    device_printf(sc->mlx_dev, "background check/rebuild operation started\n");
1347	}
1348	break;
1349
1350    case 0x0105:			/* nothing running, finalise stats and report */
1351	switch(sc->mlx_background) {
1352	case MLX_BACKGROUND_CHECK:
1353	    device_printf(sc->mlx_dev, "consistency check completed\n");	/* XXX print drive? */
1354	    break;
1355	case MLX_BACKGROUND_REBUILD:
1356	    device_printf(sc->mlx_dev, "drive rebuild completed\n");	/* XXX print channel/target? */
1357	    break;
1358	case MLX_BACKGROUND_SPONTANEOUS:
1359	default:
1360	    /* if we have previously been non-idle, report the transition */
1361	    if (sc->mlx_rebuildstat.rs_code != MLX_REBUILDSTAT_IDLE) {
1362		device_printf(sc->mlx_dev, "background check/rebuild operation completed\n");
1363	    }
1364	}
1365	sc->mlx_background = 0;
1366	sc->mlx_rebuildstat.rs_code = MLX_REBUILDSTAT_IDLE;
1367	break;
1368    }
1369    free(mc->mc_data, M_DEVBUF);
1370    mlx_releasecmd(mc);
1371}
1372
1373/********************************************************************************
1374 ********************************************************************************
1375                                                                    Channel Pause
1376 ********************************************************************************
1377 ********************************************************************************/
1378
1379/********************************************************************************
1380 * It's time to perform a channel pause action for (sc), either start or stop
1381 * the pause.
1382 */
1383static void
1384mlx_pause_action(struct mlx_softc *sc)
1385{
1386    struct mlx_command	*mc;
1387    int			failsafe, i, command;
1388
1389    /* What are we doing here? */
1390    if (sc->mlx_pause.mp_when == 0) {
1391	command = MLX_CMD_STARTCHANNEL;
1392	failsafe = 0;
1393
1394    } else {
1395	command = MLX_CMD_STOPCHANNEL;
1396
1397	/*
1398	 * Channels will always start again after the failsafe period,
1399	 * which is specified in multiples of 30 seconds.
1400	 * This constrains us to a maximum pause of 450 seconds.
1401	 */
1402	failsafe = ((sc->mlx_pause.mp_howlong - time_second) + 5) / 30;
1403	if (failsafe > 0xf) {
1404	    failsafe = 0xf;
1405	    sc->mlx_pause.mp_howlong = time_second + (0xf * 30) - 5;
1406	}
1407    }
1408
1409    /* build commands for every channel requested */
1410    for (i = 0; i < sc->mlx_enq2->me_actual_channels; i++) {
1411	if ((1 << i) & sc->mlx_pause.mp_which) {
1412
1413	    /* get ourselves a command buffer */
1414	    if ((mc = mlx_alloccmd(sc)) == NULL)
1415		goto fail;
1416	    /* get a command slot */
1417	    mc->mc_flags |= MLX_CMD_PRIORITY;
1418	    if (mlx_getslot(mc))
1419		goto fail;
1420
1421	    /* build the command */
1422	    mlx_make_type2(mc, command, (failsafe << 4) | i, 0, 0, 0, 0, 0, 0, 0);
1423	    mc->mc_complete = mlx_pause_done;
1424	    mc->mc_private = sc;		/* XXX not needed */
1425	    if (mlx_start(mc))
1426		goto fail;
1427	    /* command submitted OK */
1428	    return;
1429
1430	fail:
1431	    device_printf(sc->mlx_dev, "%s failed for channel %d\n",
1432			  command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", i);
1433	    if (mc != NULL)
1434		mlx_releasecmd(mc);
1435	}
1436    }
1437}
1438
1439static void
1440mlx_pause_done(struct mlx_command *mc)
1441{
1442    struct mlx_softc	*sc = mc->mc_sc;
1443    int			command = mc->mc_mailbox[0];
1444    int			channel = mc->mc_mailbox[2] & 0xf;
1445
1446    if (mc->mc_status != 0) {
1447	device_printf(sc->mlx_dev, "%s command failed - %s\n",
1448		      command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", mlx_diagnose_command(mc));
1449    } else if (command == MLX_CMD_STOPCHANNEL) {
1450	device_printf(sc->mlx_dev, "channel %d pausing for %ld seconds\n",
1451		      channel, (long)(sc->mlx_pause.mp_howlong - time_second));
1452    } else {
1453	device_printf(sc->mlx_dev, "channel %d resuming\n", channel);
1454    }
1455    mlx_releasecmd(mc);
1456}
1457
1458/********************************************************************************
1459 ********************************************************************************
1460                                                               Command Submission
1461 ********************************************************************************
1462 ********************************************************************************/
1463
1464static void
1465mlx_enquire_cb(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
1466{
1467    struct mlx_softc *sc;
1468    struct mlx_command *mc;
1469
1470    mc = (struct mlx_command *)arg;
1471    if (error)
1472	return;
1473
1474    mlx_setup_dmamap(mc, segs, nsegments, error);
1475
1476    /* build an enquiry command */
1477    sc = mc->mc_sc;
1478    mlx_make_type2(mc, mc->mc_command, 0, 0, 0, 0, 0, 0, mc->mc_dataphys, 0);
1479
1480    /* do we want a completion callback? */
1481    if (mc->mc_complete != NULL) {
1482	if ((error = mlx_start(mc)) != 0)
1483	    return;
1484    } else {
1485	/* run the command in either polled or wait mode */
1486	if ((sc->mlx_state & MLX_STATE_INTEN) ? mlx_wait_command(mc) :
1487						mlx_poll_command(mc))
1488	    return;
1489
1490	/* command completed OK? */
1491	if (mc->mc_status != 0) {
1492	    device_printf(sc->mlx_dev, "ENQUIRY failed - %s\n",
1493			  mlx_diagnose_command(mc));
1494	    return;
1495	}
1496    }
1497}
1498
1499/********************************************************************************
1500 * Perform an Enquiry command using a type-3 command buffer and a return a single
1501 * linear result buffer.  If the completion function is specified, it will
1502 * be called with the completed command (and the result response will not be
1503 * valid until that point).  Otherwise, the command will either be busy-waited
1504 * for (interrupts not enabled), or slept for.
1505 */
1506static void *
1507mlx_enquire(struct mlx_softc *sc, int command, size_t bufsize, void (* complete)(struct mlx_command *mc))
1508{
1509    struct mlx_command	*mc;
1510    void		*result;
1511    int			error;
1512
1513    debug_called(1);
1514
1515    /* get ourselves a command buffer */
1516    error = 1;
1517    result = NULL;
1518    if ((mc = mlx_alloccmd(sc)) == NULL)
1519	goto out;
1520    /* allocate the response structure */
1521    if ((result = malloc(bufsize, M_DEVBUF, M_NOWAIT)) == NULL)
1522	goto out;
1523    /* get a command slot */
1524    mc->mc_flags |= MLX_CMD_PRIORITY | MLX_CMD_DATAOUT;
1525    if (mlx_getslot(mc))
1526	goto out;
1527
1528    /* map the command so the controller can see it */
1529    mc->mc_data = result;
1530    mc->mc_length = bufsize;
1531    mc->mc_command = command;
1532
1533    if (complete != NULL) {
1534	mc->mc_complete = complete;
1535	mc->mc_private = mc;
1536    }
1537
1538    error = bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data,
1539			    mc->mc_length, mlx_enquire_cb, mc, BUS_DMA_NOWAIT);
1540
1541 out:
1542    /* we got a command, but nobody else will free it */
1543    if ((mc != NULL) && (mc->mc_complete == NULL))
1544	mlx_releasecmd(mc);
1545    /* we got an error, and we allocated a result */
1546    if ((error != 0) && (result != NULL)) {
1547	free(result, M_DEVBUF);
1548	result = NULL;
1549    }
1550    return(result);
1551}
1552
1553
1554/********************************************************************************
1555 * Perform a Flush command on the nominated controller.
1556 *
1557 * May be called with interrupts enabled or disabled; will not return until
1558 * the flush operation completes or fails.
1559 */
1560static int
1561mlx_flush(struct mlx_softc *sc)
1562{
1563    struct mlx_command	*mc;
1564    int			error;
1565
1566    debug_called(1);
1567
1568    /* get ourselves a command buffer */
1569    error = 1;
1570    if ((mc = mlx_alloccmd(sc)) == NULL)
1571	goto out;
1572    /* get a command slot */
1573    if (mlx_getslot(mc))
1574	goto out;
1575
1576    /* build a flush command */
1577    mlx_make_type2(mc, MLX_CMD_FLUSH, 0, 0, 0, 0, 0, 0, 0, 0);
1578
1579    /* can't assume that interrupts are going to work here, so play it safe */
1580    if (mlx_poll_command(mc))
1581	goto out;
1582
1583    /* command completed OK? */
1584    if (mc->mc_status != 0) {
1585	device_printf(sc->mlx_dev, "FLUSH failed - %s\n", mlx_diagnose_command(mc));
1586	goto out;
1587    }
1588
1589    error = 0;			/* success */
1590 out:
1591    if (mc != NULL)
1592	mlx_releasecmd(mc);
1593    return(error);
1594}
1595
1596/********************************************************************************
1597 * Start a background consistency check on (drive).
1598 *
1599 * May be called with interrupts enabled or disabled; will return as soon as the
1600 * operation has started or been refused.
1601 */
1602static int
1603mlx_check(struct mlx_softc *sc, int drive)
1604{
1605    struct mlx_command	*mc;
1606    int			error;
1607
1608    debug_called(1);
1609
1610    /* get ourselves a command buffer */
1611    error = 0x10000;
1612    if ((mc = mlx_alloccmd(sc)) == NULL)
1613	goto out;
1614    /* get a command slot */
1615    if (mlx_getslot(mc))
1616	goto out;
1617
1618    /* build a checkasync command, set the "fix it" flag */
1619    mlx_make_type2(mc, MLX_CMD_CHECKASYNC, 0, 0, 0, 0, 0, drive | 0x80, 0, 0);
1620
1621    /* start the command and wait for it to be returned */
1622    if (mlx_wait_command(mc))
1623	goto out;
1624
1625    /* command completed OK? */
1626    if (mc->mc_status != 0) {
1627	device_printf(sc->mlx_dev, "CHECK ASYNC failed - %s\n", mlx_diagnose_command(mc));
1628    } else {
1629	device_printf(sc->mlx_sysdrive[drive].ms_disk, "consistency check started");
1630    }
1631    error = mc->mc_status;
1632
1633 out:
1634    if (mc != NULL)
1635	mlx_releasecmd(mc);
1636    return(error);
1637}
1638
1639/********************************************************************************
1640 * Start a background rebuild of the physical drive at (channel),(target).
1641 *
1642 * May be called with interrupts enabled or disabled; will return as soon as the
1643 * operation has started or been refused.
1644 */
1645static int
1646mlx_rebuild(struct mlx_softc *sc, int channel, int target)
1647{
1648    struct mlx_command	*mc;
1649    int			error;
1650
1651    debug_called(1);
1652
1653    /* get ourselves a command buffer */
1654    error = 0x10000;
1655    if ((mc = mlx_alloccmd(sc)) == NULL)
1656	goto out;
1657    /* get a command slot */
1658    if (mlx_getslot(mc))
1659	goto out;
1660
1661    /* build a checkasync command, set the "fix it" flag */
1662    mlx_make_type2(mc, MLX_CMD_REBUILDASYNC, channel, target, 0, 0, 0, 0, 0, 0);
1663
1664    /* start the command and wait for it to be returned */
1665    if (mlx_wait_command(mc))
1666	goto out;
1667
1668    /* command completed OK? */
1669    if (mc->mc_status != 0) {
1670	device_printf(sc->mlx_dev, "REBUILD ASYNC failed - %s\n", mlx_diagnose_command(mc));
1671    } else {
1672	device_printf(sc->mlx_dev, "drive rebuild started for %d:%d\n", channel, target);
1673    }
1674    error = mc->mc_status;
1675
1676 out:
1677    if (mc != NULL)
1678	mlx_releasecmd(mc);
1679    return(error);
1680}
1681
1682/********************************************************************************
1683 * Run the command (mc) and return when it completes.
1684 *
1685 * Interrupts need to be enabled; returns nonzero on error.
1686 */
1687static int
1688mlx_wait_command(struct mlx_command *mc)
1689{
1690    struct mlx_softc	*sc = mc->mc_sc;
1691    int			error, count;
1692
1693    debug_called(1);
1694
1695    mc->mc_complete = NULL;
1696    mc->mc_private = mc;		/* wake us when you're done */
1697    if ((error = mlx_start(mc)) != 0)
1698	return(error);
1699
1700    count = 0;
1701    /* XXX better timeout? */
1702    while ((mc->mc_status == MLX_STATUS_BUSY) && (count < 30)) {
1703	tsleep(mc->mc_private, PRIBIO | PCATCH, "mlxwcmd", hz);
1704    }
1705
1706    if (mc->mc_status != 0) {
1707	device_printf(sc->mlx_dev, "command failed - %s\n", mlx_diagnose_command(mc));
1708	return(EIO);
1709    }
1710    return(0);
1711}
1712
1713
1714/********************************************************************************
1715 * Start the command (mc) and busy-wait for it to complete.
1716 *
1717 * Should only be used when interrupts can't be relied upon. Returns 0 on
1718 * success, nonzero on error.
1719 * Successfully completed commands are dequeued.
1720 */
1721static int
1722mlx_poll_command(struct mlx_command *mc)
1723{
1724    struct mlx_softc	*sc = mc->mc_sc;
1725    int			error, count, s;
1726
1727    debug_called(1);
1728
1729    mc->mc_complete = NULL;
1730    mc->mc_private = NULL;	/* we will poll for it */
1731    if ((error = mlx_start(mc)) != 0)
1732	return(error);
1733
1734    count = 0;
1735    do {
1736	/* poll for completion */
1737	mlx_done(mc->mc_sc);
1738
1739    } while ((mc->mc_status == MLX_STATUS_BUSY) && (count++ < 15000000));
1740    if (mc->mc_status != MLX_STATUS_BUSY) {
1741	s = splbio();
1742	TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
1743	splx(s);
1744	return(0);
1745    }
1746    device_printf(sc->mlx_dev, "command failed - %s\n", mlx_diagnose_command(mc));
1747    return(EIO);
1748}
1749
1750void
1751mlx_startio_cb(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
1752{
1753    struct mlx_command	*mc;
1754    struct mlxd_softc	*mlxd;
1755    struct mlx_softc	*sc;
1756    mlx_bio		*bp;
1757    int			blkcount;
1758    int			driveno;
1759    int			cmd;
1760
1761    mc = (struct mlx_command *)arg;
1762    mlx_setup_dmamap(mc, segs, nsegments, error);
1763
1764    sc = mc->mc_sc;
1765    bp = mc->mc_private;
1766
1767    if (MLX_BIO_IS_READ(bp)) {
1768	mc->mc_flags |= MLX_CMD_DATAIN;
1769	cmd = MLX_CMD_READSG;
1770    } else {
1771	mc->mc_flags |= MLX_CMD_DATAOUT;
1772	cmd = MLX_CMD_WRITESG;
1773    }
1774
1775    /* build a suitable I/O command (assumes 512-byte rounded transfers) */
1776    mlxd = (struct mlxd_softc *)MLX_BIO_SOFTC(bp);
1777    driveno = mlxd->mlxd_drive - sc->mlx_sysdrive;
1778    blkcount = (MLX_BIO_LENGTH(bp) + MLX_BLKSIZE - 1) / MLX_BLKSIZE;
1779
1780    if ((MLX_BIO_LBA(bp) + blkcount) > sc->mlx_sysdrive[driveno].ms_size)
1781	device_printf(sc->mlx_dev,
1782		      "I/O beyond end of unit (%lld,%d > %lu)\n",
1783		      (long long)MLX_BIO_LBA(bp), blkcount,
1784		      (u_long)sc->mlx_sysdrive[driveno].ms_size);
1785
1786    /*
1787     * Build the I/O command.  Note that the SG list type bits are set to zero,
1788     * denoting the format of SG list that we are using.
1789     */
1790    if (sc->mlx_iftype == MLX_IFTYPE_2) {
1791	mlx_make_type1(mc, (cmd == MLX_CMD_WRITESG) ? MLX_CMD_WRITESG_OLD :
1792						      MLX_CMD_READSG_OLD,
1793		       blkcount & 0xff, 	/* xfer length low byte */
1794		       MLX_BIO_LBA(bp),		/* physical block number */
1795		       driveno,			/* target drive number */
1796		       mc->mc_sgphys,		/* location of SG list */
1797		       mc->mc_nsgent & 0x3f);	/* size of SG list */
1798	} else {
1799	mlx_make_type5(mc, cmd,
1800		       blkcount & 0xff, 	/* xfer length low byte */
1801		       (driveno << 3) | ((blkcount >> 8) & 0x07),
1802						/* target+length high 3 bits */
1803		       MLX_BIO_LBA(bp),		/* physical block number */
1804		       mc->mc_sgphys,		/* location of SG list */
1805		       mc->mc_nsgent & 0x3f);	/* size of SG list */
1806    }
1807
1808    /* try to give command to controller */
1809    if (mlx_start(mc) != 0) {
1810	/* fail the command */
1811	mc->mc_status = MLX_STATUS_WEDGED;
1812	mlx_completeio(mc);
1813    }
1814}
1815
1816/********************************************************************************
1817 * Pull as much work off the softc's work queue as possible and give it to the
1818 * controller.  Leave a couple of slots free for emergencies.
1819 *
1820 * Must be called at splbio or in an equivalent fashion that prevents
1821 * reentry or activity on the bioq.
1822 */
1823static void
1824mlx_startio(struct mlx_softc *sc)
1825{
1826    struct mlx_command	*mc;
1827    mlx_bio		*bp;
1828    int			s;
1829    int			error;
1830
1831    /* avoid reentrancy */
1832    if (mlx_lock_tas(sc, MLX_LOCK_STARTING))
1833	return;
1834
1835    /* spin until something prevents us from doing any work */
1836    s = splbio();
1837    for (;;) {
1838
1839	/* see if there's work to be done */
1840	if ((bp = MLX_BIO_QFIRST(sc->mlx_bioq)) == NULL)
1841	    break;
1842	/* get a command */
1843	if ((mc = mlx_alloccmd(sc)) == NULL)
1844	    break;
1845	/* get a slot for the command */
1846	if (mlx_getslot(mc) != 0) {
1847	    mlx_releasecmd(mc);
1848	    break;
1849	}
1850	/* get the buf containing our work */
1851	MLX_BIO_QREMOVE(sc->mlx_bioq, bp);
1852	sc->mlx_waitbufs--;
1853	splx(s);
1854
1855	/* connect the buf to the command */
1856	mc->mc_complete = mlx_completeio;
1857	mc->mc_private = bp;
1858	mc->mc_data = MLX_BIO_DATA(bp);
1859	mc->mc_length = MLX_BIO_LENGTH(bp);
1860
1861	/* map the command so the controller can work with it */
1862	error = bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data,
1863				mc->mc_length, mlx_startio_cb, mc, 0);
1864	if (error == EINPROGRESS) {
1865		break;
1866	}
1867
1868	s = splbio();
1869    }
1870    splx(s);
1871    mlx_lock_clr(sc, MLX_LOCK_STARTING);
1872}
1873
1874/********************************************************************************
1875 * Handle completion of an I/O command.
1876 */
1877static void
1878mlx_completeio(struct mlx_command *mc)
1879{
1880    struct mlx_softc	*sc = mc->mc_sc;
1881    mlx_bio		*bp = (mlx_bio *)mc->mc_private;
1882    struct mlxd_softc	*mlxd = (struct mlxd_softc *)MLX_BIO_SOFTC(bp);
1883
1884    if (mc->mc_status != MLX_STATUS_OK) {	/* could be more verbose here? */
1885	MLX_BIO_SET_ERROR(bp, EIO);
1886
1887	switch(mc->mc_status) {
1888	case MLX_STATUS_RDWROFFLINE:		/* system drive has gone offline */
1889	    device_printf(mlxd->mlxd_dev, "drive offline\n");
1890	    /* should signal this with a return code */
1891	    mlxd->mlxd_drive->ms_state = MLX_SYSD_OFFLINE;
1892	    break;
1893
1894	default:				/* other I/O error */
1895	    device_printf(sc->mlx_dev, "I/O error - %s\n", mlx_diagnose_command(mc));
1896#if 0
1897	    device_printf(sc->mlx_dev, "  b_bcount %ld  blkcount %ld  b_pblkno %d\n",
1898			  MLX_BIO_LENGTH(bp), MLX_BIO_LENGTH(bp) / MLX_BLKSIZE, MLX_BIO_LBA(bp));
1899	    device_printf(sc->mlx_dev, "  %13D\n", mc->mc_mailbox, " ");
1900#endif
1901	    break;
1902	}
1903    }
1904    mlx_releasecmd(mc);
1905    mlxd_intr(bp);
1906}
1907
1908void
1909mlx_user_cb(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
1910{
1911    struct mlx_usercommand *mu;
1912    struct mlx_command *mc;
1913    struct mlx_dcdb	*dcdb;
1914
1915    mc = (struct mlx_command *)arg;
1916    if (error)
1917	return;
1918
1919    mlx_setup_dmamap(mc, segs, nsegments, error);
1920
1921    mu = (struct mlx_usercommand *)mc->mc_private;
1922    dcdb = NULL;
1923
1924    /*
1925     * If this is a passthrough SCSI command, the DCDB is packed at the
1926     * beginning of the data area.  Fix up the DCDB to point to the correct
1927     * physical address and override any bufptr supplied by the caller since
1928     * we know what it's meant to be.
1929     */
1930    if (mc->mc_mailbox[0] == MLX_CMD_DIRECT_CDB) {
1931	dcdb = (struct mlx_dcdb *)mc->mc_data;
1932	dcdb->dcdb_physaddr = mc->mc_dataphys + sizeof(*dcdb);
1933	mu->mu_bufptr = 8;
1934    }
1935
1936    /*
1937     * If there's a data buffer, fix up the command's buffer pointer.
1938     */
1939    if (mu->mu_datasize > 0) {
1940	mc->mc_mailbox[mu->mu_bufptr    ] =  mc->mc_dataphys        & 0xff;
1941	mc->mc_mailbox[mu->mu_bufptr + 1] = (mc->mc_dataphys >> 8)  & 0xff;
1942	mc->mc_mailbox[mu->mu_bufptr + 2] = (mc->mc_dataphys >> 16) & 0xff;
1943	mc->mc_mailbox[mu->mu_bufptr + 3] = (mc->mc_dataphys >> 24) & 0xff;
1944    }
1945    debug(0, "command fixup");
1946
1947    /* submit the command and wait */
1948    if (mlx_wait_command(mc) != 0)
1949	return;
1950
1951}
1952
1953/********************************************************************************
1954 * Take a command from user-space and try to run it.
1955 *
1956 * XXX Note that this can't perform very much in the way of error checking, and
1957 *     as such, applications _must_ be considered trustworthy.
1958 * XXX Commands using S/G for data are not supported.
1959 */
1960static int
1961mlx_user_command(struct mlx_softc *sc, struct mlx_usercommand *mu)
1962{
1963    struct mlx_command	*mc;
1964    void		*kbuf;
1965    int			error;
1966
1967    debug_called(0);
1968
1969    kbuf = NULL;
1970    mc = NULL;
1971    error = ENOMEM;
1972
1973    /* get ourselves a command and copy in from user space */
1974    if ((mc = mlx_alloccmd(sc)) == NULL)
1975	return(error);
1976    bcopy(mu->mu_command, mc->mc_mailbox, sizeof(mc->mc_mailbox));
1977    debug(0, "got command buffer");
1978
1979    /*
1980     * if we need a buffer for data transfer, allocate one and copy in its
1981     * initial contents
1982     */
1983    if (mu->mu_datasize > 0) {
1984	if (mu->mu_datasize > MAXPHYS) {
1985	    error = EINVAL;
1986	    goto out;
1987	}
1988	if (((kbuf = malloc(mu->mu_datasize, M_DEVBUF, M_WAITOK)) == NULL) ||
1989	    (error = copyin(mu->mu_buf, kbuf, mu->mu_datasize)))
1990	    goto out;
1991	debug(0, "got kernel buffer");
1992    }
1993
1994    /* get a command slot */
1995    if (mlx_getslot(mc))
1996	goto out;
1997    debug(0, "got a slot");
1998
1999    if (mu->mu_datasize > 0) {
2000
2001	/* range check the pointer to physical buffer address */
2002	if ((mu->mu_bufptr < 0) || (mu->mu_bufptr > (sizeof(mu->mu_command) -
2003						     sizeof(u_int32_t)))) {
2004	    error = EINVAL;
2005	    goto out;
2006	}
2007    }
2008
2009    /* map the command so the controller can see it */
2010    mc->mc_data = kbuf;
2011    mc->mc_length = mu->mu_datasize;
2012    mc->mc_private = mu;
2013    error = bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data,
2014			    mc->mc_length, mlx_user_cb, mc, BUS_DMA_NOWAIT);
2015
2016    /* copy out status and data */
2017    mu->mu_status = mc->mc_status;
2018    if ((mu->mu_datasize > 0) &&
2019	((error = copyout(kbuf, mu->mu_buf, mu->mu_datasize))))
2020	goto out;
2021
2022    error = 0;
2023
2024 out:
2025    mlx_releasecmd(mc);
2026    if (kbuf != NULL)
2027	free(kbuf, M_DEVBUF);
2028    return(error);
2029}
2030
2031/********************************************************************************
2032 ********************************************************************************
2033                                                        Command I/O to Controller
2034 ********************************************************************************
2035 ********************************************************************************/
2036
2037/********************************************************************************
2038 * Find a free command slot for (mc).
2039 *
2040 * Don't hand out a slot to a normal-priority command unless there are at least
2041 * 4 slots free for priority commands.
2042 */
2043static int
2044mlx_getslot(struct mlx_command *mc)
2045{
2046    struct mlx_softc	*sc = mc->mc_sc;
2047    int			s, slot, limit;
2048
2049    debug_called(1);
2050
2051    /*
2052     * Enforce slot-usage limit, if we have the required information.
2053     */
2054    if (sc->mlx_enq2 != NULL) {
2055	limit = sc->mlx_enq2->me_max_commands;
2056    } else {
2057	limit = 2;
2058    }
2059    if (sc->mlx_busycmds >= ((mc->mc_flags & MLX_CMD_PRIORITY) ? limit : limit - 4))
2060	return(EBUSY);
2061
2062    /*
2063     * Allocate an outstanding command slot
2064     *
2065     * XXX linear search is slow
2066     */
2067    s = splbio();
2068    for (slot = 0; slot < limit; slot++) {
2069	debug(2, "try slot %d", slot);
2070	if (sc->mlx_busycmd[slot] == NULL)
2071	    break;
2072    }
2073    if (slot < limit) {
2074	sc->mlx_busycmd[slot] = mc;
2075	sc->mlx_busycmds++;
2076    }
2077    splx(s);
2078
2079    /* out of slots? */
2080    if (slot >= limit)
2081	return(EBUSY);
2082
2083    debug(2, "got slot %d", slot);
2084    mc->mc_slot = slot;
2085    return(0);
2086}
2087
2088/********************************************************************************
2089 * Map/unmap (mc)'s data in the controller's addressable space.
2090 */
2091static void
2092mlx_setup_dmamap(struct mlx_command *mc, bus_dma_segment_t *segs, int nsegments,
2093		 int error)
2094{
2095    struct mlx_softc	*sc = mc->mc_sc;
2096    struct mlx_sgentry	*sg;
2097    int			i;
2098
2099    debug_called(1);
2100
2101    /* XXX should be unnecessary */
2102    if (sc->mlx_enq2 && (nsegments > sc->mlx_enq2->me_max_sg))
2103	panic("MLX: too many s/g segments (%d, max %d)", nsegments,
2104	      sc->mlx_enq2->me_max_sg);
2105
2106    /* get base address of s/g table */
2107    sg = sc->mlx_sgtable + (mc->mc_slot * MLX_NSEG);
2108
2109    /* save s/g table information in command */
2110    mc->mc_nsgent = nsegments;
2111    mc->mc_sgphys = sc->mlx_sgbusaddr +
2112		   (mc->mc_slot * MLX_NSEG * sizeof(struct mlx_sgentry));
2113    mc->mc_dataphys = segs[0].ds_addr;
2114
2115    /* populate s/g table */
2116    for (i = 0; i < nsegments; i++, sg++) {
2117	sg->sg_addr = segs[i].ds_addr;
2118	sg->sg_count = segs[i].ds_len;
2119    }
2120
2121    /* Make sure the buffers are visible on the bus. */
2122    if (mc->mc_flags & MLX_CMD_DATAIN)
2123	bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap,
2124			BUS_DMASYNC_PREREAD);
2125    if (mc->mc_flags & MLX_CMD_DATAOUT)
2126	bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap,
2127			BUS_DMASYNC_PREWRITE);
2128}
2129
2130static void
2131mlx_unmapcmd(struct mlx_command *mc)
2132{
2133    struct mlx_softc	*sc = mc->mc_sc;
2134
2135    debug_called(1);
2136
2137    /* if the command involved data at all */
2138    if (mc->mc_data != NULL) {
2139
2140	if (mc->mc_flags & MLX_CMD_DATAIN)
2141	    bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTREAD);
2142	if (mc->mc_flags & MLX_CMD_DATAOUT)
2143	    bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTWRITE);
2144
2145	bus_dmamap_unload(sc->mlx_buffer_dmat, mc->mc_dmamap);
2146    }
2147}
2148
2149/********************************************************************************
2150 * Try to deliver (mc) to the controller.
2151 *
2152 * Can be called at any interrupt level, with or without interrupts enabled.
2153 */
2154static int
2155mlx_start(struct mlx_command *mc)
2156{
2157    struct mlx_softc	*sc = mc->mc_sc;
2158    int			i, s, done;
2159
2160    debug_called(1);
2161
2162    /* save the slot number as ident so we can handle this command when complete */
2163    mc->mc_mailbox[0x1] = mc->mc_slot;
2164
2165    /* mark the command as currently being processed */
2166    mc->mc_status = MLX_STATUS_BUSY;
2167
2168    /* set a default 60-second timeout  XXX tunable?  XXX not currently used */
2169    mc->mc_timeout = time_second + 60;
2170
2171    /* spin waiting for the mailbox */
2172    for (i = 100000, done = 0; (i > 0) && !done; i--) {
2173	s = splbio();
2174	if (sc->mlx_tryqueue(sc, mc)) {
2175	    done = 1;
2176	    /* move command to work queue */
2177	    TAILQ_INSERT_TAIL(&sc->mlx_work, mc, mc_link);
2178	}
2179	splx(s);	/* drop spl to allow completion interrupts */
2180    }
2181
2182    /* command is enqueued */
2183    if (done)
2184	return(0);
2185
2186    /*
2187     * We couldn't get the controller to take the command.  Revoke the slot
2188     * that the command was given and return it with a bad status.
2189     */
2190    sc->mlx_busycmd[mc->mc_slot] = NULL;
2191    device_printf(sc->mlx_dev, "controller wedged (not taking commands)\n");
2192    mc->mc_status = MLX_STATUS_WEDGED;
2193    mlx_complete(sc);
2194    return(EIO);
2195}
2196
2197/********************************************************************************
2198 * Poll the controller (sc) for completed commands.
2199 * Update command status and free slots for reuse.  If any slots were freed,
2200 * new commands may be posted.
2201 *
2202 * Returns nonzero if one or more commands were completed.
2203 */
2204static int
2205mlx_done(struct mlx_softc *sc)
2206{
2207    struct mlx_command	*mc;
2208    int			s, result;
2209    u_int8_t		slot;
2210    u_int16_t		status;
2211
2212    debug_called(2);
2213
2214    result = 0;
2215
2216    /* loop collecting completed commands */
2217    s = splbio();
2218    for (;;) {
2219	/* poll for a completed command's identifier and status */
2220	if (sc->mlx_findcomplete(sc, &slot, &status)) {
2221	    result = 1;
2222	    mc = sc->mlx_busycmd[slot];			/* find command */
2223	    if (mc != NULL) {				/* paranoia */
2224		if (mc->mc_status == MLX_STATUS_BUSY) {
2225		    mc->mc_status = status;		/* save status */
2226
2227		    /* free slot for reuse */
2228		    sc->mlx_busycmd[slot] = NULL;
2229		    sc->mlx_busycmds--;
2230		} else {
2231		    device_printf(sc->mlx_dev, "duplicate done event for slot %d\n", slot);
2232		}
2233	    } else {
2234		device_printf(sc->mlx_dev, "done event for nonbusy slot %d\n", slot);
2235	    }
2236	} else {
2237	    break;
2238	}
2239    }
2240    splx(s);
2241
2242    /* if we've completed any commands, try posting some more */
2243    if (result)
2244	mlx_startio(sc);
2245
2246    /* handle completion and timeouts */
2247    mlx_complete(sc);
2248
2249    return(result);
2250}
2251
2252/********************************************************************************
2253 * Perform post-completion processing for commands on (sc).
2254 */
2255static void
2256mlx_complete(struct mlx_softc *sc)
2257{
2258    struct mlx_command	*mc, *nc;
2259    int			s, count;
2260
2261    debug_called(2);
2262
2263    /* avoid reentrancy  XXX might want to signal and request a restart */
2264    if (mlx_lock_tas(sc, MLX_LOCK_COMPLETING))
2265	return;
2266
2267    s = splbio();
2268    count = 0;
2269
2270    /* scan the list of busy/done commands */
2271    mc = TAILQ_FIRST(&sc->mlx_work);
2272    while (mc != NULL) {
2273	nc = TAILQ_NEXT(mc, mc_link);
2274
2275	/* Command has been completed in some fashion */
2276	if (mc->mc_status != MLX_STATUS_BUSY) {
2277
2278	    /* unmap the command's data buffer */
2279	    mlx_unmapcmd(mc);
2280	    /*
2281	     * Does the command have a completion handler?
2282	     */
2283	    if (mc->mc_complete != NULL) {
2284		/* remove from list and give to handler */
2285		TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
2286		mc->mc_complete(mc);
2287
2288		/*
2289		 * Is there a sleeper waiting on this command?
2290		 */
2291	    } else if (mc->mc_private != NULL) {	/* sleeping caller wants to know about it */
2292
2293		/* remove from list and wake up sleeper */
2294		TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
2295		wakeup_one(mc->mc_private);
2296
2297		/*
2298		 * Leave the command for a caller that's polling for it.
2299		 */
2300	    } else {
2301	    }
2302	}
2303	mc = nc;
2304    }
2305    splx(s);
2306
2307    mlx_lock_clr(sc, MLX_LOCK_COMPLETING);
2308}
2309
2310/********************************************************************************
2311 ********************************************************************************
2312                                                        Command Buffer Management
2313 ********************************************************************************
2314 ********************************************************************************/
2315
2316/********************************************************************************
2317 * Get a new command buffer.
2318 *
2319 * This may return NULL in low-memory cases.
2320 *
2321 * Note that using malloc() is expensive (the command buffer is << 1 page) but
2322 * necessary if we are to be a loadable module before the zone allocator is fixed.
2323 *
2324 * If possible, we recycle a command buffer that's been used before.
2325 *
2326 * XXX Note that command buffers are not cleaned out - it is the caller's
2327 *     responsibility to ensure that all required fields are filled in before
2328 *     using a buffer.
2329 */
2330static struct mlx_command *
2331mlx_alloccmd(struct mlx_softc *sc)
2332{
2333    struct mlx_command	*mc;
2334    int			error;
2335    int			s;
2336
2337    debug_called(1);
2338
2339    s = splbio();
2340    if ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL)
2341	TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link);
2342    splx(s);
2343
2344    /* allocate a new command buffer? */
2345    if (mc == NULL) {
2346	mc = (struct mlx_command *)malloc(sizeof(*mc), M_DEVBUF, M_NOWAIT | M_ZERO);
2347	if (mc != NULL) {
2348	    mc->mc_sc = sc;
2349	    error = bus_dmamap_create(sc->mlx_buffer_dmat, 0, &mc->mc_dmamap);
2350	    if (error) {
2351		free(mc, M_DEVBUF);
2352		return(NULL);
2353	    }
2354	}
2355    }
2356    return(mc);
2357}
2358
2359/********************************************************************************
2360 * Release a command buffer for recycling.
2361 *
2362 * XXX It might be a good idea to limit the number of commands we save for reuse
2363 *     if it's shown that this list bloats out massively.
2364 */
2365static void
2366mlx_releasecmd(struct mlx_command *mc)
2367{
2368    int		s;
2369
2370    debug_called(1);
2371
2372    s = splbio();
2373    TAILQ_INSERT_HEAD(&mc->mc_sc->mlx_freecmds, mc, mc_link);
2374    splx(s);
2375}
2376
2377/********************************************************************************
2378 * Permanently discard a command buffer.
2379 */
2380static void
2381mlx_freecmd(struct mlx_command *mc)
2382{
2383    struct mlx_softc	*sc = mc->mc_sc;
2384
2385    debug_called(1);
2386    bus_dmamap_destroy(sc->mlx_buffer_dmat, mc->mc_dmamap);
2387    free(mc, M_DEVBUF);
2388}
2389
2390
2391/********************************************************************************
2392 ********************************************************************************
2393                                                Type 3 interface accessor methods
2394 ********************************************************************************
2395 ********************************************************************************/
2396
2397/********************************************************************************
2398 * Try to give (mc) to the controller.  Returns 1 if successful, 0 on failure
2399 * (the controller is not ready to take a command).
2400 *
2401 * Must be called at splbio or in a fashion that prevents reentry.
2402 */
2403static int
2404mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2405{
2406    int		i;
2407
2408    debug_called(2);
2409
2410    /* ready for our command? */
2411    if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_FULL)) {
2412	/* copy mailbox data to window */
2413	for (i = 0; i < 13; i++)
2414	    MLX_V3_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
2415
2416	/* post command */
2417	MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_FULL);
2418	return(1);
2419    }
2420    return(0);
2421}
2422
2423/********************************************************************************
2424 * See if a command has been completed, if so acknowledge its completion
2425 * and recover the slot number and status code.
2426 *
2427 * Must be called at splbio or in a fashion that prevents reentry.
2428 */
2429static int
2430mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2431{
2432
2433    debug_called(2);
2434
2435    /* status available? */
2436    if (MLX_V3_GET_ODBR(sc) & MLX_V3_ODB_SAVAIL) {
2437	*slot = MLX_V3_GET_STATUS_IDENT(sc);		/* get command identifier */
2438	*status = MLX_V3_GET_STATUS(sc);		/* get status */
2439
2440	/* acknowledge completion */
2441	MLX_V3_PUT_ODBR(sc, MLX_V3_ODB_SAVAIL);
2442	MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_SACK);
2443	return(1);
2444    }
2445    return(0);
2446}
2447
2448/********************************************************************************
2449 * Enable/disable interrupts as requested. (No acknowledge required)
2450 *
2451 * Must be called at splbio or in a fashion that prevents reentry.
2452 */
2453static void
2454mlx_v3_intaction(struct mlx_softc *sc, int action)
2455{
2456    debug_called(1);
2457
2458    switch(action) {
2459    case MLX_INTACTION_DISABLE:
2460	MLX_V3_PUT_IER(sc, 0);
2461	sc->mlx_state &= ~MLX_STATE_INTEN;
2462	break;
2463    case MLX_INTACTION_ENABLE:
2464	MLX_V3_PUT_IER(sc, 1);
2465	sc->mlx_state |= MLX_STATE_INTEN;
2466	break;
2467    }
2468}
2469
2470/********************************************************************************
2471 * Poll for firmware error codes during controller initialisation.
2472 * Returns 0 if initialisation is complete, 1 if still in progress but no
2473 * error has been fetched, 2 if an error has been retrieved.
2474 */
2475static int
2476mlx_v3_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2)
2477{
2478    u_int8_t	fwerror;
2479    static int	initted = 0;
2480
2481    debug_called(2);
2482
2483    /* first time around, clear any hardware completion status */
2484    if (!initted) {
2485	MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_SACK);
2486	DELAY(1000);
2487	initted = 1;
2488    }
2489
2490    /* init in progress? */
2491    if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_INIT_BUSY))
2492	return(0);
2493
2494    /* test error value */
2495    fwerror = MLX_V3_GET_FWERROR(sc);
2496    if (!(fwerror & MLX_V3_FWERROR_PEND))
2497	return(1);
2498
2499    /* mask status pending bit, fetch status */
2500    *error = fwerror & ~MLX_V3_FWERROR_PEND;
2501    *param1 = MLX_V3_GET_FWERROR_PARAM1(sc);
2502    *param2 = MLX_V3_GET_FWERROR_PARAM2(sc);
2503
2504    /* acknowledge */
2505    MLX_V3_PUT_FWERROR(sc, 0);
2506
2507    return(2);
2508}
2509
2510/********************************************************************************
2511 ********************************************************************************
2512                                                Type 4 interface accessor methods
2513 ********************************************************************************
2514 ********************************************************************************/
2515
2516/********************************************************************************
2517 * Try to give (mc) to the controller.  Returns 1 if successful, 0 on failure
2518 * (the controller is not ready to take a command).
2519 *
2520 * Must be called at splbio or in a fashion that prevents reentry.
2521 */
2522static int
2523mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2524{
2525    int		i;
2526
2527    debug_called(2);
2528
2529    /* ready for our command? */
2530    if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_FULL)) {
2531	/* copy mailbox data to window */
2532	for (i = 0; i < 13; i++)
2533	    MLX_V4_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
2534
2535	/* memory-mapped controller, so issue a write barrier to ensure the mailbox is filled */
2536	bus_space_barrier(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_MAILBOX, MLX_V4_MAILBOX_LENGTH,
2537			  BUS_SPACE_BARRIER_WRITE);
2538
2539	/* post command */
2540	MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_HWMBOX_CMD);
2541	return(1);
2542    }
2543    return(0);
2544}
2545
2546/********************************************************************************
2547 * See if a command has been completed, if so acknowledge its completion
2548 * and recover the slot number and status code.
2549 *
2550 * Must be called at splbio or in a fashion that prevents reentry.
2551 */
2552static int
2553mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2554{
2555
2556    debug_called(2);
2557
2558    /* status available? */
2559    if (MLX_V4_GET_ODBR(sc) & MLX_V4_ODB_HWSAVAIL) {
2560	*slot = MLX_V4_GET_STATUS_IDENT(sc);		/* get command identifier */
2561	*status = MLX_V4_GET_STATUS(sc);		/* get status */
2562
2563	/* acknowledge completion */
2564	MLX_V4_PUT_ODBR(sc, MLX_V4_ODB_HWMBOX_ACK);
2565	MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_SACK);
2566	return(1);
2567    }
2568    return(0);
2569}
2570
2571/********************************************************************************
2572 * Enable/disable interrupts as requested.
2573 *
2574 * Must be called at splbio or in a fashion that prevents reentry.
2575 */
2576static void
2577mlx_v4_intaction(struct mlx_softc *sc, int action)
2578{
2579    debug_called(1);
2580
2581    switch(action) {
2582    case MLX_INTACTION_DISABLE:
2583	MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK | MLX_V4_IER_DISINT);
2584	sc->mlx_state &= ~MLX_STATE_INTEN;
2585	break;
2586    case MLX_INTACTION_ENABLE:
2587	MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK & ~MLX_V4_IER_DISINT);
2588	sc->mlx_state |= MLX_STATE_INTEN;
2589	break;
2590    }
2591}
2592
2593/********************************************************************************
2594 * Poll for firmware error codes during controller initialisation.
2595 * Returns 0 if initialisation is complete, 1 if still in progress but no
2596 * error has been fetched, 2 if an error has been retrieved.
2597 */
2598static int
2599mlx_v4_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2)
2600{
2601    u_int8_t	fwerror;
2602    static int	initted = 0;
2603
2604    debug_called(2);
2605
2606    /* first time around, clear any hardware completion status */
2607    if (!initted) {
2608	MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_SACK);
2609	DELAY(1000);
2610	initted = 1;
2611    }
2612
2613    /* init in progress? */
2614    if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_INIT_BUSY))
2615	return(0);
2616
2617    /* test error value */
2618    fwerror = MLX_V4_GET_FWERROR(sc);
2619    if (!(fwerror & MLX_V4_FWERROR_PEND))
2620	return(1);
2621
2622    /* mask status pending bit, fetch status */
2623    *error = fwerror & ~MLX_V4_FWERROR_PEND;
2624    *param1 = MLX_V4_GET_FWERROR_PARAM1(sc);
2625    *param2 = MLX_V4_GET_FWERROR_PARAM2(sc);
2626
2627    /* acknowledge */
2628    MLX_V4_PUT_FWERROR(sc, 0);
2629
2630    return(2);
2631}
2632
2633/********************************************************************************
2634 ********************************************************************************
2635                                                Type 5 interface accessor methods
2636 ********************************************************************************
2637 ********************************************************************************/
2638
2639/********************************************************************************
2640 * Try to give (mc) to the controller.  Returns 1 if successful, 0 on failure
2641 * (the controller is not ready to take a command).
2642 *
2643 * Must be called at splbio or in a fashion that prevents reentry.
2644 */
2645static int
2646mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2647{
2648    int		i;
2649
2650    debug_called(2);
2651
2652    /* ready for our command? */
2653    if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_EMPTY) {
2654	/* copy mailbox data to window */
2655	for (i = 0; i < 13; i++)
2656	    MLX_V5_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
2657
2658	/* post command */
2659	MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_HWMBOX_CMD);
2660	return(1);
2661    }
2662    return(0);
2663}
2664
2665/********************************************************************************
2666 * See if a command has been completed, if so acknowledge its completion
2667 * and recover the slot number and status code.
2668 *
2669 * Must be called at splbio or in a fashion that prevents reentry.
2670 */
2671static int
2672mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2673{
2674
2675    debug_called(2);
2676
2677    /* status available? */
2678    if (MLX_V5_GET_ODBR(sc) & MLX_V5_ODB_HWSAVAIL) {
2679	*slot = MLX_V5_GET_STATUS_IDENT(sc);		/* get command identifier */
2680	*status = MLX_V5_GET_STATUS(sc);		/* get status */
2681
2682	/* acknowledge completion */
2683	MLX_V5_PUT_ODBR(sc, MLX_V5_ODB_HWMBOX_ACK);
2684	MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_SACK);
2685	return(1);
2686    }
2687    return(0);
2688}
2689
2690/********************************************************************************
2691 * Enable/disable interrupts as requested.
2692 *
2693 * Must be called at splbio or in a fashion that prevents reentry.
2694 */
2695static void
2696mlx_v5_intaction(struct mlx_softc *sc, int action)
2697{
2698    debug_called(1);
2699
2700    switch(action) {
2701    case MLX_INTACTION_DISABLE:
2702	MLX_V5_PUT_IER(sc, 0xff & MLX_V5_IER_DISINT);
2703	sc->mlx_state &= ~MLX_STATE_INTEN;
2704	break;
2705    case MLX_INTACTION_ENABLE:
2706	MLX_V5_PUT_IER(sc, 0xff & ~MLX_V5_IER_DISINT);
2707	sc->mlx_state |= MLX_STATE_INTEN;
2708	break;
2709    }
2710}
2711
2712/********************************************************************************
2713 * Poll for firmware error codes during controller initialisation.
2714 * Returns 0 if initialisation is complete, 1 if still in progress but no
2715 * error has been fetched, 2 if an error has been retrieved.
2716 */
2717static int
2718mlx_v5_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2)
2719{
2720    u_int8_t	fwerror;
2721    static int	initted = 0;
2722
2723    debug_called(2);
2724
2725    /* first time around, clear any hardware completion status */
2726    if (!initted) {
2727	MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_SACK);
2728	DELAY(1000);
2729	initted = 1;
2730    }
2731
2732    /* init in progress? */
2733    if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_INIT_DONE)
2734	return(0);
2735
2736    /* test for error value */
2737    fwerror = MLX_V5_GET_FWERROR(sc);
2738    if (!(fwerror & MLX_V5_FWERROR_PEND))
2739	return(1);
2740
2741    /* mask status pending bit, fetch status */
2742    *error = fwerror & ~MLX_V5_FWERROR_PEND;
2743    *param1 = MLX_V5_GET_FWERROR_PARAM1(sc);
2744    *param2 = MLX_V5_GET_FWERROR_PARAM2(sc);
2745
2746    /* acknowledge */
2747    MLX_V5_PUT_FWERROR(sc, 0xff);
2748
2749    return(2);
2750}
2751
2752/********************************************************************************
2753 ********************************************************************************
2754                                                                        Debugging
2755 ********************************************************************************
2756 ********************************************************************************/
2757
2758/********************************************************************************
2759 * Return a status message describing (mc)
2760 */
2761static char *mlx_status_messages[] = {
2762    "normal completion",			/* 00 */
2763    "irrecoverable data error",			/* 01 */
2764    "drive does not exist, or is offline",	/* 02 */
2765    "attempt to write beyond end of drive",	/* 03 */
2766    "bad data encountered",			/* 04 */
2767    "invalid log entry request",		/* 05 */
2768    "attempt to rebuild online drive",		/* 06 */
2769    "new disk failed during rebuild",		/* 07 */
2770    "invalid channel/target",			/* 08 */
2771    "rebuild/check already in progress",	/* 09 */
2772    "one or more disks are dead",		/* 10 */
2773    "invalid or non-redundant drive",		/* 11 */
2774    "channel is busy",				/* 12 */
2775    "channel is not stopped",			/* 13 */
2776    "rebuild successfully terminated",		/* 14 */
2777    "unsupported command",			/* 15 */
2778    "check condition received",			/* 16 */
2779    "device is busy",				/* 17 */
2780    "selection or command timeout",		/* 18 */
2781    "command terminated abnormally",		/* 19 */
2782    ""
2783};
2784
2785static struct
2786{
2787    int		command;
2788    u_int16_t	status;
2789    int		msg;
2790} mlx_messages[] = {
2791    {MLX_CMD_READSG,		0x0001,	 1},
2792    {MLX_CMD_READSG,		0x0002,	 1},
2793    {MLX_CMD_READSG,		0x0105,	 3},
2794    {MLX_CMD_READSG,		0x010c,	 4},
2795    {MLX_CMD_WRITESG,		0x0001,	 1},
2796    {MLX_CMD_WRITESG,		0x0002,	 1},
2797    {MLX_CMD_WRITESG,		0x0105,	 3},
2798    {MLX_CMD_READSG_OLD,	0x0001,	 1},
2799    {MLX_CMD_READSG_OLD,	0x0002,	 1},
2800    {MLX_CMD_READSG_OLD,	0x0105,	 3},
2801    {MLX_CMD_WRITESG_OLD,	0x0001,	 1},
2802    {MLX_CMD_WRITESG_OLD,	0x0002,	 1},
2803    {MLX_CMD_WRITESG_OLD,	0x0105,	 3},
2804    {MLX_CMD_LOGOP,		0x0105,	 5},
2805    {MLX_CMD_REBUILDASYNC,	0x0002,  6},
2806    {MLX_CMD_REBUILDASYNC,	0x0004,  7},
2807    {MLX_CMD_REBUILDASYNC,	0x0105,  8},
2808    {MLX_CMD_REBUILDASYNC,	0x0106,  9},
2809    {MLX_CMD_REBUILDASYNC,	0x0107, 14},
2810    {MLX_CMD_CHECKASYNC,	0x0002, 10},
2811    {MLX_CMD_CHECKASYNC,	0x0105, 11},
2812    {MLX_CMD_CHECKASYNC,	0x0106,  9},
2813    {MLX_CMD_STOPCHANNEL,	0x0106, 12},
2814    {MLX_CMD_STOPCHANNEL,	0x0105,  8},
2815    {MLX_CMD_STARTCHANNEL,	0x0005, 13},
2816    {MLX_CMD_STARTCHANNEL,	0x0105,  8},
2817    {MLX_CMD_DIRECT_CDB,	0x0002, 16},
2818    {MLX_CMD_DIRECT_CDB,	0x0008, 17},
2819    {MLX_CMD_DIRECT_CDB,	0x000e, 18},
2820    {MLX_CMD_DIRECT_CDB,	0x000f, 19},
2821    {MLX_CMD_DIRECT_CDB,	0x0105,  8},
2822
2823    {0,				0x0104, 14},
2824    {-1, 0, 0}
2825};
2826
2827static char *
2828mlx_diagnose_command(struct mlx_command *mc)
2829{
2830    static char	unkmsg[80];
2831    int		i;
2832
2833    /* look up message in table */
2834    for (i = 0; mlx_messages[i].command != -1; i++)
2835	if (((mc->mc_mailbox[0] == mlx_messages[i].command) || (mlx_messages[i].command == 0)) &&
2836	    (mc->mc_status == mlx_messages[i].status))
2837	    return(mlx_status_messages[mlx_messages[i].msg]);
2838
2839    sprintf(unkmsg, "unknown response 0x%x for command 0x%x", (int)mc->mc_status, (int)mc->mc_mailbox[0]);
2840    return(unkmsg);
2841}
2842
2843/*******************************************************************************
2844 * Print a string describing the controller (sc)
2845 */
2846static struct
2847{
2848    int		hwid;
2849    char	*name;
2850} mlx_controller_names[] = {
2851    {0x01,	"960P/PD"},
2852    {0x02,	"960PL"},
2853    {0x10,	"960PG"},
2854    {0x11,	"960PJ"},
2855    {0x12,	"960PR"},
2856    {0x13,	"960PT"},
2857    {0x14,	"960PTL0"},
2858    {0x15,	"960PRL"},
2859    {0x16,	"960PTL1"},
2860    {0x20,	"1164PVX"},
2861    {-1, NULL}
2862};
2863
2864static void
2865mlx_describe_controller(struct mlx_softc *sc)
2866{
2867    static char		buf[80];
2868    char		*model;
2869    int			i;
2870
2871    for (i = 0, model = NULL; mlx_controller_names[i].name != NULL; i++) {
2872	if ((sc->mlx_enq2->me_hardware_id & 0xff) == mlx_controller_names[i].hwid) {
2873	    model = mlx_controller_names[i].name;
2874	    break;
2875	}
2876    }
2877    if (model == NULL) {
2878	sprintf(buf, " model 0x%x", sc->mlx_enq2->me_hardware_id & 0xff);
2879	model = buf;
2880    }
2881    device_printf(sc->mlx_dev, "DAC%s, %d channel%s, firmware %d.%02d-%c-%02d, %dMB RAM\n",
2882		  model,
2883		  sc->mlx_enq2->me_actual_channels,
2884		  sc->mlx_enq2->me_actual_channels > 1 ? "s" : "",
2885		  sc->mlx_enq2->me_firmware_id & 0xff,
2886		  (sc->mlx_enq2->me_firmware_id >> 8) & 0xff,
2887		  (sc->mlx_enq2->me_firmware_id >> 24) & 0xff,
2888		  (sc->mlx_enq2->me_firmware_id >> 16) & 0xff,
2889		  sc->mlx_enq2->me_mem_size / (1024 * 1024));
2890
2891    if (bootverbose) {
2892	device_printf(sc->mlx_dev, "  Hardware ID                 0x%08x\n", sc->mlx_enq2->me_hardware_id);
2893	device_printf(sc->mlx_dev, "  Firmware ID                 0x%08x\n", sc->mlx_enq2->me_firmware_id);
2894	device_printf(sc->mlx_dev, "  Configured/Actual channels  %d/%d\n", sc->mlx_enq2->me_configured_channels,
2895		      sc->mlx_enq2->me_actual_channels);
2896	device_printf(sc->mlx_dev, "  Max Targets                 %d\n", sc->mlx_enq2->me_max_targets);
2897	device_printf(sc->mlx_dev, "  Max Tags                    %d\n", sc->mlx_enq2->me_max_tags);
2898	device_printf(sc->mlx_dev, "  Max System Drives           %d\n", sc->mlx_enq2->me_max_sys_drives);
2899	device_printf(sc->mlx_dev, "  Max Arms                    %d\n", sc->mlx_enq2->me_max_arms);
2900	device_printf(sc->mlx_dev, "  Max Spans                   %d\n", sc->mlx_enq2->me_max_spans);
2901	device_printf(sc->mlx_dev, "  DRAM/cache/flash/NVRAM size %d/%d/%d/%d\n", sc->mlx_enq2->me_mem_size,
2902		      sc->mlx_enq2->me_cache_size, sc->mlx_enq2->me_flash_size, sc->mlx_enq2->me_nvram_size);
2903	device_printf(sc->mlx_dev, "  DRAM type                   %d\n", sc->mlx_enq2->me_mem_type);
2904	device_printf(sc->mlx_dev, "  Clock Speed                 %dns\n", sc->mlx_enq2->me_clock_speed);
2905	device_printf(sc->mlx_dev, "  Hardware Speed              %dns\n", sc->mlx_enq2->me_hardware_speed);
2906	device_printf(sc->mlx_dev, "  Max Commands                %d\n", sc->mlx_enq2->me_max_commands);
2907	device_printf(sc->mlx_dev, "  Max SG Entries              %d\n", sc->mlx_enq2->me_max_sg);
2908	device_printf(sc->mlx_dev, "  Max DP                      %d\n", sc->mlx_enq2->me_max_dp);
2909	device_printf(sc->mlx_dev, "  Max IOD                     %d\n", sc->mlx_enq2->me_max_iod);
2910	device_printf(sc->mlx_dev, "  Max Comb                    %d\n", sc->mlx_enq2->me_max_comb);
2911	device_printf(sc->mlx_dev, "  Latency                     %ds\n", sc->mlx_enq2->me_latency);
2912	device_printf(sc->mlx_dev, "  SCSI Timeout                %ds\n", sc->mlx_enq2->me_scsi_timeout);
2913	device_printf(sc->mlx_dev, "  Min Free Lines              %d\n", sc->mlx_enq2->me_min_freelines);
2914	device_printf(sc->mlx_dev, "  Rate Constant               %d\n", sc->mlx_enq2->me_rate_const);
2915	device_printf(sc->mlx_dev, "  MAXBLK                      %d\n", sc->mlx_enq2->me_maxblk);
2916	device_printf(sc->mlx_dev, "  Blocking Factor             %d sectors\n", sc->mlx_enq2->me_blocking_factor);
2917	device_printf(sc->mlx_dev, "  Cache Line Size             %d blocks\n", sc->mlx_enq2->me_cacheline);
2918	device_printf(sc->mlx_dev, "  SCSI Capability             %s%dMHz, %d bit\n",
2919		      sc->mlx_enq2->me_scsi_cap & (1<<4) ? "differential " : "",
2920		      (1 << ((sc->mlx_enq2->me_scsi_cap >> 2) & 3)) * 10,
2921		      8 << (sc->mlx_enq2->me_scsi_cap & 0x3));
2922	device_printf(sc->mlx_dev, "  Firmware Build Number       %d\n", sc->mlx_enq2->me_firmware_build);
2923	device_printf(sc->mlx_dev, "  Fault Management Type       %d\n", sc->mlx_enq2->me_fault_mgmt_type);
2924	device_printf(sc->mlx_dev, "  Features                    %b\n", sc->mlx_enq2->me_firmware_features,
2925		      "\20\4Background Init\3Read Ahead\2MORE\1Cluster\n");
2926
2927    }
2928}
2929
2930/*******************************************************************************
2931 * Emit a string describing the firmware handshake status code, and return a flag
2932 * indicating whether the code represents a fatal error.
2933 *
2934 * Error code interpretations are from the Linux driver, and don't directly match
2935 * the messages printed by Mylex's BIOS.  This may change if documentation on the
2936 * codes is forthcoming.
2937 */
2938static int
2939mlx_fw_message(struct mlx_softc *sc, int error, int param1, int param2)
2940{
2941    switch(error) {
2942    case 0x00:
2943	device_printf(sc->mlx_dev, "physical drive %d:%d not responding\n", param2, param1);
2944	break;
2945    case 0x08:
2946	/* we could be neater about this and give some indication when we receive more of them */
2947	if (!(sc->mlx_flags & MLX_SPINUP_REPORTED)) {
2948	    device_printf(sc->mlx_dev, "spinning up drives...\n");
2949	    sc->mlx_flags |= MLX_SPINUP_REPORTED;
2950	}
2951	break;
2952    case 0x30:
2953	device_printf(sc->mlx_dev, "configuration checksum error\n");
2954	break;
2955    case 0x60:
2956	device_printf(sc->mlx_dev, "mirror race recovery failed\n");
2957	break;
2958    case 0x70:
2959	device_printf(sc->mlx_dev, "mirror race recovery in progress\n");
2960	break;
2961    case 0x90:
2962	device_printf(sc->mlx_dev, "physical drive %d:%d COD mismatch\n", param2, param1);
2963	break;
2964    case 0xa0:
2965	device_printf(sc->mlx_dev, "logical drive installation aborted\n");
2966	break;
2967    case 0xb0:
2968	device_printf(sc->mlx_dev, "mirror race on a critical system drive\n");
2969	break;
2970    case 0xd0:
2971	device_printf(sc->mlx_dev, "new controller configuration found\n");
2972	break;
2973    case 0xf0:
2974	device_printf(sc->mlx_dev, "FATAL MEMORY PARITY ERROR\n");
2975	return(1);
2976    default:
2977	device_printf(sc->mlx_dev, "unknown firmware initialisation error %02x:%02x:%02x\n", error, param1, param2);
2978	break;
2979    }
2980    return(0);
2981}
2982
2983/********************************************************************************
2984 ********************************************************************************
2985                                                                Utility Functions
2986 ********************************************************************************
2987 ********************************************************************************/
2988
2989/********************************************************************************
2990 * Find the disk whose unit number is (unit) on this controller
2991 */
2992static struct mlx_sysdrive *
2993mlx_findunit(struct mlx_softc *sc, int unit)
2994{
2995    int		i;
2996
2997    /* search system drives */
2998    for (i = 0; i < MLX_MAXDRIVES; i++) {
2999	/* is this one attached? */
3000	if (sc->mlx_sysdrive[i].ms_disk != 0) {
3001	    /* is this the one? */
3002	    if (unit == device_get_unit(sc->mlx_sysdrive[i].ms_disk))
3003		return(&sc->mlx_sysdrive[i]);
3004	}
3005    }
3006    return(NULL);
3007}
3008