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