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