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