File:  [DragonFly] / src / sys / dev / raid / amr / amr.c
Revision 1.10: download - view: text, annotated - select for diffs
Wed May 19 22:52:46 2004 UTC (10 years, 3 months ago) by dillon
Branches: MAIN
CVS tags: HEAD
Device layer rollup commit.

* cdevsw_add() is now required.  cdevsw_add() and cdevsw_remove() may specify
  a mask/match indicating the range of supported minor numbers.  Multiple
  cdevsw_add()'s using the same major number, but distinctly different
  ranges, may be issued.  All devices that failed to call cdevsw_add() before
  now do.

* cdevsw_remove() now automatically marks all devices within its supported
  range as being destroyed.

* vnode->v_rdev is no longer resolved when the vnode is created.  Instead,
  only v_udev (a newly added field) is resolved.  v_rdev is resolved when
  the vnode is opened and cleared on the last close.

* A great deal of code was making rather dubious assumptions with regards
  to the validity of devices associated with vnodes, primarily due to
  the persistence of a device structure due to being indexed by (major, minor)
  instead of by (cdevsw, major, minor).  In particular, if you run a program
  which connects to a USB device and then you pull the USB device and plug
  it back in, the vnode subsystem will continue to believe that the device
  is open when, in fact, it isn't (because it was destroyed and recreated).

  In particular, note that all the VFS mount procedures now check devices
  via v_udev instead of v_rdev prior to calling VOP_OPEN(), since v_rdev
  is NULL prior to the first open.

* The disk layer's device interaction has been rewritten.  The disk layer
  (i.e. the slice and disklabel management layer) no longer overloads
  its data onto the device structure representing the underlying physical
  disk.  Instead, the disk layer uses the new cdevsw_add() functionality
  to register its own cdevsw using the underlying device's major number,
  and simply does NOT register the underlying device's cdevsw.  No
  confusion is created because the device hash is now based on
  (cdevsw,major,minor) rather then (major,minor).

  NOTE: This also means that underlying raw disk devices may use the entire
  device minor number instead of having to reserve the bits used by the disk
  layer, and also means that can we (theoretically) stack a fully
  disklabel-supported 'disk' on top of any block device.

* The new reference counting scheme prevents this by associating a device
  with a cdevsw and disconnecting the device from its cdevsw when the cdevsw
  is removed.  Additionally, all udev2dev() lookups run through the cdevsw
  mask/match and only successfully find devices still associated with an
  active cdevsw.

* Major work on MFS:  MFS no longer shortcuts vnode and device creation.  It
  now creates a real vnode and a real device and implements real open and
  close VOPs.  Additionally, due to the disk layer changes, MFS is no longer
  limited to 255 mounts.  The new limit is 16 million.  Since MFS creates a
  real device node, mount_mfs will now create a real /dev/mfs<PID> device
  that can be read from userland (e.g. so you can dump an MFS filesystem).

* BUF AND DEVICE STRATEGY changes.  The struct buf contains a b_dev field.
  In order to properly handle stacked devices we now require that the b_dev
  field be initialized before the device strategy routine is called.  This
  required some additional work in various VFS implementations.  To enforce
  this requirement, biodone() now sets b_dev to NODEV.  The new disk layer
  will adjust b_dev before forwarding a request to the actual physical
  device.

* A bug in the ISO CD boot sequence which resulted in a panic has been fixed.

Testing by: lots of people, but David Rhodus found the most aggregious bugs.

    1: /*-
    2:  * Copyright (c) 1999,2000 Michael Smith
    3:  * Copyright (c) 2000 BSDi
    4:  * All rights reserved.
    5:  *
    6:  * Redistribution and use in source and binary forms, with or without
    7:  * modification, are permitted provided that the following conditions
    8:  * are met:
    9:  * 1. Redistributions of source code must retain the above copyright
   10:  *    notice, this list of conditions and the following disclaimer.
   11:  * 2. Redistributions in binary form must reproduce the above copyright
   12:  *    notice, this list of conditions and the following disclaimer in the
   13:  *    documentation and/or other materials provided with the distribution.
   14:  *
   15:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25:  * SUCH DAMAGE.
   26:  *
   27:  * Copyright (c) 2002 Eric Moore
   28:  * Copyright (c) 2002 LSI Logic Corporation
   29:  * All rights reserved.
   30:  *
   31:  * Redistribution and use in source and binary forms, with or without
   32:  * modification, are permitted provided that the following conditions
   33:  * are met:
   34:  * 1. Redistributions of source code must retain the above copyright
   35:  *    notice, this list of conditions and the following disclaimer.
   36:  * 2. Redistributions in binary form must reproduce the above copyright
   37:  *    notice, this list of conditions and the following disclaimer in the
   38:  *    documentation and/or other materials provided with the distribution.
   39:  * 3. The party using or redistributing the source code and binary forms
   40:  *    agrees to the disclaimer below and the terms and conditions set forth
   41:  *    herein.
   42:  *
   43:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   44:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   45:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   46:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   47:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   48:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   49:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   50:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   51:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   52:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   53:  * SUCH DAMAGE.
   54:  *
   55:  *	$FreeBSD: src/sys/dev/amr/amr.c,v 1.7.2.13 2003/01/15 13:41:18 emoore Exp $
   56:  *	$DragonFly: src/sys/dev/raid/amr/amr.c,v 1.10 2004/05/19 22:52:46 dillon Exp $
   57:  */
   58: 
   59: /*
   60:  * Driver for the AMI MegaRaid family of controllers.
   61:  */
   62: 
   63: #include <sys/param.h>
   64: #include <sys/systm.h>
   65: #include <sys/malloc.h>
   66: #include <sys/kernel.h>
   67: 
   68: #include "amr_compat.h"
   69: #include <sys/bus.h>
   70: #include <sys/conf.h>
   71: #include <sys/devicestat.h>
   72: #include <sys/disk.h>
   73: #include <sys/stat.h>
   74: 
   75: #include <machine/bus_memio.h>
   76: #include <machine/bus_pio.h>
   77: #include <machine/bus.h>
   78: #include <machine/resource.h>
   79: #include <sys/rman.h>
   80: 
   81: #include <bus/pci/pcireg.h>
   82: #include <bus/pci/pcivar.h>
   83: 
   84: #include "amrio.h"
   85: #include "amrreg.h"
   86: #include "amrvar.h"
   87: #define AMR_DEFINE_TABLES
   88: #include "amr_tables.h"
   89: 
   90: #define AMR_CDEV_MAJOR	132
   91: 
   92: static d_open_t         amr_open;
   93: static d_close_t        amr_close;
   94: static d_ioctl_t        amr_ioctl;
   95: 
   96: static struct cdevsw amr_cdevsw = {
   97: 		/* name */ 	"amr",
   98: 		/* maj */	AMR_CDEV_MAJOR,
   99: 		/* flags */	0,
  100: 		/* port */      NULL,
  101: 		/* clone */	NULL,
  102: 
  103: 		/* open */	amr_open,
  104: 		/* close */	amr_close,
  105: 		/* read */	noread,
  106: 		/* write */	nowrite,
  107: 		/* ioctl */	amr_ioctl,
  108: 		/* poll */	nopoll,
  109: 		/* mmap */	nommap,
  110: 		/* strategy */	nostrategy,
  111: 		/* dump */	nodump,
  112: 		/* psize */ 	nopsize
  113: };
  114: 
  115: /*
  116:  * Initialisation, bus interface.
  117:  */
  118: static void	amr_startup(void *arg);
  119: 
  120: /*
  121:  * Command wrappers
  122:  */
  123: static int	amr_query_controller(struct amr_softc *sc);
  124: static void	*amr_enquiry(struct amr_softc *sc, size_t bufsize, 
  125: 			     u_int8_t cmd, u_int8_t cmdsub, u_int8_t cmdqual);
  126: static void	amr_completeio(struct amr_command *ac);
  127: static int	amr_support_ext_cdb(struct amr_softc *sc);
  128: 
  129: /*
  130:  * Command buffer allocation.
  131:  */
  132: static void	amr_alloccmd_cluster(struct amr_softc *sc);
  133: static void	amr_freecmd_cluster(struct amr_command_cluster *acc);
  134: 
  135: /*
  136:  * Command processing.
  137:  */
  138: static int	amr_bio_command(struct amr_softc *sc, struct amr_command **acp);
  139: static int	amr_wait_command(struct amr_command *ac);
  140: static int	amr_getslot(struct amr_command *ac);
  141: static void	amr_mapcmd(struct amr_command *ac);
  142: static void	amr_unmapcmd(struct amr_command *ac);
  143: static int	amr_start(struct amr_command *ac);
  144: static void	amr_complete(void *context, int pending);
  145: 
  146: /*
  147:  * Status monitoring
  148:  */
  149: static void	amr_periodic(void *data);
  150: 
  151: /*
  152:  * Interface-specific shims
  153:  */
  154: static int	amr_quartz_submit_command(struct amr_softc *sc);
  155: static int	amr_quartz_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave);
  156: static int	amr_quartz_poll_command(struct amr_command *ac);
  157: 
  158: static int	amr_std_submit_command(struct amr_softc *sc);
  159: static int	amr_std_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave);
  160: static int	amr_std_poll_command(struct amr_command *ac);
  161: static void	amr_std_attach_mailbox(struct amr_softc *sc);
  162: 
  163: #ifdef AMR_BOARD_INIT
  164: static int	amr_quartz_init(struct amr_softc *sc);
  165: static int	amr_std_init(struct amr_softc *sc);
  166: #endif
  167: 
  168: /*
  169:  * Debugging
  170:  */
  171: static void	amr_describe_controller(struct amr_softc *sc);
  172: #ifdef AMR_DEBUG
  173: #if 0
  174: static void	amr_printcommand(struct amr_command *ac);
  175: #endif
  176: #endif
  177: 
  178: DECLARE_DUMMY_MODULE(amr);
  179: 
  180: /********************************************************************************
  181:  ********************************************************************************
  182:                                                                       Inline Glue
  183:  ********************************************************************************
  184:  ********************************************************************************/
  185: 
  186: /********************************************************************************
  187:  ********************************************************************************
  188:                                                                 Public Interfaces
  189:  ********************************************************************************
  190:  ********************************************************************************/
  191: 
  192: /********************************************************************************
  193:  * Initialise the controller and softc.
  194:  */
  195: int
  196: amr_attach(struct amr_softc *sc)
  197: {
  198: 
  199:     debug_called(1);
  200: 
  201:     /*
  202:      * Initialise per-controller queues.
  203:      */
  204:     TAILQ_INIT(&sc->amr_completed);
  205:     TAILQ_INIT(&sc->amr_freecmds);
  206:     TAILQ_INIT(&sc->amr_cmd_clusters);
  207:     TAILQ_INIT(&sc->amr_ready);
  208:     bioq_init(&sc->amr_bioq);
  209: 
  210: #if defined(__FreeBSD__) && __FreeBSD_version >= 500005
  211:     /*
  212:      * Initialise command-completion task.
  213:      */
  214:     TASK_INIT(&sc->amr_task_complete, 0, amr_complete, sc);
  215: #endif
  216: 
  217:     debug(2, "queue init done");
  218: 
  219:     /*
  220:      * Configure for this controller type.
  221:      */
  222:     if (AMR_IS_QUARTZ(sc)) {
  223: 	sc->amr_submit_command = amr_quartz_submit_command;
  224: 	sc->amr_get_work       = amr_quartz_get_work;
  225: 	sc->amr_poll_command   = amr_quartz_poll_command;
  226:     } else {
  227: 	sc->amr_submit_command = amr_std_submit_command;
  228: 	sc->amr_get_work       = amr_std_get_work;
  229: 	sc->amr_poll_command   = amr_std_poll_command;
  230: 	amr_std_attach_mailbox(sc);;
  231:     }
  232: 
  233: #ifdef AMR_BOARD_INIT
  234:     if ((AMR_IS_QUARTZ(sc) ? amr_quartz_init(sc) : amr_std_init(sc))))
  235: 	return(ENXIO);
  236: #endif
  237: 
  238:     /*
  239:      * Quiz controller for features and limits.
  240:      */
  241:     if (amr_query_controller(sc))
  242: 	return(ENXIO);
  243: 
  244:     debug(2, "controller query complete");
  245: 
  246:     /*
  247:      * Attach our 'real' SCSI channels to CAM.
  248:      */
  249:     if (amr_cam_attach(sc))
  250: 	return(ENXIO);
  251:     debug(2, "CAM attach done");
  252: 
  253:     /*
  254:      * Create the control device.
  255:      */
  256:     cdevsw_add(&amr_cdevsw, -1, device_get_unit(sc->amr_dev));
  257:     sc->amr_dev_t = make_dev(&amr_cdevsw, device_get_unit(sc->amr_dev), 
  258: 			    UID_ROOT, GID_OPERATOR, S_IRUSR | S_IWUSR,
  259: 			    "amr%d", device_get_unit(sc->amr_dev));
  260:     sc->amr_dev_t->si_drv1 = sc;
  261:     reference_dev(sc->amr_dev_t);
  262: 
  263:     /*
  264:      * Schedule ourselves to bring the controller up once interrupts are
  265:      * available.
  266:      */
  267:     bzero(&sc->amr_ich, sizeof(struct intr_config_hook));
  268:     sc->amr_ich.ich_func = amr_startup;
  269:     sc->amr_ich.ich_arg = sc;
  270:     if (config_intrhook_establish(&sc->amr_ich) != 0) {
  271: 	device_printf(sc->amr_dev, "can't establish configuration hook\n");
  272: 	return(ENOMEM);
  273:     }
  274: 
  275:     /*
  276:      * Print a little information about the controller.
  277:      */
  278:     amr_describe_controller(sc);
  279: 
  280:     debug(2, "attach complete");
  281:     return(0);
  282: }
  283: 
  284: /********************************************************************************
  285:  * Locate disk resources and attach children to them.
  286:  */
  287: static void
  288: amr_startup(void *arg)
  289: {
  290:     struct amr_softc	*sc = (struct amr_softc *)arg;
  291:     struct amr_logdrive	*dr;
  292:     int			i, error;
  293:     
  294:     debug_called(1);
  295: 
  296:     /* pull ourselves off the intrhook chain */
  297:     config_intrhook_disestablish(&sc->amr_ich);
  298: 
  299:     /* get up-to-date drive information */
  300:     if (amr_query_controller(sc)) {
  301: 	device_printf(sc->amr_dev, "can't scan controller for drives\n");
  302: 	return;
  303:     }
  304: 
  305:     /* iterate over available drives */
  306:     for (i = 0, dr = &sc->amr_drive[0]; (i < AMR_MAXLD) && (dr->al_size != 0xffffffff); i++, dr++) {
  307: 	/* are we already attached to this drive? */
  308: 	if (dr->al_disk == 0) {
  309: 	    /* generate geometry information */
  310: 	    if (dr->al_size > 0x200000) {	/* extended translation? */
  311: 		dr->al_heads = 255;
  312: 		dr->al_sectors = 63;
  313: 	    } else {
  314: 		dr->al_heads = 64;
  315: 		dr->al_sectors = 32;
  316: 	    }
  317: 	    dr->al_cylinders = dr->al_size / (dr->al_heads * dr->al_sectors);
  318: 	    
  319: 	    dr->al_disk = device_add_child(sc->amr_dev, NULL, -1);
  320: 	    if (dr->al_disk == 0)
  321: 		device_printf(sc->amr_dev, "device_add_child failed\n");
  322: 	    device_set_ivars(dr->al_disk, dr);
  323: 	}
  324:     }
  325:     
  326:     if ((error = bus_generic_attach(sc->amr_dev)) != 0)
  327: 	device_printf(sc->amr_dev, "bus_generic_attach returned %d\n", error);
  328:     
  329:     /* mark controller back up */
  330:     sc->amr_state &= ~AMR_STATE_SHUTDOWN;
  331: 
  332:     /* interrupts will be enabled before we do anything more */
  333:     sc->amr_state |= AMR_STATE_INTEN;
  334: 
  335:     /*
  336:      * Start the timeout routine.
  337:      */
  338: /*    sc->amr_timeout = timeout(amr_periodic, sc, hz);*/
  339: 
  340:     return;
  341: }
  342: 
  343: /*******************************************************************************
  344:  * Free resources associated with a controller instance
  345:  */
  346: void
  347: amr_free(struct amr_softc *sc)
  348: {
  349:     struct amr_command_cluster	*acc;
  350: 
  351:     /* detach from CAM */
  352:     amr_cam_detach(sc);
  353: 
  354:     /* cancel status timeout */
  355:     untimeout(amr_periodic, sc, sc->amr_timeout);
  356:     
  357:     /* throw away any command buffers */
  358:     while ((acc = TAILQ_FIRST(&sc->amr_cmd_clusters)) != NULL) {
  359: 	TAILQ_REMOVE(&sc->amr_cmd_clusters, acc, acc_link);
  360: 	amr_freecmd_cluster(acc);
  361:     }
  362: 
  363:     /* destroy control device */
  364:     if( sc->amr_dev_t != (dev_t)NULL)
  365: 	    destroy_dev(sc->amr_dev_t);
  366:     cdevsw_remove(&amr_cdevsw, -1, device_get_unit(sc->amr_dev));
  367: }
  368: 
  369: /*******************************************************************************
  370:  * Receive a bio structure from a child device and queue it on a particular
  371:  * disk resource, then poke the disk resource to start as much work as it can.
  372:  */
  373: int
  374: amr_submit_bio(struct amr_softc *sc, struct bio *bio)
  375: {
  376:     debug_called(2);
  377: 
  378:     amr_enqueue_bio(sc, bio);
  379:     amr_startio(sc);
  380:     return(0);
  381: }
  382: 
  383: /********************************************************************************
  384:  * Accept an open operation on the control device.
  385:  */
  386: static int
  387: amr_open(dev_t dev, int flags, int fmt, d_thread_t *td)
  388: {
  389:     int			unit = minor(dev);
  390:     struct amr_softc	*sc = devclass_get_softc(devclass_find("amr"), unit);
  391: 
  392:     debug_called(1);
  393: 
  394:     sc->amr_state |= AMR_STATE_OPEN;
  395:     return(0);
  396: }
  397: 
  398: /********************************************************************************
  399:  * Accept the last close on the control device.
  400:  */
  401: static int
  402: amr_close(dev_t dev, int flags, int fmt, d_thread_t *td)
  403: {
  404:     int			unit = minor(dev);
  405:     struct amr_softc	*sc = devclass_get_softc(devclass_find("amr"), unit);
  406: 
  407:     debug_called(1);
  408: 
  409:     sc->amr_state &= ~AMR_STATE_OPEN;
  410:     return (0);
  411: }
  412: 
  413: /********************************************************************************
  414:  * Handle controller-specific control operations.
  415:  */
  416: static int
  417: amr_ioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, d_thread_t *td)
  418: {
  419:     struct amr_softc		*sc = (struct amr_softc *)dev->si_drv1;
  420:     int				*arg = (int *)addr;
  421:     struct amr_user_ioctl	*au = (struct amr_user_ioctl *)addr;
  422:     struct amr_command		*ac;
  423:     struct amr_mailbox_ioctl	*mbi;
  424:     struct amr_passthrough	*ap;
  425:     void			*dp;
  426:     int				error;
  427: 
  428:     debug_called(1);
  429: 
  430:     error = 0;
  431:     dp = NULL;
  432:     ap = NULL;
  433:     ac = NULL;
  434:     switch(cmd) {
  435: 
  436:     case AMR_IO_VERSION:
  437: 	debug(1, "AMR_IO_VERSION");
  438: 	*arg = AMR_IO_VERSION_NUMBER;
  439: 	break;
  440: 
  441:     case AMR_IO_COMMAND:
  442: 	debug(1, "AMR_IO_COMMAND  0x%x", au->au_cmd[0]);
  443: 	/* handle inbound data buffer */
  444: 	if (au->au_length != 0) {
  445: 	    if ((dp = malloc(au->au_length, M_DEVBUF, M_WAITOK)) == NULL) {
  446: 		error = ENOMEM;
  447: 		break;
  448: 	    }
  449: 	    if ((error = copyin(au->au_buffer, dp, au->au_length)) != 0)
  450: 		break;
  451: 	    debug(2, "copyin %ld bytes from %p -> %p", au->au_length, au->au_buffer, dp);
  452: 	}
  453: 
  454: 	if ((ac = amr_alloccmd(sc)) == NULL) {
  455: 	    error = ENOMEM;
  456: 	    break;
  457: 	}
  458: 
  459: 	/* handle SCSI passthrough command */
  460: 	if (au->au_cmd[0] == AMR_CMD_PASS) {
  461: 	    if ((ap = malloc(sizeof(*ap), M_DEVBUF, M_WAITOK | M_ZERO)) == NULL) {
  462: 		error = ENOMEM;
  463: 		break;
  464: 	    }
  465: 
  466: 	    /* copy cdb */
  467: 	    ap->ap_cdb_length = au->au_cmd[2];
  468: 	    bcopy(&au->au_cmd[3], &ap->ap_cdb[0], ap->ap_cdb_length);
  469: 
  470: 	    /* build passthrough */
  471: 	    ap->ap_timeout		= au->au_cmd[ap->ap_cdb_length + 3] & 0x07;
  472: 	    ap->ap_ars			= (au->au_cmd[ap->ap_cdb_length + 3] & 0x08) ? 1 : 0;
  473: 	    ap->ap_islogical		= (au->au_cmd[ap->ap_cdb_length + 3] & 0x80) ? 1 : 0;
  474: 	    ap->ap_logical_drive_no	= au->au_cmd[ap->ap_cdb_length + 4];
  475: 	    ap->ap_channel		= au->au_cmd[ap->ap_cdb_length + 5];
  476: 	    ap->ap_scsi_id 		= au->au_cmd[ap->ap_cdb_length + 6];
  477: 	    ap->ap_request_sense_length	= 14;
  478: 	    ap->ap_data_transfer_length = au->au_length;
  479: 	    /* XXX what about the request-sense area? does the caller want it? */
  480: 
  481: 	    /* build command */
  482: 	    ac->ac_data = ap;
  483: 	    ac->ac_length = sizeof(*ap);
  484: 	    ac->ac_flags |= AMR_CMD_DATAOUT;
  485: 	    ac->ac_ccb_data = dp;
  486: 	    ac->ac_ccb_length = au->au_length;
  487: 	    if (au->au_direction & AMR_IO_READ)
  488: 		ac->ac_flags |= AMR_CMD_CCB_DATAIN;
  489: 	    if (au->au_direction & AMR_IO_WRITE)
  490: 		ac->ac_flags |= AMR_CMD_CCB_DATAOUT;
  491: 
  492: 	    ac->ac_mailbox.mb_command = AMR_CMD_PASS;
  493: 
  494: 	} else {
  495: 	    /* direct command to controller */
  496: 	    mbi = (struct amr_mailbox_ioctl *)&ac->ac_mailbox;
  497: 
  498: 	    /* copy pertinent mailbox items */
  499: 	    mbi->mb_command = au->au_cmd[0];
  500: 	    mbi->mb_channel = au->au_cmd[1];
  501: 	    mbi->mb_param = au->au_cmd[2];
  502: 	    mbi->mb_pad[0] = au->au_cmd[3];
  503: 	    mbi->mb_drive = au->au_cmd[4];
  504: 
  505: 	    /* build the command */
  506: 	    ac->ac_data = dp;
  507: 	    ac->ac_length = au->au_length;
  508: 	    if (au->au_direction & AMR_IO_READ)
  509: 		ac->ac_flags |= AMR_CMD_DATAIN;
  510: 	    if (au->au_direction & AMR_IO_WRITE)
  511: 		ac->ac_flags |= AMR_CMD_DATAOUT;
  512: 	}
  513: 
  514: 	/* run the command */
  515: 	if ((error = amr_wait_command(ac)) != 0)
  516: 	    break;
  517: 
  518: 	/* copy out data and set status */
  519: 	if (au->au_length != 0)
  520: 	    error = copyout(dp, au->au_buffer, au->au_length);
  521: 	debug(2, "copyout %ld bytes from %p -> %p", au->au_length, dp, au->au_buffer);
  522: 	if (dp != NULL)
  523: 	    debug(2, "%16d", (int)dp);
  524: 	au->au_status = ac->ac_status;
  525: 	break;
  526: 
  527:     default:
  528: 	debug(1, "unknown ioctl 0x%lx", cmd);
  529: 	error = ENOIOCTL;
  530: 	break;
  531:     }
  532: 
  533:     if (dp != NULL)
  534: 	free(dp, M_DEVBUF);
  535:     if (ap != NULL)
  536: 	free(ap, M_DEVBUF);
  537:     if (ac != NULL)
  538: 	amr_releasecmd(ac);
  539:     return(error);
  540: }
  541: 
  542: /********************************************************************************
  543:  ********************************************************************************
  544:                                                                 Status Monitoring
  545:  ********************************************************************************
  546:  ********************************************************************************/
  547: 
  548: /********************************************************************************
  549:  * Perform a periodic check of the controller status
  550:  */
  551: static void
  552: amr_periodic(void *data)
  553: {
  554:     struct amr_softc	*sc = (struct amr_softc *)data;
  555: 
  556:     debug_called(2);
  557: 
  558:     /* XXX perform periodic status checks here */
  559: 
  560:     /* compensate for missed interrupts */
  561:     amr_done(sc);
  562: 
  563:     /* reschedule */
  564:     sc->amr_timeout = timeout(amr_periodic, sc, hz);
  565: }
  566: 
  567: /********************************************************************************
  568:  ********************************************************************************
  569:                                                                  Command Wrappers
  570:  ********************************************************************************
  571:  ********************************************************************************/
  572: 
  573: /********************************************************************************
  574:  * Interrogate the controller for the operational parameters we require.
  575:  */
  576: static int
  577: amr_query_controller(struct amr_softc *sc)
  578: {
  579:     struct amr_enquiry3	*aex;
  580:     struct amr_prodinfo	*ap;
  581:     struct amr_enquiry	*ae;
  582:     int			ldrv;
  583: 
  584:     /* 
  585:      * If we haven't found the real limit yet, let us have a couple of commands in
  586:      * order to be able to probe.
  587:      */
  588:     if (sc->amr_maxio == 0)
  589: 	sc->amr_maxio = 2;
  590: 
  591:     /*
  592:      * Greater than 10 byte cdb support
  593:      */
  594:     sc->support_ext_cdb = amr_support_ext_cdb(sc);
  595: 
  596:     if(sc->support_ext_cdb) {
  597: 	debug(2,"supports extended CDBs.");
  598:     }
  599: 
  600:     /* 
  601:      * Try to issue an ENQUIRY3 command 
  602:      */
  603:     if ((aex = amr_enquiry(sc, 2048, AMR_CMD_CONFIG, AMR_CONFIG_ENQ3, 
  604: 			   AMR_CONFIG_ENQ3_SOLICITED_FULL)) != NULL) {
  605: 
  606: 	/*
  607: 	 * Fetch current state of logical drives.
  608: 	 */
  609: 	for (ldrv = 0; ldrv < aex->ae_numldrives; ldrv++) {
  610: 	    sc->amr_drive[ldrv].al_size       = aex->ae_drivesize[ldrv];
  611: 	    sc->amr_drive[ldrv].al_state      = aex->ae_drivestate[ldrv];
  612: 	    sc->amr_drive[ldrv].al_properties = aex->ae_driveprop[ldrv];
  613: 	    debug(2, "  drive %d: %d state %x properties %x\n", ldrv, sc->amr_drive[ldrv].al_size,
  614: 		  sc->amr_drive[ldrv].al_state, sc->amr_drive[ldrv].al_properties);
  615: 	}
  616: 	free(aex, M_DEVBUF);
  617: 
  618: 	/*
  619: 	 * Get product info for channel count.
  620: 	 */
  621: 	if ((ap = amr_enquiry(sc, 2048, AMR_CMD_CONFIG, AMR_CONFIG_PRODUCT_INFO, 0)) == NULL) {
  622: 	    device_printf(sc->amr_dev, "can't obtain product data from controller\n");
  623: 	    return(1);
  624: 	}
  625: 	sc->amr_maxdrives = 40;
  626: 	sc->amr_maxchan = ap->ap_nschan;
  627: 	sc->amr_maxio = ap->ap_maxio;
  628: 	sc->amr_type |= AMR_TYPE_40LD;
  629: 	free(ap, M_DEVBUF);
  630: 
  631:     } else {
  632: 
  633: 	/* failed, try the 8LD ENQUIRY commands */
  634: 	if ((ae = (struct amr_enquiry *)amr_enquiry(sc, 2048, AMR_CMD_EXT_ENQUIRY2, 0, 0)) == NULL) {
  635: 	    if ((ae = (struct amr_enquiry *)amr_enquiry(sc, 2048, AMR_CMD_ENQUIRY, 0, 0)) == NULL) {
  636: 		device_printf(sc->amr_dev, "can't obtain configuration data from controller\n");
  637: 		return(1);
  638: 	    }
  639: 	    ae->ae_signature = 0;
  640: 	}
  641: 
  642: 	/*
  643: 	 * Fetch current state of logical drives.
  644: 	 */
  645: 	for (ldrv = 0; ldrv < ae->ae_ldrv.al_numdrives; ldrv++) {
  646: 	    sc->amr_drive[ldrv].al_size       = ae->ae_ldrv.al_size[ldrv];
  647: 	    sc->amr_drive[ldrv].al_state      = ae->ae_ldrv.al_state[ldrv];
  648: 	    sc->amr_drive[ldrv].al_properties = ae->ae_ldrv.al_properties[ldrv];
  649: 	    debug(2, "  drive %d: %d state %x properties %x\n", ldrv, sc->amr_drive[ldrv].al_size,
  650: 		  sc->amr_drive[ldrv].al_state, sc->amr_drive[ldrv].al_properties);
  651: 	}
  652: 
  653: 	sc->amr_maxdrives = 8;
  654: 	sc->amr_maxchan = ae->ae_adapter.aa_channels;
  655: 	sc->amr_maxio = ae->ae_adapter.aa_maxio;
  656: 	free(ae, M_DEVBUF);
  657:     }
  658: 
  659:     /*
  660:      * Mark remaining drives as unused.
  661:      */
  662:     for (; ldrv < AMR_MAXLD; ldrv++)
  663: 	sc->amr_drive[ldrv].al_size = 0xffffffff;
  664: 
  665:     /* 
  666:      * Cap the maximum number of outstanding I/Os.  AMI's Linux driver doesn't trust
  667:      * the controller's reported value, and lockups have been seen when we do.
  668:      */
  669:     sc->amr_maxio = imin(sc->amr_maxio, AMR_LIMITCMD);
  670: 
  671:     return(0);
  672: }
  673: 
  674: /********************************************************************************
  675:  * Run a generic enquiry-style command.
  676:  */
  677: static void *
  678: amr_enquiry(struct amr_softc *sc, size_t bufsize, u_int8_t cmd, u_int8_t cmdsub, u_int8_t cmdqual)
  679: {
  680:     struct amr_command	*ac;
  681:     void		*result;
  682:     u_int8_t		*mbox;
  683:     int			error;
  684: 
  685:     debug_called(1);
  686: 
  687:     error = 1;
  688:     result = NULL;
  689:     
  690:     /* get ourselves a command buffer */
  691:     if ((ac = amr_alloccmd(sc)) == NULL)
  692: 	goto out;
  693:     /* allocate the response structure */
  694:     if ((result = malloc(bufsize, M_DEVBUF, M_NOWAIT)) == NULL)
  695: 	goto out;
  696:     /* set command flags */
  697:     ac->ac_flags |= AMR_CMD_PRIORITY | AMR_CMD_DATAOUT;
  698:     
  699:     /* point the command at our data */
  700:     ac->ac_data = result;
  701:     ac->ac_length = bufsize;
  702:     
  703:     /* build the command proper */
  704:     mbox = (u_int8_t *)&ac->ac_mailbox;		/* XXX want a real structure for this? */
  705:     mbox[0] = cmd;
  706:     mbox[2] = cmdsub;
  707:     mbox[3] = cmdqual;
  708: 
  709:     /* can't assume that interrupts are going to work here, so play it safe */
  710:     if (sc->amr_poll_command(ac))
  711: 	goto out;
  712:     error = ac->ac_status;
  713:     
  714:  out:
  715:     if (ac != NULL)
  716: 	amr_releasecmd(ac);
  717:     if ((error != 0) && (result != NULL)) {
  718: 	free(result, M_DEVBUF);
  719: 	result = NULL;
  720:     }
  721:     return(result);
  722: }
  723: 
  724: /********************************************************************************
  725:  * Flush the controller's internal cache, return status.
  726:  */
  727: int
  728: amr_flush(struct amr_softc *sc)
  729: {
  730:     struct amr_command	*ac;
  731:     int			error;
  732: 
  733:     /* get ourselves a command buffer */
  734:     error = 1;
  735:     if ((ac = amr_alloccmd(sc)) == NULL)
  736: 	goto out;
  737:     /* set command flags */
  738:     ac->ac_flags |= AMR_CMD_PRIORITY | AMR_CMD_DATAOUT;
  739:     
  740:     /* build the command proper */
  741:     ac->ac_mailbox.mb_command = AMR_CMD_FLUSH;
  742: 
  743:     /* we have to poll, as the system may be going down or otherwise damaged */
  744:     if (sc->amr_poll_command(ac))
  745: 	goto out;
  746:     error = ac->ac_status;
  747:     
  748:  out:
  749:     if (ac != NULL)
  750: 	amr_releasecmd(ac);
  751:     return(error);
  752: }
  753: 
  754: /********************************************************************************
  755:  * Detect extented cdb >> greater than 10 byte cdb support
  756:  * returns '1' means this support exist
  757:  * returns '0' means this support doesn't exist
  758:  */
  759: static int
  760: amr_support_ext_cdb(struct amr_softc *sc)
  761: {
  762:     struct amr_command	*ac;
  763:     u_int8_t		*mbox;
  764:     int			error;
  765: 
  766:     /* get ourselves a command buffer */
  767:     error = 0;
  768:     if ((ac = amr_alloccmd(sc)) == NULL)
  769: 	goto out;
  770:     /* set command flags */
  771:     ac->ac_flags |= AMR_CMD_PRIORITY | AMR_CMD_DATAOUT;
  772: 
  773:     /* build the command proper */
  774:     mbox = (u_int8_t *)&ac->ac_mailbox;		/* XXX want a real structure for this? */
  775:     mbox[0] = 0xA4;
  776:     mbox[2] = 0x16;
  777: 
  778: 
  779:     /* we have to poll, as the system may be going down or otherwise damaged */
  780:     if (sc->amr_poll_command(ac))
  781: 	goto out;
  782:     if( ac->ac_status == AMR_STATUS_SUCCESS ) {
  783: 	    error = 1;
  784:     }
  785: 
  786: out:
  787:     if (ac != NULL)
  788: 	amr_releasecmd(ac);
  789:     return(error);
  790: }
  791: 
  792: /********************************************************************************
  793:  * Try to find I/O work for the controller from one or more of the work queues.
  794:  *
  795:  * We make the assumption that if the controller is not ready to take a command
  796:  * at some given time, it will generate an interrupt at some later time when
  797:  * it is.
  798:  */
  799: void
  800: amr_startio(struct amr_softc *sc)
  801: {
  802:     struct amr_command	*ac;
  803: 
  804:     /* spin until something prevents us from doing any work */
  805:     for (;;) {
  806: 
  807: 	/* try to get a ready command */
  808: 	ac = amr_dequeue_ready(sc);
  809: 
  810: 	/* if that failed, build a command from a bio */
  811: 	if (ac == NULL)
  812: 	    (void)amr_bio_command(sc, &ac);
  813: 
  814: 	/* if that failed, build a command from a ccb */
  815: 	if (ac == NULL)
  816: 	    (void)amr_cam_command(sc, &ac);
  817: 
  818: 	/* if we don't have anything to do, give up */
  819: 	if (ac == NULL)
  820: 	    break;
  821: 
  822: 	/* try to give the command to the controller; if this fails save it for later and give up */
  823: 	if (amr_start(ac)) {
  824: 	    debug(2, "controller busy, command deferred");
  825: 	    amr_requeue_ready(ac);	/* XXX schedule retry very soon? */
  826: 	    break;
  827: 	}
  828:     }
  829: }
  830: 
  831: /********************************************************************************
  832:  * Handle completion of an I/O command.
  833:  */
  834: static void
  835: amr_completeio(struct amr_command *ac)
  836: {
  837:     struct amr_softc	*sc = ac->ac_sc;
  838:     
  839:     if (ac->ac_status != AMR_STATUS_SUCCESS) {	/* could be more verbose here? */
  840: 	ac->ac_bio->bio_error = EIO;
  841: 	ac->ac_bio->bio_flags |= BIO_ERROR;
  842: 
  843: 	device_printf(sc->amr_dev, "I/O error - 0x%x\n", ac->ac_status);
  844: /*	amr_printcommand(ac);*/
  845:     }
  846:     amrd_intr(ac->ac_bio);
  847:     amr_releasecmd(ac);
  848: }
  849: 
  850: /********************************************************************************
  851:  ********************************************************************************
  852:                                                                Command Processing
  853:  ********************************************************************************
  854:  ********************************************************************************/
  855: 
  856: /********************************************************************************
  857:  * Convert a bio off the top of the bio queue into a command.
  858:  */
  859: static int
  860: amr_bio_command(struct amr_softc *sc, struct amr_command **acp)
  861: {
  862:     struct amr_command	*ac;
  863:     struct amrd_softc	*amrd;
  864:     struct bio		*bio;
  865:     int			error;
  866:     int			blkcount;
  867:     int			driveno;
  868:     int			cmd;
  869: 
  870:     ac = NULL;
  871:     error = 0;
  872: 
  873:     /* get a bio to work on */
  874:     if ((bio = amr_dequeue_bio(sc)) == NULL)
  875: 	goto out;
  876: 
  877:     /* get a command */
  878:     if ((ac = amr_alloccmd(sc)) == NULL) {
  879: 	error = ENOMEM;
  880: 	goto out;
  881:     }	
  882: 	
  883:     /* connect the bio to the command */
  884:     ac->ac_complete = amr_completeio;
  885:     ac->ac_bio = bio;
  886:     ac->ac_data = bio->bio_data;
  887:     ac->ac_length = bio->bio_bcount;
  888:     if (BIO_IS_READ(bio)) {
  889: 	ac->ac_flags |= AMR_CMD_DATAIN;
  890: 	cmd = AMR_CMD_LREAD;
  891:     } else {
  892: 	ac->ac_flags |= AMR_CMD_DATAOUT;
  893: 	cmd = AMR_CMD_LWRITE;
  894:     }
  895:     amrd = (struct amrd_softc *)bio->bio_dev->si_drv1;
  896:     driveno = amrd->amrd_drive - sc->amr_drive;
  897:     blkcount = (bio->bio_bcount + AMR_BLKSIZE - 1) / AMR_BLKSIZE;
  898: 
  899:     ac->ac_mailbox.mb_command = cmd;
  900:     ac->ac_mailbox.mb_blkcount = blkcount;
  901:     ac->ac_mailbox.mb_lba = bio->bio_pblkno;
  902:     ac->ac_mailbox.mb_drive = driveno;
  903:     /* we fill in the s/g related data when the command is mapped */
  904: 
  905:     if ((bio->bio_pblkno + blkcount) > sc->amr_drive[driveno].al_size)
  906: 	device_printf(sc->amr_dev, "I/O beyond end of unit (%lld,%d > %lu)\n", 
  907: 		      (long long)bio->bio_pblkno, blkcount,
  908: 		      (u_long)sc->amr_drive[driveno].al_size);
  909: 
  910: out:
  911:     if (error != 0) {
  912: 	if (ac != NULL)
  913: 	    amr_releasecmd(ac);
  914: 	if (bio != NULL)			/* this breaks ordering... */
  915: 	    amr_enqueue_bio(sc, bio);
  916:     }
  917:     *acp = ac;
  918:     return(error);
  919: }
  920: 
  921: /********************************************************************************
  922:  * Take a command, submit it to the controller and sleep until it completes
  923:  * or fails.  Interrupts must be enabled, returns nonzero on error.
  924:  */
  925: static int
  926: amr_wait_command(struct amr_command *ac)
  927: {
  928:     int			error, count;
  929:     
  930:     debug_called(1);
  931: 
  932:     ac->ac_complete = NULL;
  933:     ac->ac_flags |= AMR_CMD_SLEEP;
  934:     if ((error = amr_start(ac)) != 0)
  935: 	return(error);
  936:     
  937:     count = 0;
  938:     /* XXX better timeout? */
  939:     while ((ac->ac_flags & AMR_CMD_BUSY) && (count < 30)) {
  940: 	tsleep(ac, PCATCH, "amrwcmd", hz);
  941:     }
  942:     return(0);
  943: }
  944: 
  945: /********************************************************************************
  946:  * Take a command, submit it to the controller and busy-wait for it to return.
  947:  * Returns nonzero on error.  Can be safely called with interrupts enabled.
  948:  */
  949: static int
  950: amr_std_poll_command(struct amr_command *ac)
  951: {
  952:     struct amr_softc	*sc = ac->ac_sc;
  953:     int			error, count;
  954: 
  955:     debug_called(2);
  956: 
  957:     ac->ac_complete = NULL;
  958:     if ((error = amr_start(ac)) != 0)
  959: 	return(error);
  960: 
  961:     count = 0;
  962:     do {
  963: 	/* 
  964: 	 * Poll for completion, although the interrupt handler may beat us to it. 
  965: 	 * Note that the timeout here is somewhat arbitrary.
  966: 	 */
  967: 	amr_done(sc);
  968: 	DELAY(1000);
  969:     } while ((ac->ac_flags & AMR_CMD_BUSY) && (count++ < 1000));
  970:     if (!(ac->ac_flags & AMR_CMD_BUSY)) {
  971: 	error = 0;
  972:     } else {
  973: 	/* XXX the slot is now marked permanently busy */
  974: 	error = EIO;
  975: 	device_printf(sc->amr_dev, "polled command timeout\n");
  976:     }
  977:     return(error);
  978: }
  979: 
  980: /********************************************************************************
  981:  * Take a command, submit it to the controller and busy-wait for it to return.
  982:  * Returns nonzero on error.  Can be safely called with interrupts enabled.
  983:  */
  984: static int
  985: amr_quartz_poll_command(struct amr_command *ac)
  986: {
  987:     struct amr_softc	*sc = ac->ac_sc;
  988:     int			s;
  989:     int			error,count;
  990: 
  991:     debug_called(2);
  992: 
  993:     /* now we have a slot, we can map the command (unmapped in amr_complete) */
  994:     amr_mapcmd(ac);
  995: 
  996:     s = splbio();
  997: 
  998:     if (sc->amr_state & AMR_STATE_INTEN) {
  999: 	    count=0;
 1000: 	    while (sc->amr_busyslots) {
 1001: 		    tsleep(sc, PCATCH, "amrpoll", hz);
 1002: 		    if(count++>10) {
 1003: 			    break;
 1004: 		    }
 1005: 	    }
 1006: 	    
 1007: 	    if(sc->amr_busyslots) {
 1008: 		    device_printf(sc->amr_dev, "adapter is busy\n");
 1009: 		    splx(s);
 1010: 		    amr_unmapcmd(ac);
 1011: 		    ac->ac_status=0;
 1012: 		    return(1);
 1013: 	    }
 1014:     }
 1015: 
 1016:     bcopy(&ac->ac_mailbox, (void *)(uintptr_t)(volatile void *)sc->amr_mailbox, AMR_MBOX_CMDSIZE);
 1017: 
 1018:     /* clear the poll/ack fields in the mailbox */
 1019:     sc->amr_mailbox->mb_ident = 0xFE;
 1020:     sc->amr_mailbox->mb_nstatus = 0xFF;
 1021:     sc->amr_mailbox->mb_status = 0xFF;
 1022:     sc->amr_mailbox->mb_poll = 0;
 1023:     sc->amr_mailbox->mb_ack = 0;
 1024:     sc->amr_mailbox->mb_busy = 1;
 1025: 
 1026:     AMR_QPUT_IDB(sc, sc->amr_mailboxphys | AMR_QIDB_SUBMIT);
 1027: 
 1028:     while(sc->amr_mailbox->mb_nstatus == 0xFF);
 1029:     while(sc->amr_mailbox->mb_status == 0xFF);
 1030:     ac->ac_status=sc->amr_mailbox->mb_status;
 1031:     error = (ac->ac_status !=AMR_STATUS_SUCCESS) ? 1:0;
 1032:     while(sc->amr_mailbox->mb_poll != 0x77);
 1033:     sc->amr_mailbox->mb_poll = 0;
 1034:     sc->amr_mailbox->mb_ack = 0x77;
 1035: 
 1036:     /* acknowledge that we have the commands */
 1037:     AMR_QPUT_IDB(sc, sc->amr_mailboxphys | AMR_QIDB_ACK);
 1038:     while(AMR_QGET_IDB(sc) & AMR_QIDB_ACK);
 1039: 
 1040:     splx(s);
 1041: 
 1042:     /* unmap the command's data buffer */
 1043:     amr_unmapcmd(ac);
 1044: 
 1045:     return(error);
 1046: }
 1047: 
 1048: /********************************************************************************
 1049:  * Get a free command slot for a command if it doesn't already have one.
 1050:  *
 1051:  * May be safely called multiple times for a given command.
 1052:  */
 1053: static int
 1054: amr_getslot(struct amr_command *ac)
 1055: {
 1056:     struct amr_softc	*sc = ac->ac_sc;
 1057:     int			s, slot, limit, error;
 1058: 
 1059:     debug_called(3);
 1060: 
 1061:     /* if the command already has a slot, don't try to give it another one */
 1062:     if (ac->ac_slot != 0)
 1063: 	return(0);
 1064: 
 1065:     /* enforce slot usage limit */
 1066:     limit = (ac->ac_flags & AMR_CMD_PRIORITY) ? sc->amr_maxio : sc->amr_maxio - 4;
 1067:     if (sc->amr_busyslots > limit)
 1068: 	return(EBUSY);
 1069:     
 1070:     /*
 1071:      * Allocate a slot.  XXX linear scan is slow
 1072:      */
 1073:     error = EBUSY;
 1074:     s = splbio();
 1075:     for (slot = 0; slot < sc->amr_maxio; slot++) {
 1076: 	if (sc->amr_busycmd[slot] == NULL) {
 1077: 	    sc->amr_busycmd[slot] = ac;
 1078: 	    sc->amr_busyslots++;
 1079: 	    ac->ac_slot = slot;
 1080: 	    error = 0;
 1081: 	    break;
 1082: 	}
 1083:     }
 1084:     splx(s);
 1085: 
 1086:     return(error);
 1087: }
 1088: 
 1089: /********************************************************************************
 1090:  * Map/unmap (ac)'s data in the controller's addressable space as required.
 1091:  *
 1092:  * These functions may be safely called multiple times on a given command.
 1093:  */
 1094: static void
 1095: amr_setup_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
 1096: {
 1097:     struct amr_command	*ac = (struct amr_command *)arg;
 1098:     struct amr_softc	*sc = ac->ac_sc;
 1099:     struct amr_sgentry	*sg;
 1100:     int			i;
 1101:     u_int8_t		*sgc;
 1102: 
 1103:     debug_called(3);
 1104: 
 1105:     /* get base address of s/g table */
 1106:     sg = sc->amr_sgtable + (ac->ac_slot * AMR_NSEG);
 1107: 
 1108:     /* save data physical address */
 1109:     ac->ac_dataphys = segs[0].ds_addr;
 1110: 
 1111:     /* for AMR_CMD_CONFIG the s/g count goes elsewhere */
 1112:     if (ac->ac_mailbox.mb_command == AMR_CMD_CONFIG) {
 1113: 	sgc = &(((struct amr_mailbox_ioctl *)&ac->ac_mailbox)->mb_param);
 1114:     } else {
 1115: 	sgc = &ac->ac_mailbox.mb_nsgelem;
 1116:     }
 1117: 
 1118:     /* decide whether we need to populate the s/g table */
 1119:     if (nsegments < 2) {
 1120: 	*sgc = 0;
 1121: 	ac->ac_mailbox.mb_nsgelem = 0;
 1122: 	ac->ac_mailbox.mb_physaddr = ac->ac_dataphys;
 1123:     } else {
 1124:         ac->ac_mailbox.mb_nsgelem = nsegments;
 1125: 	*sgc = nsegments;
 1126: 	ac->ac_mailbox.mb_physaddr = sc->amr_sgbusaddr + (ac->ac_slot * AMR_NSEG * sizeof(struct amr_sgentry));
 1127: 	for (i = 0; i < nsegments; i++, sg++) {
 1128: 	    sg->sg_addr = segs[i].ds_addr;
 1129: 	    sg->sg_count = segs[i].ds_len;
 1130: 	}
 1131:     }
 1132: }
 1133: 
 1134: static void
 1135: amr_setup_ccbmap(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
 1136: {
 1137:     struct amr_command          *ac = (struct amr_command *)arg;
 1138:     struct amr_softc            *sc = ac->ac_sc;
 1139:     struct amr_sgentry          *sg;
 1140:     struct amr_passthrough      *ap = (struct amr_passthrough *)ac->ac_data;
 1141:     struct amr_ext_passthrough	*aep = (struct amr_ext_passthrough *)ac->ac_data;
 1142:     int                         i;
 1143: 
 1144:     /* get base address of s/g table */
 1145:     sg = sc->amr_sgtable + (ac->ac_slot * AMR_NSEG);
 1146: 
 1147:     /* decide whether we need to populate the s/g table */
 1148:     if( ac->ac_mailbox.mb_command == AMR_CMD_EXTPASS ) {
 1149: 	if (nsegments < 2) {
 1150: 	    aep->ap_no_sg_elements = 0;
 1151: 	    aep->ap_data_transfer_address =  segs[0].ds_addr;
 1152: 	} else {
 1153: 	    /* save s/g table information in passthrough */
 1154: 	    aep->ap_no_sg_elements = nsegments;
 1155: 	    aep->ap_data_transfer_address = sc->amr_sgbusaddr + (ac->ac_slot * AMR_NSEG * sizeof(struct amr_sgentry));
 1156: 	    /* populate s/g table (overwrites previous call which mapped the passthrough) */
 1157: 	    for (i = 0; i < nsegments; i++, sg++) {
 1158: 		sg->sg_addr = segs[i].ds_addr;
 1159: 		sg->sg_count = segs[i].ds_len;
 1160: 		debug(3, " %d: 0x%x/%d", i, sg->sg_addr, sg->sg_count);
 1161: 	    }
 1162: 	}
 1163: 	debug(3, "slot %d  %d segments at 0x%x, passthrough at 0x%x", ac->ac_slot,
 1164: 	    aep->ap_no_sg_elements, aep->ap_data_transfer_address, ac->ac_dataphys);
 1165:     } else {
 1166: 	if (nsegments < 2) {
 1167: 	    ap->ap_no_sg_elements = 0;
 1168: 	    ap->ap_data_transfer_address =  segs[0].ds_addr;
 1169: 	} else {
 1170: 	    /* save s/g table information in passthrough */
 1171: 	    ap->ap_no_sg_elements = nsegments;
 1172: 	    ap->ap_data_transfer_address = sc->amr_sgbusaddr + (ac->ac_slot * AMR_NSEG * sizeof(struct amr_sgentry));
 1173: 	    /* populate s/g table (overwrites previous call which mapped the passthrough) */
 1174: 	    for (i = 0; i < nsegments; i++, sg++) {
 1175: 		sg->sg_addr = segs[i].ds_addr;
 1176: 		sg->sg_count = segs[i].ds_len;
 1177: 		debug(3, " %d: 0x%x/%d", i, sg->sg_addr, sg->sg_count);
 1178: 	    }
 1179: 	}
 1180: 	debug(3, "slot %d  %d segments at 0x%x, passthrough at 0x%x", ac->ac_slot,
 1181: 	    ap->ap_no_sg_elements, ap->ap_data_transfer_address, ac->ac_dataphys);
 1182:     }
 1183: }
 1184: 
 1185: static void
 1186: amr_mapcmd(struct amr_command *ac)
 1187: {
 1188:     struct amr_softc	*sc = ac->ac_sc;
 1189: 
 1190:     debug_called(3);
 1191: 
 1192:     /* if the command involves data at all, and hasn't been mapped */
 1193:     if (!(ac->ac_flags & AMR_CMD_MAPPED)) {
 1194: 
 1195: 	if (ac->ac_data != NULL) {
 1196: 	    /* map the data buffers into bus space and build the s/g list */
 1197: 	    bus_dmamap_load(sc->amr_buffer_dmat, ac->ac_dmamap, ac->ac_data, ac->ac_length,
 1198: 			    amr_setup_dmamap, ac, 0);
 1199: 	    if (ac->ac_flags & AMR_CMD_DATAIN)
 1200: 		bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_dmamap, BUS_DMASYNC_PREREAD);
 1201: 	    if (ac->ac_flags & AMR_CMD_DATAOUT)
 1202: 		bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_dmamap, BUS_DMASYNC_PREWRITE);
 1203: 	}
 1204: 
 1205: 	if (ac->ac_ccb_data != NULL) {
 1206: 	    bus_dmamap_load(sc->amr_buffer_dmat, ac->ac_ccb_dmamap, ac->ac_ccb_data, ac->ac_ccb_length,
 1207: 			    amr_setup_ccbmap, ac, 0);
 1208: 	    if (ac->ac_flags & AMR_CMD_CCB_DATAIN)
 1209: 		bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_ccb_dmamap, BUS_DMASYNC_PREREAD);
 1210: 	    if (ac->ac_flags & AMR_CMD_CCB_DATAOUT)
 1211: 		bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_ccb_dmamap, BUS_DMASYNC_PREWRITE);
 1212: 	}
 1213: 	ac->ac_flags |= AMR_CMD_MAPPED;
 1214:     }
 1215: }
 1216: 
 1217: static void
 1218: amr_unmapcmd(struct amr_command *ac)
 1219: {
 1220:     struct amr_softc	*sc = ac->ac_sc;
 1221: 
 1222:     debug_called(3);
 1223: 
 1224:     /* if the command involved data at all and was mapped */
 1225:     if (ac->ac_flags & AMR_CMD_MAPPED) {
 1226: 
 1227: 	if (ac->ac_data != NULL) {
 1228: 	    if (ac->ac_flags & AMR_CMD_DATAIN)
 1229: 		bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_dmamap, BUS_DMASYNC_POSTREAD);
 1230: 	    if (ac->ac_flags & AMR_CMD_DATAOUT)
 1231: 		bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_dmamap, BUS_DMASYNC_POSTWRITE);
 1232: 	    bus_dmamap_unload(sc->amr_buffer_dmat, ac->ac_dmamap);
 1233: 	}
 1234: 
 1235: 	if (ac->ac_ccb_data != NULL) {
 1236: 	    if (ac->ac_flags & AMR_CMD_CCB_DATAIN)
 1237: 		bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_ccb_dmamap, BUS_DMASYNC_POSTREAD);
 1238: 	    if (ac->ac_flags & AMR_CMD_CCB_DATAOUT)
 1239: 		bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_ccb_dmamap, BUS_DMASYNC_POSTWRITE);
 1240: 	    bus_dmamap_unload(sc->amr_buffer_dmat, ac->ac_ccb_dmamap);
 1241: 	}
 1242: 	ac->ac_flags &= ~AMR_CMD_MAPPED;
 1243:     }
 1244: }
 1245: 
 1246: /********************************************************************************
 1247:  * Take a command and give it to the controller, returns 0 if successful, or
 1248:  * EBUSY if the command should be retried later.
 1249:  */
 1250: static int
 1251: amr_start(struct amr_command *ac)
 1252: {
 1253:     struct amr_softc	*sc = ac->ac_sc;
 1254:     int			done, s, i;
 1255: 
 1256:     debug_called(3);
 1257: 
 1258:     /* mark command as busy so that polling consumer can tell */
 1259:     ac->ac_flags |= AMR_CMD_BUSY;
 1260: 
 1261:     /* get a command slot (freed in amr_done) */
 1262:     if (amr_getslot(ac))
 1263: 	return(EBUSY);
 1264: 
 1265:     /* now we have a slot, we can map the command (unmapped in amr_complete) */
 1266:     amr_mapcmd(ac);
 1267: 
 1268:     /* mark the new mailbox we are going to copy in as busy */
 1269:     ac->ac_mailbox.mb_busy = 1;
 1270: 
 1271:     /* clear the poll/ack fields in the mailbox */
 1272:     sc->amr_mailbox->mb_poll = 0;
 1273:     sc->amr_mailbox->mb_ack = 0;
 1274: 
 1275:     /* 
 1276:      * Save the slot number so that we can locate this command when complete.
 1277:      * Note that ident = 0 seems to be special, so we don't use it.
 1278:      */
 1279:     ac->ac_mailbox.mb_ident = ac->ac_slot + 1;
 1280: 
 1281:     /* 
 1282:      * Spin waiting for the mailbox, give up after ~1 second.  We expect the
 1283:      * controller to be able to handle our I/O.
 1284:      *
 1285:      * XXX perhaps we should wait for less time, and count on the deferred command
 1286:      * handling to deal with retries?
 1287:      */
 1288:     debug(4, "wait for mailbox");
 1289:     for (i = 10000, done = 0; (i > 0) && !done; i--) {
 1290: 	s = splbio();
 1291: 	
 1292: 	/* is the mailbox free? */
 1293: 	if (sc->amr_mailbox->mb_busy == 0) {
 1294: 	    debug(4, "got mailbox");
 1295: 	    sc->amr_mailbox64->mb64_segment = 0;
 1296: 	    bcopy(&ac->ac_mailbox, (void *)(uintptr_t)(volatile void *)sc->amr_mailbox, AMR_MBOX_CMDSIZE);
 1297: 	    done = 1;
 1298: 
 1299: 	    /* not free, spin waiting */
 1300: 	} else {
 1301: 	    debug(4, "busy flag %x\n", sc->amr_mailbox->mb_busy);
 1302: 	    /* this is somewhat ugly */
 1303: 	    DELAY(100);
 1304: 	}
 1305: 	splx(s);	/* drop spl to allow completion interrupts */
 1306:     }
 1307: 
 1308:     /*
 1309:      * Now give the command to the controller
 1310:      */
 1311:     if (done) {
 1312: 	if (sc->amr_submit_command(sc)) {
 1313: 	    /* the controller wasn't ready to take the command, forget that we tried to post it */
 1314: 	    sc->amr_mailbox->mb_busy = 0;
 1315: 	    return(EBUSY);
 1316: 	}
 1317: 	debug(3, "posted command");
 1318: 	return(0);
 1319:     }
 1320:     
 1321:     /*
 1322:      * The controller wouldn't take the command.  Return the command as busy
 1323:      * so that it is retried later.
 1324:      */
 1325:     return(EBUSY);
 1326: }
 1327: 
 1328: /********************************************************************************
 1329:  * Extract one or more completed commands from the controller (sc)
 1330:  *
 1331:  * Returns nonzero if any commands on the work queue were marked as completed.
 1332:  */
 1333: int
 1334: amr_done(struct amr_softc *sc)
 1335: {
 1336:     struct amr_command	*ac;
 1337:     struct amr_mailbox	mbox;
 1338:     int			i, idx, result;
 1339:     
 1340:     debug_called(3);
 1341: 
 1342:     /* See if there's anything for us to do */
 1343:     result = 0;
 1344: 
 1345:     /* loop collecting completed commands */
 1346:     for (;;) {
 1347: 	/* poll for a completed command's identifier and status */
 1348: 	if (sc->amr_get_work(sc, &mbox)) {
 1349: 	    result = 1;
 1350: 	    
 1351: 	    /* iterate over completed commands in this result */
 1352: 	    for (i = 0; i < mbox.mb_nstatus; i++) {
 1353: 		/* get pointer to busy command */
 1354: 		idx = mbox.mb_completed[i] - 1;
 1355: 		ac = sc->amr_busycmd[idx];
 1356: 
 1357: 		/* really a busy command? */
 1358: 		if (ac != NULL) {
 1359: 
 1360: 		    /* pull the command from the busy index */
 1361: 		    sc->amr_busycmd[idx] = NULL;
 1362: 		    sc->amr_busyslots--;
 1363: 		
 1364: 		    /* save status for later use */
 1365: 		    ac->ac_status = mbox.mb_status;
 1366: 		    amr_enqueue_completed(ac);
 1367: 		    debug(3, "completed command with status %x", mbox.mb_status);
 1368: 		} else {
 1369: 		    device_printf(sc->amr_dev, "bad slot %d completed\n", idx);
 1370: 		}
 1371: 	    }
 1372: 	} else {
 1373: 	    break;	/* no work */
 1374: 	}
 1375:     }
 1376:     
 1377:     /* if we've completed any commands, try posting some more */
 1378:     if (result)
 1379: 	amr_startio(sc);
 1380:     
 1381:     /* handle completion and timeouts */
 1382: #if defined(__FreeBSD__) && __FreeBSD_version >= 500005
 1383:     if (sc->amr_state & AMR_STATE_INTEN) 
 1384: 	taskqueue_enqueue(taskqueue_swi, &sc->amr_task_complete);
 1385:     else
 1386: #endif
 1387: 	amr_complete(sc, 0);
 1388:     
 1389:     return(result);
 1390: }
 1391: 
 1392: /********************************************************************************
 1393:  * Do completion processing on done commands on (sc)
 1394:  */
 1395: static void
 1396: amr_complete(void *context, int pending)
 1397: {
 1398:     struct amr_softc	*sc = (struct amr_softc *)context;
 1399:     struct amr_command	*ac;
 1400: 
 1401:     debug_called(3);
 1402: 
 1403:     /* pull completed commands off the queue */
 1404:     for (;;) {
 1405: 	ac = amr_dequeue_completed(sc);
 1406: 	if (ac == NULL)
 1407: 	    break;
 1408: 
 1409: 	/* unmap the command's data buffer */
 1410: 	amr_unmapcmd(ac);
 1411: 
 1412: 	/* unbusy the command */
 1413: 	ac->ac_flags &= ~AMR_CMD_BUSY;
 1414: 	    
 1415: 	/* 
 1416: 	 * Is there a completion handler? 
 1417: 	 */
 1418: 	if (ac->ac_complete != NULL) {
 1419: 	    ac->ac_complete(ac);
 1420: 	    
 1421: 	    /* 
 1422: 	     * Is someone sleeping on this one?
 1423: 	     */
 1424: 	} else if (ac->ac_flags & AMR_CMD_SLEEP) {
 1425: 	    wakeup(ac);
 1426: 	}
 1427: 
 1428: 	if(!sc->amr_busyslots) {
 1429: 	    wakeup(sc);
 1430: 	}
 1431:     }
 1432: }
 1433: 
 1434: /********************************************************************************
 1435:  ********************************************************************************
 1436:                                                         Command Buffer Management
 1437:  ********************************************************************************
 1438:  ********************************************************************************/
 1439: 
 1440: /********************************************************************************
 1441:  * Get a new command buffer.
 1442:  *
 1443:  * This may return NULL in low-memory cases.
 1444:  *
 1445:  * If possible, we recycle a command buffer that's been used before.
 1446:  */
 1447: struct amr_command *
 1448: amr_alloccmd(struct amr_softc *sc)
 1449: {
 1450:     struct amr_command	*ac;
 1451: 
 1452:     debug_called(3);
 1453: 
 1454:     ac = amr_dequeue_free(sc);
 1455:     if (ac == NULL) {
 1456: 	amr_alloccmd_cluster(sc);
 1457: 	ac = amr_dequeue_free(sc);
 1458:     }
 1459:     if (ac == NULL)
 1460: 	return(NULL);
 1461: 
 1462:     /* clear out significant fields */
 1463:     ac->ac_slot = 0;
 1464:     ac->ac_status = 0;
 1465:     bzero(&ac->ac_mailbox, sizeof(struct amr_mailbox));
 1466:     ac->ac_flags = 0;
 1467:     ac->ac_bio = NULL;
 1468:     ac->ac_data = NULL;
 1469:     ac->ac_ccb_data = NULL;
 1470:     ac->ac_complete = NULL;
 1471:     return(ac);
 1472: }
 1473: 
 1474: /********************************************************************************
 1475:  * Release a command buffer for recycling.
 1476:  */
 1477: void
 1478: amr_releasecmd(struct amr_command *ac)
 1479: {
 1480:     debug_called(3);
 1481: 
 1482:     amr_enqueue_free(ac);
 1483: }
 1484: 
 1485: /********************************************************************************
 1486:  * Allocate a new command cluster and initialise it.
 1487:  */
 1488: static void
 1489: amr_alloccmd_cluster(struct amr_softc *sc)
 1490: {
 1491:     struct amr_command_cluster	*acc;
 1492:     struct amr_command		*ac;
 1493:     int				s, i;
 1494: 
 1495:     acc = malloc(AMR_CMD_CLUSTERSIZE, M_DEVBUF, M_NOWAIT);
 1496:     if (acc != NULL) {
 1497: 	s = splbio();
 1498: 	TAILQ_INSERT_TAIL(&sc->amr_cmd_clusters, acc, acc_link);
 1499: 	splx(s);
 1500: 	for (i = 0; i < AMR_CMD_CLUSTERCOUNT; i++) {
 1501: 	    ac = &acc->acc_command[i];
 1502: 	    bzero(ac, sizeof(*ac));
 1503: 	    ac->ac_sc = sc;
 1504: 	    if (!bus_dmamap_create(sc->amr_buffer_dmat, 0, &ac->ac_dmamap) &&
 1505: 		!bus_dmamap_create(sc->amr_buffer_dmat, 0, &ac->ac_ccb_dmamap))
 1506: 		amr_releasecmd(ac);
 1507: 	}
 1508:     }
 1509: }
 1510: 
 1511: /********************************************************************************
 1512:  * Free a command cluster
 1513:  */
 1514: static void
 1515: amr_freecmd_cluster(struct amr_command_cluster *acc)
 1516: {
 1517:     struct amr_softc	*sc = acc->acc_command[0].ac_sc;
 1518:     int			i;
 1519: 
 1520:     for (i = 0; i < AMR_CMD_CLUSTERCOUNT; i++)
 1521: 	bus_dmamap_destroy(sc->amr_buffer_dmat, acc->acc_command[i].ac_dmamap);
 1522:     free(acc, M_DEVBUF);
 1523: }
 1524: 
 1525: /********************************************************************************
 1526:  ********************************************************************************
 1527:                                                          Interface-specific Shims
 1528:  ********************************************************************************
 1529:  ********************************************************************************/
 1530: 
 1531: /********************************************************************************
 1532:  * Tell the controller that the mailbox contains a valid command
 1533:  */
 1534: static int
 1535: amr_quartz_submit_command(struct amr_softc *sc)
 1536: {
 1537:     debug_called(3);
 1538: 
 1539:     if (AMR_QGET_IDB(sc) & AMR_QIDB_SUBMIT)
 1540: 	return(EBUSY);
 1541:     AMR_QPUT_IDB(sc, sc->amr_mailboxphys | AMR_QIDB_SUBMIT);
 1542:     return(0);
 1543: }
 1544: 
 1545: static int
 1546: amr_std_submit_command(struct amr_softc *sc)
 1547: {
 1548:     debug_called(3);
 1549: 
 1550:     if (AMR_SGET_MBSTAT(sc) & AMR_SMBOX_BUSYFLAG)
 1551: 	return(EBUSY);
 1552:     AMR_SPOST_COMMAND(sc);
 1553:     return(0);
 1554: }
 1555: 
 1556: /********************************************************************************
 1557:  * Claim any work that the controller has completed; acknowledge completion,
 1558:  * save details of the completion in (mbsave)
 1559:  */
 1560: static int
 1561: amr_quartz_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave)
 1562: {
 1563:     int		s, worked;
 1564:     u_int32_t	outd;
 1565: 
 1566:     debug_called(3);
 1567: 
 1568:     worked = 0;
 1569:     s = splbio();
 1570: 
 1571:     /* work waiting for us? */
 1572:     if ((outd = AMR_QGET_ODB(sc)) == AMR_QODB_READY) {
 1573: 
 1574: 	/* save mailbox, which contains a list of completed commands */
 1575: 	bcopy((void *)(uintptr_t)(volatile void *)sc->amr_mailbox, mbsave, sizeof(*mbsave));
 1576: 
 1577: 	/* acknowledge interrupt */
 1578: 	AMR_QPUT_ODB(sc, AMR_QODB_READY);
 1579: 
 1580: 	/* acknowledge that we have the commands */
 1581: 	AMR_QPUT_IDB(sc, sc->amr_mailboxphys | AMR_QIDB_ACK);
 1582: 
 1583: #ifndef AMR_QUARTZ_GOFASTER
 1584: 	/*
 1585: 	 * This waits for the controller to notice that we've taken the
 1586: 	 * command from it.  It's very inefficient, and we shouldn't do it,
 1587: 	 * but if we remove this code, we stop completing commands under
 1588: 	 * load.
 1589: 	 *
 1590: 	 * Peter J says we shouldn't do this.  The documentation says we
 1591: 	 * should.  Who is right?
 1592: 	 */
 1593: 	while(AMR_QGET_IDB(sc) & AMR_QIDB_ACK)
 1594: 	    ;				/* XXX aiee! what if it dies? */
 1595: #endif
 1596: 
 1597: 	worked = 1;			/* got some work */
 1598:     }
 1599: 
 1600:     splx(s);
 1601:     return(worked);
 1602: }
 1603: 
 1604: static int
 1605: amr_std_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave)
 1606: {
 1607:     int		s, worked;
 1608:     u_int8_t	istat;
 1609: 
 1610:     debug_called(3);
 1611: 
 1612:     worked = 0;
 1613:     s = splbio();
 1614: 
 1615:     /* check for valid interrupt status */
 1616:     istat = AMR_SGET_ISTAT(sc);
 1617:     if ((istat & AMR_SINTR_VALID) != 0) {
 1618: 	AMR_SPUT_ISTAT(sc, istat);	/* ack interrupt status */
 1619: 
 1620: 	/* save mailbox, which contains a list of completed commands */
 1621: 	bcopy((void *)(uintptr_t)(volatile void *)sc->amr_mailbox, mbsave, sizeof(*mbsave));
 1622: 
 1623: 	AMR_SACK_INTERRUPT(sc);		/* acknowledge we have the mailbox */
 1624: 	worked = 1;
 1625:     }
 1626: 
 1627:     splx(s);
 1628:     return(worked);
 1629: }
 1630: 
 1631: /********************************************************************************
 1632:  * Notify the controller of the mailbox location.
 1633:  */
 1634: static void
 1635: amr_std_attach_mailbox(struct amr_softc *sc)
 1636: {
 1637: 
 1638:     /* program the mailbox physical address */
 1639:     AMR_SBYTE_SET(sc, AMR_SMBOX_0, sc->amr_mailboxphys         & 0xff);
 1640:     AMR_SBYTE_SET(sc, AMR_SMBOX_1, (sc->amr_mailboxphys >>  8) & 0xff);
 1641:     AMR_SBYTE_SET(sc, AMR_SMBOX_2, (sc->amr_mailboxphys >> 16) & 0xff);
 1642:     AMR_SBYTE_SET(sc, AMR_SMBOX_3, (sc->amr_mailboxphys >> 24) & 0xff);
 1643:     AMR_SBYTE_SET(sc, AMR_SMBOX_ENABLE, AMR_SMBOX_ADDR);
 1644: 
 1645:     /* clear any outstanding interrupt and enable interrupts proper */
 1646:     AMR_SACK_INTERRUPT(sc);
 1647:     AMR_SENABLE_INTR(sc);
 1648: }
 1649: 
 1650: #ifdef AMR_BOARD_INIT
 1651: /********************************************************************************
 1652:  * Initialise the controller
 1653:  */
 1654: static int
 1655: amr_quartz_init(struct amr_softc *sc)
 1656: {
 1657:     int		status, ostatus;
 1658: 
 1659:     device_printf(sc->amr_dev, "initial init status %x\n", AMR_QGET_INITSTATUS(sc));
 1660: 
 1661:     AMR_QRESET(sc);
 1662: 
 1663:     ostatus = 0xff;
 1664:     while ((status = AMR_QGET_INITSTATUS(sc)) != AMR_QINIT_DONE) {
 1665: 	if (status != ostatus) {
 1666: 	    device_printf(sc->amr_dev, "(%x) %s\n", status, amr_describe_code(amr_table_qinit, status));
 1667: 	    ostatus = status;
 1668: 	}
 1669: 	switch (status) {
 1670: 	case AMR_QINIT_NOMEM:
 1671: 	    return(ENOMEM);
 1672: 
 1673: 	case AMR_QINIT_SCAN:
 1674: 	    /* XXX we could print channel/target here */
 1675: 	    break;
 1676: 	}
 1677:     }
 1678:     return(0);
 1679: }
 1680: 
 1681: static int
 1682: amr_std_init(struct amr_softc *sc)
 1683: {
 1684:     int		status, ostatus;
 1685: 
 1686:     device_printf(sc->amr_dev, "initial init status %x\n", AMR_SGET_INITSTATUS(sc));
 1687: 
 1688:     AMR_SRESET(sc);
 1689:  
 1690:     ostatus = 0xff;
 1691:     while ((status = AMR_SGET_INITSTATUS(sc)) != AMR_SINIT_DONE) {
 1692: 	if (status != ostatus) {
 1693: 	    device_printf(sc->amr_dev, "(%x) %s\n", status, amr_describe_code(amr_table_sinit, status));
 1694: 	    ostatus = status;
 1695: 	}
 1696: 	switch (status) {
 1697: 	case AMR_SINIT_NOMEM:
 1698: 	    return(ENOMEM);
 1699: 
 1700: 	case AMR_SINIT_INPROG:
 1701: 	    /* XXX we could print channel/target here? */
 1702: 	    break;
 1703: 	}
 1704:     }
 1705:     return(0);
 1706: }
 1707: #endif
 1708: 
 1709: /********************************************************************************
 1710:  ********************************************************************************
 1711:                                                                         Debugging
 1712:  ********************************************************************************
 1713:  ********************************************************************************/
 1714: 
 1715: /********************************************************************************
 1716:  * Identify the controller and print some information about it.
 1717:  */
 1718: static void
 1719: amr_describe_controller(struct amr_softc *sc)
 1720: {
 1721:     struct amr_prodinfo	*ap;
 1722:     struct amr_enquiry	*ae;
 1723:     char		*prod;
 1724: 
 1725:     /*
 1726:      * Try to get 40LD product info, which tells us what the card is labelled as.
 1727:      */
 1728:     if ((ap = amr_enquiry(sc, 2048, AMR_CMD_CONFIG, AMR_CONFIG_PRODUCT_INFO, 0)) != NULL) {
 1729: 	device_printf(sc->amr_dev, "<LSILogic %.80s> Firmware %.16s, BIOS %.16s, %dMB RAM\n",
 1730: 		      ap->ap_product, ap->ap_firmware, ap->ap_bios,
 1731: 		      ap->ap_memsize);
 1732: 
 1733: 	free(ap, M_DEVBUF);
 1734: 	return;
 1735:     }
 1736: 
 1737:     /*
 1738:      * Try 8LD extended ENQUIRY to get controller signature, and use lookup table.
 1739:      */
 1740:     if ((ae = (struct amr_enquiry *)amr_enquiry(sc, 2048, AMR_CMD_EXT_ENQUIRY2, 0, 0)) != NULL) {
 1741: 	prod = amr_describe_code(amr_table_adaptertype, ae->ae_signature);
 1742: 
 1743:     } else if ((ae = (struct amr_enquiry *)amr_enquiry(sc, 2048, AMR_CMD_ENQUIRY, 0, 0)) != NULL) {
 1744: 
 1745: 	/*
 1746: 	 * Try to work it out based on the PCI signatures.
 1747: 	 */
 1748: 	switch (pci_get_device(sc->amr_dev)) {
 1749: 	case 0x9010:
 1750: 	    prod = "Series 428";
 1751: 	    break;
 1752: 	case 0x9060:
 1753: 	    prod = "Series 434";
 1754: 	    break;
 1755: 	default:
 1756: 	    prod = "unknown controller";
 1757: 	    break;
 1758: 	}
 1759:     } else {
 1760: 	prod = "unsupported controller";
 1761:     }
 1762: 
 1763:     /*
 1764:      * HP NetRaid controllers have a special encoding of the firmware and
 1765:      * BIOS versions. The AMI version seems to have it as strings whereas
 1766:      * the HP version does it with a leading uppercase character and two
 1767:      * binary numbers.
 1768:      */
 1769:      
 1770:     if(ae->ae_adapter.aa_firmware[2] >= 'A' &&
 1771:        ae->ae_adapter.aa_firmware[2] <= 'Z' &&
 1772:        ae->ae_adapter.aa_firmware[1] <  ' ' &&
 1773:        ae->ae_adapter.aa_firmware[0] <  ' ' &&
 1774:        ae->ae_adapter.aa_bios[2] >= 'A'     &&
 1775:        ae->ae_adapter.aa_bios[2] <= 'Z'     &&
 1776:        ae->ae_adapter.aa_bios[1] <  ' '     &&
 1777:        ae->ae_adapter.aa_bios[0] <  ' ') {
 1778: 
 1779: 	/* this looks like we have an HP NetRaid version of the MegaRaid */
 1780: 
 1781:     	if(ae->ae_signature == AMR_SIG_438) {
 1782:     		/* the AMI 438 is a NetRaid 3si in HP-land */
 1783:     		prod = "HP NetRaid 3si";
 1784:     	}
 1785:     	
 1786: 	device_printf(sc->amr_dev, "<%s> Firmware %c.%02d.%02d, BIOS %c.%02d.%02d, %dMB RAM\n",
 1787: 		      prod, ae->ae_adapter.aa_firmware[2],
 1788: 		      ae->ae_adapter.aa_firmware[1],
 1789: 		      ae->ae_adapter.aa_firmware[0],
 1790: 		      ae->ae_adapter.aa_bios[2],
 1791: 		      ae->ae_adapter.aa_bios[1],
 1792: 		      ae->ae_adapter.aa_bios[0],
 1793: 		      ae->ae_adapter.aa_memorysize);		
 1794:     } else {
 1795: 	device_printf(sc->amr_dev, "<%s> Firmware %.4s, BIOS %.4s, %dMB RAM\n", 
 1796: 		      prod, ae->ae_adapter.aa_firmware, ae->ae_adapter.aa_bios,
 1797: 		      ae->ae_adapter.aa_memorysize);
 1798:     }    	
 1799:     free(ae, M_DEVBUF);
 1800: }
 1801: 
 1802: int
 1803: amr_dump_blocks(struct amr_softc *sc, int unit, u_int32_t lba, void *data, int blks)
 1804: {
 1805: 
 1806:     struct amr_command	*ac;
 1807:     int			error = 1;
 1808: 
 1809:     debug_called(1);
 1810: 
 1811:     sc->amr_state &= ~AMR_STATE_INTEN;
 1812: 
 1813:     /* get ourselves a command buffer */
 1814:     if ((ac = amr_alloccmd(sc)) == NULL)
 1815: 	goto out;
 1816:     /* set command flags */
 1817:     ac->ac_flags |= AMR_CMD_PRIORITY | AMR_CMD_DATAOUT;
 1818:     
 1819:     /* point the command at our data */
 1820:     ac->ac_data = data;
 1821:     ac->ac_length = blks * AMR_BLKSIZE;
 1822:     
 1823:     /* build the command proper */
 1824:     ac->ac_mailbox.mb_command 	= AMR_CMD_LWRITE;
 1825:     ac->ac_mailbox.mb_blkcount	= blks;
 1826:     ac->ac_mailbox.mb_lba	= lba;
 1827:     ac->ac_mailbox.mb_drive	= unit;
 1828:     	
 1829:     /* can't assume that interrupts are going to work here, so play it safe */
 1830:     if (sc->amr_poll_command(ac))
 1831: 	goto out;
 1832:     error = ac->ac_status;
 1833:     
 1834:  out:
 1835:     if (ac != NULL)
 1836: 	amr_releasecmd(ac);
 1837: 
 1838:     sc->amr_state |= AMR_STATE_INTEN;
 1839: 
 1840:     return (error);	
 1841: }
 1842: 
 1843: 
 1844: #ifdef AMR_DEBUG
 1845: /********************************************************************************
 1846:  * Print the command (ac) in human-readable format
 1847:  */
 1848: #if 0
 1849: static void
 1850: amr_printcommand(struct amr_command *ac)
 1851: {
 1852:     struct amr_softc	*sc = ac->ac_sc;
 1853:     struct amr_sgentry	*sg;
 1854:     int			i;
 1855:     
 1856:     device_printf(sc->amr_dev, "cmd %x  ident %d  drive %d\n",
 1857: 		  ac->ac_mailbox.mb_command, ac->ac_mailbox.mb_ident, ac->ac_mailbox.mb_drive);
 1858:     device_printf(sc->amr_dev, "blkcount %d  lba %d\n", 
 1859: 		  ac->ac_mailbox.mb_blkcount, ac->ac_mailbox.mb_lba);
 1860:     device_printf(sc->amr_dev, "virtaddr %p  length %lu\n", ac->ac_data, (unsigned long)ac->ac_length);
 1861:     device_printf(sc->amr_dev, "sg physaddr %08x  nsg %d\n",
 1862: 		  ac->ac_mailbox.mb_physaddr, ac->ac_mailbox.mb_nsgelem);
 1863:     device_printf(sc->amr_dev, "ccb %p  bio %p\n", ac->ac_ccb_data, ac->ac_bio);
 1864: 
 1865:     /* get base address of s/g table */
 1866:     sg = sc->amr_sgtable + (ac->ac_slot * AMR_NSEG);
 1867:     for (i = 0; i < ac->ac_mailbox.mb_nsgelem; i++, sg++)
 1868: 	device_printf(sc->amr_dev, "  %x/%d\n", sg->sg_addr, sg->sg_count);
 1869: }
 1870: #endif
 1871: #endif