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

Cache object: b2aff3650565451287bfa422124a75e7


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