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