1195534Sscottl/*- 2195534Sscottl * Implementation of the SCSI Transport 3195534Sscottl * 4195534Sscottl * Copyright (c) 1997, 1998, 1999 Justin T. Gibbs. 5195534Sscottl * Copyright (c) 1997, 1998, 1999 Kenneth D. Merry. 6195534Sscottl * All rights reserved. 7195534Sscottl * 8195534Sscottl * Redistribution and use in source and binary forms, with or without 9195534Sscottl * modification, are permitted provided that the following conditions 10195534Sscottl * are met: 11195534Sscottl * 1. Redistributions of source code must retain the above copyright 12195534Sscottl * notice, this list of conditions, and the following disclaimer, 13195534Sscottl * without modification, immediately at the beginning of the file. 14195534Sscottl * 2. The name of the author may not be used to endorse or promote products 15195534Sscottl * derived from this software without specific prior written permission. 16195534Sscottl * 17195534Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18195534Sscottl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19195534Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20195534Sscottl * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 21195534Sscottl * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22195534Sscottl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23195534Sscottl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24195534Sscottl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25195534Sscottl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26195534Sscottl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27195534Sscottl * SUCH DAMAGE. 28195534Sscottl */ 29195534Sscottl 30195534Sscottl#include <sys/cdefs.h> 31195534Sscottl__FBSDID("$FreeBSD: stable/11/sys/cam/scsi/scsi_xpt.c 351754 2019-09-03 16:24:44Z mav $"); 32195534Sscottl 33195534Sscottl#include <sys/param.h> 34195534Sscottl#include <sys/bus.h> 35195534Sscottl#include <sys/systm.h> 36195534Sscottl#include <sys/types.h> 37195534Sscottl#include <sys/malloc.h> 38195534Sscottl#include <sys/kernel.h> 39195534Sscottl#include <sys/time.h> 40195534Sscottl#include <sys/conf.h> 41195534Sscottl#include <sys/fcntl.h> 42195534Sscottl#include <sys/md5.h> 43195534Sscottl#include <sys/sbuf.h> 44195534Sscottl 45195534Sscottl#include <sys/lock.h> 46195534Sscottl#include <sys/mutex.h> 47195534Sscottl#include <sys/sysctl.h> 48195534Sscottl 49195534Sscottl#include <cam/cam.h> 50195534Sscottl#include <cam/cam_ccb.h> 51195534Sscottl#include <cam/cam_queue.h> 52195534Sscottl#include <cam/cam_periph.h> 53195534Sscottl#include <cam/cam_sim.h> 54195534Sscottl#include <cam/cam_xpt.h> 55195534Sscottl#include <cam/cam_xpt_sim.h> 56195534Sscottl#include <cam/cam_xpt_periph.h> 57195534Sscottl#include <cam/cam_xpt_internal.h> 58195534Sscottl#include <cam/cam_debug.h> 59195534Sscottl 60195534Sscottl#include <cam/scsi/scsi_all.h> 61195534Sscottl#include <cam/scsi/scsi_message.h> 62195534Sscottl#include <cam/scsi/scsi_pass.h> 63195534Sscottl#include <machine/stdarg.h> /* for xpt_print below */ 64195534Sscottl#include "opt_cam.h" 65195534Sscottl 66195534Sscottlstruct scsi_quirk_entry { 67195534Sscottl struct scsi_inquiry_pattern inq_pat; 68195534Sscottl u_int8_t quirks; 69195534Sscottl#define CAM_QUIRK_NOLUNS 0x01 70216088Sken#define CAM_QUIRK_NOVPDS 0x02 71195534Sscottl#define CAM_QUIRK_HILUNS 0x04 72195534Sscottl#define CAM_QUIRK_NOHILUNS 0x08 73208911Smjacob#define CAM_QUIRK_NORPTLUNS 0x10 74195534Sscottl u_int mintags; 75195534Sscottl u_int maxtags; 76195534Sscottl}; 77195534Sscottl#define SCSI_QUIRK(dev) ((struct scsi_quirk_entry *)((dev)->quirk)) 78195534Sscottl 79195534Sscottlstatic int cam_srch_hi = 0; 80195534Sscottlstatic int sysctl_cam_search_luns(SYSCTL_HANDLER_ARGS); 81267992ShselaskySYSCTL_PROC(_kern_cam, OID_AUTO, cam_srch_hi, CTLTYPE_INT | CTLFLAG_RWTUN, 0, 0, 82195534Sscottl sysctl_cam_search_luns, "I", 83195534Sscottl "allow search above LUN 7 for SCSI3 and greater devices"); 84195534Sscottl 85195534Sscottl#define CAM_SCSI2_MAXLUN 8 86208911Smjacob#define CAM_CAN_GET_SIMPLE_LUN(x, i) \ 87208911Smjacob ((((x)->luns[i].lundata[0] & RPL_LUNDATA_ATYP_MASK) == \ 88208911Smjacob RPL_LUNDATA_ATYP_PERIPH) || \ 89208911Smjacob (((x)->luns[i].lundata[0] & RPL_LUNDATA_ATYP_MASK) == \ 90208911Smjacob RPL_LUNDATA_ATYP_FLAT)) 91208911Smjacob#define CAM_GET_SIMPLE_LUN(lp, i, lval) \ 92208911Smjacob if (((lp)->luns[(i)].lundata[0] & RPL_LUNDATA_ATYP_MASK) == \ 93208911Smjacob RPL_LUNDATA_ATYP_PERIPH) { \ 94208911Smjacob (lval) = (lp)->luns[(i)].lundata[1]; \ 95208911Smjacob } else { \ 96208911Smjacob (lval) = (lp)->luns[(i)].lundata[0]; \ 97208911Smjacob (lval) &= RPL_LUNDATA_FLAT_LUN_MASK; \ 98208911Smjacob (lval) <<= 8; \ 99208911Smjacob (lval) |= (lp)->luns[(i)].lundata[1]; \ 100208911Smjacob } 101257345Snwhitehorn#define CAM_GET_LUN(lp, i, lval) \ 102259397Snwhitehorn (lval) = scsi_8btou64((lp)->luns[(i)].lundata); \ 103259397Snwhitehorn (lval) = CAM_EXTLUN_BYTE_SWIZZLE(lval); 104257345Snwhitehorn 105195534Sscottl/* 106195534Sscottl * If we're not quirked to search <= the first 8 luns 107195534Sscottl * and we are either quirked to search above lun 8, 108195534Sscottl * or we're > SCSI-2 and we've enabled hilun searching, 109195534Sscottl * or we're > SCSI-2 and the last lun was a success, 110195534Sscottl * we can look for luns above lun 8. 111195534Sscottl */ 112195534Sscottl#define CAN_SRCH_HI_SPARSE(dv) \ 113195534Sscottl (((SCSI_QUIRK(dv)->quirks & CAM_QUIRK_NOHILUNS) == 0) \ 114195534Sscottl && ((SCSI_QUIRK(dv)->quirks & CAM_QUIRK_HILUNS) \ 115195534Sscottl || (SID_ANSI_REV(&dv->inq_data) > SCSI_REV_2 && cam_srch_hi))) 116195534Sscottl 117195534Sscottl#define CAN_SRCH_HI_DENSE(dv) \ 118195534Sscottl (((SCSI_QUIRK(dv)->quirks & CAM_QUIRK_NOHILUNS) == 0) \ 119195534Sscottl && ((SCSI_QUIRK(dv)->quirks & CAM_QUIRK_HILUNS) \ 120195534Sscottl || (SID_ANSI_REV(&dv->inq_data) > SCSI_REV_2))) 121195534Sscottl 122195534Sscottlstatic periph_init_t probe_periph_init; 123195534Sscottl 124195534Sscottlstatic struct periph_driver probe_driver = 125195534Sscottl{ 126195534Sscottl probe_periph_init, "probe", 127198708Smav TAILQ_HEAD_INITIALIZER(probe_driver.units), /* generation */ 0, 128198708Smav CAM_PERIPH_DRV_EARLY 129195534Sscottl}; 130195534Sscottl 131195534SscottlPERIPHDRIVER_DECLARE(probe, probe_driver); 132195534Sscottl 133195534Sscottltypedef enum { 134195534Sscottl PROBE_TUR, 135195534Sscottl PROBE_INQUIRY, /* this counts as DV0 for Basic Domain Validation */ 136195534Sscottl PROBE_FULL_INQUIRY, 137208911Smjacob PROBE_REPORT_LUNS, 138195534Sscottl PROBE_MODE_SENSE, 139216088Sken PROBE_SUPPORTED_VPD_LIST, 140216088Sken PROBE_DEVICE_ID, 141278228Sken PROBE_EXTENDED_INQUIRY, 142216088Sken PROBE_SERIAL_NUM, 143195534Sscottl PROBE_TUR_FOR_NEGOTIATION, 144195534Sscottl PROBE_INQUIRY_BASIC_DV1, 145195534Sscottl PROBE_INQUIRY_BASIC_DV2, 146195534Sscottl PROBE_DV_EXIT, 147236613Smav PROBE_DONE, 148195534Sscottl PROBE_INVALID 149195534Sscottl} probe_action; 150195534Sscottl 151195534Sscottlstatic char *probe_action_text[] = { 152195534Sscottl "PROBE_TUR", 153195534Sscottl "PROBE_INQUIRY", 154195534Sscottl "PROBE_FULL_INQUIRY", 155208911Smjacob "PROBE_REPORT_LUNS", 156195534Sscottl "PROBE_MODE_SENSE", 157216088Sken "PROBE_SUPPORTED_VPD_LIST", 158216088Sken "PROBE_DEVICE_ID", 159278228Sken "PROBE_EXTENDED_INQUIRY", 160216088Sken "PROBE_SERIAL_NUM", 161195534Sscottl "PROBE_TUR_FOR_NEGOTIATION", 162195534Sscottl "PROBE_INQUIRY_BASIC_DV1", 163195534Sscottl "PROBE_INQUIRY_BASIC_DV2", 164195534Sscottl "PROBE_DV_EXIT", 165236613Smav "PROBE_DONE", 166195534Sscottl "PROBE_INVALID" 167195534Sscottl}; 168195534Sscottl 169195534Sscottl#define PROBE_SET_ACTION(softc, newaction) \ 170195534Sscottldo { \ 171195534Sscottl char **text; \ 172195534Sscottl text = probe_action_text; \ 173236613Smav CAM_DEBUG((softc)->periph->path, CAM_DEBUG_PROBE, \ 174195534Sscottl ("Probe %s to %s\n", text[(softc)->action], \ 175195534Sscottl text[(newaction)])); \ 176195534Sscottl (softc)->action = (newaction); \ 177195534Sscottl} while(0) 178195534Sscottl 179195534Sscottltypedef enum { 180195534Sscottl PROBE_INQUIRY_CKSUM = 0x01, 181195534Sscottl PROBE_SERIAL_CKSUM = 0x02, 182257345Snwhitehorn PROBE_NO_ANNOUNCE = 0x04, 183257345Snwhitehorn PROBE_EXTLUN = 0x08 184195534Sscottl} probe_flags; 185195534Sscottl 186195534Sscottltypedef struct { 187195534Sscottl TAILQ_HEAD(, ccb_hdr) request_ccbs; 188195534Sscottl probe_action action; 189195534Sscottl union ccb saved_ccb; 190195534Sscottl probe_flags flags; 191195534Sscottl MD5_CTX context; 192195534Sscottl u_int8_t digest[16]; 193195534Sscottl struct cam_periph *periph; 194195534Sscottl} probe_softc; 195195534Sscottl 196195534Sscottlstatic const char quantum[] = "QUANTUM"; 197195534Sscottlstatic const char sony[] = "SONY"; 198195534Sscottlstatic const char west_digital[] = "WDIGTL"; 199195534Sscottlstatic const char samsung[] = "SAMSUNG"; 200195534Sscottlstatic const char seagate[] = "SEAGATE"; 201195534Sscottlstatic const char microp[] = "MICROP"; 202195534Sscottl 203195534Sscottlstatic struct scsi_quirk_entry scsi_quirk_table[] = 204195534Sscottl{ 205195534Sscottl { 206195534Sscottl /* Reports QUEUE FULL for temporary resource shortages */ 207195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, quantum, "XP39100*", "*" }, 208195534Sscottl /*quirks*/0, /*mintags*/24, /*maxtags*/32 209195534Sscottl }, 210195534Sscottl { 211195534Sscottl /* Reports QUEUE FULL for temporary resource shortages */ 212195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, quantum, "XP34550*", "*" }, 213195534Sscottl /*quirks*/0, /*mintags*/24, /*maxtags*/32 214195534Sscottl }, 215195534Sscottl { 216195534Sscottl /* Reports QUEUE FULL for temporary resource shortages */ 217195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, quantum, "XP32275*", "*" }, 218195534Sscottl /*quirks*/0, /*mintags*/24, /*maxtags*/32 219195534Sscottl }, 220195534Sscottl { 221195534Sscottl /* Broken tagged queuing drive */ 222195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, microp, "4421-07*", "*" }, 223195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 224195534Sscottl }, 225195534Sscottl { 226195534Sscottl /* Broken tagged queuing drive */ 227195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "HP", "C372*", "*" }, 228195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 229195534Sscottl }, 230195534Sscottl { 231195534Sscottl /* Broken tagged queuing drive */ 232195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, microp, "3391*", "x43h" }, 233195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 234195534Sscottl }, 235195534Sscottl { 236195534Sscottl /* 237195534Sscottl * Unfortunately, the Quantum Atlas III has the same 238195534Sscottl * problem as the Atlas II drives above. 239195534Sscottl * Reported by: "Johan Granlund" <johan@granlund.nu> 240195534Sscottl * 241195534Sscottl * For future reference, the drive with the problem was: 242195534Sscottl * QUANTUM QM39100TD-SW N1B0 243195534Sscottl * 244195534Sscottl * It's possible that Quantum will fix the problem in later 245195534Sscottl * firmware revisions. If that happens, the quirk entry 246195534Sscottl * will need to be made specific to the firmware revisions 247195534Sscottl * with the problem. 248195534Sscottl * 249195534Sscottl */ 250195534Sscottl /* Reports QUEUE FULL for temporary resource shortages */ 251195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, quantum, "QM39100*", "*" }, 252195534Sscottl /*quirks*/0, /*mintags*/24, /*maxtags*/32 253195534Sscottl }, 254195534Sscottl { 255195534Sscottl /* 256195534Sscottl * 18 Gig Atlas III, same problem as the 9G version. 257195534Sscottl * Reported by: Andre Albsmeier 258195534Sscottl * <andre.albsmeier@mchp.siemens.de> 259195534Sscottl * 260195534Sscottl * For future reference, the drive with the problem was: 261195534Sscottl * QUANTUM QM318000TD-S N491 262195534Sscottl */ 263195534Sscottl /* Reports QUEUE FULL for temporary resource shortages */ 264195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, quantum, "QM318000*", "*" }, 265195534Sscottl /*quirks*/0, /*mintags*/24, /*maxtags*/32 266195534Sscottl }, 267195534Sscottl { 268195534Sscottl /* 269195534Sscottl * Broken tagged queuing drive 270195534Sscottl * Reported by: Bret Ford <bford@uop.cs.uop.edu> 271195534Sscottl * and: Martin Renters <martin@tdc.on.ca> 272195534Sscottl */ 273195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST410800*", "71*" }, 274195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 275195534Sscottl }, 276195534Sscottl /* 277195534Sscottl * The Seagate Medalist Pro drives have very poor write 278195534Sscottl * performance with anything more than 2 tags. 279195534Sscottl * 280195534Sscottl * Reported by: Paul van der Zwan <paulz@trantor.xs4all.nl> 281195534Sscottl * Drive: <SEAGATE ST36530N 1444> 282195534Sscottl * 283195534Sscottl * Reported by: Jeremy Lea <reg@shale.csir.co.za> 284195534Sscottl * Drive: <SEAGATE ST34520W 1281> 285195534Sscottl * 286195534Sscottl * No one has actually reported that the 9G version 287195534Sscottl * (ST39140*) of the Medalist Pro has the same problem, but 288195534Sscottl * we're assuming that it does because the 4G and 6.5G 289195534Sscottl * versions of the drive are broken. 290195534Sscottl */ 291195534Sscottl { 292195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST34520*", "*"}, 293195534Sscottl /*quirks*/0, /*mintags*/2, /*maxtags*/2 294195534Sscottl }, 295195534Sscottl { 296195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST36530*", "*"}, 297195534Sscottl /*quirks*/0, /*mintags*/2, /*maxtags*/2 298195534Sscottl }, 299195534Sscottl { 300195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST39140*", "*"}, 301195534Sscottl /*quirks*/0, /*mintags*/2, /*maxtags*/2 302195534Sscottl }, 303195534Sscottl { 304195534Sscottl /* 305231745Sgibbs * Experiences command timeouts under load with a 306231745Sgibbs * tag count higher than 55. 307231745Sgibbs */ 308231745Sgibbs { T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST3146855LW", "*"}, 309231745Sgibbs /*quirks*/0, /*mintags*/2, /*maxtags*/55 310231745Sgibbs }, 311231745Sgibbs { 312231745Sgibbs /* 313195534Sscottl * Slow when tagged queueing is enabled. Write performance 314195534Sscottl * steadily drops off with more and more concurrent 315195534Sscottl * transactions. Best sequential write performance with 316195534Sscottl * tagged queueing turned off and write caching turned on. 317195534Sscottl * 318195534Sscottl * PR: kern/10398 319195534Sscottl * Submitted by: Hideaki Okada <hokada@isl.melco.co.jp> 320195534Sscottl * Drive: DCAS-34330 w/ "S65A" firmware. 321195534Sscottl * 322195534Sscottl * The drive with the problem had the "S65A" firmware 323195534Sscottl * revision, and has also been reported (by Stephen J. 324195534Sscottl * Roznowski <sjr@home.net>) for a drive with the "S61A" 325195534Sscottl * firmware revision. 326195534Sscottl * 327195534Sscottl * Although no one has reported problems with the 2 gig 328195534Sscottl * version of the DCAS drive, the assumption is that it 329195534Sscottl * has the same problems as the 4 gig version. Therefore 330195534Sscottl * this quirk entries disables tagged queueing for all 331195534Sscottl * DCAS drives. 332195534Sscottl */ 333195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "IBM", "DCAS*", "*" }, 334195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 335195534Sscottl }, 336195534Sscottl { 337195534Sscottl /* Broken tagged queuing drive */ 338195534Sscottl { T_DIRECT, SIP_MEDIA_REMOVABLE, "iomega", "jaz*", "*" }, 339195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 340195534Sscottl }, 341195534Sscottl { 342195534Sscottl /* Broken tagged queuing drive */ 343195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "CONNER", "CFP2107*", "*" }, 344195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 345195534Sscottl }, 346195534Sscottl { 347195534Sscottl /* This does not support other than LUN 0 */ 348195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "VMware*", "*", "*" }, 349195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/2, /*maxtags*/255 350195534Sscottl }, 351195534Sscottl { 352195534Sscottl /* 353195534Sscottl * Broken tagged queuing drive. 354195534Sscottl * Submitted by: 355195534Sscottl * NAKAJI Hiroyuki <nakaji@zeisei.dpri.kyoto-u.ac.jp> 356195534Sscottl * in PR kern/9535 357195534Sscottl */ 358195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, samsung, "WN34324U*", "*" }, 359195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 360195534Sscottl }, 361195534Sscottl { 362195534Sscottl /* 363195534Sscottl * Slow when tagged queueing is enabled. (1.5MB/sec versus 364195534Sscottl * 8MB/sec.) 365195534Sscottl * Submitted by: Andrew Gallatin <gallatin@cs.duke.edu> 366195534Sscottl * Best performance with these drives is achieved with 367195534Sscottl * tagged queueing turned off, and write caching turned on. 368195534Sscottl */ 369195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, west_digital, "WDE*", "*" }, 370195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 371195534Sscottl }, 372195534Sscottl { 373195534Sscottl /* 374195534Sscottl * Slow when tagged queueing is enabled. (1.5MB/sec versus 375195534Sscottl * 8MB/sec.) 376195534Sscottl * Submitted by: Andrew Gallatin <gallatin@cs.duke.edu> 377195534Sscottl * Best performance with these drives is achieved with 378195534Sscottl * tagged queueing turned off, and write caching turned on. 379195534Sscottl */ 380195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, west_digital, "ENTERPRISE", "*" }, 381195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 382195534Sscottl }, 383195534Sscottl { 384195534Sscottl /* 385195534Sscottl * Doesn't handle queue full condition correctly, 386195534Sscottl * so we need to limit maxtags to what the device 387195534Sscottl * can handle instead of determining this automatically. 388195534Sscottl */ 389195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, samsung, "WN321010S*", "*" }, 390195534Sscottl /*quirks*/0, /*mintags*/2, /*maxtags*/32 391195534Sscottl }, 392195534Sscottl { 393195534Sscottl /* Really only one LUN */ 394195534Sscottl { T_ENCLOSURE, SIP_MEDIA_FIXED, "SUN", "SENA", "*" }, 395195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 396195534Sscottl }, 397195534Sscottl { 398195534Sscottl /* I can't believe we need a quirk for DPT volumes. */ 399195534Sscottl { T_ANY, SIP_MEDIA_FIXED|SIP_MEDIA_REMOVABLE, "DPT", "*", "*" }, 400195534Sscottl CAM_QUIRK_NOLUNS, 401195534Sscottl /*mintags*/0, /*maxtags*/255 402195534Sscottl }, 403195534Sscottl { 404195534Sscottl /* 405195534Sscottl * Many Sony CDROM drives don't like multi-LUN probing. 406195534Sscottl */ 407195534Sscottl { T_CDROM, SIP_MEDIA_REMOVABLE, sony, "CD-ROM CDU*", "*" }, 408195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 409195534Sscottl }, 410195534Sscottl { 411195534Sscottl /* 412195534Sscottl * This drive doesn't like multiple LUN probing. 413195534Sscottl * Submitted by: Parag Patel <parag@cgt.com> 414195534Sscottl */ 415195534Sscottl { T_WORM, SIP_MEDIA_REMOVABLE, sony, "CD-R CDU9*", "*" }, 416195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 417195534Sscottl }, 418195534Sscottl { 419195534Sscottl { T_WORM, SIP_MEDIA_REMOVABLE, "YAMAHA", "CDR100*", "*" }, 420195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 421195534Sscottl }, 422195534Sscottl { 423195534Sscottl /* 424195534Sscottl * The 8200 doesn't like multi-lun probing, and probably 425195534Sscottl * don't like serial number requests either. 426195534Sscottl */ 427195534Sscottl { 428195534Sscottl T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "EXABYTE", 429195534Sscottl "EXB-8200*", "*" 430195534Sscottl }, 431195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 432195534Sscottl }, 433195534Sscottl { 434195534Sscottl /* 435195534Sscottl * Let's try the same as above, but for a drive that says 436195534Sscottl * it's an IPL-6860 but is actually an EXB 8200. 437195534Sscottl */ 438195534Sscottl { 439195534Sscottl T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "EXABYTE", 440195534Sscottl "IPL-6860*", "*" 441195534Sscottl }, 442195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 443195534Sscottl }, 444195534Sscottl { 445195534Sscottl /* 446195534Sscottl * These Hitachi drives don't like multi-lun probing. 447195534Sscottl * The PR submitter has a DK319H, but says that the Linux 448195534Sscottl * kernel has a similar work-around for the DK312 and DK314, 449195534Sscottl * so all DK31* drives are quirked here. 450195534Sscottl * PR: misc/18793 451195534Sscottl * Submitted by: Paul Haddad <paul@pth.com> 452195534Sscottl */ 453195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "HITACHI", "DK31*", "*" }, 454195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/2, /*maxtags*/255 455195534Sscottl }, 456195534Sscottl { 457195534Sscottl /* 458298810Spfg * The Hitachi CJ series with J8A8 firmware apparently has 459195534Sscottl * problems with tagged commands. 460195534Sscottl * PR: 23536 461195534Sscottl * Reported by: amagai@nue.org 462195534Sscottl */ 463195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "HITACHI", "DK32CJ*", "J8A8" }, 464195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 465195534Sscottl }, 466195534Sscottl { 467195534Sscottl /* 468195534Sscottl * These are the large storage arrays. 469195534Sscottl * Submitted by: William Carrel <william.carrel@infospace.com> 470195534Sscottl */ 471195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "HITACHI", "OPEN*", "*" }, 472195534Sscottl CAM_QUIRK_HILUNS, 2, 1024 473195534Sscottl }, 474195534Sscottl { 475195534Sscottl /* 476195534Sscottl * This old revision of the TDC3600 is also SCSI-1, and 477195534Sscottl * hangs upon serial number probing. 478195534Sscottl */ 479195534Sscottl { 480195534Sscottl T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG", 481195534Sscottl " TDC 3600", "U07:" 482195534Sscottl }, 483216088Sken CAM_QUIRK_NOVPDS, /*mintags*/0, /*maxtags*/0 484195534Sscottl }, 485195534Sscottl { 486195534Sscottl /* 487195534Sscottl * Would repond to all LUNs if asked for. 488195534Sscottl */ 489195534Sscottl { 490195534Sscottl T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "CALIPER", 491195534Sscottl "CP150", "*" 492195534Sscottl }, 493195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 494195534Sscottl }, 495195534Sscottl { 496195534Sscottl /* 497195534Sscottl * Would repond to all LUNs if asked for. 498195534Sscottl */ 499195534Sscottl { 500195534Sscottl T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "KENNEDY", 501195534Sscottl "96X2*", "*" 502195534Sscottl }, 503195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 504195534Sscottl }, 505195534Sscottl { 506195534Sscottl /* Submitted by: Matthew Dodd <winter@jurai.net> */ 507195534Sscottl { T_PROCESSOR, SIP_MEDIA_FIXED, "Cabletrn", "EA41*", "*" }, 508195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 509195534Sscottl }, 510195534Sscottl { 511195534Sscottl /* Submitted by: Matthew Dodd <winter@jurai.net> */ 512195534Sscottl { T_PROCESSOR, SIP_MEDIA_FIXED, "CABLETRN", "EA41*", "*" }, 513195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 514195534Sscottl }, 515195534Sscottl { 516195534Sscottl /* TeraSolutions special settings for TRC-22 RAID */ 517195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "TERASOLU", "TRC-22", "*" }, 518195534Sscottl /*quirks*/0, /*mintags*/55, /*maxtags*/255 519195534Sscottl }, 520195534Sscottl { 521195534Sscottl /* Veritas Storage Appliance */ 522195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "VERITAS", "*", "*" }, 523195534Sscottl CAM_QUIRK_HILUNS, /*mintags*/2, /*maxtags*/1024 524195534Sscottl }, 525195534Sscottl { 526195534Sscottl /* 527195534Sscottl * Would respond to all LUNs. Device type and removable 528195534Sscottl * flag are jumper-selectable. 529195534Sscottl */ 530195534Sscottl { T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED, "MaxOptix", 531195534Sscottl "Tahiti 1", "*" 532195534Sscottl }, 533195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 534195534Sscottl }, 535195534Sscottl { 536195534Sscottl /* EasyRAID E5A aka. areca ARC-6010 */ 537195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "easyRAID", "*", "*" }, 538195534Sscottl CAM_QUIRK_NOHILUNS, /*mintags*/2, /*maxtags*/255 539195534Sscottl }, 540195534Sscottl { 541195534Sscottl { T_ENCLOSURE, SIP_MEDIA_FIXED, "DP", "BACKPLANE", "*" }, 542195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 543195534Sscottl }, 544195534Sscottl { 545236283Seadler { T_DIRECT, SIP_MEDIA_REMOVABLE, "Garmin", "*", "*" }, 546236283Seadler CAM_QUIRK_NORPTLUNS, /*mintags*/2, /*maxtags*/255 547236283Seadler }, 548236283Seadler { 549331044Seadler { T_DIRECT, SIP_MEDIA_REMOVABLE, "Generic", "STORAGE DEVICE*", "120?" }, 550331044Seadler CAM_QUIRK_NORPTLUNS, /*mintags*/2, /*maxtags*/255 551331044Seadler }, 552331044Seadler { 553331044Seadler { T_DIRECT, SIP_MEDIA_REMOVABLE, "Generic", "MassStorageClass", "1533" }, 554331044Seadler CAM_QUIRK_NORPTLUNS, /*mintags*/2, /*maxtags*/255 555331044Seadler }, 556331044Seadler { 557195534Sscottl /* Default tagged queuing parameters for all devices */ 558195534Sscottl { 559195534Sscottl T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED, 560195534Sscottl /*vendor*/"*", /*product*/"*", /*revision*/"*" 561195534Sscottl }, 562195534Sscottl /*quirks*/0, /*mintags*/2, /*maxtags*/255 563195534Sscottl }, 564195534Sscottl}; 565195534Sscottl 566195534Sscottlstatic cam_status proberegister(struct cam_periph *periph, 567195534Sscottl void *arg); 568195534Sscottlstatic void probeschedule(struct cam_periph *probe_periph); 569195534Sscottlstatic void probestart(struct cam_periph *periph, union ccb *start_ccb); 570195534Sscottlstatic void proberequestdefaultnegotiation(struct cam_periph *periph); 571195534Sscottlstatic int proberequestbackoff(struct cam_periph *periph, 572195534Sscottl struct cam_ed *device); 573195534Sscottlstatic void probedone(struct cam_periph *periph, union ccb *done_ccb); 574208911Smjacobstatic void probe_purge_old(struct cam_path *path, 575257345Snwhitehorn struct scsi_report_luns_data *new, 576257345Snwhitehorn probe_flags flags); 577195534Sscottlstatic void probecleanup(struct cam_periph *periph); 578195534Sscottlstatic void scsi_find_quirk(struct cam_ed *device); 579195534Sscottlstatic void scsi_scan_bus(struct cam_periph *periph, union ccb *ccb); 580195534Sscottlstatic void scsi_scan_lun(struct cam_periph *periph, 581195534Sscottl struct cam_path *path, cam_flags flags, 582195534Sscottl union ccb *ccb); 583195534Sscottlstatic void xptscandone(struct cam_periph *periph, union ccb *done_ccb); 584195534Sscottlstatic struct cam_ed * 585195534Sscottl scsi_alloc_device(struct cam_eb *bus, struct cam_et *target, 586195534Sscottl lun_id_t lun_id); 587195534Sscottlstatic void scsi_devise_transport(struct cam_path *path); 588195534Sscottlstatic void scsi_set_transfer_settings(struct ccb_trans_settings *cts, 589256843Smav struct cam_path *path, 590195534Sscottl int async_update); 591195534Sscottlstatic void scsi_toggle_tags(struct cam_path *path); 592195534Sscottlstatic void scsi_dev_async(u_int32_t async_code, 593195534Sscottl struct cam_eb *bus, 594195534Sscottl struct cam_et *target, 595195534Sscottl struct cam_ed *device, 596195534Sscottl void *async_arg); 597195534Sscottlstatic void scsi_action(union ccb *start_ccb); 598204220Smavstatic void scsi_announce_periph(struct cam_periph *periph); 599328820Smavstatic void scsi_proto_announce(struct cam_ed *device); 600328820Smavstatic void scsi_proto_denounce(struct cam_ed *device); 601328820Smavstatic void scsi_proto_debug_out(union ccb *ccb); 602195534Sscottl 603328819Smavstatic struct xpt_xport_ops scsi_xport_ops = { 604195534Sscottl .alloc_device = scsi_alloc_device, 605195534Sscottl .action = scsi_action, 606195534Sscottl .async = scsi_dev_async, 607204220Smav .announce = scsi_announce_periph, 608195534Sscottl}; 609328819Smav#define SCSI_XPT_XPORT(x, X) \ 610328819Smavstatic struct xpt_xport scsi_xport_ ## x = { \ 611328819Smav .xport = XPORT_ ## X, \ 612328819Smav .name = #x, \ 613328819Smav .ops = &scsi_xport_ops, \ 614328819Smav}; \ 615328819SmavCAM_XPT_XPORT(scsi_xport_ ## x); 616195534Sscottl 617328819SmavSCSI_XPT_XPORT(spi, SPI); 618328819SmavSCSI_XPT_XPORT(sas, SAS); 619328819SmavSCSI_XPT_XPORT(fc, FC); 620328819SmavSCSI_XPT_XPORT(usb, USB); 621328819SmavSCSI_XPT_XPORT(iscsi, ISCSI); 622328819SmavSCSI_XPT_XPORT(srp, SRP); 623328819SmavSCSI_XPT_XPORT(ppb, PPB); 624195534Sscottl 625328819Smav#undef SCSI_XPORT_XPORT 626328819Smav 627328820Smavstatic struct xpt_proto_ops scsi_proto_ops = { 628328820Smav .announce = scsi_proto_announce, 629328820Smav .denounce = scsi_proto_denounce, 630328820Smav .debug_out = scsi_proto_debug_out, 631328820Smav}; 632328820Smavstatic struct xpt_proto scsi_proto = { 633328820Smav .proto = PROTO_SCSI, 634328820Smav .name = "scsi", 635328820Smav .ops = &scsi_proto_ops, 636328820Smav}; 637328820SmavCAM_XPT_PROTO(scsi_proto); 638328820Smav 639195534Sscottlstatic void 640195534Sscottlprobe_periph_init() 641195534Sscottl{ 642195534Sscottl} 643195534Sscottl 644195534Sscottlstatic cam_status 645195534Sscottlproberegister(struct cam_periph *periph, void *arg) 646195534Sscottl{ 647195534Sscottl union ccb *request_ccb; /* CCB representing the probe request */ 648195534Sscottl cam_status status; 649195534Sscottl probe_softc *softc; 650195534Sscottl 651195534Sscottl request_ccb = (union ccb *)arg; 652195534Sscottl if (request_ccb == NULL) { 653195534Sscottl printf("proberegister: no probe CCB, " 654195534Sscottl "can't register device\n"); 655195534Sscottl return(CAM_REQ_CMP_ERR); 656195534Sscottl } 657195534Sscottl 658195534Sscottl softc = (probe_softc *)malloc(sizeof(*softc), M_CAMXPT, M_NOWAIT); 659195534Sscottl 660195534Sscottl if (softc == NULL) { 661195534Sscottl printf("proberegister: Unable to probe new device. " 662195534Sscottl "Unable to allocate softc\n"); 663195534Sscottl return(CAM_REQ_CMP_ERR); 664195534Sscottl } 665195534Sscottl TAILQ_INIT(&softc->request_ccbs); 666195534Sscottl TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h, 667195534Sscottl periph_links.tqe); 668195534Sscottl softc->flags = 0; 669195534Sscottl periph->softc = softc; 670195534Sscottl softc->periph = periph; 671195534Sscottl softc->action = PROBE_INVALID; 672195534Sscottl status = cam_periph_acquire(periph); 673195534Sscottl if (status != CAM_REQ_CMP) { 674195534Sscottl return (status); 675195534Sscottl } 676236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe started\n")); 677256843Smav scsi_devise_transport(periph->path); 678195534Sscottl 679195534Sscottl /* 680195534Sscottl * Ensure we've waited at least a bus settle 681195534Sscottl * delay before attempting to probe the device. 682195534Sscottl * For HBAs that don't do bus resets, this won't make a difference. 683195534Sscottl */ 684195534Sscottl cam_periph_freeze_after_event(periph, &periph->path->bus->last_reset, 685195534Sscottl scsi_delay); 686195534Sscottl probeschedule(periph); 687195534Sscottl return(CAM_REQ_CMP); 688195534Sscottl} 689195534Sscottl 690195534Sscottlstatic void 691195534Sscottlprobeschedule(struct cam_periph *periph) 692195534Sscottl{ 693195534Sscottl struct ccb_pathinq cpi; 694195534Sscottl union ccb *ccb; 695195534Sscottl probe_softc *softc; 696195534Sscottl 697195534Sscottl softc = (probe_softc *)periph->softc; 698195534Sscottl ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs); 699195534Sscottl 700350804Smav xpt_path_inq(&cpi, periph->path); 701195534Sscottl 702195534Sscottl /* 703195534Sscottl * If a device has gone away and another device, or the same one, 704195534Sscottl * is back in the same place, it should have a unit attention 705195534Sscottl * condition pending. It will not report the unit attention in 706195534Sscottl * response to an inquiry, which may leave invalid transfer 707195534Sscottl * negotiations in effect. The TUR will reveal the unit attention 708195534Sscottl * condition. Only send the TUR for lun 0, since some devices 709195534Sscottl * will get confused by commands other than inquiry to non-existent 710195534Sscottl * luns. If you think a device has gone away start your scan from 711195534Sscottl * lun 0. This will insure that any bogus transfer settings are 712195534Sscottl * invalidated. 713195534Sscottl * 714195534Sscottl * If we haven't seen the device before and the controller supports 715195534Sscottl * some kind of transfer negotiation, negotiate with the first 716195534Sscottl * sent command if no bus reset was performed at startup. This 717195534Sscottl * ensures that the device is not confused by transfer negotiation 718195534Sscottl * settings left over by loader or BIOS action. 719195534Sscottl */ 720195534Sscottl if (((ccb->ccb_h.path->device->flags & CAM_DEV_UNCONFIGURED) == 0) 721195534Sscottl && (ccb->ccb_h.target_lun == 0)) { 722195534Sscottl PROBE_SET_ACTION(softc, PROBE_TUR); 723195534Sscottl } else if ((cpi.hba_inquiry & (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE)) != 0 724195534Sscottl && (cpi.hba_misc & PIM_NOBUSRESET) != 0) { 725195534Sscottl proberequestdefaultnegotiation(periph); 726195534Sscottl PROBE_SET_ACTION(softc, PROBE_INQUIRY); 727195534Sscottl } else { 728195534Sscottl PROBE_SET_ACTION(softc, PROBE_INQUIRY); 729195534Sscottl } 730195534Sscottl 731195534Sscottl if (ccb->crcn.flags & CAM_EXPECT_INQ_CHANGE) 732195534Sscottl softc->flags |= PROBE_NO_ANNOUNCE; 733195534Sscottl else 734195534Sscottl softc->flags &= ~PROBE_NO_ANNOUNCE; 735195534Sscottl 736257345Snwhitehorn if (cpi.hba_misc & PIM_EXTLUNS) 737257345Snwhitehorn softc->flags |= PROBE_EXTLUN; 738257345Snwhitehorn else 739257345Snwhitehorn softc->flags &= ~PROBE_EXTLUN; 740257345Snwhitehorn 741203108Smav xpt_schedule(periph, CAM_PRIORITY_XPT); 742195534Sscottl} 743195534Sscottl 744195534Sscottlstatic void 745195534Sscottlprobestart(struct cam_periph *periph, union ccb *start_ccb) 746195534Sscottl{ 747195534Sscottl /* Probe the device that our peripheral driver points to */ 748195534Sscottl struct ccb_scsiio *csio; 749195534Sscottl probe_softc *softc; 750195534Sscottl 751195534Sscottl CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probestart\n")); 752195534Sscottl 753195534Sscottl softc = (probe_softc *)periph->softc; 754195534Sscottl csio = &start_ccb->csio; 755208911Smjacobagain: 756195534Sscottl 757195534Sscottl switch (softc->action) { 758195534Sscottl case PROBE_TUR: 759195534Sscottl case PROBE_TUR_FOR_NEGOTIATION: 760195534Sscottl case PROBE_DV_EXIT: 761195534Sscottl { 762195534Sscottl scsi_test_unit_ready(csio, 763236814Smav /*retries*/4, 764195534Sscottl probedone, 765195534Sscottl MSG_SIMPLE_Q_TAG, 766195534Sscottl SSD_FULL_SIZE, 767195534Sscottl /*timeout*/60000); 768195534Sscottl break; 769195534Sscottl } 770195534Sscottl case PROBE_INQUIRY: 771195534Sscottl case PROBE_FULL_INQUIRY: 772195534Sscottl case PROBE_INQUIRY_BASIC_DV1: 773195534Sscottl case PROBE_INQUIRY_BASIC_DV2: 774195534Sscottl { 775195534Sscottl u_int inquiry_len; 776195534Sscottl struct scsi_inquiry_data *inq_buf; 777195534Sscottl 778195534Sscottl inq_buf = &periph->path->device->inq_data; 779195534Sscottl 780195534Sscottl /* 781195534Sscottl * If the device is currently configured, we calculate an 782195534Sscottl * MD5 checksum of the inquiry data, and if the serial number 783195534Sscottl * length is greater than 0, add the serial number data 784195534Sscottl * into the checksum as well. Once the inquiry and the 785195534Sscottl * serial number check finish, we attempt to figure out 786195534Sscottl * whether we still have the same device. 787195534Sscottl */ 788276831Sken if (((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) 789276831Sken && ((softc->flags & PROBE_INQUIRY_CKSUM) == 0)) { 790195534Sscottl 791195534Sscottl MD5Init(&softc->context); 792195534Sscottl MD5Update(&softc->context, (unsigned char *)inq_buf, 793195534Sscottl sizeof(struct scsi_inquiry_data)); 794195534Sscottl softc->flags |= PROBE_INQUIRY_CKSUM; 795195534Sscottl if (periph->path->device->serial_num_len > 0) { 796195534Sscottl MD5Update(&softc->context, 797195534Sscottl periph->path->device->serial_num, 798195534Sscottl periph->path->device->serial_num_len); 799195534Sscottl softc->flags |= PROBE_SERIAL_CKSUM; 800195534Sscottl } 801195534Sscottl MD5Final(softc->digest, &softc->context); 802195534Sscottl } 803195534Sscottl 804195534Sscottl if (softc->action == PROBE_INQUIRY) 805195534Sscottl inquiry_len = SHORT_INQUIRY_LENGTH; 806195534Sscottl else 807195534Sscottl inquiry_len = SID_ADDITIONAL_LENGTH(inq_buf); 808195534Sscottl 809195534Sscottl /* 810195534Sscottl * Some parallel SCSI devices fail to send an 811195534Sscottl * ignore wide residue message when dealing with 812195534Sscottl * odd length inquiry requests. Round up to be 813195534Sscottl * safe. 814195534Sscottl */ 815195534Sscottl inquiry_len = roundup2(inquiry_len, 2); 816195534Sscottl 817195534Sscottl if (softc->action == PROBE_INQUIRY_BASIC_DV1 818195534Sscottl || softc->action == PROBE_INQUIRY_BASIC_DV2) { 819195534Sscottl inq_buf = malloc(inquiry_len, M_CAMXPT, M_NOWAIT); 820195534Sscottl } 821195534Sscottl if (inq_buf == NULL) { 822195534Sscottl xpt_print(periph->path, "malloc failure- skipping Basic" 823195534Sscottl "Domain Validation\n"); 824195534Sscottl PROBE_SET_ACTION(softc, PROBE_DV_EXIT); 825195534Sscottl scsi_test_unit_ready(csio, 826195534Sscottl /*retries*/4, 827195534Sscottl probedone, 828195534Sscottl MSG_SIMPLE_Q_TAG, 829195534Sscottl SSD_FULL_SIZE, 830195534Sscottl /*timeout*/60000); 831195534Sscottl break; 832195534Sscottl } 833195534Sscottl scsi_inquiry(csio, 834195534Sscottl /*retries*/4, 835195534Sscottl probedone, 836195534Sscottl MSG_SIMPLE_Q_TAG, 837195534Sscottl (u_int8_t *)inq_buf, 838195534Sscottl inquiry_len, 839195534Sscottl /*evpd*/FALSE, 840195534Sscottl /*page_code*/0, 841195534Sscottl SSD_MIN_SIZE, 842195534Sscottl /*timeout*/60 * 1000); 843195534Sscottl break; 844195534Sscottl } 845208911Smjacob case PROBE_REPORT_LUNS: 846208911Smjacob { 847208911Smjacob void *rp; 848208911Smjacob 849208911Smjacob rp = malloc(periph->path->target->rpl_size, 850208911Smjacob M_CAMXPT, M_NOWAIT | M_ZERO); 851208911Smjacob if (rp == NULL) { 852208911Smjacob struct scsi_inquiry_data *inq_buf; 853208911Smjacob inq_buf = &periph->path->device->inq_data; 854208911Smjacob xpt_print(periph->path, 855208911Smjacob "Unable to alloc report luns storage\n"); 856208911Smjacob if (INQ_DATA_TQ_ENABLED(inq_buf)) 857208911Smjacob PROBE_SET_ACTION(softc, PROBE_MODE_SENSE); 858208911Smjacob else 859216088Sken PROBE_SET_ACTION(softc, 860216088Sken PROBE_SUPPORTED_VPD_LIST); 861208911Smjacob goto again; 862208911Smjacob } 863208911Smjacob scsi_report_luns(csio, 5, probedone, MSG_SIMPLE_Q_TAG, 864208911Smjacob RPL_REPORT_DEFAULT, rp, periph->path->target->rpl_size, 865208911Smjacob SSD_FULL_SIZE, 60000); break; 866208911Smjacob break; 867208911Smjacob } 868195534Sscottl case PROBE_MODE_SENSE: 869195534Sscottl { 870195534Sscottl void *mode_buf; 871195534Sscottl int mode_buf_len; 872195534Sscottl 873195534Sscottl mode_buf_len = sizeof(struct scsi_mode_header_6) 874195534Sscottl + sizeof(struct scsi_mode_blk_desc) 875195534Sscottl + sizeof(struct scsi_control_page); 876195534Sscottl mode_buf = malloc(mode_buf_len, M_CAMXPT, M_NOWAIT); 877195534Sscottl if (mode_buf != NULL) { 878195534Sscottl scsi_mode_sense(csio, 879195534Sscottl /*retries*/4, 880195534Sscottl probedone, 881195534Sscottl MSG_SIMPLE_Q_TAG, 882195534Sscottl /*dbd*/FALSE, 883195534Sscottl SMS_PAGE_CTRL_CURRENT, 884195534Sscottl SMS_CONTROL_MODE_PAGE, 885195534Sscottl mode_buf, 886195534Sscottl mode_buf_len, 887195534Sscottl SSD_FULL_SIZE, 888195534Sscottl /*timeout*/60000); 889195534Sscottl break; 890195534Sscottl } 891195534Sscottl xpt_print(periph->path, "Unable to mode sense control page - " 892195534Sscottl "malloc failure\n"); 893216088Sken PROBE_SET_ACTION(softc, PROBE_SUPPORTED_VPD_LIST); 894195534Sscottl } 895195534Sscottl /* FALLTHROUGH */ 896216088Sken case PROBE_SUPPORTED_VPD_LIST: 897195534Sscottl { 898216088Sken struct scsi_vpd_supported_page_list *vpd_list; 899195534Sscottl struct cam_ed *device; 900195534Sscottl 901216088Sken vpd_list = NULL; 902195534Sscottl device = periph->path->device; 903216088Sken 904216088Sken if ((SCSI_QUIRK(device)->quirks & CAM_QUIRK_NOVPDS) == 0) 905195534Sscottl vpd_list = malloc(sizeof(*vpd_list), M_CAMXPT, 906195534Sscottl M_NOWAIT | M_ZERO); 907195534Sscottl 908195534Sscottl if (vpd_list != NULL) { 909195534Sscottl scsi_inquiry(csio, 910195534Sscottl /*retries*/4, 911195534Sscottl probedone, 912195534Sscottl MSG_SIMPLE_Q_TAG, 913195534Sscottl (u_int8_t *)vpd_list, 914195534Sscottl sizeof(*vpd_list), 915195534Sscottl /*evpd*/TRUE, 916195534Sscottl SVPD_SUPPORTED_PAGE_LIST, 917195534Sscottl SSD_MIN_SIZE, 918195534Sscottl /*timeout*/60 * 1000); 919195534Sscottl break; 920195534Sscottl } 921260541Smavdone: 922195534Sscottl /* 923195534Sscottl * We'll have to do without, let our probedone 924195534Sscottl * routine finish up for us. 925195534Sscottl */ 926195534Sscottl start_ccb->csio.data_ptr = NULL; 927250025Smav cam_freeze_devq(periph->path); 928260541Smav cam_periph_doacquire(periph); 929195534Sscottl probedone(periph, start_ccb); 930195534Sscottl return; 931195534Sscottl } 932216088Sken case PROBE_DEVICE_ID: 933195534Sscottl { 934216088Sken struct scsi_vpd_device_id *devid; 935216088Sken 936216088Sken devid = NULL; 937249937Ssmh if (scsi_vpd_supported_page(periph, SVPD_DEVICE_ID)) 938216088Sken devid = malloc(SVPD_DEVICE_ID_MAX_SIZE, M_CAMXPT, 939216088Sken M_NOWAIT | M_ZERO); 940216088Sken 941216088Sken if (devid != NULL) { 942216088Sken scsi_inquiry(csio, 943216088Sken /*retries*/4, 944216088Sken probedone, 945216088Sken MSG_SIMPLE_Q_TAG, 946216088Sken (uint8_t *)devid, 947216088Sken SVPD_DEVICE_ID_MAX_SIZE, 948216088Sken /*evpd*/TRUE, 949216088Sken SVPD_DEVICE_ID, 950216088Sken SSD_MIN_SIZE, 951216088Sken /*timeout*/60 * 1000); 952216088Sken break; 953216088Sken } 954260541Smav goto done; 955216088Sken } 956278228Sken case PROBE_EXTENDED_INQUIRY: 957278228Sken { 958278228Sken struct scsi_vpd_extended_inquiry_data *ext_inq; 959278228Sken 960278228Sken ext_inq = NULL; 961278228Sken if (scsi_vpd_supported_page(periph, SVPD_EXTENDED_INQUIRY_DATA)) 962278228Sken ext_inq = malloc(sizeof(*ext_inq), M_CAMXPT, 963278228Sken M_NOWAIT | M_ZERO); 964278228Sken 965278228Sken if (ext_inq != NULL) { 966278228Sken scsi_inquiry(csio, 967278228Sken /*retries*/4, 968278228Sken probedone, 969278228Sken MSG_SIMPLE_Q_TAG, 970278228Sken (uint8_t *)ext_inq, 971278228Sken sizeof(*ext_inq), 972278228Sken /*evpd*/TRUE, 973278228Sken SVPD_EXTENDED_INQUIRY_DATA, 974278228Sken SSD_MIN_SIZE, 975278228Sken /*timeout*/60 * 1000); 976278228Sken break; 977278228Sken } 978278228Sken /* 979278228Sken * We'll have to do without, let our probedone 980278228Sken * routine finish up for us. 981278228Sken */ 982278228Sken goto done; 983278228Sken } 984216088Sken case PROBE_SERIAL_NUM: 985216088Sken { 986195534Sscottl struct scsi_vpd_unit_serial_number *serial_buf; 987195534Sscottl struct cam_ed* device; 988195534Sscottl 989195534Sscottl serial_buf = NULL; 990195534Sscottl device = periph->path->device; 991195685Semaste if (device->serial_num != NULL) { 992195685Semaste free(device->serial_num, M_CAMXPT); 993195685Semaste device->serial_num = NULL; 994195685Semaste device->serial_num_len = 0; 995195685Semaste } 996195534Sscottl 997249937Ssmh if (scsi_vpd_supported_page(periph, SVPD_UNIT_SERIAL_NUMBER)) 998216088Sken serial_buf = (struct scsi_vpd_unit_serial_number *) 999216088Sken malloc(sizeof(*serial_buf), M_CAMXPT, 1000216088Sken M_NOWAIT|M_ZERO); 1001195534Sscottl 1002195534Sscottl if (serial_buf != NULL) { 1003195534Sscottl scsi_inquiry(csio, 1004195534Sscottl /*retries*/4, 1005195534Sscottl probedone, 1006195534Sscottl MSG_SIMPLE_Q_TAG, 1007195534Sscottl (u_int8_t *)serial_buf, 1008195534Sscottl sizeof(*serial_buf), 1009195534Sscottl /*evpd*/TRUE, 1010195534Sscottl SVPD_UNIT_SERIAL_NUMBER, 1011195534Sscottl SSD_MIN_SIZE, 1012195534Sscottl /*timeout*/60 * 1000); 1013195534Sscottl break; 1014195534Sscottl } 1015260541Smav goto done; 1016195534Sscottl } 1017195534Sscottl default: 1018236613Smav panic("probestart: invalid action state 0x%x\n", softc->action); 1019195534Sscottl } 1020249466Smav start_ccb->ccb_h.flags |= CAM_DEV_QFREEZE; 1021260541Smav cam_periph_doacquire(periph); 1022195534Sscottl xpt_action(start_ccb); 1023195534Sscottl} 1024195534Sscottl 1025195534Sscottlstatic void 1026195534Sscottlproberequestdefaultnegotiation(struct cam_periph *periph) 1027195534Sscottl{ 1028195534Sscottl struct ccb_trans_settings cts; 1029195534Sscottl 1030203108Smav xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE); 1031195534Sscottl cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1032195534Sscottl cts.type = CTS_TYPE_USER_SETTINGS; 1033195534Sscottl xpt_action((union ccb *)&cts); 1034252382Sscottl if (cam_ccb_status((union ccb *)&cts) != CAM_REQ_CMP) { 1035195534Sscottl return; 1036195534Sscottl } 1037195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1038195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 1039195534Sscottl xpt_action((union ccb *)&cts); 1040195534Sscottl} 1041195534Sscottl 1042195534Sscottl/* 1043195534Sscottl * Backoff Negotiation Code- only pertinent for SPI devices. 1044195534Sscottl */ 1045195534Sscottlstatic int 1046195534Sscottlproberequestbackoff(struct cam_periph *periph, struct cam_ed *device) 1047195534Sscottl{ 1048195534Sscottl struct ccb_trans_settings cts; 1049195534Sscottl struct ccb_trans_settings_spi *spi; 1050195534Sscottl 1051195534Sscottl memset(&cts, 0, sizeof (cts)); 1052203108Smav xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE); 1053195534Sscottl cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1054195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 1055195534Sscottl xpt_action((union ccb *)&cts); 1056252382Sscottl if (cam_ccb_status((union ccb *)&cts) != CAM_REQ_CMP) { 1057195534Sscottl if (bootverbose) { 1058195534Sscottl xpt_print(periph->path, 1059195534Sscottl "failed to get current device settings\n"); 1060195534Sscottl } 1061195534Sscottl return (0); 1062195534Sscottl } 1063195534Sscottl if (cts.transport != XPORT_SPI) { 1064195534Sscottl if (bootverbose) { 1065195534Sscottl xpt_print(periph->path, "not SPI transport\n"); 1066195534Sscottl } 1067195534Sscottl return (0); 1068195534Sscottl } 1069195534Sscottl spi = &cts.xport_specific.spi; 1070195534Sscottl 1071195534Sscottl /* 1072195534Sscottl * We cannot renegotiate sync rate if we don't have one. 1073195534Sscottl */ 1074195534Sscottl if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) { 1075195534Sscottl if (bootverbose) { 1076195534Sscottl xpt_print(periph->path, "no sync rate known\n"); 1077195534Sscottl } 1078195534Sscottl return (0); 1079195534Sscottl } 1080195534Sscottl 1081195534Sscottl /* 1082195534Sscottl * We'll assert that we don't have to touch PPR options- the 1083195534Sscottl * SIM will see what we do with period and offset and adjust 1084195534Sscottl * the PPR options as appropriate. 1085195534Sscottl */ 1086195534Sscottl 1087195534Sscottl /* 1088195534Sscottl * A sync rate with unknown or zero offset is nonsensical. 1089195534Sscottl * A sync period of zero means Async. 1090195534Sscottl */ 1091195534Sscottl if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0 1092195534Sscottl || spi->sync_offset == 0 || spi->sync_period == 0) { 1093195534Sscottl if (bootverbose) { 1094195534Sscottl xpt_print(periph->path, "no sync rate available\n"); 1095195534Sscottl } 1096195534Sscottl return (0); 1097195534Sscottl } 1098195534Sscottl 1099195534Sscottl if (device->flags & CAM_DEV_DV_HIT_BOTTOM) { 1100236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, 1101195534Sscottl ("hit async: giving up on DV\n")); 1102195534Sscottl return (0); 1103195534Sscottl } 1104195534Sscottl 1105195534Sscottl 1106195534Sscottl /* 1107195534Sscottl * Jump sync_period up by one, but stop at 5MHz and fall back to Async. 1108195534Sscottl * We don't try to remember 'last' settings to see if the SIM actually 1109195534Sscottl * gets into the speed we want to set. We check on the SIM telling 1110195534Sscottl * us that a requested speed is bad, but otherwise don't try and 1111195534Sscottl * check the speed due to the asynchronous and handshake nature 1112195534Sscottl * of speed setting. 1113195534Sscottl */ 1114195534Sscottl spi->valid = CTS_SPI_VALID_SYNC_RATE | CTS_SPI_VALID_SYNC_OFFSET; 1115195534Sscottl for (;;) { 1116195534Sscottl spi->sync_period++; 1117195534Sscottl if (spi->sync_period >= 0xf) { 1118195534Sscottl spi->sync_period = 0; 1119195534Sscottl spi->sync_offset = 0; 1120236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, 1121195534Sscottl ("setting to async for DV\n")); 1122195534Sscottl /* 1123195534Sscottl * Once we hit async, we don't want to try 1124195534Sscottl * any more settings. 1125195534Sscottl */ 1126195534Sscottl device->flags |= CAM_DEV_DV_HIT_BOTTOM; 1127195534Sscottl } else if (bootverbose) { 1128236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, 1129195534Sscottl ("DV: period 0x%x\n", spi->sync_period)); 1130195534Sscottl printf("setting period to 0x%x\n", spi->sync_period); 1131195534Sscottl } 1132195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1133195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 1134195534Sscottl xpt_action((union ccb *)&cts); 1135252382Sscottl if (cam_ccb_status((union ccb *)&cts) != CAM_REQ_CMP) { 1136195534Sscottl break; 1137195534Sscottl } 1138236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, 1139195534Sscottl ("DV: failed to set period 0x%x\n", spi->sync_period)); 1140195534Sscottl if (spi->sync_period == 0) { 1141195534Sscottl return (0); 1142195534Sscottl } 1143195534Sscottl } 1144195534Sscottl return (1); 1145195534Sscottl} 1146195534Sscottl 1147216088Sken#define CCB_COMPLETED_OK(ccb) (((ccb).status & CAM_STATUS_MASK) == CAM_REQ_CMP) 1148216088Sken 1149195534Sscottlstatic void 1150195534Sscottlprobedone(struct cam_periph *periph, union ccb *done_ccb) 1151195534Sscottl{ 1152195534Sscottl probe_softc *softc; 1153195534Sscottl struct cam_path *path; 1154287289Smav struct scsi_inquiry_data *inq_buf; 1155195534Sscottl u_int32_t priority; 1156195534Sscottl 1157195534Sscottl CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probedone\n")); 1158195534Sscottl 1159195534Sscottl softc = (probe_softc *)periph->softc; 1160195534Sscottl path = done_ccb->ccb_h.path; 1161195534Sscottl priority = done_ccb->ccb_h.pinfo.priority; 1162326777Sasomers cam_periph_assert(periph, MA_OWNED); 1163195534Sscottl 1164195534Sscottl switch (softc->action) { 1165195534Sscottl case PROBE_TUR: 1166195534Sscottl { 1167252382Sscottl if (cam_ccb_status(done_ccb) != CAM_REQ_CMP) { 1168195534Sscottl 1169195534Sscottl if (cam_periph_error(done_ccb, 0, 1170249466Smav SF_NO_PRINT, NULL) == ERESTART) { 1171260547Smavoutr: 1172249466Smav /* Drop freeze taken due to CAM_DEV_QFREEZE */ 1173249466Smav cam_release_devq(path, 0, 0, 0, FALSE); 1174195534Sscottl return; 1175249466Smav } 1176195534Sscottl else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 1177195534Sscottl /* Don't wedge the queue */ 1178195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, 1179195534Sscottl /*count*/1, 1180195534Sscottl /*run_queue*/TRUE); 1181195534Sscottl } 1182195534Sscottl PROBE_SET_ACTION(softc, PROBE_INQUIRY); 1183195534Sscottl xpt_release_ccb(done_ccb); 1184195534Sscottl xpt_schedule(periph, priority); 1185260547Smavout: 1186260547Smav /* Drop freeze taken due to CAM_DEV_QFREEZE and release. */ 1187260547Smav cam_release_devq(path, 0, 0, 0, FALSE); 1188260547Smav cam_periph_release_locked(periph); 1189260547Smav return; 1190195534Sscottl } 1191195534Sscottl case PROBE_INQUIRY: 1192195534Sscottl case PROBE_FULL_INQUIRY: 1193195534Sscottl { 1194252382Sscottl if (cam_ccb_status(done_ccb) == CAM_REQ_CMP) { 1195195534Sscottl u_int8_t periph_qual; 1196195534Sscottl 1197195534Sscottl path->device->flags |= CAM_DEV_INQUIRY_DATA_VALID; 1198272401Smav scsi_find_quirk(path->device); 1199195534Sscottl inq_buf = &path->device->inq_data; 1200195534Sscottl 1201195534Sscottl periph_qual = SID_QUAL(inq_buf); 1202195534Sscottl 1203287289Smav if (periph_qual == SID_QUAL_LU_CONNECTED || 1204287289Smav periph_qual == SID_QUAL_LU_OFFLINE) { 1205195534Sscottl u_int8_t len; 1206195534Sscottl 1207195534Sscottl /* 1208195534Sscottl * We conservatively request only 1209195534Sscottl * SHORT_INQUIRY_LEN bytes of inquiry 1210195534Sscottl * information during our first try 1211195534Sscottl * at sending an INQUIRY. If the device 1212195534Sscottl * has more information to give, 1213195534Sscottl * perform a second request specifying 1214195534Sscottl * the amount of information the device 1215195534Sscottl * is willing to give. 1216195534Sscottl */ 1217195534Sscottl len = inq_buf->additional_length 1218195534Sscottl + offsetof(struct scsi_inquiry_data, 1219195534Sscottl additional_length) + 1; 1220195534Sscottl if (softc->action == PROBE_INQUIRY 1221195534Sscottl && len > SHORT_INQUIRY_LENGTH) { 1222195534Sscottl PROBE_SET_ACTION(softc, PROBE_FULL_INQUIRY); 1223195534Sscottl xpt_release_ccb(done_ccb); 1224195534Sscottl xpt_schedule(periph, priority); 1225249466Smav goto out; 1226195534Sscottl } 1227195534Sscottl 1228195534Sscottl scsi_devise_transport(path); 1229208911Smjacob 1230208911Smjacob if (path->device->lun_id == 0 && 1231208911Smjacob SID_ANSI_REV(inq_buf) > SCSI_REV_SPC2 && 1232208911Smjacob (SCSI_QUIRK(path->device)->quirks & 1233208911Smjacob CAM_QUIRK_NORPTLUNS) == 0) { 1234208911Smjacob PROBE_SET_ACTION(softc, 1235208911Smjacob PROBE_REPORT_LUNS); 1236208911Smjacob /* 1237208911Smjacob * Start with room for *one* lun. 1238208911Smjacob */ 1239208911Smjacob periph->path->target->rpl_size = 16; 1240208911Smjacob } else if (INQ_DATA_TQ_ENABLED(inq_buf)) 1241208911Smjacob PROBE_SET_ACTION(softc, 1242208911Smjacob PROBE_MODE_SENSE); 1243195534Sscottl else 1244208911Smjacob PROBE_SET_ACTION(softc, 1245216088Sken PROBE_SUPPORTED_VPD_LIST); 1246195534Sscottl 1247198748Smav if (path->device->flags & CAM_DEV_UNCONFIGURED) { 1248198748Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1249198748Smav xpt_acquire_device(path->device); 1250198748Smav } 1251195534Sscottl xpt_release_ccb(done_ccb); 1252195534Sscottl xpt_schedule(periph, priority); 1253249466Smav goto out; 1254208911Smjacob } else if (path->device->lun_id == 0 && 1255272409Smav SID_ANSI_REV(inq_buf) >= SCSI_REV_SPC2 && 1256208911Smjacob (SCSI_QUIRK(path->device)->quirks & 1257208911Smjacob CAM_QUIRK_NORPTLUNS) == 0) { 1258208911Smjacob PROBE_SET_ACTION(softc, PROBE_REPORT_LUNS); 1259208911Smjacob periph->path->target->rpl_size = 16; 1260208911Smjacob xpt_release_ccb(done_ccb); 1261208911Smjacob xpt_schedule(periph, priority); 1262249466Smav goto out; 1263195534Sscottl } 1264195534Sscottl } else if (cam_periph_error(done_ccb, 0, 1265195534Sscottl done_ccb->ccb_h.target_lun > 0 1266195534Sscottl ? SF_RETRY_UA|SF_QUIET_IR 1267195534Sscottl : SF_RETRY_UA, 1268195534Sscottl &softc->saved_ccb) == ERESTART) { 1269260547Smav goto outr; 1270272401Smav } else { 1271272401Smav if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1272272401Smav /* Don't wedge the queue */ 1273272401Smav xpt_release_devq(done_ccb->ccb_h.path, 1274272401Smav /*count*/1, /*run_queue*/TRUE); 1275272401Smav } 1276272401Smav path->device->flags &= ~CAM_DEV_INQUIRY_DATA_VALID; 1277195534Sscottl } 1278195534Sscottl /* 1279195534Sscottl * If we get to this point, we got an error status back 1280195534Sscottl * from the inquiry and the error status doesn't require 1281195534Sscottl * automatically retrying the command. Therefore, the 1282195534Sscottl * inquiry failed. If we had inquiry information before 1283195534Sscottl * for this device, but this latest inquiry command failed, 1284195534Sscottl * the device has probably gone away. If this device isn't 1285195534Sscottl * already marked unconfigured, notify the peripheral 1286195534Sscottl * drivers that this device is no more. 1287195534Sscottl */ 1288195534Sscottl if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0) 1289195534Sscottl /* Send the async notification. */ 1290195534Sscottl xpt_async(AC_LOST_DEVICE, path, NULL); 1291236613Smav PROBE_SET_ACTION(softc, PROBE_INVALID); 1292195534Sscottl 1293195534Sscottl xpt_release_ccb(done_ccb); 1294195534Sscottl break; 1295195534Sscottl } 1296208911Smjacob case PROBE_REPORT_LUNS: 1297208911Smjacob { 1298208911Smjacob struct ccb_scsiio *csio; 1299208911Smjacob struct scsi_report_luns_data *lp; 1300208911Smjacob u_int nlun, maxlun; 1301208911Smjacob 1302208911Smjacob csio = &done_ccb->csio; 1303208911Smjacob 1304208911Smjacob lp = (struct scsi_report_luns_data *)csio->data_ptr; 1305208911Smjacob nlun = scsi_4btoul(lp->length) / 8; 1306208911Smjacob maxlun = (csio->dxfer_len / 8) - 1; 1307208911Smjacob 1308252382Sscottl if (cam_ccb_status(done_ccb) != CAM_REQ_CMP) { 1309208911Smjacob if (cam_periph_error(done_ccb, 0, 1310208911Smjacob done_ccb->ccb_h.target_lun > 0 ? 1311208911Smjacob SF_RETRY_UA|SF_QUIET_IR : SF_RETRY_UA, 1312208911Smjacob &softc->saved_ccb) == ERESTART) { 1313260547Smav goto outr; 1314208911Smjacob } 1315208911Smjacob if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1316208911Smjacob xpt_release_devq(done_ccb->ccb_h.path, 1, 1317208911Smjacob TRUE); 1318208911Smjacob } 1319208911Smjacob free(lp, M_CAMXPT); 1320208911Smjacob lp = NULL; 1321208911Smjacob } else if (nlun > maxlun) { 1322208911Smjacob /* 1323208911Smjacob * Reallocate and retry to cover all luns 1324208911Smjacob */ 1325236613Smav CAM_DEBUG(path, CAM_DEBUG_PROBE, 1326236613Smav ("Probe: reallocating REPORT_LUNS for %u luns\n", 1327236613Smav nlun)); 1328208911Smjacob free(lp, M_CAMXPT); 1329208911Smjacob path->target->rpl_size = (nlun << 3) + 8; 1330208911Smjacob xpt_release_ccb(done_ccb); 1331208911Smjacob xpt_schedule(periph, priority); 1332249466Smav goto out; 1333208911Smjacob } else if (nlun == 0) { 1334208911Smjacob /* 1335208911Smjacob * If there don't appear to be any luns, bail. 1336208911Smjacob */ 1337208911Smjacob free(lp, M_CAMXPT); 1338208911Smjacob lp = NULL; 1339208911Smjacob } else { 1340208911Smjacob lun_id_t lun; 1341208911Smjacob int idx; 1342208911Smjacob 1343236613Smav CAM_DEBUG(path, CAM_DEBUG_PROBE, 1344236613Smav ("Probe: %u lun(s) reported\n", nlun)); 1345208911Smjacob 1346257345Snwhitehorn CAM_GET_LUN(lp, 0, lun); 1347208911Smjacob /* 1348208911Smjacob * If the first lun is not lun 0, then either there 1349208911Smjacob * is no lun 0 in the list, or the list is unsorted. 1350208911Smjacob */ 1351208911Smjacob if (lun != 0) { 1352208911Smjacob for (idx = 0; idx < nlun; idx++) { 1353257345Snwhitehorn CAM_GET_LUN(lp, idx, lun); 1354208911Smjacob if (lun == 0) { 1355208911Smjacob break; 1356208911Smjacob } 1357208911Smjacob } 1358208911Smjacob if (idx != nlun) { 1359208911Smjacob uint8_t tlun[8]; 1360208911Smjacob memcpy(tlun, 1361208911Smjacob lp->luns[0].lundata, 8); 1362208911Smjacob memcpy(lp->luns[0].lundata, 1363208911Smjacob lp->luns[idx].lundata, 8); 1364208911Smjacob memcpy(lp->luns[idx].lundata, 1365208911Smjacob tlun, 8); 1366236613Smav CAM_DEBUG(path, CAM_DEBUG_PROBE, 1367236613Smav ("lun 0 in position %u\n", idx)); 1368208911Smjacob } 1369208911Smjacob } 1370208911Smjacob /* 1371208911Smjacob * If we have an old lun list, We can either 1372208911Smjacob * retest luns that appear to have been dropped, 1373208911Smjacob * or just nuke them. We'll opt for the latter. 1374208911Smjacob * This function will also install the new list 1375208911Smjacob * in the target structure. 1376208911Smjacob */ 1377257345Snwhitehorn probe_purge_old(path, lp, softc->flags); 1378208911Smjacob lp = NULL; 1379208911Smjacob } 1380344393Sdab /* The processing above should either exit via a `goto 1381344393Sdab * out` or leave the `lp` variable `NULL` and (if 1382344393Sdab * applicable) `free()` the storage to which it had 1383344393Sdab * pointed. Assert here that is the case. 1384344393Sdab */ 1385344393Sdab KASSERT(lp == NULL, ("%s: lp is not NULL", __func__)); 1386287289Smav inq_buf = &path->device->inq_data; 1387272406Smav if (path->device->flags & CAM_DEV_INQUIRY_DATA_VALID && 1388287289Smav (SID_QUAL(inq_buf) == SID_QUAL_LU_CONNECTED || 1389287289Smav SID_QUAL(inq_buf) == SID_QUAL_LU_OFFLINE)) { 1390208911Smjacob if (INQ_DATA_TQ_ENABLED(inq_buf)) 1391208911Smjacob PROBE_SET_ACTION(softc, PROBE_MODE_SENSE); 1392208911Smjacob else 1393216088Sken PROBE_SET_ACTION(softc, 1394216088Sken PROBE_SUPPORTED_VPD_LIST); 1395208911Smjacob xpt_release_ccb(done_ccb); 1396208911Smjacob xpt_schedule(periph, priority); 1397249466Smav goto out; 1398208911Smjacob } 1399272406Smav PROBE_SET_ACTION(softc, PROBE_INVALID); 1400272406Smav xpt_release_ccb(done_ccb); 1401208911Smjacob break; 1402208911Smjacob } 1403195534Sscottl case PROBE_MODE_SENSE: 1404195534Sscottl { 1405195534Sscottl struct ccb_scsiio *csio; 1406195534Sscottl struct scsi_mode_header_6 *mode_hdr; 1407195534Sscottl 1408195534Sscottl csio = &done_ccb->csio; 1409195534Sscottl mode_hdr = (struct scsi_mode_header_6 *)csio->data_ptr; 1410252382Sscottl if (cam_ccb_status(done_ccb) == CAM_REQ_CMP) { 1411195534Sscottl struct scsi_control_page *page; 1412195534Sscottl u_int8_t *offset; 1413195534Sscottl 1414195534Sscottl offset = ((u_int8_t *)&mode_hdr[1]) 1415195534Sscottl + mode_hdr->blk_desc_len; 1416195534Sscottl page = (struct scsi_control_page *)offset; 1417195534Sscottl path->device->queue_flags = page->queue_flags; 1418195534Sscottl } else if (cam_periph_error(done_ccb, 0, 1419195534Sscottl SF_RETRY_UA|SF_NO_PRINT, 1420195534Sscottl &softc->saved_ccb) == ERESTART) { 1421260547Smav goto outr; 1422195534Sscottl } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1423195534Sscottl /* Don't wedge the queue */ 1424195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, 1425195534Sscottl /*count*/1, /*run_queue*/TRUE); 1426195534Sscottl } 1427195534Sscottl xpt_release_ccb(done_ccb); 1428195534Sscottl free(mode_hdr, M_CAMXPT); 1429216088Sken PROBE_SET_ACTION(softc, PROBE_SUPPORTED_VPD_LIST); 1430195534Sscottl xpt_schedule(periph, priority); 1431249466Smav goto out; 1432195534Sscottl } 1433216088Sken case PROBE_SUPPORTED_VPD_LIST: 1434195534Sscottl { 1435195534Sscottl struct ccb_scsiio *csio; 1436195534Sscottl struct scsi_vpd_supported_page_list *page_list; 1437195534Sscottl 1438195534Sscottl csio = &done_ccb->csio; 1439195534Sscottl page_list = 1440195534Sscottl (struct scsi_vpd_supported_page_list *)csio->data_ptr; 1441195534Sscottl 1442216088Sken if (path->device->supported_vpds != NULL) { 1443216088Sken free(path->device->supported_vpds, M_CAMXPT); 1444216088Sken path->device->supported_vpds = NULL; 1445216088Sken path->device->supported_vpds_len = 0; 1446216088Sken } 1447216088Sken 1448195534Sscottl if (page_list == NULL) { 1449195534Sscottl /* 1450195534Sscottl * Don't process the command as it was never sent 1451195534Sscottl */ 1452216088Sken } else if (CCB_COMPLETED_OK(csio->ccb_h)) { 1453216088Sken /* Got vpd list */ 1454216088Sken path->device->supported_vpds_len = page_list->length + 1455216088Sken SVPD_SUPPORTED_PAGES_HDR_LEN; 1456216088Sken path->device->supported_vpds = (uint8_t *)page_list; 1457216088Sken xpt_release_ccb(done_ccb); 1458216088Sken PROBE_SET_ACTION(softc, PROBE_DEVICE_ID); 1459216088Sken xpt_schedule(periph, priority); 1460249466Smav goto out; 1461195534Sscottl } else if (cam_periph_error(done_ccb, 0, 1462195534Sscottl SF_RETRY_UA|SF_NO_PRINT, 1463195534Sscottl &softc->saved_ccb) == ERESTART) { 1464260547Smav goto outr; 1465195534Sscottl } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1466195534Sscottl /* Don't wedge the queue */ 1467195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 1468195534Sscottl /*run_queue*/TRUE); 1469195534Sscottl } 1470195534Sscottl 1471216088Sken if (page_list) 1472195685Semaste free(page_list, M_CAMXPT); 1473216088Sken /* No VPDs available, skip to device check. */ 1474216088Sken csio->data_ptr = NULL; 1475216088Sken goto probe_device_check; 1476216088Sken } 1477216088Sken case PROBE_DEVICE_ID: 1478216088Sken { 1479216088Sken struct scsi_vpd_device_id *devid; 1480216088Sken struct ccb_scsiio *csio; 1481216088Sken uint32_t length = 0; 1482195534Sscottl 1483216088Sken csio = &done_ccb->csio; 1484216088Sken devid = (struct scsi_vpd_device_id *)csio->data_ptr; 1485216088Sken 1486216088Sken /* Clean up from previous instance of this device */ 1487216088Sken if (path->device->device_id != NULL) { 1488216088Sken path->device->device_id_len = 0; 1489216088Sken free(path->device->device_id, M_CAMXPT); 1490216088Sken path->device->device_id = NULL; 1491216088Sken } 1492216088Sken 1493216088Sken if (devid == NULL) { 1494216088Sken /* Don't process the command as it was never sent */ 1495216088Sken } else if (CCB_COMPLETED_OK(csio->ccb_h)) { 1496216088Sken length = scsi_2btoul(devid->length); 1497216088Sken if (length != 0) { 1498216088Sken /* 1499216088Sken * NB: device_id_len is actual response 1500216088Sken * size, not buffer size. 1501216088Sken */ 1502216088Sken path->device->device_id_len = length + 1503216088Sken SVPD_DEVICE_ID_HDR_LEN; 1504216088Sken path->device->device_id = (uint8_t *)devid; 1505216088Sken } 1506216088Sken } else if (cam_periph_error(done_ccb, 0, 1507223081Sgibbs SF_RETRY_UA, 1508216088Sken &softc->saved_ccb) == ERESTART) { 1509260547Smav goto outr; 1510216088Sken } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1511216088Sken /* Don't wedge the queue */ 1512216088Sken xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 1513216088Sken /*run_queue*/TRUE); 1514195534Sscottl } 1515195534Sscottl 1516216088Sken /* Free the device id space if we don't use it */ 1517216088Sken if (devid && length == 0) 1518216088Sken free(devid, M_CAMXPT); 1519216088Sken xpt_release_ccb(done_ccb); 1520278228Sken PROBE_SET_ACTION(softc, PROBE_EXTENDED_INQUIRY); 1521278228Sken xpt_schedule(periph, priority); 1522278228Sken goto out; 1523278228Sken } 1524278228Sken case PROBE_EXTENDED_INQUIRY: { 1525278228Sken struct scsi_vpd_extended_inquiry_data *ext_inq; 1526278228Sken struct ccb_scsiio *csio; 1527278228Sken int32_t length = 0; 1528278228Sken 1529278228Sken csio = &done_ccb->csio; 1530278228Sken ext_inq = (struct scsi_vpd_extended_inquiry_data *) 1531278228Sken csio->data_ptr; 1532278228Sken if (path->device->ext_inq != NULL) { 1533278228Sken path->device->ext_inq_len = 0; 1534278228Sken free(path->device->ext_inq, M_CAMXPT); 1535278228Sken path->device->ext_inq = NULL; 1536278228Sken } 1537278228Sken 1538278228Sken if (ext_inq == NULL) { 1539278228Sken /* Don't process the command as it was never sent */ 1540278228Sken } else if (CCB_COMPLETED_OK(csio->ccb_h)) { 1541278228Sken length = scsi_2btoul(ext_inq->page_length) + 1542278228Sken __offsetof(struct scsi_vpd_extended_inquiry_data, 1543278228Sken flags1); 1544278228Sken length = min(length, sizeof(*ext_inq)); 1545278228Sken length -= csio->resid; 1546278228Sken if (length > 0) { 1547278228Sken path->device->ext_inq_len = length; 1548278228Sken path->device->ext_inq = (uint8_t *)ext_inq; 1549278228Sken } 1550278228Sken } else if (cam_periph_error(done_ccb, 0, 1551278228Sken SF_RETRY_UA, 1552278228Sken &softc->saved_ccb) == ERESTART) { 1553295417Sken goto outr; 1554278228Sken } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1555278228Sken /* Don't wedge the queue */ 1556278228Sken xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 1557278228Sken /*run_queue*/TRUE); 1558278228Sken } 1559278228Sken 1560278228Sken /* Free the device id space if we don't use it */ 1561278228Sken if (ext_inq && length <= 0) 1562278228Sken free(ext_inq, M_CAMXPT); 1563278228Sken xpt_release_ccb(done_ccb); 1564216088Sken PROBE_SET_ACTION(softc, PROBE_SERIAL_NUM); 1565216088Sken xpt_schedule(periph, priority); 1566249466Smav goto out; 1567195534Sscottl } 1568195534Sscottl 1569216088Skenprobe_device_check: 1570216088Sken case PROBE_SERIAL_NUM: 1571195534Sscottl { 1572195534Sscottl struct ccb_scsiio *csio; 1573195534Sscottl struct scsi_vpd_unit_serial_number *serial_buf; 1574195534Sscottl u_int32_t priority; 1575195534Sscottl int changed; 1576195534Sscottl int have_serialnum; 1577195534Sscottl 1578195534Sscottl changed = 1; 1579195534Sscottl have_serialnum = 0; 1580195534Sscottl csio = &done_ccb->csio; 1581195534Sscottl priority = done_ccb->ccb_h.pinfo.priority; 1582195534Sscottl serial_buf = 1583195534Sscottl (struct scsi_vpd_unit_serial_number *)csio->data_ptr; 1584195534Sscottl 1585195534Sscottl if (serial_buf == NULL) { 1586195534Sscottl /* 1587195534Sscottl * Don't process the command as it was never sent 1588195534Sscottl */ 1589252382Sscottl } else if (cam_ccb_status(done_ccb) == CAM_REQ_CMP 1590195534Sscottl && (serial_buf->length > 0)) { 1591195534Sscottl 1592195534Sscottl have_serialnum = 1; 1593195534Sscottl path->device->serial_num = 1594195534Sscottl (u_int8_t *)malloc((serial_buf->length + 1), 1595195534Sscottl M_CAMXPT, M_NOWAIT); 1596195534Sscottl if (path->device->serial_num != NULL) { 1597300880Sasomers int start, slen; 1598300880Sasomers 1599300880Sasomers start = strspn(serial_buf->serial_num, " "); 1600300880Sasomers slen = serial_buf->length - start; 1601300880Sasomers if (slen <= 0) { 1602350783Smav /* 1603300880Sasomers * SPC5r05 says that an all-space serial 1604300880Sasomers * number means no product serial number 1605300880Sasomers * is available 1606300880Sasomers */ 1607300880Sasomers slen = 0; 1608300880Sasomers } 1609223081Sgibbs memcpy(path->device->serial_num, 1610300880Sasomers &serial_buf->serial_num[start], slen); 1611300880Sasomers path->device->serial_num_len = slen; 1612300880Sasomers path->device->serial_num[slen] = '\0'; 1613195534Sscottl } 1614195534Sscottl } else if (cam_periph_error(done_ccb, 0, 1615195534Sscottl SF_RETRY_UA|SF_NO_PRINT, 1616195534Sscottl &softc->saved_ccb) == ERESTART) { 1617260547Smav goto outr; 1618195534Sscottl } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1619195534Sscottl /* Don't wedge the queue */ 1620195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 1621195534Sscottl /*run_queue*/TRUE); 1622195534Sscottl } 1623195534Sscottl 1624195534Sscottl /* 1625195534Sscottl * Let's see if we have seen this device before. 1626195534Sscottl */ 1627195534Sscottl if ((softc->flags & PROBE_INQUIRY_CKSUM) != 0) { 1628195534Sscottl MD5_CTX context; 1629195534Sscottl u_int8_t digest[16]; 1630195534Sscottl 1631195534Sscottl MD5Init(&context); 1632195534Sscottl 1633195534Sscottl MD5Update(&context, 1634195534Sscottl (unsigned char *)&path->device->inq_data, 1635195534Sscottl sizeof(struct scsi_inquiry_data)); 1636195534Sscottl 1637195534Sscottl if (have_serialnum) 1638309273Sasomers MD5Update(&context, path->device->serial_num, 1639309273Sasomers path->device->serial_num_len); 1640195534Sscottl 1641195534Sscottl MD5Final(digest, &context); 1642195534Sscottl if (bcmp(softc->digest, digest, 16) == 0) 1643195534Sscottl changed = 0; 1644195534Sscottl 1645195534Sscottl /* 1646195534Sscottl * XXX Do we need to do a TUR in order to ensure 1647195534Sscottl * that the device really hasn't changed??? 1648195534Sscottl */ 1649195534Sscottl if ((changed != 0) 1650195534Sscottl && ((softc->flags & PROBE_NO_ANNOUNCE) == 0)) 1651195534Sscottl xpt_async(AC_LOST_DEVICE, path, NULL); 1652195534Sscottl } 1653195534Sscottl if (serial_buf != NULL) 1654195534Sscottl free(serial_buf, M_CAMXPT); 1655195534Sscottl 1656195534Sscottl if (changed != 0) { 1657195534Sscottl /* 1658195534Sscottl * Now that we have all the necessary 1659195534Sscottl * information to safely perform transfer 1660195534Sscottl * negotiations... Controllers don't perform 1661195534Sscottl * any negotiation or tagged queuing until 1662195534Sscottl * after the first XPT_SET_TRAN_SETTINGS ccb is 1663195534Sscottl * received. So, on a new device, just retrieve 1664195534Sscottl * the user settings, and set them as the current 1665195534Sscottl * settings to set the device up. 1666195534Sscottl */ 1667195534Sscottl proberequestdefaultnegotiation(periph); 1668195534Sscottl xpt_release_ccb(done_ccb); 1669195534Sscottl 1670195534Sscottl /* 1671195534Sscottl * Perform a TUR to allow the controller to 1672195534Sscottl * perform any necessary transfer negotiation. 1673195534Sscottl */ 1674195534Sscottl PROBE_SET_ACTION(softc, PROBE_TUR_FOR_NEGOTIATION); 1675195534Sscottl xpt_schedule(periph, priority); 1676249466Smav goto out; 1677195534Sscottl } 1678195534Sscottl xpt_release_ccb(done_ccb); 1679195534Sscottl break; 1680195534Sscottl } 1681195534Sscottl case PROBE_TUR_FOR_NEGOTIATION: 1682236814Smav case PROBE_DV_EXIT: 1683252382Sscottl if (cam_ccb_status(done_ccb) != CAM_REQ_CMP) { 1684351746Smav if (cam_periph_error(done_ccb, 0, SF_NO_PRINT | 1685351746Smav SF_NO_RECOVERY | SF_NO_RETRY, NULL) == ERESTART) 1686351746Smav goto outr; 1687195534Sscottl } 1688195534Sscottl if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1689195534Sscottl /* Don't wedge the queue */ 1690195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 1691195534Sscottl /*run_queue*/TRUE); 1692195534Sscottl } 1693195534Sscottl /* 1694195534Sscottl * Do Domain Validation for lun 0 on devices that claim 1695195534Sscottl * to support Synchronous Transfer modes. 1696195534Sscottl */ 1697195534Sscottl if (softc->action == PROBE_TUR_FOR_NEGOTIATION 1698195534Sscottl && done_ccb->ccb_h.target_lun == 0 1699195534Sscottl && (path->device->inq_data.flags & SID_Sync) != 0 1700195534Sscottl && (path->device->flags & CAM_DEV_IN_DV) == 0) { 1701236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, 1702195534Sscottl ("Begin Domain Validation\n")); 1703195534Sscottl path->device->flags |= CAM_DEV_IN_DV; 1704195534Sscottl xpt_release_ccb(done_ccb); 1705195534Sscottl PROBE_SET_ACTION(softc, PROBE_INQUIRY_BASIC_DV1); 1706195534Sscottl xpt_schedule(periph, priority); 1707249466Smav goto out; 1708195534Sscottl } 1709195534Sscottl if (softc->action == PROBE_DV_EXIT) { 1710236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, 1711195534Sscottl ("Leave Domain Validation\n")); 1712195534Sscottl } 1713198748Smav if (path->device->flags & CAM_DEV_UNCONFIGURED) { 1714198748Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1715198748Smav xpt_acquire_device(path->device); 1716198748Smav } 1717195534Sscottl path->device->flags &= 1718198748Smav ~(CAM_DEV_IN_DV|CAM_DEV_DV_HIT_BOTTOM); 1719195534Sscottl if ((softc->flags & PROBE_NO_ANNOUNCE) == 0) { 1720195534Sscottl /* Inform the XPT that a new device has been found */ 1721195534Sscottl done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1722195534Sscottl xpt_action(done_ccb); 1723195534Sscottl xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, 1724195534Sscottl done_ccb); 1725195534Sscottl } 1726236613Smav PROBE_SET_ACTION(softc, PROBE_DONE); 1727195534Sscottl xpt_release_ccb(done_ccb); 1728195534Sscottl break; 1729195534Sscottl case PROBE_INQUIRY_BASIC_DV1: 1730195534Sscottl case PROBE_INQUIRY_BASIC_DV2: 1731195534Sscottl { 1732195534Sscottl struct scsi_inquiry_data *nbuf; 1733195534Sscottl struct ccb_scsiio *csio; 1734195534Sscottl 1735252382Sscottl if (cam_ccb_status(done_ccb) != CAM_REQ_CMP) { 1736351746Smav if (cam_periph_error(done_ccb, 0, SF_NO_PRINT | 1737351746Smav SF_NO_RECOVERY | SF_NO_RETRY, NULL) == ERESTART) 1738351746Smav goto outr; 1739236814Smav } 1740195534Sscottl if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1741195534Sscottl /* Don't wedge the queue */ 1742195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 1743195534Sscottl /*run_queue*/TRUE); 1744195534Sscottl } 1745195534Sscottl csio = &done_ccb->csio; 1746195534Sscottl nbuf = (struct scsi_inquiry_data *)csio->data_ptr; 1747195534Sscottl if (bcmp(nbuf, &path->device->inq_data, SHORT_INQUIRY_LENGTH)) { 1748195534Sscottl xpt_print(path, 1749195534Sscottl "inquiry data fails comparison at DV%d step\n", 1750195534Sscottl softc->action == PROBE_INQUIRY_BASIC_DV1 ? 1 : 2); 1751195534Sscottl if (proberequestbackoff(periph, path->device)) { 1752195534Sscottl path->device->flags &= ~CAM_DEV_IN_DV; 1753195534Sscottl PROBE_SET_ACTION(softc, PROBE_TUR_FOR_NEGOTIATION); 1754195534Sscottl } else { 1755195534Sscottl /* give up */ 1756195534Sscottl PROBE_SET_ACTION(softc, PROBE_DV_EXIT); 1757195534Sscottl } 1758195534Sscottl free(nbuf, M_CAMXPT); 1759195534Sscottl xpt_release_ccb(done_ccb); 1760195534Sscottl xpt_schedule(periph, priority); 1761249466Smav goto out; 1762195534Sscottl } 1763195534Sscottl free(nbuf, M_CAMXPT); 1764195534Sscottl if (softc->action == PROBE_INQUIRY_BASIC_DV1) { 1765195534Sscottl PROBE_SET_ACTION(softc, PROBE_INQUIRY_BASIC_DV2); 1766195534Sscottl xpt_release_ccb(done_ccb); 1767195534Sscottl xpt_schedule(periph, priority); 1768249466Smav goto out; 1769195534Sscottl } 1770195534Sscottl if (softc->action == PROBE_INQUIRY_BASIC_DV2) { 1771236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, 1772195534Sscottl ("Leave Domain Validation Successfully\n")); 1773195534Sscottl } 1774198748Smav if (path->device->flags & CAM_DEV_UNCONFIGURED) { 1775198748Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1776198748Smav xpt_acquire_device(path->device); 1777198748Smav } 1778195534Sscottl path->device->flags &= 1779198748Smav ~(CAM_DEV_IN_DV|CAM_DEV_DV_HIT_BOTTOM); 1780195534Sscottl if ((softc->flags & PROBE_NO_ANNOUNCE) == 0) { 1781195534Sscottl /* Inform the XPT that a new device has been found */ 1782195534Sscottl done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1783195534Sscottl xpt_action(done_ccb); 1784195534Sscottl xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, 1785195534Sscottl done_ccb); 1786195534Sscottl } 1787236613Smav PROBE_SET_ACTION(softc, PROBE_DONE); 1788195534Sscottl xpt_release_ccb(done_ccb); 1789195534Sscottl break; 1790195534Sscottl } 1791195534Sscottl default: 1792236613Smav panic("probedone: invalid action state 0x%x\n", softc->action); 1793195534Sscottl } 1794195534Sscottl done_ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs); 1795195534Sscottl TAILQ_REMOVE(&softc->request_ccbs, &done_ccb->ccb_h, periph_links.tqe); 1796195534Sscottl done_ccb->ccb_h.status = CAM_REQ_CMP; 1797195534Sscottl xpt_done(done_ccb); 1798195534Sscottl if (TAILQ_FIRST(&softc->request_ccbs) == NULL) { 1799236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe completed\n")); 1800249466Smav /* Drop freeze taken due to CAM_DEV_QFREEZE flag set. */ 1801249466Smav cam_release_devq(path, 0, 0, 0, FALSE); 1802260541Smav cam_periph_release_locked(periph); 1803236228Smav cam_periph_invalidate(periph); 1804195534Sscottl cam_periph_release_locked(periph); 1805195534Sscottl } else { 1806195534Sscottl probeschedule(periph); 1807249466Smav goto out; 1808195534Sscottl } 1809195534Sscottl} 1810195534Sscottl 1811195534Sscottlstatic void 1812257345Snwhitehornprobe_purge_old(struct cam_path *path, struct scsi_report_luns_data *new, 1813257345Snwhitehorn probe_flags flags) 1814208911Smjacob{ 1815208911Smjacob struct cam_path *tp; 1816208911Smjacob struct scsi_report_luns_data *old; 1817257345Snwhitehorn u_int idx1, idx2, nlun_old, nlun_new; 1818257345Snwhitehorn lun_id_t this_lun; 1819208911Smjacob u_int8_t *ol, *nl; 1820208911Smjacob 1821208911Smjacob if (path->target == NULL) { 1822208911Smjacob return; 1823208911Smjacob } 1824256843Smav mtx_lock(&path->target->luns_mtx); 1825256843Smav old = path->target->luns; 1826256843Smav path->target->luns = new; 1827256843Smav mtx_unlock(&path->target->luns_mtx); 1828256843Smav if (old == NULL) 1829208911Smjacob return; 1830208911Smjacob nlun_old = scsi_4btoul(old->length) / 8; 1831208911Smjacob nlun_new = scsi_4btoul(new->length) / 8; 1832208911Smjacob 1833208911Smjacob /* 1834208911Smjacob * We are not going to assume sorted lists. Deal. 1835208911Smjacob */ 1836208911Smjacob for (idx1 = 0; idx1 < nlun_old; idx1++) { 1837208911Smjacob ol = old->luns[idx1].lundata; 1838208911Smjacob for (idx2 = 0; idx2 < nlun_new; idx2++) { 1839208911Smjacob nl = new->luns[idx2].lundata; 1840208911Smjacob if (memcmp(nl, ol, 8) == 0) { 1841208911Smjacob break; 1842208911Smjacob } 1843208911Smjacob } 1844208911Smjacob if (idx2 < nlun_new) { 1845208911Smjacob continue; 1846208911Smjacob } 1847208911Smjacob /* 1848208911Smjacob * An 'old' item not in the 'new' list. 1849208911Smjacob * Nuke it. Except that if it is lun 0, 1850208911Smjacob * that would be what the probe state 1851208911Smjacob * machine is currently working on, 1852208911Smjacob * so we won't do that. 1853208911Smjacob */ 1854257345Snwhitehorn CAM_GET_LUN(old, idx1, this_lun); 1855257345Snwhitehorn if (this_lun == 0) { 1856208911Smjacob continue; 1857208911Smjacob } 1858257345Snwhitehorn 1859257345Snwhitehorn /* 1860257345Snwhitehorn * We also cannot nuke it if it is 1861257345Snwhitehorn * not in a lun format we understand 1862257345Snwhitehorn * and replace the LUN with a "simple" LUN 1863257345Snwhitehorn * if that is all the HBA supports. 1864257345Snwhitehorn */ 1865257345Snwhitehorn if (!(flags & PROBE_EXTLUN)) { 1866257345Snwhitehorn if (!CAM_CAN_GET_SIMPLE_LUN(old, idx1)) 1867257345Snwhitehorn continue; 1868257345Snwhitehorn CAM_GET_SIMPLE_LUN(old, idx1, this_lun); 1869257345Snwhitehorn } 1870257345Snwhitehorn 1871208911Smjacob if (xpt_create_path(&tp, NULL, xpt_path_path_id(path), 1872208911Smjacob xpt_path_target_id(path), this_lun) == CAM_REQ_CMP) { 1873208911Smjacob xpt_async(AC_LOST_DEVICE, tp, NULL); 1874208911Smjacob xpt_free_path(tp); 1875208911Smjacob } 1876208911Smjacob } 1877208911Smjacob free(old, M_CAMXPT); 1878208911Smjacob} 1879208911Smjacob 1880208911Smjacobstatic void 1881195534Sscottlprobecleanup(struct cam_periph *periph) 1882195534Sscottl{ 1883195534Sscottl free(periph->softc, M_CAMXPT); 1884195534Sscottl} 1885195534Sscottl 1886195534Sscottlstatic void 1887195534Sscottlscsi_find_quirk(struct cam_ed *device) 1888195534Sscottl{ 1889195534Sscottl struct scsi_quirk_entry *quirk; 1890195534Sscottl caddr_t match; 1891195534Sscottl 1892195534Sscottl match = cam_quirkmatch((caddr_t)&device->inq_data, 1893195534Sscottl (caddr_t)scsi_quirk_table, 1894298431Spfg nitems(scsi_quirk_table), 1895195534Sscottl sizeof(*scsi_quirk_table), scsi_inquiry_match); 1896195534Sscottl 1897195534Sscottl if (match == NULL) 1898195534Sscottl panic("xpt_find_quirk: device didn't match wildcard entry!!"); 1899195534Sscottl 1900195534Sscottl quirk = (struct scsi_quirk_entry *)match; 1901195534Sscottl device->quirk = quirk; 1902195534Sscottl device->mintags = quirk->mintags; 1903195534Sscottl device->maxtags = quirk->maxtags; 1904195534Sscottl} 1905195534Sscottl 1906195534Sscottlstatic int 1907195534Sscottlsysctl_cam_search_luns(SYSCTL_HANDLER_ARGS) 1908195534Sscottl{ 1909228442Smdf int error, val; 1910195534Sscottl 1911228442Smdf val = cam_srch_hi; 1912228442Smdf error = sysctl_handle_int(oidp, &val, 0, req); 1913195534Sscottl if (error != 0 || req->newptr == NULL) 1914195534Sscottl return (error); 1915228442Smdf if (val == 0 || val == 1) { 1916228442Smdf cam_srch_hi = val; 1917195534Sscottl return (0); 1918195534Sscottl } else { 1919195534Sscottl return (EINVAL); 1920195534Sscottl } 1921195534Sscottl} 1922195534Sscottl 1923195534Sscottltypedef struct { 1924195534Sscottl union ccb *request_ccb; 1925195534Sscottl struct ccb_pathinq *cpi; 1926195534Sscottl int counter; 1927208911Smjacob int lunindex[0]; 1928195534Sscottl} scsi_scan_bus_info; 1929195534Sscottl 1930195534Sscottl/* 1931195534Sscottl * To start a scan, request_ccb is an XPT_SCAN_BUS ccb. 1932195688Semaste * As the scan progresses, scsi_scan_bus is used as the 1933195534Sscottl * callback on completion function. 1934195534Sscottl */ 1935195534Sscottlstatic void 1936195534Sscottlscsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb) 1937195534Sscottl{ 1938256843Smav struct mtx *mtx; 1939256843Smav 1940195534Sscottl CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE, 1941195688Semaste ("scsi_scan_bus\n")); 1942195534Sscottl switch (request_ccb->ccb_h.func_code) { 1943195534Sscottl case XPT_SCAN_BUS: 1944208582Smjacob case XPT_SCAN_TGT: 1945195534Sscottl { 1946195534Sscottl scsi_scan_bus_info *scan_info; 1947203108Smav union ccb *work_ccb, *reset_ccb; 1948195534Sscottl struct cam_path *path; 1949195534Sscottl u_int i; 1950208582Smjacob u_int low_target, max_target; 1951195534Sscottl u_int initiator_id; 1952195534Sscottl 1953195534Sscottl /* Find out the characteristics of the bus */ 1954195534Sscottl work_ccb = xpt_alloc_ccb_nowait(); 1955195534Sscottl if (work_ccb == NULL) { 1956195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1957195534Sscottl xpt_done(request_ccb); 1958195534Sscottl return; 1959195534Sscottl } 1960195534Sscottl xpt_setup_ccb(&work_ccb->ccb_h, request_ccb->ccb_h.path, 1961195534Sscottl request_ccb->ccb_h.pinfo.priority); 1962195534Sscottl work_ccb->ccb_h.func_code = XPT_PATH_INQ; 1963195534Sscottl xpt_action(work_ccb); 1964195534Sscottl if (work_ccb->ccb_h.status != CAM_REQ_CMP) { 1965195534Sscottl request_ccb->ccb_h.status = work_ccb->ccb_h.status; 1966195534Sscottl xpt_free_ccb(work_ccb); 1967195534Sscottl xpt_done(request_ccb); 1968195534Sscottl return; 1969195534Sscottl } 1970195534Sscottl 1971195534Sscottl if ((work_ccb->cpi.hba_misc & PIM_NOINITIATOR) != 0) { 1972195534Sscottl /* 1973195534Sscottl * Can't scan the bus on an adapter that 1974195534Sscottl * cannot perform the initiator role. 1975195534Sscottl */ 1976195534Sscottl request_ccb->ccb_h.status = CAM_REQ_CMP; 1977195534Sscottl xpt_free_ccb(work_ccb); 1978195534Sscottl xpt_done(request_ccb); 1979195534Sscottl return; 1980195534Sscottl } 1981195534Sscottl 1982203108Smav /* We may need to reset bus first, if we haven't done it yet. */ 1983203108Smav if ((work_ccb->cpi.hba_inquiry & 1984203108Smav (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE)) && 1985203108Smav !(work_ccb->cpi.hba_misc & PIM_NOBUSRESET) && 1986253370Smav !timevalisset(&request_ccb->ccb_h.path->bus->last_reset) && 1987253370Smav (reset_ccb = xpt_alloc_ccb_nowait()) != NULL) { 1988203108Smav xpt_setup_ccb(&reset_ccb->ccb_h, request_ccb->ccb_h.path, 1989203108Smav CAM_PRIORITY_NONE); 1990203108Smav reset_ccb->ccb_h.func_code = XPT_RESET_BUS; 1991203108Smav xpt_action(reset_ccb); 1992203108Smav if (reset_ccb->ccb_h.status != CAM_REQ_CMP) { 1993203108Smav request_ccb->ccb_h.status = reset_ccb->ccb_h.status; 1994203108Smav xpt_free_ccb(reset_ccb); 1995203108Smav xpt_free_ccb(work_ccb); 1996203108Smav xpt_done(request_ccb); 1997203108Smav return; 1998203108Smav } 1999203108Smav xpt_free_ccb(reset_ccb); 2000203108Smav } 2001203108Smav 2002195534Sscottl /* Save some state for use while we probe for devices */ 2003208911Smjacob scan_info = (scsi_scan_bus_info *) malloc(sizeof(scsi_scan_bus_info) + 2004208911Smjacob (work_ccb->cpi.max_target * sizeof (u_int)), M_CAMXPT, M_ZERO|M_NOWAIT); 2005195534Sscottl if (scan_info == NULL) { 2006195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 2007256843Smav xpt_free_ccb(work_ccb); 2008195534Sscottl xpt_done(request_ccb); 2009195534Sscottl return; 2010195534Sscottl } 2011236613Smav CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE, 2012208911Smjacob ("SCAN start for %p\n", scan_info)); 2013195534Sscottl scan_info->request_ccb = request_ccb; 2014195534Sscottl scan_info->cpi = &work_ccb->cpi; 2015195534Sscottl 2016195534Sscottl /* Cache on our stack so we can work asynchronously */ 2017195534Sscottl max_target = scan_info->cpi->max_target; 2018208582Smjacob low_target = 0; 2019195534Sscottl initiator_id = scan_info->cpi->initiator_id; 2020195534Sscottl 2021195534Sscottl 2022195534Sscottl /* 2023195534Sscottl * We can scan all targets in parallel, or do it sequentially. 2024195534Sscottl */ 2025208582Smjacob 2026208582Smjacob if (request_ccb->ccb_h.func_code == XPT_SCAN_TGT) { 2027208582Smjacob max_target = low_target = request_ccb->ccb_h.target_id; 2028208582Smjacob scan_info->counter = 0; 2029208582Smjacob } else if (scan_info->cpi->hba_misc & PIM_SEQSCAN) { 2030195534Sscottl max_target = 0; 2031195534Sscottl scan_info->counter = 0; 2032195534Sscottl } else { 2033195534Sscottl scan_info->counter = scan_info->cpi->max_target + 1; 2034195534Sscottl if (scan_info->cpi->initiator_id < scan_info->counter) { 2035195534Sscottl scan_info->counter--; 2036195534Sscottl } 2037195534Sscottl } 2038256843Smav mtx = xpt_path_mtx(scan_info->request_ccb->ccb_h.path); 2039256843Smav mtx_unlock(mtx); 2040195534Sscottl 2041208582Smjacob for (i = low_target; i <= max_target; i++) { 2042195534Sscottl cam_status status; 2043195534Sscottl if (i == initiator_id) 2044195534Sscottl continue; 2045195534Sscottl 2046249468Smav status = xpt_create_path(&path, NULL, 2047195534Sscottl request_ccb->ccb_h.path_id, 2048195534Sscottl i, 0); 2049195534Sscottl if (status != CAM_REQ_CMP) { 2050195688Semaste printf("scsi_scan_bus: xpt_create_path failed" 2051195534Sscottl " with status %#x, bus scan halted\n", 2052195534Sscottl status); 2053195534Sscottl free(scan_info, M_CAMXPT); 2054195534Sscottl request_ccb->ccb_h.status = status; 2055195534Sscottl xpt_free_ccb(work_ccb); 2056195534Sscottl xpt_done(request_ccb); 2057195534Sscottl break; 2058195534Sscottl } 2059195534Sscottl work_ccb = xpt_alloc_ccb_nowait(); 2060195534Sscottl if (work_ccb == NULL) { 2061195685Semaste xpt_free_ccb((union ccb *)scan_info->cpi); 2062195534Sscottl free(scan_info, M_CAMXPT); 2063195534Sscottl xpt_free_path(path); 2064195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 2065195534Sscottl xpt_done(request_ccb); 2066195534Sscottl break; 2067195534Sscottl } 2068195534Sscottl xpt_setup_ccb(&work_ccb->ccb_h, path, 2069195534Sscottl request_ccb->ccb_h.pinfo.priority); 2070195534Sscottl work_ccb->ccb_h.func_code = XPT_SCAN_LUN; 2071195534Sscottl work_ccb->ccb_h.cbfcnp = scsi_scan_bus; 2072256843Smav work_ccb->ccb_h.flags |= CAM_UNLOCKED; 2073195534Sscottl work_ccb->ccb_h.ppriv_ptr0 = scan_info; 2074195534Sscottl work_ccb->crcn.flags = request_ccb->crcn.flags; 2075195534Sscottl xpt_action(work_ccb); 2076195534Sscottl } 2077256843Smav 2078256843Smav mtx_lock(mtx); 2079195534Sscottl break; 2080195534Sscottl } 2081195534Sscottl case XPT_SCAN_LUN: 2082195534Sscottl { 2083195534Sscottl cam_status status; 2084208911Smjacob struct cam_path *path, *oldpath; 2085195534Sscottl scsi_scan_bus_info *scan_info; 2086208911Smjacob struct cam_et *target; 2087272401Smav struct cam_ed *device, *nextdev; 2088208911Smjacob int next_target; 2089195534Sscottl path_id_t path_id; 2090195534Sscottl target_id_t target_id; 2091195534Sscottl lun_id_t lun_id; 2092195534Sscottl 2093208911Smjacob oldpath = request_ccb->ccb_h.path; 2094208911Smjacob 2095252382Sscottl status = cam_ccb_status(request_ccb); 2096195534Sscottl scan_info = (scsi_scan_bus_info *)request_ccb->ccb_h.ppriv_ptr0; 2097195534Sscottl path_id = request_ccb->ccb_h.path_id; 2098195534Sscottl target_id = request_ccb->ccb_h.target_id; 2099195534Sscottl lun_id = request_ccb->ccb_h.target_lun; 2100208911Smjacob target = request_ccb->ccb_h.path->target; 2101208911Smjacob next_target = 1; 2102208911Smjacob 2103256843Smav mtx = xpt_path_mtx(scan_info->request_ccb->ccb_h.path); 2104256843Smav mtx_lock(mtx); 2105256843Smav mtx_lock(&target->luns_mtx); 2106208911Smjacob if (target->luns) { 2107257345Snwhitehorn lun_id_t first; 2108208911Smjacob u_int nluns = scsi_4btoul(target->luns->length) / 8; 2109208911Smjacob 2110208911Smjacob /* 2111208911Smjacob * Make sure we skip over lun 0 if it's the first member 2112208911Smjacob * of the list as we've actually just finished probing 2113208911Smjacob * it. 2114208911Smjacob */ 2115257345Snwhitehorn CAM_GET_LUN(target->luns, 0, first); 2116208911Smjacob if (first == 0 && scan_info->lunindex[target_id] == 0) { 2117208911Smjacob scan_info->lunindex[target_id]++; 2118350783Smav } 2119208911Smjacob 2120257345Snwhitehorn /* 2121257345Snwhitehorn * Skip any LUNs that the HBA can't deal with. 2122257345Snwhitehorn */ 2123257345Snwhitehorn while (scan_info->lunindex[target_id] < nluns) { 2124257345Snwhitehorn if (scan_info->cpi->hba_misc & PIM_EXTLUNS) { 2125257345Snwhitehorn CAM_GET_LUN(target->luns, 2126257345Snwhitehorn scan_info->lunindex[target_id], 2127257345Snwhitehorn lun_id); 2128257345Snwhitehorn break; 2129257345Snwhitehorn } 2130257345Snwhitehorn 2131257345Snwhitehorn if (CAM_CAN_GET_SIMPLE_LUN(target->luns, 2132257345Snwhitehorn scan_info->lunindex[target_id])) { 2133257345Snwhitehorn CAM_GET_SIMPLE_LUN(target->luns, 2134257345Snwhitehorn scan_info->lunindex[target_id], 2135257345Snwhitehorn lun_id); 2136257345Snwhitehorn break; 2137257345Snwhitehorn } 2138257345Snwhitehorn 2139257345Snwhitehorn scan_info->lunindex[target_id]++; 2140257345Snwhitehorn } 2141257345Snwhitehorn 2142208911Smjacob if (scan_info->lunindex[target_id] < nluns) { 2143256843Smav mtx_unlock(&target->luns_mtx); 2144208911Smjacob next_target = 0; 2145236613Smav CAM_DEBUG(request_ccb->ccb_h.path, 2146236613Smav CAM_DEBUG_PROBE, 2147257345Snwhitehorn ("next lun to try at index %u is %jx\n", 2148257345Snwhitehorn scan_info->lunindex[target_id], 2149257345Snwhitehorn (uintmax_t)lun_id)); 2150208911Smjacob scan_info->lunindex[target_id]++; 2151208911Smjacob } else { 2152256843Smav mtx_unlock(&target->luns_mtx); 2153274756Smav /* We're done with scanning all luns. */ 2154208911Smjacob } 2155256843Smav } else { 2156272401Smav mtx_unlock(&target->luns_mtx); 2157195534Sscottl device = request_ccb->ccb_h.path->device; 2158272401Smav /* Continue sequential LUN scan if: */ 2159272401Smav /* -- we have more LUNs that need recheck */ 2160272401Smav mtx_lock(&target->bus->eb_mtx); 2161272401Smav nextdev = device; 2162272401Smav while ((nextdev = TAILQ_NEXT(nextdev, links)) != NULL) 2163272401Smav if ((nextdev->flags & CAM_DEV_UNCONFIGURED) == 0) 2164272401Smav break; 2165272401Smav mtx_unlock(&target->bus->eb_mtx); 2166272401Smav if (nextdev != NULL) { 2167272401Smav next_target = 0; 2168272402Smav /* -- stop if CAM_QUIRK_NOLUNS is set. */ 2169272402Smav } else if (SCSI_QUIRK(device)->quirks & CAM_QUIRK_NOLUNS) { 2170272402Smav next_target = 1; 2171272401Smav /* -- this LUN is connected and its SCSI version 2172272401Smav * allows more LUNs. */ 2173272401Smav } else if ((device->flags & CAM_DEV_UNCONFIGURED) == 0) { 2174272401Smav if (lun_id < (CAM_SCSI2_MAXLUN-1) || 2175272401Smav CAN_SRCH_HI_DENSE(device)) 2176208911Smjacob next_target = 0; 2177272401Smav /* -- this LUN is disconnected, its SCSI version 2178272401Smav * allows more LUNs and we guess they may be. */ 2179272401Smav } else if ((device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0) { 2180272401Smav if (lun_id < (CAM_SCSI2_MAXLUN-1) || 2181272401Smav CAN_SRCH_HI_SPARSE(device)) 2182272401Smav next_target = 0; 2183195534Sscottl } 2184272401Smav if (next_target == 0) { 2185272401Smav lun_id++; 2186272401Smav if (lun_id > scan_info->cpi->max_lun) 2187272401Smav next_target = 1; 2188272401Smav } 2189195534Sscottl } 2190195534Sscottl 2191195534Sscottl /* 2192195534Sscottl * Check to see if we scan any further luns. 2193195534Sscottl */ 2194208911Smjacob if (next_target) { 2195195534Sscottl int done; 2196195534Sscottl 2197208911Smjacob /* 2198208911Smjacob * Free the current request path- we're done with it. 2199208911Smjacob */ 2200208911Smjacob xpt_free_path(oldpath); 2201195534Sscottl hop_again: 2202195534Sscottl done = 0; 2203208582Smjacob if (scan_info->request_ccb->ccb_h.func_code == XPT_SCAN_TGT) { 2204208582Smjacob done = 1; 2205208582Smjacob } else if (scan_info->cpi->hba_misc & PIM_SEQSCAN) { 2206195534Sscottl scan_info->counter++; 2207195534Sscottl if (scan_info->counter == 2208195534Sscottl scan_info->cpi->initiator_id) { 2209195534Sscottl scan_info->counter++; 2210195534Sscottl } 2211195534Sscottl if (scan_info->counter >= 2212195534Sscottl scan_info->cpi->max_target+1) { 2213195534Sscottl done = 1; 2214195534Sscottl } 2215195534Sscottl } else { 2216195534Sscottl scan_info->counter--; 2217195534Sscottl if (scan_info->counter == 0) { 2218195534Sscottl done = 1; 2219195534Sscottl } 2220195534Sscottl } 2221195534Sscottl if (done) { 2222256843Smav mtx_unlock(mtx); 2223195534Sscottl xpt_free_ccb(request_ccb); 2224195534Sscottl xpt_free_ccb((union ccb *)scan_info->cpi); 2225195534Sscottl request_ccb = scan_info->request_ccb; 2226236613Smav CAM_DEBUG(request_ccb->ccb_h.path, 2227236613Smav CAM_DEBUG_TRACE, 2228208911Smjacob ("SCAN done for %p\n", scan_info)); 2229195534Sscottl free(scan_info, M_CAMXPT); 2230195534Sscottl request_ccb->ccb_h.status = CAM_REQ_CMP; 2231195534Sscottl xpt_done(request_ccb); 2232195534Sscottl break; 2233195534Sscottl } 2234195534Sscottl 2235195534Sscottl if ((scan_info->cpi->hba_misc & PIM_SEQSCAN) == 0) { 2236256843Smav mtx_unlock(mtx); 2237195685Semaste xpt_free_ccb(request_ccb); 2238195534Sscottl break; 2239195534Sscottl } 2240249468Smav status = xpt_create_path(&path, NULL, 2241195534Sscottl scan_info->request_ccb->ccb_h.path_id, 2242195534Sscottl scan_info->counter, 0); 2243195534Sscottl if (status != CAM_REQ_CMP) { 2244256843Smav mtx_unlock(mtx); 2245195688Semaste printf("scsi_scan_bus: xpt_create_path failed" 2246195534Sscottl " with status %#x, bus scan halted\n", 2247195534Sscottl status); 2248195534Sscottl xpt_free_ccb(request_ccb); 2249195534Sscottl xpt_free_ccb((union ccb *)scan_info->cpi); 2250195534Sscottl request_ccb = scan_info->request_ccb; 2251195534Sscottl free(scan_info, M_CAMXPT); 2252195534Sscottl request_ccb->ccb_h.status = status; 2253195534Sscottl xpt_done(request_ccb); 2254195534Sscottl break; 2255195534Sscottl } 2256195534Sscottl xpt_setup_ccb(&request_ccb->ccb_h, path, 2257195534Sscottl request_ccb->ccb_h.pinfo.priority); 2258195534Sscottl request_ccb->ccb_h.func_code = XPT_SCAN_LUN; 2259195534Sscottl request_ccb->ccb_h.cbfcnp = scsi_scan_bus; 2260256843Smav request_ccb->ccb_h.flags |= CAM_UNLOCKED; 2261195534Sscottl request_ccb->ccb_h.ppriv_ptr0 = scan_info; 2262195534Sscottl request_ccb->crcn.flags = 2263195534Sscottl scan_info->request_ccb->crcn.flags; 2264195534Sscottl } else { 2265249468Smav status = xpt_create_path(&path, NULL, 2266195534Sscottl path_id, target_id, lun_id); 2267208911Smjacob /* 2268208911Smjacob * Free the old request path- we're done with it. We 2269208911Smjacob * do this *after* creating the new path so that 2270208911Smjacob * we don't remove a target that has our lun list 2271208911Smjacob * in the case that lun 0 is not present. 2272208911Smjacob */ 2273208911Smjacob xpt_free_path(oldpath); 2274195534Sscottl if (status != CAM_REQ_CMP) { 2275195688Semaste printf("scsi_scan_bus: xpt_create_path failed " 2276195534Sscottl "with status %#x, halting LUN scan\n", 2277195534Sscottl status); 2278195534Sscottl goto hop_again; 2279195534Sscottl } 2280195534Sscottl xpt_setup_ccb(&request_ccb->ccb_h, path, 2281195534Sscottl request_ccb->ccb_h.pinfo.priority); 2282195534Sscottl request_ccb->ccb_h.func_code = XPT_SCAN_LUN; 2283195534Sscottl request_ccb->ccb_h.cbfcnp = scsi_scan_bus; 2284256843Smav request_ccb->ccb_h.flags |= CAM_UNLOCKED; 2285195534Sscottl request_ccb->ccb_h.ppriv_ptr0 = scan_info; 2286195534Sscottl request_ccb->crcn.flags = 2287195534Sscottl scan_info->request_ccb->crcn.flags; 2288195534Sscottl } 2289256843Smav mtx_unlock(mtx); 2290195534Sscottl xpt_action(request_ccb); 2291195534Sscottl break; 2292195534Sscottl } 2293195534Sscottl default: 2294195534Sscottl break; 2295195534Sscottl } 2296195534Sscottl} 2297195534Sscottl 2298195534Sscottlstatic void 2299195534Sscottlscsi_scan_lun(struct cam_periph *periph, struct cam_path *path, 2300195534Sscottl cam_flags flags, union ccb *request_ccb) 2301195534Sscottl{ 2302195534Sscottl struct ccb_pathinq cpi; 2303195534Sscottl cam_status status; 2304195534Sscottl struct cam_path *new_path; 2305195534Sscottl struct cam_periph *old_periph; 2306256843Smav int lock; 2307195534Sscottl 2308203108Smav CAM_DEBUG(path, CAM_DEBUG_TRACE, ("scsi_scan_lun\n")); 2309195534Sscottl 2310203108Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 2311195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 2312195534Sscottl xpt_action((union ccb *)&cpi); 2313195534Sscottl 2314195534Sscottl if (cpi.ccb_h.status != CAM_REQ_CMP) { 2315195534Sscottl if (request_ccb != NULL) { 2316195534Sscottl request_ccb->ccb_h.status = cpi.ccb_h.status; 2317195534Sscottl xpt_done(request_ccb); 2318195534Sscottl } 2319195534Sscottl return; 2320195534Sscottl } 2321195534Sscottl 2322195534Sscottl if ((cpi.hba_misc & PIM_NOINITIATOR) != 0) { 2323195534Sscottl /* 2324195534Sscottl * Can't scan the bus on an adapter that 2325195534Sscottl * cannot perform the initiator role. 2326195534Sscottl */ 2327195534Sscottl if (request_ccb != NULL) { 2328195534Sscottl request_ccb->ccb_h.status = CAM_REQ_CMP; 2329195534Sscottl xpt_done(request_ccb); 2330195534Sscottl } 2331195534Sscottl return; 2332195534Sscottl } 2333195534Sscottl 2334195534Sscottl if (request_ccb == NULL) { 2335241455Smav request_ccb = xpt_alloc_ccb_nowait(); 2336195534Sscottl if (request_ccb == NULL) { 2337195688Semaste xpt_print(path, "scsi_scan_lun: can't allocate CCB, " 2338195534Sscottl "can't continue\n"); 2339195534Sscottl return; 2340195534Sscottl } 2341249468Smav status = xpt_create_path(&new_path, NULL, 2342195534Sscottl path->bus->path_id, 2343195534Sscottl path->target->target_id, 2344195534Sscottl path->device->lun_id); 2345195534Sscottl if (status != CAM_REQ_CMP) { 2346241455Smav xpt_print(path, "scsi_scan_lun: can't create path, " 2347195534Sscottl "can't continue\n"); 2348241455Smav xpt_free_ccb(request_ccb); 2349195534Sscottl return; 2350195534Sscottl } 2351203108Smav xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_XPT); 2352195534Sscottl request_ccb->ccb_h.cbfcnp = xptscandone; 2353195534Sscottl request_ccb->ccb_h.func_code = XPT_SCAN_LUN; 2354256843Smav request_ccb->ccb_h.flags |= CAM_UNLOCKED; 2355195534Sscottl request_ccb->crcn.flags = flags; 2356195534Sscottl } 2357195534Sscottl 2358256843Smav lock = (xpt_path_owned(path) == 0); 2359256843Smav if (lock) 2360256843Smav xpt_path_lock(path); 2361195534Sscottl if ((old_periph = cam_periph_find(path, "probe")) != NULL) { 2362236228Smav if ((old_periph->flags & CAM_PERIPH_INVALID) == 0) { 2363236228Smav probe_softc *softc; 2364195534Sscottl 2365236228Smav softc = (probe_softc *)old_periph->softc; 2366236228Smav TAILQ_INSERT_TAIL(&softc->request_ccbs, 2367236228Smav &request_ccb->ccb_h, periph_links.tqe); 2368236228Smav } else { 2369236228Smav request_ccb->ccb_h.status = CAM_REQ_CMP_ERR; 2370236228Smav xpt_done(request_ccb); 2371236228Smav } 2372195534Sscottl } else { 2373195534Sscottl status = cam_periph_alloc(proberegister, NULL, probecleanup, 2374195534Sscottl probestart, "probe", 2375195534Sscottl CAM_PERIPH_BIO, 2376195534Sscottl request_ccb->ccb_h.path, NULL, 0, 2377195534Sscottl request_ccb); 2378195534Sscottl 2379195534Sscottl if (status != CAM_REQ_CMP) { 2380195688Semaste xpt_print(path, "scsi_scan_lun: cam_alloc_periph " 2381195534Sscottl "returned an error, can't continue probe\n"); 2382195534Sscottl request_ccb->ccb_h.status = status; 2383195534Sscottl xpt_done(request_ccb); 2384195534Sscottl } 2385195534Sscottl } 2386256843Smav if (lock) 2387256843Smav xpt_path_unlock(path); 2388195534Sscottl} 2389195534Sscottl 2390195534Sscottlstatic void 2391195534Sscottlxptscandone(struct cam_periph *periph, union ccb *done_ccb) 2392195534Sscottl{ 2393241455Smav 2394241455Smav xpt_free_path(done_ccb->ccb_h.path); 2395241455Smav xpt_free_ccb(done_ccb); 2396195534Sscottl} 2397195534Sscottl 2398195534Sscottlstatic struct cam_ed * 2399195534Sscottlscsi_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id) 2400195534Sscottl{ 2401195534Sscottl struct scsi_quirk_entry *quirk; 2402195534Sscottl struct cam_ed *device; 2403195534Sscottl 2404195534Sscottl device = xpt_alloc_device(bus, target, lun_id); 2405195534Sscottl if (device == NULL) 2406195534Sscottl return (NULL); 2407195534Sscottl 2408195534Sscottl /* 2409195534Sscottl * Take the default quirk entry until we have inquiry 2410195534Sscottl * data and can determine a better quirk to use. 2411195534Sscottl */ 2412299186Spfg quirk = &scsi_quirk_table[nitems(scsi_quirk_table) - 1]; 2413195534Sscottl device->quirk = (void *)quirk; 2414195534Sscottl device->mintags = quirk->mintags; 2415195534Sscottl device->maxtags = quirk->maxtags; 2416195534Sscottl bzero(&device->inq_data, sizeof(device->inq_data)); 2417195534Sscottl device->inq_flags = 0; 2418195534Sscottl device->queue_flags = 0; 2419195534Sscottl device->serial_num = NULL; 2420195534Sscottl device->serial_num_len = 0; 2421216088Sken device->device_id = NULL; 2422216088Sken device->device_id_len = 0; 2423216088Sken device->supported_vpds = NULL; 2424216088Sken device->supported_vpds_len = 0; 2425195534Sscottl return (device); 2426195534Sscottl} 2427195534Sscottl 2428195534Sscottlstatic void 2429195534Sscottlscsi_devise_transport(struct cam_path *path) 2430195534Sscottl{ 2431195534Sscottl struct ccb_pathinq cpi; 2432195534Sscottl struct ccb_trans_settings cts; 2433195534Sscottl struct scsi_inquiry_data *inq_buf; 2434195534Sscottl 2435195534Sscottl /* Get transport information from the SIM */ 2436203108Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 2437195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 2438195534Sscottl xpt_action((union ccb *)&cpi); 2439195534Sscottl 2440195534Sscottl inq_buf = NULL; 2441195534Sscottl if ((path->device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0) 2442195534Sscottl inq_buf = &path->device->inq_data; 2443195534Sscottl path->device->protocol = PROTO_SCSI; 2444195534Sscottl path->device->protocol_version = 2445195534Sscottl inq_buf != NULL ? SID_ANSI_REV(inq_buf) : cpi.protocol_version; 2446195534Sscottl path->device->transport = cpi.transport; 2447195534Sscottl path->device->transport_version = cpi.transport_version; 2448195534Sscottl 2449195534Sscottl /* 2450195534Sscottl * Any device not using SPI3 features should 2451195534Sscottl * be considered SPI2 or lower. 2452195534Sscottl */ 2453195534Sscottl if (inq_buf != NULL) { 2454195534Sscottl if (path->device->transport == XPORT_SPI 2455195534Sscottl && (inq_buf->spi3data & SID_SPI_MASK) == 0 2456195534Sscottl && path->device->transport_version > 2) 2457195534Sscottl path->device->transport_version = 2; 2458195534Sscottl } else { 2459195534Sscottl struct cam_ed* otherdev; 2460195534Sscottl 2461195534Sscottl for (otherdev = TAILQ_FIRST(&path->target->ed_entries); 2462195534Sscottl otherdev != NULL; 2463195534Sscottl otherdev = TAILQ_NEXT(otherdev, links)) { 2464195534Sscottl if (otherdev != path->device) 2465195534Sscottl break; 2466195534Sscottl } 2467195534Sscottl 2468195534Sscottl if (otherdev != NULL) { 2469195534Sscottl /* 2470195534Sscottl * Initially assume the same versioning as 2471195534Sscottl * prior luns for this target. 2472195534Sscottl */ 2473195534Sscottl path->device->protocol_version = 2474195534Sscottl otherdev->protocol_version; 2475195534Sscottl path->device->transport_version = 2476195534Sscottl otherdev->transport_version; 2477195534Sscottl } else { 2478298810Spfg /* Until we know better, opt for safety */ 2479195534Sscottl path->device->protocol_version = 2; 2480195534Sscottl if (path->device->transport == XPORT_SPI) 2481195534Sscottl path->device->transport_version = 2; 2482195534Sscottl else 2483195534Sscottl path->device->transport_version = 0; 2484195534Sscottl } 2485195534Sscottl } 2486195534Sscottl 2487195534Sscottl /* 2488195534Sscottl * XXX 2489195534Sscottl * For a device compliant with SPC-2 we should be able 2490195534Sscottl * to determine the transport version supported by 2491195534Sscottl * scrutinizing the version descriptors in the 2492195534Sscottl * inquiry buffer. 2493195534Sscottl */ 2494195534Sscottl 2495195534Sscottl /* Tell the controller what we think */ 2496203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 2497195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 2498195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 2499195534Sscottl cts.transport = path->device->transport; 2500195534Sscottl cts.transport_version = path->device->transport_version; 2501195534Sscottl cts.protocol = path->device->protocol; 2502195534Sscottl cts.protocol_version = path->device->protocol_version; 2503195534Sscottl cts.proto_specific.valid = 0; 2504195534Sscottl cts.xport_specific.valid = 0; 2505195534Sscottl xpt_action((union ccb *)&cts); 2506195534Sscottl} 2507195534Sscottl 2508195534Sscottlstatic void 2509223081Sgibbsscsi_dev_advinfo(union ccb *start_ccb) 2510216088Sken{ 2511216088Sken struct cam_ed *device; 2512223081Sgibbs struct ccb_dev_advinfo *cdai; 2513216088Sken off_t amt; 2514216088Sken 2515351754Smav xpt_path_assert(start_ccb->ccb_h.path, MA_OWNED); 2516223448Swill start_ccb->ccb_h.status = CAM_REQ_INVALID; 2517216088Sken device = start_ccb->ccb_h.path->device; 2518223081Sgibbs cdai = &start_ccb->cdai; 2519223081Sgibbs switch(cdai->buftype) { 2520223081Sgibbs case CDAI_TYPE_SCSI_DEVID: 2521223081Sgibbs if (cdai->flags & CDAI_FLAG_STORE) 2522223448Swill return; 2523223081Sgibbs cdai->provsiz = device->device_id_len; 2524216088Sken if (device->device_id_len == 0) 2525216088Sken break; 2526216088Sken amt = device->device_id_len; 2527223081Sgibbs if (cdai->provsiz > cdai->bufsiz) 2528223081Sgibbs amt = cdai->bufsiz; 2529223081Sgibbs memcpy(cdai->buf, device->device_id, amt); 2530216088Sken break; 2531223081Sgibbs case CDAI_TYPE_SERIAL_NUM: 2532223081Sgibbs if (cdai->flags & CDAI_FLAG_STORE) 2533223448Swill return; 2534223081Sgibbs cdai->provsiz = device->serial_num_len; 2535223081Sgibbs if (device->serial_num_len == 0) 2536223081Sgibbs break; 2537223081Sgibbs amt = device->serial_num_len; 2538223081Sgibbs if (cdai->provsiz > cdai->bufsiz) 2539223081Sgibbs amt = cdai->bufsiz; 2540223081Sgibbs memcpy(cdai->buf, device->serial_num, amt); 2541223081Sgibbs break; 2542223081Sgibbs case CDAI_TYPE_PHYS_PATH: 2543223081Sgibbs if (cdai->flags & CDAI_FLAG_STORE) { 2544230590Sken if (device->physpath != NULL) { 2545223081Sgibbs free(device->physpath, M_CAMXPT); 2546230590Sken device->physpath = NULL; 2547326680Sasomers device->physpath_len = 0; 2548230590Sken } 2549223081Sgibbs /* Clear existing buffer if zero length */ 2550223081Sgibbs if (cdai->bufsiz == 0) 2551223081Sgibbs break; 2552223081Sgibbs device->physpath = malloc(cdai->bufsiz, M_CAMXPT, M_NOWAIT); 2553223081Sgibbs if (device->physpath == NULL) { 2554223081Sgibbs start_ccb->ccb_h.status = CAM_REQ_ABORTED; 2555223081Sgibbs return; 2556223081Sgibbs } 2557326680Sasomers device->physpath_len = cdai->bufsiz; 2558223081Sgibbs memcpy(device->physpath, cdai->buf, cdai->bufsiz); 2559223081Sgibbs } else { 2560223081Sgibbs cdai->provsiz = device->physpath_len; 2561223081Sgibbs if (device->physpath_len == 0) 2562223081Sgibbs break; 2563223081Sgibbs amt = device->physpath_len; 2564223081Sgibbs if (cdai->provsiz > cdai->bufsiz) 2565223081Sgibbs amt = cdai->bufsiz; 2566223081Sgibbs memcpy(cdai->buf, device->physpath, amt); 2567223081Sgibbs } 2568223081Sgibbs break; 2569230590Sken case CDAI_TYPE_RCAPLONG: 2570230590Sken if (cdai->flags & CDAI_FLAG_STORE) { 2571230590Sken if (device->rcap_buf != NULL) { 2572230590Sken free(device->rcap_buf, M_CAMXPT); 2573230590Sken device->rcap_buf = NULL; 2574230590Sken } 2575230590Sken 2576230590Sken device->rcap_len = cdai->bufsiz; 2577230590Sken /* Clear existing buffer if zero length */ 2578230590Sken if (cdai->bufsiz == 0) 2579230590Sken break; 2580230590Sken 2581230590Sken device->rcap_buf = malloc(cdai->bufsiz, M_CAMXPT, 2582230590Sken M_NOWAIT); 2583230590Sken if (device->rcap_buf == NULL) { 2584230590Sken start_ccb->ccb_h.status = CAM_REQ_ABORTED; 2585230590Sken return; 2586230590Sken } 2587230590Sken 2588230590Sken memcpy(device->rcap_buf, cdai->buf, cdai->bufsiz); 2589230590Sken } else { 2590230590Sken cdai->provsiz = device->rcap_len; 2591230590Sken if (device->rcap_len == 0) 2592230590Sken break; 2593230590Sken amt = device->rcap_len; 2594230590Sken if (cdai->provsiz > cdai->bufsiz) 2595230590Sken amt = cdai->bufsiz; 2596230590Sken memcpy(cdai->buf, device->rcap_buf, amt); 2597230590Sken } 2598230590Sken break; 2599278228Sken case CDAI_TYPE_EXT_INQ: 2600278228Sken /* 2601278228Sken * We fetch extended inquiry data during probe, if 2602278228Sken * available. We don't allow changing it. 2603278228Sken */ 2604350783Smav if (cdai->flags & CDAI_FLAG_STORE) 2605278228Sken return; 2606278228Sken cdai->provsiz = device->ext_inq_len; 2607278228Sken if (device->ext_inq_len == 0) 2608278228Sken break; 2609278228Sken amt = device->ext_inq_len; 2610278228Sken if (cdai->provsiz > cdai->bufsiz) 2611278228Sken amt = cdai->bufsiz; 2612278228Sken memcpy(cdai->buf, device->ext_inq, amt); 2613278228Sken break; 2614216088Sken default: 2615223448Swill return; 2616216088Sken } 2617216088Sken start_ccb->ccb_h.status = CAM_REQ_CMP; 2618223081Sgibbs 2619223081Sgibbs if (cdai->flags & CDAI_FLAG_STORE) { 2620223081Sgibbs xpt_async(AC_ADVINFO_CHANGED, start_ccb->ccb_h.path, 2621223081Sgibbs (void *)(uintptr_t)cdai->buftype); 2622223081Sgibbs } 2623216088Sken} 2624216088Sken 2625216088Skenstatic void 2626195534Sscottlscsi_action(union ccb *start_ccb) 2627195534Sscottl{ 2628195534Sscottl 2629195534Sscottl switch (start_ccb->ccb_h.func_code) { 2630195534Sscottl case XPT_SET_TRAN_SETTINGS: 2631195534Sscottl { 2632195534Sscottl scsi_set_transfer_settings(&start_ccb->cts, 2633256843Smav start_ccb->ccb_h.path, 2634195534Sscottl /*async_update*/FALSE); 2635195534Sscottl break; 2636195534Sscottl } 2637195534Sscottl case XPT_SCAN_BUS: 2638208582Smjacob case XPT_SCAN_TGT: 2639195534Sscottl scsi_scan_bus(start_ccb->ccb_h.path->periph, start_ccb); 2640195534Sscottl break; 2641195534Sscottl case XPT_SCAN_LUN: 2642195534Sscottl scsi_scan_lun(start_ccb->ccb_h.path->periph, 2643195534Sscottl start_ccb->ccb_h.path, start_ccb->crcn.flags, 2644195534Sscottl start_ccb); 2645195534Sscottl break; 2646223081Sgibbs case XPT_DEV_ADVINFO: 2647216088Sken { 2648223081Sgibbs scsi_dev_advinfo(start_ccb); 2649216088Sken break; 2650216088Sken } 2651195534Sscottl default: 2652195534Sscottl xpt_action_default(start_ccb); 2653195534Sscottl break; 2654195534Sscottl } 2655195534Sscottl} 2656195534Sscottl 2657195534Sscottlstatic void 2658256843Smavscsi_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_path *path, 2659195534Sscottl int async_update) 2660195534Sscottl{ 2661195534Sscottl struct ccb_pathinq cpi; 2662195534Sscottl struct ccb_trans_settings cur_cts; 2663195534Sscottl struct ccb_trans_settings_scsi *scsi; 2664195534Sscottl struct ccb_trans_settings_scsi *cur_scsi; 2665195534Sscottl struct scsi_inquiry_data *inq_data; 2666256843Smav struct cam_ed *device; 2667195534Sscottl 2668256843Smav if (path == NULL || (device = path->device) == NULL) { 2669195534Sscottl cts->ccb_h.status = CAM_PATH_INVALID; 2670195534Sscottl xpt_done((union ccb *)cts); 2671195534Sscottl return; 2672195534Sscottl } 2673195534Sscottl 2674195534Sscottl if (cts->protocol == PROTO_UNKNOWN 2675195534Sscottl || cts->protocol == PROTO_UNSPECIFIED) { 2676195534Sscottl cts->protocol = device->protocol; 2677195534Sscottl cts->protocol_version = device->protocol_version; 2678195534Sscottl } 2679195534Sscottl 2680195534Sscottl if (cts->protocol_version == PROTO_VERSION_UNKNOWN 2681195534Sscottl || cts->protocol_version == PROTO_VERSION_UNSPECIFIED) 2682195534Sscottl cts->protocol_version = device->protocol_version; 2683195534Sscottl 2684195534Sscottl if (cts->protocol != device->protocol) { 2685256843Smav xpt_print(path, "Uninitialized Protocol %x:%x?\n", 2686195534Sscottl cts->protocol, device->protocol); 2687195534Sscottl cts->protocol = device->protocol; 2688195534Sscottl } 2689195534Sscottl 2690195534Sscottl if (cts->protocol_version > device->protocol_version) { 2691195534Sscottl if (bootverbose) { 2692256843Smav xpt_print(path, "Down reving Protocol " 2693195534Sscottl "Version from %d to %d?\n", cts->protocol_version, 2694195534Sscottl device->protocol_version); 2695195534Sscottl } 2696195534Sscottl cts->protocol_version = device->protocol_version; 2697195534Sscottl } 2698195534Sscottl 2699195534Sscottl if (cts->transport == XPORT_UNKNOWN 2700195534Sscottl || cts->transport == XPORT_UNSPECIFIED) { 2701195534Sscottl cts->transport = device->transport; 2702195534Sscottl cts->transport_version = device->transport_version; 2703195534Sscottl } 2704195534Sscottl 2705195534Sscottl if (cts->transport_version == XPORT_VERSION_UNKNOWN 2706195534Sscottl || cts->transport_version == XPORT_VERSION_UNSPECIFIED) 2707195534Sscottl cts->transport_version = device->transport_version; 2708195534Sscottl 2709195534Sscottl if (cts->transport != device->transport) { 2710256843Smav xpt_print(path, "Uninitialized Transport %x:%x?\n", 2711195534Sscottl cts->transport, device->transport); 2712195534Sscottl cts->transport = device->transport; 2713195534Sscottl } 2714195534Sscottl 2715195534Sscottl if (cts->transport_version > device->transport_version) { 2716195534Sscottl if (bootverbose) { 2717256843Smav xpt_print(path, "Down reving Transport " 2718195534Sscottl "Version from %d to %d?\n", cts->transport_version, 2719195534Sscottl device->transport_version); 2720195534Sscottl } 2721195534Sscottl cts->transport_version = device->transport_version; 2722195534Sscottl } 2723195534Sscottl 2724195534Sscottl /* 2725195534Sscottl * Nothing more of interest to do unless 2726195534Sscottl * this is a device connected via the 2727195534Sscottl * SCSI protocol. 2728195534Sscottl */ 2729195534Sscottl if (cts->protocol != PROTO_SCSI) { 2730195534Sscottl if (async_update == FALSE) 2731256843Smav xpt_action_default((union ccb *)cts); 2732195534Sscottl return; 2733195534Sscottl } 2734195534Sscottl 2735195534Sscottl inq_data = &device->inq_data; 2736195534Sscottl scsi = &cts->proto_specific.scsi; 2737256843Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 2738195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 2739195534Sscottl xpt_action((union ccb *)&cpi); 2740195534Sscottl 2741195534Sscottl /* SCSI specific sanity checking */ 2742195534Sscottl if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0 2743195534Sscottl || (INQ_DATA_TQ_ENABLED(inq_data)) == 0 2744195534Sscottl || (device->queue_flags & SCP_QUEUE_DQUE) != 0 2745195534Sscottl || (device->mintags == 0)) { 2746195534Sscottl /* 2747195534Sscottl * Can't tag on hardware that doesn't support tags, 2748195534Sscottl * doesn't have it enabled, or has broken tag support. 2749195534Sscottl */ 2750195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 2751195534Sscottl } 2752195534Sscottl 2753195534Sscottl if (async_update == FALSE) { 2754195534Sscottl /* 2755195534Sscottl * Perform sanity checking against what the 2756195534Sscottl * controller and device can do. 2757195534Sscottl */ 2758256843Smav xpt_setup_ccb(&cur_cts.ccb_h, path, CAM_PRIORITY_NONE); 2759195534Sscottl cur_cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 2760195534Sscottl cur_cts.type = cts->type; 2761195534Sscottl xpt_action((union ccb *)&cur_cts); 2762252382Sscottl if (cam_ccb_status((union ccb *)&cur_cts) != CAM_REQ_CMP) { 2763195534Sscottl return; 2764195534Sscottl } 2765195534Sscottl cur_scsi = &cur_cts.proto_specific.scsi; 2766195534Sscottl if ((scsi->valid & CTS_SCSI_VALID_TQ) == 0) { 2767195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 2768195534Sscottl scsi->flags |= cur_scsi->flags & CTS_SCSI_FLAGS_TAG_ENB; 2769195534Sscottl } 2770195534Sscottl if ((cur_scsi->valid & CTS_SCSI_VALID_TQ) == 0) 2771195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 2772195534Sscottl } 2773195534Sscottl 2774195534Sscottl /* SPI specific sanity checking */ 2775195534Sscottl if (cts->transport == XPORT_SPI && async_update == FALSE) { 2776195534Sscottl u_int spi3caps; 2777195534Sscottl struct ccb_trans_settings_spi *spi; 2778195534Sscottl struct ccb_trans_settings_spi *cur_spi; 2779195534Sscottl 2780195534Sscottl spi = &cts->xport_specific.spi; 2781195534Sscottl 2782195534Sscottl cur_spi = &cur_cts.xport_specific.spi; 2783195534Sscottl 2784195534Sscottl /* Fill in any gaps in what the user gave us */ 2785195534Sscottl if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) 2786195534Sscottl spi->sync_period = cur_spi->sync_period; 2787195534Sscottl if ((cur_spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) 2788195534Sscottl spi->sync_period = 0; 2789195534Sscottl if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0) 2790195534Sscottl spi->sync_offset = cur_spi->sync_offset; 2791195534Sscottl if ((cur_spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0) 2792195534Sscottl spi->sync_offset = 0; 2793195534Sscottl if ((spi->valid & CTS_SPI_VALID_PPR_OPTIONS) == 0) 2794195534Sscottl spi->ppr_options = cur_spi->ppr_options; 2795195534Sscottl if ((cur_spi->valid & CTS_SPI_VALID_PPR_OPTIONS) == 0) 2796195534Sscottl spi->ppr_options = 0; 2797195534Sscottl if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) == 0) 2798195534Sscottl spi->bus_width = cur_spi->bus_width; 2799195534Sscottl if ((cur_spi->valid & CTS_SPI_VALID_BUS_WIDTH) == 0) 2800195534Sscottl spi->bus_width = 0; 2801195534Sscottl if ((spi->valid & CTS_SPI_VALID_DISC) == 0) { 2802195534Sscottl spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; 2803195534Sscottl spi->flags |= cur_spi->flags & CTS_SPI_FLAGS_DISC_ENB; 2804195534Sscottl } 2805195534Sscottl if ((cur_spi->valid & CTS_SPI_VALID_DISC) == 0) 2806195534Sscottl spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; 2807195534Sscottl if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0 2808195534Sscottl && (inq_data->flags & SID_Sync) == 0 2809195534Sscottl && cts->type == CTS_TYPE_CURRENT_SETTINGS) 2810195534Sscottl || ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0)) { 2811195534Sscottl /* Force async */ 2812195534Sscottl spi->sync_period = 0; 2813195534Sscottl spi->sync_offset = 0; 2814195534Sscottl } 2815195534Sscottl 2816195534Sscottl switch (spi->bus_width) { 2817195534Sscottl case MSG_EXT_WDTR_BUS_32_BIT: 2818195534Sscottl if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) == 0 2819195534Sscottl || (inq_data->flags & SID_WBus32) != 0 2820195534Sscottl || cts->type == CTS_TYPE_USER_SETTINGS) 2821195534Sscottl && (cpi.hba_inquiry & PI_WIDE_32) != 0) 2822195534Sscottl break; 2823195534Sscottl /* Fall Through to 16-bit */ 2824195534Sscottl case MSG_EXT_WDTR_BUS_16_BIT: 2825195534Sscottl if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) == 0 2826195534Sscottl || (inq_data->flags & SID_WBus16) != 0 2827195534Sscottl || cts->type == CTS_TYPE_USER_SETTINGS) 2828195534Sscottl && (cpi.hba_inquiry & PI_WIDE_16) != 0) { 2829195534Sscottl spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT; 2830195534Sscottl break; 2831195534Sscottl } 2832195534Sscottl /* Fall Through to 8-bit */ 2833195534Sscottl default: /* New bus width?? */ 2834195534Sscottl case MSG_EXT_WDTR_BUS_8_BIT: 2835195534Sscottl /* All targets can do this */ 2836195534Sscottl spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT; 2837195534Sscottl break; 2838195534Sscottl } 2839195534Sscottl 2840195534Sscottl spi3caps = cpi.xport_specific.spi.ppr_options; 2841195534Sscottl if ((device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0 2842195534Sscottl && cts->type == CTS_TYPE_CURRENT_SETTINGS) 2843195534Sscottl spi3caps &= inq_data->spi3data; 2844195534Sscottl 2845195534Sscottl if ((spi3caps & SID_SPI_CLOCK_DT) == 0) 2846195534Sscottl spi->ppr_options &= ~MSG_EXT_PPR_DT_REQ; 2847195534Sscottl 2848195534Sscottl if ((spi3caps & SID_SPI_IUS) == 0) 2849195534Sscottl spi->ppr_options &= ~MSG_EXT_PPR_IU_REQ; 2850195534Sscottl 2851195534Sscottl if ((spi3caps & SID_SPI_QAS) == 0) 2852195534Sscottl spi->ppr_options &= ~MSG_EXT_PPR_QAS_REQ; 2853195534Sscottl 2854195534Sscottl /* No SPI Transfer settings are allowed unless we are wide */ 2855195534Sscottl if (spi->bus_width == 0) 2856195534Sscottl spi->ppr_options = 0; 2857195534Sscottl 2858195534Sscottl if ((spi->valid & CTS_SPI_VALID_DISC) 2859195534Sscottl && ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) == 0)) { 2860195534Sscottl /* 2861195534Sscottl * Can't tag queue without disconnection. 2862195534Sscottl */ 2863195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 2864195534Sscottl scsi->valid |= CTS_SCSI_VALID_TQ; 2865195534Sscottl } 2866195534Sscottl 2867195534Sscottl /* 2868195534Sscottl * If we are currently performing tagged transactions to 2869195534Sscottl * this device and want to change its negotiation parameters, 2870195534Sscottl * go non-tagged for a bit to give the controller a chance to 2871195534Sscottl * negotiate unhampered by tag messages. 2872195534Sscottl */ 2873195534Sscottl if (cts->type == CTS_TYPE_CURRENT_SETTINGS 2874195534Sscottl && (device->inq_flags & SID_CmdQue) != 0 2875195534Sscottl && (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0 2876195534Sscottl && (spi->flags & (CTS_SPI_VALID_SYNC_RATE| 2877195534Sscottl CTS_SPI_VALID_SYNC_OFFSET| 2878195534Sscottl CTS_SPI_VALID_BUS_WIDTH)) != 0) 2879256843Smav scsi_toggle_tags(path); 2880195534Sscottl } 2881195534Sscottl 2882195534Sscottl if (cts->type == CTS_TYPE_CURRENT_SETTINGS 2883195534Sscottl && (scsi->valid & CTS_SCSI_VALID_TQ) != 0) { 2884195534Sscottl int device_tagenb; 2885195534Sscottl 2886195534Sscottl /* 2887195534Sscottl * If we are transitioning from tags to no-tags or 2888195534Sscottl * vice-versa, we need to carefully freeze and restart 2889195534Sscottl * the queue so that we don't overlap tagged and non-tagged 2890195534Sscottl * commands. We also temporarily stop tags if there is 2891195534Sscottl * a change in transfer negotiation settings to allow 2892195534Sscottl * "tag-less" negotiation. 2893195534Sscottl */ 2894195534Sscottl if ((device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 2895195534Sscottl || (device->inq_flags & SID_CmdQue) != 0) 2896195534Sscottl device_tagenb = TRUE; 2897195534Sscottl else 2898195534Sscottl device_tagenb = FALSE; 2899195534Sscottl 2900195534Sscottl if (((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0 2901195534Sscottl && device_tagenb == FALSE) 2902195534Sscottl || ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) == 0 2903195534Sscottl && device_tagenb == TRUE)) { 2904195534Sscottl 2905195534Sscottl if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) { 2906195534Sscottl /* 2907195534Sscottl * Delay change to use tags until after a 2908195534Sscottl * few commands have gone to this device so 2909195534Sscottl * the controller has time to perform transfer 2910195534Sscottl * negotiations without tagged messages getting 2911195534Sscottl * in the way. 2912195534Sscottl */ 2913195534Sscottl device->tag_delay_count = CAM_TAG_DELAY_COUNT; 2914195534Sscottl device->flags |= CAM_DEV_TAG_AFTER_COUNT; 2915195534Sscottl } else { 2916256843Smav xpt_stop_tags(path); 2917195534Sscottl } 2918195534Sscottl } 2919195534Sscottl } 2920195534Sscottl if (async_update == FALSE) 2921256843Smav xpt_action_default((union ccb *)cts); 2922195534Sscottl} 2923195534Sscottl 2924195534Sscottlstatic void 2925195534Sscottlscsi_toggle_tags(struct cam_path *path) 2926195534Sscottl{ 2927195534Sscottl struct cam_ed *dev; 2928195534Sscottl 2929195534Sscottl /* 2930195534Sscottl * Give controllers a chance to renegotiate 2931195534Sscottl * before starting tag operations. We 2932195534Sscottl * "toggle" tagged queuing off then on 2933195534Sscottl * which causes the tag enable command delay 2934195534Sscottl * counter to come into effect. 2935195534Sscottl */ 2936195534Sscottl dev = path->device; 2937195534Sscottl if ((dev->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 2938195534Sscottl || ((dev->inq_flags & SID_CmdQue) != 0 2939195534Sscottl && (dev->inq_flags & (SID_Sync|SID_WBus16|SID_WBus32)) != 0)) { 2940195534Sscottl struct ccb_trans_settings cts; 2941195534Sscottl 2942203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 2943195534Sscottl cts.protocol = PROTO_SCSI; 2944195534Sscottl cts.protocol_version = PROTO_VERSION_UNSPECIFIED; 2945195534Sscottl cts.transport = XPORT_UNSPECIFIED; 2946195534Sscottl cts.transport_version = XPORT_VERSION_UNSPECIFIED; 2947195534Sscottl cts.proto_specific.scsi.flags = 0; 2948195534Sscottl cts.proto_specific.scsi.valid = CTS_SCSI_VALID_TQ; 2949256843Smav scsi_set_transfer_settings(&cts, path, 2950195534Sscottl /*async_update*/TRUE); 2951195534Sscottl cts.proto_specific.scsi.flags = CTS_SCSI_FLAGS_TAG_ENB; 2952256843Smav scsi_set_transfer_settings(&cts, path, 2953195534Sscottl /*async_update*/TRUE); 2954195534Sscottl } 2955195534Sscottl} 2956195534Sscottl 2957195534Sscottl/* 2958195534Sscottl * Handle any per-device event notifications that require action by the XPT. 2959195534Sscottl */ 2960195534Sscottlstatic void 2961195534Sscottlscsi_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target, 2962195534Sscottl struct cam_ed *device, void *async_arg) 2963195534Sscottl{ 2964195534Sscottl cam_status status; 2965195534Sscottl struct cam_path newpath; 2966195534Sscottl 2967195534Sscottl /* 2968195534Sscottl * We only need to handle events for real devices. 2969195534Sscottl */ 2970195534Sscottl if (target->target_id == CAM_TARGET_WILDCARD 2971195534Sscottl || device->lun_id == CAM_LUN_WILDCARD) 2972195534Sscottl return; 2973195534Sscottl 2974195534Sscottl /* 2975195534Sscottl * We need our own path with wildcards expanded to 2976195534Sscottl * handle certain types of events. 2977195534Sscottl */ 2978195534Sscottl if ((async_code == AC_SENT_BDR) 2979195534Sscottl || (async_code == AC_BUS_RESET) 2980195534Sscottl || (async_code == AC_INQ_CHANGED)) 2981195534Sscottl status = xpt_compile_path(&newpath, NULL, 2982195534Sscottl bus->path_id, 2983195534Sscottl target->target_id, 2984195534Sscottl device->lun_id); 2985195534Sscottl else 2986195534Sscottl status = CAM_REQ_CMP_ERR; 2987195534Sscottl 2988195534Sscottl if (status == CAM_REQ_CMP) { 2989195534Sscottl 2990195534Sscottl /* 2991195534Sscottl * Allow transfer negotiation to occur in a 2992203108Smav * tag free environment and after settle delay. 2993195534Sscottl */ 2994195534Sscottl if (async_code == AC_SENT_BDR 2995203108Smav || async_code == AC_BUS_RESET) { 2996350783Smav cam_freeze_devq(&newpath); 2997203108Smav cam_release_devq(&newpath, 2998203108Smav RELSIM_RELEASE_AFTER_TIMEOUT, 2999203108Smav /*reduction*/0, 3000203108Smav /*timeout*/scsi_delay, 3001203108Smav /*getcount_only*/0); 3002195534Sscottl scsi_toggle_tags(&newpath); 3003203108Smav } 3004195534Sscottl 3005195534Sscottl if (async_code == AC_INQ_CHANGED) { 3006195534Sscottl /* 3007195534Sscottl * We've sent a start unit command, or 3008195534Sscottl * something similar to a device that 3009195534Sscottl * may have caused its inquiry data to 3010195534Sscottl * change. So we re-scan the device to 3011195534Sscottl * refresh the inquiry data for it. 3012195534Sscottl */ 3013195534Sscottl scsi_scan_lun(newpath.periph, &newpath, 3014195534Sscottl CAM_EXPECT_INQ_CHANGE, NULL); 3015195534Sscottl } 3016195534Sscottl xpt_release_path(&newpath); 3017198748Smav } else if (async_code == AC_LOST_DEVICE && 3018198748Smav (device->flags & CAM_DEV_UNCONFIGURED) == 0) { 3019195534Sscottl device->flags |= CAM_DEV_UNCONFIGURED; 3020198748Smav xpt_release_device(device); 3021195534Sscottl } else if (async_code == AC_TRANSFER_NEG) { 3022195534Sscottl struct ccb_trans_settings *settings; 3023256843Smav struct cam_path path; 3024195534Sscottl 3025195534Sscottl settings = (struct ccb_trans_settings *)async_arg; 3026256843Smav xpt_compile_path(&path, NULL, bus->path_id, target->target_id, 3027256843Smav device->lun_id); 3028256843Smav scsi_set_transfer_settings(settings, &path, 3029195534Sscottl /*async_update*/TRUE); 3030256843Smav xpt_release_path(&path); 3031195534Sscottl } 3032195534Sscottl} 3033195534Sscottl 3034204220Smavstatic void 3035204220Smavscsi_announce_periph(struct cam_periph *periph) 3036204220Smav{ 3037204220Smav struct ccb_pathinq cpi; 3038204220Smav struct ccb_trans_settings cts; 3039204220Smav struct cam_path *path = periph->path; 3040204220Smav u_int speed; 3041204220Smav u_int freq; 3042204220Smav u_int mb; 3043204220Smav 3044256843Smav cam_periph_assert(periph, MA_OWNED); 3045204220Smav 3046204220Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); 3047204220Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 3048204220Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 3049204220Smav xpt_action((union ccb*)&cts); 3050252382Sscottl if (cam_ccb_status((union ccb *)&cts) != CAM_REQ_CMP) 3051204220Smav return; 3052204220Smav /* Ask the SIM for its base transfer speed */ 3053204220Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL); 3054204220Smav cpi.ccb_h.func_code = XPT_PATH_INQ; 3055204220Smav xpt_action((union ccb *)&cpi); 3056350783Smav /* Report connection speed */ 3057204220Smav speed = cpi.base_transfer_speed; 3058204220Smav freq = 0; 3059204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SPI) { 3060204220Smav struct ccb_trans_settings_spi *spi = 3061204220Smav &cts.xport_specific.spi; 3062204220Smav 3063204220Smav if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0 3064204220Smav && spi->sync_offset != 0) { 3065204220Smav freq = scsi_calc_syncsrate(spi->sync_period); 3066204220Smav speed = freq; 3067204220Smav } 3068204220Smav if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) 3069204220Smav speed *= (0x01 << spi->bus_width); 3070204220Smav } 3071204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_FC) { 3072204220Smav struct ccb_trans_settings_fc *fc = 3073204220Smav &cts.xport_specific.fc; 3074204220Smav 3075204220Smav if (fc->valid & CTS_FC_VALID_SPEED) 3076204220Smav speed = fc->bitrate; 3077204220Smav } 3078204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SAS) { 3079204220Smav struct ccb_trans_settings_sas *sas = 3080204220Smav &cts.xport_specific.sas; 3081204220Smav 3082204220Smav if (sas->valid & CTS_SAS_VALID_SPEED) 3083204220Smav speed = sas->bitrate; 3084204220Smav } 3085204220Smav mb = speed / 1000; 3086204220Smav if (mb > 0) 3087204220Smav printf("%s%d: %d.%03dMB/s transfers", 3088204220Smav periph->periph_name, periph->unit_number, 3089204220Smav mb, speed % 1000); 3090204220Smav else 3091204220Smav printf("%s%d: %dKB/s transfers", periph->periph_name, 3092204220Smav periph->unit_number, speed); 3093204220Smav /* Report additional information about SPI connections */ 3094204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SPI) { 3095204220Smav struct ccb_trans_settings_spi *spi; 3096204220Smav 3097204220Smav spi = &cts.xport_specific.spi; 3098204220Smav if (freq != 0) { 3099204220Smav printf(" (%d.%03dMHz%s, offset %d", freq / 1000, 3100204220Smav freq % 1000, 3101204220Smav (spi->ppr_options & MSG_EXT_PPR_DT_REQ) != 0 3102204220Smav ? " DT" : "", 3103204220Smav spi->sync_offset); 3104204220Smav } 3105204220Smav if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0 3106204220Smav && spi->bus_width > 0) { 3107204220Smav if (freq != 0) { 3108204220Smav printf(", "); 3109204220Smav } else { 3110204220Smav printf(" ("); 3111204220Smav } 3112204220Smav printf("%dbit)", 8 * (0x01 << spi->bus_width)); 3113204220Smav } else if (freq != 0) { 3114204220Smav printf(")"); 3115204220Smav } 3116204220Smav } 3117204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_FC) { 3118204220Smav struct ccb_trans_settings_fc *fc; 3119204220Smav 3120204220Smav fc = &cts.xport_specific.fc; 3121204220Smav if (fc->valid & CTS_FC_VALID_WWNN) 3122204220Smav printf(" WWNN 0x%llx", (long long) fc->wwnn); 3123204220Smav if (fc->valid & CTS_FC_VALID_WWPN) 3124204220Smav printf(" WWPN 0x%llx", (long long) fc->wwpn); 3125204220Smav if (fc->valid & CTS_FC_VALID_PORT) 3126204220Smav printf(" PortID 0x%x", fc->port); 3127204220Smav } 3128204220Smav printf("\n"); 3129204220Smav} 3130204220Smav 3131328820Smavstatic void 3132328820Smavscsi_proto_announce(struct cam_ed *device) 3133328820Smav{ 3134328820Smav scsi_print_inquiry(&device->inq_data); 3135328820Smav} 3136328820Smav 3137328820Smavstatic void 3138328820Smavscsi_proto_denounce(struct cam_ed *device) 3139328820Smav{ 3140328820Smav scsi_print_inquiry_short(&device->inq_data); 3141328820Smav} 3142328820Smav 3143328820Smavstatic void 3144328820Smavscsi_proto_debug_out(union ccb *ccb) 3145328820Smav{ 3146328820Smav char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1]; 3147328820Smav struct cam_ed *device; 3148328820Smav 3149328820Smav if (ccb->ccb_h.func_code != XPT_SCSI_IO) 3150328820Smav return; 3151328820Smav 3152328820Smav device = ccb->ccb_h.path->device; 3153328820Smav CAM_DEBUG(ccb->ccb_h.path, 3154328820Smav CAM_DEBUG_CDB,("%s. CDB: %s\n", 3155328820Smav scsi_op_desc(ccb->csio.cdb_io.cdb_bytes[0], &device->inq_data), 3156328820Smav scsi_cdb_string(ccb->csio.cdb_io.cdb_bytes, cdb_str, sizeof(cdb_str)))); 3157328820Smav} 3158