mlx.c revision 109623
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 109623 2003-01-21 08:56:16Z alfred $
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,
1781			  "I/O beyond end of unit (%lld,%d > %lu)\n",
1782			  (long long)MLX_BIO_LBA(bp), blkcount,
1783			  (u_long)sc->mlx_sysdrive[driveno].ms_size);
1784
1785	/*
1786	 * Build the I/O command.  Note that the SG list type bits are set to zero,
1787	 * denoting the format of SG list that we are using.
1788	 */
1789	if (sc->mlx_iftype == MLX_IFTYPE_2) {
1790	    mlx_make_type1(mc, (cmd == MLX_CMD_WRITESG) ? MLX_CMD_WRITESG_OLD : MLX_CMD_READSG_OLD,
1791			   blkcount & 0xff, 				/* xfer length low byte */
1792			   MLX_BIO_LBA(bp),				/* physical block number */
1793			   driveno,					/* target drive number */
1794			   mc->mc_sgphys,				/* location of SG list */
1795			   mc->mc_nsgent & 0x3f);			/* size of SG list (top 3 bits clear) */
1796	} else {
1797	    mlx_make_type5(mc, cmd,
1798			   blkcount & 0xff, 				/* xfer length low byte */
1799			   (driveno << 3) | ((blkcount >> 8) & 0x07),	/* target and length high 3 bits */
1800			   MLX_BIO_LBA(bp),				/* physical block number */
1801			   mc->mc_sgphys,				/* location of SG list */
1802			   mc->mc_nsgent & 0x3f);			/* size of SG list (top 3 bits clear) */
1803	}
1804
1805	/* try to give command to controller */
1806	if (mlx_start(mc) != 0) {
1807	    /* fail the command */
1808	    mc->mc_status = MLX_STATUS_WEDGED;
1809	    mlx_completeio(mc);
1810	}
1811	s = splbio();
1812    }
1813    splx(s);
1814    mlx_lock_clr(sc, MLX_LOCK_STARTING);
1815}
1816
1817/********************************************************************************
1818 * Handle completion of an I/O command.
1819 */
1820static void
1821mlx_completeio(struct mlx_command *mc)
1822{
1823    struct mlx_softc	*sc = mc->mc_sc;
1824    mlx_bio		*bp = (mlx_bio *)mc->mc_private;
1825    struct mlxd_softc	*mlxd = (struct mlxd_softc *)MLX_BIO_SOFTC(bp);
1826
1827    if (mc->mc_status != MLX_STATUS_OK) {	/* could be more verbose here? */
1828	MLX_BIO_SET_ERROR(bp, EIO);
1829
1830	switch(mc->mc_status) {
1831	case MLX_STATUS_RDWROFFLINE:		/* system drive has gone offline */
1832	    device_printf(mlxd->mlxd_dev, "drive offline\n");
1833	    /* should signal this with a return code */
1834	    mlxd->mlxd_drive->ms_state = MLX_SYSD_OFFLINE;
1835	    break;
1836
1837	default:				/* other I/O error */
1838	    device_printf(sc->mlx_dev, "I/O error - %s\n", mlx_diagnose_command(mc));
1839#if 0
1840	    device_printf(sc->mlx_dev, "  b_bcount %ld  blkcount %ld  b_pblkno %d\n",
1841			  MLX_BIO_LENGTH(bp), MLX_BIO_LENGTH(bp) / MLX_BLKSIZE, MLX_BIO_LBA(bp));
1842	    device_printf(sc->mlx_dev, "  %13D\n", mc->mc_mailbox, " ");
1843#endif
1844	    break;
1845	}
1846    }
1847    mlx_releasecmd(mc);
1848    mlxd_intr(bp);
1849}
1850
1851/********************************************************************************
1852 * Take a command from user-space and try to run it.
1853 *
1854 * XXX Note that this can't perform very much in the way of error checking, and
1855 *     as such, applications _must_ be considered trustworthy.
1856 * XXX Commands using S/G for data are not supported.
1857 */
1858static int
1859mlx_user_command(struct mlx_softc *sc, struct mlx_usercommand *mu)
1860{
1861    struct mlx_command	*mc;
1862    struct mlx_dcdb	*dcdb;
1863    void		*kbuf;
1864    int			error;
1865
1866    debug_called(0);
1867
1868    kbuf = NULL;
1869    mc = NULL;
1870    dcdb = NULL;
1871    error = ENOMEM;
1872
1873    /* get ourselves a command and copy in from user space */
1874    if ((mc = mlx_alloccmd(sc)) == NULL)
1875	goto out;
1876    bcopy(mu->mu_command, mc->mc_mailbox, sizeof(mc->mc_mailbox));
1877    debug(0, "got command buffer");
1878
1879    /* if we need a buffer for data transfer, allocate one and copy in its initial contents */
1880    if (mu->mu_datasize > 0) {
1881	if (mu->mu_datasize > MAXPHYS)
1882	    return (EINVAL);
1883	if (((kbuf = malloc(mu->mu_datasize, M_DEVBUF, 0)) == NULL) ||
1884	    (error = copyin(mu->mu_buf, kbuf, mu->mu_datasize)))
1885	    goto out;
1886	debug(0, "got kernel buffer");
1887    }
1888
1889    /* get a command slot */
1890    if (mlx_getslot(mc))
1891	goto out;
1892    debug(0, "got a slot");
1893
1894    /* map the command so the controller can see it */
1895    mc->mc_data = kbuf;
1896    mc->mc_length = mu->mu_datasize;
1897    mlx_mapcmd(mc);
1898    debug(0, "mapped");
1899
1900    /*
1901     * If this is a passthrough SCSI command, the DCDB is packed at the
1902     * beginning of the data area.  Fix up the DCDB to point to the correct physical
1903     * address and override any bufptr supplied by the caller since we know
1904     * what it's meant to be.
1905     */
1906    if (mc->mc_mailbox[0] == MLX_CMD_DIRECT_CDB) {
1907	dcdb = (struct mlx_dcdb *)kbuf;
1908	dcdb->dcdb_physaddr = mc->mc_dataphys + sizeof(*dcdb);
1909	mu->mu_bufptr = 8;
1910    }
1911
1912    /*
1913     * If there's a data buffer, fix up the command's buffer pointer.
1914     */
1915    if (mu->mu_datasize > 0) {
1916
1917	/* range check the pointer to physical buffer address */
1918	if ((mu->mu_bufptr < 0) || (mu->mu_bufptr > (sizeof(mu->mu_command) - sizeof(u_int32_t)))) {
1919	    error = EINVAL;
1920	    goto out;
1921	}
1922	mc->mc_mailbox[mu->mu_bufptr    ] =  mc->mc_dataphys        & 0xff;
1923	mc->mc_mailbox[mu->mu_bufptr + 1] = (mc->mc_dataphys >> 8)  & 0xff;
1924	mc->mc_mailbox[mu->mu_bufptr + 2] = (mc->mc_dataphys >> 16) & 0xff;
1925	mc->mc_mailbox[mu->mu_bufptr + 3] = (mc->mc_dataphys >> 24) & 0xff;
1926    }
1927    debug(0, "command fixup");
1928
1929    /* submit the command and wait */
1930    if ((error = mlx_wait_command(mc)) != 0)
1931	goto out;
1932
1933    /* copy out status and data */
1934    mu->mu_status = mc->mc_status;
1935    if ((mu->mu_datasize > 0) && ((error = copyout(kbuf, mu->mu_buf, mu->mu_datasize))))
1936	goto out;
1937    error = 0;
1938
1939 out:
1940    mlx_releasecmd(mc);
1941    if (kbuf != NULL)
1942	free(kbuf, M_DEVBUF);
1943    return(error);
1944}
1945
1946/********************************************************************************
1947 ********************************************************************************
1948                                                        Command I/O to Controller
1949 ********************************************************************************
1950 ********************************************************************************/
1951
1952/********************************************************************************
1953 * Find a free command slot for (mc).
1954 *
1955 * Don't hand out a slot to a normal-priority command unless there are at least
1956 * 4 slots free for priority commands.
1957 */
1958static int
1959mlx_getslot(struct mlx_command *mc)
1960{
1961    struct mlx_softc	*sc = mc->mc_sc;
1962    int			s, slot, limit;
1963
1964    debug_called(1);
1965
1966    /*
1967     * Enforce slot-usage limit, if we have the required information.
1968     */
1969    if (sc->mlx_enq2 != NULL) {
1970	limit = sc->mlx_enq2->me_max_commands;
1971    } else {
1972	limit = 2;
1973    }
1974    if (sc->mlx_busycmds >= ((mc->mc_flags & MLX_CMD_PRIORITY) ? limit : limit - 4))
1975	return(EBUSY);
1976
1977    /*
1978     * Allocate an outstanding command slot
1979     *
1980     * XXX linear search is slow
1981     */
1982    s = splbio();
1983    for (slot = 0; slot < limit; slot++) {
1984	debug(2, "try slot %d", slot);
1985	if (sc->mlx_busycmd[slot] == NULL)
1986	    break;
1987    }
1988    if (slot < limit) {
1989	sc->mlx_busycmd[slot] = mc;
1990	sc->mlx_busycmds++;
1991    }
1992    splx(s);
1993
1994    /* out of slots? */
1995    if (slot >= limit)
1996	return(EBUSY);
1997
1998    debug(2, "got slot %d", slot);
1999    mc->mc_slot = slot;
2000    return(0);
2001}
2002
2003/********************************************************************************
2004 * Map/unmap (mc)'s data in the controller's addressable space.
2005 */
2006static void
2007mlx_setup_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
2008{
2009    struct mlx_command	*mc = (struct mlx_command *)arg;
2010    struct mlx_softc	*sc = mc->mc_sc;
2011    struct mlx_sgentry	*sg;
2012    int			i;
2013
2014    debug_called(1);
2015
2016    /* XXX should be unnecessary */
2017    if (sc->mlx_enq2 && (nsegments > sc->mlx_enq2->me_max_sg))
2018	panic("MLX: too many s/g segments (%d, max %d)", nsegments, sc->mlx_enq2->me_max_sg);
2019
2020    /* get base address of s/g table */
2021    sg = sc->mlx_sgtable + (mc->mc_slot * MLX_NSEG);
2022
2023    /* save s/g table information in command */
2024    mc->mc_nsgent = nsegments;
2025    mc->mc_sgphys = sc->mlx_sgbusaddr + (mc->mc_slot * MLX_NSEG * sizeof(struct mlx_sgentry));
2026    mc->mc_dataphys = segs[0].ds_addr;
2027
2028    /* populate s/g table */
2029    for (i = 0; i < nsegments; i++, sg++) {
2030	sg->sg_addr = segs[i].ds_addr;
2031	sg->sg_count = segs[i].ds_len;
2032    }
2033}
2034
2035static void
2036mlx_mapcmd(struct mlx_command *mc)
2037{
2038    struct mlx_softc	*sc = mc->mc_sc;
2039
2040    debug_called(1);
2041
2042    /* if the command involves data at all */
2043    if (mc->mc_data != NULL) {
2044
2045	/* map the data buffer into bus space and build the s/g list */
2046	bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data, mc->mc_length,
2047			mlx_setup_dmamap, mc, 0);
2048	if (mc->mc_flags & MLX_CMD_DATAIN)
2049	    bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_PREREAD);
2050	if (mc->mc_flags & MLX_CMD_DATAOUT)
2051	    bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_PREWRITE);
2052    }
2053}
2054
2055static void
2056mlx_unmapcmd(struct mlx_command *mc)
2057{
2058    struct mlx_softc	*sc = mc->mc_sc;
2059
2060    debug_called(1);
2061
2062    /* if the command involved data at all */
2063    if (mc->mc_data != NULL) {
2064
2065	if (mc->mc_flags & MLX_CMD_DATAIN)
2066	    bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTREAD);
2067	if (mc->mc_flags & MLX_CMD_DATAOUT)
2068	    bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTWRITE);
2069
2070	bus_dmamap_unload(sc->mlx_buffer_dmat, mc->mc_dmamap);
2071    }
2072}
2073
2074/********************************************************************************
2075 * Try to deliver (mc) to the controller.
2076 *
2077 * Can be called at any interrupt level, with or without interrupts enabled.
2078 */
2079static int
2080mlx_start(struct mlx_command *mc)
2081{
2082    struct mlx_softc	*sc = mc->mc_sc;
2083    int			i, s, done;
2084
2085    debug_called(1);
2086
2087    /* save the slot number as ident so we can handle this command when complete */
2088    mc->mc_mailbox[0x1] = mc->mc_slot;
2089
2090    /* mark the command as currently being processed */
2091    mc->mc_status = MLX_STATUS_BUSY;
2092
2093    /* set a default 60-second timeout  XXX tunable?  XXX not currently used */
2094    mc->mc_timeout = time_second + 60;
2095
2096    /* spin waiting for the mailbox */
2097    for (i = 100000, done = 0; (i > 0) && !done; i--) {
2098	s = splbio();
2099	if (sc->mlx_tryqueue(sc, mc)) {
2100	    done = 1;
2101	    /* move command to work queue */
2102	    TAILQ_INSERT_TAIL(&sc->mlx_work, mc, mc_link);
2103	}
2104	splx(s);	/* drop spl to allow completion interrupts */
2105    }
2106
2107    /* command is enqueued */
2108    if (done)
2109	return(0);
2110
2111    /*
2112     * We couldn't get the controller to take the command.  Revoke the slot
2113     * that the command was given and return it with a bad status.
2114     */
2115    sc->mlx_busycmd[mc->mc_slot] = NULL;
2116    device_printf(sc->mlx_dev, "controller wedged (not taking commands)\n");
2117    mc->mc_status = MLX_STATUS_WEDGED;
2118    mlx_complete(sc);
2119    return(EIO);
2120}
2121
2122/********************************************************************************
2123 * Poll the controller (sc) for completed commands.
2124 * Update command status and free slots for reuse.  If any slots were freed,
2125 * new commands may be posted.
2126 *
2127 * Returns nonzero if one or more commands were completed.
2128 */
2129static int
2130mlx_done(struct mlx_softc *sc)
2131{
2132    struct mlx_command	*mc;
2133    int			s, result;
2134    u_int8_t		slot;
2135    u_int16_t		status;
2136
2137    debug_called(2);
2138
2139    result = 0;
2140
2141    /* loop collecting completed commands */
2142    s = splbio();
2143    for (;;) {
2144	/* poll for a completed command's identifier and status */
2145	if (sc->mlx_findcomplete(sc, &slot, &status)) {
2146	    result = 1;
2147	    mc = sc->mlx_busycmd[slot];			/* find command */
2148	    if (mc != NULL) {				/* paranoia */
2149		if (mc->mc_status == MLX_STATUS_BUSY) {
2150		    mc->mc_status = status;		/* save status */
2151
2152		    /* free slot for reuse */
2153		    sc->mlx_busycmd[slot] = NULL;
2154		    sc->mlx_busycmds--;
2155		} else {
2156		    device_printf(sc->mlx_dev, "duplicate done event for slot %d\n", slot);
2157		}
2158	    } else {
2159		device_printf(sc->mlx_dev, "done event for nonbusy slot %d\n", slot);
2160	    }
2161	} else {
2162	    break;
2163	}
2164    }
2165    splx(s);
2166
2167    /* if we've completed any commands, try posting some more */
2168    if (result)
2169	mlx_startio(sc);
2170
2171    /* handle completion and timeouts */
2172    mlx_complete(sc);
2173
2174    return(result);
2175}
2176
2177/********************************************************************************
2178 * Perform post-completion processing for commands on (sc).
2179 */
2180static void
2181mlx_complete(struct mlx_softc *sc)
2182{
2183    struct mlx_command	*mc, *nc;
2184    int			s, count;
2185
2186    debug_called(2);
2187
2188    /* avoid reentrancy  XXX might want to signal and request a restart */
2189    if (mlx_lock_tas(sc, MLX_LOCK_COMPLETING))
2190	return;
2191
2192    s = splbio();
2193    count = 0;
2194
2195    /* scan the list of busy/done commands */
2196    mc = TAILQ_FIRST(&sc->mlx_work);
2197    while (mc != NULL) {
2198	nc = TAILQ_NEXT(mc, mc_link);
2199
2200	/* Command has been completed in some fashion */
2201	if (mc->mc_status != MLX_STATUS_BUSY) {
2202
2203	    /* unmap the command's data buffer */
2204	    mlx_unmapcmd(mc);
2205	    /*
2206	     * Does the command have a completion handler?
2207	     */
2208	    if (mc->mc_complete != NULL) {
2209		/* remove from list and give to handler */
2210		TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
2211		mc->mc_complete(mc);
2212
2213		/*
2214		 * Is there a sleeper waiting on this command?
2215		 */
2216	    } else if (mc->mc_private != NULL) {	/* sleeping caller wants to know about it */
2217
2218		/* remove from list and wake up sleeper */
2219		TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
2220		wakeup_one(mc->mc_private);
2221
2222		/*
2223		 * Leave the command for a caller that's polling for it.
2224		 */
2225	    } else {
2226	    }
2227	}
2228	mc = nc;
2229    }
2230    splx(s);
2231
2232    mlx_lock_clr(sc, MLX_LOCK_COMPLETING);
2233}
2234
2235/********************************************************************************
2236 ********************************************************************************
2237                                                        Command Buffer Management
2238 ********************************************************************************
2239 ********************************************************************************/
2240
2241/********************************************************************************
2242 * Get a new command buffer.
2243 *
2244 * This may return NULL in low-memory cases.
2245 *
2246 * Note that using malloc() is expensive (the command buffer is << 1 page) but
2247 * necessary if we are to be a loadable module before the zone allocator is fixed.
2248 *
2249 * If possible, we recycle a command buffer that's been used before.
2250 *
2251 * XXX Note that command buffers are not cleaned out - it is the caller's
2252 *     responsibility to ensure that all required fields are filled in before
2253 *     using a buffer.
2254 */
2255static struct mlx_command *
2256mlx_alloccmd(struct mlx_softc *sc)
2257{
2258    struct mlx_command	*mc;
2259    int			error;
2260    int			s;
2261
2262    debug_called(1);
2263
2264    s = splbio();
2265    if ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL)
2266	TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link);
2267    splx(s);
2268
2269    /* allocate a new command buffer? */
2270    if (mc == NULL) {
2271	mc = (struct mlx_command *)malloc(sizeof(*mc), M_DEVBUF, M_NOWAIT | M_ZERO);
2272	if (mc != NULL) {
2273	    mc->mc_sc = sc;
2274	    error = bus_dmamap_create(sc->mlx_buffer_dmat, 0, &mc->mc_dmamap);
2275	    if (error) {
2276		free(mc, M_DEVBUF);
2277		return(NULL);
2278	    }
2279	}
2280    }
2281    return(mc);
2282}
2283
2284/********************************************************************************
2285 * Release a command buffer for recycling.
2286 *
2287 * XXX It might be a good idea to limit the number of commands we save for reuse
2288 *     if it's shown that this list bloats out massively.
2289 */
2290static void
2291mlx_releasecmd(struct mlx_command *mc)
2292{
2293    int		s;
2294
2295    debug_called(1);
2296
2297    s = splbio();
2298    TAILQ_INSERT_HEAD(&mc->mc_sc->mlx_freecmds, mc, mc_link);
2299    splx(s);
2300}
2301
2302/********************************************************************************
2303 * Permanently discard a command buffer.
2304 */
2305static void
2306mlx_freecmd(struct mlx_command *mc)
2307{
2308    struct mlx_softc	*sc = mc->mc_sc;
2309
2310    debug_called(1);
2311    bus_dmamap_destroy(sc->mlx_buffer_dmat, mc->mc_dmamap);
2312    free(mc, M_DEVBUF);
2313}
2314
2315
2316/********************************************************************************
2317 ********************************************************************************
2318                                                Type 3 interface accessor methods
2319 ********************************************************************************
2320 ********************************************************************************/
2321
2322/********************************************************************************
2323 * Try to give (mc) to the controller.  Returns 1 if successful, 0 on failure
2324 * (the controller is not ready to take a command).
2325 *
2326 * Must be called at splbio or in a fashion that prevents reentry.
2327 */
2328static int
2329mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2330{
2331    int		i;
2332
2333    debug_called(2);
2334
2335    /* ready for our command? */
2336    if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_FULL)) {
2337	/* copy mailbox data to window */
2338	for (i = 0; i < 13; i++)
2339	    MLX_V3_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
2340
2341	/* post command */
2342	MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_FULL);
2343	return(1);
2344    }
2345    return(0);
2346}
2347
2348/********************************************************************************
2349 * See if a command has been completed, if so acknowledge its completion
2350 * and recover the slot number and status code.
2351 *
2352 * Must be called at splbio or in a fashion that prevents reentry.
2353 */
2354static int
2355mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2356{
2357
2358    debug_called(2);
2359
2360    /* status available? */
2361    if (MLX_V3_GET_ODBR(sc) & MLX_V3_ODB_SAVAIL) {
2362	*slot = MLX_V3_GET_STATUS_IDENT(sc);		/* get command identifier */
2363	*status = MLX_V3_GET_STATUS(sc);		/* get status */
2364
2365	/* acknowledge completion */
2366	MLX_V3_PUT_ODBR(sc, MLX_V3_ODB_SAVAIL);
2367	MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_SACK);
2368	return(1);
2369    }
2370    return(0);
2371}
2372
2373/********************************************************************************
2374 * Enable/disable interrupts as requested. (No acknowledge required)
2375 *
2376 * Must be called at splbio or in a fashion that prevents reentry.
2377 */
2378static void
2379mlx_v3_intaction(struct mlx_softc *sc, int action)
2380{
2381    debug_called(1);
2382
2383    switch(action) {
2384    case MLX_INTACTION_DISABLE:
2385	MLX_V3_PUT_IER(sc, 0);
2386	sc->mlx_state &= ~MLX_STATE_INTEN;
2387	break;
2388    case MLX_INTACTION_ENABLE:
2389	MLX_V3_PUT_IER(sc, 1);
2390	sc->mlx_state |= MLX_STATE_INTEN;
2391	break;
2392    }
2393}
2394
2395/********************************************************************************
2396 * Poll for firmware error codes during controller initialisation.
2397 * Returns 0 if initialisation is complete, 1 if still in progress but no
2398 * error has been fetched, 2 if an error has been retrieved.
2399 */
2400static int
2401mlx_v3_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2)
2402{
2403    u_int8_t	fwerror;
2404    static int	initted = 0;
2405
2406    debug_called(2);
2407
2408    /* first time around, clear any hardware completion status */
2409    if (!initted) {
2410	MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_SACK);
2411	DELAY(1000);
2412	initted = 1;
2413    }
2414
2415    /* init in progress? */
2416    if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_INIT_BUSY))
2417	return(0);
2418
2419    /* test error value */
2420    fwerror = MLX_V3_GET_FWERROR(sc);
2421    if (!(fwerror & MLX_V3_FWERROR_PEND))
2422	return(1);
2423
2424    /* mask status pending bit, fetch status */
2425    *error = fwerror & ~MLX_V3_FWERROR_PEND;
2426    *param1 = MLX_V3_GET_FWERROR_PARAM1(sc);
2427    *param2 = MLX_V3_GET_FWERROR_PARAM2(sc);
2428
2429    /* acknowledge */
2430    MLX_V3_PUT_FWERROR(sc, 0);
2431
2432    return(2);
2433}
2434
2435/********************************************************************************
2436 ********************************************************************************
2437                                                Type 4 interface accessor methods
2438 ********************************************************************************
2439 ********************************************************************************/
2440
2441/********************************************************************************
2442 * Try to give (mc) to the controller.  Returns 1 if successful, 0 on failure
2443 * (the controller is not ready to take a command).
2444 *
2445 * Must be called at splbio or in a fashion that prevents reentry.
2446 */
2447static int
2448mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2449{
2450    int		i;
2451
2452    debug_called(2);
2453
2454    /* ready for our command? */
2455    if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_FULL)) {
2456	/* copy mailbox data to window */
2457	for (i = 0; i < 13; i++)
2458	    MLX_V4_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
2459
2460	/* memory-mapped controller, so issue a write barrier to ensure the mailbox is filled */
2461	bus_space_barrier(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_MAILBOX, MLX_V4_MAILBOX_LENGTH,
2462			  BUS_SPACE_BARRIER_WRITE);
2463
2464	/* post command */
2465	MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_HWMBOX_CMD);
2466	return(1);
2467    }
2468    return(0);
2469}
2470
2471/********************************************************************************
2472 * See if a command has been completed, if so acknowledge its completion
2473 * and recover the slot number and status code.
2474 *
2475 * Must be called at splbio or in a fashion that prevents reentry.
2476 */
2477static int
2478mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2479{
2480
2481    debug_called(2);
2482
2483    /* status available? */
2484    if (MLX_V4_GET_ODBR(sc) & MLX_V4_ODB_HWSAVAIL) {
2485	*slot = MLX_V4_GET_STATUS_IDENT(sc);		/* get command identifier */
2486	*status = MLX_V4_GET_STATUS(sc);		/* get status */
2487
2488	/* acknowledge completion */
2489	MLX_V4_PUT_ODBR(sc, MLX_V4_ODB_HWMBOX_ACK);
2490	MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_SACK);
2491	return(1);
2492    }
2493    return(0);
2494}
2495
2496/********************************************************************************
2497 * Enable/disable interrupts as requested.
2498 *
2499 * Must be called at splbio or in a fashion that prevents reentry.
2500 */
2501static void
2502mlx_v4_intaction(struct mlx_softc *sc, int action)
2503{
2504    debug_called(1);
2505
2506    switch(action) {
2507    case MLX_INTACTION_DISABLE:
2508	MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK | MLX_V4_IER_DISINT);
2509	sc->mlx_state &= ~MLX_STATE_INTEN;
2510	break;
2511    case MLX_INTACTION_ENABLE:
2512	MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK & ~MLX_V4_IER_DISINT);
2513	sc->mlx_state |= MLX_STATE_INTEN;
2514	break;
2515    }
2516}
2517
2518/********************************************************************************
2519 * Poll for firmware error codes during controller initialisation.
2520 * Returns 0 if initialisation is complete, 1 if still in progress but no
2521 * error has been fetched, 2 if an error has been retrieved.
2522 */
2523static int
2524mlx_v4_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2)
2525{
2526    u_int8_t	fwerror;
2527    static int	initted = 0;
2528
2529    debug_called(2);
2530
2531    /* first time around, clear any hardware completion status */
2532    if (!initted) {
2533	MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_SACK);
2534	DELAY(1000);
2535	initted = 1;
2536    }
2537
2538    /* init in progress? */
2539    if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_INIT_BUSY))
2540	return(0);
2541
2542    /* test error value */
2543    fwerror = MLX_V4_GET_FWERROR(sc);
2544    if (!(fwerror & MLX_V4_FWERROR_PEND))
2545	return(1);
2546
2547    /* mask status pending bit, fetch status */
2548    *error = fwerror & ~MLX_V4_FWERROR_PEND;
2549    *param1 = MLX_V4_GET_FWERROR_PARAM1(sc);
2550    *param2 = MLX_V4_GET_FWERROR_PARAM2(sc);
2551
2552    /* acknowledge */
2553    MLX_V4_PUT_FWERROR(sc, 0);
2554
2555    return(2);
2556}
2557
2558/********************************************************************************
2559 ********************************************************************************
2560                                                Type 5 interface accessor methods
2561 ********************************************************************************
2562 ********************************************************************************/
2563
2564/********************************************************************************
2565 * Try to give (mc) to the controller.  Returns 1 if successful, 0 on failure
2566 * (the controller is not ready to take a command).
2567 *
2568 * Must be called at splbio or in a fashion that prevents reentry.
2569 */
2570static int
2571mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2572{
2573    int		i;
2574
2575    debug_called(2);
2576
2577    /* ready for our command? */
2578    if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_EMPTY) {
2579	/* copy mailbox data to window */
2580	for (i = 0; i < 13; i++)
2581	    MLX_V5_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
2582
2583	/* post command */
2584	MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_HWMBOX_CMD);
2585	return(1);
2586    }
2587    return(0);
2588}
2589
2590/********************************************************************************
2591 * See if a command has been completed, if so acknowledge its completion
2592 * and recover the slot number and status code.
2593 *
2594 * Must be called at splbio or in a fashion that prevents reentry.
2595 */
2596static int
2597mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2598{
2599
2600    debug_called(2);
2601
2602    /* status available? */
2603    if (MLX_V5_GET_ODBR(sc) & MLX_V5_ODB_HWSAVAIL) {
2604	*slot = MLX_V5_GET_STATUS_IDENT(sc);		/* get command identifier */
2605	*status = MLX_V5_GET_STATUS(sc);		/* get status */
2606
2607	/* acknowledge completion */
2608	MLX_V5_PUT_ODBR(sc, MLX_V5_ODB_HWMBOX_ACK);
2609	MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_SACK);
2610	return(1);
2611    }
2612    return(0);
2613}
2614
2615/********************************************************************************
2616 * Enable/disable interrupts as requested.
2617 *
2618 * Must be called at splbio or in a fashion that prevents reentry.
2619 */
2620static void
2621mlx_v5_intaction(struct mlx_softc *sc, int action)
2622{
2623    debug_called(1);
2624
2625    switch(action) {
2626    case MLX_INTACTION_DISABLE:
2627	MLX_V5_PUT_IER(sc, 0xff & MLX_V5_IER_DISINT);
2628	sc->mlx_state &= ~MLX_STATE_INTEN;
2629	break;
2630    case MLX_INTACTION_ENABLE:
2631	MLX_V5_PUT_IER(sc, 0xff & ~MLX_V5_IER_DISINT);
2632	sc->mlx_state |= MLX_STATE_INTEN;
2633	break;
2634    }
2635}
2636
2637/********************************************************************************
2638 * Poll for firmware error codes during controller initialisation.
2639 * Returns 0 if initialisation is complete, 1 if still in progress but no
2640 * error has been fetched, 2 if an error has been retrieved.
2641 */
2642static int
2643mlx_v5_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2)
2644{
2645    u_int8_t	fwerror;
2646    static int	initted = 0;
2647
2648    debug_called(2);
2649
2650    /* first time around, clear any hardware completion status */
2651    if (!initted) {
2652	MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_SACK);
2653	DELAY(1000);
2654	initted = 1;
2655    }
2656
2657    /* init in progress? */
2658    if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_INIT_DONE)
2659	return(0);
2660
2661    /* test for error value */
2662    fwerror = MLX_V5_GET_FWERROR(sc);
2663    if (!(fwerror & MLX_V5_FWERROR_PEND))
2664	return(1);
2665
2666    /* mask status pending bit, fetch status */
2667    *error = fwerror & ~MLX_V5_FWERROR_PEND;
2668    *param1 = MLX_V5_GET_FWERROR_PARAM1(sc);
2669    *param2 = MLX_V5_GET_FWERROR_PARAM2(sc);
2670
2671    /* acknowledge */
2672    MLX_V5_PUT_FWERROR(sc, 0xff);
2673
2674    return(2);
2675}
2676
2677/********************************************************************************
2678 ********************************************************************************
2679                                                                        Debugging
2680 ********************************************************************************
2681 ********************************************************************************/
2682
2683/********************************************************************************
2684 * Return a status message describing (mc)
2685 */
2686static char *mlx_status_messages[] = {
2687    "normal completion",			/* 00 */
2688    "irrecoverable data error",			/* 01 */
2689    "drive does not exist, or is offline",	/* 02 */
2690    "attempt to write beyond end of drive",	/* 03 */
2691    "bad data encountered",			/* 04 */
2692    "invalid log entry request",		/* 05 */
2693    "attempt to rebuild online drive",		/* 06 */
2694    "new disk failed during rebuild",		/* 07 */
2695    "invalid channel/target",			/* 08 */
2696    "rebuild/check already in progress",	/* 09 */
2697    "one or more disks are dead",		/* 10 */
2698    "invalid or non-redundant drive",		/* 11 */
2699    "channel is busy",				/* 12 */
2700    "channel is not stopped",			/* 13 */
2701    "rebuild successfully terminated",		/* 14 */
2702    "unsupported command",			/* 15 */
2703    "check condition received",			/* 16 */
2704    "device is busy",				/* 17 */
2705    "selection or command timeout",		/* 18 */
2706    "command terminated abnormally",		/* 19 */
2707    ""
2708};
2709
2710static struct
2711{
2712    int		command;
2713    u_int16_t	status;
2714    int		msg;
2715} mlx_messages[] = {
2716    {MLX_CMD_READSG,		0x0001,	 1},
2717    {MLX_CMD_READSG,		0x0002,	 1},
2718    {MLX_CMD_READSG,		0x0105,	 3},
2719    {MLX_CMD_READSG,		0x010c,	 4},
2720    {MLX_CMD_WRITESG,		0x0001,	 1},
2721    {MLX_CMD_WRITESG,		0x0002,	 1},
2722    {MLX_CMD_WRITESG,		0x0105,	 3},
2723    {MLX_CMD_READSG_OLD,	0x0001,	 1},
2724    {MLX_CMD_READSG_OLD,	0x0002,	 1},
2725    {MLX_CMD_READSG_OLD,	0x0105,	 3},
2726    {MLX_CMD_WRITESG_OLD,	0x0001,	 1},
2727    {MLX_CMD_WRITESG_OLD,	0x0002,	 1},
2728    {MLX_CMD_WRITESG_OLD,	0x0105,	 3},
2729    {MLX_CMD_LOGOP,		0x0105,	 5},
2730    {MLX_CMD_REBUILDASYNC,	0x0002,  6},
2731    {MLX_CMD_REBUILDASYNC,	0x0004,  7},
2732    {MLX_CMD_REBUILDASYNC,	0x0105,  8},
2733    {MLX_CMD_REBUILDASYNC,	0x0106,  9},
2734    {MLX_CMD_REBUILDASYNC,	0x0107, 14},
2735    {MLX_CMD_CHECKASYNC,	0x0002, 10},
2736    {MLX_CMD_CHECKASYNC,	0x0105, 11},
2737    {MLX_CMD_CHECKASYNC,	0x0106,  9},
2738    {MLX_CMD_STOPCHANNEL,	0x0106, 12},
2739    {MLX_CMD_STOPCHANNEL,	0x0105,  8},
2740    {MLX_CMD_STARTCHANNEL,	0x0005, 13},
2741    {MLX_CMD_STARTCHANNEL,	0x0105,  8},
2742    {MLX_CMD_DIRECT_CDB,	0x0002, 16},
2743    {MLX_CMD_DIRECT_CDB,	0x0008, 17},
2744    {MLX_CMD_DIRECT_CDB,	0x000e, 18},
2745    {MLX_CMD_DIRECT_CDB,	0x000f, 19},
2746    {MLX_CMD_DIRECT_CDB,	0x0105,  8},
2747
2748    {0,				0x0104, 14},
2749    {-1, 0, 0}
2750};
2751
2752static char *
2753mlx_diagnose_command(struct mlx_command *mc)
2754{
2755    static char	unkmsg[80];
2756    int		i;
2757
2758    /* look up message in table */
2759    for (i = 0; mlx_messages[i].command != -1; i++)
2760	if (((mc->mc_mailbox[0] == mlx_messages[i].command) || (mlx_messages[i].command == 0)) &&
2761	    (mc->mc_status == mlx_messages[i].status))
2762	    return(mlx_status_messages[mlx_messages[i].msg]);
2763
2764    sprintf(unkmsg, "unknown response 0x%x for command 0x%x", (int)mc->mc_status, (int)mc->mc_mailbox[0]);
2765    return(unkmsg);
2766}
2767
2768/*******************************************************************************
2769 * Print a string describing the controller (sc)
2770 */
2771static struct
2772{
2773    int		hwid;
2774    char	*name;
2775} mlx_controller_names[] = {
2776    {0x01,	"960P/PD"},
2777    {0x02,	"960PL"},
2778    {0x10,	"960PG"},
2779    {0x11,	"960PJ"},
2780    {0x12,	"960PR"},
2781    {0x13,	"960PT"},
2782    {0x14,	"960PTL0"},
2783    {0x15,	"960PRL"},
2784    {0x16,	"960PTL1"},
2785    {0x20,	"1164PVX"},
2786    {-1, NULL}
2787};
2788
2789static void
2790mlx_describe_controller(struct mlx_softc *sc)
2791{
2792    static char		buf[80];
2793    char		*model;
2794    int			i;
2795
2796    for (i = 0, model = NULL; mlx_controller_names[i].name != NULL; i++) {
2797	if ((sc->mlx_enq2->me_hardware_id & 0xff) == mlx_controller_names[i].hwid) {
2798	    model = mlx_controller_names[i].name;
2799	    break;
2800	}
2801    }
2802    if (model == NULL) {
2803	sprintf(buf, " model 0x%x", sc->mlx_enq2->me_hardware_id & 0xff);
2804	model = buf;
2805    }
2806    device_printf(sc->mlx_dev, "DAC%s, %d channel%s, firmware %d.%02d-%c-%02d, %dMB RAM\n",
2807		  model,
2808		  sc->mlx_enq2->me_actual_channels,
2809		  sc->mlx_enq2->me_actual_channels > 1 ? "s" : "",
2810		  sc->mlx_enq2->me_firmware_id & 0xff,
2811		  (sc->mlx_enq2->me_firmware_id >> 8) & 0xff,
2812		  (sc->mlx_enq2->me_firmware_id >> 24) & 0xff,
2813		  (sc->mlx_enq2->me_firmware_id >> 16) & 0xff,
2814		  sc->mlx_enq2->me_mem_size / (1024 * 1024));
2815
2816    if (bootverbose) {
2817	device_printf(sc->mlx_dev, "  Hardware ID                 0x%08x\n", sc->mlx_enq2->me_hardware_id);
2818	device_printf(sc->mlx_dev, "  Firmware ID                 0x%08x\n", sc->mlx_enq2->me_firmware_id);
2819	device_printf(sc->mlx_dev, "  Configured/Actual channels  %d/%d\n", sc->mlx_enq2->me_configured_channels,
2820		      sc->mlx_enq2->me_actual_channels);
2821	device_printf(sc->mlx_dev, "  Max Targets                 %d\n", sc->mlx_enq2->me_max_targets);
2822	device_printf(sc->mlx_dev, "  Max Tags                    %d\n", sc->mlx_enq2->me_max_tags);
2823	device_printf(sc->mlx_dev, "  Max System Drives           %d\n", sc->mlx_enq2->me_max_sys_drives);
2824	device_printf(sc->mlx_dev, "  Max Arms                    %d\n", sc->mlx_enq2->me_max_arms);
2825	device_printf(sc->mlx_dev, "  Max Spans                   %d\n", sc->mlx_enq2->me_max_spans);
2826	device_printf(sc->mlx_dev, "  DRAM/cache/flash/NVRAM size %d/%d/%d/%d\n", sc->mlx_enq2->me_mem_size,
2827		      sc->mlx_enq2->me_cache_size, sc->mlx_enq2->me_flash_size, sc->mlx_enq2->me_nvram_size);
2828	device_printf(sc->mlx_dev, "  DRAM type                   %d\n", sc->mlx_enq2->me_mem_type);
2829	device_printf(sc->mlx_dev, "  Clock Speed                 %dns\n", sc->mlx_enq2->me_clock_speed);
2830	device_printf(sc->mlx_dev, "  Hardware Speed              %dns\n", sc->mlx_enq2->me_hardware_speed);
2831	device_printf(sc->mlx_dev, "  Max Commands                %d\n", sc->mlx_enq2->me_max_commands);
2832	device_printf(sc->mlx_dev, "  Max SG Entries              %d\n", sc->mlx_enq2->me_max_sg);
2833	device_printf(sc->mlx_dev, "  Max DP                      %d\n", sc->mlx_enq2->me_max_dp);
2834	device_printf(sc->mlx_dev, "  Max IOD                     %d\n", sc->mlx_enq2->me_max_iod);
2835	device_printf(sc->mlx_dev, "  Max Comb                    %d\n", sc->mlx_enq2->me_max_comb);
2836	device_printf(sc->mlx_dev, "  Latency                     %ds\n", sc->mlx_enq2->me_latency);
2837	device_printf(sc->mlx_dev, "  SCSI Timeout                %ds\n", sc->mlx_enq2->me_scsi_timeout);
2838	device_printf(sc->mlx_dev, "  Min Free Lines              %d\n", sc->mlx_enq2->me_min_freelines);
2839	device_printf(sc->mlx_dev, "  Rate Constant               %d\n", sc->mlx_enq2->me_rate_const);
2840	device_printf(sc->mlx_dev, "  MAXBLK                      %d\n", sc->mlx_enq2->me_maxblk);
2841	device_printf(sc->mlx_dev, "  Blocking Factor             %d sectors\n", sc->mlx_enq2->me_blocking_factor);
2842	device_printf(sc->mlx_dev, "  Cache Line Size             %d blocks\n", sc->mlx_enq2->me_cacheline);
2843	device_printf(sc->mlx_dev, "  SCSI Capability             %s%dMHz, %d bit\n",
2844		      sc->mlx_enq2->me_scsi_cap & (1<<4) ? "differential " : "",
2845		      (1 << ((sc->mlx_enq2->me_scsi_cap >> 2) & 3)) * 10,
2846		      8 << (sc->mlx_enq2->me_scsi_cap & 0x3));
2847	device_printf(sc->mlx_dev, "  Firmware Build Number       %d\n", sc->mlx_enq2->me_firmware_build);
2848	device_printf(sc->mlx_dev, "  Fault Management Type       %d\n", sc->mlx_enq2->me_fault_mgmt_type);
2849	device_printf(sc->mlx_dev, "  Features                    %b\n", sc->mlx_enq2->me_firmware_features,
2850		      "\20\4Background Init\3Read Ahead\2MORE\1Cluster\n");
2851
2852    }
2853}
2854
2855/*******************************************************************************
2856 * Emit a string describing the firmware handshake status code, and return a flag
2857 * indicating whether the code represents a fatal error.
2858 *
2859 * Error code interpretations are from the Linux driver, and don't directly match
2860 * the messages printed by Mylex's BIOS.  This may change if documentation on the
2861 * codes is forthcoming.
2862 */
2863static int
2864mlx_fw_message(struct mlx_softc *sc, int error, int param1, int param2)
2865{
2866    switch(error) {
2867    case 0x00:
2868	device_printf(sc->mlx_dev, "physical drive %d:%d not responding\n", param2, param1);
2869	break;
2870    case 0x08:
2871	/* we could be neater about this and give some indication when we receive more of them */
2872	if (!(sc->mlx_flags & MLX_SPINUP_REPORTED)) {
2873	    device_printf(sc->mlx_dev, "spinning up drives...\n");
2874	    sc->mlx_flags |= MLX_SPINUP_REPORTED;
2875	}
2876	break;
2877    case 0x30:
2878	device_printf(sc->mlx_dev, "configuration checksum error\n");
2879	break;
2880    case 0x60:
2881	device_printf(sc->mlx_dev, "mirror race recovery failed\n");
2882	break;
2883    case 0x70:
2884	device_printf(sc->mlx_dev, "mirror race recovery in progress\n");
2885	break;
2886    case 0x90:
2887	device_printf(sc->mlx_dev, "physical drive %d:%d COD mismatch\n", param2, param1);
2888	break;
2889    case 0xa0:
2890	device_printf(sc->mlx_dev, "logical drive installation aborted\n");
2891	break;
2892    case 0xb0:
2893	device_printf(sc->mlx_dev, "mirror race on a critical system drive\n");
2894	break;
2895    case 0xd0:
2896	device_printf(sc->mlx_dev, "new controller configuration found\n");
2897	break;
2898    case 0xf0:
2899	device_printf(sc->mlx_dev, "FATAL MEMORY PARITY ERROR\n");
2900	return(1);
2901    default:
2902	device_printf(sc->mlx_dev, "unknown firmware initialisation error %02x:%02x:%02x\n", error, param1, param2);
2903	break;
2904    }
2905    return(0);
2906}
2907
2908/********************************************************************************
2909 ********************************************************************************
2910                                                                Utility Functions
2911 ********************************************************************************
2912 ********************************************************************************/
2913
2914/********************************************************************************
2915 * Find the disk whose unit number is (unit) on this controller
2916 */
2917static struct mlx_sysdrive *
2918mlx_findunit(struct mlx_softc *sc, int unit)
2919{
2920    int		i;
2921
2922    /* search system drives */
2923    for (i = 0; i < MLX_MAXDRIVES; i++) {
2924	/* is this one attached? */
2925	if (sc->mlx_sysdrive[i].ms_disk != 0) {
2926	    /* is this the one? */
2927	    if (unit == device_get_unit(sc->mlx_sysdrive[i].ms_disk))
2928		return(&sc->mlx_sysdrive[i]);
2929	}
2930    }
2931    return(NULL);
2932}
2933