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