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