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  * Copyright (c) 2004-05 Applied Micro Circuits Corporation.
    3  * Copyright (c) 2004-05 Vinod Kashyap.
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  *
   27  *      $FreeBSD: releng/6.0/sys/dev/twa/tw_osl_cam.c 147285 2005-06-11 00:14:23Z vkashyap $
   28  */
   29 
   30 /*
   31  * AMCC'S 3ware driver for 9000 series storage controllers.
   32  *
   33  * Author: Vinod Kashyap
   34  */
   35 
   36 
   37 /*
   38  * FreeBSD CAM related functions.
   39  */
   40 
   41 
   42 #include "tw_osl_includes.h"
   43 
   44 #include <cam/cam.h>
   45 #include <cam/cam_ccb.h>
   46 #include <cam/cam_sim.h>
   47 #include <cam/cam_xpt_sim.h>
   48 #include <cam/cam_xpt_periph.h>
   49 #include <cam/cam_debug.h>
   50 #include <cam/cam_periph.h>
   51 
   52 #include <cam/scsi/scsi_all.h>
   53 #include <cam/scsi/scsi_message.h>
   54 
   55 static TW_VOID  twa_action(struct cam_sim *sim, union ccb *ccb);
   56 static TW_VOID  twa_poll(struct cam_sim *sim);
   57 static TW_VOID  twa_async(TW_VOID *callback_arg, TW_UINT32 code,
   58         struct cam_path *path, TW_VOID *arg);
   59 static TW_VOID  twa_timeout(TW_VOID *arg);
   60 static TW_VOID  twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb);
   61 
   62 static TW_INT32 tw_osli_execute_scsi(struct tw_osli_req_context *req,
   63         union ccb *ccb);
   64 
   65 
   66 
   67 /*
   68  * Function name:       tw_osli_cam_attach
   69  * Description:         Attaches the driver to CAM.
   70  *
   71  * Input:               sc      -- ptr to OSL internal ctlr context
   72  * Output:              None
   73  * Return value:        0       -- success
   74  *                      non-zero-- failure
   75  */
   76 TW_INT32
   77 tw_osli_cam_attach(struct twa_softc *sc)
   78 {
   79         struct cam_devq         *devq;
   80         struct ccb_setasync     csa;
   81         TW_INT32                error;
   82 
   83         tw_osli_dbg_dprintf(3, sc, "entered");
   84 
   85         /*
   86          * Create the device queue for our SIM.
   87          */
   88         if ((devq = cam_simq_alloc(TW_OSLI_MAX_NUM_IOS)) == NULL) {
   89                 tw_osli_printf(sc, "error = %d",
   90                         TW_CL_SEVERITY_ERROR_STRING,
   91                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
   92                         0x2100,
   93                         "Failed to create SIM device queue",
   94                         ENOMEM);
   95                 return(ENOMEM);
   96         }
   97 
   98         /*
   99          * Create a SIM entry.  Though we can support TW_OSLI_MAX_NUM_IOS
  100          * simultaneous requests, we claim to be able to handle only
  101          * (TW_OSLI_MAX_NUM_IOS - 1), so that we always have a request
  102          * packet available to service ioctls.
  103          */
  104         tw_osli_dbg_dprintf(3, sc, "Calling cam_sim_alloc");
  105         sc->sim = cam_sim_alloc(twa_action, twa_poll, "twa", sc,
  106                         device_get_unit(sc->bus_dev),
  107                         TW_OSLI_MAX_NUM_IOS - 1, 1, devq);
  108         if (sc->sim == NULL) {
  109                 cam_simq_free(devq);
  110                 tw_osli_printf(sc, "error = %d",
  111                         TW_CL_SEVERITY_ERROR_STRING,
  112                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  113                         0x2101,
  114                         "Failed to create a SIM entry",
  115                         ENOMEM);
  116                 return(ENOMEM);
  117         }
  118 
  119         /*
  120          * Register the bus.
  121          */
  122         tw_osli_dbg_dprintf(3, sc, "Calling xpt_bus_register");
  123         if (xpt_bus_register(sc->sim, 0) != CAM_SUCCESS) {
  124                 cam_sim_free(sc->sim, TRUE);
  125                 sc->sim = NULL; /* so cam_detach will not try to free it */
  126                 tw_osli_printf(sc, "error = %d",
  127                         TW_CL_SEVERITY_ERROR_STRING,
  128                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  129                         0x2102,
  130                         "Failed to register the bus",
  131                         ENXIO);
  132                 return(ENXIO);
  133         }
  134 
  135         tw_osli_dbg_dprintf(3, sc, "Calling xpt_create_path");
  136         if (xpt_create_path(&sc->path, NULL,
  137                                 cam_sim_path(sc->sim),
  138                                 CAM_TARGET_WILDCARD,
  139                                 CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
  140                 xpt_bus_deregister(cam_sim_path (sc->sim));
  141                 /* Passing TRUE to cam_sim_free will free the devq as well. */
  142                 cam_sim_free(sc->sim, TRUE);
  143                 tw_osli_printf(sc, "error = %d",
  144                         TW_CL_SEVERITY_ERROR_STRING,
  145                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  146                         0x2103,
  147                         "Failed to create path",
  148                         ENXIO);
  149                 return(ENXIO);
  150         }
  151 
  152         tw_osli_dbg_dprintf(3, sc, "Calling xpt_setup_ccb");
  153         xpt_setup_ccb(&csa.ccb_h, sc->path, 5);
  154         csa.ccb_h.func_code = XPT_SASYNC_CB;
  155         csa.event_enable = AC_FOUND_DEVICE | AC_LOST_DEVICE;
  156         csa.callback = twa_async;
  157         csa.callback_arg = sc;
  158         xpt_action((union ccb *)&csa);
  159 
  160         tw_osli_dbg_dprintf(3, sc, "Calling tw_osli_request_bus_scan");
  161         /*
  162          * Request a bus scan, so that CAM gets to know of
  163          * the logical units that we control.
  164          */
  165         if ((error = tw_osli_request_bus_scan(sc)))
  166                 tw_osli_printf(sc, "error = %d",
  167                         TW_CL_SEVERITY_ERROR_STRING,
  168                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  169                         0x2104,
  170                         "Bus scan request to CAM failed",
  171                         error);
  172         
  173         tw_osli_dbg_dprintf(3, sc, "exiting");
  174         return(0);
  175 }
  176 
  177 
  178 
  179 /*
  180  * Function name:       tw_osli_cam_detach
  181  * Description:         Detaches the driver from CAM.
  182  *
  183  * Input:               sc      -- ptr to OSL internal ctlr context
  184  * Output:              None
  185  * Return value:        None
  186  */
  187 TW_VOID
  188 tw_osli_cam_detach(struct twa_softc *sc)
  189 {
  190         tw_osli_dbg_dprintf(3, sc, "entered");
  191 
  192         mtx_lock(&Giant);
  193         if (sc->path)
  194                 xpt_free_path(sc->path);
  195         if (sc->sim) {
  196                 xpt_bus_deregister(cam_sim_path(sc->sim));
  197                 /* Passing TRUE to cam_sim_free will free the devq as well. */
  198                 cam_sim_free(sc->sim, TRUE);
  199         }
  200         mtx_unlock(&Giant);
  201 }
  202 
  203 
  204 
  205 /*
  206  * Function name:       tw_osli_execute_scsi
  207  * Description:         Build a fw cmd, based on a CAM style ccb, and
  208  *                      send it down.
  209  *
  210  * Input:               req     -- ptr to OSL internal request context
  211  *                      ccb     -- ptr to CAM style ccb
  212  * Output:              None
  213  * Return value:        0       -- success
  214  *                      non-zero-- failure
  215  */
  216 TW_INT32
  217 tw_osli_execute_scsi(struct tw_osli_req_context *req, union ccb *ccb)
  218 {
  219         struct twa_softc                *sc = req->ctlr;
  220         struct tw_cl_req_packet         *req_pkt;
  221         struct tw_cl_scsi_req_packet    *scsi_req;
  222         struct ccb_hdr                  *ccb_h = &(ccb->ccb_h);
  223         struct ccb_scsiio               *csio = &(ccb->csio);
  224         TW_INT32                        error;
  225 
  226         tw_osli_dbg_dprintf(10, sc, "SCSI I/O request 0x%x",
  227                 csio->cdb_io.cdb_bytes[0]);
  228 
  229         if (ccb_h->target_id >= TW_CL_MAX_NUM_UNITS) {
  230                 tw_osli_dbg_dprintf(3, sc, "Invalid target. PTL = %x %x %x",
  231                         ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
  232                 ccb_h->status |= CAM_TID_INVALID;
  233                 xpt_done(ccb);
  234                 return(1);
  235         }
  236         if (ccb_h->target_lun >= TW_CL_MAX_NUM_LUNS) {
  237                 tw_osli_dbg_dprintf(3, sc, "Invalid lun. PTL = %x %x %x",
  238                         ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
  239                 ccb_h->status |= CAM_LUN_INVALID;
  240                 xpt_done(ccb);
  241                 return(1);
  242         }
  243 
  244         if(ccb_h->flags & CAM_CDB_PHYS) {
  245                 tw_osli_printf(sc, "",
  246                         TW_CL_SEVERITY_ERROR_STRING,
  247                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  248                         0x2105,
  249                         "Physical CDB address!");
  250                 ccb_h->status = CAM_REQ_CMP_ERR;
  251                 xpt_done(ccb);
  252                 return(1);
  253         }
  254 
  255         /*
  256          * We are going to work on this request.  Mark it as enqueued (though
  257          * we don't actually queue it...)
  258          */
  259         ccb_h->status |= CAM_SIM_QUEUED;
  260 
  261         if((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
  262                 if(ccb_h->flags & CAM_DIR_IN)
  263                         req->flags |= TW_OSLI_REQ_FLAGS_DATA_IN;
  264                 else
  265                         req->flags |= TW_OSLI_REQ_FLAGS_DATA_OUT;
  266         }
  267 
  268         /* Build the CL understood request packet for SCSI cmds. */
  269         req_pkt = &req->req_pkt;
  270         req_pkt->status = 0;
  271         req_pkt->tw_osl_callback = tw_osl_complete_io;
  272         scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
  273         scsi_req->unit = ccb_h->target_id;
  274         scsi_req->lun = ccb_h->target_lun;
  275         scsi_req->sense_len = 0;
  276         scsi_req->sense_data = (TW_UINT8 *)(&csio->sense_data);
  277         scsi_req->scsi_status = 0;
  278         if(ccb_h->flags & CAM_CDB_POINTER)
  279                 scsi_req->cdb = csio->cdb_io.cdb_ptr;
  280         else
  281                 scsi_req->cdb = csio->cdb_io.cdb_bytes;
  282         scsi_req->cdb_len = csio->cdb_len;
  283 
  284         if (!(ccb_h->flags & CAM_DATA_PHYS)) {
  285                 /* Virtual data addresses.  Need to convert them... */
  286                 tw_osli_dbg_dprintf(3, sc,
  287                         "XPT_SCSI_IO: Single virtual address!");
  288                 if (!(ccb_h->flags & CAM_SCATTER_VALID)) {
  289                         if (csio->dxfer_len > TW_CL_MAX_IO_SIZE) {
  290                                 tw_osli_printf(sc, "size = %d",
  291                                         TW_CL_SEVERITY_ERROR_STRING,
  292                                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  293                                         0x2106,
  294                                         "I/O size too big",
  295                                         csio->dxfer_len);
  296                                 ccb_h->status = CAM_REQ_TOO_BIG;
  297                                 xpt_done(ccb);
  298                                 return(1);
  299                         }
  300 
  301                         if ((req->length = csio->dxfer_len)) {
  302                                 req->data = csio->data_ptr;
  303                                 scsi_req->sgl_entries = 1;
  304                         }
  305                 } else {
  306                         tw_osli_printf(sc, "",
  307                                 TW_CL_SEVERITY_ERROR_STRING,
  308                                 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  309                                 0x2107,
  310                                 "XPT_SCSI_IO: Got SGList");
  311                         ccb_h->status = CAM_REQ_CMP_ERR;
  312                         xpt_done(ccb);
  313                         return(1);
  314                 }
  315         } else {
  316                 /* Data addresses are physical. */
  317                 tw_osli_printf(sc, "",
  318                         TW_CL_SEVERITY_ERROR_STRING,
  319                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  320                         0x2108,
  321                         "XPT_SCSI_IO: Physical data addresses");
  322                 ccb_h->status = CAM_REQ_CMP_ERR;
  323                 ccb_h->status |= CAM_RELEASE_SIMQ;
  324                 ccb_h->status &= ~CAM_SIM_QUEUED;
  325                 xpt_done(ccb);
  326                 return(1);
  327         }
  328 
  329         ccb_h->timeout_ch = timeout(twa_timeout, req,
  330                 (ccb_h->timeout * hz) / 1000);
  331         /*
  332          * twa_map_load_data_callback will fill in the SGL,
  333          * and submit the I/O.
  334          */
  335         error = tw_osli_map_request(req);
  336         return(error);
  337 }
  338 
  339 
  340 
  341 /*
  342  * Function name:       twa_action
  343  * Description:         Driver entry point for CAM's use.
  344  *
  345  * Input:               sim     -- sim corresponding to the ctlr
  346  *                      ccb     -- ptr to CAM request
  347  * Output:              None
  348  * Return value:        None
  349  */
  350 TW_VOID
  351 twa_action(struct cam_sim *sim, union ccb *ccb)
  352 {
  353         struct twa_softc        *sc = (struct twa_softc *)cam_sim_softc(sim);
  354         struct ccb_hdr          *ccb_h = &(ccb->ccb_h);
  355 
  356         switch (ccb_h->func_code) {
  357         case XPT_SCSI_IO:       /* SCSI I/O */
  358         {
  359                 struct tw_osli_req_context      *req;
  360 
  361                 if ((sc->state & TW_OSLI_CTLR_STATE_SIMQ_FROZEN) ||
  362                                 ((req = tw_osli_get_request(sc)) == NULL)) {
  363                         tw_osli_dbg_dprintf(2, sc,
  364                                 "simq frozen/Cannot get request pkt.");
  365                         /*
  366                          * Freeze the simq to maintain ccb ordering.  The next
  367                          * ccb that gets completed will unfreeze the simq.
  368                          */
  369                         tw_osli_disallow_new_requests(sc);
  370                         ccb_h->status |= CAM_REQUEUE_REQ;
  371                         xpt_done(ccb);
  372                         break;
  373                 }
  374                 req->req_handle.osl_req_ctxt = req;
  375                 req->orig_req = ccb;
  376                 if (tw_osli_execute_scsi(req, ccb))
  377                         tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
  378                 break;
  379         }
  380 
  381         case XPT_ABORT:
  382                 tw_osli_dbg_dprintf(2, sc, "Abort request.");
  383                 ccb_h->status = CAM_UA_ABORT;
  384                 xpt_done(ccb);
  385                 break;
  386 
  387         case XPT_RESET_BUS:
  388                 tw_cl_create_event(&(sc->ctlr_handle), TW_CL_TRUE,
  389                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  390                         0x2108, 0x3, TW_CL_SEVERITY_INFO_STRING,
  391                         "Received Reset Bus request from CAM",
  392                         " ");
  393 
  394                 if (tw_cl_reset_ctlr(&sc->ctlr_handle)) {
  395                         tw_cl_create_event(&(sc->ctlr_handle), TW_CL_TRUE,
  396                                 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  397                                 0x2109, 0x1, TW_CL_SEVERITY_ERROR_STRING,
  398                                 "Failed to reset bus",
  399                                 " ");
  400                         ccb_h->status = CAM_REQ_CMP_ERR;
  401                 }
  402                 else
  403                         ccb_h->status = CAM_REQ_CMP;
  404 
  405                 xpt_done(ccb);
  406                 break;
  407 
  408         case XPT_SET_TRAN_SETTINGS:
  409                 tw_osli_dbg_dprintf(3, sc, "XPT_SET_TRAN_SETTINGS");
  410 
  411                 /*
  412                  * This command is not supported, since it's very specific
  413                  * to SCSI, and we are doing ATA.
  414                  */
  415                 ccb_h->status = CAM_FUNC_NOTAVAIL;
  416                 xpt_done(ccb);
  417                 break;
  418 
  419         case XPT_GET_TRAN_SETTINGS: 
  420         {
  421                 struct ccb_trans_settings       *cts = &ccb->cts;
  422 
  423                 tw_osli_dbg_dprintf(3, sc, "XPT_GET_TRAN_SETTINGS");
  424                 cts->valid = (CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID);
  425                 cts->flags &= ~(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB);
  426                 ccb_h->status = CAM_REQ_CMP;
  427                 xpt_done(ccb);
  428                 break;
  429         }
  430 
  431         case XPT_CALC_GEOMETRY:
  432                 tw_osli_dbg_dprintf(3, sc, "XPT_CALC_GEOMETRY");
  433                 cam_calc_geometry(&ccb->ccg, 1/* extended */);
  434                 xpt_done(ccb);
  435                 break;
  436 
  437         case XPT_PATH_INQ:    /* Path inquiry -- get twa properties */
  438         {
  439                 struct ccb_pathinq      *path_inq = &ccb->cpi;
  440 
  441                 tw_osli_dbg_dprintf(3, sc, "XPT_PATH_INQ request");
  442 
  443                 path_inq->version_num = 1;
  444                 path_inq->hba_inquiry = 0;
  445                 path_inq->target_sprt = 0;
  446                 path_inq->hba_misc = 0;
  447                 path_inq->hba_eng_cnt = 0;
  448                 path_inq->max_target = TW_CL_MAX_NUM_UNITS;
  449                 path_inq->max_lun = TW_CL_MAX_NUM_LUNS - 1;
  450                 path_inq->unit_number = cam_sim_unit(sim);
  451                 path_inq->bus_id = cam_sim_bus(sim);
  452                 path_inq->initiator_id = 12;
  453                 path_inq->base_transfer_speed = 100000;
  454                 strncpy(path_inq->sim_vid, "FreeBSD", SIM_IDLEN);
  455                 strncpy(path_inq->hba_vid, "3ware", HBA_IDLEN);
  456                 strncpy(path_inq->dev_name, cam_sim_name(sim), DEV_IDLEN);
  457                 ccb_h->status = CAM_REQ_CMP;
  458                 xpt_done(ccb);
  459                 break;
  460         }
  461 
  462         default:
  463                 tw_osli_dbg_dprintf(3, sc, "func_code = %x", ccb_h->func_code);
  464                 ccb_h->status = CAM_REQ_INVALID;
  465                 xpt_done(ccb);
  466                 break;
  467         }
  468 }
  469 
  470 
  471 
  472 /*
  473  * Function name:       twa_poll
  474  * Description:         Driver entry point called when interrupts are not
  475  *                      available.
  476  *
  477  * Input:               sim     -- sim corresponding to the controller
  478  * Output:              None
  479  * Return value:        None
  480  */
  481 TW_VOID
  482 twa_poll(struct cam_sim *sim)
  483 {
  484         struct twa_softc *sc = (struct twa_softc *)(cam_sim_softc(sim));
  485 
  486         tw_osli_dbg_dprintf(3, sc, "entering; sc = %p", sc);
  487         /*
  488          * It's been observed that twa_poll can get called (from
  489          * dashutdown --> xpt_polled_action) even when interrupts are
  490          * active, in which case, the ISR might clear the interrupt,
  491          * leaving the call to tw_cl_interrupt below, no way of determining
  492          * that the response from firmware is ready, resulting in
  493          * tw_cl_deferred_interrupt never getting called.  To cover this case,
  494          * we will make the call to tw_cl_deferred_interrupt not dependent
  495          * on the return value from tw_cl_interrupt.
  496          */
  497         tw_cl_interrupt(&(sc->ctlr_handle));
  498         tw_cl_deferred_interrupt(&(sc->ctlr_handle));
  499         tw_osli_dbg_dprintf(3, sc, "exiting; sc = %p", sc);
  500 }
  501 
  502 
  503 
  504 /*
  505  * Function name:       twa_async
  506  * Description:         Driver entry point for CAM to notify driver of special
  507  *                      events.  We don't use this for now.
  508  *
  509  * Input:               callback_arg    -- ptr to per ctlr structure
  510  *                      code            -- code associated with the event
  511  *                      path            -- cam path
  512  *                      arg             -- 
  513  * Output:              None
  514  * Return value:        0       -- success
  515  *                      non-zero-- failure
  516  */
  517 TW_VOID
  518 twa_async(TW_VOID *callback_arg, TW_UINT32 code, 
  519         struct cam_path *path, TW_VOID *arg)
  520 {
  521 #ifdef TW_OSL_DEBUG
  522         struct twa_softc *sc = (struct twa_softc *)callback_arg;
  523 #endif /* TW_OSL_DEBUG */
  524 
  525         tw_osli_dbg_dprintf(3, sc, "sc = %p, code = %x, path = %p, arg = %p",
  526                 sc, code, path, arg);
  527 }
  528 
  529 
  530 
  531 /*
  532  * Function name:       twa_timeout
  533  * Description:         Driver entry point for being alerted on a request
  534  *                      timing out.
  535  *
  536  * Input:               arg     -- ptr to timed out request
  537  * Output:              None
  538  * Return value:        None
  539  */
  540 static TW_VOID
  541 twa_timeout(TW_VOID *arg)
  542 {
  543         struct tw_osli_req_context      *req =
  544                 (struct tw_osli_req_context *)arg;
  545 
  546         tw_cl_create_event(&(req->ctlr->ctlr_handle), TW_CL_TRUE,
  547                 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  548                 0x210B, 0x1, TW_CL_SEVERITY_ERROR_STRING,
  549                 "Request timed out!",
  550                 "request = %p", req);
  551         tw_cl_reset_ctlr(&(req->ctlr->ctlr_handle));
  552 }
  553 
  554 
  555 
  556 /*
  557  * Function name:       tw_osli_request_bus_scan
  558  * Description:         Requests CAM for a scan of the bus.
  559  *
  560  * Input:               sc      -- ptr to per ctlr structure
  561  * Output:              None
  562  * Return value:        0       -- success
  563  *                      non-zero-- failure
  564  */
  565 TW_INT32
  566 tw_osli_request_bus_scan(struct twa_softc *sc)
  567 {
  568         struct cam_path *path;
  569         union ccb       *ccb;
  570 
  571         tw_osli_dbg_dprintf(3, sc, "entering");
  572 
  573         if ((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK)) == NULL)
  574                 return(ENOMEM);
  575         bzero(ccb, sizeof(union ccb));
  576         mtx_lock(&Giant);
  577         if (xpt_create_path(&path, xpt_periph, cam_sim_path(sc->sim),
  578                 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP)
  579                 return(EIO);
  580 
  581         xpt_setup_ccb(&ccb->ccb_h, path, 5);
  582         ccb->ccb_h.func_code = XPT_SCAN_BUS;
  583         ccb->ccb_h.cbfcnp = twa_bus_scan_cb;
  584         ccb->crcn.flags = CAM_FLAG_NONE;
  585         xpt_action(ccb);
  586         mtx_unlock(&Giant);
  587         return(0);
  588 }
  589 
  590 
  591 
  592 /*
  593  * Function name:       twa_bus_scan_cb
  594  * Description:         Callback from CAM on a bus scan request.
  595  *
  596  * Input:               periph  -- we don't use this
  597  *                      ccb     -- bus scan request ccb that we sent to CAM
  598  * Output:              None
  599  * Return value:        None
  600  */
  601 static TW_VOID
  602 twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb)
  603 {
  604         tw_osli_dbg_printf(3, "entering");
  605 
  606         if (ccb->ccb_h.status != CAM_REQ_CMP)
  607                 printf("cam_scan_callback: failure status = %x\n",
  608                         ccb->ccb_h.status);
  609         else
  610                 tw_osli_dbg_printf(3, "success");
  611 
  612         xpt_free_path(ccb->ccb_h.path);
  613         free(ccb, M_TEMP);
  614 }
  615 
  616 
  617 
  618 /*
  619  * Function name:       tw_osli_allow_new_requests
  620  * Description:         Sets the appropriate status bits in a ccb such that,
  621  *                      when the ccb is completed by a call to xpt_done,
  622  *                      CAM knows that it's ok to unfreeze the flow of new
  623  *                      requests to this controller, if the flow is frozen.
  624  *
  625  * Input:               sc      -- ptr to OSL internal ctlr context
  626  *                      ccb     -- ptr to CAM request
  627  * Output:              None
  628  * Return value:        None
  629  */
  630 TW_VOID
  631 tw_osli_allow_new_requests(struct twa_softc *sc, TW_VOID *ccb)
  632 {
  633         ((union ccb *)(ccb))->ccb_h.status |= CAM_RELEASE_SIMQ;
  634         sc->state &= ~TW_OSLI_CTLR_STATE_SIMQ_FROZEN;
  635 }
  636 
  637 
  638 
  639 /*
  640  * Function name:       tw_osli_disallow_new_requests
  641  * Description:         Calls the appropriate CAM function, so as to freeze
  642  *                      the flow of new requests from CAM to this controller.
  643  *
  644  * Input:               sc      -- ptr to OSL internal ctlr context
  645  * Output:              None
  646  * Return value:        None
  647  */
  648 TW_VOID
  649 tw_osli_disallow_new_requests(struct twa_softc *sc)
  650 {
  651         xpt_freeze_simq(sc->sim, 1);
  652         sc->state |= TW_OSLI_CTLR_STATE_SIMQ_FROZEN;
  653 }
  654 
  655 
  656 
  657 /*
  658  * Function name:       tw_osl_scan_bus
  659  * Description:         CL calls this function to request for a bus scan.
  660  *
  661  * Input:               ctlr_handle     -- ptr to controller handle
  662  * Output:              None
  663  * Return value:        None
  664  */
  665 TW_VOID
  666 tw_osl_scan_bus(struct tw_cl_ctlr_handle *ctlr_handle)
  667 {
  668         struct twa_softc        *sc = ctlr_handle->osl_ctlr_ctxt;
  669         TW_INT32                error;
  670 
  671         if ((error = tw_osli_request_bus_scan(sc)))
  672                 tw_osli_printf(sc, "error = %d",
  673                         TW_CL_SEVERITY_ERROR_STRING,
  674                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  675                         0x2109,
  676                         "Bus scan request to CAM failed",
  677                         error);
  678 }
  679 
  680 
  681 
  682 /*
  683  * Function name:       tw_osl_complete_io
  684  * Description:         Called to complete CAM scsi requests.
  685  *
  686  * Input:               req_handle      -- ptr to request handle
  687  * Output:              None
  688  * Return value:        None
  689  */
  690 TW_VOID
  691 tw_osl_complete_io(struct tw_cl_req_handle *req_handle)
  692 {
  693         struct tw_osli_req_context      *req = req_handle->osl_req_ctxt;
  694         struct tw_cl_req_packet         *req_pkt =
  695                 (struct tw_cl_req_packet *)(&req->req_pkt);
  696         struct tw_cl_scsi_req_packet    *scsi_req;
  697         struct twa_softc                *sc = req->ctlr;
  698         union ccb                       *ccb = (union ccb *)(req->orig_req);
  699 
  700         tw_osli_dbg_dprintf(10, sc, "entering");
  701 
  702         if (req->state != TW_OSLI_REQ_STATE_BUSY)
  703                 tw_osli_printf(sc, "request = %p, status = %d",
  704                         TW_CL_SEVERITY_ERROR_STRING,
  705                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
  706                         0x210A,
  707                         "Unposted command completed!!",
  708                         req, req->state);
  709 
  710         /*
  711          * Remove request from the busy queue.  Just mark it complete.
  712          * There's no need to move it into the complete queue as we are
  713          * going to be done with it right now.
  714          */
  715         req->state = TW_OSLI_REQ_STATE_COMPLETE;
  716         tw_osli_req_q_remove_item(req, TW_OSLI_BUSY_Q);
  717 
  718         tw_osli_unmap_request(req);
  719 
  720         untimeout(twa_timeout, req, ccb->ccb_h.timeout_ch);
  721         if (req->error_code) {
  722                 /* This request never got submitted to the firmware. */
  723                 if (req->error_code == EBUSY) {
  724                         /*
  725                          * Cmd queue is full, or common layer is out
  726                          * of resources.  Freeze the simq to maintain
  727                          * ccb ordering.  The next ccb that gets
  728                          * completed will unfreeze the simq.
  729                          */
  730                         tw_osli_disallow_new_requests(req->ctlr);
  731                         ccb->ccb_h.status |= CAM_REQUEUE_REQ;
  732                 }
  733                 else if (req->error_code == EFBIG)
  734                         ccb->ccb_h.status = CAM_REQ_TOO_BIG;
  735                 else
  736                         ccb->ccb_h.status = CAM_REQ_CMP_ERR;
  737         } else {
  738                 scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
  739                 if (req_pkt->status == TW_CL_ERR_REQ_SUCCESS)
  740                         ccb->ccb_h.status = CAM_REQ_CMP;
  741                 else {
  742                         if (req_pkt->status & TW_CL_ERR_REQ_INVALID_TARGET)
  743                                 ccb->ccb_h.status |= CAM_TID_INVALID;
  744                         else if (req_pkt->status & TW_CL_ERR_REQ_INVALID_LUN)
  745                                 ccb->ccb_h.status |= CAM_LUN_INVALID;
  746                         else if (req_pkt->status & TW_CL_ERR_REQ_SCSI_ERROR)
  747                                 ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
  748                         else if (req_pkt->status & TW_CL_ERR_REQ_BUS_RESET)
  749                                 ccb->ccb_h.status |= CAM_SCSI_BUS_RESET;
  750                         /*
  751                          * If none of the above errors occurred, simply
  752                          * mark completion error.
  753                          */
  754                         if (ccb->ccb_h.status == 0)
  755                                 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
  756 
  757                         if (req_pkt->status & TW_CL_ERR_REQ_AUTO_SENSE_VALID) {
  758                                 ccb->csio.sense_len = scsi_req->sense_len;
  759                                 ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
  760                         }
  761                 }
  762 
  763                 ccb->csio.scsi_status = scsi_req->scsi_status;
  764                 /* If simq is frozen, unfreeze it. */
  765                 if (sc->state & TW_OSLI_CTLR_STATE_SIMQ_FROZEN)
  766                         tw_osli_allow_new_requests(sc, (TW_VOID *)ccb);
  767         }
  768 
  769         ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
  770         xpt_done(ccb);
  771         if (! req->error_code)
  772                  /* twa_action will free the request otherwise */
  773                 tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
  774 }
  775 

Cache object: eb801427f0271c78a10ea3b3446c10b1


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