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/aac/aac_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) 2002 Adaptec, 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 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD: releng/8.3/sys/dev/aac/aac_cam.c 226915 2011-10-29 23:51:21Z marius $");
   29 
   30 /*
   31  * CAM front-end for communicating with non-DASD devices
   32  */
   33 
   34 #include "opt_aac.h"
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/kernel.h>
   39 #include <sys/sysctl.h>
   40 #include <sys/lock.h>
   41 #include <sys/malloc.h>
   42 #include <sys/module.h>
   43 #include <sys/mutex.h>
   44 
   45 #include <cam/cam.h>
   46 #include <cam/cam_ccb.h>
   47 #include <cam/cam_debug.h>
   48 #include <cam/cam_periph.h>
   49 #include <cam/cam_sim.h>
   50 #include <cam/cam_xpt_sim.h>
   51 #include <cam/scsi/scsi_all.h>
   52 #include <cam/scsi/scsi_message.h>
   53 
   54 #include <sys/bus.h>
   55 #include <sys/conf.h>
   56 #include <sys/disk.h>
   57 
   58 #include <machine/md_var.h>
   59 #include <machine/bus.h>
   60 #include <sys/rman.h>
   61 
   62 #include <vm/vm.h>
   63 #include <vm/pmap.h>
   64 
   65 #include <dev/aac/aacreg.h>
   66 #include <sys/aac_ioctl.h>
   67 #include <dev/aac/aacvar.h>
   68 
   69 struct aac_cam {
   70         device_t                dev;
   71         struct aac_sim          *inf;
   72         struct cam_sim          *sim;
   73         struct cam_path         *path;
   74 };
   75 
   76 static int aac_cam_probe(device_t dev);
   77 static int aac_cam_attach(device_t dev);
   78 static int aac_cam_detach(device_t dev);
   79 static void aac_cam_action(struct cam_sim *, union ccb *);
   80 static void aac_cam_poll(struct cam_sim *);
   81 static void aac_cam_complete(struct aac_command *);
   82 static void aac_cam_rescan(struct aac_softc *sc, uint32_t channel,
   83     uint32_t target_id);
   84 
   85 static u_int32_t aac_cam_reset_bus(struct cam_sim *, union ccb *);
   86 static u_int32_t aac_cam_abort_ccb(struct cam_sim *, union ccb *);
   87 static u_int32_t aac_cam_term_io(struct cam_sim *, union ccb *);
   88 
   89 static devclass_t       aac_pass_devclass;
   90 
   91 static device_method_t  aac_pass_methods[] = {
   92         DEVMETHOD(device_probe,         aac_cam_probe),
   93         DEVMETHOD(device_attach,        aac_cam_attach),
   94         DEVMETHOD(device_detach,        aac_cam_detach),
   95         { 0, 0 }
   96 };
   97 
   98 static driver_t aac_pass_driver = {
   99         "aacp",
  100         aac_pass_methods,
  101         sizeof(struct aac_cam)
  102 };
  103 
  104 DRIVER_MODULE(aacp, aac, aac_pass_driver, aac_pass_devclass, 0, 0);
  105 MODULE_DEPEND(aacp, cam, 1, 1, 1);
  106 
  107 MALLOC_DEFINE(M_AACCAM, "aaccam", "AAC CAM info");
  108 
  109 static void
  110 aac_cam_rescan(struct aac_softc *sc, uint32_t channel, uint32_t target_id)
  111 {
  112         union ccb *ccb;
  113         struct aac_sim *sim;
  114         struct aac_cam *camsc;
  115 
  116         if (target_id == AAC_CAM_TARGET_WILDCARD)
  117                 target_id = CAM_TARGET_WILDCARD;
  118 
  119         TAILQ_FOREACH(sim, &sc->aac_sim_tqh, sim_link) {
  120                 camsc = sim->aac_cam;
  121                 if (camsc == NULL || camsc->inf == NULL ||
  122                     camsc->inf->BusNumber != channel)
  123                         continue;
  124 
  125                 ccb = xpt_alloc_ccb_nowait();
  126                 if (ccb == NULL) {
  127                         device_printf(sc->aac_dev,
  128                             "Cannot allocate ccb for bus rescan.\n");
  129                         return;
  130                 }
  131 
  132                 if (xpt_create_path(&ccb->ccb_h.path, xpt_periph,
  133                     cam_sim_path(camsc->sim),
  134                     target_id, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
  135                         xpt_free_ccb(ccb);
  136                         device_printf(sc->aac_dev,
  137                             "Cannot create path for bus rescan.\n");
  138                         return;
  139                 }
  140                 xpt_rescan(ccb);
  141                 break;
  142         }
  143 }
  144 
  145 
  146 static void
  147 aac_cam_event(struct aac_softc *sc, struct aac_event *event, void *arg)
  148 {
  149         union ccb *ccb;
  150         struct aac_cam *camsc;
  151 
  152         switch (event->ev_type) {
  153         case AAC_EVENT_CMFREE:
  154                 ccb = arg;
  155                 camsc = ccb->ccb_h.sim_priv.entries[0].ptr;
  156                 free(event, M_AACCAM);
  157                 xpt_release_simq(camsc->sim, 1);
  158                 ccb->ccb_h.status = CAM_REQUEUE_REQ;
  159                 xpt_done(ccb);
  160                 break;
  161         default:
  162                 device_printf(sc->aac_dev, "unknown event %d in aac_cam\n",
  163                     event->ev_type);
  164                 break;
  165         }
  166 
  167         return;
  168 }
  169 
  170 static int
  171 aac_cam_probe(device_t dev)
  172 {
  173         fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
  174 
  175         return (0);
  176 }
  177 
  178 static int
  179 aac_cam_detach(device_t dev)
  180 {
  181         struct aac_softc *sc;
  182         struct aac_cam *camsc;
  183         fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
  184 
  185         camsc = (struct aac_cam *)device_get_softc(dev);
  186         sc = camsc->inf->aac_sc;
  187         camsc->inf->aac_cam = NULL;
  188 
  189         mtx_lock(&sc->aac_io_lock);
  190 
  191         xpt_async(AC_LOST_DEVICE, camsc->path, NULL);
  192         xpt_free_path(camsc->path);
  193         xpt_bus_deregister(cam_sim_path(camsc->sim));
  194         cam_sim_free(camsc->sim, /*free_devq*/TRUE);
  195 
  196         sc->cam_rescan_cb = NULL;
  197 
  198         mtx_unlock(&sc->aac_io_lock);
  199 
  200         return (0);
  201 }
  202 
  203 /*
  204  * Register the driver as a CAM SIM
  205  */
  206 static int
  207 aac_cam_attach(device_t dev)
  208 {
  209         struct cam_devq *devq;
  210         struct cam_sim *sim;
  211         struct cam_path *path;
  212         struct aac_cam *camsc;
  213         struct aac_sim *inf;
  214 
  215         fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
  216 
  217         camsc = (struct aac_cam *)device_get_softc(dev);
  218         inf = (struct aac_sim *)device_get_ivars(dev);
  219         camsc->inf = inf;
  220         camsc->inf->aac_cam = camsc;
  221 
  222         devq = cam_simq_alloc(inf->TargetsPerBus);
  223         if (devq == NULL)
  224                 return (EIO);
  225 
  226         sim = cam_sim_alloc(aac_cam_action, aac_cam_poll, "aacp", camsc,
  227             device_get_unit(dev), &inf->aac_sc->aac_io_lock, 1, 1, devq);
  228         if (sim == NULL) {
  229                 cam_simq_free(devq);
  230                 return (EIO);
  231         }
  232 
  233         /* Since every bus has it's own sim, every bus 'appears' as bus 0 */
  234         mtx_lock(&inf->aac_sc->aac_io_lock);
  235         if (xpt_bus_register(sim, dev, 0) != CAM_SUCCESS) {
  236                 cam_sim_free(sim, TRUE);
  237                 mtx_unlock(&inf->aac_sc->aac_io_lock);
  238                 return (EIO);
  239         }
  240 
  241         if (xpt_create_path(&path, NULL, cam_sim_path(sim),
  242             CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
  243                 xpt_bus_deregister(cam_sim_path(sim));
  244                 cam_sim_free(sim, TRUE);
  245                 mtx_unlock(&inf->aac_sc->aac_io_lock);
  246                 return (EIO);
  247         }
  248         inf->aac_sc->cam_rescan_cb = aac_cam_rescan;
  249         mtx_unlock(&inf->aac_sc->aac_io_lock);
  250 
  251         camsc->sim = sim;
  252         camsc->path = path;
  253 
  254         return (0);
  255 }
  256 
  257 static void
  258 aac_cam_action(struct cam_sim *sim, union ccb *ccb)
  259 {
  260         struct  aac_cam *camsc;
  261         struct  aac_softc *sc;
  262         struct  aac_srb *srb;
  263         struct  aac_fib *fib;
  264         struct  aac_command *cm;
  265 
  266         camsc = (struct aac_cam *)cam_sim_softc(sim);
  267         sc = camsc->inf->aac_sc;
  268         fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
  269 
  270         /* Synchronous ops, and ops that don't require communication with the
  271          * controller */
  272         switch(ccb->ccb_h.func_code) {
  273         case XPT_SCSI_IO:
  274         case XPT_RESET_DEV:
  275                 /* These are handled down below */
  276                 break;
  277         case XPT_CALC_GEOMETRY:
  278         {
  279                 struct ccb_calc_geometry *ccg;
  280                 u_int32_t size_mb;
  281                 u_int32_t secs_per_cylinder;
  282 
  283                 ccg = &ccb->ccg;
  284                 size_mb = ccg->volume_size /
  285                     ((1024L * 1024L) / ccg->block_size);
  286                 if (size_mb >= (2 * 1024)) {            /* 2GB */
  287                         ccg->heads = 255;
  288                         ccg->secs_per_track = 63;
  289                 } else if (size_mb >= (1 * 1024)) {     /* 1GB */
  290                         ccg->heads = 128;
  291                         ccg->secs_per_track = 32;
  292                 } else {
  293                         ccg->heads = 64;
  294                         ccg->secs_per_track = 32;
  295                 }
  296                 secs_per_cylinder = ccg->heads * ccg->secs_per_track;
  297                 ccg->cylinders = ccg->volume_size / secs_per_cylinder;
  298 
  299                 ccb->ccb_h.status = CAM_REQ_CMP;
  300                 xpt_done(ccb);
  301                 return;
  302         }
  303         case XPT_PATH_INQ:
  304         {
  305                 struct ccb_pathinq *cpi = &ccb->cpi;
  306 
  307                 cpi->version_num = 1;
  308                 cpi->hba_inquiry = PI_WIDE_16;
  309                 cpi->target_sprt = 0;
  310 
  311                 /*
  312                  * Resetting via the passthrough or parallel bus scan
  313                  * causes problems.
  314                  */
  315                 cpi->hba_misc = PIM_NOBUSRESET | PIM_SEQSCAN;
  316                 cpi->hba_eng_cnt = 0;
  317                 cpi->max_target = camsc->inf->TargetsPerBus;
  318                 cpi->max_lun = 8;       /* Per the controller spec */
  319                 cpi->initiator_id = camsc->inf->InitiatorBusId;
  320                 cpi->bus_id = camsc->inf->BusNumber;
  321                 cpi->base_transfer_speed = 3300;
  322                 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
  323                 strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN);
  324                 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
  325                 cpi->unit_number = cam_sim_unit(sim);
  326                 cpi->transport = XPORT_SPI;
  327                 cpi->transport_version = 2;
  328                 cpi->protocol = PROTO_SCSI;
  329                 cpi->protocol_version = SCSI_REV_2;
  330                 ccb->ccb_h.status = CAM_REQ_CMP;
  331                 xpt_done(ccb);
  332                 return;
  333         }
  334         case XPT_GET_TRAN_SETTINGS:
  335         {
  336                 struct ccb_trans_settings_scsi *scsi =
  337                         &ccb->cts.proto_specific.scsi;
  338                 struct ccb_trans_settings_spi *spi =
  339                         &ccb->cts.xport_specific.spi;
  340                 ccb->cts.protocol = PROTO_SCSI;
  341                 ccb->cts.protocol_version = SCSI_REV_2;
  342                 ccb->cts.transport = XPORT_SPI;
  343                 ccb->cts.transport_version = 2;
  344                 if (ccb->ccb_h.target_lun != CAM_LUN_WILDCARD) {
  345                         scsi->valid = CTS_SCSI_VALID_TQ;
  346                         spi->valid |= CTS_SPI_VALID_DISC;
  347                 } else {
  348                         scsi->valid = 0;
  349                 }
  350                 ccb->ccb_h.status = CAM_REQ_CMP;
  351                 xpt_done(ccb);
  352                 return;
  353         }
  354         case XPT_SET_TRAN_SETTINGS:
  355                 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
  356                 xpt_done(ccb);
  357                 return;
  358         case XPT_RESET_BUS:
  359                 if (!(sc->flags & AAC_FLAGS_CAM_NORESET)) {
  360                         ccb->ccb_h.status = aac_cam_reset_bus(sim, ccb);
  361                 } else {
  362                         ccb->ccb_h.status = CAM_REQ_CMP;
  363                 }
  364                 xpt_done(ccb);
  365                 return;
  366         case XPT_ABORT:
  367                 ccb->ccb_h.status = aac_cam_abort_ccb(sim, ccb);
  368                 xpt_done(ccb);
  369                 return;
  370         case XPT_TERM_IO:
  371                 ccb->ccb_h.status = aac_cam_term_io(sim, ccb);
  372                 xpt_done(ccb);
  373                 return;
  374         default:
  375                 device_printf(sc->aac_dev, "Unsupported command 0x%x\n",
  376                     ccb->ccb_h.func_code);
  377                 ccb->ccb_h.status = CAM_PROVIDE_FAIL;
  378                 xpt_done(ccb);
  379                 return;
  380         }
  381 
  382         /* Async ops that require communcation with the controller */
  383 
  384         if (aac_alloc_command(sc, &cm)) {
  385                 struct aac_event *event;
  386 
  387                 xpt_freeze_simq(sim, 1);
  388                 ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
  389                 ccb->ccb_h.sim_priv.entries[0].ptr = camsc;
  390                 event = malloc(sizeof(struct aac_event), M_AACCAM,
  391                     M_NOWAIT | M_ZERO);
  392                 if (event == NULL) {
  393                         device_printf(sc->aac_dev,
  394                             "Warning, out of memory for event\n");
  395                         return;
  396                 }
  397                 event->ev_callback = aac_cam_event;
  398                 event->ev_arg = ccb;
  399                 event->ev_type = AAC_EVENT_CMFREE;
  400                 aac_add_event(sc, event);
  401                 return;
  402         }
  403 
  404         fib = cm->cm_fib;
  405         srb = (struct aac_srb *)&fib->data[0];
  406         cm->cm_datalen = 0;
  407 
  408         switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
  409         case CAM_DIR_IN:
  410                 srb->flags = AAC_SRB_FLAGS_DATA_IN;
  411                 cm->cm_flags |= AAC_CMD_DATAIN;
  412                 break;
  413         case CAM_DIR_OUT:
  414                 srb->flags = AAC_SRB_FLAGS_DATA_OUT;
  415                 cm->cm_flags |= AAC_CMD_DATAOUT;
  416                 break;
  417         case CAM_DIR_NONE:
  418                 srb->flags = AAC_SRB_FLAGS_NO_DATA_XFER;
  419                 break;
  420         default:
  421                 srb->flags = AAC_SRB_FLAGS_UNSPECIFIED_DIRECTION;
  422                 cm->cm_flags |= AAC_CMD_DATAIN | AAC_CMD_DATAOUT;
  423                 break;
  424         }
  425 
  426         switch(ccb->ccb_h.func_code) {
  427         case XPT_SCSI_IO:
  428         {
  429                 struct ccb_scsiio *csio = &ccb->csio;
  430 
  431                 srb->function = AAC_SRB_FUNC_EXECUTE_SCSI;
  432 
  433                 /*
  434                  * Copy the CDB into the SRB.  It's only 6-16 bytes,
  435                  * so a copy is not too expensive.
  436                  */
  437                 srb->cdb_len = csio->cdb_len;
  438                 if (ccb->ccb_h.flags & CAM_CDB_POINTER)
  439                         bcopy(csio->cdb_io.cdb_ptr, (u_int8_t *)&srb->cdb[0],
  440                             srb->cdb_len);
  441                 else
  442                         bcopy(csio->cdb_io.cdb_bytes, (u_int8_t *)&srb->cdb[0],
  443                             srb->cdb_len);
  444 
  445                 /* Set command */
  446                 fib->Header.Command = (sc->flags & AAC_FLAGS_SG_64BIT) ?
  447                         ScsiPortCommandU64 : ScsiPortCommand;
  448 
  449                 /* Map the s/g list. XXX 32bit addresses only! */
  450                 if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
  451                         if ((ccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) {
  452                                 srb->data_len = csio->dxfer_len;
  453                                 if (ccb->ccb_h.flags & CAM_DATA_PHYS) {
  454                                         /* Send a 32bit command */
  455                                         fib->Header.Command = ScsiPortCommand;
  456                                         srb->sg_map.SgCount = 1;
  457                                         srb->sg_map.SgEntry[0].SgAddress =
  458                                             (uint32_t)(uintptr_t)csio->data_ptr;
  459                                         srb->sg_map.SgEntry[0].SgByteCount =
  460                                             csio->dxfer_len;
  461                                 } else {
  462                                         /*
  463                                          * Arrange things so that the S/G
  464                                          * map will get set up automagically
  465                                          */
  466                                         cm->cm_data = (void *)csio->data_ptr;
  467                                         cm->cm_datalen = csio->dxfer_len;
  468                                         cm->cm_sgtable = &srb->sg_map;
  469                                 }
  470                         } else {
  471                                 /* XXX Need to handle multiple s/g elements */
  472                                 panic("aac_cam: multiple s/g elements");
  473                         }
  474                 } else {
  475                         srb->sg_map.SgCount = 0;
  476                         srb->sg_map.SgEntry[0].SgByteCount = 0;
  477                         srb->data_len = 0;
  478                 }
  479 
  480                 break;
  481         }
  482         case XPT_RESET_DEV:
  483                 if (!(sc->flags & AAC_FLAGS_CAM_NORESET)) {
  484                         srb->function = AAC_SRB_FUNC_RESET_DEVICE;
  485                         break;
  486                 } else {
  487                         ccb->ccb_h.status = CAM_REQ_CMP;
  488                         xpt_done(ccb);
  489                         return;
  490                 }
  491         default:
  492                 break;
  493         }
  494 
  495         srb->bus = camsc->inf->BusNumber; /* Bus number relative to the card */
  496         srb->target = ccb->ccb_h.target_id;
  497         srb->lun = ccb->ccb_h.target_lun;
  498         srb->timeout = ccb->ccb_h.timeout;      /* XXX */
  499         srb->retry_limit = 0;
  500 
  501         cm->cm_complete = aac_cam_complete;
  502         cm->cm_private = ccb;
  503         cm->cm_timestamp = time_uptime;
  504 
  505         fib->Header.XferState =
  506             AAC_FIBSTATE_HOSTOWNED      |
  507             AAC_FIBSTATE_INITIALISED    |
  508             AAC_FIBSTATE_FROMHOST       |
  509             AAC_FIBSTATE_REXPECTED      |
  510             AAC_FIBSTATE_NORM;
  511         fib->Header.Size = sizeof(struct aac_fib_header) +
  512             sizeof(struct aac_srb);
  513 
  514         aac_enqueue_ready(cm);
  515         aac_startio(cm->cm_sc);
  516 
  517         return;
  518 }
  519 
  520 static void
  521 aac_cam_poll(struct cam_sim *sim)
  522 {
  523         /*
  524          * Pinging the interrupt routine isn't very safe, nor is it
  525          * really necessary.  Do nothing.
  526          */
  527 }
  528 
  529 static void
  530 aac_cam_complete(struct aac_command *cm)
  531 {
  532         union   ccb *ccb;
  533         struct  aac_srb_response *srbr;
  534         struct  aac_softc *sc;
  535         int     sense_returned;
  536 
  537         sc = cm->cm_sc;
  538         fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
  539         ccb = cm->cm_private;
  540         srbr = (struct aac_srb_response *)&cm->cm_fib->data[0];
  541 
  542         if (srbr->fib_status != 0) {
  543                 device_printf(sc->aac_dev, "Passthru FIB failed!\n");
  544                 ccb->ccb_h.status = CAM_REQ_ABORTED;
  545         } else {
  546                 /*
  547                  * The SRB error codes just happen to match the CAM error
  548                  * codes.  How convienient!
  549                  */
  550                 ccb->ccb_h.status = srbr->srb_status;
  551 
  552                 /* Take care of SCSI_IO ops. */
  553                 if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
  554                         u_int8_t command, device;
  555 
  556                         ccb->csio.scsi_status = srbr->scsi_status;
  557 
  558                         /* Take care of autosense */
  559                         if (srbr->sense_len) {
  560                                 sense_returned = srbr->sense_len;
  561                                 if (sense_returned < ccb->csio.sense_len)
  562                                         ccb->csio.sense_resid =
  563                                            ccb->csio.sense_len -
  564                                            sense_returned;
  565                                         else
  566                                             ccb->csio.sense_resid = 0;
  567                                 bzero(&ccb->csio.sense_data,
  568                                     sizeof(struct scsi_sense_data));
  569                                 bcopy(&srbr->sense[0], &ccb->csio.sense_data,
  570                                     min(ccb->csio.sense_len, sense_returned));
  571                                 ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
  572                                 // scsi_sense_print(&ccb->csio);
  573                         }
  574 
  575                         /* If this is an inquiry command, fake things out */
  576                         if (ccb->ccb_h.flags & CAM_CDB_POINTER)
  577                                 command = ccb->csio.cdb_io.cdb_ptr[0];
  578                         else
  579                                 command = ccb->csio.cdb_io.cdb_bytes[0];
  580 
  581                         if (command == INQUIRY) {
  582                                 if (ccb->ccb_h.status == CAM_REQ_CMP) {
  583                                 device = ccb->csio.data_ptr[0] & 0x1f;
  584                                 /*
  585                                  * We want DASD and PROC devices to only be
  586                                  * visible through the pass device.
  587                                  */
  588                                 if ((device == T_DIRECT) ||
  589                                     (device == T_PROCESSOR) ||
  590                                     (sc->flags & AAC_FLAGS_CAM_PASSONLY))
  591                                         ccb->csio.data_ptr[0] =
  592                                             ((ccb->csio.data_ptr[0] & 0xe0) |
  593                                             T_NODEVICE);
  594                                 } else if (ccb->ccb_h.status == CAM_SEL_TIMEOUT &&
  595                                         ccb->ccb_h.target_lun != 0) {
  596                                         /* fix for INQUIRYs on Lun>0 */
  597                                         ccb->ccb_h.status = CAM_DEV_NOT_THERE;
  598                                 }
  599                         }
  600                 }
  601         }
  602 
  603         aac_release_command(cm);
  604         xpt_done(ccb);
  605 
  606         return;
  607 }
  608 
  609 static u_int32_t
  610 aac_cam_reset_bus(struct cam_sim *sim, union ccb *ccb)
  611 {
  612         struct aac_fib *fib;
  613         struct aac_softc *sc;
  614         struct aac_cam *camsc;
  615         struct aac_vmioctl *vmi;
  616         struct aac_resetbus *rbc;
  617         int e;
  618 
  619         camsc = (struct aac_cam *)cam_sim_softc(sim);
  620         sc = camsc->inf->aac_sc;
  621 
  622         if (sc == NULL) {
  623                 printf("aac: Null sc?\n");
  624                 return (CAM_REQ_ABORTED);
  625         }
  626 
  627         aac_alloc_sync_fib(sc, &fib);
  628 
  629         vmi = (struct aac_vmioctl *)&fib->data[0];
  630         bzero(vmi, sizeof(struct aac_vmioctl));
  631 
  632         vmi->Command = VM_Ioctl;
  633         vmi->ObjType = FT_DRIVE;
  634         vmi->MethId = sc->scsi_method_id;
  635         vmi->ObjId = 0;
  636         vmi->IoctlCmd = ResetBus;
  637 
  638         rbc = (struct aac_resetbus *)&vmi->IoctlBuf[0];
  639         rbc->BusNumber = camsc->inf->BusNumber;
  640 
  641         e = aac_sync_fib(sc, ContainerCommand, 0, fib,
  642             sizeof(struct aac_vmioctl));
  643         if (e) {
  644                 device_printf(sc->aac_dev,"Error %d sending ResetBus command\n",
  645                     e);
  646                 aac_release_sync_fib(sc);
  647                 return (CAM_REQ_ABORTED);
  648         }
  649 
  650         aac_release_sync_fib(sc);
  651         return (CAM_REQ_CMP);
  652 }
  653 
  654 static u_int32_t
  655 aac_cam_abort_ccb(struct cam_sim *sim, union ccb *ccb)
  656 {
  657         return (CAM_UA_ABORT);
  658 }
  659 
  660 static u_int32_t
  661 aac_cam_term_io(struct cam_sim *sim, union ccb *ccb)
  662 {
  663         return (CAM_UA_TERMIO);
  664 }
  665 

Cache object: 6a35db19d1f44f89d072a641e25301e1


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