1139743Simp/*- 239212Sgibbs * Common functions for CAM "type" (peripheral) drivers. 339212Sgibbs * 439212Sgibbs * Copyright (c) 1997, 1998 Justin T. Gibbs. 565225Sken * Copyright (c) 1997, 1998, 1999, 2000 Kenneth D. Merry. 639212Sgibbs * All rights reserved. 739212Sgibbs * 839212Sgibbs * Redistribution and use in source and binary forms, with or without 939212Sgibbs * modification, are permitted provided that the following conditions 1039212Sgibbs * are met: 1139212Sgibbs * 1. Redistributions of source code must retain the above copyright 1239212Sgibbs * notice, this list of conditions, and the following disclaimer, 1339212Sgibbs * without modification, immediately at the beginning of the file. 1439212Sgibbs * 2. The name of the author may not be used to endorse or promote products 1539212Sgibbs * derived from this software without specific prior written permission. 1639212Sgibbs * 1739212Sgibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1839212Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1939212Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2039212Sgibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 2139212Sgibbs * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2239212Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2339212Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2439212Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2539212Sgibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2639212Sgibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2739212Sgibbs * SUCH DAMAGE. 2839212Sgibbs */ 2939212Sgibbs 30116161Sobrien#include <sys/cdefs.h> 31116161Sobrien__FBSDID("$FreeBSD: releng/10.3/sys/cam/cam_periph.c 288817 2015-10-05 11:45:28Z mav $"); 32116161Sobrien 3339212Sgibbs#include <sys/param.h> 3439212Sgibbs#include <sys/systm.h> 3539212Sgibbs#include <sys/types.h> 3639212Sgibbs#include <sys/malloc.h> 37147723Savatar#include <sys/kernel.h> 3860041Sphk#include <sys/bio.h> 3974914Sjhb#include <sys/lock.h> 4074914Sjhb#include <sys/mutex.h> 4139212Sgibbs#include <sys/buf.h> 4239212Sgibbs#include <sys/proc.h> 4339212Sgibbs#include <sys/devicestat.h> 4456470Speter#include <sys/bus.h> 45223081Sgibbs#include <sys/sbuf.h> 4639212Sgibbs#include <vm/vm.h> 4739212Sgibbs#include <vm/vm_extern.h> 4839212Sgibbs 4939212Sgibbs#include <cam/cam.h> 5039212Sgibbs#include <cam/cam_ccb.h> 51195534Sscottl#include <cam/cam_queue.h> 5239212Sgibbs#include <cam/cam_xpt_periph.h> 5339212Sgibbs#include <cam/cam_periph.h> 5439212Sgibbs#include <cam/cam_debug.h> 55168752Sscottl#include <cam/cam_sim.h> 5639212Sgibbs 5739212Sgibbs#include <cam/scsi/scsi_all.h> 5839212Sgibbs#include <cam/scsi/scsi_message.h> 5939212Sgibbs#include <cam/scsi/scsi_pass.h> 6039212Sgibbs 6139212Sgibbsstatic u_int camperiphnextunit(struct periph_driver *p_drv, 6265225Sken u_int newunit, int wired, 6365225Sken path_id_t pathid, target_id_t target, 6465225Sken lun_id_t lun); 6539212Sgibbsstatic u_int camperiphunit(struct periph_driver *p_drv, 6665225Sken path_id_t pathid, target_id_t target, 6765225Sken lun_id_t lun); 6839212Sgibbsstatic void camperiphdone(struct cam_periph *periph, 6939212Sgibbs union ccb *done_ccb); 7039212Sgibbsstatic void camperiphfree(struct cam_periph *periph); 7174840Skenstatic int camperiphscsistatuserror(union ccb *ccb, 72236814Smav union ccb **orig_ccb, 7374840Sken cam_flags camflags, 7474840Sken u_int32_t sense_flags, 7574840Sken int *openings, 7674840Sken u_int32_t *relsim_flags, 77203108Smav u_int32_t *timeout, 78253322Smav u_int32_t *action, 79203108Smav const char **action_string); 8074840Skenstatic int camperiphscsisenseerror(union ccb *ccb, 81236814Smav union ccb **orig_ccb, 8274840Sken cam_flags camflags, 8374840Sken u_int32_t sense_flags, 8474840Sken int *openings, 8574840Sken u_int32_t *relsim_flags, 86203108Smav u_int32_t *timeout, 87253322Smav u_int32_t *action, 88203108Smav const char **action_string); 8939212Sgibbs 9072119Speterstatic int nperiph_drivers; 91203108Smavstatic int initialized = 0; 9272119Speterstruct periph_driver **periph_drivers; 9372119Speter 94227293Sedstatic MALLOC_DEFINE(M_CAMPERIPH, "CAM periph", "CAM peripheral buffers"); 95147723Savatar 96162938Smjacobstatic int periph_selto_delay = 1000; 97162938SmjacobTUNABLE_INT("kern.cam.periph_selto_delay", &periph_selto_delay); 98162938Smjacobstatic int periph_noresrc_delay = 500; 99162938SmjacobTUNABLE_INT("kern.cam.periph_noresrc_delay", &periph_noresrc_delay); 100162938Smjacobstatic int periph_busy_delay = 500; 101162938SmjacobTUNABLE_INT("kern.cam.periph_busy_delay", &periph_busy_delay); 102162938Smjacob 103162938Smjacob 10472119Spetervoid 10572119Speterperiphdriver_register(void *data) 10672119Speter{ 107203108Smav struct periph_driver *drv = (struct periph_driver *)data; 10872119Speter struct periph_driver **newdrivers, **old; 10972119Speter int ndrivers; 11072119Speter 111283349Straszagain: 11272119Speter ndrivers = nperiph_drivers + 2; 113169562Sscottl newdrivers = malloc(sizeof(*newdrivers) * ndrivers, M_CAMPERIPH, 114169562Sscottl M_WAITOK); 115283349Strasz xpt_lock_buses(); 116283349Strasz if (ndrivers != nperiph_drivers + 2) { 117283349Strasz /* 118283349Strasz * Lost race against itself; go around. 119283349Strasz */ 120283349Strasz xpt_unlock_buses(); 121283349Strasz free(newdrivers, M_CAMPERIPH); 122283349Strasz goto again; 123283349Strasz } 12472119Speter if (periph_drivers) 12572119Speter bcopy(periph_drivers, newdrivers, 12675549Sken sizeof(*newdrivers) * nperiph_drivers); 127203108Smav newdrivers[nperiph_drivers] = drv; 12872119Speter newdrivers[nperiph_drivers + 1] = NULL; 12972119Speter old = periph_drivers; 13072119Speter periph_drivers = newdrivers; 131283349Strasz nperiph_drivers++; 132283349Strasz xpt_unlock_buses(); 13372119Speter if (old) 134169562Sscottl free(old, M_CAMPERIPH); 135203108Smav /* If driver marked as early or it is late now, initialize it. */ 136203108Smav if (((drv->flags & CAM_PERIPH_DRV_EARLY) != 0 && initialized > 0) || 137203108Smav initialized > 1) 138203108Smav (*drv->init)(); 13972119Speter} 14072119Speter 141203108Smavvoid 142203108Smavperiphdriver_init(int level) 143203108Smav{ 144203108Smav int i, early; 145203108Smav 146203108Smav initialized = max(initialized, level); 147203108Smav for (i = 0; periph_drivers[i] != NULL; i++) { 148203108Smav early = (periph_drivers[i]->flags & CAM_PERIPH_DRV_EARLY) ? 1 : 2; 149203108Smav if (early == initialized) 150203108Smav (*periph_drivers[i]->init)(); 151203108Smav } 152203108Smav} 153203108Smav 15439212Sgibbscam_status 15540603Skencam_periph_alloc(periph_ctor_t *periph_ctor, 15640603Sken periph_oninv_t *periph_oninvalidate, 15740603Sken periph_dtor_t *periph_dtor, periph_start_t *periph_start, 15840603Sken char *name, cam_periph_type type, struct cam_path *path, 15940603Sken ac_callback_t *ac_callback, ac_code code, void *arg) 16039212Sgibbs{ 16139212Sgibbs struct periph_driver **p_drv; 162168752Sscottl struct cam_sim *sim; 16339212Sgibbs struct cam_periph *periph; 16439212Sgibbs struct cam_periph *cur_periph; 16539212Sgibbs path_id_t path_id; 16639212Sgibbs target_id_t target_id; 16739212Sgibbs lun_id_t lun_id; 16839212Sgibbs cam_status status; 16939212Sgibbs u_int init_level; 17039212Sgibbs 17139212Sgibbs init_level = 0; 17239212Sgibbs /* 17339212Sgibbs * Handle Hot-Plug scenarios. If there is already a peripheral 17439212Sgibbs * of our type assigned to this path, we are likely waiting for 17539212Sgibbs * final close on an old, invalidated, peripheral. If this is 17639212Sgibbs * the case, queue up a deferred call to the peripheral's async 177134530Sgibbs * handler. If it looks like a mistaken re-allocation, complain. 17839212Sgibbs */ 17939212Sgibbs if ((periph = cam_periph_find(path, name)) != NULL) { 18039212Sgibbs 18139212Sgibbs if ((periph->flags & CAM_PERIPH_INVALID) != 0 18239212Sgibbs && (periph->flags & CAM_PERIPH_NEW_DEV_FOUND) == 0) { 18339212Sgibbs periph->flags |= CAM_PERIPH_NEW_DEV_FOUND; 18439212Sgibbs periph->deferred_callback = ac_callback; 18539212Sgibbs periph->deferred_ac = code; 18639212Sgibbs return (CAM_REQ_INPROG); 18739212Sgibbs } else { 18839212Sgibbs printf("cam_periph_alloc: attempt to re-allocate " 189230000Sken "valid device %s%d rejected flags %#x " 190230000Sken "refcount %d\n", periph->periph_name, 191230000Sken periph->unit_number, periph->flags, 192230000Sken periph->refcount); 19339212Sgibbs } 19439212Sgibbs return (CAM_REQ_INVALID); 19539212Sgibbs } 19639212Sgibbs 197147723Savatar periph = (struct cam_periph *)malloc(sizeof(*periph), M_CAMPERIPH, 198230000Sken M_NOWAIT|M_ZERO); 19939212Sgibbs 20039212Sgibbs if (periph == NULL) 20139212Sgibbs return (CAM_RESRC_UNAVAIL); 20239212Sgibbs 20339212Sgibbs init_level++; 20439212Sgibbs 205168752Sscottl 206168752Sscottl sim = xpt_path_sim(path); 20739212Sgibbs path_id = xpt_path_path_id(path); 20839212Sgibbs target_id = xpt_path_target_id(path); 20939212Sgibbs lun_id = xpt_path_lun_id(path); 21039212Sgibbs periph->periph_start = periph_start; 21139212Sgibbs periph->periph_dtor = periph_dtor; 21240603Sken periph->periph_oninval = periph_oninvalidate; 21339212Sgibbs periph->type = type; 21439212Sgibbs periph->periph_name = name; 215260387Sscottl periph->scheduled_priority = CAM_PRIORITY_NONE; 21639212Sgibbs periph->immediate_priority = CAM_PRIORITY_NONE; 217249980Smav periph->refcount = 1; /* Dropped by invalidation. */ 218168752Sscottl periph->sim = sim; 21939212Sgibbs SLIST_INIT(&periph->ccb_list); 22039212Sgibbs status = xpt_create_path(&path, periph, path_id, target_id, lun_id); 22139212Sgibbs if (status != CAM_REQ_CMP) 22239212Sgibbs goto failure; 22339212Sgibbs periph->path = path; 22439212Sgibbs 225208752Smjacob xpt_lock_buses(); 226208752Smjacob for (p_drv = periph_drivers; *p_drv != NULL; p_drv++) { 227208752Smjacob if (strcmp((*p_drv)->driver_name, name) == 0) 228208752Smjacob break; 229208752Smjacob } 230208752Smjacob if (*p_drv == NULL) { 231208752Smjacob printf("cam_periph_alloc: invalid periph name '%s'\n", name); 232249008Strasz xpt_unlock_buses(); 233208752Smjacob xpt_free_path(periph->path); 234208752Smjacob free(periph, M_CAMPERIPH); 235208752Smjacob return (CAM_REQ_INVALID); 236208752Smjacob } 237208752Smjacob periph->unit_number = camperiphunit(*p_drv, path_id, target_id, lun_id); 23839212Sgibbs cur_periph = TAILQ_FIRST(&(*p_drv)->units); 23939212Sgibbs while (cur_periph != NULL 24039212Sgibbs && cur_periph->unit_number < periph->unit_number) 24139212Sgibbs cur_periph = TAILQ_NEXT(cur_periph, unit_links); 242208752Smjacob if (cur_periph != NULL) { 243208752Smjacob KASSERT(cur_periph->unit_number != periph->unit_number, ("duplicate units on periph list")); 24439212Sgibbs TAILQ_INSERT_BEFORE(cur_periph, periph, unit_links); 245208752Smjacob } else { 24639212Sgibbs TAILQ_INSERT_TAIL(&(*p_drv)->units, periph, unit_links); 24739212Sgibbs (*p_drv)->generation++; 24839212Sgibbs } 249208752Smjacob xpt_unlock_buses(); 25039212Sgibbs 25139212Sgibbs init_level++; 25239212Sgibbs 253208752Smjacob status = xpt_add_periph(periph); 254208752Smjacob if (status != CAM_REQ_CMP) 255208752Smjacob goto failure; 256208752Smjacob 257208752Smjacob init_level++; 258236713Smav CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("Periph created\n")); 259208752Smjacob 26039212Sgibbs status = periph_ctor(periph, arg); 26139212Sgibbs 26239212Sgibbs if (status == CAM_REQ_CMP) 26339212Sgibbs init_level++; 26439212Sgibbs 26539212Sgibbsfailure: 26639212Sgibbs switch (init_level) { 26739212Sgibbs case 4: 26839212Sgibbs /* Initialized successfully */ 26939212Sgibbs break; 27039212Sgibbs case 3: 271236713Smav CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("Periph destroyed\n")); 272254058Smav xpt_remove_periph(periph); 273115476Sphk /* FALLTHROUGH */ 27439212Sgibbs case 2: 275208752Smjacob xpt_lock_buses(); 276208752Smjacob TAILQ_REMOVE(&(*p_drv)->units, periph, unit_links); 277208752Smjacob xpt_unlock_buses(); 27839212Sgibbs xpt_free_path(periph->path); 279115476Sphk /* FALLTHROUGH */ 28039212Sgibbs case 1: 281147723Savatar free(periph, M_CAMPERIPH); 282115476Sphk /* FALLTHROUGH */ 28339212Sgibbs case 0: 28439212Sgibbs /* No cleanup to perform. */ 28539212Sgibbs break; 28639212Sgibbs default: 287237682Sken panic("%s: Unknown init level", __func__); 28839212Sgibbs } 28939212Sgibbs return(status); 29039212Sgibbs} 29139212Sgibbs 29239212Sgibbs/* 29339212Sgibbs * Find a peripheral structure with the specified path, target, lun, 29439212Sgibbs * and (optionally) type. If the name is NULL, this function will return 29539212Sgibbs * the first peripheral driver that matches the specified path. 29639212Sgibbs */ 29739212Sgibbsstruct cam_periph * 29839212Sgibbscam_periph_find(struct cam_path *path, char *name) 29939212Sgibbs{ 30039212Sgibbs struct periph_driver **p_drv; 30139212Sgibbs struct cam_periph *periph; 30239212Sgibbs 303168882Sscottl xpt_lock_buses(); 30472119Speter for (p_drv = periph_drivers; *p_drv != NULL; p_drv++) { 30539212Sgibbs 30639212Sgibbs if (name != NULL && (strcmp((*p_drv)->driver_name, name) != 0)) 30739212Sgibbs continue; 30839212Sgibbs 30972012Sphk TAILQ_FOREACH(periph, &(*p_drv)->units, unit_links) { 31039212Sgibbs if (xpt_path_comp(periph->path, path) == 0) { 311168882Sscottl xpt_unlock_buses(); 312260387Sscottl cam_periph_assert(periph, MA_OWNED); 31339212Sgibbs return(periph); 31439212Sgibbs } 31539212Sgibbs } 316168882Sscottl if (name != NULL) { 317168882Sscottl xpt_unlock_buses(); 31839212Sgibbs return(NULL); 319168882Sscottl } 32039212Sgibbs } 321168882Sscottl xpt_unlock_buses(); 32239212Sgibbs return(NULL); 32339212Sgibbs} 32439212Sgibbs 325223081Sgibbs/* 326230000Sken * Find peripheral driver instances attached to the specified path. 327223081Sgibbs */ 328223081Sgibbsint 329223081Sgibbscam_periph_list(struct cam_path *path, struct sbuf *sb) 330223081Sgibbs{ 331230000Sken struct sbuf local_sb; 332223081Sgibbs struct periph_driver **p_drv; 333223081Sgibbs struct cam_periph *periph; 334223081Sgibbs int count; 335230000Sken int sbuf_alloc_len; 336223081Sgibbs 337230000Sken sbuf_alloc_len = 16; 338230000Skenretry: 339230000Sken sbuf_new(&local_sb, NULL, sbuf_alloc_len, SBUF_FIXEDLEN); 340223081Sgibbs count = 0; 341223081Sgibbs xpt_lock_buses(); 342223081Sgibbs for (p_drv = periph_drivers; *p_drv != NULL; p_drv++) { 343223081Sgibbs 344223081Sgibbs TAILQ_FOREACH(periph, &(*p_drv)->units, unit_links) { 345223081Sgibbs if (xpt_path_comp(periph->path, path) != 0) 346223081Sgibbs continue; 347223081Sgibbs 348230000Sken if (sbuf_len(&local_sb) != 0) 349230000Sken sbuf_cat(&local_sb, ","); 350223081Sgibbs 351230000Sken sbuf_printf(&local_sb, "%s%d", periph->periph_name, 352223081Sgibbs periph->unit_number); 353230000Sken 354230000Sken if (sbuf_error(&local_sb) == ENOMEM) { 355230000Sken sbuf_alloc_len *= 2; 356230000Sken xpt_unlock_buses(); 357230000Sken sbuf_delete(&local_sb); 358230000Sken goto retry; 359230000Sken } 360223081Sgibbs count++; 361223081Sgibbs } 362223081Sgibbs } 363223081Sgibbs xpt_unlock_buses(); 364230000Sken sbuf_finish(&local_sb); 365230000Sken sbuf_cpy(sb, sbuf_data(&local_sb)); 366230000Sken sbuf_delete(&local_sb); 367223081Sgibbs return (count); 368223081Sgibbs} 369223081Sgibbs 37039212Sgibbscam_status 37139212Sgibbscam_periph_acquire(struct cam_periph *periph) 37239212Sgibbs{ 373230000Sken cam_status status; 37439212Sgibbs 375230000Sken status = CAM_REQ_CMP_ERR; 37639212Sgibbs if (periph == NULL) 377230000Sken return (status); 37839212Sgibbs 379168752Sscottl xpt_lock_buses(); 380230000Sken if ((periph->flags & CAM_PERIPH_INVALID) == 0) { 381230000Sken periph->refcount++; 382230000Sken status = CAM_REQ_CMP; 383230000Sken } 384168752Sscottl xpt_unlock_buses(); 38539212Sgibbs 386230000Sken return (status); 38739212Sgibbs} 38839212Sgibbs 38939212Sgibbsvoid 390260626Smavcam_periph_doacquire(struct cam_periph *periph) 391260626Smav{ 392260626Smav 393260626Smav xpt_lock_buses(); 394260626Smav KASSERT(periph->refcount >= 1, 395260626Smav ("cam_periph_doacquire() with refcount == %d", periph->refcount)); 396260626Smav periph->refcount++; 397260626Smav xpt_unlock_buses(); 398260626Smav} 399260626Smav 400260626Smavvoid 401230000Skencam_periph_release_locked_buses(struct cam_periph *periph) 40239212Sgibbs{ 403249108Smav 404260387Sscottl cam_periph_assert(periph, MA_OWNED); 405249108Smav KASSERT(periph->refcount >= 1, ("periph->refcount >= 1")); 406249980Smav if (--periph->refcount == 0) 40739212Sgibbs camperiphfree(periph); 408230000Sken} 409230000Sken 410230000Skenvoid 411230000Skencam_periph_release_locked(struct cam_periph *periph) 412230000Sken{ 413230000Sken 414230000Sken if (periph == NULL) 415230000Sken return; 416230000Sken 417230000Sken xpt_lock_buses(); 418230000Sken cam_periph_release_locked_buses(periph); 419168752Sscottl xpt_unlock_buses(); 420186319Strasz} 42139212Sgibbs 422186319Straszvoid 423186319Straszcam_periph_release(struct cam_periph *periph) 424186319Strasz{ 425260387Sscottl struct mtx *mtx; 426186319Strasz 427186319Strasz if (periph == NULL) 428186319Strasz return; 429186319Strasz 430260387Sscottl cam_periph_assert(periph, MA_NOTOWNED); 431260387Sscottl mtx = cam_periph_mtx(periph); 432260387Sscottl mtx_lock(mtx); 433186319Strasz cam_periph_release_locked(periph); 434260387Sscottl mtx_unlock(mtx); 43539212Sgibbs} 43639212Sgibbs 437168752Sscottlint 438168752Sscottlcam_periph_hold(struct cam_periph *periph, int priority) 439168752Sscottl{ 440168752Sscottl int error; 441168752Sscottl 442168752Sscottl /* 443168752Sscottl * Increment the reference count on the peripheral 444168752Sscottl * while we wait for our lock attempt to succeed 445168752Sscottl * to ensure the peripheral doesn't disappear out 446168752Sscottl * from user us while we sleep. 447168752Sscottl */ 448168752Sscottl 449168752Sscottl if (cam_periph_acquire(periph) != CAM_REQ_CMP) 450168752Sscottl return (ENXIO); 451168752Sscottl 452260387Sscottl cam_periph_assert(periph, MA_OWNED); 453168752Sscottl while ((periph->flags & CAM_PERIPH_LOCKED) != 0) { 454168752Sscottl periph->flags |= CAM_PERIPH_LOCK_WANTED; 455260387Sscottl if ((error = cam_periph_sleep(periph, periph, priority, 456187718Sjhb "caplck", 0)) != 0) { 457186319Strasz cam_periph_release_locked(periph); 458168752Sscottl return (error); 459168752Sscottl } 460237401Smav if (periph->flags & CAM_PERIPH_INVALID) { 461237401Smav cam_periph_release_locked(periph); 462237401Smav return (ENXIO); 463237401Smav } 464168752Sscottl } 465168752Sscottl 466168752Sscottl periph->flags |= CAM_PERIPH_LOCKED; 467168752Sscottl return (0); 468168752Sscottl} 469168752Sscottl 470168752Sscottlvoid 471168752Sscottlcam_periph_unhold(struct cam_periph *periph) 472168752Sscottl{ 473168752Sscottl 474260387Sscottl cam_periph_assert(periph, MA_OWNED); 475168752Sscottl 476168752Sscottl periph->flags &= ~CAM_PERIPH_LOCKED; 477168752Sscottl if ((periph->flags & CAM_PERIPH_LOCK_WANTED) != 0) { 478168752Sscottl periph->flags &= ~CAM_PERIPH_LOCK_WANTED; 479168752Sscottl wakeup(periph); 480168752Sscottl } 481168752Sscottl 482186319Strasz cam_periph_release_locked(periph); 483168752Sscottl} 484168752Sscottl 48539212Sgibbs/* 48639212Sgibbs * Look for the next unit number that is not currently in use for this 48739212Sgibbs * peripheral type starting at "newunit". Also exclude unit numbers that 48839212Sgibbs * are reserved by for future "hardwiring" unless we already know that this 48939212Sgibbs * is a potential wired device. Only assume that the device is "wired" the 49039212Sgibbs * first time through the loop since after that we'll be looking at unit 49139212Sgibbs * numbers that did not match a wiring entry. 49239212Sgibbs */ 49339212Sgibbsstatic u_int 49465225Skencamperiphnextunit(struct periph_driver *p_drv, u_int newunit, int wired, 49565225Sken path_id_t pathid, target_id_t target, lun_id_t lun) 49639212Sgibbs{ 49739212Sgibbs struct cam_periph *periph; 49878135Speter char *periph_name; 49978135Speter int i, val, dunit, r; 50078135Speter const char *dname, *strval; 50139212Sgibbs 50239212Sgibbs periph_name = p_drv->driver_name; 50339212Sgibbs for (;;newunit++) { 50439212Sgibbs 50539212Sgibbs for (periph = TAILQ_FIRST(&p_drv->units); 50639212Sgibbs periph != NULL && periph->unit_number != newunit; 50739212Sgibbs periph = TAILQ_NEXT(periph, unit_links)) 50839212Sgibbs ; 50939212Sgibbs 51039212Sgibbs if (periph != NULL && periph->unit_number == newunit) { 51139212Sgibbs if (wired != 0) { 512164906Smjacob xpt_print(periph->path, "Duplicate Wired " 513164906Smjacob "Device entry!\n"); 514164906Smjacob xpt_print(periph->path, "Second device (%s " 515164906Smjacob "device at scbus%d target %d lun %d) will " 516164906Smjacob "not be wired\n", periph_name, pathid, 517164906Smjacob target, lun); 51839212Sgibbs wired = 0; 51939212Sgibbs } 52039212Sgibbs continue; 52139212Sgibbs } 52256470Speter if (wired) 52356470Speter break; 52439212Sgibbs 52556470Speter /* 52656470Speter * Don't match entries like "da 4" as a wired down 52756470Speter * device, but do match entries like "da 4 target 5" 52856470Speter * or even "da 4 scbus 1". 52956470Speter */ 53078135Speter i = 0; 53178135Speter dname = periph_name; 53278135Speter for (;;) { 53378135Speter r = resource_find_dev(&i, dname, &dunit, NULL, NULL); 53478135Speter if (r != 0) 53578135Speter break; 53656470Speter /* if no "target" and no specific scbus, skip */ 53756470Speter if (resource_int_value(dname, dunit, "target", &val) && 53856470Speter (resource_string_value(dname, dunit, "at",&strval)|| 53956470Speter strcmp(strval, "scbus") == 0)) 54056470Speter continue; 54156470Speter if (newunit == dunit) 54239212Sgibbs break; 54339212Sgibbs } 54478135Speter if (r != 0) 54539212Sgibbs break; 54639212Sgibbs } 54739212Sgibbs return (newunit); 54839212Sgibbs} 54939212Sgibbs 55039212Sgibbsstatic u_int 55139212Sgibbscamperiphunit(struct periph_driver *p_drv, path_id_t pathid, 55239212Sgibbs target_id_t target, lun_id_t lun) 55339212Sgibbs{ 55456470Speter u_int unit; 555102341Speter int wired, i, val, dunit; 55678135Speter const char *dname, *strval; 55778135Speter char pathbuf[32], *periph_name; 55839212Sgibbs 55956470Speter periph_name = p_drv->driver_name; 56056470Speter snprintf(pathbuf, sizeof(pathbuf), "scbus%d", pathid); 561102341Speter unit = 0; 56278135Speter i = 0; 56378135Speter dname = periph_name; 564102341Speter for (wired = 0; resource_find_dev(&i, dname, &dunit, NULL, NULL) == 0; 565102341Speter wired = 0) { 56656470Speter if (resource_string_value(dname, dunit, "at", &strval) == 0) { 56756470Speter if (strcmp(strval, pathbuf) != 0) 56856470Speter continue; 569102341Speter wired++; 57039212Sgibbs } 57156470Speter if (resource_int_value(dname, dunit, "target", &val) == 0) { 57256470Speter if (val != target) 57356470Speter continue; 574102341Speter wired++; 57556470Speter } 57656470Speter if (resource_int_value(dname, dunit, "lun", &val) == 0) { 57756470Speter if (val != lun) 57856470Speter continue; 579102341Speter wired++; 58056470Speter } 581102341Speter if (wired != 0) { 58256470Speter unit = dunit; 58356470Speter break; 58456470Speter } 58539212Sgibbs } 58639212Sgibbs 58739212Sgibbs /* 58839212Sgibbs * Either start from 0 looking for the next unit or from 58956470Speter * the unit number given in the resource config. This way, 59039212Sgibbs * if we have wildcard matches, we don't return the same 59139212Sgibbs * unit number twice. 59239212Sgibbs */ 593102341Speter unit = camperiphnextunit(p_drv, unit, wired, pathid, target, lun); 59439212Sgibbs 59539212Sgibbs return (unit); 59639212Sgibbs} 59739212Sgibbs 59839212Sgibbsvoid 59939212Sgibbscam_periph_invalidate(struct cam_periph *periph) 60039212Sgibbs{ 60139212Sgibbs 602260387Sscottl cam_periph_assert(periph, MA_OWNED); 60340603Sken /* 60440603Sken * We only call this routine the first time a peripheral is 605168882Sscottl * invalidated. 60640603Sken */ 607249980Smav if ((periph->flags & CAM_PERIPH_INVALID) != 0) 608249980Smav return; 60940603Sken 610249980Smav CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("Periph invalidated\n")); 611267778Smarius if ((periph->flags & CAM_PERIPH_ANNOUNCED) && !rebooting) 612257049Smav xpt_denounce_periph(periph); 61339212Sgibbs periph->flags |= CAM_PERIPH_INVALID; 61439212Sgibbs periph->flags &= ~CAM_PERIPH_NEW_DEV_FOUND; 615249980Smav if (periph->periph_oninval != NULL) 616249980Smav periph->periph_oninval(periph); 617249980Smav cam_periph_release_locked(periph); 61839212Sgibbs} 61939212Sgibbs 62039212Sgibbsstatic void 62139212Sgibbscamperiphfree(struct cam_periph *periph) 62239212Sgibbs{ 62339212Sgibbs struct periph_driver **p_drv; 62439212Sgibbs 625260387Sscottl cam_periph_assert(periph, MA_OWNED); 626260387Sscottl KASSERT(periph->periph_allocating == 0, ("%s%d: freed while allocating", 627260387Sscottl periph->periph_name, periph->unit_number)); 62872119Speter for (p_drv = periph_drivers; *p_drv != NULL; p_drv++) { 62939212Sgibbs if (strcmp((*p_drv)->driver_name, periph->periph_name) == 0) 63039212Sgibbs break; 63139212Sgibbs } 632142157Sscottl if (*p_drv == NULL) { 633142157Sscottl printf("camperiphfree: attempt to free non-existant periph\n"); 634142157Sscottl return; 635142157Sscottl } 636168787Sscottl 637237328Sken /* 638244001Sken * We need to set this flag before dropping the topology lock, to 639244001Sken * let anyone who is traversing the list that this peripheral is 640244001Sken * about to be freed, and there will be no more reference count 641244001Sken * checks. 642244001Sken */ 643244001Sken periph->flags |= CAM_PERIPH_FREE; 644244001Sken 645244001Sken /* 646237328Sken * The peripheral destructor semantics dictate calling with only the 647237328Sken * SIM mutex held. Since it might sleep, it should not be called 648237328Sken * with the topology lock held. 649237328Sken */ 650168787Sscottl xpt_unlock_buses(); 65139212Sgibbs 652237328Sken /* 653237328Sken * We need to call the peripheral destructor prior to removing the 654237328Sken * peripheral from the list. Otherwise, we risk running into a 655237328Sken * scenario where the peripheral unit number may get reused 656237328Sken * (because it has been removed from the list), but some resources 657237328Sken * used by the peripheral are still hanging around. In particular, 658237328Sken * the devfs nodes used by some peripherals like the pass(4) driver 659237328Sken * aren't fully cleaned up until the destructor is run. If the 660237328Sken * unit number is reused before the devfs instance is fully gone, 661237328Sken * devfs will panic. 662237328Sken */ 663168787Sscottl if (periph->periph_dtor != NULL) 664168787Sscottl periph->periph_dtor(periph); 665237328Sken 666237328Sken /* 667237328Sken * The peripheral list is protected by the topology lock. 668237328Sken */ 669237328Sken xpt_lock_buses(); 670237328Sken 671237328Sken TAILQ_REMOVE(&(*p_drv)->units, periph, unit_links); 672237328Sken (*p_drv)->generation++; 673237328Sken 674254058Smav xpt_remove_periph(periph); 675237328Sken 676237328Sken xpt_unlock_buses(); 677267778Smarius if ((periph->flags & CAM_PERIPH_ANNOUNCED) && !rebooting) 678257049Smav xpt_print(periph->path, "Periph destroyed\n"); 679267778Smarius else 680257049Smav CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("Periph destroyed\n")); 68139212Sgibbs 68239212Sgibbs if (periph->flags & CAM_PERIPH_NEW_DEV_FOUND) { 68339212Sgibbs union ccb ccb; 68439212Sgibbs void *arg; 68539212Sgibbs 68639212Sgibbs switch (periph->deferred_ac) { 68739212Sgibbs case AC_FOUND_DEVICE: 68839212Sgibbs ccb.ccb_h.func_code = XPT_GDEV_TYPE; 689198382Smav xpt_setup_ccb(&ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 69039212Sgibbs xpt_action(&ccb); 69139212Sgibbs arg = &ccb; 69239212Sgibbs break; 69339212Sgibbs case AC_PATH_REGISTERED: 69439212Sgibbs ccb.ccb_h.func_code = XPT_PATH_INQ; 695198382Smav xpt_setup_ccb(&ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 69639212Sgibbs xpt_action(&ccb); 69739212Sgibbs arg = &ccb; 69839212Sgibbs break; 69939212Sgibbs default: 70039212Sgibbs arg = NULL; 70139212Sgibbs break; 70239212Sgibbs } 70339212Sgibbs periph->deferred_callback(NULL, periph->deferred_ac, 70439212Sgibbs periph->path, arg); 70539212Sgibbs } 70639212Sgibbs xpt_free_path(periph->path); 707147723Savatar free(periph, M_CAMPERIPH); 708168787Sscottl xpt_lock_buses(); 70939212Sgibbs} 71039212Sgibbs 71139212Sgibbs/* 71239212Sgibbs * Map user virtual pointers into kernel virtual address space, so we can 713251479Sscottl * access the memory. This is now a generic function that centralizes most 714251479Sscottl * of the sanity checks on the data flags, if any. 715251479Sscottl * This also only works for up to MAXPHYS memory. Since we use 71639212Sgibbs * buffers to map stuff in and out, we're limited to the buffer size. 71739212Sgibbs */ 71839212Sgibbsint 719288817Smavcam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo, 720288817Smav u_int maxmap) 72139212Sgibbs{ 722109572Sdillon int numbufs, i, j; 72341877Sken int flags[CAM_PERIPH_MAXMAPS]; 72439212Sgibbs u_int8_t **data_ptrs[CAM_PERIPH_MAXMAPS]; 72539212Sgibbs u_int32_t lengths[CAM_PERIPH_MAXMAPS]; 72639212Sgibbs u_int32_t dirs[CAM_PERIPH_MAXMAPS]; 72739212Sgibbs 728288817Smav if (maxmap == 0) 729288817Smav maxmap = DFLTPHYS; /* traditional default */ 730288817Smav else if (maxmap > MAXPHYS) 731288817Smav maxmap = MAXPHYS; /* for safety */ 73239212Sgibbs switch(ccb->ccb_h.func_code) { 73339212Sgibbs case XPT_DEV_MATCH: 73439212Sgibbs if (ccb->cdm.match_buf_len == 0) { 73539212Sgibbs printf("cam_periph_mapmem: invalid match buffer " 73639212Sgibbs "length 0\n"); 73739212Sgibbs return(EINVAL); 73839212Sgibbs } 73939212Sgibbs if (ccb->cdm.pattern_buf_len > 0) { 74039212Sgibbs data_ptrs[0] = (u_int8_t **)&ccb->cdm.patterns; 74139212Sgibbs lengths[0] = ccb->cdm.pattern_buf_len; 74239212Sgibbs dirs[0] = CAM_DIR_OUT; 74339212Sgibbs data_ptrs[1] = (u_int8_t **)&ccb->cdm.matches; 74439212Sgibbs lengths[1] = ccb->cdm.match_buf_len; 74539212Sgibbs dirs[1] = CAM_DIR_IN; 74639212Sgibbs numbufs = 2; 74739212Sgibbs } else { 74839212Sgibbs data_ptrs[0] = (u_int8_t **)&ccb->cdm.matches; 74939212Sgibbs lengths[0] = ccb->cdm.match_buf_len; 75039212Sgibbs dirs[0] = CAM_DIR_IN; 75139212Sgibbs numbufs = 1; 75239212Sgibbs } 753195534Sscottl /* 754195534Sscottl * This request will not go to the hardware, no reason 755195534Sscottl * to be so strict. vmapbuf() is able to map up to MAXPHYS. 756195534Sscottl */ 757195534Sscottl maxmap = MAXPHYS; 75839212Sgibbs break; 75939212Sgibbs case XPT_SCSI_IO: 76047412Sgibbs case XPT_CONT_TARGET_IO: 76139212Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE) 76239212Sgibbs return(0); 763251479Sscottl if ((ccb->ccb_h.flags & CAM_DATA_MASK) != CAM_DATA_VADDR) 764251479Sscottl return (EINVAL); 76539212Sgibbs data_ptrs[0] = &ccb->csio.data_ptr; 76641877Sken lengths[0] = ccb->csio.dxfer_len; 76739212Sgibbs dirs[0] = ccb->ccb_h.flags & CAM_DIR_MASK; 76839212Sgibbs numbufs = 1; 76939212Sgibbs break; 770195534Sscottl case XPT_ATA_IO: 771195534Sscottl if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE) 772195534Sscottl return(0); 773251479Sscottl if ((ccb->ccb_h.flags & CAM_DATA_MASK) != CAM_DATA_VADDR) 774251479Sscottl return (EINVAL); 775195534Sscottl data_ptrs[0] = &ccb->ataio.data_ptr; 776195534Sscottl lengths[0] = ccb->ataio.dxfer_len; 777195534Sscottl dirs[0] = ccb->ccb_h.flags & CAM_DIR_MASK; 778195534Sscottl numbufs = 1; 779195534Sscottl break; 780216088Sken case XPT_SMP_IO: 781216088Sken data_ptrs[0] = &ccb->smpio.smp_request; 782216088Sken lengths[0] = ccb->smpio.smp_request_len; 783216088Sken dirs[0] = CAM_DIR_OUT; 784216088Sken data_ptrs[1] = &ccb->smpio.smp_response; 785216088Sken lengths[1] = ccb->smpio.smp_response_len; 786216088Sken dirs[1] = CAM_DIR_IN; 787216088Sken numbufs = 2; 788216088Sken break; 789223081Sgibbs case XPT_DEV_ADVINFO: 790223081Sgibbs if (ccb->cdai.bufsiz == 0) 791216361Sken return (0); 792216361Sken 793223081Sgibbs data_ptrs[0] = (uint8_t **)&ccb->cdai.buf; 794223081Sgibbs lengths[0] = ccb->cdai.bufsiz; 795216088Sken dirs[0] = CAM_DIR_IN; 796216088Sken numbufs = 1; 797216361Sken 798216361Sken /* 799216361Sken * This request will not go to the hardware, no reason 800216361Sken * to be so strict. vmapbuf() is able to map up to MAXPHYS. 801216361Sken */ 802216361Sken maxmap = MAXPHYS; 803216088Sken break; 80439212Sgibbs default: 80539212Sgibbs return(EINVAL); 80639212Sgibbs break; /* NOTREACHED */ 80739212Sgibbs } 80839212Sgibbs 80939212Sgibbs /* 81041877Sken * Check the transfer length and permissions first, so we don't 81141877Sken * have to unmap any previously mapped buffers. 81239212Sgibbs */ 81339212Sgibbs for (i = 0; i < numbufs; i++) { 81439212Sgibbs 81541877Sken flags[i] = 0; 81641877Sken 81741877Sken /* 81841877Sken * The userland data pointer passed in may not be page 81941877Sken * aligned. vmapbuf() truncates the address to a page 82041877Sken * boundary, so if the address isn't page aligned, we'll 82141877Sken * need enough space for the given transfer length, plus 82241877Sken * whatever extra space is necessary to make it to the page 82341877Sken * boundary. 82441877Sken */ 82541877Sken if ((lengths[i] + 826195534Sscottl (((vm_offset_t)(*data_ptrs[i])) & PAGE_MASK)) > maxmap){ 82748410Speter printf("cam_periph_mapmem: attempt to map %lu bytes, " 828195534Sscottl "which is greater than %lu\n", 82948410Speter (long)(lengths[i] + 83048410Speter (((vm_offset_t)(*data_ptrs[i])) & PAGE_MASK)), 831195534Sscottl (u_long)maxmap); 83241877Sken return(E2BIG); 83341877Sken } 83441877Sken 83547497Sken if (dirs[i] & CAM_DIR_OUT) { 83658345Sphk flags[i] = BIO_WRITE; 83739212Sgibbs } 83839212Sgibbs 83947497Sken if (dirs[i] & CAM_DIR_IN) { 84058345Sphk flags[i] = BIO_READ; 84139212Sgibbs } 84239212Sgibbs 84341877Sken } 84441877Sken 84541877Sken /* 846251479Sscottl * This keeps the the kernel stack of current thread from getting 847251479Sscottl * swapped. In low-memory situations where the kernel stack might 848251479Sscottl * otherwise get swapped out, this holds it and allows the thread 849251479Sscottl * to make progress and release the kernel mapped pages sooner. 850251479Sscottl * 85141877Sken * XXX KDM should I use P_NOSWAP instead? 85241877Sken */ 85345359Speter PHOLD(curproc); 85441877Sken 85541877Sken for (i = 0; i < numbufs; i++) { 85639212Sgibbs /* 85739212Sgibbs * Get the buffer. 85839212Sgibbs */ 85942957Sdillon mapinfo->bp[i] = getpbuf(NULL); 86039212Sgibbs 86139212Sgibbs /* save the buffer's data address */ 86239212Sgibbs mapinfo->bp[i]->b_saveaddr = mapinfo->bp[i]->b_data; 86339212Sgibbs 86439212Sgibbs /* put our pointer in the data slot */ 86539212Sgibbs mapinfo->bp[i]->b_data = *data_ptrs[i]; 86639212Sgibbs 867195534Sscottl /* set the transfer length, we know it's < MAXPHYS */ 86839212Sgibbs mapinfo->bp[i]->b_bufsize = lengths[i]; 86939212Sgibbs 87058345Sphk /* set the direction */ 87158345Sphk mapinfo->bp[i]->b_iocmd = flags[i]; 87258345Sphk 873109572Sdillon /* 874109572Sdillon * Map the buffer into kernel memory. 875109572Sdillon * 876109572Sdillon * Note that useracc() alone is not a sufficient test. 877109572Sdillon * vmapbuf() can still fail due to a smaller file mapped 878109572Sdillon * into a larger area of VM, or if userland races against 879109572Sdillon * vmapbuf() after the useracc() check. 880109572Sdillon */ 881248515Skib if (vmapbuf(mapinfo->bp[i], 1) < 0) { 882109572Sdillon for (j = 0; j < i; ++j) { 883109572Sdillon *data_ptrs[j] = mapinfo->bp[j]->b_saveaddr; 884119957Salc vunmapbuf(mapinfo->bp[j]); 885109572Sdillon relpbuf(mapinfo->bp[j], NULL); 886109572Sdillon } 887119957Salc relpbuf(mapinfo->bp[i], NULL); 888109572Sdillon PRELE(curproc); 889109572Sdillon return(EACCES); 890109572Sdillon } 89139212Sgibbs 89239212Sgibbs /* set our pointer to the new mapped area */ 89339212Sgibbs *data_ptrs[i] = mapinfo->bp[i]->b_data; 89439212Sgibbs 89539212Sgibbs mapinfo->num_bufs_used++; 89639212Sgibbs } 89739212Sgibbs 898158883Smjacob /* 899158883Smjacob * Now that we've gotten this far, change ownership to the kernel 900158883Smjacob * of the buffers so that we don't run afoul of returning to user 901158883Smjacob * space with locks (on the buffer) held. 902158883Smjacob */ 903158883Smjacob for (i = 0; i < numbufs; i++) { 904158883Smjacob BUF_KERNPROC(mapinfo->bp[i]); 905158883Smjacob } 906158883Smjacob 907158883Smjacob 90839212Sgibbs return(0); 90939212Sgibbs} 91039212Sgibbs 91139212Sgibbs/* 91239212Sgibbs * Unmap memory segments mapped into kernel virtual address space by 91339212Sgibbs * cam_periph_mapmem(). 91439212Sgibbs */ 91539212Sgibbsvoid 91639212Sgibbscam_periph_unmapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo) 91739212Sgibbs{ 91839212Sgibbs int numbufs, i; 91939212Sgibbs u_int8_t **data_ptrs[CAM_PERIPH_MAXMAPS]; 92039212Sgibbs 92139212Sgibbs if (mapinfo->num_bufs_used <= 0) { 922251479Sscottl /* nothing to free and the process wasn't held. */ 92339212Sgibbs return; 92439212Sgibbs } 92539212Sgibbs 92639212Sgibbs switch (ccb->ccb_h.func_code) { 92739212Sgibbs case XPT_DEV_MATCH: 92839212Sgibbs numbufs = min(mapinfo->num_bufs_used, 2); 92939212Sgibbs 93039212Sgibbs if (numbufs == 1) { 93139212Sgibbs data_ptrs[0] = (u_int8_t **)&ccb->cdm.matches; 93239212Sgibbs } else { 93339212Sgibbs data_ptrs[0] = (u_int8_t **)&ccb->cdm.patterns; 93439212Sgibbs data_ptrs[1] = (u_int8_t **)&ccb->cdm.matches; 93539212Sgibbs } 93639212Sgibbs break; 93739212Sgibbs case XPT_SCSI_IO: 93847509Sgibbs case XPT_CONT_TARGET_IO: 93939212Sgibbs data_ptrs[0] = &ccb->csio.data_ptr; 94039212Sgibbs numbufs = min(mapinfo->num_bufs_used, 1); 94139212Sgibbs break; 942195534Sscottl case XPT_ATA_IO: 943195534Sscottl data_ptrs[0] = &ccb->ataio.data_ptr; 944195534Sscottl numbufs = min(mapinfo->num_bufs_used, 1); 945195534Sscottl break; 946216088Sken case XPT_SMP_IO: 947216088Sken numbufs = min(mapinfo->num_bufs_used, 2); 948216088Sken data_ptrs[0] = &ccb->smpio.smp_request; 949216088Sken data_ptrs[1] = &ccb->smpio.smp_response; 950216088Sken break; 951223081Sgibbs case XPT_DEV_ADVINFO: 952216088Sken numbufs = min(mapinfo->num_bufs_used, 1); 953223081Sgibbs data_ptrs[0] = (uint8_t **)&ccb->cdai.buf; 954216088Sken break; 95539212Sgibbs default: 95639212Sgibbs /* allow ourselves to be swapped once again */ 95745359Speter PRELE(curproc); 95839212Sgibbs return; 95939212Sgibbs break; /* NOTREACHED */ 96039212Sgibbs } 96139212Sgibbs 96239212Sgibbs for (i = 0; i < numbufs; i++) { 96339212Sgibbs /* Set the user's pointer back to the original value */ 96439212Sgibbs *data_ptrs[i] = mapinfo->bp[i]->b_saveaddr; 96539212Sgibbs 96639212Sgibbs /* unmap the buffer */ 96739212Sgibbs vunmapbuf(mapinfo->bp[i]); 96839212Sgibbs 96939212Sgibbs /* release the buffer */ 97042957Sdillon relpbuf(mapinfo->bp[i], NULL); 97139212Sgibbs } 97239212Sgibbs 97339212Sgibbs /* allow ourselves to be swapped once again */ 97445359Speter PRELE(curproc); 97539212Sgibbs} 97639212Sgibbs 97739212Sgibbsvoid 97839212Sgibbscam_periph_ccbwait(union ccb *ccb) 97939212Sgibbs{ 98039212Sgibbs 98139212Sgibbs if ((ccb->ccb_h.pinfo.index != CAM_UNQUEUED_INDEX) 98239212Sgibbs || ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG)) 983260387Sscottl xpt_path_sleep(ccb->ccb_h.path, &ccb->ccb_h.cbfcnp, PRIBIO, 984260387Sscottl "cbwait", 0); 98539212Sgibbs} 98639212Sgibbs 98739212Sgibbsint 988194627Sscottlcam_periph_ioctl(struct cam_periph *periph, u_long cmd, caddr_t addr, 98939212Sgibbs int (*error_routine)(union ccb *ccb, 99039212Sgibbs cam_flags camflags, 99139212Sgibbs u_int32_t sense_flags)) 99239212Sgibbs{ 99339212Sgibbs union ccb *ccb; 99439212Sgibbs int error; 99539212Sgibbs int found; 99639212Sgibbs 99739212Sgibbs error = found = 0; 99839212Sgibbs 99939212Sgibbs switch(cmd){ 100039212Sgibbs case CAMGETPASSTHRU: 1001198382Smav ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); 100239212Sgibbs xpt_setup_ccb(&ccb->ccb_h, 100339212Sgibbs ccb->ccb_h.path, 1004198382Smav CAM_PRIORITY_NORMAL); 100539212Sgibbs ccb->ccb_h.func_code = XPT_GDEVLIST; 100639212Sgibbs 100739212Sgibbs /* 100839212Sgibbs * Basically, the point of this is that we go through 100939212Sgibbs * getting the list of devices, until we find a passthrough 101039212Sgibbs * device. In the current version of the CAM code, the 101139212Sgibbs * only way to determine what type of device we're dealing 101239212Sgibbs * with is by its name. 101339212Sgibbs */ 101439212Sgibbs while (found == 0) { 101539212Sgibbs ccb->cgdl.index = 0; 101639212Sgibbs ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS; 101739212Sgibbs while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) { 101839212Sgibbs 101939212Sgibbs /* we want the next device in the list */ 102039212Sgibbs xpt_action(ccb); 102139212Sgibbs if (strncmp(ccb->cgdl.periph_name, 102239212Sgibbs "pass", 4) == 0){ 102339212Sgibbs found = 1; 102439212Sgibbs break; 102539212Sgibbs } 102639212Sgibbs } 102739212Sgibbs if ((ccb->cgdl.status == CAM_GDEVLIST_LAST_DEVICE) && 102839212Sgibbs (found == 0)) { 102939212Sgibbs ccb->cgdl.periph_name[0] = '\0'; 103039212Sgibbs ccb->cgdl.unit_number = 0; 103139212Sgibbs break; 103239212Sgibbs } 103339212Sgibbs } 103439212Sgibbs 103539212Sgibbs /* copy the result back out */ 103639212Sgibbs bcopy(ccb, addr, sizeof(union ccb)); 103739212Sgibbs 103839212Sgibbs /* and release the ccb */ 103939212Sgibbs xpt_release_ccb(ccb); 104039212Sgibbs 104139212Sgibbs break; 104239212Sgibbs default: 104339212Sgibbs error = ENOTTY; 104439212Sgibbs break; 104539212Sgibbs } 104639212Sgibbs return(error); 104739212Sgibbs} 104839212Sgibbs 1049260387Sscottlstatic void 1050260387Sscottlcam_periph_done(struct cam_periph *periph, union ccb *done_ccb) 1051260387Sscottl{ 1052260387Sscottl 1053260387Sscottl /* Caller will release the CCB */ 1054260387Sscottl wakeup(&done_ccb->ccb_h.cbfcnp); 1055260387Sscottl} 1056260387Sscottl 105739212Sgibbsint 105839212Sgibbscam_periph_runccb(union ccb *ccb, 105939212Sgibbs int (*error_routine)(union ccb *ccb, 106039212Sgibbs cam_flags camflags, 106139212Sgibbs u_int32_t sense_flags), 106239212Sgibbs cam_flags camflags, u_int32_t sense_flags, 106339212Sgibbs struct devstat *ds) 106439212Sgibbs{ 1065280446Sken struct bintime *starttime; 1066280446Sken struct bintime ltime; 106739212Sgibbs int error; 106839212Sgibbs 1069280446Sken starttime = NULL; 1070260387Sscottl xpt_path_assert(ccb->ccb_h.path, MA_OWNED); 1071168752Sscottl 107239212Sgibbs /* 107339212Sgibbs * If the user has supplied a stats structure, and if we understand 107439212Sgibbs * this particular type of ccb, record the transaction start. 107539212Sgibbs */ 1076198947Smav if ((ds != NULL) && (ccb->ccb_h.func_code == XPT_SCSI_IO || 1077280446Sken ccb->ccb_h.func_code == XPT_ATA_IO)) { 1078280446Sken starttime = <ime; 1079280446Sken binuptime(starttime); 1080280446Sken devstat_start_transaction(ds, starttime); 1081280446Sken } 108239212Sgibbs 1083260387Sscottl ccb->ccb_h.cbfcnp = cam_periph_done; 108439212Sgibbs xpt_action(ccb); 108539212Sgibbs 108639212Sgibbs do { 108739212Sgibbs cam_periph_ccbwait(ccb); 108839212Sgibbs if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) 108939212Sgibbs error = 0; 109039212Sgibbs else if (error_routine != NULL) 109139212Sgibbs error = (*error_routine)(ccb, camflags, sense_flags); 109239212Sgibbs else 109339212Sgibbs error = 0; 109439212Sgibbs 109539212Sgibbs } while (error == ERESTART); 109639212Sgibbs 1097203108Smav if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 109839212Sgibbs cam_release_devq(ccb->ccb_h.path, 109939212Sgibbs /* relsim_flags */0, 110039212Sgibbs /* openings */0, 110139212Sgibbs /* timeout */0, 110239212Sgibbs /* getcount_only */ FALSE); 1103203108Smav ccb->ccb_h.status &= ~CAM_DEV_QFRZN; 1104203108Smav } 110539212Sgibbs 1106198947Smav if (ds != NULL) { 1107198947Smav if (ccb->ccb_h.func_code == XPT_SCSI_IO) { 1108198947Smav devstat_end_transaction(ds, 1109280446Sken ccb->csio.dxfer_len - ccb->csio.resid, 1110198947Smav ccb->csio.tag_action & 0x3, 111139212Sgibbs ((ccb->ccb_h.flags & CAM_DIR_MASK) == 111239212Sgibbs CAM_DIR_NONE) ? DEVSTAT_NO_DATA : 111339212Sgibbs (ccb->ccb_h.flags & CAM_DIR_OUT) ? 111439212Sgibbs DEVSTAT_WRITE : 1115280446Sken DEVSTAT_READ, NULL, starttime); 1116198947Smav } else if (ccb->ccb_h.func_code == XPT_ATA_IO) { 1117198947Smav devstat_end_transaction(ds, 1118280446Sken ccb->ataio.dxfer_len - ccb->ataio.resid, 1119198947Smav ccb->ataio.tag_action & 0x3, 1120198947Smav ((ccb->ccb_h.flags & CAM_DIR_MASK) == 1121198947Smav CAM_DIR_NONE) ? DEVSTAT_NO_DATA : 1122198947Smav (ccb->ccb_h.flags & CAM_DIR_OUT) ? 1123198947Smav DEVSTAT_WRITE : 1124280446Sken DEVSTAT_READ, NULL, starttime); 1125198947Smav } 1126198947Smav } 112739212Sgibbs 112839212Sgibbs return(error); 112939212Sgibbs} 113039212Sgibbs 113147412Sgibbsvoid 113247412Sgibbscam_freeze_devq(struct cam_path *path) 113347412Sgibbs{ 1134249466Smav struct ccb_hdr ccb_h; 113547412Sgibbs 1136255126Smav CAM_DEBUG(path, CAM_DEBUG_TRACE, ("cam_freeze_devq\n")); 1137249466Smav xpt_setup_ccb(&ccb_h, path, /*priority*/1); 1138249466Smav ccb_h.func_code = XPT_NOOP; 1139249466Smav ccb_h.flags = CAM_DEV_QFREEZE; 1140249466Smav xpt_action((union ccb *)&ccb_h); 114147412Sgibbs} 114247412Sgibbs 114339212Sgibbsu_int32_t 114439212Sgibbscam_release_devq(struct cam_path *path, u_int32_t relsim_flags, 1145203108Smav u_int32_t openings, u_int32_t arg, 114639212Sgibbs int getcount_only) 114739212Sgibbs{ 114839212Sgibbs struct ccb_relsim crs; 114939212Sgibbs 1150255126Smav CAM_DEBUG(path, CAM_DEBUG_TRACE, ("cam_release_devq(%u, %u, %u, %d)\n", 1151255126Smav relsim_flags, openings, arg, getcount_only)); 1152198382Smav xpt_setup_ccb(&crs.ccb_h, path, CAM_PRIORITY_NORMAL); 115339212Sgibbs crs.ccb_h.func_code = XPT_REL_SIMQ; 115439212Sgibbs crs.ccb_h.flags = getcount_only ? CAM_DEV_QFREEZE : 0; 115539212Sgibbs crs.release_flags = relsim_flags; 115639212Sgibbs crs.openings = openings; 1157203108Smav crs.release_timeout = arg; 115839212Sgibbs xpt_action((union ccb *)&crs); 115939212Sgibbs return (crs.qfrozen_cnt); 116039212Sgibbs} 116139212Sgibbs 116239212Sgibbs#define saved_ccb_ptr ppriv_ptr0 116339212Sgibbsstatic void 116439212Sgibbscamperiphdone(struct cam_periph *periph, union ccb *done_ccb) 116539212Sgibbs{ 1166236814Smav union ccb *saved_ccb; 116739212Sgibbs cam_status status; 116839212Sgibbs struct scsi_start_stop_unit *scsi_cmd; 1169237478Smav int error_code, sense_key, asc, ascq; 117039212Sgibbs 1171236814Smav scsi_cmd = (struct scsi_start_stop_unit *) 1172236814Smav &done_ccb->csio.cdb_io.cdb_bytes; 117339212Sgibbs status = done_ccb->ccb_h.status; 117439212Sgibbs 1175236814Smav if ((status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1176237478Smav if (scsi_extract_sense_ccb(done_ccb, 1177237478Smav &error_code, &sense_key, &asc, &ascq)) { 117839212Sgibbs /* 1179236814Smav * If the error is "invalid field in CDB", 1180236814Smav * and the load/eject flag is set, turn the 1181236814Smav * flag off and try again. This is just in 1182236814Smav * case the drive in question barfs on the 1183236814Smav * load eject flag. The CAM code should set 1184236814Smav * the load/eject flag by default for 118539212Sgibbs * removable media. 118639212Sgibbs */ 118739212Sgibbs if ((scsi_cmd->opcode == START_STOP_UNIT) && 118839212Sgibbs ((scsi_cmd->how & SSS_LOEJ) != 0) && 1189236814Smav (asc == 0x24) && (ascq == 0x00)) { 119039212Sgibbs scsi_cmd->how &= ~SSS_LOEJ; 1191236814Smav if (status & CAM_DEV_QFRZN) { 1192236814Smav cam_release_devq(done_ccb->ccb_h.path, 1193236814Smav 0, 0, 0, 0); 1194236814Smav done_ccb->ccb_h.status &= 1195236814Smav ~CAM_DEV_QFRZN; 1196236814Smav } 119739212Sgibbs xpt_action(done_ccb); 1198236814Smav goto out; 119939212Sgibbs } 120039212Sgibbs } 1201236814Smav if (cam_periph_error(done_ccb, 1202236814Smav 0, SF_RETRY_UA | SF_NO_PRINT, NULL) == ERESTART) 1203236814Smav goto out; 1204236814Smav if (done_ccb->ccb_h.status & CAM_DEV_QFRZN) { 1205236814Smav cam_release_devq(done_ccb->ccb_h.path, 0, 0, 0, 0); 1206236814Smav done_ccb->ccb_h.status &= ~CAM_DEV_QFRZN; 1207236814Smav } 1208236814Smav } else { 1209236814Smav /* 1210236814Smav * If we have successfully taken a device from the not 1211236814Smav * ready to ready state, re-scan the device and re-get 1212236814Smav * the inquiry information. Many devices (mostly disks) 1213236814Smav * don't properly report their inquiry information unless 1214236814Smav * they are spun up. 1215236814Smav */ 1216236814Smav if (scsi_cmd->opcode == START_STOP_UNIT) 1217236814Smav xpt_async(AC_INQ_CHANGED, done_ccb->ccb_h.path, NULL); 121839212Sgibbs } 121939212Sgibbs 122074840Sken /* 1221236814Smav * Perform the final retry with the original CCB so that final 1222236814Smav * error processing is performed by the owner of the CCB. 122374840Sken */ 1224236814Smav saved_ccb = (union ccb *)done_ccb->ccb_h.saved_ccb_ptr; 1225236814Smav bcopy(saved_ccb, done_ccb, sizeof(*done_ccb)); 1226236814Smav xpt_free_ccb(saved_ccb); 1227236814Smav if (done_ccb->ccb_h.cbfcnp != camperiphdone) 1228236814Smav periph->flags &= ~CAM_PERIPH_RECOVERY_INPROG; 1229236814Smav xpt_action(done_ccb); 1230236814Smav 1231236814Smavout: 1232236814Smav /* Drop freeze taken due to CAM_DEV_QFREEZE flag set. */ 1233236814Smav cam_release_devq(done_ccb->ccb_h.path, 0, 0, 0, 0); 123439212Sgibbs} 123539212Sgibbs 123639212Sgibbs/* 123747412Sgibbs * Generic Async Event handler. Peripheral drivers usually 123847412Sgibbs * filter out the events that require personal attention, 123947412Sgibbs * and leave the rest to this function. 124047412Sgibbs */ 124147412Sgibbsvoid 124247412Sgibbscam_periph_async(struct cam_periph *periph, u_int32_t code, 124347412Sgibbs struct cam_path *path, void *arg) 124447412Sgibbs{ 124547412Sgibbs switch (code) { 124647412Sgibbs case AC_LOST_DEVICE: 124747412Sgibbs cam_periph_invalidate(periph); 124847412Sgibbs break; 124947412Sgibbs default: 125047412Sgibbs break; 125147412Sgibbs } 125247412Sgibbs} 125347412Sgibbs 125447412Sgibbsvoid 125547412Sgibbscam_periph_bus_settle(struct cam_periph *periph, u_int bus_settle) 125647412Sgibbs{ 125747412Sgibbs struct ccb_getdevstats cgds; 125847412Sgibbs 1259198382Smav xpt_setup_ccb(&cgds.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 126047412Sgibbs cgds.ccb_h.func_code = XPT_GDEV_STATS; 126147412Sgibbs xpt_action((union ccb *)&cgds); 126247412Sgibbs cam_periph_freeze_after_event(periph, &cgds.last_reset, bus_settle); 126347412Sgibbs} 126447412Sgibbs 126547412Sgibbsvoid 126647412Sgibbscam_periph_freeze_after_event(struct cam_periph *periph, 126747412Sgibbs struct timeval* event_time, u_int duration_ms) 126847412Sgibbs{ 126947412Sgibbs struct timeval delta; 127047412Sgibbs struct timeval duration_tv; 127147412Sgibbs 1272241536Smav if (!timevalisset(event_time)) 1273241536Smav return; 1274241536Smav 127547412Sgibbs microtime(&delta); 127647412Sgibbs timevalsub(&delta, event_time); 127747412Sgibbs duration_tv.tv_sec = duration_ms / 1000; 127847412Sgibbs duration_tv.tv_usec = (duration_ms % 1000) * 1000; 127947412Sgibbs if (timevalcmp(&delta, &duration_tv, <)) { 128047412Sgibbs timevalsub(&duration_tv, &delta); 128147412Sgibbs 128247412Sgibbs duration_ms = duration_tv.tv_sec * 1000; 128347412Sgibbs duration_ms += duration_tv.tv_usec / 1000; 128447412Sgibbs cam_freeze_devq(periph->path); 128547412Sgibbs cam_release_devq(periph->path, 128647412Sgibbs RELSIM_RELEASE_AFTER_TIMEOUT, 128747412Sgibbs /*reduction*/0, 128847412Sgibbs /*timeout*/duration_ms, 128947412Sgibbs /*getcount_only*/0); 129047412Sgibbs } 129147412Sgibbs 129247412Sgibbs} 129347412Sgibbs 129474840Skenstatic int 1295236814Smavcamperiphscsistatuserror(union ccb *ccb, union ccb **orig_ccb, 1296236814Smav cam_flags camflags, u_int32_t sense_flags, 1297236814Smav int *openings, u_int32_t *relsim_flags, 1298253322Smav u_int32_t *timeout, u_int32_t *action, const char **action_string) 129939212Sgibbs{ 130074840Sken int error; 130139212Sgibbs 130274840Sken switch (ccb->csio.scsi_status) { 130374840Sken case SCSI_STATUS_OK: 130474840Sken case SCSI_STATUS_COND_MET: 130574840Sken case SCSI_STATUS_INTERMED: 130674840Sken case SCSI_STATUS_INTERMED_COND_MET: 130739212Sgibbs error = 0; 130839212Sgibbs break; 130974840Sken case SCSI_STATUS_CMD_TERMINATED: 131074840Sken case SCSI_STATUS_CHECK_COND: 1311236814Smav error = camperiphscsisenseerror(ccb, orig_ccb, 131274840Sken camflags, 131374840Sken sense_flags, 131474840Sken openings, 131574840Sken relsim_flags, 1316203108Smav timeout, 1317253322Smav action, 1318203108Smav action_string); 131974840Sken break; 132074840Sken case SCSI_STATUS_QUEUE_FULL: 132174840Sken { 132274840Sken /* no decrement */ 132374840Sken struct ccb_getdevstats cgds; 132439212Sgibbs 132574840Sken /* 132674840Sken * First off, find out what the current 132774840Sken * transaction counts are. 132874840Sken */ 132974840Sken xpt_setup_ccb(&cgds.ccb_h, 133074840Sken ccb->ccb_h.path, 1331198382Smav CAM_PRIORITY_NORMAL); 133274840Sken cgds.ccb_h.func_code = XPT_GDEV_STATS; 133374840Sken xpt_action((union ccb *)&cgds); 133439212Sgibbs 133574840Sken /* 133674840Sken * If we were the only transaction active, treat 133774840Sken * the QUEUE FULL as if it were a BUSY condition. 133874840Sken */ 133974840Sken if (cgds.dev_active != 0) { 134074840Sken int total_openings; 134139212Sgibbs 134274840Sken /* 134374840Sken * Reduce the number of openings to 134474840Sken * be 1 less than the amount it took 134574840Sken * to get a queue full bounded by the 134674840Sken * minimum allowed tag count for this 134774840Sken * device. 134874840Sken */ 134974840Sken total_openings = cgds.dev_active + cgds.dev_openings; 135074840Sken *openings = cgds.dev_active; 135174840Sken if (*openings < cgds.mintags) 135274840Sken *openings = cgds.mintags; 135374840Sken if (*openings < total_openings) 135474840Sken *relsim_flags = RELSIM_ADJUST_OPENINGS; 135574840Sken else { 135639212Sgibbs /* 135774840Sken * Some devices report queue full for 135874840Sken * temporary resource shortages. For 135974840Sken * this reason, we allow a minimum 136074840Sken * tag count to be entered via a 136174840Sken * quirk entry to prevent the queue 136274840Sken * count on these devices from falling 136374840Sken * to a pessimisticly low value. We 136474840Sken * still wait for the next successful 136574840Sken * completion, however, before queueing 136674840Sken * more transactions to the device. 136739212Sgibbs */ 136874840Sken *relsim_flags = RELSIM_RELEASE_AFTER_CMDCMPLT; 136974840Sken } 137074840Sken *timeout = 0; 137174840Sken error = ERESTART; 1372253322Smav *action &= ~SSQ_PRINT_SENSE; 137374840Sken break; 137474840Sken } 137574840Sken /* FALLTHROUGH */ 137674840Sken } 137774840Sken case SCSI_STATUS_BUSY: 137874840Sken /* 137974840Sken * Restart the queue after either another 138074840Sken * command completes or a 1 second timeout. 138174840Sken */ 1382278440Smav if ((sense_flags & SF_RETRY_BUSY) != 0 || 1383278440Smav (ccb->ccb_h.retry_count--) > 0) { 138474840Sken error = ERESTART; 138574840Sken *relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT 138674840Sken | RELSIM_RELEASE_AFTER_CMDCMPLT; 138774840Sken *timeout = 1000; 138874840Sken } else { 138974840Sken error = EIO; 139074840Sken } 139174840Sken break; 139274840Sken case SCSI_STATUS_RESERV_CONFLICT: 139374840Sken default: 139474840Sken error = EIO; 139574840Sken break; 139674840Sken } 139774840Sken return (error); 139874840Sken} 139939212Sgibbs 140074840Skenstatic int 1401236814Smavcamperiphscsisenseerror(union ccb *ccb, union ccb **orig, 1402236814Smav cam_flags camflags, u_int32_t sense_flags, 1403236814Smav int *openings, u_int32_t *relsim_flags, 1404253322Smav u_int32_t *timeout, u_int32_t *action, const char **action_string) 140574840Sken{ 140674840Sken struct cam_periph *periph; 1407203108Smav union ccb *orig_ccb = ccb; 1408236814Smav int error, recoveryccb; 140939212Sgibbs 141074840Sken periph = xpt_path_periph(ccb->ccb_h.path); 1411236814Smav recoveryccb = (ccb->ccb_h.cbfcnp == camperiphdone); 1412236814Smav if ((periph->flags & CAM_PERIPH_RECOVERY_INPROG) && !recoveryccb) { 141374840Sken /* 141474840Sken * If error recovery is already in progress, don't attempt 141574840Sken * to process this error, but requeue it unconditionally 141674840Sken * and attempt to process it once error recovery has 141774840Sken * completed. This failed command is probably related to 141874840Sken * the error that caused the currently active error recovery 141974840Sken * action so our current recovery efforts should also 142074840Sken * address this command. Be aware that the error recovery 142174840Sken * code assumes that only one recovery action is in progress 142274840Sken * on a particular peripheral instance at any given time 142374840Sken * (e.g. only one saved CCB for error recovery) so it is 142474840Sken * imperitive that we don't violate this assumption. 142574840Sken */ 142674840Sken error = ERESTART; 1427253322Smav *action &= ~SSQ_PRINT_SENSE; 142874840Sken } else { 142974840Sken scsi_sense_action err_action; 143074840Sken struct ccb_getdev cgd; 143140318Sken 143274840Sken /* 143374840Sken * Grab the inquiry data for this device. 143474840Sken */ 1435198382Smav xpt_setup_ccb(&cgd.ccb_h, ccb->ccb_h.path, CAM_PRIORITY_NORMAL); 143674840Sken cgd.ccb_h.func_code = XPT_GDEV_TYPE; 143774840Sken xpt_action((union ccb *)&cgd); 143839212Sgibbs 1439237478Smav err_action = scsi_error_action(&ccb->csio, &cgd.inq_data, 1440237478Smav sense_flags); 144174840Sken error = err_action & SS_ERRMASK; 144239212Sgibbs 144374840Sken /* 1444236814Smav * Do not autostart sequential access devices 1445236814Smav * to avoid unexpected tape loading. 1446236814Smav */ 1447236814Smav if ((err_action & SS_MASK) == SS_START && 1448236814Smav SID_TYPE(&cgd.inq_data) == T_SEQUENTIAL) { 1449236814Smav *action_string = "Will not autostart a " 1450236814Smav "sequential access device"; 1451236814Smav goto sense_error_done; 1452236814Smav } 1453236814Smav 1454236814Smav /* 1455236814Smav * Avoid recovery recursion if recovery action is the same. 1456236814Smav */ 1457236814Smav if ((err_action & SS_MASK) >= SS_START && recoveryccb) { 1458236814Smav if (((err_action & SS_MASK) == SS_START && 1459236814Smav ccb->csio.cdb_io.cdb_bytes[0] == START_STOP_UNIT) || 1460236814Smav ((err_action & SS_MASK) == SS_TUR && 1461236814Smav (ccb->csio.cdb_io.cdb_bytes[0] == TEST_UNIT_READY))) { 1462236814Smav err_action = SS_RETRY|SSQ_DECREMENT_COUNT|EIO; 1463236814Smav *relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT; 1464236814Smav *timeout = 500; 1465236814Smav } 1466236814Smav } 1467236814Smav 1468236814Smav /* 146974840Sken * If the recovery action will consume a retry, 147074840Sken * make sure we actually have retries available. 147174840Sken */ 147274840Sken if ((err_action & SSQ_DECREMENT_COUNT) != 0) { 1473224496Smav if (ccb->ccb_h.retry_count > 0 && 1474224496Smav (periph->flags & CAM_PERIPH_INVALID) == 0) 147574840Sken ccb->ccb_h.retry_count--; 147674840Sken else { 1477203108Smav *action_string = "Retries exhausted"; 147874840Sken goto sense_error_done; 147974840Sken } 148074840Sken } 148139212Sgibbs 148274840Sken if ((err_action & SS_MASK) >= SS_START) { 148374840Sken /* 148474840Sken * Do common portions of commands that 148574840Sken * use recovery CCBs. 148674840Sken */ 1487203108Smav orig_ccb = xpt_alloc_ccb_nowait(); 1488203108Smav if (orig_ccb == NULL) { 1489203108Smav *action_string = "Can't allocate recovery CCB"; 149074840Sken goto sense_error_done; 149174840Sken } 1492199281Smav /* 1493199281Smav * Clear freeze flag for original request here, as 1494199281Smav * this freeze will be dropped as part of ERESTART. 1495199281Smav */ 1496199281Smav ccb->ccb_h.status &= ~CAM_DEV_QFRZN; 1497203108Smav bcopy(ccb, orig_ccb, sizeof(*orig_ccb)); 149874840Sken } 149939212Sgibbs 150074840Sken switch (err_action & SS_MASK) { 150174840Sken case SS_NOP: 1502203108Smav *action_string = "No recovery action needed"; 150376158Sken error = 0; 150476158Sken break; 150574840Sken case SS_RETRY: 1506203108Smav *action_string = "Retrying command (per sense data)"; 150774840Sken error = ERESTART; 150839212Sgibbs break; 150974840Sken case SS_FAIL: 1510203108Smav *action_string = "Unretryable error"; 151174840Sken break; 151274840Sken case SS_START: 151339212Sgibbs { 151474840Sken int le; 151539212Sgibbs 151639212Sgibbs /* 151774840Sken * Send a start unit command to the device, and 151874840Sken * then retry the command. 151939212Sgibbs */ 1520203108Smav *action_string = "Attempting to start unit"; 1521203108Smav periph->flags |= CAM_PERIPH_RECOVERY_INPROG; 152239212Sgibbs 152339212Sgibbs /* 152474840Sken * Check for removable media and set 152574840Sken * load/eject flag appropriately. 152639212Sgibbs */ 152774840Sken if (SID_IS_REMOVABLE(&cgd.inq_data)) 152874840Sken le = TRUE; 152974840Sken else 153074840Sken le = FALSE; 153147434Sgibbs 153274840Sken scsi_start_stop(&ccb->csio, 153374840Sken /*retries*/1, 153474840Sken camperiphdone, 153574840Sken MSG_SIMPLE_Q_TAG, 153674840Sken /*start*/TRUE, 153774840Sken /*load/eject*/le, 153874840Sken /*immediate*/FALSE, 153974840Sken SSD_FULL_SIZE, 154074840Sken /*timeout*/50000); 154174840Sken break; 154239212Sgibbs } 154374840Sken case SS_TUR: 154474840Sken { 154539212Sgibbs /* 154674840Sken * Send a Test Unit Ready to the device. 154774840Sken * If the 'many' flag is set, we send 120 154874840Sken * test unit ready commands, one every half 154974840Sken * second. Otherwise, we just send one TUR. 155074840Sken * We only want to do this if the retry 155174840Sken * count has not been exhausted. 155239212Sgibbs */ 155374840Sken int retries; 155474840Sken 155574840Sken if ((err_action & SSQ_MANY) != 0) { 1556203108Smav *action_string = "Polling device for readiness"; 155774840Sken retries = 120; 155852326Smjacob } else { 1559203108Smav *action_string = "Testing device for readiness"; 156074840Sken retries = 1; 156152326Smjacob } 1562203108Smav periph->flags |= CAM_PERIPH_RECOVERY_INPROG; 156374840Sken scsi_test_unit_ready(&ccb->csio, 156474840Sken retries, 156574840Sken camperiphdone, 156674840Sken MSG_SIMPLE_Q_TAG, 156774840Sken SSD_FULL_SIZE, 156874840Sken /*timeout*/5000); 156974840Sken 157074840Sken /* 157174840Sken * Accomplish our 500ms delay by deferring 157274840Sken * the release of our device queue appropriately. 157374840Sken */ 157474840Sken *relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT; 157574840Sken *timeout = 500; 157639212Sgibbs break; 157774840Sken } 157839212Sgibbs default: 1579106902Simp panic("Unhandled error action %x", err_action); 158039212Sgibbs } 158174840Sken 158274840Sken if ((err_action & SS_MASK) >= SS_START) { 158374840Sken /* 1584198382Smav * Drop the priority, so that the recovery 158574840Sken * CCB is the first to execute. Freeze the queue 158674840Sken * after this command is sent so that we can 158774840Sken * restore the old csio and have it queued in 158874840Sken * the proper order before we release normal 158974840Sken * transactions to the device. 159074840Sken */ 1591203108Smav ccb->ccb_h.pinfo.priority--; 159274840Sken ccb->ccb_h.flags |= CAM_DEV_QFREEZE; 1593203108Smav ccb->ccb_h.saved_ccb_ptr = orig_ccb; 159474840Sken error = ERESTART; 1595236814Smav *orig = orig_ccb; 159674840Sken } 159774840Sken 159874840Skensense_error_done: 1599253322Smav *action = err_action; 160074840Sken } 160174840Sken return (error); 160274840Sken} 160374840Sken 160474840Sken/* 160574840Sken * Generic error handler. Peripheral drivers usually filter 160674840Sken * out the errors that they handle in a unique mannor, then 160774840Sken * call this function. 160874840Sken */ 160974840Skenint 161074840Skencam_periph_error(union ccb *ccb, cam_flags camflags, 161174840Sken u_int32_t sense_flags, union ccb *save_ccb) 161274840Sken{ 1613253322Smav struct cam_path *newpath; 1614253322Smav union ccb *orig_ccb, *scan_ccb; 1615224496Smav struct cam_periph *periph; 161674840Sken const char *action_string; 161774840Sken cam_status status; 1618253322Smav int frozen, error, openings; 1619253322Smav u_int32_t action, relsim_flags, timeout; 1620224496Smav 1621253322Smav action = SSQ_PRINT_SENSE; 1622224496Smav periph = xpt_path_periph(ccb->ccb_h.path); 162374840Sken action_string = NULL; 162474840Sken status = ccb->ccb_h.status; 162574840Sken frozen = (status & CAM_DEV_QFRZN) != 0; 162674840Sken status &= CAM_STATUS_MASK; 1627253322Smav openings = relsim_flags = timeout = 0; 1628236814Smav orig_ccb = ccb; 162974840Sken 163074840Sken switch (status) { 163174840Sken case CAM_REQ_CMP: 163274840Sken error = 0; 1633253322Smav action &= ~SSQ_PRINT_SENSE; 163439212Sgibbs break; 163574840Sken case CAM_SCSI_STATUS_ERROR: 1636236814Smav error = camperiphscsistatuserror(ccb, &orig_ccb, 1637236814Smav camflags, sense_flags, &openings, &relsim_flags, 1638253322Smav &timeout, &action, &action_string); 163974840Sken break; 164074840Sken case CAM_AUTOSENSE_FAIL: 164180578Smjacob error = EIO; /* we have to kill the command */ 164280578Smjacob break; 164339212Sgibbs case CAM_UA_ABORT: 164439212Sgibbs case CAM_UA_TERMIO: 164539212Sgibbs case CAM_MSG_REJECT_REC: 164639212Sgibbs /* XXX Don't know that these are correct */ 164739212Sgibbs error = EIO; 164839212Sgibbs break; 164939212Sgibbs case CAM_SEL_TIMEOUT: 165074840Sken if ((camflags & CAM_RETRY_SELTO) != 0) { 1651224496Smav if (ccb->ccb_h.retry_count > 0 && 1652224496Smav (periph->flags & CAM_PERIPH_INVALID) == 0) { 165374840Sken ccb->ccb_h.retry_count--; 165474840Sken error = ERESTART; 165574840Sken 165674840Sken /* 1657162938Smjacob * Wait a bit to give the device 165874840Sken * time to recover before we try again. 165974840Sken */ 166074840Sken relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT; 1661162938Smjacob timeout = periph_selto_delay; 166274840Sken break; 166374840Sken } 1664224496Smav action_string = "Retries exhausted"; 166574840Sken } 1666230000Sken /* FALLTHROUGH */ 1667230000Sken case CAM_DEV_NOT_THERE: 166874840Sken error = ENXIO; 1669253322Smav action = SSQ_LOST; 167039212Sgibbs break; 167139212Sgibbs case CAM_REQ_INVALID: 167239212Sgibbs case CAM_PATH_INVALID: 167339212Sgibbs case CAM_NO_HBA: 167439212Sgibbs case CAM_PROVIDE_FAIL: 167574840Sken case CAM_REQ_TOO_BIG: 1676154119Siedowse case CAM_LUN_INVALID: 1677154119Siedowse case CAM_TID_INVALID: 1678263299Smav case CAM_FUNC_NOTAVAIL: 167939212Sgibbs error = EINVAL; 168039212Sgibbs break; 168139212Sgibbs case CAM_SCSI_BUS_RESET: 168274840Sken case CAM_BDR_SENT: 168374840Sken /* 168474840Sken * Commands that repeatedly timeout and cause these 168574840Sken * kinds of error recovery actions, should return 168674840Sken * CAM_CMD_TIMEOUT, which allows us to safely assume 168774840Sken * that this command was an innocent bystander to 168874840Sken * these events and should be unconditionally 168974840Sken * retried. 169074840Sken */ 169139212Sgibbs case CAM_REQUEUE_REQ: 1692236814Smav /* Unconditional requeue if device is still there */ 1693236814Smav if (periph->flags & CAM_PERIPH_INVALID) { 1694236814Smav action_string = "Periph was invalidated"; 1695236814Smav error = EIO; 1696236814Smav } else if (sense_flags & SF_NO_RETRY) { 1697236814Smav error = EIO; 1698236814Smav action_string = "Retry was blocked"; 1699237446Smav } else { 1700224496Smav error = ERESTART; 1701253322Smav action &= ~SSQ_PRINT_SENSE; 1702237446Smav } 170339212Sgibbs break; 170439212Sgibbs case CAM_RESRC_UNAVAIL: 1705162938Smjacob /* Wait a bit for the resource shortage to abate. */ 1706162938Smjacob timeout = periph_noresrc_delay; 1707162938Smjacob /* FALLTHROUGH */ 170839212Sgibbs case CAM_BUSY: 1709162938Smjacob if (timeout == 0) { 1710162938Smjacob /* Wait a bit for the busy condition to abate. */ 1711162938Smjacob timeout = periph_busy_delay; 1712162938Smjacob } 1713162938Smjacob relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT; 1714162938Smjacob /* FALLTHROUGH */ 1715236814Smav case CAM_ATA_STATUS_ERROR: 1716236814Smav case CAM_REQ_CMP_ERR: 1717236814Smav case CAM_CMD_TIMEOUT: 1718236814Smav case CAM_UNEXP_BUSFREE: 1719236814Smav case CAM_UNCOR_PARITY: 1720236814Smav case CAM_DATA_RUN_ERR: 172139212Sgibbs default: 1722236814Smav if (periph->flags & CAM_PERIPH_INVALID) { 1723236814Smav error = EIO; 1724236814Smav action_string = "Periph was invalidated"; 1725236814Smav } else if (ccb->ccb_h.retry_count == 0) { 1726236814Smav error = EIO; 1727236814Smav action_string = "Retries exhausted"; 1728236814Smav } else if (sense_flags & SF_NO_RETRY) { 1729236814Smav error = EIO; 1730236814Smav action_string = "Retry was blocked"; 1731236814Smav } else { 173239212Sgibbs ccb->ccb_h.retry_count--; 173339212Sgibbs error = ERESTART; 173439212Sgibbs } 173539212Sgibbs break; 173639212Sgibbs } 173739212Sgibbs 1738236814Smav if ((sense_flags & SF_PRINT_ALWAYS) || 1739236814Smav CAM_DEBUGGED(ccb->ccb_h.path, CAM_DEBUG_INFO)) 1740253322Smav action |= SSQ_PRINT_SENSE; 1741236814Smav else if (sense_flags & SF_NO_PRINT) 1742253322Smav action &= ~SSQ_PRINT_SENSE; 1743253322Smav if ((action & SSQ_PRINT_SENSE) != 0) 1744236814Smav cam_error_print(orig_ccb, CAM_ESF_ALL, CAM_EPF_ALL); 1745253322Smav if (error != 0 && (action & SSQ_PRINT_SENSE) != 0) { 1746198394Smav if (error != ERESTART) { 1747198394Smav if (action_string == NULL) 1748203108Smav action_string = "Unretryable error"; 1749203108Smav xpt_print(ccb->ccb_h.path, "Error %d, %s\n", 1750203108Smav error, action_string); 1751203108Smav } else if (action_string != NULL) 1752198394Smav xpt_print(ccb->ccb_h.path, "%s\n", action_string); 1753203108Smav else 1754203108Smav xpt_print(ccb->ccb_h.path, "Retrying command\n"); 1755198394Smav } 1756198394Smav 1757253322Smav if ((action & SSQ_LOST) != 0) { 1758236814Smav lun_id_t lun_id; 1759236814Smav 1760236814Smav /* 1761236814Smav * For a selection timeout, we consider all of the LUNs on 1762236814Smav * the target to be gone. If the status is CAM_DEV_NOT_THERE, 1763236814Smav * then we only get rid of the device(s) specified by the 1764236814Smav * path in the original CCB. 1765236814Smav */ 1766253322Smav if (status == CAM_SEL_TIMEOUT) 1767253322Smav lun_id = CAM_LUN_WILDCARD; 1768253322Smav else 1769236814Smav lun_id = xpt_path_lun_id(ccb->ccb_h.path); 1770236814Smav 1771236814Smav /* Should we do more if we can't create the path?? */ 1772236814Smav if (xpt_create_path(&newpath, periph, 1773236814Smav xpt_path_path_id(ccb->ccb_h.path), 1774236814Smav xpt_path_target_id(ccb->ccb_h.path), 1775236814Smav lun_id) == CAM_REQ_CMP) { 1776236814Smav 1777236814Smav /* 1778236814Smav * Let peripheral drivers know that this 1779236814Smav * device has gone away. 1780236814Smav */ 1781236814Smav xpt_async(AC_LOST_DEVICE, newpath, NULL); 1782236814Smav xpt_free_path(newpath); 1783236814Smav } 1784253322Smav } 1785238886Smav 1786238886Smav /* Broadcast UNIT ATTENTIONs to all periphs. */ 1787253322Smav if ((action & SSQ_UA) != 0) 1788238886Smav xpt_async(AC_UNIT_ATTENTION, orig_ccb->ccb_h.path, orig_ccb); 1789253322Smav 1790253322Smav /* Rescan target on "Reported LUNs data has changed" */ 1791253322Smav if ((action & SSQ_RESCAN) != 0) { 1792253322Smav if (xpt_create_path(&newpath, NULL, 1793253322Smav xpt_path_path_id(ccb->ccb_h.path), 1794253322Smav xpt_path_target_id(ccb->ccb_h.path), 1795253370Smav CAM_LUN_WILDCARD) == CAM_REQ_CMP) { 1796253322Smav 1797253322Smav scan_ccb = xpt_alloc_ccb_nowait(); 1798253370Smav if (scan_ccb != NULL) { 1799253370Smav scan_ccb->ccb_h.path = newpath; 1800253370Smav scan_ccb->ccb_h.func_code = XPT_SCAN_TGT; 1801253370Smav scan_ccb->crcn.flags = 0; 1802253370Smav xpt_rescan(scan_ccb); 1803260387Sscottl } else { 1804253370Smav xpt_print(newpath, 1805253370Smav "Can't allocate CCB to rescan target\n"); 1806260387Sscottl xpt_free_path(newpath); 1807260387Sscottl } 1808253322Smav } 1809236814Smav } 1810236814Smav 181139212Sgibbs /* Attempt a retry */ 1812198394Smav if (error == ERESTART || error == 0) { 181339212Sgibbs if (frozen != 0) 181439212Sgibbs ccb->ccb_h.status &= ~CAM_DEV_QFRZN; 1815198394Smav if (error == ERESTART) 181639212Sgibbs xpt_action(ccb); 181774840Sken if (frozen != 0) 181839212Sgibbs cam_release_devq(ccb->ccb_h.path, 181939212Sgibbs relsim_flags, 182039212Sgibbs openings, 182139212Sgibbs timeout, 182239212Sgibbs /*getcount_only*/0); 182374840Sken } 182474840Sken 182539212Sgibbs return (error); 182639212Sgibbs} 1827