amr.c revision 59249
155714Skris/*-
255714Skris * Copyright (c) 1999 Michael Smith
355714Skris * All rights reserved.
455714Skris *
555714Skris * Redistribution and use in source and binary forms, with or without
655714Skris * modification, are permitted provided that the following conditions
755714Skris * are met:
8280297Sjkim * 1. Redistributions of source code must retain the above copyright
955714Skris *    notice, this list of conditions and the following disclaimer.
1055714Skris * 2. Redistributions in binary form must reproduce the above copyright
1155714Skris *    notice, this list of conditions and the following disclaimer in the
1255714Skris *    documentation and/or other materials provided with the distribution.
1355714Skris *
1455714Skris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15280297Sjkim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1655714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1755714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1855714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1955714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2055714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2155714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22280297Sjkim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2355714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2455714Skris * SUCH DAMAGE.
2555714Skris *
2655714Skris *	$FreeBSD: head/sys/dev/amr/amr.c 59249 2000-04-15 05:54:02Z phk $
2755714Skris */
2855714Skris
2955714Skris/*
3055714Skris * Driver for the AMI MegaRaid family of controllers
3155714Skris */
3255714Skris
3355714Skris#include <sys/param.h>
3455714Skris#include <sys/systm.h>
3555714Skris#include <sys/malloc.h>
3655714Skris#include <sys/kernel.h>
37280297Sjkim
3855714Skris#include <sys/buf.h>
3955714Skris#include <sys/bus.h>
40280297Sjkim#include <sys/conf.h>
4155714Skris#include <sys/devicestat.h>
4255714Skris#include <sys/disk.h>
4355714Skris
4455714Skris#include <machine/resource.h>
4555714Skris#include <machine/bus.h>
4655714Skris#include <machine/clock.h>
4755714Skris#include <sys/rman.h>
4855714Skris
4955714Skris#include <dev/amr/amrio.h>
5055714Skris#include <dev/amr/amrreg.h>
5155714Skris#include <dev/amr/amrvar.h>
52280297Sjkim
5355714Skris#if 0
5455714Skris#define debug(fmt, args...)	printf("%s: " fmt "\n", __FUNCTION__ , ##args)
5555714Skris#else
5655714Skris#define debug(fmt, args...)
5755714Skris#endif
5855714Skris
5955714Skris#define AMR_CDEV_MAJOR	132
6055714Skris
6155714Skrisstatic struct cdevsw amr_cdevsw = {
6255714Skris		/* open */	amr_open,
6359191Skris		/* close */	amr_close,
64280297Sjkim		/* read */	noread,
6555714Skris		/* write */	nowrite,
66280297Sjkim		/* ioctl */	amr_ioctl,
6755714Skris		/* poll */	nopoll,
68280297Sjkim		/* mmap */	nommap,
6955714Skris		/* strategy */	nostrategy,
70280297Sjkim		/* name */ 	"amr",
7155714Skris		/* maj */	AMR_CDEV_MAJOR,
72280297Sjkim		/* dump */	nodump,
73280297Sjkim		/* psize */ 	nopsize,
74160814Ssimon		/* flags */	0,
75306195Sjkim		/* bmaj */	254	/* XXX magic no-bdev */
76306195Sjkim};
77306195Sjkim
78306195Sjkimstatic int	cdev_registered = 0;
79306195Sjkimdevclass_t	amr_devclass;
80306195Sjkim
81306195Sjkim/*
82306195Sjkim * Command wrappers
83306195Sjkim */
84306195Sjkimstatic int			amr_query_controller(struct amr_softc *sc);
85306195Sjkimstatic void			*amr_enquiry(struct amr_softc *sc, size_t bufsize,
86306195Sjkim					     u_int8_t cmd, u_int8_t cmdsub, u_int8_t cmdqual);
87306195Sjkimstatic int			amr_flush(struct amr_softc *sc);
88306195Sjkimstatic void			amr_startio(struct amr_softc *sc);
89306195Sjkimstatic void			amr_completeio(struct amr_command *ac);
90306195Sjkim
91306195Sjkim/*
92280297Sjkim * Command processing.
93280297Sjkim */
94280297Sjkimstatic int			amr_wait_command(struct amr_command *ac);
9555714Skrisstatic int			amr_poll_command(struct amr_command *ac);
96306195Sjkimstatic int			amr_getslot(struct amr_command *ac);
97306195Sjkimstatic void			amr_mapcmd(struct amr_command *ac);
98306195Sjkimstatic void			amr_unmapcmd(struct amr_command *ac);
99306195Sjkimstatic int			amr_start(struct amr_command *ac);
100306195Sjkimstatic int			amr_done(struct amr_softc *sc);
101280297Sjkimstatic void			amr_complete(struct amr_softc *sc);
102280297Sjkim
10355714Skris/*
104280297Sjkim * Command buffer allocation.
105280297Sjkim */
10655714Skrisstatic struct amr_command	*amr_alloccmd(struct amr_softc *sc);
107280297Sjkimstatic void			amr_releasecmd(struct amr_command *ac);
108280297Sjkimstatic void			amr_freecmd(struct amr_command *ac);
109280297Sjkim
11055714Skris/*
11155714Skris * Status monitoring
112280297Sjkim */
113280297Sjkimstatic void			amr_periodic(void *data);
114280297Sjkim
11555714Skris/*
116280297Sjkim * Interface-specific shims
117280297Sjkim */
118160814Ssimonstatic void			amr_quartz_submit_command(struct amr_softc *sc);
119280297Sjkimstatic int			amr_quartz_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave);
120280297Sjkimstatic void			amr_quartz_attach_mailbox(struct amr_softc *sc);
121280297Sjkim
122280297Sjkimstatic void			amr_std_submit_command(struct amr_softc *sc);
123280297Sjkimstatic int			amr_std_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave);
124160814Ssimonstatic void			amr_std_attach_mailbox(struct amr_softc *sc);
125280297Sjkim
126280297Sjkim/*
127280297Sjkim * Debugging
128280297Sjkim */
129280297Sjkimstatic void			amr_printcommand(struct amr_command *ac);
130160814Ssimon
131280297Sjkim/********************************************************************************
132280297Sjkim ********************************************************************************
13355714Skris                                                                Public Interfaces
134280297Sjkim ********************************************************************************
135280297Sjkim ********************************************************************************/
136280297Sjkim
137280297Sjkim/********************************************************************************
138280297Sjkim * Free all of the resources associated with (sc)
139280297Sjkim *
140280297Sjkim * Should not be called if the controller is active.
141280297Sjkim */
142280297Sjkimvoid
143280297Sjkimamr_free(struct amr_softc *sc)
144280297Sjkim{
145280297Sjkim    struct amr_command	*ac;
14655714Skris    u_int8_t		*p;
147280297Sjkim
148280297Sjkim    debug("called");
149280297Sjkim
15055714Skris    /* cancel status timeout */
151280297Sjkim    untimeout(amr_periodic, sc, sc->amr_timeout);
152280297Sjkim
153160814Ssimon    /* throw away any command buffers */
154280297Sjkim    while ((ac = TAILQ_FIRST(&sc->amr_freecmds)) != NULL) {
155280297Sjkim	TAILQ_REMOVE(&sc->amr_freecmds, ac, ac_link);
156280297Sjkim	amr_freecmd(ac);
157280297Sjkim    }
158280297Sjkim
159280297Sjkim    /* destroy data-transfer DMA tag */
160280297Sjkim    if (sc->amr_buffer_dmat)
161280297Sjkim	bus_dma_tag_destroy(sc->amr_buffer_dmat);
162280297Sjkim
163280297Sjkim    /* free and destroy DMA memory and tag for s/g lists */
164280297Sjkim    if (sc->amr_sgtable)
165280297Sjkim	bus_dmamem_free(sc->amr_sg_dmat, sc->amr_sgtable, sc->amr_sg_dmamap);
166280297Sjkim    if (sc->amr_sg_dmat)
167280297Sjkim	bus_dma_tag_destroy(sc->amr_sg_dmat);
168280297Sjkim
169280297Sjkim    /* free and destroy DMA memory and tag for mailbox */
170280297Sjkim    if (sc->amr_mailbox) {
171280297Sjkim	p = (u_int8_t *)sc->amr_mailbox;
172280297Sjkim	bus_dmamem_free(sc->amr_sg_dmat, p - 16, sc->amr_sg_dmamap);
173280297Sjkim    }
174280297Sjkim    if (sc->amr_sg_dmat)
175280297Sjkim	bus_dma_tag_destroy(sc->amr_sg_dmat);
176280297Sjkim
177280297Sjkim    /* disconnect the interrupt handler */
178280297Sjkim    if (sc->amr_intr)
179280297Sjkim	bus_teardown_intr(sc->amr_dev, sc->amr_irq, sc->amr_intr);
180280297Sjkim    if (sc->amr_irq != NULL)
18155714Skris	bus_release_resource(sc->amr_dev, SYS_RES_IRQ, 0, sc->amr_irq);
18255714Skris
183280297Sjkim    /* destroy the parent DMA tag */
184280297Sjkim    if (sc->amr_parent_dmat)
18555714Skris	bus_dma_tag_destroy(sc->amr_parent_dmat);
186280297Sjkim
187280297Sjkim    /* release the register window mapping */
188160814Ssimon    if (sc->amr_reg != NULL)
189280297Sjkim	bus_release_resource(sc->amr_dev,
190280297Sjkim			     (sc->amr_type == AMR_TYPE_QUARTZ) ? SYS_RES_MEMORY : SYS_RES_IOPORT,
191280297Sjkim			     AMR_CFG_BASE, sc->amr_reg);
192280297Sjkim}
193280297Sjkim
194280297Sjkim/********************************************************************************
195280297Sjkim * Allocate and map the scatter/gather table in bus space.
196280297Sjkim */
197280297Sjkimstatic void
198280297Sjkimamr_dma_map_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error)
199280297Sjkim{
200280297Sjkim    struct amr_softc	*sc = (struct amr_softc *)arg;
201280297Sjkim
202280297Sjkim    debug("called");
203280297Sjkim
204280297Sjkim    /* save base of s/g table's address in bus space */
205280297Sjkim    sc->amr_sgbusaddr = segs->ds_addr;
20655714Skris}
207280297Sjkim
208280297Sjkimstatic int
209280297Sjkimamr_sglist_map(struct amr_softc *sc)
210280297Sjkim{
211280297Sjkim    size_t	segsize;
212280297Sjkim    int		error;
213280297Sjkim
214280297Sjkim    debug("called");
215280297Sjkim
216280297Sjkim    /* destroy any existing mappings */
217280297Sjkim    if (sc->amr_sgtable)
218280297Sjkim	bus_dmamem_free(sc->amr_sg_dmat, sc->amr_sgtable, sc->amr_sg_dmamap);
219280297Sjkim    if (sc->amr_sg_dmat)
220280297Sjkim	bus_dma_tag_destroy(sc->amr_sg_dmat);
221280297Sjkim
222280297Sjkim    /*
223280297Sjkim     * Create a single tag describing a region large enough to hold all of
224280297Sjkim     * the s/g lists we will need.
225280297Sjkim     */
226280297Sjkim    segsize = sizeof(struct amr_sgentry) * AMR_NSEG * sc->amr_maxio;
227280297Sjkim    error = bus_dma_tag_create(sc->amr_parent_dmat, 	/* parent */
22855714Skris			       1, 0, 			/* alignment, boundary */
22955714Skris			       BUS_SPACE_MAXADDR,	/* lowaddr */
230280297Sjkim			       BUS_SPACE_MAXADDR, 	/* highaddr */
231280297Sjkim			       NULL, NULL, 		/* filter, filterarg */
23255714Skris			       segsize, 1,		/* maxsize, nsegments */
233280297Sjkim			       BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
234280297Sjkim			       0,			/* flags */
235280297Sjkim			       &sc->amr_sg_dmat);
236280297Sjkim    if (error != 0) {
237280297Sjkim	device_printf(sc->amr_dev, "can't allocate scatter/gather DMA tag\n");
238280297Sjkim	return(ENOMEM);
239280297Sjkim    }
240280297Sjkim
241280297Sjkim    /*
242280297Sjkim     * Allocate enough s/g maps for all commands and permanently map them into
243280297Sjkim     * controller-visible space.
244280297Sjkim     *
245280297Sjkim     * XXX this assumes we can get enough space for all the s/g maps in one
246280297Sjkim     * contiguous slab.  We may need to switch to a more complex arrangement where
247280297Sjkim     * we allocate in smaller chunks and keep a lookup table from slot to bus address.
248280297Sjkim     */
249280297Sjkim    error = bus_dmamem_alloc(sc->amr_sg_dmat, (void **)&sc->amr_sgtable, BUS_DMA_NOWAIT, &sc->amr_sg_dmamap);
250    if (error) {
251	device_printf(sc->amr_dev, "can't allocate s/g table\n");
252	return(ENOMEM);
253    }
254    bus_dmamap_load(sc->amr_sg_dmat, sc->amr_sg_dmamap, sc->amr_sgtable, segsize, amr_dma_map_sg, sc, 0);
255    return(0);
256}
257
258/********************************************************************************
259 * Allocate and set up mailbox areas for the controller (sc)
260 *
261 * The basic mailbox structure should be 16-byte aligned.  This means that the
262 * mailbox64 structure has 4 bytes hanging off the bottom.
263 */
264static void
265amr_map_mailbox(void *arg, bus_dma_segment_t *segs, int nseg, int error)
266{
267    struct amr_softc	*sc = (struct amr_softc *)arg;
268
269    debug("called");
270
271    /* save phsyical base of the basic mailbox structure */
272    sc->amr_mailboxphys = segs->ds_addr + 16;
273}
274
275static int
276amr_setup_mbox(struct amr_softc *sc)
277{
278    int		error;
279    u_int8_t	*p;
280
281    debug("called");
282
283    /*
284     * Create a single tag describing a region large enough to hold the entire
285     * mailbox.
286     */
287    error = bus_dma_tag_create(sc->amr_parent_dmat,	/* parent */
288			       16, 0,			/* alignment, boundary */
289			       BUS_SPACE_MAXADDR,	/* lowaddr */
290			       BUS_SPACE_MAXADDR,	/* highaddr */
291			       NULL, NULL,		/* filter, filterarg */
292			       sizeof(struct amr_mailbox) + 16, 1, /* maxsize, nsegments */
293			       BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
294			       0,			/* flags */
295			       &sc->amr_mailbox_dmat);
296    if (error != 0) {
297	device_printf(sc->amr_dev, "can't allocate mailbox tag\n");
298	return(ENOMEM);
299    }
300
301    /*
302     * Allocate the mailbox structure and permanently map it into
303     * controller-visible space.
304     */
305    error = bus_dmamem_alloc(sc->amr_mailbox_dmat, (void **)&p, BUS_DMA_NOWAIT,
306			     &sc->amr_mailbox_dmamap);
307    if (error) {
308	device_printf(sc->amr_dev, "can't allocate mailbox memory\n");
309	return(ENOMEM);
310    }
311    bus_dmamap_load(sc->amr_mailbox_dmat, sc->amr_mailbox_dmamap, p,
312		    sizeof(struct amr_mailbox64), amr_map_mailbox, sc, 0);
313    /*
314     * Conventional mailbox is inside the mailbox64 region.
315     */
316    bzero(p, sizeof(struct amr_mailbox64));
317    sc->amr_mailbox64 = (struct amr_mailbox64 *)(p + 12);
318    sc->amr_mailbox = (struct amr_mailbox *)(p + 16);
319
320    if (sc->amr_type == AMR_TYPE_STD) {
321	/* XXX we have to tell the controller where we put it */
322    }
323    return(0);
324}
325
326
327/********************************************************************************
328 * Initialise the controller and softc.
329 */
330int
331amr_attach(struct amr_softc *sc)
332{
333    int			rid, error;
334
335    /*
336     * Initialise per-controller queues.
337     */
338    TAILQ_INIT(&sc->amr_work);
339    TAILQ_INIT(&sc->amr_freecmds);
340    bioq_init(&sc->amr_bioq);
341
342    /*
343     * Configure for this controller type.
344     */
345    if (sc->amr_type == AMR_TYPE_QUARTZ) {
346	sc->amr_submit_command = amr_quartz_submit_command;
347	sc->amr_get_work       = amr_quartz_get_work;
348	sc->amr_attach_mailbox = amr_quartz_attach_mailbox;
349    } else {
350	sc->amr_submit_command = amr_std_submit_command;
351	sc->amr_get_work       = amr_std_get_work;
352	sc->amr_attach_mailbox = amr_std_attach_mailbox;
353    }
354
355    /*
356     * Allocate and connect our interrupt.
357     */
358    rid = 0;
359    sc->amr_irq = bus_alloc_resource(sc->amr_dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);
360    if (sc->amr_irq == NULL) {
361        device_printf(sc->amr_dev, "couldn't allocate interrupt\n");
362        amr_free(sc);
363        return(ENXIO);
364    }
365    error = bus_setup_intr(sc->amr_dev, sc->amr_irq, INTR_TYPE_BIO,  amr_intr, sc, &sc->amr_intr);
366    if (error) {
367        device_printf(sc->amr_dev, "couldn't set up interrupt\n");
368        amr_free(sc);
369        return(ENXIO);
370    }
371
372    /*
373     * Create DMA tag for mapping buffers into controller-addressable space.
374     */
375    error = bus_dma_tag_create(sc->amr_parent_dmat,     /* parent */
376                               1, 0,                    /* alignment, boundary */
377                               BUS_SPACE_MAXADDR,       /* lowaddr */
378                               BUS_SPACE_MAXADDR,       /* highaddr */
379                               NULL, NULL,              /* filter, filterarg */
380                               MAXBSIZE, AMR_NSEG,      /* maxsize, nsegments */
381                               BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
382                               0,                       /* flags */
383                               &sc->amr_buffer_dmat);
384    if (error != 0) {
385        device_printf(sc->amr_dev, "can't allocate buffer DMA tag\n");
386        return(ENOMEM);
387    }
388
389    /*
390     * Allocate and set up mailbox in a bus-visible fashion, attach to controller.
391     */
392    if ((error = amr_setup_mbox(sc)) != 0)
393	return(error);
394    sc->amr_attach_mailbox(sc);
395
396    /*
397     * Build a temporary set of scatter/gather buffers.
398     */
399    sc->amr_maxio = 2;
400    if (amr_sglist_map(sc))
401	return(ENXIO);
402
403    /*
404     * Quiz controller for features and limits.
405     */
406    if (amr_query_controller(sc))
407	return(ENXIO);
408
409    /*
410     * Rebuild the scatter/gather buffers now we know how many we need.
411     */
412    if (amr_sglist_map(sc))
413	return(ENXIO);
414
415    /*
416     * Start the timeout routine.
417     */
418    sc->amr_timeout = timeout(amr_periodic, sc, hz);
419
420    return(0);
421}
422
423/********************************************************************************
424 * Locate disk resources and attach children to them.
425 */
426void
427amr_startup(struct amr_softc *sc)
428{
429    struct amr_logdrive	*dr;
430    int			i, error;
431
432    debug("called");
433
434    /* get up-to-date drive information */
435    if (amr_query_controller(sc)) {
436	device_printf(sc->amr_dev, "couldn't scan controller for drives\n");
437	return;
438    }
439
440    /* iterate over available drives */
441    for (i = 0, dr = &sc->amr_drive[0]; (i < AMR_MAXLD) && (dr->al_size != 0xffffffff); i++, dr++) {
442	/* are we already attached to this drive? */
443	if (dr->al_disk == 0) {
444	    /* generate geometry information */
445	    if (dr->al_size > 0x200000) {	/* extended translation? */
446		dr->al_heads = 255;
447		dr->al_sectors = 63;
448	    } else {
449		dr->al_heads = 64;
450		dr->al_sectors = 32;
451	    }
452	    dr->al_cylinders = dr->al_size / (dr->al_heads * dr->al_sectors);
453
454	    dr->al_disk = device_add_child(sc->amr_dev, NULL, -1);
455	    if (dr->al_disk == 0)
456		device_printf(sc->amr_dev, "device_add_child failed\n");
457	    device_set_ivars(dr->al_disk, dr);
458	}
459    }
460
461    if ((error = bus_generic_attach(sc->amr_dev)) != 0)
462	device_printf(sc->amr_dev, "bus_generic_attach returned %d\n", error);
463
464    /* mark controller back up */
465    sc->amr_state &= ~AMR_STATE_SHUTDOWN;
466
467    /* interrupts will be enabled before we do anything more */
468    sc->amr_state |= AMR_STATE_INTEN;
469}
470
471/********************************************************************************
472 * Disconnect from the controller completely, in preparation for unload.
473 */
474int
475amr_detach(device_t dev)
476{
477    struct amr_softc	*sc = device_get_softc(dev);
478    int			error;
479
480    debug("called");
481
482    if (sc->amr_state & AMR_STATE_OPEN)
483	return(EBUSY);
484
485    if ((error = amr_shutdown(dev)))
486	return(error);
487
488    amr_free(sc);
489
490    /*
491     * Deregister the control device on last detach.
492     */
493    if (--cdev_registered == 0)
494	cdevsw_remove(&amr_cdevsw);
495
496    return(0);
497}
498
499/********************************************************************************
500 * Bring the controller down to a dormant state and detach all child devices.
501 *
502 * This function is called before detach, system shutdown, or before performing
503 * an operation which may add or delete system disks.  (Call amr_startup to
504 * resume normal operation.)
505 *
506 * Note that we can assume that the bioq on the controller is empty, as we won't
507 * allow shutdown if any device is open.
508 */
509int
510amr_shutdown(device_t dev)
511{
512    struct amr_softc	*sc = device_get_softc(dev);
513    struct amrd_softc	*ad;
514    int			i, s, error;
515
516    debug("called");
517
518    s = splbio();
519    error = 0;
520
521    /* assume we're going to shut down */
522    sc->amr_state |= AMR_STATE_SHUTDOWN;
523    for (i = 0; i < AMR_MAXLD; i++) {
524	if (sc->amr_drive[i].al_disk != 0) {
525	    ad = device_get_softc(sc->amr_drive[i].al_disk);
526	    if (ad->amrd_flags & AMRD_OPEN) {		/* drive is mounted, abort shutdown */
527		sc->amr_state &= ~AMR_STATE_SHUTDOWN;
528		device_printf(sc->amr_drive[i].al_disk, "still open, can't shutdown\n");
529		error = EBUSY;
530		goto out;
531	    }
532	}
533    }
534
535    /* flush controller */
536    device_printf(sc->amr_dev, "flushing cache...");
537    if (amr_flush(sc)) {
538	printf("failed\n");
539    } else {
540	printf("done\n");
541    }
542
543    /* delete all our child devices */
544    for (i = 0; i < AMR_MAXLD; i++) {
545	if (sc->amr_drive[i].al_disk != 0) {
546	    if ((error = device_delete_child(sc->amr_dev, sc->amr_drive[i].al_disk)) != 0)
547		goto out;
548	    sc->amr_drive[i].al_disk = 0;
549	}
550    }
551
552 out:
553    splx(s);
554    return(error);
555}
556
557/********************************************************************************
558 * Bring the controller to a quiescent state, ready for system suspend.
559 */
560int
561amr_suspend(device_t dev)
562{
563    struct amr_softc	*sc = device_get_softc(dev);
564
565    debug("called");
566
567    sc->amr_state |= AMR_STATE_SUSPEND;
568
569    /* flush controller */
570    device_printf(sc->amr_dev, "flushing cache...");
571    printf("%s\n", amr_flush(sc) ? "failed" : "done");
572
573    return(0);
574}
575
576/********************************************************************************
577 * Bring the controller back to a state ready for operation.
578 */
579int
580amr_resume(device_t dev)
581{
582    struct amr_softc	*sc = device_get_softc(dev);
583
584    debug("called");
585
586    sc->amr_state &= ~AMR_STATE_SUSPEND;
587
588    return(0);
589}
590
591/*******************************************************************************
592 * Take an interrupt, or be poked by other code to look for interrupt-worthy
593 * status.
594 */
595void
596amr_intr(void *arg)
597{
598    struct amr_softc	*sc = (struct amr_softc *)arg;
599
600    debug("called");
601
602    /* collect finished commands, queue anything waiting */
603    amr_done(sc);
604};
605
606/*******************************************************************************
607 * Receive a buf structure from a child device and queue it on a particular
608 * disk resource, then poke the disk resource to start as much work as it can.
609 */
610int
611amr_submit_buf(struct amr_softc *sc, struct bio *bp)
612{
613    int		s;
614
615    debug("called");
616
617    s = splbio();
618    bioq_insert_tail(&sc->amr_bioq, bp);
619    splx(s);
620    sc->amr_waitbufs++;
621    amr_startio(sc);
622    return(0);
623}
624
625/********************************************************************************
626 * Accept an open operation on the control device.
627 */
628int
629amr_open(dev_t dev, int flags, int fmt, struct proc *p)
630{
631    int			unit = minor(dev);
632    struct amr_softc	*sc = devclass_get_softc(amr_devclass, unit);
633
634    sc->amr_state |= AMR_STATE_OPEN;
635    return(0);
636}
637
638/********************************************************************************
639 * Accept the last close on the control device.
640 */
641int
642amr_close(dev_t dev, int flags, int fmt, struct proc *p)
643{
644    int			unit = minor(dev);
645    struct amr_softc	*sc = devclass_get_softc(amr_devclass, unit);
646
647    sc->amr_state &= ~AMR_STATE_OPEN;
648    return (0);
649}
650
651/********************************************************************************
652 * Handle controller-specific control operations.
653 */
654int
655amr_ioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
656{
657
658    switch(cmd) {
659    default:
660	return(ENOTTY);
661    }
662}
663
664/********************************************************************************
665 * Handle operations requested by a drive connected to this controller.
666 */
667int
668amr_submit_ioctl(struct amr_softc *sc, struct amr_logdrive *drive, u_long cmd,
669		 caddr_t addr, int32_t flag, struct proc *p)
670{
671    return(ENOTTY);
672}
673
674/********************************************************************************
675 ********************************************************************************
676                                                                Status Monitoring
677 ********************************************************************************
678 ********************************************************************************/
679
680/********************************************************************************
681 * Perform a periodic check of the controller status
682 */
683static void
684amr_periodic(void *data)
685{
686    struct amr_softc	*sc = (struct amr_softc *)data;
687    int			s, i;
688
689    debug("called");
690
691
692    /*
693     * Check for commands that are massively late.  This will need to be
694     * revisited if/when we deal with eg. device format commands.
695     * The 30 second value is entirely arbitrary.
696     */
697    s = splbio();
698    if (sc->amr_busycmdcount > 0) {
699	for (i = 0; i < AMR_MAXCMD; i++) {
700	    /*
701	     * If the command has been busy for more than 30 seconds, declare it
702	     * wedged and retire it with an error.
703	     */
704	    if ((sc->amr_busycmd[i] != NULL) &&
705		(sc->amr_busycmd[i]->ac_status == AMR_STATUS_BUSY) &&
706		((sc->amr_busycmd[i]->ac_stamp + 30) < time_second)) {
707		device_printf(sc->amr_dev, "command %d wedged after 30 seconds\n", i);
708		sc->amr_busycmd[i]->ac_status = AMR_STATUS_WEDGED;
709		amr_completeio(sc->amr_busycmd[i]);
710	    }
711	}
712    }
713    splx(s);
714
715    /* reschedule */
716    sc->amr_timeout = timeout(amr_periodic, sc, hz);
717}
718
719
720/********************************************************************************
721 ********************************************************************************
722                                                                 Command Wrappers
723 ********************************************************************************
724 ********************************************************************************/
725
726/********************************************************************************
727 * Interrogate the controller for the operational parameters we require.
728 */
729static int
730amr_query_controller(struct amr_softc *sc)
731{
732    void	*buf;
733    int		i;
734
735    /* try to issue an ENQUIRY3 command */
736    if ((buf = amr_enquiry(sc, 2048, AMR_CMD_CONFIG, AMR_CONFIG_ENQ3,
737			   AMR_CONFIG_ENQ3_SOLICITED_FULL)) == NULL) {
738
739	struct amr_enquiry	*ae;
740
741	/* failed, try the old ENQUIRY command */
742	if ((ae = (struct amr_enquiry *)amr_enquiry(sc, 2048, AMR_CMD_ENQUIRY, 0, 0)) == NULL) {
743	    device_printf(sc->amr_dev, "could not obtain configuration data from controller\n");
744	    return(1);
745	}
746	/* first-time enquiry? */
747	if (sc->amr_maxdrives == 0) {
748	    device_printf(sc->amr_dev, "firmware %.4s bios %.4s  %dMB memory\n",
749			  ae->ae_adapter.aa_firmware, ae->ae_adapter.aa_bios,
750			  ae->ae_adapter.aa_memorysize);
751	}
752	sc->amr_maxdrives = 8;
753
754	/*
755	 * Cap the maximum number of outstanding I/Os.  AMI's Linux driver doesn't trust
756	 * the controller's reported value, and lockups have been seen when we do.
757	 */
758	sc->amr_maxio = imin(ae->ae_adapter.aa_maxio, AMR_LIMITCMD);
759
760	for (i = 0; i < ae->ae_ldrv.al_numdrives; i++) {
761	    sc->amr_drive[i].al_size = ae->ae_ldrv.al_size[i];
762	    sc->amr_drive[i].al_state = ae->ae_ldrv.al_state[i];
763	    sc->amr_drive[i].al_properties = ae->ae_ldrv.al_properties[i];
764	    debug("  drive %d: %d state %x properties %x\n", i, sc->amr_drive[i].al_size,
765		  sc->amr_drive[i].al_state, sc->amr_drive[i].al_properties);
766	}
767	for (; i < AMR_MAXLD; i++)
768	    sc->amr_drive[i].al_size = 0xffffffff;
769	free(ae, M_DEVBUF);
770    } else {
771	/*
772	 * The "40LD" (40 logical drive support) firmware is mentioned in the Linux
773	 * driver, but no adapters from AMI appear to support it.
774	 */
775	free(buf, M_DEVBUF);
776	sc->amr_maxdrives = 40;
777
778	/* get static product info */
779	if ((buf = amr_enquiry(sc, 2048, AMR_CMD_CONFIG, AMR_CONFIG_PRODINFO, 0)) == NULL) {
780	    device_printf(sc->amr_dev, "controller supports 40ld but CONFIG_PRODINFO failed\n");
781	    return(1);
782	}
783	free(buf, M_DEVBUF);
784	device_printf(sc->amr_dev, "40LD firmware unsupported; send controller to msmith@freebsd.org\n");
785	return(1);
786    }
787    return(0);
788}
789
790/********************************************************************************
791 * Run a generic enquiry-style command.
792 */
793static void *
794amr_enquiry(struct amr_softc *sc, size_t bufsize, u_int8_t cmd, u_int8_t cmdsub, u_int8_t cmdqual)
795{
796    struct amr_command	*ac;
797    void		*result;
798    u_int8_t		*mbox;
799    int			error;
800
801    debug("called");
802
803    error = 1;
804    result = NULL;
805
806    /* get ourselves a command buffer */
807    if ((ac = amr_alloccmd(sc)) == NULL)
808	goto out;
809    /* allocate the response structure */
810    if ((result = malloc(bufsize, M_DEVBUF, M_NOWAIT)) == NULL)
811	goto out;
812    /* get a command slot */
813    ac->ac_flags |= AMR_CMD_PRIORITY | AMR_CMD_DATAOUT;
814    if (amr_getslot(ac))
815	goto out;
816
817    /* map the command so the controller can see it */
818    ac->ac_data = result;
819    ac->ac_length = bufsize;
820    amr_mapcmd(ac);
821
822    /* build the command proper */
823    mbox = (u_int8_t *)&ac->ac_mailbox;		/* XXX want a real structure for this? */
824    mbox[0] = cmd;
825    mbox[2] = cmdsub;
826    mbox[3] = cmdqual;
827    ac->ac_mailbox.mb_physaddr = ac->ac_dataphys;
828
829    /* can't assume that interrupts are going to work here, so play it safe */
830    if (amr_poll_command(ac))
831	goto out;
832    error = ac->ac_status;
833
834 out:
835    if (ac != NULL)
836	amr_releasecmd(ac);
837    if ((error != 0) && (result != NULL)) {
838	free(result, M_DEVBUF);
839	result = NULL;
840    }
841    return(result);
842}
843
844/********************************************************************************
845 * Flush the controller's internal cache, return status.
846 */
847static int
848amr_flush(struct amr_softc *sc)
849{
850    struct amr_command	*ac;
851    int			error;
852
853    /* get ourselves a command buffer */
854    error = 1;
855    if ((ac = amr_alloccmd(sc)) == NULL)
856	goto out;
857    /* get a command slot */
858    ac->ac_flags |= AMR_CMD_PRIORITY | AMR_CMD_DATAOUT;
859    if (amr_getslot(ac))
860	goto out;
861
862    /* build the command proper */
863    ac->ac_mailbox.mb_command = AMR_CMD_FLUSH;
864
865    /* we have to poll, as the system may be going down or otherwise damaged */
866    if (amr_poll_command(ac))
867	goto out;
868    error = ac->ac_status;
869
870 out:
871    if (ac != NULL)
872	amr_releasecmd(ac);
873    return(error);
874}
875
876/********************************************************************************
877 * Pull as much work off the softc's work queue as possible and give it to the
878 * controller.  Leave a couple of slots free for emergencies.
879 *
880 * We avoid running at splbio() whenever possible.
881 */
882static void
883amr_startio(struct amr_softc *sc)
884{
885    struct amr_command	*ac;
886    struct amrd_softc	*amrd;
887    struct bio		*bp;
888    int			blkcount;
889    int			driveno;
890    int			cmd;
891    int			s;
892
893    /* avoid reentrancy */
894    if (amr_lock_tas(sc, AMR_LOCK_STARTING))
895	return;
896
897    /* spin until something prevents us from doing any work */
898    s = splbio();
899    for (;;) {
900
901	/* see if there's work to be done */
902	if ((bp = bioq_first(&sc->amr_bioq)) == NULL)
903	    break;
904	/* get a command */
905	if ((ac = amr_alloccmd(sc)) == NULL)
906	    break;
907	/* get a slot for the command */
908	if (amr_getslot(ac) != 0) {
909	    amr_releasecmd(ac);
910	    break;
911	}
912	/* get the buf containing our work */
913	bioq_remove(&sc->amr_bioq, bp);
914	sc->amr_waitbufs--;
915	splx(s);
916
917	/* connect the buf to the command */
918	ac->ac_complete = amr_completeio;
919	ac->ac_private = bp;
920	ac->ac_data = bp->bio_data;
921	ac->ac_length = bp->bio_bcount;
922	if (bp->bio_cmd == BIO_READ) {
923	    ac->ac_flags |= AMR_CMD_DATAIN;
924	    cmd = AMR_CMD_LREAD;
925	} else {
926	    ac->ac_flags |= AMR_CMD_DATAOUT;
927	    cmd = AMR_CMD_LWRITE;
928	}
929
930	/* map the command so the controller can work with it */
931	amr_mapcmd(ac);
932
933	/* build a suitable I/O command (assumes 512-byte rounded transfers) */
934	amrd = (struct amrd_softc *)bp->bio_dev->si_drv1;
935	driveno = amrd->amrd_drive - sc->amr_drive;
936	blkcount = (bp->bio_bcount + AMR_BLKSIZE - 1) / AMR_BLKSIZE;
937
938	if ((bp->bio_pblkno + blkcount) > sc->amr_drive[driveno].al_size)
939	    device_printf(sc->amr_dev, "I/O beyond end of unit (%u,%d > %u)\n",
940			  bp->bio_pblkno, blkcount, sc->amr_drive[driveno].al_size);
941
942	/*
943	 * Build the I/O command.
944	 */
945	ac->ac_mailbox.mb_command = cmd;
946	ac->ac_mailbox.mb_blkcount = blkcount;
947	ac->ac_mailbox.mb_lba = bp->bio_pblkno;
948	ac->ac_mailbox.mb_physaddr = ac->ac_sgphys;
949	ac->ac_mailbox.mb_drive = driveno;
950	ac->ac_mailbox.mb_nsgelem = ac->ac_nsgent;
951
952	/* try to give command to controller */
953	if (amr_start(ac) != 0) {
954	    /* fail the command */
955	    ac->ac_status = AMR_STATUS_WEDGED;
956	    amr_completeio(ac);
957	}
958	s = splbio();
959    }
960    splx(s);
961    amr_lock_clr(sc, AMR_LOCK_STARTING);
962}
963
964/********************************************************************************
965 * Handle completion of an I/O command.
966 */
967static void
968amr_completeio(struct amr_command *ac)
969{
970    struct amr_softc	*sc = ac->ac_sc;
971    struct bio		*bp = (struct bio *)ac->ac_private;
972    int			notify, release;
973
974    notify = 1;
975    release = 1;
976
977    if (ac->ac_status != AMR_STATUS_SUCCESS) {	/* could be more verbose here? */
978	bp->bio_error = EIO;
979	bp->bio_flags |= BIO_ERROR;
980
981	switch(ac->ac_status) {
982	    /* XXX need more information on I/O error reasons */
983	case AMR_STATUS_LATE:
984	    notify = 0;				/* we've already notified the parent */
985	    break;
986
987	case AMR_STATUS_WEDGED:
988	    release = 0;			/* the command is still outstanding, we can't release */
989	    break;
990
991	default:
992	    device_printf(sc->amr_dev, "I/O error - %x\n", ac->ac_status);
993	    amr_printcommand(ac);
994	    break;
995	}
996    }
997    if (release)
998	amr_releasecmd(ac);
999    if (notify)
1000	amrd_intr(bp);
1001}
1002
1003/********************************************************************************
1004 ********************************************************************************
1005                                                               Command Processing
1006 ********************************************************************************
1007 ********************************************************************************/
1008
1009/********************************************************************************
1010 * Take a command, submit it to the controller and sleep until it completes
1011 * or fails.  Interrupts must be enabled, returns nonzero on error.
1012 */
1013static int
1014amr_wait_command(struct amr_command *ac)
1015{
1016    struct amr_softc	*sc = ac->ac_sc;
1017    int			error, count;
1018
1019    debug("called");
1020
1021    ac->ac_complete = NULL;
1022    ac->ac_private = ac;
1023    if ((error = amr_start(ac)) != 0)
1024	return(error);
1025
1026    count = 0;
1027    /* XXX better timeout? */
1028    while ((ac->ac_status == AMR_STATUS_BUSY) && (count < 30)) {
1029	tsleep(ac->ac_private, PRIBIO | PCATCH, "amrwcmd", hz);
1030    }
1031
1032    if (ac->ac_status != 0) {
1033	device_printf(sc->amr_dev, "I/O error 0x%x\n", ac->ac_status);
1034	return(EIO);
1035    }
1036    return(0);
1037}
1038
1039/********************************************************************************
1040 * Take a command, submit it to the controller and busy-wait for it to return.
1041 * Returns nonzero on error.  Can be safely called with interrupts enabled.
1042 */
1043static int
1044amr_poll_command(struct amr_command *ac)
1045{
1046    struct amr_softc	*sc = ac->ac_sc;
1047    int			error, count, s;
1048
1049    debug("called");
1050
1051    ac->ac_complete = NULL;
1052    ac->ac_private = NULL;
1053    if ((error = amr_start(ac)) != 0)
1054	return(error);
1055
1056    count = 0;
1057    do {
1058	/*
1059	 * Poll for completion, although the interrupt handler may beat us to it.
1060	 * Note that the timeout here is somewhat arbitrary.
1061	 */
1062	amr_done(sc);
1063    } while ((ac->ac_status == AMR_STATUS_BUSY) && (count++ < 100000));
1064    s = splbio();
1065    if (ac->ac_status != AMR_STATUS_BUSY) {
1066	TAILQ_REMOVE(&sc->amr_work, ac, ac_link);
1067	sc->amr_workcount--;
1068	error = 0;
1069    } else {
1070	/* take the command out of the busy list, mark slot as bogus */
1071	sc->amr_busycmd[ac->ac_slot] = (struct amr_command *)sc;
1072	error = EIO;
1073	device_printf(sc->amr_dev, "I/O error 0x%x\n", ac->ac_status);
1074    }
1075    splx(s);
1076    return(error);
1077}
1078
1079/********************************************************************************
1080 * Get a free command slot.
1081 */
1082static int
1083amr_getslot(struct amr_command *ac)
1084{
1085    struct amr_softc	*sc = ac->ac_sc;
1086    int			s, slot, limit;
1087
1088    debug("called");
1089
1090    /* enforce slot usage limit */
1091    limit = (ac->ac_flags & AMR_CMD_PRIORITY) ? sc->amr_maxio : sc->amr_maxio - 4;
1092    if (sc->amr_busycmdcount > limit)
1093	return(EBUSY);
1094
1095    /*
1096     * Allocate a slot
1097     */
1098    s = splbio();
1099    for (slot = 0; slot < sc->amr_maxio; slot++) {
1100	if (sc->amr_busycmd[slot] == NULL)
1101	    break;
1102    }
1103    if (slot < sc->amr_maxio) {
1104	sc->amr_busycmdcount++;
1105	sc->amr_busycmd[slot] = ac;
1106    }
1107    splx(s);
1108
1109    /* out of slots? */
1110    if (slot >= sc->amr_maxio)
1111	return(EBUSY);
1112
1113    ac->ac_slot = slot;
1114    return(0);
1115}
1116
1117/********************************************************************************
1118 * Map/unmap (ac)'s data in the controller's addressable space.
1119 */
1120static void
1121amr_setup_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
1122{
1123    struct amr_command	*ac = (struct amr_command *)arg;
1124    struct amr_softc	*sc = ac->ac_sc;
1125    struct amr_sgentry	*sg;
1126    int			i;
1127
1128    debug("called");
1129
1130    /* get base address of s/g table */
1131    sg = sc->amr_sgtable + (ac->ac_slot * AMR_NSEG);
1132
1133    /* save s/g table information in command */
1134    ac->ac_nsgent = nsegments;
1135    ac->ac_sgphys = sc->amr_sgbusaddr + (ac->ac_slot * AMR_NSEG * sizeof(struct amr_sgentry));
1136    ac->ac_dataphys = segs[0].ds_addr;
1137
1138    /* populate s/g table */
1139    for (i = 0; i < nsegments; i++, sg++) {
1140	sg->sg_addr = segs[i].ds_addr;
1141	sg->sg_count = segs[i].ds_len;
1142    }
1143}
1144
1145static void
1146amr_mapcmd(struct amr_command *ac)
1147{
1148    struct amr_softc	*sc = ac->ac_sc;
1149
1150    debug("called");
1151
1152    /* if the command involves data at all */
1153    if (ac->ac_data != NULL) {
1154
1155	/* map the data buffer into bus space and build the s/g list */
1156	bus_dmamap_load(sc->amr_buffer_dmat, ac->ac_dmamap, ac->ac_data, ac->ac_length,
1157			amr_setup_dmamap, ac, 0);
1158	if (ac->ac_flags & AMR_CMD_DATAIN)
1159	    bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_dmamap, BUS_DMASYNC_PREREAD);
1160	if (ac->ac_flags & AMR_CMD_DATAOUT)
1161	    bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_dmamap, BUS_DMASYNC_PREWRITE);
1162    }
1163}
1164
1165static void
1166amr_unmapcmd(struct amr_command *ac)
1167{
1168    struct amr_softc	*sc = ac->ac_sc;
1169
1170    debug("called");
1171
1172    /* if the command involved data at all */
1173    if (ac->ac_data != NULL) {
1174
1175	if (ac->ac_flags & AMR_CMD_DATAIN)
1176	    bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_dmamap, BUS_DMASYNC_POSTREAD);
1177	if (ac->ac_flags & AMR_CMD_DATAOUT)
1178	    bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_dmamap, BUS_DMASYNC_POSTWRITE);
1179
1180	bus_dmamap_unload(sc->amr_buffer_dmat, ac->ac_dmamap);
1181    }
1182}
1183
1184/********************************************************************************
1185 * Take a command and give it to the controller.
1186 */
1187static int
1188amr_start(struct amr_command *ac)
1189{
1190    struct amr_softc	*sc = ac->ac_sc;
1191    int			done, s, i;
1192
1193    debug("called");
1194
1195    /*
1196     * Save the slot number so that we can locate this command when complete.
1197     * Note that ident = 0 seems to be special, so we don't use it.
1198     */
1199    ac->ac_mailbox.mb_ident = ac->ac_slot + 1;
1200
1201    /* set the busy flag when we copy the mailbox in */
1202    ac->ac_mailbox.mb_busy = 1;
1203
1204    /* set impossible status so that a woken sleeper can tell the command is busy */
1205    ac->ac_status = AMR_STATUS_BUSY;
1206
1207    /*
1208     * Spin waiting for the mailbox, give up after ~1 second.
1209     */
1210    debug("wait for mailbox");
1211    for (i = 10000, done = 0; (i > 0) && !done; i--) {
1212	s = splbio();
1213
1214	/* is the mailbox free? */
1215	if (sc->amr_mailbox->mb_busy == 0) {
1216	    debug("got mailbox");
1217	    sc->amr_mailbox64->mb64_segment = 0;
1218	    bcopy(&ac->ac_mailbox, sc->amr_mailbox, AMR_MBOX_CMDSIZE);
1219	    sc->amr_submit_command(sc);
1220	    done = 1;
1221	    sc->amr_workcount++;
1222	    TAILQ_INSERT_TAIL(&sc->amr_work, ac, ac_link);
1223
1224	    /* not free, try to clean up while we wait */
1225	} else {
1226	    debug("busy flag %x\n", sc->amr_mailbox->mb_busy);
1227	    /* this is somewhat ugly */
1228	    DELAY(100);
1229	}
1230	splx(s);	/* drop spl to allow completion interrupts */
1231    }
1232
1233    /* command is enqueued? */
1234    if (done) {
1235	ac->ac_stamp = time_second;
1236	debug("posted command");
1237	return(0);
1238    }
1239
1240    /*
1241     * The controller wouldn't take the command.  Revoke the slot
1242     * that the command was given and return with a bad status.
1243     */
1244    sc->amr_busycmd[ac->ac_slot] = NULL;
1245    device_printf(sc->amr_dev, "controller wedged (not taking commands)\n");
1246    ac->ac_status = AMR_STATUS_WEDGED;
1247    amr_complete(sc);
1248    return(EIO);
1249}
1250
1251/********************************************************************************
1252 * Extract one or more completed commands from the controller (sc)
1253 *
1254 * Returns nonzero if any commands on the work queue were marked as completed.
1255 */
1256static int
1257amr_done(struct amr_softc *sc)
1258{
1259    struct amr_command	*ac;
1260    struct amr_mailbox	mbox;
1261    int			i, idx, s, result;
1262
1263    debug("called");
1264
1265    /* See if there's anything for us to do */
1266    result = 0;
1267
1268    /* loop collecting completed commands */
1269    s = splbio();
1270    for (;;) {
1271	/* poll for a completed command's identifier and status */
1272	if (sc->amr_get_work(sc, &mbox)) {
1273	    result = 1;
1274
1275	    /* iterate over completed commands in this result */
1276	    for (i = 0; i < mbox.mb_nstatus; i++) {
1277		/* get pointer to busy command */
1278		idx = mbox.mb_completed[i] - 1;
1279		ac = sc->amr_busycmd[idx];
1280
1281		/* really a busy command? */
1282		if (ac != NULL) {
1283
1284		    /* pull the command from the busy index */
1285		    sc->amr_busycmd[idx] = NULL;
1286		    sc->amr_busycmdcount--;
1287
1288		    /* aborted command? */
1289		    if (ac == (struct amr_command *)sc) {
1290			device_printf(sc->amr_dev, "aborted command completed (%d)\n", idx);
1291			sc->amr_busycmd[idx] = NULL;	/* free the slot again */
1292			ac = NULL;
1293
1294			/* wedged command? */
1295		    } else if (ac->ac_status == AMR_STATUS_WEDGED) {
1296			device_printf(sc->amr_dev, "wedged command completed (%d)\n", idx);
1297			ac->ac_status = AMR_STATUS_LATE;
1298
1299			/* completed normally, save status */
1300		    } else {
1301			ac->ac_status = mbox.mb_status;
1302			debug("completed command with status %x", mbox.mb_status);
1303		    }
1304		}
1305	    }
1306	} else {
1307	    break;
1308	}
1309    }
1310
1311    /* if we've completed any commands, try posting some more */
1312    if (result)
1313	amr_startio(sc);
1314
1315    /* handle completion and timeouts */
1316    amr_complete(sc);
1317
1318    return(result);
1319}
1320
1321/********************************************************************************
1322 * Do completion processing on done commands on (sc)
1323 */
1324static void
1325amr_complete(struct amr_softc *sc)
1326{
1327    struct amr_command	*ac, *nc;
1328    int			s, count;
1329
1330    debug("called");
1331
1332    if (amr_lock_tas(sc, AMR_LOCK_COMPLETING))
1333	return;
1334
1335    s = splbio();
1336    count = 0;
1337
1338    /* scan the list of busy/done commands */
1339    ac = TAILQ_FIRST(&sc->amr_work);
1340    while (ac != NULL) {
1341	nc = TAILQ_NEXT(ac, ac_link);
1342
1343	/* Command has been completed in some fashion */
1344	if (ac->ac_status != AMR_STATUS_BUSY) {
1345
1346	    /* unmap the command's data buffer */
1347	    amr_unmapcmd(ac);
1348
1349	    /*
1350	     * Is there a completion handler?
1351	     */
1352	    if (ac->ac_complete != NULL) {
1353
1354		/* remove and give to completion handler */
1355		TAILQ_REMOVE(&sc->amr_work, ac, ac_link);
1356		sc->amr_workcount--;
1357		ac->ac_complete(ac);
1358
1359		/*
1360		 * Is someone sleeping on this one?
1361		 */
1362	    } else if (ac->ac_private != NULL) {
1363
1364		/* remove and wake up */
1365		TAILQ_REMOVE(&sc->amr_work, ac, ac_link);
1366		sc->amr_workcount--;
1367		wakeup_one(ac->ac_private);
1368
1369		/*
1370		 * Leave it for a polling caller.
1371		 */
1372	    } else {
1373	    }
1374	}
1375	ac = nc;
1376    }
1377    splx(s);
1378
1379    amr_lock_clr(sc, AMR_LOCK_COMPLETING);
1380}
1381
1382/********************************************************************************
1383 ********************************************************************************
1384                                                        Command Buffer Management
1385 ********************************************************************************
1386 ********************************************************************************/
1387
1388/********************************************************************************
1389 * Get a new command buffer.
1390 *
1391 * This may return NULL in low-memory cases.
1392 *
1393 * Note that using malloc() is expensive (the command buffer is << 1 page) but
1394 * necessary if we are to be a loadable module before the zone allocator is fixed.
1395 *
1396 * If possible, we recycle a command buffer that's been used before.
1397 *
1398 * XXX Note that command buffers are not cleaned out - it is the caller's
1399 *     responsibility to ensure that all required fields are filled in before
1400 *     using a buffer.
1401 */
1402static struct amr_command *
1403amr_alloccmd(struct amr_softc *sc)
1404{
1405    struct amr_command	*ac;
1406    int			error;
1407    int			s;
1408
1409    debug("called");
1410
1411    s = splbio();
1412    if ((ac = TAILQ_FIRST(&sc->amr_freecmds)) != NULL)
1413	TAILQ_REMOVE(&sc->amr_freecmds, ac, ac_link);
1414    splx(s);
1415
1416    /* allocate a new command buffer? */
1417    if (ac == NULL) {
1418	ac = (struct amr_command *)malloc(sizeof(*ac), M_DEVBUF, M_NOWAIT);
1419	if (ac != NULL) {
1420	    bzero(ac, sizeof(*ac));
1421	    ac->ac_sc = sc;
1422	    error = bus_dmamap_create(sc->amr_buffer_dmat, 0, &ac->ac_dmamap);
1423	    if (error) {
1424		free(ac, M_DEVBUF);
1425		return(NULL);
1426	    }
1427	}
1428    }
1429    bzero(&ac->ac_mailbox, sizeof(struct amr_mailbox));
1430    return(ac);
1431}
1432
1433/********************************************************************************
1434 * Release a command buffer for recycling.
1435 *
1436 * XXX It might be a good idea to limit the number of commands we save for reuse
1437 *     if it's shown that this list bloats out massively.
1438 */
1439static void
1440amr_releasecmd(struct amr_command *ac)
1441{
1442    int		s;
1443
1444    debug("called");
1445
1446    s = splbio();
1447    TAILQ_INSERT_HEAD(&ac->ac_sc->amr_freecmds, ac, ac_link);
1448    splx(s);
1449}
1450
1451/********************************************************************************
1452 * Permanently discard a command buffer.
1453 */
1454static void
1455amr_freecmd(struct amr_command *ac)
1456{
1457    struct amr_softc	*sc = ac->ac_sc;
1458
1459    debug("called");
1460
1461    bus_dmamap_destroy(sc->amr_buffer_dmat, ac->ac_dmamap);
1462    free(ac, M_DEVBUF);
1463}
1464
1465/********************************************************************************
1466 ********************************************************************************
1467                                                         Interface-specific Shims
1468 ********************************************************************************
1469 ********************************************************************************/
1470
1471/********************************************************************************
1472 * Tell the controller that the mailbox contains a valid command
1473 */
1474static void
1475amr_quartz_submit_command(struct amr_softc *sc)
1476{
1477    debug("called");
1478
1479    sc->amr_mailbox->mb_poll = 0;
1480    sc->amr_mailbox->mb_ack = 0;
1481    while(AMR_QGET_IDB(sc) & AMR_QIDB_SUBMIT)
1482	;				/* XXX aiee! what if it dies? */
1483    AMR_QPUT_IDB(sc, sc->amr_mailboxphys | AMR_QIDB_SUBMIT);
1484}
1485
1486static void
1487amr_std_submit_command(struct amr_softc *sc)
1488{
1489    debug("called");
1490
1491    /* XXX write barrier? */
1492    while (AMR_SGET_MBSTAT(sc) & AMR_SMBOX_BUSYFLAG)
1493	;				/* XXX aiee! what if it dies? */
1494    AMR_SPOST_COMMAND(sc);
1495}
1496
1497/********************************************************************************
1498 * Claim any work that the controller has completed; acknowledge completion,
1499 * save details of the completion in (mbsave)
1500 */
1501static int
1502amr_quartz_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave)
1503{
1504    int		s, worked;
1505    u_int32_t	outd;
1506
1507/*    debug("called"); */
1508
1509    worked = 0;
1510    s = splbio();
1511
1512    /* work waiting for us? */
1513    if ((outd = AMR_QGET_ODB(sc)) == AMR_QODB_READY) {
1514	AMR_QPUT_ODB(sc, AMR_QODB_READY);
1515
1516	/* save mailbox, which contains a list of completed commands */
1517	/* XXX read barrier? */
1518	bcopy(sc->amr_mailbox, mbsave, sizeof(*mbsave));
1519
1520	/* acknowledge that we have the commands */
1521	AMR_QPUT_IDB(sc, sc->amr_mailboxphys | AMR_QIDB_ACK);
1522	while(AMR_QGET_IDB(sc) & AMR_QIDB_ACK)
1523	    ;				/* XXX aiee! what if it dies? */
1524	worked = 1;			/* got some work */
1525    }
1526
1527    splx(s);
1528    return(worked);
1529}
1530
1531static int
1532amr_std_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave)
1533{
1534    int		s, worked;
1535    u_int8_t	istat;
1536
1537    debug("called");
1538
1539    worked = 0;
1540    s = splbio();
1541
1542    /* check for valid interrupt status */
1543    istat = AMR_SGET_ISTAT(sc);
1544    if ((istat & AMR_SINTR_VALID) != 0) {
1545	AMR_SPUT_ISTAT(sc, istat);	/* ack interrupt status */
1546
1547	/* save mailbox, which contains a list of completed commands */
1548	/* XXX read barrier? */
1549	bcopy(sc->amr_mailbox, mbsave, sizeof(*mbsave));
1550
1551	AMR_SACK_INTERRUPT(sc);		/* acknowledge we have the mailbox */
1552	worked = 1;
1553    }
1554
1555    splx(s);
1556    return(worked);
1557}
1558
1559/********************************************************************************
1560 * Notify the controller of the mailbox location.
1561 */
1562static void
1563amr_quartz_attach_mailbox(struct amr_softc *sc)
1564{
1565    /* Quartz is given the mailbox location when a command is submitted */
1566}
1567
1568static void
1569amr_std_attach_mailbox(struct amr_softc *sc)
1570{
1571
1572    /* program the mailbox physical address */
1573    AMR_SBYTE_SET(sc, AMR_SMBOX_0, sc->amr_mailboxphys         & 0xff);
1574    AMR_SBYTE_SET(sc, AMR_SMBOX_1, (sc->amr_mailboxphys >>  8) & 0xff);
1575    AMR_SBYTE_SET(sc, AMR_SMBOX_2, (sc->amr_mailboxphys >> 16) & 0xff);
1576    AMR_SBYTE_SET(sc, AMR_SMBOX_3, (sc->amr_mailboxphys >> 24) & 0xff);
1577    AMR_SBYTE_SET(sc, AMR_SMBOX_ENABLE, AMR_SMBOX_ADDR);
1578
1579    /* clear any outstanding interrupt and enable interrupts proper */
1580    AMR_SACK_INTERRUPT(sc);
1581    AMR_SENABLE_INTR(sc);
1582}
1583
1584/********************************************************************************
1585 ********************************************************************************
1586                                                                        Debugging
1587 ********************************************************************************
1588 ********************************************************************************/
1589
1590/********************************************************************************
1591 * Print the command (ac) in human-readable format
1592 */
1593static void
1594amr_printcommand(struct amr_command *ac)
1595{
1596    struct amr_softc	*sc = ac->ac_sc;
1597    struct amr_sgentry	*sg;
1598    int			i;
1599
1600    device_printf(sc->amr_dev, "cmd %x  ident %d  drive %d\n",
1601		  ac->ac_mailbox.mb_command, ac->ac_mailbox.mb_ident, ac->ac_mailbox.mb_drive);
1602    device_printf(sc->amr_dev, "blkcount %d  lba %d\n",
1603		  ac->ac_mailbox.mb_blkcount, ac->ac_mailbox.mb_lba);
1604    device_printf(sc->amr_dev, "virtaddr %p  length %lu\n", ac->ac_data, (unsigned long)ac->ac_length);
1605    device_printf(sc->amr_dev, "sg physaddr %08x  nsg %d\n",
1606		  ac->ac_mailbox.mb_physaddr, ac->ac_mailbox.mb_nsgelem);
1607
1608    /* get base address of s/g table */
1609    sg = sc->amr_sgtable + (ac->ac_slot * AMR_NSEG);
1610    for (i = 0; i < ac->ac_mailbox.mb_nsgelem; i++, sg++)
1611	device_printf(sc->amr_dev, "  %x/%d\n", sg->sg_addr, sg->sg_count);
1612}
1613
1614/********************************************************************************
1615 * Print information on all the controllers in the system, useful mostly
1616 * for calling from DDB.
1617 */
1618void
1619amr_report(void)
1620{
1621    struct amr_softc	*sc;
1622    int			i, s;
1623
1624    s = splbio();
1625    for (i = 0; (sc = devclass_get_softc(amr_devclass, i)) != NULL; i++) {
1626	device_printf(sc->amr_dev, "amr_waitbufs %d  amr_busycmdcount %d  amr_workcount %d\n",
1627		      sc->amr_waitbufs, sc->amr_busycmdcount, sc->amr_workcount);
1628    }
1629}
1630