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