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/iscsi_initiator/isc_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) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
    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 /*
   28  | $Id: isc_cam.c 998 2009-12-20 10:32:45Z danny $
   29  */
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD: releng/10.0/sys/dev/iscsi_initiator/isc_cam.c 254657 2013-08-22 14:02:34Z trasz $");
   32 
   33 #include "opt_iscsi_initiator.h"
   34 
   35 #include <sys/param.h>
   36 #include <sys/kernel.h>
   37 #include <sys/callout.h>
   38 #if __FreeBSD_version >= 700000
   39 #include <sys/lock.h>
   40 #include <sys/mutex.h>
   41 #endif
   42 #include <sys/conf.h>
   43 #include <sys/systm.h>
   44 #include <sys/malloc.h>
   45 #include <sys/mbuf.h>
   46 #include <sys/uio.h>
   47 #include <sys/sysctl.h>
   48 #include <sys/sx.h>
   49 
   50 #include <cam/cam.h>
   51 #include <cam/cam_ccb.h>
   52 #include <cam/cam_sim.h>
   53 #include <cam/cam_xpt_sim.h>
   54 #include <cam/cam_periph.h>
   55 
   56 #include <dev/iscsi_initiator/iscsi.h>
   57 #include <dev/iscsi_initiator/iscsivar.h>
   58 
   59 static void
   60 _inq(struct cam_sim *sim, union ccb *ccb)
   61 {
   62      struct ccb_pathinq *cpi = &ccb->cpi;
   63      isc_session_t *sp = cam_sim_softc(sim);
   64 
   65      debug_called(8);
   66      debug(3, "sid=%d target=%d lun=%d", sp->sid, ccb->ccb_h.target_id, ccb->ccb_h.target_lun);
   67 
   68      cpi->version_num = 1; /* XXX??? */
   69      cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE | PI_WIDE_32;
   70      cpi->target_sprt = 0;
   71      cpi->hba_misc = 0;
   72      cpi->hba_eng_cnt = 0;
   73      cpi->max_target = 0; //ISCSI_MAX_TARGETS - 1;
   74      cpi->initiator_id = ISCSI_MAX_TARGETS;
   75      cpi->max_lun = sp->opt.maxluns - 1;
   76      cpi->bus_id = cam_sim_bus(sim);
   77      cpi->base_transfer_speed = 3300; // 40000; // XXX:
   78      strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
   79      strncpy(cpi->hba_vid, "iSCSI", HBA_IDLEN);
   80      strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
   81      cpi->unit_number = cam_sim_unit(sim);
   82      cpi->ccb_h.status = CAM_REQ_CMP;
   83 #if defined(KNOB_VALID_ADDRESS)
   84      cpi->transport = XPORT_ISCSI;
   85      cpi->transport_version = 0;
   86 #endif
   87 }
   88 
   89 static __inline int
   90 _scsi_encap(struct cam_sim *sim, union ccb *ccb)
   91 {
   92      int                ret;
   93 
   94 #if __FreeBSD_version < 700000
   95      ret = scsi_encap(sim, ccb);
   96 #else
   97      isc_session_t      *sp = cam_sim_softc(sim);
   98 
   99      mtx_unlock(&sp->cam_mtx);
  100      ret = scsi_encap(sim, ccb);
  101      mtx_lock(&sp->cam_mtx);
  102 #endif
  103      return ret;
  104 }
  105 
  106 void
  107 ic_lost_target(isc_session_t *sp, int target)
  108 {
  109      debug_called(8);
  110      sdebug(2, "lost target=%d", target);
  111 
  112      if(sp->cam_path != NULL) {
  113           mtx_lock(&sp->cam_mtx);
  114           xpt_async(AC_LOST_DEVICE, sp->cam_path, NULL);
  115           xpt_free_path(sp->cam_path);
  116           mtx_unlock(&sp->cam_mtx);
  117           sp->cam_path = 0; // XXX
  118      }
  119 }
  120 
  121 static void
  122 scan_callback(struct cam_periph *periph, union ccb *ccb)
  123 {
  124      isc_session_t *sp = (isc_session_t *)ccb->ccb_h.spriv_ptr0;
  125 
  126      debug_called(8);
  127 
  128      free(ccb, M_TEMP);
  129 
  130      if(sp->flags & ISC_SCANWAIT) {
  131           sp->flags &= ~ISC_SCANWAIT;
  132           wakeup(sp);
  133      }
  134 }
  135 
  136 static int
  137 ic_scan(isc_session_t *sp)
  138 {
  139      union ccb  *ccb;
  140 
  141      debug_called(8);
  142      sdebug(2, "scanning sid=%d", sp->sid);
  143 
  144      if((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK | M_ZERO)) == NULL) {
  145           xdebug("scan failed (can't allocate CCB)");
  146           return ENOMEM; // XXX
  147      }
  148 
  149      sp->flags &= ~ISC_CAMDEVS;
  150      sp->flags |= ISC_SCANWAIT;
  151 
  152      CAM_LOCK(sp);
  153      if(xpt_create_path(&sp->cam_path, NULL, cam_sim_path(sp->cam_sim),
  154                         0, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
  155           xdebug("can't create cam path");
  156           CAM_UNLOCK(sp);
  157           free(ccb, M_TEMP);
  158           return ENODEV; // XXX
  159      }
  160      xpt_setup_ccb(&ccb->ccb_h, sp->cam_path, 5/*priority (low)*/);
  161      ccb->ccb_h.func_code       = XPT_SCAN_BUS;
  162      ccb->ccb_h.cbfcnp          = scan_callback;
  163      ccb->crcn.flags            = CAM_FLAG_NONE;
  164      ccb->ccb_h.spriv_ptr0      = sp;
  165 
  166      xpt_action(ccb);
  167      CAM_UNLOCK(sp);
  168 
  169      while(sp->flags & ISC_SCANWAIT)
  170           tsleep(sp, PRIBIO, "ffp", 5*hz); // the timeout time should
  171                                             // be configurable
  172      sdebug(2, "# of luns=%d", sp->target_nluns);
  173 
  174      if(sp->target_nluns > 0) {
  175           sp->flags |= ISC_CAMDEVS;
  176           return 0;
  177      }
  178 
  179      return ENODEV;
  180 }
  181 
  182 static void
  183 ic_action(struct cam_sim *sim, union ccb *ccb)
  184 {
  185      isc_session_t      *sp = cam_sim_softc(sim);
  186      struct ccb_hdr     *ccb_h = &ccb->ccb_h;
  187 
  188      debug_called(8);
  189 
  190      ccb_h->spriv_ptr0 = sp;
  191      sdebug(4, "func_code=0x%x flags=0x%x status=0x%x target=%d lun=%d retry_count=%d timeout=%d",
  192            ccb_h->func_code, ccb->ccb_h.flags, ccb->ccb_h.status,
  193            ccb->ccb_h.target_id, ccb->ccb_h.target_lun, 
  194            ccb->ccb_h.retry_count, ccb_h->timeout);
  195      if(sp == NULL) {
  196           xdebug("sp == NULL! cannot happen");
  197           return;
  198      }    
  199      switch(ccb_h->func_code) {
  200      case XPT_PATH_INQ:
  201           _inq(sim, ccb);
  202           break;
  203 
  204      case XPT_RESET_BUS: // (can just be a stub that does nothing and completes)
  205      {
  206           struct ccb_pathinq *cpi = &ccb->cpi;
  207 
  208           debug(3, "XPT_RESET_BUS");
  209           cpi->ccb_h.status = CAM_REQ_CMP;
  210           break;
  211      }
  212 
  213      case XPT_SCSI_IO: 
  214      {
  215           struct ccb_scsiio* csio = &ccb->csio;
  216 
  217           debug(4, "XPT_SCSI_IO cmd=0x%x", csio->cdb_io.cdb_bytes[0]);
  218           if(sp == NULL) {
  219                ccb_h->status = CAM_REQ_INVALID; //CAM_NO_NEXUS;
  220                debug(4, "xpt_done.status=%d", ccb_h->status);
  221                break;
  222           }
  223           if(ccb_h->target_lun == CAM_LUN_WILDCARD) {
  224                debug(3, "target=%d: bad lun (-1)", ccb_h->target_id);
  225                ccb_h->status = CAM_LUN_INVALID;
  226                break;
  227           }
  228           if(_scsi_encap(sim, ccb) != 0)
  229                return;
  230           break;
  231      }
  232  
  233      case XPT_CALC_GEOMETRY:
  234      {
  235           struct        ccb_calc_geometry *ccg;
  236 
  237           ccg = &ccb->ccg;
  238           debug(4, "sid=%d target=%d lun=%d XPT_CALC_GEOMETRY vsize=%jd bsize=%d",
  239                 sp->sid, ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
  240                 ccg->volume_size, ccg->block_size);
  241           if(ccg->block_size == 0 ||
  242              (ccg->volume_size < ccg->block_size)) {
  243                // print error message  ...
  244                /* XXX: what error is appropiate? */
  245                break;
  246           } 
  247           else {
  248                int      lun, *off, boff;
  249 
  250                lun = ccb->ccb_h.target_lun;
  251                if(lun > ISCSI_MAX_LUNS) {
  252                     // XXX: 
  253                     xdebug("lun %d > ISCSI_MAX_LUNS!\n", lun);
  254                     lun %= ISCSI_MAX_LUNS;
  255                }
  256                off = &sp->target_lun[lun / (sizeof(int)*8)];
  257                boff = BIT(lun % (sizeof(int)*8));
  258                debug(4, "sp->target_nluns=%d *off=%x boff=%x",
  259                      sp->target_nluns, *off, boff);
  260 
  261                if((*off & boff) == 0) {
  262                     sp->target_nluns++;
  263                     *off |= boff;
  264                }
  265                cam_calc_geometry(ccg, /*extended*/1);
  266           }
  267           break;
  268      }
  269 
  270      case XPT_GET_TRAN_SETTINGS:
  271      default:
  272           ccb_h->status = CAM_REQ_INVALID;
  273           break;
  274      }
  275 #if __FreeBSD_version < 700000
  276      XPT_DONE(sp, ccb);
  277 #else
  278      xpt_done(ccb);
  279 #endif
  280      return;
  281 }
  282 
  283 static void
  284 ic_poll(struct cam_sim *sim)
  285 {
  286      debug_called(4);
  287 
  288 }
  289 
  290 int
  291 ic_getCamVals(isc_session_t *sp, iscsi_cam_t *cp)
  292 {
  293      debug_called(8);
  294 
  295      if(sp && sp->cam_sim) {
  296           cp->path_id = cam_sim_path(sp->cam_sim);
  297           cp->target_id = 0;
  298           cp->target_nluns = ISCSI_MAX_LUNS; // XXX: -1?
  299           return 0;
  300      }
  301      return ENXIO;
  302 }
  303 
  304 void
  305 ic_destroy(isc_session_t *sp )
  306 {
  307      debug_called(8);
  308 
  309      if(sp->cam_path != NULL) {
  310           sdebug(2, "name=%s unit=%d",
  311                  cam_sim_name(sp->cam_sim), cam_sim_unit(sp->cam_sim));
  312           CAM_LOCK(sp);
  313 #if 0
  314           xpt_async(AC_LOST_DEVICE, sp->cam_path, NULL);
  315 #else
  316           xpt_async(XPT_RESET_BUS, sp->cam_path, NULL);
  317 #endif
  318           xpt_free_path(sp->cam_path);
  319           xpt_bus_deregister(cam_sim_path(sp->cam_sim));
  320           cam_sim_free(sp->cam_sim, TRUE /*free_devq*/);
  321 
  322           CAM_UNLOCK(sp);
  323           sdebug(2, "done");
  324      }
  325 }
  326 
  327 int
  328 ic_init(isc_session_t *sp)
  329 {
  330      struct cam_sim     *sim;
  331      struct cam_devq    *devq;
  332 
  333      debug_called(8);
  334 
  335      if((devq = cam_simq_alloc(256)) == NULL)
  336           return ENOMEM;
  337 
  338 #if __FreeBSD_version >= 700000
  339      mtx_init(&sp->cam_mtx, "isc-cam", NULL, MTX_DEF);
  340 #else
  341      isp->cam_mtx = Giant;
  342 #endif
  343      sim = cam_sim_alloc(ic_action,
  344                          ic_poll,
  345                          "iscsi",
  346                          sp,
  347                          sp->sid,       // unit
  348 #if __FreeBSD_version >= 700000
  349                          &sp->cam_mtx,
  350 #endif
  351                          1,             // max_dev_transactions
  352                          0,             // max_tagged_dev_transactions
  353                          devq);
  354      if(sim == NULL) {
  355           cam_simq_free(devq);
  356 #if __FreeBSD_version >= 700000
  357           mtx_destroy(&sp->cam_mtx);
  358 #endif
  359           return ENXIO;
  360      }
  361 
  362      CAM_LOCK(sp);
  363      if(xpt_bus_register(sim,
  364 #if __FreeBSD_version >= 700000
  365                          NULL,
  366 #endif
  367                          0/*bus_number*/) != CAM_SUCCESS) {
  368 
  369           cam_sim_free(sim, /*free_devq*/TRUE);
  370           CAM_UNLOCK(sp);
  371 #if __FreeBSD_version >= 700000
  372           mtx_destroy(&sp->cam_mtx);
  373 #endif
  374           return ENXIO;
  375      }
  376      sp->cam_sim = sim;
  377      CAM_UNLOCK(sp);
  378 
  379      sdebug(1, "cam subsystem initialized");
  380 
  381      ic_scan(sp);
  382 
  383      return 0;
  384 }

Cache object: e052ce650eca0bff5f90d29046540629


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