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_cam.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  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  *      $FreeBSD$
   30  */
   31 
   32 /*
   33  * AMCC'S 3ware driver for 9000 series storage controllers.
   34  *
   35  * Author: Vinod Kashyap
   36  * Modifications by: Adam Radford
   37  * Modifications by: Manjunath Ranganathaiah
   38  */
   39 
   40 /*
   41  * FreeBSD CAM related functions.
   42  */
   43 
   44 #include <dev/twa/tw_osl_includes.h>
   45 
   46 #include <cam/cam.h>
   47 #include <cam/cam_ccb.h>
   48 #include <cam/cam_sim.h>
   49 #include <cam/cam_xpt_sim.h>
   50 #include <cam/cam_debug.h>
   51 #include <cam/cam_periph.h>
   52 
   53 #include <cam/scsi/scsi_all.h>
   54 #include <cam/scsi/scsi_message.h>
   55 
   56 static TW_VOID  twa_action(struct cam_sim *sim, union ccb *ccb);
   57 static TW_VOID  twa_poll(struct cam_sim *sim);
   58 
   59 static TW_INT32 tw_osli_execute_scsi(struct tw_osli_req_context *req,
   60         union ccb *ccb);
   61 
   62 /*
   63  * Function name:       tw_osli_cam_attach
   64  * Description:         Attaches the driver to CAM.
   65  *
   66  * Input:               sc      -- ptr to OSL internal ctlr context
   67  * Output:              None
   68  * Return value:        0       -- success
   69  *                      non-zero-- failure
   70  */
   71 TW_INT32
   72 tw_osli_cam_attach(struct twa_softc *sc)
   73 {
   74         struct cam_devq         *devq;
   75 
   76         tw_osli_dbg_dprintf(3, sc, "entered");
   77 
   78         /*
   79          * Create the device queue for our SIM.
   80          */
   81         if ((devq = cam_simq_alloc(TW_OSLI_MAX_NUM_IOS)) == NULL) {
   82                 tw_osli_printf(sc, "error = %d",
   83                         TW_CL_SEVERITY_ERROR_STRING,
   84                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
   85                         0x2100,
   86                         "Failed to create SIM device queue",
   87                         ENOMEM);
   88                 return(ENOMEM);
   89         }
   90 
   91         /*
   92          * Create a SIM entry.  Though we can support TW_OSLI_MAX_NUM_REQUESTS
   93          * simultaneous requests, we claim to be able to handle only
   94          * TW_OSLI_MAX_NUM_IOS (two less), so that we always have a request
   95          * packet available to service ioctls and AENs.
   96          */
   97         tw_osli_dbg_dprintf(3, sc, "Calling cam_sim_alloc");
   98         sc->sim = cam_sim_alloc(twa_action, twa_poll, "twa", sc,
   99                         device_get_unit(sc->bus_dev), sc->sim_lock,
  100                         TW_OSLI_MAX_NUM_IOS, 1, devq);
  101         if (sc->sim == NULL) {
  102                 cam_simq_free(devq);
  103                 tw_osli_printf(sc, "error = %d",
  104                         TW_CL_SEVERITY_ERROR_STRING,
  105                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  106                         0x2101,
  107                         "Failed to create a SIM entry",
  108                         ENOMEM);
  109                 return(ENOMEM);
  110         }
  111 
  112         /*
  113          * Register the bus.
  114          */
  115         tw_osli_dbg_dprintf(3, sc, "Calling xpt_bus_register");
  116         mtx_lock(sc->sim_lock);
  117         if (xpt_bus_register(sc->sim, sc->bus_dev, 0) != CAM_SUCCESS) {
  118                 cam_sim_free(sc->sim, TRUE);
  119                 sc->sim = NULL; /* so cam_detach will not try to free it */
  120                 tw_osli_printf(sc, "error = %d",
  121                         TW_CL_SEVERITY_ERROR_STRING,
  122                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  123                         0x2102,
  124                         "Failed to register the bus",
  125                         ENXIO);
  126                 mtx_unlock(sc->sim_lock);
  127                 return(ENXIO);
  128         }
  129 
  130         tw_osli_dbg_dprintf(3, sc, "Calling xpt_create_path");
  131         if (xpt_create_path(&sc->path, NULL,
  132                                 cam_sim_path(sc->sim),
  133                                 CAM_TARGET_WILDCARD,
  134                                 CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
  135                 xpt_bus_deregister(cam_sim_path (sc->sim));
  136                 /* Passing TRUE to cam_sim_free will free the devq as well. */
  137                 cam_sim_free(sc->sim, TRUE);
  138                 tw_osli_printf(sc, "error = %d",
  139                         TW_CL_SEVERITY_ERROR_STRING,
  140                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  141                         0x2103,
  142                         "Failed to create path",
  143                         ENXIO);
  144                 mtx_unlock(sc->sim_lock);
  145                 return(ENXIO);
  146         }
  147         mtx_unlock(sc->sim_lock);
  148 
  149         tw_osli_dbg_dprintf(3, sc, "exiting");
  150         return(0);
  151 }
  152 
  153 /*
  154  * Function name:       tw_osli_cam_detach
  155  * Description:         Detaches the driver from CAM.
  156  *
  157  * Input:               sc      -- ptr to OSL internal ctlr context
  158  * Output:              None
  159  * Return value:        None
  160  */
  161 TW_VOID
  162 tw_osli_cam_detach(struct twa_softc *sc)
  163 {
  164         tw_osli_dbg_dprintf(3, sc, "entered");
  165 
  166         mtx_lock(sc->sim_lock);
  167            
  168         if (sc->path)
  169                 xpt_free_path(sc->path);
  170         if (sc->sim) {
  171                 xpt_bus_deregister(cam_sim_path(sc->sim));
  172                 /* Passing TRUE to cam_sim_free will free the devq as well. */
  173                 cam_sim_free(sc->sim, TRUE);
  174         }
  175         /* It's ok have 1 hold count while destroying the mutex */
  176         mtx_destroy(sc->sim_lock);
  177 }
  178 
  179 /*
  180  * Function name:       tw_osli_execute_scsi
  181  * Description:         Build a fw cmd, based on a CAM style ccb, and
  182  *                      send it down.
  183  *
  184  * Input:               req     -- ptr to OSL internal request context
  185  *                      ccb     -- ptr to CAM style ccb
  186  * Output:              None
  187  * Return value:        0       -- success
  188  *                      non-zero-- failure
  189  */
  190 TW_INT32
  191 tw_osli_execute_scsi(struct tw_osli_req_context *req, union ccb *ccb)
  192 {
  193         struct twa_softc                *sc = req->ctlr;
  194         struct tw_cl_req_packet         *req_pkt;
  195         struct tw_cl_scsi_req_packet    *scsi_req;
  196         struct ccb_hdr                  *ccb_h = &(ccb->ccb_h);
  197         struct ccb_scsiio               *csio = &(ccb->csio);
  198         TW_INT32                        error;
  199 
  200         tw_osli_dbg_dprintf(10, sc, "SCSI I/O request 0x%x",
  201                 csio->cdb_io.cdb_bytes[0]);
  202 
  203         if (ccb_h->target_id >= TW_CL_MAX_NUM_UNITS) {
  204                 tw_osli_dbg_dprintf(3, sc, "Invalid target. PTL = %x %x %jx",
  205                         ccb_h->path_id, ccb_h->target_id,
  206                         (uintmax_t)ccb_h->target_lun);
  207                 ccb_h->status |= CAM_TID_INVALID;
  208                 xpt_done(ccb);
  209                 return(1);
  210         }
  211         if (ccb_h->target_lun >= TW_CL_MAX_NUM_LUNS) {
  212                 tw_osli_dbg_dprintf(3, sc, "Invalid lun. PTL = %x %x %jx",
  213                         ccb_h->path_id, ccb_h->target_id,
  214                         (uintmax_t)ccb_h->target_lun);
  215                 ccb_h->status |= CAM_LUN_INVALID;
  216                 xpt_done(ccb);
  217                 return(1);
  218         }
  219 
  220         if(ccb_h->flags & CAM_CDB_PHYS) {
  221                 tw_osli_printf(sc, "",
  222                         TW_CL_SEVERITY_ERROR_STRING,
  223                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  224                         0x2105,
  225                         "Physical CDB address!");
  226                 ccb_h->status = CAM_REQ_INVALID;
  227                 xpt_done(ccb);
  228                 return(1);
  229         }
  230 
  231         /*
  232          * We are going to work on this request.  Mark it as enqueued (though
  233          * we don't actually queue it...)
  234          */
  235         ccb_h->status |= CAM_SIM_QUEUED;
  236 
  237         if((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
  238                 if(ccb_h->flags & CAM_DIR_IN)
  239                         req->flags |= TW_OSLI_REQ_FLAGS_DATA_IN;
  240                 else
  241                         req->flags |= TW_OSLI_REQ_FLAGS_DATA_OUT;
  242         }
  243 
  244         /* Build the CL understood request packet for SCSI cmds. */
  245         req_pkt = &req->req_pkt;
  246         req_pkt->status = 0;
  247         req_pkt->tw_osl_callback = tw_osl_complete_io;
  248         scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
  249         scsi_req->unit = ccb_h->target_id;
  250         scsi_req->lun = ccb_h->target_lun;
  251         scsi_req->sense_len = 0;
  252         scsi_req->sense_data = (TW_UINT8 *)(&csio->sense_data);
  253         scsi_req->scsi_status = 0;
  254         if(ccb_h->flags & CAM_CDB_POINTER)
  255                 scsi_req->cdb = csio->cdb_io.cdb_ptr;
  256         else
  257                 scsi_req->cdb = csio->cdb_io.cdb_bytes;
  258         scsi_req->cdb_len = csio->cdb_len;
  259 
  260         if (csio->dxfer_len > TW_CL_MAX_IO_SIZE) {
  261                 tw_osli_printf(sc, "size = %d",
  262                         TW_CL_SEVERITY_ERROR_STRING,
  263                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  264                         0x2106,
  265                         "I/O size too big",
  266                         csio->dxfer_len);
  267                 ccb_h->status = CAM_REQ_TOO_BIG;
  268                 ccb_h->status &= ~CAM_SIM_QUEUED;
  269                 xpt_done(ccb);
  270                 return(1);
  271         }
  272         if ((ccb_h->flags & CAM_DATA_MASK) == CAM_DATA_VADDR) {
  273                 if ((req->length = csio->dxfer_len) != 0) {
  274                         req->data = csio->data_ptr;
  275                         scsi_req->sgl_entries = 1;
  276                 }
  277         } else
  278                 req->flags |= TW_OSLI_REQ_FLAGS_CCB;
  279         req->deadline = tw_osl_get_local_time() + (ccb_h->timeout / 1000);
  280 
  281         /*
  282          * twa_map_load_data_callback will fill in the SGL,
  283          * and submit the I/O.
  284          */
  285         error = tw_osli_map_request(req);
  286         if ((error) && (req->flags & TW_OSLI_REQ_FLAGS_FAILED)) {
  287                 req->deadline = 0;
  288                 ccb_h->status = CAM_REQ_CMP_ERR;
  289                 ccb_h->status &= ~CAM_SIM_QUEUED;
  290                 xpt_done(ccb);
  291         }
  292         return(error);
  293 }
  294 
  295 /*
  296  * Function name:       twa_action
  297  * Description:         Driver entry point for CAM's use.
  298  *
  299  * Input:               sim     -- sim corresponding to the ctlr
  300  *                      ccb     -- ptr to CAM request
  301  * Output:              None
  302  * Return value:        None
  303  */
  304 TW_VOID
  305 twa_action(struct cam_sim *sim, union ccb *ccb)
  306 {
  307         struct twa_softc        *sc = (struct twa_softc *)cam_sim_softc(sim);
  308         struct ccb_hdr          *ccb_h = &(ccb->ccb_h);
  309 
  310         switch (ccb_h->func_code) {
  311         case XPT_SCSI_IO:       /* SCSI I/O */
  312         {
  313                 struct tw_osli_req_context      *req;
  314 
  315                 req = tw_osli_get_request(sc);
  316                 if (req == NULL) {
  317                         tw_osli_dbg_dprintf(2, sc, "Cannot get request pkt.");
  318                         /*
  319                          * Freeze the simq to maintain ccb ordering.  The next
  320                          * ccb that gets completed will unfreeze the simq.
  321                          */
  322                         ccb_h->status &= ~CAM_SIM_QUEUED;
  323                         ccb_h->status |= CAM_REQUEUE_REQ;
  324                         xpt_done(ccb);
  325                         break;
  326                 }
  327 
  328                 if ((tw_cl_is_reset_needed(&(req->ctlr->ctlr_handle)))) {
  329                         ccb_h->status &= ~CAM_SIM_QUEUED;
  330                         ccb_h->status |= CAM_REQUEUE_REQ;
  331                         xpt_done(ccb);
  332                         tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
  333                         break;
  334                 }
  335 
  336                 req->req_handle.osl_req_ctxt = req;
  337                 req->req_handle.is_io = TW_CL_TRUE;
  338                 req->orig_req = ccb;
  339                 if (tw_osli_execute_scsi(req, ccb))
  340                         tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
  341                 break;
  342         }
  343 
  344         case XPT_ABORT:
  345                 tw_osli_dbg_dprintf(2, sc, "Abort request.");
  346                 ccb_h->status = CAM_UA_ABORT;
  347                 xpt_done(ccb);
  348                 break;
  349 
  350         case XPT_RESET_BUS:
  351                 tw_cl_create_event(&(sc->ctlr_handle), TW_CL_FALSE,
  352                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  353                         0x2108, 0x3, TW_CL_SEVERITY_INFO_STRING,
  354                         "Received Reset Bus request from CAM",
  355                         " ");
  356 
  357                 tw_cl_set_reset_needed(&(sc->ctlr_handle));
  358                 ccb_h->status = CAM_REQ_CMP;
  359                 xpt_done(ccb);
  360                 break;
  361 
  362         case XPT_SET_TRAN_SETTINGS:
  363                 tw_osli_dbg_dprintf(3, sc, "XPT_SET_TRAN_SETTINGS");
  364 
  365                 /*
  366                  * This command is not supported, since it's very specific
  367                  * to SCSI, and we are doing ATA.
  368                  */
  369                 ccb_h->status = CAM_FUNC_NOTAVAIL;
  370                 xpt_done(ccb);
  371                 break;
  372 
  373         case XPT_GET_TRAN_SETTINGS: 
  374         {
  375                 struct ccb_trans_settings       *cts = &ccb->cts;
  376                 struct ccb_trans_settings_scsi *scsi =
  377                     &cts->proto_specific.scsi;
  378                 struct ccb_trans_settings_spi *spi =
  379                     &cts->xport_specific.spi;
  380 
  381                 cts->protocol = PROTO_SCSI;
  382                 cts->protocol_version = SCSI_REV_2;
  383                 cts->transport = XPORT_SPI;
  384                 cts->transport_version = 2;
  385 
  386                 spi->valid = CTS_SPI_VALID_DISC;
  387                 spi->flags = CTS_SPI_FLAGS_DISC_ENB;
  388                 scsi->valid = CTS_SCSI_VALID_TQ;
  389                 scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
  390                 tw_osli_dbg_dprintf(3, sc, "XPT_GET_TRAN_SETTINGS");
  391                 ccb_h->status = CAM_REQ_CMP;
  392                 xpt_done(ccb);
  393                 break;
  394         }
  395 
  396         case XPT_CALC_GEOMETRY:
  397                 tw_osli_dbg_dprintf(3, sc, "XPT_CALC_GEOMETRY");
  398                 cam_calc_geometry(&ccb->ccg, 1/* extended */);
  399                 xpt_done(ccb);
  400                 break;
  401 
  402         case XPT_PATH_INQ:    /* Path inquiry -- get twa properties */
  403         {
  404                 struct ccb_pathinq      *path_inq = &ccb->cpi;
  405 
  406                 tw_osli_dbg_dprintf(3, sc, "XPT_PATH_INQ request");
  407 
  408                 path_inq->version_num = 1;
  409                 path_inq->hba_inquiry = 0;
  410                 path_inq->target_sprt = 0;
  411                 path_inq->hba_misc = 0;
  412                 path_inq->hba_eng_cnt = 0;
  413                 path_inq->max_target = TW_CL_MAX_NUM_UNITS;
  414                 path_inq->max_lun = TW_CL_MAX_NUM_LUNS - 1;
  415                 path_inq->unit_number = cam_sim_unit(sim);
  416                 path_inq->bus_id = cam_sim_bus(sim);
  417                 path_inq->initiator_id = TW_CL_MAX_NUM_UNITS;
  418                 path_inq->base_transfer_speed = 100000;
  419                 strlcpy(path_inq->sim_vid, "FreeBSD", SIM_IDLEN);
  420                 strlcpy(path_inq->hba_vid, "3ware", HBA_IDLEN);
  421                 strlcpy(path_inq->dev_name, cam_sim_name(sim), DEV_IDLEN);
  422                 path_inq->transport = XPORT_SPI;
  423                 path_inq->transport_version = 2;
  424                 path_inq->protocol = PROTO_SCSI;
  425                 path_inq->protocol_version = SCSI_REV_2;
  426                 path_inq->maxio = TW_CL_MAX_IO_SIZE;
  427                 ccb_h->status = CAM_REQ_CMP;
  428                 xpt_done(ccb);
  429                 break;
  430         }
  431 
  432         default:
  433                 tw_osli_dbg_dprintf(3, sc, "func_code = %x", ccb_h->func_code);
  434                 ccb_h->status = CAM_REQ_INVALID;
  435                 xpt_done(ccb);
  436                 break;
  437         }
  438 }
  439 
  440 /*
  441  * Function name:       twa_poll
  442  * Description:         Driver entry point called when interrupts are not
  443  *                      available.
  444  *
  445  * Input:               sim     -- sim corresponding to the controller
  446  * Output:              None
  447  * Return value:        None
  448  */
  449 TW_VOID
  450 twa_poll(struct cam_sim *sim)
  451 {
  452         struct twa_softc *sc = (struct twa_softc *)(cam_sim_softc(sim));
  453 
  454         tw_osli_dbg_dprintf(3, sc, "entering; sc = %p", sc);
  455         tw_cl_interrupt(&(sc->ctlr_handle));
  456         tw_osli_dbg_dprintf(3, sc, "exiting; sc = %p", sc);
  457 }
  458 
  459 /*
  460  * Function name:       tw_osli_request_bus_scan
  461  * Description:         Requests CAM for a scan of the bus.
  462  *
  463  * Input:               sc      -- ptr to per ctlr structure
  464  * Output:              None
  465  * Return value:        0       -- success
  466  *                      non-zero-- failure
  467  */
  468 TW_INT32
  469 tw_osli_request_bus_scan(struct twa_softc *sc)
  470 {
  471         union ccb       *ccb;
  472 
  473         tw_osli_dbg_dprintf(3, sc, "entering");
  474 
  475         /* If we get here before sc->sim is initialized, return an error. */
  476         if (!(sc->sim))
  477                 return(ENXIO);
  478         if ((ccb = xpt_alloc_ccb()) == NULL)
  479                 return(ENOMEM);
  480         mtx_lock(sc->sim_lock);
  481         if (xpt_create_path(&ccb->ccb_h.path, NULL, cam_sim_path(sc->sim),
  482             CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
  483                 xpt_free_ccb(ccb);
  484                 mtx_unlock(sc->sim_lock);
  485                 return(EIO);
  486         }
  487 
  488         xpt_rescan(ccb);
  489         mtx_unlock(sc->sim_lock);
  490         return(0);
  491 }
  492 
  493 /*
  494  * Function name:       tw_osli_disallow_new_requests
  495  * Description:         Calls the appropriate CAM function, so as to freeze
  496  *                      the flow of new requests from CAM to this controller.
  497  *
  498  * Input:               sc      -- ptr to OSL internal ctlr context
  499  *                      req_handle -- ptr to request handle sent by OSL.
  500  * Output:              None
  501  * Return value:        None
  502  */
  503 TW_VOID
  504 tw_osli_disallow_new_requests(struct twa_softc *sc,
  505         struct tw_cl_req_handle *req_handle)
  506 {
  507         /* Only freeze/release the simq for IOs */
  508         if (req_handle->is_io) {
  509                 struct tw_osli_req_context      *req = req_handle->osl_req_ctxt;
  510                 union ccb                       *ccb = (union ccb *)(req->orig_req);
  511 
  512                 xpt_freeze_simq(sc->sim, 1);
  513                 ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
  514         }
  515 }
  516 
  517 /*
  518  * Function name:       tw_osl_timeout
  519  * Description:         Call to timeout().
  520  *
  521  * Input:               req_handle -- ptr to request handle sent by OSL.
  522  * Output:              None
  523  * Return value:        None
  524  */
  525 TW_VOID
  526 tw_osl_timeout(struct tw_cl_req_handle *req_handle)
  527 {
  528         struct tw_osli_req_context      *req = req_handle->osl_req_ctxt;
  529         union ccb                       *ccb = (union ccb *)(req->orig_req);
  530         struct ccb_hdr                  *ccb_h = &(ccb->ccb_h);
  531 
  532         req->deadline = tw_osl_get_local_time() + (ccb_h->timeout / 1000);
  533 }
  534 
  535 /*
  536  * Function name:       tw_osl_untimeout
  537  * Description:         Inverse of call to timeout().
  538  *
  539  * Input:               req_handle -- ptr to request handle sent by OSL.
  540  * Output:              None
  541  * Return value:        None
  542  */
  543 TW_VOID
  544 tw_osl_untimeout(struct tw_cl_req_handle *req_handle)
  545 {
  546         struct tw_osli_req_context      *req = req_handle->osl_req_ctxt;
  547 
  548         req->deadline = 0;
  549 }
  550 
  551 /*
  552  * Function name:       tw_osl_scan_bus
  553  * Description:         CL calls this function to request for a bus scan.
  554  *
  555  * Input:               ctlr_handle     -- ptr to controller handle
  556  * Output:              None
  557  * Return value:        None
  558  */
  559 TW_VOID
  560 tw_osl_scan_bus(struct tw_cl_ctlr_handle *ctlr_handle)
  561 {
  562         struct twa_softc        *sc = ctlr_handle->osl_ctlr_ctxt;
  563         TW_INT32                error;
  564 
  565         if ((error = tw_osli_request_bus_scan(sc)))
  566                 tw_osli_printf(sc, "error = %d",
  567                         TW_CL_SEVERITY_ERROR_STRING,
  568                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  569                         0x2109,
  570                         "Bus scan request to CAM failed",
  571                         error);
  572 }
  573 
  574 /*
  575  * Function name:       tw_osl_complete_io
  576  * Description:         Called to complete CAM scsi requests.
  577  *
  578  * Input:               req_handle      -- ptr to request handle
  579  * Output:              None
  580  * Return value:        None
  581  */
  582 TW_VOID
  583 tw_osl_complete_io(struct tw_cl_req_handle *req_handle)
  584 {
  585         struct tw_osli_req_context      *req = req_handle->osl_req_ctxt;
  586         struct tw_cl_req_packet         *req_pkt =
  587                 (struct tw_cl_req_packet *)(&req->req_pkt);
  588         struct tw_cl_scsi_req_packet    *scsi_req;
  589         struct twa_softc                *sc = req->ctlr;
  590         union ccb                       *ccb = (union ccb *)(req->orig_req);
  591 
  592         tw_osli_dbg_dprintf(10, sc, "entering");
  593 
  594         if (req->state != TW_OSLI_REQ_STATE_BUSY)
  595                 tw_osli_printf(sc, "request = %p, status = %d",
  596                         TW_CL_SEVERITY_ERROR_STRING,
  597                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  598                         0x210A,
  599                         "Unposted command completed!!",
  600                         req, req->state);
  601 
  602         /*
  603          * Remove request from the busy queue.  Just mark it complete.
  604          * There's no need to move it into the complete queue as we are
  605          * going to be done with it right now.
  606          */
  607         req->state = TW_OSLI_REQ_STATE_COMPLETE;
  608         tw_osli_req_q_remove_item(req, TW_OSLI_BUSY_Q);
  609 
  610         tw_osli_unmap_request(req);
  611 
  612         req->deadline = 0;
  613         if (req->error_code) {
  614                 /* This request never got submitted to the firmware. */
  615                 if (req->error_code == EBUSY) {
  616                         /*
  617                          * Cmd queue is full, or the Common Layer is out of
  618                          * resources.  The simq will already have been frozen.
  619                          * When this ccb gets completed will unfreeze the simq.
  620                          */
  621                         ccb->ccb_h.status |= CAM_REQUEUE_REQ;
  622                 }
  623                 else if (req->error_code == EFBIG)
  624                         ccb->ccb_h.status = CAM_REQ_TOO_BIG;
  625                 else
  626                         ccb->ccb_h.status = CAM_REQ_CMP_ERR;
  627         } else {
  628                 scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
  629                 if (req_pkt->status == TW_CL_ERR_REQ_SUCCESS)
  630                         ccb->ccb_h.status = CAM_REQ_CMP;
  631                 else {
  632                         if (req_pkt->status & TW_CL_ERR_REQ_INVALID_TARGET)
  633                                 ccb->ccb_h.status |= CAM_SEL_TIMEOUT;
  634                         else if (req_pkt->status & TW_CL_ERR_REQ_INVALID_LUN)
  635                                 ccb->ccb_h.status |= CAM_DEV_NOT_THERE;
  636                         else if (req_pkt->status & TW_CL_ERR_REQ_SCSI_ERROR)
  637                                 ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
  638                         else if (req_pkt->status & TW_CL_ERR_REQ_BUS_RESET)
  639                                 ccb->ccb_h.status |= (CAM_REQUEUE_REQ | CAM_SCSI_BUS_RESET);
  640                         /*
  641                          * If none of the above errors occurred, simply
  642                          * mark completion error.
  643                          */
  644                         if (ccb->ccb_h.status == 0)
  645                                 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
  646 
  647                         if (req_pkt->status & TW_CL_ERR_REQ_AUTO_SENSE_VALID) {
  648                                 ccb->csio.sense_len = scsi_req->sense_len;
  649                                 ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
  650                         }
  651                 }
  652 
  653                 ccb->csio.scsi_status = scsi_req->scsi_status;
  654         }
  655 
  656         ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
  657         mtx_lock(sc->sim_lock);
  658         xpt_done(ccb);
  659         mtx_unlock(sc->sim_lock);
  660         if (! req->error_code)
  661                  /* twa_action will free the request otherwise */
  662                 tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
  663 }

Cache object: 2bce90b0ffa738d32018a86a4689770e


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