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