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

Cache object: cb06d6a3433c330189edf5f466b376c2


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