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$"); 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 11172119Speter ndrivers = nperiph_drivers + 2; 112169562Sscottl newdrivers = malloc(sizeof(*newdrivers) * ndrivers, M_CAMPERIPH, 113169562Sscottl M_WAITOK); 11472119Speter if (periph_drivers) 11572119Speter bcopy(periph_drivers, newdrivers, 11675549Sken sizeof(*newdrivers) * nperiph_drivers); 117203108Smav newdrivers[nperiph_drivers] = drv; 11872119Speter newdrivers[nperiph_drivers + 1] = NULL; 11972119Speter old = periph_drivers; 12072119Speter periph_drivers = newdrivers; 12172119Speter if (old) 122169562Sscottl free(old, M_CAMPERIPH); 12372119Speter nperiph_drivers++; 124203108Smav /* If driver marked as early or it is late now, initialize it. */ 125203108Smav if (((drv->flags & CAM_PERIPH_DRV_EARLY) != 0 && initialized > 0) || 126203108Smav initialized > 1) 127203108Smav (*drv->init)(); 12872119Speter} 12972119Speter 130203108Smavvoid 131203108Smavperiphdriver_init(int level) 132203108Smav{ 133203108Smav int i, early; 134203108Smav 135203108Smav initialized = max(initialized, level); 136203108Smav for (i = 0; periph_drivers[i] != NULL; i++) { 137203108Smav early = (periph_drivers[i]->flags & CAM_PERIPH_DRV_EARLY) ? 1 : 2; 138203108Smav if (early == initialized) 139203108Smav (*periph_drivers[i]->init)(); 140203108Smav } 141203108Smav} 142203108Smav 14339212Sgibbscam_status 14440603Skencam_periph_alloc(periph_ctor_t *periph_ctor, 14540603Sken periph_oninv_t *periph_oninvalidate, 14640603Sken periph_dtor_t *periph_dtor, periph_start_t *periph_start, 14740603Sken char *name, cam_periph_type type, struct cam_path *path, 14840603Sken ac_callback_t *ac_callback, ac_code code, void *arg) 14939212Sgibbs{ 15039212Sgibbs struct periph_driver **p_drv; 151168752Sscottl struct cam_sim *sim; 15239212Sgibbs struct cam_periph *periph; 15339212Sgibbs struct cam_periph *cur_periph; 15439212Sgibbs path_id_t path_id; 15539212Sgibbs target_id_t target_id; 15639212Sgibbs lun_id_t lun_id; 15739212Sgibbs cam_status status; 15839212Sgibbs u_int init_level; 15939212Sgibbs 16039212Sgibbs init_level = 0; 16139212Sgibbs /* 16239212Sgibbs * Handle Hot-Plug scenarios. If there is already a peripheral 16339212Sgibbs * of our type assigned to this path, we are likely waiting for 16439212Sgibbs * final close on an old, invalidated, peripheral. If this is 16539212Sgibbs * the case, queue up a deferred call to the peripheral's async 166134530Sgibbs * handler. If it looks like a mistaken re-allocation, complain. 16739212Sgibbs */ 16839212Sgibbs if ((periph = cam_periph_find(path, name)) != NULL) { 16939212Sgibbs 17039212Sgibbs if ((periph->flags & CAM_PERIPH_INVALID) != 0 17139212Sgibbs && (periph->flags & CAM_PERIPH_NEW_DEV_FOUND) == 0) { 17239212Sgibbs periph->flags |= CAM_PERIPH_NEW_DEV_FOUND; 17339212Sgibbs periph->deferred_callback = ac_callback; 17439212Sgibbs periph->deferred_ac = code; 17539212Sgibbs return (CAM_REQ_INPROG); 17639212Sgibbs } else { 17739212Sgibbs printf("cam_periph_alloc: attempt to re-allocate " 178230000Sken "valid device %s%d rejected flags %#x " 179230000Sken "refcount %d\n", periph->periph_name, 180230000Sken periph->unit_number, periph->flags, 181230000Sken periph->refcount); 18239212Sgibbs } 18339212Sgibbs return (CAM_REQ_INVALID); 18439212Sgibbs } 18539212Sgibbs 186147723Savatar periph = (struct cam_periph *)malloc(sizeof(*periph), M_CAMPERIPH, 187230000Sken M_NOWAIT|M_ZERO); 18839212Sgibbs 18939212Sgibbs if (periph == NULL) 19039212Sgibbs return (CAM_RESRC_UNAVAIL); 19139212Sgibbs 19239212Sgibbs init_level++; 19339212Sgibbs 194168752Sscottl 195168752Sscottl sim = xpt_path_sim(path); 19639212Sgibbs path_id = xpt_path_path_id(path); 19739212Sgibbs target_id = xpt_path_target_id(path); 19839212Sgibbs lun_id = xpt_path_lun_id(path); 19939212Sgibbs cam_init_pinfo(&periph->pinfo); 20039212Sgibbs periph->periph_start = periph_start; 20139212Sgibbs periph->periph_dtor = periph_dtor; 20240603Sken periph->periph_oninval = periph_oninvalidate; 20339212Sgibbs periph->type = type; 20439212Sgibbs periph->periph_name = name; 20539212Sgibbs periph->immediate_priority = CAM_PRIORITY_NONE; 206249980Smav periph->refcount = 1; /* Dropped by invalidation. */ 207168752Sscottl periph->sim = sim; 20839212Sgibbs SLIST_INIT(&periph->ccb_list); 20939212Sgibbs status = xpt_create_path(&path, periph, path_id, target_id, lun_id); 21039212Sgibbs if (status != CAM_REQ_CMP) 21139212Sgibbs goto failure; 21239212Sgibbs periph->path = path; 21339212Sgibbs 214208752Smjacob xpt_lock_buses(); 215208752Smjacob for (p_drv = periph_drivers; *p_drv != NULL; p_drv++) { 216208752Smjacob if (strcmp((*p_drv)->driver_name, name) == 0) 217208752Smjacob break; 218208752Smjacob } 219208752Smjacob if (*p_drv == NULL) { 220208752Smjacob printf("cam_periph_alloc: invalid periph name '%s'\n", name); 221249008Strasz xpt_unlock_buses(); 222208752Smjacob xpt_free_path(periph->path); 223208752Smjacob free(periph, M_CAMPERIPH); 224208752Smjacob return (CAM_REQ_INVALID); 225208752Smjacob } 226208752Smjacob periph->unit_number = camperiphunit(*p_drv, path_id, target_id, lun_id); 22739212Sgibbs cur_periph = TAILQ_FIRST(&(*p_drv)->units); 22839212Sgibbs while (cur_periph != NULL 22939212Sgibbs && cur_periph->unit_number < periph->unit_number) 23039212Sgibbs cur_periph = TAILQ_NEXT(cur_periph, unit_links); 231208752Smjacob if (cur_periph != NULL) { 232208752Smjacob KASSERT(cur_periph->unit_number != periph->unit_number, ("duplicate units on periph list")); 23339212Sgibbs TAILQ_INSERT_BEFORE(cur_periph, periph, unit_links); 234208752Smjacob } else { 23539212Sgibbs TAILQ_INSERT_TAIL(&(*p_drv)->units, periph, unit_links); 23639212Sgibbs (*p_drv)->generation++; 23739212Sgibbs } 238208752Smjacob xpt_unlock_buses(); 23939212Sgibbs 24039212Sgibbs init_level++; 24139212Sgibbs 242208752Smjacob status = xpt_add_periph(periph); 243208752Smjacob if (status != CAM_REQ_CMP) 244208752Smjacob goto failure; 245208752Smjacob 246208752Smjacob init_level++; 247236713Smav CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("Periph created\n")); 248208752Smjacob 24939212Sgibbs status = periph_ctor(periph, arg); 25039212Sgibbs 25139212Sgibbs if (status == CAM_REQ_CMP) 25239212Sgibbs init_level++; 25339212Sgibbs 25439212Sgibbsfailure: 25539212Sgibbs switch (init_level) { 25639212Sgibbs case 4: 25739212Sgibbs /* Initialized successfully */ 25839212Sgibbs break; 25939212Sgibbs case 3: 260236713Smav CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("Periph destroyed\n")); 261254058Smav xpt_remove_periph(periph); 262115476Sphk /* FALLTHROUGH */ 26339212Sgibbs case 2: 264208752Smjacob xpt_lock_buses(); 265208752Smjacob TAILQ_REMOVE(&(*p_drv)->units, periph, unit_links); 266208752Smjacob xpt_unlock_buses(); 26739212Sgibbs xpt_free_path(periph->path); 268115476Sphk /* FALLTHROUGH */ 26939212Sgibbs case 1: 270147723Savatar free(periph, M_CAMPERIPH); 271115476Sphk /* FALLTHROUGH */ 27239212Sgibbs case 0: 27339212Sgibbs /* No cleanup to perform. */ 27439212Sgibbs break; 27539212Sgibbs default: 276237682Sken panic("%s: Unknown init level", __func__); 27739212Sgibbs } 27839212Sgibbs return(status); 27939212Sgibbs} 28039212Sgibbs 28139212Sgibbs/* 28239212Sgibbs * Find a peripheral structure with the specified path, target, lun, 28339212Sgibbs * and (optionally) type. If the name is NULL, this function will return 28439212Sgibbs * the first peripheral driver that matches the specified path. 28539212Sgibbs */ 28639212Sgibbsstruct cam_periph * 28739212Sgibbscam_periph_find(struct cam_path *path, char *name) 28839212Sgibbs{ 28939212Sgibbs struct periph_driver **p_drv; 29039212Sgibbs struct cam_periph *periph; 29139212Sgibbs 292168882Sscottl xpt_lock_buses(); 29372119Speter for (p_drv = periph_drivers; *p_drv != NULL; p_drv++) { 29439212Sgibbs 29539212Sgibbs if (name != NULL && (strcmp((*p_drv)->driver_name, name) != 0)) 29639212Sgibbs continue; 29739212Sgibbs 29872012Sphk TAILQ_FOREACH(periph, &(*p_drv)->units, unit_links) { 29939212Sgibbs if (xpt_path_comp(periph->path, path) == 0) { 300168882Sscottl xpt_unlock_buses(); 301208752Smjacob mtx_assert(periph->sim->mtx, MA_OWNED); 30239212Sgibbs return(periph); 30339212Sgibbs } 30439212Sgibbs } 305168882Sscottl if (name != NULL) { 306168882Sscottl xpt_unlock_buses(); 30739212Sgibbs return(NULL); 308168882Sscottl } 30939212Sgibbs } 310168882Sscottl xpt_unlock_buses(); 31139212Sgibbs return(NULL); 31239212Sgibbs} 31339212Sgibbs 314223081Sgibbs/* 315230000Sken * Find peripheral driver instances attached to the specified path. 316223081Sgibbs */ 317223081Sgibbsint 318223081Sgibbscam_periph_list(struct cam_path *path, struct sbuf *sb) 319223081Sgibbs{ 320230000Sken struct sbuf local_sb; 321223081Sgibbs struct periph_driver **p_drv; 322223081Sgibbs struct cam_periph *periph; 323223081Sgibbs int count; 324230000Sken int sbuf_alloc_len; 325223081Sgibbs 326230000Sken sbuf_alloc_len = 16; 327230000Skenretry: 328230000Sken sbuf_new(&local_sb, NULL, sbuf_alloc_len, SBUF_FIXEDLEN); 329223081Sgibbs count = 0; 330223081Sgibbs xpt_lock_buses(); 331223081Sgibbs for (p_drv = periph_drivers; *p_drv != NULL; p_drv++) { 332223081Sgibbs 333223081Sgibbs TAILQ_FOREACH(periph, &(*p_drv)->units, unit_links) { 334223081Sgibbs if (xpt_path_comp(periph->path, path) != 0) 335223081Sgibbs continue; 336223081Sgibbs 337230000Sken if (sbuf_len(&local_sb) != 0) 338230000Sken sbuf_cat(&local_sb, ","); 339223081Sgibbs 340230000Sken sbuf_printf(&local_sb, "%s%d", periph->periph_name, 341223081Sgibbs periph->unit_number); 342230000Sken 343230000Sken if (sbuf_error(&local_sb) == ENOMEM) { 344230000Sken sbuf_alloc_len *= 2; 345230000Sken xpt_unlock_buses(); 346230000Sken sbuf_delete(&local_sb); 347230000Sken goto retry; 348230000Sken } 349223081Sgibbs count++; 350223081Sgibbs } 351223081Sgibbs } 352223081Sgibbs xpt_unlock_buses(); 353230000Sken sbuf_finish(&local_sb); 354230000Sken sbuf_cpy(sb, sbuf_data(&local_sb)); 355230000Sken sbuf_delete(&local_sb); 356223081Sgibbs return (count); 357223081Sgibbs} 358223081Sgibbs 35939212Sgibbscam_status 36039212Sgibbscam_periph_acquire(struct cam_periph *periph) 36139212Sgibbs{ 362230000Sken cam_status status; 36339212Sgibbs 364230000Sken status = CAM_REQ_CMP_ERR; 36539212Sgibbs if (periph == NULL) 366230000Sken return (status); 36739212Sgibbs 368168752Sscottl xpt_lock_buses(); 369230000Sken if ((periph->flags & CAM_PERIPH_INVALID) == 0) { 370230000Sken periph->refcount++; 371230000Sken status = CAM_REQ_CMP; 372230000Sken } 373168752Sscottl xpt_unlock_buses(); 37439212Sgibbs 375230000Sken return (status); 37639212Sgibbs} 37739212Sgibbs 37839212Sgibbsvoid 379230000Skencam_periph_release_locked_buses(struct cam_periph *periph) 38039212Sgibbs{ 381249108Smav 382249108Smav mtx_assert(periph->sim->mtx, MA_OWNED); 383249108Smav KASSERT(periph->refcount >= 1, ("periph->refcount >= 1")); 384249980Smav if (--periph->refcount == 0) 38539212Sgibbs camperiphfree(periph); 386230000Sken} 387230000Sken 388230000Skenvoid 389230000Skencam_periph_release_locked(struct cam_periph *periph) 390230000Sken{ 391230000Sken 392230000Sken if (periph == NULL) 393230000Sken return; 394230000Sken 395230000Sken xpt_lock_buses(); 396230000Sken cam_periph_release_locked_buses(periph); 397168752Sscottl xpt_unlock_buses(); 398186319Strasz} 39939212Sgibbs 400186319Straszvoid 401186319Straszcam_periph_release(struct cam_periph *periph) 402186319Strasz{ 403186319Strasz struct cam_sim *sim; 404186319Strasz 405186319Strasz if (periph == NULL) 406186319Strasz return; 407186319Strasz 408186319Strasz sim = periph->sim; 409186319Strasz mtx_assert(sim->mtx, MA_NOTOWNED); 410186319Strasz mtx_lock(sim->mtx); 411186319Strasz cam_periph_release_locked(periph); 412186319Strasz mtx_unlock(sim->mtx); 41339212Sgibbs} 41439212Sgibbs 415168752Sscottlint 416168752Sscottlcam_periph_hold(struct cam_periph *periph, int priority) 417168752Sscottl{ 418168752Sscottl int error; 419168752Sscottl 420168752Sscottl /* 421168752Sscottl * Increment the reference count on the peripheral 422168752Sscottl * while we wait for our lock attempt to succeed 423168752Sscottl * to ensure the peripheral doesn't disappear out 424168752Sscottl * from user us while we sleep. 425168752Sscottl */ 426168752Sscottl 427168752Sscottl if (cam_periph_acquire(periph) != CAM_REQ_CMP) 428168752Sscottl return (ENXIO); 429168752Sscottl 430187718Sjhb mtx_assert(periph->sim->mtx, MA_OWNED); 431168752Sscottl while ((periph->flags & CAM_PERIPH_LOCKED) != 0) { 432168752Sscottl periph->flags |= CAM_PERIPH_LOCK_WANTED; 433187718Sjhb if ((error = mtx_sleep(periph, periph->sim->mtx, priority, 434187718Sjhb "caplck", 0)) != 0) { 435186319Strasz cam_periph_release_locked(periph); 436168752Sscottl return (error); 437168752Sscottl } 438237401Smav if (periph->flags & CAM_PERIPH_INVALID) { 439237401Smav cam_periph_release_locked(periph); 440237401Smav return (ENXIO); 441237401Smav } 442168752Sscottl } 443168752Sscottl 444168752Sscottl periph->flags |= CAM_PERIPH_LOCKED; 445168752Sscottl return (0); 446168752Sscottl} 447168752Sscottl 448168752Sscottlvoid 449168752Sscottlcam_periph_unhold(struct cam_periph *periph) 450168752Sscottl{ 451168752Sscottl 452168752Sscottl mtx_assert(periph->sim->mtx, MA_OWNED); 453168752Sscottl 454168752Sscottl periph->flags &= ~CAM_PERIPH_LOCKED; 455168752Sscottl if ((periph->flags & CAM_PERIPH_LOCK_WANTED) != 0) { 456168752Sscottl periph->flags &= ~CAM_PERIPH_LOCK_WANTED; 457168752Sscottl wakeup(periph); 458168752Sscottl } 459168752Sscottl 460186319Strasz cam_periph_release_locked(periph); 461168752Sscottl} 462168752Sscottl 46339212Sgibbs/* 46439212Sgibbs * Look for the next unit number that is not currently in use for this 46539212Sgibbs * peripheral type starting at "newunit". Also exclude unit numbers that 46639212Sgibbs * are reserved by for future "hardwiring" unless we already know that this 46739212Sgibbs * is a potential wired device. Only assume that the device is "wired" the 46839212Sgibbs * first time through the loop since after that we'll be looking at unit 46939212Sgibbs * numbers that did not match a wiring entry. 47039212Sgibbs */ 47139212Sgibbsstatic u_int 47265225Skencamperiphnextunit(struct periph_driver *p_drv, u_int newunit, int wired, 47365225Sken path_id_t pathid, target_id_t target, lun_id_t lun) 47439212Sgibbs{ 47539212Sgibbs struct cam_periph *periph; 47678135Speter char *periph_name; 47778135Speter int i, val, dunit, r; 47878135Speter const char *dname, *strval; 47939212Sgibbs 48039212Sgibbs periph_name = p_drv->driver_name; 48139212Sgibbs for (;;newunit++) { 48239212Sgibbs 48339212Sgibbs for (periph = TAILQ_FIRST(&p_drv->units); 48439212Sgibbs periph != NULL && periph->unit_number != newunit; 48539212Sgibbs periph = TAILQ_NEXT(periph, unit_links)) 48639212Sgibbs ; 48739212Sgibbs 48839212Sgibbs if (periph != NULL && periph->unit_number == newunit) { 48939212Sgibbs if (wired != 0) { 490164906Smjacob xpt_print(periph->path, "Duplicate Wired " 491164906Smjacob "Device entry!\n"); 492164906Smjacob xpt_print(periph->path, "Second device (%s " 493164906Smjacob "device at scbus%d target %d lun %d) will " 494164906Smjacob "not be wired\n", periph_name, pathid, 495164906Smjacob target, lun); 49639212Sgibbs wired = 0; 49739212Sgibbs } 49839212Sgibbs continue; 49939212Sgibbs } 50056470Speter if (wired) 50156470Speter break; 50239212Sgibbs 50356470Speter /* 50456470Speter * Don't match entries like "da 4" as a wired down 50556470Speter * device, but do match entries like "da 4 target 5" 50656470Speter * or even "da 4 scbus 1". 50756470Speter */ 50878135Speter i = 0; 50978135Speter dname = periph_name; 51078135Speter for (;;) { 51178135Speter r = resource_find_dev(&i, dname, &dunit, NULL, NULL); 51278135Speter if (r != 0) 51378135Speter break; 51456470Speter /* if no "target" and no specific scbus, skip */ 51556470Speter if (resource_int_value(dname, dunit, "target", &val) && 51656470Speter (resource_string_value(dname, dunit, "at",&strval)|| 51756470Speter strcmp(strval, "scbus") == 0)) 51856470Speter continue; 51956470Speter if (newunit == dunit) 52039212Sgibbs break; 52139212Sgibbs } 52278135Speter if (r != 0) 52339212Sgibbs break; 52439212Sgibbs } 52539212Sgibbs return (newunit); 52639212Sgibbs} 52739212Sgibbs 52839212Sgibbsstatic u_int 52939212Sgibbscamperiphunit(struct periph_driver *p_drv, path_id_t pathid, 53039212Sgibbs target_id_t target, lun_id_t lun) 53139212Sgibbs{ 53256470Speter u_int unit; 533102341Speter int wired, i, val, dunit; 53478135Speter const char *dname, *strval; 53578135Speter char pathbuf[32], *periph_name; 53639212Sgibbs 53756470Speter periph_name = p_drv->driver_name; 53856470Speter snprintf(pathbuf, sizeof(pathbuf), "scbus%d", pathid); 539102341Speter unit = 0; 54078135Speter i = 0; 54178135Speter dname = periph_name; 542102341Speter for (wired = 0; resource_find_dev(&i, dname, &dunit, NULL, NULL) == 0; 543102341Speter wired = 0) { 54456470Speter if (resource_string_value(dname, dunit, "at", &strval) == 0) { 54556470Speter if (strcmp(strval, pathbuf) != 0) 54656470Speter continue; 547102341Speter wired++; 54839212Sgibbs } 54956470Speter if (resource_int_value(dname, dunit, "target", &val) == 0) { 55056470Speter if (val != target) 55156470Speter continue; 552102341Speter wired++; 55356470Speter } 55456470Speter if (resource_int_value(dname, dunit, "lun", &val) == 0) { 55556470Speter if (val != lun) 55656470Speter continue; 557102341Speter wired++; 55856470Speter } 559102341Speter if (wired != 0) { 56056470Speter unit = dunit; 56156470Speter break; 56256470Speter } 56339212Sgibbs } 56439212Sgibbs 56539212Sgibbs /* 56639212Sgibbs * Either start from 0 looking for the next unit or from 56756470Speter * the unit number given in the resource config. This way, 56839212Sgibbs * if we have wildcard matches, we don't return the same 56939212Sgibbs * unit number twice. 57039212Sgibbs */ 571102341Speter unit = camperiphnextunit(p_drv, unit, wired, pathid, target, lun); 57239212Sgibbs 57339212Sgibbs return (unit); 57439212Sgibbs} 57539212Sgibbs 57639212Sgibbsvoid 57739212Sgibbscam_periph_invalidate(struct cam_periph *periph) 57839212Sgibbs{ 57939212Sgibbs 580249108Smav mtx_assert(periph->sim->mtx, MA_OWNED); 58140603Sken /* 58240603Sken * We only call this routine the first time a peripheral is 583168882Sscottl * invalidated. 58440603Sken */ 585249980Smav if ((periph->flags & CAM_PERIPH_INVALID) != 0) 586249980Smav return; 58740603Sken 588249980Smav CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("Periph invalidated\n")); 589257049Smav if (periph->flags & CAM_PERIPH_ANNOUNCED) 590257049Smav xpt_denounce_periph(periph); 59139212Sgibbs periph->flags |= CAM_PERIPH_INVALID; 59239212Sgibbs periph->flags &= ~CAM_PERIPH_NEW_DEV_FOUND; 593249980Smav if (periph->periph_oninval != NULL) 594249980Smav periph->periph_oninval(periph); 595249980Smav cam_periph_release_locked(periph); 59639212Sgibbs} 59739212Sgibbs 59839212Sgibbsstatic void 59939212Sgibbscamperiphfree(struct cam_periph *periph) 60039212Sgibbs{ 60139212Sgibbs struct periph_driver **p_drv; 60239212Sgibbs 603249108Smav mtx_assert(periph->sim->mtx, MA_OWNED); 60472119Speter for (p_drv = periph_drivers; *p_drv != NULL; p_drv++) { 60539212Sgibbs if (strcmp((*p_drv)->driver_name, periph->periph_name) == 0) 60639212Sgibbs break; 60739212Sgibbs } 608142157Sscottl if (*p_drv == NULL) { 609142157Sscottl printf("camperiphfree: attempt to free non-existant periph\n"); 610142157Sscottl return; 611142157Sscottl } 612168787Sscottl 613237328Sken /* 614244001Sken * We need to set this flag before dropping the topology lock, to 615244001Sken * let anyone who is traversing the list that this peripheral is 616244001Sken * about to be freed, and there will be no more reference count 617244001Sken * checks. 618244001Sken */ 619244001Sken periph->flags |= CAM_PERIPH_FREE; 620244001Sken 621244001Sken /* 622237328Sken * The peripheral destructor semantics dictate calling with only the 623237328Sken * SIM mutex held. Since it might sleep, it should not be called 624237328Sken * with the topology lock held. 625237328Sken */ 626168787Sscottl xpt_unlock_buses(); 62739212Sgibbs 628237328Sken /* 629237328Sken * We need to call the peripheral destructor prior to removing the 630237328Sken * peripheral from the list. Otherwise, we risk running into a 631237328Sken * scenario where the peripheral unit number may get reused 632237328Sken * (because it has been removed from the list), but some resources 633237328Sken * used by the peripheral are still hanging around. In particular, 634237328Sken * the devfs nodes used by some peripherals like the pass(4) driver 635237328Sken * aren't fully cleaned up until the destructor is run. If the 636237328Sken * unit number is reused before the devfs instance is fully gone, 637237328Sken * devfs will panic. 638237328Sken */ 639168787Sscottl if (periph->periph_dtor != NULL) 640168787Sscottl periph->periph_dtor(periph); 641237328Sken 642237328Sken /* 643237328Sken * The peripheral list is protected by the topology lock. 644237328Sken */ 645237328Sken xpt_lock_buses(); 646237328Sken 647237328Sken TAILQ_REMOVE(&(*p_drv)->units, periph, unit_links); 648237328Sken (*p_drv)->generation++; 649237328Sken 650254058Smav xpt_remove_periph(periph); 651237328Sken 652237328Sken xpt_unlock_buses(); 653257049Smav if (periph->flags & CAM_PERIPH_ANNOUNCED) { 654257049Smav xpt_print(periph->path, "Periph destroyed\n"); 655257049Smav } else 656257049Smav CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("Periph destroyed\n")); 65739212Sgibbs 65839212Sgibbs if (periph->flags & CAM_PERIPH_NEW_DEV_FOUND) { 65939212Sgibbs union ccb ccb; 66039212Sgibbs void *arg; 66139212Sgibbs 66239212Sgibbs switch (periph->deferred_ac) { 66339212Sgibbs case AC_FOUND_DEVICE: 66439212Sgibbs ccb.ccb_h.func_code = XPT_GDEV_TYPE; 665198382Smav xpt_setup_ccb(&ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 66639212Sgibbs xpt_action(&ccb); 66739212Sgibbs arg = &ccb; 66839212Sgibbs break; 66939212Sgibbs case AC_PATH_REGISTERED: 67039212Sgibbs ccb.ccb_h.func_code = XPT_PATH_INQ; 671198382Smav xpt_setup_ccb(&ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 67239212Sgibbs xpt_action(&ccb); 67339212Sgibbs arg = &ccb; 67439212Sgibbs break; 67539212Sgibbs default: 67639212Sgibbs arg = NULL; 67739212Sgibbs break; 67839212Sgibbs } 67939212Sgibbs periph->deferred_callback(NULL, periph->deferred_ac, 68039212Sgibbs periph->path, arg); 68139212Sgibbs } 68239212Sgibbs xpt_free_path(periph->path); 683147723Savatar free(periph, M_CAMPERIPH); 684168787Sscottl xpt_lock_buses(); 68539212Sgibbs} 68639212Sgibbs 68739212Sgibbs/* 68839212Sgibbs * Map user virtual pointers into kernel virtual address space, so we can 689251479Sscottl * access the memory. This is now a generic function that centralizes most 690251479Sscottl * of the sanity checks on the data flags, if any. 691251479Sscottl * This also only works for up to MAXPHYS memory. Since we use 69239212Sgibbs * buffers to map stuff in and out, we're limited to the buffer size. 69339212Sgibbs */ 69439212Sgibbsint 69539212Sgibbscam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo) 69639212Sgibbs{ 697109572Sdillon int numbufs, i, j; 69841877Sken int flags[CAM_PERIPH_MAXMAPS]; 69939212Sgibbs u_int8_t **data_ptrs[CAM_PERIPH_MAXMAPS]; 70039212Sgibbs u_int32_t lengths[CAM_PERIPH_MAXMAPS]; 70139212Sgibbs u_int32_t dirs[CAM_PERIPH_MAXMAPS]; 702195534Sscottl /* Some controllers may not be able to handle more data. */ 703195534Sscottl size_t maxmap = DFLTPHYS; 70439212Sgibbs 70539212Sgibbs switch(ccb->ccb_h.func_code) { 70639212Sgibbs case XPT_DEV_MATCH: 70739212Sgibbs if (ccb->cdm.match_buf_len == 0) { 70839212Sgibbs printf("cam_periph_mapmem: invalid match buffer " 70939212Sgibbs "length 0\n"); 71039212Sgibbs return(EINVAL); 71139212Sgibbs } 71239212Sgibbs if (ccb->cdm.pattern_buf_len > 0) { 71339212Sgibbs data_ptrs[0] = (u_int8_t **)&ccb->cdm.patterns; 71439212Sgibbs lengths[0] = ccb->cdm.pattern_buf_len; 71539212Sgibbs dirs[0] = CAM_DIR_OUT; 71639212Sgibbs data_ptrs[1] = (u_int8_t **)&ccb->cdm.matches; 71739212Sgibbs lengths[1] = ccb->cdm.match_buf_len; 71839212Sgibbs dirs[1] = CAM_DIR_IN; 71939212Sgibbs numbufs = 2; 72039212Sgibbs } else { 72139212Sgibbs data_ptrs[0] = (u_int8_t **)&ccb->cdm.matches; 72239212Sgibbs lengths[0] = ccb->cdm.match_buf_len; 72339212Sgibbs dirs[0] = CAM_DIR_IN; 72439212Sgibbs numbufs = 1; 72539212Sgibbs } 726195534Sscottl /* 727195534Sscottl * This request will not go to the hardware, no reason 728195534Sscottl * to be so strict. vmapbuf() is able to map up to MAXPHYS. 729195534Sscottl */ 730195534Sscottl maxmap = MAXPHYS; 73139212Sgibbs break; 73239212Sgibbs case XPT_SCSI_IO: 73347412Sgibbs case XPT_CONT_TARGET_IO: 73439212Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE) 73539212Sgibbs return(0); 736251479Sscottl if ((ccb->ccb_h.flags & CAM_DATA_MASK) != CAM_DATA_VADDR) 737251479Sscottl return (EINVAL); 73839212Sgibbs data_ptrs[0] = &ccb->csio.data_ptr; 73941877Sken lengths[0] = ccb->csio.dxfer_len; 74039212Sgibbs dirs[0] = ccb->ccb_h.flags & CAM_DIR_MASK; 74139212Sgibbs numbufs = 1; 74239212Sgibbs break; 743195534Sscottl case XPT_ATA_IO: 744195534Sscottl if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE) 745195534Sscottl return(0); 746251479Sscottl if ((ccb->ccb_h.flags & CAM_DATA_MASK) != CAM_DATA_VADDR) 747251479Sscottl return (EINVAL); 748195534Sscottl data_ptrs[0] = &ccb->ataio.data_ptr; 749195534Sscottl lengths[0] = ccb->ataio.dxfer_len; 750195534Sscottl dirs[0] = ccb->ccb_h.flags & CAM_DIR_MASK; 751195534Sscottl numbufs = 1; 752195534Sscottl break; 753216088Sken case XPT_SMP_IO: 754216088Sken data_ptrs[0] = &ccb->smpio.smp_request; 755216088Sken lengths[0] = ccb->smpio.smp_request_len; 756216088Sken dirs[0] = CAM_DIR_OUT; 757216088Sken data_ptrs[1] = &ccb->smpio.smp_response; 758216088Sken lengths[1] = ccb->smpio.smp_response_len; 759216088Sken dirs[1] = CAM_DIR_IN; 760216088Sken numbufs = 2; 761216088Sken break; 762223081Sgibbs case XPT_DEV_ADVINFO: 763223081Sgibbs if (ccb->cdai.bufsiz == 0) 764216361Sken return (0); 765216361Sken 766223081Sgibbs data_ptrs[0] = (uint8_t **)&ccb->cdai.buf; 767223081Sgibbs lengths[0] = ccb->cdai.bufsiz; 768216088Sken dirs[0] = CAM_DIR_IN; 769216088Sken numbufs = 1; 770216361Sken 771216361Sken /* 772216361Sken * This request will not go to the hardware, no reason 773216361Sken * to be so strict. vmapbuf() is able to map up to MAXPHYS. 774216361Sken */ 775216361Sken maxmap = MAXPHYS; 776216088Sken break; 77739212Sgibbs default: 77839212Sgibbs return(EINVAL); 77939212Sgibbs break; /* NOTREACHED */ 78039212Sgibbs } 78139212Sgibbs 78239212Sgibbs /* 78341877Sken * Check the transfer length and permissions first, so we don't 78441877Sken * have to unmap any previously mapped buffers. 78539212Sgibbs */ 78639212Sgibbs for (i = 0; i < numbufs; i++) { 78739212Sgibbs 78841877Sken flags[i] = 0; 78941877Sken 79041877Sken /* 79141877Sken * The userland data pointer passed in may not be page 79241877Sken * aligned. vmapbuf() truncates the address to a page 79341877Sken * boundary, so if the address isn't page aligned, we'll 79441877Sken * need enough space for the given transfer length, plus 79541877Sken * whatever extra space is necessary to make it to the page 79641877Sken * boundary. 79741877Sken */ 79841877Sken if ((lengths[i] + 799195534Sscottl (((vm_offset_t)(*data_ptrs[i])) & PAGE_MASK)) > maxmap){ 80048410Speter printf("cam_periph_mapmem: attempt to map %lu bytes, " 801195534Sscottl "which is greater than %lu\n", 80248410Speter (long)(lengths[i] + 80348410Speter (((vm_offset_t)(*data_ptrs[i])) & PAGE_MASK)), 804195534Sscottl (u_long)maxmap); 80541877Sken return(E2BIG); 80641877Sken } 80741877Sken 80847497Sken if (dirs[i] & CAM_DIR_OUT) { 80958345Sphk flags[i] = BIO_WRITE; 81039212Sgibbs } 81139212Sgibbs 81247497Sken if (dirs[i] & CAM_DIR_IN) { 81358345Sphk flags[i] = BIO_READ; 81439212Sgibbs } 81539212Sgibbs 81641877Sken } 81741877Sken 81841877Sken /* 819251479Sscottl * This keeps the the kernel stack of current thread from getting 820251479Sscottl * swapped. In low-memory situations where the kernel stack might 821251479Sscottl * otherwise get swapped out, this holds it and allows the thread 822251479Sscottl * to make progress and release the kernel mapped pages sooner. 823251479Sscottl * 82441877Sken * XXX KDM should I use P_NOSWAP instead? 82541877Sken */ 82645359Speter PHOLD(curproc); 82741877Sken 82841877Sken for (i = 0; i < numbufs; i++) { 82939212Sgibbs /* 83039212Sgibbs * Get the buffer. 83139212Sgibbs */ 83242957Sdillon mapinfo->bp[i] = getpbuf(NULL); 83339212Sgibbs 83439212Sgibbs /* save the buffer's data address */ 83539212Sgibbs mapinfo->bp[i]->b_saveaddr = mapinfo->bp[i]->b_data; 83639212Sgibbs 83739212Sgibbs /* put our pointer in the data slot */ 83839212Sgibbs mapinfo->bp[i]->b_data = *data_ptrs[i]; 83939212Sgibbs 840195534Sscottl /* set the transfer length, we know it's < MAXPHYS */ 84139212Sgibbs mapinfo->bp[i]->b_bufsize = lengths[i]; 84239212Sgibbs 84358345Sphk /* set the direction */ 84458345Sphk mapinfo->bp[i]->b_iocmd = flags[i]; 84558345Sphk 846109572Sdillon /* 847109572Sdillon * Map the buffer into kernel memory. 848109572Sdillon * 849109572Sdillon * Note that useracc() alone is not a sufficient test. 850109572Sdillon * vmapbuf() can still fail due to a smaller file mapped 851109572Sdillon * into a larger area of VM, or if userland races against 852109572Sdillon * vmapbuf() after the useracc() check. 853109572Sdillon */ 854248515Skib if (vmapbuf(mapinfo->bp[i], 1) < 0) { 855109572Sdillon for (j = 0; j < i; ++j) { 856109572Sdillon *data_ptrs[j] = mapinfo->bp[j]->b_saveaddr; 857119957Salc vunmapbuf(mapinfo->bp[j]); 858109572Sdillon relpbuf(mapinfo->bp[j], NULL); 859109572Sdillon } 860119957Salc relpbuf(mapinfo->bp[i], NULL); 861109572Sdillon PRELE(curproc); 862109572Sdillon return(EACCES); 863109572Sdillon } 86439212Sgibbs 86539212Sgibbs /* set our pointer to the new mapped area */ 86639212Sgibbs *data_ptrs[i] = mapinfo->bp[i]->b_data; 86739212Sgibbs 86839212Sgibbs mapinfo->num_bufs_used++; 86939212Sgibbs } 87039212Sgibbs 871158883Smjacob /* 872158883Smjacob * Now that we've gotten this far, change ownership to the kernel 873158883Smjacob * of the buffers so that we don't run afoul of returning to user 874158883Smjacob * space with locks (on the buffer) held. 875158883Smjacob */ 876158883Smjacob for (i = 0; i < numbufs; i++) { 877158883Smjacob BUF_KERNPROC(mapinfo->bp[i]); 878158883Smjacob } 879158883Smjacob 880158883Smjacob 88139212Sgibbs return(0); 88239212Sgibbs} 88339212Sgibbs 88439212Sgibbs/* 88539212Sgibbs * Unmap memory segments mapped into kernel virtual address space by 88639212Sgibbs * cam_periph_mapmem(). 88739212Sgibbs */ 88839212Sgibbsvoid 88939212Sgibbscam_periph_unmapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo) 89039212Sgibbs{ 89139212Sgibbs int numbufs, i; 89239212Sgibbs u_int8_t **data_ptrs[CAM_PERIPH_MAXMAPS]; 89339212Sgibbs 89439212Sgibbs if (mapinfo->num_bufs_used <= 0) { 895251479Sscottl /* nothing to free and the process wasn't held. */ 89639212Sgibbs return; 89739212Sgibbs } 89839212Sgibbs 89939212Sgibbs switch (ccb->ccb_h.func_code) { 90039212Sgibbs case XPT_DEV_MATCH: 90139212Sgibbs numbufs = min(mapinfo->num_bufs_used, 2); 90239212Sgibbs 90339212Sgibbs if (numbufs == 1) { 90439212Sgibbs data_ptrs[0] = (u_int8_t **)&ccb->cdm.matches; 90539212Sgibbs } else { 90639212Sgibbs data_ptrs[0] = (u_int8_t **)&ccb->cdm.patterns; 90739212Sgibbs data_ptrs[1] = (u_int8_t **)&ccb->cdm.matches; 90839212Sgibbs } 90939212Sgibbs break; 91039212Sgibbs case XPT_SCSI_IO: 91147509Sgibbs case XPT_CONT_TARGET_IO: 91239212Sgibbs data_ptrs[0] = &ccb->csio.data_ptr; 91339212Sgibbs numbufs = min(mapinfo->num_bufs_used, 1); 91439212Sgibbs break; 915195534Sscottl case XPT_ATA_IO: 916195534Sscottl data_ptrs[0] = &ccb->ataio.data_ptr; 917195534Sscottl numbufs = min(mapinfo->num_bufs_used, 1); 918195534Sscottl break; 919216088Sken case XPT_SMP_IO: 920216088Sken numbufs = min(mapinfo->num_bufs_used, 2); 921216088Sken data_ptrs[0] = &ccb->smpio.smp_request; 922216088Sken data_ptrs[1] = &ccb->smpio.smp_response; 923216088Sken break; 924223081Sgibbs case XPT_DEV_ADVINFO: 925216088Sken numbufs = min(mapinfo->num_bufs_used, 1); 926223081Sgibbs data_ptrs[0] = (uint8_t **)&ccb->cdai.buf; 927216088Sken break; 92839212Sgibbs default: 92939212Sgibbs /* allow ourselves to be swapped once again */ 93045359Speter PRELE(curproc); 93139212Sgibbs return; 93239212Sgibbs break; /* NOTREACHED */ 93339212Sgibbs } 93439212Sgibbs 93539212Sgibbs for (i = 0; i < numbufs; i++) { 93639212Sgibbs /* Set the user's pointer back to the original value */ 93739212Sgibbs *data_ptrs[i] = mapinfo->bp[i]->b_saveaddr; 93839212Sgibbs 93939212Sgibbs /* unmap the buffer */ 94039212Sgibbs vunmapbuf(mapinfo->bp[i]); 94139212Sgibbs 94239212Sgibbs /* release the buffer */ 94342957Sdillon relpbuf(mapinfo->bp[i], NULL); 94439212Sgibbs } 94539212Sgibbs 94639212Sgibbs /* allow ourselves to be swapped once again */ 94745359Speter PRELE(curproc); 94839212Sgibbs} 94939212Sgibbs 95039212Sgibbsunion ccb * 95139212Sgibbscam_periph_getccb(struct cam_periph *periph, u_int32_t priority) 95239212Sgibbs{ 95339212Sgibbs struct ccb_hdr *ccb_h; 95439212Sgibbs 955168752Sscottl mtx_assert(periph->sim->mtx, MA_OWNED); 95639212Sgibbs CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdgetccb\n")); 95739212Sgibbs 95871999Sphk while (SLIST_FIRST(&periph->ccb_list) == NULL) { 95939212Sgibbs if (periph->immediate_priority > priority) 96039212Sgibbs periph->immediate_priority = priority; 96139212Sgibbs xpt_schedule(periph, priority); 96271999Sphk if ((SLIST_FIRST(&periph->ccb_list) != NULL) 96371999Sphk && (SLIST_FIRST(&periph->ccb_list)->pinfo.priority == priority)) 96439212Sgibbs break; 965168752Sscottl mtx_assert(periph->sim->mtx, MA_OWNED); 966187718Sjhb mtx_sleep(&periph->ccb_list, periph->sim->mtx, PRIBIO, "cgticb", 967187718Sjhb 0); 96839212Sgibbs } 96939212Sgibbs 97071999Sphk ccb_h = SLIST_FIRST(&periph->ccb_list); 97139212Sgibbs SLIST_REMOVE_HEAD(&periph->ccb_list, periph_links.sle); 97239212Sgibbs return ((union ccb *)ccb_h); 97339212Sgibbs} 97439212Sgibbs 97539212Sgibbsvoid 97639212Sgibbscam_periph_ccbwait(union ccb *ccb) 97739212Sgibbs{ 978168752Sscottl struct cam_sim *sim; 97939212Sgibbs 980168752Sscottl sim = xpt_path_sim(ccb->ccb_h.path); 98139212Sgibbs if ((ccb->ccb_h.pinfo.index != CAM_UNQUEUED_INDEX) 98239212Sgibbs || ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG)) 983187718Sjhb mtx_sleep(&ccb->ccb_h.cbfcnp, sim->mtx, PRIBIO, "cbwait", 0); 98439212Sgibbs} 98539212Sgibbs 98639212Sgibbsint 987194627Sscottlcam_periph_ioctl(struct cam_periph *periph, u_long cmd, caddr_t addr, 98839212Sgibbs int (*error_routine)(union ccb *ccb, 98939212Sgibbs cam_flags camflags, 99039212Sgibbs u_int32_t sense_flags)) 99139212Sgibbs{ 99239212Sgibbs union ccb *ccb; 99339212Sgibbs int error; 99439212Sgibbs int found; 99539212Sgibbs 99639212Sgibbs error = found = 0; 99739212Sgibbs 99839212Sgibbs switch(cmd){ 99939212Sgibbs case CAMGETPASSTHRU: 1000198382Smav ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); 100139212Sgibbs xpt_setup_ccb(&ccb->ccb_h, 100239212Sgibbs ccb->ccb_h.path, 1003198382Smav CAM_PRIORITY_NORMAL); 100439212Sgibbs ccb->ccb_h.func_code = XPT_GDEVLIST; 100539212Sgibbs 100639212Sgibbs /* 100739212Sgibbs * Basically, the point of this is that we go through 100839212Sgibbs * getting the list of devices, until we find a passthrough 100939212Sgibbs * device. In the current version of the CAM code, the 101039212Sgibbs * only way to determine what type of device we're dealing 101139212Sgibbs * with is by its name. 101239212Sgibbs */ 101339212Sgibbs while (found == 0) { 101439212Sgibbs ccb->cgdl.index = 0; 101539212Sgibbs ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS; 101639212Sgibbs while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) { 101739212Sgibbs 101839212Sgibbs /* we want the next device in the list */ 101939212Sgibbs xpt_action(ccb); 102039212Sgibbs if (strncmp(ccb->cgdl.periph_name, 102139212Sgibbs "pass", 4) == 0){ 102239212Sgibbs found = 1; 102339212Sgibbs break; 102439212Sgibbs } 102539212Sgibbs } 102639212Sgibbs if ((ccb->cgdl.status == CAM_GDEVLIST_LAST_DEVICE) && 102739212Sgibbs (found == 0)) { 102839212Sgibbs ccb->cgdl.periph_name[0] = '\0'; 102939212Sgibbs ccb->cgdl.unit_number = 0; 103039212Sgibbs break; 103139212Sgibbs } 103239212Sgibbs } 103339212Sgibbs 103439212Sgibbs /* copy the result back out */ 103539212Sgibbs bcopy(ccb, addr, sizeof(union ccb)); 103639212Sgibbs 103739212Sgibbs /* and release the ccb */ 103839212Sgibbs xpt_release_ccb(ccb); 103939212Sgibbs 104039212Sgibbs break; 104139212Sgibbs default: 104239212Sgibbs error = ENOTTY; 104339212Sgibbs break; 104439212Sgibbs } 104539212Sgibbs return(error); 104639212Sgibbs} 104739212Sgibbs 104839212Sgibbsint 104939212Sgibbscam_periph_runccb(union ccb *ccb, 105039212Sgibbs int (*error_routine)(union ccb *ccb, 105139212Sgibbs cam_flags camflags, 105239212Sgibbs u_int32_t sense_flags), 105339212Sgibbs cam_flags camflags, u_int32_t sense_flags, 105439212Sgibbs struct devstat *ds) 105539212Sgibbs{ 1056168752Sscottl struct cam_sim *sim; 105739212Sgibbs int error; 105839212Sgibbs 105939212Sgibbs error = 0; 1060168752Sscottl sim = xpt_path_sim(ccb->ccb_h.path); 1061168752Sscottl mtx_assert(sim->mtx, MA_OWNED); 1062168752Sscottl 106339212Sgibbs /* 106439212Sgibbs * If the user has supplied a stats structure, and if we understand 106539212Sgibbs * this particular type of ccb, record the transaction start. 106639212Sgibbs */ 1067198947Smav if ((ds != NULL) && (ccb->ccb_h.func_code == XPT_SCSI_IO || 1068198947Smav ccb->ccb_h.func_code == XPT_ATA_IO)) 1069112288Sphk devstat_start_transaction(ds, NULL); 107039212Sgibbs 107139212Sgibbs xpt_action(ccb); 107239212Sgibbs 107339212Sgibbs do { 107439212Sgibbs cam_periph_ccbwait(ccb); 107539212Sgibbs if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) 107639212Sgibbs error = 0; 107739212Sgibbs else if (error_routine != NULL) 107839212Sgibbs error = (*error_routine)(ccb, camflags, sense_flags); 107939212Sgibbs else 108039212Sgibbs error = 0; 108139212Sgibbs 108239212Sgibbs } while (error == ERESTART); 108339212Sgibbs 1084203108Smav if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 108539212Sgibbs cam_release_devq(ccb->ccb_h.path, 108639212Sgibbs /* relsim_flags */0, 108739212Sgibbs /* openings */0, 108839212Sgibbs /* timeout */0, 108939212Sgibbs /* getcount_only */ FALSE); 1090203108Smav ccb->ccb_h.status &= ~CAM_DEV_QFRZN; 1091203108Smav } 109239212Sgibbs 1093198947Smav if (ds != NULL) { 1094198947Smav if (ccb->ccb_h.func_code == XPT_SCSI_IO) { 1095198947Smav devstat_end_transaction(ds, 109639212Sgibbs ccb->csio.dxfer_len, 1097198947Smav ccb->csio.tag_action & 0x3, 109839212Sgibbs ((ccb->ccb_h.flags & CAM_DIR_MASK) == 109939212Sgibbs CAM_DIR_NONE) ? DEVSTAT_NO_DATA : 110039212Sgibbs (ccb->ccb_h.flags & CAM_DIR_OUT) ? 110139212Sgibbs DEVSTAT_WRITE : 1102112288Sphk DEVSTAT_READ, NULL, NULL); 1103198947Smav } else if (ccb->ccb_h.func_code == XPT_ATA_IO) { 1104198947Smav devstat_end_transaction(ds, 1105198947Smav ccb->ataio.dxfer_len, 1106198947Smav ccb->ataio.tag_action & 0x3, 1107198947Smav ((ccb->ccb_h.flags & CAM_DIR_MASK) == 1108198947Smav CAM_DIR_NONE) ? DEVSTAT_NO_DATA : 1109198947Smav (ccb->ccb_h.flags & CAM_DIR_OUT) ? 1110198947Smav DEVSTAT_WRITE : 1111198947Smav DEVSTAT_READ, NULL, NULL); 1112198947Smav } 1113198947Smav } 111439212Sgibbs 111539212Sgibbs return(error); 111639212Sgibbs} 111739212Sgibbs 111847412Sgibbsvoid 111947412Sgibbscam_freeze_devq(struct cam_path *path) 112047412Sgibbs{ 1121249466Smav struct ccb_hdr ccb_h; 112247412Sgibbs 1123255126Smav CAM_DEBUG(path, CAM_DEBUG_TRACE, ("cam_freeze_devq\n")); 1124249466Smav xpt_setup_ccb(&ccb_h, path, /*priority*/1); 1125249466Smav ccb_h.func_code = XPT_NOOP; 1126249466Smav ccb_h.flags = CAM_DEV_QFREEZE; 1127249466Smav xpt_action((union ccb *)&ccb_h); 112847412Sgibbs} 112947412Sgibbs 113039212Sgibbsu_int32_t 113139212Sgibbscam_release_devq(struct cam_path *path, u_int32_t relsim_flags, 1132203108Smav u_int32_t openings, u_int32_t arg, 113339212Sgibbs int getcount_only) 113439212Sgibbs{ 113539212Sgibbs struct ccb_relsim crs; 113639212Sgibbs 1137255126Smav CAM_DEBUG(path, CAM_DEBUG_TRACE, ("cam_release_devq(%u, %u, %u, %d)\n", 1138255126Smav relsim_flags, openings, arg, getcount_only)); 1139198382Smav xpt_setup_ccb(&crs.ccb_h, path, CAM_PRIORITY_NORMAL); 114039212Sgibbs crs.ccb_h.func_code = XPT_REL_SIMQ; 114139212Sgibbs crs.ccb_h.flags = getcount_only ? CAM_DEV_QFREEZE : 0; 114239212Sgibbs crs.release_flags = relsim_flags; 114339212Sgibbs crs.openings = openings; 1144203108Smav crs.release_timeout = arg; 114539212Sgibbs xpt_action((union ccb *)&crs); 114639212Sgibbs return (crs.qfrozen_cnt); 114739212Sgibbs} 114839212Sgibbs 114939212Sgibbs#define saved_ccb_ptr ppriv_ptr0 115039212Sgibbsstatic void 115139212Sgibbscamperiphdone(struct cam_periph *periph, union ccb *done_ccb) 115239212Sgibbs{ 1153236814Smav union ccb *saved_ccb; 115439212Sgibbs cam_status status; 115539212Sgibbs struct scsi_start_stop_unit *scsi_cmd; 1156237478Smav int error_code, sense_key, asc, ascq; 115739212Sgibbs 1158236814Smav scsi_cmd = (struct scsi_start_stop_unit *) 1159236814Smav &done_ccb->csio.cdb_io.cdb_bytes; 116039212Sgibbs status = done_ccb->ccb_h.status; 116139212Sgibbs 1162236814Smav if ((status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1163237478Smav if (scsi_extract_sense_ccb(done_ccb, 1164237478Smav &error_code, &sense_key, &asc, &ascq)) { 116539212Sgibbs /* 1166236814Smav * If the error is "invalid field in CDB", 1167236814Smav * and the load/eject flag is set, turn the 1168236814Smav * flag off and try again. This is just in 1169236814Smav * case the drive in question barfs on the 1170236814Smav * load eject flag. The CAM code should set 1171236814Smav * the load/eject flag by default for 117239212Sgibbs * removable media. 117339212Sgibbs */ 117439212Sgibbs if ((scsi_cmd->opcode == START_STOP_UNIT) && 117539212Sgibbs ((scsi_cmd->how & SSS_LOEJ) != 0) && 1176236814Smav (asc == 0x24) && (ascq == 0x00)) { 117739212Sgibbs scsi_cmd->how &= ~SSS_LOEJ; 1178236814Smav if (status & CAM_DEV_QFRZN) { 1179236814Smav cam_release_devq(done_ccb->ccb_h.path, 1180236814Smav 0, 0, 0, 0); 1181236814Smav done_ccb->ccb_h.status &= 1182236814Smav ~CAM_DEV_QFRZN; 1183236814Smav } 118439212Sgibbs xpt_action(done_ccb); 1185236814Smav goto out; 118639212Sgibbs } 118739212Sgibbs } 1188236814Smav if (cam_periph_error(done_ccb, 1189236814Smav 0, SF_RETRY_UA | SF_NO_PRINT, NULL) == ERESTART) 1190236814Smav goto out; 1191236814Smav if (done_ccb->ccb_h.status & CAM_DEV_QFRZN) { 1192236814Smav cam_release_devq(done_ccb->ccb_h.path, 0, 0, 0, 0); 1193236814Smav done_ccb->ccb_h.status &= ~CAM_DEV_QFRZN; 1194236814Smav } 1195236814Smav } else { 1196236814Smav /* 1197236814Smav * If we have successfully taken a device from the not 1198236814Smav * ready to ready state, re-scan the device and re-get 1199236814Smav * the inquiry information. Many devices (mostly disks) 1200236814Smav * don't properly report their inquiry information unless 1201236814Smav * they are spun up. 1202236814Smav */ 1203236814Smav if (scsi_cmd->opcode == START_STOP_UNIT) 1204236814Smav xpt_async(AC_INQ_CHANGED, done_ccb->ccb_h.path, NULL); 120539212Sgibbs } 120639212Sgibbs 120774840Sken /* 1208236814Smav * Perform the final retry with the original CCB so that final 1209236814Smav * error processing is performed by the owner of the CCB. 121074840Sken */ 1211236814Smav saved_ccb = (union ccb *)done_ccb->ccb_h.saved_ccb_ptr; 1212236814Smav bcopy(saved_ccb, done_ccb, sizeof(*done_ccb)); 1213236814Smav xpt_free_ccb(saved_ccb); 1214236814Smav if (done_ccb->ccb_h.cbfcnp != camperiphdone) 1215236814Smav periph->flags &= ~CAM_PERIPH_RECOVERY_INPROG; 1216236814Smav xpt_action(done_ccb); 1217236814Smav 1218236814Smavout: 1219236814Smav /* Drop freeze taken due to CAM_DEV_QFREEZE flag set. */ 1220236814Smav cam_release_devq(done_ccb->ccb_h.path, 0, 0, 0, 0); 122139212Sgibbs} 122239212Sgibbs 122339212Sgibbs/* 122447412Sgibbs * Generic Async Event handler. Peripheral drivers usually 122547412Sgibbs * filter out the events that require personal attention, 122647412Sgibbs * and leave the rest to this function. 122747412Sgibbs */ 122847412Sgibbsvoid 122947412Sgibbscam_periph_async(struct cam_periph *periph, u_int32_t code, 123047412Sgibbs struct cam_path *path, void *arg) 123147412Sgibbs{ 123247412Sgibbs switch (code) { 123347412Sgibbs case AC_LOST_DEVICE: 123447412Sgibbs cam_periph_invalidate(periph); 123547412Sgibbs break; 123647412Sgibbs default: 123747412Sgibbs break; 123847412Sgibbs } 123947412Sgibbs} 124047412Sgibbs 124147412Sgibbsvoid 124247412Sgibbscam_periph_bus_settle(struct cam_periph *periph, u_int bus_settle) 124347412Sgibbs{ 124447412Sgibbs struct ccb_getdevstats cgds; 124547412Sgibbs 1246198382Smav xpt_setup_ccb(&cgds.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 124747412Sgibbs cgds.ccb_h.func_code = XPT_GDEV_STATS; 124847412Sgibbs xpt_action((union ccb *)&cgds); 124947412Sgibbs cam_periph_freeze_after_event(periph, &cgds.last_reset, bus_settle); 125047412Sgibbs} 125147412Sgibbs 125247412Sgibbsvoid 125347412Sgibbscam_periph_freeze_after_event(struct cam_periph *periph, 125447412Sgibbs struct timeval* event_time, u_int duration_ms) 125547412Sgibbs{ 125647412Sgibbs struct timeval delta; 125747412Sgibbs struct timeval duration_tv; 125847412Sgibbs 1259241536Smav if (!timevalisset(event_time)) 1260241536Smav return; 1261241536Smav 126247412Sgibbs microtime(&delta); 126347412Sgibbs timevalsub(&delta, event_time); 126447412Sgibbs duration_tv.tv_sec = duration_ms / 1000; 126547412Sgibbs duration_tv.tv_usec = (duration_ms % 1000) * 1000; 126647412Sgibbs if (timevalcmp(&delta, &duration_tv, <)) { 126747412Sgibbs timevalsub(&duration_tv, &delta); 126847412Sgibbs 126947412Sgibbs duration_ms = duration_tv.tv_sec * 1000; 127047412Sgibbs duration_ms += duration_tv.tv_usec / 1000; 127147412Sgibbs cam_freeze_devq(periph->path); 127247412Sgibbs cam_release_devq(periph->path, 127347412Sgibbs RELSIM_RELEASE_AFTER_TIMEOUT, 127447412Sgibbs /*reduction*/0, 127547412Sgibbs /*timeout*/duration_ms, 127647412Sgibbs /*getcount_only*/0); 127747412Sgibbs } 127847412Sgibbs 127947412Sgibbs} 128047412Sgibbs 128174840Skenstatic int 1282236814Smavcamperiphscsistatuserror(union ccb *ccb, union ccb **orig_ccb, 1283236814Smav cam_flags camflags, u_int32_t sense_flags, 1284236814Smav int *openings, u_int32_t *relsim_flags, 1285253322Smav u_int32_t *timeout, u_int32_t *action, const char **action_string) 128639212Sgibbs{ 128774840Sken int error; 128839212Sgibbs 128974840Sken switch (ccb->csio.scsi_status) { 129074840Sken case SCSI_STATUS_OK: 129174840Sken case SCSI_STATUS_COND_MET: 129274840Sken case SCSI_STATUS_INTERMED: 129374840Sken case SCSI_STATUS_INTERMED_COND_MET: 129439212Sgibbs error = 0; 129539212Sgibbs break; 129674840Sken case SCSI_STATUS_CMD_TERMINATED: 129774840Sken case SCSI_STATUS_CHECK_COND: 1298236814Smav error = camperiphscsisenseerror(ccb, orig_ccb, 129974840Sken camflags, 130074840Sken sense_flags, 130174840Sken openings, 130274840Sken relsim_flags, 1303203108Smav timeout, 1304253322Smav action, 1305203108Smav action_string); 130674840Sken break; 130774840Sken case SCSI_STATUS_QUEUE_FULL: 130874840Sken { 130974840Sken /* no decrement */ 131074840Sken struct ccb_getdevstats cgds; 131139212Sgibbs 131274840Sken /* 131374840Sken * First off, find out what the current 131474840Sken * transaction counts are. 131574840Sken */ 131674840Sken xpt_setup_ccb(&cgds.ccb_h, 131774840Sken ccb->ccb_h.path, 1318198382Smav CAM_PRIORITY_NORMAL); 131974840Sken cgds.ccb_h.func_code = XPT_GDEV_STATS; 132074840Sken xpt_action((union ccb *)&cgds); 132139212Sgibbs 132274840Sken /* 132374840Sken * If we were the only transaction active, treat 132474840Sken * the QUEUE FULL as if it were a BUSY condition. 132574840Sken */ 132674840Sken if (cgds.dev_active != 0) { 132774840Sken int total_openings; 132839212Sgibbs 132974840Sken /* 133074840Sken * Reduce the number of openings to 133174840Sken * be 1 less than the amount it took 133274840Sken * to get a queue full bounded by the 133374840Sken * minimum allowed tag count for this 133474840Sken * device. 133574840Sken */ 133674840Sken total_openings = cgds.dev_active + cgds.dev_openings; 133774840Sken *openings = cgds.dev_active; 133874840Sken if (*openings < cgds.mintags) 133974840Sken *openings = cgds.mintags; 134074840Sken if (*openings < total_openings) 134174840Sken *relsim_flags = RELSIM_ADJUST_OPENINGS; 134274840Sken else { 134339212Sgibbs /* 134474840Sken * Some devices report queue full for 134574840Sken * temporary resource shortages. For 134674840Sken * this reason, we allow a minimum 134774840Sken * tag count to be entered via a 134874840Sken * quirk entry to prevent the queue 134974840Sken * count on these devices from falling 135074840Sken * to a pessimisticly low value. We 135174840Sken * still wait for the next successful 135274840Sken * completion, however, before queueing 135374840Sken * more transactions to the device. 135439212Sgibbs */ 135574840Sken *relsim_flags = RELSIM_RELEASE_AFTER_CMDCMPLT; 135674840Sken } 135774840Sken *timeout = 0; 135874840Sken error = ERESTART; 1359253322Smav *action &= ~SSQ_PRINT_SENSE; 136074840Sken break; 136174840Sken } 136274840Sken /* FALLTHROUGH */ 136374840Sken } 136474840Sken case SCSI_STATUS_BUSY: 136574840Sken /* 136674840Sken * Restart the queue after either another 136774840Sken * command completes or a 1 second timeout. 136874840Sken */ 136974840Sken if (ccb->ccb_h.retry_count > 0) { 137074840Sken ccb->ccb_h.retry_count--; 137174840Sken error = ERESTART; 137274840Sken *relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT 137374840Sken | RELSIM_RELEASE_AFTER_CMDCMPLT; 137474840Sken *timeout = 1000; 137574840Sken } else { 137674840Sken error = EIO; 137774840Sken } 137874840Sken break; 137974840Sken case SCSI_STATUS_RESERV_CONFLICT: 138074840Sken default: 138174840Sken error = EIO; 138274840Sken break; 138374840Sken } 138474840Sken return (error); 138574840Sken} 138639212Sgibbs 138774840Skenstatic int 1388236814Smavcamperiphscsisenseerror(union ccb *ccb, union ccb **orig, 1389236814Smav cam_flags camflags, u_int32_t sense_flags, 1390236814Smav int *openings, u_int32_t *relsim_flags, 1391253322Smav u_int32_t *timeout, u_int32_t *action, const char **action_string) 139274840Sken{ 139374840Sken struct cam_periph *periph; 1394203108Smav union ccb *orig_ccb = ccb; 1395236814Smav int error, recoveryccb; 139639212Sgibbs 139774840Sken periph = xpt_path_periph(ccb->ccb_h.path); 1398236814Smav recoveryccb = (ccb->ccb_h.cbfcnp == camperiphdone); 1399236814Smav if ((periph->flags & CAM_PERIPH_RECOVERY_INPROG) && !recoveryccb) { 140074840Sken /* 140174840Sken * If error recovery is already in progress, don't attempt 140274840Sken * to process this error, but requeue it unconditionally 140374840Sken * and attempt to process it once error recovery has 140474840Sken * completed. This failed command is probably related to 140574840Sken * the error that caused the currently active error recovery 140674840Sken * action so our current recovery efforts should also 140774840Sken * address this command. Be aware that the error recovery 140874840Sken * code assumes that only one recovery action is in progress 140974840Sken * on a particular peripheral instance at any given time 141074840Sken * (e.g. only one saved CCB for error recovery) so it is 141174840Sken * imperitive that we don't violate this assumption. 141274840Sken */ 141374840Sken error = ERESTART; 1414253322Smav *action &= ~SSQ_PRINT_SENSE; 141574840Sken } else { 141674840Sken scsi_sense_action err_action; 141774840Sken struct ccb_getdev cgd; 141840318Sken 141974840Sken /* 142074840Sken * Grab the inquiry data for this device. 142174840Sken */ 1422198382Smav xpt_setup_ccb(&cgd.ccb_h, ccb->ccb_h.path, CAM_PRIORITY_NORMAL); 142374840Sken cgd.ccb_h.func_code = XPT_GDEV_TYPE; 142474840Sken xpt_action((union ccb *)&cgd); 142539212Sgibbs 1426237478Smav err_action = scsi_error_action(&ccb->csio, &cgd.inq_data, 1427237478Smav sense_flags); 142874840Sken error = err_action & SS_ERRMASK; 142939212Sgibbs 143074840Sken /* 1431236814Smav * Do not autostart sequential access devices 1432236814Smav * to avoid unexpected tape loading. 1433236814Smav */ 1434236814Smav if ((err_action & SS_MASK) == SS_START && 1435236814Smav SID_TYPE(&cgd.inq_data) == T_SEQUENTIAL) { 1436236814Smav *action_string = "Will not autostart a " 1437236814Smav "sequential access device"; 1438236814Smav goto sense_error_done; 1439236814Smav } 1440236814Smav 1441236814Smav /* 1442236814Smav * Avoid recovery recursion if recovery action is the same. 1443236814Smav */ 1444236814Smav if ((err_action & SS_MASK) >= SS_START && recoveryccb) { 1445236814Smav if (((err_action & SS_MASK) == SS_START && 1446236814Smav ccb->csio.cdb_io.cdb_bytes[0] == START_STOP_UNIT) || 1447236814Smav ((err_action & SS_MASK) == SS_TUR && 1448236814Smav (ccb->csio.cdb_io.cdb_bytes[0] == TEST_UNIT_READY))) { 1449236814Smav err_action = SS_RETRY|SSQ_DECREMENT_COUNT|EIO; 1450236814Smav *relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT; 1451236814Smav *timeout = 500; 1452236814Smav } 1453236814Smav } 1454236814Smav 1455236814Smav /* 145674840Sken * If the recovery action will consume a retry, 145774840Sken * make sure we actually have retries available. 145874840Sken */ 145974840Sken if ((err_action & SSQ_DECREMENT_COUNT) != 0) { 1460224496Smav if (ccb->ccb_h.retry_count > 0 && 1461224496Smav (periph->flags & CAM_PERIPH_INVALID) == 0) 146274840Sken ccb->ccb_h.retry_count--; 146374840Sken else { 1464203108Smav *action_string = "Retries exhausted"; 146574840Sken goto sense_error_done; 146674840Sken } 146774840Sken } 146839212Sgibbs 146974840Sken if ((err_action & SS_MASK) >= SS_START) { 147074840Sken /* 147174840Sken * Do common portions of commands that 147274840Sken * use recovery CCBs. 147374840Sken */ 1474203108Smav orig_ccb = xpt_alloc_ccb_nowait(); 1475203108Smav if (orig_ccb == NULL) { 1476203108Smav *action_string = "Can't allocate recovery CCB"; 147774840Sken goto sense_error_done; 147874840Sken } 1479199281Smav /* 1480199281Smav * Clear freeze flag for original request here, as 1481199281Smav * this freeze will be dropped as part of ERESTART. 1482199281Smav */ 1483199281Smav ccb->ccb_h.status &= ~CAM_DEV_QFRZN; 1484203108Smav bcopy(ccb, orig_ccb, sizeof(*orig_ccb)); 148574840Sken } 148639212Sgibbs 148774840Sken switch (err_action & SS_MASK) { 148874840Sken case SS_NOP: 1489203108Smav *action_string = "No recovery action needed"; 149076158Sken error = 0; 149176158Sken break; 149274840Sken case SS_RETRY: 1493203108Smav *action_string = "Retrying command (per sense data)"; 149474840Sken error = ERESTART; 149539212Sgibbs break; 149674840Sken case SS_FAIL: 1497203108Smav *action_string = "Unretryable error"; 149874840Sken break; 149974840Sken case SS_START: 150039212Sgibbs { 150174840Sken int le; 150239212Sgibbs 150339212Sgibbs /* 150474840Sken * Send a start unit command to the device, and 150574840Sken * then retry the command. 150639212Sgibbs */ 1507203108Smav *action_string = "Attempting to start unit"; 1508203108Smav periph->flags |= CAM_PERIPH_RECOVERY_INPROG; 150939212Sgibbs 151039212Sgibbs /* 151174840Sken * Check for removable media and set 151274840Sken * load/eject flag appropriately. 151339212Sgibbs */ 151474840Sken if (SID_IS_REMOVABLE(&cgd.inq_data)) 151574840Sken le = TRUE; 151674840Sken else 151774840Sken le = FALSE; 151847434Sgibbs 151974840Sken scsi_start_stop(&ccb->csio, 152074840Sken /*retries*/1, 152174840Sken camperiphdone, 152274840Sken MSG_SIMPLE_Q_TAG, 152374840Sken /*start*/TRUE, 152474840Sken /*load/eject*/le, 152574840Sken /*immediate*/FALSE, 152674840Sken SSD_FULL_SIZE, 152774840Sken /*timeout*/50000); 152874840Sken break; 152939212Sgibbs } 153074840Sken case SS_TUR: 153174840Sken { 153239212Sgibbs /* 153374840Sken * Send a Test Unit Ready to the device. 153474840Sken * If the 'many' flag is set, we send 120 153574840Sken * test unit ready commands, one every half 153674840Sken * second. Otherwise, we just send one TUR. 153774840Sken * We only want to do this if the retry 153874840Sken * count has not been exhausted. 153939212Sgibbs */ 154074840Sken int retries; 154174840Sken 154274840Sken if ((err_action & SSQ_MANY) != 0) { 1543203108Smav *action_string = "Polling device for readiness"; 154474840Sken retries = 120; 154552326Smjacob } else { 1546203108Smav *action_string = "Testing device for readiness"; 154774840Sken retries = 1; 154852326Smjacob } 1549203108Smav periph->flags |= CAM_PERIPH_RECOVERY_INPROG; 155074840Sken scsi_test_unit_ready(&ccb->csio, 155174840Sken retries, 155274840Sken camperiphdone, 155374840Sken MSG_SIMPLE_Q_TAG, 155474840Sken SSD_FULL_SIZE, 155574840Sken /*timeout*/5000); 155674840Sken 155774840Sken /* 155874840Sken * Accomplish our 500ms delay by deferring 155974840Sken * the release of our device queue appropriately. 156074840Sken */ 156174840Sken *relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT; 156274840Sken *timeout = 500; 156339212Sgibbs break; 156474840Sken } 156539212Sgibbs default: 1566106902Simp panic("Unhandled error action %x", err_action); 156739212Sgibbs } 156874840Sken 156974840Sken if ((err_action & SS_MASK) >= SS_START) { 157074840Sken /* 1571198382Smav * Drop the priority, so that the recovery 157274840Sken * CCB is the first to execute. Freeze the queue 157374840Sken * after this command is sent so that we can 157474840Sken * restore the old csio and have it queued in 157574840Sken * the proper order before we release normal 157674840Sken * transactions to the device. 157774840Sken */ 1578203108Smav ccb->ccb_h.pinfo.priority--; 157974840Sken ccb->ccb_h.flags |= CAM_DEV_QFREEZE; 1580203108Smav ccb->ccb_h.saved_ccb_ptr = orig_ccb; 158174840Sken error = ERESTART; 1582236814Smav *orig = orig_ccb; 158374840Sken } 158474840Sken 158574840Skensense_error_done: 1586253322Smav *action = err_action; 158774840Sken } 158874840Sken return (error); 158974840Sken} 159074840Sken 159174840Sken/* 159274840Sken * Generic error handler. Peripheral drivers usually filter 159374840Sken * out the errors that they handle in a unique mannor, then 159474840Sken * call this function. 159574840Sken */ 159674840Skenint 159774840Skencam_periph_error(union ccb *ccb, cam_flags camflags, 159874840Sken u_int32_t sense_flags, union ccb *save_ccb) 159974840Sken{ 1600253322Smav struct cam_path *newpath; 1601253322Smav union ccb *orig_ccb, *scan_ccb; 1602224496Smav struct cam_periph *periph; 160374840Sken const char *action_string; 160474840Sken cam_status status; 1605253322Smav int frozen, error, openings; 1606253322Smav u_int32_t action, relsim_flags, timeout; 1607224496Smav 1608253322Smav action = SSQ_PRINT_SENSE; 1609224496Smav periph = xpt_path_periph(ccb->ccb_h.path); 161074840Sken action_string = NULL; 161174840Sken status = ccb->ccb_h.status; 161274840Sken frozen = (status & CAM_DEV_QFRZN) != 0; 161374840Sken status &= CAM_STATUS_MASK; 1614253322Smav openings = relsim_flags = timeout = 0; 1615236814Smav orig_ccb = ccb; 161674840Sken 161774840Sken switch (status) { 161874840Sken case CAM_REQ_CMP: 161974840Sken error = 0; 1620253322Smav action &= ~SSQ_PRINT_SENSE; 162139212Sgibbs break; 162274840Sken case CAM_SCSI_STATUS_ERROR: 1623236814Smav error = camperiphscsistatuserror(ccb, &orig_ccb, 1624236814Smav camflags, sense_flags, &openings, &relsim_flags, 1625253322Smav &timeout, &action, &action_string); 162674840Sken break; 162774840Sken case CAM_AUTOSENSE_FAIL: 162880578Smjacob error = EIO; /* we have to kill the command */ 162980578Smjacob break; 163039212Sgibbs case CAM_UA_ABORT: 163139212Sgibbs case CAM_UA_TERMIO: 163239212Sgibbs case CAM_MSG_REJECT_REC: 163339212Sgibbs /* XXX Don't know that these are correct */ 163439212Sgibbs error = EIO; 163539212Sgibbs break; 163639212Sgibbs case CAM_SEL_TIMEOUT: 163774840Sken if ((camflags & CAM_RETRY_SELTO) != 0) { 1638224496Smav if (ccb->ccb_h.retry_count > 0 && 1639224496Smav (periph->flags & CAM_PERIPH_INVALID) == 0) { 164074840Sken ccb->ccb_h.retry_count--; 164174840Sken error = ERESTART; 164274840Sken 164374840Sken /* 1644162938Smjacob * Wait a bit to give the device 164574840Sken * time to recover before we try again. 164674840Sken */ 164774840Sken relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT; 1648162938Smjacob timeout = periph_selto_delay; 164974840Sken break; 165074840Sken } 1651224496Smav action_string = "Retries exhausted"; 165274840Sken } 1653230000Sken /* FALLTHROUGH */ 1654230000Sken case CAM_DEV_NOT_THERE: 165574840Sken error = ENXIO; 1656253322Smav action = SSQ_LOST; 165739212Sgibbs break; 165839212Sgibbs case CAM_REQ_INVALID: 165939212Sgibbs case CAM_PATH_INVALID: 166039212Sgibbs case CAM_NO_HBA: 166139212Sgibbs case CAM_PROVIDE_FAIL: 166274840Sken case CAM_REQ_TOO_BIG: 1663154119Siedowse case CAM_LUN_INVALID: 1664154119Siedowse case CAM_TID_INVALID: 166539212Sgibbs error = EINVAL; 166639212Sgibbs break; 166739212Sgibbs case CAM_SCSI_BUS_RESET: 166874840Sken case CAM_BDR_SENT: 166974840Sken /* 167074840Sken * Commands that repeatedly timeout and cause these 167174840Sken * kinds of error recovery actions, should return 167274840Sken * CAM_CMD_TIMEOUT, which allows us to safely assume 167374840Sken * that this command was an innocent bystander to 167474840Sken * these events and should be unconditionally 167574840Sken * retried. 167674840Sken */ 167739212Sgibbs case CAM_REQUEUE_REQ: 1678236814Smav /* Unconditional requeue if device is still there */ 1679236814Smav if (periph->flags & CAM_PERIPH_INVALID) { 1680236814Smav action_string = "Periph was invalidated"; 1681236814Smav error = EIO; 1682236814Smav } else if (sense_flags & SF_NO_RETRY) { 1683236814Smav error = EIO; 1684236814Smav action_string = "Retry was blocked"; 1685237446Smav } else { 1686224496Smav error = ERESTART; 1687253322Smav action &= ~SSQ_PRINT_SENSE; 1688237446Smav } 168939212Sgibbs break; 169039212Sgibbs case CAM_RESRC_UNAVAIL: 1691162938Smjacob /* Wait a bit for the resource shortage to abate. */ 1692162938Smjacob timeout = periph_noresrc_delay; 1693162938Smjacob /* FALLTHROUGH */ 169439212Sgibbs case CAM_BUSY: 1695162938Smjacob if (timeout == 0) { 1696162938Smjacob /* Wait a bit for the busy condition to abate. */ 1697162938Smjacob timeout = periph_busy_delay; 1698162938Smjacob } 1699162938Smjacob relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT; 1700162938Smjacob /* FALLTHROUGH */ 1701236814Smav case CAM_ATA_STATUS_ERROR: 1702236814Smav case CAM_REQ_CMP_ERR: 1703236814Smav case CAM_CMD_TIMEOUT: 1704236814Smav case CAM_UNEXP_BUSFREE: 1705236814Smav case CAM_UNCOR_PARITY: 1706236814Smav case CAM_DATA_RUN_ERR: 170739212Sgibbs default: 1708236814Smav if (periph->flags & CAM_PERIPH_INVALID) { 1709236814Smav error = EIO; 1710236814Smav action_string = "Periph was invalidated"; 1711236814Smav } else if (ccb->ccb_h.retry_count == 0) { 1712236814Smav error = EIO; 1713236814Smav action_string = "Retries exhausted"; 1714236814Smav } else if (sense_flags & SF_NO_RETRY) { 1715236814Smav error = EIO; 1716236814Smav action_string = "Retry was blocked"; 1717236814Smav } else { 171839212Sgibbs ccb->ccb_h.retry_count--; 171939212Sgibbs error = ERESTART; 172039212Sgibbs } 172139212Sgibbs break; 172239212Sgibbs } 172339212Sgibbs 1724236814Smav if ((sense_flags & SF_PRINT_ALWAYS) || 1725236814Smav CAM_DEBUGGED(ccb->ccb_h.path, CAM_DEBUG_INFO)) 1726253322Smav action |= SSQ_PRINT_SENSE; 1727236814Smav else if (sense_flags & SF_NO_PRINT) 1728253322Smav action &= ~SSQ_PRINT_SENSE; 1729253322Smav if ((action & SSQ_PRINT_SENSE) != 0) 1730236814Smav cam_error_print(orig_ccb, CAM_ESF_ALL, CAM_EPF_ALL); 1731253322Smav if (error != 0 && (action & SSQ_PRINT_SENSE) != 0) { 1732198394Smav if (error != ERESTART) { 1733198394Smav if (action_string == NULL) 1734203108Smav action_string = "Unretryable error"; 1735203108Smav xpt_print(ccb->ccb_h.path, "Error %d, %s\n", 1736203108Smav error, action_string); 1737203108Smav } else if (action_string != NULL) 1738198394Smav xpt_print(ccb->ccb_h.path, "%s\n", action_string); 1739203108Smav else 1740203108Smav xpt_print(ccb->ccb_h.path, "Retrying command\n"); 1741198394Smav } 1742198394Smav 1743253322Smav if ((action & SSQ_LOST) != 0) { 1744236814Smav lun_id_t lun_id; 1745236814Smav 1746236814Smav /* 1747236814Smav * For a selection timeout, we consider all of the LUNs on 1748236814Smav * the target to be gone. If the status is CAM_DEV_NOT_THERE, 1749236814Smav * then we only get rid of the device(s) specified by the 1750236814Smav * path in the original CCB. 1751236814Smav */ 1752253322Smav if (status == CAM_SEL_TIMEOUT) 1753253322Smav lun_id = CAM_LUN_WILDCARD; 1754253322Smav else 1755236814Smav lun_id = xpt_path_lun_id(ccb->ccb_h.path); 1756236814Smav 1757236814Smav /* Should we do more if we can't create the path?? */ 1758236814Smav if (xpt_create_path(&newpath, periph, 1759236814Smav xpt_path_path_id(ccb->ccb_h.path), 1760236814Smav xpt_path_target_id(ccb->ccb_h.path), 1761236814Smav lun_id) == CAM_REQ_CMP) { 1762236814Smav 1763236814Smav /* 1764236814Smav * Let peripheral drivers know that this 1765236814Smav * device has gone away. 1766236814Smav */ 1767236814Smav xpt_async(AC_LOST_DEVICE, newpath, NULL); 1768236814Smav xpt_free_path(newpath); 1769236814Smav } 1770253322Smav } 1771238886Smav 1772238886Smav /* Broadcast UNIT ATTENTIONs to all periphs. */ 1773253322Smav if ((action & SSQ_UA) != 0) 1774238886Smav xpt_async(AC_UNIT_ATTENTION, orig_ccb->ccb_h.path, orig_ccb); 1775253322Smav 1776253322Smav /* Rescan target on "Reported LUNs data has changed" */ 1777253322Smav if ((action & SSQ_RESCAN) != 0) { 1778253322Smav if (xpt_create_path(&newpath, NULL, 1779253322Smav xpt_path_path_id(ccb->ccb_h.path), 1780253322Smav xpt_path_target_id(ccb->ccb_h.path), 1781253370Smav CAM_LUN_WILDCARD) == CAM_REQ_CMP) { 1782253322Smav 1783253322Smav scan_ccb = xpt_alloc_ccb_nowait(); 1784253370Smav if (scan_ccb != NULL) { 1785253370Smav scan_ccb->ccb_h.path = newpath; 1786253370Smav scan_ccb->ccb_h.func_code = XPT_SCAN_TGT; 1787253370Smav scan_ccb->crcn.flags = 0; 1788253370Smav xpt_rescan(scan_ccb); 1789253370Smav } else 1790253370Smav xpt_print(newpath, 1791253370Smav "Can't allocate CCB to rescan target\n"); 1792253322Smav } 1793236814Smav } 1794236814Smav 179539212Sgibbs /* Attempt a retry */ 1796198394Smav if (error == ERESTART || error == 0) { 179739212Sgibbs if (frozen != 0) 179839212Sgibbs ccb->ccb_h.status &= ~CAM_DEV_QFRZN; 1799198394Smav if (error == ERESTART) 180039212Sgibbs xpt_action(ccb); 180174840Sken if (frozen != 0) 180239212Sgibbs cam_release_devq(ccb->ccb_h.path, 180339212Sgibbs relsim_flags, 180439212Sgibbs openings, 180539212Sgibbs timeout, 180639212Sgibbs /*getcount_only*/0); 180774840Sken } 180874840Sken 180939212Sgibbs return (error); 181039212Sgibbs} 1811