xref: /freebsd/sys/dev/mlx/mlx.c (revision 7f9d26bd9d1b2754da8429257edbde0a8237f84f)
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 
44 #include <machine/resource.h>
45 #include <machine/bus.h>
46 #include <machine/clock.h>
47 #include <sys/rman.h>
48 
49 #include <dev/mlx/mlxio.h>
50 #include <dev/mlx/mlxvar.h>
51 #include <dev/mlx/mlxreg.h>
52 
53 #if 0
54 #define debug(fmt, args...)	printf("%s: " fmt "\n", __FUNCTION__ , ##args)
55 #else
56 #define debug(fmt, args...)
57 #endif
58 
59 #define MLX_CDEV_MAJOR	130
60 
61 static struct cdevsw mlx_cdevsw = {
62 		/* open */	mlx_open,
63 		/* close */	mlx_close,
64 		/* read */	noread,
65 		/* write */	nowrite,
66 		/* ioctl */	mlx_ioctl,
67 		/* poll */	nopoll,
68 		/* mmap */	nommap,
69 		/* strategy */	nostrategy,
70 		/* name */ 	"mlx",
71 		/* maj */	MLX_CDEV_MAJOR,
72 		/* dump */	nodump,
73 		/* psize */ 	nopsize,
74 		/* flags */	0,
75 		/* bmaj */	-1
76 };
77 
78 static int	cdev_registered = 0;
79 devclass_t	mlx_devclass;
80 
81 /*
82  * Per-interface accessor methods
83  */
84 static int			mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
85 static int			mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
86 static void			mlx_v3_intaction(struct mlx_softc *sc, int action);
87 
88 static int			mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
89 static int			mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
90 static void			mlx_v4_intaction(struct mlx_softc *sc, int action);
91 
92 /*
93  * Status monitoring
94  */
95 static void			mlx_periodic(void *data);
96 static void			mlx_periodic_enquiry(struct mlx_command *mc);
97 static void			mlx_periodic_eventlog_poll(struct mlx_softc *sc);
98 static void			mlx_periodic_eventlog_respond(struct mlx_command *mc);
99 static void			mlx_periodic_rebuild(struct mlx_command *mc);
100 
101 /*
102  * Channel Pause
103  */
104 static void			mlx_pause_action(struct mlx_softc *sc);
105 static void			mlx_pause_done(struct mlx_command *mc);
106 
107 /*
108  * Command submission.
109  */
110 static void			*mlx_enquire(struct mlx_softc *sc, int command, size_t bufsize,
111 					     void (*complete)(struct mlx_command *mc));
112 static int			mlx_flush(struct mlx_softc *sc);
113 static int			mlx_rebuild(struct mlx_softc *sc, int channel, int target);
114 static int			mlx_wait_command(struct mlx_command *mc);
115 static int			mlx_poll_command(struct mlx_command *mc);
116 static void			mlx_startio(struct mlx_softc *sc);
117 static void			mlx_completeio(struct mlx_command *mc);
118 static int			mlx_user_command(struct mlx_softc *sc, struct mlx_usercommand *mu);
119 
120 /*
121  * Command buffer allocation.
122  */
123 static struct mlx_command	*mlx_alloccmd(struct mlx_softc *sc);
124 static void			mlx_releasecmd(struct mlx_command *mc);
125 static void			mlx_freecmd(struct mlx_command *mc);
126 
127 /*
128  * Command management.
129  */
130 static int			mlx_getslot(struct mlx_command *mc);
131 static void			mlx_mapcmd(struct mlx_command *mc);
132 static void			mlx_unmapcmd(struct mlx_command *mc);
133 static int			mlx_start(struct mlx_command *mc);
134 static int			mlx_done(struct mlx_softc *sc);
135 static void			mlx_complete(struct mlx_softc *sc);
136 
137 /*
138  * Debugging.
139  */
140 static char			*mlx_diagnose_command(struct mlx_command *mc);
141 static char			*mlx_name_controller(u_int32_t hwid);
142 
143 
144 /*
145  * Utility functions.
146  */
147 static struct mlx_sysdrive	*mlx_findunit(struct mlx_softc *sc, int unit);
148 
149 /********************************************************************************
150  ********************************************************************************
151                                                                 Public Interfaces
152  ********************************************************************************
153  ********************************************************************************/
154 
155 /********************************************************************************
156  * Free all of the resources associated with (sc)
157  *
158  * Should not be called if the controller is active.
159  */
160 void
161 mlx_free(struct mlx_softc *sc)
162 {
163     struct mlx_command	*mc;
164 
165     debug("called");
166 
167     /* cancel status timeout */
168     untimeout(mlx_periodic, sc, sc->mlx_timeout);
169 
170     /* throw away any command buffers */
171     while ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL) {
172 	TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link);
173 	mlx_freecmd(mc);
174     }
175 
176     /* destroy data-transfer DMA tag */
177     if (sc->mlx_buffer_dmat)
178 	bus_dma_tag_destroy(sc->mlx_buffer_dmat);
179 
180     /* free and destroy DMA memory and tag for s/g lists */
181     if (sc->mlx_sgtable)
182 	bus_dmamem_free(sc->mlx_sg_dmat, sc->mlx_sgtable, sc->mlx_sg_dmamap);
183     if (sc->mlx_sg_dmat)
184 	bus_dma_tag_destroy(sc->mlx_sg_dmat);
185 
186     /* disconnect the interrupt handler */
187     if (sc->mlx_intr)
188 	bus_teardown_intr(sc->mlx_dev, sc->mlx_irq, sc->mlx_intr);
189     if (sc->mlx_irq != NULL)
190 	bus_release_resource(sc->mlx_dev, SYS_RES_IRQ, 0, sc->mlx_irq);
191 
192     /* destroy the parent DMA tag */
193     if (sc->mlx_parent_dmat)
194 	bus_dma_tag_destroy(sc->mlx_parent_dmat);
195 
196     /* release the register window mapping */
197     if (sc->mlx_mem != NULL)
198 	bus_release_resource(sc->mlx_dev, SYS_RES_MEMORY,
199 			     (sc->mlx_iftype == MLX_IFTYPE_3) ? MLX_CFG_BASE1 : MLX_CFG_BASE0, sc->mlx_mem);
200 }
201 
202 /********************************************************************************
203  * Map the scatter/gather table into bus space
204  */
205 static void
206 mlx_dma_map_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error)
207 {
208     struct mlx_softc	*sc = (struct mlx_softc *)arg;
209 
210     debug("called");
211 
212     /* save base of s/g table's address in bus space */
213     sc->mlx_sgbusaddr = segs->ds_addr;
214 }
215 
216 static int
217 mlx_sglist_map(struct mlx_softc *sc)
218 {
219     size_t	segsize;
220     int		error;
221 
222     debug("called");
223 
224     /* destroy any existing mappings */
225     if (sc->mlx_sgtable)
226 	bus_dmamem_free(sc->mlx_sg_dmat, sc->mlx_sgtable, sc->mlx_sg_dmamap);
227     if (sc->mlx_sg_dmat)
228 	bus_dma_tag_destroy(sc->mlx_sg_dmat);
229 
230     /*
231      * Create a single tag describing a region large enough to hold all of
232      * the s/g lists we will need.
233      */
234     segsize = sizeof(struct mlx_sgentry) * MLX_NSEG * sc->mlx_maxiop;
235     error = bus_dma_tag_create(sc->mlx_parent_dmat, 	/* parent */
236 			       1, 0, 			/* alignment, boundary */
237 			       BUS_SPACE_MAXADDR,	/* lowaddr */
238 			       BUS_SPACE_MAXADDR, 	/* highaddr */
239 			       NULL, NULL, 		/* filter, filterarg */
240 			       segsize, 1,		/* maxsize, nsegments */
241 			       BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
242 			       0,			/* flags */
243 			       &sc->mlx_sg_dmat);
244     if (error != 0) {
245 	device_printf(sc->mlx_dev, "can't allocate scatter/gather DMA tag\n");
246 	return(ENOMEM);
247     }
248 
249     /*
250      * Allocate enough s/g maps for all commands and permanently map them into
251      * controller-visible space.
252      *
253      * XXX this assumes we can get enough space for all the s/g maps in one
254      * contiguous slab.  We may need to switch to a more complex arrangement where
255      * we allocate in smaller chunks and keep a lookup table from slot to bus address.
256      */
257     error = bus_dmamem_alloc(sc->mlx_sg_dmat, (void **)&sc->mlx_sgtable, BUS_DMA_NOWAIT, &sc->mlx_sg_dmamap);
258     if (error) {
259 	device_printf(sc->mlx_dev, "can't allocate s/g table\n");
260 	return(ENOMEM);
261     }
262     bus_dmamap_load(sc->mlx_sg_dmat, sc->mlx_sg_dmamap, sc->mlx_sgtable, segsize, mlx_dma_map_sg, sc, 0);
263     return(0);
264 }
265 
266 /********************************************************************************
267  * Initialise the controller and softc
268  */
269 int
270 mlx_attach(struct mlx_softc *sc)
271 {
272     struct mlx_enquiry	*me;
273     struct mlx_enquiry2	*me2;
274     int			rid, error;
275 
276     debug("called");
277 
278     /*
279      * Initialise per-controller queues.
280      */
281     TAILQ_INIT(&sc->mlx_work);
282     TAILQ_INIT(&sc->mlx_freecmds);
283     bufq_init(&sc->mlx_bufq);
284 
285     /*
286      * Select accessor methods based on controller interface type.
287      */
288     switch(sc->mlx_iftype) {
289     case MLX_IFTYPE_3:
290 	sc->mlx_tryqueue	= mlx_v3_tryqueue;
291 	sc->mlx_findcomplete	= mlx_v3_findcomplete;
292 	sc->mlx_intaction	= mlx_v3_intaction;
293 	break;
294     case MLX_IFTYPE_4:
295 	sc->mlx_tryqueue	= mlx_v4_tryqueue;
296 	sc->mlx_findcomplete	= mlx_v4_findcomplete;
297 	sc->mlx_intaction	= mlx_v4_intaction;
298 	break;
299     default:
300 	device_printf(sc->mlx_dev, "attaching unsupported interface version %d\n", sc->mlx_iftype);
301 	return(ENXIO);		/* should never happen */
302     }
303 
304     /* disable interrupts before we start talking to the controller */
305     sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
306 
307     /*
308      * Allocate and connect our interrupt.
309      */
310     rid = 0;
311     sc->mlx_irq = bus_alloc_resource(sc->mlx_dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);
312     if (sc->mlx_irq == NULL) {
313 	device_printf(sc->mlx_dev, "couldn't allocate interrupt\n");
314 	mlx_free(sc);
315 	return(ENXIO);
316     }
317     error = bus_setup_intr(sc->mlx_dev, sc->mlx_irq, INTR_TYPE_BIO,  mlx_intr, sc, &sc->mlx_intr);
318     if (error) {
319 	device_printf(sc->mlx_dev, "couldn't set up interrupt\n");
320 	mlx_free(sc);
321 	return(ENXIO);
322     }
323 
324     /*
325      * Create DMA tag for mapping buffers into controller-addressable space.
326      */
327     error = bus_dma_tag_create(sc->mlx_parent_dmat, 	/* parent */
328 			       1, 0, 			/* alignment, boundary */
329 			       BUS_SPACE_MAXADDR,	/* lowaddr */
330 			       BUS_SPACE_MAXADDR, 	/* highaddr */
331 			       NULL, NULL, 		/* filter, filterarg */
332 			       MAXBSIZE, MLX_NSEG,	/* maxsize, nsegments */
333 			       BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
334 			       0,			/* flags */
335 			       &sc->mlx_buffer_dmat);
336     if (error != 0) {
337 	device_printf(sc->mlx_dev, "can't allocate buffer DMA tag\n");
338 	return(ENOMEM);
339     }
340 
341     /*
342      * Create an initial set of s/g mappings.
343      */
344     sc->mlx_maxiop = 2;
345     error = mlx_sglist_map(sc);
346     if (error != 0) {
347 	device_printf(sc->mlx_dev, "couldn't make initial s/g list mapping\n");
348 	return(error);
349     }
350 
351     /*
352      * Probe the controller for more information.
353      */
354     /* send an ENQUIRY to the controller */
355     if ((me = mlx_enquire(sc, MLX_CMD_ENQUIRY, sizeof(*me), NULL)) == NULL) {
356 	device_printf(sc->mlx_dev, "ENQUIRY failed\n");
357 	return(ENXIO);
358     }
359 
360     /* pull information out of the ENQUIRY result */
361     sc->mlx_fwminor = me->me_fwminor;
362     sc->mlx_fwmajor = me->me_fwmajor;
363     sc->mlx_maxiop = me->me_max_commands;
364     sc->mlx_lastevent = sc->mlx_currevent = me->me_event_log_seq_num;
365     free(me, M_DEVBUF);
366 
367     /* send an ENQUIRY2 to the controller */
368     if ((me2 = mlx_enquire(sc, MLX_CMD_ENQUIRY2, sizeof(*me2), NULL)) == NULL) {
369 	device_printf(sc->mlx_dev, "ENQUIRY2 failed\n");
370 	return(ENXIO);
371     }
372 
373     /* pull information out of the ENQUIRY2 result */
374     sc->mlx_nchan = me2->me_configured_channels;
375     sc->mlx_maxiosize = me2->me_maxblk;
376     sc->mlx_maxtarg = me2->me_max_targets;
377     sc->mlx_maxtags = me2->me_max_tags;
378     sc->mlx_scsicap = me2->me_scsi_cap;
379     sc->mlx_hwid = me2->me_hardware_id;
380 
381     /* print a little information about the controller and ourselves */
382     device_printf(sc->mlx_dev, "Mylex %s, firmware %d.%02d, %dMB RAM\n",
383 	   mlx_name_controller(sc->mlx_hwid), sc->mlx_fwmajor, sc->mlx_fwminor,
384 	me2->me_mem_size / (1024 * 1024));
385     free(me2, M_DEVBUF);
386 
387     /*
388      * Do quirk/feature related things.
389      */
390     switch(sc->mlx_iftype) {
391     case MLX_IFTYPE_3:
392 	/* XXX certify 3.52? */
393 	if (sc->mlx_fwminor < 51) {
394 	    device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
395 	    device_printf(sc->mlx_dev, " *** WARNING *** Use revision 3.51 or later\n");
396 	}
397 	break;
398     case MLX_IFTYPE_4:
399 	/* XXX certify firmware versions? */
400 	if (sc->mlx_fwminor < 6) {
401 	    device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
402 	    device_printf(sc->mlx_dev, " *** WARNING *** Use revision 4.06 or later\n");
403 	}
404 	break;
405     default:
406 	device_printf(sc->mlx_dev, "interface version corrupted to %d\n", sc->mlx_iftype);
407 	return(ENXIO);		/* should never happen */
408     }
409 
410     /*
411      * Create the final set of s/g mappings now that we know how many commands
412      * the controller actually supports.
413      */
414     error = mlx_sglist_map(sc);
415     if (error != 0) {
416 	device_printf(sc->mlx_dev, "couldn't make initial s/g list mapping\n");
417 	return(error);
418     }
419 
420     /*
421      * No rebuild or check is in progress.
422      */
423     sc->mlx_rebuild = -1;
424     sc->mlx_check = -1;
425 
426     /*
427      * Register the control device on first attach.
428      */
429     if (cdev_registered++ == 0)
430 	cdevsw_add(&mlx_cdevsw);
431 
432     /*
433      * Start the timeout routine.
434      */
435     sc->mlx_timeout = timeout(mlx_periodic, sc, hz);
436 
437     return(0);
438 }
439 
440 /********************************************************************************
441  * Locate disk resources and attach children to them.
442  */
443 void
444 mlx_startup(struct mlx_softc *sc)
445 {
446     struct mlx_enq_sys_drive	*mes;
447     struct mlx_sysdrive		*dr;
448     int				i, error;
449 
450     debug("called");
451 
452     /*
453      * Scan all the system drives and attach children for those that
454      * don't currently have them.
455      */
456     mes = mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(*mes) * MLX_MAXDRIVES, NULL);
457     if (mes == NULL) {
458 	device_printf(sc->mlx_dev, "error fetching drive status");
459 	return;
460     }
461 
462     /* iterate over drives returned */
463     for (i = 0, dr = &sc->mlx_sysdrive[0];
464 	 (i < MLX_MAXDRIVES) && (mes[i].sd_size != 0xffffffff);
465 	 i++, dr++) {
466 	/* are we already attached to this drive? */
467     	if (dr->ms_disk == 0) {
468 	    /* pick up drive information */
469 	    dr->ms_size = mes[i].sd_size;
470 	    dr->ms_raidlevel = mes[i].sd_raidlevel & 0xf;
471 	    dr->ms_state = mes[i].sd_state;
472 
473 	    /* generate geometry information */
474 	    if (sc->mlx_geom == MLX_GEOM_128_32) {
475 		dr->ms_heads = 128;
476 		dr->ms_sectors = 32;
477 		dr->ms_cylinders = dr->ms_size / (128 * 32);
478 	    } else {        /* MLX_GEOM_255/63 */
479 		dr->ms_heads = 255;
480 		dr->ms_sectors = 63;
481 		dr->ms_cylinders = dr->ms_size / (255 * 63);
482 	    }
483 	    dr->ms_disk =  device_add_child(sc->mlx_dev, /*"mlxd"*/NULL, -1, dr);
484 	    if (dr->ms_disk == 0)
485 		device_printf(sc->mlx_dev, "device_add_child failed\n");
486 	}
487     }
488     free(mes, M_DEVBUF);
489     if ((error = bus_generic_attach(sc->mlx_dev)) != 0)
490 	device_printf(sc->mlx_dev, "bus_generic_attach returned %d", error);
491 
492     /* mark controller back up */
493     sc->mlx_state &= ~MLX_STATE_SHUTDOWN;
494 
495     /* enable interrupts */
496     sc->mlx_intaction(sc, MLX_INTACTION_ENABLE);
497 }
498 
499 /********************************************************************************
500  * Disconnect from the controller completely, in preparation for unload.
501  */
502 int
503 mlx_detach(device_t dev)
504 {
505     struct mlx_softc	*sc = device_get_softc(dev);
506     int			error;
507 
508     debug("called");
509 
510     if (sc->mlx_state & MLX_STATE_OPEN)
511 	return(EBUSY);
512 
513     if ((error = mlx_shutdown(dev)))
514 	return(error);
515 
516     mlx_free(sc);
517 
518     /*
519      * Deregister the control device on last detach.
520      */
521     if (--cdev_registered == 0)
522 	cdevsw_remove(&mlx_cdevsw);
523 
524     return(0);
525 }
526 
527 /********************************************************************************
528  * Bring the controller down to a dormant state and detach all child devices.
529  *
530  * This function is called before detach, system shutdown, or before performing
531  * an operation which may add or delete system disks.  (Call mlx_startup to
532  * resume normal operation.)
533  *
534  * Note that we can assume that the bufq on the controller is empty, as we won't
535  * allow shutdown if any device is open.
536  */
537 int
538 mlx_shutdown(device_t dev)
539 {
540     struct mlx_softc	*sc = device_get_softc(dev);
541     struct mlxd_softc	*mlxd;
542     int			i, s, error;
543 
544     debug("called");
545 
546     s = splbio();
547     error = 0;
548 
549     /* assume we're going to shut down */
550     sc->mlx_state |= MLX_STATE_SHUTDOWN;
551     for (i = 0; i < MLX_MAXDRIVES; i++) {
552 	if (sc->mlx_sysdrive[i].ms_disk != 0) {
553 	    mlxd = device_get_softc(sc->mlx_sysdrive[i].ms_disk);
554 	    if (mlxd->mlxd_flags & MLXD_OPEN) {		/* drive is mounted, abort shutdown */
555 		sc->mlx_state &= ~MLX_STATE_SHUTDOWN;
556 		device_printf(sc->mlx_sysdrive[i].ms_disk, "still open, can't shutdown\n");
557 		error = EBUSY;
558 		goto out;
559 	    }
560 	}
561     }
562 
563     /* flush controller */
564     device_printf(sc->mlx_dev, "flushing cache...");
565     if (mlx_flush(sc)) {
566 	printf("failed\n");
567     } else {
568 	printf("done\n");
569     }
570 
571     /* delete all our child devices */
572     for (i = 0; i < MLX_MAXDRIVES; i++) {
573 	if (sc->mlx_sysdrive[i].ms_disk != 0) {
574 	    if ((error = device_delete_child(sc->mlx_dev, sc->mlx_sysdrive[i].ms_disk)) != 0)
575 		goto out;
576 	    sc->mlx_sysdrive[i].ms_disk = 0;
577 	}
578     }
579 
580     bus_generic_detach(sc->mlx_dev);
581 
582  out:
583     splx(s);
584     return(error);
585 }
586 
587 /********************************************************************************
588  * Bring the controller to a quiescent state, ready for system suspend.
589  */
590 int
591 mlx_suspend(device_t dev)
592 {
593     struct mlx_softc	*sc = device_get_softc(dev);
594     int			s;
595 
596     debug("called");
597 
598     s = splbio();
599     sc->mlx_state |= MLX_STATE_SUSPEND;
600 
601     /* flush controller */
602     device_printf(sc->mlx_dev, "flushing cache...");
603     printf("%s\n", mlx_flush(sc) ? "failed" : "done");
604 
605     sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
606     splx(s);
607 
608     return(0);
609 }
610 
611 /********************************************************************************
612  * Bring the controller back to a state ready for operation.
613  */
614 int
615 mlx_resume(device_t dev)
616 {
617     struct mlx_softc	*sc = device_get_softc(dev);
618 
619     debug("called");
620 
621     sc->mlx_state &= ~MLX_STATE_SUSPEND;
622     sc->mlx_intaction(sc, MLX_INTACTION_ENABLE);
623 
624     return(0);
625 }
626 
627 /*******************************************************************************
628  * Take an interrupt, or be poked by other code to look for interrupt-worthy
629  * status.
630  */
631 void
632 mlx_intr(void *arg)
633 {
634     struct mlx_softc	*sc = (struct mlx_softc *)arg;
635     int			worked;
636 
637     debug("called");
638 
639     /* spin collecting finished commands */
640     worked = 0;
641     while (mlx_done(sc))
642 	worked = 1;
643 
644     /* did we do anything? */
645     if (worked)
646 	mlx_complete(sc);
647 };
648 
649 /*******************************************************************************
650  * Receive a buf structure from a child device and queue it on a particular
651  * disk resource, then poke the disk resource to start as much work as it can.
652  */
653 int
654 mlx_submit_buf(struct mlx_softc *sc, struct buf *bp)
655 {
656     int		s;
657 
658     debug("called");
659 
660     s = splbio();
661     bufq_insert_tail(&sc->mlx_bufq, bp);
662     sc->mlx_waitbufs++;
663     splx(s);
664     mlx_startio(sc);
665     return(0);
666 }
667 
668 /********************************************************************************
669  * Accept an open operation on the control device.
670  */
671 int
672 mlx_open(dev_t dev, int flags, int fmt, struct proc *p)
673 {
674     int			unit = minor(dev);
675     struct mlx_softc	*sc = devclass_get_softc(mlx_devclass, unit);
676 
677     sc->mlx_state |= MLX_STATE_OPEN;
678     return(0);
679 }
680 
681 /********************************************************************************
682  * Accept the last close on the control device.
683  */
684 int
685 mlx_close(dev_t dev, int flags, int fmt, struct proc *p)
686 {
687     int			unit = minor(dev);
688     struct mlx_softc	*sc = devclass_get_softc(mlx_devclass, unit);
689 
690     sc->mlx_state &= ~MLX_STATE_OPEN;
691     return (0);
692 }
693 
694 /********************************************************************************
695  * Handle controller-specific control operations.
696  */
697 int
698 mlx_ioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
699 {
700     int			unit = minor(dev);
701     struct mlx_softc	*sc = devclass_get_softc(mlx_devclass, unit);
702     int			*arg = (int *)addr;
703     struct mlx_pause	*mp;
704     struct mlx_sysdrive	*dr;
705     struct mlxd_softc	*mlxd;
706     int			i, error;
707 
708     switch(cmd) {
709 	/*
710 	 * Enumerate connected system drives; returns the first system drive's
711 	 * unit number if *arg is -1, or the next unit after *arg if it's
712 	 * a valid unit on this controller.
713 	 */
714     case MLX_NEXT_CHILD:
715 	/* search system drives */
716 	for (i = 0; i < MLX_MAXDRIVES; i++) {
717 	    /* is this one attached? */
718 	    if (sc->mlx_sysdrive[i].ms_disk != 0) {
719 		/* looking for the next one we come across? */
720 		if (*arg == -1) {
721 		    *arg = device_get_unit(sc->mlx_sysdrive[i].ms_disk);
722 		    return(0);
723 		}
724 		/* we want the one after this one */
725 		if (*arg == device_get_unit(sc->mlx_sysdrive[i].ms_disk))
726 		    *arg = -1;
727 	    }
728 	}
729 	return(ENOENT);
730 
731 	/*
732 	 * Scan the controller to see whether new drives have appeared.
733 	 */
734     case MLX_RESCAN_DRIVES:
735 	mlx_startup(sc);
736 	return(0);
737 
738 	/*
739 	 * Disconnect from the specified drive; it may be about to go
740 	 * away.
741 	 */
742     case MLX_DETACH_DRIVE:			/* detach one drive */
743 
744 	if (((dr = mlx_findunit(sc, *arg)) == NULL) ||
745 	    ((mlxd = device_get_softc(dr->ms_disk)) == NULL))
746 	    return(ENOENT);
747 
748 	device_printf(dr->ms_disk, "detaching...");
749 	error = 0;
750 	if (mlxd->mlxd_flags & MLXD_OPEN) {
751 	    error = EBUSY;
752 	    goto detach_out;
753 	}
754 
755 	/* flush controller */
756 	if (mlx_flush(sc)) {
757 	    error = EBUSY;
758 	    goto detach_out;
759 	}
760 
761 	/* nuke drive */
762 	if ((error = device_delete_child(sc->mlx_dev, dr->ms_disk)) != 0)
763 	    goto detach_out;
764 	dr->ms_disk = 0;
765 	bus_generic_detach(sc->mlx_dev);
766 
767     detach_out:
768 	if (error) {
769 	    printf("failed\n");
770 	} else {
771 	    printf("done\n");
772 	}
773 	return(error);
774 
775 	/*
776 	 * Pause one or more SCSI channels for a period of time, to assist
777 	 * in the process of hot-swapping devices.
778 	 *
779 	 * Note that at least the 3.51 firmware on the DAC960PL doesn't seem
780 	 * to do this right.
781 	 */
782     case MLX_PAUSE_CHANNEL:			/* schedule a channel pause */
783 	/* Does this command work on this firmware? */
784 	if (!(sc->mlx_feature & MLX_FEAT_PAUSEWORKS))
785 	    return(EOPNOTSUPP);
786 
787 	mp = (struct mlx_pause *)addr;
788 	if ((mp->mp_which == MLX_PAUSE_CANCEL) && (sc->mlx_pause.mp_when != 0)) {
789 	    /* cancel a pending pause operation */
790 	    sc->mlx_pause.mp_which = 0;
791 	} else {
792 	    /* fix for legal channels */
793 	    mp->mp_which &= ((1 << sc->mlx_nchan) -1);
794 	    /* check time values */
795 	    if ((mp->mp_when < 0) || (mp->mp_when > 3600))
796 		return(EINVAL);
797 	    if ((mp->mp_howlong < 1) || (mp->mp_howlong > (0xf * 30)))
798 		return(EINVAL);
799 
800 	    /* check for a pause currently running */
801 	    if ((sc->mlx_pause.mp_which != 0) && (sc->mlx_pause.mp_when == 0))
802 		return(EBUSY);
803 
804 	    /* looks ok, go with it */
805 	    sc->mlx_pause.mp_which = mp->mp_which;
806 	    sc->mlx_pause.mp_when = time_second + mp->mp_when;
807 	    sc->mlx_pause.mp_howlong = sc->mlx_pause.mp_when + mp->mp_howlong;
808 	}
809 	return(0);
810 
811 	/*
812 	 * Accept a command passthrough-style.
813 	 */
814     case MLX_COMMAND:
815 	return(mlx_user_command(sc, (struct mlx_usercommand *)addr));
816 
817     default:
818 	return(ENOTTY);
819     }
820 }
821 
822 /********************************************************************************
823  * Handle operations requested by a System Drive connected to this controller.
824  */
825 int
826 mlx_submit_ioctl(struct mlx_softc *sc, struct mlx_sysdrive *drive, u_long cmd,
827 		caddr_t addr, int32_t flag, struct proc *p)
828 {
829     struct mlxd_rebuild		*mr = (struct mlxd_rebuild *)addr;
830     struct mlxd_rebuild_status	*mp = (struct mlxd_rebuild_status *)addr;
831     int				*arg = (int *)addr;
832     int				error;
833 
834     switch(cmd) {
835 	/*
836 	 * Return the current status of this drive.
837 	 */
838     case MLXD_STATUS:
839 	*arg = drive->ms_state;
840 	return(0);
841 
842 	/*
843 	 * Start a background rebuild on this drive.
844 	 */
845     case MLXD_REBUILDASYNC:
846 	/* XXX lock? */
847 	if (sc->mlx_rebuild >= 0)
848 	    return(EBUSY);
849 	sc->mlx_rebuild = drive - &sc->mlx_sysdrive[0];
850 
851 	switch (mlx_rebuild(sc, mr->rb_channel, mr->rb_target)) {
852 	case 0:
853 	    drive->ms_state = MLX_SYSD_REBUILD;
854 	    error = 0;
855 	    break;
856 	case 0x10000:
857 	    error = ENOMEM;		/* couldn't set up the command */
858 	    break;
859 	case 0x0002:
860 	case 0x0106:
861 	    error = EBUSY;
862 	    break;
863 	case 0x0004:
864 	    error = EIO;
865 	    break;
866 	case 0x0105:
867 	    error = ERANGE;
868 	    break;
869 	default:
870 	    error = EINVAL;
871 	    break;
872 	}
873 	if (error != 0)
874 	    sc->mlx_rebuild = -1;
875 	return(error);
876 
877 	/*
878 	 * Start a background consistency check on this drive.
879 	 */
880     case MLXD_CHECKASYNC:		/* start a background consistency check */
881 	/* XXX implement */
882 	break;
883 
884 	/*
885 	 * Get the status of the current rebuild or consistency check.
886 	 */
887     case MLXD_REBUILDSTAT:
888 
889 	if (sc->mlx_rebuild >= 0) {	/* may be a second or so out of date */
890 	    mp->rs_drive = sc->mlx_rebuild;
891 	    mp->rs_size = sc->mlx_sysdrive[sc->mlx_rebuild].ms_size;
892 	    mp->rs_remaining = sc->mlx_rebuildstat;
893 	    return(0);
894 	} else if (sc->mlx_check >= 0) {
895 	    /* XXX implement */
896 	} else {
897 	    /* XXX should return status of last completed operation? */
898 	    return(EINVAL);
899 	}
900 
901     }
902     return(ENOIOCTL);
903 }
904 
905 
906 /********************************************************************************
907  ********************************************************************************
908                                                                 Status Monitoring
909  ********************************************************************************
910  ********************************************************************************/
911 
912 #define MLX_PERIODIC_ISBUSY(sc)	(sc->mlx_polling <= 0)
913 #define MLX_PERIODIC_BUSY(sc)	atomic_add_int(&sc->mlx_polling, 1);
914 #define MLX_PERIODIC_UNBUSY(sc) atomic_subtract_int(&sc->mlx_polling, 1);
915 
916 /********************************************************************************
917  * Fire off commands to periodically check the status of connected drives.
918  */
919 static void
920 mlx_periodic(void *data)
921 {
922     struct mlx_softc *sc = (struct mlx_softc *)data;
923 
924     debug("called");
925 
926     /*
927      * Run a bus pause?
928      */
929     if ((sc->mlx_pause.mp_which != 0) &&
930 	(sc->mlx_pause.mp_when > 0) &&
931 	(time_second >= sc->mlx_pause.mp_when)){
932 
933 	mlx_pause_action(sc);		/* pause is running */
934 	sc->mlx_pause.mp_when = 0;
935 	sysbeep(500, hz);
936 
937 	/*
938 	 * Bus pause still running?
939 	 */
940     } else if ((sc->mlx_pause.mp_which != 0) &&
941 	       (sc->mlx_pause.mp_when == 0)) {
942 
943 	/* time to stop bus pause? */
944 	if (time_second >= sc->mlx_pause.mp_howlong) {
945 	    mlx_pause_action(sc);
946 	    sc->mlx_pause.mp_which = 0;	/* pause is complete */
947 	    sysbeep(500, hz);
948 	} else {
949 	    sysbeep((time_second % 5) * 100 + 500, hz/8);
950 	}
951 
952 	/*
953 	 * Run normal periodic activities?
954 	 */
955     } else if (MLX_PERIODIC_ISBUSY(sc)) {
956 
957 	/* time to perform a periodic status poll? XXX tuneable interval? */
958 	if (time_second > (sc->mlx_lastpoll + 10)) {
959 	    sc->mlx_lastpoll = time_second;
960 
961 	    /* for caution's sake */
962 	    if (sc->mlx_polling < 0) {
963 		device_printf(sc->mlx_dev, "mlx_polling < 0\n");
964 		atomic_set_int(&sc->mlx_polling, 0);
965 	    }
966 
967 	    /*
968 	     * Check controller status.
969 	     */
970 	    MLX_PERIODIC_BUSY(sc);
971 	    mlx_enquire(sc, MLX_CMD_ENQUIRY, sizeof(struct mlx_enquiry), mlx_periodic_enquiry);
972 
973 	    /*
974 	     * Check system drive status.
975 	     *
976 	     * XXX This might be better left to event-driven detection, eg. I/O to an offline
977 	     *     drive will detect it's offline, rebuilds etc. should detect the drive is back
978 	     *     online.
979 	     */
980 	    MLX_PERIODIC_BUSY(sc);
981 	    mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(struct mlx_enq_sys_drive) * MLX_MAXDRIVES,
982 			mlx_periodic_enquiry);
983 	}
984 
985 	/*
986 	 * Get drive rebuild/check status
987 	 */
988 	if (sc->mlx_rebuild >= 0) {
989 	    MLX_PERIODIC_BUSY(sc);
990 	    mlx_enquire(sc, MLX_CMD_REBUILDSTAT, sizeof(struct mlx_rebuild_stat), mlx_periodic_rebuild);
991 	}
992     } else {
993 	/*
994 	 * If things are still running from the last poll, complain about it.
995 	 *
996 	 * XXX If this becomes an issue, we should have some way of telling what
997 	 *     has become stuck.
998 	 */
999 	device_printf(sc->mlx_dev, "poll still busy (%d)\n", sc->mlx_polling);
1000     }
1001 
1002     /* XXX check for wedged/timed out commands? */
1003 
1004     /* reschedule another poll next second or so */
1005     sc->mlx_timeout = timeout(mlx_periodic, sc, hz);
1006 }
1007 
1008 /********************************************************************************
1009  * Handle the result of an ENQUIRY command instigated by periodic status polling.
1010  */
1011 static void
1012 mlx_periodic_enquiry(struct mlx_command *mc)
1013 {
1014     struct mlx_softc		*sc = mc->mc_sc;
1015 
1016     debug("called");
1017 
1018     /* Command completed OK? */
1019     if (mc->mc_status != 0) {
1020 	device_printf(sc->mlx_dev, "periodic enquiry failed\n");
1021 	goto out;
1022     }
1023 
1024     /* respond to command */
1025     switch(mc->mc_mailbox[0]) {
1026 	/*
1027 	 * Generic controller status update.  We could do more with this than just
1028 	 * checking the event log.
1029 	 */
1030     case MLX_CMD_ENQUIRY:
1031     {
1032 	struct mlx_enquiry		*me = (struct mlx_enquiry *)mc->mc_data;
1033 
1034 	/* New stuff in the event log? */
1035 	if (me->me_event_log_seq_num != sc->mlx_lastevent) {
1036 	    /* record where current events are up to */
1037 	    sc->mlx_currevent = me->me_event_log_seq_num;
1038 	    device_printf(sc->mlx_dev, "event log pointer was %d, now %d\n",
1039 			  sc->mlx_lastevent, sc->mlx_currevent);
1040 
1041 	    /* start poll of event log */
1042 	    mlx_periodic_eventlog_poll(sc);
1043 	}
1044 	break;
1045     }
1046     case MLX_CMD_ENQSYSDRIVE:
1047     {
1048 	struct mlx_enq_sys_drive	*mes = (struct mlx_enq_sys_drive *)mc->mc_data;
1049 	struct mlx_sysdrive		*dr;
1050 	int				i;
1051 
1052 	for (i = 0, dr = &sc->mlx_sysdrive[0];
1053 	     (i < MLX_MAXDRIVES) && (mes[i].sd_size != 0xffffffff);
1054 	     i++) {
1055 
1056 	    /* if disk is being rebuilt, we should not check it */
1057 	    if (dr->ms_state == MLX_SYSD_REBUILD) {
1058 		/* has state been changed by controller? */
1059 		if (dr->ms_state != mes[i].sd_state) {
1060 		    switch(mes[i].sd_state) {
1061 		    case MLX_SYSD_OFFLINE:
1062 			device_printf(dr->ms_disk, "drive offline\n");
1063 			break;
1064 		    case MLX_SYSD_ONLINE:
1065 			device_printf(dr->ms_disk, "drive online\n");
1066 			break;
1067 		    case MLX_SYSD_CRITICAL:
1068 			device_printf(dr->ms_disk, "drive critical\n");
1069 			break;
1070 		    }
1071 		    /* save new state */
1072 		    dr->ms_state = mes[i].sd_state;
1073 		}
1074 	    }
1075 	}
1076 	break;
1077     }
1078     default:
1079 	break;
1080     }
1081 
1082  out:
1083     free(mc->mc_data, M_DEVBUF);
1084     mlx_releasecmd(mc);
1085     /* this event is done */
1086     MLX_PERIODIC_UNBUSY(sc);
1087 }
1088 
1089 /********************************************************************************
1090  * Instigate a poll for one event log message on (sc).
1091  * We only poll for one message at a time, to keep our command usage down.
1092  */
1093 static void
1094 mlx_periodic_eventlog_poll(struct mlx_softc *sc)
1095 {
1096     struct mlx_command	*mc;
1097     void		*result = NULL;
1098     int			error;
1099 
1100     debug("called");
1101 
1102     /* presume we are going to create another event */
1103     MLX_PERIODIC_BUSY(sc);
1104 
1105     /* get ourselves a command buffer */
1106     error = 1;
1107     if ((mc = mlx_alloccmd(sc)) == NULL)
1108 	goto out;
1109     /* allocate the response structure */
1110     if ((result = malloc(/*sizeof(struct mlx_eventlog_entry)*/1024, M_DEVBUF, M_NOWAIT)) == NULL)
1111 	goto out;
1112     /* get a command slot */
1113     if (mlx_getslot(mc))
1114 	goto out;
1115 
1116     /* map the command so the controller can see it */
1117     mc->mc_data = result;
1118     mc->mc_length = /*sizeof(struct mlx_eventlog_entry)*/1024;
1119     mlx_mapcmd(mc);
1120 
1121     /* build the command to get one entry */
1122     mlx_make_type3(mc, MLX_CMD_LOGOP, MLX_LOGOP_GET, 1, sc->mlx_lastevent, 0, 0, mc->mc_dataphys, 0);
1123     mc->mc_complete = mlx_periodic_eventlog_respond;
1124     mc->mc_private = mc;
1125 
1126     /* start the command */
1127     if ((error = mlx_start(mc)) != 0)
1128 	goto out;
1129 
1130     error = 0;			/* success */
1131  out:
1132     if (error != 0) {
1133 	if (mc != NULL)
1134 	    mlx_releasecmd(mc);
1135 	if (result != NULL)
1136 	    free(result, M_DEVBUF);
1137 	/* abort this event */
1138 	MLX_PERIODIC_UNBUSY(sc);
1139     }
1140 }
1141 
1142 /********************************************************************************
1143  * Handle the result of polling for a log message, generate diagnostic output.
1144  * If this wasn't the last message waiting for us, we'll go collect another.
1145  */
1146 static char *mlx_sense_messages[] = {
1147     "because write recovery failed",
1148     "because of SCSI bus reset failure",
1149     "because of double check condition",
1150     "because it was removed",
1151     "because of gross error on SCSI chip",
1152     "because of bad tag returned from drive",
1153     "because of timeout on SCSI command",
1154     "because of reset SCSI command issued from system",
1155     "because busy or parity error count exceeded limit",
1156     "because of 'kill drive' command from system",
1157     "because of selection timeout",
1158     "due to SCSI phase sequence error",
1159     "due to unknown status"
1160 };
1161 
1162 static void
1163 mlx_periodic_eventlog_respond(struct mlx_command *mc)
1164 {
1165     struct mlx_softc		*sc = mc->mc_sc;
1166     struct mlx_eventlog_entry	*el = (struct mlx_eventlog_entry *)mc->mc_data;
1167     char			*reason;
1168 
1169     debug("called");
1170 
1171     if (mc->mc_status == 0) {
1172 	sc->mlx_lastevent++;		/* got the message OK */
1173 
1174 	/* handle event log message */
1175 	switch(el->el_type) {
1176 	    /*
1177 	     * This is the only sort of message we understand at the moment.
1178 	     * The tests here are probably incomplete.
1179 	     */
1180 	case MLX_LOGMSG_SENSE:	/* sense data */
1181 	    /* Mylex vendor-specific message indicating a drive was killed? */
1182 	    if ((el->el_sensekey == 9) &&
1183 		(el->el_asc == 0x80)) {
1184 		if (el->el_asq < (sizeof(mlx_sense_messages) / sizeof(mlx_sense_messages[0]))) {
1185 		    reason = mlx_sense_messages[el->el_asq];
1186 		} else {
1187 		    reason = "for unknown reason";
1188 		}
1189 		device_printf(sc->mlx_dev, "physical drive %d:%d killed %s\n",
1190 			      el->el_channel, el->el_target, reason);
1191 	    }
1192 	    /* SCSI drive was reset? */
1193 	    if ((el->el_sensekey == 6) && (el->el_asc == 0x29)) {
1194 		device_printf(sc->mlx_dev, "physical drive %d:%d reset\n",
1195 			      el->el_channel, el->el_target);
1196 	    }
1197 	    /* SCSI drive error? */
1198 	    if (!((el->el_sensekey == 0) ||
1199 		  ((el->el_sensekey == 2) &&
1200 		   (el->el_asc == 0x04) &&
1201 		   ((el->el_asq == 0x01) ||
1202 		    (el->el_asq == 0x02))))) {
1203 		device_printf(sc->mlx_dev, "physical drive %d:%d error log: sense = %d asc = %x asq = %x\n",
1204 			      el->el_channel, el->el_target, el->el_sensekey, el->el_asc, el->el_asq);
1205 		device_printf(sc->mlx_dev, "  info %4D csi %4D\n", el->el_information, ":", el->el_csi, ":");
1206 	    }
1207 	    break;
1208 
1209 	default:
1210 	    device_printf(sc->mlx_dev, "unknown log message type 0x%x\n", el->el_type);
1211 	    break;
1212 	}
1213     } else {
1214 	device_printf(sc->mlx_dev, "error reading message log - %s\n", mlx_diagnose_command(mc));
1215     }
1216 
1217     /* dispose of command and data */
1218     free(mc->mc_data, M_DEVBUF);
1219     mlx_releasecmd(mc);
1220 
1221     /* is there another message to obtain? */
1222     if (sc->mlx_lastevent != sc->mlx_currevent)
1223 	mlx_periodic_eventlog_poll(sc);
1224 
1225     /* this event is done */
1226     MLX_PERIODIC_UNBUSY(sc);
1227 }
1228 
1229 /********************************************************************************
1230  * Handle the completion of a rebuild operation.
1231  */
1232 static void
1233 mlx_periodic_rebuild(struct mlx_command *mc)
1234 {
1235     struct mlx_softc		*sc = mc->mc_sc;
1236     struct mlx_rebuild_stat	*mr = (struct mlx_rebuild_stat *)mc->mc_private;
1237 
1238     switch(mc->mc_status) {
1239     case 0:				/* all OK, rebuild still running */
1240 	sc->mlx_rebuildstat = mr->rb_remaining;
1241 	break;
1242 
1243     case 0x0105:			/* rebuild/check finished */
1244 	if (sc->mlx_rebuild >= 0) {
1245 	    device_printf(sc->mlx_sysdrive[sc->mlx_rebuild].ms_disk, "rebuild completed\n");
1246 	    sc->mlx_rebuild = -1;
1247 	} else if (sc->mlx_check >= 0) {
1248 	    device_printf(sc->mlx_sysdrive[sc->mlx_check].ms_disk, "consistency check completed\n");
1249 	    sc->mlx_check = -1;
1250 	} else {
1251 	    device_printf(sc->mlx_dev, "consistency check completed\n");
1252 	}
1253 	break;
1254     }
1255     free(mc->mc_data, M_DEVBUF);
1256     mlx_releasecmd(mc);
1257     /* this event is done */
1258     MLX_PERIODIC_UNBUSY(sc);
1259 }
1260 
1261 /********************************************************************************
1262  ********************************************************************************
1263                                                                     Channel Pause
1264  ********************************************************************************
1265  ********************************************************************************/
1266 
1267 /********************************************************************************
1268  * It's time to perform a channel pause action for (sc), either start or stop
1269  * the pause.
1270  */
1271 static void
1272 mlx_pause_action(struct mlx_softc *sc)
1273 {
1274     struct mlx_command	*mc;
1275     int			failsafe, i, command;
1276 
1277     /* What are we doing here? */
1278     if (sc->mlx_pause.mp_when == 0) {
1279 	command = MLX_CMD_STARTCHANNEL;
1280 	failsafe = 0;
1281 
1282     } else {
1283 	command = MLX_CMD_STOPCHANNEL;
1284 
1285 	/*
1286 	 * Channels will always start again after the failsafe period,
1287 	 * which is specified in multiples of 30 seconds.
1288 	 * This constrains us to a maximum pause of 450 seconds.
1289 	 */
1290 	failsafe = ((sc->mlx_pause.mp_howlong - time_second) + 5) / 30;
1291 	if (failsafe > 0xf) {
1292 	    failsafe = 0xf;
1293 	    sc->mlx_pause.mp_howlong = time_second + (0xf * 30) - 5;
1294 	}
1295     }
1296 
1297     /* build commands for every channel requested */
1298     for (i = 0; i < sc->mlx_nchan; i++) {
1299 	if ((1 << i) & sc->mlx_pause.mp_which) {
1300 
1301 	    /* get ourselves a command buffer */
1302 	    if ((mc = mlx_alloccmd(sc)) == NULL)
1303 		goto fail;
1304 	    /* get a command slot */
1305 	    mc->mc_flags |= MLX_CMD_PRIORITY;
1306 	    if (mlx_getslot(mc))
1307 		goto fail;
1308 
1309 	    /* build the command */
1310 	    mlx_make_type2(mc, command, (failsafe << 4) | i, 0, 0, 0, 0, 0, 0, 0);
1311 	    mc->mc_complete = mlx_pause_done;
1312 	    mc->mc_private = sc;		/* XXX not needed */
1313 	    if (mlx_start(mc))
1314 		goto fail;
1315 	    /* command submitted OK */
1316 	    return;
1317 
1318 	fail:
1319 	    device_printf(sc->mlx_dev, "%s failed for channel %d\n",
1320 			  command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", i);
1321 	    if (mc != NULL)
1322 		mlx_releasecmd(mc);
1323 	}
1324     }
1325 }
1326 
1327 static void
1328 mlx_pause_done(struct mlx_command *mc)
1329 {
1330     struct mlx_softc	*sc = mc->mc_sc;
1331     int			command = mc->mc_mailbox[0];
1332     int			channel = mc->mc_mailbox[2] & 0xf;
1333 
1334     if (mc->mc_status != 0) {
1335 	device_printf(sc->mlx_dev, "%s command failed - %s\n",
1336 		      command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", mlx_diagnose_command(mc));
1337     } else if (command == MLX_CMD_STOPCHANNEL) {
1338 	device_printf(sc->mlx_dev, "channel %d pausing for %ld seconds\n",
1339 		      channel, sc->mlx_pause.mp_howlong - time_second);
1340     } else {
1341 	device_printf(sc->mlx_dev, "channel %d resuming\n", channel);
1342     }
1343     mlx_releasecmd(mc);
1344 }
1345 
1346 /********************************************************************************
1347  ********************************************************************************
1348                                                                Command Submission
1349  ********************************************************************************
1350  ********************************************************************************/
1351 
1352 /********************************************************************************
1353  * Perform an Enquiry command using a type-3 command buffer and a return a single
1354  * linear result buffer.  If the completion function is specified, it will
1355  * be called with the completed command (and the result response will not be
1356  * valid until that point).  Otherwise, the command will either be busy-waited
1357  * for (interrupts not enabled), or slept for.
1358  */
1359 static void *
1360 mlx_enquire(struct mlx_softc *sc, int command, size_t bufsize, void (* complete)(struct mlx_command *mc))
1361 {
1362     struct mlx_command	*mc;
1363     void		*result;
1364     int			error;
1365 
1366     debug("called");
1367 
1368     /* get ourselves a command buffer */
1369     error = 1;
1370     result = NULL;
1371     if ((mc = mlx_alloccmd(sc)) == NULL)
1372 	goto out;
1373     /* allocate the response structure */
1374     if ((result = malloc(bufsize, M_DEVBUF, M_NOWAIT)) == NULL)
1375 	goto out;
1376     /* get a command slot */
1377     mc->mc_flags |= MLX_CMD_PRIORITY | MLX_CMD_DATAOUT;
1378     if (mlx_getslot(mc))
1379 	goto out;
1380 
1381     /* map the command so the controller can see it */
1382     mc->mc_data = result;
1383     mc->mc_length = bufsize;
1384     mlx_mapcmd(mc);
1385 
1386     /* build an enquiry command */
1387     mlx_make_type2(mc, command, 0, 0, 0, 0, 0, 0, mc->mc_dataphys, 0);
1388 
1389     /* do we want a completion callback? */
1390     if (complete != NULL) {
1391 	mc->mc_complete = complete;
1392 	mc->mc_private = mc;
1393 	if ((error = mlx_start(mc)) != 0)
1394 	    goto out;
1395     } else {
1396 	/* run the command in either polled or wait mode */
1397 	if ((sc->mlx_state & MLX_STATE_INTEN) ? mlx_wait_command(mc) : mlx_poll_command(mc))
1398 	    goto out;
1399 
1400 	/* command completed OK? */
1401 	if (mc->mc_status != 0) {
1402 	    device_printf(sc->mlx_dev, "ENQUIRY failed - %s\n", mlx_diagnose_command(mc));
1403 	    goto out;
1404 	}
1405     }
1406     error = 0;			/* success */
1407  out:
1408     /* we got a command, but nobody else will free it */
1409     if ((complete == NULL) && (mc != NULL))
1410 	mlx_releasecmd(mc);
1411     /* we got an error, and we allocated a result */
1412     if ((error != 0) && (result != NULL)) {
1413 	free(result, M_DEVBUF);
1414 	result = NULL;
1415     }
1416     return(result);
1417 }
1418 
1419 
1420 /********************************************************************************
1421  * Perform a Flush command on the nominated controller.
1422  *
1423  * May be called with interrupts enabled or disabled; will not return until
1424  * the flush operation completes or fails.
1425  */
1426 static int
1427 mlx_flush(struct mlx_softc *sc)
1428 {
1429     struct mlx_command	*mc;
1430     int			error;
1431 
1432     debug("called");
1433 
1434     /* get ourselves a command buffer */
1435     error = 1;
1436     if ((mc = mlx_alloccmd(sc)) == NULL)
1437 	goto out;
1438     /* get a command slot */
1439     if (mlx_getslot(mc))
1440 	goto out;
1441 
1442     /* build a flush command */
1443     mlx_make_type2(mc, MLX_CMD_FLUSH, 0, 0, 0, 0, 0, 0, 0, 0);
1444 
1445     /* run the command in either polled or wait mode */
1446     if ((sc->mlx_state & MLX_STATE_INTEN) ? mlx_wait_command(mc) : mlx_poll_command(mc))
1447 	goto out;
1448 
1449     /* command completed OK? */
1450     if (mc->mc_status != 0) {
1451 	device_printf(sc->mlx_dev, "FLUSH failed - %s\n", mlx_diagnose_command(mc));
1452 	goto out;
1453     }
1454 
1455     error = 0;			/* success */
1456  out:
1457     if (mc != NULL)
1458 	mlx_releasecmd(mc);
1459     return(error);
1460 }
1461 
1462 /********************************************************************************
1463  * Start a background rebuild on the nominated controller/channel/target.
1464  *
1465  * May be called with interrupts enabled or disabled; will return as soon as the
1466  * operation has started or been refused.
1467  */
1468 static int
1469 mlx_rebuild(struct mlx_softc *sc, int channel, int target)
1470 {
1471     struct mlx_command	*mc;
1472     int			error;
1473 
1474     debug("called");
1475 
1476     /* get ourselves a command buffer */
1477     error = 0x10000;
1478     if ((mc = mlx_alloccmd(sc)) == NULL)
1479 	goto out;
1480     /* get a command slot */
1481     if (mlx_getslot(mc))
1482 	goto out;
1483 
1484     /* build a rebuild command */
1485     mlx_make_type2(mc, MLX_CMD_REBUILDASYNC, channel, target, 0, 0, 0, 0, 0, 0);
1486 
1487     /* run the command in either polled or wait mode */
1488     if ((sc->mlx_state & MLX_STATE_INTEN) ? mlx_wait_command(mc) : mlx_poll_command(mc))
1489 	goto out;
1490 
1491     /* command completed OK? */
1492     if (mc->mc_status != 0) {
1493 	device_printf(sc->mlx_dev, "REBUILD ASYNC failed - %s\n", mlx_diagnose_command(mc));
1494     } else {
1495 	device_printf(sc->mlx_sysdrive[sc->mlx_rebuild].ms_disk, "rebuild started");
1496     }
1497     error = mc->mc_status;
1498 
1499  out:
1500     if (mc != NULL)
1501 	mlx_releasecmd(mc);
1502     return(error);
1503 }
1504 
1505 /********************************************************************************
1506  * Run the command (mc) and return when it completes.
1507  *
1508  * Interrupts need to be enabled; returns nonzero on error.
1509  */
1510 static int
1511 mlx_wait_command(struct mlx_command *mc)
1512 {
1513     struct mlx_softc	*sc = mc->mc_sc;
1514     int			error, count;
1515 
1516     debug("called");
1517 
1518     mc->mc_complete = NULL;
1519     mc->mc_private = mc;		/* wake us when you're done */
1520     if ((error = mlx_start(mc)) != 0)
1521 	return(error);
1522 
1523     count = 0;
1524     /* XXX better timeout? */
1525     while ((mc->mc_status == MLX_STATUS_BUSY) && (count < 30)) {
1526 	tsleep(mc->mc_private, PRIBIO | PCATCH, "mlxwcmd", hz);
1527     }
1528 
1529     if (mc->mc_status != 0) {
1530 	device_printf(sc->mlx_dev, "I/O error 0x%x\n", mc->mc_status);
1531 	return(EIO);
1532     }
1533     return(0);
1534 }
1535 
1536 
1537 /********************************************************************************
1538  * Start the command (mc) and busy-wait for it to complete.
1539  *
1540  * Should only be used when interrupts are not available. Returns 0 on
1541  * success, nonzero on error.
1542  * Successfully completed commands are dequeued.
1543  */
1544 static int
1545 mlx_poll_command(struct mlx_command *mc)
1546 {
1547     struct mlx_softc	*sc = mc->mc_sc;
1548     int			error, count, s;
1549 
1550     debug("called");
1551 
1552     mc->mc_complete = NULL;
1553     mc->mc_private = NULL;	/* we will poll for it */
1554     if ((error = mlx_start(mc)) != 0)
1555 	return(error);
1556 
1557     count = 0;
1558     do {
1559 	/* poll for completion */
1560 	mlx_done(mc->mc_sc);
1561     } while ((mc->mc_status == MLX_STATUS_BUSY) && (count < 10000));
1562     if (mc->mc_status != MLX_STATUS_BUSY) {
1563 	s = splbio();
1564 	TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
1565 	splx(s);
1566 	return(0);
1567     }
1568     device_printf(sc->mlx_dev, "I/O error 0x%x\n", mc->mc_status);
1569     return(EIO);
1570 }
1571 
1572 /********************************************************************************
1573  * Pull as much work off the softc's work queue as possible and give it to the
1574  * controller.  Leave a couple of slots free for emergencies.
1575  *
1576  * Must be called at splbio or in an equivalent fashion that prevents
1577  * reentry or activity on the bufq..
1578  */
1579 static void
1580 mlx_startio(struct mlx_softc *sc)
1581 {
1582     struct mlx_command	*mc;
1583     struct mlxd_softc	*mlxd;
1584     struct buf		*bp;
1585     int			blkcount;
1586     int			driveno;
1587     int			cmd;
1588     int			s;
1589 
1590     /* spin until something prevents us from doing any work */
1591     s = splbio();
1592     for (;;) {
1593 
1594 	/* see if there's work to be done */
1595 	if ((bp = bufq_first(&sc->mlx_bufq)) == NULL)
1596 	    break;
1597 	/* get a command */
1598 	if ((mc = mlx_alloccmd(sc)) == NULL)
1599 	    break;
1600 	/* get a slot for the command */
1601 	if (mlx_getslot(mc) != 0) {
1602 	    mlx_releasecmd(mc);
1603 	    break;
1604 	}
1605 	/* get the buf containing our work */
1606 	bufq_remove(&sc->mlx_bufq, bp);
1607 	sc->mlx_waitbufs--;
1608 	splx(s);
1609 
1610 	/* connect the buf to the command */
1611 	mc->mc_complete = mlx_completeio;
1612 	mc->mc_private = bp;
1613 	mc->mc_data = bp->b_data;
1614 	mc->mc_length = bp->b_bcount;
1615 	if (bp->b_flags & B_READ) {
1616 	    mc->mc_flags |= MLX_CMD_DATAIN;
1617 	    cmd = MLX_CMD_READOLDSG;
1618 	} else {
1619 	    mc->mc_flags |= MLX_CMD_DATAOUT;
1620 	    cmd = MLX_CMD_WRITEOLDSG;
1621 	}
1622 
1623 	/* map the command so the controller can work with it */
1624 	mlx_mapcmd(mc);
1625 
1626 	/* build a suitable I/O command (assumes 512-byte rounded transfers) */
1627 	mlxd = (struct mlxd_softc *)bp->b_dev->si_drv1;
1628 	driveno = mlxd->mlxd_drive - &sc->mlx_sysdrive[0];
1629 	blkcount = bp->b_bcount / MLX_BLKSIZE;
1630 
1631 	if ((bp->b_pblkno + blkcount) > sc->mlx_sysdrive[driveno].ms_size)
1632 	    device_printf(sc->mlx_dev, "I/O beyond end of unit (%u,%d > %u)\n",
1633 			  bp->b_pblkno, blkcount, sc->mlx_sysdrive[driveno].ms_size);
1634 
1635 	/*
1636 	 * Build the I/O command.  Note that the SG list type bits are set to zero,
1637 	 * denoting the format of SG list that we are using.
1638 	 */
1639 	mlx_make_type5(mc, cmd,
1640 		       blkcount & 0xff, 				/* xfer length low byte */
1641 		       (driveno << 3) | ((blkcount >> 8) & 0x07),	/* target and length high 3 bits */
1642 		       bp->b_pblkno,					/* physical block number */
1643 		       mc->mc_sgphys,					/* location of SG list */
1644 		       mc->mc_nsgent & 0x3f);				/* size of SG list (top 2 bits clear) */
1645 
1646 
1647 	/* try to give command to controller */
1648 	if (mlx_start(mc) != 0) {
1649 	    /* fail the command */
1650 	    mc->mc_status = MLX_STATUS_WEDGED;
1651 	    mlx_completeio(mc);
1652 	}
1653 	s = splbio();
1654     }
1655     splx(s);
1656 }
1657 
1658 /********************************************************************************
1659  * Handle completion of an I/O command.
1660  */
1661 static void
1662 mlx_completeio(struct mlx_command *mc)
1663 {
1664     struct mlx_softc	*sc = mc->mc_sc;
1665     struct buf		*bp = (struct buf *)mc->mc_private;
1666     struct mlxd_softc	*mlxd = (struct mlxd_softc *)bp->b_dev->si_drv1;
1667 
1668     if (mc->mc_status != MLX_STATUS_OK) {	/* could be more verbose here? */
1669 	bp->b_error = EIO;
1670 	bp->b_flags |= B_ERROR;
1671 
1672 	switch(mc->mc_status) {
1673 	case MLX_STATUS_RDWROFFLINE:		/* system drive has gone offline */
1674 	    device_printf(mlxd->mlxd_dev, "drive offline\n");
1675 	    /* should signal this with a return code */
1676 	    mlxd->mlxd_drive->ms_state = MLX_SYSD_OFFLINE;
1677 	    break;
1678 
1679 	default:				/* other I/O error */
1680 	    device_printf(sc->mlx_dev, "I/O error - %s\n", mlx_diagnose_command(mc));
1681 #if 0
1682 	    device_printf(sc->mlx_dev, "  b_bcount %ld  blkcount %ld  b_pblkno %d\n",
1683 			  bp->b_bcount, bp->b_bcount / MLX_BLKSIZE, bp->b_pblkno);
1684 	    device_printf(sc->mlx_dev, "  %13D\n", mc->mc_mailbox, " ");
1685 #endif
1686 	    break;
1687 	}
1688     }
1689     mlx_releasecmd(mc);
1690     mlxd_intr(bp);
1691 }
1692 
1693 /********************************************************************************
1694  * Take a command from user-space and try to run it.
1695  */
1696 static int
1697 mlx_user_command(struct mlx_softc *sc, struct mlx_usercommand *mu)
1698 {
1699     struct mlx_command	*mc;
1700     void		*kbuf;
1701     int			error;
1702 
1703     kbuf = NULL;
1704     mc = NULL;
1705     error = ENOMEM;
1706     /* get a kernel buffer for the transfer */
1707     if (mu->mu_datasize > 0) {
1708 	if ((kbuf = malloc(mu->mu_datasize, M_DEVBUF, M_WAITOK)) == NULL)
1709 	    goto out;
1710 	if ((mu->mu_bufptr < 0) || (mu->mu_bufptr > (sizeof(mu->mu_command) < sizeof(u_int32_t)))) {
1711 	    error = EINVAL;
1712 	    goto out;
1713 	}
1714     }
1715     /* get ourselves a command buffer */
1716     if ((mc = mlx_alloccmd(sc)) == NULL)
1717 	goto out;
1718 
1719     /* copy the command and data */
1720     bcopy(mu->mu_command, mc->mc_mailbox, sizeof(mc->mc_mailbox));
1721     if ((mu->mu_datasize > 0) && ((error = copyin(mu->mu_buf, kbuf, mu->mu_datasize))))
1722 	goto out;
1723 
1724     /* get a command slot */
1725     if (mlx_getslot(mc))
1726 	goto out;
1727 
1728     /* map the command so the controller can see it */
1729     mc->mc_data = kbuf;
1730     mc->mc_length = mu->mu_datasize;
1731     mlx_mapcmd(mc);
1732 
1733     /* if there's a data buffer, fix up the command */
1734     if (mu->mu_datasize > 0) {
1735 	mc->mc_mailbox[mu->mu_bufptr    ] =  mc->mc_length        & 0xff;
1736 	mc->mc_mailbox[mu->mu_bufptr + 1] = (mc->mc_length >> 8)  & 0xff;
1737 	mc->mc_mailbox[mu->mu_bufptr + 2] = (mc->mc_length >> 16) & 0xff;
1738 	mc->mc_mailbox[mu->mu_bufptr + 3] = (mc->mc_length >> 24) & 0xff;
1739     }
1740 
1741     /* submit the command and wait */
1742     if ((error = mlx_wait_command(mc)) != 0)
1743 	goto out;
1744 
1745     /* copy out status and data */
1746     mu->mu_status = mc->mc_status;
1747     if ((mu->mu_datasize > 0) && ((error = copyout(kbuf, mu->mu_buf, mu->mu_datasize))))
1748 	goto out;
1749     error = 0;
1750 
1751  out:
1752     mlx_releasecmd(mc);
1753     if (kbuf != NULL)
1754 	free(kbuf, M_DEVBUF);
1755     return(error);
1756 }
1757 
1758 /********************************************************************************
1759  ********************************************************************************
1760                                                         Command I/O to Controller
1761  ********************************************************************************
1762  ********************************************************************************/
1763 
1764 /********************************************************************************
1765  * Find a free command slot for (mc).
1766  *
1767  * Don't hand out a slot to a normal-priority command unless there are at least
1768  * 4 slots free for priority commands.
1769  */
1770 static int
1771 mlx_getslot(struct mlx_command *mc)
1772 {
1773     struct mlx_softc	*sc = mc->mc_sc;
1774     int			s, slot, limit;
1775 
1776     debug("called  mc %p  sc %p", mc, sc);
1777 
1778     /* enforce slot-usage limit */
1779     limit = (mc->mc_flags & MLX_CMD_PRIORITY) ? sc->mlx_maxiop : sc->mlx_maxiop - 4;
1780     if (sc->mlx_busycmds > limit)
1781 	return(EBUSY);
1782 
1783     /*
1784      * Allocate an outstanding command slot
1785      *
1786      * XXX linear search is slow
1787      */
1788     s = splbio();
1789     for (slot = 0; slot < sc->mlx_maxiop; slot++) {
1790 	debug("try slot %d", slot);
1791 	if (sc->mlx_busycmd[slot] == NULL)
1792 	    break;
1793     }
1794     if (slot < sc->mlx_maxiop) {
1795 	sc->mlx_busycmd[slot] = mc;
1796 	sc->mlx_busycmds++;
1797     }
1798     splx(s);
1799 
1800     /* out of slots? */
1801     if (slot >= sc->mlx_maxiop)
1802 	return(EBUSY);
1803 
1804     debug("got slot %d", slot);
1805     mc->mc_slot = slot;
1806     return(0);
1807 }
1808 
1809 /********************************************************************************
1810  * Map/unmap (mc)'s data in the controller's addressable space.
1811  */
1812 static void
1813 mlx_setup_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
1814 {
1815     struct mlx_command	*mc = (struct mlx_command *)arg;
1816     struct mlx_softc	*sc = mc->mc_sc;
1817     struct mlx_sgentry	*sg;
1818     int			i;
1819 
1820     debug("called");
1821 
1822     /* get base address of s/g table */
1823     sg = sc->mlx_sgtable + (mc->mc_slot * MLX_NSEG);
1824 
1825     /* save s/g table information in command */
1826     mc->mc_nsgent = nsegments;
1827     mc->mc_sgphys = sc->mlx_sgbusaddr + (mc->mc_slot * MLX_NSEG * sizeof(struct mlx_sgentry));
1828     mc->mc_dataphys = segs[0].ds_addr;
1829 
1830     /* populate s/g table */
1831     for (i = 0; i < nsegments; i++, sg++) {
1832 	sg->sg_addr = segs[i].ds_addr;
1833 	sg->sg_count = segs[i].ds_len;
1834     }
1835 }
1836 
1837 static void
1838 mlx_mapcmd(struct mlx_command *mc)
1839 {
1840     struct mlx_softc	*sc = mc->mc_sc;
1841 
1842     debug("called");
1843 
1844     /* if the command involves data at all */
1845     if (mc->mc_data != NULL) {
1846 
1847 	/* map the data buffer into bus space and build the s/g list */
1848 	bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data, mc->mc_length,
1849 			mlx_setup_dmamap, mc, 0);
1850 	if (mc->mc_flags & MLX_CMD_DATAIN)
1851 	    bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_PREREAD);
1852 	if (mc->mc_flags & MLX_CMD_DATAOUT)
1853 	    bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_PREWRITE);
1854     }
1855 }
1856 
1857 static void
1858 mlx_unmapcmd(struct mlx_command *mc)
1859 {
1860     struct mlx_softc	*sc = mc->mc_sc;
1861 
1862     debug("called");
1863 
1864     /* if the command involved data at all */
1865     if (mc->mc_data != NULL) {
1866 
1867 	if (mc->mc_flags & MLX_CMD_DATAIN)
1868 	    bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTREAD);
1869 	if (mc->mc_flags & MLX_CMD_DATAOUT)
1870 	    bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTWRITE);
1871 
1872 	bus_dmamap_unload(sc->mlx_buffer_dmat, mc->mc_dmamap);
1873     }
1874 }
1875 
1876 /********************************************************************************
1877  * Try to deliver (mc) to the controller.  Take care of any completed commands
1878  * that we encounter while doing so.
1879  *
1880  * Can be called at any interrupt level, with or without interrupts enabled.
1881  */
1882 static int
1883 mlx_start(struct mlx_command *mc)
1884 {
1885     struct mlx_softc	*sc = mc->mc_sc;
1886     int			i, s, done, worked;
1887 
1888     debug("called");
1889 
1890     /* save the slot number as ident so we can handle this command when complete */
1891     mc->mc_mailbox[0x1] = mc->mc_slot;
1892 
1893     /* mark the command as currently being processed */
1894     mc->mc_status = MLX_STATUS_BUSY;
1895 
1896     /* assume we don't collect any completed commands */
1897     worked = 0;
1898 
1899     /* spin waiting for the mailbox */
1900     for (i = 100000, done = 0; (i > 0) && !done; i--) {
1901 	s = splbio();
1902 	if (sc->mlx_tryqueue(sc, mc)) {
1903 	    done = 1;
1904 	    /* move command to work queue */
1905 	    TAILQ_INSERT_TAIL(&sc->mlx_work, mc, mc_link);
1906 	}
1907 	splx(s);
1908 	/* check for command completion while we're at it */
1909 	if (mlx_done(sc))
1910 	    worked = 1;
1911     }
1912     /* check to see if we picked up any completed commands */
1913     if (worked)
1914 	mlx_complete(sc);
1915 
1916     /* command is enqueued */
1917     if (done)
1918 	return(0);
1919 
1920     /*
1921      * We couldn't get the controller to take the command.  Revoke the slot
1922      * that the command was given and return it with a bad status.
1923      */
1924     sc->mlx_busycmd[mc->mc_slot] = NULL;
1925     device_printf(sc->mlx_dev, "controller wedged (not taking commands)\n");
1926     mc->mc_status = MLX_STATUS_WEDGED;
1927     return(EIO);
1928 }
1929 
1930 /********************************************************************************
1931  * Look at the controller (sc) and see if a command has been completed.
1932  * If so, move the command buffer to the done queue for later collection
1933  * and free the slot for immediate reuse.
1934  *
1935  * Returns nonzero if anything was added to the done queue.
1936  */
1937 static int
1938 mlx_done(struct mlx_softc *sc)
1939 {
1940     struct mlx_command	*mc;
1941     int			s;
1942     u_int8_t		slot;
1943     u_int16_t		status;
1944 
1945     debug("called");
1946 
1947     mc = NULL;
1948     slot = 0;
1949 
1950     /* poll for a completed command's identifier and status */
1951     s = splbio();
1952     if (sc->mlx_findcomplete(sc, &slot, &status)) {
1953 	mc = sc->mlx_busycmd[slot];			/* find command */
1954 	if (mc != NULL) {				/* paranoia */
1955 	    if (mc->mc_status == MLX_STATUS_BUSY) {
1956 		mc->mc_status = status;			/* save status */
1957 
1958 		/* free slot for reuse */
1959 		sc->mlx_busycmd[slot] = NULL;
1960 		sc->mlx_busycmds--;
1961 	    } else {
1962 		device_printf(sc->mlx_dev, "duplicate done event for slot %d\n", slot);
1963 		mc = NULL;
1964 	    }
1965 	} else {
1966 	    device_printf(sc->mlx_dev, "done event for nonbusy slot %d\n", slot);
1967 	}
1968     }
1969     splx(s);
1970 
1971     if (mc != NULL) {
1972 	/* unmap the command's data buffer */
1973 	mlx_unmapcmd(mc);
1974 	return(1);
1975     }
1976     return(0);
1977 }
1978 
1979 /********************************************************************************
1980  * Handle completion for all commands on (sc)'s done queue.
1981  */
1982 static void
1983 mlx_complete(struct mlx_softc *sc)
1984 {
1985     struct mlx_command	*mc, *nc;
1986     int			s, count;
1987 
1988     debug("called");
1989 
1990     s = splbio();
1991     count = 0;
1992 
1993     /* scan the list of done commands */
1994     mc = TAILQ_FIRST(&sc->mlx_work);
1995     while (mc != NULL) {
1996 	nc = TAILQ_NEXT(mc, mc_link);
1997 
1998 	/* XXX this is slightly bogus */
1999 	if (count++ > (sc->mlx_maxiop * 2))
2000 	    panic("mlx_work list corrupt!");
2001 
2002 	/* Skip commands that are still busy */
2003 	if (mc->mc_status != MLX_STATUS_BUSY) {
2004 
2005 
2006 	    /*
2007 	 * Does the command have a completion handler?
2008 	 */
2009 	    if (mc->mc_complete != NULL) {
2010 		/* remove from list and give to handler */
2011 		TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
2012 		mc->mc_complete(mc);
2013 
2014 		/*
2015 		 * Is there a sleeper waiting on this command?
2016 		 */
2017 	    } else if (mc->mc_private != NULL) {	/* sleeping caller wants to know about it */
2018 
2019 		/* remove from list and wake up sleeper */
2020 		TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
2021 		wakeup_one(mc->mc_private);
2022 
2023 		/*
2024 		 * Leave the command for a caller that's polling for it.
2025 		 */
2026 	    } else {
2027 	    }
2028 	}
2029 	mc = nc;
2030     }
2031     splx(s);
2032 
2033     /* queue some more work if there is any */
2034     mlx_startio(sc);
2035 }
2036 
2037 /********************************************************************************
2038  ********************************************************************************
2039                                                         Command Buffer Management
2040  ********************************************************************************
2041  ********************************************************************************/
2042 
2043 /********************************************************************************
2044  * Get a new command buffer.
2045  *
2046  * This may return NULL in low-memory cases.
2047  *
2048  * Note that using malloc() is expensive (the command buffer is << 1 page) but
2049  * necessary if we are to be a loadable module before the zone allocator is fixed.
2050  *
2051  * If possible, we recycle a command buffer that's been used before.
2052  *
2053  * XXX Note that command buffers are not cleaned out - it is the caller's
2054  *     responsibility to ensure that all required fields are filled in before
2055  *     using a buffer.
2056  */
2057 static struct mlx_command *
2058 mlx_alloccmd(struct mlx_softc *sc)
2059 {
2060     struct mlx_command	*mc;
2061     int			error;
2062     int			s;
2063 
2064     debug("called");
2065 
2066     s = splbio();
2067     if ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL)
2068 	TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link);
2069     splx(s);
2070 
2071     /* allocate a new command buffer? */
2072     if (mc == NULL) {
2073 	mc = (struct mlx_command *)malloc(sizeof(*mc), M_DEVBUF, M_NOWAIT);
2074 	if (mc != NULL) {
2075 	    bzero(mc, sizeof(*mc));
2076 	    mc->mc_sc = sc;
2077 	    error = bus_dmamap_create(sc->mlx_buffer_dmat, 0, &mc->mc_dmamap);
2078 	    if (error) {
2079 		free(mc, M_DEVBUF);
2080 		return(NULL);
2081 	    }
2082 	}
2083     }
2084     return(mc);
2085 }
2086 
2087 /********************************************************************************
2088  * Release a command buffer for recycling.
2089  *
2090  * XXX It might be a good idea to limit the number of commands we save for reuse
2091  *     if it's shown that this list bloats out massively.
2092  */
2093 static void
2094 mlx_releasecmd(struct mlx_command *mc)
2095 {
2096     int		s;
2097 
2098     debug("called");
2099 
2100     s = splbio();
2101     TAILQ_INSERT_HEAD(&mc->mc_sc->mlx_freecmds, mc, mc_link);
2102     splx(s);
2103 }
2104 
2105 /********************************************************************************
2106  * Permanently discard a command buffer.
2107  */
2108 static void
2109 mlx_freecmd(struct mlx_command *mc)
2110 {
2111     struct mlx_softc	*sc = mc->mc_sc;
2112 
2113     debug("called");
2114 
2115     bus_dmamap_destroy(sc->mlx_buffer_dmat, mc->mc_dmamap);
2116     free(mc, M_DEVBUF);
2117 }
2118 
2119 
2120 /********************************************************************************
2121  ********************************************************************************
2122                                                 Type 3 interface accessor methods
2123  ********************************************************************************
2124  ********************************************************************************/
2125 
2126 /********************************************************************************
2127  * Try to give (mc) to the controller.  Returns 1 if successful, 0 on failure
2128  * (the controller is not ready to take a command).
2129  *
2130  * Must be called at splbio or in a fashion that prevents reentry.
2131  */
2132 static int
2133 mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2134 {
2135     int		i;
2136 
2137     debug("called");
2138 
2139     /* ready for our command? */
2140     if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_FULL)) {
2141 	/* copy mailbox data to window */
2142 	for (i = 0; i < 13; i++)
2143 	    MLX_V3_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
2144 
2145 	/* post command */
2146 	MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_FULL);
2147 	return(1);
2148     }
2149     return(0);
2150 }
2151 
2152 /********************************************************************************
2153  * See if a command has been completed, if so acknowledge its completion
2154  * and recover the slot number and status code.
2155  *
2156  * Must be called at splbio or in a fashion that prevents reentry.
2157  */
2158 static int
2159 mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2160 {
2161 
2162     debug("called");
2163 
2164     /* status available? */
2165     if (MLX_V3_GET_ODBR(sc) & MLX_V3_ODB_SAVAIL) {
2166 	*slot = MLX_V3_GET_STATUS_IDENT(sc);		/* get command identifier */
2167 	*status = MLX_V3_GET_STATUS(sc);		/* get status */
2168 
2169 	/* acknowledge completion */
2170 	MLX_V3_PUT_ODBR(sc, MLX_V3_ODB_SAVAIL);
2171 	MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_SACK);
2172 	return(1);
2173     }
2174     return(0);
2175 }
2176 
2177 /********************************************************************************
2178  * Enable/disable interrupts as requested. (No acknowledge required)
2179  *
2180  * Must be called at splbio or in a fashion that prevents reentry.
2181  */
2182 static void
2183 mlx_v3_intaction(struct mlx_softc *sc, int action)
2184 {
2185     debug("called");
2186 
2187     switch(action) {
2188     case MLX_INTACTION_DISABLE:
2189 	MLX_V3_PUT_IER(sc, 0);
2190 	sc->mlx_state &= ~MLX_STATE_INTEN;
2191 	break;
2192     case MLX_INTACTION_ENABLE:
2193 	MLX_V3_PUT_IER(sc, 1);
2194 	sc->mlx_state |= MLX_STATE_INTEN;
2195 	break;
2196     }
2197 }
2198 
2199 
2200 /********************************************************************************
2201  ********************************************************************************
2202                                                 Type 4 interface accessor methods
2203  ********************************************************************************
2204  ********************************************************************************/
2205 
2206 /********************************************************************************
2207  * Try to give (mc) to the controller.  Returns 1 if successful, 0 on failure
2208  * (the controller is not ready to take a command).
2209  *
2210  * Must be called at splbio or in a fashion that prevents reentry.
2211  */
2212 static int
2213 mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2214 {
2215     int		i;
2216 
2217     debug("called");
2218 
2219     /* ready for our command? */
2220     if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_FULL)) {
2221 	/* copy mailbox data to window */
2222 	for (i = 0; i < 13; i++)
2223 	    MLX_V4_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
2224 
2225 	/* post command */
2226 	MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_HWMBOX_CMD);
2227 	return(1);
2228     }
2229     return(0);
2230 }
2231 
2232 /********************************************************************************
2233  * See if a command has been completed, if so acknowledge its completion
2234  * and recover the slot number and status code.
2235  *
2236  * Must be called at splbio or in a fashion that prevents reentry.
2237  */
2238 static int
2239 mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2240 {
2241 
2242     debug("called");
2243 
2244     /* status available? */
2245     if (MLX_V4_GET_ODBR(sc) & MLX_V4_ODB_HWSAVAIL) {
2246 	*slot = MLX_V4_GET_STATUS_IDENT(sc);		/* get command identifier */
2247 	*status = MLX_V4_GET_STATUS(sc);		/* get status */
2248 
2249 	/* acknowledge completion */
2250 	MLX_V4_PUT_ODBR(sc, MLX_V4_ODB_HWMBOX_ACK);
2251 	MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_SACK);
2252 	return(1);
2253     }
2254     return(0);
2255 }
2256 
2257 /********************************************************************************
2258  * Enable/disable interrupts as requested.
2259  *
2260  * Must be called at splbio or in a fashion that prevents reentry.
2261  */
2262 static void
2263 mlx_v4_intaction(struct mlx_softc *sc, int action)
2264 {
2265     debug("called");
2266 
2267     switch(action) {
2268     case MLX_INTACTION_DISABLE:
2269 	MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK | MLX_V4_IER_DISINT);
2270 	sc->mlx_state &= ~MLX_STATE_INTEN;
2271 	break;
2272     case MLX_INTACTION_ENABLE:
2273 	MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK & ~MLX_V4_IER_DISINT);
2274 	sc->mlx_state |= MLX_STATE_INTEN;
2275 	break;
2276     }
2277 }
2278 
2279 
2280 /********************************************************************************
2281  ********************************************************************************
2282                                                                         Debugging
2283  ********************************************************************************
2284  ********************************************************************************/
2285 
2286 /********************************************************************************
2287  * Return a status message describing (mc)
2288  */
2289 static char *mlx_status_messages[] = {
2290     "normal completion",			/* 00 */
2291     "irrecoverable data error",			/* 01 */
2292     "drive does not exist, or is offline",	/* 02 */
2293     "attempt to write beyond end of drive",	/* 03 */
2294     "bad data encountered",			/* 04 */
2295     "invalid log entry request",		/* 05 */
2296     "attempt to rebuild online drive",		/* 06 */
2297     "new disk failed during rebuild",		/* 07 */
2298     "invalid channel/target",			/* 08 */
2299     "rebuild/check already in progress",	/* 09 */
2300     "one or more disks are dead",		/* 10 */
2301     "invalid or non-redundant drive",		/* 11 */
2302     "channel is busy",				/* 12 */
2303     "channel is not stopped",			/* 13 */
2304 };
2305 
2306 static struct
2307 {
2308     int		command;
2309     u_int16_t	status;
2310     int		msg;
2311 } mlx_messages[] = {
2312     {MLX_CMD_READOLDSG,		0x0001,	 1},
2313     {MLX_CMD_READOLDSG,		0x0002,	 1},
2314     {MLX_CMD_READOLDSG,		0x0105,	 3},
2315     {MLX_CMD_READOLDSG,		0x010c,	 4},
2316     {MLX_CMD_WRITEOLDSG,	0x0001,	 1},
2317     {MLX_CMD_WRITEOLDSG,	0x0002,	 1},
2318     {MLX_CMD_WRITEOLDSG,	0x0105,	 3},
2319     {MLX_CMD_LOGOP,		0x0105,	 5},
2320     {MLX_CMD_REBUILDASYNC,	0x0002,  6},
2321     {MLX_CMD_REBUILDASYNC,	0x0004,  7},
2322     {MLX_CMD_REBUILDASYNC,	0x0105,  8},
2323     {MLX_CMD_REBUILDASYNC,	0x0106,  9},
2324     {MLX_CMD_CHECKASYNC,	0x0002, 10},
2325     {MLX_CMD_CHECKASYNC,	0x0105, 11},
2326     {MLX_CMD_CHECKASYNC,	0x0106,  9},
2327     {MLX_CMD_STOPCHANNEL,	0x0106, 12},
2328     {MLX_CMD_STOPCHANNEL,	0x0105,  8},
2329     {MLX_CMD_STARTCHANNEL,	0x0005, 13},
2330     {MLX_CMD_STARTCHANNEL,	0x0105,  8},
2331     {-1, 0, 0}
2332 };
2333 
2334 static char *
2335 mlx_diagnose_command(struct mlx_command *mc)
2336 {
2337     static char	unkmsg[80];
2338     int		i;
2339 
2340     /* look up message in table */
2341     for (i = 0; mlx_messages[i].command != -1; i++)
2342 	if ((mc->mc_mailbox[0] == mlx_messages[i].command) &&
2343 	    (mc->mc_status == mlx_messages[i].status))
2344 	    return(mlx_status_messages[mlx_messages[i].msg]);
2345 
2346     sprintf(unkmsg, "unknown response 0x%x for command 0x%x", (int)mc->mc_status, (int)mc->mc_mailbox[0]);
2347     return(unkmsg);
2348 }
2349 
2350 /*******************************************************************************
2351  * Return a string describing the controller (hwid)
2352  */
2353 static char *
2354 mlx_name_controller(u_int32_t hwid)
2355 {
2356     static char		buf[80];
2357     char		smbuf[16];
2358     char		*submodel;
2359     int			nchn;
2360 
2361     switch(hwid & 0xff) {
2362     case 0x01:
2363 	submodel = "P/PD";
2364 	break;
2365     case 0x02:
2366 	submodel = "PL";
2367 	break;
2368     case 0x10:
2369 	submodel = "PG";
2370 	break;
2371     case 0x11:
2372 	submodel = "PJ";
2373 	break;
2374     case 0x16:
2375 	submodel = "PTL";
2376 	break;
2377     default:
2378 	sprintf(smbuf, " model 0x%x", hwid & 0xff);
2379 	submodel = smbuf;
2380 	break;
2381     }
2382     nchn = (hwid >> 8) & 0xff;
2383     sprintf(buf, "DAC960%s, %d channel%s", submodel, nchn, nchn > 1 ? "s" : "");
2384     return(buf);
2385 }
2386 
2387 /********************************************************************************
2388  ********************************************************************************
2389                                                                 Utility Functions
2390  ********************************************************************************
2391  ********************************************************************************/
2392 
2393 /********************************************************************************
2394  * Find the disk whose unit number is (unit) on this controller
2395  */
2396 static struct mlx_sysdrive *
2397 mlx_findunit(struct mlx_softc *sc, int unit)
2398 {
2399     int		i;
2400 
2401     /* search system drives */
2402     for (i = 0; i < MLX_MAXDRIVES; i++) {
2403 	/* is this one attached? */
2404 	if (sc->mlx_sysdrive[i].ms_disk != 0) {
2405 	    /* is this the one? */
2406 	    if (unit == device_get_unit(sc->mlx_sysdrive[i].ms_disk))
2407 		return(&sc->mlx_sysdrive[i]);
2408 	}
2409     }
2410     return(NULL);
2411 }
2412