mlx.c revision 52276
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: head/sys/dev/mlx/mlx.c 52276 1999-10-16 03:21:20Z msmith $
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
61static 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
78static int	cdev_registered = 0;
79devclass_t	mlx_devclass;
80
81/*
82 * Per-interface accessor methods
83 */
84static int			mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
85static int			mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
86static void			mlx_v3_intaction(struct mlx_softc *sc, int action);
87
88static int			mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
89static int			mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
90static void			mlx_v4_intaction(struct mlx_softc *sc, int action);
91
92/*
93 * Status monitoring
94 */
95static void			mlx_periodic(void *data);
96static void			mlx_periodic_enquiry(struct mlx_command *mc);
97static void			mlx_periodic_eventlog_poll(struct mlx_softc *sc);
98static void			mlx_periodic_eventlog_respond(struct mlx_command *mc);
99static void			mlx_periodic_rebuild(struct mlx_command *mc);
100
101/*
102 * Channel Pause
103 */
104static void			mlx_pause_action(struct mlx_softc *sc);
105static void			mlx_pause_done(struct mlx_command *mc);
106
107/*
108 * Command submission.
109 */
110static void			*mlx_enquire(struct mlx_softc *sc, int command, size_t bufsize,
111					     void (*complete)(struct mlx_command *mc));
112static int			mlx_flush(struct mlx_softc *sc);
113static int			mlx_rebuild(struct mlx_softc *sc, int channel, int target);
114static int			mlx_wait_command(struct mlx_command *mc);
115static int			mlx_poll_command(struct mlx_command *mc);
116static void			mlx_startio(struct mlx_softc *sc);
117static void			mlx_completeio(struct mlx_command *mc);
118static int			mlx_user_command(struct mlx_softc *sc, struct mlx_usercommand *mu);
119
120/*
121 * Command buffer allocation.
122 */
123static struct mlx_command	*mlx_alloccmd(struct mlx_softc *sc);
124static void			mlx_releasecmd(struct mlx_command *mc);
125static void			mlx_freecmd(struct mlx_command *mc);
126
127/*
128 * Command management.
129 */
130static int			mlx_getslot(struct mlx_command *mc);
131static void			mlx_mapcmd(struct mlx_command *mc);
132static void			mlx_unmapcmd(struct mlx_command *mc);
133static int			mlx_start(struct mlx_command *mc);
134static int			mlx_done(struct mlx_softc *sc);
135static void			mlx_complete(struct mlx_softc *sc);
136
137/*
138 * Debugging.
139 */
140static char			*mlx_diagnose_command(struct mlx_command *mc);
141static char			*mlx_name_controller(u_int32_t hwid);
142
143
144/*
145 * Utility functions.
146 */
147static 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 */
160void
161mlx_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 */
205static void
206mlx_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
216static int
217mlx_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 */
269int
270mlx_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_donecmd);
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.%d, %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 SUPPORTED\n");
395	    device_printf(sc->mlx_dev, " *** WARNING *** Use revision 3.51 only\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 SUPPORTED\n");
402	    device_printf(sc->mlx_dev, " *** WARNING *** Use revision 4.6 only\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 */
443void
444mlx_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 */
502int
503mlx_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 */
537int
538mlx_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 */
590int
591mlx_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 */
614int
615mlx_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 */
631void
632mlx_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 */
653int
654mlx_submit_buf(struct mlx_softc *sc, struct buf *bp)
655{
656    debug("called");
657
658    bufq_insert_tail(&sc->mlx_bufq, bp);
659    sc->mlx_waitbufs++;
660    mlx_startio(sc);
661    return(0);
662}
663
664/********************************************************************************
665 * Accept an open operation on the control device.
666 */
667int
668mlx_open(dev_t dev, int flags, int fmt, struct proc *p)
669{
670    int			unit = minor(dev);
671    struct mlx_softc	*sc = devclass_get_softc(mlx_devclass, unit);
672
673    sc->mlx_state |= MLX_STATE_OPEN;
674    return(0);
675}
676
677/********************************************************************************
678 * Accept the last close on the control device.
679 */
680int
681mlx_close(dev_t dev, int flags, int fmt, struct proc *p)
682{
683    int			unit = minor(dev);
684    struct mlx_softc	*sc = devclass_get_softc(mlx_devclass, unit);
685
686    sc->mlx_state &= ~MLX_STATE_OPEN;
687    return (0);
688}
689
690/********************************************************************************
691 * Handle controller-specific control operations.
692 */
693int
694mlx_ioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
695{
696    int			unit = minor(dev);
697    struct mlx_softc	*sc = devclass_get_softc(mlx_devclass, unit);
698    int			*arg = (int *)addr;
699    struct mlx_pause	*mp;
700    struct mlx_sysdrive	*dr;
701    struct mlxd_softc	*mlxd;
702    int			i, error;
703
704    switch(cmd) {
705	/*
706	 * Enumerate connected system drives; returns the first system drive's
707	 * unit number if *arg is -1, or the next unit after *arg if it's
708	 * a valid unit on this controller.
709	 */
710    case MLX_NEXT_CHILD:
711	/* search system drives */
712	for (i = 0; i < MLX_MAXDRIVES; i++) {
713	    /* is this one attached? */
714	    if (sc->mlx_sysdrive[i].ms_disk != 0) {
715		/* looking for the next one we come across? */
716		if (*arg == -1) {
717		    *arg = device_get_unit(sc->mlx_sysdrive[i].ms_disk);
718		    return(0);
719		}
720		/* we want the one after this one */
721		if (*arg == device_get_unit(sc->mlx_sysdrive[i].ms_disk))
722		    *arg = -1;
723	    }
724	}
725	return(ENOENT);
726
727	/*
728	 * Scan the controller to see whether new drives have appeared.
729	 */
730    case MLX_RESCAN_DRIVES:
731	mlx_startup(sc);
732	return(0);
733
734	/*
735	 * Disconnect from the specified drive; it may be about to go
736	 * away.
737	 */
738    case MLX_DETACH_DRIVE:			/* detach one drive */
739
740	if (((dr = mlx_findunit(sc, *arg)) == NULL) ||
741	    ((mlxd = device_get_softc(dr->ms_disk)) == NULL))
742	    return(ENOENT);
743
744	device_printf(dr->ms_disk, "detaching...");
745	error = 0;
746	if (mlxd->mlxd_flags & MLXD_OPEN) {
747	    error = EBUSY;
748	    goto detach_out;
749	}
750
751	/* flush controller */
752	if (mlx_flush(sc)) {
753	    error = EBUSY;
754	    goto detach_out;
755	}
756
757	/* nuke drive */
758	if ((error = device_delete_child(sc->mlx_dev, dr->ms_disk)) != 0)
759	    goto detach_out;
760	dr->ms_disk = 0;
761	bus_generic_detach(sc->mlx_dev);
762
763    detach_out:
764	if (error) {
765	    printf("failed\n");
766	} else {
767	    printf("done\n");
768	}
769	return(error);
770
771	/*
772	 * Pause one or more SCSI channels for a period of time, to assist
773	 * in the process of hot-swapping devices.
774	 *
775	 * Note that at least the 3.51 firmware on the DAC960PL doesn't seem
776	 * to do this right.
777	 */
778    case MLX_PAUSE_CHANNEL:			/* schedule a channel pause */
779	/* Does this command work on this firmware? */
780	if (!(sc->mlx_feature & MLX_FEAT_PAUSEWORKS))
781	    return(EOPNOTSUPP);
782
783	mp = (struct mlx_pause *)addr;
784	if ((mp->mp_which == MLX_PAUSE_CANCEL) && (sc->mlx_pause.mp_when != 0)) {
785	    /* cancel a pending pause operation */
786	    sc->mlx_pause.mp_which = 0;
787	} else {
788	    /* fix for legal channels */
789	    mp->mp_which &= ((1 << sc->mlx_nchan) -1);
790	    /* check time values */
791	    if ((mp->mp_when < 0) || (mp->mp_when > 3600))
792		return(EINVAL);
793	    if ((mp->mp_howlong < 1) || (mp->mp_howlong > (0xf * 30)))
794		return(EINVAL);
795
796	    /* check for a pause currently running */
797	    if ((sc->mlx_pause.mp_which != 0) && (sc->mlx_pause.mp_when == 0))
798		return(EBUSY);
799
800	    /* looks ok, go with it */
801	    sc->mlx_pause.mp_which = mp->mp_which;
802	    sc->mlx_pause.mp_when = time_second + mp->mp_when;
803	    sc->mlx_pause.mp_howlong = sc->mlx_pause.mp_when + mp->mp_howlong;
804	}
805	return(0);
806
807	/*
808	 * Accept a command passthrough-style.
809	 */
810    case MLX_COMMAND:
811	return(mlx_user_command(sc, (struct mlx_usercommand *)addr));
812
813    default:
814	return(ENOTTY);
815    }
816}
817
818/********************************************************************************
819 * Handle operations requested by a System Drive connected to this controller.
820 */
821int
822mlx_submit_ioctl(struct mlx_softc *sc, struct mlx_sysdrive *drive, u_long cmd,
823		caddr_t addr, int32_t flag, struct proc *p)
824{
825    struct mlxd_rebuild		*mr = (struct mlxd_rebuild *)addr;
826    struct mlxd_rebuild_status	*mp = (struct mlxd_rebuild_status *)addr;
827    int				*arg = (int *)addr;
828    int				error;
829
830    switch(cmd) {
831	/*
832	 * Return the current status of this drive.
833	 */
834    case MLXD_STATUS:
835	*arg = drive->ms_state;
836	return(0);
837
838	/*
839	 * Start a background rebuild on this drive.
840	 */
841    case MLXD_REBUILDASYNC:
842	/* XXX lock? */
843	if (sc->mlx_rebuild >= 0)
844	    return(EBUSY);
845	sc->mlx_rebuild = drive - &sc->mlx_sysdrive[0];
846
847	switch (mlx_rebuild(sc, mr->rb_channel, mr->rb_target)) {
848	case 0:
849	    drive->ms_state = MLX_SYSD_REBUILD;
850	    error = 0;
851	    break;
852	case 0x10000:
853	    error = ENOMEM;		/* couldn't set up the command */
854	    break;
855	case 0x0002:
856	case 0x0106:
857	    error = EBUSY;
858	    break;
859	case 0x0004:
860	    error = EIO;
861	    break;
862	case 0x0105:
863	    error = ERANGE;
864	    break;
865	default:
866	    error = EINVAL;
867	    break;
868	}
869	if (error != 0)
870	    sc->mlx_rebuild = -1;
871	return(error);
872
873	/*
874	 * Start a background consistency check on this drive.
875	 */
876    case MLXD_CHECKASYNC:		/* start a background consistency check */
877	/* XXX implement */
878	break;
879
880	/*
881	 * Get the status of the current rebuild or consistency check.
882	 */
883    case MLXD_REBUILDSTAT:
884
885	if (sc->mlx_rebuild >= 0) {	/* may be a second or so out of date */
886	    mp->rs_drive = sc->mlx_rebuild;
887	    mp->rs_size = sc->mlx_sysdrive[sc->mlx_rebuild].ms_size;
888	    mp->rs_remaining = sc->mlx_rebuildstat;
889	    return(0);
890	} else if (sc->mlx_check >= 0) {
891	    /* XXX implement */
892	} else {
893	    /* XXX should return status of last completed operation? */
894	    return(EINVAL);
895	}
896
897    }
898    return(ENOIOCTL);
899}
900
901
902/********************************************************************************
903 ********************************************************************************
904                                                                Status Monitoring
905 ********************************************************************************
906 ********************************************************************************/
907
908#define MLX_PERIODIC_ISBUSY(sc)	(sc->mlx_polling <= 0)
909#define MLX_PERIODIC_BUSY(sc)	atomic_add_int(&sc->mlx_polling, 1);
910#define MLX_PERIODIC_UNBUSY(sc) atomic_subtract_int(&sc->mlx_polling, 1);
911
912/********************************************************************************
913 * Fire off commands to periodically check the status of connected drives.
914 */
915static void
916mlx_periodic(void *data)
917{
918    struct mlx_softc *sc = (struct mlx_softc *)data;
919
920    debug("called");
921
922    /*
923     * Run a bus pause?
924     */
925    if ((sc->mlx_pause.mp_which != 0) &&
926	(sc->mlx_pause.mp_when > 0) &&
927	(time_second >= sc->mlx_pause.mp_when)){
928
929	mlx_pause_action(sc);		/* pause is running */
930	sc->mlx_pause.mp_when = 0;
931	sysbeep(500, hz);
932
933	/*
934	 * Bus pause still running?
935	 */
936    } else if ((sc->mlx_pause.mp_which != 0) &&
937	       (sc->mlx_pause.mp_when == 0)) {
938
939	/* time to stop bus pause? */
940	if (time_second >= sc->mlx_pause.mp_howlong) {
941	    mlx_pause_action(sc);
942	    sc->mlx_pause.mp_which = 0;	/* pause is complete */
943	    sysbeep(500, hz);
944	} else {
945	    sysbeep((time_second % 5) * 100 + 500, hz/8);
946	}
947
948	/*
949	 * Run normal periodic activities?
950	 */
951    } else if (MLX_PERIODIC_ISBUSY(sc)) {
952
953	/* time to perform a periodic status poll? XXX tuneable interval? */
954	if (time_second > (sc->mlx_lastpoll + 10)) {
955	    sc->mlx_lastpoll = time_second;
956
957	    /* for caution's sake */
958	    if (sc->mlx_polling < 0) {
959		device_printf(sc->mlx_dev, "mlx_polling < 0\n");
960		atomic_set_int(&sc->mlx_polling, 0);
961	    }
962
963	    /*
964	     * Check controller status.
965	     */
966	    MLX_PERIODIC_BUSY(sc);
967	    mlx_enquire(sc, MLX_CMD_ENQUIRY, sizeof(struct mlx_enquiry), mlx_periodic_enquiry);
968
969	    /*
970	     * Check system drive status.
971	     *
972	     * XXX This might be better left to event-driven detection, eg. I/O to an offline
973	     *     drive will detect it's offline, rebuilds etc. should detect the drive is back
974	     *     online.
975	     */
976	    MLX_PERIODIC_BUSY(sc);
977	    mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(struct mlx_enq_sys_drive) * MLX_MAXDRIVES,
978			mlx_periodic_enquiry);
979	}
980
981	/*
982	 * Get drive rebuild/check status
983	 */
984	if (sc->mlx_rebuild >= 0) {
985	    MLX_PERIODIC_BUSY(sc);
986	    mlx_enquire(sc, MLX_CMD_REBUILDSTAT, sizeof(struct mlx_rebuild_stat), mlx_periodic_rebuild);
987	}
988    } else {
989	/*
990	 * If things are still running from the last poll, complain about it.
991	 *
992	 * XXX If this becomes an issue, we should have some way of telling what
993	 *     has become stuck.
994	 */
995	device_printf(sc->mlx_dev, "poll still busy (%d)\n", sc->mlx_polling);
996    }
997
998    /* XXX check for wedged/timed out commands? */
999
1000    /* reschedule another poll next second or so */
1001    sc->mlx_timeout = timeout(mlx_periodic, sc, hz);
1002}
1003
1004/********************************************************************************
1005 * Handle the result of an ENQUIRY command instigated by periodic status polling.
1006 */
1007static void
1008mlx_periodic_enquiry(struct mlx_command *mc)
1009{
1010    struct mlx_softc		*sc = mc->mc_sc;
1011
1012    debug("called");
1013
1014    /* Command completed OK? */
1015    if (mc->mc_status != 0) {
1016	device_printf(sc->mlx_dev, "periodic enquiry failed\n");
1017	goto out;
1018    }
1019
1020    /* respond to command */
1021    switch(mc->mc_mailbox[0]) {
1022	/*
1023	 * Generic controller status update.  We could do more with this than just
1024	 * checking the event log.
1025	 */
1026    case MLX_CMD_ENQUIRY:
1027    {
1028	struct mlx_enquiry		*me = (struct mlx_enquiry *)mc->mc_data;
1029
1030	/* New stuff in the event log? */
1031	if (me->me_event_log_seq_num != sc->mlx_lastevent) {
1032	    /* record where current events are up to */
1033	    sc->mlx_currevent = me->me_event_log_seq_num;
1034	    device_printf(sc->mlx_dev, "event log pointer was %d, now %d\n",
1035			  sc->mlx_lastevent, sc->mlx_currevent);
1036
1037	    /* start poll of event log */
1038	    mlx_periodic_eventlog_poll(sc);
1039	}
1040	break;
1041    }
1042    case MLX_CMD_ENQSYSDRIVE:
1043    {
1044	struct mlx_enq_sys_drive	*mes = (struct mlx_enq_sys_drive *)mc->mc_data;
1045	struct mlx_sysdrive		*dr;
1046	int				i;
1047
1048	for (i = 0, dr = &sc->mlx_sysdrive[0];
1049	     (i < MLX_MAXDRIVES) && (mes[i].sd_size != 0xffffffff);
1050	     i++) {
1051
1052	    /* if disk is being rebuilt, we should not check it */
1053	    if (dr->ms_state == MLX_SYSD_REBUILD) {
1054		/* has state been changed by controller? */
1055		if (dr->ms_state != mes[i].sd_state) {
1056		    switch(mes[i].sd_state) {
1057		    case MLX_SYSD_OFFLINE:
1058			device_printf(dr->ms_disk, "drive offline\n");
1059			break;
1060		    case MLX_SYSD_ONLINE:
1061			device_printf(dr->ms_disk, "drive online\n");
1062			break;
1063		    case MLX_SYSD_CRITICAL:
1064			device_printf(dr->ms_disk, "drive critical\n");
1065			break;
1066		    }
1067		    /* save new state */
1068		    dr->ms_state = mes[i].sd_state;
1069		}
1070	    }
1071	}
1072	break;
1073    }
1074    default:
1075	break;
1076    }
1077
1078 out:
1079    free(mc->mc_data, M_DEVBUF);
1080    mlx_releasecmd(mc);
1081    /* this event is done */
1082    MLX_PERIODIC_UNBUSY(sc);
1083}
1084
1085/********************************************************************************
1086 * Instigate a poll for one event log message on (sc).
1087 * We only poll for one message at a time, to keep our command usage down.
1088 */
1089static void
1090mlx_periodic_eventlog_poll(struct mlx_softc *sc)
1091{
1092    struct mlx_command	*mc;
1093    void		*result = NULL;
1094    int			error;
1095
1096    debug("called");
1097
1098    /* presume we are going to create another event */
1099    MLX_PERIODIC_BUSY(sc);
1100
1101    /* get ourselves a command buffer */
1102    error = 1;
1103    if ((mc = mlx_alloccmd(sc)) == NULL)
1104	goto out;
1105    /* allocate the response structure */
1106    if ((result = malloc(/*sizeof(struct mlx_eventlog_entry)*/1024, M_DEVBUF, M_NOWAIT)) == NULL)
1107	goto out;
1108    /* get a command slot */
1109    if (mlx_getslot(mc))
1110	goto out;
1111
1112    /* map the command so the controller can see it */
1113    mc->mc_data = result;
1114    mc->mc_length = /*sizeof(struct mlx_eventlog_entry)*/1024;
1115    mlx_mapcmd(mc);
1116
1117    /* build the command to get one entry */
1118    mlx_make_type3(mc, MLX_CMD_LOGOP, MLX_LOGOP_GET, 1, sc->mlx_lastevent, 0, 0, mc->mc_dataphys, 0);
1119    mc->mc_complete = mlx_periodic_eventlog_respond;
1120    mc->mc_private = mc;
1121
1122    /* start the command */
1123    if ((error = mlx_start(mc)) != 0)
1124	goto out;
1125
1126    error = 0;			/* success */
1127 out:
1128    if (error != 0) {
1129	if (mc != NULL)
1130	    mlx_releasecmd(mc);
1131	if (result != NULL)
1132	    free(result, M_DEVBUF);
1133	/* abort this event */
1134	MLX_PERIODIC_UNBUSY(sc);
1135    }
1136}
1137
1138/********************************************************************************
1139 * Handle the result of polling for a log message, generate diagnostic output.
1140 * If this wasn't the last message waiting for us, we'll go collect another.
1141 */
1142static char *mlx_sense_messages[] = {
1143    "because write recovery failed",
1144    "because of SCSI bus reset failure",
1145    "because of double check condition",
1146    "because it was removed",
1147    "because of gross error on SCSI chip",
1148    "because of bad tag returned from drive",
1149    "because of timeout on SCSI command",
1150    "because of reset SCSI command issued from system",
1151    "because busy or parity error count exceeded limit",
1152    "because of 'kill drive' command from system",
1153    "because of selection timeout",
1154    "due to SCSI phase sequence error",
1155    "due to unknown status"
1156};
1157
1158static void
1159mlx_periodic_eventlog_respond(struct mlx_command *mc)
1160{
1161    struct mlx_softc		*sc = mc->mc_sc;
1162    struct mlx_eventlog_entry	*el = (struct mlx_eventlog_entry *)mc->mc_data;
1163    char			*reason;
1164
1165    debug("called");
1166
1167    if (mc->mc_status == 0) {
1168	sc->mlx_lastevent++;		/* got the message OK */
1169
1170	/* handle event log message */
1171	switch(el->el_type) {
1172	    /*
1173	     * This is the only sort of message we understand at the moment.
1174	     * The tests here are probably incomplete.
1175	     */
1176	case MLX_LOGMSG_SENSE:	/* sense data */
1177	    /* Mylex vendor-specific message indicating a drive was killed? */
1178	    if ((el->el_sensekey == 9) &&
1179		(el->el_asc == 0x80)) {
1180		if (el->el_asq < (sizeof(mlx_sense_messages) / sizeof(mlx_sense_messages[0]))) {
1181		    reason = mlx_sense_messages[el->el_asq];
1182		} else {
1183		    reason = "for unknown reason";
1184		}
1185		device_printf(sc->mlx_dev, "physical drive %d:%d killed %s\n",
1186			      el->el_channel, el->el_target, reason);
1187	    }
1188	    /* SCSI drive was reset? */
1189	    if ((el->el_sensekey == 6) && (el->el_asc == 0x29)) {
1190		device_printf(sc->mlx_dev, "physical drive %d:%d reset\n",
1191			      el->el_channel, el->el_target);
1192	    }
1193	    /* SCSI drive error? */
1194	    if (!((el->el_sensekey == 0) ||
1195		  ((el->el_sensekey == 2) &&
1196		   (el->el_asc == 0x04) &&
1197		   ((el->el_asq == 0x01) ||
1198		    (el->el_asq == 0x02))))) {
1199		device_printf(sc->mlx_dev, "physical drive %d:%d error log: sense = %d asc = %x asq = %x\n",
1200			      el->el_channel, el->el_target, el->el_sensekey, el->el_asc, el->el_asq);
1201		device_printf(sc->mlx_dev, "  info %4D csi %4D\n", el->el_information, ":", el->el_csi, ":");
1202	    }
1203	    break;
1204
1205	default:
1206	    device_printf(sc->mlx_dev, "unknown log message type 0x%x\n", el->el_type);
1207	    break;
1208	}
1209    } else {
1210	device_printf(sc->mlx_dev, "error reading message log - %s\n", mlx_diagnose_command(mc));
1211    }
1212
1213    /* dispose of command and data */
1214    free(mc->mc_data, M_DEVBUF);
1215    mlx_releasecmd(mc);
1216
1217    /* is there another message to obtain? */
1218    if (sc->mlx_lastevent != sc->mlx_currevent)
1219	mlx_periodic_eventlog_poll(sc);
1220
1221    /* this event is done */
1222    MLX_PERIODIC_UNBUSY(sc);
1223}
1224
1225/********************************************************************************
1226 * Handle the completion of a rebuild operation.
1227 */
1228static void
1229mlx_periodic_rebuild(struct mlx_command *mc)
1230{
1231    struct mlx_softc		*sc = mc->mc_sc;
1232    struct mlx_rebuild_stat	*mr = (struct mlx_rebuild_stat *)mc->mc_private;
1233
1234    switch(mc->mc_status) {
1235    case 0:				/* all OK, rebuild still running */
1236	sc->mlx_rebuildstat = mr->rb_remaining;
1237	break;
1238
1239    case 0x0105:			/* rebuild/check finished */
1240	if (sc->mlx_rebuild >= 0) {
1241	    device_printf(sc->mlx_sysdrive[sc->mlx_rebuild].ms_disk, "rebuild completed\n");
1242	    sc->mlx_rebuild = -1;
1243	} else if (sc->mlx_check >= 0) {
1244	    device_printf(sc->mlx_sysdrive[sc->mlx_check].ms_disk, "consistency check completed\n");
1245	    sc->mlx_check = -1;
1246	} else {
1247	    device_printf(sc->mlx_dev, "consistency check completed\n");
1248	}
1249	break;
1250    }
1251    free(mc->mc_data, M_DEVBUF);
1252    mlx_releasecmd(mc);
1253    /* this event is done */
1254    MLX_PERIODIC_UNBUSY(sc);
1255}
1256
1257/********************************************************************************
1258 ********************************************************************************
1259                                                                    Channel Pause
1260 ********************************************************************************
1261 ********************************************************************************/
1262
1263/********************************************************************************
1264 * It's time to perform a channel pause action for (sc), either start or stop
1265 * the pause.
1266 */
1267static void
1268mlx_pause_action(struct mlx_softc *sc)
1269{
1270    struct mlx_command	*mc;
1271    int			failsafe, i, command;
1272
1273    /* What are we doing here? */
1274    if (sc->mlx_pause.mp_when == 0) {
1275	command = MLX_CMD_STARTCHANNEL;
1276	failsafe = 0;
1277
1278    } else {
1279	command = MLX_CMD_STOPCHANNEL;
1280
1281	/*
1282	 * Channels will always start again after the failsafe period,
1283	 * which is specified in multiples of 30 seconds.
1284	 * This constrains us to a maximum pause of 450 seconds.
1285	 */
1286	failsafe = ((sc->mlx_pause.mp_howlong - time_second) + 5) / 30;
1287	if (failsafe > 0xf) {
1288	    failsafe = 0xf;
1289	    sc->mlx_pause.mp_howlong = time_second + (0xf * 30) - 5;
1290	}
1291    }
1292
1293    /* build commands for every channel requested */
1294    for (i = 0; i < sc->mlx_nchan; i++) {
1295	if ((1 << i) & sc->mlx_pause.mp_which) {
1296
1297	    /* get ourselves a command buffer */
1298	    if ((mc = mlx_alloccmd(sc)) == NULL)
1299		goto fail;
1300	    /* get a command slot */
1301	    mc->mc_flags |= MLX_CMD_PRIORITY;
1302	    if (mlx_getslot(mc))
1303		goto fail;
1304
1305	    /* build the command */
1306	    mlx_make_type2(mc, command, (failsafe << 4) | i, 0, 0, 0, 0, 0, 0, 0);
1307	    mc->mc_complete = mlx_pause_done;
1308	    mc->mc_private = sc;		/* XXX not needed */
1309	    if (mlx_start(mc))
1310		goto fail;
1311	    /* command submitted OK */
1312	    return;
1313
1314	fail:
1315	    device_printf(sc->mlx_dev, "%s failed for channel %d\n",
1316			  command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", i);
1317	    if (mc != NULL)
1318		mlx_releasecmd(mc);
1319	}
1320    }
1321}
1322
1323static void
1324mlx_pause_done(struct mlx_command *mc)
1325{
1326    struct mlx_softc	*sc = mc->mc_sc;
1327    int			command = mc->mc_mailbox[0];
1328    int			channel = mc->mc_mailbox[2] & 0xf;
1329
1330    if (mc->mc_status != 0) {
1331	device_printf(sc->mlx_dev, "%s command failed - %s\n",
1332		      command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", mlx_diagnose_command(mc));
1333    } else if (command == MLX_CMD_STOPCHANNEL) {
1334	device_printf(sc->mlx_dev, "channel %d pausing for %ld seconds\n",
1335		      channel, sc->mlx_pause.mp_howlong - time_second);
1336    } else {
1337	device_printf(sc->mlx_dev, "channel %d resuming\n", channel);
1338    }
1339    mlx_releasecmd(mc);
1340}
1341
1342/********************************************************************************
1343 ********************************************************************************
1344                                                               Command Submission
1345 ********************************************************************************
1346 ********************************************************************************/
1347
1348/********************************************************************************
1349 * Perform an Enquiry command using a type-3 command buffer and a return a single
1350 * linear result buffer.  If the completion function is specified, it will
1351 * be called with the completed command (and the result response will not be
1352 * valid until that point).  Otherwise, the command will either be busy-waited
1353 * for (interrupts not enabled), or slept for.
1354 */
1355static void *
1356mlx_enquire(struct mlx_softc *sc, int command, size_t bufsize, void (* complete)(struct mlx_command *mc))
1357{
1358    struct mlx_command	*mc;
1359    void		*result;
1360    int			error;
1361
1362    debug("called");
1363
1364    /* get ourselves a command buffer */
1365    error = 1;
1366    result = NULL;
1367    if ((mc = mlx_alloccmd(sc)) == NULL)
1368	goto out;
1369    /* allocate the response structure */
1370    if ((result = malloc(bufsize, M_DEVBUF, M_NOWAIT)) == NULL)
1371	goto out;
1372    /* get a command slot */
1373    mc->mc_flags |= MLX_CMD_PRIORITY | MLX_CMD_DATAOUT;
1374    if (mlx_getslot(mc))
1375	goto out;
1376
1377    /* map the command so the controller can see it */
1378    mc->mc_data = result;
1379    mc->mc_length = bufsize;
1380    mlx_mapcmd(mc);
1381
1382    /* build an enquiry command */
1383    mlx_make_type2(mc, command, 0, 0, 0, 0, 0, 0, mc->mc_dataphys, 0);
1384
1385    /* do we want a completion callback? */
1386    if (complete != NULL) {
1387	mc->mc_complete = complete;
1388	mc->mc_private = mc;
1389	if ((error = mlx_start(mc)) != 0)
1390	    goto out;
1391    } else {
1392	/* run the command in either polled or wait mode */
1393	if ((sc->mlx_state & MLX_STATE_INTEN) ? mlx_wait_command(mc) : mlx_poll_command(mc))
1394	    goto out;
1395
1396	/* command completed OK? */
1397	if (mc->mc_status != 0) {
1398	    device_printf(sc->mlx_dev, "ENQUIRY failed - %s\n", mlx_diagnose_command(mc));
1399	    goto out;
1400	}
1401    }
1402    error = 0;			/* success */
1403 out:
1404    /* we got a command, but nobody else will free it */
1405    if ((complete == NULL) && (mc != NULL))
1406	mlx_releasecmd(mc);
1407    /* we got an error, and we allocated a result */
1408    if ((error != 0) && (result != NULL)) {
1409	free(result, M_DEVBUF);
1410	result = NULL;
1411    }
1412    return(result);
1413}
1414
1415
1416/********************************************************************************
1417 * Perform a Flush command on the nominated controller.
1418 *
1419 * May be called with interrupts enabled or disabled; will not return until
1420 * the flush operation completes or fails.
1421 */
1422static int
1423mlx_flush(struct mlx_softc *sc)
1424{
1425    struct mlx_command	*mc;
1426    int			error;
1427
1428    debug("called");
1429
1430    /* get ourselves a command buffer */
1431    error = 1;
1432    if ((mc = mlx_alloccmd(sc)) == NULL)
1433	goto out;
1434    /* get a command slot */
1435    if (mlx_getslot(mc))
1436	goto out;
1437
1438    /* build a flush command */
1439    mlx_make_type2(mc, MLX_CMD_FLUSH, 0, 0, 0, 0, 0, 0, 0, 0);
1440
1441    /* run the command in either polled or wait mode */
1442    if ((sc->mlx_state & MLX_STATE_INTEN) ? mlx_wait_command(mc) : mlx_poll_command(mc))
1443	goto out;
1444
1445    /* command completed OK? */
1446    if (mc->mc_status != 0) {
1447	device_printf(sc->mlx_dev, "FLUSH failed - %s\n", mlx_diagnose_command(mc));
1448	goto out;
1449    }
1450
1451    error = 0;			/* success */
1452 out:
1453    if (mc != NULL)
1454	mlx_releasecmd(mc);
1455    return(error);
1456}
1457
1458/********************************************************************************
1459 * Start a background rebuild on the nominated controller/channel/target.
1460 *
1461 * May be called with interrupts enabled or disabled; will return as soon as the
1462 * operation has started or been refused.
1463 */
1464static int
1465mlx_rebuild(struct mlx_softc *sc, int channel, int target)
1466{
1467    struct mlx_command	*mc;
1468    int			error;
1469
1470    debug("called");
1471
1472    /* get ourselves a command buffer */
1473    error = 0x10000;
1474    if ((mc = mlx_alloccmd(sc)) == NULL)
1475	goto out;
1476    /* get a command slot */
1477    if (mlx_getslot(mc))
1478	goto out;
1479
1480    /* build a rebuild command */
1481    mlx_make_type2(mc, MLX_CMD_REBUILDASYNC, channel, target, 0, 0, 0, 0, 0, 0);
1482
1483    /* run the command in either polled or wait mode */
1484    if ((sc->mlx_state & MLX_STATE_INTEN) ? mlx_wait_command(mc) : mlx_poll_command(mc))
1485	goto out;
1486
1487    /* command completed OK? */
1488    if (mc->mc_status != 0) {
1489	device_printf(sc->mlx_dev, "REBUILD ASYNC failed - %s\n", mlx_diagnose_command(mc));
1490    } else {
1491	device_printf(sc->mlx_sysdrive[sc->mlx_rebuild].ms_disk, "rebuild started");
1492    }
1493    error = mc->mc_status;
1494
1495 out:
1496    if (mc != NULL)
1497	mlx_releasecmd(mc);
1498    return(error);
1499}
1500
1501/********************************************************************************
1502 * Run the command (mc) and return when it completes.
1503 *
1504 * Interrupts need to be enabled; returns nonzero on error.
1505 */
1506static int
1507mlx_wait_command(struct mlx_command *mc)
1508{
1509    struct mlx_softc	*sc = mc->mc_sc;
1510    int			error, count;
1511
1512    debug("called");
1513
1514    mc->mc_complete = NULL;
1515    mc->mc_private = mc;		/* wake us when you're done */
1516    if ((error = mlx_start(mc)) != 0)
1517	return(error);
1518
1519    count = 0;
1520    /* XXX better timeout? */
1521    while ((mc->mc_status == MLX_STATUS_BUSY) && (count < 30)) {
1522	tsleep(mc->mc_private, PRIBIO | PCATCH, "mlxwcmd", hz);
1523    }
1524
1525    if (mc->mc_status != 0) {
1526	device_printf(sc->mlx_dev, "I/O error 0x%x\n", mc->mc_status);
1527	return(EIO);
1528    }
1529    return(0);
1530}
1531
1532
1533/********************************************************************************
1534 * Start the command (mc) and busy-wait for it to complete.
1535 *
1536 * Should only be used when interrupts are not available. Returns 0 on
1537 * success, nonzero on error.
1538 * Successfully completed commands are dequeued.
1539 */
1540static int
1541mlx_poll_command(struct mlx_command *mc)
1542{
1543    struct mlx_softc	*sc = mc->mc_sc;
1544    int			error, count, s;
1545
1546    debug("called");
1547
1548    mc->mc_complete = NULL;
1549    mc->mc_private = NULL;	/* we will poll for it */
1550    if ((error = mlx_start(mc)) != 0)
1551	return(error);
1552
1553    count = 0;
1554    do {
1555	/* poll for completion */
1556	mlx_done(mc->mc_sc);
1557    } while ((mc->mc_status == MLX_STATUS_BUSY) && (count < 10000));
1558    if (mc->mc_status != MLX_STATUS_BUSY) {
1559	s = splbio();
1560	TAILQ_REMOVE(&sc->mlx_donecmd, mc, mc_link);
1561	splx(s);
1562	return(0);
1563    }
1564    device_printf(sc->mlx_dev, "I/O error 0x%x\n", mc->mc_status);
1565    return(EIO);
1566}
1567
1568/********************************************************************************
1569 * Pull as much work off the softc's work queue as possible and give it to the
1570 * controller.  Leave a couple of slots free for emergencies.
1571 *
1572 * Must be called at splbio or in an equivalent fashion that prevents
1573 * reentry or activity on the bufq..
1574 */
1575static void
1576mlx_startio(struct mlx_softc *sc)
1577{
1578    struct mlx_command	*mc;
1579    struct mlxd_softc	*mlxd;
1580    struct buf		*bp;
1581    int			blkcount;
1582    int			driveno;
1583    int			cmd;
1584
1585    /* spin until something prevents us from doing any work */
1586    for (;;) {
1587
1588	/* see if there's work to be done */
1589	if ((bp = bufq_first(&sc->mlx_bufq)) == NULL)
1590	    break;
1591	/* get a command */
1592	if ((mc = mlx_alloccmd(sc)) == NULL)
1593	    break;
1594	/* get a slot for the command */
1595	if (mlx_getslot(mc) != 0) {
1596	    mlx_releasecmd(mc);
1597	    break;
1598	}
1599	/* get the buf containing our work */
1600	bufq_remove(&sc->mlx_bufq, bp);
1601	sc->mlx_waitbufs--;
1602
1603	/* connect the buf to the command */
1604	mc->mc_complete = mlx_completeio;
1605	mc->mc_private = bp;
1606	mc->mc_data = bp->b_data;
1607	mc->mc_length = bp->b_bcount;
1608	if (bp->b_flags & B_READ) {
1609	    mc->mc_flags |= MLX_CMD_DATAIN;
1610	    cmd = MLX_CMD_READOLDSG;
1611	} else {
1612	    mc->mc_flags |= MLX_CMD_DATAOUT;
1613	    cmd = MLX_CMD_WRITEOLDSG;
1614	}
1615
1616	/* map the command so the controller can work with it */
1617	mlx_mapcmd(mc);
1618
1619	/* build a suitable I/O command (assumes 512-byte rounded transfers) */
1620	mlxd = (struct mlxd_softc *)bp->b_dev->si_drv1;
1621	driveno = mlxd->mlxd_drive - &sc->mlx_sysdrive[0];
1622	blkcount = bp->b_bcount / MLX_BLKSIZE;
1623
1624	if ((bp->b_blkno + blkcount) > sc->mlx_sysdrive[driveno].ms_size)
1625	    device_printf(sc->mlx_dev, "I/O beyond end of unit (%u,%d > %u)\n",
1626			  bp->b_blkno, blkcount, sc->mlx_sysdrive[driveno].ms_size);
1627
1628	/*
1629	 * Build the I/O command.  Note that the SG list type bits are set to zero,
1630	 * denoting the format of SG list that we are using.
1631	 */
1632	mlx_make_type5(mc, cmd,
1633		       blkcount & 0xff, 				/* xfer length low byte */
1634		       (driveno << 3) | ((blkcount >> 8) & 0x07),	/* target and length high 3 bits */
1635		       bp->b_blkno,					/* physical block number */
1636		       mc->mc_sgphys,					/* location of SG list */
1637		       mc->mc_nsgent & 0x3f);				/* size of SG list (top 2 bits clear) */
1638
1639
1640	/* try to give command to controller */
1641	if (mlx_start(mc) != 0) {
1642	    /* fail the command */
1643	    mc->mc_status = MLX_STATUS_WEDGED;
1644	    mlx_completeio(mc);
1645	}
1646    }
1647}
1648
1649/********************************************************************************
1650 * Handle completion of an I/O command.
1651 */
1652static void
1653mlx_completeio(struct mlx_command *mc)
1654{
1655    struct mlx_softc	*sc = mc->mc_sc;
1656    struct buf		*bp = (struct buf *)mc->mc_private;
1657    struct mlxd_softc	*mlxd = (struct mlxd_softc *)bp->b_dev->si_drv1;
1658
1659    if (mc->mc_status != MLX_STATUS_OK) {	/* could be more verbose here? */
1660	bp->b_error = EIO;
1661	bp->b_flags |= B_ERROR;
1662
1663	switch(mc->mc_status) {
1664	case MLX_STATUS_RDWROFFLINE:		/* system drive has gone offline */
1665	    device_printf(mlxd->mlxd_dev, "drive offline\n");
1666	    /* should signal this with a return code */
1667	    mlxd->mlxd_drive->ms_state = MLX_SYSD_OFFLINE;
1668	    break;
1669
1670	default:				/* other I/O error */
1671	    device_printf(sc->mlx_dev, "I/O error - %s\n", mlx_diagnose_command(mc));
1672#if 0
1673	    device_printf(sc->mlx_dev, "  b_bcount %ld  blkcount %ld  b_blkno %d\n",
1674			  bp->b_bcount, bp->b_bcount / MLX_BLKSIZE, bp->b_blkno);
1675	    device_printf(sc->mlx_dev, "  %13D\n", mc->mc_mailbox, " ");
1676#endif
1677	    break;
1678	}
1679    }
1680    mlx_releasecmd(mc);
1681    mlxd_intr(bp);
1682}
1683
1684/********************************************************************************
1685 * Take a command from user-space and try to run it.
1686 */
1687static int
1688mlx_user_command(struct mlx_softc *sc, struct mlx_usercommand *mu)
1689{
1690    struct mlx_command	*mc;
1691    void		*kbuf;
1692    int			error;
1693
1694    kbuf = NULL;
1695    mc = NULL;
1696    error = ENOMEM;
1697    /* get a kernel buffer for the transfer */
1698    if (mu->mu_datasize > 0) {
1699	if ((kbuf = malloc(mu->mu_datasize, M_DEVBUF, M_WAITOK)) == NULL)
1700	    goto out;
1701	if ((mu->mu_bufptr < 0) || (mu->mu_bufptr > (sizeof(mu->mu_command) < sizeof(u_int32_t)))) {
1702	    error = EINVAL;
1703	    goto out;
1704	}
1705    }
1706    /* get ourselves a command buffer */
1707    if ((mc = mlx_alloccmd(sc)) == NULL)
1708	goto out;
1709
1710    /* copy the command and data */
1711    bcopy(mu->mu_command, mc->mc_mailbox, sizeof(mc->mc_mailbox));
1712    if ((mu->mu_datasize > 0) && ((error = copyin(mu->mu_buf, kbuf, mu->mu_datasize))))
1713	goto out;
1714
1715    /* get a command slot */
1716    if (mlx_getslot(mc))
1717	goto out;
1718
1719    /* map the command so the controller can see it */
1720    mc->mc_data = kbuf;
1721    mc->mc_length = mu->mu_datasize;
1722    mlx_mapcmd(mc);
1723
1724    /* if there's a data buffer, fix up the command */
1725    if (mu->mu_datasize > 0) {
1726	mc->mc_mailbox[mu->mu_bufptr    ] =  mc->mc_length        & 0xff;
1727	mc->mc_mailbox[mu->mu_bufptr + 1] = (mc->mc_length >> 8)  & 0xff;
1728	mc->mc_mailbox[mu->mu_bufptr + 2] = (mc->mc_length >> 16) & 0xff;
1729	mc->mc_mailbox[mu->mu_bufptr + 3] = (mc->mc_length >> 24) & 0xff;
1730    }
1731
1732    /* submit the command and wait */
1733    if ((error = mlx_wait_command(mc)) != 0)
1734	goto out;
1735
1736    /* copy out status and data */
1737    mu->mu_status = mc->mc_status;
1738    if ((mu->mu_datasize > 0) && ((error = copyout(kbuf, mu->mu_buf, mu->mu_datasize))))
1739	goto out;
1740    error = 0;
1741
1742 out:
1743    mlx_releasecmd(mc);
1744    if (kbuf != NULL)
1745	free(kbuf, M_DEVBUF);
1746    return(error);
1747}
1748
1749/********************************************************************************
1750 ********************************************************************************
1751                                                        Command I/O to Controller
1752 ********************************************************************************
1753 ********************************************************************************/
1754
1755/********************************************************************************
1756 * Find a free command slot for (mc).
1757 *
1758 * Don't hand out a slot to a normal-priority command unless there are at least
1759 * 4 slots free for priority commands.
1760 */
1761static int
1762mlx_getslot(struct mlx_command *mc)
1763{
1764    struct mlx_softc	*sc = mc->mc_sc;
1765    int			s, slot, limit;
1766
1767    debug("called  mc %p  sc %p", mc, sc);
1768
1769    /* enforce slot-usage limit */
1770    limit = (mc->mc_flags & MLX_CMD_PRIORITY) ? sc->mlx_maxiop : sc->mlx_maxiop - 4;
1771    if (sc->mlx_busycmds > limit)
1772	return(EBUSY);
1773
1774    /*
1775     * Allocate an outstanding command slot
1776     *
1777     * XXX linear search is slow
1778     */
1779    s = splbio();
1780    for (slot = 0; slot < sc->mlx_maxiop; slot++) {
1781	debug("try slot %d", slot);
1782	if (sc->mlx_busycmd[slot] == NULL)
1783	    break;
1784    }
1785    if (slot < sc->mlx_maxiop) {
1786	sc->mlx_busycmd[slot] = mc;
1787	sc->mlx_busycmds++;
1788    }
1789    splx(s);
1790
1791    /* out of slots? */
1792    if (slot >= sc->mlx_maxiop)
1793	return(EBUSY);
1794
1795    debug("got slot %d", slot);
1796    mc->mc_slot = slot;
1797    return(0);
1798}
1799
1800/********************************************************************************
1801 * Map/unmap (mc)'s data in the controller's addressable space.
1802 */
1803static void
1804mlx_setup_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
1805{
1806    struct mlx_command	*mc = (struct mlx_command *)arg;
1807    struct mlx_softc	*sc = mc->mc_sc;
1808    struct mlx_sgentry	*sg;
1809    int			i;
1810
1811    debug("called");
1812
1813    /* get base address of s/g table */
1814    sg = sc->mlx_sgtable + (mc->mc_slot * MLX_NSEG);
1815
1816    /* save s/g table information in command */
1817    mc->mc_nsgent = nsegments;
1818    mc->mc_sgphys = sc->mlx_sgbusaddr + (mc->mc_slot * MLX_NSEG * sizeof(struct mlx_sgentry));
1819    mc->mc_dataphys = segs[0].ds_addr;
1820
1821    /* populate s/g table */
1822    for (i = 0; i < nsegments; i++, sg++) {
1823	sg->sg_addr = segs[i].ds_addr;
1824	sg->sg_count = segs[i].ds_len;
1825    }
1826}
1827
1828static void
1829mlx_mapcmd(struct mlx_command *mc)
1830{
1831    struct mlx_softc	*sc = mc->mc_sc;
1832
1833    debug("called");
1834
1835    /* if the command involves data at all */
1836    if (mc->mc_data != NULL) {
1837
1838	/* map the data buffer into bus space and build the s/g list */
1839	bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data, mc->mc_length,
1840			mlx_setup_dmamap, mc, 0);
1841	if (mc->mc_flags & MLX_CMD_DATAIN)
1842	    bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_PREREAD);
1843	if (mc->mc_flags & MLX_CMD_DATAOUT)
1844	    bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_PREWRITE);
1845    }
1846}
1847
1848static void
1849mlx_unmapcmd(struct mlx_command *mc)
1850{
1851    struct mlx_softc	*sc = mc->mc_sc;
1852
1853    debug("called");
1854
1855    /* if the command involved data at all */
1856    if (mc->mc_data != NULL) {
1857
1858	if (mc->mc_flags & MLX_CMD_DATAIN)
1859	    bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTREAD);
1860	if (mc->mc_flags & MLX_CMD_DATAOUT)
1861	    bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTWRITE);
1862
1863	bus_dmamap_unload(sc->mlx_buffer_dmat, mc->mc_dmamap);
1864    }
1865}
1866
1867/********************************************************************************
1868 * Try to deliver (mc) to the controller.  Take care of any completed commands
1869 * that we encounter while doing so.
1870 *
1871 * Can be called at any interrupt level, with or without interrupts enabled.
1872 */
1873static int
1874mlx_start(struct mlx_command *mc)
1875{
1876    struct mlx_softc	*sc = mc->mc_sc;
1877    int			i, s, done, worked;
1878
1879    debug("called");
1880
1881    /* save the slot number as ident so we can handle this command when complete */
1882    mc->mc_mailbox[0x1] = mc->mc_slot;
1883
1884    /* set impossible status so that a woken sleeper can tell the command is in progress */
1885    mc->mc_status = MLX_STATUS_BUSY;
1886
1887    /* assume we don't collect any completed commands */
1888    worked = 0;
1889
1890    /* spin waiting for the mailbox */
1891    for (i = 100000, done = 0; (i > 0) && !done; i--) {
1892	s = splbio();
1893	done = sc->mlx_tryqueue(sc, mc);
1894	splx(s);
1895	/* check for command completion while we're at it */
1896	if (mlx_done(sc))
1897	    worked = 1;
1898    }
1899    /* check to see if we picked up any completed commands */
1900    if (worked)
1901	mlx_complete(sc);
1902
1903    /* command is enqueued */
1904    if (done)
1905	return(0);
1906
1907    /*
1908     * We couldn't get the controller to take the command.  Revoke the slot
1909     * that the command was given and return it with a bad status.
1910     */
1911    sc->mlx_busycmd[mc->mc_slot] = NULL;
1912    device_printf(sc->mlx_dev, "controller wedged (not taking commands)\n");
1913    mc->mc_status = MLX_STATUS_WEDGED;
1914    return(EIO);
1915}
1916
1917/********************************************************************************
1918 * Look at the controller (sc) and see if a command has been completed.
1919 * If so, move the command buffer to the done queue for later collection
1920 * and free the slot for immediate reuse.
1921 *
1922 * Returns nonzero if anything was added to the done queue.
1923 */
1924static int
1925mlx_done(struct mlx_softc *sc)
1926{
1927    struct mlx_command	*mc;
1928    int			s;
1929    u_int8_t		slot;
1930    u_int16_t		status;
1931
1932    debug("called");
1933
1934    s = splbio();
1935    mc = NULL;
1936    slot = 0;
1937
1938    /* poll for a completed command's identifier and status */
1939    if (sc->mlx_findcomplete(sc, &slot, &status)) {
1940	mc = sc->mlx_busycmd[slot];		/* find command */
1941	if (mc != NULL) {			/* paranoia */
1942	    if (mc->mc_status == MLX_STATUS_BUSY) {
1943		mc->mc_status = status;			/* save status */
1944
1945		/* move completed command to 'done' queue */
1946		TAILQ_INSERT_TAIL(&sc->mlx_donecmd, mc, mc_link);
1947
1948		/* free slot for reuse */
1949		sc->mlx_busycmd[slot] = NULL;
1950		sc->mlx_busycmds--;
1951	    } else {
1952		device_printf(sc->mlx_dev, "duplicate done event for slot %d\n", slot);
1953		mc = NULL;
1954	    }
1955	} else {
1956	    device_printf(sc->mlx_dev, "done event for nonbusy slot %d\n", slot);
1957	}
1958    }
1959    splx(s);
1960
1961    if (mc != NULL) {
1962	/* unmap the command's data buffer */
1963	mlx_unmapcmd(mc);
1964	return(1);
1965    }
1966    return(0);
1967}
1968
1969/********************************************************************************
1970 * Handle completion for all commands on (sc)'s done queue.
1971 */
1972static void
1973mlx_complete(struct mlx_softc *sc)
1974{
1975    struct mlx_command	*mc, *nc;
1976    int			s, count;
1977
1978    debug("called");
1979
1980    s = splbio();
1981    count = 0;
1982
1983    /* scan the list of done commands */
1984    mc = TAILQ_FIRST(&sc->mlx_donecmd);
1985    while (mc != NULL) {
1986	nc = TAILQ_NEXT(mc, mc_link);
1987
1988	/* XXX this is slightly bogus */
1989	if (count++ > (sc->mlx_maxiop * 2))
1990	    panic("mlx_donecmd list corrupt!");
1991
1992	/*
1993	 * Does the command have a completion handler?
1994	 */
1995	if (mc->mc_complete != NULL) {
1996	    /* remove from list and give to handler */
1997	    TAILQ_REMOVE(&sc->mlx_donecmd, mc, mc_link);
1998	    mc->mc_complete(mc);
1999
2000	    /*
2001	     * Is there a sleeper waiting on this command?
2002	     */
2003	} else if (mc->mc_private != NULL) {	/* sleeping caller wants to know about it */
2004
2005	    /* remove from list and wake up sleeper */
2006	    TAILQ_REMOVE(&sc->mlx_donecmd, mc, mc_link);
2007	    wakeup_one(mc->mc_private);
2008
2009	    /*
2010	     * Leave the command for a caller that's polling for it.
2011	     */
2012	} else {
2013	}
2014	mc = nc;
2015    }
2016    splx(s);
2017
2018    /* queue some more work if there is any */
2019    mlx_startio(sc);
2020}
2021
2022/********************************************************************************
2023 ********************************************************************************
2024                                                        Command Buffer Management
2025 ********************************************************************************
2026 ********************************************************************************/
2027
2028/********************************************************************************
2029 * Get a new command buffer.
2030 *
2031 * This may return NULL in low-memory cases.
2032 *
2033 * Note that using malloc() is expensive (the command buffer is << 1 page) but
2034 * necessary if we are to be a loadable module before the zone allocator is fixed.
2035 *
2036 * If possible, we recycle a command buffer that's been used before.
2037 *
2038 * XXX Note that command buffers are not cleaned out - it is the caller's
2039 *     responsibility to ensure that all required fields are filled in before
2040 *     using a buffer.
2041 */
2042static struct mlx_command *
2043mlx_alloccmd(struct mlx_softc *sc)
2044{
2045    struct mlx_command	*mc;
2046    int			error;
2047    int			s;
2048
2049    debug("called");
2050
2051    s = splbio();
2052    if ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL)
2053	TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link);
2054    splx(s);
2055
2056    /* allocate a new command buffer? */
2057    if (mc == NULL) {
2058	mc = (struct mlx_command *)malloc(sizeof(*mc), M_DEVBUF, M_NOWAIT);
2059	if (mc != NULL) {
2060	    bzero(mc, sizeof(*mc));
2061	    mc->mc_sc = sc;
2062	    error = bus_dmamap_create(sc->mlx_buffer_dmat, 0, &mc->mc_dmamap);
2063	    if (error) {
2064		free(mc, M_DEVBUF);
2065		return(NULL);
2066	    }
2067	}
2068    }
2069    return(mc);
2070}
2071
2072/********************************************************************************
2073 * Release a command buffer for recycling.
2074 *
2075 * XXX It might be a good idea to limit the number of commands we save for reuse
2076 *     if it's shown that this list bloats out massively.
2077 */
2078static void
2079mlx_releasecmd(struct mlx_command *mc)
2080{
2081    int		s;
2082
2083    debug("called");
2084
2085    s = splbio();
2086    TAILQ_INSERT_HEAD(&mc->mc_sc->mlx_freecmds, mc, mc_link);
2087    splx(s);
2088}
2089
2090/********************************************************************************
2091 * Permanently discard a command buffer.
2092 */
2093static void
2094mlx_freecmd(struct mlx_command *mc)
2095{
2096    struct mlx_softc	*sc = mc->mc_sc;
2097
2098    debug("called");
2099
2100    bus_dmamap_destroy(sc->mlx_buffer_dmat, mc->mc_dmamap);
2101    free(mc, M_DEVBUF);
2102}
2103
2104
2105/********************************************************************************
2106 ********************************************************************************
2107                                                Type 3 interface accessor methods
2108 ********************************************************************************
2109 ********************************************************************************/
2110
2111/********************************************************************************
2112 * Try to give (mc) to the controller.  Returns 1 if successful, 0 on failure
2113 * (the controller is not ready to take a command).
2114 *
2115 * Must be called at splbio or in a fashion that prevents reentry.
2116 */
2117static int
2118mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2119{
2120    int		i;
2121
2122    debug("called");
2123
2124    /* ready for our command? */
2125    if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_FULL)) {
2126	/* copy mailbox data to window */
2127	for (i = 0; i < 13; i++)
2128	    MLX_V3_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
2129
2130	/* post command */
2131	MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_FULL);
2132	return(1);
2133    }
2134    return(0);
2135}
2136
2137/********************************************************************************
2138 * See if a command has been completed, if so acknowledge its completion
2139 * and recover the slot number and status code.
2140 *
2141 * Must be called at splbio or in a fashion that prevents reentry.
2142 */
2143static int
2144mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2145{
2146
2147    debug("called");
2148
2149    /* status available? */
2150    if (MLX_V3_GET_ODBR(sc) & MLX_V3_ODB_SAVAIL) {
2151	*slot = MLX_V3_GET_STATUS_IDENT(sc);		/* get command identifier */
2152	*status = MLX_V3_GET_STATUS(sc);		/* get status */
2153
2154	/* acknowledge completion */
2155	MLX_V3_PUT_ODBR(sc, MLX_V3_ODB_SAVAIL);
2156	MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_SACK);
2157	return(1);
2158    }
2159    return(0);
2160}
2161
2162/********************************************************************************
2163 * Enable/disable interrupts as requested. (No acknowledge required)
2164 *
2165 * Must be called at splbio or in a fashion that prevents reentry.
2166 */
2167static void
2168mlx_v3_intaction(struct mlx_softc *sc, int action)
2169{
2170    debug("called");
2171
2172    switch(action) {
2173    case MLX_INTACTION_DISABLE:
2174	MLX_V3_PUT_IER(sc, 0);
2175	sc->mlx_state &= ~MLX_STATE_INTEN;
2176	break;
2177    case MLX_INTACTION_ENABLE:
2178	MLX_V3_PUT_IER(sc, 1);
2179	sc->mlx_state |= MLX_STATE_INTEN;
2180	break;
2181    }
2182}
2183
2184
2185/********************************************************************************
2186 ********************************************************************************
2187                                                Type 4 interface accessor methods
2188 ********************************************************************************
2189 ********************************************************************************/
2190
2191/********************************************************************************
2192 * Try to give (mc) to the controller.  Returns 1 if successful, 0 on failure
2193 * (the controller is not ready to take a command).
2194 *
2195 * Must be called at splbio or in a fashion that prevents reentry.
2196 */
2197static int
2198mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2199{
2200    int		i;
2201
2202    debug("called");
2203
2204    /* ready for our command? */
2205    if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_FULL)) {
2206	/* copy mailbox data to window */
2207	for (i = 0; i < 13; i++)
2208	    MLX_V4_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
2209
2210	/* post command */
2211	MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_HWMBOX_CMD);
2212	return(1);
2213    }
2214    return(0);
2215}
2216
2217/********************************************************************************
2218 * See if a command has been completed, if so acknowledge its completion
2219 * and recover the slot number and status code.
2220 *
2221 * Must be called at splbio or in a fashion that prevents reentry.
2222 */
2223static int
2224mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2225{
2226
2227    debug("called");
2228
2229    /* status available? */
2230    if (MLX_V4_GET_ODBR(sc) & MLX_V4_ODB_HWSAVAIL) {
2231	*slot = MLX_V4_GET_STATUS_IDENT(sc);		/* get command identifier */
2232	*status = MLX_V4_GET_STATUS(sc);		/* get status */
2233
2234	/* acknowledge completion */
2235	MLX_V4_PUT_ODBR(sc, MLX_V4_ODB_HWMBOX_ACK);
2236	MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_SACK);
2237	return(1);
2238    }
2239    return(0);
2240}
2241
2242/********************************************************************************
2243 * Enable/disable interrupts as requested.
2244 *
2245 * Must be called at splbio or in a fashion that prevents reentry.
2246 */
2247static void
2248mlx_v4_intaction(struct mlx_softc *sc, int action)
2249{
2250    debug("called");
2251
2252    switch(action) {
2253    case MLX_INTACTION_DISABLE:
2254	MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK | MLX_V4_IER_DISINT);
2255	sc->mlx_state &= ~MLX_STATE_INTEN;
2256	break;
2257    case MLX_INTACTION_ENABLE:
2258	MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK & ~MLX_V4_IER_DISINT);
2259	sc->mlx_state |= MLX_STATE_INTEN;
2260	break;
2261    }
2262}
2263
2264
2265/********************************************************************************
2266 ********************************************************************************
2267                                                                        Debugging
2268 ********************************************************************************
2269 ********************************************************************************/
2270
2271/********************************************************************************
2272 * Return a status message describing (mc)
2273 */
2274static char *mlx_status_messages[] = {
2275    "normal completion",			/* 00 */
2276    "irrecoverable data error",			/* 01 */
2277    "drive does not exist, or is offline",	/* 02 */
2278    "attempt to write beyond end of drive",	/* 03 */
2279    "bad data encountered",			/* 04 */
2280    "invalid log entry request",		/* 05 */
2281    "attempt to rebuild online drive",		/* 06 */
2282    "new disk failed during rebuild",		/* 07 */
2283    "invalid channel/target",			/* 08 */
2284    "rebuild/check already in progress",	/* 09 */
2285    "one or more disks are dead",		/* 10 */
2286    "invalid or non-redundant drive",		/* 11 */
2287    "channel is busy",				/* 12 */
2288    "channel is not stopped",			/* 13 */
2289};
2290
2291static struct
2292{
2293    int		command;
2294    u_int16_t	status;
2295    int		msg;
2296} mlx_messages[] = {
2297    {MLX_CMD_READOLDSG,		0x0001,	 1},
2298    {MLX_CMD_READOLDSG,		0x0002,	 1},
2299    {MLX_CMD_READOLDSG,		0x0105,	 3},
2300    {MLX_CMD_READOLDSG,		0x010c,	 4},
2301    {MLX_CMD_WRITEOLDSG,	0x0001,	 1},
2302    {MLX_CMD_WRITEOLDSG,	0x0002,	 1},
2303    {MLX_CMD_WRITEOLDSG,	0x0105,	 3},
2304    {MLX_CMD_LOGOP,		0x0105,	 5},
2305    {MLX_CMD_REBUILDASYNC,	0x0002,  6},
2306    {MLX_CMD_REBUILDASYNC,	0x0004,  7},
2307    {MLX_CMD_REBUILDASYNC,	0x0105,  8},
2308    {MLX_CMD_REBUILDASYNC,	0x0106,  9},
2309    {MLX_CMD_CHECKASYNC,	0x0002, 10},
2310    {MLX_CMD_CHECKASYNC,	0x0105, 11},
2311    {MLX_CMD_CHECKASYNC,	0x0106,  9},
2312    {MLX_CMD_STOPCHANNEL,	0x0106, 12},
2313    {MLX_CMD_STOPCHANNEL,	0x0105,  8},
2314    {MLX_CMD_STARTCHANNEL,	0x0005, 13},
2315    {MLX_CMD_STARTCHANNEL,	0x0105,  8},
2316    {-1, 0, 0}
2317};
2318
2319static char *
2320mlx_diagnose_command(struct mlx_command *mc)
2321{
2322    static char	unkmsg[80];
2323    int		i;
2324
2325    /* look up message in table */
2326    for (i = 0; mlx_messages[i].command != -1; i++)
2327	if ((mc->mc_mailbox[0] == mlx_messages[i].command) &&
2328	    (mc->mc_status == mlx_messages[i].status))
2329	    return(mlx_status_messages[mlx_messages[i].msg]);
2330
2331    sprintf(unkmsg, "unknown response 0x%x for command 0x%x", (int)mc->mc_status, (int)mc->mc_mailbox[0]);
2332    return(unkmsg);
2333}
2334
2335/*******************************************************************************
2336 * Return a string describing the controller (hwid)
2337 */
2338static char *
2339mlx_name_controller(u_int32_t hwid)
2340{
2341    static char		buf[80];
2342    char		smbuf[16];
2343    char		*submodel;
2344    int			nchn;
2345
2346    switch(hwid & 0xff) {
2347    case 0x01:
2348	submodel = "P/PD";
2349	break;
2350    case 0x02:
2351	submodel = "PL";
2352	break;
2353    case 0x10:
2354	submodel = "PG";
2355	break;
2356    case 0x11:
2357	submodel = "PJ";
2358	break;
2359    default:
2360	sprintf(smbuf, " model 0x%x", hwid & 0xff);
2361	submodel = smbuf;
2362	break;
2363    }
2364    nchn = (hwid >> 8) & 0xff;
2365    sprintf(buf, "DAC960%s, %d channel%s", submodel, nchn, nchn > 1 ? "s" : "");
2366    return(buf);
2367}
2368
2369/********************************************************************************
2370 ********************************************************************************
2371                                                                Utility Functions
2372 ********************************************************************************
2373 ********************************************************************************/
2374
2375/********************************************************************************
2376 * Find the disk whose unit number is (unit) on this controller
2377 */
2378static struct mlx_sysdrive *
2379mlx_findunit(struct mlx_softc *sc, int unit)
2380{
2381    int		i;
2382
2383    /* search system drives */
2384    for (i = 0; i < MLX_MAXDRIVES; i++) {
2385	/* is this one attached? */
2386	if (sc->mlx_sysdrive[i].ms_disk != 0) {
2387	    /* is this the one? */
2388	    if (unit == device_get_unit(sc->mlx_sysdrive[i].ms_disk))
2389		return(&sc->mlx_sysdrive[i]);
2390	}
2391    }
2392    return(NULL);
2393}
2394