File:  [DragonFly] / src / sys / dev / raid / ciss / ciss.c
Revision 1.8: download - view: text, annotated - select for diffs
Wed May 19 22:52:46 2004 UTC (10 years, 5 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) 2001 Michael Smith
    3:  * All rights reserved.
    4:  *
    5:  * Redistribution and use in source and binary forms, with or without
    6:  * modification, are permitted provided that the following conditions
    7:  * are met:
    8:  * 1. Redistributions of source code must retain the above copyright
    9:  *    notice, this list of conditions and the following disclaimer.
   10:  * 2. Redistributions in binary form must reproduce the above copyright
   11:  *    notice, this list of conditions and the following disclaimer in the
   12:  *    documentation and/or other materials provided with the distribution.
   13:  *
   14:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24:  * SUCH DAMAGE.
   25:  *
   26:  *	$FreeBSD: src/sys/dev/ciss/ciss.c,v 1.2.2.6 2003/02/18 22:27:41 ps Exp $
   27:  *	$DragonFly: src/sys/dev/raid/ciss/ciss.c,v 1.8 2004/05/19 22:52:46 dillon Exp $
   28:  */
   29: 
   30: /*
   31:  * Common Interface for SCSI-3 Support driver.
   32:  *
   33:  * CISS claims to provide a common interface between a generic SCSI
   34:  * transport and an intelligent host adapter.
   35:  *
   36:  * This driver supports CISS as defined in the document "CISS Command
   37:  * Interface for SCSI-3 Support Open Specification", Version 1.04,
   38:  * Valence Number 1, dated 20001127, produced by Compaq Computer
   39:  * Corporation.  This document appears to be a hastily and somewhat
   40:  * arbitrarlily cut-down version of a larger (and probably even more
   41:  * chaotic and inconsistent) Compaq internal document.  Various
   42:  * details were also gleaned from Compaq's "cciss" driver for Linux.
   43:  *
   44:  * We provide a shim layer between the CISS interface and CAM,
   45:  * offloading most of the queueing and being-a-disk chores onto CAM.
   46:  * Entry to the driver is via the PCI bus attachment (ciss_probe,
   47:  * ciss_attach, etc) and via the CAM interface (ciss_cam_action,
   48:  * ciss_cam_poll).  The Compaq CISS adapters are, however, poor SCSI
   49:  * citizens and we have to fake up some responses to get reasonable
   50:  * behaviour out of them.  In addition, the CISS command set is by no
   51:  * means adequate to support the functionality of a RAID controller,
   52:  * and thus the supported Compaq adapters utilise portions of the
   53:  * control protocol from earlier Compaq adapter families.
   54:  *
   55:  * Note that we only support the "simple" transport layer over PCI.
   56:  * This interface (ab)uses the I2O register set (specifically the post
   57:  * queues) to exchange commands with the adapter.  Other interfaces
   58:  * are available, but we aren't supposed to know about them, and it is
   59:  * dubious whether they would provide major performance improvements
   60:  * except under extreme load.
   61:  * 
   62:  * Currently the only supported CISS adapters are the Compaq Smart
   63:  * Array 5* series (5300, 5i, 532).  Even with only three adapters,
   64:  * Compaq still manage to have interface variations.
   65:  *
   66:  *
   67:  * Thanks must go to Fred Harris and Darryl DeVinney at Compaq, as
   68:  * well as Paul Saab at Yahoo! for their assistance in making this
   69:  * driver happen.
   70:  */
   71: 
   72: #include <sys/param.h>
   73: #include <sys/systm.h>
   74: #include <sys/malloc.h>
   75: #include <sys/kernel.h>
   76: #include <sys/bus.h>
   77: #include <sys/conf.h>
   78: #include <sys/devicestat.h>
   79: #include <sys/stat.h>
   80: 
   81: #include <bus/cam/cam.h>
   82: #include <bus/cam/cam_ccb.h>
   83: #include <bus/cam/cam_periph.h>
   84: #include <bus/cam/cam_sim.h>
   85: #include <bus/cam/cam_xpt_sim.h>
   86: #include <bus/cam/scsi/scsi_all.h>
   87: #include <bus/cam/scsi/scsi_message.h>
   88: 
   89: #include <machine/clock.h>
   90: #include <machine/bus_memio.h>
   91: #include <machine/bus.h>
   92: #include <machine/endian.h>
   93: #include <machine/resource.h>
   94: #include <sys/rman.h>
   95: 
   96: #include <bus/pci/pcireg.h>
   97: #include <bus/pci/pcivar.h>
   98: 
   99: #include "cissreg.h"
  100: #include "cissvar.h"
  101: #include "cissio.h"
  102: 
  103: MALLOC_DEFINE(CISS_MALLOC_CLASS, "ciss_data", "ciss internal data buffers");
  104: 
  105: /* pci interface */
  106: static int	ciss_lookup(device_t dev);
  107: static int	ciss_probe(device_t dev);
  108: static int	ciss_attach(device_t dev);
  109: static int	ciss_detach(device_t dev);
  110: static int	ciss_shutdown(device_t dev);
  111: 
  112: /* (de)initialisation functions, control wrappers */
  113: static int	ciss_init_pci(struct ciss_softc *sc);
  114: static int	ciss_wait_adapter(struct ciss_softc *sc);
  115: static int	ciss_flush_adapter(struct ciss_softc *sc);
  116: static int	ciss_init_requests(struct ciss_softc *sc);
  117: static void	ciss_command_map_helper(void *arg, bus_dma_segment_t *segs,
  118: 					int nseg, int error);
  119: static int	ciss_identify_adapter(struct ciss_softc *sc);
  120: static int	ciss_init_logical(struct ciss_softc *sc);
  121: static int	ciss_identify_logical(struct ciss_softc *sc, struct ciss_ldrive *ld);
  122: static int	ciss_get_ldrive_status(struct ciss_softc *sc,  struct ciss_ldrive *ld);
  123: static int	ciss_update_config(struct ciss_softc *sc);
  124: static int	ciss_accept_media(struct ciss_softc *sc, int ldrive, int async);
  125: static void	ciss_accept_media_complete(struct ciss_request *cr);
  126: static void	ciss_free(struct ciss_softc *sc);
  127: 
  128: /* request submission/completion */
  129: static int	ciss_start(struct ciss_request *cr);
  130: static void	ciss_done(struct ciss_softc *sc);
  131: static void	ciss_intr(void *arg);
  132: static void	ciss_complete(struct ciss_softc *sc);
  133: static int	ciss_report_request(struct ciss_request *cr, int *command_status,
  134: 				    int *scsi_status);
  135: static int	ciss_synch_request(struct ciss_request *cr, int timeout);
  136: static int	ciss_poll_request(struct ciss_request *cr, int timeout);
  137: static int	ciss_wait_request(struct ciss_request *cr, int timeout);
  138: #if 0
  139: static int	ciss_abort_request(struct ciss_request *cr);
  140: #endif
  141: 
  142: /* request queueing */
  143: static int	ciss_get_request(struct ciss_softc *sc, struct ciss_request **crp);
  144: static void	ciss_preen_command(struct ciss_request *cr);
  145: static void 	ciss_release_request(struct ciss_request *cr);
  146: 
  147: /* request helpers */
  148: static int	ciss_get_bmic_request(struct ciss_softc *sc, struct ciss_request **crp,
  149: 				      int opcode, void **bufp, size_t bufsize);
  150: static int	ciss_user_command(struct ciss_softc *sc, IOCTL_Command_struct *ioc);
  151: 
  152: /* DMA map/unmap */
  153: static int	ciss_map_request(struct ciss_request *cr);
  154: static void	ciss_request_map_helper(void *arg, bus_dma_segment_t *segs,
  155: 					int nseg, int error);
  156: static void	ciss_unmap_request(struct ciss_request *cr);
  157: 
  158: /* CAM interface */
  159: static int	ciss_cam_init(struct ciss_softc *sc);
  160: static void	ciss_cam_rescan_target(struct ciss_softc *sc, int target);
  161: static void	ciss_cam_rescan_all(struct ciss_softc *sc);
  162: static void	ciss_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb);
  163: static void	ciss_cam_action(struct cam_sim *sim, union ccb *ccb);
  164: static int	ciss_cam_action_io(struct cam_sim *sim, struct ccb_scsiio *csio);
  165: static int	ciss_cam_emulate(struct ciss_softc *sc, struct ccb_scsiio *csio);
  166: static void	ciss_cam_poll(struct cam_sim *sim);
  167: static void	ciss_cam_complete(struct ciss_request *cr);
  168: static void	ciss_cam_complete_fixup(struct ciss_softc *sc, struct ccb_scsiio *csio);
  169: static struct cam_periph *ciss_find_periph(struct ciss_softc *sc, int target);
  170: static int	ciss_name_device(struct ciss_softc *sc, int target);
  171: 
  172: /* periodic status monitoring */
  173: static void	ciss_periodic(void *arg);
  174: static void	ciss_notify_event(struct ciss_softc *sc);
  175: static void	ciss_notify_complete(struct ciss_request *cr);
  176: static int	ciss_notify_abort(struct ciss_softc *sc);
  177: static int	ciss_notify_abort_bmic(struct ciss_softc *sc);
  178: static void	ciss_notify_logical(struct ciss_softc *sc, struct ciss_notify *cn);
  179: static void	ciss_notify_physical(struct ciss_softc *sc, struct ciss_notify *cn);
  180: 
  181: /* debugging output */
  182: static void	ciss_print_request(struct ciss_request *cr);
  183: static void	ciss_print_ldrive(struct ciss_softc *sc, struct ciss_ldrive *ld);
  184: static const char *ciss_name_ldrive_status(int status);
  185: static int	ciss_decode_ldrive_status(int status);
  186: static const char *ciss_name_ldrive_org(int org);
  187: static const char *ciss_name_command_status(int status);
  188: 
  189: /*
  190:  * PCI bus interface.
  191:  */
  192: static device_method_t ciss_methods[] = {
  193:     /* Device interface */
  194:     DEVMETHOD(device_probe,	ciss_probe),
  195:     DEVMETHOD(device_attach,	ciss_attach),
  196:     DEVMETHOD(device_detach,	ciss_detach),
  197:     DEVMETHOD(device_shutdown,	ciss_shutdown),
  198:     { 0, 0 }
  199: };
  200: 
  201: static driver_t ciss_pci_driver = {
  202:     "ciss",
  203:     ciss_methods,
  204:     sizeof(struct ciss_softc)
  205: };
  206: 
  207: static devclass_t	ciss_devclass;
  208: 
  209: DECLARE_DUMMY_MODULE(ciss);
  210: DRIVER_MODULE(ciss, pci, ciss_pci_driver, ciss_devclass, 0, 0);
  211: 
  212: /*
  213:  * Control device interface.
  214:  */
  215: static d_open_t		ciss_open;
  216: static d_close_t	ciss_close;
  217: static d_ioctl_t	ciss_ioctl;
  218: 
  219: #define CISS_CDEV_MAJOR  166
  220: 
  221: static struct cdevsw ciss_cdevsw = {
  222:     /* name */		"ciss",
  223:     /* cmaj */		CISS_CDEV_MAJOR,
  224:     /* flags */		0, 
  225:     /* port */		NULL,
  226:     /* clone */		NULL,
  227:     ciss_open, ciss_close, noread, nowrite, ciss_ioctl,
  228:     nopoll, nommap, nostrategy,
  229:     nodump, nopsize, nokqfilter
  230: };
  231: 
  232: /************************************************************************
  233:  * CISS adapters amazingly don't have a defined programming interface
  234:  * value.  (One could say some very despairing things about PCI and
  235:  * people just not getting the general idea.)  So we are forced to
  236:  * stick with matching against subvendor/subdevice, and thus have to
  237:  * be updated for every new CISS adapter that appears.
  238:  */
  239: #define CISS_BOARD_SA5	(1<<0)
  240: #define CISS_BOARD_SA5B	(1<<1)
  241: 
  242: static struct
  243: {
  244:     u_int16_t	subvendor;
  245:     u_int16_t	subdevice;
  246:     int		flags;
  247:     char	*desc;
  248: } ciss_vendor_data[] = {
  249:     { 0x0e11, 0x4070, CISS_BOARD_SA5,	"Compaq Smart Array 5300" },
  250:     { 0x0e11, 0x4080, CISS_BOARD_SA5B,	"Compaq Smart Array 5i" },
  251:     { 0x0e11, 0x4082, CISS_BOARD_SA5B,	"Compaq Smart Array 532" },
  252:     { 0x0e11, 0x4083, CISS_BOARD_SA5B,	"HP Smart Array 5312" },
  253:     { 0x0e11, 0x409A, CISS_BOARD_SA5B,	"HP Smart Array 641" },
  254:     { 0x0e11, 0x409B, CISS_BOARD_SA5B,	"HP Smart Array 642" },
  255:     { 0x0e11, 0x409C, CISS_BOARD_SA5B,	"HP Smart Array 6400" },
  256:     { 0, 0, 0, NULL }
  257: };
  258: 
  259: /************************************************************************
  260:  * Find a match for the device in our list of known adapters.
  261:  */
  262: static int
  263: ciss_lookup(device_t dev)
  264: {
  265:     int 	i;
  266:     
  267:     for (i = 0; ciss_vendor_data[i].desc != NULL; i++)
  268: 	if ((pci_get_subvendor(dev) == ciss_vendor_data[i].subvendor) &&
  269: 	    (pci_get_subdevice(dev) == ciss_vendor_data[i].subdevice)) {
  270: 	    return(i);
  271: 	}
  272:     return(-1);
  273: }
  274: 
  275: /************************************************************************
  276:  * Match a known CISS adapter.
  277:  */
  278: static int
  279: ciss_probe(device_t dev)
  280: {
  281:     int		i;
  282:     
  283:     i = ciss_lookup(dev);
  284:     if (i != -1) {
  285: 	device_set_desc(dev, ciss_vendor_data[i].desc);
  286: 	return(-10);
  287:     }
  288:     return(ENOENT);
  289: }	
  290: 
  291: /************************************************************************
  292:  * Attach the driver to this adapter.
  293:  */
  294: static int
  295: ciss_attach(device_t dev)
  296: {
  297:     struct ciss_softc	*sc;
  298:     int			i, error;
  299: 
  300:     debug_called(1);
  301: 
  302: #ifdef CISS_DEBUG
  303:     /* print structure/union sizes */
  304:     debug_struct(ciss_command);
  305:     debug_struct(ciss_header);
  306:     debug_union(ciss_device_address);
  307:     debug_struct(ciss_cdb);
  308:     debug_struct(ciss_report_cdb);
  309:     debug_struct(ciss_notify_cdb);
  310:     debug_struct(ciss_notify);
  311:     debug_struct(ciss_message_cdb);
  312:     debug_struct(ciss_error_info_pointer);
  313:     debug_struct(ciss_error_info);
  314:     debug_struct(ciss_sg_entry);
  315:     debug_struct(ciss_config_table);
  316:     debug_struct(ciss_bmic_cdb);
  317:     debug_struct(ciss_bmic_id_ldrive);
  318:     debug_struct(ciss_bmic_id_lstatus);
  319:     debug_struct(ciss_bmic_id_table);
  320:     debug_struct(ciss_bmic_id_pdrive);
  321:     debug_struct(ciss_bmic_blink_pdrive);
  322:     debug_struct(ciss_bmic_flush_cache);
  323:     debug_const(CISS_MAX_REQUESTS);
  324:     debug_const(CISS_MAX_LOGICAL);
  325:     debug_const(CISS_INTERRUPT_COALESCE_DELAY);
  326:     debug_const(CISS_INTERRUPT_COALESCE_COUNT);
  327:     debug_const(CISS_COMMAND_ALLOC_SIZE);
  328:     debug_const(CISS_COMMAND_SG_LENGTH);
  329: 
  330:     debug_type(cciss_pci_info_struct);
  331:     debug_type(cciss_coalint_struct);
  332:     debug_type(cciss_coalint_struct);
  333:     debug_type(NodeName_type);
  334:     debug_type(NodeName_type);
  335:     debug_type(Heartbeat_type);
  336:     debug_type(BusTypes_type);
  337:     debug_type(FirmwareVer_type);
  338:     debug_type(DriverVer_type);
  339:     debug_type(IOCTL_Command_struct);
  340: #endif
  341: 
  342:     sc = device_get_softc(dev);
  343:     sc->ciss_dev = dev;
  344: 
  345:     /*
  346:      * Work out adapter type.
  347:      */
  348:     i = ciss_lookup(dev);
  349:     if (ciss_vendor_data[i].flags & CISS_BOARD_SA5) {
  350: 	sc->ciss_interrupt_mask = CISS_TL_SIMPLE_INTR_OPQ_SA5;
  351:     } else if (ciss_vendor_data[i].flags & CISS_BOARD_SA5B) {
  352: 	sc->ciss_interrupt_mask = CISS_TL_SIMPLE_INTR_OPQ_SA5B;
  353:     } else {
  354: 	/* really an error on our part */
  355: 	ciss_printf(sc, "unable to determine hardware type\n");
  356: 	error = ENXIO;
  357: 	goto out;
  358:     }
  359: 	
  360:     /*
  361:      * Do PCI-specific init.
  362:      */
  363:     if ((error = ciss_init_pci(sc)) != 0)
  364: 	goto out;
  365: 
  366:     /*
  367:      * Initialise driver queues.
  368:      */
  369:     ciss_initq_free(sc);
  370:     ciss_initq_busy(sc);
  371:     ciss_initq_complete(sc);
  372: 
  373:     /*
  374:      * Initialise command/request pool.
  375:      */
  376:     if ((error = ciss_init_requests(sc)) != 0)
  377: 	goto out;
  378: 
  379:     /*
  380:      * Get adapter information.
  381:      */
  382:     if ((error = ciss_identify_adapter(sc)) != 0)
  383: 	goto out;
  384:     
  385:     /*
  386:      * Build our private table of logical devices.
  387:      */
  388:     if ((error = ciss_init_logical(sc)) != 0)
  389: 	goto out;
  390: 
  391:     /*
  392:      * Enable interrupts so that the CAM scan can complete.
  393:      */
  394:     CISS_TL_SIMPLE_ENABLE_INTERRUPTS(sc);
  395: 
  396:     /*
  397:      * Initialise the CAM interface.
  398:      */
  399:     if ((error = ciss_cam_init(sc)) != 0)
  400: 	goto out;
  401: 
  402:     /*
  403:      * Start the heartbeat routine and event chain.
  404:      */
  405:     ciss_periodic(sc);
  406: 
  407:    /*
  408:      * Create the control device.
  409:      */
  410:     cdevsw_add(&ciss_cdevsw, -1, device_get_unit(sc->ciss_dev));
  411:     sc->ciss_dev_t = make_dev(&ciss_cdevsw, device_get_unit(sc->ciss_dev),
  412: 			      UID_ROOT, GID_OPERATOR, S_IRUSR | S_IWUSR,
  413: 			      "ciss%d", device_get_unit(sc->ciss_dev));
  414:     sc->ciss_dev_t->si_drv1 = sc;
  415: 
  416:     /*
  417:      * The adapter is running; synchronous commands can now sleep
  418:      * waiting for an interrupt to signal completion.
  419:      */
  420:     sc->ciss_flags |= CISS_FLAG_RUNNING;
  421: 
  422:     error = 0;
  423:  out:
  424:     if (error != 0)
  425: 	ciss_free(sc);
  426:     return(error);
  427: }
  428: 
  429: /************************************************************************
  430:  * Detach the driver from this adapter.
  431:  */
  432: static int
  433: ciss_detach(device_t dev)
  434: {
  435:     struct ciss_softc	*sc = device_get_softc(dev);
  436: 
  437:     debug_called(1);
  438:     
  439:     /* flush adapter cache */
  440:     ciss_flush_adapter(sc);
  441: 
  442:     /* release all resources */
  443:     ciss_free(sc);
  444: 
  445:     return(0);
  446:     
  447: }
  448: 
  449: /************************************************************************
  450:  * Prepare adapter for system shutdown.
  451:  */
  452: static int
  453: ciss_shutdown(device_t dev)
  454: {
  455:     struct ciss_softc	*sc = device_get_softc(dev);
  456: 
  457:     debug_called(1);
  458: 
  459:     /* flush adapter cache */
  460:     ciss_flush_adapter(sc);
  461: 
  462:     return(0);
  463: }
  464: 
  465: /************************************************************************
  466:  * Perform PCI-specific attachment actions.
  467:  */
  468: static int
  469: ciss_init_pci(struct ciss_softc *sc)
  470: {
  471:     uintptr_t		cbase, csize, cofs;
  472:     int			error;
  473: 
  474:     debug_called(1);
  475: 
  476:     /*
  477:      * Allocate register window first (we need this to find the config
  478:      * struct).
  479:      */
  480:     error = ENXIO;
  481:     sc->ciss_regs_rid = CISS_TL_SIMPLE_BAR_REGS;
  482:     if ((sc->ciss_regs_resource =
  483: 	 bus_alloc_resource(sc->ciss_dev, SYS_RES_MEMORY, &sc->ciss_regs_rid,
  484: 			    0, ~0, 1, RF_ACTIVE)) == NULL) {
  485: 	ciss_printf(sc, "can't allocate register window\n");
  486: 	return(ENXIO);
  487:     }
  488:     sc->ciss_regs_bhandle = rman_get_bushandle(sc->ciss_regs_resource);
  489:     sc->ciss_regs_btag = rman_get_bustag(sc->ciss_regs_resource);
  490:     
  491:     /*
  492:      * Find the BAR holding the config structure.  If it's not the one
  493:      * we already mapped for registers, map it too.
  494:      */
  495:     sc->ciss_cfg_rid = CISS_TL_SIMPLE_READ(sc, CISS_TL_SIMPLE_CFG_BAR) & 0xffff;
  496:     if (sc->ciss_cfg_rid != sc->ciss_regs_rid) {
  497: 	if ((sc->ciss_cfg_resource =
  498: 	     bus_alloc_resource(sc->ciss_dev, SYS_RES_MEMORY, &sc->ciss_cfg_rid,
  499: 				0, ~0, 1, RF_ACTIVE)) == NULL) {
  500: 	    ciss_printf(sc, "can't allocate config window\n");
  501: 	    return(ENXIO);
  502: 	}
  503: 	cbase = (uintptr_t)rman_get_virtual(sc->ciss_cfg_resource);
  504: 	csize = rman_get_end(sc->ciss_cfg_resource) -
  505: 	    rman_get_start(sc->ciss_cfg_resource) + 1;
  506:     } else {
  507: 	cbase = (uintptr_t)rman_get_virtual(sc->ciss_regs_resource);
  508: 	csize = rman_get_end(sc->ciss_regs_resource) -
  509: 	    rman_get_start(sc->ciss_regs_resource) + 1;
  510:     }
  511:     cofs = CISS_TL_SIMPLE_READ(sc, CISS_TL_SIMPLE_CFG_OFF);
  512:     
  513:     /*
  514:      * Use the base/size/offset values we just calculated to
  515:      * sanity-check the config structure.  If it's OK, point to it.
  516:      */
  517:     if ((cofs + sizeof(struct ciss_config_table)) > csize) {
  518: 	ciss_printf(sc, "config table outside window\n");
  519: 	return(ENXIO);
  520:     }
  521:     sc->ciss_cfg = (struct ciss_config_table *)(cbase + cofs);
  522:     debug(1, "config struct at %p", sc->ciss_cfg);
  523:     
  524:     /*
  525:      * Validate the config structure.  If we supported other transport
  526:      * methods, we could select amongst them at this point in time.
  527:      */
  528:     if (strncmp(sc->ciss_cfg->signature, "CISS", 4)) {
  529: 	ciss_printf(sc, "config signature mismatch (got '%c%c%c%c')\n",
  530: 		    sc->ciss_cfg->signature[0], sc->ciss_cfg->signature[1],
  531: 		    sc->ciss_cfg->signature[2], sc->ciss_cfg->signature[3]);
  532: 	return(ENXIO);
  533:     }
  534:     if ((sc->ciss_cfg->valence < CISS_MIN_VALENCE) ||
  535: 	(sc->ciss_cfg->valence > CISS_MAX_VALENCE)) {
  536: 	ciss_printf(sc, "adapter interface specification (%d) unsupported\n", 
  537: 		    sc->ciss_cfg->valence);
  538: 	return(ENXIO);
  539:     }
  540: 
  541:     /*
  542:      * Put the board into simple mode, and tell it we're using the low
  543:      * 4GB of RAM.  Set the default interrupt coalescing options.
  544:      */
  545:     if (!(sc->ciss_cfg->supported_methods & CISS_TRANSPORT_METHOD_SIMPLE)) {
  546: 	ciss_printf(sc, "adapter does not support 'simple' transport layer\n");
  547: 	return(ENXIO);
  548:     }
  549:     sc->ciss_cfg->requested_method = CISS_TRANSPORT_METHOD_SIMPLE;
  550:     sc->ciss_cfg->command_physlimit = 0;
  551:     sc->ciss_cfg->interrupt_coalesce_delay = CISS_INTERRUPT_COALESCE_DELAY;
  552:     sc->ciss_cfg->interrupt_coalesce_count = CISS_INTERRUPT_COALESCE_COUNT;
  553: 
  554:     if (ciss_update_config(sc)) {
  555: 	ciss_printf(sc, "adapter refuses to accept config update (IDBR 0x%x)\n",
  556: 		    CISS_TL_SIMPLE_READ(sc, CISS_TL_SIMPLE_IDBR));
  557: 	return(ENXIO);
  558:     }
  559:     if (!(sc->ciss_cfg->active_method != CISS_TRANSPORT_METHOD_SIMPLE)) {
  560: 	ciss_printf(sc,
  561: 		    "adapter refuses to go into 'simple' transport mode (0x%x, 0x%x)\n",
  562: 		    sc->ciss_cfg->supported_methods, sc->ciss_cfg->active_method);
  563: 	return(ENXIO);
  564:     }
  565: 
  566:     /*
  567:      * Wait for the adapter to come ready.
  568:      */
  569:     if ((error = ciss_wait_adapter(sc)) != 0)
  570: 	return(error);
  571: 
  572:     /*
  573:      * Turn off interrupts before we go routing anything.
  574:      */
  575:     CISS_TL_SIMPLE_DISABLE_INTERRUPTS(sc);
  576:     
  577:     /*
  578:      * Allocate and set up our interrupt.
  579:      */
  580:     sc->ciss_irq_rid = 0;
  581:     if ((sc->ciss_irq_resource =
  582: 	 bus_alloc_resource(sc->ciss_dev, SYS_RES_IRQ, &sc->ciss_irq_rid, 0, ~0, 1, 
  583: 			    RF_ACTIVE | RF_SHAREABLE)) == NULL) {
  584: 	ciss_printf(sc, "can't allocate interrupt\n");
  585: 	return(ENXIO);
  586:     }
  587:     if (bus_setup_intr(sc->ciss_dev, sc->ciss_irq_resource, INTR_TYPE_CAM, ciss_intr, sc,
  588: 		       &sc->ciss_intr)) {
  589: 	ciss_printf(sc, "can't set up interrupt\n");
  590: 	return(ENXIO);
  591:     }
  592: 
  593:     /*
  594:      * Allocate the parent bus DMA tag appropriate for our PCI
  595:      * interface.
  596:      * 
  597:      * Note that "simple" adapters can only address within a 32-bit
  598:      * span.
  599:      */
  600:     if (bus_dma_tag_create(NULL, 			/* parent */
  601: 			   1, 0, 			/* alignment, boundary */
  602: 			   BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */
  603: 			   BUS_SPACE_MAXADDR, 		/* highaddr */
  604: 			   NULL, NULL, 			/* filter, filterarg */
  605: 			   MAXBSIZE, CISS_COMMAND_SG_LENGTH,	/* maxsize, nsegments */
  606: 			   BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
  607: 			   BUS_DMA_ALLOCNOW,		/* flags */
  608: 			   &sc->ciss_parent_dmat)) {
  609: 	ciss_printf(sc, "can't allocate parent DMA tag\n");
  610: 	return(ENOMEM);
  611:     }
  612: 
  613:     /*
  614:      * Create DMA tag for mapping buffers into adapter-addressable
  615:      * space.
  616:      */
  617:     if (bus_dma_tag_create(sc->ciss_parent_dmat, 	/* parent */
  618: 			   1, 0, 			/* alignment, boundary */
  619: 			   BUS_SPACE_MAXADDR,		/* lowaddr */
  620: 			   BUS_SPACE_MAXADDR, 		/* highaddr */
  621: 			   NULL, NULL, 			/* filter, filterarg */
  622: 			   MAXBSIZE, CISS_COMMAND_SG_LENGTH,	/* maxsize, nsegments */
  623: 			   BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
  624: 			   0,				/* flags */
  625: 			   &sc->ciss_buffer_dmat)) {
  626: 	ciss_printf(sc, "can't allocate buffer DMA tag\n");
  627: 	return(ENOMEM);
  628:     }
  629:     return(0);
  630: }
  631: 
  632: /************************************************************************
  633:  * Wait for the adapter to come ready.
  634:  */
  635: static int
  636: ciss_wait_adapter(struct ciss_softc *sc)
  637: {
  638:     int		i;
  639: 
  640:     debug_called(1);
  641:     
  642:     /*
  643:      * Wait for the adapter to come ready.
  644:      */
  645:     if (!(sc->ciss_cfg->active_method & CISS_TRANSPORT_METHOD_READY)) {
  646: 	ciss_printf(sc, "waiting for adapter to come ready...\n");
  647: 	for (i = 0; !(sc->ciss_cfg->active_method & CISS_TRANSPORT_METHOD_READY); i++) {
  648: 	    DELAY(1000000);	/* one second */
  649: 	    if (i > 30) {
  650: 		ciss_printf(sc, "timed out waiting for adapter to come ready\n");
  651: 		return(EIO);
  652: 	    }
  653: 	}
  654:     }
  655:     return(0);
  656: }
  657: 
  658: /************************************************************************
  659:  * Flush the adapter cache.
  660:  */
  661: static int
  662: ciss_flush_adapter(struct ciss_softc *sc)
  663: {
  664:     struct ciss_request			*cr;
  665:     struct ciss_bmic_flush_cache	*cbfc;
  666:     int					error, command_status;
  667: 
  668:     debug_called(1);
  669: 
  670:     cr = NULL;
  671:     cbfc = NULL;
  672: 
  673:     /*
  674:      * Build a BMIC request to flush the cache.  We don't disable
  675:      * it, as we may be going to do more I/O (eg. we are emulating
  676:      * the Synchronise Cache command).
  677:      */
  678:     if ((cbfc = malloc(sizeof(*cbfc), CISS_MALLOC_CLASS, M_NOWAIT | M_ZERO)) == NULL) {
  679: 	error = ENOMEM;
  680: 	goto out;
  681:     }
  682:     if ((error = ciss_get_bmic_request(sc, &cr, CISS_BMIC_FLUSH_CACHE,
  683: 				       (void **)&cbfc, sizeof(*cbfc))) != 0)
  684: 	goto out;
  685: 
  686:     /*
  687:      * Submit the request and wait for it to complete.
  688:      */
  689:     if ((error = ciss_synch_request(cr, 60 * 1000)) != 0) {
  690: 	ciss_printf(sc, "error sending BMIC FLUSH_CACHE command (%d)\n", error);
  691: 	goto out;
  692:     }
  693:     
  694:     /*
  695:      * Check response.
  696:      */
  697:     ciss_report_request(cr, &command_status, NULL);
  698:     switch(command_status) {
  699:     case CISS_CMD_STATUS_SUCCESS:
  700: 	break;
  701:     default:
  702: 	ciss_printf(sc, "error flushing cache (%s)\n",  
  703: 		    ciss_name_command_status(command_status));
  704: 	error = EIO;
  705: 	goto out;
  706:     }
  707: 
  708: out:
  709:     if (cbfc != NULL)
  710: 	free(cbfc, CISS_MALLOC_CLASS);
  711:     if (cr != NULL)
  712: 	ciss_release_request(cr);
  713:     return(error);
  714: }
  715: 
  716: /************************************************************************
  717:  * Allocate memory for the adapter command structures, initialise
  718:  * the request structures.
  719:  *
  720:  * Note that the entire set of commands are allocated in a single
  721:  * contiguous slab.
  722:  */
  723: static int
  724: ciss_init_requests(struct ciss_softc *sc)
  725: {
  726:     struct ciss_request	*cr;
  727:     int			i;
  728: 
  729:     debug_called(1);
  730:     
  731:     /*
  732:      * Calculate the number of request structures/commands we are
  733:      * going to provide for this adapter.
  734:      */
  735:     sc->ciss_max_requests = min(CISS_MAX_REQUESTS, sc->ciss_cfg->max_outstanding_commands);
  736:     
  737:     if (1/*bootverbose*/)
  738: 	ciss_printf(sc, "using %d of %d available commands\n",
  739: 		    sc->ciss_max_requests, sc->ciss_cfg->max_outstanding_commands);
  740: 
  741:     /*
  742:      * Create the DMA tag for commands.
  743:      */
  744:     if (bus_dma_tag_create(sc->ciss_parent_dmat,	/* parent */
  745: 			   1, 0, 			/* alignment, boundary */
  746: 			   BUS_SPACE_MAXADDR,		/* lowaddr */
  747: 			   BUS_SPACE_MAXADDR, 		/* highaddr */
  748: 			   NULL, NULL, 			/* filter, filterarg */
  749: 			   CISS_COMMAND_ALLOC_SIZE * 
  750: 			   sc->ciss_max_requests, 1,	/* maxsize, nsegments */
  751: 			   BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
  752: 			   0,				/* flags */
  753: 			   &sc->ciss_command_dmat)) {
  754: 	ciss_printf(sc, "can't allocate command DMA tag\n");
  755: 	return(ENOMEM);
  756:     }
  757:     /*
  758:      * Allocate memory and make it available for DMA.
  759:      */
  760:     if (bus_dmamem_alloc(sc->ciss_command_dmat, (void **)&sc->ciss_command, 
  761: 			 BUS_DMA_NOWAIT, &sc->ciss_command_map)) {
  762: 	ciss_printf(sc, "can't allocate command memory\n");
  763: 	return(ENOMEM);
  764:     }
  765:     bus_dmamap_load(sc->ciss_command_dmat, sc->ciss_command_map, sc->ciss_command, 
  766: 		    sizeof(struct ciss_command) * sc->ciss_max_requests,
  767: 		    ciss_command_map_helper, sc, 0);
  768:     bzero(sc->ciss_command, CISS_COMMAND_ALLOC_SIZE * sc->ciss_max_requests);
  769: 
  770:     /*
  771:      * Set up the request and command structures, push requests onto
  772:      * the free queue.
  773:      */
  774:     for (i = 1; i < sc->ciss_max_requests; i++) {
  775: 	cr = &sc->ciss_request[i];
  776: 	cr->cr_sc = sc;
  777: 	cr->cr_tag = i;
  778: 	ciss_enqueue_free(cr);
  779:     }
  780:     return(0);
  781: }
  782: 
  783: static void
  784: ciss_command_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error)
  785: {
  786:     struct ciss_softc	*sc = (struct ciss_softc *)arg;
  787: 
  788:     sc->ciss_command_phys = segs->ds_addr;
  789: }
  790: 
  791: /************************************************************************
  792:  * Identify the adapter, print some information about it.
  793:  */
  794: static int
  795: ciss_identify_adapter(struct ciss_softc *sc)
  796: {
  797:     struct ciss_request	*cr;
  798:     int			error, command_status;
  799: 
  800:     debug_called(1);
  801: 
  802:     cr = NULL;
  803: 
  804:     /*
  805:      * Get a request, allocate storage for the adapter data.
  806:      */
  807:     if ((error = ciss_get_bmic_request(sc, &cr, CISS_BMIC_ID_CTLR,
  808: 				       (void **)&sc->ciss_id,
  809: 				       sizeof(*sc->ciss_id))) != 0)
  810: 	goto out;
  811: 
  812:     /*
  813:      * Submit the request and wait for it to complete.
  814:      */
  815:     if ((error = ciss_synch_request(cr, 60 * 1000)) != 0) {
  816: 	ciss_printf(sc, "error sending BMIC ID_CTLR command (%d)\n", error);
  817: 	goto out;
  818:     }
  819:     
  820:     /*
  821:      * Check response.
  822:      */
  823:     ciss_report_request(cr, &command_status, NULL);
  824:     switch(command_status) {
  825:     case CISS_CMD_STATUS_SUCCESS:		/* buffer right size */
  826: 	break;
  827:     case CISS_CMD_STATUS_DATA_UNDERRUN:
  828:     case CISS_CMD_STATUS_DATA_OVERRUN:
  829: 	ciss_printf(sc, "data over/underrun reading adapter information\n");
  830:     default:
  831: 	ciss_printf(sc, "error reading adapter information (%s)\n",
  832: 		    ciss_name_command_status(command_status));
  833: 	error = EIO;
  834: 	goto out;
  835:     }
  836: 
  837:     /* sanity-check reply */
  838:     if (!sc->ciss_id->big_map_supported) {
  839: 	ciss_printf(sc, "adapter does not support BIG_MAP\n");
  840: 	error = ENXIO;
  841: 	goto out;
  842:     }
  843: 
  844: #if 0
  845:     /* XXX later revisions may not need this */
  846:     sc->ciss_flags |= CISS_FLAG_FAKE_SYNCH;
  847: #endif
  848: 
  849:     /* XXX only really required for old 5300 adapters? */
  850:     sc->ciss_flags |= CISS_FLAG_BMIC_ABORT;
  851:     
  852:     /* print information */
  853:     if (1/*bootverbose*/) {
  854: 	ciss_printf(sc, "  %d logical drive%s configured\n",
  855: 		    sc->ciss_id->configured_logical_drives,
  856: 		    (sc->ciss_id->configured_logical_drives == 1) ? "" : "s");
  857: 	ciss_printf(sc, "  firmware %4.4s\n", sc->ciss_id->running_firmware_revision);
  858: 	ciss_printf(sc, "  %d SCSI channels\n", sc->ciss_id->scsi_bus_count);
  859: 
  860: 	ciss_printf(sc, "  signature '%.4s'\n", sc->ciss_cfg->signature);
  861: 	ciss_printf(sc, "  valence %d\n", sc->ciss_cfg->valence);
  862: 	ciss_printf(sc, "  supported I/O methods 0x%b\n",
  863: 		    sc->ciss_cfg->supported_methods, 
  864: 		    "\20\1READY\2simple\3performant\4MEMQ\n");
  865: 	ciss_printf(sc, "  active I/O method 0x%b\n",
  866: 		    sc->ciss_cfg->active_method, "\20\2simple\3performant\4MEMQ\n");
  867: 	ciss_printf(sc, "  4G page base 0x%08x\n",
  868: 		    sc->ciss_cfg->command_physlimit);
  869: 	ciss_printf(sc, "  interrupt coalesce delay %dus\n",
  870: 		    sc->ciss_cfg->interrupt_coalesce_delay);
  871: 	ciss_printf(sc, "  interrupt coalesce count %d\n",
  872: 		    sc->ciss_cfg->interrupt_coalesce_count);
  873: 	ciss_printf(sc, "  max outstanding commands %d\n",
  874: 		    sc->ciss_cfg->max_outstanding_commands);
  875: 	ciss_printf(sc, "  bus types 0x%b\n", sc->ciss_cfg->bus_types, 
  876: 		    "\20\1ultra2\2ultra3\10fibre1\11fibre2\n");
  877: 	ciss_printf(sc, "  server name '%.16s'\n", sc->ciss_cfg->server_name);
  878: 	ciss_printf(sc, "  heartbeat 0x%x\n", sc->ciss_cfg->heartbeat);
  879:     }
  880: 
  881: out:
  882:     if (error) {
  883: 	if (sc->ciss_id != NULL) {
  884: 	    free(sc->ciss_id, CISS_MALLOC_CLASS);
  885: 	    sc->ciss_id = NULL;
  886: 	}
  887:     }	
  888:     if (cr != NULL)
  889: 	ciss_release_request(cr);
  890:     return(error);
  891: }
  892: 
  893: /************************************************************************
  894:  * Find logical drives on the adapter.
  895:  */
  896: static int
  897: ciss_init_logical(struct ciss_softc *sc)
  898: {
  899:     struct ciss_request		*cr;
  900:     struct ciss_command		*cc;
  901:     struct ciss_report_cdb	*crc;
  902:     struct ciss_lun_report	*cll;
  903:     int				error, i;
  904:     size_t			report_size;
  905:     int				ndrives;
  906:     int				command_status;
  907: 
  908:     debug_called(1);
  909: 
  910:     cr = NULL;
  911:     cll = NULL;
  912: 
  913:     /*
  914:      * Get a request, allocate storage for the address list.
  915:      */
  916:     if ((error = ciss_get_request(sc, &cr)) != 0)
  917: 	goto out;
  918:     report_size = sizeof(*cll) + CISS_MAX_LOGICAL * sizeof(union ciss_device_address);
  919:     if ((cll = malloc(report_size, CISS_MALLOC_CLASS, M_NOWAIT | M_ZERO)) == NULL) {
  920: 	ciss_printf(sc, "can't allocate memory for logical drive list\n");
  921: 	error = ENOMEM;
  922: 	goto out;
  923:     }
  924: 
  925:     /*
  926:      * Build the Report Logical LUNs command.
  927:      */
  928:     cc = CISS_FIND_COMMAND(cr);
  929:     cr->cr_data = cll;
  930:     cr->cr_length = report_size;
  931:     cr->cr_flags = CISS_REQ_DATAIN;
  932:     
  933:     cc->header.address.physical.mode = CISS_HDR_ADDRESS_MODE_PERIPHERAL;
  934:     cc->header.address.physical.bus = 0;
  935:     cc->header.address.physical.target = 0;
  936:     cc->cdb.cdb_length = sizeof(*crc);
  937:     cc->cdb.type = CISS_CDB_TYPE_COMMAND;
  938:     cc->cdb.attribute = CISS_CDB_ATTRIBUTE_SIMPLE;
  939:     cc->cdb.direction = CISS_CDB_DIRECTION_READ;
  940:     cc->cdb.timeout = 30;	/* XXX better suggestions? */
  941: 
  942:     crc = (struct ciss_report_cdb *)&(cc->cdb.cdb[0]);
  943:     bzero(crc, sizeof(*crc));
  944:     crc->opcode = CISS_OPCODE_REPORT_LOGICAL_LUNS;
  945:     crc->length = htonl(report_size);			/* big-endian field */
  946:     cll->list_size = htonl(report_size - sizeof(*cll));	/* big-endian field */
  947:     
  948:     /*
  949:      * Submit the request and wait for it to complete.  (timeout
  950:      * here should be much greater than above)
  951:      */
  952:     if ((error = ciss_synch_request(cr, 60 * 1000)) != 0) {
  953: 	ciss_printf(sc, "error sending Report Logical LUNs command (%d)\n", error);
  954: 	goto out;
  955:     }
  956: 
  957:     /*
  958:      * Check response.  Note that data over/underrun is OK.
  959:      */
  960:     ciss_report_request(cr, &command_status, NULL);
  961:     switch(command_status) {
  962:     case CISS_CMD_STATUS_SUCCESS:	/* buffer right size */
  963:     case CISS_CMD_STATUS_DATA_UNDERRUN:	/* buffer too large, not bad */
  964: 	break;
  965:     case CISS_CMD_STATUS_DATA_OVERRUN:
  966: 	ciss_printf(sc, "WARNING: more logical drives than driver limit (%d), adjust CISS_MAX_LOGICAL\n",
  967: 		    CISS_MAX_LOGICAL);
  968: 	break;
  969:     default:
  970: 	ciss_printf(sc, "error detecting logical drive configuration (%s)\n",
  971: 		    ciss_name_command_status(command_status));
  972: 	error = EIO;
  973: 	goto out;
  974:     }
  975:     ciss_release_request(cr);
  976:     cr = NULL;
  977: 
  978:     /* sanity-check reply */
  979:     ndrives = (ntohl(cll->list_size) / sizeof(union ciss_device_address));
  980:     if ((ndrives < 0) || (ndrives > CISS_MAX_LOGICAL)) {
  981: 	ciss_printf(sc, "adapter claims to report absurd number of logical drives (%d > %d)\n",
  982: 		    ndrives, CISS_MAX_LOGICAL);
  983: 	return(ENXIO);
  984:     }
  985: 
  986:     /*
  987:      * Save logical drive information.
  988:      */
  989:     if (1/*bootverbose*/)
  990: 	ciss_printf(sc, "%d logical drive%s\n", ndrives, (ndrives > 1) ? "s" : "");
  991:     if (ndrives != sc->ciss_id->configured_logical_drives)
  992: 	ciss_printf(sc, "logical drive map claims %d drives, but adapter claims %d\n",
  993: 		    ndrives, sc->ciss_id->configured_logical_drives);
  994:     for (i = 0; i < CISS_MAX_LOGICAL; i++) {
  995: 	if (i < ndrives) {
  996: 	    sc->ciss_logical[i].cl_address = cll->lun[i];	/* XXX endianness? */
  997: 	    if (ciss_identify_logical(sc, &sc->ciss_logical[i]) != 0)
  998: 		continue;
  999: 	    /*
 1000: 	     * If the drive has had media exchanged, we should bring it online.
 1001: 	     */
 1002: 	    if (sc->ciss_logical[i].cl_lstatus->media_exchanged)
 1003: 		ciss_accept_media(sc, i, 0);
 1004: 
 1005: 	} else {
 1006: 	    sc->ciss_logical[i].cl_status = CISS_LD_NONEXISTENT;
 1007: 	}
 1008:     }
 1009:     error = 0;
 1010:     
 1011:  out:
 1012:     /*
 1013:      * Note that if the error is a timeout, we are taking a slight
 1014:      * risk here and assuming that the adapter will not respond at a
 1015:      * later time, scribbling over host memory.
 1016:      */
 1017:     if (cr != NULL)
 1018: 	ciss_release_request(cr);
 1019:     if (cll != NULL)
 1020: 	free(cll, CISS_MALLOC_CLASS);
 1021:     return(error);
 1022: }
 1023: 
 1024: static int
 1025: ciss_inquiry_logical(struct ciss_softc *sc, struct ciss_ldrive *ld)
 1026: {
 1027:     struct ciss_request			*cr;
 1028:     struct ciss_command			*cc;
 1029:     struct scsi_inquiry			*inq;
 1030:     int					error;
 1031:     int					command_status;
 1032:     int					lun;
 1033: 
 1034:     cr = NULL;
 1035:     lun = ld->cl_address.logical.lun;
 1036: 
 1037:     bzero(&ld->cl_geometry, sizeof(ld->cl_geometry));
 1038: 
 1039:     if ((error = ciss_get_request(sc, &cr)) != 0)
 1040: 	goto out;
 1041: 
 1042:     cc = CISS_FIND_COMMAND(cr);
 1043:     cr->cr_data = &ld->cl_geometry;
 1044:     cr->cr_length = sizeof(ld->cl_geometry);
 1045:     cr->cr_flags = CISS_REQ_DATAIN;
 1046: 
 1047:     cc->header.address.logical.mode = CISS_HDR_ADDRESS_MODE_LOGICAL;
 1048:     cc->header.address.logical.lun  = lun;
 1049:     cc->cdb.cdb_length = 6;
 1050:     cc->cdb.type = CISS_CDB_TYPE_COMMAND;
 1051:     cc->cdb.attribute = CISS_CDB_ATTRIBUTE_SIMPLE;
 1052:     cc->cdb.direction = CISS_CDB_DIRECTION_READ;
 1053:     cc->cdb.timeout = 30;
 1054: 
 1055:     inq = (struct scsi_inquiry *)&(cc->cdb.cdb[0]);
 1056:     inq->opcode = INQUIRY;
 1057:     inq->byte2 = SI_EVPD;
 1058:     inq->page_code = CISS_VPD_LOGICAL_DRIVE_GEOMETRY;
 1059:     inq->length = sizeof(ld->cl_geometry);
 1060: 
 1061:     if ((error = ciss_synch_request(cr, 60 * 1000)) != 0) {
 1062: 	ciss_printf(sc, "error getting geometry (%d)\n", error);
 1063: 	goto out;
 1064:     }
 1065: 
 1066:     ciss_report_request(cr, &command_status, NULL);
 1067:     switch(command_status) {
 1068:     case CISS_CMD_STATUS_SUCCESS:
 1069:     case CISS_CMD_STATUS_DATA_UNDERRUN:
 1070: 	break;
 1071:     case CISS_CMD_STATUS_DATA_OVERRUN:
 1072: 	ciss_printf(sc, "WARNING: Data overrun\n");
 1073: 	break;
 1074:     default:
 1075: 	ciss_printf(sc, "Error detecting logical drive geometry (%s)\n",
 1076: 		    ciss_name_command_status(command_status));
 1077: 	break;
 1078:     }
 1079: 
 1080: out:
 1081:     if (cr != NULL)
 1082: 	ciss_release_request(cr);
 1083:     return(error);
 1084: }
 1085: /************************************************************************
 1086:  * Identify a logical drive, initialise state related to it.
 1087:  */
 1088: static int
 1089: ciss_identify_logical(struct ciss_softc *sc, struct ciss_ldrive *ld)
 1090: {
 1091:     struct ciss_request		*cr;
 1092:     struct ciss_command		*cc;
 1093:     struct ciss_bmic_cdb	*cbc;
 1094:     int				error, command_status;
 1095: 
 1096:     debug_called(1);
 1097: 
 1098:     cr = NULL;
 1099: 
 1100:     /*
 1101:      * Build a BMIC request to fetch the drive ID.
 1102:      */
 1103:     if ((error = ciss_get_bmic_request(sc, &cr, CISS_BMIC_ID_LDRIVE,
 1104: 				       (void **)&ld->cl_ldrive, 
 1105: 				       sizeof(*ld->cl_ldrive))) != 0)
 1106: 	goto out;
 1107:     cc = CISS_FIND_COMMAND(cr);
 1108:     cbc = (struct ciss_bmic_cdb *)&(cc->cdb.cdb[0]);
 1109:     cbc->log_drive = ld->cl_address.logical.lun;
 1110: 
 1111:     /*
 1112:      * Submit the request and wait for it to complete.
 1113:      */
 1114:     if ((error = ciss_synch_request(cr, 60 * 1000)) != 0) {
 1115: 	ciss_printf(sc, "error sending BMIC LDRIVE command (%d)\n", error);
 1116: 	goto out;
 1117:     }
 1118:     
 1119:     /*
 1120:      * Check response.
 1121:      */
 1122:     ciss_report_request(cr, &command_status, NULL);
 1123:     switch(command_status) {
 1124:     case CISS_CMD_STATUS_SUCCESS:		/* buffer right size */
 1125: 	break;
 1126:     case CISS_CMD_STATUS_DATA_UNDERRUN:
 1127:     case CISS_CMD_STATUS_DATA_OVERRUN:
 1128: 	ciss_printf(sc, "data over/underrun reading logical drive ID\n");
 1129:     default:
 1130: 	ciss_printf(sc, "error reading logical drive ID (%s)\n",
 1131: 		    ciss_name_command_status(command_status));
 1132: 	error = EIO;
 1133: 	goto out;
 1134:     }
 1135:     ciss_release_request(cr);
 1136:     cr = NULL;
 1137: 
 1138:     /*
 1139:      * Build a CISS BMIC command to get the logical drive status.
 1140:      */
 1141:     if ((error = ciss_get_ldrive_status(sc, ld)) != 0)
 1142: 	goto out;
 1143: 
 1144:     /*
 1145:      * Get the logical drive geometry.
 1146:      */
 1147:     if ((error = ciss_inquiry_logical(sc, ld)) != 0)
 1148: 	goto out;
 1149: 
 1150:     /*
 1151:      * Print the drive's basic characteristics.
 1152:      */
 1153:     if (1/*bootverbose*/) {
 1154: 	ciss_printf(sc, "logical drive %d: %s, %dMB ",
 1155: 		    cbc->log_drive, ciss_name_ldrive_org(ld->cl_ldrive->fault_tolerance),
 1156: 		    ((ld->cl_ldrive->blocks_available / (1024 * 1024)) *
 1157: 		     ld->cl_ldrive->block_size));
 1158: 
 1159: 	ciss_print_ldrive(sc, ld);
 1160:     }
 1161: out:
 1162:     if (error != 0) {
 1163: 	/* make the drive not-exist */
 1164: 	ld->cl_status = CISS_LD_NONEXISTENT;
 1165: 	if (ld->cl_ldrive != NULL) {
 1166: 	    free(ld->cl_ldrive, CISS_MALLOC_CLASS);
 1167: 	    ld->cl_ldrive = NULL;
 1168: 	}
 1169: 	if (ld->cl_lstatus != NULL) {
 1170: 	    free(ld->cl_lstatus, CISS_MALLOC_CLASS);
 1171: 	    ld->cl_lstatus = NULL;
 1172: 	}
 1173:     }
 1174:     if (cr != NULL)
 1175: 	ciss_release_request(cr);
 1176: 	
 1177:     return(error);
 1178: }
 1179: 
 1180: /************************************************************************
 1181:  * Get status for a logical drive.
 1182:  *
 1183:  * XXX should we also do this in response to Test Unit Ready?
 1184:  */
 1185: static int
 1186: ciss_get_ldrive_status(struct ciss_softc *sc,  struct ciss_ldrive *ld)
 1187: {
 1188:     struct ciss_request		*cr;
 1189:     struct ciss_command		*cc;
 1190:     struct ciss_bmic_cdb	*cbc;
 1191:     int				error, command_status;
 1192: 
 1193:     /*
 1194:      * Build a CISS BMIC command to get the logical drive status.
 1195:      */
 1196:     if ((error = ciss_get_bmic_request(sc, &cr, CISS_BMIC_ID_LSTATUS,
 1197: 				       (void **)&ld->cl_lstatus, 
 1198: 				       sizeof(*ld->cl_lstatus))) != 0)
 1199: 	goto out;
 1200:     cc = CISS_FIND_COMMAND(cr);
 1201:     cbc = (struct ciss_bmic_cdb *)&(cc->cdb.cdb[0]);
 1202:     cbc->log_drive = ld->cl_address.logical.lun;
 1203: 
 1204:     /*
 1205:      * Submit the request and wait for it to complete.
 1206:      */
 1207:     if ((error = ciss_synch_request(cr, 60 * 1000)) != 0) {
 1208: 	ciss_printf(sc, "error sending BMIC LSTATUS command (%d)\n", error);
 1209: 	goto out;
 1210:     }
 1211:     
 1212:     /*
 1213:      * Check response.
 1214:      */
 1215:     ciss_report_request(cr, &command_status, NULL);
 1216:     switch(command_status) {
 1217:     case CISS_CMD_STATUS_SUCCESS:		/* buffer right size */
 1218: 	break;
 1219:     case CISS_CMD_STATUS_DATA_UNDERRUN:
 1220:     case CISS_CMD_STATUS_DATA_OVERRUN:
 1221: 	ciss_printf(sc, "data over/underrun reading logical drive status\n");
 1222:     default:
 1223: 	ciss_printf(sc, "error reading logical drive status (%s)\n",
 1224: 		    ciss_name_command_status(command_status));
 1225: 	error = EIO;
 1226: 	goto out;
 1227:     }
 1228: 
 1229:     /*
 1230:      * Set the drive's summary status based on the returned status.
 1231:      *
 1232:      * XXX testing shows that a failed JBOD drive comes back at next 
 1233:      * boot in "queued for expansion" mode.  WTF?
 1234:      */
 1235:     ld->cl_status = ciss_decode_ldrive_status(ld->cl_lstatus->status);
 1236: 
 1237: out:
 1238:     if (cr != NULL)
 1239: 	ciss_release_request(cr);
 1240:     return(error);
 1241: }
 1242: 
 1243: /************************************************************************
 1244:  * Notify the adapter of a config update.
 1245:  */
 1246: static int
 1247: ciss_update_config(struct ciss_softc *sc)
 1248: {
 1249:     int		i;
 1250: 
 1251:     debug_called(1);
 1252: 
 1253:     CISS_TL_SIMPLE_WRITE(sc, CISS_TL_SIMPLE_IDBR, CISS_TL_SIMPLE_IDBR_CFG_TABLE);
 1254:     for (i = 0; i < 1000; i++) {
 1255: 	if (!(CISS_TL_SIMPLE_READ(sc, CISS_TL_SIMPLE_IDBR) &
 1256: 	      CISS_TL_SIMPLE_IDBR_CFG_TABLE)) {
 1257: 	    return(0);
 1258: 	}
 1259: 	DELAY(1000);
 1260:     }
 1261:     return(1);
 1262: }
 1263: 
 1264: /************************************************************************
 1265:  * Accept new media into a logical drive.
 1266:  *
 1267:  * XXX The drive has previously been offline; it would be good if we
 1268:  *     could make sure it's not open right now.
 1269:  */
 1270: static int
 1271: ciss_accept_media(struct ciss_softc *sc, int ldrive, int async)
 1272: {
 1273:     struct ciss_request		*cr;
 1274:     struct ciss_command		*cc;
 1275:     struct ciss_bmic_cdb	*cbc;
 1276:     int				error;
 1277: 
 1278:     debug(0, "bringing logical drive %d back online %ssynchronously", 
 1279: 	  ldrive, async ? "a" : "");
 1280: 
 1281:     /*
 1282:      * Build a CISS BMIC command to bring the drive back online.
 1283:      */
 1284:     if ((error = ciss_get_bmic_request(sc, &cr, CISS_BMIC_ACCEPT_MEDIA,
 1285: 				       NULL, 0)) != 0)
 1286: 	goto out;
 1287:     cc = CISS_FIND_COMMAND(cr);
 1288:     cbc = (struct ciss_bmic_cdb *)&(cc->cdb.cdb[0]);
 1289:     cbc->log_drive = ldrive;
 1290: 
 1291:     /*
 1292:      * Dispatch the request asynchronously if we can't sleep waiting
 1293:      * for it to complete.
 1294:      */
 1295:     if (async) {
 1296: 	cr->cr_complete = ciss_accept_media_complete;
 1297: 	if ((error = ciss_start(cr)) != 0)
 1298: 	    goto out;
 1299: 	return(0);
 1300:     } else {
 1301: 	/*
 1302: 	 * Submit the request and wait for it to complete.
 1303: 	 */
 1304: 	if ((error = ciss_synch_request(cr, 60 * 1000)) != 0) {
 1305: 	    ciss_printf(sc, "error sending BMIC LSTATUS command (%d)\n", error);
 1306: 	    goto out;
 1307: 	}
 1308:     }
 1309: 
 1310:     /*
 1311:      * Call the completion callback manually.
 1312:      */
 1313:     ciss_accept_media_complete(cr);
 1314:     return(0);
 1315:     
 1316: out:
 1317:     if (cr != NULL)
 1318: 	ciss_release_request(cr);
 1319:     return(error);
 1320: }
 1321: 
 1322: static void
 1323: ciss_accept_media_complete(struct ciss_request *cr)
 1324: {
 1325:     int				command_status;
 1326:     
 1327:     /*
 1328:      * Check response.
 1329:      */
 1330:     ciss_report_request(cr, &command_status, NULL);
 1331:     switch(command_status) {
 1332:     case CISS_CMD_STATUS_SUCCESS:		/* all OK */
 1333: 	/* we should get a logical drive status changed event here */
 1334: 	break;
 1335:     default:
 1336: 	ciss_printf(cr->cr_sc, "error accepting media into failed logical drive (%s)\n",
 1337: 		    ciss_name_command_status(command_status));
 1338: 	break;
 1339:     }
 1340:     ciss_release_request(cr);
 1341: }
 1342: 
 1343: /************************************************************************
 1344:  * Release adapter resources.
 1345:  */
 1346: static void
 1347: ciss_free(struct ciss_softc *sc)
 1348: {
 1349:     debug_called(1);
 1350: 
 1351:     /* we're going away */
 1352:     sc->ciss_flags |= CISS_FLAG_ABORTING;
 1353: 
 1354:     /* terminate the periodic heartbeat routine */
 1355:     untimeout(ciss_periodic, sc, sc->ciss_periodic);
 1356: 
 1357:     /* cancel the Event Notify chain */
 1358:     ciss_notify_abort(sc);
 1359:     
 1360:     /* free the controller data */
 1361:     if (sc->ciss_id != NULL)
 1362: 	free(sc->ciss_id, CISS_MALLOC_CLASS);
 1363: 
 1364:     /* release I/O resources */
 1365:     if (sc->ciss_regs_resource != NULL)
 1366: 	bus_release_resource(sc->ciss_dev, SYS_RES_MEMORY,
 1367: 			     sc->ciss_regs_rid, sc->ciss_regs_resource);
 1368:     if (sc->ciss_cfg_resource != NULL)
 1369: 	bus_release_resource(sc->ciss_dev, SYS_RES_MEMORY,
 1370: 			     sc->ciss_cfg_rid, sc->ciss_cfg_resource);
 1371:     if (sc->ciss_intr != NULL)
 1372: 	bus_teardown_intr(sc->ciss_dev, sc->ciss_irq_resource, sc->ciss_intr);
 1373:     if (sc->ciss_irq_resource != NULL)
 1374: 	bus_release_resource(sc->ciss_dev, SYS_RES_IRQ,
 1375: 			     sc->ciss_irq_rid, sc->ciss_irq_resource);
 1376: 
 1377:     /* destroy DMA tags */
 1378:     if (sc->ciss_parent_dmat)
 1379: 	bus_dma_tag_destroy(sc->ciss_parent_dmat);
 1380:     if (sc->ciss_buffer_dmat)
 1381: 	bus_dma_tag_destroy(sc->ciss_buffer_dmat);
 1382: 
 1383:     /* destroy command memory and DMA tag */
 1384:     if (sc->ciss_command != NULL) {
 1385: 	bus_dmamap_unload(sc->ciss_command_dmat, sc->ciss_command_map);
 1386: 	bus_dmamem_free(sc->ciss_command_dmat, sc->ciss_command, sc->ciss_command_map);
 1387:     }
 1388:     if (sc->ciss_buffer_dmat)
 1389: 	bus_dma_tag_destroy(sc->ciss_command_dmat);
 1390: 
 1391:     /* disconnect from CAM */
 1392:     if (sc->ciss_cam_sim) {
 1393: 	xpt_bus_deregister(cam_sim_path(sc->ciss_cam_sim));
 1394: 	cam_sim_free(sc->ciss_cam_sim);
 1395:     }
 1396:     if (sc->ciss_cam_devq)
 1397: 	cam_simq_release(sc->ciss_cam_devq);
 1398:     /* XXX what about ciss_cam_path? */
 1399: }
 1400: 
 1401: /************************************************************************
 1402:  * Give a command to the adapter.
 1403:  *
 1404:  * Note that this uses the simple transport layer directly.  If we
 1405:  * want to add support for other layers, we'll need a switch of some
 1406:  * sort.
 1407:  *
 1408:  * Note that the simple transport layer has no way of refusing a
 1409:  * command; we only have as many request structures as the adapter
 1410:  * supports commands, so we don't have to check (this presumes that
 1411:  * the adapter can handle commands as fast as we throw them at it).
 1412:  */
 1413: static int
 1414: ciss_start(struct ciss_request *cr)
 1415: {
 1416:     struct ciss_command	*cc;	/* XXX debugging only */
 1417:     int			error;
 1418: 
 1419:     cc = CISS_FIND_COMMAND(cr);
 1420:     debug(2, "post command %d tag %d ", cr->cr_tag, cc->header.host_tag);
 1421: 
 1422:     /*
 1423:      * Map the request's data.
 1424:      */
 1425:     if ((error = ciss_map_request(cr)))
 1426: 	return(error);
 1427: 
 1428: #if 0
 1429:     ciss_print_request(cr);
 1430: #endif
 1431: 
 1432:     /*
 1433:      * Post the command to the adapter.
 1434:      */
 1435:     ciss_enqueue_busy(cr);
 1436:     CISS_TL_SIMPLE_POST_CMD(cr->cr_sc, CISS_FIND_COMMANDPHYS(cr));
 1437: 
 1438:     return(0);
 1439: }
 1440: 
 1441: /************************************************************************
 1442:  * Fetch completed request(s) from the adapter, queue them for
 1443:  * completion handling.
 1444:  *
 1445:  * Note that this uses the simple transport layer directly.  If we
 1446:  * want to add support for other layers, we'll need a switch of some
 1447:  * sort.
 1448:  *
 1449:  * Note that the simple transport mechanism does not require any
 1450:  * reentrancy protection; the OPQ read is atomic.  If there is a
 1451:  * chance of a race with something else that might move the request
 1452:  * off the busy list, then we will have to lock against that
 1453:  * (eg. timeouts, etc.)
 1454:  */
 1455: static void
 1456: ciss_done(struct ciss_softc *sc)
 1457: {
 1458:     struct ciss_request	*cr;
 1459:     struct ciss_command	*cc;
 1460:     u_int32_t		tag, index;
 1461:     int			complete;
 1462:     
 1463:     debug_called(3);
 1464: 
 1465:     /*
 1466:      * Loop quickly taking requests from the adapter and moving them
 1467:      * from the busy queue to the completed queue.
 1468:      */
 1469:     complete = 0;
 1470:     for (;;) {
 1471: 
 1472: 	/* see if the OPQ contains anything */
 1473: 	if (!CISS_TL_SIMPLE_OPQ_INTERRUPT(sc))
 1474: 	    break;
 1475: 
 1476: 	tag = CISS_TL_SIMPLE_FETCH_CMD(sc);
 1477: 	if (tag == CISS_TL_SIMPLE_OPQ_EMPTY)
 1478: 	    break;
 1479: 	index = tag >> 2;
 1480: 	debug(2, "completed command %d%s", index, 
 1481: 	      (tag & CISS_HDR_HOST_TAG_ERROR) ? " with error" : "");
 1482: 	if (index >= sc->ciss_max_requests) {
 1483: 	    ciss_printf(sc, "completed invalid request %d (0x%x)\n", index, tag);
 1484: 	    continue;
 1485: 	}
 1486: 	cr = &(sc->ciss_request[index]);
 1487: 	cc = CISS_FIND_COMMAND(cr);
 1488: 	cc->header.host_tag = tag;	/* not updated by adapter */
 1489: 	if (ciss_remove_busy(cr)) {
 1490: 	    /* assume this is garbage out of the adapter */
 1491: 	    ciss_printf(sc, "completed nonbusy request %d\n", index);
 1492: 	} else {
 1493: 	    ciss_enqueue_complete(cr);
 1494: 	}
 1495: 	complete = 1;
 1496:     }
 1497:     
 1498:     /*
 1499:      * Invoke completion processing.  If we can defer this out of
 1500:      * interrupt context, that'd be good.
 1501:      */
 1502:     if (complete)
 1503: 	ciss_complete(sc);
 1504: }
 1505: 
 1506: /************************************************************************
 1507:  * Take an interrupt from the adapter.
 1508:  */
 1509: static void
 1510: ciss_intr(void *arg)
 1511: {
 1512:     struct ciss_softc	*sc = (struct ciss_softc *)arg;
 1513: 
 1514:     /*
 1515:      * The only interrupt we recognise indicates that there are
 1516:      * entries in the outbound post queue.
 1517:      */
 1518:     ciss_done(sc);
 1519: }
 1520: 
 1521: /************************************************************************
 1522:  * Process completed requests.
 1523:  *
 1524:  * Requests can be completed in three fashions:
 1525:  *
 1526:  * - by invoking a callback function (cr_complete is non-null)
 1527:  * - by waking up a sleeper (cr_flags has CISS_REQ_SLEEP set)
 1528:  * - by clearing the CISS_REQ_POLL flag in interrupt/timeout context
 1529:  */
 1530: static void
 1531: ciss_complete(struct ciss_softc *sc)
 1532: {
 1533:     struct ciss_request	*cr;
 1534: 
 1535:     debug_called(2);
 1536: 
 1537:     /*
 1538:      * Loop taking requests off the completed queue and performing
 1539:      * completion processing on them.
 1540:      */
 1541:     for (;;) {
 1542: 	if ((cr = ciss_dequeue_complete(sc)) == NULL)
 1543: 	    break;
 1544: 	ciss_unmap_request(cr);
 1545: 	
 1546: 	/*
 1547: 	 * If the request has a callback, invoke it.
 1548: 	 */
 1549: 	if (cr->cr_complete != NULL) {
 1550: 	    cr->cr_complete(cr);
 1551: 	    continue;
 1552: 	}
 1553: 	
 1554: 	/*
 1555: 	 * If someone is sleeping on this request, wake them up.
 1556: 	 */
 1557: 	if (cr->cr_flags & CISS_REQ_SLEEP) {
 1558: 	    cr->cr_flags &= ~CISS_REQ_SLEEP;
 1559: 	    wakeup(cr);
 1560: 	    continue;
 1561: 	}
 1562: 
 1563: 	/*
 1564: 	 * If someone is polling this request for completion, signal.
 1565: 	 */
 1566: 	if (cr->cr_flags & CISS_REQ_POLL) {
 1567: 	    cr->cr_flags &= ~CISS_REQ_POLL;
 1568: 	    continue;
 1569: 	}
 1570: 	
 1571: 	/*
 1572: 	 * Give up and throw the request back on the free queue.  This
 1573: 	 * should never happen; resources will probably be lost.
 1574: 	 */
 1575: 	ciss_printf(sc, "WARNING: completed command with no submitter\n");
 1576: 	ciss_enqueue_free(cr);
 1577:     }
 1578: }
 1579: 
 1580: /************************************************************************
 1581:  * Report on the completion status of a request, and pass back SCSI
 1582:  * and command status values.
 1583:  */
 1584: static int
 1585: ciss_report_request(struct ciss_request *cr, int *command_status, int *scsi_status)
 1586: {
 1587:     struct ciss_command		*cc;
 1588:     struct ciss_error_info	*ce;
 1589: 
 1590:     debug_called(2);
 1591: 
 1592:     cc = CISS_FIND_COMMAND(cr);
 1593:     ce = (struct ciss_error_info *)&(cc->sg[0]);
 1594: 
 1595:     /*
 1596:      * We don't consider data under/overrun an error for the Report
 1597:      * Logical/Physical LUNs commands.
 1598:      */
 1599:     if ((cc->header.host_tag & CISS_HDR_HOST_TAG_ERROR) &&
 1600: 	((cc->cdb.cdb[0] == CISS_OPCODE_REPORT_LOGICAL_LUNS) ||
 1601: 	 (cc->cdb.cdb[0] == CISS_OPCODE_REPORT_PHYSICAL_LUNS))) {
 1602: 	cc->header.host_tag &= ~CISS_HDR_HOST_TAG_ERROR;
 1603: 	debug(2, "ignoring irrelevant under/overrun error");
 1604:     }
 1605:     
 1606:     /*
 1607:      * Check the command's error bit, if clear, there's no status and
 1608:      * everything is OK.
 1609:      */
 1610:     if (!(cc->header.host_tag & CISS_HDR_HOST_TAG_ERROR)) {
 1611: 	if (scsi_status != NULL)
 1612: 	    *scsi_status = SCSI_STATUS_OK;
 1613: 	if (command_status != NULL)
 1614: 	    *command_status = CISS_CMD_STATUS_SUCCESS;
 1615: 	return(0);
 1616:     } else {
 1617: 	if (command_status != NULL)
 1618: 	    *command_status = ce->command_status;
 1619: 	if (scsi_status != NULL) {
 1620: 	    if (ce->command_status == CISS_CMD_STATUS_TARGET_STATUS) {
 1621: 		*scsi_status = ce->scsi_status;
 1622: 	    } else {
 1623: 		*scsi_status = -1;
 1624: 	    }
 1625: 	}
 1626: 	if (bootverbose)
 1627: 	    ciss_printf(cr->cr_sc, "command status 0x%x (%s) scsi status 0x%x\n",
 1628: 			ce->command_status, ciss_name_command_status(ce->command_status),
 1629: 			ce->scsi_status);
 1630: 	if (ce->command_status == CISS_CMD_STATUS_INVALID_COMMAND) {
 1631: 	    ciss_printf(cr->cr_sc, "invalid command, offense size %d at %d, value 0x%x\n",
 1632: 			ce->additional_error_info.invalid_command.offense_size,
 1633: 			ce->additional_error_info.invalid_command.offense_offset,
 1634: 			ce->additional_error_info.invalid_command.offense_value);
 1635: 	}
 1636:     }
 1637:     return(1);
 1638: }
 1639: 
 1640: /************************************************************************
 1641:  * Issue a request and don't return until it's completed.
 1642:  *
 1643:  * Depending on adapter status, we may poll or sleep waiting for
 1644:  * completion.
 1645:  */
 1646: static int
 1647: ciss_synch_request(struct ciss_request *cr, int timeout)
 1648: {
 1649:     if (cr->cr_sc->ciss_flags & CISS_FLAG_RUNNING) {
 1650: 	return(ciss_wait_request(cr, timeout));
 1651:     } else {
 1652: 	return(ciss_poll_request(cr, timeout));
 1653:     }
 1654: }
 1655: 
 1656: /************************************************************************
 1657:  * Issue a request and poll for completion.
 1658:  *
 1659:  * Timeout in milliseconds.
 1660:  */
 1661: static int
 1662: ciss_poll_request(struct ciss_request *cr, int timeout)
 1663: {
 1664:     int		error;
 1665:     
 1666:     debug_called(2);
 1667: 
 1668:     cr->cr_flags |= CISS_REQ_POLL;
 1669:     if ((error = ciss_start(cr)) != 0)
 1670: 	return(error);
 1671: 
 1672:     do {
 1673: 	ciss_done(cr->cr_sc);
 1674: 	if (!(cr->cr_flags & CISS_REQ_POLL))
 1675: 	    return(0);
 1676: 	DELAY(1000);
 1677:     } while (timeout-- >= 0);
 1678:     return(EWOULDBLOCK);
 1679: }
 1680: 
 1681: /************************************************************************
 1682:  * Issue a request and sleep waiting for completion.
 1683:  *
 1684:  * Timeout in milliseconds.  Note that a spurious wakeup will reset
 1685:  * the timeout.
 1686:  */
 1687: static int
 1688: ciss_wait_request(struct ciss_request *cr, int timeout)
 1689: {
 1690:     int		s, error;
 1691: 
 1692:     debug_called(2);
 1693: 
 1694:     cr->cr_flags |= CISS_REQ_SLEEP;
 1695:     if ((error = ciss_start(cr)) != 0)
 1696: 	return(error);
 1697: 
 1698:     s = splcam();
 1699:     while (cr->cr_flags & CISS_REQ_SLEEP) {
 1700: 	error = tsleep(cr, PCATCH, "cissREQ", (timeout * hz) / 1000);
 1701: 	/* 
 1702: 	 * On wakeup or interruption due to restartable activity, go
 1703: 	 * back and check to see if we're done.
 1704: 	 */
 1705: 	if ((error == 0) || (error == ERESTART)) {
 1706: 	    error = 0;
 1707: 	    continue;
 1708: 	}
 1709: 	/*
 1710: 	 * Timeout, interrupted system call, etc.
 1711: 	 */
 1712: 	break;
 1713:     }
 1714:     splx(s);
 1715:     return(error);
 1716: }
 1717: 
 1718: #if 0
 1719: /************************************************************************
 1720:  * Abort a request.  Note that a potential exists here to race the
 1721:  * request being completed; the caller must deal with this.
 1722:  */
 1723: static int
 1724: ciss_abort_request(struct ciss_request *ar)
 1725: {
 1726:     struct ciss_request		*cr;
 1727:     struct ciss_command		*cc;
 1728:     struct ciss_message_cdb	*cmc;
 1729:     int				error;
 1730: 
 1731:     debug_called(1);
 1732: 
 1733:     /* get a request */
 1734:     if ((error = ciss_get_request(ar->cr_sc, &cr)) != 0)
 1735: 	return(error);
 1736: 
 1737:     /* build the abort command */	
 1738:     cc = CISS_FIND_COMMAND(cr);
 1739:     cc->header.address.mode.mode = CISS_HDR_ADDRESS_MODE_PERIPHERAL;	/* addressing? */
 1740:     cc->header.address.physical.target = 0;
 1741:     cc->header.address.physical.bus = 0;
 1742:     cc->cdb.cdb_length = sizeof(*cmc);
 1743:     cc->cdb.type = CISS_CDB_TYPE_MESSAGE;
 1744:     cc->cdb.attribute = CISS_CDB_ATTRIBUTE_SIMPLE;
 1745:     cc->cdb.direction = CISS_CDB_DIRECTION_NONE;
 1746:     cc->cdb.timeout = 30;
 1747: 
 1748:     cmc = (struct ciss_message_cdb *)&(cc->cdb.cdb[0]);
 1749:     cmc->opcode = CISS_OPCODE_MESSAGE_ABORT;
 1750:     cmc->type = CISS_MESSAGE_ABORT_TASK;
 1751:     cmc->abort_tag = ar->cr_tag;	/* endianness?? */
 1752: 
 1753:     /*
 1754:      * Send the request and wait for a response.  If we believe we
 1755:      * aborted the request OK, clear the flag that indicates it's
 1756:      * running.
 1757:      */
 1758:     error = ciss_synch_request(cr, 35 * 1000);
 1759:     if (!error)
 1760: 	error = ciss_report_request(cr, NULL, NULL);
 1761:     ciss_release_request(cr);
 1762: 
 1763:     return(error);
 1764: }
 1765: #endif
 1766: 
 1767: 
 1768: /************************************************************************
 1769:  * Fetch and initialise a request
 1770:  */
 1771: static int
 1772: ciss_get_request(struct ciss_softc *sc, struct ciss_request **crp)
 1773: {
 1774:     struct ciss_request *cr;
 1775: 
 1776:     debug_called(2);
 1777: 
 1778:     /*
 1779:      * Get a request and clean it up.
 1780:      */
 1781:     if ((cr = ciss_dequeue_free(sc)) == NULL)
 1782: 	return(ENOMEM);
 1783: 
 1784:     cr->cr_data = NULL;
 1785:     cr->cr_flags = 0;
 1786:     cr->cr_complete = NULL;
 1787:     
 1788:     ciss_preen_command(cr);
 1789:     *crp = cr;
 1790:     return(0);
 1791: }
 1792: 
 1793: static void
 1794: ciss_preen_command(struct ciss_request *cr)
 1795: {
 1796:     struct ciss_command	*cc;
 1797:     u_int32_t		cmdphys;
 1798: 
 1799:     /*
 1800:      * Clean up the command structure.
 1801:      *
 1802:      * Note that we set up the error_info structure here, since the
 1803:      * length can be overwritten by any command.
 1804:      */
 1805:     cc = CISS_FIND_COMMAND(cr);
 1806:     cc->header.sg_in_list = 0;		/* kinda inefficient this way */
 1807:     cc->header.sg_total = 0;
 1808:     cc->header.host_tag = cr->cr_tag << 2;
 1809:     cc->header.host_tag_zeroes = 0;
 1810:     cmdphys = CISS_FIND_COMMANDPHYS(cr);
 1811:     cc->error_info.error_info_address = cmdphys + sizeof(struct ciss_command);
 1812:     cc->error_info.error_info_length = CISS_COMMAND_ALLOC_SIZE - sizeof(struct ciss_command);
 1813:     
 1814: }
 1815: 
 1816: /************************************************************************
 1817:  * Release a request to the free list.
 1818:  */
 1819: static void
 1820: ciss_release_request(struct ciss_request *cr)
 1821: {
 1822:     struct ciss_softc	*sc;
 1823: 
 1824:     debug_called(2);
 1825: 
 1826:     sc = cr->cr_sc;
 1827:     
 1828:     /* release the request to the free queue */
 1829:     ciss_requeue_free(cr);
 1830: }
 1831: 
 1832: /************************************************************************
 1833:  * Allocate a request that will be used to send a BMIC command.  Do some
 1834:  * of the common setup here to avoid duplicating it everywhere else.
 1835:  */
 1836: static int
 1837: ciss_get_bmic_request(struct ciss_softc *sc, struct ciss_request **crp,
 1838: 		      int opcode, void **bufp, size_t bufsize)
 1839: {
 1840:     struct ciss_request		*cr;
 1841:     struct ciss_command		*cc;
 1842:     struct ciss_bmic_cdb	*cbc;
 1843:     void			*buf;
 1844:     int				error;
 1845:     int				dataout;
 1846: 
 1847:     debug_called(2);
 1848: 
 1849:     cr = NULL;
 1850:     buf = NULL;	
 1851: 
 1852:     /*
 1853:      * Get a request.
 1854:      */
 1855:     if ((error = ciss_get_request(sc, &cr)) != 0)
 1856: 	goto out;
 1857: 
 1858:     /*
 1859:      * Allocate data storage if requested, determine the data direction.
 1860:      */
 1861:     dataout = 0;
 1862:     if ((bufsize > 0) && (bufp != NULL)) {
 1863: 	if (*bufp == NULL) {
 1864: 	    if ((buf = malloc(bufsize, CISS_MALLOC_CLASS, M_NOWAIT | M_ZERO)) == NULL) {
 1865: 		error = ENOMEM;
 1866: 		goto out;
 1867: 	    }
 1868: 	} else {
 1869: 	    buf = *bufp;
 1870: 	    dataout = 1;	/* we are given a buffer, so we are writing */
 1871: 	}
 1872:     }
 1873: 
 1874:     /*
 1875:      * Build a CISS BMIC command to get the logical drive ID.
 1876:      */
 1877:     cr->cr_data = buf;
 1878:     cr->cr_length = bufsize;
 1879:     if (!dataout)
 1880: 	cr->cr_flags = CISS_REQ_DATAIN;
 1881:     
 1882:     cc = CISS_FIND_COMMAND(cr);
 1883:     cc->header.address.physical.mode = CISS_HDR_ADDRESS_MODE_PERIPHERAL;
 1884:     cc->header.address.physical.bus = 0;
 1885:     cc->header.address.physical.target = 0;
 1886:     cc->cdb.cdb_length = sizeof(*cbc);
 1887:     cc->cdb.type = CISS_CDB_TYPE_COMMAND;
 1888:     cc->cdb.attribute = CISS_CDB_ATTRIBUTE_SIMPLE;
 1889:     cc->cdb.direction = dataout ? CISS_CDB_DIRECTION_WRITE : CISS_CDB_DIRECTION_READ;
 1890:     cc->cdb.timeout = 0;
 1891: 
 1892:     cbc = (struct ciss_bmic_cdb *)&(cc->cdb.cdb[0]);
 1893:     bzero(cbc, sizeof(*cbc));
 1894:     cbc->opcode = dataout ? CISS_ARRAY_CONTROLLER_WRITE : CISS_ARRAY_CONTROLLER_READ;
 1895:     cbc->bmic_opcode = opcode;
 1896:     cbc->size = htons((u_int16_t)bufsize);
 1897: 
 1898: out:
 1899:     if (error) {
 1900: 	if (cr != NULL)
 1901: 	    ciss_release_request(cr);
 1902: 	if ((bufp != NULL) && (*bufp == NULL) && (buf != NULL))
 1903: 	    free(buf, CISS_MALLOC_CLASS);
 1904:     } else {
 1905: 	*crp = cr;
 1906: 	if ((bufp != NULL) && (*bufp == NULL) && (buf != NULL))
 1907: 	    *bufp = buf;
 1908:     }
 1909:     return(error);
 1910: }
 1911: 
 1912: /************************************************************************
 1913:  * Handle a command passed in from userspace.
 1914:  */
 1915: static int
 1916: ciss_user_command(struct ciss_softc *sc, IOCTL_Command_struct *ioc)
 1917: {
 1918:     struct ciss_request		*cr;
 1919:     struct ciss_command		*cc;
 1920:     struct ciss_error_info	*ce;
 1921:     int				error;
 1922: 
 1923:     debug_called(1);
 1924: 
 1925:     cr = NULL;
 1926: 
 1927:     /*
 1928:      * Get a request.
 1929:      */
 1930:     if ((error = ciss_get_request(sc, &cr)) != 0)
 1931: 	goto out;
 1932:     cc = CISS_FIND_COMMAND(cr);
 1933: 
 1934:     /*
 1935:      * Allocate an in-kernel databuffer if required, copy in user data.
 1936:      */
 1937:     cr->cr_length = ioc->buf_size;
 1938:     if (ioc->buf_size > 0) {
 1939: 	if ((cr->cr_data = malloc(ioc->buf_size, CISS_MALLOC_CLASS, M_WAITOK)) == NULL) {
 1940: 	    error = ENOMEM;
 1941: 	    goto out;
 1942: 	}
 1943: 	if ((error = copyin(ioc->buf, cr->cr_data, ioc->buf_size))) {
 1944: 	    debug(0, "copyin: bad data buffer %p/%d", ioc->buf, ioc->buf_size);
 1945: 	    goto out;
 1946: 	}
 1947:     }
 1948: 
 1949:     /*
 1950:      * Build the request based on the user command.
 1951:      */
 1952:     bcopy(&ioc->LUN_info, &cc->header.address, sizeof(cc->header.address));
 1953:     bcopy(&ioc->Request, &cc->cdb, sizeof(cc->cdb));
 1954: 
 1955:     /* XXX anything else to populate here? */
 1956: 
 1957:     /*
 1958:      * Run the command.
 1959:      */
 1960:     if ((error = ciss_synch_request(cr, 60 * 1000))) {
 1961: 	debug(0, "request failed - %d", error);
 1962: 	goto out;
 1963:     }
 1964: 
 1965:     /*
 1966:      * Copy the results back to the user.
 1967:      */
 1968:     ce = (struct ciss_error_info *)&(cc->sg[0]);
 1969:     bcopy(ce, &ioc->error_info, sizeof(*ce));
 1970:     if ((ioc->buf_size > 0) &&
 1971: 	(error = copyout(cr->cr_data, ioc->buf, ioc->buf_size))) {
 1972: 	debug(0, "copyout: bad data buffer %p/%d", ioc->buf, ioc->buf_size);
 1973: 	goto out;
 1974:     }
 1975: 
 1976:     /* done OK */
 1977:     error = 0;
 1978: 
 1979: out:
 1980:     if ((cr != NULL) && (cr->cr_data != NULL))
 1981: 	free(cr->cr_data, CISS_MALLOC_CLASS);
 1982:     if (cr != NULL)
 1983: 	ciss_release_request(cr);
 1984:     return(error);
 1985: }
 1986: 
 1987: /************************************************************************
 1988:  * Map a request into bus-visible space, initialise the scatter/gather
 1989:  * list.
 1990:  */
 1991: static int
 1992: ciss_map_request(struct ciss_request *cr)
 1993: {
 1994:     struct ciss_softc	*sc;
 1995: 
 1996:     debug_called(2);
 1997:     
 1998:     sc = cr->cr_sc;
 1999: 
 2000:     /* check that mapping is necessary */
 2001:     if ((cr->cr_flags & CISS_REQ_MAPPED) || (cr->cr_data == NULL))
 2002: 	return(0);
 2003:     
 2004:     bus_dmamap_load(sc->ciss_buffer_dmat, cr->cr_datamap, cr->cr_data, cr->cr_length,
 2005: 		    ciss_request_map_helper, CISS_FIND_COMMAND(cr), 0);
 2006: 	
 2007:     if (cr->cr_flags & CISS_REQ_DATAIN)
 2008: 	bus_dmamap_sync(sc->ciss_buffer_dmat, cr->cr_datamap, BUS_DMASYNC_PREREAD);
 2009:     if (cr->cr_flags & CISS_REQ_DATAOUT)
 2010: 	bus_dmamap_sync(sc->ciss_buffer_dmat, cr->cr_datamap, BUS_DMASYNC_PREWRITE);
 2011: 
 2012:     cr->cr_flags |= CISS_REQ_MAPPED;
 2013:     return(0);
 2014: }
 2015: 
 2016: static void
 2017: ciss_request_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error)
 2018: {
 2019:     struct ciss_command	*cc;
 2020:     int			i;
 2021: 
 2022:     debug_called(2);
 2023:     
 2024:     cc = (struct ciss_command *)arg;
 2025:     for (i = 0; i < nseg; i++) {
 2026: 	cc->sg[i].address = segs[i].ds_addr;
 2027: 	cc->sg[i].length = segs[i].ds_len;
 2028: 	cc->sg[i].extension = 0;
 2029:     }
 2030:     /* we leave the s/g table entirely within the command */
 2031:     cc->header.sg_in_list = nseg;
 2032:     cc->header.sg_total = nseg;
 2033: }
 2034: 
 2035: /************************************************************************
 2036:  * Unmap a request from bus-visible space.
 2037:  */
 2038: static void
 2039: ciss_unmap_request(struct ciss_request *cr)
 2040: {
 2041:     struct ciss_softc	*sc;
 2042: 
 2043:     debug_called(2);
 2044:     
 2045:     sc = cr->cr_sc;
 2046: 
 2047:     /* check that unmapping is necessary */
 2048:     if (!(cr->cr_flags & CISS_REQ_MAPPED) || (cr->cr_data == NULL))
 2049: 	return;
 2050: 
 2051:     if (cr->cr_flags & CISS_REQ_DATAIN)
 2052: 	bus_dmamap_sync(sc->ciss_buffer_dmat, cr->cr_datamap, BUS_DMASYNC_POSTREAD);
 2053:     if (cr->cr_flags & CISS_REQ_DATAOUT)
 2054: 	bus_dmamap_sync(sc->ciss_buffer_dmat, cr->cr_datamap, BUS_DMASYNC_POSTWRITE);
 2055: 
 2056:     bus_dmamap_unload(sc->ciss_buffer_dmat, cr->cr_datamap);
 2057:     cr->cr_flags &= ~CISS_REQ_MAPPED;
 2058: }
 2059: 
 2060: /************************************************************************
 2061:  * Attach the driver to CAM.
 2062:  *
 2063:  * We put all the logical drives on a single SCSI bus.
 2064:  */
 2065: static int
 2066: ciss_cam_init(struct ciss_softc *sc)
 2067: {
 2068: 
 2069:     debug_called(1);
 2070: 
 2071:     /*
 2072:      * Allocate a devq.  We can reuse this for the masked physical
 2073:      * devices if we decide to export these as well.
 2074:      */
 2075:     if ((sc->ciss_cam_devq = cam_simq_alloc(sc->ciss_max_requests)) == NULL) {
 2076: 	ciss_printf(sc, "can't allocate CAM SIM queue\n");
 2077: 	return(ENOMEM);
 2078:     }
 2079: 
 2080:     /*
 2081:      * Create a SIM.
 2082:      */
 2083:     if ((sc->ciss_cam_sim = cam_sim_alloc(ciss_cam_action, ciss_cam_poll, "ciss", sc,
 2084: 					  device_get_unit(sc->ciss_dev),
 2085: 					  sc->ciss_max_requests - 2,
 2086: 					  1,
 2087: 					  sc->ciss_cam_devq)) == NULL) {
 2088: 	ciss_printf(sc, "can't allocate CAM SIM\n");
 2089: 	return(ENOMEM);
 2090:     }
 2091: 
 2092:     /*
 2093:      * Register bus 0 (the 'logical drives' bus) with this SIM.
 2094:      */
 2095:     if (xpt_bus_register(sc->ciss_cam_sim, 0) != 0) {
 2096: 	ciss_printf(sc, "can't register SCSI bus 0\n");
 2097: 	return(ENXIO);
 2098:     }
 2099: 
 2100:     /*
 2101:      * Initiate a rescan of the bus.
 2102:      */
 2103:     ciss_cam_rescan_all(sc);
 2104:     
 2105:     return(0);
 2106: }
 2107: 
 2108: /************************************************************************
 2109:  * Initiate a rescan of the 'logical devices' SIM
 2110:  */ 
 2111: static void
 2112: ciss_cam_rescan_target(struct ciss_softc *sc, int target)
 2113: {
 2114:     union ccb	*ccb;
 2115: 
 2116:     debug_called(1);
 2117: 
 2118:     if ((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK | M_ZERO)) == NULL) {
 2119: 	ciss_printf(sc, "rescan failed (can't allocate CCB)\n");
 2120: 	return;
 2121:     }
 2122:     
 2123:     if (xpt_create_path(&sc->ciss_cam_path, xpt_periph, cam_sim_path(sc->ciss_cam_sim), target, 0)
 2124: 	!= CAM_REQ_CMP) {
 2125: 	ciss_printf(sc, "rescan failed (can't create path)\n");
 2126: 	return;
 2127:     }
 2128:     
 2129:     xpt_setup_ccb(&ccb->ccb_h, sc->ciss_cam_path, 5/*priority (low)*/);
 2130:     ccb->ccb_h.func_code = XPT_SCAN_BUS;
 2131:     ccb->ccb_h.cbfcnp = ciss_cam_rescan_callback;
 2132:     ccb->crcn.flags = CAM_FLAG_NONE;
 2133:     xpt_action(ccb);
 2134:  
 2135:     /* scan is now in progress */
 2136: }
 2137: 
 2138: static void
 2139: ciss_cam_rescan_all(struct ciss_softc *sc)
 2140: {
 2141:     return(ciss_cam_rescan_target(sc, 0));
 2142: }
 2143: 
 2144: static void
 2145: ciss_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb)
 2146: {
 2147:     xpt_free_path(ccb->ccb_h.path);
 2148:     free(ccb, M_TEMP);
 2149: }
 2150: 
 2151: /************************************************************************
 2152:  * Handle requests coming from CAM
 2153:  */
 2154: static void
 2155: ciss_cam_action(struct cam_sim *sim, union ccb *ccb)
 2156: {
 2157:     struct ciss_softc	*sc;
 2158:     struct ccb_scsiio	*csio;
 2159:     int			target;
 2160: 
 2161:     sc = cam_sim_softc(sim);
 2162:     csio = (struct ccb_scsiio *)&ccb->csio;
 2163:     target = csio->ccb_h.target_id;
 2164: 
 2165:     switch (ccb->ccb_h.func_code) {
 2166: 
 2167: 	/* perform SCSI I/O */
 2168:     case XPT_SCSI_IO:
 2169: 	if (!ciss_cam_action_io(sim, csio))
 2170: 	    return;
 2171: 	break;
 2172: 
 2173: 	/* perform geometry calculations */
 2174:     case XPT_CALC_GEOMETRY:
 2175:     {
 2176: 	struct ccb_calc_geometry	*ccg = &ccb->ccg;
 2177: 	struct ciss_ldrive		*ld = &sc->ciss_logical[target];
 2178: 
 2179: 	debug(1, "XPT_CALC_GEOMETRY %d:%d:%d", cam_sim_bus(sim), ccb->ccb_h.target_id, ccb->ccb_h.target_lun);
 2180: 
 2181: 	/*
 2182: 	 * Use the cached geometry settings unless the fault tolerance
 2183: 	 * is invalid.
 2184: 	 */
 2185: 	if (ld->cl_geometry.fault_tolerance == 0xFF) {
 2186: 	    u_int32_t			secs_per_cylinder;
 2187: 
 2188: 	    ccg->heads = 255;
 2189: 	    ccg->secs_per_track = 32;
 2190: 	    secs_per_cylinder = ccg->heads * ccg->secs_per_track;
 2191: 	    ccg->cylinders = ccg->volume_size / secs_per_cylinder;
 2192: 	} else {
 2193: 	    ccg->heads = ld->cl_geometry.heads;
 2194: 	    ccg->secs_per_track = ld->cl_geometry.sectors;
 2195: 	    ccg->cylinders = ntohs(ld->cl_geometry.cylinders);
 2196: 	}
 2197: 	ccb->ccb_h.status = CAM_REQ_CMP;
 2198:         break;
 2199:     }
 2200: 
 2201: 	/* handle path attribute inquiry */
 2202:     case XPT_PATH_INQ:
 2203:     {
 2204: 	struct ccb_pathinq	*cpi = &ccb->cpi;
 2205: 
 2206: 	debug(1, "XPT_PATH_INQ %d:%d:%d", cam_sim_bus(sim), ccb->ccb_h.target_id, ccb->ccb_h.target_lun);
 2207: 
 2208: 	cpi->version_num = 1;
 2209: 	cpi->hba_inquiry = PI_TAG_ABLE;	/* XXX is this correct? */
 2210: 	cpi->target_sprt = 0;
 2211: 	cpi->hba_misc = 0;
 2212: 	cpi->max_target = CISS_MAX_LOGICAL;
 2213: 	cpi->max_lun = 0;		/* 'logical drive' channel only */
 2214: 	cpi->initiator_id = CISS_MAX_LOGICAL;
 2215: 	strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
 2216:         strncpy(cpi->hba_vid, "msmith@freebsd.org", HBA_IDLEN);
 2217:         strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
 2218:         cpi->unit_number = cam_sim_unit(sim);
 2219:         cpi->bus_id = cam_sim_bus(sim);
 2220: 	cpi->base_transfer_speed = 132 * 1024;	/* XXX what to set this to? */
 2221: 	ccb->ccb_h.status = CAM_REQ_CMP;
 2222: 	break;
 2223:     }
 2224: 
 2225:     case XPT_GET_TRAN_SETTINGS:
 2226:     {
 2227: 	struct ccb_trans_settings	*cts = &ccb->cts;
 2228: 	int				bus, target;
 2229: 
 2230: 	bus = cam_sim_bus(sim);
 2231: 	target = cts->ccb_h.target_id;
 2232: 
 2233: 	debug(1, "XPT_GET_TRAN_SETTINGS %d:%d", bus, target);
 2234: 	cts->valid = 0;
 2235: 
 2236: 	/* disconnect always OK */
 2237: 	cts->flags |= CCB_TRANS_DISC_ENB;
 2238: 	cts->valid |= CCB_TRANS_DISC_VALID;
 2239: 
 2240: 	cts->ccb_h.status = CAM_REQ_CMP;
 2241: 	break;
 2242:     }
 2243: 
 2244:     default:		/* we can't do this */
 2245: 	debug(1, "unspported func_code = 0x%x", ccb->ccb_h.func_code);
 2246: 	ccb->ccb_h.status = CAM_REQ_INVALID;
 2247: 	break;
 2248:     }
 2249: 
 2250:     xpt_done(ccb);
 2251: }
 2252: 
 2253: /************************************************************************
 2254:  * Handle a CAM SCSI I/O request.
 2255:  */
 2256: static int
 2257: ciss_cam_action_io(struct cam_sim *sim, struct ccb_scsiio *csio)
 2258: {
 2259:     struct ciss_softc	*sc;
 2260:     int			bus, target;
 2261:     struct ciss_request	*cr;
 2262:     struct ciss_command	*cc;
 2263:     int			error;
 2264: 
 2265:     sc = cam_sim_softc(sim);
 2266:     bus = cam_sim_bus(sim);
 2267:     target = csio->ccb_h.target_id;
 2268: 
 2269:     debug(2, "XPT_SCSI_IO %d:%d:%d", bus, target, csio->ccb_h.target_lun);
 2270: 
 2271:     /* check for I/O attempt to nonexistent device */
 2272:     if ((bus != 0) ||
 2273: 	(target > CISS_MAX_LOGICAL) ||
 2274: 	(sc->ciss_logical[target].cl_status == CISS_LD_NONEXISTENT)) {
 2275: 	debug(3, "  device does not exist");
 2276: 	csio->ccb_h.status = CAM_REQ_CMP_ERR;
 2277:     }
 2278: 
 2279:     /* firmware does not support commands > 10 bytes */
 2280:     if (csio->cdb_len > 12/*CISS_CDB_BUFFER_SIZE*/) {
 2281: 	debug(3, "  command too large (%d > %d)", csio->cdb_len, CISS_CDB_BUFFER_SIZE);
 2282: 	csio->ccb_h.status = CAM_REQ_CMP_ERR;
 2283:     }
 2284: 
 2285:     /* check that the CDB pointer is not to a physical address */
 2286:     if ((csio->ccb_h.flags & CAM_CDB_POINTER) && (csio->ccb_h.flags & CAM_CDB_PHYS)) {
 2287: 	debug(3, "  CDB pointer is to physical address");
 2288: 	csio->ccb_h.status = CAM_REQ_CMP_ERR;
 2289:     }
 2290: 
 2291:     /* if there is data transfer, it must be to/from a virtual address */
 2292:     if ((csio->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
 2293: 	if (csio->ccb_h.flags & CAM_DATA_PHYS) {		/* we can't map it */
 2294: 	    debug(3, "  data pointer is to physical address");
 2295: 	    csio->ccb_h.status = CAM_REQ_CMP_ERR;
 2296: 	}
 2297: 	if (csio->ccb_h.flags & CAM_SCATTER_VALID) {	/* we want to do the s/g setup */
 2298: 	    debug(3, "  data has premature s/g setup");
 2299: 	    csio->ccb_h.status = CAM_REQ_CMP_ERR;
 2300: 	}
 2301:     }
 2302: 
 2303:     /* abandon aborted ccbs or those that have failed validation */
 2304:     if ((csio->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
 2305: 	debug(3, "abandoning CCB due to abort/validation failure");
 2306: 	return(EINVAL);
 2307:     }
 2308: 
 2309:     /* handle emulation of some SCSI commands ourself */
 2310:     if (ciss_cam_emulate(sc, csio))
 2311: 	return(0);
 2312: 
 2313:     /*
 2314:      * Get a request to manage this command.  If we can't, return the
 2315:      * ccb, freeze the queue and flag so that we unfreeze it when a
 2316:      * request completes.
 2317:      */
 2318:     if ((error = ciss_get_request(sc, &cr)) != 0) {
 2319: 	xpt_freeze_simq(sc->ciss_cam_sim, 1);
 2320: 	csio->ccb_h.status |= CAM_REQUEUE_REQ;
 2321: 	return(error);
 2322:     }
 2323: 
 2324:     /*
 2325:      * Build the command.
 2326:      */
 2327:     cc = CISS_FIND_COMMAND(cr);
 2328:     cr->cr_data = csio->data_ptr;
 2329:     cr->cr_length = csio->dxfer_len;
 2330:     cr->cr_complete = ciss_cam_complete;
 2331:     cr->cr_private = csio;
 2332: 	
 2333:     cc->header.address.logical.mode = CISS_HDR_ADDRESS_MODE_LOGICAL;
 2334:     cc->header.address.logical.lun = target;
 2335:     cc->cdb.cdb_length = csio->cdb_len;
 2336:     cc->cdb.type = CISS_CDB_TYPE_COMMAND;
 2337:     cc->cdb.attribute = CISS_CDB_ATTRIBUTE_SIMPLE;	/* XXX ordered tags? */
 2338:     if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) {
 2339: 	cr->cr_flags = CISS_REQ_DATAOUT;
 2340: 	cc->cdb.direction = CISS_CDB_DIRECTION_WRITE;
 2341:     } else if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
 2342: 	cr->cr_flags = CISS_REQ_DATAIN;
 2343: 	cc->cdb.direction = CISS_CDB_DIRECTION_READ;
 2344:     } else {
 2345: 	cr->cr_flags = 0;
 2346: 	cc->cdb.direction = CISS_CDB_DIRECTION_NONE;
 2347:     }
 2348:     cc->cdb.timeout = (csio->ccb_h.timeout / 1000) + 1;
 2349:     if (csio->ccb_h.flags & CAM_CDB_POINTER) {
 2350: 	bcopy(csio->cdb_io.cdb_ptr, &cc->cdb.cdb[0], csio->cdb_len);
 2351:     } else {
 2352: 	bcopy(csio->cdb_io.cdb_bytes, &cc->cdb.cdb[0], csio->cdb_len);
 2353:     }
 2354: 
 2355:     /*
 2356:      * Submit the request to the adapter.
 2357:      *
 2358:      * Note that this may fail if we're unable to map the request (and
 2359:      * if we ever learn a transport layer other than simple, may fail
 2360:      * if the adapter rejects the command).
 2361:      */
 2362:     if ((error = ciss_start(cr)) != 0) {
 2363: 	xpt_freeze_simq(sc->ciss_cam_sim, 1);
 2364: 	csio->ccb_h.status |= CAM_REQUEUE_REQ;
 2365: 	ciss_release_request(cr);
 2366: 	return(error);
 2367:     }
 2368: 	
 2369:     return(0);
 2370: }
 2371: 
 2372: /************************************************************************
 2373:  * Emulate SCSI commands the adapter doesn't handle as we might like.
 2374:  */
 2375: static int
 2376: ciss_cam_emulate(struct ciss_softc *sc, struct ccb_scsiio *csio)
 2377: {
 2378:     int		target;
 2379:     u_int8_t	opcode;
 2380:     
 2381:     
 2382:     target = csio->ccb_h.target_id;
 2383:     opcode = (csio->ccb_h.flags & CAM_CDB_POINTER) ? 
 2384: 	*(u_int8_t *)csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes[0];
 2385: 
 2386:     /*
 2387:      * Handle requests for volumes that don't exist.  A selection timeout
 2388:      * is slightly better than an illegal request.  Other errors might be 
 2389:      * better.
 2390:      */
 2391:     if (sc->ciss_logical[target].cl_status == CISS_LD_NONEXISTENT) {
 2392: 	csio->ccb_h.status = CAM_SEL_TIMEOUT;
 2393: 	xpt_done((union ccb *)csio);
 2394: 	return(1);
 2395:     }
 2396: 
 2397:     /*
 2398:      * Handle requests for volumes that exist but are offline.
 2399:      *
 2400:      * I/O operations should fail, everything else should work.
 2401:      */
 2402:     if (sc->ciss_logical[target].cl_status == CISS_LD_OFFLINE) {
 2403: 	switch(opcode) {
 2404: 	case READ_6:
 2405: 	case READ_10:
 2406: 	case READ_12:
 2407: 	case WRITE_6:
 2408: 	case WRITE_10:
 2409: 	case WRITE_12:
 2410: 	    csio->ccb_h.status = CAM_SEL_TIMEOUT;
 2411: 	    xpt_done((union ccb *)csio);
 2412: 	    return(1);
 2413: 	}
 2414:     }
 2415: 	    
 2416: 
 2417:     /* if we have to fake Synchronise Cache */
 2418:     if (sc->ciss_flags & CISS_FLAG_FAKE_SYNCH) {
 2419: 	
 2420: 	/*
 2421: 	 * If this is a Synchronise Cache command, typically issued when
 2422: 	 * a device is closed, flush the adapter and complete now.
 2423: 	 */
 2424: 	if (((csio->ccb_h.flags & CAM_CDB_POINTER) ? 
 2425: 	     *(u_int8_t *)csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes[0]) == SYNCHRONIZE_CACHE) {
 2426: 	    ciss_flush_adapter(sc);
 2427: 	    csio->ccb_h.status = CAM_REQ_CMP;
 2428: 	    xpt_done((union ccb *)csio);
 2429: 	    return(1);
 2430: 	}
 2431:     }
 2432: 
 2433:     return(0);
 2434: }
 2435: 
 2436: /************************************************************************
 2437:  * Check for possibly-completed commands.
 2438:  */
 2439: static void
 2440: ciss_cam_poll(struct cam_sim *sim)
 2441: {
 2442:     struct ciss_softc	*sc = cam_sim_softc(sim);
 2443: 
 2444:     debug_called(2);
 2445: 
 2446:     ciss_done(sc);
 2447: }
 2448: 
 2449: /************************************************************************
 2450:  * Handle completion of a command - pass results back through the CCB
 2451:  */
 2452: static void
 2453: ciss_cam_complete(struct ciss_request *cr)
 2454: {
 2455:     struct ciss_softc		*sc;
 2456:     struct ciss_command		*cc;
 2457:     struct ciss_error_info	*ce;
 2458:     struct ccb_scsiio		*csio;
 2459:     int				scsi_status;
 2460:     int				command_status;
 2461: 
 2462:     debug_called(2);
 2463: 
 2464:     sc = cr->cr_sc;
 2465:     cc = CISS_FIND_COMMAND(cr);
 2466:     ce = (struct ciss_error_info *)&(cc->sg[0]);
 2467:     csio = (struct ccb_scsiio *)cr->cr_private;
 2468: 
 2469:     /*
 2470:      * Extract status values from request.
 2471:      */
 2472:     ciss_report_request(cr, &command_status, &scsi_status);
 2473:     csio->scsi_status = scsi_status;
 2474:     
 2475:     /*
 2476:      * Handle specific SCSI status values.
 2477:      */
 2478:     switch(scsi_status) {
 2479: 	/* no status due to adapter error */
 2480:     case -1:				
 2481: 	debug(0, "adapter error");
 2482: 	csio->ccb_h.status = CAM_REQ_CMP_ERR;
 2483: 	break;
 2484: 	
 2485: 	/* no status due to command completed OK */
 2486:     case SCSI_STATUS_OK:		/* CISS_SCSI_STATUS_GOOD */
 2487: 	debug(2, "SCSI_STATUS_OK");
 2488: 	csio->ccb_h.status = CAM_REQ_CMP;
 2489: 	break;
 2490: 
 2491: 	/* check condition, sense data included */
 2492:     case SCSI_STATUS_CHECK_COND:	/* CISS_SCSI_STATUS_CHECK_CONDITION */
 2493: 	debug(0, "SCSI_STATUS_CHECK_COND  sense size %d  resid %d",
 2494: 	      ce->sense_length, ce->residual_count);
 2495: 	bzero(&csio->sense_data, SSD_FULL_SIZE);
 2496: 	bcopy(&ce->sense_info[0], &csio->sense_data, ce->sense_length);
 2497: 	csio->sense_len = ce->sense_length;
 2498: 	csio->resid = ce->residual_count;	
 2499: 	csio->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID;
 2500: #ifdef CISS_DEBUG
 2501: 	{
 2502: 	    struct scsi_sense_data	*sns = (struct scsi_sense_data *)&ce->sense_info[0];
 2503: 	    debug(0, "sense key %x", sns->flags & SSD_KEY);
 2504: 	}
 2505: #endif	    
 2506: 	break;
 2507: 
 2508:     case SCSI_STATUS_BUSY:		/* CISS_SCSI_STATUS_BUSY */
 2509: 	debug(0, "SCSI_STATUS_BUSY");
 2510: 	csio->ccb_h.status = CAM_SCSI_BUSY;
 2511: 	break;
 2512: 
 2513:     default:
 2514: 	debug(0, "unknown status 0x%x", csio->scsi_status);
 2515: 	csio->ccb_h.status = CAM_REQ_CMP_ERR;
 2516: 	break;
 2517:     }
 2518: 
 2519:     /* handle post-command fixup */
 2520:     ciss_cam_complete_fixup(sc, csio);
 2521: 
 2522:     /* tell CAM we're ready for more commands */
 2523:     csio->ccb_h.status |= CAM_RELEASE_SIMQ;
 2524: 
 2525:     xpt_done((union ccb *)csio);
 2526:     ciss_release_request(cr);
 2527: }
 2528: 
 2529: /********************************************************************************
 2530:  * Fix up the result of some commands here.
 2531:  */
 2532: static void
 2533: ciss_cam_complete_fixup(struct ciss_softc *sc, struct ccb_scsiio *csio)
 2534: {
 2535:     struct scsi_inquiry_data	*inq;
 2536:     struct ciss_ldrive		*cl;
 2537:     int				target;
 2538: 
 2539:     if (((csio->ccb_h.flags & CAM_CDB_POINTER) ? 
 2540: 	 *(u_int8_t *)csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes[0]) == INQUIRY) {
 2541: 
 2542: 	inq = (struct scsi_inquiry_data *)csio->data_ptr;
 2543: 	target = csio->ccb_h.target_id;
 2544: 	cl = &sc->ciss_logical[target];
 2545: 	
 2546: 	padstr(inq->vendor, "COMPAQ", 8);
 2547: 	padstr(inq->product, ciss_name_ldrive_org(cl->cl_ldrive->fault_tolerance), 8);
 2548: 	padstr(inq->revision, ciss_name_ldrive_status(cl->cl_lstatus->status), 16);
 2549:     }
 2550: }
 2551: 
 2552: 
 2553: /********************************************************************************
 2554:  * Find a peripheral attached at (target)
 2555:  */
 2556: static struct cam_periph *
 2557: ciss_find_periph(struct ciss_softc *sc, int target)
 2558: {
 2559:     struct cam_periph	*periph;
 2560:     struct cam_path	*path;
 2561:     int			status;
 2562: 
 2563:     status = xpt_create_path(&path, NULL, cam_sim_path(sc->ciss_cam_sim), target, 0);
 2564:     if (status == CAM_REQ_CMP) {
 2565: 	periph = cam_periph_find(path, NULL);
 2566: 	xpt_free_path(path);
 2567:     } else {
 2568: 	periph = NULL;
 2569:     }
 2570:     return(periph);
 2571: }
 2572: 
 2573: /********************************************************************************
 2574:  * Name the device at (target)
 2575:  *
 2576:  * XXX is this strictly correct?
 2577:  */
 2578: int
 2579: ciss_name_device(struct ciss_softc *sc, int target)
 2580: {
 2581:     struct cam_periph	*periph;
 2582: 
 2583:     if ((periph = ciss_find_periph(sc, target)) != NULL) {
 2584: 	sprintf(sc->ciss_logical[target].cl_name, "%s%d", periph->periph_name, periph->unit_number);
 2585: 	return(0);
 2586:     }
 2587:     sc->ciss_logical[target].cl_name[0] = 0;
 2588:     return(ENOENT);
 2589: }
 2590: 
 2591: /************************************************************************
 2592:  * Periodic status monitoring.
 2593:  */
 2594: static void
 2595: ciss_periodic(void *arg)
 2596: {
 2597:     struct ciss_softc	*sc;
 2598: 
 2599:     debug_called(1);
 2600:     
 2601:     sc = (struct ciss_softc *)arg;
 2602: 
 2603:     /*
 2604:      * Check the adapter heartbeat.
 2605:      */
 2606:     if (sc->ciss_cfg->heartbeat == sc->ciss_heartbeat) {
 2607: 	sc->ciss_heart_attack++;
 2608: 	debug(0, "adapter heart attack in progress 0x%x/%d", 
 2609: 	      sc->ciss_heartbeat, sc->ciss_heart_attack);
 2610: 	if (sc->ciss_heart_attack == 3) {
 2611: 	    ciss_printf(sc, "ADAPTER HEARTBEAT FAILED\n");
 2612: 	    /* XXX should reset adapter here */
 2613: 	}
 2614:     } else {
 2615: 	sc->ciss_heartbeat = sc->ciss_cfg->heartbeat;
 2616: 	sc->ciss_heart_attack = 0;
 2617: 	debug(3, "new heartbeat 0x%x", sc->ciss_heartbeat);
 2618:     }
 2619:     
 2620:     /*
 2621:      * If the notify event request has died for some reason, or has
 2622:      * not started yet, restart it.
 2623:      */
 2624:     if (!(sc->ciss_flags & CISS_FLAG_NOTIFY_OK)) {
 2625: 	debug(0, "(re)starting Event Notify chain");
 2626: 	ciss_notify_event(sc);
 2627:     }
 2628: 
 2629:     /*
 2630:      * Reschedule.
 2631:      */
 2632:     if (!(sc->ciss_flags & CISS_FLAG_ABORTING))
 2633: 	sc->ciss_periodic = timeout(ciss_periodic, sc, CISS_HEARTBEAT_RATE * hz);
 2634: }
 2635: 
 2636: /************************************************************************
 2637:  * Request a notification response from the adapter.
 2638:  *
 2639:  * If (cr) is NULL, this is the first request of the adapter, so
 2640:  * reset the adapter's message pointer and start with the oldest
 2641:  * message available.
 2642:  */
 2643: static void
 2644: ciss_notify_event(struct ciss_softc *sc)
 2645: {
 2646:     struct ciss_request		*cr;
 2647:     struct ciss_command		*cc;
 2648:     struct ciss_notify_cdb	*cnc;
 2649:     int				error;
 2650: 
 2651:     debug_called(1);
 2652: 
 2653:     cr = sc->ciss_periodic_notify;
 2654:     
 2655:     /* get a request if we don't already have one */
 2656:     if (cr == NULL) {
 2657: 	if ((error = ciss_get_request(sc, &cr)) != 0) {
 2658: 	    debug(0, "can't get notify event request");
 2659: 	    goto out;
 2660: 	}
 2661: 	sc->ciss_periodic_notify = cr;
 2662: 	cr->cr_complete = ciss_notify_complete;
 2663: 	debug(1, "acquired request %d", cr->cr_tag);
 2664:     }
 2665:     
 2666:     /* 
 2667:      * Get a databuffer if we don't already have one, note that the
 2668:      * adapter command wants a larger buffer than the actual
 2669:      * structure.
 2670:      */
 2671:     if (cr->cr_data == NULL) {
 2672: 	if ((cr->cr_data = malloc(CISS_NOTIFY_DATA_SIZE, CISS_MALLOC_CLASS, M_NOWAIT)) == NULL) {
 2673: 	    debug(0, "can't get notify event request buffer");
 2674: 	    error = ENOMEM;
 2675: 	    goto out;
 2676: 	}
 2677: 	cr->cr_length = CISS_NOTIFY_DATA_SIZE;
 2678:     }
 2679: 
 2680:     /* re-setup the request's command (since we never release it) XXX overkill*/
 2681:     ciss_preen_command(cr);
 2682: 
 2683:     /* (re)build the notify event command */
 2684:     cc = CISS_FIND_COMMAND(cr);
 2685:     cc->header.address.physical.mode = CISS_HDR_ADDRESS_MODE_PERIPHERAL;
 2686:     cc->header.address.physical.bus = 0;
 2687:     cc->header.address.physical.target = 0;
 2688: 
 2689:     cc->cdb.cdb_length = sizeof(*cnc);
 2690:     cc->cdb.type = CISS_CDB_TYPE_COMMAND;
 2691:     cc->cdb.attribute = CISS_CDB_ATTRIBUTE_SIMPLE;
 2692:     cc->cdb.direction = CISS_CDB_DIRECTION_READ;
 2693:     cc->cdb.timeout = 0;	/* no timeout, we hope */
 2694:     
 2695:     cnc = (struct ciss_notify_cdb *)&(cc->cdb.cdb[0]);
 2696:     bzero(cr->cr_data, CISS_NOTIFY_DATA_SIZE);
 2697:     cnc->opcode = CISS_OPCODE_READ;
 2698:     cnc->command = CISS_COMMAND_NOTIFY_ON_EVENT;
 2699:     cnc->timeout = 0;		/* no timeout, we hope */
 2700:     cnc->synchronous = 0;
 2701:     cnc->ordered = 0;
 2702:     cnc->seek_to_oldest = 0;
 2703:     cnc->new_only = 0;
 2704:     cnc->length = htonl(CISS_NOTIFY_DATA_SIZE);
 2705: 
 2706:     /* submit the request */
 2707:     error = ciss_start(cr);
 2708: 
 2709:  out:
 2710:     if (error) {
 2711: 	if (cr != NULL) {
 2712: 	    if (cr->cr_data != NULL)
 2713: 		free(cr->cr_data, CISS_MALLOC_CLASS);
 2714: 	    ciss_release_request(cr);
 2715: 	}
 2716: 	sc->ciss_periodic_notify = NULL;
 2717: 	debug(0, "can't submit notify event request");
 2718: 	sc->ciss_flags &= ~CISS_FLAG_NOTIFY_OK;
 2719:     } else {
 2720: 	debug(1, "notify event submitted");
 2721: 	sc->ciss_flags |= CISS_FLAG_NOTIFY_OK;
 2722:     }
 2723: }
 2724: 
 2725: static void
 2726: ciss_notify_complete(struct ciss_request *cr)
 2727: {
 2728:     struct ciss_command	*cc;
 2729:     struct ciss_notify	*cn;
 2730:     struct ciss_softc	*sc;
 2731:     int			scsi_status;
 2732:     int			command_status;
 2733: 
 2734:     debug_called(1);
 2735:     
 2736:     cc = CISS_FIND_COMMAND(cr);
 2737:     cn = (struct ciss_notify *)cr->cr_data;
 2738:     sc = cr->cr_sc;
 2739:     
 2740:     /*
 2741:      * Report request results, decode status.
 2742:      */
 2743:     ciss_report_request(cr, &command_status, &scsi_status);
 2744: 
 2745:     /*
 2746:      * Abort the chain on a fatal error.
 2747:      *
 2748:      * XXX which of these are actually errors?
 2749:      */
 2750:     if ((command_status != CISS_CMD_STATUS_SUCCESS) &&
 2751: 	(command_status != CISS_CMD_STATUS_TARGET_STATUS) &&
 2752: 	(command_status != CISS_CMD_STATUS_TIMEOUT)) {	/* XXX timeout? */
 2753: 	ciss_printf(sc, "fatal error in Notify Event request (%s)\n",
 2754: 		    ciss_name_command_status(command_status));
 2755: 	ciss_release_request(cr);
 2756: 	sc->ciss_flags &= ~CISS_FLAG_NOTIFY_OK;
 2757: 	return;
 2758:     }
 2759: 
 2760:     /* 
 2761:      * If the adapter gave us a text message, print it.
 2762:      */
 2763:     if (cn->message[0] != 0)
 2764: 	ciss_printf(sc, "*** %.80s\n", cn->message);
 2765: 
 2766:     debug(0, "notify event class %d subclass %d detail %d",
 2767: 		cn->class, cn->subclass, cn->detail);
 2768: 
 2769:     /*
 2770:      * If there's room, save the event for a user-level tool.
 2771:      */
 2772:     if (((sc->ciss_notify_head + 1) % CISS_MAX_EVENTS) != sc->ciss_notify_tail) {
 2773: 	sc->ciss_notify[sc->ciss_notify_head] = *cn;
 2774: 	sc->ciss_notify_head = (sc->ciss_notify_head + 1) % CISS_MAX_EVENTS;
 2775:     }
 2776: 
 2777:     /*
 2778:      * Some events are directly of interest to us.
 2779:      */
 2780:     switch (cn->class) {
 2781:     case CISS_NOTIFY_LOGICAL:
 2782: 	ciss_notify_logical(sc, cn);
 2783: 	break;
 2784:     case CISS_NOTIFY_PHYSICAL:
 2785: 	ciss_notify_physical(sc, cn);
 2786: 	break;
 2787:     }
 2788: 
 2789:     /*
 2790:      * If the response indicates that the notifier has been aborted,
 2791:      * release the notifier command.
 2792:      */
 2793:     if ((cn->class == CISS_NOTIFY_NOTIFIER) &&
 2794: 	(cn->subclass == CISS_NOTIFY_NOTIFIER_STATUS) &&
 2795: 	(cn->detail == 1)) {
 2796: 	debug(0, "notifier exiting");
 2797: 	sc->ciss_flags &= ~CISS_FLAG_NOTIFY_OK;
 2798: 	ciss_release_request(cr);
 2799: 	sc->ciss_periodic_notify = NULL;
 2800: 	wakeup(&sc->ciss_periodic_notify);
 2801:     }
 2802: 	
 2803:     /*
 2804:      * Send a new notify event command, if we're not aborting.
 2805:      */
 2806:     if (!(sc->ciss_flags & CISS_FLAG_ABORTING)) {
 2807: 	ciss_notify_event(sc);
 2808:     }
 2809: }
 2810: 
 2811: /************************************************************************
 2812:  * Abort the Notify Event chain.
 2813:  *
 2814:  * Note that we can't just abort the command in progress; we have to
 2815:  * explicitly issue an Abort Notify Event command in order for the
 2816:  * adapter to clean up correctly.
 2817:  *
 2818:  * If we are called with CISS_FLAG_ABORTING set in the adapter softc,
 2819:  * the chain will not restart itself.
 2820:  */
 2821: static int
 2822: ciss_notify_abort(struct ciss_softc *sc)
 2823: {
 2824:     struct ciss_request		*cr;
 2825:     struct ciss_command		*cc;
 2826:     struct ciss_notify_cdb	*cnc;
 2827:     int				error, s, command_status, scsi_status;
 2828: 
 2829:     debug_called(1);
 2830: 
 2831:     cr = NULL;
 2832:     error = 0;
 2833:     
 2834:     /* verify that there's an outstanding command */
 2835:     if (!(sc->ciss_flags & CISS_FLAG_NOTIFY_OK))
 2836: 	goto out;
 2837:     
 2838:     /* get a command to issue the abort with */
 2839:     if ((error = ciss_get_request(sc, &cr)))
 2840: 	goto out;
 2841: 
 2842:     /* get a buffer for the result */
 2843:     if ((cr->cr_data = malloc(CISS_NOTIFY_DATA_SIZE, CISS_MALLOC_CLASS, M_NOWAIT)) == NULL) {
 2844: 	debug(0, "can't get notify event request buffer");
 2845: 	error = ENOMEM;
 2846: 	goto out;
 2847:     }
 2848:     cr->cr_length = CISS_NOTIFY_DATA_SIZE;
 2849:     
 2850:     /* build the CDB */
 2851:     cc = CISS_FIND_COMMAND(cr);
 2852:     cc->header.address.physical.mode = CISS_HDR_ADDRESS_MODE_PERIPHERAL;
 2853:     cc->header.address.physical.bus = 0;
 2854:     cc->header.address.physical.target = 0;
 2855:     cc->cdb.cdb_length = sizeof(*cnc);
 2856:     cc->cdb.type = CISS_CDB_TYPE_COMMAND;
 2857:     cc->cdb.attribute = CISS_CDB_ATTRIBUTE_SIMPLE;
 2858:     cc->cdb.direction = CISS_CDB_DIRECTION_READ;
 2859:     cc->cdb.timeout = 0;	/* no timeout, we hope */
 2860:     
 2861:     cnc = (struct ciss_notify_cdb *)&(cc->cdb.cdb[0]);
 2862:     bzero(cnc, sizeof(*cnc));
 2863:     cnc->opcode = CISS_OPCODE_WRITE;
 2864:     cnc->command = CISS_COMMAND_ABORT_NOTIFY;
 2865:     cnc->length = htonl(CISS_NOTIFY_DATA_SIZE);
 2866: 
 2867:     ciss_print_request(cr);
 2868:     
 2869:     /*
 2870:      * Submit the request and wait for it to complete.
 2871:      */
 2872:     if ((error = ciss_synch_request(cr, 60 * 1000)) != 0) {
 2873: 	ciss_printf(sc, "Abort Notify Event command failed (%d)\n", error);
 2874: 	goto out;
 2875:     }
 2876: 
 2877:     /*
 2878:      * Check response.
 2879:      */
 2880:     ciss_report_request(cr, &command_status, &scsi_status);
 2881:     switch(command_status) {
 2882:     case CISS_CMD_STATUS_SUCCESS:
 2883: 	break;
 2884:     case CISS_CMD_STATUS_INVALID_COMMAND:
 2885: 	/*
 2886: 	 * Some older adapters don't support the CISS version of this
 2887: 	 * command.  Fall back to using the BMIC version.
 2888: 	 */
 2889: 	error = ciss_notify_abort_bmic(sc);
 2890: 	if (error != 0)
 2891: 	    goto out;
 2892: 	break;
 2893: 	
 2894:     case CISS_CMD_STATUS_TARGET_STATUS:
 2895: 	/*
 2896: 	 * This can happen if the adapter thinks there wasn't an outstanding
 2897: 	 * Notify Event command but we did.  We clean up here.
 2898: 	 */
 2899: 	if (scsi_status == CISS_SCSI_STATUS_CHECK_CONDITION) {
 2900: 	    if (sc->ciss_periodic_notify != NULL)
 2901: 		ciss_release_request(sc->ciss_periodic_notify);
 2902: 	    error = 0;
 2903: 	    goto out;
 2904: 	}
 2905: 	/* FALLTHROUGH */
 2906: 	    
 2907:     default:
 2908: 	ciss_printf(sc, "Abort Notify Event command failed (%s)\n",
 2909: 		    ciss_name_command_status(command_status));
 2910: 	error = EIO;
 2911: 	goto out;
 2912:     }
 2913:     
 2914:     /*
 2915:      * Sleep waiting for the notifier command to complete.  Note
 2916:      * that if it doesn't, we may end up in a bad situation, since
 2917:      * the adapter may deliver it later.  Also note that the adapter
 2918:      * requires the Notify Event command to be cancelled in order to
 2919:      * maintain internal bookkeeping.
 2920:      */
 2921:     s = splcam();
 2922:     while (sc->ciss_periodic_notify != NULL) {
 2923: 	error = tsleep(&sc->ciss_periodic_notify, 0, "cissNEA", hz * 5);
 2924: 	if (error == EWOULDBLOCK) {
 2925: 	    ciss_printf(sc, "Notify Event command failed to abort, adapter may wedge.\n");
 2926: 	    break;
 2927: 	}
 2928:     }
 2929:     splx(s);
 2930: 
 2931:  out:
 2932:     /* release the cancel request */
 2933:     if (cr != NULL) {
 2934: 	if (cr->cr_data != NULL)
 2935: 	    free(cr->cr_data, CISS_MALLOC_CLASS);
 2936: 	ciss_release_request(cr);
 2937:     }
 2938:     if (error == 0)
 2939: 	sc->ciss_flags &= ~CISS_FLAG_NOTIFY_OK;
 2940:     return(error);
 2941: }
 2942: 
 2943: /************************************************************************
 2944:  * Abort the Notify Event chain using a BMIC command.
 2945:  */
 2946: static int
 2947: ciss_notify_abort_bmic(struct ciss_softc *sc)
 2948: {
 2949:     struct ciss_request			*cr;
 2950:     int					error, command_status;
 2951: 
 2952:     debug_called(1);
 2953: 
 2954:     cr = NULL;
 2955:     error = 0;
 2956: 
 2957:     /* verify that there's an outstanding command */
 2958:     if (!(sc->ciss_flags & CISS_FLAG_NOTIFY_OK))
 2959: 	goto out;
 2960:     
 2961:     /*
 2962:      * Build a BMIC command to cancel the Notify on Event command.
 2963:      *
 2964:      * Note that we are sending a CISS opcode here.  Odd.
 2965:      */
 2966:     if ((error = ciss_get_bmic_request(sc, &cr, CISS_COMMAND_ABORT_NOTIFY,
 2967: 				       NULL, 0)) != 0)
 2968: 	goto out;
 2969: 
 2970:     /*
 2971:      * Submit the request and wait for it to complete.
 2972:      */
 2973:     if ((error = ciss_synch_request(cr, 60 * 1000)) != 0) {
 2974: 	ciss_printf(sc, "error sending BMIC Cancel Notify on Event command (%d)\n", error);
 2975: 	goto out;
 2976:     }
 2977:     
 2978:     /*
 2979:      * Check response.
 2980:      */
 2981:     ciss_report_request(cr, &command_status, NULL);
 2982:     switch(command_status) {
 2983:     case CISS_CMD_STATUS_SUCCESS:
 2984: 	break;
 2985:     default:
 2986: 	ciss_printf(sc, "error cancelling Notify on Event (%s)\n",  
 2987: 		    ciss_name_command_status(command_status));
 2988: 	error = EIO;
 2989: 	goto out;
 2990:     }
 2991: 
 2992: out:
 2993:     if (cr != NULL)
 2994: 	ciss_release_request(cr);
 2995:     return(error);
 2996: }
 2997: 
 2998: /************************************************************************
 2999:  * Handle a notify event relating to the status of a logical drive.
 3000:  *
 3001:  * XXX need to be able to defer some of these to properly handle
 3002:  *     calling the "ID Physical drive" command, unless the 'extended'
 3003:  *     drive IDs are always in BIG_MAP format.
 3004:  */
 3005: static void
 3006: ciss_notify_logical(struct ciss_softc *sc, struct ciss_notify *cn)
 3007: {
 3008:     struct ciss_ldrive	*ld;
 3009:     int			ostatus;
 3010: 
 3011:     debug_called(2);
 3012: 
 3013:     ld = &sc->ciss_logical[cn->data.logical_status.logical_drive];
 3014: 
 3015:     switch (cn->subclass) {
 3016:     case CISS_NOTIFY_LOGICAL_STATUS:
 3017: 	switch (cn->detail) {
 3018: 	case 0:
 3019: 	    ciss_name_device(sc, cn->data.logical_status.logical_drive);
 3020: 	    ciss_printf(sc, "logical drive %d (%s) changed status %s->%s, spare status 0x%b\n",
 3021: 			cn->data.logical_status.logical_drive, ld->cl_name,
 3022: 			ciss_name_ldrive_status(cn->data.logical_status.previous_state),
 3023: 			ciss_name_ldrive_status(cn->data.logical_status.new_state),
 3024: 			cn->data.logical_status.spare_state,
 3025: 			"\20\1configured\2rebuilding\3failed\4in use\5available\n");
 3026: 
 3027: 	    /*
 3028: 	     * Update our idea of the drive's status.
 3029: 	     */
 3030: 	    ostatus = ciss_decode_ldrive_status(cn->data.logical_status.previous_state);
 3031: 	    ld->cl_status = ciss_decode_ldrive_status(cn->data.logical_status.new_state);
 3032: 	    if (ld->cl_lstatus != NULL)
 3033: 		ld->cl_lstatus->status = cn->data.logical_status.new_state;
 3034: 
 3035: #if 0
 3036: 	    /*
 3037: 	     * Have CAM rescan the drive if its status has changed.
 3038: 	     */
 3039: 	    if (ostatus != ld->cl_status)
 3040: 		ciss_cam_rescan_target(sc, cn->data.logical_status.logical_drive);
 3041: #endif
 3042: 
 3043: 	    break;
 3044: 
 3045: 	case 1:	/* logical drive has recognised new media, needs Accept Media Exchange */
 3046: 	    ciss_name_device(sc, cn->data.logical_status.logical_drive);
 3047: 	    ciss_printf(sc, "logical drive %d (%s) media exchanged, ready to go online\n",
 3048: 			cn->data.logical_status.logical_drive, ld->cl_name);
 3049: 	    ciss_accept_media(sc, cn->data.logical_status.logical_drive, 1);
 3050: 	    break;
 3051: 
 3052: 	case 2:
 3053: 	case 3:
 3054: 	    ciss_printf(sc, "rebuild of logical drive %d (%s) failed due to %s error\n",
 3055: 			cn->data.rebuild_aborted.logical_drive,
 3056: 			sc->ciss_logical[cn->data.rebuild_aborted.logical_drive].cl_name,
 3057: 			(cn->detail == 2) ? "read" : "write");
 3058: 	    break;
 3059: 	}
 3060: 	break;
 3061: 
 3062:     case CISS_NOTIFY_LOGICAL_ERROR:
 3063: 	if (cn->detail == 0) {
 3064: 	    ciss_printf(sc, "FATAL I/O ERROR on logical drive %d (%s), SCSI port %d ID %d\n",
 3065: 			cn->data.io_error.logical_drive,
 3066: 			sc->ciss_logical[cn->data.io_error.logical_drive].cl_name,
 3067: 			cn->data.io_error.failure_bus,
 3068: 			cn->data.io_error.failure_drive);
 3069: 	    /* XXX should we take the drive down at this point, or will we be told? */
 3070: 	}
 3071: 	break;
 3072: 
 3073:     case CISS_NOTIFY_LOGICAL_SURFACE:
 3074: 	if (cn->detail == 0)
 3075: 	    ciss_printf(sc, "logical drive %d (%s) completed consistency initialisation\n",
 3076: 			cn->data.consistency_completed.logical_drive,
 3077: 			sc->ciss_logical[cn->data.consistency_completed.logical_drive].cl_name);
 3078: 	break;
 3079:     }
 3080: }
 3081: 
 3082: /************************************************************************
 3083:  * Handle a notify event relating to the status of a physical drive.
 3084:  */
 3085: static void
 3086: ciss_notify_physical(struct ciss_softc *sc, struct ciss_notify *cn)
 3087: {
 3088:     
 3089: }
 3090: 
 3091: /************************************************************************
 3092:  * Print a request.
 3093:  */
 3094: static void
 3095: ciss_print_request(struct ciss_request *cr)
 3096: {
 3097:     struct ciss_softc	*sc;
 3098:     struct ciss_command	*cc;
 3099:     int			i;
 3100: 
 3101:     sc = cr->cr_sc;
 3102:     cc = CISS_FIND_COMMAND(cr);
 3103:     
 3104:     ciss_printf(sc, "REQUEST @ %p\n", cr);
 3105:     ciss_printf(sc, "  data %p/%d  tag %d  flags %b\n",
 3106: 	      cr->cr_data, cr->cr_length, cr->cr_tag, cr->cr_flags,
 3107: 	      "\20\1mapped\2sleep\3poll\4dataout\5datain\n");
 3108:     ciss_printf(sc, "  sg list/total %d/%d  host tag 0x%x\n",
 3109: 		cc->header.sg_in_list, cc->header.sg_total, cc->header.host_tag);
 3110:     switch(cc->header.address.mode.mode) {
 3111:     case CISS_HDR_ADDRESS_MODE_PERIPHERAL:
 3112:     case CISS_HDR_ADDRESS_MODE_MASK_PERIPHERAL:
 3113: 	ciss_printf(sc, "  physical bus %d target %d\n",
 3114: 		    cc->header.address.physical.bus, cc->header.address.physical.target);
 3115: 	break;
 3116:     case CISS_HDR_ADDRESS_MODE_LOGICAL:
 3117: 	ciss_printf(sc, "  logical unit %d\n", cc->header.address.logical.lun);
 3118: 	break;
 3119:     }
 3120:     ciss_printf(sc, "  %s cdb length %d type %s attribute %s\n", 
 3121: 		(cc->cdb.direction == CISS_CDB_DIRECTION_NONE) ? "no-I/O" :
 3122: 		(cc->cdb.direction == CISS_CDB_DIRECTION_READ) ? "READ" :
 3123: 		(cc->cdb.direction == CISS_CDB_DIRECTION_WRITE) ? "WRITE" : "??",
 3124: 		cc->cdb.cdb_length,
 3125: 		(cc->cdb.type == CISS_CDB_TYPE_COMMAND) ? "command" :
 3126: 		(cc->cdb.type == CISS_CDB_TYPE_MESSAGE) ? "message" : "??",
 3127: 		(cc->cdb.attribute == CISS_CDB_ATTRIBUTE_UNTAGGED) ? "untagged" :
 3128: 		(cc->cdb.attribute == CISS_CDB_ATTRIBUTE_SIMPLE) ? "simple" :
 3129: 		(cc->cdb.attribute == CISS_CDB_ATTRIBUTE_HEAD_OF_QUEUE) ? "head-of-queue" :
 3130: 		(cc->cdb.attribute == CISS_CDB_ATTRIBUTE_ORDERED) ? "ordered" :
 3131: 		(cc->cdb.attribute == CISS_CDB_ATTRIBUTE_AUTO_CONTINGENT) ? "auto-contingent" : "??");
 3132:     ciss_printf(sc, "  %*D\n", cc->cdb.cdb_length, &cc->cdb.cdb[0], " ");
 3133: 
 3134:     if (cc->header.host_tag & CISS_HDR_HOST_TAG_ERROR) {
 3135: 	/* XXX print error info */
 3136:     } else {
 3137: 	/* since we don't use chained s/g, don't support it here */
 3138: 	for (i = 0; i < cc->header.sg_in_list; i++) {
 3139: 	    if ((i % 4) == 0)
 3140: 		ciss_printf(sc, "   ");
 3141: 	    printf("0x%08x/%d ", (u_int32_t)cc->sg[i].address, cc->sg[i].length);
 3142: 	    if ((((i + 1) % 4) == 0) || (i == (cc->header.sg_in_list - 1)))
 3143: 		printf("\n");
 3144: 	}
 3145:     }
 3146: }
 3147: 
 3148: /************************************************************************
 3149:  * Print information about the status of a logical drive.
 3150:  */
 3151: static void
 3152: ciss_print_ldrive(struct ciss_softc *sc, struct ciss_ldrive *ld)
 3153: {
 3154:     int		bus, target, i;
 3155: 
 3156:     if (ld->cl_lstatus == NULL) {
 3157: 	printf("does not exist\n");
 3158: 	return;
 3159:     }
 3160: 
 3161:     /* print drive status */
 3162:     switch(ld->cl_lstatus->status) {
 3163:     case CISS_LSTATUS_OK:
 3164: 	printf("online\n");
 3165: 	break;
 3166:     case CISS_LSTATUS_INTERIM_RECOVERY:
 3167: 	printf("in interim recovery mode\n");
 3168: 	break;
 3169:     case CISS_LSTATUS_READY_RECOVERY:
 3170: 	printf("ready to begin recovery\n");
 3171: 	break;
 3172:     case CISS_LSTATUS_RECOVERING:
 3173: 	bus = CISS_BIG_MAP_BUS(sc, ld->cl_lstatus->drive_rebuilding);
 3174: 	target = CISS_BIG_MAP_BUS(sc, ld->cl_lstatus->drive_rebuilding);
 3175: 	printf("being recovered, working on physical drive %d.%d, %u blocks remaining\n",
 3176: 	       bus, target, ld->cl_lstatus->blocks_to_recover);
 3177: 	break;
 3178:     case CISS_LSTATUS_EXPANDING:
 3179: 	printf("being expanded, %u blocks remaining\n",
 3180: 	       ld->cl_lstatus->blocks_to_recover);
 3181: 	break;
 3182:     case CISS_LSTATUS_QUEUED_FOR_EXPANSION:
 3183: 	printf("queued for expansion\n");
 3184: 	break;
 3185:     case CISS_LSTATUS_FAILED:
 3186: 	printf("queued for expansion\n");
 3187: 	break;
 3188:     case CISS_LSTATUS_WRONG_PDRIVE:
 3189: 	printf("wrong physical drive inserted\n");
 3190: 	break;
 3191:     case CISS_LSTATUS_MISSING_PDRIVE:
 3192: 	printf("missing a needed physical drive\n");
 3193: 	break;
 3194:     case CISS_LSTATUS_BECOMING_READY:
 3195: 	printf("becoming ready\n");
 3196: 	break;
 3197:     }
 3198: 
 3199:     /* print failed physical drives */
 3200:     for (i = 0; i < CISS_BIG_MAP_ENTRIES / 8; i++) {
 3201: 	bus = CISS_BIG_MAP_BUS(sc, ld->cl_lstatus->drive_failure_map[i]);
 3202: 	target = CISS_BIG_MAP_TARGET(sc, ld->cl_lstatus->drive_failure_map[i]);
 3203: 	if (bus == -1)
 3204: 	    continue;
 3205: 	ciss_printf(sc, "physical drive %d:%d (%x) failed\n", bus, target, 
 3206: 		    ld->cl_lstatus->drive_failure_map[i]);
 3207:     }
 3208: }
 3209: 
 3210: #ifdef CISS_DEBUG
 3211: /************************************************************************
 3212:  * Print information about the controller/driver.
 3213:  */
 3214: static void
 3215: ciss_print_adapter(struct ciss_softc *sc)
 3216: {
 3217:     int		i;
 3218: 
 3219:     ciss_printf(sc, "ADAPTER:\n");
 3220:     for (i = 0; i < CISSQ_COUNT; i++) {
 3221: 	ciss_printf(sc, "%s     %d/%d\n",
 3222: 	    i == 0 ? "free" :
 3223: 	    i == 1 ? "busy" : "complete",
 3224: 	    sc->ciss_qstat[i].q_length,
 3225: 	    sc->ciss_qstat[i].q_max);
 3226:     }
 3227:     ciss_printf(sc, "max_requests %d\n", sc->ciss_max_requests);
 3228:     ciss_printf(sc, "notify_head/tail %d/%d\n",
 3229: 	sc->ciss_notify_head, sc->ciss_notify_tail);
 3230:     ciss_printf(sc, "flags %b\n", sc->ciss_flags,
 3231: 	"\20\1notify_ok\2control_open\3aborting\4running\21fake_synch\22bmic_abort\n");
 3232: 
 3233:     for (i = 0; i < CISS_MAX_LOGICAL; i++) {
 3234: 	ciss_printf(sc, "LOGICAL DRIVE %d:  ", i);
 3235: 	ciss_print_ldrive(sc, sc->ciss_logical + i);
 3236:     }
 3237: 
 3238:     for (i = 1; i < sc->ciss_max_requests; i++)
 3239: 	ciss_print_request(sc->ciss_request + i);
 3240: 
 3241: }
 3242: 
 3243: /* DDB hook */
 3244: void
 3245: ciss_print0(void)
 3246: {
 3247:     struct ciss_softc	*sc;
 3248:     
 3249:     sc = devclass_get_softc(devclass_find("ciss"), 0);
 3250:     if (sc == NULL) {
 3251: 	printf("no ciss controllers\n");
 3252:     } else {
 3253: 	ciss_print_adapter(sc);
 3254:     }
 3255: }
 3256: #endif
 3257: 
 3258: /************************************************************************
 3259:  * Return a name for a logical drive status value.
 3260:  */
 3261: static const char *
 3262: ciss_name_ldrive_status(int status)
 3263: {
 3264:     switch (status) {
 3265:     case CISS_LSTATUS_OK:
 3266: 	return("OK");
 3267:     case CISS_LSTATUS_FAILED:
 3268: 	return("failed");
 3269:     case CISS_LSTATUS_NOT_CONFIGURED:
 3270: 	return("not configured");
 3271:     case CISS_LSTATUS_INTERIM_RECOVERY:
 3272: 	return("interim recovery");
 3273:     case CISS_LSTATUS_READY_RECOVERY:
 3274: 	return("ready for recovery");
 3275:     case CISS_LSTATUS_RECOVERING:
 3276: 	return("recovering");
 3277:     case CISS_LSTATUS_WRONG_PDRIVE:
 3278: 	return("wrong physical drive inserted");
 3279:     case CISS_LSTATUS_MISSING_PDRIVE:
 3280: 	return("missing physical drive");
 3281:     case CISS_LSTATUS_EXPANDING:
 3282: 	return("expanding");
 3283:     case CISS_LSTATUS_BECOMING_READY:
 3284: 	return("becoming ready");
 3285:     case CISS_LSTATUS_QUEUED_FOR_EXPANSION:
 3286: 	return("queued for expansion");
 3287:     }
 3288:     return("unknown status");
 3289: }
 3290: 
 3291: /************************************************************************
 3292:  * Return an online/offline/nonexistent value for a logical drive
 3293:  * status value.
 3294:  */
 3295: static int
 3296: ciss_decode_ldrive_status(int status)
 3297: {
 3298:     switch(status) {
 3299:     case CISS_LSTATUS_NOT_CONFIGURED:
 3300: 	return(CISS_LD_NONEXISTENT);
 3301: 
 3302:     case CISS_LSTATUS_OK:
 3303:     case CISS_LSTATUS_INTERIM_RECOVERY:
 3304:     case CISS_LSTATUS_READY_RECOVERY:
 3305:     case CISS_LSTATUS_RECOVERING:
 3306:     case CISS_LSTATUS_EXPANDING:
 3307:     case CISS_LSTATUS_QUEUED_FOR_EXPANSION:
 3308: 	return(CISS_LD_ONLINE);
 3309: 
 3310:     case CISS_LSTATUS_FAILED:
 3311:     case CISS_LSTATUS_WRONG_PDRIVE:
 3312:     case CISS_LSTATUS_MISSING_PDRIVE:
 3313:     case CISS_LSTATUS_BECOMING_READY:
 3314:     default:
 3315: 	return(CISS_LD_OFFLINE);
 3316:     }
 3317: }
 3318: 
 3319: 
 3320: /************************************************************************
 3321:  * Return a name for a logical drive's organisation.
 3322:  */
 3323: static const char *
 3324: ciss_name_ldrive_org(int org)
 3325: {
 3326:     switch(org) {
 3327:     case CISS_LDRIVE_RAID0:
 3328: 	return("RAID 0");
 3329:     case CISS_LDRIVE_RAID1:
 3330: 	return("RAID 1");
 3331:     case CISS_LDRIVE_RAID4:
 3332: 	return("RAID 4");
 3333:     case CISS_LDRIVE_RAID5:
 3334: 	return("RAID 5");
 3335:     }
 3336:     return("unkown");
 3337: }
 3338: 
 3339: /************************************************************************
 3340:  * Return a name for a command status value.
 3341:  */
 3342: static const char *
 3343: ciss_name_command_status(int status)
 3344: {
 3345:     switch(status) {
 3346:     case CISS_CMD_STATUS_SUCCESS:
 3347: 	return("success");
 3348:     case CISS_CMD_STATUS_TARGET_STATUS:
 3349: 	return("target status");
 3350:     case CISS_CMD_STATUS_DATA_UNDERRUN:
 3351: 	return("data underrun");
 3352:     case CISS_CMD_STATUS_DATA_OVERRUN:
 3353: 	return("data overrun");
 3354:     case CISS_CMD_STATUS_INVALID_COMMAND:
 3355: 	return("invalid command");
 3356:     case CISS_CMD_STATUS_PROTOCOL_ERROR:
 3357: 	return("protocol error");
 3358:     case CISS_CMD_STATUS_HARDWARE_ERROR:
 3359: 	return("hardware error");
 3360:     case CISS_CMD_STATUS_CONNECTION_LOST:
 3361: 	return("connection lost");
 3362:     case CISS_CMD_STATUS_ABORTED:
 3363: 	return("aborted");
 3364:     case CISS_CMD_STATUS_ABORT_FAILED:
 3365: 	return("abort failed");
 3366:     case CISS_CMD_STATUS_UNSOLICITED_ABORT:
 3367: 	return("unsolicited abort");
 3368:     case CISS_CMD_STATUS_TIMEOUT:
 3369: 	return("timeout");
 3370:     case CISS_CMD_STATUS_UNABORTABLE:
 3371: 	return("unabortable");
 3372:     }
 3373:     return("unknown status");
 3374: }
 3375: 
 3376: /************************************************************************
 3377:  * Handle an open on the control device.
 3378:  */
 3379: static int
 3380: ciss_open(dev_t dev, int flags, int fmt, d_thread_t *p)
 3381: {
 3382:     struct ciss_softc	*sc;
 3383: 
 3384:     debug_called(1);
 3385:     
 3386:     sc = (struct ciss_softc *)dev->si_drv1;
 3387: 
 3388:     /* we might want to veto if someone already has us open */
 3389: 	
 3390:     sc->ciss_flags |= CISS_FLAG_CONTROL_OPEN;
 3391:     return(0);
 3392: }
 3393: 
 3394: /************************************************************************
 3395:  * Handle the last close on the control device.
 3396:  */
 3397: static int
 3398: ciss_close(dev_t dev, int flags, int fmt, d_thread_t *p)
 3399: {
 3400:     struct ciss_softc	*sc;
 3401: 
 3402:     debug_called(1);
 3403:     
 3404:     sc = (struct ciss_softc *)dev->si_drv1;
 3405:     
 3406:     sc->ciss_flags &= ~CISS_FLAG_CONTROL_OPEN;
 3407:     return (0);
 3408: }
 3409: 
 3410: /********************************************************************************
 3411:  * Handle adapter-specific control operations.
 3412:  *
 3413:  * Note that the API here is compatible with the Linux driver, in order to
 3414:  * simplify the porting of Compaq's userland tools.
 3415:  */
 3416: static int
 3417: ciss_ioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, d_thread_t *p)
 3418: {
 3419:     struct ciss_softc		*sc;
 3420:     int				error;
 3421: 
 3422:     debug_called(1);
 3423: 
 3424:     sc = (struct ciss_softc *)dev->si_drv1;
 3425:     error = 0;
 3426: 
 3427:     switch(cmd) {
 3428:     case CCISS_GETPCIINFO:
 3429:     {
 3430: 	cciss_pci_info_struct	*pis = (cciss_pci_info_struct *)addr;
 3431: 
 3432: 	pis->bus = pci_get_bus(sc->ciss_dev);
 3433: 	pis->dev_fn = pci_get_slot(sc->ciss_dev);
 3434: 	pis->board_id = pci_get_devid(sc->ciss_dev);
 3435: 
 3436: 	break;
 3437:     }
 3438:     
 3439:     case CCISS_GETINTINFO:
 3440:     {
 3441: 	cciss_coalint_struct	*cis = (cciss_coalint_struct *)addr;
 3442: 
 3443: 	cis->delay = sc->ciss_cfg->interrupt_coalesce_delay;
 3444: 	cis->count = sc->ciss_cfg->interrupt_coalesce_count;
 3445: 
 3446: 	break;
 3447:     }
 3448: 
 3449:     case CCISS_SETINTINFO:
 3450:     {
 3451: 	cciss_coalint_struct	*cis = (cciss_coalint_struct *)addr;
 3452: 
 3453: 	if ((cis->delay == 0) && (cis->count == 0)) {
 3454: 	    error = EINVAL;
 3455: 	    break;
 3456: 	}
 3457: 
 3458: 	/*
 3459: 	 * XXX apparently this is only safe if the controller is idle,
 3460: 	 *     we should suspend it before doing this.
 3461: 	 */
 3462: 	sc->ciss_cfg->interrupt_coalesce_delay = cis->delay;
 3463: 	sc->ciss_cfg->interrupt_coalesce_count = cis->count;
 3464: 
 3465: 	if (ciss_update_config(sc))
 3466: 	    error = EIO;
 3467: 
 3468: 	/* XXX resume the controller here */
 3469: 	break;
 3470:     }
 3471: 
 3472:     case CCISS_GETNODENAME:
 3473: 	bcopy(sc->ciss_cfg->server_name, (NodeName_type *)addr,
 3474: 	      sizeof(NodeName_type));
 3475: 	break;
 3476: 
 3477:     case CCISS_SETNODENAME:
 3478: 	bcopy((NodeName_type *)addr, sc->ciss_cfg->server_name,
 3479: 	      sizeof(NodeName_type));
 3480: 	if (ciss_update_config(sc))
 3481: 	    error = EIO;
 3482: 	break;
 3483: 	
 3484:     case CCISS_GETHEARTBEAT:
 3485: 	*(Heartbeat_type *)addr = sc->ciss_cfg->heartbeat;
 3486: 	break;
 3487: 
 3488:     case CCISS_GETBUSTYPES:
 3489: 	*(BusTypes_type *)addr = sc->ciss_cfg->bus_types;
 3490: 	break;
 3491: 
 3492:     case CCISS_GETFIRMVER:
 3493: 	bcopy(sc->ciss_id->running_firmware_revision, (FirmwareVer_type *)addr,
 3494: 	      sizeof(FirmwareVer_type));
 3495: 	break;
 3496: 
 3497:     case CCISS_GETDRIVERVER:
 3498: 	*(DriverVer_type *)addr = CISS_DRIVER_VERSION;
 3499: 	break;
 3500: 
 3501:     case CCISS_REVALIDVOLS:
 3502: 	/*
 3503: 	 * This is a bit ugly; to do it "right" we really need
 3504: 	 * to find any disks that have changed, kick CAM off them,
 3505: 	 * then rescan only these disks.  It'd be nice if they
 3506: 	 * a) told us which disk(s) they were going to play with,
 3507: 	 * and b) which ones had arrived. 8(
 3508: 	 */
 3509: 	break;
 3510: 
 3511:     case CCISS_PASSTHRU:
 3512: 	error = ciss_user_command(sc, (IOCTL_Command_struct *)addr);
 3513: 	break;
 3514: 
 3515:     default:
 3516: 	debug(0, "unknown ioctl 0x%lx", cmd);
 3517: 
 3518: 	debug(1, "CCISS_GETPCIINFO:   0x%lx", CCISS_GETPCIINFO);
 3519: 	debug(1, "CCISS_GETINTINFO:   0x%lx", CCISS_GETINTINFO);
 3520: 	debug(1, "CCISS_SETINTINFO:   0x%lx", CCISS_SETINTINFO);
 3521: 	debug(1, "CCISS_GETNODENAME:  0x%lx", CCISS_GETNODENAME);
 3522: 	debug(1, "CCISS_SETNODENAME:  0x%lx", CCISS_SETNODENAME);
 3523: 	debug(1, "CCISS_GETHEARTBEAT: 0x%lx", CCISS_GETHEARTBEAT);
 3524: 	debug(1, "CCISS_GETBUSTYPES:  0x%lx", CCISS_GETBUSTYPES);
 3525: 	debug(1, "CCISS_GETFIRMVER:   0x%lx", CCISS_GETFIRMVER);
 3526: 	debug(1, "CCISS_GETDRIVERVER: 0x%lx", CCISS_GETDRIVERVER);
 3527: 	debug(1, "CCISS_REVALIDVOLS:  0x%lx", CCISS_REVALIDVOLS);
 3528: 	debug(1, "CCISS_PASSTHRU:     0x%lx", CCISS_PASSTHRU);
 3529: 
 3530: 	error = ENOIOCTL;
 3531: 	break;
 3532:     }
 3533: 
 3534:     return(error);
 3535: }