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/amr/amr_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) 2000 Michael Smith
    3  * Copyright (c) 2000 BSDi
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 /*-
   28  * Copyright (c) 2002 Eric Moore
   29  * Copyright (c) 2002 LSI Logic Corporation
   30  * All rights reserved.
   31  *
   32  * Redistribution and use in source and binary forms, with or without
   33  * modification, are permitted provided that the following conditions
   34  * are met:
   35  * 1. Redistributions of source code must retain the above copyright
   36  *    notice, this list of conditions and the following disclaimer.
   37  * 2. Redistributions in binary form must reproduce the above copyright
   38  *    notice, this list of conditions and the following disclaimer in the
   39  *    documentation and/or other materials provided with the distribution.
   40  * 3. The party using or redistributing the source code and binary forms
   41  *    agrees to the disclaimer below and the terms and conditions set forth
   42  *    herein.
   43  *
   44  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   45  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   46  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   47  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   48  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   49  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   50  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   51  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   52  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   53  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   54  * SUCH DAMAGE.
   55  */
   56 
   57 #include <sys/cdefs.h>
   58 __FBSDID("$FreeBSD$");
   59 
   60 #include <sys/param.h>
   61 #include <sys/systm.h>
   62 #include <sys/malloc.h>
   63 #include <sys/kernel.h>
   64 
   65 #include <dev/amr/amr_compat.h>
   66 #include <sys/bus.h>
   67 #include <sys/conf.h>
   68 #include <sys/stat.h>
   69 
   70 #include <cam/cam.h>
   71 #include <cam/cam_ccb.h>
   72 #include <cam/cam_sim.h>
   73 #include <cam/cam_xpt.h>
   74 #include <cam/cam_xpt_sim.h>
   75 #include <cam/cam_debug.h>
   76 #include <cam/scsi/scsi_all.h>
   77 #include <cam/scsi/scsi_message.h>
   78 
   79 #include <machine/resource.h>
   80 #include <machine/bus.h>
   81 
   82 #include <dev/amr/amrreg.h>
   83 #include <dev/amr/amrvar.h>
   84 
   85 static void             amr_cam_action(struct cam_sim *sim, union ccb *ccb);
   86 static void             amr_cam_poll(struct cam_sim *sim);
   87 static void             amr_cam_complete(struct amr_command *ac);
   88 static void             amr_cam_complete_extcdb(struct amr_command *ac);
   89 
   90 
   91 /********************************************************************************
   92  * Enqueue/dequeue functions
   93  */
   94 static __inline void
   95 amr_enqueue_ccb(struct amr_softc *sc, union ccb *ccb)
   96 {
   97     int         s;
   98 
   99     s = splbio();
  100     TAILQ_INSERT_TAIL(&sc->amr_cam_ccbq, &ccb->ccb_h, sim_links.tqe);
  101     splx(s);
  102 }
  103 
  104 static __inline void
  105 amr_requeue_ccb(struct amr_softc *sc, union ccb *ccb)
  106 {
  107     int         s;
  108 
  109     s = splbio();
  110     TAILQ_INSERT_HEAD(&sc->amr_cam_ccbq, &ccb->ccb_h, sim_links.tqe);
  111     splx(s);
  112 }
  113 
  114 static __inline union ccb *
  115 amr_dequeue_ccb(struct amr_softc *sc)
  116 {
  117     union ccb   *ccb;
  118     int         s;
  119 
  120     s = splbio();
  121     if ((ccb = (union ccb *)TAILQ_FIRST(&sc->amr_cam_ccbq)) != NULL)
  122         TAILQ_REMOVE(&sc->amr_cam_ccbq, &ccb->ccb_h, sim_links.tqe);
  123     splx(s);
  124     return(ccb);
  125 }
  126 
  127 /********************************************************************************
  128  * Attach our 'real' SCSI channels to CAM
  129  */
  130 int
  131 amr_cam_attach(struct amr_softc *sc)
  132 {
  133     struct cam_devq     *devq;
  134     int                 chn;
  135 
  136     /* initialise the ccb queue */
  137     TAILQ_INIT(&sc->amr_cam_ccbq);
  138 
  139     /*
  140      * Allocate a devq for all our channels combined.  This should
  141      * allow for the maximum number of SCSI commands we will accept
  142      * at one time. Save the pointer in the softc so we can find it later
  143      * during detach.
  144      */
  145     if ((devq = cam_simq_alloc(AMR_MAX_SCSI_CMDS)) == NULL)
  146         return(ENOMEM);
  147     sc->amr_cam_devq = devq;
  148 
  149     /*
  150      * Iterate over our channels, registering them with CAM
  151      */
  152     for (chn = 0; chn < sc->amr_maxchan; chn++) {
  153 
  154         /* allocate a sim */
  155         if ((sc->amr_cam_sim[chn] = cam_sim_alloc(amr_cam_action,
  156                                                   amr_cam_poll,
  157                                                   "amr",
  158                                                   sc,
  159                                                   device_get_unit(sc->amr_dev),
  160                                                   1,
  161                                                   AMR_MAX_SCSI_CMDS,
  162                                                   devq)) == NULL) {
  163             cam_simq_free(devq);
  164             device_printf(sc->amr_dev, "CAM SIM attach failed\n");
  165             return(ENOMEM);
  166         }
  167 
  168         /* register the bus ID so we can get it later */
  169         if (xpt_bus_register(sc->amr_cam_sim[chn], chn)) {
  170             device_printf(sc->amr_dev, "CAM XPT bus registration failed\n");
  171             return(ENXIO);
  172         }
  173     }
  174     /*
  175      * XXX we should scan the config and work out which devices are actually
  176      * protected.
  177      */
  178     return(0);
  179 }
  180 
  181 /********************************************************************************
  182  * Disconnect ourselves from CAM
  183  */
  184 void
  185 amr_cam_detach(struct amr_softc *sc)
  186 {
  187     int         chn;
  188 
  189     for (chn = 0; chn < sc->amr_maxchan; chn++) {
  190 
  191         /*
  192          * If a sim was allocated for this channel, free it
  193          */
  194         if (sc->amr_cam_sim[chn] != NULL) {
  195             xpt_bus_deregister(cam_sim_path(sc->amr_cam_sim[chn]));
  196             cam_sim_free(sc->amr_cam_sim[chn], FALSE);
  197         }
  198     }
  199 
  200     /* Now free the devq */
  201     if (sc->amr_cam_devq != NULL)
  202         cam_simq_free(sc->amr_cam_devq);
  203 }
  204 
  205 /********************************************************************************
  206  ********************************************************************************
  207                                                         CAM passthrough interface
  208  ********************************************************************************
  209  ********************************************************************************/
  210 
  211 /********************************************************************************
  212  * Handle a request for action from CAM
  213  */
  214 static void
  215 amr_cam_action(struct cam_sim *sim, union ccb *ccb)
  216 {
  217     struct amr_softc    *sc = cam_sim_softc(sim);
  218 
  219     switch(ccb->ccb_h.func_code) {
  220 
  221     /*
  222      * Perform SCSI I/O to a physical device.
  223      */
  224     case XPT_SCSI_IO:
  225     {
  226         struct ccb_hdr          *ccbh = &ccb->ccb_h;
  227         struct ccb_scsiio       *csio = &ccb->csio;
  228 
  229         /* Validate the CCB */
  230         ccbh->status = CAM_REQ_INPROG;
  231 
  232         /* check the CDB length */
  233         if (csio->cdb_len > AMR_MAX_EXTCDB_LEN)
  234             ccbh->status = CAM_REQ_CMP_ERR;
  235 
  236         if ((csio->cdb_len > AMR_MAX_CDB_LEN) && (sc->support_ext_cdb == 0 ))
  237             ccbh->status = CAM_REQ_CMP_ERR;
  238 
  239         /* check that the CDB pointer is not to a physical address */
  240         if ((ccbh->flags & CAM_CDB_POINTER) && (ccbh->flags & CAM_CDB_PHYS))
  241             ccbh->status = CAM_REQ_CMP_ERR;
  242 
  243         /* if there is data transfer, it must be to/from a virtual address */
  244         if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
  245             if (ccbh->flags & CAM_DATA_PHYS)            /* we can't map it */
  246                 ccbh->status = CAM_REQ_CMP_ERR;         
  247             if (ccbh->flags & CAM_SCATTER_VALID)        /* we want to do the s/g setup */
  248                 ccbh->status = CAM_REQ_CMP_ERR;
  249         }
  250 
  251         /*
  252          * If the command is to a LUN other than 0, fail it.
  253          * This is probably incorrect, but during testing the firmware did not
  254          * seem to respect the LUN field, and thus devices appear echoed.
  255          */
  256         if (csio->ccb_h.target_lun != 0)
  257             ccbh->status = CAM_REQ_CMP_ERR;
  258 
  259         /* if we're happy with the request, queue it for attention */
  260         if (ccbh->status == CAM_REQ_INPROG) {
  261 
  262             /* save the channel number in the ccb */
  263             csio->ccb_h.sim_priv.entries[0].field = cam_sim_bus(sim);
  264 
  265             mtx_lock(&sc->amr_io_lock);
  266             amr_enqueue_ccb(sc, ccb);
  267             amr_startio(sc);
  268             mtx_unlock(&sc->amr_io_lock);
  269             return;
  270         }
  271         break;
  272     }
  273 
  274     case XPT_CALC_GEOMETRY:
  275     {
  276         cam_calc_geometry(&ccb->ccg, /*extended*/1);
  277         break;
  278     }
  279 
  280     /*
  281      * Return path stats.  Some of these should probably be
  282      * amended.
  283      */
  284     case XPT_PATH_INQ:
  285     {
  286         struct ccb_pathinq      *cpi = & ccb->cpi;
  287 
  288         debug(3, "XPT_PATH_INQ");
  289         cpi->version_num = 1;           /* XXX??? */
  290         cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
  291         cpi->target_sprt = 0;
  292         cpi->hba_misc = PIM_NOBUSRESET;
  293         cpi->hba_eng_cnt = 0;
  294         cpi->max_target = AMR_MAX_TARGETS;
  295         cpi->max_lun = 0 /* AMR_MAX_LUNS*/;
  296         cpi->initiator_id = 7;          /* XXX variable? */
  297         strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
  298         strncpy(cpi->hba_vid, "LSI", HBA_IDLEN);
  299         strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
  300         cpi->unit_number = cam_sim_unit(sim);
  301         cpi->bus_id = cam_sim_bus(sim);
  302         cpi->base_transfer_speed = 132 * 1024;  /* XXX get from controller? */
  303         cpi->ccb_h.status = CAM_REQ_CMP;
  304 
  305         break;
  306     }
  307 
  308     case XPT_RESET_BUS:
  309     {
  310         struct ccb_pathinq      *cpi = & ccb->cpi;
  311 
  312         debug(1, "XPT_RESET_BUS");
  313         cpi->ccb_h.status = CAM_REQ_CMP;
  314         break;
  315     }
  316 
  317     case XPT_RESET_DEV:
  318     {
  319         debug(1, "XPT_RESET_DEV");
  320         ccb->ccb_h.status = CAM_REQ_CMP;
  321         break;
  322     }
  323 
  324     case XPT_GET_TRAN_SETTINGS:
  325     {
  326         struct ccb_trans_settings       *cts;
  327 
  328         debug(3, "XPT_GET_TRAN_SETTINGS");
  329 
  330         cts = &(ccb->cts);
  331 
  332         if ((cts->flags & CCB_TRANS_USER_SETTINGS) == 0) {
  333                 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
  334                 break;
  335         }
  336 
  337         cts->flags = CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB;
  338         cts->bus_width = MSG_EXT_WDTR_BUS_32_BIT;
  339         cts->sync_period = 6;   /* 40MHz how wide is this bus? */
  340         cts->sync_offset = 31;  /* How to extract this from board? */
  341 
  342         cts->valid = CCB_TRANS_SYNC_RATE_VALID
  343             | CCB_TRANS_SYNC_OFFSET_VALID
  344             | CCB_TRANS_BUS_WIDTH_VALID
  345             | CCB_TRANS_DISC_VALID
  346             | CCB_TRANS_TQ_VALID;
  347         ccb->ccb_h.status = CAM_REQ_CMP;
  348         break;
  349     }
  350 
  351     case XPT_SET_TRAN_SETTINGS:
  352         debug(3, "XPT_SET_TRAN_SETTINGS");
  353         ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
  354         break;
  355 
  356 
  357     /*
  358      * Reject anything else as unsupported.
  359      */
  360     default:
  361         /* we can't do this */
  362         ccb->ccb_h.status = CAM_REQ_INVALID;
  363         break;
  364     }
  365     xpt_done(ccb);
  366 }
  367 
  368 /********************************************************************************
  369  * Convert a CAM CCB off the top of the CCB queue to a passthrough SCSI command.
  370  */
  371 int
  372 amr_cam_command(struct amr_softc *sc, struct amr_command **acp)
  373 {
  374     struct amr_command          *ac;
  375     struct amr_passthrough              *ap;
  376     struct amr_ext_passthrough  *aep;
  377     struct ccb_scsiio                   *csio;
  378     int                         bus, target, error;
  379 
  380     error = 0;
  381     ac = NULL;
  382     ap = NULL;
  383     aep = NULL;
  384 
  385     /* check to see if there is a ccb for us to work with */
  386     if ((csio = (struct ccb_scsiio *)amr_dequeue_ccb(sc)) == NULL)
  387         goto out;
  388 
  389     /* get bus/target, XXX validate against protected devices? */
  390     bus = csio->ccb_h.sim_priv.entries[0].field;
  391     target = csio->ccb_h.target_id;
  392 
  393     /*
  394      * Build a passthrough command.
  395      */
  396 
  397     /* construct passthrough */
  398     if (sc->support_ext_cdb ) {
  399             if ((aep = malloc(sizeof(*aep), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
  400                 error = ENOMEM;
  401                 goto out;
  402             }
  403             aep->ap_timeout = 2;
  404             aep->ap_ars = 1;
  405             aep->ap_request_sense_length = 14;
  406             aep->ap_islogical = 0;
  407             aep->ap_channel = bus;
  408             aep->ap_scsi_id = target;
  409             aep->ap_logical_drive_no = csio->ccb_h.target_lun;
  410             aep->ap_cdb_length = csio->cdb_len;
  411             aep->ap_data_transfer_length = csio->dxfer_len;
  412             if (csio->ccb_h.flags & CAM_CDB_POINTER) {
  413                 bcopy(csio->cdb_io.cdb_ptr, aep->ap_cdb, csio->cdb_len);
  414             } else {
  415                 bcopy(csio->cdb_io.cdb_bytes, aep->ap_cdb, csio->cdb_len);
  416             }
  417             /* we leave the data s/g list and s/g count to the map routine later */
  418 
  419             debug(2, " COMMAND %x/%d+%d to %d:%d:%d", aep->ap_cdb[0], aep->ap_cdb_length, csio->dxfer_len,
  420                   aep->ap_channel, aep->ap_scsi_id, aep->ap_logical_drive_no);
  421 
  422     } else {
  423             if ((ap = malloc(sizeof(*ap), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
  424                 error = ENOMEM;
  425                 goto out;
  426             }
  427             ap->ap_timeout = 0;
  428             ap->ap_ars = 1;
  429             ap->ap_request_sense_length = 14;
  430             ap->ap_islogical = 0;
  431             ap->ap_channel = bus;
  432             ap->ap_scsi_id = target;
  433             ap->ap_logical_drive_no = csio->ccb_h.target_lun;
  434             ap->ap_cdb_length = csio->cdb_len;
  435             ap->ap_data_transfer_length = csio->dxfer_len;
  436             if (csio->ccb_h.flags & CAM_CDB_POINTER) {
  437                 bcopy(csio->cdb_io.cdb_ptr, ap->ap_cdb, csio->cdb_len);
  438             } else {
  439                 bcopy(csio->cdb_io.cdb_bytes, ap->ap_cdb, csio->cdb_len);
  440             }
  441             /* we leave the data s/g list and s/g count to the map routine later */
  442 
  443             debug(2, " COMMAND %x/%d+%d to %d:%d:%d", ap->ap_cdb[0], ap->ap_cdb_length, csio->dxfer_len,
  444                   ap->ap_channel, ap->ap_scsi_id, ap->ap_logical_drive_no);
  445     }
  446 
  447     /* construct command */
  448     if ((ac = amr_alloccmd(sc)) == NULL) {
  449         error = ENOMEM;
  450         goto out;
  451     }
  452 
  453     ac->ac_flags |= AMR_CMD_DATAOUT | AMR_CMD_DATAIN;
  454 
  455     ac->ac_ccb_data = csio->data_ptr;
  456     ac->ac_ccb_length = csio->dxfer_len;
  457     if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
  458         ac->ac_flags |= AMR_CMD_CCB_DATAIN;
  459     if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
  460         ac->ac_flags |= AMR_CMD_CCB_DATAOUT;
  461 
  462     ac->ac_private = csio;
  463     if ( sc->support_ext_cdb ) {
  464             ac->ac_data = aep;
  465             ac->ac_length = sizeof(*aep);
  466             ac->ac_complete = amr_cam_complete_extcdb;
  467             ac->ac_mailbox.mb_command = AMR_CMD_EXTPASS;
  468     } else {
  469             ac->ac_data = ap;
  470             ac->ac_length = sizeof(*ap);
  471             ac->ac_complete = amr_cam_complete;
  472             ac->ac_mailbox.mb_command = AMR_CMD_PASS;
  473     }
  474 
  475 out:
  476     if (error != 0) {
  477         if (ac != NULL)
  478             amr_releasecmd(ac);
  479         if (ap != NULL)
  480             free(ap, M_DEVBUF);
  481         if (aep != NULL)
  482             free(aep, M_DEVBUF);
  483         if (csio != NULL)                       /* put it back and try again later */
  484             amr_requeue_ccb(sc, (union ccb *)csio);
  485     }
  486     *acp = ac;
  487     return(error);
  488 }
  489 
  490 /********************************************************************************
  491  * Check for interrupt status
  492  */
  493 static void
  494 amr_cam_poll(struct cam_sim *sim)
  495 {
  496     struct amr_softc    *sc = cam_sim_softc(sim);
  497 
  498     mtx_lock(&sc->amr_io_lock);
  499     amr_done(cam_sim_softc(sim));
  500     mtx_unlock(&sc->amr_io_lock);
  501 }
  502 
  503  /********************************************************************************
  504  * Handle completion of a command submitted via CAM.
  505  */
  506 static void
  507 amr_cam_complete(struct amr_command *ac)
  508 {
  509     struct amr_passthrough      *ap = (struct amr_passthrough *)ac->ac_data;
  510     struct ccb_scsiio           *csio = (struct ccb_scsiio *)ac->ac_private;
  511     struct scsi_inquiry_data    *inq = (struct scsi_inquiry_data *)csio->data_ptr;
  512 
  513     /* XXX note that we're ignoring ac->ac_status - good idea? */
  514 
  515     debug(1, "status 0x%x  AP scsi_status 0x%x", ac->ac_status, ap->ap_scsi_status);
  516 
  517     /*
  518      * Hide disks from CAM so that they're not picked up and treated as 'normal' disks.
  519      *
  520      * If the configuration provides a mechanism to mark a disk a "not managed", we
  521      * could add handling for that to allow disks to be selectively visible.
  522      */
  523 
  524     if ((ap->ap_cdb[0] == INQUIRY) && (SID_TYPE(inq) == T_DIRECT)) {
  525         bzero(csio->data_ptr, csio->dxfer_len);
  526         if (ap->ap_scsi_status == 0xf0) {
  527             csio->ccb_h.status = CAM_SCSI_STATUS_ERROR;
  528         } else {
  529             csio->ccb_h.status = CAM_DEV_NOT_THERE;
  530         }
  531     } else {
  532 
  533         /* handle passthrough SCSI status */
  534         switch(ap->ap_scsi_status) {
  535         case 0:                         /* completed OK */
  536             csio->ccb_h.status = CAM_REQ_CMP;
  537             break;
  538 
  539         case 0x02:
  540             csio->ccb_h.status = CAM_SCSI_STATUS_ERROR;
  541             csio->scsi_status = SCSI_STATUS_CHECK_COND;
  542             bcopy(ap->ap_request_sense_area, &csio->sense_data, AMR_MAX_REQ_SENSE_LEN);
  543             csio->sense_len = AMR_MAX_REQ_SENSE_LEN;
  544             csio->ccb_h.status |= CAM_AUTOSNS_VALID;
  545             break;
  546 
  547         case 0x08:
  548             csio->ccb_h.status = CAM_SCSI_BUSY;
  549             break;
  550 
  551         case 0xf0:
  552         case 0xf4:
  553         default:
  554             csio->ccb_h.status = CAM_REQ_CMP_ERR;
  555             break;
  556         }
  557     }
  558     free(ap, M_DEVBUF);
  559     if ((csio->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)
  560         debug(2, "%*D\n", imin(csio->dxfer_len, 16), csio->data_ptr, " ");
  561     mtx_unlock(&ac->ac_sc->amr_io_lock);
  562     mtx_lock(&Giant);
  563     xpt_done((union ccb *)csio);
  564     mtx_unlock(&Giant);
  565     mtx_lock(&ac->ac_sc->amr_io_lock);
  566     amr_releasecmd(ac);
  567 }
  568 
  569 /********************************************************************************
  570  * Handle completion of a command submitted via CAM.
  571  * Completion for extended cdb
  572  */
  573 static void
  574 amr_cam_complete_extcdb(struct amr_command *ac)
  575 {
  576     struct amr_ext_passthrough      *aep = (struct amr_ext_passthrough *)ac->ac_data;
  577     struct ccb_scsiio           *csio = (struct ccb_scsiio *)ac->ac_private;
  578     struct scsi_inquiry_data    *inq = (struct scsi_inquiry_data *)csio->data_ptr;
  579 
  580     /* XXX note that we're ignoring ac->ac_status - good idea? */
  581 
  582     debug(1, "status 0x%x  AEP scsi_status 0x%x", ac->ac_status, aep->ap_scsi_status);
  583 
  584     /*
  585      * Hide disks from CAM so that they're not picked up and treated as 'normal' disks.
  586      *
  587      * If the configuration provides a mechanism to mark a disk a "not managed", we
  588      * could add handling for that to allow disks to be selectively visible.
  589      */
  590 
  591     if ((aep->ap_cdb[0] == INQUIRY) && (SID_TYPE(inq) == T_DIRECT)) {
  592         bzero(csio->data_ptr, csio->dxfer_len);
  593         if (aep->ap_scsi_status == 0xf0) {
  594             csio->ccb_h.status = CAM_SCSI_STATUS_ERROR;
  595         } else {
  596             csio->ccb_h.status = CAM_DEV_NOT_THERE;
  597         }
  598     } else {
  599 
  600         /* handle passthrough SCSI status */
  601         switch(aep->ap_scsi_status) {
  602         case 0:                         /* completed OK */
  603             csio->ccb_h.status = CAM_REQ_CMP;
  604             break;
  605 
  606         case 0x02:
  607             csio->ccb_h.status = CAM_SCSI_STATUS_ERROR;
  608             csio->scsi_status = SCSI_STATUS_CHECK_COND;
  609             bcopy(aep->ap_request_sense_area, &csio->sense_data, AMR_MAX_REQ_SENSE_LEN);
  610             csio->sense_len = AMR_MAX_REQ_SENSE_LEN;
  611             csio->ccb_h.status |= CAM_AUTOSNS_VALID;
  612             break;
  613 
  614         case 0x08:
  615             csio->ccb_h.status = CAM_SCSI_BUSY;
  616             break;
  617 
  618         case 0xf0:
  619         case 0xf4:
  620         default:
  621             csio->ccb_h.status = CAM_REQ_CMP_ERR;
  622             break;
  623         }
  624     }
  625     free(aep, M_DEVBUF);
  626     if ((csio->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)
  627         debug(2, "%*D\n", imin(csio->dxfer_len, 16), csio->data_ptr, " ");
  628     mtx_unlock(&ac->ac_sc->amr_io_lock);
  629     mtx_lock(&Giant);
  630     xpt_done((union ccb *)csio);
  631     mtx_unlock(&Giant);
  632     mtx_lock(&ac->ac_sc->amr_io_lock);
  633     amr_releasecmd(ac);
  634 }

Cache object: 25c47f74d5cfcf7dafd162070bf0a9c0


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