xref: /dragonfly/sys/dev/raid/mlx/mlx.c (revision 2d8a3be7)
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.6 2003/08/07 21:17:09 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 		/* autoq */	0,
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     /* destroy control device */
212     if (sc->mlx_dev_t != (dev_t)NULL)
213 	destroy_dev(sc->mlx_dev_t);
214 }
215 
216 /********************************************************************************
217  * Map the scatter/gather table into bus space
218  */
219 static void
220 mlx_dma_map_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error)
221 {
222     struct mlx_softc	*sc = (struct mlx_softc *)arg;
223 
224     debug_called(1);
225 
226     /* save base of s/g table's address in bus space */
227     sc->mlx_sgbusaddr = segs->ds_addr;
228 }
229 
230 static int
231 mlx_sglist_map(struct mlx_softc *sc)
232 {
233     size_t	segsize;
234     int		error, ncmd;
235 
236     debug_called(1);
237 
238     /* destroy any existing mappings */
239     if (sc->mlx_sgtable)
240 	bus_dmamem_free(sc->mlx_sg_dmat, sc->mlx_sgtable, sc->mlx_sg_dmamap);
241     if (sc->mlx_sg_dmat)
242 	bus_dma_tag_destroy(sc->mlx_sg_dmat);
243 
244     /*
245      * Create a single tag describing a region large enough to hold all of
246      * the s/g lists we will need.  If we're called early on, we don't know how
247      * many commands we're going to be asked to support, so only allocate enough
248      * for a couple.
249      */
250     if (sc->mlx_enq2 == NULL) {
251 	ncmd = 2;
252     } else {
253 	ncmd = sc->mlx_enq2->me_max_commands;
254     }
255     segsize = sizeof(struct mlx_sgentry) * MLX_NSEG * ncmd;
256     error = bus_dma_tag_create(sc->mlx_parent_dmat, 	/* parent */
257 			       1, 0, 			/* alignment, boundary */
258 			       BUS_SPACE_MAXADDR,	/* lowaddr */
259 			       BUS_SPACE_MAXADDR, 	/* highaddr */
260 			       NULL, NULL, 		/* filter, filterarg */
261 			       segsize, 1,		/* maxsize, nsegments */
262 			       BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
263 			       0,			/* flags */
264 			       &sc->mlx_sg_dmat);
265     if (error != 0) {
266 	device_printf(sc->mlx_dev, "can't allocate scatter/gather DMA tag\n");
267 	return(ENOMEM);
268     }
269 
270     /*
271      * Allocate enough s/g maps for all commands and permanently map them into
272      * controller-visible space.
273      *
274      * XXX this assumes we can get enough space for all the s/g maps in one
275      * contiguous slab.  We may need to switch to a more complex arrangement where
276      * we allocate in smaller chunks and keep a lookup table from slot to bus address.
277      */
278     error = bus_dmamem_alloc(sc->mlx_sg_dmat, (void **)&sc->mlx_sgtable, BUS_DMA_NOWAIT, &sc->mlx_sg_dmamap);
279     if (error) {
280 	device_printf(sc->mlx_dev, "can't allocate s/g table\n");
281 	return(ENOMEM);
282     }
283     bus_dmamap_load(sc->mlx_sg_dmat, sc->mlx_sg_dmamap, sc->mlx_sgtable, segsize, mlx_dma_map_sg, sc, 0);
284     return(0);
285 }
286 
287 /********************************************************************************
288  * Initialise the controller and softc
289  */
290 int
291 mlx_attach(struct mlx_softc *sc)
292 {
293     struct mlx_enquiry_old	*meo;
294     int				rid, error, fwminor, hscode, hserror, hsparam1, hsparam2, hsmsg;
295 
296     debug_called(1);
297 
298     /*
299      * Initialise per-controller queues.
300      */
301     TAILQ_INIT(&sc->mlx_work);
302     TAILQ_INIT(&sc->mlx_freecmds);
303     MLX_BIO_QINIT(sc->mlx_bioq);
304 
305     /*
306      * Select accessor methods based on controller interface type.
307      */
308     switch(sc->mlx_iftype) {
309     case MLX_IFTYPE_2:
310     case MLX_IFTYPE_3:
311 	sc->mlx_tryqueue	= mlx_v3_tryqueue;
312 	sc->mlx_findcomplete	= mlx_v3_findcomplete;
313 	sc->mlx_intaction	= mlx_v3_intaction;
314 	sc->mlx_fw_handshake	= mlx_v3_fw_handshake;
315 	break;
316     case MLX_IFTYPE_4:
317 	sc->mlx_tryqueue	= mlx_v4_tryqueue;
318 	sc->mlx_findcomplete	= mlx_v4_findcomplete;
319 	sc->mlx_intaction	= mlx_v4_intaction;
320 	sc->mlx_fw_handshake	= mlx_v4_fw_handshake;
321 	break;
322     case MLX_IFTYPE_5:
323 	sc->mlx_tryqueue	= mlx_v5_tryqueue;
324 	sc->mlx_findcomplete	= mlx_v5_findcomplete;
325 	sc->mlx_intaction	= mlx_v5_intaction;
326 	sc->mlx_fw_handshake	= mlx_v5_fw_handshake;
327 	break;
328     default:
329 	mlx_free(sc);
330 	return(ENXIO);		/* should never happen */
331     }
332 
333     /* disable interrupts before we start talking to the controller */
334     sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
335 
336     /*
337      * Wait for the controller to come ready, handshake with the firmware if required.
338      * This is typically only necessary on platforms where the controller BIOS does not
339      * run.
340      */
341     hsmsg = 0;
342     DELAY(1000);
343     while ((hscode = sc->mlx_fw_handshake(sc, &hserror, &hsparam1, &hsparam2)) != 0) {
344 	/* report first time around... */
345 	if (hsmsg == 0) {
346 	    device_printf(sc->mlx_dev, "controller initialisation in progress...\n");
347 	    hsmsg = 1;
348 	}
349 	/* did we get a real message? */
350 	if (hscode == 2) {
351 	    hscode = mlx_fw_message(sc, hserror, hsparam1, hsparam2);
352 	    /* fatal initialisation error? */
353 	    if (hscode != 0) {
354 		mlx_free(sc);
355 		return(ENXIO);
356 	    }
357 	}
358     }
359     if (hsmsg == 1)
360 	device_printf(sc->mlx_dev, "initialisation complete.\n");
361 
362     /*
363      * Allocate and connect our interrupt.
364      */
365     rid = 0;
366     sc->mlx_irq = bus_alloc_resource(sc->mlx_dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);
367     if (sc->mlx_irq == NULL) {
368 	device_printf(sc->mlx_dev, "can't allocate interrupt\n");
369 	mlx_free(sc);
370 	return(ENXIO);
371     }
372     error = bus_setup_intr(sc->mlx_dev, sc->mlx_irq, INTR_TYPE_BIO | INTR_ENTROPY,  mlx_intr, sc, &sc->mlx_intr);
373     if (error) {
374 	device_printf(sc->mlx_dev, "can't set up interrupt\n");
375 	mlx_free(sc);
376 	return(ENXIO);
377     }
378 
379     /*
380      * Create DMA tag for mapping buffers into controller-addressable space.
381      */
382     error = bus_dma_tag_create(sc->mlx_parent_dmat, 		/* parent */
383 			       1, 0, 				/* alignment, boundary */
384 			       BUS_SPACE_MAXADDR,		/* lowaddr */
385 			       BUS_SPACE_MAXADDR, 		/* highaddr */
386 			       NULL, NULL, 			/* filter, filterarg */
387 			       MAXBSIZE, MLX_NSEG,		/* maxsize, nsegments */
388 			       BUS_SPACE_MAXSIZE_32BIT,		/* maxsegsize */
389 			       0,				/* flags */
390 			       &sc->mlx_buffer_dmat);
391     if (error != 0) {
392 	device_printf(sc->mlx_dev, "can't allocate buffer DMA tag\n");
393 	mlx_free(sc);
394 	return(ENOMEM);
395     }
396 
397     /*
398      * Create some initial scatter/gather mappings so we can run the probe commands.
399      */
400     error = mlx_sglist_map(sc);
401     if (error != 0) {
402 	device_printf(sc->mlx_dev, "can't make initial s/g list mapping\n");
403 	mlx_free(sc);
404 	return(error);
405     }
406 
407     /*
408      * We don't (yet) know where the event log is up to.
409      */
410     sc->mlx_currevent = -1;
411 
412     /*
413      * Obtain controller feature information
414      */
415     if ((sc->mlx_enq2 = mlx_enquire(sc, MLX_CMD_ENQUIRY2, sizeof(struct mlx_enquiry2), NULL)) == NULL) {
416 	device_printf(sc->mlx_dev, "ENQUIRY2 failed\n");
417 	mlx_free(sc);
418 	return(ENXIO);
419     }
420 
421     /*
422      * Do quirk/feature related things.
423      */
424     fwminor = (sc->mlx_enq2->me_firmware_id >> 8) & 0xff;
425     switch(sc->mlx_iftype) {
426     case MLX_IFTYPE_2:
427 	/* These controllers don't report the firmware version in the ENQUIRY2 response */
428 	if ((meo = mlx_enquire(sc, MLX_CMD_ENQUIRY_OLD, sizeof(struct mlx_enquiry_old), NULL)) == NULL) {
429 	    device_printf(sc->mlx_dev, "ENQUIRY_OLD failed\n");
430 	    mlx_free(sc);
431 	    return(ENXIO);
432 	}
433 	sc->mlx_enq2->me_firmware_id = ('0' << 24) | (0 << 16) | (meo->me_fwminor << 8) | meo->me_fwmajor;
434 	free(meo, M_DEVBUF);
435 
436 	/* XXX require 2.42 or better (PCI) or 2.14 or better (EISA) */
437 	if (meo->me_fwminor < 42) {
438 	    device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
439 	    device_printf(sc->mlx_dev, " *** WARNING *** Use revision 2.42 or later\n");
440 	}
441 	break;
442     case MLX_IFTYPE_3:
443 	/* XXX certify 3.52? */
444 	if (fwminor < 51) {
445 	    device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
446 	    device_printf(sc->mlx_dev, " *** WARNING *** Use revision 3.51 or later\n");
447 	}
448 	break;
449     case MLX_IFTYPE_4:
450 	/* XXX certify firmware versions? */
451 	if (fwminor < 6) {
452 	    device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
453 	    device_printf(sc->mlx_dev, " *** WARNING *** Use revision 4.06 or later\n");
454 	}
455 	break;
456     case MLX_IFTYPE_5:
457 	if (fwminor < 7) {
458 	    device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
459 	    device_printf(sc->mlx_dev, " *** WARNING *** Use revision 5.07 or later\n");
460 	}
461 	break;
462     default:
463 	mlx_free(sc);
464 	return(ENXIO);		/* should never happen */
465     }
466 
467     /*
468      * Create the final scatter/gather mappings now that we have characterised the controller.
469      */
470     error = mlx_sglist_map(sc);
471     if (error != 0) {
472 	device_printf(sc->mlx_dev, "can't make final s/g list mapping\n");
473 	mlx_free(sc);
474 	return(error);
475     }
476 
477     /*
478      * No user-requested background operation is in progress.
479      */
480     sc->mlx_background = 0;
481     sc->mlx_rebuildstat.rs_code = MLX_REBUILDSTAT_IDLE;
482 
483     /*
484      * Create the control device.
485      */
486     sc->mlx_dev_t = make_dev(&mlx_cdevsw, device_get_unit(sc->mlx_dev), UID_ROOT, GID_OPERATOR,
487 			     S_IRUSR | S_IWUSR, "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     /* allocate the response structure */
1202     if ((result = malloc(/*sizeof(struct mlx_eventlog_entry)*/1024, M_DEVBUF, M_NOWAIT)) == NULL)
1203 	goto out;
1204     /* get a command slot */
1205     if (mlx_getslot(mc))
1206 	goto out;
1207 
1208     /* map the command so the controller can see it */
1209     mc->mc_data = result;
1210     mc->mc_length = /*sizeof(struct mlx_eventlog_entry)*/1024;
1211     mlx_mapcmd(mc);
1212 
1213     /* build the command to get one entry */
1214     mlx_make_type3(mc, MLX_CMD_LOGOP, MLX_LOGOP_GET, 1, sc->mlx_lastevent, 0, 0, mc->mc_dataphys, 0);
1215     mc->mc_complete = mlx_periodic_eventlog_respond;
1216     mc->mc_private = mc;
1217 
1218     /* start the command */
1219     if ((error = mlx_start(mc)) != 0)
1220 	goto out;
1221 
1222     error = 0;			/* success */
1223  out:
1224     if (error != 0) {
1225 	if (mc != NULL)
1226 	    mlx_releasecmd(mc);
1227 	if (result != NULL)
1228 	    free(result, M_DEVBUF);
1229     }
1230 }
1231 
1232 /********************************************************************************
1233  * Handle the result of polling for a log message, generate diagnostic output.
1234  * If this wasn't the last message waiting for us, we'll go collect another.
1235  */
1236 static char *mlx_sense_messages[] = {
1237     "because write recovery failed",
1238     "because of SCSI bus reset failure",
1239     "because of double check condition",
1240     "because it was removed",
1241     "because of gross error on SCSI chip",
1242     "because of bad tag returned from drive",
1243     "because of timeout on SCSI command",
1244     "because of reset SCSI command issued from system",
1245     "because busy or parity error count exceeded limit",
1246     "because of 'kill drive' command from system",
1247     "because of selection timeout",
1248     "due to SCSI phase sequence error",
1249     "due to unknown status"
1250 };
1251 
1252 static void
1253 mlx_periodic_eventlog_respond(struct mlx_command *mc)
1254 {
1255     struct mlx_softc		*sc = mc->mc_sc;
1256     struct mlx_eventlog_entry	*el = (struct mlx_eventlog_entry *)mc->mc_data;
1257     char			*reason;
1258 
1259     debug_called(1);
1260 
1261     sc->mlx_lastevent++;		/* next message... */
1262     if (mc->mc_status == 0) {
1263 
1264 	/* handle event log message */
1265 	switch(el->el_type) {
1266 	    /*
1267 	     * This is the only sort of message we understand at the moment.
1268 	     * The tests here are probably incomplete.
1269 	     */
1270 	case MLX_LOGMSG_SENSE:	/* sense data */
1271 	    /* Mylex vendor-specific message indicating a drive was killed? */
1272 	    if ((el->el_sensekey == 9) &&
1273 		(el->el_asc == 0x80)) {
1274 		if (el->el_asq < (sizeof(mlx_sense_messages) / sizeof(mlx_sense_messages[0]))) {
1275 		    reason = mlx_sense_messages[el->el_asq];
1276 		} else {
1277 		    reason = "for unknown reason";
1278 		}
1279 		device_printf(sc->mlx_dev, "physical drive %d:%d killed %s\n",
1280 			      el->el_channel, el->el_target, reason);
1281 	    }
1282 	    /* SCSI drive was reset? */
1283 	    if ((el->el_sensekey == 6) && (el->el_asc == 0x29)) {
1284 		device_printf(sc->mlx_dev, "physical drive %d:%d reset\n",
1285 			      el->el_channel, el->el_target);
1286 	    }
1287 	    /* SCSI drive error? */
1288 	    if (!((el->el_sensekey == 0) ||
1289 		  ((el->el_sensekey == 2) &&
1290 		   (el->el_asc == 0x04) &&
1291 		   ((el->el_asq == 0x01) ||
1292 		    (el->el_asq == 0x02))))) {
1293 		device_printf(sc->mlx_dev, "physical drive %d:%d error log: sense = %d asc = %x asq = %x\n",
1294 			      el->el_channel, el->el_target, el->el_sensekey, el->el_asc, el->el_asq);
1295 		device_printf(sc->mlx_dev, "  info %4D csi %4D\n", el->el_information, ":", el->el_csi, ":");
1296 	    }
1297 	    break;
1298 
1299 	default:
1300 	    device_printf(sc->mlx_dev, "unknown log message type 0x%x\n", el->el_type);
1301 	    break;
1302 	}
1303     } else {
1304 	device_printf(sc->mlx_dev, "error reading message log - %s\n", mlx_diagnose_command(mc));
1305 	/* give up on all the outstanding messages, as we may have come unsynched */
1306 	sc->mlx_lastevent = sc->mlx_currevent;
1307     }
1308 
1309     /* dispose of command and data */
1310     free(mc->mc_data, M_DEVBUF);
1311     mlx_releasecmd(mc);
1312 
1313     /* is there another message to obtain? */
1314     if (sc->mlx_lastevent != sc->mlx_currevent) {
1315 	mlx_periodic_eventlog_poll(sc);
1316     } else {
1317 	/* clear log-busy status */
1318 	atomic_clear_int(&sc->mlx_flags, MLX_EVENTLOG_BUSY);
1319     }
1320 }
1321 
1322 /********************************************************************************
1323  * Handle check/rebuild operations in progress.
1324  */
1325 static void
1326 mlx_periodic_rebuild(struct mlx_command *mc)
1327 {
1328     struct mlx_softc		*sc = mc->mc_sc;
1329     struct mlx_rebuild_status	*mr = (struct mlx_rebuild_status *)mc->mc_data;
1330 
1331     switch(mc->mc_status) {
1332     case 0:				/* operation running, update stats */
1333 	sc->mlx_rebuildstat = *mr;
1334 
1335 	/* spontaneous rebuild/check? */
1336 	if (sc->mlx_background == 0) {
1337 	    sc->mlx_background = MLX_BACKGROUND_SPONTANEOUS;
1338 	    device_printf(sc->mlx_dev, "background check/rebuild operation started\n");
1339 	}
1340 	break;
1341 
1342     case 0x0105:			/* nothing running, finalise stats and report */
1343 	switch(sc->mlx_background) {
1344 	case MLX_BACKGROUND_CHECK:
1345 	    device_printf(sc->mlx_dev, "consistency check completed\n");	/* XXX print drive? */
1346 	    break;
1347 	case MLX_BACKGROUND_REBUILD:
1348 	    device_printf(sc->mlx_dev, "drive rebuild completed\n");	/* XXX print channel/target? */
1349 	    break;
1350 	case MLX_BACKGROUND_SPONTANEOUS:
1351 	default:
1352 	    /* if we have previously been non-idle, report the transition */
1353 	    if (sc->mlx_rebuildstat.rs_code != MLX_REBUILDSTAT_IDLE) {
1354 		device_printf(sc->mlx_dev, "background check/rebuild operation completed\n");
1355 	    }
1356 	}
1357 	sc->mlx_background = 0;
1358 	sc->mlx_rebuildstat.rs_code = MLX_REBUILDSTAT_IDLE;
1359 	break;
1360     }
1361     free(mc->mc_data, M_DEVBUF);
1362     mlx_releasecmd(mc);
1363 }
1364 
1365 /********************************************************************************
1366  ********************************************************************************
1367                                                                     Channel Pause
1368  ********************************************************************************
1369  ********************************************************************************/
1370 
1371 /********************************************************************************
1372  * It's time to perform a channel pause action for (sc), either start or stop
1373  * the pause.
1374  */
1375 static void
1376 mlx_pause_action(struct mlx_softc *sc)
1377 {
1378     struct mlx_command	*mc;
1379     int			failsafe, i, command;
1380 
1381     /* What are we doing here? */
1382     if (sc->mlx_pause.mp_when == 0) {
1383 	command = MLX_CMD_STARTCHANNEL;
1384 	failsafe = 0;
1385 
1386     } else {
1387 	command = MLX_CMD_STOPCHANNEL;
1388 
1389 	/*
1390 	 * Channels will always start again after the failsafe period,
1391 	 * which is specified in multiples of 30 seconds.
1392 	 * This constrains us to a maximum pause of 450 seconds.
1393 	 */
1394 	failsafe = ((sc->mlx_pause.mp_howlong - time_second) + 5) / 30;
1395 	if (failsafe > 0xf) {
1396 	    failsafe = 0xf;
1397 	    sc->mlx_pause.mp_howlong = time_second + (0xf * 30) - 5;
1398 	}
1399     }
1400 
1401     /* build commands for every channel requested */
1402     for (i = 0; i < sc->mlx_enq2->me_actual_channels; i++) {
1403 	if ((1 << i) & sc->mlx_pause.mp_which) {
1404 
1405 	    /* get ourselves a command buffer */
1406 	    if ((mc = mlx_alloccmd(sc)) == NULL)
1407 		goto fail;
1408 	    /* get a command slot */
1409 	    mc->mc_flags |= MLX_CMD_PRIORITY;
1410 	    if (mlx_getslot(mc))
1411 		goto fail;
1412 
1413 	    /* build the command */
1414 	    mlx_make_type2(mc, command, (failsafe << 4) | i, 0, 0, 0, 0, 0, 0, 0);
1415 	    mc->mc_complete = mlx_pause_done;
1416 	    mc->mc_private = sc;		/* XXX not needed */
1417 	    if (mlx_start(mc))
1418 		goto fail;
1419 	    /* command submitted OK */
1420 	    return;
1421 
1422 	fail:
1423 	    device_printf(sc->mlx_dev, "%s failed for channel %d\n",
1424 			  command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", i);
1425 	    if (mc != NULL)
1426 		mlx_releasecmd(mc);
1427 	}
1428     }
1429 }
1430 
1431 static void
1432 mlx_pause_done(struct mlx_command *mc)
1433 {
1434     struct mlx_softc	*sc = mc->mc_sc;
1435     int			command = mc->mc_mailbox[0];
1436     int			channel = mc->mc_mailbox[2] & 0xf;
1437 
1438     if (mc->mc_status != 0) {
1439 	device_printf(sc->mlx_dev, "%s command failed - %s\n",
1440 		      command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", mlx_diagnose_command(mc));
1441     } else if (command == MLX_CMD_STOPCHANNEL) {
1442 	device_printf(sc->mlx_dev, "channel %d pausing for %ld seconds\n",
1443 		      channel, (long)(sc->mlx_pause.mp_howlong - time_second));
1444     } else {
1445 	device_printf(sc->mlx_dev, "channel %d resuming\n", channel);
1446     }
1447     mlx_releasecmd(mc);
1448 }
1449 
1450 /********************************************************************************
1451  ********************************************************************************
1452                                                                Command Submission
1453  ********************************************************************************
1454  ********************************************************************************/
1455 
1456 /********************************************************************************
1457  * Perform an Enquiry command using a type-3 command buffer and a return a single
1458  * linear result buffer.  If the completion function is specified, it will
1459  * be called with the completed command (and the result response will not be
1460  * valid until that point).  Otherwise, the command will either be busy-waited
1461  * for (interrupts not enabled), or slept for.
1462  */
1463 static void *
1464 mlx_enquire(struct mlx_softc *sc, int command, size_t bufsize, void (* complete)(struct mlx_command *mc))
1465 {
1466     struct mlx_command	*mc;
1467     void		*result;
1468     int			error;
1469 
1470     debug_called(1);
1471 
1472     /* get ourselves a command buffer */
1473     error = 1;
1474     result = NULL;
1475     if ((mc = mlx_alloccmd(sc)) == NULL)
1476 	goto out;
1477     /* allocate the response structure */
1478     if ((result = malloc(bufsize, M_DEVBUF, M_NOWAIT)) == NULL)
1479 	goto out;
1480     /* get a command slot */
1481     mc->mc_flags |= MLX_CMD_PRIORITY | MLX_CMD_DATAOUT;
1482     if (mlx_getslot(mc))
1483 	goto out;
1484 
1485     /* map the command so the controller can see it */
1486     mc->mc_data = result;
1487     mc->mc_length = bufsize;
1488     mlx_mapcmd(mc);
1489 
1490     /* build an enquiry command */
1491     mlx_make_type2(mc, command, 0, 0, 0, 0, 0, 0, mc->mc_dataphys, 0);
1492 
1493     /* do we want a completion callback? */
1494     if (complete != NULL) {
1495 	mc->mc_complete = complete;
1496 	mc->mc_private = mc;
1497 	if ((error = mlx_start(mc)) != 0)
1498 	    goto out;
1499     } else {
1500 	/* run the command in either polled or wait mode */
1501 	if ((sc->mlx_state & MLX_STATE_INTEN) ? mlx_wait_command(mc) : mlx_poll_command(mc))
1502 	    goto out;
1503 
1504 	/* command completed OK? */
1505 	if (mc->mc_status != 0) {
1506 	    device_printf(sc->mlx_dev, "ENQUIRY failed - %s\n", mlx_diagnose_command(mc));
1507 	    goto out;
1508 	}
1509     }
1510     error = 0;			/* success */
1511  out:
1512     /* we got a command, but nobody else will free it */
1513     if ((complete == NULL) && (mc != NULL))
1514 	mlx_releasecmd(mc);
1515     /* we got an error, and we allocated a result */
1516     if ((error != 0) && (result != NULL)) {
1517 	free(result, M_DEVBUF);
1518 	result = NULL;
1519     }
1520     return(result);
1521 }
1522 
1523 
1524 /********************************************************************************
1525  * Perform a Flush command on the nominated controller.
1526  *
1527  * May be called with interrupts enabled or disabled; will not return until
1528  * the flush operation completes or fails.
1529  */
1530 static int
1531 mlx_flush(struct mlx_softc *sc)
1532 {
1533     struct mlx_command	*mc;
1534     int			error;
1535 
1536     debug_called(1);
1537 
1538     /* get ourselves a command buffer */
1539     error = 1;
1540     if ((mc = mlx_alloccmd(sc)) == NULL)
1541 	goto out;
1542     /* get a command slot */
1543     if (mlx_getslot(mc))
1544 	goto out;
1545 
1546     /* build a flush command */
1547     mlx_make_type2(mc, MLX_CMD_FLUSH, 0, 0, 0, 0, 0, 0, 0, 0);
1548 
1549     /* can't assume that interrupts are going to work here, so play it safe */
1550     if (mlx_poll_command(mc))
1551 	goto out;
1552 
1553     /* command completed OK? */
1554     if (mc->mc_status != 0) {
1555 	device_printf(sc->mlx_dev, "FLUSH failed - %s\n", mlx_diagnose_command(mc));
1556 	goto out;
1557     }
1558 
1559     error = 0;			/* success */
1560  out:
1561     if (mc != NULL)
1562 	mlx_releasecmd(mc);
1563     return(error);
1564 }
1565 
1566 /********************************************************************************
1567  * Start a background consistency check on (drive).
1568  *
1569  * May be called with interrupts enabled or disabled; will return as soon as the
1570  * operation has started or been refused.
1571  */
1572 static int
1573 mlx_check(struct mlx_softc *sc, int drive)
1574 {
1575     struct mlx_command	*mc;
1576     int			error;
1577 
1578     debug_called(1);
1579 
1580     /* get ourselves a command buffer */
1581     error = 0x10000;
1582     if ((mc = mlx_alloccmd(sc)) == NULL)
1583 	goto out;
1584     /* get a command slot */
1585     if (mlx_getslot(mc))
1586 	goto out;
1587 
1588     /* build a checkasync command, set the "fix it" flag */
1589     mlx_make_type2(mc, MLX_CMD_CHECKASYNC, 0, 0, 0, 0, 0, drive | 0x80, 0, 0);
1590 
1591     /* start the command and wait for it to be returned */
1592     if (mlx_wait_command(mc))
1593 	goto out;
1594 
1595     /* command completed OK? */
1596     if (mc->mc_status != 0) {
1597 	device_printf(sc->mlx_dev, "CHECK ASYNC failed - %s\n", mlx_diagnose_command(mc));
1598     } else {
1599 	device_printf(sc->mlx_sysdrive[drive].ms_disk, "consistency check started");
1600     }
1601     error = mc->mc_status;
1602 
1603  out:
1604     if (mc != NULL)
1605 	mlx_releasecmd(mc);
1606     return(error);
1607 }
1608 
1609 /********************************************************************************
1610  * Start a background rebuild of the physical drive at (channel),(target).
1611  *
1612  * May be called with interrupts enabled or disabled; will return as soon as the
1613  * operation has started or been refused.
1614  */
1615 static int
1616 mlx_rebuild(struct mlx_softc *sc, int channel, int target)
1617 {
1618     struct mlx_command	*mc;
1619     int			error;
1620 
1621     debug_called(1);
1622 
1623     /* get ourselves a command buffer */
1624     error = 0x10000;
1625     if ((mc = mlx_alloccmd(sc)) == NULL)
1626 	goto out;
1627     /* get a command slot */
1628     if (mlx_getslot(mc))
1629 	goto out;
1630 
1631     /* build a checkasync command, set the "fix it" flag */
1632     mlx_make_type2(mc, MLX_CMD_REBUILDASYNC, channel, target, 0, 0, 0, 0, 0, 0);
1633 
1634     /* start the command and wait for it to be returned */
1635     if (mlx_wait_command(mc))
1636 	goto out;
1637 
1638     /* command completed OK? */
1639     if (mc->mc_status != 0) {
1640 	device_printf(sc->mlx_dev, "REBUILD ASYNC failed - %s\n", mlx_diagnose_command(mc));
1641     } else {
1642 	device_printf(sc->mlx_dev, "drive rebuild started for %d:%d\n", channel, target);
1643     }
1644     error = mc->mc_status;
1645 
1646  out:
1647     if (mc != NULL)
1648 	mlx_releasecmd(mc);
1649     return(error);
1650 }
1651 
1652 /********************************************************************************
1653  * Run the command (mc) and return when it completes.
1654  *
1655  * Interrupts need to be enabled; returns nonzero on error.
1656  */
1657 static int
1658 mlx_wait_command(struct mlx_command *mc)
1659 {
1660     struct mlx_softc	*sc = mc->mc_sc;
1661     int			error, count;
1662 
1663     debug_called(1);
1664 
1665     mc->mc_complete = NULL;
1666     mc->mc_private = mc;		/* wake us when you're done */
1667     if ((error = mlx_start(mc)) != 0)
1668 	return(error);
1669 
1670     count = 0;
1671     /* XXX better timeout? */
1672     while ((mc->mc_status == MLX_STATUS_BUSY) && (count < 30)) {
1673 	tsleep(mc->mc_private, PCATCH, "mlxwcmd", hz);
1674     }
1675 
1676     if (mc->mc_status != 0) {
1677 	device_printf(sc->mlx_dev, "command failed - %s\n", mlx_diagnose_command(mc));
1678 	return(EIO);
1679     }
1680     return(0);
1681 }
1682 
1683 
1684 /********************************************************************************
1685  * Start the command (mc) and busy-wait for it to complete.
1686  *
1687  * Should only be used when interrupts can't be relied upon. Returns 0 on
1688  * success, nonzero on error.
1689  * Successfully completed commands are dequeued.
1690  */
1691 static int
1692 mlx_poll_command(struct mlx_command *mc)
1693 {
1694     struct mlx_softc	*sc = mc->mc_sc;
1695     int			error, count, s;
1696 
1697     debug_called(1);
1698 
1699     mc->mc_complete = NULL;
1700     mc->mc_private = NULL;	/* we will poll for it */
1701     if ((error = mlx_start(mc)) != 0)
1702 	return(error);
1703 
1704     count = 0;
1705     do {
1706 	/* poll for completion */
1707 	mlx_done(mc->mc_sc);
1708 
1709     } while ((mc->mc_status == MLX_STATUS_BUSY) && (count++ < 15000000));
1710     if (mc->mc_status != MLX_STATUS_BUSY) {
1711 	s = splbio();
1712 	TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
1713 	splx(s);
1714 	return(0);
1715     }
1716     device_printf(sc->mlx_dev, "command failed - %s\n", mlx_diagnose_command(mc));
1717     return(EIO);
1718 }
1719 
1720 /********************************************************************************
1721  * Pull as much work off the softc's work queue as possible and give it to the
1722  * controller.  Leave a couple of slots free for emergencies.
1723  *
1724  * Must be called at splbio or in an equivalent fashion that prevents
1725  * reentry or activity on the bioq.
1726  */
1727 static void
1728 mlx_startio(struct mlx_softc *sc)
1729 {
1730     struct mlx_command	*mc;
1731     struct mlxd_softc	*mlxd;
1732     mlx_bio		*bp;
1733     int			blkcount;
1734     int			driveno;
1735     int			cmd;
1736     int			s;
1737 
1738     /* avoid reentrancy */
1739     if (mlx_lock_tas(sc, MLX_LOCK_STARTING))
1740 	return;
1741 
1742     /* spin until something prevents us from doing any work */
1743     s = splbio();
1744     for (;;) {
1745 
1746 	/* see if there's work to be done */
1747 	if ((bp = MLX_BIO_QFIRST(sc->mlx_bioq)) == NULL)
1748 	    break;
1749 	/* get a command */
1750 	if ((mc = mlx_alloccmd(sc)) == NULL)
1751 	    break;
1752 	/* get a slot for the command */
1753 	if (mlx_getslot(mc) != 0) {
1754 	    mlx_releasecmd(mc);
1755 	    break;
1756 	}
1757 	/* get the buf containing our work */
1758 	MLX_BIO_QREMOVE(sc->mlx_bioq, bp);
1759 	sc->mlx_waitbufs--;
1760 	splx(s);
1761 
1762 	/* connect the buf to the command */
1763 	mc->mc_complete = mlx_completeio;
1764 	mc->mc_private = bp;
1765 	mc->mc_data = MLX_BIO_DATA(bp);
1766 	mc->mc_length = MLX_BIO_LENGTH(bp);
1767 	if (MLX_BIO_IS_READ(bp)) {
1768 	    mc->mc_flags |= MLX_CMD_DATAIN;
1769 	    cmd = MLX_CMD_READSG;
1770 	} else {
1771 	    mc->mc_flags |= MLX_CMD_DATAOUT;
1772 	    cmd = MLX_CMD_WRITESG;
1773 	}
1774 
1775 	/* map the command so the controller can work with it */
1776 	mlx_mapcmd(mc);
1777 
1778 	/* build a suitable I/O command (assumes 512-byte rounded transfers) */
1779 	mlxd = (struct mlxd_softc *)MLX_BIO_SOFTC(bp);
1780 	driveno = mlxd->mlxd_drive - sc->mlx_sysdrive;
1781 	blkcount = (MLX_BIO_LENGTH(bp) + MLX_BLKSIZE - 1) / MLX_BLKSIZE;
1782 
1783 	if ((MLX_BIO_LBA(bp) + blkcount) > sc->mlx_sysdrive[driveno].ms_size)
1784 	    device_printf(sc->mlx_dev, "I/O beyond end of unit (%u,%d > %u)\n",
1785 			  MLX_BIO_LBA(bp), blkcount, sc->mlx_sysdrive[driveno].ms_size);
1786 
1787 	/*
1788 	 * Build the I/O command.  Note that the SG list type bits are set to zero,
1789 	 * denoting the format of SG list that we are using.
1790 	 */
1791 	if (sc->mlx_iftype == MLX_IFTYPE_2) {
1792 	    mlx_make_type1(mc, (cmd == MLX_CMD_WRITESG) ? MLX_CMD_WRITESG_OLD : MLX_CMD_READSG_OLD,
1793 			   blkcount & 0xff, 				/* xfer length low byte */
1794 			   MLX_BIO_LBA(bp),				/* physical block number */
1795 			   driveno,					/* target drive number */
1796 			   mc->mc_sgphys,				/* location of SG list */
1797 			   mc->mc_nsgent & 0x3f);			/* size of SG list (top 3 bits clear) */
1798 	} else {
1799 	    mlx_make_type5(mc, cmd,
1800 			   blkcount & 0xff, 				/* xfer length low byte */
1801 			   (driveno << 3) | ((blkcount >> 8) & 0x07),	/* target and length high 3 bits */
1802 			   MLX_BIO_LBA(bp),				/* physical block number */
1803 			   mc->mc_sgphys,				/* location of SG list */
1804 			   mc->mc_nsgent & 0x3f);			/* size of SG list (top 3 bits clear) */
1805 	}
1806 
1807 	/* try to give command to controller */
1808 	if (mlx_start(mc) != 0) {
1809 	    /* fail the command */
1810 	    mc->mc_status = MLX_STATUS_WEDGED;
1811 	    mlx_completeio(mc);
1812 	}
1813 	s = splbio();
1814     }
1815     splx(s);
1816     mlx_lock_clr(sc, MLX_LOCK_STARTING);
1817 }
1818 
1819 /********************************************************************************
1820  * Handle completion of an I/O command.
1821  */
1822 static void
1823 mlx_completeio(struct mlx_command *mc)
1824 {
1825     struct mlx_softc	*sc = mc->mc_sc;
1826     mlx_bio		*bp = (mlx_bio *)mc->mc_private;
1827     struct mlxd_softc	*mlxd = (struct mlxd_softc *)MLX_BIO_SOFTC(bp);
1828 
1829     if (mc->mc_status != MLX_STATUS_OK) {	/* could be more verbose here? */
1830 	MLX_BIO_SET_ERROR(bp, EIO);
1831 
1832 	switch(mc->mc_status) {
1833 	case MLX_STATUS_RDWROFFLINE:		/* system drive has gone offline */
1834 	    device_printf(mlxd->mlxd_dev, "drive offline\n");
1835 	    /* should signal this with a return code */
1836 	    mlxd->mlxd_drive->ms_state = MLX_SYSD_OFFLINE;
1837 	    break;
1838 
1839 	default:				/* other I/O error */
1840 	    device_printf(sc->mlx_dev, "I/O error - %s\n", mlx_diagnose_command(mc));
1841 #if 0
1842 	    device_printf(sc->mlx_dev, "  b_bcount %ld  blkcount %ld  b_pblkno %d\n",
1843 			  MLX_BIO_LENGTH(bp), MLX_BIO_LENGTH(bp) / MLX_BLKSIZE, MLX_BIO_LBA(bp));
1844 	    device_printf(sc->mlx_dev, "  %13D\n", mc->mc_mailbox, " ");
1845 #endif
1846 	    break;
1847 	}
1848     }
1849     mlx_releasecmd(mc);
1850     mlxd_intr(bp);
1851 }
1852 
1853 /********************************************************************************
1854  * Take a command from user-space and try to run it.
1855  *
1856  * XXX Note that this can't perform very much in the way of error checking, and
1857  *     as such, applications _must_ be considered trustworthy.
1858  * XXX Commands using S/G for data are not supported.
1859  */
1860 static int
1861 mlx_user_command(struct mlx_softc *sc, struct mlx_usercommand *mu)
1862 {
1863     struct mlx_command	*mc;
1864     struct mlx_dcdb	*dcdb;
1865     void		*kbuf;
1866     int			error;
1867 
1868     debug_called(0);
1869 
1870     kbuf = NULL;
1871     mc = NULL;
1872     dcdb = NULL;
1873     error = ENOMEM;
1874 
1875     /* get ourselves a command and copy in from user space */
1876     if ((mc = mlx_alloccmd(sc)) == NULL)
1877 	goto out;
1878     bcopy(mu->mu_command, mc->mc_mailbox, sizeof(mc->mc_mailbox));
1879     debug(0, "got command buffer");
1880 
1881     /* if we need a buffer for data transfer, allocate one and copy in its initial contents */
1882     if (mu->mu_datasize > 0) {
1883 	if (mu->mu_datasize > MAXPHYS)
1884 	    return (EINVAL);
1885 	if (((kbuf = malloc(mu->mu_datasize, M_DEVBUF, M_WAITOK)) == NULL) ||
1886 	    (error = copyin(mu->mu_buf, kbuf, mu->mu_datasize)))
1887 	    goto out;
1888 	debug(0, "got kernel buffer");
1889     }
1890 
1891     /* get a command slot */
1892     if (mlx_getslot(mc))
1893 	goto out;
1894     debug(0, "got a slot");
1895 
1896     /* map the command so the controller can see it */
1897     mc->mc_data = kbuf;
1898     mc->mc_length = mu->mu_datasize;
1899     mlx_mapcmd(mc);
1900     debug(0, "mapped");
1901 
1902     /*
1903      * If this is a passthrough SCSI command, the DCDB is packed at the
1904      * beginning of the data area.  Fix up the DCDB to point to the correct physical
1905      * address and override any bufptr supplied by the caller since we know
1906      * what it's meant to be.
1907      */
1908     if (mc->mc_mailbox[0] == MLX_CMD_DIRECT_CDB) {
1909 	dcdb = (struct mlx_dcdb *)kbuf;
1910 	dcdb->dcdb_physaddr = mc->mc_dataphys + sizeof(*dcdb);
1911 	mu->mu_bufptr = 8;
1912     }
1913 
1914     /*
1915      * If there's a data buffer, fix up the command's buffer pointer.
1916      */
1917     if (mu->mu_datasize > 0) {
1918 
1919 	/* range check the pointer to physical buffer address */
1920 	if ((mu->mu_bufptr < 0) || (mu->mu_bufptr > (sizeof(mu->mu_command) - sizeof(u_int32_t)))) {
1921 	    error = EINVAL;
1922 	    goto out;
1923 	}
1924 	mc->mc_mailbox[mu->mu_bufptr    ] =  mc->mc_dataphys        & 0xff;
1925 	mc->mc_mailbox[mu->mu_bufptr + 1] = (mc->mc_dataphys >> 8)  & 0xff;
1926 	mc->mc_mailbox[mu->mu_bufptr + 2] = (mc->mc_dataphys >> 16) & 0xff;
1927 	mc->mc_mailbox[mu->mu_bufptr + 3] = (mc->mc_dataphys >> 24) & 0xff;
1928     }
1929     debug(0, "command fixup");
1930 
1931     /* submit the command and wait */
1932     if ((error = mlx_wait_command(mc)) != 0)
1933 	goto out;
1934 
1935     /* copy out status and data */
1936     mu->mu_status = mc->mc_status;
1937     if ((mu->mu_datasize > 0) && ((error = copyout(kbuf, mu->mu_buf, mu->mu_datasize))))
1938 	goto out;
1939     error = 0;
1940 
1941  out:
1942     mlx_releasecmd(mc);
1943     if (kbuf != NULL)
1944 	free(kbuf, M_DEVBUF);
1945     return(error);
1946 }
1947 
1948 /********************************************************************************
1949  ********************************************************************************
1950                                                         Command I/O to Controller
1951  ********************************************************************************
1952  ********************************************************************************/
1953 
1954 /********************************************************************************
1955  * Find a free command slot for (mc).
1956  *
1957  * Don't hand out a slot to a normal-priority command unless there are at least
1958  * 4 slots free for priority commands.
1959  */
1960 static int
1961 mlx_getslot(struct mlx_command *mc)
1962 {
1963     struct mlx_softc	*sc = mc->mc_sc;
1964     int			s, slot, limit;
1965 
1966     debug_called(1);
1967 
1968     /*
1969      * Enforce slot-usage limit, if we have the required information.
1970      */
1971     if (sc->mlx_enq2 != NULL) {
1972 	limit = sc->mlx_enq2->me_max_commands;
1973     } else {
1974 	limit = 2;
1975     }
1976     if (sc->mlx_busycmds >= ((mc->mc_flags & MLX_CMD_PRIORITY) ? limit : limit - 4))
1977 	return(EBUSY);
1978 
1979     /*
1980      * Allocate an outstanding command slot
1981      *
1982      * XXX linear search is slow
1983      */
1984     s = splbio();
1985     for (slot = 0; slot < limit; slot++) {
1986 	debug(2, "try slot %d", slot);
1987 	if (sc->mlx_busycmd[slot] == NULL)
1988 	    break;
1989     }
1990     if (slot < limit) {
1991 	sc->mlx_busycmd[slot] = mc;
1992 	sc->mlx_busycmds++;
1993     }
1994     splx(s);
1995 
1996     /* out of slots? */
1997     if (slot >= limit)
1998 	return(EBUSY);
1999 
2000     debug(2, "got slot %d", slot);
2001     mc->mc_slot = slot;
2002     return(0);
2003 }
2004 
2005 /********************************************************************************
2006  * Map/unmap (mc)'s data in the controller's addressable space.
2007  */
2008 static void
2009 mlx_setup_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
2010 {
2011     struct mlx_command	*mc = (struct mlx_command *)arg;
2012     struct mlx_softc	*sc = mc->mc_sc;
2013     struct mlx_sgentry	*sg;
2014     int			i;
2015 
2016     debug_called(1);
2017 
2018     /* XXX should be unnecessary */
2019     if (sc->mlx_enq2 && (nsegments > sc->mlx_enq2->me_max_sg))
2020 	panic("MLX: too many s/g segments (%d, max %d)", nsegments, sc->mlx_enq2->me_max_sg);
2021 
2022     /* get base address of s/g table */
2023     sg = sc->mlx_sgtable + (mc->mc_slot * MLX_NSEG);
2024 
2025     /* save s/g table information in command */
2026     mc->mc_nsgent = nsegments;
2027     mc->mc_sgphys = sc->mlx_sgbusaddr + (mc->mc_slot * MLX_NSEG * sizeof(struct mlx_sgentry));
2028     mc->mc_dataphys = segs[0].ds_addr;
2029 
2030     /* populate s/g table */
2031     for (i = 0; i < nsegments; i++, sg++) {
2032 	sg->sg_addr = segs[i].ds_addr;
2033 	sg->sg_count = segs[i].ds_len;
2034     }
2035 }
2036 
2037 static void
2038 mlx_mapcmd(struct mlx_command *mc)
2039 {
2040     struct mlx_softc	*sc = mc->mc_sc;
2041 
2042     debug_called(1);
2043 
2044     /* if the command involves data at all */
2045     if (mc->mc_data != NULL) {
2046 
2047 	/* map the data buffer into bus space and build the s/g list */
2048 	bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data, mc->mc_length,
2049 			mlx_setup_dmamap, mc, 0);
2050 	if (mc->mc_flags & MLX_CMD_DATAIN)
2051 	    bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_PREREAD);
2052 	if (mc->mc_flags & MLX_CMD_DATAOUT)
2053 	    bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_PREWRITE);
2054     }
2055 }
2056 
2057 static void
2058 mlx_unmapcmd(struct mlx_command *mc)
2059 {
2060     struct mlx_softc	*sc = mc->mc_sc;
2061 
2062     debug_called(1);
2063 
2064     /* if the command involved data at all */
2065     if (mc->mc_data != NULL) {
2066 
2067 	if (mc->mc_flags & MLX_CMD_DATAIN)
2068 	    bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTREAD);
2069 	if (mc->mc_flags & MLX_CMD_DATAOUT)
2070 	    bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTWRITE);
2071 
2072 	bus_dmamap_unload(sc->mlx_buffer_dmat, mc->mc_dmamap);
2073     }
2074 }
2075 
2076 /********************************************************************************
2077  * Try to deliver (mc) to the controller.
2078  *
2079  * Can be called at any interrupt level, with or without interrupts enabled.
2080  */
2081 static int
2082 mlx_start(struct mlx_command *mc)
2083 {
2084     struct mlx_softc	*sc = mc->mc_sc;
2085     int			i, s, done;
2086 
2087     debug_called(1);
2088 
2089     /* save the slot number as ident so we can handle this command when complete */
2090     mc->mc_mailbox[0x1] = mc->mc_slot;
2091 
2092     /* mark the command as currently being processed */
2093     mc->mc_status = MLX_STATUS_BUSY;
2094 
2095     /* set a default 60-second timeout  XXX tunable?  XXX not currently used */
2096     mc->mc_timeout = time_second + 60;
2097 
2098     /* spin waiting for the mailbox */
2099     for (i = 100000, done = 0; (i > 0) && !done; i--) {
2100 	s = splbio();
2101 	if (sc->mlx_tryqueue(sc, mc)) {
2102 	    done = 1;
2103 	    /* move command to work queue */
2104 	    TAILQ_INSERT_TAIL(&sc->mlx_work, mc, mc_link);
2105 	}
2106 	splx(s);	/* drop spl to allow completion interrupts */
2107     }
2108 
2109     /* command is enqueued */
2110     if (done)
2111 	return(0);
2112 
2113     /*
2114      * We couldn't get the controller to take the command.  Revoke the slot
2115      * that the command was given and return it with a bad status.
2116      */
2117     sc->mlx_busycmd[mc->mc_slot] = NULL;
2118     device_printf(sc->mlx_dev, "controller wedged (not taking commands)\n");
2119     mc->mc_status = MLX_STATUS_WEDGED;
2120     mlx_complete(sc);
2121     return(EIO);
2122 }
2123 
2124 /********************************************************************************
2125  * Poll the controller (sc) for completed commands.
2126  * Update command status and free slots for reuse.  If any slots were freed,
2127  * new commands may be posted.
2128  *
2129  * Returns nonzero if one or more commands were completed.
2130  */
2131 static int
2132 mlx_done(struct mlx_softc *sc)
2133 {
2134     struct mlx_command	*mc;
2135     int			s, result;
2136     u_int8_t		slot;
2137     u_int16_t		status;
2138 
2139     debug_called(2);
2140 
2141     result = 0;
2142 
2143     /* loop collecting completed commands */
2144     s = splbio();
2145     for (;;) {
2146 	/* poll for a completed command's identifier and status */
2147 	if (sc->mlx_findcomplete(sc, &slot, &status)) {
2148 	    result = 1;
2149 	    mc = sc->mlx_busycmd[slot];			/* find command */
2150 	    if (mc != NULL) {				/* paranoia */
2151 		if (mc->mc_status == MLX_STATUS_BUSY) {
2152 		    mc->mc_status = status;		/* save status */
2153 
2154 		    /* free slot for reuse */
2155 		    sc->mlx_busycmd[slot] = NULL;
2156 		    sc->mlx_busycmds--;
2157 		} else {
2158 		    device_printf(sc->mlx_dev, "duplicate done event for slot %d\n", slot);
2159 		}
2160 	    } else {
2161 		device_printf(sc->mlx_dev, "done event for nonbusy slot %d\n", slot);
2162 	    }
2163 	} else {
2164 	    break;
2165 	}
2166     }
2167     splx(s);
2168 
2169     /* if we've completed any commands, try posting some more */
2170     if (result)
2171 	mlx_startio(sc);
2172 
2173     /* handle completion and timeouts */
2174     mlx_complete(sc);
2175 
2176     return(result);
2177 }
2178 
2179 /********************************************************************************
2180  * Perform post-completion processing for commands on (sc).
2181  */
2182 static void
2183 mlx_complete(struct mlx_softc *sc)
2184 {
2185     struct mlx_command	*mc, *nc;
2186     int			s, count;
2187 
2188     debug_called(2);
2189 
2190     /* avoid reentrancy  XXX might want to signal and request a restart */
2191     if (mlx_lock_tas(sc, MLX_LOCK_COMPLETING))
2192 	return;
2193 
2194     s = splbio();
2195     count = 0;
2196 
2197     /* scan the list of busy/done commands */
2198     mc = TAILQ_FIRST(&sc->mlx_work);
2199     while (mc != NULL) {
2200 	nc = TAILQ_NEXT(mc, mc_link);
2201 
2202 	/* Command has been completed in some fashion */
2203 	if (mc->mc_status != MLX_STATUS_BUSY) {
2204 
2205 	    /* unmap the command's data buffer */
2206 	    mlx_unmapcmd(mc);
2207 	    /*
2208 	     * Does the command have a completion handler?
2209 	     */
2210 	    if (mc->mc_complete != NULL) {
2211 		/* remove from list and give to handler */
2212 		TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
2213 		mc->mc_complete(mc);
2214 
2215 		/*
2216 		 * Is there a sleeper waiting on this command?
2217 		 */
2218 	    } else if (mc->mc_private != NULL) {	/* sleeping caller wants to know about it */
2219 
2220 		/* remove from list and wake up sleeper */
2221 		TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
2222 		wakeup_one(mc->mc_private);
2223 
2224 		/*
2225 		 * Leave the command for a caller that's polling for it.
2226 		 */
2227 	    } else {
2228 	    }
2229 	}
2230 	mc = nc;
2231     }
2232     splx(s);
2233 
2234     mlx_lock_clr(sc, MLX_LOCK_COMPLETING);
2235 }
2236 
2237 /********************************************************************************
2238  ********************************************************************************
2239                                                         Command Buffer Management
2240  ********************************************************************************
2241  ********************************************************************************/
2242 
2243 /********************************************************************************
2244  * Get a new command buffer.
2245  *
2246  * This may return NULL in low-memory cases.
2247  *
2248  * Note that using malloc() is expensive (the command buffer is << 1 page) but
2249  * necessary if we are to be a loadable module before the zone allocator is fixed.
2250  *
2251  * If possible, we recycle a command buffer that's been used before.
2252  *
2253  * XXX Note that command buffers are not cleaned out - it is the caller's
2254  *     responsibility to ensure that all required fields are filled in before
2255  *     using a buffer.
2256  */
2257 static struct mlx_command *
2258 mlx_alloccmd(struct mlx_softc *sc)
2259 {
2260     struct mlx_command	*mc;
2261     int			error;
2262     int			s;
2263 
2264     debug_called(1);
2265 
2266     s = splbio();
2267     if ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL)
2268 	TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link);
2269     splx(s);
2270 
2271     /* allocate a new command buffer? */
2272     if (mc == NULL) {
2273 	mc = (struct mlx_command *)malloc(sizeof(*mc), M_DEVBUF, M_NOWAIT | M_ZERO);
2274 	if (mc != NULL) {
2275 	    mc->mc_sc = sc;
2276 	    error = bus_dmamap_create(sc->mlx_buffer_dmat, 0, &mc->mc_dmamap);
2277 	    if (error) {
2278 		free(mc, M_DEVBUF);
2279 		return(NULL);
2280 	    }
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