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/twa/twa_freebsd.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) 2003-04 3ware, Inc.
    3  * Copyright (c) 2000 Michael Smith
    4  * Copyright (c) 2000 BSDi
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  *
   28  *      $FreeBSD$
   29  */
   30 
   31 /*
   32  * 3ware driver for 9000 series storage controllers.
   33  *
   34  * Author: Vinod Kashyap
   35  */
   36 
   37 
   38 #include <dev/twa/twa_includes.h>
   39 
   40 static void     twa_setup_data_dmamap(void *arg, bus_dma_segment_t *segs,
   41                                                 int nsegments, int error);
   42 static void     twa_setup_request_dmamap(void *arg, bus_dma_segment_t *segs,
   43                                                 int nsegments, int error);
   44 
   45 MALLOC_DEFINE(TWA_MALLOC_CLASS, "twa commands", "twa commands");
   46 
   47 
   48 static  d_open_t                twa_open;
   49 static  d_close_t               twa_close;
   50 static  d_ioctl_t               twa_ioctl_wrapper;
   51 
   52 static struct cdevsw twa_cdevsw = {
   53         twa_open,
   54         twa_close,
   55         noread,
   56         nowrite,
   57         twa_ioctl_wrapper,
   58         nopoll,
   59         nommap,
   60         nostrategy,
   61         "twa",
   62         TWA_CDEV_MAJOR,
   63         nodump,
   64         nopsize,
   65         0
   66 };
   67 
   68 static devclass_t       twa_devclass;
   69 
   70 
   71 /*
   72  * Function name:       twa_open
   73  * Description:         Called when the controller is opened.
   74  *                      Simply marks the controller as open.
   75  *
   76  * Input:               dev     -- control device corresponding to the ctlr
   77  *                      flags   -- mode of open
   78  *                      fmt     -- device type (character/block etc.)
   79  *                      proc    -- current process
   80  * Output:              None
   81  * Return value:        0       -- success
   82  *                      non-zero-- failure
   83  */
   84 static int
   85 twa_open(dev_t dev, int flags, int fmt, d_thread_t *proc)
   86 {
   87         int                     unit = minor(dev);
   88         struct twa_softc        *sc = devclass_get_softc(twa_devclass, unit);
   89 
   90         sc->twa_state |= TWA_STATE_OPEN;
   91         return(0);
   92 }
   93 
   94 
   95 
   96 /*
   97  * Function name:       twa_close
   98  * Description:         Called when the controller is closed.
   99  *                      Simply marks the controller as not open.
  100  *
  101  * Input:               dev     -- control device corresponding to the ctlr
  102  *                      flags   -- mode of corresponding open
  103  *                      fmt     -- device type (character/block etc.)
  104  *                      proc    -- current process
  105  * Output:              None
  106  * Return value:        0       -- success
  107  *                      non-zero-- failure
  108  */
  109 static int
  110 twa_close(dev_t dev, int flags, int fmt, d_thread_t *proc)
  111 {
  112         int                     unit = minor(dev);
  113         struct twa_softc        *sc = devclass_get_softc(twa_devclass, unit);
  114 
  115         sc->twa_state &= ~TWA_STATE_OPEN;
  116         return(0);
  117 }
  118 
  119 
  120 
  121 /*
  122  * Function name:       twa_ioctl_wrapper
  123  * Description:         Called when an ioctl is posted to the controller.
  124  *                      Simply calls the ioctl handler.
  125  *
  126  * Input:               dev     -- control device corresponding to the ctlr
  127  *                      cmd     -- ioctl cmd
  128  *                      buf     -- ptr to buffer in kernel memory, which is
  129  *                                 a copy of the input buffer in user-space
  130  *                      flags   -- mode of corresponding open
  131  *                      proc    -- current process
  132  * Output:              buf     -- ptr to buffer in kernel memory, which will
  133  *                                 be copied to the output buffer in user-space
  134  * Return value:        0       -- success
  135  *                      non-zero-- failure
  136  */
  137 static int
  138 twa_ioctl_wrapper(dev_t dev, u_long cmd, caddr_t buf,
  139                                         int flags, d_thread_t *proc)
  140 {
  141         struct twa_softc        *sc = (struct twa_softc *)(dev->si_drv1);
  142 
  143         return(twa_ioctl(sc, cmd, buf));
  144 }
  145 
  146 
  147 
  148 static int      twa_probe (device_t dev);
  149 static int      twa_attach (device_t dev);
  150 static void     twa_free (struct twa_softc *sc);
  151 static int      twa_detach (device_t dev);
  152 static int      twa_shutdown (device_t dev);
  153 static int      twa_suspend (device_t dev);
  154 static int      twa_resume (device_t dev);
  155 static void     twa_pci_intr(void *arg);
  156 
  157 static device_method_t  twa_methods[] = {
  158         /* Device interface */
  159         DEVMETHOD(device_probe,         twa_probe),
  160         DEVMETHOD(device_attach,        twa_attach),
  161         DEVMETHOD(device_detach,        twa_detach),
  162         DEVMETHOD(device_shutdown,      twa_shutdown),
  163         DEVMETHOD(device_suspend,       twa_suspend),
  164         DEVMETHOD(device_resume,        twa_resume),
  165 
  166         DEVMETHOD(bus_print_child,      bus_generic_print_child),
  167         DEVMETHOD(bus_driver_added,     bus_generic_driver_added),
  168         {0, 0}
  169 };
  170 
  171 static driver_t twa_pci_driver = {
  172         "twa",
  173         twa_methods,
  174         sizeof(struct twa_softc)
  175 };
  176 
  177 DRIVER_MODULE(twa, pci, twa_pci_driver, twa_devclass, 0, 0);
  178 
  179 
  180 
  181 /*
  182  * Function name:       twa_probe
  183  * Description:         Called at driver load time.  Claims 9000 ctlrs.
  184  *
  185  * Input:               dev     -- bus device corresponding to the ctlr
  186  * Output:              None
  187  * Return value:        <= 0    -- success
  188  *                      > 0     -- failure
  189  */
  190 static int
  191 twa_probe(device_t dev)
  192 {
  193         static u_int8_t first_ctlr = 1;
  194 
  195         twa_dbg_print(3, "entered");
  196 
  197         if ((pci_get_vendor(dev) == TWA_VENDOR_ID) &&
  198                         (pci_get_device(dev) == TWA_DEVICE_ID_9K)) {
  199                 device_set_desc(dev, TWA_DEVICE_NAME);
  200                 /* Print the driver version only once. */
  201                 if (first_ctlr) {
  202                         printf("3ware device driver for 9000 series storage controllers, version: %s\n",
  203                                         TWA_DRIVER_VERSION_STRING);
  204                         first_ctlr = 0;
  205                 }
  206                 return(0);
  207         }
  208         return(ENXIO);
  209 }
  210 
  211 
  212 
  213 /*
  214  * Function name:       twa_attach
  215  * Description:         Allocates pci resources; updates sc; adds a node to the
  216  *                      sysctl tree to expose the driver version; makes calls
  217  *                      to initialize ctlr, and to attach to CAM.
  218  *
  219  * Input:               dev     -- bus device corresponding to the ctlr
  220  * Output:              None
  221  * Return value:        0       -- success
  222  *                      non-zero-- failure
  223  */
  224 static int
  225 twa_attach(device_t dev)
  226 {
  227         struct twa_softc        *sc = device_get_softc(dev);
  228         u_int32_t               command;
  229         int                     res_id;
  230         int                     error;
  231 
  232         twa_dbg_dprint_enter(3, sc);
  233 
  234         /* Initialize the softc structure. */
  235         sc->twa_bus_dev = dev;
  236 
  237         sysctl_ctx_init(&sc->twa_sysctl_ctx);
  238         sc->twa_sysctl_tree = SYSCTL_ADD_NODE(&sc->twa_sysctl_ctx,
  239                                 SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
  240                                 device_get_nameunit(dev), CTLFLAG_RD, 0, "");
  241         if (sc->twa_sysctl_tree == NULL) {
  242                 twa_printf(sc, "Cannot add sysctl tree node.\n");
  243                 return(ENXIO);
  244         }
  245         SYSCTL_ADD_STRING(&sc->twa_sysctl_ctx, SYSCTL_CHILDREN(sc->twa_sysctl_tree),
  246                                 OID_AUTO, "driver_version", CTLFLAG_RD,
  247                                 TWA_DRIVER_VERSION_STRING, 0, "TWA driver version");
  248 
  249         /* Make sure we are going to be able to talk to this board. */
  250         command = pci_read_config(dev, PCIR_COMMAND, 2);
  251         if ((command & PCIM_CMD_PORTEN) == 0) {
  252                 twa_printf(sc, "Register window not available.\n");
  253                 return(ENXIO);
  254         }
  255         
  256         /* Force the busmaster enable bit on, in case the BIOS forgot. */
  257         command |= PCIM_CMD_BUSMASTEREN;
  258         pci_write_config(dev, PCIR_COMMAND, command, 2);
  259 
  260         /* Allocate the PCI register window. */
  261         res_id = TWA_IO_CONFIG_REG;
  262         if ((sc->twa_io_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &res_id,
  263                                         0, ~0, 1, RF_ACTIVE)) == NULL) {
  264                 twa_printf(sc, "can't allocate register window.\n");
  265                 twa_free(sc);
  266                 return(ENXIO);
  267         }
  268         sc->twa_bus_tag = rman_get_bustag(sc->twa_io_res);
  269         sc->twa_bus_handle = rman_get_bushandle(sc->twa_io_res);
  270 
  271         /* Allocate and connect our interrupt. */
  272         res_id = 0;
  273         if ((sc->twa_irq_res = bus_alloc_resource(sc->twa_bus_dev, SYS_RES_IRQ,
  274                                         &res_id, 0, ~0, 1,
  275                                         RF_SHAREABLE | RF_ACTIVE)) == NULL) {
  276                 twa_printf(sc, "Can't allocate interrupt.\n");
  277                 twa_free(sc);
  278                 return(ENXIO);
  279         }
  280         if (bus_setup_intr(sc->twa_bus_dev, sc->twa_irq_res, INTR_TYPE_CAM,
  281                                 twa_pci_intr, sc, &sc->twa_intr_handle)) {
  282                 twa_printf(sc, "Can't set up interrupt.\n");
  283                 twa_free(sc);
  284                 return(ENXIO);
  285         }
  286 
  287         /* Initialize the driver for this controller. */
  288         if ((error = twa_setup(sc))) {
  289                 twa_free(sc);
  290                 return(error);
  291         }
  292 
  293         /* Print some information about the controller and configuration. */
  294         twa_describe_controller(sc);
  295 
  296         /* Create the control device. */
  297         sc->twa_ctrl_dev = make_dev(&twa_cdevsw, device_get_unit(sc->twa_bus_dev),
  298                                         UID_ROOT, GID_OPERATOR, S_IRUSR | S_IWUSR,
  299                                         "twa%d", device_get_unit(sc->twa_bus_dev));
  300         sc->twa_ctrl_dev->si_drv1 = sc;
  301 
  302         if ((error = twa_cam_setup(sc))) {
  303                 twa_free(sc);
  304                 return(error);
  305         }
  306         return(0);
  307 }
  308 
  309 
  310 
  311 /*
  312  * Function name:       twa_free
  313  * Description:         Performs clean-up at the time of going down.
  314  *
  315  * Input:               sc      -- ptr to per ctlr structure
  316  * Output:              None
  317  * Return value:        None
  318  */
  319 static void
  320 twa_free(struct twa_softc *sc)
  321 {
  322         struct twa_request      *tr;
  323 
  324         twa_dbg_dprint_enter(3, sc);
  325 
  326         /* Detach from CAM */
  327         twa_cam_detach(sc);
  328 
  329         /* Destroy dma handles. */
  330 
  331         bus_dmamap_unload(sc->twa_cmd_tag, sc->twa_cmd_map); 
  332         while ((tr = twa_dequeue_free(sc)) != NULL)
  333                 bus_dmamap_destroy(sc->twa_buf_tag, tr->tr_buf_map);
  334 
  335         /* Free all memory allocated so far. */
  336         if (sc->twa_req_buf)
  337                 free(sc->twa_req_buf, TWA_MALLOC_CLASS);
  338         if (sc->twa_cmd_pkt_buf)
  339                 bus_dmamem_free(sc->twa_cmd_tag, sc->twa_cmd_pkt_buf,
  340                                         sc->twa_cmd_map);
  341         if (sc->twa_aen_queue[0])
  342                 free(sc->twa_aen_queue[0], M_DEVBUF);
  343 
  344         /* Destroy the data-transfer DMA tag. */
  345         if (sc->twa_buf_tag)
  346                 bus_dma_tag_destroy(sc->twa_buf_tag);
  347 
  348         /* Destroy the cmd DMA tag. */
  349         if (sc->twa_cmd_tag)
  350                 bus_dma_tag_destroy(sc->twa_cmd_tag);
  351 
  352         /* Destroy the parent DMA tag. */
  353         if (sc->twa_parent_tag)
  354                 bus_dma_tag_destroy(sc->twa_parent_tag);
  355 
  356         /* Disconnect the interrupt handler. */
  357         if (sc->twa_intr_handle)
  358                 bus_teardown_intr(sc->twa_bus_dev, sc->twa_irq_res,
  359                                         sc->twa_intr_handle);
  360         if (sc->twa_irq_res != NULL)
  361                 bus_release_resource(sc->twa_bus_dev, SYS_RES_IRQ,
  362                                         0, sc->twa_irq_res);
  363 
  364         /* Release the register window mapping. */
  365         if (sc->twa_io_res != NULL)
  366                 bus_release_resource(sc->twa_bus_dev, SYS_RES_IOPORT,
  367                                         TWA_IO_CONFIG_REG, sc->twa_io_res);
  368 
  369         /* Destroy the control device. */
  370         if (sc->twa_ctrl_dev != (dev_t)NULL)
  371                 destroy_dev(sc->twa_ctrl_dev);
  372 
  373         sysctl_ctx_free(&sc->twa_sysctl_ctx);
  374 }
  375 
  376 
  377 
  378 /*
  379  * Function name:       twa_detach
  380  * Description:         Called when the controller is being detached from
  381  *                      the pci bus.
  382  *
  383  * Input:               dev     -- bus device corresponding to the ctlr
  384  * Output:              None
  385  * Return value:        0       -- success
  386  *                      non-zero-- failure
  387  */
  388 static int
  389 twa_detach(device_t dev)
  390 {
  391         struct twa_softc        *sc = device_get_softc(dev);
  392         int                     s;
  393         int                     error;
  394 
  395         twa_dbg_dprint_enter(3, sc);
  396 
  397         error = EBUSY;
  398         s = splcam();
  399         if (sc->twa_state & TWA_STATE_OPEN)
  400                 goto out;
  401 
  402         /* Shut the controller down. */
  403         if ((error = twa_shutdown(dev)))
  404                 goto out;
  405 
  406         /* Free all resources associated with this controller. */
  407         twa_free(sc);
  408         error = 0;
  409 
  410 out:
  411         splx(s);
  412         return(error);
  413 }
  414 
  415 
  416 
  417 /*
  418  * Function name:       twa_shutdown
  419  * Description:         Called at unload/shutdown time.  Lets the controller
  420  *                      know that we are going down.
  421  *
  422  * Input:               dev     -- bus device corresponding to the ctlr
  423  * Output:              None
  424  * Return value:        0       -- success
  425  *                      non-zero-- failure
  426  */
  427 static int
  428 twa_shutdown(device_t dev)
  429 {
  430         struct twa_softc        *sc = device_get_softc(dev);
  431         int                     s;
  432         int                     error = 0;
  433 
  434         twa_dbg_dprint_enter(3, sc);
  435 
  436         s = splcam();
  437 
  438         /* Disconnect from the controller. */
  439         error = twa_deinit_ctlr(sc);
  440 
  441         splx(s);
  442         return(error);
  443 }
  444 
  445 
  446 
  447 /*
  448  * Function name:       twa_suspend
  449  * Description:         Called to suspend I/O before hot-swapping PCI ctlrs.
  450  *                      Doesn't do much as of now.
  451  *
  452  * Input:               dev     -- bus device corresponding to the ctlr
  453  * Output:              None
  454  * Return value:        0       -- success
  455  *                      non-zero-- failure
  456  */
  457 static int
  458 twa_suspend(device_t dev)
  459 {
  460         struct twa_softc        *sc = device_get_softc(dev);
  461         int                     s;
  462 
  463         twa_dbg_dprint_enter(3, sc);
  464 
  465         s = splcam();
  466         sc->twa_state |= TWA_STATE_SUSPEND;
  467     
  468         twa_disable_interrupts(sc);
  469         splx(s);
  470 
  471         return(1);
  472 }
  473 
  474 
  475 
  476 /*
  477  * Function name:       twa_resume
  478  * Description:         Called to resume I/O after hot-swapping PCI ctlrs.
  479  *                      Doesn't do much as of now.
  480  *
  481  * Input:               dev     -- bus device corresponding to the ctlr
  482  * Output:              None
  483  * Return value:        0       -- success
  484  *                      non-zero-- failure
  485  */
  486 static int
  487 twa_resume(device_t dev)
  488 {
  489         struct twa_softc        *sc = device_get_softc(dev);
  490 
  491         twa_dbg_dprint_enter(3, sc);
  492 
  493         sc->twa_state &= ~TWA_STATE_SUSPEND;
  494         twa_enable_interrupts(sc);
  495 
  496         return(1);
  497 }
  498 
  499 
  500 
  501 /*
  502  * Function name:       twa_pci_intr
  503  * Description:         Interrupt handler.  Wrapper for twa_interrupt.
  504  *
  505  * Input:               arg     -- ptr to per ctlr structure
  506  * Output:              None
  507  * Return value:        None
  508  */
  509 static void
  510 twa_pci_intr(void *arg)
  511 {
  512         struct twa_softc        *sc = (struct twa_softc *)arg;
  513 
  514         twa_interrupt(sc);
  515 }
  516 
  517 
  518 
  519 /*
  520  * Function name:       twa_write_pci_config
  521  * Description:         Writes to the PCI config space.
  522  *
  523  * Input:               sc      -- ptr to per ctlr structure
  524  *                      value   -- value to be written
  525  *                      size    -- # of bytes to be written
  526  * Output:              None
  527  * Return value:        None
  528  */
  529 void
  530 twa_write_pci_config(struct twa_softc *sc, u_int32_t value, int size)
  531 {
  532         pci_write_config(sc->twa_bus_dev, PCIR_STATUS, value, size);
  533 }
  534 
  535 
  536 
  537 /*
  538  * Function name:       twa_alloc_req_pkts
  539  * Description:         Allocates memory for, and initializes request pkts,
  540  *                      and queues them in the free queue.
  541  *
  542  * Input:               sc      -- ptr to per ctlr structure
  543  *                      num_reqs-- # of request pkts to allocate and initialize.
  544  * Output:              None
  545  * Return value:        0       -- success
  546  *                      non-zero-- failure
  547  */
  548 int
  549 twa_alloc_req_pkts(struct twa_softc *sc, int num_reqs)
  550 {
  551         struct twa_request      *tr;
  552         int                     i;
  553 
  554         if ((sc->twa_req_buf = malloc(num_reqs * sizeof(struct twa_request),
  555                                         TWA_MALLOC_CLASS, M_NOWAIT)) == NULL)
  556                 return(ENOMEM);
  557 
  558         /* Create the parent dma tag. */
  559         if (bus_dma_tag_create(NULL,                    /* parent */
  560                                 TWA_ALIGNMENT,          /* alignment */
  561                                 0,                      /* boundary */
  562                                 BUS_SPACE_MAXADDR,      /* lowaddr */
  563                                 BUS_SPACE_MAXADDR,      /* highaddr */
  564                                 NULL, NULL,             /* filter, filterarg */
  565                                 TWA_Q_LENGTH *
  566                                 (sizeof(struct twa_command_packet)),/* maxsize */
  567                                 TWA_MAX_SG_ELEMENTS,    /* nsegments */
  568                                 BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */
  569                                 BUS_DMA_ALLOCNOW,       /* flags */
  570                                 &sc->twa_parent_tag     /* tag */)) {
  571                 twa_printf(sc, "Can't allocate parent DMA tag.\n");
  572                 return(ENOMEM);
  573         }
  574 
  575         /* Create a bus dma tag for cmd pkts. */
  576         if (bus_dma_tag_create(sc->twa_parent_tag,      /* parent */
  577                                 TWA_ALIGNMENT,          /* alignment */
  578                                 0,                      /* boundary */
  579                                 BUS_SPACE_MAXADDR,      /* lowaddr */
  580                                 BUS_SPACE_MAXADDR,      /* highaddr */
  581                                 NULL, NULL,             /* filter, filterarg */
  582                                 TWA_Q_LENGTH *
  583                                 (sizeof(struct twa_command_packet)),/* maxsize */
  584                                 1,                      /* nsegments */
  585                                 BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */
  586                                 0,                      /* flags */
  587                                 &sc->twa_cmd_tag        /* tag */)) {
  588                 twa_printf(sc, "Can't allocate cmd DMA tag.\n");
  589                 return(ENOMEM);
  590         }
  591 
  592 
  593         /* Allocate memory for cmd pkts. */
  594         if (bus_dmamem_alloc(sc->twa_cmd_tag,
  595                                 (void *)(&(sc->twa_cmd_pkt_buf)),
  596                                 BUS_DMA_WAITOK, &(sc->twa_cmd_map))) {
  597                 twa_printf(sc, "Can't allocate memory for cmd pkts.\n");
  598                 return(ENOMEM);
  599         }
  600 
  601         bus_dmamap_load(sc->twa_cmd_tag, sc->twa_cmd_map,
  602                                 sc->twa_cmd_pkt_buf,
  603                                 num_reqs * sizeof(struct twa_command_packet),
  604                                 twa_setup_request_dmamap, sc, 0);
  605         bzero(sc->twa_req_buf, num_reqs * sizeof(struct twa_request));
  606         bzero(sc->twa_cmd_pkt_buf,
  607                         num_reqs * sizeof(struct twa_command_packet));
  608 
  609         /* Create a bus dma tag for data buffers. */
  610         if (bus_dma_tag_create(sc->twa_parent_tag,      /* parent */
  611                                 TWA_ALIGNMENT,          /* alignment */
  612                                 0,                      /* boundary */
  613                                 BUS_SPACE_MAXADDR,      /* lowaddr */
  614                                 BUS_SPACE_MAXADDR,      /* highaddr */
  615                                 NULL, NULL,             /* filter, filterarg */
  616                                 TWA_MAX_IO_SIZE,        /* maxsize */
  617                                 TWA_MAX_SG_ELEMENTS,    /* nsegments */
  618                                 TWA_MAX_IO_SIZE,        /* maxsegsize */
  619                                 BUS_DMA_WAITOK,         /* flags */
  620                                 &sc->twa_buf_tag        /* tag */)) {
  621                 twa_printf(sc, "Can't allocate buf DMA tag.\n");
  622                 return(ENOMEM);
  623         }
  624 
  625         for (i = 0; i < num_reqs; i++) {
  626                 tr = &(sc->twa_req_buf[i]);
  627                 tr->tr_command = &(sc->twa_cmd_pkt_buf[i]);
  628                 tr->tr_cmd_phys = sc->twa_cmd_pkt_phys +
  629                                         (i * sizeof(struct twa_command_packet));
  630                 tr->tr_request_id = i;
  631                 tr->tr_sc = sc;
  632                 sc->twa_lookup[i] = tr;
  633 
  634                 /* Create maps for data buffers. */
  635                 if (bus_dmamap_create(sc->twa_buf_tag, 0,
  636                                                 &tr->tr_buf_map))
  637                         return(ENOMEM);
  638 
  639                 /* Insert request into the free queue. */
  640                 twa_release_request(tr);
  641         }
  642         return(0);
  643 }
  644 
  645 
  646 
  647 /*
  648  * Function name:       twa_fillin_sgl
  649  * Description:         Fills in the scatter/gather list.
  650  *
  651  * Input:               sgl     -- ptr to sg list
  652  *                      segs    -- ptr to fill the sg list from
  653  *                      nsegments--# of segments
  654  * Output:              None
  655  * Return value:        None
  656  */
  657 static void
  658 twa_fillin_sgl(struct twa_sg *sgl, bus_dma_segment_t *segs, int nsegments)
  659 {
  660         int     i;
  661 
  662         for (i = 0; i < nsegments; i++) {
  663                 sgl[i].address = segs[i].ds_addr;
  664                 sgl[i].length = (u_int32_t)(segs[i].ds_len);
  665         }
  666 }
  667 
  668 
  669 
  670 /*
  671  * Function name:       twa_setup_data_dmamap
  672  * Description:         Callback of bus_dmamap_load for the buffer associated
  673  *                      with data.  Updates the cmd pkt (size/sgl_entries
  674  *                      fields, as applicable) to reflect the number of sg
  675  *                      elements.
  676  *
  677  * Input:               arg     -- ptr to request pkt
  678  *                      segs    -- ptr to a list of segment descriptors
  679  *                      nsegments--# of segments
  680  *                      error   -- 0 if no errors encountered before callback,
  681  *                                 non-zero if errors were encountered
  682  * Output:              None
  683  * Return value:        None
  684  */
  685 static void
  686 twa_setup_data_dmamap(void *arg, bus_dma_segment_t *segs,
  687                                         int nsegments, int error)
  688 {
  689         struct twa_request              *tr = (struct twa_request *)arg;
  690         struct twa_command_packet       *cmdpkt = tr->tr_command;
  691         struct twa_command_9k           *cmd9k;
  692         union twa_command_7k            *cmd7k;
  693         u_int8_t                        sgl_offset;
  694 
  695         twa_dbg_dprint_enter(10, tr->tr_sc);
  696 
  697         tr->tr_flags |= TWA_CMD_MAPPED;
  698         if ((tr->tr_flags & TWA_CMD_IN_PROGRESS) &&
  699                         (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL))
  700                 twa_allow_new_requests(tr->tr_sc, (void *)(tr->tr_private));
  701 
  702         if (error == EFBIG) {
  703                 tr->tr_error = error;
  704                 goto out;
  705         }
  706 
  707         if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_9K) {
  708                 cmd9k = &(cmdpkt->command.cmd_pkt_9k);
  709                 twa_fillin_sgl(&(cmd9k->sg_list[0]), segs, nsegments);
  710                 cmd9k->sgl_entries += nsegments - 1;
  711         } else {
  712                 /* It's a 7000 command packet. */
  713                 cmd7k = &(cmdpkt->command.cmd_pkt_7k);
  714                 if ((sgl_offset = cmdpkt->command.cmd_pkt_7k.generic.sgl_offset))
  715                         twa_fillin_sgl((struct twa_sg *)
  716                                         (((u_int32_t *)cmd7k) + sgl_offset),
  717                                         segs, nsegments);
  718                 /* Modify the size field, based on sg address size. */
  719                 cmd7k->generic.size += 
  720                                 ((TWA_64BIT_ADDRESSES ? 3 : 2) * nsegments);
  721         }
  722 
  723         if (tr->tr_flags & TWA_CMD_DATA_IN)
  724                 bus_dmamap_sync(tr->tr_sc->twa_buf_tag, tr->tr_buf_map,
  725                                                         BUS_DMASYNC_PREREAD);
  726         if (tr->tr_flags & TWA_CMD_DATA_OUT) {
  727                 /* 
  728                  * If we're using an alignment buffer, and we're
  729                  * writing data, copy the real data out.
  730                  */
  731                 if (tr->tr_flags & TWA_CMD_DATA_COPY_NEEDED)
  732                         bcopy(tr->tr_real_data, tr->tr_data, tr->tr_real_length);
  733                 bus_dmamap_sync(tr->tr_sc->twa_buf_tag, tr->tr_buf_map,
  734                                                 BUS_DMASYNC_PREWRITE);
  735         }
  736         error = twa_submit_io(tr);
  737 
  738 out:
  739         if (error) {
  740                 twa_unmap_request(tr);
  741                 /*
  742                  * If the caller had been returned EINPROGRESS, and he has
  743                  * registered a callback for handling completion, the callback
  744                  * will never get called because we were unable to submit the
  745                  * request.  So, free up the request right here.
  746                  */
  747                 if ((tr->tr_flags & TWA_CMD_IN_PROGRESS) && (tr->tr_callback))
  748                         twa_release_request(tr);
  749         }
  750 }
  751 
  752 
  753 
  754 /*
  755  * Function name:       twa_setup_request_dmamap
  756  * Description:         Callback of bus_dmamap_load for the buffer associated
  757  *                      with a cmd pkt.
  758  *
  759  * Input:               arg     -- ptr to request pkt
  760  *                      segs    -- ptr to a list of segment descriptors
  761  *                      nsegments--# of segments
  762  *                      error   -- 0 if no errors encountered before callback,
  763  *                                 non-zero if errors were encountered
  764  * Output:              None
  765  * Return value:        None
  766  */
  767 static void
  768 twa_setup_request_dmamap(void *arg, bus_dma_segment_t *segs,
  769                                                 int nsegments, int error)
  770 {
  771         struct twa_softc        *sc = (struct twa_softc *)arg;
  772 
  773         twa_dbg_dprint_enter(10, sc);
  774 
  775         sc->twa_cmd_pkt_phys = segs[0].ds_addr;
  776 }
  777 
  778 
  779 
  780 /*
  781  * Function name:       twa_map_request
  782  * Description:         Maps a cmd pkt and data associated with it, into
  783  *                      DMA'able memory.
  784  *
  785  * Input:               tr      -- ptr to request pkt
  786  * Output:              None
  787  * Return value:        0       -- success
  788  *                      non-zero-- failure
  789  */
  790 int
  791 twa_map_request(struct twa_request *tr)
  792 {
  793         struct twa_softc        *sc = tr->tr_sc;
  794         int                     error = 0;
  795 
  796         twa_dbg_dprint_enter(10, sc);
  797 
  798         /* If the command involves data, map that too. */
  799         if (tr->tr_data != NULL) {
  800                 /*
  801                  * It's sufficient for the data pointer to be 4-byte aligned
  802                  * to work with 9000.  However, if 4-byte aligned addresses
  803                  * are passed to bus_dmamap_load, we can get back sg elements
  804                  * that are not 512-byte multiples in size.  So, we will let
  805                  * only those buffers that are 512-byte aligned to pass
  806                  * through, and bounce the rest, so as to make sure that we
  807                  * always get back sg elements that are 512-byte multiples
  808                  * in size.
  809                  */
  810                 if (((vm_offset_t)tr->tr_data % 512) || (tr->tr_length % 512)) {
  811                         tr->tr_flags |= TWA_CMD_DATA_COPY_NEEDED;
  812                         tr->tr_real_data = tr->tr_data; /* save original data pointer */
  813                         tr->tr_real_length = tr->tr_length; /* save original data length */
  814                         tr->tr_length = (tr->tr_length + 511) & ~511;
  815                         tr->tr_data = malloc(tr->tr_length, TWA_MALLOC_CLASS, M_NOWAIT);
  816                         if (tr->tr_data == NULL) {
  817                                 twa_printf(sc, "%s: malloc failed\n", __func__);
  818                                 tr->tr_data = tr->tr_real_data; /* restore original data pointer */
  819                                 tr->tr_length = tr->tr_real_length; /* restore original data length */
  820                                 return(ENOMEM);
  821                         }
  822                 }
  823         
  824                 /*
  825                  * Map the data buffer into bus space and build the s/g list.
  826                  */
  827                 if ((error = bus_dmamap_load(sc->twa_buf_tag, tr->tr_buf_map,
  828                                         tr->tr_data,
  829                                         (bus_size_t)(tr->tr_length),
  830                                         twa_setup_data_dmamap, tr,
  831                                         BUS_DMA_WAITOK))) {
  832                         if (error == EINPROGRESS) {
  833                                 int     s;
  834 
  835                                 s = splcam();
  836                                 if (!(tr->tr_flags & TWA_CMD_MAPPED)) {
  837                                         tr->tr_flags |= TWA_CMD_IN_PROGRESS;
  838                                         if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL)
  839                                                 twa_disallow_new_requests(sc);
  840                                 }
  841                                 splx(s);
  842                                 error = 0;
  843                         } else {
  844                                 /* Free alignment buffer if it was used. */
  845                                 if (tr->tr_flags & TWA_CMD_DATA_COPY_NEEDED) {
  846                                         free(tr->tr_data, TWA_MALLOC_CLASS);
  847                                         tr->tr_data = tr->tr_real_data; /* restore 'real' data pointer */
  848                                         tr->tr_length = tr->tr_real_length;/* restore 'real' data length */
  849                                 }
  850                         }
  851                 } else
  852                         error = tr->tr_error;
  853 
  854         } else
  855                 if ((error = twa_submit_io(tr)))
  856                         twa_unmap_request(tr);
  857 
  858         return(error);
  859 }
  860 
  861 
  862 
  863 /*
  864  * Function name:       twa_unmap_request
  865  * Description:         Undoes the mapping done by twa_map_request.
  866  *
  867  * Input:               tr      -- ptr to request pkt
  868  * Output:              None
  869  * Return value:        None
  870  */
  871 void
  872 twa_unmap_request(struct twa_request *tr)
  873 {
  874         struct twa_softc        *sc = tr->tr_sc;
  875         u_int8_t                cmd_status;
  876 
  877         twa_dbg_dprint_enter(10, sc);
  878 
  879         /* If the command involved data, unmap that too. */
  880         if (tr->tr_data != NULL) {
  881                 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_9K)
  882                         cmd_status = tr->tr_command->command.cmd_pkt_9k.status;
  883                 else
  884                         cmd_status = tr->tr_command->command.cmd_pkt_7k.generic.status;
  885 
  886                 if (tr->tr_flags & TWA_CMD_DATA_IN) {
  887                         bus_dmamap_sync(sc->twa_buf_tag,
  888                                         tr->tr_buf_map, BUS_DMASYNC_POSTREAD);
  889 
  890                         /* 
  891                          * If we are using a bounce buffer, and we are reading
  892                          * data, copy the real data in.
  893                          */
  894                         if (tr->tr_flags & TWA_CMD_DATA_COPY_NEEDED)
  895                                 if (cmd_status == 0)
  896                                         bcopy(tr->tr_data, tr->tr_real_data,
  897                                                         tr->tr_real_length);
  898                 }
  899                 if (tr->tr_flags & TWA_CMD_DATA_OUT)
  900                         bus_dmamap_sync(sc->twa_buf_tag, tr->tr_buf_map,
  901                                                         BUS_DMASYNC_POSTWRITE);
  902 
  903                 bus_dmamap_unload(sc->twa_buf_tag, tr->tr_buf_map); 
  904         }
  905 
  906         /* Free alignment buffer if it was used. */
  907         if (tr->tr_flags & TWA_CMD_DATA_COPY_NEEDED) {
  908                 free(tr->tr_data, TWA_MALLOC_CLASS);
  909                 tr->tr_data = tr->tr_real_data; /* restore 'real' data pointer */
  910                 tr->tr_length = tr->tr_real_length;/* restore 'real' data length */
  911         }
  912 }
  913 
  914 
  915 
  916 #ifdef TWA_DEBUG
  917 void    twa_report(void);
  918 void    twa_reset_stats(void);
  919 void    twa_print_request(struct twa_request *tr, int req_type);
  920 
  921 
  922 
  923 /*
  924  * Function name:       twa_report
  925  * Description:         For being called from ddb.  Prints controller stats,
  926  *                      and requests, if any, that are in the wrong queue.
  927  *
  928  * Input:               None
  929  * Output:              None
  930  * Return value:        None
  931  */
  932 void
  933 twa_report(void)
  934 {
  935         struct twa_softc        *sc;
  936         struct twa_request      *tr;
  937         int                     s;
  938         int                     i;
  939 
  940         s = splcam();
  941         for (i = 0; (sc = devclass_get_softc(twa_devclass, i)) != NULL; i++) {
  942                 twa_print_controller(sc);
  943                 TAILQ_FOREACH(tr, &sc->twa_busy, tr_link)
  944                         twa_print_request(tr, TWA_CMD_BUSY);
  945                 TAILQ_FOREACH(tr, &sc->twa_complete, tr_link)
  946                         twa_print_request(tr, TWA_CMD_COMPLETE);
  947         }
  948         splx(s);
  949 }
  950 
  951 
  952 
  953 /*
  954  * Function name:       twa_reset_stats
  955  * Description:         For being called from ddb.
  956  *                      Resets some controller stats.
  957  *
  958  * Input:               None
  959  * Output:              None
  960  * Return value:        None
  961  */
  962 void
  963 twa_reset_stats(void)
  964 {
  965         struct twa_softc        *sc;
  966         int                     s;
  967         int                     i;
  968 
  969         s = splcam();
  970         for (i = 0; (sc = devclass_get_softc(twa_devclass, i)) != NULL; i++) {
  971                 sc->twa_qstats[TWAQ_FREE].q_max = 0;
  972                 sc->twa_qstats[TWAQ_BUSY].q_max = 0;
  973                 sc->twa_qstats[TWAQ_PENDING].q_max = 0;
  974                 sc->twa_qstats[TWAQ_COMPLETE].q_max = 0;
  975         }
  976         splx(s);
  977 }
  978 
  979 
  980 
  981 /*
  982  * Function name:       twa_print_request
  983  * Description:         Prints a given request if it's in the wrong queue.
  984  *
  985  * Input:               tr      -- ptr to request pkt
  986  *                      req_type-- expected status of the given request
  987  * Output:              None
  988  * Return value:        None
  989  */
  990 void
  991 twa_print_request(struct twa_request *tr, int req_type)
  992 {
  993         struct twa_softc                *sc = tr->tr_sc;
  994         struct twa_command_packet       *cmdpkt = tr->tr_command;
  995         struct twa_command_9k           *cmd9k;
  996         union twa_command_7k            *cmd7k;
  997         u_int8_t                        *cdb;
  998 
  999         if (tr->tr_status != req_type) {
 1000                 twa_printf(sc, "Invalid %s request %p in queue! req_type = %x, queue_type = %x\n",
 1001                         (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_INTERNAL) ? "INTERNAL" : "EXTERNAL",
 1002                         tr, tr->tr_status, req_type);
 1003 
 1004                 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_9K) {
 1005                         cmd9k = &(cmdpkt->command.cmd_pkt_9k);
 1006                         twa_printf(sc, "9K cmd = %x %x %x %x %x %x %x %llx %x\n",
 1007                                         cmd9k->command.opcode,
 1008                                         cmd9k->command.reserved,
 1009                                         cmd9k->unit,
 1010                                         cmd9k->request_id,
 1011                                         cmd9k->status,
 1012                                         cmd9k->sgl_offset,
 1013                                         cmd9k->sgl_entries,
 1014                                         (__uint64_t)(cmd9k->sg_list[0].address),
 1015                                         cmd9k->sg_list[0].length);
 1016                         cdb = (u_int8_t *)(cmdpkt->command.cmd_pkt_9k.cdb);
 1017                         twa_printf(sc, "cdb = %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
 1018                                 cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7],
 1019                                 cdb[8], cdb[9], cdb[10], cdb[11], cdb[12], cdb[13], cdb[14], cdb[15]);
 1020                 } else {
 1021                         cmd7k = &(cmdpkt->command.cmd_pkt_7k);
 1022                         twa_printf(sc, "7K cmd = %x %x %x %x %x %x %x %x %x\n",
 1023                                         cmd7k->generic.opcode,
 1024                                         cmd7k->generic.sgl_offset,
 1025                                         cmd7k->generic.size,
 1026                                         cmd7k->generic.request_id,
 1027                                         cmd7k->generic.unit,
 1028                                         cmd7k->generic.host_id,
 1029                                         cmd7k->generic.status,
 1030                                         cmd7k->generic.flags,
 1031                                         cmd7k->generic.count);
 1032                 }
 1033 
 1034                 twa_printf(sc, "cmd_phys=0x%llx data=%p length=0x%x\n",
 1035                         (__uint64_t)(tr->tr_cmd_phys), tr->tr_data,
 1036                         tr->tr_length);
 1037                 twa_printf(sc, "req_id=0x%x flags=0x%x callback=%p private=%p\n",
 1038                         tr->tr_request_id, tr->tr_flags,
 1039                         tr->tr_callback, tr->tr_private);
 1040         }
 1041 }
 1042 #endif

Cache object: 05043a9bd33db0fbfea8a6de5be565b8


[ 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.