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