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