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