mlx.c revision 92608
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 92608 2002-03-18 20:50:04Z imp $
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/devicestat.h>
41#include <sys/disk.h>
42#include <sys/stat.h>
43
44#include <machine/resource.h>
45#include <machine/bus_memio.h>
46#include <machine/bus_pio.h>
47#include <machine/bus.h>
48#include <machine/clock.h>
49#include <sys/rman.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		/* open */	mlx_open,
60		/* close */	mlx_close,
61		/* read */	noread,
62		/* write */	nowrite,
63		/* ioctl */	mlx_ioctl,
64		/* poll */	nopoll,
65		/* mmap */	nommap,
66		/* strategy */	nostrategy,
67		/* name */ 	"mlx",
68		/* maj */	MLX_CDEV_MAJOR,
69		/* dump */	nodump,
70		/* psize */ 	nopsize,
71		/* flags */	0,
72};
73
74devclass_t	mlx_devclass;
75
76/*
77 * Per-interface accessor methods
78 */
79static int			mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
80static int			mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
81static void			mlx_v3_intaction(struct mlx_softc *sc, int action);
82static int			mlx_v3_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2);
83
84static int			mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
85static int			mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
86static void			mlx_v4_intaction(struct mlx_softc *sc, int action);
87static int			mlx_v4_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2);
88
89static int			mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
90static int			mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
91static void			mlx_v5_intaction(struct mlx_softc *sc, int action);
92static int			mlx_v5_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2);
93
94/*
95 * Status monitoring
96 */
97static void			mlx_periodic(void *data);
98static void			mlx_periodic_enquiry(struct mlx_command *mc);
99static void			mlx_periodic_eventlog_poll(struct mlx_softc *sc);
100static void			mlx_periodic_eventlog_respond(struct mlx_command *mc);
101static void			mlx_periodic_rebuild(struct mlx_command *mc);
102
103/*
104 * Channel Pause
105 */
106static void			mlx_pause_action(struct mlx_softc *sc);
107static void			mlx_pause_done(struct mlx_command *mc);
108
109/*
110 * Command submission.
111 */
112static void			*mlx_enquire(struct mlx_softc *sc, int command, size_t bufsize,
113					     void (*complete)(struct mlx_command *mc));
114static int			mlx_flush(struct mlx_softc *sc);
115static int			mlx_check(struct mlx_softc *sc, int drive);
116static int			mlx_rebuild(struct mlx_softc *sc, int channel, int target);
117static int			mlx_wait_command(struct mlx_command *mc);
118static int			mlx_poll_command(struct mlx_command *mc);
119static void			mlx_startio(struct mlx_softc *sc);
120static void			mlx_completeio(struct mlx_command *mc);
121static int			mlx_user_command(struct mlx_softc *sc, struct mlx_usercommand *mu);
122
123/*
124 * Command buffer allocation.
125 */
126static struct mlx_command	*mlx_alloccmd(struct mlx_softc *sc);
127static void			mlx_releasecmd(struct mlx_command *mc);
128static void			mlx_freecmd(struct mlx_command *mc);
129
130/*
131 * Command management.
132 */
133static int			mlx_getslot(struct mlx_command *mc);
134static void			mlx_mapcmd(struct mlx_command *mc);
135static void			mlx_unmapcmd(struct mlx_command *mc);
136static int			mlx_start(struct mlx_command *mc);
137static int			mlx_done(struct mlx_softc *sc);
138static void			mlx_complete(struct mlx_softc *sc);
139
140/*
141 * Debugging.
142 */
143static char			*mlx_diagnose_command(struct mlx_command *mc);
144static void			mlx_describe_controller(struct mlx_softc *sc);
145static int			mlx_fw_message(struct mlx_softc *sc, int status, int param1, int param2);
146
147/*
148 * Utility functions.
149 */
150static struct mlx_sysdrive	*mlx_findunit(struct mlx_softc *sc, int unit);
151
152/********************************************************************************
153 ********************************************************************************
154                                                                Public Interfaces
155 ********************************************************************************
156 ********************************************************************************/
157
158/********************************************************************************
159 * Free all of the resources associated with (sc)
160 *
161 * Should not be called if the controller is active.
162 */
163void
164mlx_free(struct mlx_softc *sc)
165{
166    struct mlx_command	*mc;
167
168    debug_called(1);
169
170    /* cancel status timeout */
171    untimeout(mlx_periodic, sc, sc->mlx_timeout);
172
173    /* throw away any command buffers */
174    while ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL) {
175	TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link);
176	mlx_freecmd(mc);
177    }
178
179    /* destroy data-transfer DMA tag */
180    if (sc->mlx_buffer_dmat)
181	bus_dma_tag_destroy(sc->mlx_buffer_dmat);
182
183    /* free and destroy DMA memory and tag for s/g lists */
184    if (sc->mlx_sgtable)
185	bus_dmamem_free(sc->mlx_sg_dmat, sc->mlx_sgtable, sc->mlx_sg_dmamap);
186    if (sc->mlx_sg_dmat)
187	bus_dma_tag_destroy(sc->mlx_sg_dmat);
188
189    /* disconnect the interrupt handler */
190    if (sc->mlx_intr)
191	bus_teardown_intr(sc->mlx_dev, sc->mlx_irq, sc->mlx_intr);
192    if (sc->mlx_irq != NULL)
193	bus_release_resource(sc->mlx_dev, SYS_RES_IRQ, 0, sc->mlx_irq);
194
195    /* destroy the parent DMA tag */
196    if (sc->mlx_parent_dmat)
197	bus_dma_tag_destroy(sc->mlx_parent_dmat);
198
199    /* release the register window mapping */
200    if (sc->mlx_mem != NULL)
201	bus_release_resource(sc->mlx_dev, sc->mlx_mem_type, sc->mlx_mem_rid, sc->mlx_mem);
202
203    /* free controller enquiry data */
204    if (sc->mlx_enq2 != NULL)
205	free(sc->mlx_enq2, M_DEVBUF);
206
207    /* destroy control device */
208    if (sc->mlx_dev_t != (dev_t)NULL)
209	destroy_dev(sc->mlx_dev_t);
210}
211
212/********************************************************************************
213 * Map the scatter/gather table into bus space
214 */
215static void
216mlx_dma_map_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error)
217{
218    struct mlx_softc	*sc = (struct mlx_softc *)arg;
219
220    debug_called(1);
221
222    /* save base of s/g table's address in bus space */
223    sc->mlx_sgbusaddr = segs->ds_addr;
224}
225
226static int
227mlx_sglist_map(struct mlx_softc *sc)
228{
229    size_t	segsize;
230    int		error, ncmd;
231
232    debug_called(1);
233
234    /* destroy any existing mappings */
235    if (sc->mlx_sgtable)
236	bus_dmamem_free(sc->mlx_sg_dmat, sc->mlx_sgtable, sc->mlx_sg_dmamap);
237    if (sc->mlx_sg_dmat)
238	bus_dma_tag_destroy(sc->mlx_sg_dmat);
239
240    /*
241     * Create a single tag describing a region large enough to hold all of
242     * the s/g lists we will need.  If we're called early on, we don't know how
243     * many commands we're going to be asked to support, so only allocate enough
244     * for a couple.
245     */
246    if (sc->mlx_enq2 == NULL) {
247	ncmd = 2;
248    } else {
249	ncmd = sc->mlx_enq2->me_max_commands;
250    }
251    segsize = sizeof(struct mlx_sgentry) * MLX_NSEG * ncmd;
252    error = bus_dma_tag_create(sc->mlx_parent_dmat, 	/* parent */
253			       1, 0, 			/* alignment, boundary */
254			       BUS_SPACE_MAXADDR,	/* lowaddr */
255			       BUS_SPACE_MAXADDR, 	/* highaddr */
256			       NULL, NULL, 		/* filter, filterarg */
257			       segsize, 1,		/* maxsize, nsegments */
258			       BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
259			       0,			/* flags */
260			       &sc->mlx_sg_dmat);
261    if (error != 0) {
262	device_printf(sc->mlx_dev, "can't allocate scatter/gather DMA tag\n");
263	return(ENOMEM);
264    }
265
266    /*
267     * Allocate enough s/g maps for all commands and permanently map them into
268     * controller-visible space.
269     *
270     * XXX this assumes we can get enough space for all the s/g maps in one
271     * contiguous slab.  We may need to switch to a more complex arrangement where
272     * we allocate in smaller chunks and keep a lookup table from slot to bus address.
273     */
274    error = bus_dmamem_alloc(sc->mlx_sg_dmat, (void **)&sc->mlx_sgtable, BUS_DMA_NOWAIT, &sc->mlx_sg_dmamap);
275    if (error) {
276	device_printf(sc->mlx_dev, "can't allocate s/g table\n");
277	return(ENOMEM);
278    }
279    bus_dmamap_load(sc->mlx_sg_dmat, sc->mlx_sg_dmamap, sc->mlx_sgtable, segsize, mlx_dma_map_sg, sc, 0);
280    return(0);
281}
282
283/********************************************************************************
284 * Initialise the controller and softc
285 */
286int
287mlx_attach(struct mlx_softc *sc)
288{
289    struct mlx_enquiry_old	*meo;
290    int				rid, error, fwminor, hscode, hserror, hsparam1, hsparam2, hsmsg;
291
292    debug_called(1);
293
294    /*
295     * Initialise per-controller queues.
296     */
297    TAILQ_INIT(&sc->mlx_work);
298    TAILQ_INIT(&sc->mlx_freecmds);
299    MLX_BIO_QINIT(sc->mlx_bioq);
300
301    /*
302     * Select accessor methods based on controller interface type.
303     */
304    switch(sc->mlx_iftype) {
305    case MLX_IFTYPE_2:
306    case MLX_IFTYPE_3:
307	sc->mlx_tryqueue	= mlx_v3_tryqueue;
308	sc->mlx_findcomplete	= mlx_v3_findcomplete;
309	sc->mlx_intaction	= mlx_v3_intaction;
310	sc->mlx_fw_handshake	= mlx_v3_fw_handshake;
311	break;
312    case MLX_IFTYPE_4:
313	sc->mlx_tryqueue	= mlx_v4_tryqueue;
314	sc->mlx_findcomplete	= mlx_v4_findcomplete;
315	sc->mlx_intaction	= mlx_v4_intaction;
316	sc->mlx_fw_handshake	= mlx_v4_fw_handshake;
317	break;
318    case MLX_IFTYPE_5:
319	sc->mlx_tryqueue	= mlx_v5_tryqueue;
320	sc->mlx_findcomplete	= mlx_v5_findcomplete;
321	sc->mlx_intaction	= mlx_v5_intaction;
322	sc->mlx_fw_handshake	= mlx_v5_fw_handshake;
323	break;
324    default:
325	mlx_free(sc);
326	return(ENXIO);		/* should never happen */
327    }
328
329    /* disable interrupts before we start talking to the controller */
330    sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
331
332    /*
333     * Wait for the controller to come ready, handshake with the firmware if required.
334     * This is typically only necessary on platforms where the controller BIOS does not
335     * run.
336     */
337    hsmsg = 0;
338    DELAY(1000);
339    while ((hscode = sc->mlx_fw_handshake(sc, &hserror, &hsparam1, &hsparam2)) != 0) {
340	/* report first time around... */
341	if (hsmsg == 0) {
342	    device_printf(sc->mlx_dev, "controller initialisation in progress...\n");
343	    hsmsg = 1;
344	}
345	/* did we get a real message? */
346	if (hscode == 2) {
347	    hscode = mlx_fw_message(sc, hserror, hsparam1, hsparam2);
348	    /* fatal initialisation error? */
349	    if (hscode != 0) {
350		mlx_free(sc);
351		return(ENXIO);
352	    }
353	}
354    }
355    if (hsmsg == 1)
356	device_printf(sc->mlx_dev, "initialisation complete.\n");
357
358    /*
359     * Allocate and connect our interrupt.
360     */
361    rid = 0;
362    sc->mlx_irq = bus_alloc_resource(sc->mlx_dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);
363    if (sc->mlx_irq == NULL) {
364	device_printf(sc->mlx_dev, "can't allocate interrupt\n");
365	mlx_free(sc);
366	return(ENXIO);
367    }
368    error = bus_setup_intr(sc->mlx_dev, sc->mlx_irq, INTR_TYPE_BIO | INTR_ENTROPY,  mlx_intr, sc, &sc->mlx_intr);
369    if (error) {
370	device_printf(sc->mlx_dev, "can't set up interrupt\n");
371	mlx_free(sc);
372	return(ENXIO);
373    }
374
375    /*
376     * Create DMA tag for mapping buffers into controller-addressable space.
377     */
378    error = bus_dma_tag_create(sc->mlx_parent_dmat, 		/* parent */
379			       1, 0, 				/* alignment, boundary */
380			       BUS_SPACE_MAXADDR,		/* lowaddr */
381			       BUS_SPACE_MAXADDR, 		/* highaddr */
382			       NULL, NULL, 			/* filter, filterarg */
383			       MAXBSIZE, MLX_NSEG,		/* maxsize, nsegments */
384			       BUS_SPACE_MAXSIZE_32BIT,		/* maxsegsize */
385			       0,				/* flags */
386			       &sc->mlx_buffer_dmat);
387    if (error != 0) {
388	device_printf(sc->mlx_dev, "can't allocate buffer DMA tag\n");
389	mlx_free(sc);
390	return(ENOMEM);
391    }
392
393    /*
394     * Create some initial scatter/gather mappings so we can run the probe commands.
395     */
396    error = mlx_sglist_map(sc);
397    if (error != 0) {
398	device_printf(sc->mlx_dev, "can't make initial s/g list mapping\n");
399	mlx_free(sc);
400	return(error);
401    }
402
403    /*
404     * We don't (yet) know where the event log is up to.
405     */
406    sc->mlx_currevent = -1;
407
408    /*
409     * Obtain controller feature information
410     */
411    if ((sc->mlx_enq2 = mlx_enquire(sc, MLX_CMD_ENQUIRY2, sizeof(struct mlx_enquiry2), NULL)) == NULL) {
412	device_printf(sc->mlx_dev, "ENQUIRY2 failed\n");
413	mlx_free(sc);
414	return(ENXIO);
415    }
416
417    /*
418     * Do quirk/feature related things.
419     */
420    fwminor = (sc->mlx_enq2->me_firmware_id >> 8) & 0xff;
421    switch(sc->mlx_iftype) {
422    case MLX_IFTYPE_2:
423	/* These controllers don't report the firmware version in the ENQUIRY2 response */
424	if ((meo = mlx_enquire(sc, MLX_CMD_ENQUIRY_OLD, sizeof(struct mlx_enquiry_old), NULL)) == NULL) {
425	    device_printf(sc->mlx_dev, "ENQUIRY_OLD failed\n");
426	    mlx_free(sc);
427	    return(ENXIO);
428	}
429	sc->mlx_enq2->me_firmware_id = ('0' << 24) | (0 << 16) | (meo->me_fwminor << 8) | meo->me_fwmajor;
430	free(meo, M_DEVBUF);
431
432	/* XXX require 2.42 or better (PCI) or 2.14 or better (EISA) */
433	if (meo->me_fwminor < 42) {
434	    device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
435	    device_printf(sc->mlx_dev, " *** WARNING *** Use revision 2.42 or later\n");
436	}
437	break;
438    case MLX_IFTYPE_3:
439	/* XXX certify 3.52? */
440	if (fwminor < 51) {
441	    device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
442	    device_printf(sc->mlx_dev, " *** WARNING *** Use revision 3.51 or later\n");
443	}
444	break;
445    case MLX_IFTYPE_4:
446	/* XXX certify firmware versions? */
447	if (fwminor < 6) {
448	    device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
449	    device_printf(sc->mlx_dev, " *** WARNING *** Use revision 4.06 or later\n");
450	}
451	break;
452    case MLX_IFTYPE_5:
453	if (fwminor < 7) {
454	    device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
455	    device_printf(sc->mlx_dev, " *** WARNING *** Use revision 5.07 or later\n");
456	}
457	break;
458    default:
459	mlx_free(sc);
460	return(ENXIO);		/* should never happen */
461    }
462
463    /*
464     * Create the final scatter/gather mappings now that we have characterised the controller.
465     */
466    error = mlx_sglist_map(sc);
467    if (error != 0) {
468	device_printf(sc->mlx_dev, "can't make final s/g list mapping\n");
469	mlx_free(sc);
470	return(error);
471    }
472
473    /*
474     * No user-requested background operation is in progress.
475     */
476    sc->mlx_background = 0;
477    sc->mlx_rebuildstat.rs_code = MLX_REBUILDSTAT_IDLE;
478
479    /*
480     * Create the control device.
481     */
482    sc->mlx_dev_t = make_dev(&mlx_cdevsw, device_get_unit(sc->mlx_dev), UID_ROOT, GID_OPERATOR,
483			     S_IRUSR | S_IWUSR, "mlx%d", device_get_unit(sc->mlx_dev));
484
485    /*
486     * Start the timeout routine.
487     */
488    sc->mlx_timeout = timeout(mlx_periodic, sc, hz);
489
490    /* print a little information about the controller */
491    mlx_describe_controller(sc);
492
493    return(0);
494}
495
496/********************************************************************************
497 * Locate disk resources and attach children to them.
498 */
499void
500mlx_startup(struct mlx_softc *sc)
501{
502    struct mlx_enq_sys_drive	*mes;
503    struct mlx_sysdrive		*dr;
504    int				i, error;
505
506    debug_called(1);
507
508    /*
509     * Scan all the system drives and attach children for those that
510     * don't currently have them.
511     */
512    mes = mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(*mes) * MLX_MAXDRIVES, NULL);
513    if (mes == NULL) {
514	device_printf(sc->mlx_dev, "error fetching drive status\n");
515	return;
516    }
517
518    /* iterate over drives returned */
519    for (i = 0, dr = &sc->mlx_sysdrive[0];
520	 (i < MLX_MAXDRIVES) && (mes[i].sd_size != 0xffffffff);
521	 i++, dr++) {
522	/* are we already attached to this drive? */
523    	if (dr->ms_disk == 0) {
524	    /* pick up drive information */
525	    dr->ms_size = mes[i].sd_size;
526	    dr->ms_raidlevel = mes[i].sd_raidlevel & 0xf;
527	    dr->ms_state = mes[i].sd_state;
528
529	    /* generate geometry information */
530	    if (sc->mlx_geom == MLX_GEOM_128_32) {
531		dr->ms_heads = 128;
532		dr->ms_sectors = 32;
533		dr->ms_cylinders = dr->ms_size / (128 * 32);
534	    } else {        /* MLX_GEOM_255/63 */
535		dr->ms_heads = 255;
536		dr->ms_sectors = 63;
537		dr->ms_cylinders = dr->ms_size / (255 * 63);
538	    }
539	    dr->ms_disk =  device_add_child(sc->mlx_dev, /*"mlxd"*/NULL, -1);
540	    if (dr->ms_disk == 0)
541		device_printf(sc->mlx_dev, "device_add_child failed\n");
542	    device_set_ivars(dr->ms_disk, dr);
543	}
544    }
545    free(mes, M_DEVBUF);
546    if ((error = bus_generic_attach(sc->mlx_dev)) != 0)
547	device_printf(sc->mlx_dev, "bus_generic_attach returned %d", error);
548
549    /* mark controller back up */
550    sc->mlx_state &= ~MLX_STATE_SHUTDOWN;
551
552    /* enable interrupts */
553    sc->mlx_intaction(sc, MLX_INTACTION_ENABLE);
554}
555
556/********************************************************************************
557 * Disconnect from the controller completely, in preparation for unload.
558 */
559int
560mlx_detach(device_t dev)
561{
562    struct mlx_softc	*sc = device_get_softc(dev);
563    struct mlxd_softc	*mlxd;
564    int			i, s, error;
565
566    debug_called(1);
567
568    error = EBUSY;
569    s = splbio();
570    if (sc->mlx_state & MLX_STATE_OPEN)
571	goto out;
572
573    for (i = 0; i < MLX_MAXDRIVES; i++) {
574	if (sc->mlx_sysdrive[i].ms_disk != 0) {
575	    mlxd = device_get_softc(sc->mlx_sysdrive[i].ms_disk);
576	    if (mlxd->mlxd_flags & MLXD_OPEN) {		/* drive is mounted, abort detach */
577		device_printf(sc->mlx_sysdrive[i].ms_disk, "still open, can't detach\n");
578		goto out;
579	    }
580	}
581    }
582    if ((error = mlx_shutdown(dev)))
583	goto out;
584
585    mlx_free(sc);
586
587    error = 0;
588 out:
589    splx(s);
590    return(error);
591}
592
593/********************************************************************************
594 * Bring the controller down to a dormant state and detach all child devices.
595 *
596 * This function is called before detach, system shutdown, or before performing
597 * an operation which may add or delete system disks.  (Call mlx_startup to
598 * resume normal operation.)
599 *
600 * Note that we can assume that the bioq on the controller is empty, as we won't
601 * allow shutdown if any device is open.
602 */
603int
604mlx_shutdown(device_t dev)
605{
606    struct mlx_softc	*sc = device_get_softc(dev);
607    int			i, s, error;
608
609    debug_called(1);
610
611    s = splbio();
612    error = 0;
613
614    sc->mlx_state |= MLX_STATE_SHUTDOWN;
615    sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
616
617    /* flush controller */
618    device_printf(sc->mlx_dev, "flushing cache...");
619    if (mlx_flush(sc)) {
620	printf("failed\n");
621    } else {
622	printf("done\n");
623    }
624
625    /* delete all our child devices */
626    for (i = 0; i < MLX_MAXDRIVES; i++) {
627	if (sc->mlx_sysdrive[i].ms_disk != 0) {
628	    if ((error = device_delete_child(sc->mlx_dev, sc->mlx_sysdrive[i].ms_disk)) != 0)
629		goto out;
630	    sc->mlx_sysdrive[i].ms_disk = 0;
631	}
632    }
633
634 out:
635    splx(s);
636    return(error);
637}
638
639/********************************************************************************
640 * Bring the controller to a quiescent state, ready for system suspend.
641 */
642int
643mlx_suspend(device_t dev)
644{
645    struct mlx_softc	*sc = device_get_softc(dev);
646    int			s;
647
648    debug_called(1);
649
650    s = splbio();
651    sc->mlx_state |= MLX_STATE_SUSPEND;
652
653    /* flush controller */
654    device_printf(sc->mlx_dev, "flushing cache...");
655    printf("%s\n", mlx_flush(sc) ? "failed" : "done");
656
657    sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
658    splx(s);
659
660    return(0);
661}
662
663/********************************************************************************
664 * Bring the controller back to a state ready for operation.
665 */
666int
667mlx_resume(device_t dev)
668{
669    struct mlx_softc	*sc = device_get_softc(dev);
670
671    debug_called(1);
672
673    sc->mlx_state &= ~MLX_STATE_SUSPEND;
674    sc->mlx_intaction(sc, MLX_INTACTION_ENABLE);
675
676    return(0);
677}
678
679/*******************************************************************************
680 * Take an interrupt, or be poked by other code to look for interrupt-worthy
681 * status.
682 */
683void
684mlx_intr(void *arg)
685{
686    struct mlx_softc	*sc = (struct mlx_softc *)arg;
687
688    debug_called(1);
689
690    /* collect finished commands, queue anything waiting */
691    mlx_done(sc);
692};
693
694/*******************************************************************************
695 * Receive a buf structure from a child device and queue it on a particular
696 * disk resource, then poke the disk resource to start as much work as it can.
697 */
698int
699mlx_submit_buf(struct mlx_softc *sc, mlx_bio *bp)
700{
701    int		s;
702
703    debug_called(1);
704
705    s = splbio();
706    MLX_BIO_QINSERT(sc->mlx_bioq, bp);
707    sc->mlx_waitbufs++;
708    splx(s);
709    mlx_startio(sc);
710    return(0);
711}
712
713/********************************************************************************
714 * Accept an open operation on the control device.
715 */
716int
717mlx_open(dev_t dev, int flags, int fmt, struct thread *td)
718{
719    int			unit = minor(dev);
720    struct mlx_softc	*sc = devclass_get_softc(mlx_devclass, unit);
721
722    sc->mlx_state |= MLX_STATE_OPEN;
723    return(0);
724}
725
726/********************************************************************************
727 * Accept the last close on the control device.
728 */
729int
730mlx_close(dev_t dev, int flags, int fmt, struct thread *td)
731{
732    int			unit = minor(dev);
733    struct mlx_softc	*sc = devclass_get_softc(mlx_devclass, unit);
734
735    sc->mlx_state &= ~MLX_STATE_OPEN;
736    return (0);
737}
738
739/********************************************************************************
740 * Handle controller-specific control operations.
741 */
742int
743mlx_ioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td)
744{
745    int				unit = minor(dev);
746    struct mlx_softc		*sc = devclass_get_softc(mlx_devclass, unit);
747    struct mlx_rebuild_request	*rb = (struct mlx_rebuild_request *)addr;
748    struct mlx_rebuild_status	*rs = (struct mlx_rebuild_status *)addr;
749    int				*arg = (int *)addr;
750    struct mlx_pause		*mp;
751    struct mlx_sysdrive		*dr;
752    struct mlxd_softc		*mlxd;
753    int				i, error;
754
755    switch(cmd) {
756	/*
757	 * Enumerate connected system drives; returns the first system drive's
758	 * unit number if *arg is -1, or the next unit after *arg if it's
759	 * a valid unit on this controller.
760	 */
761    case MLX_NEXT_CHILD:
762	/* search system drives */
763	for (i = 0; i < MLX_MAXDRIVES; i++) {
764	    /* is this one attached? */
765	    if (sc->mlx_sysdrive[i].ms_disk != 0) {
766		/* looking for the next one we come across? */
767		if (*arg == -1) {
768		    *arg = device_get_unit(sc->mlx_sysdrive[0].ms_disk);
769		    return(0);
770		}
771		/* we want the one after this one */
772		if (*arg == device_get_unit(sc->mlx_sysdrive[i].ms_disk))
773		    *arg = -1;
774	    }
775	}
776	return(ENOENT);
777
778	/*
779	 * Scan the controller to see whether new drives have appeared.
780	 */
781    case MLX_RESCAN_DRIVES:
782	mlx_startup(sc);
783	return(0);
784
785	/*
786	 * Disconnect from the specified drive; it may be about to go
787	 * away.
788	 */
789    case MLX_DETACH_DRIVE:			/* detach one drive */
790
791	if (((dr = mlx_findunit(sc, *arg)) == NULL) ||
792	    ((mlxd = device_get_softc(dr->ms_disk)) == NULL))
793	    return(ENOENT);
794
795	device_printf(dr->ms_disk, "detaching...");
796	error = 0;
797	if (mlxd->mlxd_flags & MLXD_OPEN) {
798	    error = EBUSY;
799	    goto detach_out;
800	}
801
802	/* flush controller */
803	if (mlx_flush(sc)) {
804	    error = EBUSY;
805	    goto detach_out;
806	}
807
808	/* nuke drive */
809	if ((error = device_delete_child(sc->mlx_dev, dr->ms_disk)) != 0)
810	    goto detach_out;
811	dr->ms_disk = 0;
812
813    detach_out:
814	if (error) {
815	    printf("failed\n");
816	} else {
817	    printf("done\n");
818	}
819	return(error);
820
821	/*
822	 * Pause one or more SCSI channels for a period of time, to assist
823	 * in the process of hot-swapping devices.
824	 *
825	 * Note that at least the 3.51 firmware on the DAC960PL doesn't seem
826	 * to do this right.
827	 */
828    case MLX_PAUSE_CHANNEL:			/* schedule a channel pause */
829	/* Does this command work on this firmware? */
830	if (!(sc->mlx_feature & MLX_FEAT_PAUSEWORKS))
831	    return(EOPNOTSUPP);
832
833	mp = (struct mlx_pause *)addr;
834	if ((mp->mp_which == MLX_PAUSE_CANCEL) && (sc->mlx_pause.mp_when != 0)) {
835	    /* cancel a pending pause operation */
836	    sc->mlx_pause.mp_which = 0;
837	} else {
838	    /* fix for legal channels */
839	    mp->mp_which &= ((1 << sc->mlx_enq2->me_actual_channels) -1);
840	    /* check time values */
841	    if ((mp->mp_when < 0) || (mp->mp_when > 3600))
842		return(EINVAL);
843	    if ((mp->mp_howlong < 1) || (mp->mp_howlong > (0xf * 30)))
844		return(EINVAL);
845
846	    /* check for a pause currently running */
847	    if ((sc->mlx_pause.mp_which != 0) && (sc->mlx_pause.mp_when == 0))
848		return(EBUSY);
849
850	    /* looks ok, go with it */
851	    sc->mlx_pause.mp_which = mp->mp_which;
852	    sc->mlx_pause.mp_when = time_second + mp->mp_when;
853	    sc->mlx_pause.mp_howlong = sc->mlx_pause.mp_when + mp->mp_howlong;
854	}
855	return(0);
856
857	/*
858	 * Accept a command passthrough-style.
859	 */
860    case MLX_COMMAND:
861	return(mlx_user_command(sc, (struct mlx_usercommand *)addr));
862
863	/*
864	 * Start a rebuild on a given SCSI disk
865	 */
866    case MLX_REBUILDASYNC:
867	if (sc->mlx_background != 0) {
868	    rb->rr_status = 0x0106;
869	    return(EBUSY);
870	}
871	rb->rr_status = mlx_rebuild(sc, rb->rr_channel, rb->rr_target);
872	switch (rb->rr_status) {
873	case 0:
874	    error = 0;
875	    break;
876	case 0x10000:
877	    error = ENOMEM;		/* couldn't set up the command */
878	    break;
879	case 0x0002:
880	    error = EBUSY;
881	    break;
882	case 0x0104:
883	    error = EIO;
884	    break;
885	case 0x0105:
886	    error = ERANGE;
887	    break;
888	case 0x0106:
889	    error = EBUSY;
890	    break;
891	default:
892	    error = EINVAL;
893	    break;
894	}
895	if (error == 0)
896	    sc->mlx_background = MLX_BACKGROUND_REBUILD;
897	return(error);
898
899	/*
900	 * Get the status of the current rebuild or consistency check.
901	 */
902    case MLX_REBUILDSTAT:
903	*rs = sc->mlx_rebuildstat;
904	return(0);
905
906	/*
907	 * Return the per-controller system drive number matching the
908	 * disk device number in (arg), if it happens to belong to us.
909	 */
910    case MLX_GET_SYSDRIVE:
911	error = ENOENT;
912	mlxd = (struct mlxd_softc *)devclass_get_softc(mlxd_devclass, *arg);
913	if ((mlxd != NULL) && (mlxd->mlxd_drive >= sc->mlx_sysdrive) &&
914	    (mlxd->mlxd_drive < (sc->mlx_sysdrive + MLX_MAXDRIVES))) {
915	    error = 0;
916	    *arg = mlxd->mlxd_drive - sc->mlx_sysdrive;
917	}
918	return(error);
919
920    default:
921	return(ENOTTY);
922    }
923}
924
925/********************************************************************************
926 * Handle operations requested by a System Drive connected to this controller.
927 */
928int
929mlx_submit_ioctl(struct mlx_softc *sc, struct mlx_sysdrive *drive, u_long cmd,
930		caddr_t addr, int32_t flag, struct thread *td)
931{
932    int				*arg = (int *)addr;
933    int				error, result;
934
935    switch(cmd) {
936	/*
937	 * Return the current status of this drive.
938	 */
939    case MLXD_STATUS:
940	*arg = drive->ms_state;
941	return(0);
942
943	/*
944	 * Start a background consistency check on this drive.
945	 */
946    case MLXD_CHECKASYNC:		/* start a background consistency check */
947	if (sc->mlx_background != 0) {
948	    *arg = 0x0106;
949	    return(EBUSY);
950	}
951	result = mlx_check(sc, drive - &sc->mlx_sysdrive[0]);
952	switch (result) {
953	case 0:
954	    error = 0;
955	    break;
956	case 0x10000:
957	    error = ENOMEM;		/* couldn't set up the command */
958	    break;
959	case 0x0002:
960	    error = EIO;
961	    break;
962	case 0x0105:
963	    error = ERANGE;
964	    break;
965	case 0x0106:
966	    error = EBUSY;
967	    break;
968	default:
969	    error = EINVAL;
970	    break;
971	}
972	if (error == 0)
973	    sc->mlx_background = MLX_BACKGROUND_CHECK;
974	*arg = result;
975	return(error);
976
977    }
978    return(ENOIOCTL);
979}
980
981
982/********************************************************************************
983 ********************************************************************************
984                                                                Status Monitoring
985 ********************************************************************************
986 ********************************************************************************/
987
988/********************************************************************************
989 * Fire off commands to periodically check the status of connected drives.
990 */
991static void
992mlx_periodic(void *data)
993{
994    struct mlx_softc *sc = (struct mlx_softc *)data;
995
996    debug_called(1);
997
998    /*
999     * Run a bus pause?
1000     */
1001    if ((sc->mlx_pause.mp_which != 0) &&
1002	(sc->mlx_pause.mp_when > 0) &&
1003	(time_second >= sc->mlx_pause.mp_when)){
1004
1005	mlx_pause_action(sc);		/* pause is running */
1006	sc->mlx_pause.mp_when = 0;
1007	sysbeep(500, hz);
1008
1009	/*
1010	 * Bus pause still running?
1011	 */
1012    } else if ((sc->mlx_pause.mp_which != 0) &&
1013	       (sc->mlx_pause.mp_when == 0)) {
1014
1015	/* time to stop bus pause? */
1016	if (time_second >= sc->mlx_pause.mp_howlong) {
1017	    mlx_pause_action(sc);
1018	    sc->mlx_pause.mp_which = 0;	/* pause is complete */
1019	    sysbeep(500, hz);
1020	} else {
1021	    sysbeep((time_second % 5) * 100 + 500, hz/8);
1022	}
1023
1024	/*
1025	 * Run normal periodic activities?
1026	 */
1027    } else if (time_second > (sc->mlx_lastpoll + 10)) {
1028	sc->mlx_lastpoll = time_second;
1029
1030	/*
1031	 * Check controller status.
1032	 *
1033	 * XXX Note that this may not actually launch a command in situations of high load.
1034	 */
1035	mlx_enquire(sc, (sc->mlx_iftype == MLX_IFTYPE_2) ? MLX_CMD_ENQUIRY_OLD : MLX_CMD_ENQUIRY,
1036		    imax(sizeof(struct mlx_enquiry), sizeof(struct mlx_enquiry_old)), mlx_periodic_enquiry);
1037
1038	/*
1039	 * Check system drive status.
1040	 *
1041	 * XXX This might be better left to event-driven detection, eg. I/O to an offline
1042	 *     drive will detect it's offline, rebuilds etc. should detect the drive is back
1043	 *     online.
1044	 */
1045	mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(struct mlx_enq_sys_drive) * MLX_MAXDRIVES,
1046			mlx_periodic_enquiry);
1047
1048    }
1049
1050    /* get drive rebuild/check status */
1051    /* XXX should check sc->mlx_background if this is only valid while in progress */
1052    mlx_enquire(sc, MLX_CMD_REBUILDSTAT, sizeof(struct mlx_rebuild_stat), mlx_periodic_rebuild);
1053
1054    /* deal with possibly-missed interrupts and timed-out commands */
1055    mlx_done(sc);
1056
1057    /* reschedule another poll next second or so */
1058    sc->mlx_timeout = timeout(mlx_periodic, sc, hz);
1059}
1060
1061/********************************************************************************
1062 * Handle the result of an ENQUIRY command instigated by periodic status polling.
1063 */
1064static void
1065mlx_periodic_enquiry(struct mlx_command *mc)
1066{
1067    struct mlx_softc		*sc = mc->mc_sc;
1068
1069    debug_called(1);
1070
1071    /* Command completed OK? */
1072    if (mc->mc_status != 0) {
1073	device_printf(sc->mlx_dev, "periodic enquiry failed - %s\n", mlx_diagnose_command(mc));
1074	goto out;
1075    }
1076
1077    /* respond to command */
1078    switch(mc->mc_mailbox[0]) {
1079	/*
1080	 * This is currently a bit fruitless, as we don't know how to extract the eventlog
1081	 * pointer yet.
1082	 */
1083    case MLX_CMD_ENQUIRY_OLD:
1084    {
1085	struct mlx_enquiry		*me = (struct mlx_enquiry *)mc->mc_data;
1086	struct mlx_enquiry_old		*meo = (struct mlx_enquiry_old *)mc->mc_data;
1087	int				i;
1088
1089	/* convert data in-place to new format */
1090	for (i = (sizeof(me->me_dead) / sizeof(me->me_dead[0])) - 1; i >= 0; i--) {
1091	    me->me_dead[i].dd_chan = meo->me_dead[i].dd_chan;
1092	    me->me_dead[i].dd_targ = meo->me_dead[i].dd_targ;
1093	}
1094	me->me_misc_flags        = 0;
1095	me->me_rebuild_count     = meo->me_rebuild_count;
1096	me->me_dead_count        = meo->me_dead_count;
1097	me->me_critical_sd_count = meo->me_critical_sd_count;
1098	me->me_event_log_seq_num = 0;
1099	me->me_offline_sd_count  = meo->me_offline_sd_count;
1100	me->me_max_commands      = meo->me_max_commands;
1101	me->me_rebuild_flag      = meo->me_rebuild_flag;
1102	me->me_fwmajor           = meo->me_fwmajor;
1103	me->me_fwminor           = meo->me_fwminor;
1104	me->me_status_flags      = meo->me_status_flags;
1105	me->me_flash_age         = meo->me_flash_age;
1106	for (i = (sizeof(me->me_drvsize) / sizeof(me->me_drvsize[0])) - 1; i >= 0; i--) {
1107	    if (i > ((sizeof(meo->me_drvsize) / sizeof(meo->me_drvsize[0])) - 1)) {
1108		me->me_drvsize[i] = 0;		/* drive beyond supported range */
1109	    } else {
1110		me->me_drvsize[i] = meo->me_drvsize[i];
1111	    }
1112	}
1113	me->me_num_sys_drvs = meo->me_num_sys_drvs;
1114    }
1115    /* FALLTHROUGH */
1116
1117	/*
1118	 * Generic controller status update.  We could do more with this than just
1119	 * checking the event log.
1120	 */
1121    case MLX_CMD_ENQUIRY:
1122    {
1123	struct mlx_enquiry		*me = (struct mlx_enquiry *)mc->mc_data;
1124
1125	if (sc->mlx_currevent == -1) {
1126	    /* initialise our view of the event log */
1127	    sc->mlx_currevent = sc->mlx_lastevent = me->me_event_log_seq_num;
1128	} else if ((me->me_event_log_seq_num != sc->mlx_lastevent) && !(sc->mlx_flags & MLX_EVENTLOG_BUSY)) {
1129	    /* record where current events are up to */
1130	    sc->mlx_currevent = me->me_event_log_seq_num;
1131	    debug(1, "event log pointer was %d, now %d\n", sc->mlx_lastevent, sc->mlx_currevent);
1132
1133	    /* mark the event log as busy */
1134	    atomic_set_int(&sc->mlx_flags, MLX_EVENTLOG_BUSY);
1135
1136	    /* drain new eventlog entries */
1137	    mlx_periodic_eventlog_poll(sc);
1138	}
1139	break;
1140    }
1141    case MLX_CMD_ENQSYSDRIVE:
1142    {
1143	struct mlx_enq_sys_drive	*mes = (struct mlx_enq_sys_drive *)mc->mc_data;
1144	struct mlx_sysdrive		*dr;
1145	int				i;
1146
1147	for (i = 0, dr = &sc->mlx_sysdrive[0];
1148	     (i < MLX_MAXDRIVES) && (mes[i].sd_size != 0xffffffff);
1149	     i++) {
1150
1151	    /* has state been changed by controller? */
1152	    if (dr->ms_state != mes[i].sd_state) {
1153		switch(mes[i].sd_state) {
1154		case MLX_SYSD_OFFLINE:
1155		    device_printf(dr->ms_disk, "drive offline\n");
1156		    break;
1157		case MLX_SYSD_ONLINE:
1158		    device_printf(dr->ms_disk, "drive online\n");
1159		    break;
1160		case MLX_SYSD_CRITICAL:
1161		    device_printf(dr->ms_disk, "drive critical\n");
1162		    break;
1163		}
1164		/* save new state */
1165		dr->ms_state = mes[i].sd_state;
1166	    }
1167	}
1168	break;
1169    }
1170    default:
1171	device_printf(sc->mlx_dev, "%s: unknown command 0x%x", __func__, mc->mc_mailbox[0]);
1172	break;
1173    }
1174
1175 out:
1176    free(mc->mc_data, M_DEVBUF);
1177    mlx_releasecmd(mc);
1178}
1179
1180/********************************************************************************
1181 * Instigate a poll for one event log message on (sc).
1182 * We only poll for one message at a time, to keep our command usage down.
1183 */
1184static void
1185mlx_periodic_eventlog_poll(struct mlx_softc *sc)
1186{
1187    struct mlx_command	*mc;
1188    void		*result = NULL;
1189    int			error;
1190
1191    debug_called(1);
1192
1193    /* get ourselves a command buffer */
1194    error = 1;
1195    if ((mc = mlx_alloccmd(sc)) == NULL)
1196	goto out;
1197    /* allocate the response structure */
1198    if ((result = malloc(/*sizeof(struct mlx_eventlog_entry)*/1024, M_DEVBUF, M_NOWAIT)) == NULL)
1199	goto out;
1200    /* get a command slot */
1201    if (mlx_getslot(mc))
1202	goto out;
1203
1204    /* map the command so the controller can see it */
1205    mc->mc_data = result;
1206    mc->mc_length = /*sizeof(struct mlx_eventlog_entry)*/1024;
1207    mlx_mapcmd(mc);
1208
1209    /* build the command to get one entry */
1210    mlx_make_type3(mc, MLX_CMD_LOGOP, MLX_LOGOP_GET, 1, sc->mlx_lastevent, 0, 0, mc->mc_dataphys, 0);
1211    mc->mc_complete = mlx_periodic_eventlog_respond;
1212    mc->mc_private = mc;
1213
1214    /* start the command */
1215    if ((error = mlx_start(mc)) != 0)
1216	goto out;
1217
1218    error = 0;			/* success */
1219 out:
1220    if (error != 0) {
1221	if (mc != NULL)
1222	    mlx_releasecmd(mc);
1223	if (result != NULL)
1224	    free(result, M_DEVBUF);
1225    }
1226}
1227
1228/********************************************************************************
1229 * Handle the result of polling for a log message, generate diagnostic output.
1230 * If this wasn't the last message waiting for us, we'll go collect another.
1231 */
1232static char *mlx_sense_messages[] = {
1233    "because write recovery failed",
1234    "because of SCSI bus reset failure",
1235    "because of double check condition",
1236    "because it was removed",
1237    "because of gross error on SCSI chip",
1238    "because of bad tag returned from drive",
1239    "because of timeout on SCSI command",
1240    "because of reset SCSI command issued from system",
1241    "because busy or parity error count exceeded limit",
1242    "because of 'kill drive' command from system",
1243    "because of selection timeout",
1244    "due to SCSI phase sequence error",
1245    "due to unknown status"
1246};
1247
1248static void
1249mlx_periodic_eventlog_respond(struct mlx_command *mc)
1250{
1251    struct mlx_softc		*sc = mc->mc_sc;
1252    struct mlx_eventlog_entry	*el = (struct mlx_eventlog_entry *)mc->mc_data;
1253    char			*reason;
1254
1255    debug_called(1);
1256
1257    sc->mlx_lastevent++;		/* next message... */
1258    if (mc->mc_status == 0) {
1259
1260	/* handle event log message */
1261	switch(el->el_type) {
1262	    /*
1263	     * This is the only sort of message we understand at the moment.
1264	     * The tests here are probably incomplete.
1265	     */
1266	case MLX_LOGMSG_SENSE:	/* sense data */
1267	    /* Mylex vendor-specific message indicating a drive was killed? */
1268	    if ((el->el_sensekey == 9) &&
1269		(el->el_asc == 0x80)) {
1270		if (el->el_asq < (sizeof(mlx_sense_messages) / sizeof(mlx_sense_messages[0]))) {
1271		    reason = mlx_sense_messages[el->el_asq];
1272		} else {
1273		    reason = "for unknown reason";
1274		}
1275		device_printf(sc->mlx_dev, "physical drive %d:%d killed %s\n",
1276			      el->el_channel, el->el_target, reason);
1277	    }
1278	    /* SCSI drive was reset? */
1279	    if ((el->el_sensekey == 6) && (el->el_asc == 0x29)) {
1280		device_printf(sc->mlx_dev, "physical drive %d:%d reset\n",
1281			      el->el_channel, el->el_target);
1282	    }
1283	    /* SCSI drive error? */
1284	    if (!((el->el_sensekey == 0) ||
1285		  ((el->el_sensekey == 2) &&
1286		   (el->el_asc == 0x04) &&
1287		   ((el->el_asq == 0x01) ||
1288		    (el->el_asq == 0x02))))) {
1289		device_printf(sc->mlx_dev, "physical drive %d:%d error log: sense = %d asc = %x asq = %x\n",
1290			      el->el_channel, el->el_target, el->el_sensekey, el->el_asc, el->el_asq);
1291		device_printf(sc->mlx_dev, "  info %4D csi %4D\n", el->el_information, ":", el->el_csi, ":");
1292	    }
1293	    break;
1294
1295	default:
1296	    device_printf(sc->mlx_dev, "unknown log message type 0x%x\n", el->el_type);
1297	    break;
1298	}
1299    } else {
1300	device_printf(sc->mlx_dev, "error reading message log - %s\n", mlx_diagnose_command(mc));
1301	/* give up on all the outstanding messages, as we may have come unsynched */
1302	sc->mlx_lastevent = sc->mlx_currevent;
1303    }
1304
1305    /* dispose of command and data */
1306    free(mc->mc_data, M_DEVBUF);
1307    mlx_releasecmd(mc);
1308
1309    /* is there another message to obtain? */
1310    if (sc->mlx_lastevent != sc->mlx_currevent) {
1311	mlx_periodic_eventlog_poll(sc);
1312    } else {
1313	/* clear log-busy status */
1314	atomic_clear_int(&sc->mlx_flags, MLX_EVENTLOG_BUSY);
1315    }
1316}
1317
1318/********************************************************************************
1319 * Handle check/rebuild operations in progress.
1320 */
1321static void
1322mlx_periodic_rebuild(struct mlx_command *mc)
1323{
1324    struct mlx_softc		*sc = mc->mc_sc;
1325    struct mlx_rebuild_status	*mr = (struct mlx_rebuild_status *)mc->mc_data;
1326
1327    switch(mc->mc_status) {
1328    case 0:				/* operation running, update stats */
1329	sc->mlx_rebuildstat = *mr;
1330
1331	/* spontaneous rebuild/check? */
1332	if (sc->mlx_background == 0) {
1333	    sc->mlx_background = MLX_BACKGROUND_SPONTANEOUS;
1334	    device_printf(sc->mlx_dev, "background check/rebuild operation started\n");
1335	}
1336	break;
1337
1338    case 0x0105:			/* nothing running, finalise stats and report */
1339	switch(sc->mlx_background) {
1340	case MLX_BACKGROUND_CHECK:
1341	    device_printf(sc->mlx_dev, "consistency check completed\n");	/* XXX print drive? */
1342	    break;
1343	case MLX_BACKGROUND_REBUILD:
1344	    device_printf(sc->mlx_dev, "drive rebuild completed\n");	/* XXX print channel/target? */
1345	    break;
1346	case MLX_BACKGROUND_SPONTANEOUS:
1347	default:
1348	    /* if we have previously been non-idle, report the transition */
1349	    if (sc->mlx_rebuildstat.rs_code != MLX_REBUILDSTAT_IDLE) {
1350		device_printf(sc->mlx_dev, "background check/rebuild operation completed\n");
1351	    }
1352	}
1353	sc->mlx_background = 0;
1354	sc->mlx_rebuildstat.rs_code = MLX_REBUILDSTAT_IDLE;
1355	break;
1356    }
1357    free(mc->mc_data, M_DEVBUF);
1358    mlx_releasecmd(mc);
1359}
1360
1361/********************************************************************************
1362 ********************************************************************************
1363                                                                    Channel Pause
1364 ********************************************************************************
1365 ********************************************************************************/
1366
1367/********************************************************************************
1368 * It's time to perform a channel pause action for (sc), either start or stop
1369 * the pause.
1370 */
1371static void
1372mlx_pause_action(struct mlx_softc *sc)
1373{
1374    struct mlx_command	*mc;
1375    int			failsafe, i, command;
1376
1377    /* What are we doing here? */
1378    if (sc->mlx_pause.mp_when == 0) {
1379	command = MLX_CMD_STARTCHANNEL;
1380	failsafe = 0;
1381
1382    } else {
1383	command = MLX_CMD_STOPCHANNEL;
1384
1385	/*
1386	 * Channels will always start again after the failsafe period,
1387	 * which is specified in multiples of 30 seconds.
1388	 * This constrains us to a maximum pause of 450 seconds.
1389	 */
1390	failsafe = ((sc->mlx_pause.mp_howlong - time_second) + 5) / 30;
1391	if (failsafe > 0xf) {
1392	    failsafe = 0xf;
1393	    sc->mlx_pause.mp_howlong = time_second + (0xf * 30) - 5;
1394	}
1395    }
1396
1397    /* build commands for every channel requested */
1398    for (i = 0; i < sc->mlx_enq2->me_actual_channels; i++) {
1399	if ((1 << i) & sc->mlx_pause.mp_which) {
1400
1401	    /* get ourselves a command buffer */
1402	    if ((mc = mlx_alloccmd(sc)) == NULL)
1403		goto fail;
1404	    /* get a command slot */
1405	    mc->mc_flags |= MLX_CMD_PRIORITY;
1406	    if (mlx_getslot(mc))
1407		goto fail;
1408
1409	    /* build the command */
1410	    mlx_make_type2(mc, command, (failsafe << 4) | i, 0, 0, 0, 0, 0, 0, 0);
1411	    mc->mc_complete = mlx_pause_done;
1412	    mc->mc_private = sc;		/* XXX not needed */
1413	    if (mlx_start(mc))
1414		goto fail;
1415	    /* command submitted OK */
1416	    return;
1417
1418	fail:
1419	    device_printf(sc->mlx_dev, "%s failed for channel %d\n",
1420			  command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", i);
1421	    if (mc != NULL)
1422		mlx_releasecmd(mc);
1423	}
1424    }
1425}
1426
1427static void
1428mlx_pause_done(struct mlx_command *mc)
1429{
1430    struct mlx_softc	*sc = mc->mc_sc;
1431    int			command = mc->mc_mailbox[0];
1432    int			channel = mc->mc_mailbox[2] & 0xf;
1433
1434    if (mc->mc_status != 0) {
1435	device_printf(sc->mlx_dev, "%s command failed - %s\n",
1436		      command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", mlx_diagnose_command(mc));
1437    } else if (command == MLX_CMD_STOPCHANNEL) {
1438	device_printf(sc->mlx_dev, "channel %d pausing for %ld seconds\n",
1439		      channel, (long)(sc->mlx_pause.mp_howlong - time_second));
1440    } else {
1441	device_printf(sc->mlx_dev, "channel %d resuming\n", channel);
1442    }
1443    mlx_releasecmd(mc);
1444}
1445
1446/********************************************************************************
1447 ********************************************************************************
1448                                                               Command Submission
1449 ********************************************************************************
1450 ********************************************************************************/
1451
1452/********************************************************************************
1453 * Perform an Enquiry command using a type-3 command buffer and a return a single
1454 * linear result buffer.  If the completion function is specified, it will
1455 * be called with the completed command (and the result response will not be
1456 * valid until that point).  Otherwise, the command will either be busy-waited
1457 * for (interrupts not enabled), or slept for.
1458 */
1459static void *
1460mlx_enquire(struct mlx_softc *sc, int command, size_t bufsize, void (* complete)(struct mlx_command *mc))
1461{
1462    struct mlx_command	*mc;
1463    void		*result;
1464    int			error;
1465
1466    debug_called(1);
1467
1468    /* get ourselves a command buffer */
1469    error = 1;
1470    result = NULL;
1471    if ((mc = mlx_alloccmd(sc)) == NULL)
1472	goto out;
1473    /* allocate the response structure */
1474    if ((result = malloc(bufsize, M_DEVBUF, M_NOWAIT)) == NULL)
1475	goto out;
1476    /* get a command slot */
1477    mc->mc_flags |= MLX_CMD_PRIORITY | MLX_CMD_DATAOUT;
1478    if (mlx_getslot(mc))
1479	goto out;
1480
1481    /* map the command so the controller can see it */
1482    mc->mc_data = result;
1483    mc->mc_length = bufsize;
1484    mlx_mapcmd(mc);
1485
1486    /* build an enquiry command */
1487    mlx_make_type2(mc, command, 0, 0, 0, 0, 0, 0, mc->mc_dataphys, 0);
1488
1489    /* do we want a completion callback? */
1490    if (complete != NULL) {
1491	mc->mc_complete = complete;
1492	mc->mc_private = mc;
1493	if ((error = mlx_start(mc)) != 0)
1494	    goto out;
1495    } else {
1496	/* run the command in either polled or wait mode */
1497	if ((sc->mlx_state & MLX_STATE_INTEN) ? mlx_wait_command(mc) : mlx_poll_command(mc))
1498	    goto out;
1499
1500	/* command completed OK? */
1501	if (mc->mc_status != 0) {
1502	    device_printf(sc->mlx_dev, "ENQUIRY failed - %s\n", mlx_diagnose_command(mc));
1503	    goto out;
1504	}
1505    }
1506    error = 0;			/* success */
1507 out:
1508    /* we got a command, but nobody else will free it */
1509    if ((complete == NULL) && (mc != NULL))
1510	mlx_releasecmd(mc);
1511    /* we got an error, and we allocated a result */
1512    if ((error != 0) && (result != NULL)) {
1513	free(result, M_DEVBUF);
1514	result = NULL;
1515    }
1516    return(result);
1517}
1518
1519
1520/********************************************************************************
1521 * Perform a Flush command on the nominated controller.
1522 *
1523 * May be called with interrupts enabled or disabled; will not return until
1524 * the flush operation completes or fails.
1525 */
1526static int
1527mlx_flush(struct mlx_softc *sc)
1528{
1529    struct mlx_command	*mc;
1530    int			error;
1531
1532    debug_called(1);
1533
1534    /* get ourselves a command buffer */
1535    error = 1;
1536    if ((mc = mlx_alloccmd(sc)) == NULL)
1537	goto out;
1538    /* get a command slot */
1539    if (mlx_getslot(mc))
1540	goto out;
1541
1542    /* build a flush command */
1543    mlx_make_type2(mc, MLX_CMD_FLUSH, 0, 0, 0, 0, 0, 0, 0, 0);
1544
1545    /* can't assume that interrupts are going to work here, so play it safe */
1546    if (mlx_poll_command(mc))
1547	goto out;
1548
1549    /* command completed OK? */
1550    if (mc->mc_status != 0) {
1551	device_printf(sc->mlx_dev, "FLUSH failed - %s\n", mlx_diagnose_command(mc));
1552	goto out;
1553    }
1554
1555    error = 0;			/* success */
1556 out:
1557    if (mc != NULL)
1558	mlx_releasecmd(mc);
1559    return(error);
1560}
1561
1562/********************************************************************************
1563 * Start a background consistency check on (drive).
1564 *
1565 * May be called with interrupts enabled or disabled; will return as soon as the
1566 * operation has started or been refused.
1567 */
1568static int
1569mlx_check(struct mlx_softc *sc, int drive)
1570{
1571    struct mlx_command	*mc;
1572    int			error;
1573
1574    debug_called(1);
1575
1576    /* get ourselves a command buffer */
1577    error = 0x10000;
1578    if ((mc = mlx_alloccmd(sc)) == NULL)
1579	goto out;
1580    /* get a command slot */
1581    if (mlx_getslot(mc))
1582	goto out;
1583
1584    /* build a checkasync command, set the "fix it" flag */
1585    mlx_make_type2(mc, MLX_CMD_CHECKASYNC, 0, 0, 0, 0, 0, drive | 0x80, 0, 0);
1586
1587    /* start the command and wait for it to be returned */
1588    if (mlx_wait_command(mc))
1589	goto out;
1590
1591    /* command completed OK? */
1592    if (mc->mc_status != 0) {
1593	device_printf(sc->mlx_dev, "CHECK ASYNC failed - %s\n", mlx_diagnose_command(mc));
1594    } else {
1595	device_printf(sc->mlx_sysdrive[drive].ms_disk, "consistency check started");
1596    }
1597    error = mc->mc_status;
1598
1599 out:
1600    if (mc != NULL)
1601	mlx_releasecmd(mc);
1602    return(error);
1603}
1604
1605/********************************************************************************
1606 * Start a background rebuild of the physical drive at (channel),(target).
1607 *
1608 * May be called with interrupts enabled or disabled; will return as soon as the
1609 * operation has started or been refused.
1610 */
1611static int
1612mlx_rebuild(struct mlx_softc *sc, int channel, int target)
1613{
1614    struct mlx_command	*mc;
1615    int			error;
1616
1617    debug_called(1);
1618
1619    /* get ourselves a command buffer */
1620    error = 0x10000;
1621    if ((mc = mlx_alloccmd(sc)) == NULL)
1622	goto out;
1623    /* get a command slot */
1624    if (mlx_getslot(mc))
1625	goto out;
1626
1627    /* build a checkasync command, set the "fix it" flag */
1628    mlx_make_type2(mc, MLX_CMD_REBUILDASYNC, channel, target, 0, 0, 0, 0, 0, 0);
1629
1630    /* start the command and wait for it to be returned */
1631    if (mlx_wait_command(mc))
1632	goto out;
1633
1634    /* command completed OK? */
1635    if (mc->mc_status != 0) {
1636	device_printf(sc->mlx_dev, "REBUILD ASYNC failed - %s\n", mlx_diagnose_command(mc));
1637    } else {
1638	device_printf(sc->mlx_dev, "drive rebuild started for %d:%d\n", channel, target);
1639    }
1640    error = mc->mc_status;
1641
1642 out:
1643    if (mc != NULL)
1644	mlx_releasecmd(mc);
1645    return(error);
1646}
1647
1648/********************************************************************************
1649 * Run the command (mc) and return when it completes.
1650 *
1651 * Interrupts need to be enabled; returns nonzero on error.
1652 */
1653static int
1654mlx_wait_command(struct mlx_command *mc)
1655{
1656    struct mlx_softc	*sc = mc->mc_sc;
1657    int			error, count;
1658
1659    debug_called(1);
1660
1661    mc->mc_complete = NULL;
1662    mc->mc_private = mc;		/* wake us when you're done */
1663    if ((error = mlx_start(mc)) != 0)
1664	return(error);
1665
1666    count = 0;
1667    /* XXX better timeout? */
1668    while ((mc->mc_status == MLX_STATUS_BUSY) && (count < 30)) {
1669	tsleep(mc->mc_private, PRIBIO | PCATCH, "mlxwcmd", hz);
1670    }
1671
1672    if (mc->mc_status != 0) {
1673	device_printf(sc->mlx_dev, "command failed - %s\n", mlx_diagnose_command(mc));
1674	return(EIO);
1675    }
1676    return(0);
1677}
1678
1679
1680/********************************************************************************
1681 * Start the command (mc) and busy-wait for it to complete.
1682 *
1683 * Should only be used when interrupts can't be relied upon. Returns 0 on
1684 * success, nonzero on error.
1685 * Successfully completed commands are dequeued.
1686 */
1687static int
1688mlx_poll_command(struct mlx_command *mc)
1689{
1690    struct mlx_softc	*sc = mc->mc_sc;
1691    int			error, count, s;
1692
1693    debug_called(1);
1694
1695    mc->mc_complete = NULL;
1696    mc->mc_private = NULL;	/* we will poll for it */
1697    if ((error = mlx_start(mc)) != 0)
1698	return(error);
1699
1700    count = 0;
1701    do {
1702	/* poll for completion */
1703	mlx_done(mc->mc_sc);
1704
1705    } while ((mc->mc_status == MLX_STATUS_BUSY) && (count++ < 15000000));
1706    if (mc->mc_status != MLX_STATUS_BUSY) {
1707	s = splbio();
1708	TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
1709	splx(s);
1710	return(0);
1711    }
1712    device_printf(sc->mlx_dev, "command failed - %s\n", mlx_diagnose_command(mc));
1713    return(EIO);
1714}
1715
1716/********************************************************************************
1717 * Pull as much work off the softc's work queue as possible and give it to the
1718 * controller.  Leave a couple of slots free for emergencies.
1719 *
1720 * Must be called at splbio or in an equivalent fashion that prevents
1721 * reentry or activity on the bioq.
1722 */
1723static void
1724mlx_startio(struct mlx_softc *sc)
1725{
1726    struct mlx_command	*mc;
1727    struct mlxd_softc	*mlxd;
1728    mlx_bio		*bp;
1729    int			blkcount;
1730    int			driveno;
1731    int			cmd;
1732    int			s;
1733
1734    /* avoid reentrancy */
1735    if (mlx_lock_tas(sc, MLX_LOCK_STARTING))
1736	return;
1737
1738    /* spin until something prevents us from doing any work */
1739    s = splbio();
1740    for (;;) {
1741
1742	/* see if there's work to be done */
1743	if ((bp = MLX_BIO_QFIRST(sc->mlx_bioq)) == NULL)
1744	    break;
1745	/* get a command */
1746	if ((mc = mlx_alloccmd(sc)) == NULL)
1747	    break;
1748	/* get a slot for the command */
1749	if (mlx_getslot(mc) != 0) {
1750	    mlx_releasecmd(mc);
1751	    break;
1752	}
1753	/* get the buf containing our work */
1754	MLX_BIO_QREMOVE(sc->mlx_bioq, bp);
1755	sc->mlx_waitbufs--;
1756	splx(s);
1757
1758	/* connect the buf to the command */
1759	mc->mc_complete = mlx_completeio;
1760	mc->mc_private = bp;
1761	mc->mc_data = MLX_BIO_DATA(bp);
1762	mc->mc_length = MLX_BIO_LENGTH(bp);
1763	if (MLX_BIO_IS_READ(bp)) {
1764	    mc->mc_flags |= MLX_CMD_DATAIN;
1765	    cmd = MLX_CMD_READSG;
1766	} else {
1767	    mc->mc_flags |= MLX_CMD_DATAOUT;
1768	    cmd = MLX_CMD_WRITESG;
1769	}
1770
1771	/* map the command so the controller can work with it */
1772	mlx_mapcmd(mc);
1773
1774	/* build a suitable I/O command (assumes 512-byte rounded transfers) */
1775	mlxd = (struct mlxd_softc *)MLX_BIO_SOFTC(bp);
1776	driveno = mlxd->mlxd_drive - sc->mlx_sysdrive;
1777	blkcount = (MLX_BIO_LENGTH(bp) + MLX_BLKSIZE - 1) / MLX_BLKSIZE;
1778
1779	if ((MLX_BIO_LBA(bp) + blkcount) > sc->mlx_sysdrive[driveno].ms_size)
1780	    device_printf(sc->mlx_dev, "I/O beyond end of unit (%llu,%d > %u)\n",
1781		MLX_BIO_LBA(bp), blkcount, 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