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: releng/5.3/sys/dev/twa/twa_cam.c 129344 2004-05-17 17:16:58Z vkashyap $
   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_bus_scan_cb(struct cam_periph *periph, union ccb *ccb);
   54 
   55 
   56 
   57 /*
   58  * Function name:       twa_cam_setup
   59  * Description:         Attaches the driver to CAM.
   60  *
   61  * Input:               sc      -- ptr to per ctlr structure
   62  * Output:              None
   63  * Return value:        0       -- success
   64  *                      non-zero-- failure
   65  */
   66 int
   67 twa_cam_setup(struct twa_softc *sc)
   68 {
   69         struct cam_devq         *devq;
   70         struct ccb_setasync     csa;
   71 
   72         twa_dbg_dprint(3, sc, "sc = %p", sc);
   73         /*
   74          * Create the device queue for our SIM.
   75          */
   76         devq = cam_simq_alloc(TWA_Q_LENGTH);
   77         if (devq == NULL)
   78                 return(ENOMEM);
   79 
   80         /*
   81          * Create a SIM entry.  Though we can support TWA_Q_LENGTH simultaneous
   82          * requests, we claim to be able to handle only (TWA_Q_LENGTH - 1), so
   83          * that we always have a request packet available to service attention
   84          * interrupts.
   85          */
   86         twa_dbg_dprint(3, sc, "Calling cam_sim_alloc");
   87         sc->twa_sim = cam_sim_alloc(twa_action, twa_poll, "twa", sc,
   88                                         device_get_unit(sc->twa_bus_dev),
   89                                         TWA_Q_LENGTH - 1, 1, devq);
   90         if (sc->twa_sim == NULL) {
   91                 cam_simq_free(devq);
   92                 return(ENOMEM);
   93         }
   94 
   95         /*
   96          * Register the bus.
   97          */
   98         twa_dbg_dprint(3, sc, "Calling xpt_bus_register");
   99         if (xpt_bus_register(sc->twa_sim, 0) != CAM_SUCCESS) {
  100                 cam_sim_free(sc->twa_sim, TRUE);
  101                 sc->twa_sim = NULL; /* so twa_cam_detach will not try to free it */
  102                 return(ENXIO);
  103         }
  104 
  105         twa_dbg_dprint(3, sc, "Calling xpt_create_path");
  106         if (xpt_create_path(&sc->twa_path, NULL,
  107                                 cam_sim_path(sc->twa_sim),
  108                                 CAM_TARGET_WILDCARD,
  109                                 CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
  110                 xpt_bus_deregister(cam_sim_path (sc->twa_sim));
  111                 cam_sim_free(sc->twa_sim, TRUE); /* passing TRUE will free the devq as well */
  112                 return(ENXIO);
  113         }
  114 
  115         twa_dbg_dprint(3, sc, "Calling xpt_setup_ccb");
  116         xpt_setup_ccb(&csa.ccb_h, sc->twa_path, 5);
  117         csa.ccb_h.func_code = XPT_SASYNC_CB;
  118         csa.event_enable = AC_FOUND_DEVICE | AC_LOST_DEVICE;
  119         csa.callback = twa_async;
  120         csa.callback_arg = sc;
  121         xpt_action((union ccb *)&csa);
  122 
  123         twa_dbg_dprint(3, sc, "Calling twa_request_bus_scan");
  124         /*
  125          * Request a bus scan, so that CAM gets to know of
  126          * the logical units that we control.
  127          */
  128         twa_request_bus_scan(sc);
  129         twa_dbg_dprint(3, sc, "Exiting");
  130         return(0);
  131 }
  132 
  133 
  134 
  135 /*
  136  * Function name:       twa_cam_detach
  137  * Description:         Detaches the driver from CAM.
  138  *
  139  * Input:               sc      -- ptr to per ctlr structure
  140  * Output:              None
  141  * Return value:        None
  142  */
  143 void
  144 twa_cam_detach(struct twa_softc *sc)
  145 {
  146         if (sc->twa_path)
  147                 xpt_free_path(sc->twa_path);
  148         if (sc->twa_sim) {
  149                 xpt_bus_deregister(cam_sim_path(sc->twa_sim));
  150                 cam_sim_free(sc->twa_sim, TRUE); /* passing TRUE will free the devq as well */
  151         }
  152 }
  153 
  154 
  155 
  156 /*
  157  * Function name:       twa_send_scsi_cmd
  158  * Description:         Sends down a scsi cmd to fw.
  159  *
  160  * Input:               tr      -- ptr to request pkt
  161  *                      cmd     -- opcode of scsi cmd to send
  162  * Output:              None
  163  * Return value:        0       -- success
  164  *                      non-zero-- failure
  165  */
  166 int
  167 twa_send_scsi_cmd(struct twa_request *tr, int cmd)
  168 {
  169         union ccb       ccb;
  170 
  171         bzero(&ccb, sizeof(union ccb));
  172         ccb.csio.cdb_io.cdb_bytes[0] = (u_int8_t)cmd;
  173         ccb.csio.cdb_io.cdb_bytes[4] = 128;
  174         ccb.csio.cdb_len = 16;
  175         if ((ccb.csio.data_ptr = malloc(TWA_SECTOR_SIZE, M_DEVBUF, M_NOWAIT))
  176                                         == NULL)
  177                 return(ENOMEM);
  178         bzero(ccb.csio.data_ptr, TWA_SECTOR_SIZE);
  179         ccb.csio.dxfer_len = TWA_SECTOR_SIZE;
  180 
  181         ccb.ccb_h.target_id = 0;
  182         ccb.ccb_h.flags |= CAM_DIR_IN;
  183 
  184         if (twa_execute_scsi(tr, &ccb))
  185                 return(EIO);
  186         return(0);
  187 }
  188 
  189 
  190 
  191 /*
  192  * Function name:       twa_execute_scsi
  193  * Description:         Build a fw cmd, based on a CAM style ccb, and
  194  *                      send it down.
  195  *
  196  * Input:               tr      -- ptr to request pkt
  197  *                      ccb     -- ptr to CAM style ccb
  198  * Output:              None
  199  * Return value:        0       -- success
  200  *                      non-zero-- failure
  201  */
  202 int
  203 twa_execute_scsi(struct twa_request *tr, union ccb *ccb)
  204 {
  205         struct twa_softc                *sc = tr->tr_sc;
  206         struct twa_command_packet       *cmdpkt;
  207         struct twa_command_9k           *cmd9k;
  208         struct ccb_hdr                  *ccb_h = &(ccb->ccb_h);
  209         struct ccb_scsiio               *csio = &(ccb->csio);
  210         int                             error;
  211 
  212         twa_dbg_dprint(3, sc, "SCSI I/O request 0x%x", 
  213                                 csio->cdb_io.cdb_bytes[0]);
  214 
  215         if (ccb_h->target_id >= TWA_MAX_UNITS) {
  216                 twa_dbg_dprint(3, sc, "Invalid target. PTL = %x %x %x",
  217                         ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
  218                 ccb_h->status |= CAM_TID_INVALID;
  219                 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL)
  220                         xpt_done(ccb);
  221                 return(1);
  222         }
  223         if (ccb_h->target_lun != 0) {
  224                 twa_dbg_dprint(3, sc, "Invalid lun. PTL = %x %x %x",
  225                         ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
  226                 ccb_h->status |= CAM_LUN_INVALID;
  227                 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL)
  228                         xpt_done(ccb);
  229                 return(1);
  230         }
  231 
  232         if(ccb_h->flags & CAM_CDB_PHYS) {
  233                 twa_printf(sc, "Physical CDB address!\n");
  234                 ccb_h->status = CAM_REQ_CMP_ERR;
  235                 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL)
  236                         xpt_done(ccb);
  237                 return(1);
  238         }
  239 
  240         /*
  241          * We are going to work on this request.  Mark it as enqueued (though
  242          * we don't actually queue it...)
  243          */
  244         ccb_h->status |= CAM_SIM_QUEUED;
  245 
  246         if((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
  247                 if(ccb_h->flags & CAM_DIR_IN)
  248                         tr->tr_flags |= TWA_CMD_DATA_IN;
  249                 else
  250                         tr->tr_flags |= TWA_CMD_DATA_OUT;
  251         }
  252 
  253         cmdpkt = tr->tr_command;
  254 
  255         cmdpkt->cmd_hdr.header_desc.size_header = 128;
  256                 
  257         cmd9k = &(cmdpkt->command.cmd_pkt_9k);
  258         cmd9k->command.opcode = TWA_OP_EXECUTE_SCSI_COMMAND;
  259         cmd9k->unit = ccb_h->target_id;
  260         cmd9k->request_id = tr->tr_request_id;
  261         cmd9k->status = 0;
  262         cmd9k->sgl_offset = 16; /* offset from end of hdr = max cdb len */
  263 
  264         if(ccb_h->flags & CAM_CDB_POINTER)
  265                 bcopy(csio->cdb_io.cdb_ptr, cmd9k->cdb, csio->cdb_len);
  266         else
  267                 bcopy(csio->cdb_io.cdb_bytes, cmd9k->cdb, csio->cdb_len);
  268 
  269         if (!(ccb_h->flags & CAM_DATA_PHYS)) {
  270                 /* Virtual data addresses.  Need to convert them... */
  271                 twa_dbg_dprint(3, sc, "XPT_SCSI_IO: Single virtual address!");
  272                 if (!(ccb_h->flags & CAM_SCATTER_VALID)) {
  273                         if (csio->dxfer_len > TWA_MAX_IO_SIZE) {
  274                                 twa_printf(sc, "I/O size %d too big.\n",
  275                                                         csio->dxfer_len);
  276                                 ccb_h->status = CAM_REQ_TOO_BIG;
  277                                 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL)
  278                                         xpt_done(ccb);
  279                                 return(1);
  280                         }
  281 
  282                         if ((tr->tr_length = csio->dxfer_len)) {
  283                                 tr->tr_data = csio->data_ptr;
  284                                 cmd9k->sgl_entries = 1;
  285                         }
  286                 } else {
  287                         twa_printf(sc, "twa_execute_scsi: XPT_SCSI_IO: Got SGList!\n");
  288                         ccb_h->status = CAM_REQ_CMP_ERR;
  289                         if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL) {
  290                                 xpt_done(ccb);
  291                         }
  292                         return(1);
  293                 }
  294         } else {
  295                 /* Data addresses are physical. */
  296                 twa_printf(sc, "twa_execute_scsi: XPT_SCSI_IO: Physical data addresses!\n");
  297                 ccb_h->status = CAM_REQ_CMP_ERR;
  298                 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL) {
  299                         ccb_h->status |= CAM_RELEASE_SIMQ;
  300                         ccb_h->status &= ~CAM_SIM_QUEUED;
  301                         xpt_done(ccb);
  302                 }
  303                 return(1);
  304         }
  305 
  306         tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_9K;
  307         /* twa_setup_data_dmamap will fill in the SGL, and submit the I/O. */
  308         error = twa_map_request(tr);
  309         return(error);
  310 }
  311 
  312 
  313 
  314 /*
  315  * Function name:       twa_action
  316  * Description:         Driver entry point for CAM's use.
  317  *
  318  * Input:               sim     -- sim corresponding to the ctlr
  319  *                      ccb     -- ptr to CAM request
  320  * Output:              None
  321  * Return value:        None
  322  */
  323 void
  324 twa_action(struct cam_sim *sim, union ccb *ccb)
  325 {
  326         struct twa_softc        *sc = (struct twa_softc *)cam_sim_softc(sim);
  327         struct ccb_hdr          *ccb_h = &(ccb->ccb_h);
  328 
  329         switch (ccb_h->func_code) {
  330         case XPT_SCSI_IO:       /* SCSI I/O */
  331         {
  332                 struct twa_request      *tr;
  333 
  334                 if ((sc->twa_state & TWA_STATE_SIMQ_FROZEN) ||
  335                                 ((tr = twa_get_request(sc)) == NULL)) {
  336                         twa_dbg_dprint(2, sc, "simq frozen/Cannot get request pkt.");
  337                         /*
  338                          * Freeze the simq to maintain ccb ordering.  The next
  339                          * ccb that gets completed will unfreeze the simq.
  340                          */
  341                         twa_disallow_new_requests(sc);
  342                         ccb_h->status |= CAM_REQUEUE_REQ;
  343                         xpt_done(ccb);
  344                         break;
  345                 }
  346                 tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_EXTERNAL;
  347                 tr->tr_private = ccb;
  348                 tr->tr_callback = twa_complete_io;
  349                 if (twa_execute_scsi(tr, ccb))
  350                         twa_release_request(tr);
  351                 break;
  352         }
  353 
  354         case XPT_ABORT:
  355                 twa_dbg_dprint(2, sc, "Abort request");
  356                 ccb_h->status = CAM_UA_ABORT;
  357                 xpt_done(ccb);
  358                 break;
  359 
  360         case XPT_RESET_BUS:
  361                 twa_printf(sc, "Reset Bus request from CAM...\n");
  362                 if (twa_reset(sc)) {
  363                         twa_printf(sc, "Reset Bus failed!\n");
  364                         ccb_h->status = CAM_REQ_CMP_ERR;
  365                 }
  366                 else
  367                         ccb_h->status = CAM_REQ_CMP;
  368 
  369                 xpt_done(ccb);
  370                 break;
  371 
  372         case XPT_SET_TRAN_SETTINGS:
  373                 twa_dbg_dprint(3, sc, "XPT_SET_TRAN_SETTINGS");
  374 
  375                 /*
  376                  * This command is not supported, since it's very specific
  377                  * to SCSI, and we are doing ATA.
  378                  */
  379                 ccb_h->status = CAM_FUNC_NOTAVAIL;
  380                 xpt_done(ccb);
  381                 break;
  382 
  383         case XPT_GET_TRAN_SETTINGS: 
  384         {
  385                 struct ccb_trans_settings       *cts = &ccb->cts;
  386 
  387                 twa_dbg_dprint(3, sc, "XPT_GET_TRAN_SETTINGS");
  388                 cts->valid = (CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID);
  389                 cts->flags &= ~(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB);
  390                 ccb_h->status = CAM_REQ_CMP;
  391                 xpt_done(ccb);
  392                 break;
  393         }
  394 
  395         case XPT_CALC_GEOMETRY:
  396                 twa_dbg_dprint(3, sc, "XPT_CALC_GEOMETRY request");
  397                 cam_calc_geometry(&ccb->ccg, 1/* extended */);
  398                 xpt_done(ccb);
  399                 break;
  400 
  401         case XPT_PATH_INQ:    /* Path inquiry -- get twa properties */
  402         {
  403                 struct ccb_pathinq      *path_inq = &ccb->cpi;
  404 
  405                 twa_dbg_dprint(3, sc, "XPT_PATH_INQ request");
  406 
  407                 path_inq->version_num = 1;
  408                 path_inq->hba_inquiry = 0;
  409                 path_inq->target_sprt = 0;
  410                 path_inq->hba_misc = 0;
  411                 path_inq->hba_eng_cnt = 0;
  412                 path_inq->max_target = TWA_MAX_UNITS;
  413                 path_inq->max_lun = 0;
  414                 path_inq->unit_number = cam_sim_unit(sim);
  415                 path_inq->bus_id = cam_sim_bus(sim);
  416                 path_inq->initiator_id = 12;
  417                 path_inq->base_transfer_speed = 100000;
  418                 strncpy(path_inq->sim_vid, "FreeBSD", SIM_IDLEN);
  419                 strncpy(path_inq->hba_vid, "3ware", HBA_IDLEN);
  420                 strncpy(path_inq->dev_name, cam_sim_name(sim), DEV_IDLEN);
  421                 ccb_h->status = CAM_REQ_CMP;
  422                 xpt_done(ccb);
  423                 break;
  424         }
  425 
  426         default:
  427                 twa_dbg_dprint(3, sc, "func_code = %x", ccb_h->func_code);
  428                 ccb_h->status = CAM_REQ_INVALID;
  429                 xpt_done(ccb);
  430                 break;
  431         }
  432 }
  433 
  434 
  435 
  436 /*
  437  * Function name:       twa_poll
  438  * Description:         Driver entry point called when interrupts are not available.
  439  *
  440  * Input:               sim     -- sim corresponding to the controller
  441  * Output:              None
  442  * Return value:        None
  443  */
  444 void
  445 twa_poll(struct cam_sim *sim)
  446 {
  447 #ifdef TWA_DEBUG
  448         struct twa_softc *sc = (struct twa_softc *)cam_sim_softc(sim);
  449 #endif /* TWA_DEBUG */
  450 
  451         twa_dbg_dprint(3, sc, "Entering sc = %p", sc);
  452         twa_interrupt(cam_sim_softc(sim));
  453         twa_dbg_dprint(3, sc, "Exiting sc = %p", sc);
  454 }
  455 
  456 
  457 
  458 /*
  459  * Function name:       twa_async
  460  * Description:         Driver entry point for CAM to notify driver of special
  461  *                      events.  We don't use this for now.
  462  *
  463  * Input:               callback_arg    -- ptr to per ctlr structure
  464  *                      code            -- code associated with the event
  465  *                      path            -- cam path
  466  *                      arg             -- 
  467  * Output:              None
  468  * Return value:        0       -- success
  469  *                      non-zero-- failure
  470  */
  471 void
  472 twa_async(void *callback_arg, u_int32_t code, 
  473                         struct cam_path *path, void *arg)
  474 {
  475 #ifdef TWA_DEBUG
  476         struct twa_softc *sc = (struct twa_softc *)callback_arg;
  477 #endif /* TWA_DEBUG */
  478 
  479         twa_dbg_dprint(3, sc, "sc = %p, code = %x, path = %p, arg = %p",
  480                                 sc, code, path, arg);
  481 }
  482 
  483 
  484 
  485 /*
  486  * Function name:       twa_request_bus_scan
  487  * Description:         Requests CAM for a scan of the bus.
  488  *
  489  * Input:               sc      -- ptr to per ctlr structure
  490  * Output:              None
  491  * Return value:        None
  492  */
  493 void
  494 twa_request_bus_scan(struct twa_softc *sc)
  495 {
  496         struct cam_path *path;
  497         union ccb       *ccb;
  498 
  499         if ((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK)) == NULL)
  500                 return;
  501         bzero(ccb, sizeof(union ccb));
  502         if (xpt_create_path(&path, xpt_periph, cam_sim_path(sc->twa_sim),
  503                         CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP)
  504                 return;
  505 
  506         xpt_setup_ccb(&ccb->ccb_h, path, 5);
  507         ccb->ccb_h.func_code = XPT_SCAN_BUS;
  508         ccb->ccb_h.cbfcnp = twa_bus_scan_cb;
  509         ccb->crcn.flags = CAM_FLAG_NONE;
  510         xpt_action(ccb);
  511 }
  512 
  513 
  514 
  515 /*
  516  * Function name:       twa_bus_scan_cb
  517  * Description:         Callback from CAM on a bus scan request.
  518  *
  519  * Input:               periph  -- we don't use this
  520  *                      ccb     -- bus scan request ccb that we sent to CAM
  521  * Output:              None
  522  * Return value:        None
  523  */
  524 static void
  525 twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb)
  526 {
  527         twa_dbg_print(3, "ccb = %p\n", ccb);
  528         if (ccb->ccb_h.status != CAM_REQ_CMP)
  529                 printf("cam_scan_callback: failure status = %x\n",
  530                                         ccb->ccb_h.status);
  531         else
  532                 twa_dbg_print(3, "success");
  533 
  534         xpt_free_path(ccb->ccb_h.path);
  535         free(ccb, M_TEMP);
  536 }
  537 
  538 
  539 
  540 /*
  541  * Function name:       twa_scsi_complete
  542  * Description:         Called to complete CAM scsi requests.
  543  *
  544  * Input:               tr      -- ptr to request pkt to be completed
  545  * Output:              None
  546  * Return value:        None
  547  */
  548 void
  549 twa_scsi_complete(struct twa_request *tr)
  550 {
  551         struct twa_softc                *sc = tr->tr_sc;
  552         struct twa_command_header       *cmd_hdr = &(tr->tr_command->cmd_hdr);
  553         struct twa_command_9k           *cmd = &(tr->tr_command->command.cmd_pkt_9k);
  554         union ccb                       *ccb = (union ccb *)(tr->tr_private);
  555         u_int16_t                       error;
  556         u_int8_t                        *cdb;
  557 
  558         if (tr->tr_error) {
  559                 if (tr->tr_error == EBUSY)
  560                         ccb->ccb_h.status |= CAM_REQUEUE_REQ;
  561                 else if (tr->tr_error == EFBIG)
  562                         ccb->ccb_h.status = CAM_REQ_TOO_BIG;
  563                 else
  564                         ccb->ccb_h.status = CAM_REQ_CMP_ERR;
  565         } else {
  566                 if (cmd->status) {
  567                         twa_dbg_dprint(1, sc, "req_id = 0x%x, status = 0x%x",
  568                                                 cmd->request_id,
  569                                                 cmd->status);
  570 
  571                         error = cmd_hdr->status_block.error;
  572                         if ((error == TWA_ERROR_LOGICAL_UNIT_NOT_SUPPORTED) ||
  573                                         (error == TWA_ERROR_UNIT_OFFLINE)) {
  574                                 twa_dbg_dprint(3, sc, "Unsupported unit. PTL = %x %x %x",
  575                                                         ccb->ccb_h.path_id,
  576                                                         ccb->ccb_h.target_id,
  577                                                         ccb->ccb_h.target_lun);
  578                                 ccb->ccb_h.status |= CAM_TID_INVALID;
  579                         } else {
  580                                 twa_dbg_dprint(2, sc, "cmd = %x %x %x %x %x %x %x",
  581                                                 cmd->command.opcode,
  582                                                 cmd->command.reserved,
  583                                                 cmd->unit,
  584                                                 cmd->request_id,
  585                                                 cmd->status,
  586                                                 cmd->sgl_offset,
  587                                                 cmd->sgl_entries);
  588 
  589                                 cdb = (u_int8_t *)(cmd->cdb);
  590                                 twa_dbg_dprint(2, sc, "cdb = %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
  591                                         cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7],
  592                                         cdb[8], cdb[9], cdb[10], cdb[11], cdb[12], cdb[13], cdb[14], cdb[15]);
  593 
  594                                 cmd_hdr->err_specific_desc[sizeof(cmd_hdr->err_specific_desc) - 1] = '\0';
  595                                 /* 
  596                                  * Print the error. Firmware doesn't yet support
  597                                  * the 'Mode Sense' cmd.  Don't print if the cmd
  598                                  * is 'Mode Sense', and the error is 'Invalid field
  599                                  * in CDB'.
  600                                  */
  601                                 if (! ((cdb[0] == 0x1A) && (error == 0x10D)))
  602                                         twa_printf(sc, "SCSI cmd = 0x%x: ERROR: (0x%02X: 0x%04X): %s: %s\n",
  603                                                 cdb[0],
  604                                                 TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
  605                                                 error,
  606                                                 twa_find_msg_string(twa_error_table, error),
  607                                                 cmd_hdr->err_specific_desc);
  608                         }
  609 
  610                         bcopy(cmd_hdr->sense_data, &(ccb->csio.sense_data),
  611                                                 TWA_SENSE_DATA_LENGTH);
  612                         ccb->csio.sense_len = TWA_SENSE_DATA_LENGTH;
  613                         ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID;
  614                 } else
  615                         ccb->ccb_h.status = CAM_REQ_CMP;
  616 
  617                 ccb->csio.scsi_status = cmd->status;
  618                 /* If simq is frozen, unfreeze it. */
  619                 if (sc->twa_state & TWA_STATE_SIMQ_FROZEN)
  620                         twa_allow_new_requests(sc, (void *)ccb);
  621         }
  622 
  623         ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
  624         xpt_done(ccb);
  625 }
  626 
  627 
  628 
  629 /*
  630  * Function name:       twa_drain_busy_queue
  631  * Description:         This function gets called after a controller reset.
  632  *                      It errors back to CAM, all those requests that were
  633  *                      pending with the firmware, at the time of the reset.
  634  *
  635  * Input:               sc      -- ptr to per ctlr structure
  636  * Output:              None
  637  * Return value:        None
  638  */
  639 void
  640 twa_drain_busy_queue(struct twa_softc *sc)
  641 {
  642         struct twa_request      *tr;
  643         union ccb               *ccb;
  644 
  645         /* Walk the busy queue. */
  646         while ((tr = twa_dequeue_busy(sc))) {
  647                 twa_unmap_request(tr);
  648                 if ((tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_INTERNAL) ||
  649                         (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_IOCTL)) {
  650                         /* It's an internal/ioctl request.  Simply free it. */
  651                         if (tr->tr_data)
  652                                 free(tr->tr_data, M_DEVBUF);
  653                 } else {
  654                         if ((ccb = tr->tr_private)) {
  655                                 /* It's a SCSI request.  Complete it. */
  656                                 ccb->ccb_h.status = CAM_SCSI_BUS_RESET |
  657                                                         CAM_RELEASE_SIMQ;
  658                                 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
  659                                 xpt_done(ccb);
  660                         }
  661                 }
  662                 twa_release_request(tr);
  663         }
  664 }
  665 
  666 
  667 
  668 /*
  669  * Function name:       twa_allow_new_requests
  670  * Description:         Sets the appropriate status bits in a ccb such that,
  671  *                      when the ccb is completed by a call to xpt_done,
  672  *                      CAM knows that it's ok to unfreeze the flow of new
  673  *                      requests to this controller, if the flow is frozen.
  674  *
  675  * Input:               sc      -- ptr to per ctlr structure
  676  *                      ccb     -- ptr to CAM request
  677  * Output:              None
  678  * Return value:        None
  679  */
  680 void
  681 twa_allow_new_requests(struct twa_softc *sc, void *ccb)
  682 {
  683         ((union ccb *)(ccb))->ccb_h.status |= CAM_RELEASE_SIMQ;
  684         sc->twa_state &= ~TWA_STATE_SIMQ_FROZEN;
  685 }
  686 
  687 
  688 
  689 /*
  690  * Function name:       twa_disallow_new_requests
  691  * Description:         Calls the appropriate CAM function, so as to freeze
  692  *                      the flow of new requests from CAM to this controller.
  693  *
  694  * Input:               sc      -- ptr to per ctlr structure
  695  * Output:              None
  696  * Return value:        None
  697  */
  698 void
  699 twa_disallow_new_requests(struct twa_softc *sc)
  700 {
  701         xpt_freeze_simq(sc->twa_sim, 1);
  702         sc->twa_state |= TWA_STATE_SIMQ_FROZEN;
  703 }

Cache object: a3b55a89adb4012681706f7c75c3875a


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