1e25c779eSMatthew Dillon /*- 2e25c779eSMatthew Dillon * Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il> 3e25c779eSMatthew Dillon * All rights reserved. 4e25c779eSMatthew Dillon * 5e25c779eSMatthew Dillon * Redistribution and use in source and binary forms, with or without 6e25c779eSMatthew Dillon * modification, are permitted provided that the following conditions 7e25c779eSMatthew Dillon * are met: 8e25c779eSMatthew Dillon * 1. Redistributions of source code must retain the above copyright 9e25c779eSMatthew Dillon * notice, this list of conditions and the following disclaimer. 10e25c779eSMatthew Dillon * 2. Redistributions in binary form must reproduce the above copyright 11e25c779eSMatthew Dillon * notice, this list of conditions and the following disclaimer in the 12e25c779eSMatthew Dillon * documentation and/or other materials provided with the distribution. 13e25c779eSMatthew Dillon * 14e25c779eSMatthew Dillon * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15e25c779eSMatthew Dillon * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16e25c779eSMatthew Dillon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17e25c779eSMatthew Dillon * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18e25c779eSMatthew Dillon * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19e25c779eSMatthew Dillon * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20e25c779eSMatthew Dillon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21e25c779eSMatthew Dillon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22e25c779eSMatthew Dillon * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23e25c779eSMatthew Dillon * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24e25c779eSMatthew Dillon * SUCH DAMAGE. 25e25c779eSMatthew Dillon * 26e25c779eSMatthew Dillon * $FreeBSD: src/sys/dev/iscsi/initiator/isc_cam.c,v 1.3 2008/11/25 07:17:11 scottl Exp $ 27e25c779eSMatthew Dillon */ 28e25c779eSMatthew Dillon 29e25c779eSMatthew Dillon #include <sys/param.h> 30e25c779eSMatthew Dillon #include <sys/kernel.h> 31e25c779eSMatthew Dillon #include <sys/callout.h> 32e25c779eSMatthew Dillon #include <sys/lock.h> 33e25c779eSMatthew Dillon #include <sys/conf.h> 34e25c779eSMatthew Dillon #include <sys/systm.h> 35e25c779eSMatthew Dillon #include <sys/malloc.h> 36e25c779eSMatthew Dillon #include <sys/mbuf.h> 37e25c779eSMatthew Dillon #include <sys/uio.h> 38e25c779eSMatthew Dillon #include <sys/sysctl.h> 39e25c779eSMatthew Dillon #include <sys/eventhandler.h> 40265af2b5SMatthew Dillon #include <sys/globaldata.h> 41e25c779eSMatthew Dillon #include <sys/mutex2.h> 42e25c779eSMatthew Dillon 43e25c779eSMatthew Dillon #include <bus/cam/cam.h> 44e25c779eSMatthew Dillon #include <bus/cam/cam_ccb.h> 45e25c779eSMatthew Dillon #include <bus/cam/cam_sim.h> 46*cec957e9SMatthew Dillon #include <bus/cam/cam_xpt.h> 47e25c779eSMatthew Dillon #include <bus/cam/cam_xpt_sim.h> 48*cec957e9SMatthew Dillon #include <bus/cam/cam_xpt_periph.h> 49e25c779eSMatthew Dillon #include <bus/cam/cam_periph.h> 50e25c779eSMatthew Dillon 51e25c779eSMatthew Dillon #include <dev/disk/iscsi/initiator/iscsi.h> 52e25c779eSMatthew Dillon #include <dev/disk/iscsi/initiator/iscsivar.h> 53e25c779eSMatthew Dillon 54e25c779eSMatthew Dillon // XXX: untested/incomplete 55e25c779eSMatthew Dillon void 56e25c779eSMatthew Dillon ic_freeze(isc_session_t *sp) 57e25c779eSMatthew Dillon { 58e25c779eSMatthew Dillon debug_called(8); 59e25c779eSMatthew Dillon #if 0 60e25c779eSMatthew Dillon sdebug(2, "freezing path=%p", sp->cam_path == NULL? 0: sp->cam_path); 61e25c779eSMatthew Dillon if((sp->cam_path != NULL) && !(sp->flags & ISC_FROZEN)) { 62e25c779eSMatthew Dillon xpt_freeze_devq(sp->cam_path, 1); 63e25c779eSMatthew Dillon } 64e25c779eSMatthew Dillon #endif 65e25c779eSMatthew Dillon sp->flags |= ISC_FROZEN; 66e25c779eSMatthew Dillon } 67e25c779eSMatthew Dillon 68e25c779eSMatthew Dillon // XXX: untested/incomplete 69e25c779eSMatthew Dillon void 70e25c779eSMatthew Dillon ic_release(isc_session_t *sp) 71e25c779eSMatthew Dillon { 72e25c779eSMatthew Dillon debug_called(8); 73e25c779eSMatthew Dillon #if 0 74e25c779eSMatthew Dillon sdebug(2, "release path=%p", sp->cam_path == NULL? 0: sp->cam_path); 75e25c779eSMatthew Dillon if((sp->cam_path != NULL) && (sp->flags & ISC_FROZEN)) { 76e25c779eSMatthew Dillon xpt_release_devq(sp->cam_path, 1, TRUE); 77e25c779eSMatthew Dillon } 78e25c779eSMatthew Dillon #endif 79e25c779eSMatthew Dillon sp->flags &= ~ISC_FROZEN; 80e25c779eSMatthew Dillon } 81e25c779eSMatthew Dillon 82e25c779eSMatthew Dillon void 83e25c779eSMatthew Dillon ic_lost_target(isc_session_t *sp, int target) 84e25c779eSMatthew Dillon { 85e25c779eSMatthew Dillon struct isc_softc *isp = sp->isc; 86e25c779eSMatthew Dillon 87e25c779eSMatthew Dillon debug_called(8); 88e25c779eSMatthew Dillon sdebug(2, "target=%d", target); 89e25c779eSMatthew Dillon if(sp->cam_path != NULL) { 90e25c779eSMatthew Dillon lockmgr(&isp->cam_lock, LK_EXCLUSIVE); 91e25c779eSMatthew Dillon xpt_async(AC_LOST_DEVICE, sp->cam_path, NULL); 92e25c779eSMatthew Dillon xpt_free_path(sp->cam_path); 93e25c779eSMatthew Dillon lockmgr(&isp->cam_lock, LK_RELEASE); 94e25c779eSMatthew Dillon sp->cam_path = 0; // XXX 95e25c779eSMatthew Dillon } 96e25c779eSMatthew Dillon } 97e25c779eSMatthew Dillon 98e25c779eSMatthew Dillon static void 99e25c779eSMatthew Dillon _scan_callback(struct cam_periph *periph, union ccb *ccb) 100e25c779eSMatthew Dillon { 101e25c779eSMatthew Dillon isc_session_t *sp = (isc_session_t *)ccb->ccb_h.spriv_ptr0; 102e25c779eSMatthew Dillon 103e25c779eSMatthew Dillon debug_called(8); 104e25c779eSMatthew Dillon 105*cec957e9SMatthew Dillon xpt_free_ccb(&ccb->ccb_h); 106e25c779eSMatthew Dillon if (sp->flags & ISC_FFPWAIT) { 107e25c779eSMatthew Dillon sp->flags &= ~ISC_FFPWAIT; 108e25c779eSMatthew Dillon wakeup(sp); 109e25c779eSMatthew Dillon } 110e25c779eSMatthew Dillon } 111e25c779eSMatthew Dillon 112e25c779eSMatthew Dillon static void 113e25c779eSMatthew Dillon _scan_target(isc_session_t *sp, int target) 114e25c779eSMatthew Dillon { 115e25c779eSMatthew Dillon union ccb *ccb; 116e25c779eSMatthew Dillon 117e25c779eSMatthew Dillon debug_called(8); 118e25c779eSMatthew Dillon sdebug(2, "target=%d", target); 119e25c779eSMatthew Dillon 120*cec957e9SMatthew Dillon ccb = xpt_alloc_ccb(); 121*cec957e9SMatthew Dillon 122e25c779eSMatthew Dillon CAM_LOCK(sp->isc); 123e25c779eSMatthew Dillon xpt_setup_ccb(&ccb->ccb_h, sp->cam_path, 5/*priority (low)*/); 124e25c779eSMatthew Dillon ccb->ccb_h.func_code = XPT_SCAN_BUS; 125e25c779eSMatthew Dillon ccb->ccb_h.cbfcnp = _scan_callback; 126e25c779eSMatthew Dillon ccb->crcn.flags = CAM_FLAG_NONE; 127e25c779eSMatthew Dillon ccb->ccb_h.spriv_ptr0 = sp; 128e25c779eSMatthew Dillon 129e25c779eSMatthew Dillon xpt_action(ccb); 130e25c779eSMatthew Dillon CAM_UNLOCK(sp->isc); 131e25c779eSMatthew Dillon } 132e25c779eSMatthew Dillon 133e25c779eSMatthew Dillon int 134e25c779eSMatthew Dillon ic_fullfeature(struct cdev *dev) 135e25c779eSMatthew Dillon { 136e25c779eSMatthew Dillon struct isc_softc *isp = dev->si_drv1; 137e25c779eSMatthew Dillon isc_session_t *sp = (isc_session_t *)dev->si_drv2; 138e25c779eSMatthew Dillon 139e25c779eSMatthew Dillon debug_called(8); 140e25c779eSMatthew Dillon sdebug(3, "dev=%d sc=%p", minor(dev), isp); 141e25c779eSMatthew Dillon 142e25c779eSMatthew Dillon sp->flags &= ~ISC_FFPHASE; 143e25c779eSMatthew Dillon sp->flags |= ISC_FFPWAIT; 144e25c779eSMatthew Dillon 145e25c779eSMatthew Dillon CAM_LOCK(isp); 146e25c779eSMatthew Dillon if(xpt_create_path(&sp->cam_path, xpt_periph, cam_sim_path(sp->isc->cam_sim), 147e25c779eSMatthew Dillon sp->sid, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 148e25c779eSMatthew Dillon xdebug("can't create cam path"); 149e25c779eSMatthew Dillon CAM_UNLOCK(isp); 150e25c779eSMatthew Dillon return ENODEV; // XXX 151e25c779eSMatthew Dillon } 152e25c779eSMatthew Dillon CAM_UNLOCK(isp); 153e25c779eSMatthew Dillon 154e25c779eSMatthew Dillon _scan_target(sp, sp->sid); 155e25c779eSMatthew Dillon 156e25c779eSMatthew Dillon while(sp->flags & ISC_FFPWAIT) 157e25c779eSMatthew Dillon tsleep(sp, 0, "ffp", 5*hz); // timeout should be configurable 158e25c779eSMatthew Dillon if(sp->target_nluns > 0) { 159e25c779eSMatthew Dillon sp->flags |= ISC_FFPHASE; 160e25c779eSMatthew Dillon return 0; 161e25c779eSMatthew Dillon } 162e25c779eSMatthew Dillon 163e25c779eSMatthew Dillon return ENODEV; 164e25c779eSMatthew Dillon } 165e25c779eSMatthew Dillon 166e25c779eSMatthew Dillon static void 167e25c779eSMatthew Dillon _inq(struct cam_sim *sim, union ccb *ccb, int maxluns) 168e25c779eSMatthew Dillon { 169e25c779eSMatthew Dillon struct ccb_pathinq *cpi = &ccb->cpi; 170e25c779eSMatthew Dillon 171e25c779eSMatthew Dillon debug_called(4); 172e25c779eSMatthew Dillon 173e25c779eSMatthew Dillon cpi->version_num = 1; /* XXX??? */ 174e25c779eSMatthew Dillon cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE | PI_WIDE_32; 175e25c779eSMatthew Dillon cpi->target_sprt = 0; 176e25c779eSMatthew Dillon cpi->hba_misc = 0; 177e25c779eSMatthew Dillon cpi->hba_eng_cnt = 0; 178e25c779eSMatthew Dillon cpi->max_target = ISCSI_MAX_TARGETS - 1; 179e25c779eSMatthew Dillon cpi->initiator_id = ISCSI_MAX_TARGETS; 180e25c779eSMatthew Dillon cpi->max_lun = maxluns; 181e25c779eSMatthew Dillon cpi->bus_id = cam_sim_bus(sim); 182e25c779eSMatthew Dillon cpi->base_transfer_speed = 3300; 183e25c779eSMatthew Dillon strncpy(cpi->sim_vid, "DragonFly", SIM_IDLEN); 184e25c779eSMatthew Dillon strncpy(cpi->hba_vid, "iSCSI", HBA_IDLEN); 185e25c779eSMatthew Dillon strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 186e25c779eSMatthew Dillon cpi->unit_number = cam_sim_unit(sim); 187e25c779eSMatthew Dillon cpi->ccb_h.status = CAM_REQ_CMP; 188e25c779eSMatthew Dillon } 189e25c779eSMatthew Dillon 190e25c779eSMatthew Dillon static __inline int 191e25c779eSMatthew Dillon _scsi_encap(struct cam_sim *sim, union ccb *ccb) 192e25c779eSMatthew Dillon { 193e25c779eSMatthew Dillon int ret; 194e25c779eSMatthew Dillon struct isc_softc *isp = (struct isc_softc *)cam_sim_softc(sim); 195e25c779eSMatthew Dillon 196e25c779eSMatthew Dillon lockmgr(&isp->cam_lock, LK_EXCLUSIVE); 197e25c779eSMatthew Dillon ret = scsi_encap(sim, ccb); 198e25c779eSMatthew Dillon lockmgr(&isp->cam_lock, LK_RELEASE); 199e25c779eSMatthew Dillon return ret; 200e25c779eSMatthew Dillon } 201e25c779eSMatthew Dillon 202e25c779eSMatthew Dillon static void 203e25c779eSMatthew Dillon ic_action(struct cam_sim *sim, union ccb *ccb) 204e25c779eSMatthew Dillon { 205e25c779eSMatthew Dillon struct ccb_hdr *ccb_h = &ccb->ccb_h; 206e25c779eSMatthew Dillon struct isc_softc *isp = (struct isc_softc *)cam_sim_softc(sim); 207e25c779eSMatthew Dillon isc_session_t *sp; 208e25c779eSMatthew Dillon 209e25c779eSMatthew Dillon debug_called(8); 210e25c779eSMatthew Dillon 211e25c779eSMatthew Dillon if((ccb_h->target_id != CAM_TARGET_WILDCARD) && (ccb_h->target_id < MAX_SESSIONS)) 212e25c779eSMatthew Dillon sp = isp->sessions[ccb_h->target_id]; 213e25c779eSMatthew Dillon else 214e25c779eSMatthew Dillon sp = NULL; 215e25c779eSMatthew Dillon 216e25c779eSMatthew Dillon ccb_h->spriv_ptr0 = sp; 217e25c779eSMatthew Dillon 218e25c779eSMatthew Dillon debug(4, "func_code=0x%x flags=0x%x status=0x%x target=%d lun=%d retry_count=%d timeout=%d", 219e25c779eSMatthew Dillon ccb_h->func_code, ccb->ccb_h.flags, ccb->ccb_h.status, 220e25c779eSMatthew Dillon ccb->ccb_h.target_id, ccb->ccb_h.target_lun, 221e25c779eSMatthew Dillon ccb->ccb_h.retry_count, ccb_h->timeout); 222e25c779eSMatthew Dillon /* 223e25c779eSMatthew Dillon | first quick check 224e25c779eSMatthew Dillon */ 225e25c779eSMatthew Dillon switch(ccb_h->func_code) { 226e25c779eSMatthew Dillon default: 227e25c779eSMatthew Dillon // XXX: maybe check something else? 228e25c779eSMatthew Dillon break; 229e25c779eSMatthew Dillon 230e25c779eSMatthew Dillon case XPT_SCSI_IO: 231e25c779eSMatthew Dillon case XPT_RESET_DEV: 232e25c779eSMatthew Dillon case XPT_GET_TRAN_SETTINGS: 233e25c779eSMatthew Dillon case XPT_SET_TRAN_SETTINGS: 234e25c779eSMatthew Dillon case XPT_CALC_GEOMETRY: 235e25c779eSMatthew Dillon if(sp == NULL) { 236e25c779eSMatthew Dillon ccb->ccb_h.status = CAM_DEV_NOT_THERE; 237e25c779eSMatthew Dillon xpt_done(ccb); 238e25c779eSMatthew Dillon return; 239e25c779eSMatthew Dillon } 240e25c779eSMatthew Dillon break; 241e25c779eSMatthew Dillon 242e25c779eSMatthew Dillon case XPT_PATH_INQ: 243e25c779eSMatthew Dillon case XPT_NOOP: 244e25c779eSMatthew Dillon if(sp == NULL && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) { 245e25c779eSMatthew Dillon ccb->ccb_h.status = CAM_DEV_NOT_THERE; 246e25c779eSMatthew Dillon xpt_done(ccb); 247e25c779eSMatthew Dillon debug(4, "status = CAM_DEV_NOT_THERE"); 248e25c779eSMatthew Dillon return; 249e25c779eSMatthew Dillon } 250e25c779eSMatthew Dillon } 251e25c779eSMatthew Dillon 252e25c779eSMatthew Dillon switch(ccb_h->func_code) { 253e25c779eSMatthew Dillon 254e25c779eSMatthew Dillon case XPT_PATH_INQ: 255e25c779eSMatthew Dillon _inq(sim, ccb, (sp? sp->opt.maxluns: ISCSI_MAX_LUNS) - 1); 256e25c779eSMatthew Dillon break; 257e25c779eSMatthew Dillon 258e25c779eSMatthew Dillon case XPT_RESET_BUS: // (can just be a stub that does nothing and completes) 259e25c779eSMatthew Dillon { 260e25c779eSMatthew Dillon struct ccb_pathinq *cpi = &ccb->cpi; 261e25c779eSMatthew Dillon 262e25c779eSMatthew Dillon debug(3, "XPT_RESET_BUS"); 263e25c779eSMatthew Dillon cpi->ccb_h.status = CAM_REQ_CMP; 264e25c779eSMatthew Dillon break; 265e25c779eSMatthew Dillon } 266e25c779eSMatthew Dillon 267e25c779eSMatthew Dillon case XPT_SCSI_IO: 268e25c779eSMatthew Dillon { 269e25c779eSMatthew Dillon struct ccb_scsiio* csio = &ccb->csio; 270e25c779eSMatthew Dillon 271e25c779eSMatthew Dillon debug(4, "XPT_SCSI_IO cmd=0x%x", csio->cdb_io.cdb_bytes[0]); 272e25c779eSMatthew Dillon if(sp == NULL) { 273e25c779eSMatthew Dillon ccb_h->status = CAM_REQ_INVALID; //CAM_NO_NEXUS; 274e25c779eSMatthew Dillon debug(4, "xpt_done.status=%d", ccb_h->status); 275e25c779eSMatthew Dillon break; 276e25c779eSMatthew Dillon } 277e25c779eSMatthew Dillon if(ccb_h->target_lun == CAM_LUN_WILDCARD) { 278e25c779eSMatthew Dillon debug(3, "target=%d: bad lun (-1)", ccb_h->target_id); 279e25c779eSMatthew Dillon ccb_h->status = CAM_LUN_INVALID; 280e25c779eSMatthew Dillon break; 281e25c779eSMatthew Dillon } 282e25c779eSMatthew Dillon if(_scsi_encap(sim, ccb) != 0) 283e25c779eSMatthew Dillon return; 284e25c779eSMatthew Dillon break; 285e25c779eSMatthew Dillon } 286e25c779eSMatthew Dillon 287e25c779eSMatthew Dillon case XPT_CALC_GEOMETRY: 288e25c779eSMatthew Dillon { 289e25c779eSMatthew Dillon struct ccb_calc_geometry *ccg; 290e25c779eSMatthew Dillon 291e25c779eSMatthew Dillon ccg = &ccb->ccg; 292e25c779eSMatthew Dillon debug(6, "XPT_CALC_GEOMETRY vsize=%jd bsize=%d", ccg->volume_size, ccg->block_size); 293e25c779eSMatthew Dillon if(ccg->block_size == 0 || 294e25c779eSMatthew Dillon (ccg->volume_size < ccg->block_size)) { 295e25c779eSMatthew Dillon // print error message ... 296e25c779eSMatthew Dillon /* XXX: what error is appropiate? */ 297e25c779eSMatthew Dillon break; 298e25c779eSMatthew Dillon } else 299e25c779eSMatthew Dillon cam_calc_geometry(ccg, /*extended*/1); 300e25c779eSMatthew Dillon break; 301e25c779eSMatthew Dillon } 302e25c779eSMatthew Dillon 303e25c779eSMatthew Dillon case XPT_GET_TRAN_SETTINGS: 304e25c779eSMatthew Dillon default: 305e25c779eSMatthew Dillon ccb_h->status = CAM_REQ_INVALID; 306e25c779eSMatthew Dillon break; 307e25c779eSMatthew Dillon } 308e25c779eSMatthew Dillon xpt_done(ccb); 309e25c779eSMatthew Dillon return; 310e25c779eSMatthew Dillon } 311e25c779eSMatthew Dillon 312e25c779eSMatthew Dillon static void 313e25c779eSMatthew Dillon ic_poll(struct cam_sim *sim) 314e25c779eSMatthew Dillon { 315e25c779eSMatthew Dillon debug_called(8); 316e25c779eSMatthew Dillon 317e25c779eSMatthew Dillon } 318e25c779eSMatthew Dillon 319e25c779eSMatthew Dillon int 320e25c779eSMatthew Dillon ic_getCamVals(isc_session_t *sp, iscsi_cam_t *cp) 321e25c779eSMatthew Dillon { 322e25c779eSMatthew Dillon int i; 323e25c779eSMatthew Dillon 324e25c779eSMatthew Dillon debug_called(8); 325e25c779eSMatthew Dillon 326e25c779eSMatthew Dillon if(sp && sp->isc->cam_sim) { 327e25c779eSMatthew Dillon cp->path_id = cam_sim_path(sp->isc->cam_sim); 328e25c779eSMatthew Dillon cp->target_id = sp->sid; 329e25c779eSMatthew Dillon cp->target_nluns = sp->target_nluns; // XXX: -1? 330e25c779eSMatthew Dillon for(i = 0; i < cp->target_nluns; i++) 331e25c779eSMatthew Dillon cp->target_lun[i] = sp->target_lun[i]; 332e25c779eSMatthew Dillon return 0; 333e25c779eSMatthew Dillon } 334e25c779eSMatthew Dillon return ENXIO; 335e25c779eSMatthew Dillon } 336e25c779eSMatthew Dillon 337e25c779eSMatthew Dillon void 338e25c779eSMatthew Dillon ic_destroy(struct isc_softc *isp) 339e25c779eSMatthew Dillon { 340e25c779eSMatthew Dillon debug_called(8); 341e25c779eSMatthew Dillon 342e25c779eSMatthew Dillon CAM_LOCK(isp); // can't harm :-) 343e25c779eSMatthew Dillon 344e25c779eSMatthew Dillon xpt_async(AC_LOST_DEVICE, isp->cam_path, NULL); 345e25c779eSMatthew Dillon xpt_free_path(isp->cam_path); 346e25c779eSMatthew Dillon xpt_bus_deregister(cam_sim_path(isp->cam_sim)); 347e25c779eSMatthew Dillon cam_sim_free(isp->cam_sim); 348e25c779eSMatthew Dillon 349e25c779eSMatthew Dillon CAM_UNLOCK(isp); 350e25c779eSMatthew Dillon } 351e25c779eSMatthew Dillon 352e25c779eSMatthew Dillon int 353e25c779eSMatthew Dillon ic_init(struct isc_softc *isp) 354e25c779eSMatthew Dillon { 355e25c779eSMatthew Dillon struct cam_sim *sim; 356e25c779eSMatthew Dillon struct cam_devq *devq; 357e25c779eSMatthew Dillon struct cam_path *path; 358e25c779eSMatthew Dillon 359e25c779eSMatthew Dillon if((devq = cam_simq_alloc(256)) == NULL) 360e25c779eSMatthew Dillon return ENOMEM; 361e25c779eSMatthew Dillon 362e25c779eSMatthew Dillon lockinit(&isp->cam_lock, "isc-cam", 0, LK_CANRECURSE); 363e25c779eSMatthew Dillon sim = cam_sim_alloc(ic_action, ic_poll, 364e25c779eSMatthew Dillon "iscsi", isp, 0, /* unit */ 365e25c779eSMatthew Dillon &sim_mplock, 366e25c779eSMatthew Dillon 1, /* max_dev_transactions */ 367e25c779eSMatthew Dillon 100, /* max_tagged_dev_transactions */ 368e25c779eSMatthew Dillon devq); 369e25c779eSMatthew Dillon cam_simq_release(devq); 370284d4d40SSascha Wildner if(sim == NULL) { 371e25c779eSMatthew Dillon lockuninit(&isp->cam_lock); 372e25c779eSMatthew Dillon return ENXIO; 373e25c779eSMatthew Dillon } 374e25c779eSMatthew Dillon CAM_LOCK(isp); 375e25c779eSMatthew Dillon if(xpt_bus_register(sim, 376e25c779eSMatthew Dillon 0/*bus_number*/) != CAM_SUCCESS) 377e25c779eSMatthew Dillon goto bad; 378e25c779eSMatthew Dillon 379e25c779eSMatthew Dillon if(xpt_create_path(&path, xpt_periph, cam_sim_path(sim), 380e25c779eSMatthew Dillon CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 381e25c779eSMatthew Dillon xpt_bus_deregister(cam_sim_path(sim)); 382e25c779eSMatthew Dillon goto bad; 383e25c779eSMatthew Dillon } 384e25c779eSMatthew Dillon 385e25c779eSMatthew Dillon CAM_UNLOCK(isp); 386e25c779eSMatthew Dillon 387e25c779eSMatthew Dillon isp->cam_sim = sim; 388e25c779eSMatthew Dillon isp->cam_path = path; 389e25c779eSMatthew Dillon 390e25c779eSMatthew Dillon debug(2, "cam subsystem initialized"); // XXX: add dev ... 391e25c779eSMatthew Dillon debug(4, "sim=%p path=%p", sim, path); 392e25c779eSMatthew Dillon return 0; 393e25c779eSMatthew Dillon 394e25c779eSMatthew Dillon bad: 395e25c779eSMatthew Dillon cam_sim_free(sim); 396e25c779eSMatthew Dillon CAM_UNLOCK(isp); 397e25c779eSMatthew Dillon return ENXIO; 398e25c779eSMatthew Dillon } 399