xref: /freebsd/sys/dev/mlx/mlx.c (revision 1a9527eaaad28d19a91707c53bb0b38003b42e59)
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$
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/buf.h>
39 #include <sys/bus.h>
40 #include <sys/conf.h>
41 #include <sys/devicestat.h>
42 #include <sys/disk.h>
43 
44 #include <machine/resource.h>
45 #include <machine/bus.h>
46 #include <machine/clock.h>
47 #include <sys/rman.h>
48 
49 #include <dev/mlx/mlxio.h>
50 #include <dev/mlx/mlxvar.h>
51 #include <dev/mlx/mlxreg.h>
52 
53 #if 0
54 #define debug(fmt, args...)	printf("%s: " fmt "\n", __FUNCTION__ , ##args)
55 #else
56 #define debug(fmt, args...)
57 #endif
58 
59 #define MLX_CDEV_MAJOR	130
60 
61 static struct cdevsw mlx_cdevsw = {
62 		/* open */	mlx_open,
63 		/* close */	mlx_close,
64 		/* read */	noread,
65 		/* write */	nowrite,
66 		/* ioctl */	mlx_ioctl,
67 		/* poll */	nopoll,
68 		/* mmap */	nommap,
69 		/* strategy */	nostrategy,
70 		/* name */ 	"mlx",
71 		/* maj */	MLX_CDEV_MAJOR,
72 		/* dump */	nodump,
73 		/* psize */ 	nopsize,
74 		/* flags */	0,
75 		/* bmaj */	-1
76 };
77 
78 static int	cdev_registered = 0;
79 devclass_t	mlx_devclass;
80 
81 /*
82  * Per-interface accessor methods
83  */
84 static int			mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
85 static int			mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
86 static void			mlx_v3_intaction(struct mlx_softc *sc, int action);
87 
88 static int			mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
89 static int			mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
90 static void			mlx_v4_intaction(struct mlx_softc *sc, int action);
91 
92 static int			mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
93 static int			mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
94 static void			mlx_v5_intaction(struct mlx_softc *sc, int action);
95 
96 /*
97  * Status monitoring
98  */
99 static void			mlx_periodic(void *data);
100 static void			mlx_periodic_enquiry(struct mlx_command *mc);
101 static void			mlx_periodic_eventlog_poll(struct mlx_softc *sc);
102 static void			mlx_periodic_eventlog_respond(struct mlx_command *mc);
103 static void			mlx_periodic_rebuild(struct mlx_command *mc);
104 
105 /*
106  * Channel Pause
107  */
108 static void			mlx_pause_action(struct mlx_softc *sc);
109 static void			mlx_pause_done(struct mlx_command *mc);
110 
111 /*
112  * Command submission.
113  */
114 static void			*mlx_enquire(struct mlx_softc *sc, int command, size_t bufsize,
115 					     void (*complete)(struct mlx_command *mc));
116 static int			mlx_flush(struct mlx_softc *sc);
117 static int			mlx_rebuild(struct mlx_softc *sc, int channel, int target);
118 static int			mlx_wait_command(struct mlx_command *mc);
119 static int			mlx_poll_command(struct mlx_command *mc);
120 static void			mlx_startio(struct mlx_softc *sc);
121 static void			mlx_completeio(struct mlx_command *mc);
122 static int			mlx_user_command(struct mlx_softc *sc, struct mlx_usercommand *mu);
123 
124 /*
125  * Command buffer allocation.
126  */
127 static struct mlx_command	*mlx_alloccmd(struct mlx_softc *sc);
128 static void			mlx_releasecmd(struct mlx_command *mc);
129 static void			mlx_freecmd(struct mlx_command *mc);
130 
131 /*
132  * Command management.
133  */
134 static int			mlx_getslot(struct mlx_command *mc);
135 static void			mlx_mapcmd(struct mlx_command *mc);
136 static void			mlx_unmapcmd(struct mlx_command *mc);
137 static int			mlx_start(struct mlx_command *mc);
138 static int			mlx_done(struct mlx_softc *sc);
139 static void			mlx_complete(struct mlx_softc *sc);
140 
141 /*
142  * Debugging.
143  */
144 static char			*mlx_diagnose_command(struct mlx_command *mc);
145 static char			*mlx_name_controller(u_int32_t hwid);
146 
147 
148 /*
149  * Utility functions.
150  */
151 static struct mlx_sysdrive	*mlx_findunit(struct mlx_softc *sc, int unit);
152 
153 /********************************************************************************
154  ********************************************************************************
155                                                                 Public Interfaces
156  ********************************************************************************
157  ********************************************************************************/
158 
159 /********************************************************************************
160  * Free all of the resources associated with (sc)
161  *
162  * Should not be called if the controller is active.
163  */
164 void
165 mlx_free(struct mlx_softc *sc)
166 {
167     struct mlx_command	*mc;
168 
169     debug("called");
170 
171     /* cancel status timeout */
172     untimeout(mlx_periodic, sc, sc->mlx_timeout);
173 
174     /* throw away any command buffers */
175     while ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL) {
176 	TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link);
177 	mlx_freecmd(mc);
178     }
179 
180     /* destroy data-transfer DMA tag */
181     if (sc->mlx_buffer_dmat)
182 	bus_dma_tag_destroy(sc->mlx_buffer_dmat);
183 
184     /* free and destroy DMA memory and tag for s/g lists */
185     if (sc->mlx_sgtable)
186 	bus_dmamem_free(sc->mlx_sg_dmat, sc->mlx_sgtable, sc->mlx_sg_dmamap);
187     if (sc->mlx_sg_dmat)
188 	bus_dma_tag_destroy(sc->mlx_sg_dmat);
189 
190     /* disconnect the interrupt handler */
191     if (sc->mlx_intr)
192 	bus_teardown_intr(sc->mlx_dev, sc->mlx_irq, sc->mlx_intr);
193     if (sc->mlx_irq != NULL)
194 	bus_release_resource(sc->mlx_dev, SYS_RES_IRQ, 0, sc->mlx_irq);
195 
196     /* destroy the parent DMA tag */
197     if (sc->mlx_parent_dmat)
198 	bus_dma_tag_destroy(sc->mlx_parent_dmat);
199 
200     /* release the register window mapping */
201     if (sc->mlx_mem != NULL)
202 	bus_release_resource(sc->mlx_dev, SYS_RES_MEMORY,
203 			     (sc->mlx_iftype == MLX_IFTYPE_3) ? MLX_CFG_BASE1 : MLX_CFG_BASE0, sc->mlx_mem);
204 }
205 
206 /********************************************************************************
207  * Map the scatter/gather table into bus space
208  */
209 static void
210 mlx_dma_map_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error)
211 {
212     struct mlx_softc	*sc = (struct mlx_softc *)arg;
213 
214     debug("called");
215 
216     /* save base of s/g table's address in bus space */
217     sc->mlx_sgbusaddr = segs->ds_addr;
218 }
219 
220 static int
221 mlx_sglist_map(struct mlx_softc *sc)
222 {
223     size_t	segsize;
224     int		error;
225 
226     debug("called");
227 
228     /* destroy any existing mappings */
229     if (sc->mlx_sgtable)
230 	bus_dmamem_free(sc->mlx_sg_dmat, sc->mlx_sgtable, sc->mlx_sg_dmamap);
231     if (sc->mlx_sg_dmat)
232 	bus_dma_tag_destroy(sc->mlx_sg_dmat);
233 
234     /*
235      * Create a single tag describing a region large enough to hold all of
236      * the s/g lists we will need.
237      */
238     segsize = sizeof(struct mlx_sgentry) * MLX_NSEG * sc->mlx_maxiop;
239     error = bus_dma_tag_create(sc->mlx_parent_dmat, 	/* parent */
240 			       1, 0, 			/* alignment, boundary */
241 			       BUS_SPACE_MAXADDR,	/* lowaddr */
242 			       BUS_SPACE_MAXADDR, 	/* highaddr */
243 			       NULL, NULL, 		/* filter, filterarg */
244 			       segsize, 1,		/* maxsize, nsegments */
245 			       BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
246 			       0,			/* flags */
247 			       &sc->mlx_sg_dmat);
248     if (error != 0) {
249 	device_printf(sc->mlx_dev, "can't allocate scatter/gather DMA tag\n");
250 	return(ENOMEM);
251     }
252 
253     /*
254      * Allocate enough s/g maps for all commands and permanently map them into
255      * controller-visible space.
256      *
257      * XXX this assumes we can get enough space for all the s/g maps in one
258      * contiguous slab.  We may need to switch to a more complex arrangement where
259      * we allocate in smaller chunks and keep a lookup table from slot to bus address.
260      */
261     error = bus_dmamem_alloc(sc->mlx_sg_dmat, (void **)&sc->mlx_sgtable, BUS_DMA_NOWAIT, &sc->mlx_sg_dmamap);
262     if (error) {
263 	device_printf(sc->mlx_dev, "can't allocate s/g table\n");
264 	return(ENOMEM);
265     }
266     bus_dmamap_load(sc->mlx_sg_dmat, sc->mlx_sg_dmamap, sc->mlx_sgtable, segsize, mlx_dma_map_sg, sc, 0);
267     return(0);
268 }
269 
270 /********************************************************************************
271  * Initialise the controller and softc
272  */
273 int
274 mlx_attach(struct mlx_softc *sc)
275 {
276     struct mlx_enquiry	*me;
277     struct mlx_enquiry2	*me2;
278     int			rid, error;
279 
280     debug("called");
281 
282     /*
283      * Initialise per-controller queues.
284      */
285     TAILQ_INIT(&sc->mlx_work);
286     TAILQ_INIT(&sc->mlx_freecmds);
287     bufq_init(&sc->mlx_bufq);
288 
289     /*
290      * Select accessor methods based on controller interface type.
291      */
292     switch(sc->mlx_iftype) {
293     case MLX_IFTYPE_3:
294 	sc->mlx_tryqueue	= mlx_v3_tryqueue;
295 	sc->mlx_findcomplete	= mlx_v3_findcomplete;
296 	sc->mlx_intaction	= mlx_v3_intaction;
297 	break;
298     case MLX_IFTYPE_4:
299 	sc->mlx_tryqueue	= mlx_v4_tryqueue;
300 	sc->mlx_findcomplete	= mlx_v4_findcomplete;
301 	sc->mlx_intaction	= mlx_v4_intaction;
302 	break;
303     case MLX_IFTYPE_5:
304 	sc->mlx_tryqueue	= mlx_v5_tryqueue;
305 	sc->mlx_findcomplete	= mlx_v5_findcomplete;
306 	sc->mlx_intaction	= mlx_v5_intaction;
307 	break;
308     default:
309 	device_printf(sc->mlx_dev, "attaching unsupported interface version %d\n", sc->mlx_iftype);
310 	return(ENXIO);		/* should never happen */
311     }
312 
313     /* disable interrupts before we start talking to the controller */
314     sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
315 
316     /*
317      * Allocate and connect our interrupt.
318      */
319     rid = 0;
320     sc->mlx_irq = bus_alloc_resource(sc->mlx_dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);
321     if (sc->mlx_irq == NULL) {
322 	device_printf(sc->mlx_dev, "couldn't allocate interrupt\n");
323 	mlx_free(sc);
324 	return(ENXIO);
325     }
326     error = bus_setup_intr(sc->mlx_dev, sc->mlx_irq, INTR_TYPE_BIO,  mlx_intr, sc, &sc->mlx_intr);
327     if (error) {
328 	device_printf(sc->mlx_dev, "couldn't set up interrupt\n");
329 	mlx_free(sc);
330 	return(ENXIO);
331     }
332 
333     /*
334      * Create DMA tag for mapping buffers into controller-addressable space.
335      */
336     error = bus_dma_tag_create(sc->mlx_parent_dmat, 	/* parent */
337 			       1, 0, 			/* alignment, boundary */
338 			       BUS_SPACE_MAXADDR,	/* lowaddr */
339 			       BUS_SPACE_MAXADDR, 	/* highaddr */
340 			       NULL, NULL, 		/* filter, filterarg */
341 			       MAXBSIZE, MLX_NSEG,	/* maxsize, nsegments */
342 			       BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
343 			       0,			/* flags */
344 			       &sc->mlx_buffer_dmat);
345     if (error != 0) {
346 	device_printf(sc->mlx_dev, "can't allocate buffer DMA tag\n");
347 	return(ENOMEM);
348     }
349 
350     /*
351      * Create an initial set of s/g mappings.
352      */
353     sc->mlx_maxiop = 2;
354     error = mlx_sglist_map(sc);
355     if (error != 0) {
356 	device_printf(sc->mlx_dev, "couldn't make initial s/g list mapping\n");
357 	return(error);
358     }
359 
360     /*
361      * Probe the controller for more information.
362      */
363     /* send an ENQUIRY to the controller */
364     if ((me = mlx_enquire(sc, MLX_CMD_ENQUIRY, sizeof(*me), NULL)) == NULL) {
365 	device_printf(sc->mlx_dev, "ENQUIRY failed\n");
366 	return(ENXIO);
367     }
368 
369     /* pull information out of the ENQUIRY result */
370     sc->mlx_fwminor = me->me_fwminor;
371     sc->mlx_fwmajor = me->me_fwmajor;
372     sc->mlx_maxiop = me->me_max_commands;
373     sc->mlx_lastevent = sc->mlx_currevent = me->me_event_log_seq_num;
374     free(me, M_DEVBUF);
375 
376     /* send an ENQUIRY2 to the controller */
377     if ((me2 = mlx_enquire(sc, MLX_CMD_ENQUIRY2, sizeof(*me2), NULL)) == NULL) {
378 	device_printf(sc->mlx_dev, "ENQUIRY2 failed\n");
379 	return(ENXIO);
380     }
381 
382     /* pull information out of the ENQUIRY2 result */
383     sc->mlx_nchan = me2->me_configured_channels;
384     sc->mlx_maxiosize = me2->me_maxblk;
385     sc->mlx_maxtarg = me2->me_max_targets;
386     sc->mlx_maxtags = me2->me_max_tags;
387     sc->mlx_scsicap = me2->me_scsi_cap;
388     sc->mlx_hwid = me2->me_hardware_id;
389 
390     /* print a little information about the controller and ourselves */
391     device_printf(sc->mlx_dev, "Mylex %s, firmware %d.%02d, %dMB RAM\n",
392 	   mlx_name_controller(sc->mlx_hwid), sc->mlx_fwmajor, sc->mlx_fwminor,
393 	me2->me_mem_size / (1024 * 1024));
394     free(me2, M_DEVBUF);
395 
396     /*
397      * Do quirk/feature related things.
398      */
399     switch(sc->mlx_iftype) {
400     case MLX_IFTYPE_3:
401 	/* XXX certify 3.52? */
402 	if (sc->mlx_fwminor < 51) {
403 	    device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
404 	    device_printf(sc->mlx_dev, " *** WARNING *** Use revision 3.51 or later\n");
405 	}
406 	break;
407     case MLX_IFTYPE_4:
408 	/* XXX certify firmware versions? */
409 	if (sc->mlx_fwminor < 6) {
410 	    device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
411 	    device_printf(sc->mlx_dev, " *** WARNING *** Use revision 4.06 or later\n");
412 	}
413 	break;
414     case MLX_IFTYPE_5:
415 	if (sc->mlx_fwminor < 7) {
416 	    device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
417 	    device_printf(sc->mlx_dev, " *** WARNING *** Use revision 5.07 or later\n");
418 	}
419 	break;
420     default:
421 	device_printf(sc->mlx_dev, "interface version corrupted to %d\n", sc->mlx_iftype);
422 	return(ENXIO);		/* should never happen */
423     }
424 
425     /*
426      * Create the final set of s/g mappings now that we know how many commands
427      * the controller actually supports.
428      */
429     error = mlx_sglist_map(sc);
430     if (error != 0) {
431 	device_printf(sc->mlx_dev, "couldn't make initial s/g list mapping\n");
432 	return(error);
433     }
434 
435     /*
436      * No rebuild or check is in progress.
437      */
438     sc->mlx_rebuild = -1;
439     sc->mlx_check = -1;
440 
441     /*
442      * Register the control device on first attach.
443      */
444     if (cdev_registered++ == 0)
445 	cdevsw_add(&mlx_cdevsw);
446 
447     /*
448      * Start the timeout routine.
449      */
450     sc->mlx_timeout = timeout(mlx_periodic, sc, hz);
451 
452     return(0);
453 }
454 
455 /********************************************************************************
456  * Locate disk resources and attach children to them.
457  */
458 void
459 mlx_startup(struct mlx_softc *sc)
460 {
461     struct mlx_enq_sys_drive	*mes;
462     struct mlx_sysdrive		*dr;
463     int				i, error;
464 
465     debug("called");
466 
467     /*
468      * Scan all the system drives and attach children for those that
469      * don't currently have them.
470      */
471     mes = mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(*mes) * MLX_MAXDRIVES, NULL);
472     if (mes == NULL) {
473 	device_printf(sc->mlx_dev, "error fetching drive status");
474 	return;
475     }
476 
477     /* iterate over drives returned */
478     for (i = 0, dr = &sc->mlx_sysdrive[0];
479 	 (i < MLX_MAXDRIVES) && (mes[i].sd_size != 0xffffffff);
480 	 i++, dr++) {
481 	/* are we already attached to this drive? */
482     	if (dr->ms_disk == 0) {
483 	    /* pick up drive information */
484 	    dr->ms_size = mes[i].sd_size;
485 	    dr->ms_raidlevel = mes[i].sd_raidlevel & 0xf;
486 	    dr->ms_state = mes[i].sd_state;
487 
488 	    /* generate geometry information */
489 	    if (sc->mlx_geom == MLX_GEOM_128_32) {
490 		dr->ms_heads = 128;
491 		dr->ms_sectors = 32;
492 		dr->ms_cylinders = dr->ms_size / (128 * 32);
493 	    } else {        /* MLX_GEOM_255/63 */
494 		dr->ms_heads = 255;
495 		dr->ms_sectors = 63;
496 		dr->ms_cylinders = dr->ms_size / (255 * 63);
497 	    }
498 	    dr->ms_disk =  device_add_child(sc->mlx_dev, /*"mlxd"*/NULL, -1);
499 	    if (dr->ms_disk == 0)
500 		device_printf(sc->mlx_dev, "device_add_child failed\n");
501 	    device_set_ivars(dr->ms_disk, dr);
502 	}
503     }
504     free(mes, M_DEVBUF);
505     if ((error = bus_generic_attach(sc->mlx_dev)) != 0)
506 	device_printf(sc->mlx_dev, "bus_generic_attach returned %d", error);
507 
508     /* mark controller back up */
509     sc->mlx_state &= ~MLX_STATE_SHUTDOWN;
510 
511     /* enable interrupts */
512     sc->mlx_intaction(sc, MLX_INTACTION_ENABLE);
513 }
514 
515 /********************************************************************************
516  * Disconnect from the controller completely, in preparation for unload.
517  */
518 int
519 mlx_detach(device_t dev)
520 {
521     struct mlx_softc	*sc = device_get_softc(dev);
522     struct mlxd_softc	*mlxd;
523     int			i, s, error;
524 
525     debug("called");
526 
527     error = EBUSY;
528     s = splbio();
529     if (sc->mlx_state & MLX_STATE_OPEN)
530 	goto out;
531 
532     for (i = 0; i < MLX_MAXDRIVES; i++) {
533 	if (sc->mlx_sysdrive[i].ms_disk != 0) {
534 	    mlxd = device_get_softc(sc->mlx_sysdrive[i].ms_disk);
535 	    if (mlxd->mlxd_flags & MLXD_OPEN) {		/* drive is mounted, abort detach */
536 		device_printf(sc->mlx_sysdrive[i].ms_disk, "still open, can't detach\n");
537 		goto out;
538 	    }
539 	}
540     }
541     if ((error = mlx_shutdown(dev)))
542 	goto out;
543 
544     mlx_free(sc);
545 
546     /*
547      * Deregister the control device on last detach.
548      */
549     if (--cdev_registered == 0)
550 	cdevsw_remove(&mlx_cdevsw);
551     error = 0;
552  out:
553     splx(s);
554     return(error);
555 }
556 
557 /********************************************************************************
558  * Bring the controller down to a dormant state and detach all child devices.
559  *
560  * This function is called before detach, system shutdown, or before performing
561  * an operation which may add or delete system disks.  (Call mlx_startup to
562  * resume normal operation.)
563  *
564  * Note that we can assume that the bufq on the controller is empty, as we won't
565  * allow shutdown if any device is open.
566  */
567 int
568 mlx_shutdown(device_t dev)
569 {
570     struct mlx_softc	*sc = device_get_softc(dev);
571     int			i, s, error;
572 
573     debug("called");
574 
575     s = splbio();
576     error = 0;
577 
578     sc->mlx_state |= MLX_STATE_SHUTDOWN;
579     sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
580 
581     /* flush controller */
582     device_printf(sc->mlx_dev, "flushing cache...");
583     if (mlx_flush(sc)) {
584 	printf("failed\n");
585     } else {
586 	printf("done\n");
587     }
588 
589     /* delete all our child devices */
590     for (i = 0; i < MLX_MAXDRIVES; i++) {
591 	if (sc->mlx_sysdrive[i].ms_disk != 0) {
592 	    if ((error = device_delete_child(sc->mlx_dev, sc->mlx_sysdrive[i].ms_disk)) != 0)
593 		goto out;
594 	    sc->mlx_sysdrive[i].ms_disk = 0;
595 	}
596     }
597 
598  out:
599     splx(s);
600     return(error);
601 }
602 
603 /********************************************************************************
604  * Bring the controller to a quiescent state, ready for system suspend.
605  */
606 int
607 mlx_suspend(device_t dev)
608 {
609     struct mlx_softc	*sc = device_get_softc(dev);
610     int			s;
611 
612     debug("called");
613 
614     s = splbio();
615     sc->mlx_state |= MLX_STATE_SUSPEND;
616 
617     /* flush controller */
618     device_printf(sc->mlx_dev, "flushing cache...");
619     printf("%s\n", mlx_flush(sc) ? "failed" : "done");
620 
621     sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
622     splx(s);
623 
624     return(0);
625 }
626 
627 /********************************************************************************
628  * Bring the controller back to a state ready for operation.
629  */
630 int
631 mlx_resume(device_t dev)
632 {
633     struct mlx_softc	*sc = device_get_softc(dev);
634 
635     debug("called");
636 
637     sc->mlx_state &= ~MLX_STATE_SUSPEND;
638     sc->mlx_intaction(sc, MLX_INTACTION_ENABLE);
639 
640     return(0);
641 }
642 
643 /*******************************************************************************
644  * Take an interrupt, or be poked by other code to look for interrupt-worthy
645  * status.
646  */
647 void
648 mlx_intr(void *arg)
649 {
650     struct mlx_softc	*sc = (struct mlx_softc *)arg;
651 
652     debug("called");
653 
654     /* collect finished commands, queue anything waiting */
655     mlx_done(sc);
656 };
657 
658 /*******************************************************************************
659  * Receive a buf structure from a child device and queue it on a particular
660  * disk resource, then poke the disk resource to start as much work as it can.
661  */
662 int
663 mlx_submit_buf(struct mlx_softc *sc, struct buf *bp)
664 {
665     int		s;
666 
667     debug("called");
668 
669     s = splbio();
670     bufq_insert_tail(&sc->mlx_bufq, bp);
671     sc->mlx_waitbufs++;
672     splx(s);
673     mlx_startio(sc);
674     return(0);
675 }
676 
677 /********************************************************************************
678  * Accept an open operation on the control device.
679  */
680 int
681 mlx_open(dev_t dev, int flags, int fmt, struct proc *p)
682 {
683     int			unit = minor(dev);
684     struct mlx_softc	*sc = devclass_get_softc(mlx_devclass, unit);
685 
686     sc->mlx_state |= MLX_STATE_OPEN;
687     return(0);
688 }
689 
690 /********************************************************************************
691  * Accept the last close on the control device.
692  */
693 int
694 mlx_close(dev_t dev, int flags, int fmt, struct proc *p)
695 {
696     int			unit = minor(dev);
697     struct mlx_softc	*sc = devclass_get_softc(mlx_devclass, unit);
698 
699     sc->mlx_state &= ~MLX_STATE_OPEN;
700     return (0);
701 }
702 
703 /********************************************************************************
704  * Handle controller-specific control operations.
705  */
706 int
707 mlx_ioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
708 {
709     int			unit = minor(dev);
710     struct mlx_softc	*sc = devclass_get_softc(mlx_devclass, unit);
711     int			*arg = (int *)addr;
712     struct mlx_pause	*mp;
713     struct mlx_sysdrive	*dr;
714     struct mlxd_softc	*mlxd;
715     int			i, error;
716 
717     switch(cmd) {
718 	/*
719 	 * Enumerate connected system drives; returns the first system drive's
720 	 * unit number if *arg is -1, or the next unit after *arg if it's
721 	 * a valid unit on this controller.
722 	 */
723     case MLX_NEXT_CHILD:
724 	/* search system drives */
725 	for (i = 0; i < MLX_MAXDRIVES; i++) {
726 	    /* is this one attached? */
727 	    if (sc->mlx_sysdrive[i].ms_disk != 0) {
728 		/* looking for the next one we come across? */
729 		if (*arg == -1) {
730 		    *arg = device_get_unit(sc->mlx_sysdrive[i].ms_disk);
731 		    return(0);
732 		}
733 		/* we want the one after this one */
734 		if (*arg == device_get_unit(sc->mlx_sysdrive[i].ms_disk))
735 		    *arg = -1;
736 	    }
737 	}
738 	return(ENOENT);
739 
740 	/*
741 	 * Scan the controller to see whether new drives have appeared.
742 	 */
743     case MLX_RESCAN_DRIVES:
744 	mlx_startup(sc);
745 	return(0);
746 
747 	/*
748 	 * Disconnect from the specified drive; it may be about to go
749 	 * away.
750 	 */
751     case MLX_DETACH_DRIVE:			/* detach one drive */
752 
753 	if (((dr = mlx_findunit(sc, *arg)) == NULL) ||
754 	    ((mlxd = device_get_softc(dr->ms_disk)) == NULL))
755 	    return(ENOENT);
756 
757 	device_printf(dr->ms_disk, "detaching...");
758 	error = 0;
759 	if (mlxd->mlxd_flags & MLXD_OPEN) {
760 	    error = EBUSY;
761 	    goto detach_out;
762 	}
763 
764 	/* flush controller */
765 	if (mlx_flush(sc)) {
766 	    error = EBUSY;
767 	    goto detach_out;
768 	}
769 
770 	/* nuke drive */
771 	if ((error = device_delete_child(sc->mlx_dev, dr->ms_disk)) != 0)
772 	    goto detach_out;
773 	dr->ms_disk = 0;
774 
775     detach_out:
776 	if (error) {
777 	    printf("failed\n");
778 	} else {
779 	    printf("done\n");
780 	}
781 	return(error);
782 
783 	/*
784 	 * Pause one or more SCSI channels for a period of time, to assist
785 	 * in the process of hot-swapping devices.
786 	 *
787 	 * Note that at least the 3.51 firmware on the DAC960PL doesn't seem
788 	 * to do this right.
789 	 */
790     case MLX_PAUSE_CHANNEL:			/* schedule a channel pause */
791 	/* Does this command work on this firmware? */
792 	if (!(sc->mlx_feature & MLX_FEAT_PAUSEWORKS))
793 	    return(EOPNOTSUPP);
794 
795 	mp = (struct mlx_pause *)addr;
796 	if ((mp->mp_which == MLX_PAUSE_CANCEL) && (sc->mlx_pause.mp_when != 0)) {
797 	    /* cancel a pending pause operation */
798 	    sc->mlx_pause.mp_which = 0;
799 	} else {
800 	    /* fix for legal channels */
801 	    mp->mp_which &= ((1 << sc->mlx_nchan) -1);
802 	    /* check time values */
803 	    if ((mp->mp_when < 0) || (mp->mp_when > 3600))
804 		return(EINVAL);
805 	    if ((mp->mp_howlong < 1) || (mp->mp_howlong > (0xf * 30)))
806 		return(EINVAL);
807 
808 	    /* check for a pause currently running */
809 	    if ((sc->mlx_pause.mp_which != 0) && (sc->mlx_pause.mp_when == 0))
810 		return(EBUSY);
811 
812 	    /* looks ok, go with it */
813 	    sc->mlx_pause.mp_which = mp->mp_which;
814 	    sc->mlx_pause.mp_when = time_second + mp->mp_when;
815 	    sc->mlx_pause.mp_howlong = sc->mlx_pause.mp_when + mp->mp_howlong;
816 	}
817 	return(0);
818 
819 	/*
820 	 * Accept a command passthrough-style.
821 	 */
822     case MLX_COMMAND:
823 	return(mlx_user_command(sc, (struct mlx_usercommand *)addr));
824 
825     default:
826 	return(ENOTTY);
827     }
828 }
829 
830 /********************************************************************************
831  * Handle operations requested by a System Drive connected to this controller.
832  */
833 int
834 mlx_submit_ioctl(struct mlx_softc *sc, struct mlx_sysdrive *drive, u_long cmd,
835 		caddr_t addr, int32_t flag, struct proc *p)
836 {
837     struct mlxd_rebuild		*mr = (struct mlxd_rebuild *)addr;
838     struct mlxd_rebuild_status	*mp = (struct mlxd_rebuild_status *)addr;
839     int				*arg = (int *)addr;
840     int				error;
841 
842     switch(cmd) {
843 	/*
844 	 * Return the current status of this drive.
845 	 */
846     case MLXD_STATUS:
847 	*arg = drive->ms_state;
848 	return(0);
849 
850 	/*
851 	 * Start a background rebuild on this drive.
852 	 */
853     case MLXD_REBUILDASYNC:
854 	/* XXX lock? */
855 	if (sc->mlx_rebuild >= 0)
856 	    return(EBUSY);
857 	sc->mlx_rebuild = drive - &sc->mlx_sysdrive[0];
858 
859 	switch (mlx_rebuild(sc, mr->rb_channel, mr->rb_target)) {
860 	case 0:
861 	    drive->ms_state = MLX_SYSD_REBUILD;
862 	    error = 0;
863 	    break;
864 	case 0x10000:
865 	    error = ENOMEM;		/* couldn't set up the command */
866 	    break;
867 	case 0x0002:
868 	case 0x0106:
869 	    error = EBUSY;
870 	    break;
871 	case 0x0004:
872 	    error = EIO;
873 	    break;
874 	case 0x0105:
875 	    error = ERANGE;
876 	    break;
877 	default:
878 	    error = EINVAL;
879 	    break;
880 	}
881 	if (error != 0)
882 	    sc->mlx_rebuild = -1;
883 	return(error);
884 
885 	/*
886 	 * Start a background consistency check on this drive.
887 	 */
888     case MLXD_CHECKASYNC:		/* start a background consistency check */
889 	/* XXX implement */
890 	break;
891 
892 	/*
893 	 * Get the status of the current rebuild or consistency check.
894 	 */
895     case MLXD_REBUILDSTAT:
896 
897 	if (sc->mlx_rebuild >= 0) {	/* may be a second or so out of date */
898 	    mp->rs_drive = sc->mlx_rebuild;
899 	    mp->rs_size = sc->mlx_sysdrive[sc->mlx_rebuild].ms_size;
900 	    mp->rs_remaining = sc->mlx_rebuildstat;
901 	    return(0);
902 	} else if (sc->mlx_check >= 0) {
903 	    /* XXX implement */
904 	} else {
905 	    /* XXX should return status of last completed operation? */
906 	    return(EINVAL);
907 	}
908 
909     }
910     return(ENOIOCTL);
911 }
912 
913 
914 /********************************************************************************
915  ********************************************************************************
916                                                                 Status Monitoring
917  ********************************************************************************
918  ********************************************************************************/
919 
920 /********************************************************************************
921  * Fire off commands to periodically check the status of connected drives.
922  */
923 static void
924 mlx_periodic(void *data)
925 {
926     struct mlx_softc *sc = (struct mlx_softc *)data;
927 
928     debug("called");
929 
930     /*
931      * Run a bus pause?
932      */
933     if ((sc->mlx_pause.mp_which != 0) &&
934 	(sc->mlx_pause.mp_when > 0) &&
935 	(time_second >= sc->mlx_pause.mp_when)){
936 
937 	mlx_pause_action(sc);		/* pause is running */
938 	sc->mlx_pause.mp_when = 0;
939 	sysbeep(500, hz);
940 
941 	/*
942 	 * Bus pause still running?
943 	 */
944     } else if ((sc->mlx_pause.mp_which != 0) &&
945 	       (sc->mlx_pause.mp_when == 0)) {
946 
947 	/* time to stop bus pause? */
948 	if (time_second >= sc->mlx_pause.mp_howlong) {
949 	    mlx_pause_action(sc);
950 	    sc->mlx_pause.mp_which = 0;	/* pause is complete */
951 	    sysbeep(500, hz);
952 	} else {
953 	    sysbeep((time_second % 5) * 100 + 500, hz/8);
954 	}
955 
956 	/*
957 	 * Run normal periodic activities?
958 	 */
959     } else if (time_second > (sc->mlx_lastpoll + 10)) {
960 	sc->mlx_lastpoll = time_second;
961 
962 	/*
963 	 * Check controller status.
964 	 *
965 	 * XXX Note that this may not actually launch a command in situations of high load.
966 	 */
967 	mlx_enquire(sc, MLX_CMD_ENQUIRY, sizeof(struct mlx_enquiry), mlx_periodic_enquiry);
968 
969 	/*
970 	 * Check system drive status.
971 	 *
972 	 * XXX This might be better left to event-driven detection, eg. I/O to an offline
973 	 *     drive will detect it's offline, rebuilds etc. should detect the drive is back
974 	 *     online.
975 	 */
976 	mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(struct mlx_enq_sys_drive) * MLX_MAXDRIVES,
977 			mlx_periodic_enquiry);
978 
979 	/*
980 	 * Get drive rebuild/check status
981 	 */
982 	if (sc->mlx_rebuild >= 0)
983 	    mlx_enquire(sc, MLX_CMD_REBUILDSTAT, sizeof(struct mlx_rebuild_stat), mlx_periodic_rebuild);
984     }
985 
986     /* deal with possibly-missed interrupts and timed-out commands */
987     mlx_done(sc);
988 
989     /* reschedule another poll next second or so */
990     sc->mlx_timeout = timeout(mlx_periodic, sc, hz);
991 }
992 
993 /********************************************************************************
994  * Handle the result of an ENQUIRY command instigated by periodic status polling.
995  */
996 static void
997 mlx_periodic_enquiry(struct mlx_command *mc)
998 {
999     struct mlx_softc		*sc = mc->mc_sc;
1000 
1001     debug("called");
1002 
1003     /* Command completed OK? */
1004     if (mc->mc_status != 0) {
1005 	device_printf(sc->mlx_dev, "periodic enquiry failed\n");
1006 	goto out;
1007     }
1008 
1009     /* respond to command */
1010     switch(mc->mc_mailbox[0]) {
1011 	/*
1012 	 * Generic controller status update.  We could do more with this than just
1013 	 * checking the event log.
1014 	 */
1015     case MLX_CMD_ENQUIRY:
1016     {
1017 	struct mlx_enquiry		*me = (struct mlx_enquiry *)mc->mc_data;
1018 
1019 	/* New stuff in the event log? */
1020 	if (me->me_event_log_seq_num != sc->mlx_lastevent) {
1021 	    /* record where current events are up to */
1022 	    sc->mlx_currevent = me->me_event_log_seq_num;
1023 	    device_printf(sc->mlx_dev, "event log pointer was %d, now %d\n",
1024 			  sc->mlx_lastevent, sc->mlx_currevent);
1025 
1026 	    /* start poll of event log */
1027 	    mlx_periodic_eventlog_poll(sc);
1028 	}
1029 	break;
1030     }
1031     case MLX_CMD_ENQSYSDRIVE:
1032     {
1033 	struct mlx_enq_sys_drive	*mes = (struct mlx_enq_sys_drive *)mc->mc_data;
1034 	struct mlx_sysdrive		*dr;
1035 	int				i;
1036 
1037 	for (i = 0, dr = &sc->mlx_sysdrive[0];
1038 	     (i < MLX_MAXDRIVES) && (mes[i].sd_size != 0xffffffff);
1039 	     i++) {
1040 
1041 	    /* if disk is being rebuilt, we should not check it */
1042 	    if (dr->ms_state == MLX_SYSD_REBUILD) {
1043 		/* has state been changed by controller? */
1044 		if (dr->ms_state != mes[i].sd_state) {
1045 		    switch(mes[i].sd_state) {
1046 		    case MLX_SYSD_OFFLINE:
1047 			device_printf(dr->ms_disk, "drive offline\n");
1048 			break;
1049 		    case MLX_SYSD_ONLINE:
1050 			device_printf(dr->ms_disk, "drive online\n");
1051 			break;
1052 		    case MLX_SYSD_CRITICAL:
1053 			device_printf(dr->ms_disk, "drive critical\n");
1054 			break;
1055 		    }
1056 		    /* save new state */
1057 		    dr->ms_state = mes[i].sd_state;
1058 		}
1059 	    }
1060 	}
1061 	break;
1062     }
1063     default:
1064 	device_printf(sc->mlx_dev, "%s: unknown command 0x%x", __FUNCTION__, mc->mc_mailbox[0]);
1065 	break;
1066     }
1067 
1068  out:
1069     free(mc->mc_data, M_DEVBUF);
1070     mlx_releasecmd(mc);
1071 }
1072 
1073 /********************************************************************************
1074  * Instigate a poll for one event log message on (sc).
1075  * We only poll for one message at a time, to keep our command usage down.
1076  */
1077 static void
1078 mlx_periodic_eventlog_poll(struct mlx_softc *sc)
1079 {
1080     struct mlx_command	*mc;
1081     void		*result = NULL;
1082     int			error;
1083 
1084     debug("called");
1085 
1086     /* get ourselves a command buffer */
1087     error = 1;
1088     if ((mc = mlx_alloccmd(sc)) == NULL)
1089 	goto out;
1090     /* allocate the response structure */
1091     if ((result = malloc(/*sizeof(struct mlx_eventlog_entry)*/1024, M_DEVBUF, M_NOWAIT)) == NULL)
1092 	goto out;
1093     /* get a command slot */
1094     if (mlx_getslot(mc))
1095 	goto out;
1096 
1097     /* map the command so the controller can see it */
1098     mc->mc_data = result;
1099     mc->mc_length = /*sizeof(struct mlx_eventlog_entry)*/1024;
1100     mlx_mapcmd(mc);
1101 
1102     /* build the command to get one entry */
1103     mlx_make_type3(mc, MLX_CMD_LOGOP, MLX_LOGOP_GET, 1, sc->mlx_lastevent, 0, 0, mc->mc_dataphys, 0);
1104     mc->mc_complete = mlx_periodic_eventlog_respond;
1105     mc->mc_private = mc;
1106 
1107     /* start the command */
1108     if ((error = mlx_start(mc)) != 0)
1109 	goto out;
1110 
1111     error = 0;			/* success */
1112  out:
1113     if (error != 0) {
1114 	if (mc != NULL)
1115 	    mlx_releasecmd(mc);
1116 	if (result != NULL)
1117 	    free(result, M_DEVBUF);
1118     }
1119 }
1120 
1121 /********************************************************************************
1122  * Handle the result of polling for a log message, generate diagnostic output.
1123  * If this wasn't the last message waiting for us, we'll go collect another.
1124  */
1125 static char *mlx_sense_messages[] = {
1126     "because write recovery failed",
1127     "because of SCSI bus reset failure",
1128     "because of double check condition",
1129     "because it was removed",
1130     "because of gross error on SCSI chip",
1131     "because of bad tag returned from drive",
1132     "because of timeout on SCSI command",
1133     "because of reset SCSI command issued from system",
1134     "because busy or parity error count exceeded limit",
1135     "because of 'kill drive' command from system",
1136     "because of selection timeout",
1137     "due to SCSI phase sequence error",
1138     "due to unknown status"
1139 };
1140 
1141 static void
1142 mlx_periodic_eventlog_respond(struct mlx_command *mc)
1143 {
1144     struct mlx_softc		*sc = mc->mc_sc;
1145     struct mlx_eventlog_entry	*el = (struct mlx_eventlog_entry *)mc->mc_data;
1146     char			*reason;
1147 
1148     debug("called");
1149 
1150     sc->mlx_lastevent++;		/* next message... */
1151     if (mc->mc_status == 0) {
1152 
1153 	/* handle event log message */
1154 	switch(el->el_type) {
1155 	    /*
1156 	     * This is the only sort of message we understand at the moment.
1157 	     * The tests here are probably incomplete.
1158 	     */
1159 	case MLX_LOGMSG_SENSE:	/* sense data */
1160 	    /* Mylex vendor-specific message indicating a drive was killed? */
1161 	    if ((el->el_sensekey == 9) &&
1162 		(el->el_asc == 0x80)) {
1163 		if (el->el_asq < (sizeof(mlx_sense_messages) / sizeof(mlx_sense_messages[0]))) {
1164 		    reason = mlx_sense_messages[el->el_asq];
1165 		} else {
1166 		    reason = "for unknown reason";
1167 		}
1168 		device_printf(sc->mlx_dev, "physical drive %d:%d killed %s\n",
1169 			      el->el_channel, el->el_target, reason);
1170 	    }
1171 	    /* SCSI drive was reset? */
1172 	    if ((el->el_sensekey == 6) && (el->el_asc == 0x29)) {
1173 		device_printf(sc->mlx_dev, "physical drive %d:%d reset\n",
1174 			      el->el_channel, el->el_target);
1175 	    }
1176 	    /* SCSI drive error? */
1177 	    if (!((el->el_sensekey == 0) ||
1178 		  ((el->el_sensekey == 2) &&
1179 		   (el->el_asc == 0x04) &&
1180 		   ((el->el_asq == 0x01) ||
1181 		    (el->el_asq == 0x02))))) {
1182 		device_printf(sc->mlx_dev, "physical drive %d:%d error log: sense = %d asc = %x asq = %x\n",
1183 			      el->el_channel, el->el_target, el->el_sensekey, el->el_asc, el->el_asq);
1184 		device_printf(sc->mlx_dev, "  info %4D csi %4D\n", el->el_information, ":", el->el_csi, ":");
1185 	    }
1186 	    break;
1187 
1188 	default:
1189 	    device_printf(sc->mlx_dev, "unknown log message type 0x%x\n", el->el_type);
1190 	    break;
1191 	}
1192     } else {
1193 	device_printf(sc->mlx_dev, "error reading message log - %s\n", mlx_diagnose_command(mc));
1194     }
1195 
1196     /* dispose of command and data */
1197     free(mc->mc_data, M_DEVBUF);
1198     mlx_releasecmd(mc);
1199 
1200     /* is there another message to obtain? */
1201     if (sc->mlx_lastevent != sc->mlx_currevent)
1202 	mlx_periodic_eventlog_poll(sc);
1203 }
1204 
1205 /********************************************************************************
1206  * Handle the completion of a rebuild operation.
1207  */
1208 static void
1209 mlx_periodic_rebuild(struct mlx_command *mc)
1210 {
1211     struct mlx_softc		*sc = mc->mc_sc;
1212     struct mlx_rebuild_stat	*mr = (struct mlx_rebuild_stat *)mc->mc_private;
1213 
1214     switch(mc->mc_status) {
1215     case 0:				/* all OK, rebuild still running */
1216 	sc->mlx_rebuildstat = mr->rb_remaining;
1217 	break;
1218 
1219     case 0x0105:			/* rebuild/check finished */
1220 	if (sc->mlx_rebuild >= 0) {
1221 	    device_printf(sc->mlx_sysdrive[sc->mlx_rebuild].ms_disk, "rebuild completed\n");
1222 	    sc->mlx_rebuild = -1;
1223 	} else if (sc->mlx_check >= 0) {
1224 	    device_printf(sc->mlx_sysdrive[sc->mlx_check].ms_disk, "consistency check completed\n");
1225 	    sc->mlx_check = -1;
1226 	} else {
1227 	    device_printf(sc->mlx_dev, "consistency check completed\n");
1228 	}
1229 	break;
1230     }
1231     free(mc->mc_data, M_DEVBUF);
1232     mlx_releasecmd(mc);
1233 }
1234 
1235 /********************************************************************************
1236  ********************************************************************************
1237                                                                     Channel Pause
1238  ********************************************************************************
1239  ********************************************************************************/
1240 
1241 /********************************************************************************
1242  * It's time to perform a channel pause action for (sc), either start or stop
1243  * the pause.
1244  */
1245 static void
1246 mlx_pause_action(struct mlx_softc *sc)
1247 {
1248     struct mlx_command	*mc;
1249     int			failsafe, i, command;
1250 
1251     /* What are we doing here? */
1252     if (sc->mlx_pause.mp_when == 0) {
1253 	command = MLX_CMD_STARTCHANNEL;
1254 	failsafe = 0;
1255 
1256     } else {
1257 	command = MLX_CMD_STOPCHANNEL;
1258 
1259 	/*
1260 	 * Channels will always start again after the failsafe period,
1261 	 * which is specified in multiples of 30 seconds.
1262 	 * This constrains us to a maximum pause of 450 seconds.
1263 	 */
1264 	failsafe = ((sc->mlx_pause.mp_howlong - time_second) + 5) / 30;
1265 	if (failsafe > 0xf) {
1266 	    failsafe = 0xf;
1267 	    sc->mlx_pause.mp_howlong = time_second + (0xf * 30) - 5;
1268 	}
1269     }
1270 
1271     /* build commands for every channel requested */
1272     for (i = 0; i < sc->mlx_nchan; i++) {
1273 	if ((1 << i) & sc->mlx_pause.mp_which) {
1274 
1275 	    /* get ourselves a command buffer */
1276 	    if ((mc = mlx_alloccmd(sc)) == NULL)
1277 		goto fail;
1278 	    /* get a command slot */
1279 	    mc->mc_flags |= MLX_CMD_PRIORITY;
1280 	    if (mlx_getslot(mc))
1281 		goto fail;
1282 
1283 	    /* build the command */
1284 	    mlx_make_type2(mc, command, (failsafe << 4) | i, 0, 0, 0, 0, 0, 0, 0);
1285 	    mc->mc_complete = mlx_pause_done;
1286 	    mc->mc_private = sc;		/* XXX not needed */
1287 	    if (mlx_start(mc))
1288 		goto fail;
1289 	    /* command submitted OK */
1290 	    return;
1291 
1292 	fail:
1293 	    device_printf(sc->mlx_dev, "%s failed for channel %d\n",
1294 			  command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", i);
1295 	    if (mc != NULL)
1296 		mlx_releasecmd(mc);
1297 	}
1298     }
1299 }
1300 
1301 static void
1302 mlx_pause_done(struct mlx_command *mc)
1303 {
1304     struct mlx_softc	*sc = mc->mc_sc;
1305     int			command = mc->mc_mailbox[0];
1306     int			channel = mc->mc_mailbox[2] & 0xf;
1307 
1308     if (mc->mc_status != 0) {
1309 	device_printf(sc->mlx_dev, "%s command failed - %s\n",
1310 		      command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", mlx_diagnose_command(mc));
1311     } else if (command == MLX_CMD_STOPCHANNEL) {
1312 	device_printf(sc->mlx_dev, "channel %d pausing for %ld seconds\n",
1313 		      channel, (long)(sc->mlx_pause.mp_howlong - time_second));
1314     } else {
1315 	device_printf(sc->mlx_dev, "channel %d resuming\n", channel);
1316     }
1317     mlx_releasecmd(mc);
1318 }
1319 
1320 /********************************************************************************
1321  ********************************************************************************
1322                                                                Command Submission
1323  ********************************************************************************
1324  ********************************************************************************/
1325 
1326 /********************************************************************************
1327  * Perform an Enquiry command using a type-3 command buffer and a return a single
1328  * linear result buffer.  If the completion function is specified, it will
1329  * be called with the completed command (and the result response will not be
1330  * valid until that point).  Otherwise, the command will either be busy-waited
1331  * for (interrupts not enabled), or slept for.
1332  */
1333 static void *
1334 mlx_enquire(struct mlx_softc *sc, int command, size_t bufsize, void (* complete)(struct mlx_command *mc))
1335 {
1336     struct mlx_command	*mc;
1337     void		*result;
1338     int			error;
1339 
1340     debug("called");
1341 
1342     /* get ourselves a command buffer */
1343     error = 1;
1344     result = NULL;
1345     if ((mc = mlx_alloccmd(sc)) == NULL)
1346 	goto out;
1347     /* allocate the response structure */
1348     if ((result = malloc(bufsize, M_DEVBUF, M_NOWAIT)) == NULL)
1349 	goto out;
1350     /* get a command slot */
1351     mc->mc_flags |= MLX_CMD_PRIORITY | MLX_CMD_DATAOUT;
1352     if (mlx_getslot(mc))
1353 	goto out;
1354 
1355     /* map the command so the controller can see it */
1356     mc->mc_data = result;
1357     mc->mc_length = bufsize;
1358     mlx_mapcmd(mc);
1359 
1360     /* build an enquiry command */
1361     mlx_make_type2(mc, command, 0, 0, 0, 0, 0, 0, mc->mc_dataphys, 0);
1362 
1363     /* do we want a completion callback? */
1364     if (complete != NULL) {
1365 	mc->mc_complete = complete;
1366 	mc->mc_private = mc;
1367 	if ((error = mlx_start(mc)) != 0)
1368 	    goto out;
1369     } else {
1370 	/* run the command in either polled or wait mode */
1371 	if ((sc->mlx_state & MLX_STATE_INTEN) ? mlx_wait_command(mc) : mlx_poll_command(mc))
1372 	    goto out;
1373 
1374 	/* command completed OK? */
1375 	if (mc->mc_status != 0) {
1376 	    device_printf(sc->mlx_dev, "ENQUIRY failed - %s\n", mlx_diagnose_command(mc));
1377 	    goto out;
1378 	}
1379     }
1380     error = 0;			/* success */
1381  out:
1382     /* we got a command, but nobody else will free it */
1383     if ((complete == NULL) && (mc != NULL))
1384 	mlx_releasecmd(mc);
1385     /* we got an error, and we allocated a result */
1386     if ((error != 0) && (result != NULL)) {
1387 	free(result, M_DEVBUF);
1388 	result = NULL;
1389     }
1390     return(result);
1391 }
1392 
1393 
1394 /********************************************************************************
1395  * Perform a Flush command on the nominated controller.
1396  *
1397  * May be called with interrupts enabled or disabled; will not return until
1398  * the flush operation completes or fails.
1399  */
1400 static int
1401 mlx_flush(struct mlx_softc *sc)
1402 {
1403     struct mlx_command	*mc;
1404     int			error;
1405 
1406     debug("called");
1407 
1408     /* get ourselves a command buffer */
1409     error = 1;
1410     if ((mc = mlx_alloccmd(sc)) == NULL)
1411 	goto out;
1412     /* get a command slot */
1413     if (mlx_getslot(mc))
1414 	goto out;
1415 
1416     /* build a flush command */
1417     mlx_make_type2(mc, MLX_CMD_FLUSH, 0, 0, 0, 0, 0, 0, 0, 0);
1418 
1419     /* can't assume that interrupts are going to work here, so play it safe */
1420     if (mlx_poll_command(mc))
1421 	goto out;
1422 
1423     /* command completed OK? */
1424     if (mc->mc_status != 0) {
1425 	device_printf(sc->mlx_dev, "FLUSH failed - %s\n", mlx_diagnose_command(mc));
1426 	goto out;
1427     }
1428 
1429     error = 0;			/* success */
1430  out:
1431     if (mc != NULL)
1432 	mlx_releasecmd(mc);
1433     return(error);
1434 }
1435 
1436 /********************************************************************************
1437  * Start a background rebuild on the nominated controller/channel/target.
1438  *
1439  * May be called with interrupts enabled or disabled; will return as soon as the
1440  * operation has started or been refused.
1441  */
1442 static int
1443 mlx_rebuild(struct mlx_softc *sc, int channel, int target)
1444 {
1445     struct mlx_command	*mc;
1446     int			error;
1447 
1448     debug("called");
1449 
1450     /* get ourselves a command buffer */
1451     error = 0x10000;
1452     if ((mc = mlx_alloccmd(sc)) == NULL)
1453 	goto out;
1454     /* get a command slot */
1455     if (mlx_getslot(mc))
1456 	goto out;
1457 
1458     /* build a rebuild command */
1459     mlx_make_type2(mc, MLX_CMD_REBUILDASYNC, channel, target, 0, 0, 0, 0, 0, 0);
1460 
1461     /* run the command in either polled or wait mode */
1462     if ((sc->mlx_state & MLX_STATE_INTEN) ? mlx_wait_command(mc) : mlx_poll_command(mc))
1463 	goto out;
1464 
1465     /* command completed OK? */
1466     if (mc->mc_status != 0) {
1467 	device_printf(sc->mlx_dev, "REBUILD ASYNC failed - %s\n", mlx_diagnose_command(mc));
1468     } else {
1469 	device_printf(sc->mlx_sysdrive[sc->mlx_rebuild].ms_disk, "rebuild started");
1470     }
1471     error = mc->mc_status;
1472 
1473  out:
1474     if (mc != NULL)
1475 	mlx_releasecmd(mc);
1476     return(error);
1477 }
1478 
1479 /********************************************************************************
1480  * Run the command (mc) and return when it completes.
1481  *
1482  * Interrupts need to be enabled; returns nonzero on error.
1483  */
1484 static int
1485 mlx_wait_command(struct mlx_command *mc)
1486 {
1487     struct mlx_softc	*sc = mc->mc_sc;
1488     int			error, count;
1489 
1490     debug("called");
1491 
1492     mc->mc_complete = NULL;
1493     mc->mc_private = mc;		/* wake us when you're done */
1494     if ((error = mlx_start(mc)) != 0)
1495 	return(error);
1496 
1497     count = 0;
1498     /* XXX better timeout? */
1499     while ((mc->mc_status == MLX_STATUS_BUSY) && (count < 30)) {
1500 	tsleep(mc->mc_private, PRIBIO | PCATCH, "mlxwcmd", hz);
1501     }
1502 
1503     if (mc->mc_status != 0) {
1504 	device_printf(sc->mlx_dev, "I/O error 0x%x\n", mc->mc_status);
1505 	return(EIO);
1506     }
1507     return(0);
1508 }
1509 
1510 
1511 /********************************************************************************
1512  * Start the command (mc) and busy-wait for it to complete.
1513  *
1514  * Should only be used when interrupts are not available. Returns 0 on
1515  * success, nonzero on error.
1516  * Successfully completed commands are dequeued.
1517  */
1518 static int
1519 mlx_poll_command(struct mlx_command *mc)
1520 {
1521     struct mlx_softc	*sc = mc->mc_sc;
1522     int			error, count, s;
1523 
1524     debug("called");
1525 
1526     mc->mc_complete = NULL;
1527     mc->mc_private = NULL;	/* we will poll for it */
1528     if ((error = mlx_start(mc)) != 0)
1529 	return(error);
1530 
1531     count = 0;
1532     do {
1533 	/* poll for completion */
1534 	mlx_done(mc->mc_sc);
1535     } while ((mc->mc_status == MLX_STATUS_BUSY) && (count < 10000));
1536     if (mc->mc_status != MLX_STATUS_BUSY) {
1537 	s = splbio();
1538 	TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
1539 	splx(s);
1540 	return(0);
1541     }
1542     device_printf(sc->mlx_dev, "I/O error 0x%x\n", mc->mc_status);
1543     return(EIO);
1544 }
1545 
1546 /********************************************************************************
1547  * Pull as much work off the softc's work queue as possible and give it to the
1548  * controller.  Leave a couple of slots free for emergencies.
1549  *
1550  * Must be called at splbio or in an equivalent fashion that prevents
1551  * reentry or activity on the bufq..
1552  */
1553 static void
1554 mlx_startio(struct mlx_softc *sc)
1555 {
1556     struct mlx_command	*mc;
1557     struct mlxd_softc	*mlxd;
1558     struct buf		*bp;
1559     int			blkcount;
1560     int			driveno;
1561     int			cmd;
1562     int			s;
1563 
1564     /* avoid reentrancy */
1565     if (mlx_lock_tas(sc, MLX_LOCK_STARTING))
1566 	return;
1567 
1568     /* spin until something prevents us from doing any work */
1569     s = splbio();
1570     for (;;) {
1571 
1572 	/* see if there's work to be done */
1573 	if ((bp = bufq_first(&sc->mlx_bufq)) == NULL)
1574 	    break;
1575 	/* get a command */
1576 	if ((mc = mlx_alloccmd(sc)) == NULL)
1577 	    break;
1578 	/* get a slot for the command */
1579 	if (mlx_getslot(mc) != 0) {
1580 	    mlx_releasecmd(mc);
1581 	    break;
1582 	}
1583 	/* get the buf containing our work */
1584 	bufq_remove(&sc->mlx_bufq, bp);
1585 	sc->mlx_waitbufs--;
1586 	splx(s);
1587 
1588 	/* connect the buf to the command */
1589 	mc->mc_complete = mlx_completeio;
1590 	mc->mc_private = bp;
1591 	mc->mc_data = bp->b_data;
1592 	mc->mc_length = bp->b_bcount;
1593 	if (bp->b_flags & B_READ) {
1594 	    mc->mc_flags |= MLX_CMD_DATAIN;
1595 	    cmd = MLX_CMD_READOLDSG;
1596 	} else {
1597 	    mc->mc_flags |= MLX_CMD_DATAOUT;
1598 	    cmd = MLX_CMD_WRITEOLDSG;
1599 	}
1600 
1601 	/* map the command so the controller can work with it */
1602 	mlx_mapcmd(mc);
1603 
1604 	/* build a suitable I/O command (assumes 512-byte rounded transfers) */
1605 	mlxd = (struct mlxd_softc *)bp->b_dev->si_drv1;
1606 	driveno = mlxd->mlxd_drive - sc->mlx_sysdrive;
1607 	blkcount = (bp->b_bcount + MLX_BLKSIZE - 1) / MLX_BLKSIZE;
1608 
1609 	if ((bp->b_pblkno + blkcount) > sc->mlx_sysdrive[driveno].ms_size)
1610 	    device_printf(sc->mlx_dev, "I/O beyond end of unit (%u,%d > %u)\n",
1611 			  bp->b_pblkno, blkcount, sc->mlx_sysdrive[driveno].ms_size);
1612 
1613 	/*
1614 	 * Build the I/O command.  Note that the SG list type bits are set to zero,
1615 	 * denoting the format of SG list that we are using.
1616 	 */
1617 	mlx_make_type5(mc, cmd,
1618 		       blkcount & 0xff, 				/* xfer length low byte */
1619 		       (driveno << 3) | ((blkcount >> 8) & 0x07),	/* target and length high 3 bits */
1620 		       bp->b_pblkno,					/* physical block number */
1621 		       mc->mc_sgphys,					/* location of SG list */
1622 		       mc->mc_nsgent & 0x3f);				/* size of SG list (top 2 bits clear) */
1623 
1624 
1625 	/* try to give command to controller */
1626 	if (mlx_start(mc) != 0) {
1627 	    /* fail the command */
1628 	    mc->mc_status = MLX_STATUS_WEDGED;
1629 	    mlx_completeio(mc);
1630 	}
1631 	s = splbio();
1632     }
1633     splx(s);
1634     mlx_lock_clr(sc, MLX_LOCK_STARTING);
1635 }
1636 
1637 /********************************************************************************
1638  * Handle completion of an I/O command.
1639  */
1640 static void
1641 mlx_completeio(struct mlx_command *mc)
1642 {
1643     struct mlx_softc	*sc = mc->mc_sc;
1644     struct buf		*bp = (struct buf *)mc->mc_private;
1645     struct mlxd_softc	*mlxd = (struct mlxd_softc *)bp->b_dev->si_drv1;
1646 
1647     if (mc->mc_status != MLX_STATUS_OK) {	/* could be more verbose here? */
1648 	bp->b_error = EIO;
1649 	bp->b_flags |= B_ERROR;
1650 
1651 	switch(mc->mc_status) {
1652 	case MLX_STATUS_RDWROFFLINE:		/* system drive has gone offline */
1653 	    device_printf(mlxd->mlxd_dev, "drive offline\n");
1654 	    /* should signal this with a return code */
1655 	    mlxd->mlxd_drive->ms_state = MLX_SYSD_OFFLINE;
1656 	    break;
1657 
1658 	default:				/* other I/O error */
1659 	    device_printf(sc->mlx_dev, "I/O error - %s\n", mlx_diagnose_command(mc));
1660 #if 0
1661 	    device_printf(sc->mlx_dev, "  b_bcount %ld  blkcount %ld  b_pblkno %d\n",
1662 			  bp->b_bcount, bp->b_bcount / MLX_BLKSIZE, bp->b_pblkno);
1663 	    device_printf(sc->mlx_dev, "  %13D\n", mc->mc_mailbox, " ");
1664 #endif
1665 	    break;
1666 	}
1667     }
1668     mlx_releasecmd(mc);
1669     mlxd_intr(bp);
1670 }
1671 
1672 /********************************************************************************
1673  * Take a command from user-space and try to run it.
1674  */
1675 static int
1676 mlx_user_command(struct mlx_softc *sc, struct mlx_usercommand *mu)
1677 {
1678     struct mlx_command	*mc;
1679     void		*kbuf;
1680     int			error;
1681 
1682     kbuf = NULL;
1683     mc = NULL;
1684     error = ENOMEM;
1685     /* get a kernel buffer for the transfer */
1686     if (mu->mu_datasize > 0) {
1687 	if ((kbuf = malloc(mu->mu_datasize, M_DEVBUF, M_WAITOK)) == NULL)
1688 	    goto out;
1689 	if ((mu->mu_bufptr < 0) || (mu->mu_bufptr > (sizeof(mu->mu_command) < sizeof(u_int32_t)))) {
1690 	    error = EINVAL;
1691 	    goto out;
1692 	}
1693     }
1694     /* get ourselves a command buffer */
1695     if ((mc = mlx_alloccmd(sc)) == NULL)
1696 	goto out;
1697 
1698     /* copy the command and data */
1699     bcopy(mu->mu_command, mc->mc_mailbox, sizeof(mc->mc_mailbox));
1700     if ((mu->mu_datasize > 0) && ((error = copyin(mu->mu_buf, kbuf, mu->mu_datasize))))
1701 	goto out;
1702 
1703     /* get a command slot */
1704     if (mlx_getslot(mc))
1705 	goto out;
1706 
1707     /* map the command so the controller can see it */
1708     mc->mc_data = kbuf;
1709     mc->mc_length = mu->mu_datasize;
1710     mlx_mapcmd(mc);
1711 
1712     /* if there's a data buffer, fix up the command */
1713     if (mu->mu_datasize > 0) {
1714 	mc->mc_mailbox[mu->mu_bufptr    ] =  mc->mc_length        & 0xff;
1715 	mc->mc_mailbox[mu->mu_bufptr + 1] = (mc->mc_length >> 8)  & 0xff;
1716 	mc->mc_mailbox[mu->mu_bufptr + 2] = (mc->mc_length >> 16) & 0xff;
1717 	mc->mc_mailbox[mu->mu_bufptr + 3] = (mc->mc_length >> 24) & 0xff;
1718     }
1719 
1720     /* submit the command and wait */
1721     if ((error = mlx_wait_command(mc)) != 0)
1722 	goto out;
1723 
1724     /* copy out status and data */
1725     mu->mu_status = mc->mc_status;
1726     if ((mu->mu_datasize > 0) && ((error = copyout(kbuf, mu->mu_buf, mu->mu_datasize))))
1727 	goto out;
1728     error = 0;
1729 
1730  out:
1731     mlx_releasecmd(mc);
1732     if (kbuf != NULL)
1733 	free(kbuf, M_DEVBUF);
1734     return(error);
1735 }
1736 
1737 /********************************************************************************
1738  ********************************************************************************
1739                                                         Command I/O to Controller
1740  ********************************************************************************
1741  ********************************************************************************/
1742 
1743 /********************************************************************************
1744  * Find a free command slot for (mc).
1745  *
1746  * Don't hand out a slot to a normal-priority command unless there are at least
1747  * 4 slots free for priority commands.
1748  */
1749 static int
1750 mlx_getslot(struct mlx_command *mc)
1751 {
1752     struct mlx_softc	*sc = mc->mc_sc;
1753     int			s, slot, limit;
1754 
1755     debug("called  mc %p  sc %p", mc, sc);
1756 
1757     /* enforce slot-usage limit */
1758     limit = (mc->mc_flags & MLX_CMD_PRIORITY) ? sc->mlx_maxiop : sc->mlx_maxiop - 4;
1759     if (sc->mlx_busycmds > limit)
1760 	return(EBUSY);
1761 
1762     /*
1763      * Allocate an outstanding command slot
1764      *
1765      * XXX linear search is slow
1766      */
1767     s = splbio();
1768     for (slot = 0; slot < sc->mlx_maxiop; slot++) {
1769 	debug("try slot %d", slot);
1770 	if (sc->mlx_busycmd[slot] == NULL)
1771 	    break;
1772     }
1773     if (slot < sc->mlx_maxiop) {
1774 	sc->mlx_busycmd[slot] = mc;
1775 	sc->mlx_busycmds++;
1776     }
1777     splx(s);
1778 
1779     /* out of slots? */
1780     if (slot >= sc->mlx_maxiop)
1781 	return(EBUSY);
1782 
1783     debug("got slot %d", slot);
1784     mc->mc_slot = slot;
1785     return(0);
1786 }
1787 
1788 /********************************************************************************
1789  * Map/unmap (mc)'s data in the controller's addressable space.
1790  */
1791 static void
1792 mlx_setup_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
1793 {
1794     struct mlx_command	*mc = (struct mlx_command *)arg;
1795     struct mlx_softc	*sc = mc->mc_sc;
1796     struct mlx_sgentry	*sg;
1797     int			i;
1798 
1799     debug("called");
1800 
1801     /* get base address of s/g table */
1802     sg = sc->mlx_sgtable + (mc->mc_slot * MLX_NSEG);
1803 
1804     /* save s/g table information in command */
1805     mc->mc_nsgent = nsegments;
1806     mc->mc_sgphys = sc->mlx_sgbusaddr + (mc->mc_slot * MLX_NSEG * sizeof(struct mlx_sgentry));
1807     mc->mc_dataphys = segs[0].ds_addr;
1808 
1809     /* populate s/g table */
1810     for (i = 0; i < nsegments; i++, sg++) {
1811 	sg->sg_addr = segs[i].ds_addr;
1812 	sg->sg_count = segs[i].ds_len;
1813     }
1814 }
1815 
1816 static void
1817 mlx_mapcmd(struct mlx_command *mc)
1818 {
1819     struct mlx_softc	*sc = mc->mc_sc;
1820 
1821     debug("called");
1822 
1823     /* if the command involves data at all */
1824     if (mc->mc_data != NULL) {
1825 
1826 	/* map the data buffer into bus space and build the s/g list */
1827 	bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data, mc->mc_length,
1828 			mlx_setup_dmamap, mc, 0);
1829 	if (mc->mc_flags & MLX_CMD_DATAIN)
1830 	    bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_PREREAD);
1831 	if (mc->mc_flags & MLX_CMD_DATAOUT)
1832 	    bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_PREWRITE);
1833     }
1834 }
1835 
1836 static void
1837 mlx_unmapcmd(struct mlx_command *mc)
1838 {
1839     struct mlx_softc	*sc = mc->mc_sc;
1840 
1841     debug("called");
1842 
1843     /* if the command involved data at all */
1844     if (mc->mc_data != NULL) {
1845 
1846 	if (mc->mc_flags & MLX_CMD_DATAIN)
1847 	    bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTREAD);
1848 	if (mc->mc_flags & MLX_CMD_DATAOUT)
1849 	    bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTWRITE);
1850 
1851 	bus_dmamap_unload(sc->mlx_buffer_dmat, mc->mc_dmamap);
1852     }
1853 }
1854 
1855 /********************************************************************************
1856  * Try to deliver (mc) to the controller.
1857  *
1858  * Can be called at any interrupt level, with or without interrupts enabled.
1859  */
1860 static int
1861 mlx_start(struct mlx_command *mc)
1862 {
1863     struct mlx_softc	*sc = mc->mc_sc;
1864     int			i, s, done;
1865 
1866     debug("called");
1867 
1868     /* save the slot number as ident so we can handle this command when complete */
1869     mc->mc_mailbox[0x1] = mc->mc_slot;
1870 
1871     /* mark the command as currently being processed */
1872     mc->mc_status = MLX_STATUS_BUSY;
1873 
1874     /* set a default 60-second timeout  XXX tunable?  XXX not currently used */
1875     mc->mc_timeout = time_second + 60;
1876 
1877     /* spin waiting for the mailbox */
1878     for (i = 100000, done = 0; (i > 0) && !done; i--) {
1879 	s = splbio();
1880 	if (sc->mlx_tryqueue(sc, mc)) {
1881 	    done = 1;
1882 	    /* move command to work queue */
1883 	    TAILQ_INSERT_TAIL(&sc->mlx_work, mc, mc_link);
1884 	}
1885 	splx(s);	/* drop spl to allow completion interrupts */
1886     }
1887 
1888     /* command is enqueued */
1889     if (done)
1890 	return(0);
1891 
1892     /*
1893      * We couldn't get the controller to take the command.  Revoke the slot
1894      * that the command was given and return it with a bad status.
1895      */
1896     sc->mlx_busycmd[mc->mc_slot] = NULL;
1897     device_printf(sc->mlx_dev, "controller wedged (not taking commands)\n");
1898     mc->mc_status = MLX_STATUS_WEDGED;
1899     mlx_complete(sc);
1900     return(EIO);
1901 }
1902 
1903 /********************************************************************************
1904  * Poll the controller (sc) for completed commands.
1905  * Update command status and free slots for reuse.  If any slots were freed,
1906  * new commands may be posted.
1907  *
1908  * Returns nonzero if one or more commands were completed.
1909  */
1910 static int
1911 mlx_done(struct mlx_softc *sc)
1912 {
1913     struct mlx_command	*mc;
1914     int			s, result;
1915     u_int8_t		slot;
1916     u_int16_t		status;
1917 
1918     debug("called");
1919 
1920     result = 0;
1921 
1922     /* loop collecting completed commands */
1923     s = splbio();
1924     for (;;) {
1925 	/* poll for a completed command's identifier and status */
1926 	if (sc->mlx_findcomplete(sc, &slot, &status)) {
1927 	    result = 1;
1928 	    mc = sc->mlx_busycmd[slot];			/* find command */
1929 	    if (mc != NULL) {				/* paranoia */
1930 		if (mc->mc_status == MLX_STATUS_BUSY) {
1931 		    mc->mc_status = status;		/* save status */
1932 
1933 		    /* free slot for reuse */
1934 		    sc->mlx_busycmd[slot] = NULL;
1935 		    sc->mlx_busycmds--;
1936 		} else {
1937 		    device_printf(sc->mlx_dev, "duplicate done event for slot %d\n", slot);
1938 		}
1939 	    } else {
1940 		device_printf(sc->mlx_dev, "done event for nonbusy slot %d\n", slot);
1941 	    }
1942 	} else {
1943 	    break;
1944 	}
1945     }
1946 
1947     /* if we've completed any commands, try posting some more */
1948     if (result)
1949 	mlx_startio(sc);
1950 
1951     /* handle completion and timeouts */
1952     mlx_complete(sc);
1953 
1954     return(result);
1955 }
1956 
1957 /********************************************************************************
1958  * Perform post-completion processing for commands on (sc).
1959  */
1960 static void
1961 mlx_complete(struct mlx_softc *sc)
1962 {
1963     struct mlx_command	*mc, *nc;
1964     int			s, count;
1965 
1966     debug("called");
1967 
1968     /* avoid reentrancy  XXX might want to signal and request a restart */
1969     if (mlx_lock_tas(sc, MLX_LOCK_COMPLETING))
1970 	return;
1971 
1972     s = splbio();
1973     count = 0;
1974 
1975     /* scan the list of busy/done commands */
1976     mc = TAILQ_FIRST(&sc->mlx_work);
1977     while (mc != NULL) {
1978 	nc = TAILQ_NEXT(mc, mc_link);
1979 
1980 	/* XXX this is slightly bogus */
1981 	if (count++ > (sc->mlx_maxiop * 2))
1982 	    panic("mlx_work list corrupt!");
1983 
1984 	/* Command has been completed in some fashion */
1985 	if (mc->mc_status != MLX_STATUS_BUSY) {
1986 
1987 	    /* unmap the command's data buffer */
1988 	    mlx_unmapcmd(mc);
1989 	    /*
1990 	     * Does the command have a completion handler?
1991 	     */
1992 	    if (mc->mc_complete != NULL) {
1993 		/* remove from list and give to handler */
1994 		TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
1995 		mc->mc_complete(mc);
1996 
1997 		/*
1998 		 * Is there a sleeper waiting on this command?
1999 		 */
2000 	    } else if (mc->mc_private != NULL) {	/* sleeping caller wants to know about it */
2001 
2002 		/* remove from list and wake up sleeper */
2003 		TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
2004 		wakeup_one(mc->mc_private);
2005 
2006 		/*
2007 		 * Leave the command for a caller that's polling for it.
2008 		 */
2009 	    } else {
2010 	    }
2011 	}
2012 	mc = nc;
2013     }
2014     splx(s);
2015 
2016     mlx_lock_clr(sc, MLX_LOCK_COMPLETING);
2017 }
2018 
2019 /********************************************************************************
2020  ********************************************************************************
2021                                                         Command Buffer Management
2022  ********************************************************************************
2023  ********************************************************************************/
2024 
2025 /********************************************************************************
2026  * Get a new command buffer.
2027  *
2028  * This may return NULL in low-memory cases.
2029  *
2030  * Note that using malloc() is expensive (the command buffer is << 1 page) but
2031  * necessary if we are to be a loadable module before the zone allocator is fixed.
2032  *
2033  * If possible, we recycle a command buffer that's been used before.
2034  *
2035  * XXX Note that command buffers are not cleaned out - it is the caller's
2036  *     responsibility to ensure that all required fields are filled in before
2037  *     using a buffer.
2038  */
2039 static struct mlx_command *
2040 mlx_alloccmd(struct mlx_softc *sc)
2041 {
2042     struct mlx_command	*mc;
2043     int			error;
2044     int			s;
2045 
2046     debug("called");
2047 
2048     s = splbio();
2049     if ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL)
2050 	TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link);
2051     splx(s);
2052 
2053     /* allocate a new command buffer? */
2054     if (mc == NULL) {
2055 	mc = (struct mlx_command *)malloc(sizeof(*mc), M_DEVBUF, M_NOWAIT);
2056 	if (mc != NULL) {
2057 	    bzero(mc, sizeof(*mc));
2058 	    mc->mc_sc = sc;
2059 	    error = bus_dmamap_create(sc->mlx_buffer_dmat, 0, &mc->mc_dmamap);
2060 	    if (error) {
2061 		free(mc, M_DEVBUF);
2062 		return(NULL);
2063 	    }
2064 	}
2065     }
2066     return(mc);
2067 }
2068 
2069 /********************************************************************************
2070  * Release a command buffer for recycling.
2071  *
2072  * XXX It might be a good idea to limit the number of commands we save for reuse
2073  *     if it's shown that this list bloats out massively.
2074  */
2075 static void
2076 mlx_releasecmd(struct mlx_command *mc)
2077 {
2078     int		s;
2079 
2080     debug("called");
2081 
2082     s = splbio();
2083     TAILQ_INSERT_HEAD(&mc->mc_sc->mlx_freecmds, mc, mc_link);
2084     splx(s);
2085 }
2086 
2087 /********************************************************************************
2088  * Permanently discard a command buffer.
2089  */
2090 static void
2091 mlx_freecmd(struct mlx_command *mc)
2092 {
2093     struct mlx_softc	*sc = mc->mc_sc;
2094 
2095     debug("called");
2096 
2097     bus_dmamap_destroy(sc->mlx_buffer_dmat, mc->mc_dmamap);
2098     free(mc, M_DEVBUF);
2099 }
2100 
2101 
2102 /********************************************************************************
2103  ********************************************************************************
2104                                                 Type 3 interface accessor methods
2105  ********************************************************************************
2106  ********************************************************************************/
2107 
2108 /********************************************************************************
2109  * Try to give (mc) to the controller.  Returns 1 if successful, 0 on failure
2110  * (the controller is not ready to take a command).
2111  *
2112  * Must be called at splbio or in a fashion that prevents reentry.
2113  */
2114 static int
2115 mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2116 {
2117     int		i;
2118 
2119     debug("called");
2120 
2121     /* ready for our command? */
2122     if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_FULL)) {
2123 	/* copy mailbox data to window */
2124 	for (i = 0; i < 13; i++)
2125 	    MLX_V3_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
2126 
2127 	/* post command */
2128 	MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_FULL);
2129 	return(1);
2130     }
2131     return(0);
2132 }
2133 
2134 /********************************************************************************
2135  * See if a command has been completed, if so acknowledge its completion
2136  * and recover the slot number and status code.
2137  *
2138  * Must be called at splbio or in a fashion that prevents reentry.
2139  */
2140 static int
2141 mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2142 {
2143 
2144     debug("called");
2145 
2146     /* status available? */
2147     if (MLX_V3_GET_ODBR(sc) & MLX_V3_ODB_SAVAIL) {
2148 	*slot = MLX_V3_GET_STATUS_IDENT(sc);		/* get command identifier */
2149 	*status = MLX_V3_GET_STATUS(sc);		/* get status */
2150 
2151 	/* acknowledge completion */
2152 	MLX_V3_PUT_ODBR(sc, MLX_V3_ODB_SAVAIL);
2153 	MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_SACK);
2154 	return(1);
2155     }
2156     return(0);
2157 }
2158 
2159 /********************************************************************************
2160  * Enable/disable interrupts as requested. (No acknowledge required)
2161  *
2162  * Must be called at splbio or in a fashion that prevents reentry.
2163  */
2164 static void
2165 mlx_v3_intaction(struct mlx_softc *sc, int action)
2166 {
2167     debug("called");
2168 
2169     switch(action) {
2170     case MLX_INTACTION_DISABLE:
2171 	MLX_V3_PUT_IER(sc, 0);
2172 	sc->mlx_state &= ~MLX_STATE_INTEN;
2173 	break;
2174     case MLX_INTACTION_ENABLE:
2175 	MLX_V3_PUT_IER(sc, 1);
2176 	sc->mlx_state |= MLX_STATE_INTEN;
2177 	break;
2178     }
2179 }
2180 
2181 
2182 /********************************************************************************
2183  ********************************************************************************
2184                                                 Type 4 interface accessor methods
2185  ********************************************************************************
2186  ********************************************************************************/
2187 
2188 /********************************************************************************
2189  * Try to give (mc) to the controller.  Returns 1 if successful, 0 on failure
2190  * (the controller is not ready to take a command).
2191  *
2192  * Must be called at splbio or in a fashion that prevents reentry.
2193  */
2194 static int
2195 mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2196 {
2197     int		i;
2198 
2199     debug("called");
2200 
2201     /* ready for our command? */
2202     if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_FULL)) {
2203 	/* copy mailbox data to window */
2204 	for (i = 0; i < 13; i++)
2205 	    MLX_V4_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
2206 
2207 	/* post command */
2208 	MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_HWMBOX_CMD);
2209 	return(1);
2210     }
2211     return(0);
2212 }
2213 
2214 /********************************************************************************
2215  * See if a command has been completed, if so acknowledge its completion
2216  * and recover the slot number and status code.
2217  *
2218  * Must be called at splbio or in a fashion that prevents reentry.
2219  */
2220 static int
2221 mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2222 {
2223 
2224     debug("called");
2225 
2226     /* status available? */
2227     if (MLX_V4_GET_ODBR(sc) & MLX_V4_ODB_HWSAVAIL) {
2228 	*slot = MLX_V4_GET_STATUS_IDENT(sc);		/* get command identifier */
2229 	*status = MLX_V4_GET_STATUS(sc);		/* get status */
2230 
2231 	/* acknowledge completion */
2232 	MLX_V4_PUT_ODBR(sc, MLX_V4_ODB_HWMBOX_ACK);
2233 	MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_SACK);
2234 	return(1);
2235     }
2236     return(0);
2237 }
2238 
2239 /********************************************************************************
2240  * Enable/disable interrupts as requested.
2241  *
2242  * Must be called at splbio or in a fashion that prevents reentry.
2243  */
2244 static void
2245 mlx_v4_intaction(struct mlx_softc *sc, int action)
2246 {
2247     debug("called");
2248 
2249     switch(action) {
2250     case MLX_INTACTION_DISABLE:
2251 	MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK | MLX_V4_IER_DISINT);
2252 	sc->mlx_state &= ~MLX_STATE_INTEN;
2253 	break;
2254     case MLX_INTACTION_ENABLE:
2255 	MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK & ~MLX_V4_IER_DISINT);
2256 	sc->mlx_state |= MLX_STATE_INTEN;
2257 	break;
2258     }
2259 }
2260 
2261 
2262 /********************************************************************************
2263  ********************************************************************************
2264                                                 Type 5 interface accessor methods
2265  ********************************************************************************
2266  ********************************************************************************/
2267 
2268 /********************************************************************************
2269  * Try to give (mc) to the controller.  Returns 1 if successful, 0 on failure
2270  * (the controller is not ready to take a command).
2271  *
2272  * Must be called at splbio or in a fashion that prevents reentry.
2273  */
2274 static int
2275 mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2276 {
2277     int		i;
2278 
2279     debug("called");
2280 
2281     /* ready for our command? */
2282     if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_EMPTY) {
2283 	/* copy mailbox data to window */
2284 	for (i = 0; i < 13; i++)
2285 	    MLX_V5_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
2286 
2287 	/* post command */
2288 	MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_HWMBOX_CMD);
2289 	return(1);
2290     }
2291     return(0);
2292 }
2293 
2294 /********************************************************************************
2295  * See if a command has been completed, if so acknowledge its completion
2296  * and recover the slot number and status code.
2297  *
2298  * Must be called at splbio or in a fashion that prevents reentry.
2299  */
2300 static int
2301 mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2302 {
2303 
2304     debug("called");
2305 
2306     /* status available? */
2307     if (MLX_V5_GET_ODBR(sc) & MLX_V5_ODB_HWSAVAIL) {
2308 	*slot = MLX_V5_GET_STATUS_IDENT(sc);		/* get command identifier */
2309 	*status = MLX_V5_GET_STATUS(sc);		/* get status */
2310 
2311 	/* acknowledge completion */
2312 	MLX_V5_PUT_ODBR(sc, MLX_V5_ODB_HWMBOX_ACK);
2313 	MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_SACK);
2314 	return(1);
2315     }
2316     return(0);
2317 }
2318 
2319 /********************************************************************************
2320  * Enable/disable interrupts as requested.
2321  *
2322  * Must be called at splbio or in a fashion that prevents reentry.
2323  */
2324 static void
2325 mlx_v5_intaction(struct mlx_softc *sc, int action)
2326 {
2327     debug("called");
2328 
2329     switch(action) {
2330     case MLX_INTACTION_DISABLE:
2331 	MLX_V5_PUT_IER(sc, MLX_V5_IER_DISINT);
2332 	sc->mlx_state &= ~MLX_STATE_INTEN;
2333 	break;
2334     case MLX_INTACTION_ENABLE:
2335 	MLX_V5_PUT_IER(sc, 0);
2336 	sc->mlx_state |= MLX_STATE_INTEN;
2337 	break;
2338     }
2339 }
2340 
2341 
2342 /********************************************************************************
2343  ********************************************************************************
2344                                                                         Debugging
2345  ********************************************************************************
2346  ********************************************************************************/
2347 
2348 /********************************************************************************
2349  * Return a status message describing (mc)
2350  */
2351 static char *mlx_status_messages[] = {
2352     "normal completion",			/* 00 */
2353     "irrecoverable data error",			/* 01 */
2354     "drive does not exist, or is offline",	/* 02 */
2355     "attempt to write beyond end of drive",	/* 03 */
2356     "bad data encountered",			/* 04 */
2357     "invalid log entry request",		/* 05 */
2358     "attempt to rebuild online drive",		/* 06 */
2359     "new disk failed during rebuild",		/* 07 */
2360     "invalid channel/target",			/* 08 */
2361     "rebuild/check already in progress",	/* 09 */
2362     "one or more disks are dead",		/* 10 */
2363     "invalid or non-redundant drive",		/* 11 */
2364     "channel is busy",				/* 12 */
2365     "channel is not stopped",			/* 13 */
2366 };
2367 
2368 static struct
2369 {
2370     int		command;
2371     u_int16_t	status;
2372     int		msg;
2373 } mlx_messages[] = {
2374     {MLX_CMD_READOLDSG,		0x0001,	 1},
2375     {MLX_CMD_READOLDSG,		0x0002,	 1},
2376     {MLX_CMD_READOLDSG,		0x0105,	 3},
2377     {MLX_CMD_READOLDSG,		0x010c,	 4},
2378     {MLX_CMD_WRITEOLDSG,	0x0001,	 1},
2379     {MLX_CMD_WRITEOLDSG,	0x0002,	 1},
2380     {MLX_CMD_WRITEOLDSG,	0x0105,	 3},
2381     {MLX_CMD_LOGOP,		0x0105,	 5},
2382     {MLX_CMD_REBUILDASYNC,	0x0002,  6},
2383     {MLX_CMD_REBUILDASYNC,	0x0004,  7},
2384     {MLX_CMD_REBUILDASYNC,	0x0105,  8},
2385     {MLX_CMD_REBUILDASYNC,	0x0106,  9},
2386     {MLX_CMD_CHECKASYNC,	0x0002, 10},
2387     {MLX_CMD_CHECKASYNC,	0x0105, 11},
2388     {MLX_CMD_CHECKASYNC,	0x0106,  9},
2389     {MLX_CMD_STOPCHANNEL,	0x0106, 12},
2390     {MLX_CMD_STOPCHANNEL,	0x0105,  8},
2391     {MLX_CMD_STARTCHANNEL,	0x0005, 13},
2392     {MLX_CMD_STARTCHANNEL,	0x0105,  8},
2393     {-1, 0, 0}
2394 };
2395 
2396 static char *
2397 mlx_diagnose_command(struct mlx_command *mc)
2398 {
2399     static char	unkmsg[80];
2400     int		i;
2401 
2402     /* look up message in table */
2403     for (i = 0; mlx_messages[i].command != -1; i++)
2404 	if ((mc->mc_mailbox[0] == mlx_messages[i].command) &&
2405 	    (mc->mc_status == mlx_messages[i].status))
2406 	    return(mlx_status_messages[mlx_messages[i].msg]);
2407 
2408     sprintf(unkmsg, "unknown response 0x%x for command 0x%x", (int)mc->mc_status, (int)mc->mc_mailbox[0]);
2409     return(unkmsg);
2410 }
2411 
2412 /*******************************************************************************
2413  * Return a string describing the controller (hwid)
2414  */
2415 static struct
2416 {
2417     int		hwid;
2418     char	*name;
2419 } mlx_controller_names[] = {
2420     {0x01,	"960P/PD"},
2421     {0x02,	"960PL"},
2422     {0x10,	"960PG"},
2423     {0x11,	"960PJ"},
2424     {0x16,	"960PTL"},
2425     {0x20,	"1164P"},
2426     {-1, NULL}
2427 };
2428 
2429 static char *
2430 mlx_name_controller(u_int32_t hwid)
2431 {
2432     static char		buf[80];
2433     char		*model;
2434     int			nchn, i;
2435 
2436     for (i = 0, model = NULL; mlx_controller_names[i].name != NULL; i++) {
2437 	if ((hwid & 0xff) == mlx_controller_names[i].hwid) {
2438 	    model = mlx_controller_names[i].name;
2439 	    break;
2440 	}
2441     }
2442     if (model == NULL) {
2443 	sprintf(buf, " model 0x%x", hwid & 0xff);
2444 	model = buf;
2445     }
2446     nchn = (hwid >> 8) & 0xff;
2447     sprintf(buf, "DAC%s, %d channel%s", model, nchn, nchn > 1 ? "s" : "");
2448     return(buf);
2449 }
2450 
2451 /********************************************************************************
2452  ********************************************************************************
2453                                                                 Utility Functions
2454  ********************************************************************************
2455  ********************************************************************************/
2456 
2457 /********************************************************************************
2458  * Find the disk whose unit number is (unit) on this controller
2459  */
2460 static struct mlx_sysdrive *
2461 mlx_findunit(struct mlx_softc *sc, int unit)
2462 {
2463     int		i;
2464 
2465     /* search system drives */
2466     for (i = 0; i < MLX_MAXDRIVES; i++) {
2467 	/* is this one attached? */
2468 	if (sc->mlx_sysdrive[i].ms_disk != 0) {
2469 	    /* is this the one? */
2470 	    if (unit == device_get_unit(sc->mlx_sysdrive[i].ms_disk))
2471 		return(&sc->mlx_sysdrive[i]);
2472 	}
2473     }
2474     return(NULL);
2475 }
2476