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/twa_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) 2003-04 3ware, Inc.
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  *      $FreeBSD$
   27  */
   28 
   29 /*
   30  * 3ware driver for 9000 series storage controllers.
   31  *
   32  * Author: Vinod Kashyap
   33  */
   34 
   35 
   36 #include <dev/twa/twa_includes.h>
   37 
   38 #include <cam/cam.h>
   39 #include <cam/cam_ccb.h>
   40 #include <cam/cam_sim.h>
   41 #include <cam/cam_xpt_sim.h>
   42 #include <cam/cam_xpt_periph.h>
   43 #include <cam/cam_debug.h>
   44 #include <cam/cam_periph.h>
   45 
   46 #include <cam/scsi/scsi_all.h>
   47 #include <cam/scsi/scsi_message.h>
   48 
   49 static int      twa_execute_scsi(struct twa_request *tr, union ccb *ccb);
   50 static void     twa_action(struct cam_sim *sim, union ccb *ccb);
   51 static void     twa_poll(struct cam_sim *sim);
   52 static void     twa_async(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg);
   53 static void     twa_timeout(void *arg);
   54 static void     twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb);
   55 
   56 
   57 
   58 /*
   59  * Function name:       twa_cam_setup
   60  * Description:         Attaches the driver to CAM.
   61  *
   62  * Input:               sc      -- ptr to per ctlr structure
   63  * Output:              None
   64  * Return value:        0       -- success
   65  *                      non-zero-- failure
   66  */
   67 int
   68 twa_cam_setup(struct twa_softc *sc)
   69 {
   70         struct cam_devq         *devq;
   71         struct ccb_setasync     csa;
   72 
   73         twa_dbg_dprint(3, sc, "sc = %p", sc);
   74         /*
   75          * Create the device queue for our SIM.
   76          */
   77         devq = cam_simq_alloc(TWA_Q_LENGTH);
   78         if (devq == NULL)
   79                 return(ENOMEM);
   80 
   81         /*
   82          * Create a SIM entry.  Though we can support TWA_Q_LENGTH simultaneous
   83          * requests, we claim to be able to handle only (TWA_Q_LENGTH - 1), so
   84          * that we always have a request packet available to service attention
   85          * interrupts.
   86          */
   87         twa_dbg_dprint(3, sc, "Calling cam_sim_alloc");
   88         sc->twa_sim = cam_sim_alloc(twa_action, twa_poll, "twa", sc,
   89                                         device_get_unit(sc->twa_bus_dev),
   90                                         TWA_Q_LENGTH - 1, 1, devq);
   91         if (sc->twa_sim == NULL) {
   92                 cam_simq_free(devq);
   93                 return(ENOMEM);
   94         }
   95 
   96         /*
   97          * Register the bus.
   98          */
   99         twa_dbg_dprint(3, sc, "Calling xpt_bus_register");
  100         if (xpt_bus_register(sc->twa_sim, 0) != CAM_SUCCESS) {
  101                 cam_sim_free(sc->twa_sim, TRUE);
  102                 sc->twa_sim = NULL; /* so twa_cam_detach will not try to free it */
  103                 return(ENXIO);
  104         }
  105 
  106         twa_dbg_dprint(3, sc, "Calling xpt_create_path");
  107         if (xpt_create_path(&sc->twa_path, NULL,
  108                                 cam_sim_path(sc->twa_sim),
  109                                 CAM_TARGET_WILDCARD,
  110                                 CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
  111                 xpt_bus_deregister(cam_sim_path (sc->twa_sim));
  112                 cam_sim_free(sc->twa_sim, TRUE); /* passing TRUE will free the devq as well */
  113                 return(ENXIO);
  114         }
  115 
  116         twa_dbg_dprint(3, sc, "Calling xpt_setup_ccb");
  117         xpt_setup_ccb(&csa.ccb_h, sc->twa_path, 5);
  118         csa.ccb_h.func_code = XPT_SASYNC_CB;
  119         csa.event_enable = AC_FOUND_DEVICE | AC_LOST_DEVICE;
  120         csa.callback = twa_async;
  121         csa.callback_arg = sc;
  122         xpt_action((union ccb *)&csa);
  123 
  124         twa_dbg_dprint(3, sc, "Calling twa_request_bus_scan");
  125         /*
  126          * Request a bus scan, so that CAM gets to know of
  127          * the logical units that we control.
  128          */
  129         twa_request_bus_scan(sc);
  130         twa_dbg_dprint(3, sc, "Exiting");
  131         return(0);
  132 }
  133 
  134 
  135 
  136 /*
  137  * Function name:       twa_cam_detach
  138  * Description:         Detaches the driver from CAM.
  139  *
  140  * Input:               sc      -- ptr to per ctlr structure
  141  * Output:              None
  142  * Return value:        None
  143  */
  144 void
  145 twa_cam_detach(struct twa_softc *sc)
  146 {
  147         if (sc->twa_path)
  148                 xpt_free_path(sc->twa_path);
  149         if (sc->twa_sim) {
  150                 xpt_bus_deregister(cam_sim_path(sc->twa_sim));
  151                 cam_sim_free(sc->twa_sim, TRUE); /* passing TRUE will free the devq as well */
  152         }
  153 }
  154 
  155 
  156 
  157 /*
  158  * Function name:       twa_send_scsi_cmd
  159  * Description:         Sends down a scsi cmd to fw.
  160  *
  161  * Input:               tr      -- ptr to request pkt
  162  *                      cmd     -- opcode of scsi cmd to send
  163  * Output:              None
  164  * Return value:        0       -- success
  165  *                      non-zero-- failure
  166  */
  167 int
  168 twa_send_scsi_cmd(struct twa_request *tr, int cmd)
  169 {
  170         union ccb       ccb;
  171 
  172         bzero(&ccb, sizeof(union ccb));
  173         ccb.csio.cdb_io.cdb_bytes[0] = (u_int8_t)cmd;
  174         ccb.csio.cdb_io.cdb_bytes[4] = 128;
  175         ccb.csio.cdb_len = 16;
  176         if ((ccb.csio.data_ptr = malloc(TWA_SECTOR_SIZE, M_DEVBUF, M_NOWAIT))
  177                                         == NULL)
  178                 return(ENOMEM);
  179         bzero(ccb.csio.data_ptr, TWA_SECTOR_SIZE);
  180         ccb.csio.dxfer_len = TWA_SECTOR_SIZE;
  181 
  182         ccb.ccb_h.target_id = 0;
  183         ccb.ccb_h.flags |= CAM_DIR_IN;
  184 
  185         if (twa_execute_scsi(tr, &ccb))
  186                 return(EIO);
  187         return(0);
  188 }
  189 
  190 
  191 
  192 /*
  193  * Function name:       twa_execute_scsi
  194  * Description:         Build a fw cmd, based on a CAM style ccb, and
  195  *                      send it down.
  196  *
  197  * Input:               tr      -- ptr to request pkt
  198  *                      ccb     -- ptr to CAM style ccb
  199  * Output:              None
  200  * Return value:        0       -- success
  201  *                      non-zero-- failure
  202  */
  203 int
  204 twa_execute_scsi(struct twa_request *tr, union ccb *ccb)
  205 {
  206         struct twa_softc                *sc = tr->tr_sc;
  207         struct twa_command_packet       *cmdpkt;
  208         struct twa_command_9k           *cmd9k;
  209         struct ccb_hdr                  *ccb_h = &(ccb->ccb_h);
  210         struct ccb_scsiio               *csio = &(ccb->csio);
  211         int                             error;
  212 
  213         twa_dbg_dprint(3, sc, "SCSI I/O request 0x%x", 
  214                                 csio->cdb_io.cdb_bytes[0]);
  215 
  216         if (ccb_h->target_id >= TWA_MAX_UNITS) {
  217                 twa_dbg_dprint(3, sc, "Invalid target. PTL = %x %x %x",
  218                         ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
  219                 ccb_h->status |= CAM_TID_INVALID;
  220                 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL)
  221                         xpt_done(ccb);
  222                 return(1);
  223         }
  224         if (ccb_h->target_lun != 0) {
  225                 twa_dbg_dprint(3, sc, "Invalid lun. PTL = %x %x %x",
  226                         ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
  227                 ccb_h->status |= CAM_LUN_INVALID;
  228                 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL)
  229                         xpt_done(ccb);
  230                 return(1);
  231         }
  232 
  233         if(ccb_h->flags & CAM_CDB_PHYS) {
  234                 twa_printf(sc, "Physical CDB address!\n");
  235                 ccb_h->status = CAM_REQ_CMP_ERR;
  236                 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL)
  237                         xpt_done(ccb);
  238                 return(1);
  239         }
  240 
  241         /*
  242          * We are going to work on this request.  Mark it as enqueued (though
  243          * we don't actually queue it...)
  244          */
  245         ccb_h->status |= CAM_SIM_QUEUED;
  246 
  247         if((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
  248                 if(ccb_h->flags & CAM_DIR_IN)
  249                         tr->tr_flags |= TWA_CMD_DATA_IN;
  250                 else
  251                         tr->tr_flags |= TWA_CMD_DATA_OUT;
  252         }
  253 
  254         cmdpkt = tr->tr_command;
  255 
  256         cmdpkt->cmd_hdr.header_desc.size_header = 128;
  257                 
  258         cmd9k = &(cmdpkt->command.cmd_pkt_9k);
  259         cmd9k->command.opcode = TWA_OP_EXECUTE_SCSI_COMMAND;
  260         cmd9k->unit = ccb_h->target_id;
  261         cmd9k->request_id = tr->tr_request_id;
  262         cmd9k->status = 0;
  263         cmd9k->sgl_offset = 16; /* offset from end of hdr = max cdb len */
  264 
  265         if(ccb_h->flags & CAM_CDB_POINTER)
  266                 bcopy(csio->cdb_io.cdb_ptr, cmd9k->cdb, csio->cdb_len);
  267         else
  268                 bcopy(csio->cdb_io.cdb_bytes, cmd9k->cdb, csio->cdb_len);
  269 
  270         if (!(ccb_h->flags & CAM_DATA_PHYS)) {
  271                 /* Virtual data addresses.  Need to convert them... */
  272                 twa_dbg_dprint(3, sc, "XPT_SCSI_IO: Single virtual address!");
  273                 if (!(ccb_h->flags & CAM_SCATTER_VALID)) {
  274                         if (csio->dxfer_len > TWA_MAX_IO_SIZE) {
  275                                 twa_printf(sc, "I/O size %d too big.\n",
  276                                                         csio->dxfer_len);
  277                                 ccb_h->status = CAM_REQ_TOO_BIG;
  278                                 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL)
  279                                         xpt_done(ccb);
  280                                 return(1);
  281                         }
  282 
  283                         if ((tr->tr_length = csio->dxfer_len)) {
  284                                 tr->tr_data = csio->data_ptr;
  285                                 cmd9k->sgl_entries = 1;
  286                         }
  287                 } else {
  288                         twa_printf(sc, "twa_execute_scsi: XPT_SCSI_IO: Got SGList!\n");
  289                         ccb_h->status = CAM_REQ_CMP_ERR;
  290                         if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL) {
  291                                 xpt_done(ccb);
  292                         }
  293                         return(1);
  294                 }
  295         } else {
  296                 /* Data addresses are physical. */
  297                 twa_printf(sc, "twa_execute_scsi: XPT_SCSI_IO: Physical data addresses!\n");
  298                 ccb_h->status = CAM_REQ_CMP_ERR;
  299                 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL) {
  300                         ccb_h->status |= CAM_RELEASE_SIMQ;
  301                         ccb_h->status &= ~CAM_SIM_QUEUED;
  302                         xpt_done(ccb);
  303                 }
  304                 return(1);
  305         }
  306 
  307         tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_9K;
  308 
  309         twa_set_timer(tr);
  310 
  311         /* twa_setup_data_dmamap will fill in the SGL, and submit the I/O. */
  312         error = twa_map_request(tr);
  313         return(error);
  314 }
  315 
  316 
  317 
  318 /*
  319  * Function name:       twa_action
  320  * Description:         Driver entry point for CAM's use.
  321  *
  322  * Input:               sim     -- sim corresponding to the ctlr
  323  *                      ccb     -- ptr to CAM request
  324  * Output:              None
  325  * Return value:        None
  326  */
  327 void
  328 twa_action(struct cam_sim *sim, union ccb *ccb)
  329 {
  330         struct twa_softc        *sc = (struct twa_softc *)cam_sim_softc(sim);
  331         struct ccb_hdr          *ccb_h = &(ccb->ccb_h);
  332 
  333         switch (ccb_h->func_code) {
  334         case XPT_SCSI_IO:       /* SCSI I/O */
  335         {
  336                 struct twa_request      *tr;
  337 
  338                 if ((sc->twa_state & TWA_STATE_SIMQ_FROZEN) ||
  339                                 ((tr = twa_get_request(sc)) == NULL)) {
  340                         twa_dbg_dprint(2, sc, "simq frozen/Cannot get request pkt.");
  341                         /*
  342                          * Freeze the simq to maintain ccb ordering.  The next
  343                          * ccb that gets completed will unfreeze the simq.
  344                          */
  345                         twa_disallow_new_requests(sc);
  346                         ccb_h->status |= CAM_REQUEUE_REQ;
  347                         xpt_done(ccb);
  348                         break;
  349                 }
  350                 tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_EXTERNAL;
  351                 tr->tr_private = ccb;
  352                 tr->tr_callback = twa_complete_io;
  353                 if (twa_execute_scsi(tr, ccb))
  354                         twa_release_request(tr);
  355                 break;
  356         }
  357 
  358         case XPT_ABORT:
  359                 twa_dbg_dprint(2, sc, "Abort request");
  360                 ccb_h->status = CAM_UA_ABORT;
  361                 xpt_done(ccb);
  362                 break;
  363 
  364         case XPT_RESET_BUS:
  365                 twa_printf(sc, "Reset Bus request from CAM...\n");
  366                 if (twa_reset(sc)) {
  367                         twa_printf(sc, "Reset Bus failed!\n");
  368                         ccb_h->status = CAM_REQ_CMP_ERR;
  369                 }
  370                 else
  371                         ccb_h->status = CAM_REQ_CMP;
  372 
  373                 xpt_done(ccb);
  374                 break;
  375 
  376         case XPT_SET_TRAN_SETTINGS:
  377                 twa_dbg_dprint(3, sc, "XPT_SET_TRAN_SETTINGS");
  378 
  379                 /*
  380                  * This command is not supported, since it's very specific
  381                  * to SCSI, and we are doing ATA.
  382                  */
  383                 ccb_h->status = CAM_FUNC_NOTAVAIL;
  384                 xpt_done(ccb);
  385                 break;
  386 
  387         case XPT_GET_TRAN_SETTINGS: 
  388         {
  389                 struct ccb_trans_settings       *cts = &ccb->cts;
  390 
  391                 twa_dbg_dprint(3, sc, "XPT_GET_TRAN_SETTINGS");
  392                 cts->valid = (CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID);
  393                 cts->flags &= ~(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB);
  394                 ccb_h->status = CAM_REQ_CMP;
  395                 xpt_done(ccb);
  396                 break;
  397         }
  398 
  399         case XPT_CALC_GEOMETRY:
  400         {
  401                 struct ccb_calc_geometry        *geom;
  402 
  403                 twa_dbg_dprint(3, sc, "XPT_CALC_GEOMETRY request");
  404                 geom = &ccb->ccg;
  405 
  406                 if (geom->volume_size > 0x200000) /* 1 GB */ {
  407                         geom->heads = 255;
  408                         geom->secs_per_track = 63;
  409                 } else {
  410                         geom->heads = 64;
  411                         geom->secs_per_track = 32;
  412                 }
  413                 geom->cylinders = geom->volume_size /
  414                                         (geom->heads * geom->secs_per_track);
  415                 ccb_h->status = CAM_REQ_CMP;
  416                 xpt_done(ccb);
  417                 break;
  418         }
  419 
  420         case XPT_PATH_INQ:    /* Path inquiry -- get twa properties */
  421         {
  422                 struct ccb_pathinq      *path_inq = &ccb->cpi;
  423 
  424                 twa_dbg_dprint(3, sc, "XPT_PATH_INQ request");
  425 
  426                 path_inq->version_num = 1;
  427                 path_inq->hba_inquiry = PI_WIDE_16;
  428                 path_inq->target_sprt = 0;
  429                 path_inq->hba_misc |= PIM_NOBUSRESET;
  430                 path_inq->hba_eng_cnt = 0;
  431                 path_inq->max_target = TWA_MAX_UNITS;
  432                 path_inq->max_lun = 0;
  433                 path_inq->unit_number = cam_sim_unit(sim);
  434                 path_inq->bus_id = cam_sim_bus(sim);
  435                 path_inq->initiator_id = 12;
  436                 path_inq->base_transfer_speed = 100000;
  437                 strncpy(path_inq->sim_vid, "FreeBSD", SIM_IDLEN);
  438                 strncpy(path_inq->hba_vid, "3ware", HBA_IDLEN);
  439                 strncpy(path_inq->dev_name, cam_sim_name(sim), DEV_IDLEN);
  440                 ccb_h->status = CAM_REQ_CMP;
  441                 xpt_done(ccb);
  442                 break;
  443         }
  444 
  445         default:
  446                 twa_dbg_dprint(3, sc, "func_code = %x", ccb_h->func_code);
  447                 ccb_h->status = CAM_REQ_INVALID;
  448                 xpt_done(ccb);
  449                 break;
  450         }
  451 }
  452 
  453 
  454 
  455 /*
  456  * Function name:       twa_poll
  457  * Description:         Driver entry point called when interrupts are not available.
  458  *
  459  * Input:               sim     -- sim corresponding to the controller
  460  * Output:              None
  461  * Return value:        None
  462  */
  463 void
  464 twa_poll(struct cam_sim *sim)
  465 {
  466 #ifdef TWA_DEBUG
  467         struct twa_softc *sc = (struct twa_softc *)cam_sim_softc(sim);
  468 #endif /* TWA_DEBUG */
  469 
  470         twa_dbg_dprint(3, sc, "Entering sc = %p", sc);
  471         twa_interrupt(cam_sim_softc(sim));
  472         twa_dbg_dprint(3, sc, "Exiting sc = %p", sc);
  473 }
  474 
  475 
  476 
  477 /*
  478  * Function name:       twa_async
  479  * Description:         Driver entry point for CAM to notify driver of special
  480  *                      events.  We don't use this for now.
  481  *
  482  * Input:               callback_arg    -- ptr to per ctlr structure
  483  *                      code            -- code associated with the event
  484  *                      path            -- cam path
  485  *                      arg             -- 
  486  * Output:              None
  487  * Return value:        0       -- success
  488  *                      non-zero-- failure
  489  */
  490 void
  491 twa_async(void *callback_arg, u_int32_t code, 
  492                         struct cam_path *path, void *arg)
  493 {
  494 #ifdef TWA_DEBUG
  495         struct twa_softc *sc = (struct twa_softc *)callback_arg;
  496 #endif /* TWA_DEBUG */
  497 
  498         twa_dbg_dprint(3, sc, "sc = %p, code = %x, path = %p, arg = %p",
  499                                 sc, code, path, arg);
  500 }
  501 
  502 
  503 
  504 /*
  505  * Function name:       twa_timeout
  506  * Description:         Driver entry point for being alerted on a request
  507  *                      timing out.
  508  *
  509  * Input:               arg     -- ptr to timed out request
  510  * Output:              None
  511  * Return value:        None
  512  */
  513 static void
  514 twa_timeout(void *arg)
  515 {
  516         struct twa_request      *tr = (struct twa_request *)arg;
  517         struct twa_softc        *sc = (struct twa_softc *)(tr->tr_sc);
  518 
  519         twa_printf(sc, "Request timed out!  tr = %p\n", tr);
  520 
  521         twa_reset(sc);
  522 }
  523 
  524 
  525 
  526 /*
  527  * Function name:       twa_request_bus_scan
  528  * Description:         Requests CAM for a scan of the bus.
  529  *
  530  * Input:               sc      -- ptr to per ctlr structure
  531  * Output:              None
  532  * Return value:        None
  533  */
  534 void
  535 twa_request_bus_scan(struct twa_softc *sc)
  536 {
  537         struct cam_path *path;
  538         union ccb       *ccb;
  539 
  540         if ((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK)) == NULL)
  541                 return;
  542         bzero(ccb, sizeof(union ccb));
  543         if (xpt_create_path(&path, xpt_periph, cam_sim_path(sc->twa_sim),
  544                         CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP)
  545                 return;
  546 
  547         xpt_setup_ccb(&ccb->ccb_h, path, 5);
  548         ccb->ccb_h.func_code = XPT_SCAN_BUS;
  549         ccb->ccb_h.cbfcnp = twa_bus_scan_cb;
  550         ccb->crcn.flags = CAM_FLAG_NONE;
  551         xpt_action(ccb);
  552 }
  553 
  554 
  555 
  556 /*
  557  * Function name:       twa_bus_scan_cb
  558  * Description:         Callback from CAM on a bus scan request.
  559  *
  560  * Input:               periph  -- we don't use this
  561  *                      ccb     -- bus scan request ccb that we sent to CAM
  562  * Output:              None
  563  * Return value:        None
  564  */
  565 static void
  566 twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb)
  567 {
  568         twa_dbg_print(3, "ccb = %p\n", ccb);
  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                 twa_dbg_print(3, "success");
  574 
  575         xpt_free_path(ccb->ccb_h.path);
  576         free(ccb, M_TEMP);
  577 }
  578 
  579 
  580 
  581 /*
  582  * Function name:       twa_scsi_complete
  583  * Description:         Called to complete CAM scsi requests.
  584  *
  585  * Input:               tr      -- ptr to request pkt to be completed
  586  * Output:              None
  587  * Return value:        None
  588  */
  589 void
  590 twa_scsi_complete(struct twa_request *tr)
  591 {
  592         struct twa_softc                *sc = tr->tr_sc;
  593         struct twa_command_header       *cmd_hdr = &(tr->tr_command->cmd_hdr);
  594         struct twa_command_9k           *cmd = &(tr->tr_command->command.cmd_pkt_9k);
  595         union ccb                       *ccb = (union ccb *)(tr->tr_private);
  596         u_int16_t                       error;
  597         u_int8_t                        *cdb;
  598 
  599         twa_unset_timer(tr);
  600 
  601         if (tr->tr_error) {
  602                 if (tr->tr_error == EBUSY)
  603                         ccb->ccb_h.status |= CAM_REQUEUE_REQ;
  604                 else if (tr->tr_error == EFBIG)
  605                         ccb->ccb_h.status = CAM_REQ_TOO_BIG;
  606                 else
  607                         ccb->ccb_h.status = CAM_REQ_CMP_ERR;
  608         } else {
  609                 if (cmd->status) {
  610                         twa_dbg_dprint(1, sc, "req_id = 0x%x, status = 0x%x",
  611                                                 cmd->request_id,
  612                                                 cmd->status);
  613 
  614                         error = cmd_hdr->status_block.error;
  615                         if ((error == TWA_ERROR_LOGICAL_UNIT_NOT_SUPPORTED) ||
  616                                         (error == TWA_ERROR_UNIT_OFFLINE)) {
  617                                 twa_dbg_dprint(3, sc, "Unsupported unit. PTL = %x %x %x",
  618                                                         ccb->ccb_h.path_id,
  619                                                         ccb->ccb_h.target_id,
  620                                                         ccb->ccb_h.target_lun);
  621                                 ccb->ccb_h.status |= CAM_TID_INVALID;
  622                         } else {
  623                                 twa_dbg_dprint(2, sc, "cmd = %x %x %x %x %x %x %x",
  624                                                 cmd->command.opcode,
  625                                                 cmd->command.reserved,
  626                                                 cmd->unit,
  627                                                 cmd->request_id,
  628                                                 cmd->status,
  629                                                 cmd->sgl_offset,
  630                                                 cmd->sgl_entries);
  631 
  632                                 cdb = (u_int8_t *)(cmd->cdb);
  633                                 twa_dbg_dprint(2, sc, "cdb = %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
  634                                         cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7],
  635                                         cdb[8], cdb[9], cdb[10], cdb[11], cdb[12], cdb[13], cdb[14], cdb[15]);
  636 
  637                                 /* 
  638                                  * Print the error. Firmware doesn't yet support
  639                                  * the 'Mode Sense' cmd.  Don't print if the cmd
  640                                  * is 'Mode Sense', and the error is 'Invalid field
  641                                  * in CDB'.
  642                                  */
  643                                 if (! ((cdb[0] == 0x1A) && (error == 0x10D))) {
  644                                         u_int8_t *error_str =
  645                                         &(cmd_hdr->err_desc[strlen(cmd_hdr->err_desc) + 1]);
  646 
  647                                         if (error_str[0] == '\0')
  648                                                 error_str =
  649                                                 twa_find_msg_string(twa_error_table, error);
  650 
  651                                         twa_printf(sc, "SCSI cmd = 0x%x: ERROR: (0x%02X: 0x%04X): %s: %s\n",
  652                                                 cdb[0],
  653                                                 TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
  654                                                 error,
  655                                                 error_str,
  656                                                 cmd_hdr->err_desc);
  657                                 }
  658                         }
  659 
  660                         bcopy(cmd_hdr->sense_data, &(ccb->csio.sense_data),
  661                                                 TWA_SENSE_DATA_LENGTH);
  662                         ccb->csio.sense_len = TWA_SENSE_DATA_LENGTH;
  663                         ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID;
  664                 } else
  665                         ccb->ccb_h.status = CAM_REQ_CMP;
  666 
  667                 ccb->csio.scsi_status = cmd->status;
  668                 /* If simq is frozen, unfreeze it. */
  669                 if (sc->twa_state & TWA_STATE_SIMQ_FROZEN)
  670                         twa_allow_new_requests(sc, (void *)ccb);
  671         }
  672 
  673         ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
  674         xpt_done(ccb);
  675 }
  676 
  677 
  678 
  679 /*
  680  * Function name:       twa_drain_busy_queue
  681  * Description:         This function gets called after a controller reset.
  682  *                      It errors back to CAM, all those requests that were
  683  *                      pending with the firmware, at the time of the reset.
  684  *
  685  * Input:               sc      -- ptr to per ctlr structure
  686  * Output:              None
  687  * Return value:        None
  688  */
  689 void
  690 twa_drain_busy_queue(struct twa_softc *sc)
  691 {
  692         struct twa_request      *tr;
  693         union ccb               *ccb;
  694 
  695         /* Walk the busy queue. */
  696         while ((tr = twa_dequeue_busy(sc))) {
  697                 twa_unmap_request(tr);
  698                 if ((tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_INTERNAL) ||
  699                         (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_IOCTL)) {
  700                         /*
  701                          * It's an internal/ioctl request.  The callback/
  702                          * originator should do the clean-up (except unmapping).
  703                          */
  704                         tr->tr_error = EIO;
  705                         if (tr->tr_flags & TWA_CMD_SLEEP_ON_REQUEST) {
  706                                 tr->tr_flags &= ~TWA_CMD_SLEEP_ON_REQUEST;
  707                                 wakeup_one(tr);/* let the caller know */
  708                         }
  709                         else
  710                                 if (tr->tr_callback)
  711                                         tr->tr_callback(tr);
  712                 } else {
  713                         if ((ccb = tr->tr_private)) {
  714                                 twa_unset_timer(tr);
  715                                 /* It's a SCSI request.  Complete it. */
  716                                 ccb->ccb_h.status = CAM_SCSI_BUS_RESET;
  717                                 twa_allow_new_requests(sc, ccb);
  718                                 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
  719                                 xpt_done(ccb);
  720                         }
  721                         twa_release_request(tr);
  722                 }
  723         }
  724 }
  725 
  726 
  727 
  728 /*
  729  * Function name:       twa_allow_new_requests
  730  * Description:         Sets the appropriate status bits in a ccb such that,
  731  *                      when the ccb is completed by a call to xpt_done,
  732  *                      CAM knows that it's ok to unfreeze the flow of new
  733  *                      requests to this controller, if the flow is frozen.
  734  *
  735  * Input:               sc      -- ptr to per ctlr structure
  736  *                      ccb     -- ptr to CAM request
  737  * Output:              None
  738  * Return value:        None
  739  */
  740 void
  741 twa_allow_new_requests(struct twa_softc *sc, void *ccb)
  742 {
  743         ((union ccb *)(ccb))->ccb_h.status |= CAM_RELEASE_SIMQ;
  744         sc->twa_state &= ~TWA_STATE_SIMQ_FROZEN;
  745 }
  746 
  747 
  748 
  749 /*
  750  * Function name:       twa_disallow_new_requests
  751  * Description:         Calls the appropriate CAM function, so as to freeze
  752  *                      the flow of new requests from CAM to this controller.
  753  *
  754  * Input:               sc      -- ptr to per ctlr structure
  755  * Output:              None
  756  * Return value:        None
  757  */
  758 void
  759 twa_disallow_new_requests(struct twa_softc *sc)
  760 {
  761         xpt_freeze_simq(sc->twa_sim, 1);
  762         sc->twa_state |= TWA_STATE_SIMQ_FROZEN;
  763 }
  764 
  765 
  766 
  767 /*
  768  * Function name:       twa_set_timer
  769  * Description:         Set a timer to time a given request.
  770  *
  771  * Input:               tr      -- ptr to request pkt
  772  * Output:              None
  773  * Return value:        None
  774  */
  775 void
  776 twa_set_timer(struct twa_request *tr)
  777 {
  778         union ccb       *ccb = (union ccb *)(tr->tr_private);
  779 
  780         /* Set the timer only if external (CAM) request. */
  781         if (ccb) {
  782                 tr->tr_flags |= TWA_CMD_TIMER_SET;
  783                 ccb->ccb_h.timeout_ch = timeout(twa_timeout, tr,
  784                         (ccb->ccb_h.timeout * hz) / 1000);
  785         }
  786 }
  787 
  788 
  789 
  790 /*
  791  * Function name:       twa_unset_timer
  792  * Description:         Unset a previously set timer.
  793  *
  794  * Input:               tr      -- ptr to request pkt
  795  * Output:              None
  796  * Return value:        None
  797  */
  798 void
  799 twa_unset_timer(struct twa_request *tr)
  800 {
  801         union ccb       *ccb = (union ccb *)(tr->tr_private);
  802 
  803         if (tr->tr_flags & TWA_CMD_TIMER_SET) {
  804                 untimeout(twa_timeout, tr, ccb->ccb_h.timeout_ch);
  805                 tr->tr_flags &= ~TWA_CMD_TIMER_SET;
  806         }
  807 }

Cache object: 1e87aae412119d8910c2d0dc009c8525


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