The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/mly/mly.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2000, 2001 Michael Smith
    3  * Copyright (c) 2000 BSDi
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  *
   27  *      $FreeBSD: releng/6.4/sys/dev/mly/mly.c 165194 2006-12-14 02:57:07Z mjacob $
   28  */
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/malloc.h>
   33 #include <sys/kernel.h>
   34 #include <sys/bus.h>
   35 #include <sys/conf.h>
   36 #include <sys/ctype.h>
   37 #include <sys/ioccom.h>
   38 #include <sys/stat.h>
   39 
   40 #include <machine/bus.h>
   41 #include <machine/resource.h>
   42 #include <sys/rman.h>
   43 
   44 #include <cam/cam.h>
   45 #include <cam/cam_ccb.h>
   46 #include <cam/cam_periph.h>
   47 #include <cam/cam_sim.h>
   48 #include <cam/cam_xpt_sim.h>
   49 #include <cam/scsi/scsi_all.h>
   50 #include <cam/scsi/scsi_message.h>
   51 
   52 #include <dev/pci/pcireg.h>
   53 #include <dev/pci/pcivar.h>
   54 
   55 #include <dev/mly/mlyreg.h>
   56 #include <dev/mly/mlyio.h>
   57 #include <dev/mly/mlyvar.h>
   58 #include <dev/mly/mly_tables.h>
   59 
   60 static int      mly_probe(device_t dev);
   61 static int      mly_attach(device_t dev);
   62 static int      mly_pci_attach(struct mly_softc *sc);
   63 static int      mly_detach(device_t dev);
   64 static int      mly_shutdown(device_t dev);
   65 static void     mly_intr(void *arg);
   66 
   67 static int      mly_sg_map(struct mly_softc *sc);
   68 static void     mly_sg_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error);
   69 static int      mly_mmbox_map(struct mly_softc *sc);
   70 static void     mly_mmbox_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error);
   71 static void     mly_free(struct mly_softc *sc);
   72 
   73 static int      mly_get_controllerinfo(struct mly_softc *sc);
   74 static void     mly_scan_devices(struct mly_softc *sc);
   75 static void     mly_rescan_btl(struct mly_softc *sc, int bus, int target);
   76 static void     mly_complete_rescan(struct mly_command *mc);
   77 static int      mly_get_eventstatus(struct mly_softc *sc);
   78 static int      mly_enable_mmbox(struct mly_softc *sc);
   79 static int      mly_flush(struct mly_softc *sc);
   80 static int      mly_ioctl(struct mly_softc *sc, struct mly_command_ioctl *ioctl, void **data, 
   81                           size_t datasize, u_int8_t *status, void *sense_buffer, size_t *sense_length);
   82 static void     mly_check_event(struct mly_softc *sc);
   83 static void     mly_fetch_event(struct mly_softc *sc);
   84 static void     mly_complete_event(struct mly_command *mc);
   85 static void     mly_process_event(struct mly_softc *sc, struct mly_event *me);
   86 static void     mly_periodic(void *data);
   87 
   88 static int      mly_immediate_command(struct mly_command *mc);
   89 static int      mly_start(struct mly_command *mc);
   90 static void     mly_done(struct mly_softc *sc);
   91 static void     mly_complete(void *context, int pending);
   92 
   93 static int      mly_alloc_command(struct mly_softc *sc, struct mly_command **mcp);
   94 static void     mly_release_command(struct mly_command *mc);
   95 static void     mly_alloc_commands_map(void *arg, bus_dma_segment_t *segs, int nseg, int error);
   96 static int      mly_alloc_commands(struct mly_softc *sc);
   97 static void     mly_release_commands(struct mly_softc *sc);
   98 static void     mly_map_command(struct mly_command *mc);
   99 static void     mly_unmap_command(struct mly_command *mc);
  100 
  101 static int      mly_cam_attach(struct mly_softc *sc);
  102 static void     mly_cam_detach(struct mly_softc *sc);
  103 static void     mly_cam_rescan_btl(struct mly_softc *sc, int bus, int target);
  104 static void     mly_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb);
  105 static void     mly_cam_action(struct cam_sim *sim, union ccb *ccb);
  106 static int      mly_cam_action_io(struct cam_sim *sim, struct ccb_scsiio *csio);
  107 static void     mly_cam_poll(struct cam_sim *sim);
  108 static void     mly_cam_complete(struct mly_command *mc);
  109 static struct cam_periph *mly_find_periph(struct mly_softc *sc, int bus, int target);
  110 static int      mly_name_device(struct mly_softc *sc, int bus, int target);
  111 
  112 static int      mly_fwhandshake(struct mly_softc *sc);
  113 
  114 static void     mly_describe_controller(struct mly_softc *sc);
  115 #ifdef MLY_DEBUG
  116 static void     mly_printstate(struct mly_softc *sc);
  117 static void     mly_print_command(struct mly_command *mc);
  118 static void     mly_print_packet(struct mly_command *mc);
  119 static void     mly_panic(struct mly_softc *sc, char *reason);
  120 #endif
  121 void            mly_print_controller(int controller);
  122 static int      mly_timeout(struct mly_softc *sc);
  123 
  124 
  125 static d_open_t         mly_user_open;
  126 static d_close_t        mly_user_close;
  127 static d_ioctl_t        mly_user_ioctl;
  128 static int      mly_user_command(struct mly_softc *sc, struct mly_user_command *uc);
  129 static int      mly_user_health(struct mly_softc *sc, struct mly_user_health *uh);
  130 
  131 #define MLY_CMD_TIMEOUT         20
  132 
  133 static device_method_t mly_methods[] = {
  134     /* Device interface */
  135     DEVMETHOD(device_probe,     mly_probe),
  136     DEVMETHOD(device_attach,    mly_attach),
  137     DEVMETHOD(device_detach,    mly_detach),
  138     DEVMETHOD(device_shutdown,  mly_shutdown),
  139     { 0, 0 }
  140 };
  141 
  142 static driver_t mly_pci_driver = {
  143         "mly",
  144         mly_methods,
  145         sizeof(struct mly_softc)
  146 };
  147 
  148 static devclass_t       mly_devclass;
  149 DRIVER_MODULE(mly, pci, mly_pci_driver, mly_devclass, 0, 0);
  150 MODULE_DEPEND(mly, pci, 1, 1, 1);
  151 MODULE_DEPEND(mly, cam, 1, 1, 1);
  152 
  153 static struct cdevsw mly_cdevsw = {
  154         .d_version =    D_VERSION,
  155         .d_flags =      D_NEEDGIANT,
  156         .d_open =       mly_user_open,
  157         .d_close =      mly_user_close,
  158         .d_ioctl =      mly_user_ioctl,
  159         .d_name =       "mly",
  160 };
  161 
  162 /********************************************************************************
  163  ********************************************************************************
  164                                                                  Device Interface
  165  ********************************************************************************
  166  ********************************************************************************/
  167 
  168 static struct mly_ident
  169 {
  170     u_int16_t           vendor;
  171     u_int16_t           device;
  172     u_int16_t           subvendor;
  173     u_int16_t           subdevice;
  174     int                 hwif;
  175     char                *desc;
  176 } mly_identifiers[] = {
  177     {0x1069, 0xba56, 0x1069, 0x0040, MLY_HWIF_STRONGARM, "Mylex eXtremeRAID 2000"},
  178     {0x1069, 0xba56, 0x1069, 0x0030, MLY_HWIF_STRONGARM, "Mylex eXtremeRAID 3000"},
  179     {0x1069, 0x0050, 0x1069, 0x0050, MLY_HWIF_I960RX,    "Mylex AcceleRAID 352"},
  180     {0x1069, 0x0050, 0x1069, 0x0052, MLY_HWIF_I960RX,    "Mylex AcceleRAID 170"},
  181     {0x1069, 0x0050, 0x1069, 0x0054, MLY_HWIF_I960RX,    "Mylex AcceleRAID 160"},
  182     {0, 0, 0, 0, 0, 0}
  183 };
  184 
  185 /********************************************************************************
  186  * Compare the provided PCI device with the list we support.
  187  */
  188 static int
  189 mly_probe(device_t dev)
  190 {
  191     struct mly_ident    *m;
  192 
  193     debug_called(1);
  194 
  195     for (m = mly_identifiers; m->vendor != 0; m++) {
  196         if ((m->vendor == pci_get_vendor(dev)) &&
  197             (m->device == pci_get_device(dev)) &&
  198             ((m->subvendor == 0) || ((m->subvendor == pci_get_subvendor(dev)) &&
  199                                      (m->subdevice == pci_get_subdevice(dev))))) {
  200             
  201             device_set_desc(dev, m->desc);
  202             return(BUS_PROBE_DEFAULT);  /* allow room to be overridden */
  203         }
  204     }
  205     return(ENXIO);
  206 }
  207 
  208 /********************************************************************************
  209  * Initialise the controller and softc
  210  */
  211 static int
  212 mly_attach(device_t dev)
  213 {
  214     struct mly_softc    *sc = device_get_softc(dev);
  215     int                 error;
  216 
  217     debug_called(1);
  218 
  219     sc->mly_dev = dev;
  220 
  221 #ifdef MLY_DEBUG
  222     if (device_get_unit(sc->mly_dev) == 0)
  223         mly_softc0 = sc;
  224 #endif    
  225 
  226     /*
  227      * Do PCI-specific initialisation.
  228      */
  229     if ((error = mly_pci_attach(sc)) != 0)
  230         goto out;
  231 
  232     /*
  233      * Initialise per-controller queues.
  234      */
  235     mly_initq_free(sc);
  236     mly_initq_busy(sc);
  237     mly_initq_complete(sc);
  238 
  239 #if __FreeBSD_version >= 500005
  240     /*
  241      * Initialise command-completion task.
  242      */
  243     TASK_INIT(&sc->mly_task_complete, 0, mly_complete, sc);
  244 #endif
  245 
  246     /* disable interrupts before we start talking to the controller */
  247     MLY_MASK_INTERRUPTS(sc);
  248 
  249     /* 
  250      * Wait for the controller to come ready, handshake with the firmware if required.
  251      * This is typically only necessary on platforms where the controller BIOS does not
  252      * run.
  253      */
  254     if ((error = mly_fwhandshake(sc)))
  255         goto out;
  256 
  257     /*
  258      * Allocate initial command buffers.
  259      */
  260     if ((error = mly_alloc_commands(sc)))
  261         goto out;
  262 
  263     /* 
  264      * Obtain controller feature information
  265      */
  266     if ((error = mly_get_controllerinfo(sc)))
  267         goto out;
  268 
  269     /*
  270      * Reallocate command buffers now we know how many we want.
  271      */
  272     mly_release_commands(sc);
  273     if ((error = mly_alloc_commands(sc)))
  274         goto out;
  275 
  276     /*
  277      * Get the current event counter for health purposes, populate the initial
  278      * health status buffer.
  279      */
  280     if ((error = mly_get_eventstatus(sc)))
  281         goto out;
  282 
  283     /*
  284      * Enable memory-mailbox mode.
  285      */
  286     if ((error = mly_enable_mmbox(sc)))
  287         goto out;
  288 
  289     /*
  290      * Attach to CAM.
  291      */
  292     if ((error = mly_cam_attach(sc)))
  293         goto out;
  294 
  295     /* 
  296      * Print a little information about the controller 
  297      */
  298     mly_describe_controller(sc);
  299 
  300     /*
  301      * Mark all attached devices for rescan.
  302      */
  303     mly_scan_devices(sc);
  304 
  305     /*
  306      * Instigate the first status poll immediately.  Rescan completions won't
  307      * happen until interrupts are enabled, which should still be before
  308      * the SCSI subsystem gets to us, courtesy of the "SCSI settling delay".
  309      */
  310     mly_periodic((void *)sc);
  311 
  312     /*
  313      * Create the control device.
  314      */
  315     sc->mly_dev_t = make_dev(&mly_cdevsw, device_get_unit(sc->mly_dev), UID_ROOT, GID_OPERATOR,
  316                              S_IRUSR | S_IWUSR, "mly%d", device_get_unit(sc->mly_dev));
  317     sc->mly_dev_t->si_drv1 = sc;
  318 
  319     /* enable interrupts now */
  320     MLY_UNMASK_INTERRUPTS(sc);
  321 
  322 #ifdef MLY_DEBUG
  323     timeout((timeout_t *)mly_timeout, sc, MLY_CMD_TIMEOUT * hz);
  324 #endif
  325 
  326  out:
  327     if (error != 0)
  328         mly_free(sc);
  329     return(error);
  330 }
  331 
  332 /********************************************************************************
  333  * Perform PCI-specific initialisation.
  334  */
  335 static int
  336 mly_pci_attach(struct mly_softc *sc)
  337 {
  338     int                 i, error;
  339     u_int32_t           command;
  340 
  341     debug_called(1);
  342 
  343     /* assume failure is 'not configured' */
  344     error = ENXIO;
  345 
  346     /* 
  347      * Verify that the adapter is correctly set up in PCI space.
  348      * 
  349      * XXX we shouldn't do this; the PCI code should.
  350      */
  351     command = pci_read_config(sc->mly_dev, PCIR_COMMAND, 2);
  352     command |= PCIM_CMD_BUSMASTEREN;
  353     pci_write_config(sc->mly_dev, PCIR_COMMAND, command, 2);
  354     command = pci_read_config(sc->mly_dev, PCIR_COMMAND, 2);
  355     if (!(command & PCIM_CMD_BUSMASTEREN)) {
  356         mly_printf(sc, "can't enable busmaster feature\n");
  357         goto fail;
  358     }
  359     if ((command & PCIM_CMD_MEMEN) == 0) {
  360         mly_printf(sc, "memory window not available\n");
  361         goto fail;
  362     }
  363 
  364     /*
  365      * Allocate the PCI register window.
  366      */
  367     sc->mly_regs_rid = PCIR_BAR(0);     /* first base address register */
  368     if ((sc->mly_regs_resource = bus_alloc_resource_any(sc->mly_dev, 
  369             SYS_RES_MEMORY, &sc->mly_regs_rid, RF_ACTIVE)) == NULL) {
  370         mly_printf(sc, "can't allocate register window\n");
  371         goto fail;
  372     }
  373     sc->mly_btag = rman_get_bustag(sc->mly_regs_resource);
  374     sc->mly_bhandle = rman_get_bushandle(sc->mly_regs_resource);
  375 
  376     /* 
  377      * Allocate and connect our interrupt.
  378      */
  379     sc->mly_irq_rid = 0;
  380     if ((sc->mly_irq = bus_alloc_resource_any(sc->mly_dev, SYS_RES_IRQ, 
  381                     &sc->mly_irq_rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
  382         mly_printf(sc, "can't allocate interrupt\n");
  383         goto fail;
  384     }
  385     if (bus_setup_intr(sc->mly_dev, sc->mly_irq, INTR_TYPE_CAM | INTR_ENTROPY,  mly_intr, sc, &sc->mly_intr)) {
  386         mly_printf(sc, "can't set up interrupt\n");
  387         goto fail;
  388     }
  389 
  390     /* assume failure is 'out of memory' */
  391     error = ENOMEM;
  392 
  393     /*
  394      * Allocate the parent bus DMA tag appropriate for our PCI interface.
  395      * 
  396      * Note that all of these controllers are 64-bit capable.
  397      */
  398     if (bus_dma_tag_create(NULL,                        /* parent */
  399                            1, 0,                        /* alignment, boundary */
  400                            BUS_SPACE_MAXADDR_32BIT,     /* lowaddr */
  401                            BUS_SPACE_MAXADDR,           /* highaddr */
  402                            NULL, NULL,                  /* filter, filterarg */
  403                            MAXBSIZE, MLY_MAX_SGENTRIES, /* maxsize, nsegments */
  404                            BUS_SPACE_MAXSIZE_32BIT,     /* maxsegsize */
  405                            BUS_DMA_ALLOCNOW,            /* flags */
  406                            NULL,                        /* lockfunc */
  407                            NULL,                        /* lockarg */
  408                            &sc->mly_parent_dmat)) {
  409         mly_printf(sc, "can't allocate parent DMA tag\n");
  410         goto fail;
  411     }
  412 
  413     /*
  414      * Create DMA tag for mapping buffers into controller-addressable space.
  415      */
  416     if (bus_dma_tag_create(sc->mly_parent_dmat,         /* parent */
  417                            1, 0,                        /* alignment, boundary */
  418                            BUS_SPACE_MAXADDR,           /* lowaddr */
  419                            BUS_SPACE_MAXADDR,           /* highaddr */
  420                            NULL, NULL,                  /* filter, filterarg */
  421                            MAXBSIZE, MLY_MAX_SGENTRIES, /* maxsize, nsegments */
  422                            BUS_SPACE_MAXSIZE_32BIT,     /* maxsegsize */
  423                            0,                           /* flags */
  424                            busdma_lock_mutex,           /* lockfunc */
  425                            &Giant,                      /* lockarg */
  426                            &sc->mly_buffer_dmat)) {
  427         mly_printf(sc, "can't allocate buffer DMA tag\n");
  428         goto fail;
  429     }
  430 
  431     /*
  432      * Initialise the DMA tag for command packets.
  433      */
  434     if (bus_dma_tag_create(sc->mly_parent_dmat,         /* parent */
  435                            1, 0,                        /* alignment, boundary */
  436                            BUS_SPACE_MAXADDR,           /* lowaddr */
  437                            BUS_SPACE_MAXADDR,           /* highaddr */
  438                            NULL, NULL,                  /* filter, filterarg */
  439                            sizeof(union mly_command_packet) * MLY_MAX_COMMANDS, 1,      /* maxsize, nsegments */
  440                            BUS_SPACE_MAXSIZE_32BIT,     /* maxsegsize */
  441                            BUS_DMA_ALLOCNOW,            /* flags */
  442                            NULL, NULL,                  /* lockfunc, lockarg */
  443                            &sc->mly_packet_dmat)) {
  444         mly_printf(sc, "can't allocate command packet DMA tag\n");
  445         goto fail;
  446     }
  447 
  448     /* 
  449      * Detect the hardware interface version 
  450      */
  451     for (i = 0; mly_identifiers[i].vendor != 0; i++) {
  452         if ((mly_identifiers[i].vendor == pci_get_vendor(sc->mly_dev)) &&
  453             (mly_identifiers[i].device == pci_get_device(sc->mly_dev))) {
  454             sc->mly_hwif = mly_identifiers[i].hwif;
  455             switch(sc->mly_hwif) {
  456             case MLY_HWIF_I960RX:
  457                 debug(1, "set hardware up for i960RX");
  458                 sc->mly_doorbell_true = 0x00;
  459                 sc->mly_command_mailbox =  MLY_I960RX_COMMAND_MAILBOX;
  460                 sc->mly_status_mailbox =   MLY_I960RX_STATUS_MAILBOX;
  461                 sc->mly_idbr =             MLY_I960RX_IDBR;
  462                 sc->mly_odbr =             MLY_I960RX_ODBR;
  463                 sc->mly_error_status =     MLY_I960RX_ERROR_STATUS;
  464                 sc->mly_interrupt_status = MLY_I960RX_INTERRUPT_STATUS;
  465                 sc->mly_interrupt_mask =   MLY_I960RX_INTERRUPT_MASK;
  466                 break;
  467             case MLY_HWIF_STRONGARM:
  468                 debug(1, "set hardware up for StrongARM");
  469                 sc->mly_doorbell_true = 0xff;           /* doorbell 'true' is 0 */
  470                 sc->mly_command_mailbox =  MLY_STRONGARM_COMMAND_MAILBOX;
  471                 sc->mly_status_mailbox =   MLY_STRONGARM_STATUS_MAILBOX;
  472                 sc->mly_idbr =             MLY_STRONGARM_IDBR;
  473                 sc->mly_odbr =             MLY_STRONGARM_ODBR;
  474                 sc->mly_error_status =     MLY_STRONGARM_ERROR_STATUS;
  475                 sc->mly_interrupt_status = MLY_STRONGARM_INTERRUPT_STATUS;
  476                 sc->mly_interrupt_mask =   MLY_STRONGARM_INTERRUPT_MASK;
  477                 break;
  478             }
  479             break;
  480         }
  481     }
  482 
  483     /*
  484      * Create the scatter/gather mappings.
  485      */
  486     if ((error = mly_sg_map(sc)))
  487         goto fail;
  488 
  489     /*
  490      * Allocate and map the memory mailbox
  491      */
  492     if ((error = mly_mmbox_map(sc)))
  493         goto fail;
  494 
  495     error = 0;
  496             
  497 fail:
  498     return(error);
  499 }
  500 
  501 /********************************************************************************
  502  * Shut the controller down and detach all our resources.
  503  */
  504 static int
  505 mly_detach(device_t dev)
  506 {
  507     int                 error;
  508 
  509     if ((error = mly_shutdown(dev)) != 0)
  510         return(error);
  511     
  512     mly_free(device_get_softc(dev));
  513     return(0);
  514 }
  515 
  516 /********************************************************************************
  517  * Bring the controller to a state where it can be safely left alone.
  518  *
  519  * Note that it should not be necessary to wait for any outstanding commands,
  520  * as they should be completed prior to calling here.
  521  *
  522  * XXX this applies for I/O, but not status polls; we should beware of
  523  *     the case where a status command is running while we detach.
  524  */
  525 static int
  526 mly_shutdown(device_t dev)
  527 {
  528     struct mly_softc    *sc = device_get_softc(dev);
  529 
  530     debug_called(1);
  531     
  532     if (sc->mly_state & MLY_STATE_OPEN)
  533         return(EBUSY);
  534 
  535     /* kill the periodic event */
  536     untimeout(mly_periodic, sc, sc->mly_periodic);
  537 
  538     /* flush controller */
  539     mly_printf(sc, "flushing cache...");
  540     printf("%s\n", mly_flush(sc) ? "failed" : "done");
  541 
  542     MLY_MASK_INTERRUPTS(sc);
  543 
  544     return(0);
  545 }
  546 
  547 /*******************************************************************************
  548  * Take an interrupt, or be poked by other code to look for interrupt-worthy
  549  * status.
  550  */
  551 static void
  552 mly_intr(void *arg)
  553 {
  554     struct mly_softc    *sc = (struct mly_softc *)arg;
  555 
  556     debug_called(2);
  557 
  558     mly_done(sc);
  559 };
  560 
  561 /********************************************************************************
  562  ********************************************************************************
  563                                                 Bus-dependant Resource Management
  564  ********************************************************************************
  565  ********************************************************************************/
  566 
  567 /********************************************************************************
  568  * Allocate memory for the scatter/gather tables
  569  */
  570 static int
  571 mly_sg_map(struct mly_softc *sc)
  572 {
  573     size_t      segsize;
  574 
  575     debug_called(1);
  576 
  577     /*
  578      * Create a single tag describing a region large enough to hold all of
  579      * the s/g lists we will need.
  580      */
  581     segsize = sizeof(struct mly_sg_entry) * MLY_MAX_COMMANDS *MLY_MAX_SGENTRIES;
  582     if (bus_dma_tag_create(sc->mly_parent_dmat,         /* parent */
  583                            1, 0,                        /* alignment,boundary */
  584                            BUS_SPACE_MAXADDR,           /* lowaddr */
  585                            BUS_SPACE_MAXADDR,           /* highaddr */
  586                            NULL, NULL,                  /* filter, filterarg */
  587                            segsize, 1,                  /* maxsize, nsegments */
  588                            BUS_SPACE_MAXSIZE_32BIT,     /* maxsegsize */
  589                            BUS_DMA_ALLOCNOW,            /* flags */
  590                            NULL, NULL,                  /* lockfunc, lockarg */
  591                            &sc->mly_sg_dmat)) {
  592         mly_printf(sc, "can't allocate scatter/gather DMA tag\n");
  593         return(ENOMEM);
  594     }
  595 
  596     /*
  597      * Allocate enough s/g maps for all commands and permanently map them into
  598      * controller-visible space.
  599      *  
  600      * XXX this assumes we can get enough space for all the s/g maps in one 
  601      * contiguous slab.
  602      */
  603     if (bus_dmamem_alloc(sc->mly_sg_dmat, (void **)&sc->mly_sg_table,
  604                          BUS_DMA_NOWAIT, &sc->mly_sg_dmamap)) {
  605         mly_printf(sc, "can't allocate s/g table\n");
  606         return(ENOMEM);
  607     }
  608     if (bus_dmamap_load(sc->mly_sg_dmat, sc->mly_sg_dmamap, sc->mly_sg_table,
  609                         segsize, mly_sg_map_helper, sc, BUS_DMA_NOWAIT) != 0)
  610         return (ENOMEM);
  611     return(0);
  612 }
  613 
  614 /********************************************************************************
  615  * Save the physical address of the base of the s/g table.
  616  */
  617 static void
  618 mly_sg_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error)
  619 {
  620     struct mly_softc    *sc = (struct mly_softc *)arg;
  621 
  622     debug_called(1);
  623 
  624     /* save base of s/g table's address in bus space */
  625     sc->mly_sg_busaddr = segs->ds_addr;
  626 }
  627 
  628 /********************************************************************************
  629  * Allocate memory for the memory-mailbox interface
  630  */
  631 static int
  632 mly_mmbox_map(struct mly_softc *sc)
  633 {
  634 
  635     /*
  636      * Create a DMA tag for a single contiguous region large enough for the
  637      * memory mailbox structure.
  638      */
  639     if (bus_dma_tag_create(sc->mly_parent_dmat,         /* parent */
  640                            1, 0,                        /* alignment,boundary */
  641                            BUS_SPACE_MAXADDR,           /* lowaddr */
  642                            BUS_SPACE_MAXADDR,           /* highaddr */
  643                            NULL, NULL,                  /* filter, filterarg */
  644                            sizeof(struct mly_mmbox), 1, /* maxsize, nsegments */
  645                            BUS_SPACE_MAXSIZE_32BIT,     /* maxsegsize */
  646                            BUS_DMA_ALLOCNOW,            /* flags */
  647                            NULL, NULL,                  /* lockfunc, lockarg */
  648                            &sc->mly_mmbox_dmat)) {
  649         mly_printf(sc, "can't allocate memory mailbox DMA tag\n");
  650         return(ENOMEM);
  651     }
  652 
  653     /*
  654      * Allocate the buffer
  655      */
  656     if (bus_dmamem_alloc(sc->mly_mmbox_dmat, (void **)&sc->mly_mmbox, BUS_DMA_NOWAIT, &sc->mly_mmbox_dmamap)) {
  657         mly_printf(sc, "can't allocate memory mailbox\n");
  658         return(ENOMEM);
  659     }
  660     if (bus_dmamap_load(sc->mly_mmbox_dmat, sc->mly_mmbox_dmamap, sc->mly_mmbox,
  661                         sizeof(struct mly_mmbox), mly_mmbox_map_helper, sc, 
  662                         BUS_DMA_NOWAIT) != 0)
  663         return (ENOMEM);
  664     bzero(sc->mly_mmbox, sizeof(*sc->mly_mmbox));
  665     return(0);
  666 
  667 }
  668 
  669 /********************************************************************************
  670  * Save the physical address of the memory mailbox 
  671  */
  672 static void
  673 mly_mmbox_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error)
  674 {
  675     struct mly_softc    *sc = (struct mly_softc *)arg;
  676 
  677     debug_called(1);
  678 
  679     sc->mly_mmbox_busaddr = segs->ds_addr;
  680 }
  681 
  682 /********************************************************************************
  683  * Free all of the resources associated with (sc)
  684  *
  685  * Should not be called if the controller is active.
  686  */
  687 static void
  688 mly_free(struct mly_softc *sc)
  689 {
  690     
  691     debug_called(1);
  692 
  693     /* Remove the management device */
  694     destroy_dev(sc->mly_dev_t);
  695 
  696     /* detach from CAM */
  697     mly_cam_detach(sc);
  698 
  699     /* release command memory */
  700     mly_release_commands(sc);
  701     
  702     /* throw away the controllerinfo structure */
  703     if (sc->mly_controllerinfo != NULL)
  704         free(sc->mly_controllerinfo, M_DEVBUF);
  705 
  706     /* throw away the controllerparam structure */
  707     if (sc->mly_controllerparam != NULL)
  708         free(sc->mly_controllerparam, M_DEVBUF);
  709 
  710     /* destroy data-transfer DMA tag */
  711     if (sc->mly_buffer_dmat)
  712         bus_dma_tag_destroy(sc->mly_buffer_dmat);
  713 
  714     /* free and destroy DMA memory and tag for s/g lists */
  715     if (sc->mly_sg_table) {
  716         bus_dmamap_unload(sc->mly_sg_dmat, sc->mly_sg_dmamap);
  717         bus_dmamem_free(sc->mly_sg_dmat, sc->mly_sg_table, sc->mly_sg_dmamap);
  718     }
  719     if (sc->mly_sg_dmat)
  720         bus_dma_tag_destroy(sc->mly_sg_dmat);
  721 
  722     /* free and destroy DMA memory and tag for memory mailbox */
  723     if (sc->mly_mmbox) {
  724         bus_dmamap_unload(sc->mly_mmbox_dmat, sc->mly_mmbox_dmamap);
  725         bus_dmamem_free(sc->mly_mmbox_dmat, sc->mly_mmbox, sc->mly_mmbox_dmamap);
  726     }
  727     if (sc->mly_mmbox_dmat)
  728         bus_dma_tag_destroy(sc->mly_mmbox_dmat);
  729 
  730     /* disconnect the interrupt handler */
  731     if (sc->mly_intr)
  732         bus_teardown_intr(sc->mly_dev, sc->mly_irq, sc->mly_intr);
  733     if (sc->mly_irq != NULL)
  734         bus_release_resource(sc->mly_dev, SYS_RES_IRQ, sc->mly_irq_rid, sc->mly_irq);
  735 
  736     /* destroy the parent DMA tag */
  737     if (sc->mly_parent_dmat)
  738         bus_dma_tag_destroy(sc->mly_parent_dmat);
  739 
  740     /* release the register window mapping */
  741     if (sc->mly_regs_resource != NULL)
  742         bus_release_resource(sc->mly_dev, SYS_RES_MEMORY, sc->mly_regs_rid, sc->mly_regs_resource);
  743 }
  744 
  745 /********************************************************************************
  746  ********************************************************************************
  747                                                                  Command Wrappers
  748  ********************************************************************************
  749  ********************************************************************************/
  750 
  751 /********************************************************************************
  752  * Fill in the mly_controllerinfo and mly_controllerparam fields in the softc.
  753  */
  754 static int
  755 mly_get_controllerinfo(struct mly_softc *sc)
  756 {
  757     struct mly_command_ioctl    mci;
  758     u_int8_t                    status;
  759     int                         error;
  760 
  761     debug_called(1);
  762 
  763     if (sc->mly_controllerinfo != NULL)
  764         free(sc->mly_controllerinfo, M_DEVBUF);
  765 
  766     /* build the getcontrollerinfo ioctl and send it */
  767     bzero(&mci, sizeof(mci));
  768     sc->mly_controllerinfo = NULL;
  769     mci.sub_ioctl = MDACIOCTL_GETCONTROLLERINFO;
  770     if ((error = mly_ioctl(sc, &mci, (void **)&sc->mly_controllerinfo, sizeof(*sc->mly_controllerinfo),
  771                            &status, NULL, NULL)))
  772         return(error);
  773     if (status != 0)
  774         return(EIO);
  775 
  776     if (sc->mly_controllerparam != NULL)
  777         free(sc->mly_controllerparam, M_DEVBUF);
  778 
  779     /* build the getcontrollerparameter ioctl and send it */
  780     bzero(&mci, sizeof(mci));
  781     sc->mly_controllerparam = NULL;
  782     mci.sub_ioctl = MDACIOCTL_GETCONTROLLERPARAMETER;
  783     if ((error = mly_ioctl(sc, &mci, (void **)&sc->mly_controllerparam, sizeof(*sc->mly_controllerparam),
  784                            &status, NULL, NULL)))
  785         return(error);
  786     if (status != 0)
  787         return(EIO);
  788 
  789     return(0);
  790 }
  791 
  792 /********************************************************************************
  793  * Schedule all possible devices for a rescan.
  794  *
  795  */
  796 static void
  797 mly_scan_devices(struct mly_softc *sc)
  798 {
  799     int         bus, target;
  800 
  801     debug_called(1);
  802 
  803     /*
  804      * Clear any previous BTL information.
  805      */
  806     bzero(&sc->mly_btl, sizeof(sc->mly_btl));
  807 
  808     /*
  809      * Mark all devices as requiring a rescan, and let the next
  810      * periodic scan collect them. 
  811      */
  812     for (bus = 0; bus < sc->mly_cam_channels; bus++)
  813         if (MLY_BUS_IS_VALID(sc, bus)) 
  814             for (target = 0; target < MLY_MAX_TARGETS; target++)
  815                 sc->mly_btl[bus][target].mb_flags = MLY_BTL_RESCAN;
  816 
  817 }
  818 
  819 /********************************************************************************
  820  * Rescan a device, possibly as a consequence of getting an event which suggests
  821  * that it may have changed.
  822  *
  823  * If we suffer resource starvation, we can abandon the rescan as we'll be
  824  * retried.
  825  */
  826 static void
  827 mly_rescan_btl(struct mly_softc *sc, int bus, int target)
  828 {
  829     struct mly_command          *mc;
  830     struct mly_command_ioctl    *mci;
  831 
  832     debug_called(1);
  833 
  834     /* check that this bus is valid */
  835     if (!MLY_BUS_IS_VALID(sc, bus))
  836         return;
  837 
  838     /* get a command */
  839     if (mly_alloc_command(sc, &mc))
  840         return;
  841 
  842     /* set up the data buffer */
  843     if ((mc->mc_data = malloc(sizeof(union mly_devinfo), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
  844         mly_release_command(mc);
  845         return;
  846     }
  847     mc->mc_flags |= MLY_CMD_DATAIN;
  848     mc->mc_complete = mly_complete_rescan;
  849 
  850     /* 
  851      * Build the ioctl.
  852      */
  853     mci = (struct mly_command_ioctl *)&mc->mc_packet->ioctl;
  854     mci->opcode = MDACMD_IOCTL;
  855     mci->addr.phys.controller = 0;
  856     mci->timeout.value = 30;
  857     mci->timeout.scale = MLY_TIMEOUT_SECONDS;
  858     if (MLY_BUS_IS_VIRTUAL(sc, bus)) {
  859         mc->mc_length = mci->data_size = sizeof(struct mly_ioctl_getlogdevinfovalid);
  860         mci->sub_ioctl = MDACIOCTL_GETLOGDEVINFOVALID;
  861         mci->addr.log.logdev = MLY_LOGDEV_ID(sc, bus, target);
  862         debug(1, "logical device %d", mci->addr.log.logdev);
  863     } else {
  864         mc->mc_length = mci->data_size = sizeof(struct mly_ioctl_getphysdevinfovalid);
  865         mci->sub_ioctl = MDACIOCTL_GETPHYSDEVINFOVALID;
  866         mci->addr.phys.lun = 0;
  867         mci->addr.phys.target = target;
  868         mci->addr.phys.channel = bus;
  869         debug(1, "physical device %d:%d", mci->addr.phys.channel, mci->addr.phys.target);
  870     }
  871     
  872     /*
  873      * Dispatch the command.  If we successfully send the command, clear the rescan
  874      * bit.
  875      */
  876     if (mly_start(mc) != 0) {
  877         mly_release_command(mc);
  878     } else {
  879         sc->mly_btl[bus][target].mb_flags &= ~MLY_BTL_RESCAN;   /* success */   
  880     }
  881 }
  882 
  883 /********************************************************************************
  884  * Handle the completion of a rescan operation
  885  */
  886 static void
  887 mly_complete_rescan(struct mly_command *mc)
  888 {
  889     struct mly_softc                            *sc = mc->mc_sc;
  890     struct mly_ioctl_getlogdevinfovalid         *ldi;
  891     struct mly_ioctl_getphysdevinfovalid        *pdi;
  892     struct mly_command_ioctl                    *mci;
  893     struct mly_btl                              btl, *btlp;
  894     int                                         bus, target, rescan;
  895 
  896     debug_called(1);
  897 
  898     /*
  899      * Recover the bus and target from the command.  We need these even in
  900      * the case where we don't have a useful response.
  901      */
  902     mci = (struct mly_command_ioctl *)&mc->mc_packet->ioctl;
  903     if (mci->sub_ioctl == MDACIOCTL_GETLOGDEVINFOVALID) {
  904         bus = MLY_LOGDEV_BUS(sc, mci->addr.log.logdev);
  905         target = MLY_LOGDEV_TARGET(sc, mci->addr.log.logdev);
  906     } else {
  907         bus = mci->addr.phys.channel;
  908         target = mci->addr.phys.target;
  909     }
  910     /* XXX validate bus/target? */
  911     
  912     /* the default result is 'no device' */
  913     bzero(&btl, sizeof(btl));
  914 
  915     /* if the rescan completed OK, we have possibly-new BTL data */
  916     if (mc->mc_status == 0) {
  917         if (mc->mc_length == sizeof(*ldi)) {
  918             ldi = (struct mly_ioctl_getlogdevinfovalid *)mc->mc_data;
  919             if ((MLY_LOGDEV_BUS(sc, ldi->logical_device_number) != bus) ||
  920                 (MLY_LOGDEV_TARGET(sc, ldi->logical_device_number) != target)) {
  921                 mly_printf(sc, "WARNING: BTL rescan for %d:%d returned data for %d:%d instead\n",
  922                            bus, target, MLY_LOGDEV_BUS(sc, ldi->logical_device_number),
  923                            MLY_LOGDEV_TARGET(sc, ldi->logical_device_number));
  924                 /* XXX what can we do about this? */
  925             }
  926             btl.mb_flags = MLY_BTL_LOGICAL;
  927             btl.mb_type = ldi->raid_level;
  928             btl.mb_state = ldi->state;
  929             debug(1, "BTL rescan for %d returns %s, %s", ldi->logical_device_number, 
  930                   mly_describe_code(mly_table_device_type, ldi->raid_level),
  931                   mly_describe_code(mly_table_device_state, ldi->state));
  932         } else if (mc->mc_length == sizeof(*pdi)) {
  933             pdi = (struct mly_ioctl_getphysdevinfovalid *)mc->mc_data;
  934             if ((pdi->channel != bus) || (pdi->target != target)) {
  935                 mly_printf(sc, "WARNING: BTL rescan for %d:%d returned data for %d:%d instead\n",
  936                            bus, target, pdi->channel, pdi->target);
  937                 /* XXX what can we do about this? */
  938             }
  939             btl.mb_flags = MLY_BTL_PHYSICAL;
  940             btl.mb_type = MLY_DEVICE_TYPE_PHYSICAL;
  941             btl.mb_state = pdi->state;
  942             btl.mb_speed = pdi->speed;
  943             btl.mb_width = pdi->width;
  944             if (pdi->state != MLY_DEVICE_STATE_UNCONFIGURED)
  945                 sc->mly_btl[bus][target].mb_flags |= MLY_BTL_PROTECTED;
  946             debug(1, "BTL rescan for %d:%d returns %s", bus, target, 
  947                   mly_describe_code(mly_table_device_state, pdi->state));
  948         } else {
  949             mly_printf(sc, "BTL rescan result invalid\n");
  950         }
  951     }
  952 
  953     free(mc->mc_data, M_DEVBUF);
  954     mly_release_command(mc);
  955 
  956     /*
  957      * Decide whether we need to rescan the device.
  958      */
  959     rescan = 0;
  960 
  961     /* device type changes (usually between 'nothing' and 'something') */
  962     btlp = &sc->mly_btl[bus][target];
  963     if (btl.mb_flags != btlp->mb_flags) {
  964         debug(1, "flags changed, rescanning");
  965         rescan = 1;
  966     }
  967     
  968     /* XXX other reasons? */
  969 
  970     /*
  971      * Update BTL information.
  972      */
  973     *btlp = btl;
  974 
  975     /*
  976      * Perform CAM rescan if required.
  977      */
  978     if (rescan)
  979         mly_cam_rescan_btl(sc, bus, target);
  980 }
  981 
  982 /********************************************************************************
  983  * Get the current health status and set the 'next event' counter to suit.
  984  */
  985 static int
  986 mly_get_eventstatus(struct mly_softc *sc)
  987 {
  988     struct mly_command_ioctl    mci;
  989     struct mly_health_status    *mh;
  990     u_int8_t                    status;
  991     int                         error;
  992 
  993     /* build the gethealthstatus ioctl and send it */
  994     bzero(&mci, sizeof(mci));
  995     mh = NULL;
  996     mci.sub_ioctl = MDACIOCTL_GETHEALTHSTATUS;
  997 
  998     if ((error = mly_ioctl(sc, &mci, (void **)&mh, sizeof(*mh), &status, NULL, NULL)))
  999         return(error);
 1000     if (status != 0)
 1001         return(EIO);
 1002 
 1003     /* get the event counter */
 1004     sc->mly_event_change = mh->change_counter;
 1005     sc->mly_event_waiting = mh->next_event;
 1006     sc->mly_event_counter = mh->next_event;
 1007 
 1008     /* save the health status into the memory mailbox */
 1009     bcopy(mh, &sc->mly_mmbox->mmm_health.status, sizeof(*mh));
 1010 
 1011     debug(1, "initial change counter %d, event counter %d", mh->change_counter, mh->next_event);
 1012     
 1013     free(mh, M_DEVBUF);
 1014     return(0);
 1015 }
 1016 
 1017 /********************************************************************************
 1018  * Enable the memory mailbox mode.
 1019  */
 1020 static int
 1021 mly_enable_mmbox(struct mly_softc *sc)
 1022 {
 1023     struct mly_command_ioctl    mci;
 1024     u_int8_t                    *sp, status;
 1025     int                         error;
 1026 
 1027     debug_called(1);
 1028 
 1029     /* build the ioctl and send it */
 1030     bzero(&mci, sizeof(mci));
 1031     mci.sub_ioctl = MDACIOCTL_SETMEMORYMAILBOX;
 1032     /* set buffer addresses */
 1033     mci.param.setmemorymailbox.command_mailbox_physaddr = 
 1034         sc->mly_mmbox_busaddr + offsetof(struct mly_mmbox, mmm_command);
 1035     mci.param.setmemorymailbox.status_mailbox_physaddr = 
 1036         sc->mly_mmbox_busaddr + offsetof(struct mly_mmbox, mmm_status);
 1037     mci.param.setmemorymailbox.health_buffer_physaddr = 
 1038         sc->mly_mmbox_busaddr + offsetof(struct mly_mmbox, mmm_health);
 1039 
 1040     /* set buffer sizes - abuse of data_size field is revolting */
 1041     sp = (u_int8_t *)&mci.data_size;
 1042     sp[0] = ((sizeof(union mly_command_packet) * MLY_MMBOX_COMMANDS) / 1024);
 1043     sp[1] = (sizeof(union mly_status_packet) * MLY_MMBOX_STATUS) / 1024;
 1044     mci.param.setmemorymailbox.health_buffer_size = sizeof(union mly_health_region) / 1024;
 1045 
 1046     debug(1, "memory mailbox at %p (0x%llx/%d 0x%llx/%d 0x%llx/%d", sc->mly_mmbox,
 1047           mci.param.setmemorymailbox.command_mailbox_physaddr, sp[0],
 1048           mci.param.setmemorymailbox.status_mailbox_physaddr, sp[1],
 1049           mci.param.setmemorymailbox.health_buffer_physaddr, 
 1050           mci.param.setmemorymailbox.health_buffer_size);
 1051 
 1052     if ((error = mly_ioctl(sc, &mci, NULL, 0, &status, NULL, NULL)))
 1053         return(error);
 1054     if (status != 0)
 1055         return(EIO);
 1056     sc->mly_state |= MLY_STATE_MMBOX_ACTIVE;
 1057     debug(1, "memory mailbox active");
 1058     return(0);
 1059 }
 1060 
 1061 /********************************************************************************
 1062  * Flush all pending I/O from the controller.
 1063  */
 1064 static int
 1065 mly_flush(struct mly_softc *sc)
 1066 {
 1067     struct mly_command_ioctl    mci;
 1068     u_int8_t                    status;
 1069     int                         error;
 1070 
 1071     debug_called(1);
 1072 
 1073     /* build the ioctl */
 1074     bzero(&mci, sizeof(mci));
 1075     mci.sub_ioctl = MDACIOCTL_FLUSHDEVICEDATA;
 1076     mci.param.deviceoperation.operation_device = MLY_OPDEVICE_PHYSICAL_CONTROLLER;
 1077 
 1078     /* pass it off to the controller */
 1079     if ((error = mly_ioctl(sc, &mci, NULL, 0, &status, NULL, NULL)))
 1080         return(error);
 1081 
 1082     return((status == 0) ? 0 : EIO);
 1083 }
 1084 
 1085 /********************************************************************************
 1086  * Perform an ioctl command.
 1087  *
 1088  * If (data) is not NULL, the command requires data transfer.  If (*data) is NULL
 1089  * the command requires data transfer from the controller, and we will allocate
 1090  * a buffer for it.  If (*data) is not NULL, the command requires data transfer
 1091  * to the controller.
 1092  *
 1093  * XXX passing in the whole ioctl structure is ugly.  Better ideas?
 1094  *
 1095  * XXX we don't even try to handle the case where datasize > 4k.  We should.
 1096  */
 1097 static int
 1098 mly_ioctl(struct mly_softc *sc, struct mly_command_ioctl *ioctl, void **data, size_t datasize, 
 1099           u_int8_t *status, void *sense_buffer, size_t *sense_length)
 1100 {
 1101     struct mly_command          *mc;
 1102     struct mly_command_ioctl    *mci;
 1103     int                         error;
 1104 
 1105     debug_called(1);
 1106 
 1107     mc = NULL;
 1108     if (mly_alloc_command(sc, &mc)) {
 1109         error = ENOMEM;
 1110         goto out;
 1111     }
 1112 
 1113     /* copy the ioctl structure, but save some important fields and then fixup */
 1114     mci = &mc->mc_packet->ioctl;
 1115     ioctl->sense_buffer_address = mci->sense_buffer_address;
 1116     ioctl->maximum_sense_size = mci->maximum_sense_size;
 1117     *mci = *ioctl;
 1118     mci->opcode = MDACMD_IOCTL;
 1119     mci->timeout.value = 30;
 1120     mci->timeout.scale = MLY_TIMEOUT_SECONDS;
 1121     
 1122     /* handle the data buffer */
 1123     if (data != NULL) {
 1124         if (*data == NULL) {
 1125             /* allocate data buffer */
 1126             if ((mc->mc_data = malloc(datasize, M_DEVBUF, M_NOWAIT)) == NULL) {
 1127                 error = ENOMEM;
 1128                 goto out;
 1129             }
 1130             mc->mc_flags |= MLY_CMD_DATAIN;
 1131         } else {
 1132             mc->mc_data = *data;
 1133             mc->mc_flags |= MLY_CMD_DATAOUT;
 1134         }
 1135         mc->mc_length = datasize;
 1136         mc->mc_packet->generic.data_size = datasize;
 1137     }
 1138     
 1139     /* run the command */
 1140     if ((error = mly_immediate_command(mc)))
 1141         goto out;
 1142     
 1143     /* clean up and return any data */
 1144     *status = mc->mc_status;
 1145     if ((mc->mc_sense > 0) && (sense_buffer != NULL)) {
 1146         bcopy(mc->mc_packet, sense_buffer, mc->mc_sense);
 1147         *sense_length = mc->mc_sense;
 1148         goto out;
 1149     }
 1150 
 1151     /* should we return a data pointer? */
 1152     if ((data != NULL) && (*data == NULL))
 1153         *data = mc->mc_data;
 1154 
 1155     /* command completed OK */
 1156     error = 0;
 1157 
 1158 out:
 1159     if (mc != NULL) {
 1160         /* do we need to free a data buffer we allocated? */
 1161         if (error && (mc->mc_data != NULL) && (*data == NULL))
 1162             free(mc->mc_data, M_DEVBUF);
 1163         mly_release_command(mc);
 1164     }
 1165     return(error);
 1166 }
 1167 
 1168 /********************************************************************************
 1169  * Check for event(s) outstanding in the controller.
 1170  */
 1171 static void
 1172 mly_check_event(struct mly_softc *sc)
 1173 {
 1174     
 1175     /*
 1176      * The controller may have updated the health status information,
 1177      * so check for it here.  Note that the counters are all in host memory,
 1178      * so this check is very cheap.  Also note that we depend on checking on
 1179      * completion 
 1180      */
 1181     if (sc->mly_mmbox->mmm_health.status.change_counter != sc->mly_event_change) {
 1182         sc->mly_event_change = sc->mly_mmbox->mmm_health.status.change_counter;
 1183         debug(1, "event change %d, event status update, %d -> %d", sc->mly_event_change,
 1184               sc->mly_event_waiting, sc->mly_mmbox->mmm_health.status.next_event);
 1185         sc->mly_event_waiting = sc->mly_mmbox->mmm_health.status.next_event;
 1186 
 1187         /* wake up anyone that might be interested in this */
 1188         wakeup(&sc->mly_event_change);
 1189     }
 1190     if (sc->mly_event_counter != sc->mly_event_waiting)
 1191     mly_fetch_event(sc);
 1192 }
 1193 
 1194 /********************************************************************************
 1195  * Fetch one event from the controller.
 1196  *
 1197  * If we fail due to resource starvation, we'll be retried the next time a 
 1198  * command completes.
 1199  */
 1200 static void
 1201 mly_fetch_event(struct mly_softc *sc)
 1202 {
 1203     struct mly_command          *mc;
 1204     struct mly_command_ioctl    *mci;
 1205     int                         s;
 1206     u_int32_t                   event;
 1207 
 1208     debug_called(1);
 1209 
 1210     /* get a command */
 1211     if (mly_alloc_command(sc, &mc))
 1212         return;
 1213 
 1214     /* set up the data buffer */
 1215     if ((mc->mc_data = malloc(sizeof(struct mly_event), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
 1216         mly_release_command(mc);
 1217         return;
 1218     }
 1219     mc->mc_length = sizeof(struct mly_event);
 1220     mc->mc_flags |= MLY_CMD_DATAIN;
 1221     mc->mc_complete = mly_complete_event;
 1222 
 1223     /*
 1224      * Get an event number to fetch.  It's possible that we've raced with another
 1225      * context for the last event, in which case there will be no more events.
 1226      */
 1227     s = splcam();
 1228     if (sc->mly_event_counter == sc->mly_event_waiting) {
 1229         mly_release_command(mc);
 1230         splx(s);
 1231         return;
 1232     }
 1233     event = sc->mly_event_counter++;
 1234     splx(s);
 1235 
 1236     /* 
 1237      * Build the ioctl.
 1238      *
 1239      * At this point we are committed to sending this request, as it
 1240      * will be the only one constructed for this particular event number.
 1241      */
 1242     mci = (struct mly_command_ioctl *)&mc->mc_packet->ioctl;
 1243     mci->opcode = MDACMD_IOCTL;
 1244     mci->data_size = sizeof(struct mly_event);
 1245     mci->addr.phys.lun = (event >> 16) & 0xff;
 1246     mci->addr.phys.target = (event >> 24) & 0xff;
 1247     mci->addr.phys.channel = 0;
 1248     mci->addr.phys.controller = 0;
 1249     mci->timeout.value = 30;
 1250     mci->timeout.scale = MLY_TIMEOUT_SECONDS;
 1251     mci->sub_ioctl = MDACIOCTL_GETEVENT;
 1252     mci->param.getevent.sequence_number_low = event & 0xffff;
 1253 
 1254     debug(1, "fetch event %u", event);
 1255 
 1256     /*
 1257      * Submit the command.
 1258      *
 1259      * Note that failure of mly_start() will result in this event never being
 1260      * fetched.
 1261      */
 1262     if (mly_start(mc) != 0) {
 1263         mly_printf(sc, "couldn't fetch event %u\n", event);
 1264         mly_release_command(mc);
 1265     }
 1266 }
 1267 
 1268 /********************************************************************************
 1269  * Handle the completion of an event poll.
 1270  */
 1271 static void
 1272 mly_complete_event(struct mly_command *mc)
 1273 {
 1274     struct mly_softc    *sc = mc->mc_sc;
 1275     struct mly_event    *me = (struct mly_event *)mc->mc_data;
 1276 
 1277     debug_called(1);
 1278 
 1279     /* 
 1280      * If the event was successfully fetched, process it.
 1281      */
 1282     if (mc->mc_status == SCSI_STATUS_OK) {
 1283         mly_process_event(sc, me);
 1284         free(me, M_DEVBUF);
 1285     }
 1286     mly_release_command(mc);
 1287 
 1288     /*
 1289      * Check for another event.
 1290      */
 1291     mly_check_event(sc);
 1292 }
 1293 
 1294 /********************************************************************************
 1295  * Process a controller event.
 1296  */
 1297 static void
 1298 mly_process_event(struct mly_softc *sc, struct mly_event *me)
 1299 {
 1300     struct scsi_sense_data      *ssd = (struct scsi_sense_data *)&me->sense[0];
 1301     char                        *fp, *tp;
 1302     int                         bus, target, event, class, action;
 1303 
 1304     /* 
 1305      * Errors can be reported using vendor-unique sense data.  In this case, the
 1306      * event code will be 0x1c (Request sense data present), the sense key will
 1307      * be 0x09 (vendor specific), the MSB of the ASC will be set, and the 
 1308      * actual event code will be a 16-bit value comprised of the ASCQ (low byte)
 1309      * and low seven bits of the ASC (low seven bits of the high byte).
 1310      */
 1311     if ((me->code == 0x1c) && 
 1312         ((ssd->flags & SSD_KEY) == SSD_KEY_Vendor_Specific) &&
 1313         (ssd->add_sense_code & 0x80)) {
 1314         event = ((int)(ssd->add_sense_code & ~0x80) << 8) + ssd->add_sense_code_qual;
 1315     } else {
 1316         event = me->code;
 1317     }
 1318 
 1319     /* look up event, get codes */
 1320     fp = mly_describe_code(mly_table_event, event);
 1321 
 1322     debug(1, "Event %d  code 0x%x", me->sequence_number, me->code);
 1323 
 1324     /* quiet event? */
 1325     class = fp[0];
 1326     if (isupper(class) && bootverbose)
 1327         class = tolower(class);
 1328 
 1329     /* get action code, text string */
 1330     action = fp[1];
 1331     tp = &fp[2];
 1332 
 1333     /*
 1334      * Print some information about the event.
 1335      *
 1336      * This code uses a table derived from the corresponding portion of the Linux
 1337      * driver, and thus the parser is very similar.
 1338      */
 1339     switch(class) {
 1340     case 'p':           /* error on physical device */
 1341         mly_printf(sc, "physical device %d:%d %s\n", me->channel, me->target, tp);
 1342         if (action == 'r')
 1343             sc->mly_btl[me->channel][me->target].mb_flags |= MLY_BTL_RESCAN;
 1344         break;
 1345     case 'l':           /* error on logical unit */
 1346     case 'm':           /* message about logical unit */
 1347         bus = MLY_LOGDEV_BUS(sc, me->lun);
 1348         target = MLY_LOGDEV_TARGET(sc, me->lun);
 1349         mly_name_device(sc, bus, target);
 1350         mly_printf(sc, "logical device %d (%s) %s\n", me->lun, sc->mly_btl[bus][target].mb_name, tp);
 1351         if (action == 'r')
 1352             sc->mly_btl[bus][target].mb_flags |= MLY_BTL_RESCAN;
 1353         break;
 1354       break;
 1355     case 's':           /* report of sense data */
 1356         if (((ssd->flags & SSD_KEY) == SSD_KEY_NO_SENSE) ||
 1357             (((ssd->flags & SSD_KEY) == SSD_KEY_NOT_READY) && 
 1358              (ssd->add_sense_code == 0x04) && 
 1359              ((ssd->add_sense_code_qual == 0x01) || (ssd->add_sense_code_qual == 0x02))))
 1360             break;      /* ignore NO_SENSE or NOT_READY in one case */
 1361 
 1362         mly_printf(sc, "physical device %d:%d %s\n", me->channel, me->target, tp);
 1363         mly_printf(sc, "  sense key %d  asc %02x  ascq %02x\n", 
 1364                       ssd->flags & SSD_KEY, ssd->add_sense_code, ssd->add_sense_code_qual);
 1365         mly_printf(sc, "  info %4D  csi %4D\n", ssd->info, "", ssd->cmd_spec_info, "");
 1366         if (action == 'r')
 1367             sc->mly_btl[me->channel][me->target].mb_flags |= MLY_BTL_RESCAN;
 1368         break;
 1369     case 'e':
 1370         mly_printf(sc, tp, me->target, me->lun);
 1371         printf("\n");
 1372         break;
 1373     case 'c':
 1374         mly_printf(sc, "controller %s\n", tp);
 1375         break;
 1376     case '?':
 1377         mly_printf(sc, "%s - %d\n", tp, me->code);
 1378         break;
 1379     default:    /* probably a 'noisy' event being ignored */
 1380         break;
 1381     }
 1382 }
 1383 
 1384 /********************************************************************************
 1385  * Perform periodic activities.
 1386  */
 1387 static void
 1388 mly_periodic(void *data)
 1389 {
 1390     struct mly_softc    *sc = (struct mly_softc *)data;
 1391     int                 bus, target;
 1392 
 1393     debug_called(2);
 1394 
 1395     /*
 1396      * Scan devices.
 1397      */
 1398     for (bus = 0; bus < sc->mly_cam_channels; bus++) {
 1399         if (MLY_BUS_IS_VALID(sc, bus)) {
 1400             for (target = 0; target < MLY_MAX_TARGETS; target++) {
 1401 
 1402                 /* ignore the controller in this scan */
 1403                 if (target == sc->mly_controllerparam->initiator_id)
 1404                     continue;
 1405 
 1406                 /* perform device rescan? */
 1407                 if (sc->mly_btl[bus][target].mb_flags & MLY_BTL_RESCAN)
 1408                     mly_rescan_btl(sc, bus, target);
 1409             }
 1410         }
 1411     }
 1412     
 1413     /* check for controller events */
 1414     mly_check_event(sc);
 1415 
 1416     /* reschedule ourselves */
 1417     sc->mly_periodic = timeout(mly_periodic, sc, MLY_PERIODIC_INTERVAL * hz);
 1418 }
 1419 
 1420 /********************************************************************************
 1421  ********************************************************************************
 1422                                                                Command Processing
 1423  ********************************************************************************
 1424  ********************************************************************************/
 1425 
 1426 /********************************************************************************
 1427  * Run a command and wait for it to complete.
 1428  *
 1429  */
 1430 static int
 1431 mly_immediate_command(struct mly_command *mc)
 1432 {
 1433     struct mly_softc    *sc = mc->mc_sc;
 1434     int                 error, s;
 1435 
 1436     debug_called(1);
 1437 
 1438     /* spinning at splcam is ugly, but we're only used during controller init */
 1439     s = splcam();
 1440     if ((error = mly_start(mc))) {
 1441         splx(s);
 1442         return(error);
 1443     }
 1444 
 1445     if (sc->mly_state & MLY_STATE_INTERRUPTS_ON) {
 1446         /* sleep on the command */
 1447         while(!(mc->mc_flags & MLY_CMD_COMPLETE)) {
 1448             tsleep(mc, PRIBIO, "mlywait", 0);
 1449         }
 1450     } else {
 1451         /* spin and collect status while we do */
 1452         while(!(mc->mc_flags & MLY_CMD_COMPLETE)) {
 1453             mly_done(mc->mc_sc);
 1454         }
 1455     }
 1456     splx(s);
 1457     return(0);
 1458 }
 1459 
 1460 /********************************************************************************
 1461  * Deliver a command to the controller.
 1462  *
 1463  * XXX it would be good to just queue commands that we can't submit immediately
 1464  *     and send them later, but we probably want a wrapper for that so that
 1465  *     we don't hang on a failed submission for an immediate command.
 1466  */
 1467 static int
 1468 mly_start(struct mly_command *mc)
 1469 {
 1470     struct mly_softc            *sc = mc->mc_sc;
 1471     union mly_command_packet    *pkt;
 1472     int                         s;
 1473 
 1474     debug_called(2);
 1475 
 1476     /* 
 1477      * Set the command up for delivery to the controller. 
 1478      */
 1479     mly_map_command(mc);
 1480     mc->mc_packet->generic.command_id = mc->mc_slot;
 1481 
 1482 #ifdef MLY_DEBUG
 1483     mc->mc_timestamp = time_second;
 1484 #endif
 1485 
 1486     s = splcam();
 1487 
 1488     /*
 1489      * Do we have to use the hardware mailbox?
 1490      */
 1491     if (!(sc->mly_state & MLY_STATE_MMBOX_ACTIVE)) {
 1492         /*
 1493          * Check to see if the controller is ready for us.
 1494          */
 1495         if (MLY_IDBR_TRUE(sc, MLY_HM_CMDSENT)) {
 1496             splx(s);
 1497             return(EBUSY);
 1498         }
 1499         mc->mc_flags |= MLY_CMD_BUSY;
 1500         
 1501         /*
 1502          * It's ready, send the command.
 1503          */
 1504         MLY_SET_MBOX(sc, sc->mly_command_mailbox, &mc->mc_packetphys);
 1505         MLY_SET_REG(sc, sc->mly_idbr, MLY_HM_CMDSENT);
 1506 
 1507     } else {    /* use memory-mailbox mode */
 1508 
 1509         pkt = &sc->mly_mmbox->mmm_command[sc->mly_mmbox_command_index];
 1510 
 1511         /* check to see if the next index is free yet */
 1512         if (pkt->mmbox.flag != 0) {
 1513             splx(s);
 1514             return(EBUSY);
 1515         }
 1516         mc->mc_flags |= MLY_CMD_BUSY;
 1517         
 1518         /* copy in new command */
 1519         bcopy(mc->mc_packet->mmbox.data, pkt->mmbox.data, sizeof(pkt->mmbox.data));
 1520         /* barrier to ensure completion of previous write before we write the flag */
 1521         bus_space_barrier(sc->mly_btag, sc->mly_bhandle, 0, 0,
 1522             BUS_SPACE_BARRIER_WRITE);
 1523         /* copy flag last */
 1524         pkt->mmbox.flag = mc->mc_packet->mmbox.flag;
 1525         /* barrier to ensure completion of previous write before we notify the controller */
 1526         bus_space_barrier(sc->mly_btag, sc->mly_bhandle, 0, 0,
 1527             BUS_SPACE_BARRIER_WRITE);
 1528 
 1529         /* signal controller, update index */
 1530         MLY_SET_REG(sc, sc->mly_idbr, MLY_AM_CMDSENT);
 1531         sc->mly_mmbox_command_index = (sc->mly_mmbox_command_index + 1) % MLY_MMBOX_COMMANDS;
 1532     }
 1533 
 1534     mly_enqueue_busy(mc);
 1535     splx(s);
 1536     return(0);
 1537 }
 1538 
 1539 /********************************************************************************
 1540  * Pick up command status from the controller, schedule a completion event
 1541  */
 1542 static void
 1543 mly_done(struct mly_softc *sc) 
 1544 {
 1545     struct mly_command          *mc;
 1546     union mly_status_packet     *sp;
 1547     u_int16_t                   slot;
 1548     int                         s, worked;
 1549 
 1550     s = splcam();
 1551     worked = 0;
 1552 
 1553     /* pick up hardware-mailbox commands */
 1554     if (MLY_ODBR_TRUE(sc, MLY_HM_STSREADY)) {
 1555         slot = MLY_GET_REG2(sc, sc->mly_status_mailbox);
 1556         if (slot < MLY_SLOT_MAX) {
 1557             mc = &sc->mly_command[slot - MLY_SLOT_START];
 1558             mc->mc_status = MLY_GET_REG(sc, sc->mly_status_mailbox + 2);
 1559             mc->mc_sense = MLY_GET_REG(sc, sc->mly_status_mailbox + 3);
 1560             mc->mc_resid = MLY_GET_REG4(sc, sc->mly_status_mailbox + 4);
 1561             mly_remove_busy(mc);
 1562             mc->mc_flags &= ~MLY_CMD_BUSY;
 1563             mly_enqueue_complete(mc);
 1564             worked = 1;
 1565         } else {
 1566             /* slot 0xffff may mean "extremely bogus command" */
 1567             mly_printf(sc, "got HM completion for illegal slot %u\n", slot);
 1568         }
 1569         /* unconditionally acknowledge status */
 1570         MLY_SET_REG(sc, sc->mly_odbr, MLY_HM_STSREADY);
 1571         MLY_SET_REG(sc, sc->mly_idbr, MLY_HM_STSACK);
 1572     }
 1573 
 1574     /* pick up memory-mailbox commands */
 1575     if (MLY_ODBR_TRUE(sc, MLY_AM_STSREADY)) {
 1576         for (;;) {
 1577             sp = &sc->mly_mmbox->mmm_status[sc->mly_mmbox_status_index];
 1578 
 1579             /* check for more status */
 1580             if (sp->mmbox.flag == 0)
 1581                 break;
 1582 
 1583             /* get slot number */
 1584             slot = sp->status.command_id;
 1585             if (slot < MLY_SLOT_MAX) {
 1586                 mc = &sc->mly_command[slot - MLY_SLOT_START];
 1587                 mc->mc_status = sp->status.status;
 1588                 mc->mc_sense = sp->status.sense_length;
 1589                 mc->mc_resid = sp->status.residue;
 1590                 mly_remove_busy(mc);
 1591                 mc->mc_flags &= ~MLY_CMD_BUSY;
 1592                 mly_enqueue_complete(mc);
 1593                 worked = 1;
 1594             } else {
 1595                 /* slot 0xffff may mean "extremely bogus command" */
 1596                 mly_printf(sc, "got AM completion for illegal slot %u at %d\n", 
 1597                            slot, sc->mly_mmbox_status_index);
 1598             }
 1599 
 1600             /* clear and move to next index */
 1601             sp->mmbox.flag = 0;
 1602             sc->mly_mmbox_status_index = (sc->mly_mmbox_status_index + 1) % MLY_MMBOX_STATUS;
 1603         }
 1604         /* acknowledge that we have collected status value(s) */
 1605         MLY_SET_REG(sc, sc->mly_odbr, MLY_AM_STSREADY);
 1606     }
 1607 
 1608     splx(s);
 1609     if (worked) {
 1610 #if __FreeBSD_version >= 500005
 1611         if (sc->mly_state & MLY_STATE_INTERRUPTS_ON)
 1612             taskqueue_enqueue(taskqueue_swi_giant, &sc->mly_task_complete);
 1613         else
 1614 #endif
 1615             mly_complete(sc, 0);
 1616     }
 1617 }
 1618 
 1619 /********************************************************************************
 1620  * Process completed commands
 1621  */
 1622 static void
 1623 mly_complete(void *context, int pending)
 1624 {
 1625     struct mly_softc    *sc = (struct mly_softc *)context;
 1626     struct mly_command  *mc;
 1627     void                (* mc_complete)(struct mly_command *mc);
 1628 
 1629 
 1630     debug_called(2);
 1631 
 1632     /* 
 1633      * Spin pulling commands off the completed queue and processing them.
 1634      */
 1635     while ((mc = mly_dequeue_complete(sc)) != NULL) {
 1636 
 1637         /*
 1638          * Free controller resources, mark command complete.
 1639          *
 1640          * Note that as soon as we mark the command complete, it may be freed
 1641          * out from under us, so we need to save the mc_complete field in
 1642          * order to later avoid dereferencing mc.  (We would not expect to
 1643          * have a polling/sleeping consumer with mc_complete != NULL).
 1644          */
 1645         mly_unmap_command(mc);
 1646         mc_complete = mc->mc_complete;
 1647         mc->mc_flags |= MLY_CMD_COMPLETE;
 1648 
 1649         /* 
 1650          * Call completion handler or wake up sleeping consumer.
 1651          */
 1652         if (mc_complete != NULL) {
 1653             mc_complete(mc);
 1654         } else {
 1655             wakeup(mc);
 1656         }
 1657     }
 1658     
 1659     /*
 1660      * XXX if we are deferring commands due to controller-busy status, we should
 1661      *     retry submitting them here.
 1662      */
 1663 }
 1664 
 1665 /********************************************************************************
 1666  ********************************************************************************
 1667                                                         Command Buffer Management
 1668  ********************************************************************************
 1669  ********************************************************************************/
 1670 
 1671 /********************************************************************************
 1672  * Allocate a command.
 1673  */
 1674 static int
 1675 mly_alloc_command(struct mly_softc *sc, struct mly_command **mcp)
 1676 {
 1677     struct mly_command  *mc;
 1678 
 1679     debug_called(3);
 1680 
 1681     if ((mc = mly_dequeue_free(sc)) == NULL)
 1682         return(ENOMEM);
 1683 
 1684     *mcp = mc;
 1685     return(0);
 1686 }
 1687 
 1688 /********************************************************************************
 1689  * Release a command back to the freelist.
 1690  */
 1691 static void
 1692 mly_release_command(struct mly_command *mc)
 1693 {
 1694     debug_called(3);
 1695 
 1696     /*
 1697      * Fill in parts of the command that may cause confusion if
 1698      * a consumer doesn't when we are later allocated.
 1699      */
 1700     mc->mc_data = NULL;
 1701     mc->mc_flags = 0;
 1702     mc->mc_complete = NULL;
 1703     mc->mc_private = NULL;
 1704 
 1705     /*
 1706      * By default, we set up to overwrite the command packet with
 1707      * sense information.
 1708      */
 1709     mc->mc_packet->generic.sense_buffer_address = mc->mc_packetphys;
 1710     mc->mc_packet->generic.maximum_sense_size = sizeof(union mly_command_packet);
 1711 
 1712     mly_enqueue_free(mc);
 1713 }
 1714 
 1715 /********************************************************************************
 1716  * Map helper for command allocation.
 1717  */
 1718 static void
 1719 mly_alloc_commands_map(void *arg, bus_dma_segment_t *segs, int nseg, int error)
 1720 {
 1721     struct mly_softc    *sc = (struct mly_softc *)arg;
 1722 
 1723     debug_called(1);
 1724 
 1725     sc->mly_packetphys = segs[0].ds_addr;
 1726 }
 1727 
 1728 /********************************************************************************
 1729  * Allocate and initialise command and packet structures.
 1730  *
 1731  * If the controller supports fewer than MLY_MAX_COMMANDS commands, limit our
 1732  * allocation to that number.  If we don't yet know how many commands the
 1733  * controller supports, allocate a very small set (suitable for initialisation
 1734  * purposes only).
 1735  */
 1736 static int
 1737 mly_alloc_commands(struct mly_softc *sc)
 1738 {
 1739     struct mly_command          *mc;
 1740     int                         i, ncmd;
 1741  
 1742     if (sc->mly_controllerinfo == NULL) {
 1743         ncmd = 4;
 1744     } else {
 1745         ncmd = min(MLY_MAX_COMMANDS, sc->mly_controllerinfo->maximum_parallel_commands);
 1746     }
 1747 
 1748     /*
 1749      * Allocate enough space for all the command packets in one chunk and
 1750      * map them permanently into controller-visible space.
 1751      */
 1752     if (bus_dmamem_alloc(sc->mly_packet_dmat, (void **)&sc->mly_packet, 
 1753                          BUS_DMA_NOWAIT, &sc->mly_packetmap)) {
 1754         return(ENOMEM);
 1755     }
 1756     if (bus_dmamap_load(sc->mly_packet_dmat, sc->mly_packetmap, sc->mly_packet, 
 1757                         ncmd * sizeof(union mly_command_packet), 
 1758                         mly_alloc_commands_map, sc, BUS_DMA_NOWAIT) != 0)
 1759         return (ENOMEM);
 1760 
 1761     for (i = 0; i < ncmd; i++) {
 1762         mc = &sc->mly_command[i];
 1763         bzero(mc, sizeof(*mc));
 1764         mc->mc_sc = sc;
 1765         mc->mc_slot = MLY_SLOT_START + i;
 1766         mc->mc_packet = sc->mly_packet + i;
 1767         mc->mc_packetphys = sc->mly_packetphys + (i * sizeof(union mly_command_packet));
 1768         if (!bus_dmamap_create(sc->mly_buffer_dmat, 0, &mc->mc_datamap))
 1769             mly_release_command(mc);
 1770     }
 1771     return(0);
 1772 }
 1773 
 1774 /********************************************************************************
 1775  * Free all the storage held by commands.
 1776  *
 1777  * Must be called with all commands on the free list.
 1778  */
 1779 static void
 1780 mly_release_commands(struct mly_softc *sc)
 1781 {
 1782     struct mly_command  *mc;
 1783 
 1784     /* throw away command buffer DMA maps */
 1785     while (mly_alloc_command(sc, &mc) == 0)
 1786         bus_dmamap_destroy(sc->mly_buffer_dmat, mc->mc_datamap);
 1787 
 1788     /* release the packet storage */
 1789     if (sc->mly_packet != NULL) {
 1790         bus_dmamap_unload(sc->mly_packet_dmat, sc->mly_packetmap);
 1791         bus_dmamem_free(sc->mly_packet_dmat, sc->mly_packet, sc->mly_packetmap);
 1792         sc->mly_packet = NULL;
 1793     }
 1794 }
 1795 
 1796 
 1797 /********************************************************************************
 1798  * Command-mapping helper function - populate this command's s/g table
 1799  * with the s/g entries for its data.
 1800  */
 1801 static void
 1802 mly_map_command_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error)
 1803 {
 1804     struct mly_command          *mc = (struct mly_command *)arg;
 1805     struct mly_softc            *sc = mc->mc_sc;
 1806     struct mly_command_generic  *gen = &(mc->mc_packet->generic);
 1807     struct mly_sg_entry         *sg;
 1808     int                         i, tabofs;
 1809 
 1810     debug_called(2);
 1811 
 1812     /* can we use the transfer structure directly? */
 1813     if (nseg <= 2) {
 1814         sg = &gen->transfer.direct.sg[0];
 1815         gen->command_control.extended_sg_table = 0;
 1816     } else {
 1817         tabofs = ((mc->mc_slot - MLY_SLOT_START) * MLY_MAX_SGENTRIES);
 1818         sg = sc->mly_sg_table + tabofs;
 1819         gen->transfer.indirect.entries[0] = nseg;
 1820         gen->transfer.indirect.table_physaddr[0] = sc->mly_sg_busaddr + (tabofs * sizeof(struct mly_sg_entry));
 1821         gen->command_control.extended_sg_table = 1;
 1822     }
 1823 
 1824     /* copy the s/g table */
 1825     for (i = 0; i < nseg; i++) {
 1826         sg[i].physaddr = segs[i].ds_addr;
 1827         sg[i].length = segs[i].ds_len;
 1828     }
 1829 
 1830 }
 1831 
 1832 #if 0
 1833 /********************************************************************************
 1834  * Command-mapping helper function - save the cdb's physical address.
 1835  *
 1836  * We don't support 'large' SCSI commands at this time, so this is unused.
 1837  */
 1838 static void
 1839 mly_map_command_cdb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
 1840 {
 1841     struct mly_command                  *mc = (struct mly_command *)arg;
 1842 
 1843     debug_called(2);
 1844 
 1845     /* XXX can we safely assume that a CDB will never cross a page boundary? */
 1846     if ((segs[0].ds_addr % PAGE_SIZE) > 
 1847         ((segs[0].ds_addr + mc->mc_packet->scsi_large.cdb_length) % PAGE_SIZE))
 1848         panic("cdb crosses page boundary");
 1849 
 1850     /* fix up fields in the command packet */
 1851     mc->mc_packet->scsi_large.cdb_physaddr = segs[0].ds_addr;
 1852 }
 1853 #endif
 1854 
 1855 /********************************************************************************
 1856  * Map a command into controller-visible space
 1857  */
 1858 static void
 1859 mly_map_command(struct mly_command *mc)
 1860 {
 1861     struct mly_softc    *sc = mc->mc_sc;
 1862 
 1863     debug_called(2);
 1864 
 1865     /* don't map more than once */
 1866     if (mc->mc_flags & MLY_CMD_MAPPED)
 1867         return;
 1868 
 1869     /* does the command have a data buffer? */
 1870     if (mc->mc_data != NULL) {
 1871         bus_dmamap_load(sc->mly_buffer_dmat, mc->mc_datamap, mc->mc_data, mc->mc_length, 
 1872                         mly_map_command_sg, mc, 0);
 1873         
 1874         if (mc->mc_flags & MLY_CMD_DATAIN)
 1875             bus_dmamap_sync(sc->mly_buffer_dmat, mc->mc_datamap, BUS_DMASYNC_PREREAD);
 1876         if (mc->mc_flags & MLY_CMD_DATAOUT)
 1877             bus_dmamap_sync(sc->mly_buffer_dmat, mc->mc_datamap, BUS_DMASYNC_PREWRITE);
 1878     }
 1879     mc->mc_flags |= MLY_CMD_MAPPED;
 1880 }
 1881 
 1882 /********************************************************************************
 1883  * Unmap a command from controller-visible space
 1884  */
 1885 static void
 1886 mly_unmap_command(struct mly_command *mc)
 1887 {
 1888     struct mly_softc    *sc = mc->mc_sc;
 1889 
 1890     debug_called(2);
 1891 
 1892     if (!(mc->mc_flags & MLY_CMD_MAPPED))
 1893         return;
 1894 
 1895     /* does the command have a data buffer? */
 1896     if (mc->mc_data != NULL) {
 1897         if (mc->mc_flags & MLY_CMD_DATAIN)
 1898             bus_dmamap_sync(sc->mly_buffer_dmat, mc->mc_datamap, BUS_DMASYNC_POSTREAD);
 1899         if (mc->mc_flags & MLY_CMD_DATAOUT)
 1900             bus_dmamap_sync(sc->mly_buffer_dmat, mc->mc_datamap, BUS_DMASYNC_POSTWRITE);
 1901 
 1902         bus_dmamap_unload(sc->mly_buffer_dmat, mc->mc_datamap);
 1903     }
 1904     mc->mc_flags &= ~MLY_CMD_MAPPED;
 1905 }
 1906 
 1907 
 1908 /********************************************************************************
 1909  ********************************************************************************
 1910                                                                     CAM interface
 1911  ********************************************************************************
 1912  ********************************************************************************/
 1913 
 1914 /********************************************************************************
 1915  * Attach the physical and virtual SCSI busses to CAM.
 1916  *
 1917  * Physical bus numbering starts from 0, virtual bus numbering from one greater
 1918  * than the highest physical bus.  Physical busses are only registered if
 1919  * the kernel environment variable "hw.mly.register_physical_channels" is set.
 1920  *
 1921  * When we refer to a "bus", we are referring to the bus number registered with
 1922  * the SIM, wheras a "channel" is a channel number given to the adapter.  In order
 1923  * to keep things simple, we map these 1:1, so "bus" and "channel" may be used
 1924  * interchangeably.
 1925  */
 1926 static int
 1927 mly_cam_attach(struct mly_softc *sc)
 1928 {
 1929     struct cam_devq     *devq;
 1930     int                 chn, i;
 1931 
 1932     debug_called(1);
 1933 
 1934     /*
 1935      * Allocate a devq for all our channels combined.
 1936      */
 1937     if ((devq = cam_simq_alloc(sc->mly_controllerinfo->maximum_parallel_commands)) == NULL) {
 1938         mly_printf(sc, "can't allocate CAM SIM queue\n");
 1939         return(ENOMEM);
 1940     }
 1941 
 1942     /*
 1943      * If physical channel registration has been requested, register these first.
 1944      * Note that we enable tagged command queueing for physical channels.
 1945      */
 1946     if (testenv("hw.mly.register_physical_channels")) {
 1947         chn = 0;
 1948         for (i = 0; i < sc->mly_controllerinfo->physical_channels_present; i++, chn++) {
 1949 
 1950             if ((sc->mly_cam_sim[chn] = cam_sim_alloc(mly_cam_action, mly_cam_poll, "mly", sc,
 1951                                                       device_get_unit(sc->mly_dev),
 1952                                                       sc->mly_controllerinfo->maximum_parallel_commands,
 1953                                                       1, devq)) == NULL) {
 1954                 return(ENOMEM);
 1955             }
 1956             if (xpt_bus_register(sc->mly_cam_sim[chn], chn)) {
 1957                 mly_printf(sc, "CAM XPT phsyical channel registration failed\n");
 1958                 return(ENXIO);
 1959             }
 1960             debug(1, "registered physical channel %d", chn);
 1961         }
 1962     }
 1963 
 1964     /*
 1965      * Register our virtual channels, with bus numbers matching channel numbers.
 1966      */
 1967     chn = sc->mly_controllerinfo->physical_channels_present;
 1968     for (i = 0; i < sc->mly_controllerinfo->virtual_channels_present; i++, chn++) {
 1969         if ((sc->mly_cam_sim[chn] = cam_sim_alloc(mly_cam_action, mly_cam_poll, "mly", sc,
 1970                                                   device_get_unit(sc->mly_dev),
 1971                                                   sc->mly_controllerinfo->maximum_parallel_commands,
 1972                                                   0, devq)) == NULL) {
 1973             return(ENOMEM);
 1974         }
 1975         if (xpt_bus_register(sc->mly_cam_sim[chn], chn)) {
 1976             mly_printf(sc, "CAM XPT virtual channel registration failed\n");
 1977             return(ENXIO);
 1978         }
 1979         debug(1, "registered virtual channel %d", chn);
 1980     }
 1981 
 1982     /*
 1983      * This is the total number of channels that (might have been) registered with
 1984      * CAM.  Some may not have been; check the mly_cam_sim array to be certain.
 1985      */
 1986     sc->mly_cam_channels = sc->mly_controllerinfo->physical_channels_present +
 1987         sc->mly_controllerinfo->virtual_channels_present;
 1988 
 1989     return(0);
 1990 }
 1991 
 1992 /********************************************************************************
 1993  * Detach from CAM
 1994  */
 1995 static void
 1996 mly_cam_detach(struct mly_softc *sc)
 1997 {
 1998     int         i;
 1999     
 2000     debug_called(1);
 2001 
 2002     for (i = 0; i < sc->mly_cam_channels; i++) {
 2003         if (sc->mly_cam_sim[i] != NULL) {
 2004             xpt_bus_deregister(cam_sim_path(sc->mly_cam_sim[i]));
 2005             cam_sim_free(sc->mly_cam_sim[i], 0);
 2006         }
 2007     }
 2008     if (sc->mly_cam_devq != NULL)
 2009         cam_simq_free(sc->mly_cam_devq);
 2010 }
 2011 
 2012 /************************************************************************
 2013  * Rescan a device.
 2014  */ 
 2015 static void
 2016 mly_cam_rescan_btl(struct mly_softc *sc, int bus, int target)
 2017 {
 2018     union ccb   *ccb;
 2019 
 2020     debug_called(1);
 2021 
 2022     if ((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK | M_ZERO)) == NULL) {
 2023         mly_printf(sc, "rescan failed (can't allocate CCB)\n");
 2024         return;
 2025     }
 2026     
 2027     if (xpt_create_path(&sc->mly_cam_path, xpt_periph, 
 2028                         cam_sim_path(sc->mly_cam_sim[bus]), target, 0) != CAM_REQ_CMP) {
 2029         mly_printf(sc, "rescan failed (can't create path)\n");
 2030         free(ccb, M_TEMP);
 2031         return;
 2032     }
 2033     xpt_setup_ccb(&ccb->ccb_h, sc->mly_cam_path, 5/*priority (low)*/);
 2034     ccb->ccb_h.func_code = XPT_SCAN_LUN;
 2035     ccb->ccb_h.cbfcnp = mly_cam_rescan_callback;
 2036     ccb->crcn.flags = CAM_FLAG_NONE;
 2037     debug(1, "rescan target %d:%d", bus, target);
 2038     xpt_action(ccb);
 2039 }
 2040 
 2041 static void
 2042 mly_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb)
 2043 {
 2044     free(ccb, M_TEMP);
 2045 }
 2046 
 2047 /********************************************************************************
 2048  * Handle an action requested by CAM
 2049  */
 2050 static void
 2051 mly_cam_action(struct cam_sim *sim, union ccb *ccb)
 2052 {
 2053     struct mly_softc    *sc = cam_sim_softc(sim);
 2054 
 2055     debug_called(2);
 2056 
 2057     switch (ccb->ccb_h.func_code) {
 2058 
 2059         /* perform SCSI I/O */
 2060     case XPT_SCSI_IO:
 2061         if (!mly_cam_action_io(sim, (struct ccb_scsiio *)&ccb->csio))
 2062             return;
 2063         break;
 2064 
 2065         /* perform geometry calculations */
 2066     case XPT_CALC_GEOMETRY:
 2067     {
 2068         struct ccb_calc_geometry        *ccg = &ccb->ccg;
 2069         u_int32_t                       secs_per_cylinder;
 2070 
 2071         debug(2, "XPT_CALC_GEOMETRY %d:%d:%d", cam_sim_bus(sim), ccb->ccb_h.target_id, ccb->ccb_h.target_lun);
 2072 
 2073         if (sc->mly_controllerparam->bios_geometry == MLY_BIOSGEOM_8G) {
 2074             ccg->heads = 255;
 2075             ccg->secs_per_track = 63;
 2076         } else {                                /* MLY_BIOSGEOM_2G */
 2077             ccg->heads = 128;
 2078             ccg->secs_per_track = 32;
 2079         }
 2080         secs_per_cylinder = ccg->heads * ccg->secs_per_track;
 2081         ccg->cylinders = ccg->volume_size / secs_per_cylinder;
 2082         ccb->ccb_h.status = CAM_REQ_CMP;
 2083         break;
 2084     }
 2085 
 2086         /* handle path attribute inquiry */
 2087     case XPT_PATH_INQ:
 2088     {
 2089         struct ccb_pathinq      *cpi = &ccb->cpi;
 2090 
 2091         debug(2, "XPT_PATH_INQ %d:%d:%d", cam_sim_bus(sim), ccb->ccb_h.target_id, ccb->ccb_h.target_lun);
 2092 
 2093         cpi->version_num = 1;
 2094         cpi->hba_inquiry = PI_TAG_ABLE;         /* XXX extra flags for physical channels? */
 2095         cpi->target_sprt = 0;
 2096         cpi->hba_misc = 0;
 2097         cpi->max_target = MLY_MAX_TARGETS - 1;
 2098         cpi->max_lun = MLY_MAX_LUNS - 1;
 2099         cpi->initiator_id = sc->mly_controllerparam->initiator_id;
 2100         strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
 2101         strncpy(cpi->hba_vid, "FreeBSD", HBA_IDLEN);
 2102         strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
 2103         cpi->unit_number = cam_sim_unit(sim);
 2104         cpi->bus_id = cam_sim_bus(sim);
 2105         cpi->base_transfer_speed = 132 * 1024;  /* XXX what to set this to? */
 2106         ccb->ccb_h.status = CAM_REQ_CMP;
 2107         break;
 2108     }
 2109 
 2110     case XPT_GET_TRAN_SETTINGS:
 2111     {
 2112         struct ccb_trans_settings       *cts = &ccb->cts;
 2113         int                             bus, target;
 2114 
 2115         bus = cam_sim_bus(sim);
 2116         target = cts->ccb_h.target_id;
 2117         /* XXX validate bus/target? */
 2118 
 2119         debug(2, "XPT_GET_TRAN_SETTINGS %d:%d", bus, target);
 2120         cts->valid = 0;
 2121 
 2122         /* logical device? */
 2123         if (sc->mly_btl[bus][target].mb_flags & MLY_BTL_LOGICAL) {
 2124             /* nothing special for these */
 2125 
 2126         /* physical device? */
 2127         } else if (sc->mly_btl[bus][target].mb_flags & MLY_BTL_PHYSICAL) {
 2128             /* allow CAM to try tagged transactions */
 2129             cts->flags |= CCB_TRANS_TAG_ENB;
 2130             cts->valid |= CCB_TRANS_TQ_VALID;
 2131 
 2132             /* convert speed (MHz) to usec */
 2133             if (sc->mly_btl[bus][target].mb_speed == 0) {
 2134                 cts->sync_period = 1000000 / 5;
 2135             } else {
 2136                 cts->sync_period = 1000000 / sc->mly_btl[bus][target].mb_speed;
 2137             }
 2138 
 2139             /* convert bus width to CAM internal encoding */
 2140             switch (sc->mly_btl[bus][target].mb_width) {
 2141             case 32:
 2142                 cts->bus_width = MSG_EXT_WDTR_BUS_32_BIT;
 2143                 break;
 2144             case 16:
 2145                 cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
 2146                 break;
 2147             case 8:
 2148             default:
 2149                 cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
 2150                 break;
 2151             }
 2152             cts->valid |= CCB_TRANS_SYNC_RATE_VALID | CCB_TRANS_BUS_WIDTH_VALID;
 2153 
 2154             /* not a device, bail out */
 2155         } else {
 2156             cts->ccb_h.status = CAM_REQ_CMP_ERR;
 2157             break;
 2158         }
 2159 
 2160         /* disconnect always OK */
 2161         cts->flags |= CCB_TRANS_DISC_ENB;
 2162         cts->valid |= CCB_TRANS_DISC_VALID;
 2163 
 2164         cts->ccb_h.status = CAM_REQ_CMP;
 2165         break;
 2166     }
 2167 
 2168     default:            /* we can't do this */
 2169         debug(2, "unspported func_code = 0x%x", ccb->ccb_h.func_code);
 2170         ccb->ccb_h.status = CAM_REQ_INVALID;
 2171         break;
 2172     }
 2173 
 2174     xpt_done(ccb);
 2175 }
 2176 
 2177 /********************************************************************************
 2178  * Handle an I/O operation requested by CAM
 2179  */
 2180 static int
 2181 mly_cam_action_io(struct cam_sim *sim, struct ccb_scsiio *csio)
 2182 {
 2183     struct mly_softc                    *sc = cam_sim_softc(sim);
 2184     struct mly_command                  *mc;
 2185     struct mly_command_scsi_small       *ss;
 2186     int                                 bus, target;
 2187     int                                 error;
 2188     int                                 s;
 2189 
 2190     bus = cam_sim_bus(sim);
 2191     target = csio->ccb_h.target_id;
 2192 
 2193     debug(2, "XPT_SCSI_IO %d:%d:%d", bus, target, csio->ccb_h.target_lun);
 2194 
 2195     /* validate bus number */
 2196     if (!MLY_BUS_IS_VALID(sc, bus)) {
 2197         debug(0, " invalid bus %d", bus);
 2198         csio->ccb_h.status = CAM_REQ_CMP_ERR;
 2199     }
 2200 
 2201     /*  check for I/O attempt to a protected device */
 2202     if (sc->mly_btl[bus][target].mb_flags & MLY_BTL_PROTECTED) {
 2203         debug(2, "  device protected");
 2204         csio->ccb_h.status = CAM_REQ_CMP_ERR;
 2205     }
 2206 
 2207     /* check for I/O attempt to nonexistent device */
 2208     if (!(sc->mly_btl[bus][target].mb_flags & (MLY_BTL_LOGICAL | MLY_BTL_PHYSICAL))) {
 2209         debug(2, "  device %d:%d does not exist", bus, target);
 2210         csio->ccb_h.status = CAM_REQ_CMP_ERR;
 2211     }
 2212 
 2213     /* XXX increase if/when we support large SCSI commands */
 2214     if (csio->cdb_len > MLY_CMD_SCSI_SMALL_CDB) {
 2215         debug(0, "  command too large (%d > %d)", csio->cdb_len, MLY_CMD_SCSI_SMALL_CDB);
 2216         csio->ccb_h.status = CAM_REQ_CMP_ERR;
 2217     }
 2218 
 2219     /* check that the CDB pointer is not to a physical address */
 2220     if ((csio->ccb_h.flags & CAM_CDB_POINTER) && (csio->ccb_h.flags & CAM_CDB_PHYS)) {
 2221         debug(0, "  CDB pointer is to physical address");
 2222         csio->ccb_h.status = CAM_REQ_CMP_ERR;
 2223     }
 2224 
 2225     /* if there is data transfer, it must be to/from a virtual address */
 2226     if ((csio->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
 2227         if (csio->ccb_h.flags & CAM_DATA_PHYS) {                /* we can't map it */
 2228             debug(0, "  data pointer is to physical address");
 2229             csio->ccb_h.status = CAM_REQ_CMP_ERR;
 2230         }
 2231         if (csio->ccb_h.flags & CAM_SCATTER_VALID) {    /* we want to do the s/g setup */
 2232             debug(0, "  data has premature s/g setup");
 2233             csio->ccb_h.status = CAM_REQ_CMP_ERR;
 2234         }
 2235     }
 2236 
 2237     /* abandon aborted ccbs or those that have failed validation */
 2238     if ((csio->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
 2239         debug(2, "abandoning CCB due to abort/validation failure");
 2240         return(EINVAL);
 2241     }
 2242 
 2243     /*
 2244      * Get a command, or push the ccb back to CAM and freeze the queue.
 2245      */
 2246     if ((error = mly_alloc_command(sc, &mc))) {
 2247         s = splcam();
 2248         xpt_freeze_simq(sim, 1);
 2249         csio->ccb_h.status |= CAM_REQUEUE_REQ;
 2250         sc->mly_qfrzn_cnt++;
 2251         splx(s);
 2252         return(error);
 2253     }
 2254     
 2255     /* build the command */
 2256     mc->mc_data = csio->data_ptr;
 2257     mc->mc_length = csio->dxfer_len;
 2258     mc->mc_complete = mly_cam_complete;
 2259     mc->mc_private = csio;
 2260 
 2261     /* save the bus number in the ccb for later recovery XXX should be a better way */
 2262      csio->ccb_h.sim_priv.entries[0].field = bus;
 2263 
 2264     /* build the packet for the controller */
 2265     ss = &mc->mc_packet->scsi_small;
 2266     ss->opcode = MDACMD_SCSI;
 2267     if (csio->ccb_h.flags & CAM_DIS_DISCONNECT)
 2268         ss->command_control.disable_disconnect = 1;
 2269     if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
 2270         ss->command_control.data_direction = MLY_CCB_WRITE;
 2271     ss->data_size = csio->dxfer_len;
 2272     ss->addr.phys.lun = csio->ccb_h.target_lun;
 2273     ss->addr.phys.target = csio->ccb_h.target_id;
 2274     ss->addr.phys.channel = bus;
 2275     if (csio->ccb_h.timeout < (60 * 1000)) {
 2276         ss->timeout.value = csio->ccb_h.timeout / 1000;
 2277         ss->timeout.scale = MLY_TIMEOUT_SECONDS;
 2278     } else if (csio->ccb_h.timeout < (60 * 60 * 1000)) {
 2279         ss->timeout.value = csio->ccb_h.timeout / (60 * 1000);
 2280         ss->timeout.scale = MLY_TIMEOUT_MINUTES;
 2281     } else {
 2282         ss->timeout.value = csio->ccb_h.timeout / (60 * 60 * 1000);     /* overflow? */
 2283         ss->timeout.scale = MLY_TIMEOUT_HOURS;
 2284     }
 2285     ss->maximum_sense_size = csio->sense_len;
 2286     ss->cdb_length = csio->cdb_len;
 2287     if (csio->ccb_h.flags & CAM_CDB_POINTER) {
 2288         bcopy(csio->cdb_io.cdb_ptr, ss->cdb, csio->cdb_len);
 2289     } else {
 2290         bcopy(csio->cdb_io.cdb_bytes, ss->cdb, csio->cdb_len);
 2291     }
 2292 
 2293     /* give the command to the controller */
 2294     if ((error = mly_start(mc))) {
 2295         s = splcam();
 2296         xpt_freeze_simq(sim, 1);
 2297         csio->ccb_h.status |= CAM_REQUEUE_REQ;
 2298         sc->mly_qfrzn_cnt++;
 2299         splx(s);
 2300         return(error);
 2301     }
 2302 
 2303     return(0);
 2304 }
 2305 
 2306 /********************************************************************************
 2307  * Check for possibly-completed commands.
 2308  */
 2309 static void
 2310 mly_cam_poll(struct cam_sim *sim)
 2311 {
 2312     struct mly_softc    *sc = cam_sim_softc(sim);
 2313 
 2314     debug_called(2);
 2315 
 2316     mly_done(sc);
 2317 }
 2318 
 2319 /********************************************************************************
 2320  * Handle completion of a command - pass results back through the CCB
 2321  */
 2322 static void
 2323 mly_cam_complete(struct mly_command *mc)
 2324 {
 2325     struct mly_softc            *sc = mc->mc_sc;
 2326     struct ccb_scsiio           *csio = (struct ccb_scsiio *)mc->mc_private;
 2327     struct scsi_inquiry_data    *inq = (struct scsi_inquiry_data *)csio->data_ptr;
 2328     struct mly_btl              *btl;
 2329     u_int8_t                    cmd;
 2330     int                         bus, target;
 2331     int                         s;
 2332 
 2333     debug_called(2);
 2334 
 2335     csio->scsi_status = mc->mc_status;
 2336     switch(mc->mc_status) {
 2337     case SCSI_STATUS_OK:
 2338         /*
 2339          * In order to report logical device type and status, we overwrite
 2340          * the result of the INQUIRY command to logical devices.
 2341          */
 2342         bus = csio->ccb_h.sim_priv.entries[0].field;
 2343         target = csio->ccb_h.target_id;
 2344         /* XXX validate bus/target? */
 2345         if (sc->mly_btl[bus][target].mb_flags & MLY_BTL_LOGICAL) {
 2346             if (csio->ccb_h.flags & CAM_CDB_POINTER) {
 2347                 cmd = *csio->cdb_io.cdb_ptr;
 2348             } else {
 2349                 cmd = csio->cdb_io.cdb_bytes[0];
 2350             }
 2351             if (cmd == INQUIRY) {
 2352                 btl = &sc->mly_btl[bus][target];
 2353                 padstr(inq->vendor, mly_describe_code(mly_table_device_type, btl->mb_type), 8);
 2354                 padstr(inq->product, mly_describe_code(mly_table_device_state, btl->mb_state), 16);
 2355                 padstr(inq->revision, "", 4);
 2356             }
 2357         }
 2358 
 2359         debug(2, "SCSI_STATUS_OK");
 2360         csio->ccb_h.status = CAM_REQ_CMP;
 2361         break;
 2362 
 2363     case SCSI_STATUS_CHECK_COND:
 2364         debug(1, "SCSI_STATUS_CHECK_COND  sense %d  resid %d", mc->mc_sense, mc->mc_resid);
 2365         csio->ccb_h.status = CAM_SCSI_STATUS_ERROR;
 2366         bzero(&csio->sense_data, SSD_FULL_SIZE);
 2367         bcopy(mc->mc_packet, &csio->sense_data, mc->mc_sense);
 2368         csio->sense_len = mc->mc_sense;
 2369         csio->ccb_h.status |= CAM_AUTOSNS_VALID;
 2370         csio->resid = mc->mc_resid;     /* XXX this is a signed value... */
 2371         break;
 2372 
 2373     case SCSI_STATUS_BUSY:
 2374         debug(1, "SCSI_STATUS_BUSY");
 2375         csio->ccb_h.status = CAM_SCSI_BUSY;
 2376         break;
 2377 
 2378     default:
 2379         debug(1, "unknown status 0x%x", csio->scsi_status);
 2380         csio->ccb_h.status = CAM_REQ_CMP_ERR;
 2381         break;
 2382     }
 2383 
 2384     s = splcam();
 2385     if (sc->mly_qfrzn_cnt) {
 2386         csio->ccb_h.status |= CAM_RELEASE_SIMQ;
 2387         sc->mly_qfrzn_cnt--;
 2388     }
 2389     splx(s);
 2390 
 2391     xpt_done((union ccb *)csio);
 2392     mly_release_command(mc);
 2393 }
 2394 
 2395 /********************************************************************************
 2396  * Find a peripheral attahed at (bus),(target)
 2397  */
 2398 static struct cam_periph *
 2399 mly_find_periph(struct mly_softc *sc, int bus, int target)
 2400 {
 2401     struct cam_periph   *periph;
 2402     struct cam_path     *path;
 2403     int                 status;
 2404 
 2405     status = xpt_create_path(&path, NULL, cam_sim_path(sc->mly_cam_sim[bus]), target, 0);
 2406     if (status == CAM_REQ_CMP) {
 2407         periph = cam_periph_find(path, NULL);
 2408         xpt_free_path(path);
 2409     } else {
 2410         periph = NULL;
 2411     }
 2412     return(periph);
 2413 }
 2414 
 2415 /********************************************************************************
 2416  * Name the device at (bus)(target)
 2417  */
 2418 static int
 2419 mly_name_device(struct mly_softc *sc, int bus, int target)
 2420 {
 2421     struct cam_periph   *periph;
 2422 
 2423     if ((periph = mly_find_periph(sc, bus, target)) != NULL) {
 2424         sprintf(sc->mly_btl[bus][target].mb_name, "%s%d", periph->periph_name, periph->unit_number);
 2425         return(0);
 2426     }
 2427     sc->mly_btl[bus][target].mb_name[0] = 0;
 2428     return(ENOENT);
 2429 }
 2430 
 2431 /********************************************************************************
 2432  ********************************************************************************
 2433                                                                  Hardware Control
 2434  ********************************************************************************
 2435  ********************************************************************************/
 2436 
 2437 /********************************************************************************
 2438  * Handshake with the firmware while the card is being initialised.
 2439  */
 2440 static int
 2441 mly_fwhandshake(struct mly_softc *sc) 
 2442 {
 2443     u_int8_t    error, param0, param1;
 2444     int         spinup = 0;
 2445 
 2446     debug_called(1);
 2447 
 2448     /* set HM_STSACK and let the firmware initialise */
 2449     MLY_SET_REG(sc, sc->mly_idbr, MLY_HM_STSACK);
 2450     DELAY(1000);        /* too short? */
 2451 
 2452     /* if HM_STSACK is still true, the controller is initialising */
 2453     if (!MLY_IDBR_TRUE(sc, MLY_HM_STSACK))
 2454         return(0);
 2455     mly_printf(sc, "controller initialisation started\n");
 2456 
 2457     /* spin waiting for initialisation to finish, or for a message to be delivered */
 2458     while (MLY_IDBR_TRUE(sc, MLY_HM_STSACK)) {
 2459         /* check for a message */
 2460         if (MLY_ERROR_VALID(sc)) {
 2461             error = MLY_GET_REG(sc, sc->mly_error_status) & ~MLY_MSG_EMPTY;
 2462             param0 = MLY_GET_REG(sc, sc->mly_command_mailbox);
 2463             param1 = MLY_GET_REG(sc, sc->mly_command_mailbox + 1);
 2464 
 2465             switch(error) {
 2466             case MLY_MSG_SPINUP:
 2467                 if (!spinup) {
 2468                     mly_printf(sc, "drive spinup in progress\n");
 2469                     spinup = 1;                 /* only print this once (should print drive being spun?) */
 2470                 }
 2471                 break;
 2472             case MLY_MSG_RACE_RECOVERY_FAIL:
 2473                 mly_printf(sc, "mirror race recovery failed, one or more drives offline\n");
 2474                 break;
 2475             case MLY_MSG_RACE_IN_PROGRESS:
 2476                 mly_printf(sc, "mirror race recovery in progress\n");
 2477                 break;
 2478             case MLY_MSG_RACE_ON_CRITICAL:
 2479                 mly_printf(sc, "mirror race recovery on a critical drive\n");
 2480                 break;
 2481             case MLY_MSG_PARITY_ERROR:
 2482                 mly_printf(sc, "FATAL MEMORY PARITY ERROR\n");
 2483                 return(ENXIO);
 2484             default:
 2485                 mly_printf(sc, "unknown initialisation code 0x%x\n", error);
 2486             }
 2487         }
 2488     }
 2489     return(0);
 2490 }
 2491 
 2492 /********************************************************************************
 2493  ********************************************************************************
 2494                                                         Debugging and Diagnostics
 2495  ********************************************************************************
 2496  ********************************************************************************/
 2497 
 2498 /********************************************************************************
 2499  * Print some information about the controller.
 2500  */
 2501 static void
 2502 mly_describe_controller(struct mly_softc *sc)
 2503 {
 2504     struct mly_ioctl_getcontrollerinfo  *mi = sc->mly_controllerinfo;
 2505 
 2506     mly_printf(sc, "%16s, %d channel%s, firmware %d.%02d-%d-%02d (%02d%02d%02d%02d), %dMB RAM\n", 
 2507                mi->controller_name, mi->physical_channels_present, (mi->physical_channels_present) > 1 ? "s" : "",
 2508                mi->fw_major, mi->fw_minor, mi->fw_turn, mi->fw_build,   /* XXX turn encoding? */
 2509                mi->fw_century, mi->fw_year, mi->fw_month, mi->fw_day,
 2510                mi->memory_size);
 2511 
 2512     if (bootverbose) {
 2513         mly_printf(sc, "%s %s (%x), %dMHz %d-bit %.16s\n", 
 2514                    mly_describe_code(mly_table_oemname, mi->oem_information), 
 2515                    mly_describe_code(mly_table_controllertype, mi->controller_type), mi->controller_type,
 2516                    mi->interface_speed, mi->interface_width, mi->interface_name);
 2517         mly_printf(sc, "%dMB %dMHz %d-bit %s%s%s, cache %dMB\n",
 2518                    mi->memory_size, mi->memory_speed, mi->memory_width, 
 2519                    mly_describe_code(mly_table_memorytype, mi->memory_type),
 2520                    mi->memory_parity ? "+parity": "",mi->memory_ecc ? "+ECC": "",
 2521                    mi->cache_size);
 2522         mly_printf(sc, "CPU: %s @ %dMHZ\n", 
 2523                    mly_describe_code(mly_table_cputype, mi->cpu[0].type), mi->cpu[0].speed);
 2524         if (mi->l2cache_size != 0)
 2525             mly_printf(sc, "%dKB L2 cache\n", mi->l2cache_size);
 2526         if (mi->exmemory_size != 0)
 2527             mly_printf(sc, "%dMB %dMHz %d-bit private %s%s%s\n",
 2528                        mi->exmemory_size, mi->exmemory_speed, mi->exmemory_width,
 2529                        mly_describe_code(mly_table_memorytype, mi->exmemory_type),
 2530                        mi->exmemory_parity ? "+parity": "",mi->exmemory_ecc ? "+ECC": "");
 2531         mly_printf(sc, "battery backup %s\n", mi->bbu_present ? "present" : "not installed");
 2532         mly_printf(sc, "maximum data transfer %d blocks, maximum sg entries/command %d\n",
 2533                    mi->maximum_block_count, mi->maximum_sg_entries);
 2534         mly_printf(sc, "logical devices present/critical/offline %d/%d/%d\n",
 2535                    mi->logical_devices_present, mi->logical_devices_critical, mi->logical_devices_offline);
 2536         mly_printf(sc, "physical devices present %d\n",
 2537                    mi->physical_devices_present);
 2538         mly_printf(sc, "physical disks present/offline %d/%d\n",
 2539                    mi->physical_disks_present, mi->physical_disks_offline);
 2540         mly_printf(sc, "%d physical channel%s, %d virtual channel%s of %d possible\n",
 2541                    mi->physical_channels_present, mi->physical_channels_present == 1 ? "" : "s",
 2542                    mi->virtual_channels_present, mi->virtual_channels_present == 1 ? "" : "s",
 2543                    mi->virtual_channels_possible);
 2544         mly_printf(sc, "%d parallel commands supported\n", mi->maximum_parallel_commands);
 2545         mly_printf(sc, "%dMB flash ROM, %d of %d maximum cycles\n",
 2546                    mi->flash_size, mi->flash_age, mi->flash_maximum_age);
 2547     }
 2548 }
 2549 
 2550 #ifdef MLY_DEBUG
 2551 /********************************************************************************
 2552  * Print some controller state
 2553  */
 2554 static void
 2555 mly_printstate(struct mly_softc *sc)
 2556 {
 2557     mly_printf(sc, "IDBR %02x  ODBR %02x  ERROR %02x  (%x %x %x)\n",
 2558                   MLY_GET_REG(sc, sc->mly_idbr),
 2559                   MLY_GET_REG(sc, sc->mly_odbr),
 2560                   MLY_GET_REG(sc, sc->mly_error_status),
 2561                   sc->mly_idbr,
 2562                   sc->mly_odbr,
 2563                   sc->mly_error_status);
 2564     mly_printf(sc, "IMASK %02x  ISTATUS %02x\n",
 2565                   MLY_GET_REG(sc, sc->mly_interrupt_mask),
 2566                   MLY_GET_REG(sc, sc->mly_interrupt_status));
 2567     mly_printf(sc, "COMMAND %02x %02x %02x %02x %02x %02x %02x %02x\n",
 2568                   MLY_GET_REG(sc, sc->mly_command_mailbox),
 2569                   MLY_GET_REG(sc, sc->mly_command_mailbox + 1),
 2570                   MLY_GET_REG(sc, sc->mly_command_mailbox + 2),
 2571                   MLY_GET_REG(sc, sc->mly_command_mailbox + 3),
 2572                   MLY_GET_REG(sc, sc->mly_command_mailbox + 4),
 2573                   MLY_GET_REG(sc, sc->mly_command_mailbox + 5),
 2574                   MLY_GET_REG(sc, sc->mly_command_mailbox + 6),
 2575                   MLY_GET_REG(sc, sc->mly_command_mailbox + 7));
 2576     mly_printf(sc, "STATUS  %02x %02x %02x %02x %02x %02x %02x %02x\n",
 2577                   MLY_GET_REG(sc, sc->mly_status_mailbox),
 2578                   MLY_GET_REG(sc, sc->mly_status_mailbox + 1),
 2579                   MLY_GET_REG(sc, sc->mly_status_mailbox + 2),
 2580                   MLY_GET_REG(sc, sc->mly_status_mailbox + 3),
 2581                   MLY_GET_REG(sc, sc->mly_status_mailbox + 4),
 2582                   MLY_GET_REG(sc, sc->mly_status_mailbox + 5),
 2583                   MLY_GET_REG(sc, sc->mly_status_mailbox + 6),
 2584                   MLY_GET_REG(sc, sc->mly_status_mailbox + 7));
 2585     mly_printf(sc, "        %04x        %08x\n",
 2586                   MLY_GET_REG2(sc, sc->mly_status_mailbox),
 2587                   MLY_GET_REG4(sc, sc->mly_status_mailbox + 4));
 2588 }
 2589 
 2590 struct mly_softc        *mly_softc0 = NULL;
 2591 void
 2592 mly_printstate0(void)
 2593 {
 2594     if (mly_softc0 != NULL)
 2595         mly_printstate(mly_softc0);
 2596 }
 2597 
 2598 /********************************************************************************
 2599  * Print a command
 2600  */
 2601 static void
 2602 mly_print_command(struct mly_command *mc)
 2603 {
 2604     struct mly_softc    *sc = mc->mc_sc;
 2605     
 2606     mly_printf(sc, "COMMAND @ %p\n", mc);
 2607     mly_printf(sc, "  slot      %d\n", mc->mc_slot);
 2608     mly_printf(sc, "  status    0x%x\n", mc->mc_status);
 2609     mly_printf(sc, "  sense len %d\n", mc->mc_sense);
 2610     mly_printf(sc, "  resid     %d\n", mc->mc_resid);
 2611     mly_printf(sc, "  packet    %p/0x%llx\n", mc->mc_packet, mc->mc_packetphys);
 2612     if (mc->mc_packet != NULL)
 2613         mly_print_packet(mc);
 2614     mly_printf(sc, "  data      %p/%d\n", mc->mc_data, mc->mc_length);
 2615     mly_printf(sc, "  flags     %b\n", mc->mc_flags, "\2\1busy\2complete\3slotted\4mapped\5datain\6dataout\n");
 2616     mly_printf(sc, "  complete  %p\n", mc->mc_complete);
 2617     mly_printf(sc, "  private   %p\n", mc->mc_private);
 2618 }
 2619 
 2620 /********************************************************************************
 2621  * Print a command packet
 2622  */
 2623 static void
 2624 mly_print_packet(struct mly_command *mc)
 2625 {
 2626     struct mly_softc                    *sc = mc->mc_sc;
 2627     struct mly_command_generic          *ge = (struct mly_command_generic *)mc->mc_packet;
 2628     struct mly_command_scsi_small       *ss = (struct mly_command_scsi_small *)mc->mc_packet;
 2629     struct mly_command_scsi_large       *sl = (struct mly_command_scsi_large *)mc->mc_packet;
 2630     struct mly_command_ioctl            *io = (struct mly_command_ioctl *)mc->mc_packet;
 2631     int                                 transfer;
 2632 
 2633     mly_printf(sc, "   command_id           %d\n", ge->command_id);
 2634     mly_printf(sc, "   opcode               %d\n", ge->opcode);
 2635     mly_printf(sc, "   command_control      fua %d  dpo %d  est %d  dd %s  nas %d ddis %d\n",
 2636                   ge->command_control.force_unit_access,
 2637                   ge->command_control.disable_page_out,
 2638                   ge->command_control.extended_sg_table,
 2639                   (ge->command_control.data_direction == MLY_CCB_WRITE) ? "WRITE" : "READ",
 2640                   ge->command_control.no_auto_sense,
 2641                   ge->command_control.disable_disconnect);
 2642     mly_printf(sc, "   data_size            %d\n", ge->data_size);
 2643     mly_printf(sc, "   sense_buffer_address 0x%llx\n", ge->sense_buffer_address);
 2644     mly_printf(sc, "   lun                  %d\n", ge->addr.phys.lun);
 2645     mly_printf(sc, "   target               %d\n", ge->addr.phys.target);
 2646     mly_printf(sc, "   channel              %d\n", ge->addr.phys.channel);
 2647     mly_printf(sc, "   logical device       %d\n", ge->addr.log.logdev);
 2648     mly_printf(sc, "   controller           %d\n", ge->addr.phys.controller);
 2649     mly_printf(sc, "   timeout              %d %s\n", 
 2650                   ge->timeout.value,
 2651                   (ge->timeout.scale == MLY_TIMEOUT_SECONDS) ? "seconds" : 
 2652                   ((ge->timeout.scale == MLY_TIMEOUT_MINUTES) ? "minutes" : "hours"));
 2653     mly_printf(sc, "   maximum_sense_size   %d\n", ge->maximum_sense_size);
 2654     switch(ge->opcode) {
 2655     case MDACMD_SCSIPT:
 2656     case MDACMD_SCSI:
 2657         mly_printf(sc, "   cdb length           %d\n", ss->cdb_length);
 2658         mly_printf(sc, "   cdb                  %*D\n", ss->cdb_length, ss->cdb, " ");
 2659         transfer = 1;
 2660         break;
 2661     case MDACMD_SCSILC:
 2662     case MDACMD_SCSILCPT:
 2663         mly_printf(sc, "   cdb length           %d\n", sl->cdb_length);
 2664         mly_printf(sc, "   cdb                  0x%llx\n", sl->cdb_physaddr);
 2665         transfer = 1;
 2666         break;
 2667     case MDACMD_IOCTL:
 2668         mly_printf(sc, "   sub_ioctl            0x%x\n", io->sub_ioctl);
 2669         switch(io->sub_ioctl) {
 2670         case MDACIOCTL_SETMEMORYMAILBOX:
 2671             mly_printf(sc, "   health_buffer_size   %d\n", 
 2672                           io->param.setmemorymailbox.health_buffer_size);
 2673             mly_printf(sc, "   health_buffer_phys   0x%llx\n",
 2674                           io->param.setmemorymailbox.health_buffer_physaddr);
 2675             mly_printf(sc, "   command_mailbox      0x%llx\n",
 2676                           io->param.setmemorymailbox.command_mailbox_physaddr);
 2677             mly_printf(sc, "   status_mailbox       0x%llx\n",
 2678                           io->param.setmemorymailbox.status_mailbox_physaddr);
 2679             transfer = 0;
 2680             break;
 2681 
 2682         case MDACIOCTL_SETREALTIMECLOCK:
 2683         case MDACIOCTL_GETHEALTHSTATUS:
 2684         case MDACIOCTL_GETCONTROLLERINFO:
 2685         case MDACIOCTL_GETLOGDEVINFOVALID:
 2686         case MDACIOCTL_GETPHYSDEVINFOVALID:
 2687         case MDACIOCTL_GETPHYSDEVSTATISTICS:
 2688         case MDACIOCTL_GETLOGDEVSTATISTICS:
 2689         case MDACIOCTL_GETCONTROLLERSTATISTICS:
 2690         case MDACIOCTL_GETBDT_FOR_SYSDRIVE:         
 2691         case MDACIOCTL_CREATENEWCONF:
 2692         case MDACIOCTL_ADDNEWCONF:
 2693         case MDACIOCTL_GETDEVCONFINFO:
 2694         case MDACIOCTL_GETFREESPACELIST:
 2695         case MDACIOCTL_MORE:
 2696         case MDACIOCTL_SETPHYSDEVPARAMETER:
 2697         case MDACIOCTL_GETPHYSDEVPARAMETER:
 2698         case MDACIOCTL_GETLOGDEVPARAMETER:
 2699         case MDACIOCTL_SETLOGDEVPARAMETER:
 2700             mly_printf(sc, "   param                %10D\n", io->param.data.param, " ");
 2701             transfer = 1;
 2702             break;
 2703 
 2704         case MDACIOCTL_GETEVENT:
 2705             mly_printf(sc, "   event                %d\n", 
 2706                        io->param.getevent.sequence_number_low + ((u_int32_t)io->addr.log.logdev << 16));
 2707             transfer = 1;
 2708             break;
 2709 
 2710         case MDACIOCTL_SETRAIDDEVSTATE:
 2711             mly_printf(sc, "   state                %d\n", io->param.setraiddevstate.state);
 2712             transfer = 0;
 2713             break;
 2714 
 2715         case MDACIOCTL_XLATEPHYSDEVTORAIDDEV:
 2716             mly_printf(sc, "   raid_device          %d\n", io->param.xlatephysdevtoraiddev.raid_device);
 2717             mly_printf(sc, "   controller           %d\n", io->param.xlatephysdevtoraiddev.controller);
 2718             mly_printf(sc, "   channel              %d\n", io->param.xlatephysdevtoraiddev.channel);
 2719             mly_printf(sc, "   target               %d\n", io->param.xlatephysdevtoraiddev.target);
 2720             mly_printf(sc, "   lun                  %d\n", io->param.xlatephysdevtoraiddev.lun);
 2721             transfer = 0;
 2722             break;
 2723 
 2724         case MDACIOCTL_GETGROUPCONFINFO:
 2725             mly_printf(sc, "   group                %d\n", io->param.getgroupconfinfo.group);
 2726             transfer = 1;
 2727             break;
 2728 
 2729         case MDACIOCTL_GET_SUBSYSTEM_DATA:
 2730         case MDACIOCTL_SET_SUBSYSTEM_DATA:
 2731         case MDACIOCTL_STARTDISOCVERY:
 2732         case MDACIOCTL_INITPHYSDEVSTART:
 2733         case MDACIOCTL_INITPHYSDEVSTOP:
 2734         case MDACIOCTL_INITRAIDDEVSTART:
 2735         case MDACIOCTL_INITRAIDDEVSTOP:
 2736         case MDACIOCTL_REBUILDRAIDDEVSTART:
 2737         case MDACIOCTL_REBUILDRAIDDEVSTOP:
 2738         case MDACIOCTL_MAKECONSISTENTDATASTART:
 2739         case MDACIOCTL_MAKECONSISTENTDATASTOP:
 2740         case MDACIOCTL_CONSISTENCYCHECKSTART:
 2741         case MDACIOCTL_CONSISTENCYCHECKSTOP:
 2742         case MDACIOCTL_RESETDEVICE:
 2743         case MDACIOCTL_FLUSHDEVICEDATA:
 2744         case MDACIOCTL_PAUSEDEVICE:
 2745         case MDACIOCTL_UNPAUSEDEVICE:
 2746         case MDACIOCTL_LOCATEDEVICE:
 2747         case MDACIOCTL_SETMASTERSLAVEMODE:
 2748         case MDACIOCTL_DELETERAIDDEV:
 2749         case MDACIOCTL_REPLACEINTERNALDEV:
 2750         case MDACIOCTL_CLEARCONF:
 2751         case MDACIOCTL_GETCONTROLLERPARAMETER:
 2752         case MDACIOCTL_SETCONTRLLERPARAMETER:
 2753         case MDACIOCTL_CLEARCONFSUSPMODE:
 2754         case MDACIOCTL_STOREIMAGE:
 2755         case MDACIOCTL_READIMAGE:
 2756         case MDACIOCTL_FLASHIMAGES:
 2757         case MDACIOCTL_RENAMERAIDDEV:
 2758         default:                        /* no idea what to print */
 2759             transfer = 0;
 2760             break;
 2761         }
 2762         break;
 2763 
 2764     case MDACMD_IOCTLCHECK:
 2765     case MDACMD_MEMCOPY:
 2766     default:
 2767         transfer = 0;
 2768         break;  /* print nothing */
 2769     }
 2770     if (transfer) {
 2771         if (ge->command_control.extended_sg_table) {
 2772             mly_printf(sc, "   sg table             0x%llx/%d\n",
 2773                           ge->transfer.indirect.table_physaddr[0], ge->transfer.indirect.entries[0]);
 2774         } else {
 2775             mly_printf(sc, "   0000                 0x%llx/%lld\n",
 2776                           ge->transfer.direct.sg[0].physaddr, ge->transfer.direct.sg[0].length);
 2777             mly_printf(sc, "   0001                 0x%llx/%lld\n",
 2778                           ge->transfer.direct.sg[1].physaddr, ge->transfer.direct.sg[1].length);
 2779         }
 2780     }
 2781 }
 2782 
 2783 /********************************************************************************
 2784  * Panic in a slightly informative fashion
 2785  */
 2786 static void
 2787 mly_panic(struct mly_softc *sc, char *reason)
 2788 {
 2789     mly_printstate(sc);
 2790     panic(reason);
 2791 }
 2792 
 2793 /********************************************************************************
 2794  * Print queue statistics, callable from DDB.
 2795  */
 2796 void
 2797 mly_print_controller(int controller)
 2798 {
 2799     struct mly_softc    *sc;
 2800     
 2801     if ((sc = devclass_get_softc(devclass_find("mly"), controller)) == NULL) {
 2802         printf("mly: controller %d invalid\n", controller);
 2803     } else {
 2804         device_printf(sc->mly_dev, "queue    curr max\n");
 2805         device_printf(sc->mly_dev, "free     %04d/%04d\n", 
 2806                       sc->mly_qstat[MLYQ_FREE].q_length, sc->mly_qstat[MLYQ_FREE].q_max);
 2807         device_printf(sc->mly_dev, "busy     %04d/%04d\n", 
 2808                       sc->mly_qstat[MLYQ_BUSY].q_length, sc->mly_qstat[MLYQ_BUSY].q_max);
 2809         device_printf(sc->mly_dev, "complete %04d/%04d\n", 
 2810                       sc->mly_qstat[MLYQ_COMPLETE].q_length, sc->mly_qstat[MLYQ_COMPLETE].q_max);
 2811     }
 2812 }
 2813 #endif
 2814 
 2815 
 2816 /********************************************************************************
 2817  ********************************************************************************
 2818                                                          Control device interface
 2819  ********************************************************************************
 2820  ********************************************************************************/
 2821 
 2822 /********************************************************************************
 2823  * Accept an open operation on the control device.
 2824  */
 2825 static int
 2826 mly_user_open(struct cdev *dev, int flags, int fmt, struct thread *td)
 2827 {
 2828     int                 unit = minor(dev);
 2829     struct mly_softc    *sc = devclass_get_softc(devclass_find("mly"), unit);
 2830 
 2831     sc->mly_state |= MLY_STATE_OPEN;
 2832     return(0);
 2833 }
 2834 
 2835 /********************************************************************************
 2836  * Accept the last close on the control device.
 2837  */
 2838 static int
 2839 mly_user_close(struct cdev *dev, int flags, int fmt, struct thread *td)
 2840 {
 2841     int                 unit = minor(dev);
 2842     struct mly_softc    *sc = devclass_get_softc(devclass_find("mly"), unit);
 2843 
 2844     sc->mly_state &= ~MLY_STATE_OPEN;
 2845     return (0);
 2846 }
 2847 
 2848 /********************************************************************************
 2849  * Handle controller-specific control operations.
 2850  */
 2851 static int
 2852 mly_user_ioctl(struct cdev *dev, u_long cmd, caddr_t addr,
 2853                                 int32_t flag, struct thread *td)
 2854 {
 2855     struct mly_softc            *sc = (struct mly_softc *)dev->si_drv1;
 2856     struct mly_user_command     *uc = (struct mly_user_command *)addr;
 2857     struct mly_user_health      *uh = (struct mly_user_health *)addr;
 2858     
 2859     switch(cmd) {
 2860     case MLYIO_COMMAND:
 2861         return(mly_user_command(sc, uc));
 2862     case MLYIO_HEALTH:
 2863         return(mly_user_health(sc, uh));
 2864     default:
 2865         return(ENOIOCTL);
 2866     }
 2867 }
 2868 
 2869 /********************************************************************************
 2870  * Execute a command passed in from userspace.
 2871  *
 2872  * The control structure contains the actual command for the controller, as well
 2873  * as the user-space data pointer and data size, and an optional sense buffer
 2874  * size/pointer.  On completion, the data size is adjusted to the command
 2875  * residual, and the sense buffer size to the size of the returned sense data.
 2876  * 
 2877  */
 2878 static int
 2879 mly_user_command(struct mly_softc *sc, struct mly_user_command *uc)
 2880 {
 2881     struct mly_command  *mc;
 2882     int                 error, s;
 2883 
 2884     /* allocate a command */
 2885     if (mly_alloc_command(sc, &mc)) {
 2886         error = ENOMEM;
 2887         goto out;               /* XXX Linux version will wait for a command */
 2888     }
 2889 
 2890     /* handle data size/direction */
 2891     mc->mc_length = (uc->DataTransferLength >= 0) ? uc->DataTransferLength : -uc->DataTransferLength;
 2892     if (mc->mc_length > 0) {
 2893         if ((mc->mc_data = malloc(mc->mc_length, M_DEVBUF, M_NOWAIT)) == NULL) {
 2894             error = ENOMEM;
 2895             goto out;
 2896         }
 2897     }
 2898     if (uc->DataTransferLength > 0) {
 2899         mc->mc_flags |= MLY_CMD_DATAIN;
 2900         bzero(mc->mc_data, mc->mc_length);
 2901     }
 2902     if (uc->DataTransferLength < 0) {
 2903         mc->mc_flags |= MLY_CMD_DATAOUT;
 2904         if ((error = copyin(uc->DataTransferBuffer, mc->mc_data, mc->mc_length)) != 0)
 2905             goto out;
 2906     }
 2907 
 2908     /* copy the controller command */
 2909     bcopy(&uc->CommandMailbox, mc->mc_packet, sizeof(uc->CommandMailbox));
 2910 
 2911     /* clear command completion handler so that we get woken up */
 2912     mc->mc_complete = NULL;
 2913 
 2914     /* execute the command */
 2915     if ((error = mly_start(mc)) != 0)
 2916         goto out;
 2917     s = splcam();
 2918     while (!(mc->mc_flags & MLY_CMD_COMPLETE))
 2919         tsleep(mc, PRIBIO, "mlyioctl", 0);
 2920     splx(s);
 2921 
 2922     /* return the data to userspace */
 2923     if (uc->DataTransferLength > 0)
 2924         if ((error = copyout(mc->mc_data, uc->DataTransferBuffer, mc->mc_length)) != 0)
 2925             goto out;
 2926     
 2927     /* return the sense buffer to userspace */
 2928     if ((uc->RequestSenseLength > 0) && (mc->mc_sense > 0)) {
 2929         if ((error = copyout(mc->mc_packet, uc->RequestSenseBuffer, 
 2930                              min(uc->RequestSenseLength, mc->mc_sense))) != 0)
 2931             goto out;
 2932     }
 2933     
 2934     /* return command results to userspace (caller will copy out) */
 2935     uc->DataTransferLength = mc->mc_resid;
 2936     uc->RequestSenseLength = min(uc->RequestSenseLength, mc->mc_sense);
 2937     uc->CommandStatus = mc->mc_status;
 2938     error = 0;
 2939 
 2940  out:
 2941     if (mc->mc_data != NULL)
 2942         free(mc->mc_data, M_DEVBUF);
 2943     if (mc != NULL)
 2944         mly_release_command(mc);
 2945     return(error);
 2946 }
 2947 
 2948 /********************************************************************************
 2949  * Return health status to userspace.  If the health change index in the user
 2950  * structure does not match that currently exported by the controller, we
 2951  * return the current status immediately.  Otherwise, we block until either
 2952  * interrupted or new status is delivered.
 2953  */
 2954 static int
 2955 mly_user_health(struct mly_softc *sc, struct mly_user_health *uh)
 2956 {
 2957     struct mly_health_status            mh;
 2958     int                                 error, s;
 2959     
 2960     /* fetch the current health status from userspace */
 2961     if ((error = copyin(uh->HealthStatusBuffer, &mh, sizeof(mh))) != 0)
 2962         return(error);
 2963 
 2964     /* spin waiting for a status update */
 2965     s = splcam();
 2966     error = EWOULDBLOCK;
 2967     while ((error != 0) && (sc->mly_event_change == mh.change_counter))
 2968         error = tsleep(&sc->mly_event_change, PRIBIO | PCATCH, "mlyhealth", 0);
 2969     splx(s);
 2970     
 2971     /* copy the controller's health status buffer out (there is a race here if it changes again) */
 2972     error = copyout(&sc->mly_mmbox->mmm_health.status, uh->HealthStatusBuffer, 
 2973                     sizeof(uh->HealthStatusBuffer));
 2974     return(error);
 2975 }
 2976 
 2977 static int
 2978 mly_timeout(struct mly_softc *sc)
 2979 {
 2980         struct mly_command *mc;
 2981         int deadline;
 2982 
 2983         deadline = time_second - MLY_CMD_TIMEOUT;
 2984         TAILQ_FOREACH(mc, &sc->mly_busy, mc_link) {
 2985                 if ((mc->mc_timestamp < deadline)) {
 2986                         device_printf(sc->mly_dev,
 2987                             "COMMAND %p TIMEOUT AFTER %d SECONDS\n", mc,
 2988                             (int)(time_second - mc->mc_timestamp));
 2989                 }
 2990         }
 2991 
 2992         timeout((timeout_t *)mly_timeout, sc, MLY_CMD_TIMEOUT * hz);
 2993 
 2994         return (0);
 2995 }

Cache object: 35acf0534bf9e00b2adfca21f0c16a92


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.