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