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

Cache object: 68d49e7ed7dd651a202058eb3f38f894


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