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/cam/ctl/ctl_frontend_cam_sim.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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2009 Silicon Graphics International Corp.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions, and the following disclaimer,
   12  *    without modification.
   13  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
   14  *    substantially similar to the "NO WARRANTY" disclaimer below
   15  *    ("Disclaimer") and any redistribution must be conditioned upon
   16  *    including a substantially similar Disclaimer requirement for further
   17  *    binary redistribution.
   18  *
   19  * NO WARRANTY
   20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
   23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   24  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   28  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
   29  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   30  * POSSIBILITY OF SUCH DAMAGES.
   31  *
   32  * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/ctl_frontend_cam_sim.c#4 $
   33  */
   34 /*
   35  * CTL frontend to CAM SIM interface.  This allows access to CTL LUNs via
   36  * the da(4) and pass(4) drivers from inside the system.
   37  *
   38  * Author: Ken Merry <ken@FreeBSD.org>
   39  */
   40 
   41 #include <sys/cdefs.h>
   42 __FBSDID("$FreeBSD$");
   43 
   44 #include <sys/param.h>
   45 #include <sys/systm.h>
   46 #include <sys/kernel.h>
   47 #include <sys/types.h>
   48 #include <sys/malloc.h>
   49 #include <sys/bus.h>
   50 #include <sys/sysctl.h>
   51 #include <machine/atomic.h>
   52 #include <machine/bus.h>
   53 #include <sys/sbuf.h>
   54 
   55 #include <cam/cam.h>
   56 #include <cam/cam_ccb.h>
   57 #include <cam/cam_sim.h>
   58 #include <cam/cam_xpt_sim.h>
   59 #include <cam/cam_xpt.h>
   60 #include <cam/cam_periph.h>
   61 #include <cam/scsi/scsi_all.h>
   62 #include <cam/scsi/scsi_message.h>
   63 #include <cam/ctl/ctl_io.h>
   64 #include <cam/ctl/ctl.h>
   65 #include <cam/ctl/ctl_frontend.h>
   66 #include <cam/ctl/ctl_debug.h>
   67 
   68 #define io_ptr          spriv_ptr1
   69 
   70 struct cfcs_io {
   71         union ccb *ccb;
   72 };
   73 
   74 struct cfcs_softc {
   75         struct ctl_port port;
   76         char port_name[32];
   77         struct cam_sim *sim;
   78         struct cam_devq *devq;
   79         struct cam_path *path;
   80         uint64_t wwnn;
   81         uint64_t wwpn;
   82         uint32_t cur_tag_num;
   83         int online;
   84 };
   85 
   86 /*
   87  * We can't handle CCBs with these flags.  For the most part, we just don't
   88  * handle physical addresses yet.  That would require mapping things in
   89  * order to do the copy.
   90  */
   91 #define CFCS_BAD_CCB_FLAGS (CAM_DATA_ISPHYS | CAM_CDB_PHYS | CAM_SENSE_PTR |            \
   92         CAM_SENSE_PHYS)
   93 
   94 static int cfcs_init(void);
   95 static int cfcs_shutdown(void);
   96 static void cfcs_poll(struct cam_sim *sim);
   97 static void cfcs_online(void *arg);
   98 static void cfcs_offline(void *arg);
   99 static void cfcs_datamove(union ctl_io *io);
  100 static void cfcs_done(union ctl_io *io);
  101 void cfcs_action(struct cam_sim *sim, union ccb *ccb);
  102 
  103 struct cfcs_softc cfcs_softc;
  104 /*
  105  * This is primarily intended to allow for error injection to test the CAM
  106  * sense data and sense residual handling code.  This sets the maximum
  107  * amount of SCSI sense data that we will report to CAM.
  108  */
  109 static int cfcs_max_sense = sizeof(struct scsi_sense_data);
  110 
  111 SYSCTL_NODE(_kern_cam, OID_AUTO, ctl2cam, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
  112     "CAM Target Layer SIM frontend");
  113 SYSCTL_INT(_kern_cam_ctl2cam, OID_AUTO, max_sense, CTLFLAG_RW,
  114            &cfcs_max_sense, 0, "Maximum sense data size");
  115 
  116 static struct ctl_frontend cfcs_frontend =
  117 {
  118         .name = "camsim",
  119         .init = cfcs_init,
  120         .shutdown = cfcs_shutdown,
  121 };
  122 CTL_FRONTEND_DECLARE(ctlcfcs, cfcs_frontend);
  123 
  124 static int
  125 cfcs_init(void)
  126 {
  127         struct cfcs_softc *softc;
  128         struct ctl_port *port;
  129         int retval;
  130 
  131         softc = &cfcs_softc;
  132         bzero(softc, sizeof(*softc));
  133         port = &softc->port;
  134 
  135         port->frontend = &cfcs_frontend;
  136         port->port_type = CTL_PORT_INTERNAL;
  137         /* XXX KDM what should the real number be here? */
  138         port->num_requested_ctl_io = 4096;
  139         snprintf(softc->port_name, sizeof(softc->port_name), "camsim");
  140         port->port_name = softc->port_name;
  141         port->port_online = cfcs_online;
  142         port->port_offline = cfcs_offline;
  143         port->onoff_arg = softc;
  144         port->fe_datamove = cfcs_datamove;
  145         port->fe_done = cfcs_done;
  146         port->targ_port = -1;
  147 
  148         retval = ctl_port_register(port);
  149         if (retval != 0) {
  150                 printf("%s: ctl_port_register() failed with error %d!\n",
  151                        __func__, retval);
  152                 return (retval);
  153         }
  154 
  155         /*
  156          * If the CTL frontend didn't tell us what our WWNN/WWPN is, go
  157          * ahead and set something random.
  158          */
  159         if (port->wwnn == 0) {
  160                 uint64_t random_bits;
  161 
  162                 arc4rand(&random_bits, sizeof(random_bits), 0);
  163                 softc->wwnn = (random_bits & 0x0000000fffffff00ULL) |
  164                         /* Company ID */ 0x5000000000000000ULL |
  165                         /* NL-Port */    0x0300;
  166                 softc->wwpn = softc->wwnn + port->targ_port + 1;
  167                 ctl_port_set_wwns(port, true, softc->wwnn, true, softc->wwpn);
  168         } else {
  169                 softc->wwnn = port->wwnn;
  170                 softc->wwpn = port->wwpn;
  171         }
  172 
  173         softc->devq = cam_simq_alloc(port->num_requested_ctl_io);
  174         if (softc->devq == NULL) {
  175                 printf("%s: error allocating devq\n", __func__);
  176                 retval = ENOMEM;
  177                 goto bailout;
  178         }
  179 
  180         softc->sim = cam_sim_alloc(cfcs_action, cfcs_poll, softc->port_name,
  181                                    softc, /*unit*/ 0, NULL, 1,
  182                                    port->num_requested_ctl_io, softc->devq);
  183         if (softc->sim == NULL) {
  184                 printf("%s: error allocating SIM\n", __func__);
  185                 retval = ENOMEM;
  186                 goto bailout;
  187         }
  188 
  189         if (xpt_bus_register(softc->sim, NULL, 0) != CAM_SUCCESS) {
  190                 printf("%s: error registering SIM\n", __func__);
  191                 retval = ENOMEM;
  192                 goto bailout;
  193         }
  194 
  195         if (xpt_create_path(&softc->path, /*periph*/NULL,
  196                             cam_sim_path(softc->sim),
  197                             CAM_TARGET_WILDCARD,
  198                             CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
  199                 printf("%s: error creating path\n", __func__);
  200                 xpt_bus_deregister(cam_sim_path(softc->sim));
  201                 retval = EINVAL;
  202                 goto bailout;
  203         }
  204 
  205         return (retval);
  206 
  207 bailout:
  208         if (softc->sim)
  209                 cam_sim_free(softc->sim, /*free_devq*/ TRUE);
  210         else if (softc->devq)
  211                 cam_simq_free(softc->devq);
  212         return (retval);
  213 }
  214 
  215 static int
  216 cfcs_shutdown(void)
  217 {
  218         struct cfcs_softc *softc = &cfcs_softc;
  219         struct ctl_port *port = &softc->port;
  220         int error;
  221 
  222         ctl_port_offline(port);
  223 
  224         xpt_free_path(softc->path);
  225         xpt_bus_deregister(cam_sim_path(softc->sim));
  226         cam_sim_free(softc->sim, /*free_devq*/ TRUE);
  227 
  228         if ((error = ctl_port_deregister(port)) != 0)
  229                 printf("%s: cam_sim port deregistration failed\n", __func__);
  230         return (error);
  231 }
  232 
  233 static void
  234 cfcs_poll(struct cam_sim *sim)
  235 {
  236 
  237 }
  238 
  239 static void
  240 cfcs_onoffline(void *arg, int online)
  241 {
  242         struct cfcs_softc *softc = (struct cfcs_softc *)arg;
  243         union ccb *ccb;
  244 
  245         softc->online = online;
  246 
  247         ccb = xpt_alloc_ccb_nowait();
  248         if (ccb == NULL) {
  249                 printf("%s: unable to allocate CCB for rescan\n", __func__);
  250                 return;
  251         }
  252 
  253         if (xpt_create_path(&ccb->ccb_h.path, NULL,
  254                             cam_sim_path(softc->sim), CAM_TARGET_WILDCARD,
  255                             CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
  256                 printf("%s: can't allocate path for rescan\n", __func__);
  257                 xpt_free_ccb(ccb);
  258                 return;
  259         }
  260         xpt_rescan(ccb);
  261 }
  262 
  263 static void
  264 cfcs_online(void *arg)
  265 {
  266         cfcs_onoffline(arg, /*online*/ 1);
  267 }
  268 
  269 static void
  270 cfcs_offline(void *arg)
  271 {
  272         cfcs_onoffline(arg, /*online*/ 0);
  273 }
  274 
  275 /*
  276  * This function is very similar to ctl_ioctl_do_datamove().  Is there a
  277  * way to combine the functionality?
  278  *
  279  * XXX KDM may need to move this into a thread.  We're doing a bcopy in the
  280  * caller's context, which will usually be the backend.  That may not be a
  281  * good thing.
  282  */
  283 static void
  284 cfcs_datamove(union ctl_io *io)
  285 {
  286         union ccb *ccb;
  287         bus_dma_segment_t cam_sg_entry, *cam_sglist;
  288         struct ctl_sg_entry ctl_sg_entry, *ctl_sglist;
  289         int cam_sg_count, ctl_sg_count, cam_sg_start;
  290         int cam_sg_offset;
  291         int len_to_copy;
  292         int ctl_watermark, cam_watermark;
  293         int i, j;
  294 
  295         ccb = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
  296 
  297         /*
  298          * Note that we have a check in cfcs_action() to make sure that any
  299          * CCBs with "bad" flags are returned with CAM_REQ_INVALID.  This
  300          * is just to make sure no one removes that check without updating
  301          * this code to provide the additional functionality necessary to
  302          * support those modes of operation.
  303          */
  304         KASSERT(((ccb->ccb_h.flags & CFCS_BAD_CCB_FLAGS) == 0), ("invalid "
  305                   "CAM flags %#x", (ccb->ccb_h.flags & CFCS_BAD_CCB_FLAGS)));
  306 
  307         /*
  308          * Simplify things on both sides by putting single buffers into a
  309          * single entry S/G list.
  310          */
  311         switch ((ccb->ccb_h.flags & CAM_DATA_MASK)) {
  312         case CAM_DATA_SG: {
  313                 int len_seen;
  314 
  315                 cam_sglist = (bus_dma_segment_t *)ccb->csio.data_ptr;
  316                 cam_sg_count = ccb->csio.sglist_cnt;
  317                 cam_sg_start = cam_sg_count;
  318                 cam_sg_offset = 0;
  319 
  320                 for (i = 0, len_seen = 0; i < cam_sg_count; i++) {
  321                         if ((len_seen + cam_sglist[i].ds_len) >=
  322                              io->scsiio.kern_rel_offset) {
  323                                 cam_sg_start = i;
  324                                 cam_sg_offset = io->scsiio.kern_rel_offset -
  325                                         len_seen;
  326                                 break;
  327                         }
  328                         len_seen += cam_sglist[i].ds_len;
  329                 }
  330                 break;
  331         }
  332         case CAM_DATA_VADDR:
  333                 cam_sglist = &cam_sg_entry;
  334                 cam_sglist[0].ds_len = ccb->csio.dxfer_len;
  335                 cam_sglist[0].ds_addr = (bus_addr_t)(uintptr_t)ccb->csio.data_ptr;
  336                 cam_sg_count = 1;
  337                 cam_sg_start = 0;
  338                 cam_sg_offset = io->scsiio.kern_rel_offset;
  339                 break;
  340         default:
  341                 panic("Invalid CAM flags %#x", ccb->ccb_h.flags);
  342         }
  343 
  344         if (io->scsiio.kern_sg_entries > 0) {
  345                 ctl_sglist = (struct ctl_sg_entry *)io->scsiio.kern_data_ptr;
  346                 ctl_sg_count = io->scsiio.kern_sg_entries;
  347         } else {
  348                 ctl_sglist = &ctl_sg_entry;
  349                 ctl_sglist->addr = io->scsiio.kern_data_ptr;
  350                 ctl_sglist->len = io->scsiio.kern_data_len;
  351                 ctl_sg_count = 1;
  352         }
  353 
  354         ctl_watermark = 0;
  355         cam_watermark = cam_sg_offset;
  356         for (i = cam_sg_start, j = 0;
  357              i < cam_sg_count && j < ctl_sg_count;) {
  358                 uint8_t *cam_ptr, *ctl_ptr;
  359 
  360                 len_to_copy = MIN(cam_sglist[i].ds_len - cam_watermark,
  361                                   ctl_sglist[j].len - ctl_watermark);
  362 
  363                 cam_ptr = (uint8_t *)(uintptr_t)cam_sglist[i].ds_addr;
  364                 cam_ptr = cam_ptr + cam_watermark;
  365                 if (io->io_hdr.flags & CTL_FLAG_BUS_ADDR) {
  366                         /*
  367                          * XXX KDM fix this!
  368                          */
  369                         panic("need to implement bus address support");
  370 #if 0
  371                         kern_ptr = bus_to_virt(kern_sglist[j].addr);
  372 #endif
  373                 } else
  374                         ctl_ptr = (uint8_t *)ctl_sglist[j].addr;
  375                 ctl_ptr = ctl_ptr + ctl_watermark;
  376 
  377                 if ((io->io_hdr.flags & CTL_FLAG_DATA_MASK) ==
  378                      CTL_FLAG_DATA_IN) {
  379                         CTL_DEBUG_PRINT(("%s: copying %d bytes to CAM\n",
  380                                          __func__, len_to_copy));
  381                         CTL_DEBUG_PRINT(("%s: from %p to %p\n", ctl_ptr,
  382                                          __func__, cam_ptr));
  383                         bcopy(ctl_ptr, cam_ptr, len_to_copy);
  384                 } else {
  385                         CTL_DEBUG_PRINT(("%s: copying %d bytes from CAM\n",
  386                                          __func__, len_to_copy));
  387                         CTL_DEBUG_PRINT(("%s: from %p to %p\n", cam_ptr,
  388                                          __func__, ctl_ptr));
  389                         bcopy(cam_ptr, ctl_ptr, len_to_copy);
  390                 }
  391 
  392                 io->scsiio.ext_data_filled += len_to_copy;
  393                 io->scsiio.kern_data_resid -= len_to_copy;
  394 
  395                 cam_watermark += len_to_copy;
  396                 if (cam_sglist[i].ds_len == cam_watermark) {
  397                         i++;
  398                         cam_watermark = 0;
  399                 }
  400 
  401                 ctl_watermark += len_to_copy;
  402                 if (ctl_sglist[j].len == ctl_watermark) {
  403                         j++;
  404                         ctl_watermark = 0;
  405                 }
  406         }
  407 
  408         if ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS) {
  409                 io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = NULL;
  410                 io->io_hdr.flags |= CTL_FLAG_STATUS_SENT;
  411                 ccb->csio.resid = ccb->csio.dxfer_len -
  412                     io->scsiio.ext_data_filled;
  413                 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
  414                 ccb->ccb_h.status |= CAM_REQ_CMP;
  415                 xpt_done(ccb);
  416         }
  417 
  418         ctl_datamove_done(io, true);
  419 }
  420 
  421 static void
  422 cfcs_done(union ctl_io *io)
  423 {
  424         union ccb *ccb;
  425 
  426         ccb = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
  427         if (ccb == NULL) {
  428                 ctl_free_io(io);
  429                 return;
  430         }
  431 
  432         /*
  433          * At this point we should have status.  If we don't, that's a bug.
  434          */
  435         KASSERT(((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE),
  436                 ("invalid CTL status %#x", io->io_hdr.status));
  437 
  438         /*
  439          * Translate CTL status to CAM status.
  440          */
  441         if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
  442                 ccb->csio.resid = ccb->csio.dxfer_len -
  443                     io->scsiio.ext_data_filled;
  444         }
  445         ccb->ccb_h.status &= ~CAM_STATUS_MASK;
  446         switch (io->io_hdr.status & CTL_STATUS_MASK) {
  447         case CTL_SUCCESS:
  448                 ccb->ccb_h.status |= CAM_REQ_CMP;
  449                 break;
  450         case CTL_SCSI_ERROR:
  451                 ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID;
  452                 ccb->csio.scsi_status = io->scsiio.scsi_status;
  453                 bcopy(&io->scsiio.sense_data, &ccb->csio.sense_data,
  454                       min(io->scsiio.sense_len, ccb->csio.sense_len));
  455                 if (ccb->csio.sense_len > io->scsiio.sense_len)
  456                         ccb->csio.sense_resid = ccb->csio.sense_len -
  457                                                 io->scsiio.sense_len;
  458                 else
  459                         ccb->csio.sense_resid = 0;
  460                 if ((ccb->csio.sense_len - ccb->csio.sense_resid) >
  461                      cfcs_max_sense) {
  462                         ccb->csio.sense_resid = ccb->csio.sense_len -
  463                                                 cfcs_max_sense;
  464                 }
  465                 break;
  466         case CTL_CMD_ABORTED:
  467                 ccb->ccb_h.status |= CAM_REQ_ABORTED;
  468                 break;
  469         case CTL_ERROR:
  470         default:
  471                 ccb->ccb_h.status |= CAM_REQ_CMP_ERR;
  472                 break;
  473         }
  474         ctl_free_io(io);
  475         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP &&
  476             (ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
  477                 xpt_freeze_devq(ccb->ccb_h.path, 1);
  478                 ccb->ccb_h.status |= CAM_DEV_QFRZN;
  479         }
  480         xpt_done(ccb);
  481 }
  482 
  483 void
  484 cfcs_action(struct cam_sim *sim, union ccb *ccb)
  485 {
  486         struct cfcs_softc *softc;
  487         int err;
  488 
  489         softc = (struct cfcs_softc *)cam_sim_softc(sim);
  490 
  491         switch (ccb->ccb_h.func_code) {
  492         case XPT_SCSI_IO: {
  493                 union ctl_io *io;
  494                 struct ccb_scsiio *csio;
  495 
  496                 csio = &ccb->csio;
  497 
  498                 /*
  499                  * Catch CCB flags, like physical address flags, that
  500                  * indicate situations we currently can't handle.
  501                  */
  502                 if (ccb->ccb_h.flags & CFCS_BAD_CCB_FLAGS) {
  503                         ccb->ccb_h.status = CAM_REQ_INVALID;
  504                         printf("%s: bad CCB flags %#x (all flags %#x)\n",
  505                                __func__, ccb->ccb_h.flags & CFCS_BAD_CCB_FLAGS,
  506                                ccb->ccb_h.flags);
  507                         xpt_done(ccb);
  508                         return;
  509                 }
  510 
  511                 /*
  512                  * If we aren't online, there are no devices to see.
  513                  */
  514                 if (softc->online == 0) {
  515                         ccb->ccb_h.status = CAM_DEV_NOT_THERE;
  516                         xpt_done(ccb);
  517                         return;
  518                 }
  519 
  520                 io = ctl_alloc_io_nowait(softc->port.ctl_pool_ref);
  521                 if (io == NULL) {
  522                         printf("%s: can't allocate ctl_io\n", __func__);
  523                         ccb->ccb_h.status = CAM_BUSY | CAM_DEV_QFRZN;
  524                         xpt_freeze_devq(ccb->ccb_h.path, 1);
  525                         xpt_done(ccb);
  526                         return;
  527                 }
  528                 ctl_zero_io(io);
  529                 /* Save pointers on both sides */
  530                 io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = ccb;
  531                 ccb->ccb_h.io_ptr = io;
  532 
  533                 /*
  534                  * Only SCSI I/O comes down this path, resets, etc. come
  535                  * down via the XPT_RESET_BUS/LUN CCBs below.
  536                  */
  537                 io->io_hdr.io_type = CTL_IO_SCSI;
  538                 io->io_hdr.nexus.initid = 1;
  539                 io->io_hdr.nexus.targ_port = softc->port.targ_port;
  540                 io->io_hdr.nexus.targ_lun = ctl_decode_lun(
  541                     CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun));
  542                 io->scsiio.priority = csio->priority;
  543                 /*
  544                  * This tag scheme isn't the best, since we could in theory
  545                  * have a very long-lived I/O and tag collision, especially
  546                  * in a high I/O environment.  But it should work well
  547                  * enough for now.  Since we're using unsigned ints,
  548                  * they'll just wrap around.
  549                  */
  550                 io->scsiio.tag_num = atomic_fetchadd_32(&softc->cur_tag_num, 1);
  551                 csio->tag_id = io->scsiio.tag_num;
  552                 switch (csio->tag_action) {
  553                 case CAM_TAG_ACTION_NONE:
  554                         io->scsiio.tag_type = CTL_TAG_UNTAGGED;
  555                         break;
  556                 case MSG_SIMPLE_TASK:
  557                         io->scsiio.tag_type = CTL_TAG_SIMPLE;
  558                         break;
  559                 case MSG_HEAD_OF_QUEUE_TASK:
  560                         io->scsiio.tag_type = CTL_TAG_HEAD_OF_QUEUE;
  561                         break;
  562                 case MSG_ORDERED_TASK:
  563                         io->scsiio.tag_type = CTL_TAG_ORDERED;
  564                         break;
  565                 case MSG_ACA_TASK:
  566                         io->scsiio.tag_type = CTL_TAG_ACA;
  567                         break;
  568                 default:
  569                         io->scsiio.tag_type = CTL_TAG_UNTAGGED;
  570                         printf("%s: unhandled tag type %#x!!\n", __func__,
  571                                csio->tag_action);
  572                         break;
  573                 }
  574                 if (csio->cdb_len > sizeof(io->scsiio.cdb)) {
  575                         printf("%s: WARNING: CDB len %d > ctl_io space %zd\n",
  576                                __func__, csio->cdb_len, sizeof(io->scsiio.cdb));
  577                 }
  578                 io->scsiio.cdb_len = min(csio->cdb_len, sizeof(io->scsiio.cdb));
  579                 bcopy(scsiio_cdb_ptr(csio), io->scsiio.cdb, io->scsiio.cdb_len);
  580 
  581                 ccb->ccb_h.status |= CAM_SIM_QUEUED;
  582                 err = ctl_queue(io);
  583                 if (err != CTL_RETVAL_COMPLETE) {
  584                         printf("%s: func %d: error %d returned by "
  585                                "ctl_queue()!\n", __func__,
  586                                ccb->ccb_h.func_code, err);
  587                         ctl_free_io(io);
  588                         ccb->ccb_h.status = CAM_REQ_INVALID;
  589                         xpt_done(ccb);
  590                         return;
  591                 }
  592                 break;
  593         }
  594         case XPT_ABORT: {
  595                 union ctl_io *io;
  596                 union ccb *abort_ccb;
  597 
  598                 abort_ccb = ccb->cab.abort_ccb;
  599 
  600                 if (abort_ccb->ccb_h.func_code != XPT_SCSI_IO) {
  601                         ccb->ccb_h.status = CAM_REQ_INVALID;
  602                         xpt_done(ccb);
  603                 }
  604 
  605                 /*
  606                  * If we aren't online, there are no devices to talk to.
  607                  */
  608                 if (softc->online == 0) {
  609                         ccb->ccb_h.status = CAM_DEV_NOT_THERE;
  610                         xpt_done(ccb);
  611                         return;
  612                 }
  613 
  614                 io = ctl_alloc_io_nowait(softc->port.ctl_pool_ref);
  615                 if (io == NULL) {
  616                         ccb->ccb_h.status = CAM_BUSY | CAM_DEV_QFRZN;
  617                         xpt_freeze_devq(ccb->ccb_h.path, 1);
  618                         xpt_done(ccb);
  619                         return;
  620                 }
  621 
  622                 ctl_zero_io(io);
  623                 /* Save pointers on both sides */
  624                 io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = ccb;
  625                 ccb->ccb_h.io_ptr = io;
  626 
  627                 io->io_hdr.io_type = CTL_IO_TASK;
  628                 io->io_hdr.nexus.initid = 1;
  629                 io->io_hdr.nexus.targ_port = softc->port.targ_port;
  630                 io->io_hdr.nexus.targ_lun = ctl_decode_lun(
  631                     CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun));
  632                 io->taskio.task_action = CTL_TASK_ABORT_TASK;
  633                 io->taskio.tag_num = abort_ccb->csio.tag_id;
  634                 switch (abort_ccb->csio.tag_action) {
  635                 case CAM_TAG_ACTION_NONE:
  636                         io->taskio.tag_type = CTL_TAG_UNTAGGED;
  637                         break;
  638                 case MSG_SIMPLE_TASK:
  639                         io->taskio.tag_type = CTL_TAG_SIMPLE;
  640                         break;
  641                 case MSG_HEAD_OF_QUEUE_TASK:
  642                         io->taskio.tag_type = CTL_TAG_HEAD_OF_QUEUE;
  643                         break;
  644                 case MSG_ORDERED_TASK:
  645                         io->taskio.tag_type = CTL_TAG_ORDERED;
  646                         break;
  647                 case MSG_ACA_TASK:
  648                         io->taskio.tag_type = CTL_TAG_ACA;
  649                         break;
  650                 default:
  651                         io->taskio.tag_type = CTL_TAG_UNTAGGED;
  652                         printf("%s: unhandled tag type %#x!!\n", __func__,
  653                                abort_ccb->csio.tag_action);
  654                         break;
  655                 }
  656                 err = ctl_queue(io);
  657                 if (err != CTL_RETVAL_COMPLETE) {
  658                         printf("%s func %d: error %d returned by "
  659                                "ctl_queue()!\n", __func__,
  660                                ccb->ccb_h.func_code, err);
  661                         ctl_free_io(io);
  662                 }
  663                 break;
  664         }
  665         case XPT_GET_TRAN_SETTINGS: {
  666                 struct ccb_trans_settings *cts;
  667                 struct ccb_trans_settings_scsi *scsi;
  668                 struct ccb_trans_settings_fc *fc;
  669 
  670                 cts = &ccb->cts;
  671                 scsi = &cts->proto_specific.scsi;
  672                 fc = &cts->xport_specific.fc;
  673 
  674                 
  675                 cts->protocol = PROTO_SCSI;
  676                 cts->protocol_version = SCSI_REV_SPC2;
  677                 cts->transport = XPORT_FC;
  678                 cts->transport_version = 0;
  679 
  680                 scsi->valid = CTS_SCSI_VALID_TQ;
  681                 scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
  682                 fc->valid = CTS_FC_VALID_SPEED;
  683                 fc->bitrate = 800000;
  684                 fc->wwnn = softc->wwnn;
  685                 fc->wwpn = softc->wwpn;
  686                 fc->port = softc->port.targ_port;
  687                 fc->valid |= CTS_FC_VALID_WWNN | CTS_FC_VALID_WWPN |
  688                         CTS_FC_VALID_PORT; 
  689                 ccb->ccb_h.status = CAM_REQ_CMP;
  690                 break;
  691         }
  692         case XPT_SET_TRAN_SETTINGS:
  693                 /* XXX KDM should we actually do something here? */
  694                 ccb->ccb_h.status = CAM_REQ_CMP;
  695                 break;
  696         case XPT_RESET_BUS:
  697         case XPT_RESET_DEV: {
  698                 union ctl_io *io;
  699 
  700                 /*
  701                  * If we aren't online, there are no devices to talk to.
  702                  */
  703                 if (softc->online == 0) {
  704                         ccb->ccb_h.status = CAM_DEV_NOT_THERE;
  705                         xpt_done(ccb);
  706                         return;
  707                 }
  708 
  709                 io = ctl_alloc_io_nowait(softc->port.ctl_pool_ref);
  710                 if (io == NULL) {
  711                         ccb->ccb_h.status = CAM_BUSY | CAM_DEV_QFRZN;
  712                         xpt_freeze_devq(ccb->ccb_h.path, 1);
  713                         xpt_done(ccb);
  714                         return;
  715                 }
  716 
  717                 ctl_zero_io(io);
  718                 /* Save pointers on both sides */
  719                 if (ccb->ccb_h.func_code == XPT_RESET_DEV)
  720                         io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = ccb;
  721                 ccb->ccb_h.io_ptr = io;
  722 
  723                 io->io_hdr.io_type = CTL_IO_TASK;
  724                 io->io_hdr.nexus.initid = 1;
  725                 io->io_hdr.nexus.targ_port = softc->port.targ_port;
  726                 io->io_hdr.nexus.targ_lun = ctl_decode_lun(
  727                     CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun));
  728                 if (ccb->ccb_h.func_code == XPT_RESET_BUS)
  729                         io->taskio.task_action = CTL_TASK_BUS_RESET;
  730                 else
  731                         io->taskio.task_action = CTL_TASK_LUN_RESET;
  732 
  733                 err = ctl_queue(io);
  734                 if (err != CTL_RETVAL_COMPLETE) {
  735                         printf("%s func %d: error %d returned by "
  736                               "ctl_queue()!\n", __func__,
  737                               ccb->ccb_h.func_code, err);
  738                         ctl_free_io(io);
  739                 }
  740                 break;
  741         }
  742         case XPT_CALC_GEOMETRY:
  743                 cam_calc_geometry(&ccb->ccg, 1);
  744                 xpt_done(ccb);
  745                 break;
  746         case XPT_PATH_INQ: {
  747                 struct ccb_pathinq *cpi;
  748 
  749                 cpi = &ccb->cpi;
  750 
  751                 cpi->version_num = 0;
  752                 cpi->hba_inquiry = PI_TAG_ABLE;
  753                 cpi->target_sprt = 0;
  754                 cpi->hba_misc = PIM_EXTLUNS;
  755                 cpi->hba_eng_cnt = 0;
  756                 cpi->max_target = 0;
  757                 cpi->max_lun = 1024;
  758                 /* Do we really have a limit? */
  759                 cpi->maxio = 1024 * 1024;
  760                 cpi->async_flags = 0;
  761                 cpi->hpath_id = 0;
  762                 cpi->initiator_id = 1;
  763 
  764                 strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
  765                 strlcpy(cpi->hba_vid, "FreeBSD", HBA_IDLEN);
  766                 strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
  767                 cpi->unit_number = 0;
  768                 cpi->bus_id = 0;
  769                 cpi->base_transfer_speed = 800000;
  770                 cpi->protocol = PROTO_SCSI;
  771                 cpi->protocol_version = SCSI_REV_SPC2;
  772                 /*
  773                  * Pretend to be Fibre Channel.
  774                  */
  775                 cpi->transport = XPORT_FC;
  776                 cpi->transport_version = 0;
  777                 cpi->xport_specific.fc.wwnn = softc->wwnn;
  778                 cpi->xport_specific.fc.wwpn = softc->wwpn;
  779                 cpi->xport_specific.fc.port = softc->port.targ_port;
  780                 cpi->xport_specific.fc.bitrate = 8 * 1000 * 1000;
  781                 cpi->ccb_h.status = CAM_REQ_CMP;
  782                 break;
  783         }
  784         default:
  785                 ccb->ccb_h.status = CAM_PROVIDE_FAIL;
  786                 printf("%s: unsupported CCB type %#x\n", __func__,
  787                        ccb->ccb_h.func_code);
  788                 xpt_done(ccb);
  789                 break;
  790         }
  791 }

Cache object: fcce1a3080b31df13e1be70bd7724026


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