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