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