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 periph->periph_start = periph_start; 20039212Sgibbs periph->periph_dtor = periph_dtor; 20140603Sken periph->periph_oninval = periph_oninvalidate; 20239212Sgibbs periph->type = type; 20339212Sgibbs periph->periph_name = name; 204260387Sscottl periph->scheduled_priority = CAM_PRIORITY_NONE; 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(); 301260387Sscottl cam_periph_assert(periph, 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 379260626Smavcam_periph_doacquire(struct cam_periph *periph) 380260626Smav{ 381260626Smav 382260626Smav xpt_lock_buses(); 383260626Smav KASSERT(periph->refcount >= 1, 384260626Smav ("cam_periph_doacquire() with refcount == %d", periph->refcount)); 385260626Smav periph->refcount++; 386260626Smav xpt_unlock_buses(); 387260626Smav} 388260626Smav 389260626Smavvoid 390230000Skencam_periph_release_locked_buses(struct cam_periph *periph) 39139212Sgibbs{ 392249108Smav 393260387Sscottl cam_periph_assert(periph, MA_OWNED); 394249108Smav KASSERT(periph->refcount >= 1, ("periph->refcount >= 1")); 395249980Smav if (--periph->refcount == 0) 39639212Sgibbs camperiphfree(periph); 397230000Sken} 398230000Sken 399230000Skenvoid 400230000Skencam_periph_release_locked(struct cam_periph *periph) 401230000Sken{ 402230000Sken 403230000Sken if (periph == NULL) 404230000Sken return; 405230000Sken 406230000Sken xpt_lock_buses(); 407230000Sken cam_periph_release_locked_buses(periph); 408168752Sscottl xpt_unlock_buses(); 409186319Strasz} 41039212Sgibbs 411186319Straszvoid 412186319Straszcam_periph_release(struct cam_periph *periph) 413186319Strasz{ 414260387Sscottl struct mtx *mtx; 415186319Strasz 416186319Strasz if (periph == NULL) 417186319Strasz return; 418186319Strasz 419260387Sscottl cam_periph_assert(periph, MA_NOTOWNED); 420260387Sscottl mtx = cam_periph_mtx(periph); 421260387Sscottl mtx_lock(mtx); 422186319Strasz cam_periph_release_locked(periph); 423260387Sscottl mtx_unlock(mtx); 42439212Sgibbs} 42539212Sgibbs 426168752Sscottlint 427168752Sscottlcam_periph_hold(struct cam_periph *periph, int priority) 428168752Sscottl{ 429168752Sscottl int error; 430168752Sscottl 431168752Sscottl /* 432168752Sscottl * Increment the reference count on the peripheral 433168752Sscottl * while we wait for our lock attempt to succeed 434168752Sscottl * to ensure the peripheral doesn't disappear out 435168752Sscottl * from user us while we sleep. 436168752Sscottl */ 437168752Sscottl 438168752Sscottl if (cam_periph_acquire(periph) != CAM_REQ_CMP) 439168752Sscottl return (ENXIO); 440168752Sscottl 441260387Sscottl cam_periph_assert(periph, MA_OWNED); 442168752Sscottl while ((periph->flags & CAM_PERIPH_LOCKED) != 0) { 443168752Sscottl periph->flags |= CAM_PERIPH_LOCK_WANTED; 444260387Sscottl if ((error = cam_periph_sleep(periph, periph, priority, 445187718Sjhb "caplck", 0)) != 0) { 446186319Strasz cam_periph_release_locked(periph); 447168752Sscottl return (error); 448168752Sscottl } 449237401Smav if (periph->flags & CAM_PERIPH_INVALID) { 450237401Smav cam_periph_release_locked(periph); 451237401Smav return (ENXIO); 452237401Smav } 453168752Sscottl } 454168752Sscottl 455168752Sscottl periph->flags |= CAM_PERIPH_LOCKED; 456168752Sscottl return (0); 457168752Sscottl} 458168752Sscottl 459168752Sscottlvoid 460168752Sscottlcam_periph_unhold(struct cam_periph *periph) 461168752Sscottl{ 462168752Sscottl 463260387Sscottl cam_periph_assert(periph, MA_OWNED); 464168752Sscottl 465168752Sscottl periph->flags &= ~CAM_PERIPH_LOCKED; 466168752Sscottl if ((periph->flags & CAM_PERIPH_LOCK_WANTED) != 0) { 467168752Sscottl periph->flags &= ~CAM_PERIPH_LOCK_WANTED; 468168752Sscottl wakeup(periph); 469168752Sscottl } 470168752Sscottl 471186319Strasz cam_periph_release_locked(periph); 472168752Sscottl} 473168752Sscottl 47439212Sgibbs/* 47539212Sgibbs * Look for the next unit number that is not currently in use for this 47639212Sgibbs * peripheral type starting at "newunit". Also exclude unit numbers that 47739212Sgibbs * are reserved by for future "hardwiring" unless we already know that this 47839212Sgibbs * is a potential wired device. Only assume that the device is "wired" the 47939212Sgibbs * first time through the loop since after that we'll be looking at unit 48039212Sgibbs * numbers that did not match a wiring entry. 48139212Sgibbs */ 48239212Sgibbsstatic u_int 48365225Skencamperiphnextunit(struct periph_driver *p_drv, u_int newunit, int wired, 48465225Sken path_id_t pathid, target_id_t target, lun_id_t lun) 48539212Sgibbs{ 48639212Sgibbs struct cam_periph *periph; 48778135Speter char *periph_name; 48878135Speter int i, val, dunit, r; 48978135Speter const char *dname, *strval; 49039212Sgibbs 49139212Sgibbs periph_name = p_drv->driver_name; 49239212Sgibbs for (;;newunit++) { 49339212Sgibbs 49439212Sgibbs for (periph = TAILQ_FIRST(&p_drv->units); 49539212Sgibbs periph != NULL && periph->unit_number != newunit; 49639212Sgibbs periph = TAILQ_NEXT(periph, unit_links)) 49739212Sgibbs ; 49839212Sgibbs 49939212Sgibbs if (periph != NULL && periph->unit_number == newunit) { 50039212Sgibbs if (wired != 0) { 501164906Smjacob xpt_print(periph->path, "Duplicate Wired " 502164906Smjacob "Device entry!\n"); 503164906Smjacob xpt_print(periph->path, "Second device (%s " 504164906Smjacob "device at scbus%d target %d lun %d) will " 505164906Smjacob "not be wired\n", periph_name, pathid, 506164906Smjacob target, lun); 50739212Sgibbs wired = 0; 50839212Sgibbs } 50939212Sgibbs continue; 51039212Sgibbs } 51156470Speter if (wired) 51256470Speter break; 51339212Sgibbs 51456470Speter /* 51556470Speter * Don't match entries like "da 4" as a wired down 51656470Speter * device, but do match entries like "da 4 target 5" 51756470Speter * or even "da 4 scbus 1". 51856470Speter */ 51978135Speter i = 0; 52078135Speter dname = periph_name; 52178135Speter for (;;) { 52278135Speter r = resource_find_dev(&i, dname, &dunit, NULL, NULL); 52378135Speter if (r != 0) 52478135Speter break; 52556470Speter /* if no "target" and no specific scbus, skip */ 52656470Speter if (resource_int_value(dname, dunit, "target", &val) && 52756470Speter (resource_string_value(dname, dunit, "at",&strval)|| 52856470Speter strcmp(strval, "scbus") == 0)) 52956470Speter continue; 53056470Speter if (newunit == dunit) 53139212Sgibbs break; 53239212Sgibbs } 53378135Speter if (r != 0) 53439212Sgibbs break; 53539212Sgibbs } 53639212Sgibbs return (newunit); 53739212Sgibbs} 53839212Sgibbs 53939212Sgibbsstatic u_int 54039212Sgibbscamperiphunit(struct periph_driver *p_drv, path_id_t pathid, 54139212Sgibbs target_id_t target, lun_id_t lun) 54239212Sgibbs{ 54356470Speter u_int unit; 544102341Speter int wired, i, val, dunit; 54578135Speter const char *dname, *strval; 54678135Speter char pathbuf[32], *periph_name; 54739212Sgibbs 54856470Speter periph_name = p_drv->driver_name; 54956470Speter snprintf(pathbuf, sizeof(pathbuf), "scbus%d", pathid); 550102341Speter unit = 0; 55178135Speter i = 0; 55278135Speter dname = periph_name; 553102341Speter for (wired = 0; resource_find_dev(&i, dname, &dunit, NULL, NULL) == 0; 554102341Speter wired = 0) { 55556470Speter if (resource_string_value(dname, dunit, "at", &strval) == 0) { 55656470Speter if (strcmp(strval, pathbuf) != 0) 55756470Speter continue; 558102341Speter wired++; 55939212Sgibbs } 56056470Speter if (resource_int_value(dname, dunit, "target", &val) == 0) { 56156470Speter if (val != target) 56256470Speter continue; 563102341Speter wired++; 56456470Speter } 56556470Speter if (resource_int_value(dname, dunit, "lun", &val) == 0) { 56656470Speter if (val != lun) 56756470Speter continue; 568102341Speter wired++; 56956470Speter } 570102341Speter if (wired != 0) { 57156470Speter unit = dunit; 57256470Speter break; 57356470Speter } 57439212Sgibbs } 57539212Sgibbs 57639212Sgibbs /* 57739212Sgibbs * Either start from 0 looking for the next unit or from 57856470Speter * the unit number given in the resource config. This way, 57939212Sgibbs * if we have wildcard matches, we don't return the same 58039212Sgibbs * unit number twice. 58139212Sgibbs */ 582102341Speter unit = camperiphnextunit(p_drv, unit, wired, pathid, target, lun); 58339212Sgibbs 58439212Sgibbs return (unit); 58539212Sgibbs} 58639212Sgibbs 58739212Sgibbsvoid 58839212Sgibbscam_periph_invalidate(struct cam_periph *periph) 58939212Sgibbs{ 59039212Sgibbs 591260387Sscottl cam_periph_assert(periph, MA_OWNED); 59240603Sken /* 59340603Sken * We only call this routine the first time a peripheral is 594168882Sscottl * invalidated. 59540603Sken */ 596249980Smav if ((periph->flags & CAM_PERIPH_INVALID) != 0) 597249980Smav return; 59840603Sken 599249980Smav CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("Periph invalidated\n")); 600267778Smarius if ((periph->flags & CAM_PERIPH_ANNOUNCED) && !rebooting) 601257049Smav xpt_denounce_periph(periph); 60239212Sgibbs periph->flags |= CAM_PERIPH_INVALID; 60339212Sgibbs periph->flags &= ~CAM_PERIPH_NEW_DEV_FOUND; 604249980Smav if (periph->periph_oninval != NULL) 605249980Smav periph->periph_oninval(periph); 606249980Smav cam_periph_release_locked(periph); 60739212Sgibbs} 60839212Sgibbs 60939212Sgibbsstatic void 61039212Sgibbscamperiphfree(struct cam_periph *periph) 61139212Sgibbs{ 61239212Sgibbs struct periph_driver **p_drv; 61339212Sgibbs 614260387Sscottl cam_periph_assert(periph, MA_OWNED); 615260387Sscottl KASSERT(periph->periph_allocating == 0, ("%s%d: freed while allocating", 616260387Sscottl periph->periph_name, periph->unit_number)); 61772119Speter for (p_drv = periph_drivers; *p_drv != NULL; p_drv++) { 61839212Sgibbs if (strcmp((*p_drv)->driver_name, periph->periph_name) == 0) 61939212Sgibbs break; 62039212Sgibbs } 621142157Sscottl if (*p_drv == NULL) { 622142157Sscottl printf("camperiphfree: attempt to free non-existant periph\n"); 623142157Sscottl return; 624142157Sscottl } 625168787Sscottl 626237328Sken /* 627244001Sken * We need to set this flag before dropping the topology lock, to 628244001Sken * let anyone who is traversing the list that this peripheral is 629244001Sken * about to be freed, and there will be no more reference count 630244001Sken * checks. 631244001Sken */ 632244001Sken periph->flags |= CAM_PERIPH_FREE; 633244001Sken 634244001Sken /* 635237328Sken * The peripheral destructor semantics dictate calling with only the 636237328Sken * SIM mutex held. Since it might sleep, it should not be called 637237328Sken * with the topology lock held. 638237328Sken */ 639168787Sscottl xpt_unlock_buses(); 64039212Sgibbs 641237328Sken /* 642237328Sken * We need to call the peripheral destructor prior to removing the 643237328Sken * peripheral from the list. Otherwise, we risk running into a 644237328Sken * scenario where the peripheral unit number may get reused 645237328Sken * (because it has been removed from the list), but some resources 646237328Sken * used by the peripheral are still hanging around. In particular, 647237328Sken * the devfs nodes used by some peripherals like the pass(4) driver 648237328Sken * aren't fully cleaned up until the destructor is run. If the 649237328Sken * unit number is reused before the devfs instance is fully gone, 650237328Sken * devfs will panic. 651237328Sken */ 652168787Sscottl if (periph->periph_dtor != NULL) 653168787Sscottl periph->periph_dtor(periph); 654237328Sken 655237328Sken /* 656237328Sken * The peripheral list is protected by the topology lock. 657237328Sken */ 658237328Sken xpt_lock_buses(); 659237328Sken 660237328Sken TAILQ_REMOVE(&(*p_drv)->units, periph, unit_links); 661237328Sken (*p_drv)->generation++; 662237328Sken 663254058Smav xpt_remove_periph(periph); 664237328Sken 665237328Sken xpt_unlock_buses(); 666267778Smarius if ((periph->flags & CAM_PERIPH_ANNOUNCED) && !rebooting) 667257049Smav xpt_print(periph->path, "Periph destroyed\n"); 668267778Smarius else 669257049Smav CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("Periph destroyed\n")); 67039212Sgibbs 67139212Sgibbs if (periph->flags & CAM_PERIPH_NEW_DEV_FOUND) { 67239212Sgibbs union ccb ccb; 67339212Sgibbs void *arg; 67439212Sgibbs 67539212Sgibbs switch (periph->deferred_ac) { 67639212Sgibbs case AC_FOUND_DEVICE: 67739212Sgibbs ccb.ccb_h.func_code = XPT_GDEV_TYPE; 678198382Smav xpt_setup_ccb(&ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 67939212Sgibbs xpt_action(&ccb); 68039212Sgibbs arg = &ccb; 68139212Sgibbs break; 68239212Sgibbs case AC_PATH_REGISTERED: 68339212Sgibbs ccb.ccb_h.func_code = XPT_PATH_INQ; 684198382Smav xpt_setup_ccb(&ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 68539212Sgibbs xpt_action(&ccb); 68639212Sgibbs arg = &ccb; 68739212Sgibbs break; 68839212Sgibbs default: 68939212Sgibbs arg = NULL; 69039212Sgibbs break; 69139212Sgibbs } 69239212Sgibbs periph->deferred_callback(NULL, periph->deferred_ac, 69339212Sgibbs periph->path, arg); 69439212Sgibbs } 69539212Sgibbs xpt_free_path(periph->path); 696147723Savatar free(periph, M_CAMPERIPH); 697168787Sscottl xpt_lock_buses(); 69839212Sgibbs} 69939212Sgibbs 70039212Sgibbs/* 70139212Sgibbs * Map user virtual pointers into kernel virtual address space, so we can 702251479Sscottl * access the memory. This is now a generic function that centralizes most 703251479Sscottl * of the sanity checks on the data flags, if any. 704251479Sscottl * This also only works for up to MAXPHYS memory. Since we use 70539212Sgibbs * buffers to map stuff in and out, we're limited to the buffer size. 70639212Sgibbs */ 70739212Sgibbsint 70839212Sgibbscam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo) 70939212Sgibbs{ 710109572Sdillon int numbufs, i, j; 71141877Sken int flags[CAM_PERIPH_MAXMAPS]; 71239212Sgibbs u_int8_t **data_ptrs[CAM_PERIPH_MAXMAPS]; 71339212Sgibbs u_int32_t lengths[CAM_PERIPH_MAXMAPS]; 71439212Sgibbs u_int32_t dirs[CAM_PERIPH_MAXMAPS]; 715195534Sscottl /* Some controllers may not be able to handle more data. */ 716195534Sscottl size_t maxmap = DFLTPHYS; 71739212Sgibbs 71839212Sgibbs switch(ccb->ccb_h.func_code) { 71939212Sgibbs case XPT_DEV_MATCH: 72039212Sgibbs if (ccb->cdm.match_buf_len == 0) { 72139212Sgibbs printf("cam_periph_mapmem: invalid match buffer " 72239212Sgibbs "length 0\n"); 72339212Sgibbs return(EINVAL); 72439212Sgibbs } 72539212Sgibbs if (ccb->cdm.pattern_buf_len > 0) { 72639212Sgibbs data_ptrs[0] = (u_int8_t **)&ccb->cdm.patterns; 72739212Sgibbs lengths[0] = ccb->cdm.pattern_buf_len; 72839212Sgibbs dirs[0] = CAM_DIR_OUT; 72939212Sgibbs data_ptrs[1] = (u_int8_t **)&ccb->cdm.matches; 73039212Sgibbs lengths[1] = ccb->cdm.match_buf_len; 73139212Sgibbs dirs[1] = CAM_DIR_IN; 73239212Sgibbs numbufs = 2; 73339212Sgibbs } else { 73439212Sgibbs data_ptrs[0] = (u_int8_t **)&ccb->cdm.matches; 73539212Sgibbs lengths[0] = ccb->cdm.match_buf_len; 73639212Sgibbs dirs[0] = CAM_DIR_IN; 73739212Sgibbs numbufs = 1; 73839212Sgibbs } 739195534Sscottl /* 740195534Sscottl * This request will not go to the hardware, no reason 741195534Sscottl * to be so strict. vmapbuf() is able to map up to MAXPHYS. 742195534Sscottl */ 743195534Sscottl maxmap = MAXPHYS; 74439212Sgibbs break; 74539212Sgibbs case XPT_SCSI_IO: 74647412Sgibbs case XPT_CONT_TARGET_IO: 74739212Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE) 74839212Sgibbs return(0); 749251479Sscottl if ((ccb->ccb_h.flags & CAM_DATA_MASK) != CAM_DATA_VADDR) 750251479Sscottl return (EINVAL); 75139212Sgibbs data_ptrs[0] = &ccb->csio.data_ptr; 75241877Sken lengths[0] = ccb->csio.dxfer_len; 75339212Sgibbs dirs[0] = ccb->ccb_h.flags & CAM_DIR_MASK; 75439212Sgibbs numbufs = 1; 75539212Sgibbs break; 756195534Sscottl case XPT_ATA_IO: 757195534Sscottl if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE) 758195534Sscottl return(0); 759251479Sscottl if ((ccb->ccb_h.flags & CAM_DATA_MASK) != CAM_DATA_VADDR) 760251479Sscottl return (EINVAL); 761195534Sscottl data_ptrs[0] = &ccb->ataio.data_ptr; 762195534Sscottl lengths[0] = ccb->ataio.dxfer_len; 763195534Sscottl dirs[0] = ccb->ccb_h.flags & CAM_DIR_MASK; 764195534Sscottl numbufs = 1; 765195534Sscottl break; 766216088Sken case XPT_SMP_IO: 767216088Sken data_ptrs[0] = &ccb->smpio.smp_request; 768216088Sken lengths[0] = ccb->smpio.smp_request_len; 769216088Sken dirs[0] = CAM_DIR_OUT; 770216088Sken data_ptrs[1] = &ccb->smpio.smp_response; 771216088Sken lengths[1] = ccb->smpio.smp_response_len; 772216088Sken dirs[1] = CAM_DIR_IN; 773216088Sken numbufs = 2; 774216088Sken break; 775223081Sgibbs case XPT_DEV_ADVINFO: 776223081Sgibbs if (ccb->cdai.bufsiz == 0) 777216361Sken return (0); 778216361Sken 779223081Sgibbs data_ptrs[0] = (uint8_t **)&ccb->cdai.buf; 780223081Sgibbs lengths[0] = ccb->cdai.bufsiz; 781216088Sken dirs[0] = CAM_DIR_IN; 782216088Sken numbufs = 1; 783216361Sken 784216361Sken /* 785216361Sken * This request will not go to the hardware, no reason 786216361Sken * to be so strict. vmapbuf() is able to map up to MAXPHYS. 787216361Sken */ 788216361Sken maxmap = MAXPHYS; 789216088Sken break; 79039212Sgibbs default: 79139212Sgibbs return(EINVAL); 79239212Sgibbs break; /* NOTREACHED */ 79339212Sgibbs } 79439212Sgibbs 79539212Sgibbs /* 79641877Sken * Check the transfer length and permissions first, so we don't 79741877Sken * have to unmap any previously mapped buffers. 79839212Sgibbs */ 79939212Sgibbs for (i = 0; i < numbufs; i++) { 80039212Sgibbs 80141877Sken flags[i] = 0; 80241877Sken 80341877Sken /* 80441877Sken * The userland data pointer passed in may not be page 80541877Sken * aligned. vmapbuf() truncates the address to a page 80641877Sken * boundary, so if the address isn't page aligned, we'll 80741877Sken * need enough space for the given transfer length, plus 80841877Sken * whatever extra space is necessary to make it to the page 80941877Sken * boundary. 81041877Sken */ 81141877Sken if ((lengths[i] + 812195534Sscottl (((vm_offset_t)(*data_ptrs[i])) & PAGE_MASK)) > maxmap){ 81348410Speter printf("cam_periph_mapmem: attempt to map %lu bytes, " 814195534Sscottl "which is greater than %lu\n", 81548410Speter (long)(lengths[i] + 81648410Speter (((vm_offset_t)(*data_ptrs[i])) & PAGE_MASK)), 817195534Sscottl (u_long)maxmap); 81841877Sken return(E2BIG); 81941877Sken } 82041877Sken 82147497Sken if (dirs[i] & CAM_DIR_OUT) { 82258345Sphk flags[i] = BIO_WRITE; 82339212Sgibbs } 82439212Sgibbs 82547497Sken if (dirs[i] & CAM_DIR_IN) { 82658345Sphk flags[i] = BIO_READ; 82739212Sgibbs } 82839212Sgibbs 82941877Sken } 83041877Sken 83141877Sken /* 832251479Sscottl * This keeps the the kernel stack of current thread from getting 833251479Sscottl * swapped. In low-memory situations where the kernel stack might 834251479Sscottl * otherwise get swapped out, this holds it and allows the thread 835251479Sscottl * to make progress and release the kernel mapped pages sooner. 836251479Sscottl * 83741877Sken * XXX KDM should I use P_NOSWAP instead? 83841877Sken */ 83945359Speter PHOLD(curproc); 84041877Sken 84141877Sken for (i = 0; i < numbufs; i++) { 84239212Sgibbs /* 84339212Sgibbs * Get the buffer. 84439212Sgibbs */ 84542957Sdillon mapinfo->bp[i] = getpbuf(NULL); 84639212Sgibbs 84739212Sgibbs /* save the buffer's data address */ 84839212Sgibbs mapinfo->bp[i]->b_saveaddr = mapinfo->bp[i]->b_data; 84939212Sgibbs 85039212Sgibbs /* put our pointer in the data slot */ 85139212Sgibbs mapinfo->bp[i]->b_data = *data_ptrs[i]; 85239212Sgibbs 853195534Sscottl /* set the transfer length, we know it's < MAXPHYS */ 85439212Sgibbs mapinfo->bp[i]->b_bufsize = lengths[i]; 85539212Sgibbs 85658345Sphk /* set the direction */ 85758345Sphk mapinfo->bp[i]->b_iocmd = flags[i]; 85858345Sphk 859109572Sdillon /* 860109572Sdillon * Map the buffer into kernel memory. 861109572Sdillon * 862109572Sdillon * Note that useracc() alone is not a sufficient test. 863109572Sdillon * vmapbuf() can still fail due to a smaller file mapped 864109572Sdillon * into a larger area of VM, or if userland races against 865109572Sdillon * vmapbuf() after the useracc() check. 866109572Sdillon */ 867248515Skib if (vmapbuf(mapinfo->bp[i], 1) < 0) { 868109572Sdillon for (j = 0; j < i; ++j) { 869109572Sdillon *data_ptrs[j] = mapinfo->bp[j]->b_saveaddr; 870119957Salc vunmapbuf(mapinfo->bp[j]); 871109572Sdillon relpbuf(mapinfo->bp[j], NULL); 872109572Sdillon } 873119957Salc relpbuf(mapinfo->bp[i], NULL); 874109572Sdillon PRELE(curproc); 875109572Sdillon return(EACCES); 876109572Sdillon } 87739212Sgibbs 87839212Sgibbs /* set our pointer to the new mapped area */ 87939212Sgibbs *data_ptrs[i] = mapinfo->bp[i]->b_data; 88039212Sgibbs 88139212Sgibbs mapinfo->num_bufs_used++; 88239212Sgibbs } 88339212Sgibbs 884158883Smjacob /* 885158883Smjacob * Now that we've gotten this far, change ownership to the kernel 886158883Smjacob * of the buffers so that we don't run afoul of returning to user 887158883Smjacob * space with locks (on the buffer) held. 888158883Smjacob */ 889158883Smjacob for (i = 0; i < numbufs; i++) { 890158883Smjacob BUF_KERNPROC(mapinfo->bp[i]); 891158883Smjacob } 892158883Smjacob 893158883Smjacob 89439212Sgibbs return(0); 89539212Sgibbs} 89639212Sgibbs 89739212Sgibbs/* 89839212Sgibbs * Unmap memory segments mapped into kernel virtual address space by 89939212Sgibbs * cam_periph_mapmem(). 90039212Sgibbs */ 90139212Sgibbsvoid 90239212Sgibbscam_periph_unmapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo) 90339212Sgibbs{ 90439212Sgibbs int numbufs, i; 90539212Sgibbs u_int8_t **data_ptrs[CAM_PERIPH_MAXMAPS]; 90639212Sgibbs 90739212Sgibbs if (mapinfo->num_bufs_used <= 0) { 908251479Sscottl /* nothing to free and the process wasn't held. */ 90939212Sgibbs return; 91039212Sgibbs } 91139212Sgibbs 91239212Sgibbs switch (ccb->ccb_h.func_code) { 91339212Sgibbs case XPT_DEV_MATCH: 91439212Sgibbs numbufs = min(mapinfo->num_bufs_used, 2); 91539212Sgibbs 91639212Sgibbs if (numbufs == 1) { 91739212Sgibbs data_ptrs[0] = (u_int8_t **)&ccb->cdm.matches; 91839212Sgibbs } else { 91939212Sgibbs data_ptrs[0] = (u_int8_t **)&ccb->cdm.patterns; 92039212Sgibbs data_ptrs[1] = (u_int8_t **)&ccb->cdm.matches; 92139212Sgibbs } 92239212Sgibbs break; 92339212Sgibbs case XPT_SCSI_IO: 92447509Sgibbs case XPT_CONT_TARGET_IO: 92539212Sgibbs data_ptrs[0] = &ccb->csio.data_ptr; 92639212Sgibbs numbufs = min(mapinfo->num_bufs_used, 1); 92739212Sgibbs break; 928195534Sscottl case XPT_ATA_IO: 929195534Sscottl data_ptrs[0] = &ccb->ataio.data_ptr; 930195534Sscottl numbufs = min(mapinfo->num_bufs_used, 1); 931195534Sscottl break; 932216088Sken case XPT_SMP_IO: 933216088Sken numbufs = min(mapinfo->num_bufs_used, 2); 934216088Sken data_ptrs[0] = &ccb->smpio.smp_request; 935216088Sken data_ptrs[1] = &ccb->smpio.smp_response; 936216088Sken break; 937223081Sgibbs case XPT_DEV_ADVINFO: 938216088Sken numbufs = min(mapinfo->num_bufs_used, 1); 939223081Sgibbs data_ptrs[0] = (uint8_t **)&ccb->cdai.buf; 940216088Sken break; 94139212Sgibbs default: 94239212Sgibbs /* allow ourselves to be swapped once again */ 94345359Speter PRELE(curproc); 94439212Sgibbs return; 94539212Sgibbs break; /* NOTREACHED */ 94639212Sgibbs } 94739212Sgibbs 94839212Sgibbs for (i = 0; i < numbufs; i++) { 94939212Sgibbs /* Set the user's pointer back to the original value */ 95039212Sgibbs *data_ptrs[i] = mapinfo->bp[i]->b_saveaddr; 95139212Sgibbs 95239212Sgibbs /* unmap the buffer */ 95339212Sgibbs vunmapbuf(mapinfo->bp[i]); 95439212Sgibbs 95539212Sgibbs /* release the buffer */ 95642957Sdillon relpbuf(mapinfo->bp[i], NULL); 95739212Sgibbs } 95839212Sgibbs 95939212Sgibbs /* allow ourselves to be swapped once again */ 96045359Speter PRELE(curproc); 96139212Sgibbs} 96239212Sgibbs 96339212Sgibbsvoid 96439212Sgibbscam_periph_ccbwait(union ccb *ccb) 96539212Sgibbs{ 96639212Sgibbs 96739212Sgibbs if ((ccb->ccb_h.pinfo.index != CAM_UNQUEUED_INDEX) 96839212Sgibbs || ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG)) 969260387Sscottl xpt_path_sleep(ccb->ccb_h.path, &ccb->ccb_h.cbfcnp, PRIBIO, 970260387Sscottl "cbwait", 0); 97139212Sgibbs} 97239212Sgibbs 97339212Sgibbsint 974194627Sscottlcam_periph_ioctl(struct cam_periph *periph, u_long cmd, caddr_t addr, 97539212Sgibbs int (*error_routine)(union ccb *ccb, 97639212Sgibbs cam_flags camflags, 97739212Sgibbs u_int32_t sense_flags)) 97839212Sgibbs{ 97939212Sgibbs union ccb *ccb; 98039212Sgibbs int error; 98139212Sgibbs int found; 98239212Sgibbs 98339212Sgibbs error = found = 0; 98439212Sgibbs 98539212Sgibbs switch(cmd){ 98639212Sgibbs case CAMGETPASSTHRU: 987198382Smav ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); 98839212Sgibbs xpt_setup_ccb(&ccb->ccb_h, 98939212Sgibbs ccb->ccb_h.path, 990198382Smav CAM_PRIORITY_NORMAL); 99139212Sgibbs ccb->ccb_h.func_code = XPT_GDEVLIST; 99239212Sgibbs 99339212Sgibbs /* 99439212Sgibbs * Basically, the point of this is that we go through 99539212Sgibbs * getting the list of devices, until we find a passthrough 99639212Sgibbs * device. In the current version of the CAM code, the 99739212Sgibbs * only way to determine what type of device we're dealing 99839212Sgibbs * with is by its name. 99939212Sgibbs */ 100039212Sgibbs while (found == 0) { 100139212Sgibbs ccb->cgdl.index = 0; 100239212Sgibbs ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS; 100339212Sgibbs while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) { 100439212Sgibbs 100539212Sgibbs /* we want the next device in the list */ 100639212Sgibbs xpt_action(ccb); 100739212Sgibbs if (strncmp(ccb->cgdl.periph_name, 100839212Sgibbs "pass", 4) == 0){ 100939212Sgibbs found = 1; 101039212Sgibbs break; 101139212Sgibbs } 101239212Sgibbs } 101339212Sgibbs if ((ccb->cgdl.status == CAM_GDEVLIST_LAST_DEVICE) && 101439212Sgibbs (found == 0)) { 101539212Sgibbs ccb->cgdl.periph_name[0] = '\0'; 101639212Sgibbs ccb->cgdl.unit_number = 0; 101739212Sgibbs break; 101839212Sgibbs } 101939212Sgibbs } 102039212Sgibbs 102139212Sgibbs /* copy the result back out */ 102239212Sgibbs bcopy(ccb, addr, sizeof(union ccb)); 102339212Sgibbs 102439212Sgibbs /* and release the ccb */ 102539212Sgibbs xpt_release_ccb(ccb); 102639212Sgibbs 102739212Sgibbs break; 102839212Sgibbs default: 102939212Sgibbs error = ENOTTY; 103039212Sgibbs break; 103139212Sgibbs } 103239212Sgibbs return(error); 103339212Sgibbs} 103439212Sgibbs 1035260387Sscottlstatic void 1036260387Sscottlcam_periph_done(struct cam_periph *periph, union ccb *done_ccb) 1037260387Sscottl{ 1038260387Sscottl 1039260387Sscottl /* Caller will release the CCB */ 1040260387Sscottl wakeup(&done_ccb->ccb_h.cbfcnp); 1041260387Sscottl} 1042260387Sscottl 104339212Sgibbsint 104439212Sgibbscam_periph_runccb(union ccb *ccb, 104539212Sgibbs int (*error_routine)(union ccb *ccb, 104639212Sgibbs cam_flags camflags, 104739212Sgibbs u_int32_t sense_flags), 104839212Sgibbs cam_flags camflags, u_int32_t sense_flags, 104939212Sgibbs struct devstat *ds) 105039212Sgibbs{ 105139212Sgibbs int error; 105239212Sgibbs 1053260387Sscottl xpt_path_assert(ccb->ccb_h.path, MA_OWNED); 1054168752Sscottl 105539212Sgibbs /* 105639212Sgibbs * If the user has supplied a stats structure, and if we understand 105739212Sgibbs * this particular type of ccb, record the transaction start. 105839212Sgibbs */ 1059198947Smav if ((ds != NULL) && (ccb->ccb_h.func_code == XPT_SCSI_IO || 1060198947Smav ccb->ccb_h.func_code == XPT_ATA_IO)) 1061112288Sphk devstat_start_transaction(ds, NULL); 106239212Sgibbs 1063260387Sscottl ccb->ccb_h.cbfcnp = cam_periph_done; 106439212Sgibbs xpt_action(ccb); 106539212Sgibbs 106639212Sgibbs do { 106739212Sgibbs cam_periph_ccbwait(ccb); 106839212Sgibbs if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) 106939212Sgibbs error = 0; 107039212Sgibbs else if (error_routine != NULL) 107139212Sgibbs error = (*error_routine)(ccb, camflags, sense_flags); 107239212Sgibbs else 107339212Sgibbs error = 0; 107439212Sgibbs 107539212Sgibbs } while (error == ERESTART); 107639212Sgibbs 1077203108Smav if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 107839212Sgibbs cam_release_devq(ccb->ccb_h.path, 107939212Sgibbs /* relsim_flags */0, 108039212Sgibbs /* openings */0, 108139212Sgibbs /* timeout */0, 108239212Sgibbs /* getcount_only */ FALSE); 1083203108Smav ccb->ccb_h.status &= ~CAM_DEV_QFRZN; 1084203108Smav } 108539212Sgibbs 1086198947Smav if (ds != NULL) { 1087198947Smav if (ccb->ccb_h.func_code == XPT_SCSI_IO) { 1088198947Smav devstat_end_transaction(ds, 108939212Sgibbs ccb->csio.dxfer_len, 1090198947Smav ccb->csio.tag_action & 0x3, 109139212Sgibbs ((ccb->ccb_h.flags & CAM_DIR_MASK) == 109239212Sgibbs CAM_DIR_NONE) ? DEVSTAT_NO_DATA : 109339212Sgibbs (ccb->ccb_h.flags & CAM_DIR_OUT) ? 109439212Sgibbs DEVSTAT_WRITE : 1095112288Sphk DEVSTAT_READ, NULL, NULL); 1096198947Smav } else if (ccb->ccb_h.func_code == XPT_ATA_IO) { 1097198947Smav devstat_end_transaction(ds, 1098198947Smav ccb->ataio.dxfer_len, 1099198947Smav ccb->ataio.tag_action & 0x3, 1100198947Smav ((ccb->ccb_h.flags & CAM_DIR_MASK) == 1101198947Smav CAM_DIR_NONE) ? DEVSTAT_NO_DATA : 1102198947Smav (ccb->ccb_h.flags & CAM_DIR_OUT) ? 1103198947Smav DEVSTAT_WRITE : 1104198947Smav DEVSTAT_READ, NULL, NULL); 1105198947Smav } 1106198947Smav } 110739212Sgibbs 110839212Sgibbs return(error); 110939212Sgibbs} 111039212Sgibbs 111147412Sgibbsvoid 111247412Sgibbscam_freeze_devq(struct cam_path *path) 111347412Sgibbs{ 1114249466Smav struct ccb_hdr ccb_h; 111547412Sgibbs 1116255126Smav CAM_DEBUG(path, CAM_DEBUG_TRACE, ("cam_freeze_devq\n")); 1117249466Smav xpt_setup_ccb(&ccb_h, path, /*priority*/1); 1118249466Smav ccb_h.func_code = XPT_NOOP; 1119249466Smav ccb_h.flags = CAM_DEV_QFREEZE; 1120249466Smav xpt_action((union ccb *)&ccb_h); 112147412Sgibbs} 112247412Sgibbs 112339212Sgibbsu_int32_t 112439212Sgibbscam_release_devq(struct cam_path *path, u_int32_t relsim_flags, 1125203108Smav u_int32_t openings, u_int32_t arg, 112639212Sgibbs int getcount_only) 112739212Sgibbs{ 112839212Sgibbs struct ccb_relsim crs; 112939212Sgibbs 1130255126Smav CAM_DEBUG(path, CAM_DEBUG_TRACE, ("cam_release_devq(%u, %u, %u, %d)\n", 1131255126Smav relsim_flags, openings, arg, getcount_only)); 1132198382Smav xpt_setup_ccb(&crs.ccb_h, path, CAM_PRIORITY_NORMAL); 113339212Sgibbs crs.ccb_h.func_code = XPT_REL_SIMQ; 113439212Sgibbs crs.ccb_h.flags = getcount_only ? CAM_DEV_QFREEZE : 0; 113539212Sgibbs crs.release_flags = relsim_flags; 113639212Sgibbs crs.openings = openings; 1137203108Smav crs.release_timeout = arg; 113839212Sgibbs xpt_action((union ccb *)&crs); 113939212Sgibbs return (crs.qfrozen_cnt); 114039212Sgibbs} 114139212Sgibbs 114239212Sgibbs#define saved_ccb_ptr ppriv_ptr0 114339212Sgibbsstatic void 114439212Sgibbscamperiphdone(struct cam_periph *periph, union ccb *done_ccb) 114539212Sgibbs{ 1146236814Smav union ccb *saved_ccb; 114739212Sgibbs cam_status status; 114839212Sgibbs struct scsi_start_stop_unit *scsi_cmd; 1149237478Smav int error_code, sense_key, asc, ascq; 115039212Sgibbs 1151236814Smav scsi_cmd = (struct scsi_start_stop_unit *) 1152236814Smav &done_ccb->csio.cdb_io.cdb_bytes; 115339212Sgibbs status = done_ccb->ccb_h.status; 115439212Sgibbs 1155236814Smav if ((status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1156237478Smav if (scsi_extract_sense_ccb(done_ccb, 1157237478Smav &error_code, &sense_key, &asc, &ascq)) { 115839212Sgibbs /* 1159236814Smav * If the error is "invalid field in CDB", 1160236814Smav * and the load/eject flag is set, turn the 1161236814Smav * flag off and try again. This is just in 1162236814Smav * case the drive in question barfs on the 1163236814Smav * load eject flag. The CAM code should set 1164236814Smav * the load/eject flag by default for 116539212Sgibbs * removable media. 116639212Sgibbs */ 116739212Sgibbs if ((scsi_cmd->opcode == START_STOP_UNIT) && 116839212Sgibbs ((scsi_cmd->how & SSS_LOEJ) != 0) && 1169236814Smav (asc == 0x24) && (ascq == 0x00)) { 117039212Sgibbs scsi_cmd->how &= ~SSS_LOEJ; 1171236814Smav if (status & CAM_DEV_QFRZN) { 1172236814Smav cam_release_devq(done_ccb->ccb_h.path, 1173236814Smav 0, 0, 0, 0); 1174236814Smav done_ccb->ccb_h.status &= 1175236814Smav ~CAM_DEV_QFRZN; 1176236814Smav } 117739212Sgibbs xpt_action(done_ccb); 1178236814Smav goto out; 117939212Sgibbs } 118039212Sgibbs } 1181236814Smav if (cam_periph_error(done_ccb, 1182236814Smav 0, SF_RETRY_UA | SF_NO_PRINT, NULL) == ERESTART) 1183236814Smav goto out; 1184236814Smav if (done_ccb->ccb_h.status & CAM_DEV_QFRZN) { 1185236814Smav cam_release_devq(done_ccb->ccb_h.path, 0, 0, 0, 0); 1186236814Smav done_ccb->ccb_h.status &= ~CAM_DEV_QFRZN; 1187236814Smav } 1188236814Smav } else { 1189236814Smav /* 1190236814Smav * If we have successfully taken a device from the not 1191236814Smav * ready to ready state, re-scan the device and re-get 1192236814Smav * the inquiry information. Many devices (mostly disks) 1193236814Smav * don't properly report their inquiry information unless 1194236814Smav * they are spun up. 1195236814Smav */ 1196236814Smav if (scsi_cmd->opcode == START_STOP_UNIT) 1197236814Smav xpt_async(AC_INQ_CHANGED, done_ccb->ccb_h.path, NULL); 119839212Sgibbs } 119939212Sgibbs 120074840Sken /* 1201236814Smav * Perform the final retry with the original CCB so that final 1202236814Smav * error processing is performed by the owner of the CCB. 120374840Sken */ 1204236814Smav saved_ccb = (union ccb *)done_ccb->ccb_h.saved_ccb_ptr; 1205236814Smav bcopy(saved_ccb, done_ccb, sizeof(*done_ccb)); 1206236814Smav xpt_free_ccb(saved_ccb); 1207236814Smav if (done_ccb->ccb_h.cbfcnp != camperiphdone) 1208236814Smav periph->flags &= ~CAM_PERIPH_RECOVERY_INPROG; 1209236814Smav xpt_action(done_ccb); 1210236814Smav 1211236814Smavout: 1212236814Smav /* Drop freeze taken due to CAM_DEV_QFREEZE flag set. */ 1213236814Smav cam_release_devq(done_ccb->ccb_h.path, 0, 0, 0, 0); 121439212Sgibbs} 121539212Sgibbs 121639212Sgibbs/* 121747412Sgibbs * Generic Async Event handler. Peripheral drivers usually 121847412Sgibbs * filter out the events that require personal attention, 121947412Sgibbs * and leave the rest to this function. 122047412Sgibbs */ 122147412Sgibbsvoid 122247412Sgibbscam_periph_async(struct cam_periph *periph, u_int32_t code, 122347412Sgibbs struct cam_path *path, void *arg) 122447412Sgibbs{ 122547412Sgibbs switch (code) { 122647412Sgibbs case AC_LOST_DEVICE: 122747412Sgibbs cam_periph_invalidate(periph); 122847412Sgibbs break; 122947412Sgibbs default: 123047412Sgibbs break; 123147412Sgibbs } 123247412Sgibbs} 123347412Sgibbs 123447412Sgibbsvoid 123547412Sgibbscam_periph_bus_settle(struct cam_periph *periph, u_int bus_settle) 123647412Sgibbs{ 123747412Sgibbs struct ccb_getdevstats cgds; 123847412Sgibbs 1239198382Smav xpt_setup_ccb(&cgds.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 124047412Sgibbs cgds.ccb_h.func_code = XPT_GDEV_STATS; 124147412Sgibbs xpt_action((union ccb *)&cgds); 124247412Sgibbs cam_periph_freeze_after_event(periph, &cgds.last_reset, bus_settle); 124347412Sgibbs} 124447412Sgibbs 124547412Sgibbsvoid 124647412Sgibbscam_periph_freeze_after_event(struct cam_periph *periph, 124747412Sgibbs struct timeval* event_time, u_int duration_ms) 124847412Sgibbs{ 124947412Sgibbs struct timeval delta; 125047412Sgibbs struct timeval duration_tv; 125147412Sgibbs 1252241536Smav if (!timevalisset(event_time)) 1253241536Smav return; 1254241536Smav 125547412Sgibbs microtime(&delta); 125647412Sgibbs timevalsub(&delta, event_time); 125747412Sgibbs duration_tv.tv_sec = duration_ms / 1000; 125847412Sgibbs duration_tv.tv_usec = (duration_ms % 1000) * 1000; 125947412Sgibbs if (timevalcmp(&delta, &duration_tv, <)) { 126047412Sgibbs timevalsub(&duration_tv, &delta); 126147412Sgibbs 126247412Sgibbs duration_ms = duration_tv.tv_sec * 1000; 126347412Sgibbs duration_ms += duration_tv.tv_usec / 1000; 126447412Sgibbs cam_freeze_devq(periph->path); 126547412Sgibbs cam_release_devq(periph->path, 126647412Sgibbs RELSIM_RELEASE_AFTER_TIMEOUT, 126747412Sgibbs /*reduction*/0, 126847412Sgibbs /*timeout*/duration_ms, 126947412Sgibbs /*getcount_only*/0); 127047412Sgibbs } 127147412Sgibbs 127247412Sgibbs} 127347412Sgibbs 127474840Skenstatic int 1275236814Smavcamperiphscsistatuserror(union ccb *ccb, union ccb **orig_ccb, 1276236814Smav cam_flags camflags, u_int32_t sense_flags, 1277236814Smav int *openings, u_int32_t *relsim_flags, 1278253322Smav u_int32_t *timeout, u_int32_t *action, const char **action_string) 127939212Sgibbs{ 128074840Sken int error; 128139212Sgibbs 128274840Sken switch (ccb->csio.scsi_status) { 128374840Sken case SCSI_STATUS_OK: 128474840Sken case SCSI_STATUS_COND_MET: 128574840Sken case SCSI_STATUS_INTERMED: 128674840Sken case SCSI_STATUS_INTERMED_COND_MET: 128739212Sgibbs error = 0; 128839212Sgibbs break; 128974840Sken case SCSI_STATUS_CMD_TERMINATED: 129074840Sken case SCSI_STATUS_CHECK_COND: 1291236814Smav error = camperiphscsisenseerror(ccb, orig_ccb, 129274840Sken camflags, 129374840Sken sense_flags, 129474840Sken openings, 129574840Sken relsim_flags, 1296203108Smav timeout, 1297253322Smav action, 1298203108Smav action_string); 129974840Sken break; 130074840Sken case SCSI_STATUS_QUEUE_FULL: 130174840Sken { 130274840Sken /* no decrement */ 130374840Sken struct ccb_getdevstats cgds; 130439212Sgibbs 130574840Sken /* 130674840Sken * First off, find out what the current 130774840Sken * transaction counts are. 130874840Sken */ 130974840Sken xpt_setup_ccb(&cgds.ccb_h, 131074840Sken ccb->ccb_h.path, 1311198382Smav CAM_PRIORITY_NORMAL); 131274840Sken cgds.ccb_h.func_code = XPT_GDEV_STATS; 131374840Sken xpt_action((union ccb *)&cgds); 131439212Sgibbs 131574840Sken /* 131674840Sken * If we were the only transaction active, treat 131774840Sken * the QUEUE FULL as if it were a BUSY condition. 131874840Sken */ 131974840Sken if (cgds.dev_active != 0) { 132074840Sken int total_openings; 132139212Sgibbs 132274840Sken /* 132374840Sken * Reduce the number of openings to 132474840Sken * be 1 less than the amount it took 132574840Sken * to get a queue full bounded by the 132674840Sken * minimum allowed tag count for this 132774840Sken * device. 132874840Sken */ 132974840Sken total_openings = cgds.dev_active + cgds.dev_openings; 133074840Sken *openings = cgds.dev_active; 133174840Sken if (*openings < cgds.mintags) 133274840Sken *openings = cgds.mintags; 133374840Sken if (*openings < total_openings) 133474840Sken *relsim_flags = RELSIM_ADJUST_OPENINGS; 133574840Sken else { 133639212Sgibbs /* 133774840Sken * Some devices report queue full for 133874840Sken * temporary resource shortages. For 133974840Sken * this reason, we allow a minimum 134074840Sken * tag count to be entered via a 134174840Sken * quirk entry to prevent the queue 134274840Sken * count on these devices from falling 134374840Sken * to a pessimisticly low value. We 134474840Sken * still wait for the next successful 134574840Sken * completion, however, before queueing 134674840Sken * more transactions to the device. 134739212Sgibbs */ 134874840Sken *relsim_flags = RELSIM_RELEASE_AFTER_CMDCMPLT; 134974840Sken } 135074840Sken *timeout = 0; 135174840Sken error = ERESTART; 1352253322Smav *action &= ~SSQ_PRINT_SENSE; 135374840Sken break; 135474840Sken } 135574840Sken /* FALLTHROUGH */ 135674840Sken } 135774840Sken case SCSI_STATUS_BUSY: 135874840Sken /* 135974840Sken * Restart the queue after either another 136074840Sken * command completes or a 1 second timeout. 136174840Sken */ 136274840Sken if (ccb->ccb_h.retry_count > 0) { 136374840Sken ccb->ccb_h.retry_count--; 136474840Sken error = ERESTART; 136574840Sken *relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT 136674840Sken | RELSIM_RELEASE_AFTER_CMDCMPLT; 136774840Sken *timeout = 1000; 136874840Sken } else { 136974840Sken error = EIO; 137074840Sken } 137174840Sken break; 137274840Sken case SCSI_STATUS_RESERV_CONFLICT: 137374840Sken default: 137474840Sken error = EIO; 137574840Sken break; 137674840Sken } 137774840Sken return (error); 137874840Sken} 137939212Sgibbs 138074840Skenstatic int 1381236814Smavcamperiphscsisenseerror(union ccb *ccb, union ccb **orig, 1382236814Smav cam_flags camflags, u_int32_t sense_flags, 1383236814Smav int *openings, u_int32_t *relsim_flags, 1384253322Smav u_int32_t *timeout, u_int32_t *action, const char **action_string) 138574840Sken{ 138674840Sken struct cam_periph *periph; 1387203108Smav union ccb *orig_ccb = ccb; 1388236814Smav int error, recoveryccb; 138939212Sgibbs 139074840Sken periph = xpt_path_periph(ccb->ccb_h.path); 1391236814Smav recoveryccb = (ccb->ccb_h.cbfcnp == camperiphdone); 1392236814Smav if ((periph->flags & CAM_PERIPH_RECOVERY_INPROG) && !recoveryccb) { 139374840Sken /* 139474840Sken * If error recovery is already in progress, don't attempt 139574840Sken * to process this error, but requeue it unconditionally 139674840Sken * and attempt to process it once error recovery has 139774840Sken * completed. This failed command is probably related to 139874840Sken * the error that caused the currently active error recovery 139974840Sken * action so our current recovery efforts should also 140074840Sken * address this command. Be aware that the error recovery 140174840Sken * code assumes that only one recovery action is in progress 140274840Sken * on a particular peripheral instance at any given time 140374840Sken * (e.g. only one saved CCB for error recovery) so it is 140474840Sken * imperitive that we don't violate this assumption. 140574840Sken */ 140674840Sken error = ERESTART; 1407253322Smav *action &= ~SSQ_PRINT_SENSE; 140874840Sken } else { 140974840Sken scsi_sense_action err_action; 141074840Sken struct ccb_getdev cgd; 141140318Sken 141274840Sken /* 141374840Sken * Grab the inquiry data for this device. 141474840Sken */ 1415198382Smav xpt_setup_ccb(&cgd.ccb_h, ccb->ccb_h.path, CAM_PRIORITY_NORMAL); 141674840Sken cgd.ccb_h.func_code = XPT_GDEV_TYPE; 141774840Sken xpt_action((union ccb *)&cgd); 141839212Sgibbs 1419237478Smav err_action = scsi_error_action(&ccb->csio, &cgd.inq_data, 1420237478Smav sense_flags); 142174840Sken error = err_action & SS_ERRMASK; 142239212Sgibbs 142374840Sken /* 1424236814Smav * Do not autostart sequential access devices 1425236814Smav * to avoid unexpected tape loading. 1426236814Smav */ 1427236814Smav if ((err_action & SS_MASK) == SS_START && 1428236814Smav SID_TYPE(&cgd.inq_data) == T_SEQUENTIAL) { 1429236814Smav *action_string = "Will not autostart a " 1430236814Smav "sequential access device"; 1431236814Smav goto sense_error_done; 1432236814Smav } 1433236814Smav 1434236814Smav /* 1435236814Smav * Avoid recovery recursion if recovery action is the same. 1436236814Smav */ 1437236814Smav if ((err_action & SS_MASK) >= SS_START && recoveryccb) { 1438236814Smav if (((err_action & SS_MASK) == SS_START && 1439236814Smav ccb->csio.cdb_io.cdb_bytes[0] == START_STOP_UNIT) || 1440236814Smav ((err_action & SS_MASK) == SS_TUR && 1441236814Smav (ccb->csio.cdb_io.cdb_bytes[0] == TEST_UNIT_READY))) { 1442236814Smav err_action = SS_RETRY|SSQ_DECREMENT_COUNT|EIO; 1443236814Smav *relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT; 1444236814Smav *timeout = 500; 1445236814Smav } 1446236814Smav } 1447236814Smav 1448236814Smav /* 144974840Sken * If the recovery action will consume a retry, 145074840Sken * make sure we actually have retries available. 145174840Sken */ 145274840Sken if ((err_action & SSQ_DECREMENT_COUNT) != 0) { 1453224496Smav if (ccb->ccb_h.retry_count > 0 && 1454224496Smav (periph->flags & CAM_PERIPH_INVALID) == 0) 145574840Sken ccb->ccb_h.retry_count--; 145674840Sken else { 1457203108Smav *action_string = "Retries exhausted"; 145874840Sken goto sense_error_done; 145974840Sken } 146074840Sken } 146139212Sgibbs 146274840Sken if ((err_action & SS_MASK) >= SS_START) { 146374840Sken /* 146474840Sken * Do common portions of commands that 146574840Sken * use recovery CCBs. 146674840Sken */ 1467203108Smav orig_ccb = xpt_alloc_ccb_nowait(); 1468203108Smav if (orig_ccb == NULL) { 1469203108Smav *action_string = "Can't allocate recovery CCB"; 147074840Sken goto sense_error_done; 147174840Sken } 1472199281Smav /* 1473199281Smav * Clear freeze flag for original request here, as 1474199281Smav * this freeze will be dropped as part of ERESTART. 1475199281Smav */ 1476199281Smav ccb->ccb_h.status &= ~CAM_DEV_QFRZN; 1477203108Smav bcopy(ccb, orig_ccb, sizeof(*orig_ccb)); 147874840Sken } 147939212Sgibbs 148074840Sken switch (err_action & SS_MASK) { 148174840Sken case SS_NOP: 1482203108Smav *action_string = "No recovery action needed"; 148376158Sken error = 0; 148476158Sken break; 148574840Sken case SS_RETRY: 1486203108Smav *action_string = "Retrying command (per sense data)"; 148774840Sken error = ERESTART; 148839212Sgibbs break; 148974840Sken case SS_FAIL: 1490203108Smav *action_string = "Unretryable error"; 149174840Sken break; 149274840Sken case SS_START: 149339212Sgibbs { 149474840Sken int le; 149539212Sgibbs 149639212Sgibbs /* 149774840Sken * Send a start unit command to the device, and 149874840Sken * then retry the command. 149939212Sgibbs */ 1500203108Smav *action_string = "Attempting to start unit"; 1501203108Smav periph->flags |= CAM_PERIPH_RECOVERY_INPROG; 150239212Sgibbs 150339212Sgibbs /* 150474840Sken * Check for removable media and set 150574840Sken * load/eject flag appropriately. 150639212Sgibbs */ 150774840Sken if (SID_IS_REMOVABLE(&cgd.inq_data)) 150874840Sken le = TRUE; 150974840Sken else 151074840Sken le = FALSE; 151147434Sgibbs 151274840Sken scsi_start_stop(&ccb->csio, 151374840Sken /*retries*/1, 151474840Sken camperiphdone, 151574840Sken MSG_SIMPLE_Q_TAG, 151674840Sken /*start*/TRUE, 151774840Sken /*load/eject*/le, 151874840Sken /*immediate*/FALSE, 151974840Sken SSD_FULL_SIZE, 152074840Sken /*timeout*/50000); 152174840Sken break; 152239212Sgibbs } 152374840Sken case SS_TUR: 152474840Sken { 152539212Sgibbs /* 152674840Sken * Send a Test Unit Ready to the device. 152774840Sken * If the 'many' flag is set, we send 120 152874840Sken * test unit ready commands, one every half 152974840Sken * second. Otherwise, we just send one TUR. 153074840Sken * We only want to do this if the retry 153174840Sken * count has not been exhausted. 153239212Sgibbs */ 153374840Sken int retries; 153474840Sken 153574840Sken if ((err_action & SSQ_MANY) != 0) { 1536203108Smav *action_string = "Polling device for readiness"; 153774840Sken retries = 120; 153852326Smjacob } else { 1539203108Smav *action_string = "Testing device for readiness"; 154074840Sken retries = 1; 154152326Smjacob } 1542203108Smav periph->flags |= CAM_PERIPH_RECOVERY_INPROG; 154374840Sken scsi_test_unit_ready(&ccb->csio, 154474840Sken retries, 154574840Sken camperiphdone, 154674840Sken MSG_SIMPLE_Q_TAG, 154774840Sken SSD_FULL_SIZE, 154874840Sken /*timeout*/5000); 154974840Sken 155074840Sken /* 155174840Sken * Accomplish our 500ms delay by deferring 155274840Sken * the release of our device queue appropriately. 155374840Sken */ 155474840Sken *relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT; 155574840Sken *timeout = 500; 155639212Sgibbs break; 155774840Sken } 155839212Sgibbs default: 1559106902Simp panic("Unhandled error action %x", err_action); 156039212Sgibbs } 156174840Sken 156274840Sken if ((err_action & SS_MASK) >= SS_START) { 156374840Sken /* 1564198382Smav * Drop the priority, so that the recovery 156574840Sken * CCB is the first to execute. Freeze the queue 156674840Sken * after this command is sent so that we can 156774840Sken * restore the old csio and have it queued in 156874840Sken * the proper order before we release normal 156974840Sken * transactions to the device. 157074840Sken */ 1571203108Smav ccb->ccb_h.pinfo.priority--; 157274840Sken ccb->ccb_h.flags |= CAM_DEV_QFREEZE; 1573203108Smav ccb->ccb_h.saved_ccb_ptr = orig_ccb; 157474840Sken error = ERESTART; 1575236814Smav *orig = orig_ccb; 157674840Sken } 157774840Sken 157874840Skensense_error_done: 1579253322Smav *action = err_action; 158074840Sken } 158174840Sken return (error); 158274840Sken} 158374840Sken 158474840Sken/* 158574840Sken * Generic error handler. Peripheral drivers usually filter 158674840Sken * out the errors that they handle in a unique mannor, then 158774840Sken * call this function. 158874840Sken */ 158974840Skenint 159074840Skencam_periph_error(union ccb *ccb, cam_flags camflags, 159174840Sken u_int32_t sense_flags, union ccb *save_ccb) 159274840Sken{ 1593253322Smav struct cam_path *newpath; 1594253322Smav union ccb *orig_ccb, *scan_ccb; 1595224496Smav struct cam_periph *periph; 159674840Sken const char *action_string; 159774840Sken cam_status status; 1598253322Smav int frozen, error, openings; 1599253322Smav u_int32_t action, relsim_flags, timeout; 1600224496Smav 1601253322Smav action = SSQ_PRINT_SENSE; 1602224496Smav periph = xpt_path_periph(ccb->ccb_h.path); 160374840Sken action_string = NULL; 160474840Sken status = ccb->ccb_h.status; 160574840Sken frozen = (status & CAM_DEV_QFRZN) != 0; 160674840Sken status &= CAM_STATUS_MASK; 1607253322Smav openings = relsim_flags = timeout = 0; 1608236814Smav orig_ccb = ccb; 160974840Sken 161074840Sken switch (status) { 161174840Sken case CAM_REQ_CMP: 161274840Sken error = 0; 1613253322Smav action &= ~SSQ_PRINT_SENSE; 161439212Sgibbs break; 161574840Sken case CAM_SCSI_STATUS_ERROR: 1616236814Smav error = camperiphscsistatuserror(ccb, &orig_ccb, 1617236814Smav camflags, sense_flags, &openings, &relsim_flags, 1618253322Smav &timeout, &action, &action_string); 161974840Sken break; 162074840Sken case CAM_AUTOSENSE_FAIL: 162180578Smjacob error = EIO; /* we have to kill the command */ 162280578Smjacob break; 162339212Sgibbs case CAM_UA_ABORT: 162439212Sgibbs case CAM_UA_TERMIO: 162539212Sgibbs case CAM_MSG_REJECT_REC: 162639212Sgibbs /* XXX Don't know that these are correct */ 162739212Sgibbs error = EIO; 162839212Sgibbs break; 162939212Sgibbs case CAM_SEL_TIMEOUT: 163074840Sken if ((camflags & CAM_RETRY_SELTO) != 0) { 1631224496Smav if (ccb->ccb_h.retry_count > 0 && 1632224496Smav (periph->flags & CAM_PERIPH_INVALID) == 0) { 163374840Sken ccb->ccb_h.retry_count--; 163474840Sken error = ERESTART; 163574840Sken 163674840Sken /* 1637162938Smjacob * Wait a bit to give the device 163874840Sken * time to recover before we try again. 163974840Sken */ 164074840Sken relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT; 1641162938Smjacob timeout = periph_selto_delay; 164274840Sken break; 164374840Sken } 1644224496Smav action_string = "Retries exhausted"; 164574840Sken } 1646230000Sken /* FALLTHROUGH */ 1647230000Sken case CAM_DEV_NOT_THERE: 164874840Sken error = ENXIO; 1649253322Smav action = SSQ_LOST; 165039212Sgibbs break; 165139212Sgibbs case CAM_REQ_INVALID: 165239212Sgibbs case CAM_PATH_INVALID: 165339212Sgibbs case CAM_NO_HBA: 165439212Sgibbs case CAM_PROVIDE_FAIL: 165574840Sken case CAM_REQ_TOO_BIG: 1656154119Siedowse case CAM_LUN_INVALID: 1657154119Siedowse case CAM_TID_INVALID: 1658263299Smav case CAM_FUNC_NOTAVAIL: 165939212Sgibbs error = EINVAL; 166039212Sgibbs break; 166139212Sgibbs case CAM_SCSI_BUS_RESET: 166274840Sken case CAM_BDR_SENT: 166374840Sken /* 166474840Sken * Commands that repeatedly timeout and cause these 166574840Sken * kinds of error recovery actions, should return 166674840Sken * CAM_CMD_TIMEOUT, which allows us to safely assume 166774840Sken * that this command was an innocent bystander to 166874840Sken * these events and should be unconditionally 166974840Sken * retried. 167074840Sken */ 167139212Sgibbs case CAM_REQUEUE_REQ: 1672236814Smav /* Unconditional requeue if device is still there */ 1673236814Smav if (periph->flags & CAM_PERIPH_INVALID) { 1674236814Smav action_string = "Periph was invalidated"; 1675236814Smav error = EIO; 1676236814Smav } else if (sense_flags & SF_NO_RETRY) { 1677236814Smav error = EIO; 1678236814Smav action_string = "Retry was blocked"; 1679237446Smav } else { 1680224496Smav error = ERESTART; 1681253322Smav action &= ~SSQ_PRINT_SENSE; 1682237446Smav } 168339212Sgibbs break; 168439212Sgibbs case CAM_RESRC_UNAVAIL: 1685162938Smjacob /* Wait a bit for the resource shortage to abate. */ 1686162938Smjacob timeout = periph_noresrc_delay; 1687162938Smjacob /* FALLTHROUGH */ 168839212Sgibbs case CAM_BUSY: 1689162938Smjacob if (timeout == 0) { 1690162938Smjacob /* Wait a bit for the busy condition to abate. */ 1691162938Smjacob timeout = periph_busy_delay; 1692162938Smjacob } 1693162938Smjacob relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT; 1694162938Smjacob /* FALLTHROUGH */ 1695236814Smav case CAM_ATA_STATUS_ERROR: 1696236814Smav case CAM_REQ_CMP_ERR: 1697236814Smav case CAM_CMD_TIMEOUT: 1698236814Smav case CAM_UNEXP_BUSFREE: 1699236814Smav case CAM_UNCOR_PARITY: 1700236814Smav case CAM_DATA_RUN_ERR: 170139212Sgibbs default: 1702236814Smav if (periph->flags & CAM_PERIPH_INVALID) { 1703236814Smav error = EIO; 1704236814Smav action_string = "Periph was invalidated"; 1705236814Smav } else if (ccb->ccb_h.retry_count == 0) { 1706236814Smav error = EIO; 1707236814Smav action_string = "Retries exhausted"; 1708236814Smav } else if (sense_flags & SF_NO_RETRY) { 1709236814Smav error = EIO; 1710236814Smav action_string = "Retry was blocked"; 1711236814Smav } else { 171239212Sgibbs ccb->ccb_h.retry_count--; 171339212Sgibbs error = ERESTART; 171439212Sgibbs } 171539212Sgibbs break; 171639212Sgibbs } 171739212Sgibbs 1718236814Smav if ((sense_flags & SF_PRINT_ALWAYS) || 1719236814Smav CAM_DEBUGGED(ccb->ccb_h.path, CAM_DEBUG_INFO)) 1720253322Smav action |= SSQ_PRINT_SENSE; 1721236814Smav else if (sense_flags & SF_NO_PRINT) 1722253322Smav action &= ~SSQ_PRINT_SENSE; 1723253322Smav if ((action & SSQ_PRINT_SENSE) != 0) 1724236814Smav cam_error_print(orig_ccb, CAM_ESF_ALL, CAM_EPF_ALL); 1725253322Smav if (error != 0 && (action & SSQ_PRINT_SENSE) != 0) { 1726198394Smav if (error != ERESTART) { 1727198394Smav if (action_string == NULL) 1728203108Smav action_string = "Unretryable error"; 1729203108Smav xpt_print(ccb->ccb_h.path, "Error %d, %s\n", 1730203108Smav error, action_string); 1731203108Smav } else if (action_string != NULL) 1732198394Smav xpt_print(ccb->ccb_h.path, "%s\n", action_string); 1733203108Smav else 1734203108Smav xpt_print(ccb->ccb_h.path, "Retrying command\n"); 1735198394Smav } 1736198394Smav 1737253322Smav if ((action & SSQ_LOST) != 0) { 1738236814Smav lun_id_t lun_id; 1739236814Smav 1740236814Smav /* 1741236814Smav * For a selection timeout, we consider all of the LUNs on 1742236814Smav * the target to be gone. If the status is CAM_DEV_NOT_THERE, 1743236814Smav * then we only get rid of the device(s) specified by the 1744236814Smav * path in the original CCB. 1745236814Smav */ 1746253322Smav if (status == CAM_SEL_TIMEOUT) 1747253322Smav lun_id = CAM_LUN_WILDCARD; 1748253322Smav else 1749236814Smav lun_id = xpt_path_lun_id(ccb->ccb_h.path); 1750236814Smav 1751236814Smav /* Should we do more if we can't create the path?? */ 1752236814Smav if (xpt_create_path(&newpath, periph, 1753236814Smav xpt_path_path_id(ccb->ccb_h.path), 1754236814Smav xpt_path_target_id(ccb->ccb_h.path), 1755236814Smav lun_id) == CAM_REQ_CMP) { 1756236814Smav 1757236814Smav /* 1758236814Smav * Let peripheral drivers know that this 1759236814Smav * device has gone away. 1760236814Smav */ 1761236814Smav xpt_async(AC_LOST_DEVICE, newpath, NULL); 1762236814Smav xpt_free_path(newpath); 1763236814Smav } 1764253322Smav } 1765238886Smav 1766238886Smav /* Broadcast UNIT ATTENTIONs to all periphs. */ 1767253322Smav if ((action & SSQ_UA) != 0) 1768238886Smav xpt_async(AC_UNIT_ATTENTION, orig_ccb->ccb_h.path, orig_ccb); 1769253322Smav 1770253322Smav /* Rescan target on "Reported LUNs data has changed" */ 1771253322Smav if ((action & SSQ_RESCAN) != 0) { 1772253322Smav if (xpt_create_path(&newpath, NULL, 1773253322Smav xpt_path_path_id(ccb->ccb_h.path), 1774253322Smav xpt_path_target_id(ccb->ccb_h.path), 1775253370Smav CAM_LUN_WILDCARD) == CAM_REQ_CMP) { 1776253322Smav 1777253322Smav scan_ccb = xpt_alloc_ccb_nowait(); 1778253370Smav if (scan_ccb != NULL) { 1779253370Smav scan_ccb->ccb_h.path = newpath; 1780253370Smav scan_ccb->ccb_h.func_code = XPT_SCAN_TGT; 1781253370Smav scan_ccb->crcn.flags = 0; 1782253370Smav xpt_rescan(scan_ccb); 1783260387Sscottl } else { 1784253370Smav xpt_print(newpath, 1785253370Smav "Can't allocate CCB to rescan target\n"); 1786260387Sscottl xpt_free_path(newpath); 1787260387Sscottl } 1788253322Smav } 1789236814Smav } 1790236814Smav 179139212Sgibbs /* Attempt a retry */ 1792198394Smav if (error == ERESTART || error == 0) { 179339212Sgibbs if (frozen != 0) 179439212Sgibbs ccb->ccb_h.status &= ~CAM_DEV_QFRZN; 1795198394Smav if (error == ERESTART) 179639212Sgibbs xpt_action(ccb); 179774840Sken if (frozen != 0) 179839212Sgibbs cam_release_devq(ccb->ccb_h.path, 179939212Sgibbs relsim_flags, 180039212Sgibbs openings, 180139212Sgibbs timeout, 180239212Sgibbs /*getcount_only*/0); 180374840Sken } 180474840Sken 180539212Sgibbs return (error); 180639212Sgibbs} 1807