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