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/tw_osl_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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2004-07 Applied Micro Circuits Corporation.
    5  * Copyright (c) 2004-05 Vinod Kashyap.
    6  * Copyright (c) 2000 Michael Smith
    7  * Copyright (c) 2000 BSDi
    8  * All rights reserved.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD: releng/12.0/sys/dev/twa/tw_osl_freebsd.c 326255 2017-11-27 14:52:40Z pfg $");
   34 
   35 /*
   36  * AMCC'S 3ware driver for 9000 series storage controllers.
   37  *
   38  * Author: Vinod Kashyap
   39  * Modifications by: Adam Radford
   40  * Modifications by: Manjunath Ranganathaiah
   41  */
   42 
   43 
   44 /*
   45  * FreeBSD specific functions not related to CAM, and other
   46  * miscellaneous functions.
   47  */
   48 
   49 
   50 #include <dev/twa/tw_osl_includes.h>
   51 #include <dev/twa/tw_cl_fwif.h>
   52 #include <dev/twa/tw_cl_ioctl.h>
   53 #include <dev/twa/tw_osl_ioctl.h>
   54 
   55 #ifdef TW_OSL_DEBUG
   56 TW_INT32        TW_DEBUG_LEVEL_FOR_OSL = TW_OSL_DEBUG;
   57 TW_INT32        TW_OSL_DEBUG_LEVEL_FOR_CL = TW_OSL_DEBUG;
   58 #endif /* TW_OSL_DEBUG */
   59 
   60 static MALLOC_DEFINE(TW_OSLI_MALLOC_CLASS, "twa_commands", "twa commands");
   61 
   62 
   63 static  d_open_t                twa_open;
   64 static  d_close_t               twa_close;
   65 static  d_ioctl_t               twa_ioctl;
   66 
   67 static struct cdevsw twa_cdevsw = {
   68         .d_version =    D_VERSION,
   69         .d_open =       twa_open,
   70         .d_close =      twa_close,
   71         .d_ioctl =      twa_ioctl,
   72         .d_name =       "twa",
   73 };
   74 
   75 static devclass_t       twa_devclass;
   76 
   77 
   78 /*
   79  * Function name:       twa_open
   80  * Description:         Called when the controller is opened.
   81  *                      Simply marks the controller as open.
   82  *
   83  * Input:               dev     -- control device corresponding to the ctlr
   84  *                      flags   -- mode of open
   85  *                      fmt     -- device type (character/block etc.)
   86  *                      proc    -- current process
   87  * Output:              None
   88  * Return value:        0       -- success
   89  *                      non-zero-- failure
   90  */
   91 static TW_INT32
   92 twa_open(struct cdev *dev, TW_INT32 flags, TW_INT32 fmt, struct thread *proc)
   93 {
   94         struct twa_softc        *sc = (struct twa_softc *)(dev->si_drv1);
   95 
   96         tw_osli_dbg_dprintf(5, sc, "entered");
   97         sc->open = TW_CL_TRUE;
   98         return(0);
   99 }
  100 
  101 
  102 
  103 /*
  104  * Function name:       twa_close
  105  * Description:         Called when the controller is closed.
  106  *                      Simply marks the controller as not open.
  107  *
  108  * Input:               dev     -- control device corresponding to the ctlr
  109  *                      flags   -- mode of corresponding open
  110  *                      fmt     -- device type (character/block etc.)
  111  *                      proc    -- current process
  112  * Output:              None
  113  * Return value:        0       -- success
  114  *                      non-zero-- failure
  115  */
  116 static TW_INT32
  117 twa_close(struct cdev *dev, TW_INT32 flags, TW_INT32 fmt, struct thread *proc)
  118 {
  119         struct twa_softc        *sc = (struct twa_softc *)(dev->si_drv1);
  120 
  121         tw_osli_dbg_dprintf(5, sc, "entered");
  122         sc->open = TW_CL_FALSE;
  123         return(0);
  124 }
  125 
  126 
  127 
  128 /*
  129  * Function name:       twa_ioctl
  130  * Description:         Called when an ioctl is posted to the controller.
  131  *                      Handles any OS Layer specific cmds, passes the rest
  132  *                      on to the Common Layer.
  133  *
  134  * Input:               dev     -- control device corresponding to the ctlr
  135  *                      cmd     -- ioctl cmd
  136  *                      buf     -- ptr to buffer in kernel memory, which is
  137  *                                 a copy of the input buffer in user-space
  138  *                      flags   -- mode of corresponding open
  139  *                      proc    -- current process
  140  * Output:              buf     -- ptr to buffer in kernel memory, which will
  141  *                                 be copied to the output buffer in user-space
  142  * Return value:        0       -- success
  143  *                      non-zero-- failure
  144  */
  145 static TW_INT32
  146 twa_ioctl(struct cdev *dev, u_long cmd, caddr_t buf, TW_INT32 flags, struct thread *proc)
  147 {
  148         struct twa_softc        *sc = (struct twa_softc *)(dev->si_drv1);
  149         TW_INT32                error;
  150 
  151         tw_osli_dbg_dprintf(5, sc, "entered");
  152 
  153         switch (cmd) {
  154         case TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH:
  155                 tw_osli_dbg_dprintf(6, sc, "ioctl: fw_passthru");
  156                 error = tw_osli_fw_passthru(sc, (TW_INT8 *)buf);
  157                 break;
  158 
  159         case TW_OSL_IOCTL_SCAN_BUS:
  160                 /* Request CAM for a bus scan. */
  161                 tw_osli_dbg_dprintf(6, sc, "ioctl: scan bus");
  162                 error = tw_osli_request_bus_scan(sc);
  163                 break;
  164 
  165         default:
  166                 tw_osli_dbg_dprintf(6, sc, "ioctl: 0x%lx", cmd);
  167                 error = tw_cl_ioctl(&sc->ctlr_handle, cmd, buf);
  168                 break;
  169         }
  170         return(error);
  171 }
  172 
  173 
  174 
  175 static TW_INT32 twa_probe(device_t dev);
  176 static TW_INT32 twa_attach(device_t dev);
  177 static TW_INT32 twa_detach(device_t dev);
  178 static TW_INT32 twa_shutdown(device_t dev);
  179 static TW_VOID  twa_busdma_lock(TW_VOID *lock_arg, bus_dma_lock_op_t op);
  180 static TW_VOID  twa_pci_intr(TW_VOID *arg);
  181 static TW_VOID  twa_watchdog(TW_VOID *arg);
  182 int twa_setup_intr(struct twa_softc *sc);
  183 int twa_teardown_intr(struct twa_softc *sc);
  184 
  185 static TW_INT32 tw_osli_alloc_mem(struct twa_softc *sc);
  186 static TW_VOID  tw_osli_free_resources(struct twa_softc *sc);
  187 
  188 static TW_VOID  twa_map_load_data_callback(TW_VOID *arg,
  189         bus_dma_segment_t *segs, TW_INT32 nsegments, TW_INT32 error);
  190 static TW_VOID  twa_map_load_callback(TW_VOID *arg,
  191         bus_dma_segment_t *segs, TW_INT32 nsegments, TW_INT32 error);
  192 
  193 
  194 static device_method_t  twa_methods[] = {
  195         /* Device interface */
  196         DEVMETHOD(device_probe,         twa_probe),
  197         DEVMETHOD(device_attach,        twa_attach),
  198         DEVMETHOD(device_detach,        twa_detach),
  199         DEVMETHOD(device_shutdown,      twa_shutdown),
  200 
  201         DEVMETHOD_END
  202 };
  203 
  204 static driver_t twa_pci_driver = {
  205         "twa",
  206         twa_methods,
  207         sizeof(struct twa_softc)
  208 };
  209 
  210 DRIVER_MODULE(twa, pci, twa_pci_driver, twa_devclass, 0, 0);
  211 MODULE_DEPEND(twa, cam, 1, 1, 1);
  212 MODULE_DEPEND(twa, pci, 1, 1, 1);
  213 
  214 
  215 /*
  216  * Function name:       twa_probe
  217  * Description:         Called at driver load time.  Claims 9000 ctlrs.
  218  *
  219  * Input:               dev     -- bus device corresponding to the ctlr
  220  * Output:              None
  221  * Return value:        <= 0    -- success
  222  *                      > 0     -- failure
  223  */
  224 static TW_INT32
  225 twa_probe(device_t dev)
  226 {
  227         static TW_UINT8 first_ctlr = 1;
  228 
  229         tw_osli_dbg_printf(3, "entered");
  230 
  231         if (tw_cl_ctlr_supported(pci_get_vendor(dev), pci_get_device(dev))) {
  232                 device_set_desc(dev, TW_OSLI_DEVICE_NAME);
  233                 /* Print the driver version only once. */
  234                 if (first_ctlr) {
  235                         printf("3ware device driver for 9000 series storage "
  236                                 "controllers, version: %s\n",
  237                                 TW_OSL_DRIVER_VERSION_STRING);
  238                         first_ctlr = 0;
  239                 }
  240                 return(0);
  241         }
  242         return(ENXIO);
  243 }
  244 
  245 int twa_setup_intr(struct twa_softc *sc)
  246 {
  247         int error = 0;
  248 
  249         if (!(sc->intr_handle) && (sc->irq_res)) {
  250                 error = bus_setup_intr(sc->bus_dev, sc->irq_res,
  251                                         INTR_TYPE_CAM | INTR_MPSAFE,
  252                                         NULL, twa_pci_intr,
  253                                         sc, &sc->intr_handle);
  254         }
  255         return( error );
  256 }
  257 
  258 
  259 int twa_teardown_intr(struct twa_softc *sc)
  260 {
  261         int error = 0;
  262 
  263         if ((sc->intr_handle) && (sc->irq_res)) {
  264                 error = bus_teardown_intr(sc->bus_dev,
  265                                                 sc->irq_res, sc->intr_handle);
  266                 sc->intr_handle = NULL;
  267         }
  268         return( error );
  269 }
  270 
  271 
  272 
  273 /*
  274  * Function name:       twa_attach
  275  * Description:         Allocates pci resources; updates sc; adds a node to the
  276  *                      sysctl tree to expose the driver version; makes calls
  277  *                      (to the Common Layer) to initialize ctlr, and to
  278  *                      attach to CAM.
  279  *
  280  * Input:               dev     -- bus device corresponding to the ctlr
  281  * Output:              None
  282  * Return value:        0       -- success
  283  *                      non-zero-- failure
  284  */
  285 static TW_INT32
  286 twa_attach(device_t dev)
  287 {
  288         struct twa_softc        *sc = device_get_softc(dev);
  289         TW_INT32                bar_num;
  290         TW_INT32                bar0_offset;
  291         TW_INT32                bar_size;
  292         TW_INT32                error;
  293 
  294         tw_osli_dbg_dprintf(3, sc, "entered");
  295 
  296         sc->ctlr_handle.osl_ctlr_ctxt = sc;
  297 
  298         /* Initialize the softc structure. */
  299         sc->bus_dev = dev;
  300         sc->device_id = pci_get_device(dev);
  301 
  302         /* Initialize the mutexes right here. */
  303         sc->io_lock = &(sc->io_lock_handle);
  304         mtx_init(sc->io_lock, "tw_osl_io_lock", NULL, MTX_SPIN);
  305         sc->q_lock = &(sc->q_lock_handle);
  306         mtx_init(sc->q_lock, "tw_osl_q_lock", NULL, MTX_SPIN);
  307         sc->sim_lock = &(sc->sim_lock_handle);
  308         mtx_init(sc->sim_lock, "tw_osl_sim_lock", NULL, MTX_DEF | MTX_RECURSE);
  309 
  310         sysctl_ctx_init(&sc->sysctl_ctxt);
  311         sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctxt,
  312                 SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
  313                 device_get_nameunit(dev), CTLFLAG_RD, 0, "");
  314         if (sc->sysctl_tree == NULL) {
  315                 tw_osli_printf(sc, "error = %d",
  316                         TW_CL_SEVERITY_ERROR_STRING,
  317                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  318                         0x2000,
  319                         "Cannot add sysctl tree node",
  320                         ENXIO);
  321                 return(ENXIO);
  322         }
  323         SYSCTL_ADD_STRING(&sc->sysctl_ctxt, SYSCTL_CHILDREN(sc->sysctl_tree),
  324                 OID_AUTO, "driver_version", CTLFLAG_RD,
  325                 TW_OSL_DRIVER_VERSION_STRING, 0, "TWA driver version");
  326 
  327         /* Force the busmaster enable bit on, in case the BIOS forgot. */
  328         pci_enable_busmaster(dev);
  329 
  330         /* Allocate the PCI register window. */
  331         if ((error = tw_cl_get_pci_bar_info(sc->device_id, TW_CL_BAR_TYPE_MEM,
  332                 &bar_num, &bar0_offset, &bar_size))) {
  333                 tw_osli_printf(sc, "error = %d",
  334                         TW_CL_SEVERITY_ERROR_STRING,
  335                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  336                         0x201F,
  337                         "Can't get PCI BAR info",
  338                         error);
  339                 tw_osli_free_resources(sc);
  340                 return(error);
  341         }
  342         sc->reg_res_id = PCIR_BARS + bar0_offset;
  343         if ((sc->reg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
  344                                 &(sc->reg_res_id), RF_ACTIVE))
  345                                 == NULL) {
  346                 tw_osli_printf(sc, "error = %d",
  347                         TW_CL_SEVERITY_ERROR_STRING,
  348                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  349                         0x2002,
  350                         "Can't allocate register window",
  351                         ENXIO);
  352                 tw_osli_free_resources(sc);
  353                 return(ENXIO);
  354         }
  355         sc->bus_tag = rman_get_bustag(sc->reg_res);
  356         sc->bus_handle = rman_get_bushandle(sc->reg_res);
  357 
  358         /* Allocate and register our interrupt. */
  359         sc->irq_res_id = 0;
  360         if ((sc->irq_res = bus_alloc_resource_any(sc->bus_dev, SYS_RES_IRQ,
  361                                 &(sc->irq_res_id),
  362                                 RF_SHAREABLE | RF_ACTIVE)) == NULL) {
  363                 tw_osli_printf(sc, "error = %d",
  364                         TW_CL_SEVERITY_ERROR_STRING,
  365                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  366                         0x2003,
  367                         "Can't allocate interrupt",
  368                         ENXIO);
  369                 tw_osli_free_resources(sc);
  370                 return(ENXIO);
  371         }
  372         if ((error = twa_setup_intr(sc))) {
  373                 tw_osli_printf(sc, "error = %d",
  374                         TW_CL_SEVERITY_ERROR_STRING,
  375                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  376                         0x2004,
  377                         "Can't set up interrupt",
  378                         error);
  379                 tw_osli_free_resources(sc);
  380                 return(error);
  381         }
  382 
  383         if ((error = tw_osli_alloc_mem(sc))) {
  384                 tw_osli_printf(sc, "error = %d",
  385                         TW_CL_SEVERITY_ERROR_STRING,
  386                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  387                         0x2005,
  388                         "Memory allocation failure",
  389                         error);
  390                 tw_osli_free_resources(sc);
  391                 return(error);
  392         }
  393 
  394         /* Initialize the Common Layer for this controller. */
  395         if ((error = tw_cl_init_ctlr(&sc->ctlr_handle, sc->flags, sc->device_id,
  396                         TW_OSLI_MAX_NUM_REQUESTS, TW_OSLI_MAX_NUM_AENS,
  397                         sc->non_dma_mem, sc->dma_mem,
  398                         sc->dma_mem_phys
  399                         ))) {
  400                 tw_osli_printf(sc, "error = %d",
  401                         TW_CL_SEVERITY_ERROR_STRING,
  402                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  403                         0x2006,
  404                         "Failed to initialize Common Layer/controller",
  405                         error);
  406                 tw_osli_free_resources(sc);
  407                 return(error);
  408         }
  409 
  410         /* Create the control device. */
  411         sc->ctrl_dev = make_dev(&twa_cdevsw, device_get_unit(sc->bus_dev),
  412                         UID_ROOT, GID_OPERATOR, S_IRUSR | S_IWUSR,
  413                         "twa%d", device_get_unit(sc->bus_dev));
  414         sc->ctrl_dev->si_drv1 = sc;
  415 
  416         if ((error = tw_osli_cam_attach(sc))) {
  417                 tw_osli_free_resources(sc);
  418                 tw_osli_printf(sc, "error = %d",
  419                         TW_CL_SEVERITY_ERROR_STRING,
  420                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  421                         0x2007,
  422                         "Failed to initialize CAM",
  423                         error);
  424                 return(error);
  425         }
  426 
  427         sc->watchdog_index = 0;
  428         callout_init(&(sc->watchdog_callout[0]), 1);
  429         callout_init(&(sc->watchdog_callout[1]), 1);
  430         callout_reset(&(sc->watchdog_callout[0]), 5*hz, twa_watchdog, &sc->ctlr_handle);
  431 
  432         return(0);
  433 }
  434 
  435 
  436 static TW_VOID
  437 twa_watchdog(TW_VOID *arg)
  438 {
  439         struct tw_cl_ctlr_handle *ctlr_handle =
  440                 (struct tw_cl_ctlr_handle *)arg;
  441         struct twa_softc                *sc = ctlr_handle->osl_ctlr_ctxt;
  442         int                             i;
  443         int                             i_need_a_reset = 0;
  444         int                             driver_is_active = 0;
  445         int                             my_watchdog_was_pending = 1234;
  446         TW_UINT64                       current_time;
  447         struct tw_osli_req_context      *my_req;
  448 
  449 
  450 //==============================================================================
  451         current_time = (TW_UINT64) (tw_osl_get_local_time());
  452 
  453         for (i = 0; i < TW_OSLI_MAX_NUM_REQUESTS; i++) {
  454                 my_req = &(sc->req_ctx_buf[i]);
  455 
  456                 if ((my_req->state == TW_OSLI_REQ_STATE_BUSY) &&
  457                         (my_req->deadline) &&
  458                         (my_req->deadline < current_time)) {
  459                         tw_cl_set_reset_needed(ctlr_handle);
  460 #ifdef    TW_OSL_DEBUG
  461                         device_printf((sc)->bus_dev, "Request %d timed out! d = %llu, c = %llu\n", i, my_req->deadline, current_time);
  462 #else  /* TW_OSL_DEBUG */
  463                         device_printf((sc)->bus_dev, "Request %d timed out!\n", i);
  464 #endif /* TW_OSL_DEBUG */
  465                         break;
  466                 }
  467         }
  468 //==============================================================================
  469 
  470         i_need_a_reset = tw_cl_is_reset_needed(ctlr_handle);
  471 
  472         i = (int) ((sc->watchdog_index++) & 1);
  473 
  474         driver_is_active = tw_cl_is_active(ctlr_handle);
  475 
  476         if (i_need_a_reset) {
  477 #ifdef    TW_OSL_DEBUG
  478                 device_printf((sc)->bus_dev, "Watchdog rescheduled in 70 seconds\n");
  479 #endif /* TW_OSL_DEBUG */
  480                 my_watchdog_was_pending =
  481                         callout_reset(&(sc->watchdog_callout[i]), 70*hz, twa_watchdog, &sc->ctlr_handle);
  482                 tw_cl_reset_ctlr(ctlr_handle);
  483 #ifdef    TW_OSL_DEBUG
  484                 device_printf((sc)->bus_dev, "Watchdog reset completed!\n");
  485 #endif /* TW_OSL_DEBUG */
  486         } else if (driver_is_active) {
  487                 my_watchdog_was_pending =
  488                         callout_reset(&(sc->watchdog_callout[i]),  5*hz, twa_watchdog, &sc->ctlr_handle);
  489         }
  490 #ifdef    TW_OSL_DEBUG
  491         if (i_need_a_reset || my_watchdog_was_pending)
  492                 device_printf((sc)->bus_dev, "i_need_a_reset = %d, "
  493                 "driver_is_active = %d, my_watchdog_was_pending = %d\n",
  494                 i_need_a_reset, driver_is_active, my_watchdog_was_pending);
  495 #endif /* TW_OSL_DEBUG */
  496 }
  497 
  498 
  499 /*
  500  * Function name:       tw_osli_alloc_mem
  501  * Description:         Allocates memory needed both by CL and OSL.
  502  *
  503  * Input:               sc      -- OSL internal controller context
  504  * Output:              None
  505  * Return value:        0       -- success
  506  *                      non-zero-- failure
  507  */
  508 static TW_INT32
  509 tw_osli_alloc_mem(struct twa_softc *sc)
  510 {
  511         struct tw_osli_req_context      *req;
  512         TW_UINT32                       max_sg_elements;
  513         TW_UINT32                       non_dma_mem_size;
  514         TW_UINT32                       dma_mem_size;
  515         TW_INT32                        error;
  516         TW_INT32                        i;
  517 
  518         tw_osli_dbg_dprintf(3, sc, "entered");
  519 
  520         sc->flags |= (sizeof(bus_addr_t) == 8) ? TW_CL_64BIT_ADDRESSES : 0;
  521         sc->flags |= (sizeof(bus_size_t) == 8) ? TW_CL_64BIT_SG_LENGTH : 0;
  522 
  523         max_sg_elements = (sizeof(bus_addr_t) == 8) ?
  524                 TW_CL_MAX_64BIT_SG_ELEMENTS : TW_CL_MAX_32BIT_SG_ELEMENTS;
  525 
  526         if ((error = tw_cl_get_mem_requirements(&sc->ctlr_handle, sc->flags,
  527                         sc->device_id, TW_OSLI_MAX_NUM_REQUESTS,  TW_OSLI_MAX_NUM_AENS,
  528                         &(sc->alignment), &(sc->sg_size_factor),
  529                         &non_dma_mem_size, &dma_mem_size
  530                         ))) {
  531                 tw_osli_printf(sc, "error = %d",
  532                         TW_CL_SEVERITY_ERROR_STRING,
  533                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  534                         0x2008,
  535                         "Can't get Common Layer's memory requirements",
  536                         error);
  537                 return(error);
  538         }
  539 
  540         if ((sc->non_dma_mem = malloc(non_dma_mem_size, TW_OSLI_MALLOC_CLASS,
  541                                 M_WAITOK)) == NULL) {
  542                 tw_osli_printf(sc, "error = %d",
  543                         TW_CL_SEVERITY_ERROR_STRING,
  544                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  545                         0x2009,
  546                         "Can't allocate non-dma memory",
  547                         ENOMEM);
  548                 return(ENOMEM);
  549         }
  550 
  551         /* Create the parent dma tag. */
  552         if (bus_dma_tag_create(bus_get_dma_tag(sc->bus_dev), /* parent */
  553                                 sc->alignment,          /* alignment */
  554                                 0,                      /* boundary */
  555                                 BUS_SPACE_MAXADDR,      /* lowaddr */
  556                                 BUS_SPACE_MAXADDR,      /* highaddr */
  557                                 NULL, NULL,             /* filter, filterarg */
  558                                 TW_CL_MAX_IO_SIZE,      /* maxsize */
  559                                 max_sg_elements,        /* nsegments */
  560                                 TW_CL_MAX_IO_SIZE,      /* maxsegsize */
  561                                 0,                      /* flags */
  562                                 NULL,                   /* lockfunc */
  563                                 NULL,                   /* lockfuncarg */
  564                                 &sc->parent_tag         /* tag */)) {
  565                 tw_osli_printf(sc, "error = %d",
  566                         TW_CL_SEVERITY_ERROR_STRING,
  567                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  568                         0x200A,
  569                         "Can't allocate parent DMA tag",
  570                         ENOMEM);
  571                 return(ENOMEM);
  572         }
  573 
  574         /* Create a dma tag for Common Layer's DMA'able memory (dma_mem). */
  575         if (bus_dma_tag_create(sc->parent_tag,          /* parent */
  576                                 sc->alignment,          /* alignment */
  577                                 0,                      /* boundary */
  578                                 BUS_SPACE_MAXADDR,      /* lowaddr */
  579                                 BUS_SPACE_MAXADDR,      /* highaddr */
  580                                 NULL, NULL,             /* filter, filterarg */
  581                                 dma_mem_size,           /* maxsize */
  582                                 1,                      /* nsegments */
  583                                 BUS_SPACE_MAXSIZE,      /* maxsegsize */
  584                                 0,                      /* flags */
  585                                 NULL,                   /* lockfunc */
  586                                 NULL,                   /* lockfuncarg */
  587                                 &sc->cmd_tag            /* tag */)) {
  588                 tw_osli_printf(sc, "error = %d",
  589                         TW_CL_SEVERITY_ERROR_STRING,
  590                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  591                         0x200B,
  592                         "Can't allocate DMA tag for Common Layer's "
  593                         "DMA'able memory",
  594                         ENOMEM);
  595                 return(ENOMEM);
  596         }
  597 
  598         if (bus_dmamem_alloc(sc->cmd_tag, &sc->dma_mem,
  599                 BUS_DMA_NOWAIT, &sc->cmd_map)) {
  600                 /* Try a second time. */
  601                 if (bus_dmamem_alloc(sc->cmd_tag, &sc->dma_mem,
  602                         BUS_DMA_NOWAIT, &sc->cmd_map)) {
  603                         tw_osli_printf(sc, "error = %d",
  604                                 TW_CL_SEVERITY_ERROR_STRING,
  605                                 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  606                                 0x200C,
  607                                 "Can't allocate DMA'able memory for the"
  608                                 "Common Layer",
  609                                 ENOMEM);
  610                         return(ENOMEM);
  611                 }
  612         }
  613 
  614         bus_dmamap_load(sc->cmd_tag, sc->cmd_map, sc->dma_mem,
  615                 dma_mem_size, twa_map_load_callback,
  616                 &sc->dma_mem_phys, 0);
  617 
  618         /*
  619          * Create a dma tag for data buffers; size will be the maximum
  620          * possible I/O size (128kB).
  621          */
  622         if (bus_dma_tag_create(sc->parent_tag,          /* parent */
  623                                 sc->alignment,          /* alignment */
  624                                 0,                      /* boundary */
  625                                 BUS_SPACE_MAXADDR,      /* lowaddr */
  626                                 BUS_SPACE_MAXADDR,      /* highaddr */
  627                                 NULL, NULL,             /* filter, filterarg */
  628                                 TW_CL_MAX_IO_SIZE,      /* maxsize */
  629                                 max_sg_elements,        /* nsegments */
  630                                 TW_CL_MAX_IO_SIZE,      /* maxsegsize */
  631                                 BUS_DMA_ALLOCNOW,       /* flags */
  632                                 twa_busdma_lock,        /* lockfunc */
  633                                 sc->io_lock,            /* lockfuncarg */
  634                                 &sc->dma_tag            /* tag */)) {
  635                 tw_osli_printf(sc, "error = %d",
  636                         TW_CL_SEVERITY_ERROR_STRING,
  637                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  638                         0x200F,
  639                         "Can't allocate DMA tag for data buffers",
  640                         ENOMEM);
  641                 return(ENOMEM);
  642         }
  643 
  644         /*
  645          * Create a dma tag for ioctl data buffers; size will be the maximum
  646          * possible I/O size (128kB).
  647          */
  648         if (bus_dma_tag_create(sc->parent_tag,          /* parent */
  649                                 sc->alignment,          /* alignment */
  650                                 0,                      /* boundary */
  651                                 BUS_SPACE_MAXADDR,      /* lowaddr */
  652                                 BUS_SPACE_MAXADDR,      /* highaddr */
  653                                 NULL, NULL,             /* filter, filterarg */
  654                                 TW_CL_MAX_IO_SIZE,      /* maxsize */
  655                                 max_sg_elements,        /* nsegments */
  656                                 TW_CL_MAX_IO_SIZE,      /* maxsegsize */
  657                                 BUS_DMA_ALLOCNOW,       /* flags */
  658                                 twa_busdma_lock,        /* lockfunc */
  659                                 sc->io_lock,            /* lockfuncarg */
  660                                 &sc->ioctl_tag          /* tag */)) {
  661                 tw_osli_printf(sc, "error = %d",
  662                         TW_CL_SEVERITY_ERROR_STRING,
  663                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  664                         0x2010,
  665                         "Can't allocate DMA tag for ioctl data buffers",
  666                         ENOMEM);
  667                 return(ENOMEM);
  668         }
  669 
  670         /* Create just one map for all ioctl request data buffers. */
  671         if (bus_dmamap_create(sc->ioctl_tag, 0, &sc->ioctl_map)) {
  672                 tw_osli_printf(sc, "error = %d",
  673                         TW_CL_SEVERITY_ERROR_STRING,
  674                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  675                         0x2011,
  676                         "Can't create ioctl map",
  677                         ENOMEM);
  678                 return(ENOMEM);
  679         }
  680 
  681 
  682         /* Initialize request queues. */
  683         tw_osli_req_q_init(sc, TW_OSLI_FREE_Q);
  684         tw_osli_req_q_init(sc, TW_OSLI_BUSY_Q);
  685 
  686         if ((sc->req_ctx_buf = (struct tw_osli_req_context *)
  687                         malloc((sizeof(struct tw_osli_req_context) *
  688                                 TW_OSLI_MAX_NUM_REQUESTS),
  689                                 TW_OSLI_MALLOC_CLASS, M_WAITOK)) == NULL) {
  690                 tw_osli_printf(sc, "error = %d",
  691                         TW_CL_SEVERITY_ERROR_STRING,
  692                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  693                         0x2012,
  694                         "Failed to allocate request packets",
  695                         ENOMEM);
  696                 return(ENOMEM);
  697         }
  698         bzero(sc->req_ctx_buf,
  699                 sizeof(struct tw_osli_req_context) * TW_OSLI_MAX_NUM_REQUESTS);
  700 
  701         for (i = 0; i < TW_OSLI_MAX_NUM_REQUESTS; i++) {
  702                 req = &(sc->req_ctx_buf[i]);
  703                 req->ctlr = sc;
  704                 if (bus_dmamap_create(sc->dma_tag, 0, &req->dma_map)) {
  705                         tw_osli_printf(sc, "request # = %d, error = %d",
  706                                 TW_CL_SEVERITY_ERROR_STRING,
  707                                 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  708                                 0x2013,
  709                                 "Can't create dma map",
  710                                 i, ENOMEM);
  711                         return(ENOMEM);
  712                 }
  713 
  714                 /* Initialize the ioctl wakeup/ timeout mutex */
  715                 req->ioctl_wake_timeout_lock = &(req->ioctl_wake_timeout_lock_handle);
  716                 mtx_init(req->ioctl_wake_timeout_lock, "tw_ioctl_wake_timeout_lock", NULL, MTX_DEF);
  717 
  718                 /* Insert request into the free queue. */
  719                 tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
  720         }
  721 
  722         return(0);
  723 }
  724 
  725 
  726 
  727 /*
  728  * Function name:       tw_osli_free_resources
  729  * Description:         Performs clean-up at the time of going down.
  730  *
  731  * Input:               sc      -- ptr to OSL internal ctlr context
  732  * Output:              None
  733  * Return value:        None
  734  */
  735 static TW_VOID
  736 tw_osli_free_resources(struct twa_softc *sc)
  737 {
  738         struct tw_osli_req_context      *req;
  739         TW_INT32                        error = 0;
  740 
  741         tw_osli_dbg_dprintf(3, sc, "entered");
  742 
  743         /* Detach from CAM */
  744         tw_osli_cam_detach(sc);
  745 
  746         if (sc->req_ctx_buf)
  747                 while ((req = tw_osli_req_q_remove_head(sc, TW_OSLI_FREE_Q)) !=
  748                         NULL) {
  749                         mtx_destroy(req->ioctl_wake_timeout_lock);
  750 
  751                         if ((error = bus_dmamap_destroy(sc->dma_tag,
  752                                         req->dma_map)))
  753                                 tw_osli_dbg_dprintf(1, sc,
  754                                         "dmamap_destroy(dma) returned %d",
  755                                         error);
  756                 }
  757 
  758         if ((sc->ioctl_tag) && (sc->ioctl_map))
  759                 if ((error = bus_dmamap_destroy(sc->ioctl_tag, sc->ioctl_map)))
  760                         tw_osli_dbg_dprintf(1, sc,
  761                                 "dmamap_destroy(ioctl) returned %d", error);
  762 
  763         /* Free all memory allocated so far. */
  764         if (sc->req_ctx_buf)
  765                 free(sc->req_ctx_buf, TW_OSLI_MALLOC_CLASS);
  766 
  767         if (sc->non_dma_mem)
  768                 free(sc->non_dma_mem, TW_OSLI_MALLOC_CLASS);
  769 
  770         if (sc->dma_mem) {
  771                 bus_dmamap_unload(sc->cmd_tag, sc->cmd_map);
  772                 bus_dmamem_free(sc->cmd_tag, sc->dma_mem,
  773                         sc->cmd_map);
  774         }
  775         if (sc->cmd_tag)
  776                 if ((error = bus_dma_tag_destroy(sc->cmd_tag)))
  777                         tw_osli_dbg_dprintf(1, sc,
  778                                 "dma_tag_destroy(cmd) returned %d", error);
  779 
  780         if (sc->dma_tag)
  781                 if ((error = bus_dma_tag_destroy(sc->dma_tag)))
  782                         tw_osli_dbg_dprintf(1, sc,
  783                                 "dma_tag_destroy(dma) returned %d", error);
  784 
  785         if (sc->ioctl_tag)
  786                 if ((error = bus_dma_tag_destroy(sc->ioctl_tag)))
  787                         tw_osli_dbg_dprintf(1, sc,
  788                                 "dma_tag_destroy(ioctl) returned %d", error);
  789 
  790         if (sc->parent_tag)
  791                 if ((error = bus_dma_tag_destroy(sc->parent_tag)))
  792                         tw_osli_dbg_dprintf(1, sc,
  793                                 "dma_tag_destroy(parent) returned %d", error);
  794 
  795 
  796         /* Disconnect the interrupt handler. */
  797         if ((error = twa_teardown_intr(sc)))
  798                         tw_osli_dbg_dprintf(1, sc,
  799                                 "teardown_intr returned %d", error);
  800 
  801         if (sc->irq_res != NULL)
  802                 if ((error = bus_release_resource(sc->bus_dev,
  803                                 SYS_RES_IRQ, sc->irq_res_id, sc->irq_res)))
  804                         tw_osli_dbg_dprintf(1, sc,
  805                                 "release_resource(irq) returned %d", error);
  806 
  807 
  808         /* Release the register window mapping. */
  809         if (sc->reg_res != NULL)
  810                 if ((error = bus_release_resource(sc->bus_dev,
  811                                 SYS_RES_MEMORY, sc->reg_res_id, sc->reg_res)))
  812                         tw_osli_dbg_dprintf(1, sc,
  813                                 "release_resource(io) returned %d", error);
  814 
  815 
  816         /* Destroy the control device. */
  817         if (sc->ctrl_dev != (struct cdev *)NULL)
  818                 destroy_dev(sc->ctrl_dev);
  819 
  820         if ((error = sysctl_ctx_free(&sc->sysctl_ctxt)))
  821                 tw_osli_dbg_dprintf(1, sc,
  822                         "sysctl_ctx_free returned %d", error);
  823 
  824 }
  825 
  826 
  827 
  828 /*
  829  * Function name:       twa_detach
  830  * Description:         Called when the controller is being detached from
  831  *                      the pci bus.
  832  *
  833  * Input:               dev     -- bus device corresponding to the ctlr
  834  * Output:              None
  835  * Return value:        0       -- success
  836  *                      non-zero-- failure
  837  */
  838 static TW_INT32
  839 twa_detach(device_t dev)
  840 {
  841         struct twa_softc        *sc = device_get_softc(dev);
  842         TW_INT32                error;
  843 
  844         tw_osli_dbg_dprintf(3, sc, "entered");
  845 
  846         error = EBUSY;
  847         if (sc->open) {
  848                 tw_osli_printf(sc, "error = %d",
  849                         TW_CL_SEVERITY_ERROR_STRING,
  850                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  851                         0x2014,
  852                         "Device open",
  853                         error);
  854                 goto out;
  855         }
  856 
  857         /* Shut the controller down. */
  858         if ((error = twa_shutdown(dev)))
  859                 goto out;
  860 
  861         /* Free all resources associated with this controller. */
  862         tw_osli_free_resources(sc);
  863         error = 0;
  864 
  865 out:
  866         return(error);
  867 }
  868 
  869 
  870 
  871 /*
  872  * Function name:       twa_shutdown
  873  * Description:         Called at unload/shutdown time.  Lets the controller
  874  *                      know that we are going down.
  875  *
  876  * Input:               dev     -- bus device corresponding to the ctlr
  877  * Output:              None
  878  * Return value:        0       -- success
  879  *                      non-zero-- failure
  880  */
  881 static TW_INT32
  882 twa_shutdown(device_t dev)
  883 {
  884         struct twa_softc        *sc = device_get_softc(dev);
  885         TW_INT32                error = 0;
  886 
  887         tw_osli_dbg_dprintf(3, sc, "entered");
  888 
  889         /* Disconnect interrupts. */
  890         error = twa_teardown_intr(sc);
  891 
  892         /* Stop watchdog task. */
  893         callout_drain(&(sc->watchdog_callout[0]));
  894         callout_drain(&(sc->watchdog_callout[1]));
  895 
  896         /* Disconnect from the controller. */
  897         if ((error = tw_cl_shutdown_ctlr(&(sc->ctlr_handle), 0))) {
  898                 tw_osli_printf(sc, "error = %d",
  899                         TW_CL_SEVERITY_ERROR_STRING,
  900                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  901                         0x2015,
  902                         "Failed to shutdown Common Layer/controller",
  903                         error);
  904         }
  905         return(error);
  906 }
  907 
  908 
  909 
  910 /*
  911  * Function name:       twa_busdma_lock
  912  * Description:         Function to provide synchronization during busdma_swi.
  913  *
  914  * Input:               lock_arg -- lock mutex sent as argument
  915  *                      op -- operation (lock/unlock) expected of the function
  916  * Output:              None
  917  * Return value:        None
  918  */
  919 TW_VOID
  920 twa_busdma_lock(TW_VOID *lock_arg, bus_dma_lock_op_t op)
  921 {
  922         struct mtx      *lock;
  923 
  924         lock = (struct mtx *)lock_arg;
  925         switch (op) {
  926         case BUS_DMA_LOCK:
  927                 mtx_lock_spin(lock);
  928                 break;
  929 
  930         case BUS_DMA_UNLOCK:
  931                 mtx_unlock_spin(lock);
  932                 break;
  933 
  934         default:
  935                 panic("Unknown operation 0x%x for twa_busdma_lock!", op);
  936         }
  937 }
  938 
  939 
  940 /*
  941  * Function name:       twa_pci_intr
  942  * Description:         Interrupt handler.  Wrapper for twa_interrupt.
  943  *
  944  * Input:               arg     -- ptr to OSL internal ctlr context
  945  * Output:              None
  946  * Return value:        None
  947  */
  948 static TW_VOID
  949 twa_pci_intr(TW_VOID *arg)
  950 {
  951         struct twa_softc        *sc = (struct twa_softc *)arg;
  952 
  953         tw_osli_dbg_dprintf(10, sc, "entered");
  954         tw_cl_interrupt(&(sc->ctlr_handle));
  955 }
  956 
  957 
  958 /*
  959  * Function name:       tw_osli_fw_passthru
  960  * Description:         Builds a fw passthru cmd pkt, and submits it to CL.
  961  *
  962  * Input:               sc      -- ptr to OSL internal ctlr context
  963  *                      buf     -- ptr to ioctl pkt understood by CL
  964  * Output:              None
  965  * Return value:        0       -- success
  966  *                      non-zero-- failure
  967  */
  968 TW_INT32
  969 tw_osli_fw_passthru(struct twa_softc *sc, TW_INT8 *buf)
  970 {
  971         struct tw_osli_req_context              *req;
  972         struct tw_osli_ioctl_no_data_buf        *user_buf =
  973                 (struct tw_osli_ioctl_no_data_buf *)buf;
  974         TW_TIME                                 end_time;
  975         TW_UINT32                               timeout = 60;
  976         TW_UINT32                               data_buf_size_adjusted;
  977         struct tw_cl_req_packet                 *req_pkt;
  978         struct tw_cl_passthru_req_packet        *pt_req;
  979         TW_INT32                                error;
  980 
  981         tw_osli_dbg_dprintf(5, sc, "ioctl: passthru");
  982                 
  983         if ((req = tw_osli_get_request(sc)) == NULL)
  984                 return(EBUSY);
  985 
  986         req->req_handle.osl_req_ctxt = req;
  987         req->orig_req = buf;
  988         req->flags |= TW_OSLI_REQ_FLAGS_PASSTHRU;
  989 
  990         req_pkt = &(req->req_pkt);
  991         req_pkt->status = 0;
  992         req_pkt->tw_osl_callback = tw_osl_complete_passthru;
  993         /* Let the Common Layer retry the request on cmd queue full. */
  994         req_pkt->flags |= TW_CL_REQ_RETRY_ON_BUSY;
  995 
  996         pt_req = &(req_pkt->gen_req_pkt.pt_req);
  997         /*
  998          * Make sure that the data buffer sent to firmware is a 
  999          * 512 byte multiple in size.
 1000          */
 1001         data_buf_size_adjusted =
 1002                 (user_buf->driver_pkt.buffer_length +
 1003                 (sc->sg_size_factor - 1)) & ~(sc->sg_size_factor - 1);
 1004         if ((req->length = data_buf_size_adjusted)) {
 1005                 if ((req->data = malloc(data_buf_size_adjusted,
 1006                         TW_OSLI_MALLOC_CLASS, M_WAITOK)) == NULL) {
 1007                         error = ENOMEM;
 1008                         tw_osli_printf(sc, "error = %d",
 1009                                 TW_CL_SEVERITY_ERROR_STRING,
 1010                                 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
 1011                                 0x2016,
 1012                                 "Could not alloc mem for "
 1013                                 "fw_passthru data_buf",
 1014                                 error);
 1015                         goto fw_passthru_err;
 1016                 }
 1017                 /* Copy the payload. */
 1018                 if ((error = copyin((TW_VOID *)(user_buf->pdata), 
 1019                         req->data,
 1020                         user_buf->driver_pkt.buffer_length)) != 0) {
 1021                         tw_osli_printf(sc, "error = %d",
 1022                                 TW_CL_SEVERITY_ERROR_STRING,
 1023                                 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
 1024                                 0x2017,
 1025                                 "Could not copyin fw_passthru data_buf",
 1026                                 error);
 1027                         goto fw_passthru_err;
 1028                 }
 1029                 pt_req->sgl_entries = 1; /* will be updated during mapping */
 1030                 req->flags |= (TW_OSLI_REQ_FLAGS_DATA_IN |
 1031                         TW_OSLI_REQ_FLAGS_DATA_OUT);
 1032         } else
 1033                 pt_req->sgl_entries = 0; /* no payload */
 1034 
 1035         pt_req->cmd_pkt = (TW_VOID *)(&(user_buf->cmd_pkt));
 1036         pt_req->cmd_pkt_length = sizeof(struct tw_cl_command_packet);
 1037 
 1038         if ((error = tw_osli_map_request(req)))
 1039                 goto fw_passthru_err;
 1040 
 1041         end_time = tw_osl_get_local_time() + timeout;
 1042         while (req->state != TW_OSLI_REQ_STATE_COMPLETE) {
 1043                 mtx_lock(req->ioctl_wake_timeout_lock);
 1044                 req->flags |= TW_OSLI_REQ_FLAGS_SLEEPING;
 1045 
 1046                 error = mtx_sleep(req, req->ioctl_wake_timeout_lock, 0,
 1047                             "twa_passthru", timeout*hz);
 1048                 mtx_unlock(req->ioctl_wake_timeout_lock);
 1049 
 1050                 if (!(req->flags & TW_OSLI_REQ_FLAGS_SLEEPING))
 1051                         error = 0;
 1052                 req->flags &= ~TW_OSLI_REQ_FLAGS_SLEEPING;
 1053 
 1054                 if (! error) {
 1055                         if (((error = req->error_code)) ||
 1056                                 ((error = (req->state !=
 1057                                 TW_OSLI_REQ_STATE_COMPLETE))) ||
 1058                                 ((error = req_pkt->status)))
 1059                                 goto fw_passthru_err;
 1060                         break;
 1061                 }
 1062 
 1063                 if (req_pkt->status) {
 1064                         error = req_pkt->status;
 1065                         goto fw_passthru_err;
 1066                 }
 1067 
 1068                 if (error == EWOULDBLOCK) {
 1069                         /* Time out! */
 1070                         if ((!(req->error_code))                       &&
 1071                             (req->state == TW_OSLI_REQ_STATE_COMPLETE) &&
 1072                             (!(req_pkt->status))                          ) {
 1073 #ifdef    TW_OSL_DEBUG
 1074                                 tw_osli_printf(sc, "request = %p",
 1075                                         TW_CL_SEVERITY_ERROR_STRING,
 1076                                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
 1077                                         0x7777,
 1078                                         "FALSE Passthru timeout!",
 1079                                         req);
 1080 #endif /* TW_OSL_DEBUG */
 1081                                 error = 0; /* False error */
 1082                                 break;
 1083                         }
 1084                         if (!(tw_cl_is_reset_needed(&(req->ctlr->ctlr_handle)))) {
 1085 #ifdef    TW_OSL_DEBUG
 1086                                 tw_osli_printf(sc, "request = %p",
 1087                                         TW_CL_SEVERITY_ERROR_STRING,
 1088                                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
 1089                                         0x2018,
 1090                                         "Passthru request timed out!",
 1091                                         req);
 1092 #else  /* TW_OSL_DEBUG */
 1093                         device_printf((sc)->bus_dev, "Passthru request timed out!\n");
 1094 #endif /* TW_OSL_DEBUG */
 1095                                 tw_cl_reset_ctlr(&(req->ctlr->ctlr_handle));
 1096                         }
 1097 
 1098                         error = 0;
 1099                         end_time = tw_osl_get_local_time() + timeout;
 1100                         continue;
 1101                         /*
 1102                          * Don't touch req after a reset.  It (and any
 1103                          * associated data) will be
 1104                          * unmapped by the callback.
 1105                          */
 1106                 }
 1107                 /* 
 1108                  * Either the request got completed, or we were woken up by a
 1109                  * signal.  Calculate the new timeout, in case it was the latter.
 1110                  */
 1111                 timeout = (end_time - tw_osl_get_local_time());
 1112         } /* End of while loop */
 1113 
 1114         /* If there was a payload, copy it back. */
 1115         if ((!error) && (req->length))
 1116                 if ((error = copyout(req->data, user_buf->pdata,
 1117                         user_buf->driver_pkt.buffer_length)))
 1118                         tw_osli_printf(sc, "error = %d",
 1119                                 TW_CL_SEVERITY_ERROR_STRING,
 1120                                 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
 1121                                 0x2019,
 1122                                 "Could not copyout fw_passthru data_buf",
 1123                                 error);
 1124         
 1125 fw_passthru_err:
 1126 
 1127         if (req_pkt->status == TW_CL_ERR_REQ_BUS_RESET)
 1128                 error = EBUSY;
 1129 
 1130         user_buf->driver_pkt.os_status = error;
 1131         /* Free resources. */
 1132         if (req->data)
 1133                 free(req->data, TW_OSLI_MALLOC_CLASS);
 1134         tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
 1135         return(error);
 1136 }
 1137 
 1138 
 1139 
 1140 /*
 1141  * Function name:       tw_osl_complete_passthru
 1142  * Description:         Called to complete passthru requests.
 1143  *
 1144  * Input:               req_handle      -- ptr to request handle
 1145  * Output:              None
 1146  * Return value:        None
 1147  */
 1148 TW_VOID
 1149 tw_osl_complete_passthru(struct tw_cl_req_handle *req_handle)
 1150 {
 1151         struct tw_osli_req_context      *req = req_handle->osl_req_ctxt;
 1152         struct tw_cl_req_packet         *req_pkt =
 1153                 (struct tw_cl_req_packet *)(&req->req_pkt);
 1154         struct twa_softc                *sc = req->ctlr;
 1155 
 1156         tw_osli_dbg_dprintf(5, sc, "entered");
 1157 
 1158         if (req->state != TW_OSLI_REQ_STATE_BUSY) {
 1159                 tw_osli_printf(sc, "request = %p, status = %d",
 1160                         TW_CL_SEVERITY_ERROR_STRING,
 1161                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
 1162                         0x201B,
 1163                         "Unposted command completed!!",
 1164                         req, req->state);
 1165         }
 1166 
 1167         /*
 1168          * Remove request from the busy queue.  Just mark it complete.
 1169          * There's no need to move it into the complete queue as we are
 1170          * going to be done with it right now.
 1171          */
 1172         req->state = TW_OSLI_REQ_STATE_COMPLETE;
 1173         tw_osli_req_q_remove_item(req, TW_OSLI_BUSY_Q);
 1174 
 1175         tw_osli_unmap_request(req);
 1176 
 1177         /*
 1178          * Don't do a wake up if there was an error even before the request
 1179          * was sent down to the Common Layer, and we hadn't gotten an
 1180          * EINPROGRESS.  The request originator will then be returned an
 1181          * error, and he can do the clean-up.
 1182          */
 1183         if ((req->error_code) && (!(req->flags & TW_OSLI_REQ_FLAGS_IN_PROGRESS)))
 1184                 return;
 1185 
 1186         if (req->flags & TW_OSLI_REQ_FLAGS_PASSTHRU) {
 1187                 if (req->flags & TW_OSLI_REQ_FLAGS_SLEEPING) {
 1188                         /* Wake up the sleeping command originator. */
 1189                         tw_osli_dbg_dprintf(5, sc,
 1190                                 "Waking up originator of request %p", req);
 1191                         req->flags &= ~TW_OSLI_REQ_FLAGS_SLEEPING;
 1192                         wakeup_one(req);
 1193                 } else {
 1194                         /*
 1195                          * If the request completed even before mtx_sleep
 1196                          * was called, simply return.
 1197                          */
 1198                         if (req->flags & TW_OSLI_REQ_FLAGS_MAPPED)
 1199                                 return;
 1200 
 1201                         if (req_pkt->status == TW_CL_ERR_REQ_BUS_RESET)
 1202                                 return;
 1203 
 1204                         tw_osli_printf(sc, "request = %p",
 1205                                 TW_CL_SEVERITY_ERROR_STRING,
 1206                                 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
 1207                                 0x201C,
 1208                                 "Passthru callback called, "
 1209                                 "and caller not sleeping",
 1210                                 req);
 1211                 }
 1212         } else {
 1213                 tw_osli_printf(sc, "request = %p",
 1214                         TW_CL_SEVERITY_ERROR_STRING,
 1215                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
 1216                         0x201D,
 1217                         "Passthru callback called for non-passthru request",
 1218                         req);
 1219         }
 1220 }
 1221 
 1222 
 1223 
 1224 /*
 1225  * Function name:       tw_osli_get_request
 1226  * Description:         Gets a request pkt from the free queue.
 1227  *
 1228  * Input:               sc      -- ptr to OSL internal ctlr context
 1229  * Output:              None
 1230  * Return value:        ptr to request pkt      -- success
 1231  *                      NULL                    -- failure
 1232  */
 1233 struct tw_osli_req_context *
 1234 tw_osli_get_request(struct twa_softc *sc)
 1235 {
 1236         struct tw_osli_req_context      *req;
 1237 
 1238         tw_osli_dbg_dprintf(4, sc, "entered");
 1239 
 1240         /* Get a free request packet. */
 1241         req = tw_osli_req_q_remove_head(sc, TW_OSLI_FREE_Q);
 1242 
 1243         /* Initialize some fields to their defaults. */
 1244         if (req) {
 1245                 req->req_handle.osl_req_ctxt = NULL;
 1246                 req->req_handle.cl_req_ctxt = NULL;
 1247                 req->req_handle.is_io = 0;
 1248                 req->data = NULL;
 1249                 req->length = 0;
 1250                 req->deadline = 0;
 1251                 req->real_data = NULL;
 1252                 req->real_length = 0;
 1253                 req->state = TW_OSLI_REQ_STATE_INIT;/* req being initialized */
 1254                 req->flags = 0;
 1255                 req->error_code = 0;
 1256                 req->orig_req = NULL;
 1257 
 1258                 bzero(&(req->req_pkt), sizeof(struct tw_cl_req_packet));
 1259 
 1260         }
 1261         return(req);
 1262 }
 1263 
 1264 
 1265 
 1266 /*
 1267  * Function name:       twa_map_load_data_callback
 1268  * Description:         Callback of bus_dmamap_load for the buffer associated
 1269  *                      with data.  Updates the cmd pkt (size/sgl_entries
 1270  *                      fields, as applicable) to reflect the number of sg
 1271  *                      elements.
 1272  *
 1273  * Input:               arg     -- ptr to OSL internal request context
 1274  *                      segs    -- ptr to a list of segment descriptors
 1275  *                      nsegments--# of segments
 1276  *                      error   -- 0 if no errors encountered before callback,
 1277  *                                 non-zero if errors were encountered
 1278  * Output:              None
 1279  * Return value:        None
 1280  */
 1281 static TW_VOID
 1282 twa_map_load_data_callback(TW_VOID *arg, bus_dma_segment_t *segs,
 1283         TW_INT32 nsegments, TW_INT32 error)
 1284 {
 1285         struct tw_osli_req_context      *req =
 1286                 (struct tw_osli_req_context *)arg;
 1287         struct twa_softc                *sc = req->ctlr;
 1288         struct tw_cl_req_packet         *req_pkt = &(req->req_pkt);
 1289 
 1290         tw_osli_dbg_dprintf(10, sc, "entered");
 1291 
 1292         if (error == EINVAL) {
 1293                 req->error_code = error;
 1294                 return;
 1295         }
 1296 
 1297         /* Mark the request as currently being processed. */
 1298         req->state = TW_OSLI_REQ_STATE_BUSY;
 1299         /* Move the request into the busy queue. */
 1300         tw_osli_req_q_insert_tail(req, TW_OSLI_BUSY_Q);
 1301 
 1302         req->flags |= TW_OSLI_REQ_FLAGS_MAPPED;
 1303 
 1304         if (error == EFBIG) {
 1305                 req->error_code = error;
 1306                 goto out;
 1307         }
 1308 
 1309         if (req->flags & TW_OSLI_REQ_FLAGS_PASSTHRU) {
 1310                 struct tw_cl_passthru_req_packet        *pt_req;
 1311 
 1312                 if (req->flags & TW_OSLI_REQ_FLAGS_DATA_IN)
 1313                         bus_dmamap_sync(sc->ioctl_tag, sc->ioctl_map,
 1314                                 BUS_DMASYNC_PREREAD);
 1315 
 1316                 if (req->flags & TW_OSLI_REQ_FLAGS_DATA_OUT) {
 1317                         /* 
 1318                          * If we're using an alignment buffer, and we're
 1319                          * writing data, copy the real data out.
 1320                          */
 1321                         if (req->flags & TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED)
 1322                                 bcopy(req->real_data, req->data, req->real_length);
 1323                         bus_dmamap_sync(sc->ioctl_tag, sc->ioctl_map,
 1324                                 BUS_DMASYNC_PREWRITE);
 1325                 }
 1326 
 1327                 pt_req = &(req_pkt->gen_req_pkt.pt_req);
 1328                 pt_req->sg_list = (TW_UINT8 *)segs;
 1329                 pt_req->sgl_entries += (nsegments - 1);
 1330                 error = tw_cl_fw_passthru(&(sc->ctlr_handle), req_pkt,
 1331                         &(req->req_handle));
 1332         } else {
 1333                 struct tw_cl_scsi_req_packet    *scsi_req;
 1334 
 1335                 if (req->flags & TW_OSLI_REQ_FLAGS_DATA_IN)
 1336                         bus_dmamap_sync(sc->dma_tag, req->dma_map,
 1337                                 BUS_DMASYNC_PREREAD);
 1338 
 1339                 if (req->flags & TW_OSLI_REQ_FLAGS_DATA_OUT) {
 1340                         /* 
 1341                          * If we're using an alignment buffer, and we're
 1342                          * writing data, copy the real data out.
 1343                          */
 1344                         if (req->flags & TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED)
 1345                                 bcopy(req->real_data, req->data, req->real_length);
 1346                         bus_dmamap_sync(sc->dma_tag, req->dma_map,
 1347                                 BUS_DMASYNC_PREWRITE);
 1348                 }
 1349 
 1350                 scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
 1351                 scsi_req->sg_list = (TW_UINT8 *)segs;
 1352                 scsi_req->sgl_entries += (nsegments - 1);
 1353                 error = tw_cl_start_io(&(sc->ctlr_handle), req_pkt,
 1354                         &(req->req_handle));
 1355         }
 1356 
 1357 out:
 1358         if (error) {
 1359                 req->error_code = error;
 1360                 req_pkt->tw_osl_callback(&(req->req_handle));
 1361                 /*
 1362                  * If the caller had been returned EINPROGRESS, and he has
 1363                  * registered a callback for handling completion, the callback
 1364                  * will never get called because we were unable to submit the
 1365                  * request.  So, free up the request right here.
 1366                  */
 1367                 if (req->flags & TW_OSLI_REQ_FLAGS_IN_PROGRESS)
 1368                         tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
 1369         }
 1370 }
 1371 
 1372 
 1373 
 1374 /*
 1375  * Function name:       twa_map_load_callback
 1376  * Description:         Callback of bus_dmamap_load for the buffer associated
 1377  *                      with a cmd pkt.
 1378  *
 1379  * Input:               arg     -- ptr to variable to hold phys addr
 1380  *                      segs    -- ptr to a list of segment descriptors
 1381  *                      nsegments--# of segments
 1382  *                      error   -- 0 if no errors encountered before callback,
 1383  *                                 non-zero if errors were encountered
 1384  * Output:              None
 1385  * Return value:        None
 1386  */
 1387 static TW_VOID
 1388 twa_map_load_callback(TW_VOID *arg, bus_dma_segment_t *segs,
 1389         TW_INT32 nsegments, TW_INT32 error)
 1390 {
 1391         *((bus_addr_t *)arg) = segs[0].ds_addr;
 1392 }
 1393 
 1394 
 1395 
 1396 /*
 1397  * Function name:       tw_osli_map_request
 1398  * Description:         Maps a cmd pkt and data associated with it, into
 1399  *                      DMA'able memory.
 1400  *
 1401  * Input:               req     -- ptr to request pkt
 1402  * Output:              None
 1403  * Return value:        0       -- success
 1404  *                      non-zero-- failure
 1405  */
 1406 TW_INT32
 1407 tw_osli_map_request(struct tw_osli_req_context *req)
 1408 {
 1409         struct twa_softc        *sc = req->ctlr;
 1410         TW_INT32                error = 0;
 1411 
 1412         tw_osli_dbg_dprintf(10, sc, "entered");
 1413 
 1414         /* If the command involves data, map that too. */
 1415         if (req->data != NULL) {
 1416                 /*
 1417                  * It's sufficient for the data pointer to be 4-byte aligned
 1418                  * to work with 9000.  However, if 4-byte aligned addresses
 1419                  * are passed to bus_dmamap_load, we can get back sg elements
 1420                  * that are not 512-byte multiples in size.  So, we will let
 1421                  * only those buffers that are 512-byte aligned to pass
 1422                  * through, and bounce the rest, so as to make sure that we
 1423                  * always get back sg elements that are 512-byte multiples
 1424                  * in size.
 1425                  */
 1426                 if (((vm_offset_t)req->data % sc->sg_size_factor) ||
 1427                         (req->length % sc->sg_size_factor)) {
 1428                         req->flags |= TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED;
 1429                         /* Save original data pointer and length. */
 1430                         req->real_data = req->data;
 1431                         req->real_length = req->length;
 1432                         req->length = (req->length +
 1433                                 (sc->sg_size_factor - 1)) &
 1434                                 ~(sc->sg_size_factor - 1);
 1435                         req->data = malloc(req->length, TW_OSLI_MALLOC_CLASS,
 1436                                         M_NOWAIT);
 1437                         if (req->data == NULL) {
 1438                                 tw_osli_printf(sc, "error = %d",
 1439                                         TW_CL_SEVERITY_ERROR_STRING,
 1440                                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
 1441                                         0x201E,
 1442                                         "Failed to allocate memory "
 1443                                         "for bounce buffer",
 1444                                         ENOMEM);
 1445                                 /* Restore original data pointer and length. */
 1446                                 req->data = req->real_data;
 1447                                 req->length = req->real_length;
 1448                                 return(ENOMEM);
 1449                         }
 1450                 }
 1451         
 1452                 /*
 1453                  * Map the data buffer into bus space and build the SG list.
 1454                  */
 1455                 if (req->flags & TW_OSLI_REQ_FLAGS_PASSTHRU) {
 1456                         /* Lock against multiple simultaneous ioctl calls. */
 1457                         mtx_lock_spin(sc->io_lock);
 1458                         error = bus_dmamap_load(sc->ioctl_tag, sc->ioctl_map,
 1459                                 req->data, req->length,
 1460                                 twa_map_load_data_callback, req,
 1461                                 BUS_DMA_WAITOK);
 1462                         mtx_unlock_spin(sc->io_lock);
 1463                 } else if (req->flags & TW_OSLI_REQ_FLAGS_CCB) {
 1464                         error = bus_dmamap_load_ccb(sc->dma_tag, req->dma_map,
 1465                                 req->orig_req, twa_map_load_data_callback, req,
 1466                                 BUS_DMA_WAITOK);
 1467                 } else {
 1468                         /*
 1469                          * There's only one CAM I/O thread running at a time.
 1470                          * So, there's no need to hold the io_lock.
 1471                          */
 1472                         error = bus_dmamap_load(sc->dma_tag, req->dma_map,
 1473                                 req->data, req->length,
 1474                                 twa_map_load_data_callback, req,
 1475                                 BUS_DMA_WAITOK);
 1476                 }
 1477                 
 1478                 if (!error)
 1479                         error = req->error_code;
 1480                 else {
 1481                         if (error == EINPROGRESS) {
 1482                                 /*
 1483                                  * Specifying sc->io_lock as the lockfuncarg
 1484                                  * in ...tag_create should protect the access
 1485                                  * of ...FLAGS_MAPPED from the callback.
 1486                                  */
 1487                                 mtx_lock_spin(sc->io_lock);
 1488                                 if (!(req->flags & TW_OSLI_REQ_FLAGS_MAPPED))
 1489                                         req->flags |= TW_OSLI_REQ_FLAGS_IN_PROGRESS;
 1490                                 tw_osli_disallow_new_requests(sc, &(req->req_handle));
 1491                                 mtx_unlock_spin(sc->io_lock);
 1492                                 error = 0;
 1493                         } else {
 1494                                 tw_osli_printf(sc, "error = %d",
 1495                                         TW_CL_SEVERITY_ERROR_STRING,
 1496                                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
 1497                                         0x9999,
 1498                                         "Failed to map DMA memory "
 1499                                         "for I/O request",
 1500                                         error);
 1501                                 req->flags |= TW_OSLI_REQ_FLAGS_FAILED;
 1502                                 /* Free alignment buffer if it was used. */
 1503                                 if (req->flags &
 1504                                         TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED) {
 1505                                         free(req->data, TW_OSLI_MALLOC_CLASS);
 1506                                         /*
 1507                                          * Restore original data pointer
 1508                                          * and length.
 1509                                          */
 1510                                         req->data = req->real_data;
 1511                                         req->length = req->real_length;
 1512                                 }
 1513                         }
 1514                 }
 1515 
 1516         } else {
 1517                 /* Mark the request as currently being processed. */
 1518                 req->state = TW_OSLI_REQ_STATE_BUSY;
 1519                 /* Move the request into the busy queue. */
 1520                 tw_osli_req_q_insert_tail(req, TW_OSLI_BUSY_Q);
 1521                 if (req->flags & TW_OSLI_REQ_FLAGS_PASSTHRU)
 1522                         error = tw_cl_fw_passthru(&sc->ctlr_handle,
 1523                                         &(req->req_pkt), &(req->req_handle));
 1524                 else
 1525                         error = tw_cl_start_io(&sc->ctlr_handle,
 1526                                         &(req->req_pkt), &(req->req_handle));
 1527                 if (error) {
 1528                         req->error_code = error;
 1529                         req->req_pkt.tw_osl_callback(&(req->req_handle));
 1530                 }
 1531         }
 1532         return(error);
 1533 }
 1534 
 1535 
 1536 
 1537 /*
 1538  * Function name:       tw_osli_unmap_request
 1539  * Description:         Undoes the mapping done by tw_osli_map_request.
 1540  *
 1541  * Input:               req     -- ptr to request pkt
 1542  * Output:              None
 1543  * Return value:        None
 1544  */
 1545 TW_VOID
 1546 tw_osli_unmap_request(struct tw_osli_req_context *req)
 1547 {
 1548         struct twa_softc        *sc = req->ctlr;
 1549 
 1550         tw_osli_dbg_dprintf(10, sc, "entered");
 1551 
 1552         /* If the command involved data, unmap that too. */
 1553         if (req->data != NULL) {
 1554                 if (req->flags & TW_OSLI_REQ_FLAGS_PASSTHRU) {
 1555                         /* Lock against multiple simultaneous ioctl calls. */
 1556                         mtx_lock_spin(sc->io_lock);
 1557 
 1558                         if (req->flags & TW_OSLI_REQ_FLAGS_DATA_IN) {
 1559                                 bus_dmamap_sync(sc->ioctl_tag,
 1560                                         sc->ioctl_map, BUS_DMASYNC_POSTREAD);
 1561 
 1562                                 /* 
 1563                                  * If we are using a bounce buffer, and we are
 1564                                  * reading data, copy the real data in.
 1565                                  */
 1566                                 if (req->flags & TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED)
 1567                                         bcopy(req->data, req->real_data,
 1568                                                 req->real_length);
 1569                         }
 1570 
 1571                         if (req->flags & TW_OSLI_REQ_FLAGS_DATA_OUT)
 1572                                 bus_dmamap_sync(sc->ioctl_tag, sc->ioctl_map,
 1573                                         BUS_DMASYNC_POSTWRITE);
 1574 
 1575                         bus_dmamap_unload(sc->ioctl_tag, sc->ioctl_map);
 1576 
 1577                         mtx_unlock_spin(sc->io_lock);
 1578                 } else {
 1579                         if (req->flags & TW_OSLI_REQ_FLAGS_DATA_IN) {
 1580                                 bus_dmamap_sync(sc->dma_tag,
 1581                                         req->dma_map, BUS_DMASYNC_POSTREAD);
 1582 
 1583                                 /* 
 1584                                  * If we are using a bounce buffer, and we are
 1585                                  * reading data, copy the real data in.
 1586                                  */
 1587                                 if (req->flags & TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED)
 1588                                         bcopy(req->data, req->real_data,
 1589                                                 req->real_length);
 1590                         }
 1591                         if (req->flags & TW_OSLI_REQ_FLAGS_DATA_OUT)
 1592                                 bus_dmamap_sync(sc->dma_tag, req->dma_map,
 1593                                         BUS_DMASYNC_POSTWRITE);
 1594 
 1595                         bus_dmamap_unload(sc->dma_tag, req->dma_map);
 1596                 }
 1597         }
 1598 
 1599         /* Free alignment buffer if it was used. */
 1600         if (req->flags & TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED) {
 1601                 free(req->data, TW_OSLI_MALLOC_CLASS);
 1602                 /* Restore original data pointer and length. */
 1603                 req->data = req->real_data;
 1604                 req->length = req->real_length;
 1605         }
 1606 }
 1607 
 1608 
 1609 
 1610 #ifdef TW_OSL_DEBUG
 1611 
 1612 TW_VOID twa_report_stats(TW_VOID);
 1613 TW_VOID twa_reset_stats(TW_VOID);
 1614 TW_VOID tw_osli_print_ctlr_stats(struct twa_softc *sc);
 1615 TW_VOID twa_print_req_info(struct tw_osli_req_context *req);
 1616 
 1617 
 1618 /*
 1619  * Function name:       twa_report_stats
 1620  * Description:         For being called from ddb.  Calls functions that print
 1621  *                      OSL and CL internal stats for the controller.
 1622  *
 1623  * Input:               None
 1624  * Output:              None
 1625  * Return value:        None
 1626  */
 1627 TW_VOID
 1628 twa_report_stats(TW_VOID)
 1629 {
 1630         struct twa_softc        *sc;
 1631         TW_INT32                i;
 1632 
 1633         for (i = 0; (sc = devclass_get_softc(twa_devclass, i)) != NULL; i++) {
 1634                 tw_osli_print_ctlr_stats(sc);
 1635                 tw_cl_print_ctlr_stats(&sc->ctlr_handle);
 1636         }
 1637 }
 1638 
 1639 
 1640 
 1641 /*
 1642  * Function name:       tw_osli_print_ctlr_stats
 1643  * Description:         For being called from ddb.  Prints OSL controller stats
 1644  *
 1645  * Input:               sc      -- ptr to OSL internal controller context
 1646  * Output:              None
 1647  * Return value:        None
 1648  */
 1649 TW_VOID
 1650 tw_osli_print_ctlr_stats(struct twa_softc *sc)
 1651 {
 1652         twa_printf(sc, "osl_ctlr_ctxt = %p\n", sc);
 1653         twa_printf(sc, "OSLq type  current  max\n");
 1654         twa_printf(sc, "free      %04d     %04d\n",
 1655                 sc->q_stats[TW_OSLI_FREE_Q].cur_len,
 1656                 sc->q_stats[TW_OSLI_FREE_Q].max_len);
 1657         twa_printf(sc, "busy      %04d     %04d\n",
 1658                 sc->q_stats[TW_OSLI_BUSY_Q].cur_len,
 1659                 sc->q_stats[TW_OSLI_BUSY_Q].max_len);
 1660 }       
 1661 
 1662 
 1663 
 1664 /*
 1665  * Function name:       twa_print_req_info
 1666  * Description:         For being called from ddb.  Calls functions that print
 1667  *                      OSL and CL internal details for the request.
 1668  *
 1669  * Input:               req     -- ptr to OSL internal request context
 1670  * Output:              None
 1671  * Return value:        None
 1672  */
 1673 TW_VOID
 1674 twa_print_req_info(struct tw_osli_req_context *req)
 1675 {
 1676         struct twa_softc        *sc = req->ctlr;
 1677 
 1678         twa_printf(sc, "OSL details for request:\n");
 1679         twa_printf(sc, "osl_req_ctxt = %p, cl_req_ctxt = %p\n"
 1680                 "data = %p, length = 0x%x, real_data = %p, real_length = 0x%x\n"
 1681                 "state = 0x%x, flags = 0x%x, error = 0x%x, orig_req = %p\n"
 1682                 "next_req = %p, prev_req = %p, dma_map = %p\n",
 1683                 req->req_handle.osl_req_ctxt, req->req_handle.cl_req_ctxt,
 1684                 req->data, req->length, req->real_data, req->real_length,
 1685                 req->state, req->flags, req->error_code, req->orig_req,
 1686                 req->link.next, req->link.prev, req->dma_map);
 1687         tw_cl_print_req_info(&(req->req_handle));
 1688 }
 1689 
 1690 
 1691 
 1692 /*
 1693  * Function name:       twa_reset_stats
 1694  * Description:         For being called from ddb.
 1695  *                      Resets some OSL controller stats.
 1696  *
 1697  * Input:               None
 1698  * Output:              None
 1699  * Return value:        None
 1700  */
 1701 TW_VOID
 1702 twa_reset_stats(TW_VOID)
 1703 {
 1704         struct twa_softc        *sc;
 1705         TW_INT32                i;
 1706 
 1707         for (i = 0; (sc = devclass_get_softc(twa_devclass, i)) != NULL; i++) {
 1708                 sc->q_stats[TW_OSLI_FREE_Q].max_len = 0;
 1709                 sc->q_stats[TW_OSLI_BUSY_Q].max_len = 0;
 1710                 tw_cl_reset_stats(&sc->ctlr_handle);
 1711         }
 1712 }
 1713 
 1714 #endif /* TW_OSL_DEBUG */

Cache object: bdceb59adfff58c3aa26f62a7958ace2


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