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