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$"); 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/interrupt.h> 44195534Sscottl#include <sys/sbuf.h> 45195534Sscottl 46195534Sscottl#include <sys/lock.h> 47195534Sscottl#include <sys/mutex.h> 48195534Sscottl#include <sys/sysctl.h> 49195534Sscottl 50195534Sscottl#include <cam/cam.h> 51195534Sscottl#include <cam/cam_ccb.h> 52195534Sscottl#include <cam/cam_queue.h> 53195534Sscottl#include <cam/cam_periph.h> 54195534Sscottl#include <cam/cam_sim.h> 55195534Sscottl#include <cam/cam_xpt.h> 56195534Sscottl#include <cam/cam_xpt_sim.h> 57195534Sscottl#include <cam/cam_xpt_periph.h> 58195534Sscottl#include <cam/cam_xpt_internal.h> 59195534Sscottl#include <cam/cam_debug.h> 60195534Sscottl 61195534Sscottl#include <cam/scsi/scsi_all.h> 62195534Sscottl#include <cam/scsi/scsi_message.h> 63195534Sscottl#include <cam/scsi/scsi_pass.h> 64195534Sscottl#include <machine/stdarg.h> /* for xpt_print below */ 65195534Sscottl#include "opt_cam.h" 66195534Sscottl 67195534Sscottlstruct scsi_quirk_entry { 68195534Sscottl struct scsi_inquiry_pattern inq_pat; 69195534Sscottl u_int8_t quirks; 70195534Sscottl#define CAM_QUIRK_NOLUNS 0x01 71216088Sken#define CAM_QUIRK_NOVPDS 0x02 72195534Sscottl#define CAM_QUIRK_HILUNS 0x04 73195534Sscottl#define CAM_QUIRK_NOHILUNS 0x08 74208911Smjacob#define CAM_QUIRK_NORPTLUNS 0x10 75195534Sscottl u_int mintags; 76195534Sscottl u_int maxtags; 77195534Sscottl}; 78195534Sscottl#define SCSI_QUIRK(dev) ((struct scsi_quirk_entry *)((dev)->quirk)) 79195534Sscottl 80195534Sscottlstatic int cam_srch_hi = 0; 81195534SscottlTUNABLE_INT("kern.cam.cam_srch_hi", &cam_srch_hi); 82195534Sscottlstatic int sysctl_cam_search_luns(SYSCTL_HANDLER_ARGS); 83195534SscottlSYSCTL_PROC(_kern_cam, OID_AUTO, cam_srch_hi, CTLTYPE_INT|CTLFLAG_RW, 0, 0, 84195534Sscottl sysctl_cam_search_luns, "I", 85195534Sscottl "allow search above LUN 7 for SCSI3 and greater devices"); 86195534Sscottl 87195534Sscottl#define CAM_SCSI2_MAXLUN 8 88208911Smjacob#define CAM_CAN_GET_SIMPLE_LUN(x, i) \ 89208911Smjacob ((((x)->luns[i].lundata[0] & RPL_LUNDATA_ATYP_MASK) == \ 90208911Smjacob RPL_LUNDATA_ATYP_PERIPH) || \ 91208911Smjacob (((x)->luns[i].lundata[0] & RPL_LUNDATA_ATYP_MASK) == \ 92208911Smjacob RPL_LUNDATA_ATYP_FLAT)) 93208911Smjacob#define CAM_GET_SIMPLE_LUN(lp, i, lval) \ 94208911Smjacob if (((lp)->luns[(i)].lundata[0] & RPL_LUNDATA_ATYP_MASK) == \ 95208911Smjacob RPL_LUNDATA_ATYP_PERIPH) { \ 96208911Smjacob (lval) = (lp)->luns[(i)].lundata[1]; \ 97208911Smjacob } else { \ 98208911Smjacob (lval) = (lp)->luns[(i)].lundata[0]; \ 99208911Smjacob (lval) &= RPL_LUNDATA_FLAT_LUN_MASK; \ 100208911Smjacob (lval) <<= 8; \ 101208911Smjacob (lval) |= (lp)->luns[(i)].lundata[1]; \ 102208911Smjacob } 103259204Snwhitehorn#define CAM_GET_LUN(lp, i, lval) \ 104259204Snwhitehorn (lval) = scsi_4btoul((lp)->luns[(i)].lundata); \ 105259204Snwhitehorn (lval) = ((lval) >> 16) | ((lval) << 16); 106259204Snwhitehorn#define CAM_LUN_ONLY_32BITS(lp, i) \ 107259204Snwhitehorn (scsi_4btoul(&((lp)->luns[(i)].lundata[4])) == 0) 108259204Snwhitehorn 109195534Sscottl/* 110195534Sscottl * If we're not quirked to search <= the first 8 luns 111195534Sscottl * and we are either quirked to search above lun 8, 112195534Sscottl * or we're > SCSI-2 and we've enabled hilun searching, 113195534Sscottl * or we're > SCSI-2 and the last lun was a success, 114195534Sscottl * we can look for luns above lun 8. 115195534Sscottl */ 116195534Sscottl#define CAN_SRCH_HI_SPARSE(dv) \ 117195534Sscottl (((SCSI_QUIRK(dv)->quirks & CAM_QUIRK_NOHILUNS) == 0) \ 118195534Sscottl && ((SCSI_QUIRK(dv)->quirks & CAM_QUIRK_HILUNS) \ 119195534Sscottl || (SID_ANSI_REV(&dv->inq_data) > SCSI_REV_2 && cam_srch_hi))) 120195534Sscottl 121195534Sscottl#define CAN_SRCH_HI_DENSE(dv) \ 122195534Sscottl (((SCSI_QUIRK(dv)->quirks & CAM_QUIRK_NOHILUNS) == 0) \ 123195534Sscottl && ((SCSI_QUIRK(dv)->quirks & CAM_QUIRK_HILUNS) \ 124195534Sscottl || (SID_ANSI_REV(&dv->inq_data) > SCSI_REV_2))) 125195534Sscottl 126195534Sscottlstatic periph_init_t probe_periph_init; 127195534Sscottl 128195534Sscottlstatic struct periph_driver probe_driver = 129195534Sscottl{ 130195534Sscottl probe_periph_init, "probe", 131198708Smav TAILQ_HEAD_INITIALIZER(probe_driver.units), /* generation */ 0, 132198708Smav CAM_PERIPH_DRV_EARLY 133195534Sscottl}; 134195534Sscottl 135195534SscottlPERIPHDRIVER_DECLARE(probe, probe_driver); 136195534Sscottl 137195534Sscottltypedef enum { 138195534Sscottl PROBE_TUR, 139195534Sscottl PROBE_INQUIRY, /* this counts as DV0 for Basic Domain Validation */ 140195534Sscottl PROBE_FULL_INQUIRY, 141208911Smjacob PROBE_REPORT_LUNS, 142195534Sscottl PROBE_MODE_SENSE, 143216088Sken PROBE_SUPPORTED_VPD_LIST, 144216088Sken PROBE_DEVICE_ID, 145216088Sken PROBE_SERIAL_NUM, 146195534Sscottl PROBE_TUR_FOR_NEGOTIATION, 147195534Sscottl PROBE_INQUIRY_BASIC_DV1, 148195534Sscottl PROBE_INQUIRY_BASIC_DV2, 149195534Sscottl PROBE_DV_EXIT, 150236613Smav PROBE_DONE, 151195534Sscottl PROBE_INVALID 152195534Sscottl} probe_action; 153195534Sscottl 154195534Sscottlstatic char *probe_action_text[] = { 155195534Sscottl "PROBE_TUR", 156195534Sscottl "PROBE_INQUIRY", 157195534Sscottl "PROBE_FULL_INQUIRY", 158208911Smjacob "PROBE_REPORT_LUNS", 159195534Sscottl "PROBE_MODE_SENSE", 160216088Sken "PROBE_SUPPORTED_VPD_LIST", 161216088Sken "PROBE_DEVICE_ID", 162216088Sken "PROBE_SERIAL_NUM", 163195534Sscottl "PROBE_TUR_FOR_NEGOTIATION", 164195534Sscottl "PROBE_INQUIRY_BASIC_DV1", 165195534Sscottl "PROBE_INQUIRY_BASIC_DV2", 166195534Sscottl "PROBE_DV_EXIT", 167236613Smav "PROBE_DONE", 168195534Sscottl "PROBE_INVALID" 169195534Sscottl}; 170195534Sscottl 171195534Sscottl#define PROBE_SET_ACTION(softc, newaction) \ 172195534Sscottldo { \ 173195534Sscottl char **text; \ 174195534Sscottl text = probe_action_text; \ 175236613Smav CAM_DEBUG((softc)->periph->path, CAM_DEBUG_PROBE, \ 176195534Sscottl ("Probe %s to %s\n", text[(softc)->action], \ 177195534Sscottl text[(newaction)])); \ 178195534Sscottl (softc)->action = (newaction); \ 179195534Sscottl} while(0) 180195534Sscottl 181195534Sscottltypedef enum { 182195534Sscottl PROBE_INQUIRY_CKSUM = 0x01, 183195534Sscottl PROBE_SERIAL_CKSUM = 0x02, 184259204Snwhitehorn PROBE_NO_ANNOUNCE = 0x04, 185259204Snwhitehorn PROBE_EXTLUN = 0x08 186195534Sscottl} probe_flags; 187195534Sscottl 188195534Sscottltypedef struct { 189195534Sscottl TAILQ_HEAD(, ccb_hdr) request_ccbs; 190195534Sscottl probe_action action; 191195534Sscottl union ccb saved_ccb; 192195534Sscottl probe_flags flags; 193195534Sscottl MD5_CTX context; 194195534Sscottl u_int8_t digest[16]; 195195534Sscottl struct cam_periph *periph; 196195534Sscottl} probe_softc; 197195534Sscottl 198195534Sscottlstatic const char quantum[] = "QUANTUM"; 199195534Sscottlstatic const char sony[] = "SONY"; 200195534Sscottlstatic const char west_digital[] = "WDIGTL"; 201195534Sscottlstatic const char samsung[] = "SAMSUNG"; 202195534Sscottlstatic const char seagate[] = "SEAGATE"; 203195534Sscottlstatic const char microp[] = "MICROP"; 204195534Sscottl 205195534Sscottlstatic struct scsi_quirk_entry scsi_quirk_table[] = 206195534Sscottl{ 207195534Sscottl { 208195534Sscottl /* Reports QUEUE FULL for temporary resource shortages */ 209195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, quantum, "XP39100*", "*" }, 210195534Sscottl /*quirks*/0, /*mintags*/24, /*maxtags*/32 211195534Sscottl }, 212195534Sscottl { 213195534Sscottl /* Reports QUEUE FULL for temporary resource shortages */ 214195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, quantum, "XP34550*", "*" }, 215195534Sscottl /*quirks*/0, /*mintags*/24, /*maxtags*/32 216195534Sscottl }, 217195534Sscottl { 218195534Sscottl /* Reports QUEUE FULL for temporary resource shortages */ 219195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, quantum, "XP32275*", "*" }, 220195534Sscottl /*quirks*/0, /*mintags*/24, /*maxtags*/32 221195534Sscottl }, 222195534Sscottl { 223195534Sscottl /* Broken tagged queuing drive */ 224195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, microp, "4421-07*", "*" }, 225195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 226195534Sscottl }, 227195534Sscottl { 228195534Sscottl /* Broken tagged queuing drive */ 229195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "HP", "C372*", "*" }, 230195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 231195534Sscottl }, 232195534Sscottl { 233195534Sscottl /* Broken tagged queuing drive */ 234195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, microp, "3391*", "x43h" }, 235195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 236195534Sscottl }, 237195534Sscottl { 238195534Sscottl /* 239195534Sscottl * Unfortunately, the Quantum Atlas III has the same 240195534Sscottl * problem as the Atlas II drives above. 241195534Sscottl * Reported by: "Johan Granlund" <johan@granlund.nu> 242195534Sscottl * 243195534Sscottl * For future reference, the drive with the problem was: 244195534Sscottl * QUANTUM QM39100TD-SW N1B0 245195534Sscottl * 246195534Sscottl * It's possible that Quantum will fix the problem in later 247195534Sscottl * firmware revisions. If that happens, the quirk entry 248195534Sscottl * will need to be made specific to the firmware revisions 249195534Sscottl * with the problem. 250195534Sscottl * 251195534Sscottl */ 252195534Sscottl /* Reports QUEUE FULL for temporary resource shortages */ 253195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, quantum, "QM39100*", "*" }, 254195534Sscottl /*quirks*/0, /*mintags*/24, /*maxtags*/32 255195534Sscottl }, 256195534Sscottl { 257195534Sscottl /* 258195534Sscottl * 18 Gig Atlas III, same problem as the 9G version. 259195534Sscottl * Reported by: Andre Albsmeier 260195534Sscottl * <andre.albsmeier@mchp.siemens.de> 261195534Sscottl * 262195534Sscottl * For future reference, the drive with the problem was: 263195534Sscottl * QUANTUM QM318000TD-S N491 264195534Sscottl */ 265195534Sscottl /* Reports QUEUE FULL for temporary resource shortages */ 266195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, quantum, "QM318000*", "*" }, 267195534Sscottl /*quirks*/0, /*mintags*/24, /*maxtags*/32 268195534Sscottl }, 269195534Sscottl { 270195534Sscottl /* 271195534Sscottl * Broken tagged queuing drive 272195534Sscottl * Reported by: Bret Ford <bford@uop.cs.uop.edu> 273195534Sscottl * and: Martin Renters <martin@tdc.on.ca> 274195534Sscottl */ 275195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST410800*", "71*" }, 276195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 277195534Sscottl }, 278195534Sscottl /* 279195534Sscottl * The Seagate Medalist Pro drives have very poor write 280195534Sscottl * performance with anything more than 2 tags. 281195534Sscottl * 282195534Sscottl * Reported by: Paul van der Zwan <paulz@trantor.xs4all.nl> 283195534Sscottl * Drive: <SEAGATE ST36530N 1444> 284195534Sscottl * 285195534Sscottl * Reported by: Jeremy Lea <reg@shale.csir.co.za> 286195534Sscottl * Drive: <SEAGATE ST34520W 1281> 287195534Sscottl * 288195534Sscottl * No one has actually reported that the 9G version 289195534Sscottl * (ST39140*) of the Medalist Pro has the same problem, but 290195534Sscottl * we're assuming that it does because the 4G and 6.5G 291195534Sscottl * versions of the drive are broken. 292195534Sscottl */ 293195534Sscottl { 294195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST34520*", "*"}, 295195534Sscottl /*quirks*/0, /*mintags*/2, /*maxtags*/2 296195534Sscottl }, 297195534Sscottl { 298195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST36530*", "*"}, 299195534Sscottl /*quirks*/0, /*mintags*/2, /*maxtags*/2 300195534Sscottl }, 301195534Sscottl { 302195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST39140*", "*"}, 303195534Sscottl /*quirks*/0, /*mintags*/2, /*maxtags*/2 304195534Sscottl }, 305195534Sscottl { 306195534Sscottl /* 307231745Sgibbs * Experiences command timeouts under load with a 308231745Sgibbs * tag count higher than 55. 309231745Sgibbs */ 310231745Sgibbs { T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST3146855LW", "*"}, 311231745Sgibbs /*quirks*/0, /*mintags*/2, /*maxtags*/55 312231745Sgibbs }, 313231745Sgibbs { 314231745Sgibbs /* 315195534Sscottl * Slow when tagged queueing is enabled. Write performance 316195534Sscottl * steadily drops off with more and more concurrent 317195534Sscottl * transactions. Best sequential write performance with 318195534Sscottl * tagged queueing turned off and write caching turned on. 319195534Sscottl * 320195534Sscottl * PR: kern/10398 321195534Sscottl * Submitted by: Hideaki Okada <hokada@isl.melco.co.jp> 322195534Sscottl * Drive: DCAS-34330 w/ "S65A" firmware. 323195534Sscottl * 324195534Sscottl * The drive with the problem had the "S65A" firmware 325195534Sscottl * revision, and has also been reported (by Stephen J. 326195534Sscottl * Roznowski <sjr@home.net>) for a drive with the "S61A" 327195534Sscottl * firmware revision. 328195534Sscottl * 329195534Sscottl * Although no one has reported problems with the 2 gig 330195534Sscottl * version of the DCAS drive, the assumption is that it 331195534Sscottl * has the same problems as the 4 gig version. Therefore 332195534Sscottl * this quirk entries disables tagged queueing for all 333195534Sscottl * DCAS drives. 334195534Sscottl */ 335195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "IBM", "DCAS*", "*" }, 336195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 337195534Sscottl }, 338195534Sscottl { 339195534Sscottl /* Broken tagged queuing drive */ 340195534Sscottl { T_DIRECT, SIP_MEDIA_REMOVABLE, "iomega", "jaz*", "*" }, 341195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 342195534Sscottl }, 343195534Sscottl { 344195534Sscottl /* Broken tagged queuing drive */ 345195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "CONNER", "CFP2107*", "*" }, 346195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 347195534Sscottl }, 348195534Sscottl { 349195534Sscottl /* This does not support other than LUN 0 */ 350195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "VMware*", "*", "*" }, 351195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/2, /*maxtags*/255 352195534Sscottl }, 353195534Sscottl { 354195534Sscottl /* 355195534Sscottl * Broken tagged queuing drive. 356195534Sscottl * Submitted by: 357195534Sscottl * NAKAJI Hiroyuki <nakaji@zeisei.dpri.kyoto-u.ac.jp> 358195534Sscottl * in PR kern/9535 359195534Sscottl */ 360195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, samsung, "WN34324U*", "*" }, 361195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 362195534Sscottl }, 363195534Sscottl { 364195534Sscottl /* 365195534Sscottl * Slow when tagged queueing is enabled. (1.5MB/sec versus 366195534Sscottl * 8MB/sec.) 367195534Sscottl * Submitted by: Andrew Gallatin <gallatin@cs.duke.edu> 368195534Sscottl * Best performance with these drives is achieved with 369195534Sscottl * tagged queueing turned off, and write caching turned on. 370195534Sscottl */ 371195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, west_digital, "WDE*", "*" }, 372195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 373195534Sscottl }, 374195534Sscottl { 375195534Sscottl /* 376195534Sscottl * Slow when tagged queueing is enabled. (1.5MB/sec versus 377195534Sscottl * 8MB/sec.) 378195534Sscottl * Submitted by: Andrew Gallatin <gallatin@cs.duke.edu> 379195534Sscottl * Best performance with these drives is achieved with 380195534Sscottl * tagged queueing turned off, and write caching turned on. 381195534Sscottl */ 382195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, west_digital, "ENTERPRISE", "*" }, 383195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 384195534Sscottl }, 385195534Sscottl { 386195534Sscottl /* 387195534Sscottl * Doesn't handle queue full condition correctly, 388195534Sscottl * so we need to limit maxtags to what the device 389195534Sscottl * can handle instead of determining this automatically. 390195534Sscottl */ 391195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, samsung, "WN321010S*", "*" }, 392195534Sscottl /*quirks*/0, /*mintags*/2, /*maxtags*/32 393195534Sscottl }, 394195534Sscottl { 395195534Sscottl /* Really only one LUN */ 396195534Sscottl { T_ENCLOSURE, SIP_MEDIA_FIXED, "SUN", "SENA", "*" }, 397195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 398195534Sscottl }, 399195534Sscottl { 400195534Sscottl /* I can't believe we need a quirk for DPT volumes. */ 401195534Sscottl { T_ANY, SIP_MEDIA_FIXED|SIP_MEDIA_REMOVABLE, "DPT", "*", "*" }, 402195534Sscottl CAM_QUIRK_NOLUNS, 403195534Sscottl /*mintags*/0, /*maxtags*/255 404195534Sscottl }, 405195534Sscottl { 406195534Sscottl /* 407195534Sscottl * Many Sony CDROM drives don't like multi-LUN probing. 408195534Sscottl */ 409195534Sscottl { T_CDROM, SIP_MEDIA_REMOVABLE, sony, "CD-ROM CDU*", "*" }, 410195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 411195534Sscottl }, 412195534Sscottl { 413195534Sscottl /* 414195534Sscottl * This drive doesn't like multiple LUN probing. 415195534Sscottl * Submitted by: Parag Patel <parag@cgt.com> 416195534Sscottl */ 417195534Sscottl { T_WORM, SIP_MEDIA_REMOVABLE, sony, "CD-R CDU9*", "*" }, 418195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 419195534Sscottl }, 420195534Sscottl { 421195534Sscottl { T_WORM, SIP_MEDIA_REMOVABLE, "YAMAHA", "CDR100*", "*" }, 422195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 423195534Sscottl }, 424195534Sscottl { 425195534Sscottl /* 426195534Sscottl * The 8200 doesn't like multi-lun probing, and probably 427195534Sscottl * don't like serial number requests either. 428195534Sscottl */ 429195534Sscottl { 430195534Sscottl T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "EXABYTE", 431195534Sscottl "EXB-8200*", "*" 432195534Sscottl }, 433195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 434195534Sscottl }, 435195534Sscottl { 436195534Sscottl /* 437195534Sscottl * Let's try the same as above, but for a drive that says 438195534Sscottl * it's an IPL-6860 but is actually an EXB 8200. 439195534Sscottl */ 440195534Sscottl { 441195534Sscottl T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "EXABYTE", 442195534Sscottl "IPL-6860*", "*" 443195534Sscottl }, 444195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 445195534Sscottl }, 446195534Sscottl { 447195534Sscottl /* 448195534Sscottl * These Hitachi drives don't like multi-lun probing. 449195534Sscottl * The PR submitter has a DK319H, but says that the Linux 450195534Sscottl * kernel has a similar work-around for the DK312 and DK314, 451195534Sscottl * so all DK31* drives are quirked here. 452195534Sscottl * PR: misc/18793 453195534Sscottl * Submitted by: Paul Haddad <paul@pth.com> 454195534Sscottl */ 455195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "HITACHI", "DK31*", "*" }, 456195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/2, /*maxtags*/255 457195534Sscottl }, 458195534Sscottl { 459195534Sscottl /* 460195534Sscottl * The Hitachi CJ series with J8A8 firmware apparantly has 461195534Sscottl * problems with tagged commands. 462195534Sscottl * PR: 23536 463195534Sscottl * Reported by: amagai@nue.org 464195534Sscottl */ 465195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "HITACHI", "DK32CJ*", "J8A8" }, 466195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 467195534Sscottl }, 468195534Sscottl { 469195534Sscottl /* 470195534Sscottl * These are the large storage arrays. 471195534Sscottl * Submitted by: William Carrel <william.carrel@infospace.com> 472195534Sscottl */ 473195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "HITACHI", "OPEN*", "*" }, 474195534Sscottl CAM_QUIRK_HILUNS, 2, 1024 475195534Sscottl }, 476195534Sscottl { 477195534Sscottl /* 478195534Sscottl * This old revision of the TDC3600 is also SCSI-1, and 479195534Sscottl * hangs upon serial number probing. 480195534Sscottl */ 481195534Sscottl { 482195534Sscottl T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG", 483195534Sscottl " TDC 3600", "U07:" 484195534Sscottl }, 485216088Sken CAM_QUIRK_NOVPDS, /*mintags*/0, /*maxtags*/0 486195534Sscottl }, 487195534Sscottl { 488195534Sscottl /* 489195534Sscottl * Would repond to all LUNs if asked for. 490195534Sscottl */ 491195534Sscottl { 492195534Sscottl T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "CALIPER", 493195534Sscottl "CP150", "*" 494195534Sscottl }, 495195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 496195534Sscottl }, 497195534Sscottl { 498195534Sscottl /* 499195534Sscottl * Would repond to all LUNs if asked for. 500195534Sscottl */ 501195534Sscottl { 502195534Sscottl T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "KENNEDY", 503195534Sscottl "96X2*", "*" 504195534Sscottl }, 505195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 506195534Sscottl }, 507195534Sscottl { 508195534Sscottl /* Submitted by: Matthew Dodd <winter@jurai.net> */ 509195534Sscottl { T_PROCESSOR, SIP_MEDIA_FIXED, "Cabletrn", "EA41*", "*" }, 510195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 511195534Sscottl }, 512195534Sscottl { 513195534Sscottl /* Submitted by: Matthew Dodd <winter@jurai.net> */ 514195534Sscottl { T_PROCESSOR, SIP_MEDIA_FIXED, "CABLETRN", "EA41*", "*" }, 515195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 516195534Sscottl }, 517195534Sscottl { 518195534Sscottl /* TeraSolutions special settings for TRC-22 RAID */ 519195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "TERASOLU", "TRC-22", "*" }, 520195534Sscottl /*quirks*/0, /*mintags*/55, /*maxtags*/255 521195534Sscottl }, 522195534Sscottl { 523195534Sscottl /* Veritas Storage Appliance */ 524195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "VERITAS", "*", "*" }, 525195534Sscottl CAM_QUIRK_HILUNS, /*mintags*/2, /*maxtags*/1024 526195534Sscottl }, 527195534Sscottl { 528195534Sscottl /* 529195534Sscottl * Would respond to all LUNs. Device type and removable 530195534Sscottl * flag are jumper-selectable. 531195534Sscottl */ 532195534Sscottl { T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED, "MaxOptix", 533195534Sscottl "Tahiti 1", "*" 534195534Sscottl }, 535195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 536195534Sscottl }, 537195534Sscottl { 538195534Sscottl /* EasyRAID E5A aka. areca ARC-6010 */ 539195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "easyRAID", "*", "*" }, 540195534Sscottl CAM_QUIRK_NOHILUNS, /*mintags*/2, /*maxtags*/255 541195534Sscottl }, 542195534Sscottl { 543195534Sscottl { T_ENCLOSURE, SIP_MEDIA_FIXED, "DP", "BACKPLANE", "*" }, 544195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 545195534Sscottl }, 546195534Sscottl { 547236283Seadler { T_DIRECT, SIP_MEDIA_REMOVABLE, "Garmin", "*", "*" }, 548236283Seadler CAM_QUIRK_NORPTLUNS, /*mintags*/2, /*maxtags*/255 549236283Seadler }, 550236283Seadler { 551195534Sscottl /* Default tagged queuing parameters for all devices */ 552195534Sscottl { 553195534Sscottl T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED, 554195534Sscottl /*vendor*/"*", /*product*/"*", /*revision*/"*" 555195534Sscottl }, 556195534Sscottl /*quirks*/0, /*mintags*/2, /*maxtags*/255 557195534Sscottl }, 558195534Sscottl}; 559195534Sscottl 560195534Sscottlstatic const int scsi_quirk_table_size = 561195534Sscottl sizeof(scsi_quirk_table) / sizeof(*scsi_quirk_table); 562195534Sscottl 563195534Sscottlstatic cam_status proberegister(struct cam_periph *periph, 564195534Sscottl void *arg); 565195534Sscottlstatic void probeschedule(struct cam_periph *probe_periph); 566195534Sscottlstatic void probestart(struct cam_periph *periph, union ccb *start_ccb); 567195534Sscottlstatic void proberequestdefaultnegotiation(struct cam_periph *periph); 568195534Sscottlstatic int proberequestbackoff(struct cam_periph *periph, 569195534Sscottl struct cam_ed *device); 570195534Sscottlstatic void probedone(struct cam_periph *periph, union ccb *done_ccb); 571208911Smjacobstatic void probe_purge_old(struct cam_path *path, 572259204Snwhitehorn struct scsi_report_luns_data *new, 573259204Snwhitehorn probe_flags flags); 574195534Sscottlstatic void probecleanup(struct cam_periph *periph); 575195534Sscottlstatic void scsi_find_quirk(struct cam_ed *device); 576195534Sscottlstatic void scsi_scan_bus(struct cam_periph *periph, union ccb *ccb); 577195534Sscottlstatic void scsi_scan_lun(struct cam_periph *periph, 578195534Sscottl struct cam_path *path, cam_flags flags, 579195534Sscottl union ccb *ccb); 580195534Sscottlstatic void xptscandone(struct cam_periph *periph, union ccb *done_ccb); 581195534Sscottlstatic struct cam_ed * 582195534Sscottl scsi_alloc_device(struct cam_eb *bus, struct cam_et *target, 583195534Sscottl lun_id_t lun_id); 584195534Sscottlstatic void scsi_devise_transport(struct cam_path *path); 585195534Sscottlstatic void scsi_set_transfer_settings(struct ccb_trans_settings *cts, 586260387Sscottl struct cam_path *path, 587195534Sscottl int async_update); 588195534Sscottlstatic void scsi_toggle_tags(struct cam_path *path); 589195534Sscottlstatic void scsi_dev_async(u_int32_t async_code, 590195534Sscottl struct cam_eb *bus, 591195534Sscottl struct cam_et *target, 592195534Sscottl struct cam_ed *device, 593195534Sscottl void *async_arg); 594195534Sscottlstatic void scsi_action(union ccb *start_ccb); 595204220Smavstatic void scsi_announce_periph(struct cam_periph *periph); 596195534Sscottl 597195534Sscottlstatic struct xpt_xport scsi_xport = { 598195534Sscottl .alloc_device = scsi_alloc_device, 599195534Sscottl .action = scsi_action, 600195534Sscottl .async = scsi_dev_async, 601204220Smav .announce = scsi_announce_periph, 602195534Sscottl}; 603195534Sscottl 604195534Sscottlstruct xpt_xport * 605195534Sscottlscsi_get_xport(void) 606195534Sscottl{ 607195534Sscottl return (&scsi_xport); 608195534Sscottl} 609195534Sscottl 610195534Sscottlstatic void 611195534Sscottlprobe_periph_init() 612195534Sscottl{ 613195534Sscottl} 614195534Sscottl 615195534Sscottlstatic cam_status 616195534Sscottlproberegister(struct cam_periph *periph, void *arg) 617195534Sscottl{ 618195534Sscottl union ccb *request_ccb; /* CCB representing the probe request */ 619195534Sscottl cam_status status; 620195534Sscottl probe_softc *softc; 621195534Sscottl 622195534Sscottl request_ccb = (union ccb *)arg; 623195534Sscottl if (request_ccb == NULL) { 624195534Sscottl printf("proberegister: no probe CCB, " 625195534Sscottl "can't register device\n"); 626195534Sscottl return(CAM_REQ_CMP_ERR); 627195534Sscottl } 628195534Sscottl 629195534Sscottl softc = (probe_softc *)malloc(sizeof(*softc), M_CAMXPT, M_NOWAIT); 630195534Sscottl 631195534Sscottl if (softc == NULL) { 632195534Sscottl printf("proberegister: Unable to probe new device. " 633195534Sscottl "Unable to allocate softc\n"); 634195534Sscottl return(CAM_REQ_CMP_ERR); 635195534Sscottl } 636195534Sscottl TAILQ_INIT(&softc->request_ccbs); 637195534Sscottl TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h, 638195534Sscottl periph_links.tqe); 639195534Sscottl softc->flags = 0; 640195534Sscottl periph->softc = softc; 641195534Sscottl softc->periph = periph; 642195534Sscottl softc->action = PROBE_INVALID; 643195534Sscottl status = cam_periph_acquire(periph); 644195534Sscottl if (status != CAM_REQ_CMP) { 645195534Sscottl return (status); 646195534Sscottl } 647236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe started\n")); 648260387Sscottl scsi_devise_transport(periph->path); 649195534Sscottl 650195534Sscottl /* 651195534Sscottl * Ensure we've waited at least a bus settle 652195534Sscottl * delay before attempting to probe the device. 653195534Sscottl * For HBAs that don't do bus resets, this won't make a difference. 654195534Sscottl */ 655195534Sscottl cam_periph_freeze_after_event(periph, &periph->path->bus->last_reset, 656195534Sscottl scsi_delay); 657195534Sscottl probeschedule(periph); 658195534Sscottl return(CAM_REQ_CMP); 659195534Sscottl} 660195534Sscottl 661195534Sscottlstatic void 662195534Sscottlprobeschedule(struct cam_periph *periph) 663195534Sscottl{ 664195534Sscottl struct ccb_pathinq cpi; 665195534Sscottl union ccb *ccb; 666195534Sscottl probe_softc *softc; 667195534Sscottl 668195534Sscottl softc = (probe_softc *)periph->softc; 669195534Sscottl ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs); 670195534Sscottl 671203108Smav xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NONE); 672195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 673195534Sscottl xpt_action((union ccb *)&cpi); 674195534Sscottl 675195534Sscottl /* 676195534Sscottl * If a device has gone away and another device, or the same one, 677195534Sscottl * is back in the same place, it should have a unit attention 678195534Sscottl * condition pending. It will not report the unit attention in 679195534Sscottl * response to an inquiry, which may leave invalid transfer 680195534Sscottl * negotiations in effect. The TUR will reveal the unit attention 681195534Sscottl * condition. Only send the TUR for lun 0, since some devices 682195534Sscottl * will get confused by commands other than inquiry to non-existent 683195534Sscottl * luns. If you think a device has gone away start your scan from 684195534Sscottl * lun 0. This will insure that any bogus transfer settings are 685195534Sscottl * invalidated. 686195534Sscottl * 687195534Sscottl * If we haven't seen the device before and the controller supports 688195534Sscottl * some kind of transfer negotiation, negotiate with the first 689195534Sscottl * sent command if no bus reset was performed at startup. This 690195534Sscottl * ensures that the device is not confused by transfer negotiation 691195534Sscottl * settings left over by loader or BIOS action. 692195534Sscottl */ 693195534Sscottl if (((ccb->ccb_h.path->device->flags & CAM_DEV_UNCONFIGURED) == 0) 694195534Sscottl && (ccb->ccb_h.target_lun == 0)) { 695195534Sscottl PROBE_SET_ACTION(softc, PROBE_TUR); 696195534Sscottl } else if ((cpi.hba_inquiry & (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE)) != 0 697195534Sscottl && (cpi.hba_misc & PIM_NOBUSRESET) != 0) { 698195534Sscottl proberequestdefaultnegotiation(periph); 699195534Sscottl PROBE_SET_ACTION(softc, PROBE_INQUIRY); 700195534Sscottl } else { 701195534Sscottl PROBE_SET_ACTION(softc, PROBE_INQUIRY); 702195534Sscottl } 703195534Sscottl 704195534Sscottl if (ccb->crcn.flags & CAM_EXPECT_INQ_CHANGE) 705195534Sscottl softc->flags |= PROBE_NO_ANNOUNCE; 706195534Sscottl else 707195534Sscottl softc->flags &= ~PROBE_NO_ANNOUNCE; 708195534Sscottl 709259204Snwhitehorn if (cpi.hba_misc & PIM_EXTLUNS) 710259204Snwhitehorn softc->flags |= PROBE_EXTLUN; 711259204Snwhitehorn else 712259204Snwhitehorn softc->flags &= ~PROBE_EXTLUN; 713259204Snwhitehorn 714203108Smav xpt_schedule(periph, CAM_PRIORITY_XPT); 715195534Sscottl} 716195534Sscottl 717195534Sscottlstatic void 718195534Sscottlprobestart(struct cam_periph *periph, union ccb *start_ccb) 719195534Sscottl{ 720195534Sscottl /* Probe the device that our peripheral driver points to */ 721195534Sscottl struct ccb_scsiio *csio; 722195534Sscottl probe_softc *softc; 723195534Sscottl 724195534Sscottl CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probestart\n")); 725195534Sscottl 726195534Sscottl softc = (probe_softc *)periph->softc; 727195534Sscottl csio = &start_ccb->csio; 728208911Smjacobagain: 729195534Sscottl 730195534Sscottl switch (softc->action) { 731195534Sscottl case PROBE_TUR: 732195534Sscottl case PROBE_TUR_FOR_NEGOTIATION: 733195534Sscottl case PROBE_DV_EXIT: 734195534Sscottl { 735195534Sscottl scsi_test_unit_ready(csio, 736236814Smav /*retries*/4, 737195534Sscottl probedone, 738195534Sscottl MSG_SIMPLE_Q_TAG, 739195534Sscottl SSD_FULL_SIZE, 740195534Sscottl /*timeout*/60000); 741195534Sscottl break; 742195534Sscottl } 743195534Sscottl case PROBE_INQUIRY: 744195534Sscottl case PROBE_FULL_INQUIRY: 745195534Sscottl case PROBE_INQUIRY_BASIC_DV1: 746195534Sscottl case PROBE_INQUIRY_BASIC_DV2: 747195534Sscottl { 748195534Sscottl u_int inquiry_len; 749195534Sscottl struct scsi_inquiry_data *inq_buf; 750195534Sscottl 751195534Sscottl inq_buf = &periph->path->device->inq_data; 752195534Sscottl 753195534Sscottl /* 754195534Sscottl * If the device is currently configured, we calculate an 755195534Sscottl * MD5 checksum of the inquiry data, and if the serial number 756195534Sscottl * length is greater than 0, add the serial number data 757195534Sscottl * into the checksum as well. Once the inquiry and the 758195534Sscottl * serial number check finish, we attempt to figure out 759195534Sscottl * whether we still have the same device. 760195534Sscottl */ 761195534Sscottl if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) { 762195534Sscottl 763195534Sscottl MD5Init(&softc->context); 764195534Sscottl MD5Update(&softc->context, (unsigned char *)inq_buf, 765195534Sscottl sizeof(struct scsi_inquiry_data)); 766195534Sscottl softc->flags |= PROBE_INQUIRY_CKSUM; 767195534Sscottl if (periph->path->device->serial_num_len > 0) { 768195534Sscottl MD5Update(&softc->context, 769195534Sscottl periph->path->device->serial_num, 770195534Sscottl periph->path->device->serial_num_len); 771195534Sscottl softc->flags |= PROBE_SERIAL_CKSUM; 772195534Sscottl } 773195534Sscottl MD5Final(softc->digest, &softc->context); 774195534Sscottl } 775195534Sscottl 776195534Sscottl if (softc->action == PROBE_INQUIRY) 777195534Sscottl inquiry_len = SHORT_INQUIRY_LENGTH; 778195534Sscottl else 779195534Sscottl inquiry_len = SID_ADDITIONAL_LENGTH(inq_buf); 780195534Sscottl 781195534Sscottl /* 782195534Sscottl * Some parallel SCSI devices fail to send an 783195534Sscottl * ignore wide residue message when dealing with 784195534Sscottl * odd length inquiry requests. Round up to be 785195534Sscottl * safe. 786195534Sscottl */ 787195534Sscottl inquiry_len = roundup2(inquiry_len, 2); 788195534Sscottl 789195534Sscottl if (softc->action == PROBE_INQUIRY_BASIC_DV1 790195534Sscottl || softc->action == PROBE_INQUIRY_BASIC_DV2) { 791195534Sscottl inq_buf = malloc(inquiry_len, M_CAMXPT, M_NOWAIT); 792195534Sscottl } 793195534Sscottl if (inq_buf == NULL) { 794195534Sscottl xpt_print(periph->path, "malloc failure- skipping Basic" 795195534Sscottl "Domain Validation\n"); 796195534Sscottl PROBE_SET_ACTION(softc, PROBE_DV_EXIT); 797195534Sscottl scsi_test_unit_ready(csio, 798195534Sscottl /*retries*/4, 799195534Sscottl probedone, 800195534Sscottl MSG_SIMPLE_Q_TAG, 801195534Sscottl SSD_FULL_SIZE, 802195534Sscottl /*timeout*/60000); 803195534Sscottl break; 804195534Sscottl } 805195534Sscottl scsi_inquiry(csio, 806195534Sscottl /*retries*/4, 807195534Sscottl probedone, 808195534Sscottl MSG_SIMPLE_Q_TAG, 809195534Sscottl (u_int8_t *)inq_buf, 810195534Sscottl inquiry_len, 811195534Sscottl /*evpd*/FALSE, 812195534Sscottl /*page_code*/0, 813195534Sscottl SSD_MIN_SIZE, 814195534Sscottl /*timeout*/60 * 1000); 815195534Sscottl break; 816195534Sscottl } 817208911Smjacob case PROBE_REPORT_LUNS: 818208911Smjacob { 819208911Smjacob void *rp; 820208911Smjacob 821208911Smjacob rp = malloc(periph->path->target->rpl_size, 822208911Smjacob M_CAMXPT, M_NOWAIT | M_ZERO); 823208911Smjacob if (rp == NULL) { 824208911Smjacob struct scsi_inquiry_data *inq_buf; 825208911Smjacob inq_buf = &periph->path->device->inq_data; 826208911Smjacob xpt_print(periph->path, 827208911Smjacob "Unable to alloc report luns storage\n"); 828208911Smjacob if (INQ_DATA_TQ_ENABLED(inq_buf)) 829208911Smjacob PROBE_SET_ACTION(softc, PROBE_MODE_SENSE); 830208911Smjacob else 831216088Sken PROBE_SET_ACTION(softc, 832216088Sken PROBE_SUPPORTED_VPD_LIST); 833208911Smjacob goto again; 834208911Smjacob } 835208911Smjacob scsi_report_luns(csio, 5, probedone, MSG_SIMPLE_Q_TAG, 836208911Smjacob RPL_REPORT_DEFAULT, rp, periph->path->target->rpl_size, 837208911Smjacob SSD_FULL_SIZE, 60000); break; 838208911Smjacob break; 839208911Smjacob } 840195534Sscottl case PROBE_MODE_SENSE: 841195534Sscottl { 842195534Sscottl void *mode_buf; 843195534Sscottl int mode_buf_len; 844195534Sscottl 845195534Sscottl mode_buf_len = sizeof(struct scsi_mode_header_6) 846195534Sscottl + sizeof(struct scsi_mode_blk_desc) 847195534Sscottl + sizeof(struct scsi_control_page); 848195534Sscottl mode_buf = malloc(mode_buf_len, M_CAMXPT, M_NOWAIT); 849195534Sscottl if (mode_buf != NULL) { 850195534Sscottl scsi_mode_sense(csio, 851195534Sscottl /*retries*/4, 852195534Sscottl probedone, 853195534Sscottl MSG_SIMPLE_Q_TAG, 854195534Sscottl /*dbd*/FALSE, 855195534Sscottl SMS_PAGE_CTRL_CURRENT, 856195534Sscottl SMS_CONTROL_MODE_PAGE, 857195534Sscottl mode_buf, 858195534Sscottl mode_buf_len, 859195534Sscottl SSD_FULL_SIZE, 860195534Sscottl /*timeout*/60000); 861195534Sscottl break; 862195534Sscottl } 863195534Sscottl xpt_print(periph->path, "Unable to mode sense control page - " 864195534Sscottl "malloc failure\n"); 865216088Sken PROBE_SET_ACTION(softc, PROBE_SUPPORTED_VPD_LIST); 866195534Sscottl } 867195534Sscottl /* FALLTHROUGH */ 868216088Sken case PROBE_SUPPORTED_VPD_LIST: 869195534Sscottl { 870216088Sken struct scsi_vpd_supported_page_list *vpd_list; 871195534Sscottl struct cam_ed *device; 872195534Sscottl 873216088Sken vpd_list = NULL; 874195534Sscottl device = periph->path->device; 875216088Sken 876216088Sken if ((SCSI_QUIRK(device)->quirks & CAM_QUIRK_NOVPDS) == 0) 877195534Sscottl vpd_list = malloc(sizeof(*vpd_list), M_CAMXPT, 878195534Sscottl M_NOWAIT | M_ZERO); 879195534Sscottl 880195534Sscottl if (vpd_list != NULL) { 881195534Sscottl scsi_inquiry(csio, 882195534Sscottl /*retries*/4, 883195534Sscottl probedone, 884195534Sscottl MSG_SIMPLE_Q_TAG, 885195534Sscottl (u_int8_t *)vpd_list, 886195534Sscottl sizeof(*vpd_list), 887195534Sscottl /*evpd*/TRUE, 888195534Sscottl SVPD_SUPPORTED_PAGE_LIST, 889195534Sscottl SSD_MIN_SIZE, 890195534Sscottl /*timeout*/60 * 1000); 891195534Sscottl break; 892195534Sscottl } 893260626Smavdone: 894195534Sscottl /* 895195534Sscottl * We'll have to do without, let our probedone 896195534Sscottl * routine finish up for us. 897195534Sscottl */ 898195534Sscottl start_ccb->csio.data_ptr = NULL; 899250025Smav cam_freeze_devq(periph->path); 900260626Smav cam_periph_doacquire(periph); 901195534Sscottl probedone(periph, start_ccb); 902195534Sscottl return; 903195534Sscottl } 904216088Sken case PROBE_DEVICE_ID: 905195534Sscottl { 906216088Sken struct scsi_vpd_device_id *devid; 907216088Sken 908216088Sken devid = NULL; 909249937Ssmh if (scsi_vpd_supported_page(periph, SVPD_DEVICE_ID)) 910216088Sken devid = malloc(SVPD_DEVICE_ID_MAX_SIZE, M_CAMXPT, 911216088Sken M_NOWAIT | M_ZERO); 912216088Sken 913216088Sken if (devid != NULL) { 914216088Sken scsi_inquiry(csio, 915216088Sken /*retries*/4, 916216088Sken probedone, 917216088Sken MSG_SIMPLE_Q_TAG, 918216088Sken (uint8_t *)devid, 919216088Sken SVPD_DEVICE_ID_MAX_SIZE, 920216088Sken /*evpd*/TRUE, 921216088Sken SVPD_DEVICE_ID, 922216088Sken SSD_MIN_SIZE, 923216088Sken /*timeout*/60 * 1000); 924216088Sken break; 925216088Sken } 926260626Smav goto done; 927216088Sken } 928216088Sken case PROBE_SERIAL_NUM: 929216088Sken { 930195534Sscottl struct scsi_vpd_unit_serial_number *serial_buf; 931195534Sscottl struct cam_ed* device; 932195534Sscottl 933195534Sscottl serial_buf = NULL; 934195534Sscottl device = periph->path->device; 935195685Semaste if (device->serial_num != NULL) { 936195685Semaste free(device->serial_num, M_CAMXPT); 937195685Semaste device->serial_num = NULL; 938195685Semaste device->serial_num_len = 0; 939195685Semaste } 940195534Sscottl 941249937Ssmh if (scsi_vpd_supported_page(periph, SVPD_UNIT_SERIAL_NUMBER)) 942216088Sken serial_buf = (struct scsi_vpd_unit_serial_number *) 943216088Sken malloc(sizeof(*serial_buf), M_CAMXPT, 944216088Sken M_NOWAIT|M_ZERO); 945195534Sscottl 946195534Sscottl if (serial_buf != NULL) { 947195534Sscottl scsi_inquiry(csio, 948195534Sscottl /*retries*/4, 949195534Sscottl probedone, 950195534Sscottl MSG_SIMPLE_Q_TAG, 951195534Sscottl (u_int8_t *)serial_buf, 952195534Sscottl sizeof(*serial_buf), 953195534Sscottl /*evpd*/TRUE, 954195534Sscottl SVPD_UNIT_SERIAL_NUMBER, 955195534Sscottl SSD_MIN_SIZE, 956195534Sscottl /*timeout*/60 * 1000); 957195534Sscottl break; 958195534Sscottl } 959260626Smav goto done; 960195534Sscottl } 961195534Sscottl default: 962236613Smav panic("probestart: invalid action state 0x%x\n", softc->action); 963195534Sscottl } 964249466Smav start_ccb->ccb_h.flags |= CAM_DEV_QFREEZE; 965260626Smav cam_periph_doacquire(periph); 966195534Sscottl xpt_action(start_ccb); 967195534Sscottl} 968195534Sscottl 969195534Sscottlstatic void 970195534Sscottlproberequestdefaultnegotiation(struct cam_periph *periph) 971195534Sscottl{ 972195534Sscottl struct ccb_trans_settings cts; 973195534Sscottl 974203108Smav xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE); 975195534Sscottl cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 976195534Sscottl cts.type = CTS_TYPE_USER_SETTINGS; 977195534Sscottl xpt_action((union ccb *)&cts); 978252382Sscottl if (cam_ccb_status((union ccb *)&cts) != CAM_REQ_CMP) { 979195534Sscottl return; 980195534Sscottl } 981195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 982195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 983195534Sscottl xpt_action((union ccb *)&cts); 984195534Sscottl} 985195534Sscottl 986195534Sscottl/* 987195534Sscottl * Backoff Negotiation Code- only pertinent for SPI devices. 988195534Sscottl */ 989195534Sscottlstatic int 990195534Sscottlproberequestbackoff(struct cam_periph *periph, struct cam_ed *device) 991195534Sscottl{ 992195534Sscottl struct ccb_trans_settings cts; 993195534Sscottl struct ccb_trans_settings_spi *spi; 994195534Sscottl 995195534Sscottl memset(&cts, 0, sizeof (cts)); 996203108Smav xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE); 997195534Sscottl cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 998195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 999195534Sscottl xpt_action((union ccb *)&cts); 1000252382Sscottl if (cam_ccb_status((union ccb *)&cts) != CAM_REQ_CMP) { 1001195534Sscottl if (bootverbose) { 1002195534Sscottl xpt_print(periph->path, 1003195534Sscottl "failed to get current device settings\n"); 1004195534Sscottl } 1005195534Sscottl return (0); 1006195534Sscottl } 1007195534Sscottl if (cts.transport != XPORT_SPI) { 1008195534Sscottl if (bootverbose) { 1009195534Sscottl xpt_print(periph->path, "not SPI transport\n"); 1010195534Sscottl } 1011195534Sscottl return (0); 1012195534Sscottl } 1013195534Sscottl spi = &cts.xport_specific.spi; 1014195534Sscottl 1015195534Sscottl /* 1016195534Sscottl * We cannot renegotiate sync rate if we don't have one. 1017195534Sscottl */ 1018195534Sscottl if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) { 1019195534Sscottl if (bootverbose) { 1020195534Sscottl xpt_print(periph->path, "no sync rate known\n"); 1021195534Sscottl } 1022195534Sscottl return (0); 1023195534Sscottl } 1024195534Sscottl 1025195534Sscottl /* 1026195534Sscottl * We'll assert that we don't have to touch PPR options- the 1027195534Sscottl * SIM will see what we do with period and offset and adjust 1028195534Sscottl * the PPR options as appropriate. 1029195534Sscottl */ 1030195534Sscottl 1031195534Sscottl /* 1032195534Sscottl * A sync rate with unknown or zero offset is nonsensical. 1033195534Sscottl * A sync period of zero means Async. 1034195534Sscottl */ 1035195534Sscottl if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0 1036195534Sscottl || spi->sync_offset == 0 || spi->sync_period == 0) { 1037195534Sscottl if (bootverbose) { 1038195534Sscottl xpt_print(periph->path, "no sync rate available\n"); 1039195534Sscottl } 1040195534Sscottl return (0); 1041195534Sscottl } 1042195534Sscottl 1043195534Sscottl if (device->flags & CAM_DEV_DV_HIT_BOTTOM) { 1044236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, 1045195534Sscottl ("hit async: giving up on DV\n")); 1046195534Sscottl return (0); 1047195534Sscottl } 1048195534Sscottl 1049195534Sscottl 1050195534Sscottl /* 1051195534Sscottl * Jump sync_period up by one, but stop at 5MHz and fall back to Async. 1052195534Sscottl * We don't try to remember 'last' settings to see if the SIM actually 1053195534Sscottl * gets into the speed we want to set. We check on the SIM telling 1054195534Sscottl * us that a requested speed is bad, but otherwise don't try and 1055195534Sscottl * check the speed due to the asynchronous and handshake nature 1056195534Sscottl * of speed setting. 1057195534Sscottl */ 1058195534Sscottl spi->valid = CTS_SPI_VALID_SYNC_RATE | CTS_SPI_VALID_SYNC_OFFSET; 1059195534Sscottl for (;;) { 1060195534Sscottl spi->sync_period++; 1061195534Sscottl if (spi->sync_period >= 0xf) { 1062195534Sscottl spi->sync_period = 0; 1063195534Sscottl spi->sync_offset = 0; 1064236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, 1065195534Sscottl ("setting to async for DV\n")); 1066195534Sscottl /* 1067195534Sscottl * Once we hit async, we don't want to try 1068195534Sscottl * any more settings. 1069195534Sscottl */ 1070195534Sscottl device->flags |= CAM_DEV_DV_HIT_BOTTOM; 1071195534Sscottl } else if (bootverbose) { 1072236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, 1073195534Sscottl ("DV: period 0x%x\n", spi->sync_period)); 1074195534Sscottl printf("setting period to 0x%x\n", spi->sync_period); 1075195534Sscottl } 1076195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1077195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 1078195534Sscottl xpt_action((union ccb *)&cts); 1079252382Sscottl if (cam_ccb_status((union ccb *)&cts) != CAM_REQ_CMP) { 1080195534Sscottl break; 1081195534Sscottl } 1082236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, 1083195534Sscottl ("DV: failed to set period 0x%x\n", spi->sync_period)); 1084195534Sscottl if (spi->sync_period == 0) { 1085195534Sscottl return (0); 1086195534Sscottl } 1087195534Sscottl } 1088195534Sscottl return (1); 1089195534Sscottl} 1090195534Sscottl 1091216088Sken#define CCB_COMPLETED_OK(ccb) (((ccb).status & CAM_STATUS_MASK) == CAM_REQ_CMP) 1092216088Sken 1093195534Sscottlstatic void 1094195534Sscottlprobedone(struct cam_periph *periph, union ccb *done_ccb) 1095195534Sscottl{ 1096195534Sscottl probe_softc *softc; 1097195534Sscottl struct cam_path *path; 1098195534Sscottl u_int32_t priority; 1099195534Sscottl 1100195534Sscottl CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probedone\n")); 1101195534Sscottl 1102195534Sscottl softc = (probe_softc *)periph->softc; 1103195534Sscottl path = done_ccb->ccb_h.path; 1104195534Sscottl priority = done_ccb->ccb_h.pinfo.priority; 1105195534Sscottl 1106195534Sscottl switch (softc->action) { 1107195534Sscottl case PROBE_TUR: 1108195534Sscottl { 1109252382Sscottl if (cam_ccb_status(done_ccb) != CAM_REQ_CMP) { 1110195534Sscottl 1111195534Sscottl if (cam_periph_error(done_ccb, 0, 1112249466Smav SF_NO_PRINT, NULL) == ERESTART) { 1113260626Smavoutr: 1114249466Smav /* Drop freeze taken due to CAM_DEV_QFREEZE */ 1115249466Smav cam_release_devq(path, 0, 0, 0, FALSE); 1116195534Sscottl return; 1117249466Smav } 1118195534Sscottl else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 1119195534Sscottl /* Don't wedge the queue */ 1120195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, 1121195534Sscottl /*count*/1, 1122195534Sscottl /*run_queue*/TRUE); 1123195534Sscottl } 1124195534Sscottl PROBE_SET_ACTION(softc, PROBE_INQUIRY); 1125195534Sscottl xpt_release_ccb(done_ccb); 1126195534Sscottl xpt_schedule(periph, priority); 1127260626Smavout: 1128260626Smav /* Drop freeze taken due to CAM_DEV_QFREEZE and release. */ 1129260626Smav cam_release_devq(path, 0, 0, 0, FALSE); 1130260626Smav cam_periph_release_locked(periph); 1131260626Smav return; 1132195534Sscottl } 1133195534Sscottl case PROBE_INQUIRY: 1134195534Sscottl case PROBE_FULL_INQUIRY: 1135195534Sscottl { 1136252382Sscottl if (cam_ccb_status(done_ccb) == CAM_REQ_CMP) { 1137195534Sscottl struct scsi_inquiry_data *inq_buf; 1138195534Sscottl u_int8_t periph_qual; 1139195534Sscottl 1140195534Sscottl path->device->flags |= CAM_DEV_INQUIRY_DATA_VALID; 1141195534Sscottl inq_buf = &path->device->inq_data; 1142195534Sscottl 1143195534Sscottl periph_qual = SID_QUAL(inq_buf); 1144195534Sscottl 1145208911Smjacob if (periph_qual == SID_QUAL_LU_CONNECTED) { 1146195534Sscottl u_int8_t len; 1147195534Sscottl 1148195534Sscottl /* 1149195534Sscottl * We conservatively request only 1150195534Sscottl * SHORT_INQUIRY_LEN bytes of inquiry 1151195534Sscottl * information during our first try 1152195534Sscottl * at sending an INQUIRY. If the device 1153195534Sscottl * has more information to give, 1154195534Sscottl * perform a second request specifying 1155195534Sscottl * the amount of information the device 1156195534Sscottl * is willing to give. 1157195534Sscottl */ 1158195534Sscottl len = inq_buf->additional_length 1159195534Sscottl + offsetof(struct scsi_inquiry_data, 1160195534Sscottl additional_length) + 1; 1161195534Sscottl if (softc->action == PROBE_INQUIRY 1162195534Sscottl && len > SHORT_INQUIRY_LENGTH) { 1163195534Sscottl PROBE_SET_ACTION(softc, PROBE_FULL_INQUIRY); 1164195534Sscottl xpt_release_ccb(done_ccb); 1165195534Sscottl xpt_schedule(periph, priority); 1166249466Smav goto out; 1167195534Sscottl } 1168195534Sscottl 1169195534Sscottl scsi_find_quirk(path->device); 1170195534Sscottl 1171195534Sscottl scsi_devise_transport(path); 1172208911Smjacob 1173208911Smjacob if (path->device->lun_id == 0 && 1174208911Smjacob SID_ANSI_REV(inq_buf) > SCSI_REV_SPC2 && 1175208911Smjacob (SCSI_QUIRK(path->device)->quirks & 1176208911Smjacob CAM_QUIRK_NORPTLUNS) == 0) { 1177208911Smjacob PROBE_SET_ACTION(softc, 1178208911Smjacob PROBE_REPORT_LUNS); 1179208911Smjacob /* 1180208911Smjacob * Start with room for *one* lun. 1181208911Smjacob */ 1182208911Smjacob periph->path->target->rpl_size = 16; 1183208911Smjacob } else if (INQ_DATA_TQ_ENABLED(inq_buf)) 1184208911Smjacob PROBE_SET_ACTION(softc, 1185208911Smjacob PROBE_MODE_SENSE); 1186195534Sscottl else 1187208911Smjacob PROBE_SET_ACTION(softc, 1188216088Sken PROBE_SUPPORTED_VPD_LIST); 1189195534Sscottl 1190198748Smav if (path->device->flags & CAM_DEV_UNCONFIGURED) { 1191198748Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1192198748Smav xpt_acquire_device(path->device); 1193198748Smav } 1194195534Sscottl xpt_release_ccb(done_ccb); 1195195534Sscottl xpt_schedule(periph, priority); 1196249466Smav goto out; 1197208911Smjacob } else if (path->device->lun_id == 0 && 1198208911Smjacob SID_ANSI_REV(inq_buf) > SCSI_REV_SPC2 && 1199208911Smjacob (SCSI_QUIRK(path->device)->quirks & 1200208911Smjacob CAM_QUIRK_NORPTLUNS) == 0) { 1201208911Smjacob if (path->device->flags & 1202208911Smjacob CAM_DEV_UNCONFIGURED) { 1203208911Smjacob path->device->flags &= 1204208911Smjacob ~CAM_DEV_UNCONFIGURED; 1205208911Smjacob xpt_acquire_device(path->device); 1206208911Smjacob } 1207208911Smjacob PROBE_SET_ACTION(softc, PROBE_REPORT_LUNS); 1208208911Smjacob periph->path->target->rpl_size = 16; 1209208911Smjacob xpt_release_ccb(done_ccb); 1210208911Smjacob xpt_schedule(periph, priority); 1211249466Smav goto out; 1212195534Sscottl } 1213195534Sscottl } else if (cam_periph_error(done_ccb, 0, 1214195534Sscottl done_ccb->ccb_h.target_lun > 0 1215195534Sscottl ? SF_RETRY_UA|SF_QUIET_IR 1216195534Sscottl : SF_RETRY_UA, 1217195534Sscottl &softc->saved_ccb) == ERESTART) { 1218260626Smav goto outr; 1219195534Sscottl } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1220195534Sscottl /* Don't wedge the queue */ 1221195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 1222195534Sscottl /*run_queue*/TRUE); 1223195534Sscottl } 1224195534Sscottl /* 1225195534Sscottl * If we get to this point, we got an error status back 1226195534Sscottl * from the inquiry and the error status doesn't require 1227195534Sscottl * automatically retrying the command. Therefore, the 1228195534Sscottl * inquiry failed. If we had inquiry information before 1229195534Sscottl * for this device, but this latest inquiry command failed, 1230195534Sscottl * the device has probably gone away. If this device isn't 1231195534Sscottl * already marked unconfigured, notify the peripheral 1232195534Sscottl * drivers that this device is no more. 1233195534Sscottl */ 1234195534Sscottl if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0) 1235195534Sscottl /* Send the async notification. */ 1236195534Sscottl xpt_async(AC_LOST_DEVICE, path, NULL); 1237236613Smav PROBE_SET_ACTION(softc, PROBE_INVALID); 1238195534Sscottl 1239195534Sscottl xpt_release_ccb(done_ccb); 1240195534Sscottl break; 1241195534Sscottl } 1242208911Smjacob case PROBE_REPORT_LUNS: 1243208911Smjacob { 1244208911Smjacob struct ccb_scsiio *csio; 1245208911Smjacob struct scsi_report_luns_data *lp; 1246208911Smjacob u_int nlun, maxlun; 1247208911Smjacob 1248208911Smjacob csio = &done_ccb->csio; 1249208911Smjacob 1250208911Smjacob lp = (struct scsi_report_luns_data *)csio->data_ptr; 1251208911Smjacob nlun = scsi_4btoul(lp->length) / 8; 1252208911Smjacob maxlun = (csio->dxfer_len / 8) - 1; 1253208911Smjacob 1254252382Sscottl if (cam_ccb_status(done_ccb) != CAM_REQ_CMP) { 1255208911Smjacob if (cam_periph_error(done_ccb, 0, 1256208911Smjacob done_ccb->ccb_h.target_lun > 0 ? 1257208911Smjacob SF_RETRY_UA|SF_QUIET_IR : SF_RETRY_UA, 1258208911Smjacob &softc->saved_ccb) == ERESTART) { 1259260626Smav goto outr; 1260208911Smjacob } 1261208911Smjacob if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1262208911Smjacob xpt_release_devq(done_ccb->ccb_h.path, 1, 1263208911Smjacob TRUE); 1264208911Smjacob } 1265208911Smjacob free(lp, M_CAMXPT); 1266208911Smjacob lp = NULL; 1267208911Smjacob } else if (nlun > maxlun) { 1268208911Smjacob /* 1269208911Smjacob * Reallocate and retry to cover all luns 1270208911Smjacob */ 1271236613Smav CAM_DEBUG(path, CAM_DEBUG_PROBE, 1272236613Smav ("Probe: reallocating REPORT_LUNS for %u luns\n", 1273236613Smav nlun)); 1274208911Smjacob free(lp, M_CAMXPT); 1275208911Smjacob path->target->rpl_size = (nlun << 3) + 8; 1276208911Smjacob xpt_release_ccb(done_ccb); 1277208911Smjacob xpt_schedule(periph, priority); 1278249466Smav goto out; 1279208911Smjacob } else if (nlun == 0) { 1280208911Smjacob /* 1281208911Smjacob * If there don't appear to be any luns, bail. 1282208911Smjacob */ 1283208911Smjacob free(lp, M_CAMXPT); 1284208911Smjacob lp = NULL; 1285208911Smjacob } else { 1286208911Smjacob lun_id_t lun; 1287208911Smjacob int idx; 1288208911Smjacob 1289236613Smav CAM_DEBUG(path, CAM_DEBUG_PROBE, 1290236613Smav ("Probe: %u lun(s) reported\n", nlun)); 1291208911Smjacob 1292259204Snwhitehorn CAM_GET_LUN(lp, 0, lun); 1293208911Smjacob /* 1294208911Smjacob * If the first lun is not lun 0, then either there 1295208911Smjacob * is no lun 0 in the list, or the list is unsorted. 1296208911Smjacob */ 1297208911Smjacob if (lun != 0) { 1298208911Smjacob for (idx = 0; idx < nlun; idx++) { 1299259204Snwhitehorn CAM_GET_LUN(lp, idx, lun); 1300208911Smjacob if (lun == 0) { 1301208911Smjacob break; 1302208911Smjacob } 1303208911Smjacob } 1304208911Smjacob if (idx != nlun) { 1305208911Smjacob uint8_t tlun[8]; 1306208911Smjacob memcpy(tlun, 1307208911Smjacob lp->luns[0].lundata, 8); 1308208911Smjacob memcpy(lp->luns[0].lundata, 1309208911Smjacob lp->luns[idx].lundata, 8); 1310208911Smjacob memcpy(lp->luns[idx].lundata, 1311208911Smjacob tlun, 8); 1312236613Smav CAM_DEBUG(path, CAM_DEBUG_PROBE, 1313236613Smav ("lun 0 in position %u\n", idx)); 1314208911Smjacob } else { 1315208911Smjacob /* 1316208911Smjacob * There is no lun 0 in our list. Destroy 1317208911Smjacob * the validity of the inquiry data so we 1318208911Smjacob * bail here and now. 1319208911Smjacob */ 1320208911Smjacob path->device->flags &= 1321208911Smjacob ~CAM_DEV_INQUIRY_DATA_VALID; 1322208911Smjacob } 1323208911Smjacob } 1324208911Smjacob /* 1325208911Smjacob * If we have an old lun list, We can either 1326208911Smjacob * retest luns that appear to have been dropped, 1327208911Smjacob * or just nuke them. We'll opt for the latter. 1328208911Smjacob * This function will also install the new list 1329208911Smjacob * in the target structure. 1330208911Smjacob */ 1331259204Snwhitehorn probe_purge_old(path, lp, softc->flags); 1332208911Smjacob lp = NULL; 1333208911Smjacob } 1334208911Smjacob if (path->device->flags & CAM_DEV_INQUIRY_DATA_VALID) { 1335208911Smjacob struct scsi_inquiry_data *inq_buf; 1336208911Smjacob inq_buf = &path->device->inq_data; 1337208911Smjacob if (INQ_DATA_TQ_ENABLED(inq_buf)) 1338208911Smjacob PROBE_SET_ACTION(softc, PROBE_MODE_SENSE); 1339208911Smjacob else 1340216088Sken PROBE_SET_ACTION(softc, 1341216088Sken PROBE_SUPPORTED_VPD_LIST); 1342208911Smjacob xpt_release_ccb(done_ccb); 1343208911Smjacob xpt_schedule(periph, priority); 1344249466Smav goto out; 1345208911Smjacob } 1346208911Smjacob if (lp) { 1347208911Smjacob free(lp, M_CAMXPT); 1348208911Smjacob } 1349208911Smjacob break; 1350208911Smjacob } 1351195534Sscottl case PROBE_MODE_SENSE: 1352195534Sscottl { 1353195534Sscottl struct ccb_scsiio *csio; 1354195534Sscottl struct scsi_mode_header_6 *mode_hdr; 1355195534Sscottl 1356195534Sscottl csio = &done_ccb->csio; 1357195534Sscottl mode_hdr = (struct scsi_mode_header_6 *)csio->data_ptr; 1358252382Sscottl if (cam_ccb_status(done_ccb) == CAM_REQ_CMP) { 1359195534Sscottl struct scsi_control_page *page; 1360195534Sscottl u_int8_t *offset; 1361195534Sscottl 1362195534Sscottl offset = ((u_int8_t *)&mode_hdr[1]) 1363195534Sscottl + mode_hdr->blk_desc_len; 1364195534Sscottl page = (struct scsi_control_page *)offset; 1365195534Sscottl path->device->queue_flags = page->queue_flags; 1366195534Sscottl } else if (cam_periph_error(done_ccb, 0, 1367195534Sscottl SF_RETRY_UA|SF_NO_PRINT, 1368195534Sscottl &softc->saved_ccb) == ERESTART) { 1369260626Smav goto outr; 1370195534Sscottl } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1371195534Sscottl /* Don't wedge the queue */ 1372195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, 1373195534Sscottl /*count*/1, /*run_queue*/TRUE); 1374195534Sscottl } 1375195534Sscottl xpt_release_ccb(done_ccb); 1376195534Sscottl free(mode_hdr, M_CAMXPT); 1377216088Sken PROBE_SET_ACTION(softc, PROBE_SUPPORTED_VPD_LIST); 1378195534Sscottl xpt_schedule(periph, priority); 1379249466Smav goto out; 1380195534Sscottl } 1381216088Sken case PROBE_SUPPORTED_VPD_LIST: 1382195534Sscottl { 1383195534Sscottl struct ccb_scsiio *csio; 1384195534Sscottl struct scsi_vpd_supported_page_list *page_list; 1385195534Sscottl 1386195534Sscottl csio = &done_ccb->csio; 1387195534Sscottl page_list = 1388195534Sscottl (struct scsi_vpd_supported_page_list *)csio->data_ptr; 1389195534Sscottl 1390216088Sken if (path->device->supported_vpds != NULL) { 1391216088Sken free(path->device->supported_vpds, M_CAMXPT); 1392216088Sken path->device->supported_vpds = NULL; 1393216088Sken path->device->supported_vpds_len = 0; 1394216088Sken } 1395216088Sken 1396195534Sscottl if (page_list == NULL) { 1397195534Sscottl /* 1398195534Sscottl * Don't process the command as it was never sent 1399195534Sscottl */ 1400216088Sken } else if (CCB_COMPLETED_OK(csio->ccb_h)) { 1401216088Sken /* Got vpd list */ 1402216088Sken path->device->supported_vpds_len = page_list->length + 1403216088Sken SVPD_SUPPORTED_PAGES_HDR_LEN; 1404216088Sken path->device->supported_vpds = (uint8_t *)page_list; 1405216088Sken xpt_release_ccb(done_ccb); 1406216088Sken PROBE_SET_ACTION(softc, PROBE_DEVICE_ID); 1407216088Sken xpt_schedule(periph, priority); 1408249466Smav goto out; 1409195534Sscottl } else if (cam_periph_error(done_ccb, 0, 1410195534Sscottl SF_RETRY_UA|SF_NO_PRINT, 1411195534Sscottl &softc->saved_ccb) == ERESTART) { 1412260626Smav goto outr; 1413195534Sscottl } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1414195534Sscottl /* Don't wedge the queue */ 1415195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 1416195534Sscottl /*run_queue*/TRUE); 1417195534Sscottl } 1418195534Sscottl 1419216088Sken if (page_list) 1420195685Semaste free(page_list, M_CAMXPT); 1421216088Sken /* No VPDs available, skip to device check. */ 1422216088Sken csio->data_ptr = NULL; 1423216088Sken goto probe_device_check; 1424216088Sken } 1425216088Sken case PROBE_DEVICE_ID: 1426216088Sken { 1427216088Sken struct scsi_vpd_device_id *devid; 1428216088Sken struct ccb_scsiio *csio; 1429216088Sken uint32_t length = 0; 1430195534Sscottl 1431216088Sken csio = &done_ccb->csio; 1432216088Sken devid = (struct scsi_vpd_device_id *)csio->data_ptr; 1433216088Sken 1434216088Sken /* Clean up from previous instance of this device */ 1435216088Sken if (path->device->device_id != NULL) { 1436216088Sken path->device->device_id_len = 0; 1437216088Sken free(path->device->device_id, M_CAMXPT); 1438216088Sken path->device->device_id = NULL; 1439216088Sken } 1440216088Sken 1441216088Sken if (devid == NULL) { 1442216088Sken /* Don't process the command as it was never sent */ 1443216088Sken } else if (CCB_COMPLETED_OK(csio->ccb_h)) { 1444216088Sken length = scsi_2btoul(devid->length); 1445216088Sken if (length != 0) { 1446216088Sken /* 1447216088Sken * NB: device_id_len is actual response 1448216088Sken * size, not buffer size. 1449216088Sken */ 1450216088Sken path->device->device_id_len = length + 1451216088Sken SVPD_DEVICE_ID_HDR_LEN; 1452216088Sken path->device->device_id = (uint8_t *)devid; 1453216088Sken } 1454216088Sken } else if (cam_periph_error(done_ccb, 0, 1455223081Sgibbs SF_RETRY_UA, 1456216088Sken &softc->saved_ccb) == ERESTART) { 1457260626Smav goto outr; 1458216088Sken } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1459216088Sken /* Don't wedge the queue */ 1460216088Sken xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 1461216088Sken /*run_queue*/TRUE); 1462195534Sscottl } 1463195534Sscottl 1464216088Sken /* Free the device id space if we don't use it */ 1465216088Sken if (devid && length == 0) 1466216088Sken free(devid, M_CAMXPT); 1467216088Sken xpt_release_ccb(done_ccb); 1468216088Sken PROBE_SET_ACTION(softc, PROBE_SERIAL_NUM); 1469216088Sken xpt_schedule(periph, priority); 1470249466Smav goto out; 1471195534Sscottl } 1472195534Sscottl 1473216088Skenprobe_device_check: 1474216088Sken case PROBE_SERIAL_NUM: 1475195534Sscottl { 1476195534Sscottl struct ccb_scsiio *csio; 1477195534Sscottl struct scsi_vpd_unit_serial_number *serial_buf; 1478195534Sscottl u_int32_t priority; 1479195534Sscottl int changed; 1480195534Sscottl int have_serialnum; 1481195534Sscottl 1482195534Sscottl changed = 1; 1483195534Sscottl have_serialnum = 0; 1484195534Sscottl csio = &done_ccb->csio; 1485195534Sscottl priority = done_ccb->ccb_h.pinfo.priority; 1486195534Sscottl serial_buf = 1487195534Sscottl (struct scsi_vpd_unit_serial_number *)csio->data_ptr; 1488195534Sscottl 1489195534Sscottl if (serial_buf == NULL) { 1490195534Sscottl /* 1491195534Sscottl * Don't process the command as it was never sent 1492195534Sscottl */ 1493252382Sscottl } else if (cam_ccb_status(done_ccb) == CAM_REQ_CMP 1494195534Sscottl && (serial_buf->length > 0)) { 1495195534Sscottl 1496195534Sscottl have_serialnum = 1; 1497195534Sscottl path->device->serial_num = 1498195534Sscottl (u_int8_t *)malloc((serial_buf->length + 1), 1499195534Sscottl M_CAMXPT, M_NOWAIT); 1500195534Sscottl if (path->device->serial_num != NULL) { 1501223081Sgibbs memcpy(path->device->serial_num, 1502223081Sgibbs serial_buf->serial_num, 1503223081Sgibbs serial_buf->length); 1504195534Sscottl path->device->serial_num_len = 1505195534Sscottl serial_buf->length; 1506195534Sscottl path->device->serial_num[serial_buf->length] 1507195534Sscottl = '\0'; 1508195534Sscottl } 1509195534Sscottl } else if (cam_periph_error(done_ccb, 0, 1510195534Sscottl SF_RETRY_UA|SF_NO_PRINT, 1511195534Sscottl &softc->saved_ccb) == ERESTART) { 1512260626Smav goto outr; 1513195534Sscottl } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1514195534Sscottl /* Don't wedge the queue */ 1515195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 1516195534Sscottl /*run_queue*/TRUE); 1517195534Sscottl } 1518195534Sscottl 1519195534Sscottl /* 1520195534Sscottl * Let's see if we have seen this device before. 1521195534Sscottl */ 1522195534Sscottl if ((softc->flags & PROBE_INQUIRY_CKSUM) != 0) { 1523195534Sscottl MD5_CTX context; 1524195534Sscottl u_int8_t digest[16]; 1525195534Sscottl 1526195534Sscottl MD5Init(&context); 1527195534Sscottl 1528195534Sscottl MD5Update(&context, 1529195534Sscottl (unsigned char *)&path->device->inq_data, 1530195534Sscottl sizeof(struct scsi_inquiry_data)); 1531195534Sscottl 1532195534Sscottl if (have_serialnum) 1533195534Sscottl MD5Update(&context, serial_buf->serial_num, 1534195534Sscottl serial_buf->length); 1535195534Sscottl 1536195534Sscottl MD5Final(digest, &context); 1537195534Sscottl if (bcmp(softc->digest, digest, 16) == 0) 1538195534Sscottl changed = 0; 1539195534Sscottl 1540195534Sscottl /* 1541195534Sscottl * XXX Do we need to do a TUR in order to ensure 1542195534Sscottl * that the device really hasn't changed??? 1543195534Sscottl */ 1544195534Sscottl if ((changed != 0) 1545195534Sscottl && ((softc->flags & PROBE_NO_ANNOUNCE) == 0)) 1546195534Sscottl xpt_async(AC_LOST_DEVICE, path, NULL); 1547195534Sscottl } 1548195534Sscottl if (serial_buf != NULL) 1549195534Sscottl free(serial_buf, M_CAMXPT); 1550195534Sscottl 1551195534Sscottl if (changed != 0) { 1552195534Sscottl /* 1553195534Sscottl * Now that we have all the necessary 1554195534Sscottl * information to safely perform transfer 1555195534Sscottl * negotiations... Controllers don't perform 1556195534Sscottl * any negotiation or tagged queuing until 1557195534Sscottl * after the first XPT_SET_TRAN_SETTINGS ccb is 1558195534Sscottl * received. So, on a new device, just retrieve 1559195534Sscottl * the user settings, and set them as the current 1560195534Sscottl * settings to set the device up. 1561195534Sscottl */ 1562195534Sscottl proberequestdefaultnegotiation(periph); 1563195534Sscottl xpt_release_ccb(done_ccb); 1564195534Sscottl 1565195534Sscottl /* 1566195534Sscottl * Perform a TUR to allow the controller to 1567195534Sscottl * perform any necessary transfer negotiation. 1568195534Sscottl */ 1569195534Sscottl PROBE_SET_ACTION(softc, PROBE_TUR_FOR_NEGOTIATION); 1570195534Sscottl xpt_schedule(periph, priority); 1571249466Smav goto out; 1572195534Sscottl } 1573195534Sscottl xpt_release_ccb(done_ccb); 1574195534Sscottl break; 1575195534Sscottl } 1576195534Sscottl case PROBE_TUR_FOR_NEGOTIATION: 1577236814Smav case PROBE_DV_EXIT: 1578252382Sscottl if (cam_ccb_status(done_ccb) != CAM_REQ_CMP) { 1579236814Smav cam_periph_error(done_ccb, 0, 1580236814Smav SF_NO_PRINT | SF_NO_RECOVERY | SF_NO_RETRY, NULL); 1581195534Sscottl } 1582195534Sscottl if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1583195534Sscottl /* Don't wedge the queue */ 1584195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 1585195534Sscottl /*run_queue*/TRUE); 1586195534Sscottl } 1587195534Sscottl /* 1588195534Sscottl * Do Domain Validation for lun 0 on devices that claim 1589195534Sscottl * to support Synchronous Transfer modes. 1590195534Sscottl */ 1591195534Sscottl if (softc->action == PROBE_TUR_FOR_NEGOTIATION 1592195534Sscottl && done_ccb->ccb_h.target_lun == 0 1593195534Sscottl && (path->device->inq_data.flags & SID_Sync) != 0 1594195534Sscottl && (path->device->flags & CAM_DEV_IN_DV) == 0) { 1595236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, 1596195534Sscottl ("Begin Domain Validation\n")); 1597195534Sscottl path->device->flags |= CAM_DEV_IN_DV; 1598195534Sscottl xpt_release_ccb(done_ccb); 1599195534Sscottl PROBE_SET_ACTION(softc, PROBE_INQUIRY_BASIC_DV1); 1600195534Sscottl xpt_schedule(periph, priority); 1601249466Smav goto out; 1602195534Sscottl } 1603195534Sscottl if (softc->action == PROBE_DV_EXIT) { 1604236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, 1605195534Sscottl ("Leave Domain Validation\n")); 1606195534Sscottl } 1607198748Smav if (path->device->flags & CAM_DEV_UNCONFIGURED) { 1608198748Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1609198748Smav xpt_acquire_device(path->device); 1610198748Smav } 1611195534Sscottl path->device->flags &= 1612198748Smav ~(CAM_DEV_IN_DV|CAM_DEV_DV_HIT_BOTTOM); 1613195534Sscottl if ((softc->flags & PROBE_NO_ANNOUNCE) == 0) { 1614195534Sscottl /* Inform the XPT that a new device has been found */ 1615195534Sscottl done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1616195534Sscottl xpt_action(done_ccb); 1617195534Sscottl xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, 1618195534Sscottl done_ccb); 1619195534Sscottl } 1620236613Smav PROBE_SET_ACTION(softc, PROBE_DONE); 1621195534Sscottl xpt_release_ccb(done_ccb); 1622195534Sscottl break; 1623195534Sscottl case PROBE_INQUIRY_BASIC_DV1: 1624195534Sscottl case PROBE_INQUIRY_BASIC_DV2: 1625195534Sscottl { 1626195534Sscottl struct scsi_inquiry_data *nbuf; 1627195534Sscottl struct ccb_scsiio *csio; 1628195534Sscottl 1629252382Sscottl if (cam_ccb_status(done_ccb) != CAM_REQ_CMP) { 1630236814Smav cam_periph_error(done_ccb, 0, 1631236814Smav SF_NO_PRINT | SF_NO_RECOVERY | SF_NO_RETRY, NULL); 1632236814Smav } 1633195534Sscottl if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1634195534Sscottl /* Don't wedge the queue */ 1635195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 1636195534Sscottl /*run_queue*/TRUE); 1637195534Sscottl } 1638195534Sscottl csio = &done_ccb->csio; 1639195534Sscottl nbuf = (struct scsi_inquiry_data *)csio->data_ptr; 1640195534Sscottl if (bcmp(nbuf, &path->device->inq_data, SHORT_INQUIRY_LENGTH)) { 1641195534Sscottl xpt_print(path, 1642195534Sscottl "inquiry data fails comparison at DV%d step\n", 1643195534Sscottl softc->action == PROBE_INQUIRY_BASIC_DV1 ? 1 : 2); 1644195534Sscottl if (proberequestbackoff(periph, path->device)) { 1645195534Sscottl path->device->flags &= ~CAM_DEV_IN_DV; 1646195534Sscottl PROBE_SET_ACTION(softc, PROBE_TUR_FOR_NEGOTIATION); 1647195534Sscottl } else { 1648195534Sscottl /* give up */ 1649195534Sscottl PROBE_SET_ACTION(softc, PROBE_DV_EXIT); 1650195534Sscottl } 1651195534Sscottl free(nbuf, M_CAMXPT); 1652195534Sscottl xpt_release_ccb(done_ccb); 1653195534Sscottl xpt_schedule(periph, priority); 1654249466Smav goto out; 1655195534Sscottl } 1656195534Sscottl free(nbuf, M_CAMXPT); 1657195534Sscottl if (softc->action == PROBE_INQUIRY_BASIC_DV1) { 1658195534Sscottl PROBE_SET_ACTION(softc, PROBE_INQUIRY_BASIC_DV2); 1659195534Sscottl xpt_release_ccb(done_ccb); 1660195534Sscottl xpt_schedule(periph, priority); 1661249466Smav goto out; 1662195534Sscottl } 1663195534Sscottl if (softc->action == PROBE_INQUIRY_BASIC_DV2) { 1664236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, 1665195534Sscottl ("Leave Domain Validation Successfully\n")); 1666195534Sscottl } 1667198748Smav if (path->device->flags & CAM_DEV_UNCONFIGURED) { 1668198748Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1669198748Smav xpt_acquire_device(path->device); 1670198748Smav } 1671195534Sscottl path->device->flags &= 1672198748Smav ~(CAM_DEV_IN_DV|CAM_DEV_DV_HIT_BOTTOM); 1673195534Sscottl if ((softc->flags & PROBE_NO_ANNOUNCE) == 0) { 1674195534Sscottl /* Inform the XPT that a new device has been found */ 1675195534Sscottl done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1676195534Sscottl xpt_action(done_ccb); 1677195534Sscottl xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, 1678195534Sscottl done_ccb); 1679195534Sscottl } 1680236613Smav PROBE_SET_ACTION(softc, PROBE_DONE); 1681195534Sscottl xpt_release_ccb(done_ccb); 1682195534Sscottl break; 1683195534Sscottl } 1684195534Sscottl default: 1685236613Smav panic("probedone: invalid action state 0x%x\n", softc->action); 1686195534Sscottl } 1687195534Sscottl done_ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs); 1688195534Sscottl TAILQ_REMOVE(&softc->request_ccbs, &done_ccb->ccb_h, periph_links.tqe); 1689195534Sscottl done_ccb->ccb_h.status = CAM_REQ_CMP; 1690195534Sscottl xpt_done(done_ccb); 1691195534Sscottl if (TAILQ_FIRST(&softc->request_ccbs) == NULL) { 1692236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe completed\n")); 1693249466Smav /* Drop freeze taken due to CAM_DEV_QFREEZE flag set. */ 1694249466Smav cam_release_devq(path, 0, 0, 0, FALSE); 1695260626Smav cam_periph_release_locked(periph); 1696236228Smav cam_periph_invalidate(periph); 1697195534Sscottl cam_periph_release_locked(periph); 1698195534Sscottl } else { 1699195534Sscottl probeschedule(periph); 1700249466Smav goto out; 1701195534Sscottl } 1702195534Sscottl} 1703195534Sscottl 1704195534Sscottlstatic void 1705259204Snwhitehornprobe_purge_old(struct cam_path *path, struct scsi_report_luns_data *new, 1706259204Snwhitehorn probe_flags flags) 1707208911Smjacob{ 1708208911Smjacob struct cam_path *tp; 1709208911Smjacob struct scsi_report_luns_data *old; 1710259204Snwhitehorn u_int idx1, idx2, nlun_old, nlun_new; 1711259204Snwhitehorn lun_id_t this_lun; 1712208911Smjacob u_int8_t *ol, *nl; 1713208911Smjacob 1714208911Smjacob if (path->target == NULL) { 1715208911Smjacob return; 1716208911Smjacob } 1717260387Sscottl mtx_lock(&path->target->luns_mtx); 1718260387Sscottl old = path->target->luns; 1719260387Sscottl path->target->luns = new; 1720260387Sscottl mtx_unlock(&path->target->luns_mtx); 1721260387Sscottl if (old == NULL) 1722208911Smjacob return; 1723208911Smjacob nlun_old = scsi_4btoul(old->length) / 8; 1724208911Smjacob nlun_new = scsi_4btoul(new->length) / 8; 1725208911Smjacob 1726208911Smjacob /* 1727208911Smjacob * We are not going to assume sorted lists. Deal. 1728208911Smjacob */ 1729208911Smjacob for (idx1 = 0; idx1 < nlun_old; idx1++) { 1730208911Smjacob ol = old->luns[idx1].lundata; 1731208911Smjacob for (idx2 = 0; idx2 < nlun_new; idx2++) { 1732208911Smjacob nl = new->luns[idx2].lundata; 1733208911Smjacob if (memcmp(nl, ol, 8) == 0) { 1734208911Smjacob break; 1735208911Smjacob } 1736208911Smjacob } 1737208911Smjacob if (idx2 < nlun_new) { 1738208911Smjacob continue; 1739208911Smjacob } 1740208911Smjacob /* 1741208911Smjacob * An 'old' item not in the 'new' list. 1742208911Smjacob * Nuke it. Except that if it is lun 0, 1743208911Smjacob * that would be what the probe state 1744208911Smjacob * machine is currently working on, 1745208911Smjacob * so we won't do that. 1746208911Smjacob */ 1747259204Snwhitehorn CAM_GET_LUN(old, idx1, this_lun); 1748259204Snwhitehorn if (this_lun == 0) { 1749208911Smjacob continue; 1750208911Smjacob } 1751259204Snwhitehorn 1752259204Snwhitehorn /* 1753259204Snwhitehorn * We also cannot nuke it if it is 1754259204Snwhitehorn * not in a lun format we understand 1755259204Snwhitehorn * and replace the LUN with a "simple" LUN 1756259204Snwhitehorn * if that is all the HBA supports. 1757259204Snwhitehorn */ 1758259204Snwhitehorn if (!(flags & PROBE_EXTLUN)) { 1759259204Snwhitehorn if (!CAM_CAN_GET_SIMPLE_LUN(old, idx1)) 1760259204Snwhitehorn continue; 1761259204Snwhitehorn CAM_GET_SIMPLE_LUN(old, idx1, this_lun); 1762259204Snwhitehorn } 1763259204Snwhitehorn if (!CAM_LUN_ONLY_32BITS(old, idx1)) 1764208911Smjacob continue; 1765259204Snwhitehorn 1766208911Smjacob if (xpt_create_path(&tp, NULL, xpt_path_path_id(path), 1767208911Smjacob xpt_path_target_id(path), this_lun) == CAM_REQ_CMP) { 1768208911Smjacob xpt_async(AC_LOST_DEVICE, tp, NULL); 1769208911Smjacob xpt_free_path(tp); 1770208911Smjacob } 1771208911Smjacob } 1772208911Smjacob free(old, M_CAMXPT); 1773208911Smjacob} 1774208911Smjacob 1775208911Smjacobstatic void 1776195534Sscottlprobecleanup(struct cam_periph *periph) 1777195534Sscottl{ 1778195534Sscottl free(periph->softc, M_CAMXPT); 1779195534Sscottl} 1780195534Sscottl 1781195534Sscottlstatic void 1782195534Sscottlscsi_find_quirk(struct cam_ed *device) 1783195534Sscottl{ 1784195534Sscottl struct scsi_quirk_entry *quirk; 1785195534Sscottl caddr_t match; 1786195534Sscottl 1787195534Sscottl match = cam_quirkmatch((caddr_t)&device->inq_data, 1788195534Sscottl (caddr_t)scsi_quirk_table, 1789195534Sscottl sizeof(scsi_quirk_table) / 1790195534Sscottl sizeof(*scsi_quirk_table), 1791195534Sscottl sizeof(*scsi_quirk_table), scsi_inquiry_match); 1792195534Sscottl 1793195534Sscottl if (match == NULL) 1794195534Sscottl panic("xpt_find_quirk: device didn't match wildcard entry!!"); 1795195534Sscottl 1796195534Sscottl quirk = (struct scsi_quirk_entry *)match; 1797195534Sscottl device->quirk = quirk; 1798195534Sscottl device->mintags = quirk->mintags; 1799195534Sscottl device->maxtags = quirk->maxtags; 1800195534Sscottl} 1801195534Sscottl 1802195534Sscottlstatic int 1803195534Sscottlsysctl_cam_search_luns(SYSCTL_HANDLER_ARGS) 1804195534Sscottl{ 1805228442Smdf int error, val; 1806195534Sscottl 1807228442Smdf val = cam_srch_hi; 1808228442Smdf error = sysctl_handle_int(oidp, &val, 0, req); 1809195534Sscottl if (error != 0 || req->newptr == NULL) 1810195534Sscottl return (error); 1811228442Smdf if (val == 0 || val == 1) { 1812228442Smdf cam_srch_hi = val; 1813195534Sscottl return (0); 1814195534Sscottl } else { 1815195534Sscottl return (EINVAL); 1816195534Sscottl } 1817195534Sscottl} 1818195534Sscottl 1819195534Sscottltypedef struct { 1820195534Sscottl union ccb *request_ccb; 1821195534Sscottl struct ccb_pathinq *cpi; 1822195534Sscottl int counter; 1823208911Smjacob int lunindex[0]; 1824195534Sscottl} scsi_scan_bus_info; 1825195534Sscottl 1826195534Sscottl/* 1827195534Sscottl * To start a scan, request_ccb is an XPT_SCAN_BUS ccb. 1828195688Semaste * As the scan progresses, scsi_scan_bus is used as the 1829195534Sscottl * callback on completion function. 1830195534Sscottl */ 1831195534Sscottlstatic void 1832195534Sscottlscsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb) 1833195534Sscottl{ 1834260387Sscottl struct mtx *mtx; 1835260387Sscottl 1836195534Sscottl CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE, 1837195688Semaste ("scsi_scan_bus\n")); 1838195534Sscottl switch (request_ccb->ccb_h.func_code) { 1839195534Sscottl case XPT_SCAN_BUS: 1840208582Smjacob case XPT_SCAN_TGT: 1841195534Sscottl { 1842195534Sscottl scsi_scan_bus_info *scan_info; 1843203108Smav union ccb *work_ccb, *reset_ccb; 1844195534Sscottl struct cam_path *path; 1845195534Sscottl u_int i; 1846208582Smjacob u_int low_target, max_target; 1847195534Sscottl u_int initiator_id; 1848195534Sscottl 1849195534Sscottl /* Find out the characteristics of the bus */ 1850195534Sscottl work_ccb = xpt_alloc_ccb_nowait(); 1851195534Sscottl if (work_ccb == NULL) { 1852195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1853195534Sscottl xpt_done(request_ccb); 1854195534Sscottl return; 1855195534Sscottl } 1856195534Sscottl xpt_setup_ccb(&work_ccb->ccb_h, request_ccb->ccb_h.path, 1857195534Sscottl request_ccb->ccb_h.pinfo.priority); 1858195534Sscottl work_ccb->ccb_h.func_code = XPT_PATH_INQ; 1859195534Sscottl xpt_action(work_ccb); 1860195534Sscottl if (work_ccb->ccb_h.status != CAM_REQ_CMP) { 1861195534Sscottl request_ccb->ccb_h.status = work_ccb->ccb_h.status; 1862195534Sscottl xpt_free_ccb(work_ccb); 1863195534Sscottl xpt_done(request_ccb); 1864195534Sscottl return; 1865195534Sscottl } 1866195534Sscottl 1867195534Sscottl if ((work_ccb->cpi.hba_misc & PIM_NOINITIATOR) != 0) { 1868195534Sscottl /* 1869195534Sscottl * Can't scan the bus on an adapter that 1870195534Sscottl * cannot perform the initiator role. 1871195534Sscottl */ 1872195534Sscottl request_ccb->ccb_h.status = CAM_REQ_CMP; 1873195534Sscottl xpt_free_ccb(work_ccb); 1874195534Sscottl xpt_done(request_ccb); 1875195534Sscottl return; 1876195534Sscottl } 1877195534Sscottl 1878203108Smav /* We may need to reset bus first, if we haven't done it yet. */ 1879203108Smav if ((work_ccb->cpi.hba_inquiry & 1880203108Smav (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE)) && 1881203108Smav !(work_ccb->cpi.hba_misc & PIM_NOBUSRESET) && 1882253370Smav !timevalisset(&request_ccb->ccb_h.path->bus->last_reset) && 1883253370Smav (reset_ccb = xpt_alloc_ccb_nowait()) != NULL) { 1884203108Smav xpt_setup_ccb(&reset_ccb->ccb_h, request_ccb->ccb_h.path, 1885203108Smav CAM_PRIORITY_NONE); 1886203108Smav reset_ccb->ccb_h.func_code = XPT_RESET_BUS; 1887203108Smav xpt_action(reset_ccb); 1888203108Smav if (reset_ccb->ccb_h.status != CAM_REQ_CMP) { 1889203108Smav request_ccb->ccb_h.status = reset_ccb->ccb_h.status; 1890203108Smav xpt_free_ccb(reset_ccb); 1891203108Smav xpt_free_ccb(work_ccb); 1892203108Smav xpt_done(request_ccb); 1893203108Smav return; 1894203108Smav } 1895203108Smav xpt_free_ccb(reset_ccb); 1896203108Smav } 1897203108Smav 1898195534Sscottl /* Save some state for use while we probe for devices */ 1899208911Smjacob scan_info = (scsi_scan_bus_info *) malloc(sizeof(scsi_scan_bus_info) + 1900208911Smjacob (work_ccb->cpi.max_target * sizeof (u_int)), M_CAMXPT, M_ZERO|M_NOWAIT); 1901195534Sscottl if (scan_info == NULL) { 1902195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1903260387Sscottl xpt_free_ccb(work_ccb); 1904195534Sscottl xpt_done(request_ccb); 1905195534Sscottl return; 1906195534Sscottl } 1907236613Smav CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE, 1908208911Smjacob ("SCAN start for %p\n", scan_info)); 1909195534Sscottl scan_info->request_ccb = request_ccb; 1910195534Sscottl scan_info->cpi = &work_ccb->cpi; 1911195534Sscottl 1912195534Sscottl /* Cache on our stack so we can work asynchronously */ 1913195534Sscottl max_target = scan_info->cpi->max_target; 1914208582Smjacob low_target = 0; 1915195534Sscottl initiator_id = scan_info->cpi->initiator_id; 1916195534Sscottl 1917195534Sscottl 1918195534Sscottl /* 1919195534Sscottl * We can scan all targets in parallel, or do it sequentially. 1920195534Sscottl */ 1921208582Smjacob 1922208582Smjacob if (request_ccb->ccb_h.func_code == XPT_SCAN_TGT) { 1923208582Smjacob max_target = low_target = request_ccb->ccb_h.target_id; 1924208582Smjacob scan_info->counter = 0; 1925208582Smjacob } else if (scan_info->cpi->hba_misc & PIM_SEQSCAN) { 1926195534Sscottl max_target = 0; 1927195534Sscottl scan_info->counter = 0; 1928195534Sscottl } else { 1929195534Sscottl scan_info->counter = scan_info->cpi->max_target + 1; 1930195534Sscottl if (scan_info->cpi->initiator_id < scan_info->counter) { 1931195534Sscottl scan_info->counter--; 1932195534Sscottl } 1933195534Sscottl } 1934260387Sscottl mtx = xpt_path_mtx(scan_info->request_ccb->ccb_h.path); 1935260387Sscottl mtx_unlock(mtx); 1936195534Sscottl 1937208582Smjacob for (i = low_target; i <= max_target; i++) { 1938195534Sscottl cam_status status; 1939195534Sscottl if (i == initiator_id) 1940195534Sscottl continue; 1941195534Sscottl 1942249468Smav status = xpt_create_path(&path, NULL, 1943195534Sscottl request_ccb->ccb_h.path_id, 1944195534Sscottl i, 0); 1945195534Sscottl if (status != CAM_REQ_CMP) { 1946195688Semaste printf("scsi_scan_bus: xpt_create_path failed" 1947195534Sscottl " with status %#x, bus scan halted\n", 1948195534Sscottl status); 1949195534Sscottl free(scan_info, M_CAMXPT); 1950195534Sscottl request_ccb->ccb_h.status = status; 1951195534Sscottl xpt_free_ccb(work_ccb); 1952195534Sscottl xpt_done(request_ccb); 1953195534Sscottl break; 1954195534Sscottl } 1955195534Sscottl work_ccb = xpt_alloc_ccb_nowait(); 1956195534Sscottl if (work_ccb == NULL) { 1957195685Semaste xpt_free_ccb((union ccb *)scan_info->cpi); 1958195534Sscottl free(scan_info, M_CAMXPT); 1959195534Sscottl xpt_free_path(path); 1960195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1961195534Sscottl xpt_done(request_ccb); 1962195534Sscottl break; 1963195534Sscottl } 1964195534Sscottl xpt_setup_ccb(&work_ccb->ccb_h, path, 1965195534Sscottl request_ccb->ccb_h.pinfo.priority); 1966195534Sscottl work_ccb->ccb_h.func_code = XPT_SCAN_LUN; 1967195534Sscottl work_ccb->ccb_h.cbfcnp = scsi_scan_bus; 1968260387Sscottl work_ccb->ccb_h.flags |= CAM_UNLOCKED; 1969195534Sscottl work_ccb->ccb_h.ppriv_ptr0 = scan_info; 1970195534Sscottl work_ccb->crcn.flags = request_ccb->crcn.flags; 1971195534Sscottl xpt_action(work_ccb); 1972195534Sscottl } 1973260387Sscottl 1974260387Sscottl mtx_lock(mtx); 1975195534Sscottl break; 1976195534Sscottl } 1977195534Sscottl case XPT_SCAN_LUN: 1978195534Sscottl { 1979195534Sscottl cam_status status; 1980208911Smjacob struct cam_path *path, *oldpath; 1981195534Sscottl scsi_scan_bus_info *scan_info; 1982208911Smjacob struct cam_et *target; 1983208911Smjacob struct cam_ed *device; 1984208911Smjacob int next_target; 1985195534Sscottl path_id_t path_id; 1986195534Sscottl target_id_t target_id; 1987195534Sscottl lun_id_t lun_id; 1988195534Sscottl 1989208911Smjacob oldpath = request_ccb->ccb_h.path; 1990208911Smjacob 1991252382Sscottl status = cam_ccb_status(request_ccb); 1992195534Sscottl /* Reuse the same CCB to query if a device was really found */ 1993195534Sscottl scan_info = (scsi_scan_bus_info *)request_ccb->ccb_h.ppriv_ptr0; 1994195534Sscottl xpt_setup_ccb(&request_ccb->ccb_h, request_ccb->ccb_h.path, 1995195534Sscottl request_ccb->ccb_h.pinfo.priority); 1996195534Sscottl request_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1997195534Sscottl 1998208911Smjacob 1999195534Sscottl path_id = request_ccb->ccb_h.path_id; 2000195534Sscottl target_id = request_ccb->ccb_h.target_id; 2001195534Sscottl lun_id = request_ccb->ccb_h.target_lun; 2002195534Sscottl xpt_action(request_ccb); 2003195534Sscottl 2004208911Smjacob target = request_ccb->ccb_h.path->target; 2005208911Smjacob next_target = 1; 2006208911Smjacob 2007260387Sscottl mtx = xpt_path_mtx(scan_info->request_ccb->ccb_h.path); 2008260387Sscottl mtx_lock(mtx); 2009260387Sscottl mtx_lock(&target->luns_mtx); 2010208911Smjacob if (target->luns) { 2011259204Snwhitehorn lun_id_t first; 2012208911Smjacob u_int nluns = scsi_4btoul(target->luns->length) / 8; 2013208911Smjacob 2014208911Smjacob /* 2015208911Smjacob * Make sure we skip over lun 0 if it's the first member 2016208911Smjacob * of the list as we've actually just finished probing 2017208911Smjacob * it. 2018208911Smjacob */ 2019259204Snwhitehorn CAM_GET_LUN(target->luns, 0, first); 2020208911Smjacob if (first == 0 && scan_info->lunindex[target_id] == 0) { 2021208911Smjacob scan_info->lunindex[target_id]++; 2022208911Smjacob } 2023208911Smjacob 2024259204Snwhitehorn /* 2025259204Snwhitehorn * Skip any LUNs that the HBA can't deal with. 2026259204Snwhitehorn */ 2027259204Snwhitehorn while (scan_info->lunindex[target_id] < nluns) { 2028259204Snwhitehorn if (scan_info->cpi->hba_misc & PIM_EXTLUNS) { 2029259204Snwhitehorn CAM_GET_LUN(target->luns, 2030259204Snwhitehorn scan_info->lunindex[target_id], 2031259204Snwhitehorn lun_id); 2032259204Snwhitehorn break; 2033259204Snwhitehorn } 2034259204Snwhitehorn 2035259204Snwhitehorn /* XXX print warning? */ 2036259204Snwhitehorn if (!CAM_LUN_ONLY_32BITS(target->luns, 2037259204Snwhitehorn scan_info->lunindex[target_id])) 2038259204Snwhitehorn continue; 2039259204Snwhitehorn if (CAM_CAN_GET_SIMPLE_LUN(target->luns, 2040259204Snwhitehorn scan_info->lunindex[target_id])) { 2041259204Snwhitehorn CAM_GET_SIMPLE_LUN(target->luns, 2042259204Snwhitehorn scan_info->lunindex[target_id], 2043259204Snwhitehorn lun_id); 2044259204Snwhitehorn break; 2045259204Snwhitehorn } 2046259204Snwhitehorn 2047259204Snwhitehorn scan_info->lunindex[target_id]++; 2048259204Snwhitehorn } 2049259204Snwhitehorn 2050208911Smjacob if (scan_info->lunindex[target_id] < nluns) { 2051260387Sscottl mtx_unlock(&target->luns_mtx); 2052208911Smjacob next_target = 0; 2053236613Smav CAM_DEBUG(request_ccb->ccb_h.path, 2054236613Smav CAM_DEBUG_PROBE, 2055259204Snwhitehorn ("next lun to try at index %u is %jx\n", 2056259204Snwhitehorn scan_info->lunindex[target_id], 2057259204Snwhitehorn (uintmax_t)lun_id)); 2058208911Smjacob scan_info->lunindex[target_id]++; 2059208911Smjacob } else { 2060260387Sscottl mtx_unlock(&target->luns_mtx); 2061208911Smjacob /* 2062208911Smjacob * We're done with scanning all luns. 2063208911Smjacob * 2064208911Smjacob * Nuke the bogus device for lun 0 if lun 0 2065208911Smjacob * wasn't on the list. 2066208911Smjacob */ 2067208911Smjacob if (first != 0) { 2068208911Smjacob TAILQ_FOREACH(device, 2069208911Smjacob &target->ed_entries, links) { 2070208911Smjacob if (device->lun_id == 0) { 2071208911Smjacob break; 2072208911Smjacob } 2073208911Smjacob } 2074208911Smjacob if (device) { 2075208911Smjacob xpt_release_device(device); 2076208911Smjacob } 2077208911Smjacob } 2078208911Smjacob } 2079260387Sscottl } else { 2080260387Sscottl mtx_unlock(&target->luns_mtx); 2081260387Sscottl if (request_ccb->ccb_h.status != CAM_REQ_CMP) { 2082195534Sscottl int phl; 2083195534Sscottl 2084195534Sscottl /* 2085195534Sscottl * If we already probed lun 0 successfully, or 2086195534Sscottl * we have additional configured luns on this 2087195534Sscottl * target that might have "gone away", go onto 2088195534Sscottl * the next lun. 2089195534Sscottl */ 2090195534Sscottl /* 2091195534Sscottl * We may touch devices that we don't 2092195534Sscottl * hold references too, so ensure they 2093195534Sscottl * don't disappear out from under us. 2094195534Sscottl * The target above is referenced by the 2095195534Sscottl * path in the request ccb. 2096195534Sscottl */ 2097195534Sscottl phl = 0; 2098195534Sscottl device = TAILQ_FIRST(&target->ed_entries); 2099195534Sscottl if (device != NULL) { 2100195534Sscottl phl = CAN_SRCH_HI_SPARSE(device); 2101195534Sscottl if (device->lun_id == 0) 2102195534Sscottl device = TAILQ_NEXT(device, links); 2103195534Sscottl } 2104195534Sscottl if ((lun_id != 0) || (device != NULL)) { 2105208911Smjacob if (lun_id < (CAM_SCSI2_MAXLUN-1) || phl) { 2106195534Sscottl lun_id++; 2107208911Smjacob next_target = 0; 2108208911Smjacob } 2109195534Sscottl } 2110208911Smjacob if (lun_id == request_ccb->ccb_h.target_lun 2111208911Smjacob || lun_id > scan_info->cpi->max_lun) 2112208911Smjacob next_target = 1; 2113260387Sscottl } else { 2114195534Sscottl 2115195534Sscottl device = request_ccb->ccb_h.path->device; 2116195534Sscottl 2117195534Sscottl if ((SCSI_QUIRK(device)->quirks & 2118195534Sscottl CAM_QUIRK_NOLUNS) == 0) { 2119195534Sscottl /* Try the next lun */ 2120195534Sscottl if (lun_id < (CAM_SCSI2_MAXLUN-1) 2121208911Smjacob || CAN_SRCH_HI_DENSE(device)) { 2122195534Sscottl lun_id++; 2123208911Smjacob next_target = 0; 2124208911Smjacob } 2125195534Sscottl } 2126208911Smjacob if (lun_id == request_ccb->ccb_h.target_lun 2127208911Smjacob || lun_id > scan_info->cpi->max_lun) 2128208911Smjacob next_target = 1; 2129260387Sscottl } 2130195534Sscottl } 2131195534Sscottl 2132195534Sscottl /* 2133195534Sscottl * Check to see if we scan any further luns. 2134195534Sscottl */ 2135208911Smjacob if (next_target) { 2136195534Sscottl int done; 2137195534Sscottl 2138208911Smjacob /* 2139208911Smjacob * Free the current request path- we're done with it. 2140208911Smjacob */ 2141208911Smjacob xpt_free_path(oldpath); 2142195534Sscottl hop_again: 2143195534Sscottl done = 0; 2144208582Smjacob if (scan_info->request_ccb->ccb_h.func_code == XPT_SCAN_TGT) { 2145208582Smjacob done = 1; 2146208582Smjacob } else if (scan_info->cpi->hba_misc & PIM_SEQSCAN) { 2147195534Sscottl scan_info->counter++; 2148195534Sscottl if (scan_info->counter == 2149195534Sscottl scan_info->cpi->initiator_id) { 2150195534Sscottl scan_info->counter++; 2151195534Sscottl } 2152195534Sscottl if (scan_info->counter >= 2153195534Sscottl scan_info->cpi->max_target+1) { 2154195534Sscottl done = 1; 2155195534Sscottl } 2156195534Sscottl } else { 2157195534Sscottl scan_info->counter--; 2158195534Sscottl if (scan_info->counter == 0) { 2159195534Sscottl done = 1; 2160195534Sscottl } 2161195534Sscottl } 2162195534Sscottl if (done) { 2163260387Sscottl mtx_unlock(mtx); 2164195534Sscottl xpt_free_ccb(request_ccb); 2165195534Sscottl xpt_free_ccb((union ccb *)scan_info->cpi); 2166195534Sscottl request_ccb = scan_info->request_ccb; 2167236613Smav CAM_DEBUG(request_ccb->ccb_h.path, 2168236613Smav CAM_DEBUG_TRACE, 2169208911Smjacob ("SCAN done for %p\n", scan_info)); 2170195534Sscottl free(scan_info, M_CAMXPT); 2171195534Sscottl request_ccb->ccb_h.status = CAM_REQ_CMP; 2172195534Sscottl xpt_done(request_ccb); 2173195534Sscottl break; 2174195534Sscottl } 2175195534Sscottl 2176195534Sscottl if ((scan_info->cpi->hba_misc & PIM_SEQSCAN) == 0) { 2177260387Sscottl mtx_unlock(mtx); 2178195685Semaste xpt_free_ccb(request_ccb); 2179195534Sscottl break; 2180195534Sscottl } 2181249468Smav status = xpt_create_path(&path, NULL, 2182195534Sscottl scan_info->request_ccb->ccb_h.path_id, 2183195534Sscottl scan_info->counter, 0); 2184195534Sscottl if (status != CAM_REQ_CMP) { 2185260387Sscottl mtx_unlock(mtx); 2186195688Semaste printf("scsi_scan_bus: xpt_create_path failed" 2187195534Sscottl " with status %#x, bus scan halted\n", 2188195534Sscottl status); 2189195534Sscottl xpt_free_ccb(request_ccb); 2190195534Sscottl xpt_free_ccb((union ccb *)scan_info->cpi); 2191195534Sscottl request_ccb = scan_info->request_ccb; 2192195534Sscottl free(scan_info, M_CAMXPT); 2193195534Sscottl request_ccb->ccb_h.status = status; 2194195534Sscottl xpt_done(request_ccb); 2195195534Sscottl break; 2196195534Sscottl } 2197195534Sscottl xpt_setup_ccb(&request_ccb->ccb_h, path, 2198195534Sscottl request_ccb->ccb_h.pinfo.priority); 2199195534Sscottl request_ccb->ccb_h.func_code = XPT_SCAN_LUN; 2200195534Sscottl request_ccb->ccb_h.cbfcnp = scsi_scan_bus; 2201260387Sscottl request_ccb->ccb_h.flags |= CAM_UNLOCKED; 2202195534Sscottl request_ccb->ccb_h.ppriv_ptr0 = scan_info; 2203195534Sscottl request_ccb->crcn.flags = 2204195534Sscottl scan_info->request_ccb->crcn.flags; 2205195534Sscottl } else { 2206249468Smav status = xpt_create_path(&path, NULL, 2207195534Sscottl path_id, target_id, lun_id); 2208208911Smjacob /* 2209208911Smjacob * Free the old request path- we're done with it. We 2210208911Smjacob * do this *after* creating the new path so that 2211208911Smjacob * we don't remove a target that has our lun list 2212208911Smjacob * in the case that lun 0 is not present. 2213208911Smjacob */ 2214208911Smjacob xpt_free_path(oldpath); 2215195534Sscottl if (status != CAM_REQ_CMP) { 2216195688Semaste printf("scsi_scan_bus: xpt_create_path failed " 2217195534Sscottl "with status %#x, halting LUN scan\n", 2218195534Sscottl status); 2219195534Sscottl goto hop_again; 2220195534Sscottl } 2221195534Sscottl xpt_setup_ccb(&request_ccb->ccb_h, path, 2222195534Sscottl request_ccb->ccb_h.pinfo.priority); 2223195534Sscottl request_ccb->ccb_h.func_code = XPT_SCAN_LUN; 2224195534Sscottl request_ccb->ccb_h.cbfcnp = scsi_scan_bus; 2225260387Sscottl request_ccb->ccb_h.flags |= CAM_UNLOCKED; 2226195534Sscottl request_ccb->ccb_h.ppriv_ptr0 = scan_info; 2227195534Sscottl request_ccb->crcn.flags = 2228195534Sscottl scan_info->request_ccb->crcn.flags; 2229195534Sscottl } 2230260387Sscottl mtx_unlock(mtx); 2231195534Sscottl xpt_action(request_ccb); 2232195534Sscottl break; 2233195534Sscottl } 2234195534Sscottl default: 2235195534Sscottl break; 2236195534Sscottl } 2237195534Sscottl} 2238195534Sscottl 2239195534Sscottlstatic void 2240195534Sscottlscsi_scan_lun(struct cam_periph *periph, struct cam_path *path, 2241195534Sscottl cam_flags flags, union ccb *request_ccb) 2242195534Sscottl{ 2243195534Sscottl struct ccb_pathinq cpi; 2244195534Sscottl cam_status status; 2245195534Sscottl struct cam_path *new_path; 2246195534Sscottl struct cam_periph *old_periph; 2247260387Sscottl int lock; 2248195534Sscottl 2249203108Smav CAM_DEBUG(path, CAM_DEBUG_TRACE, ("scsi_scan_lun\n")); 2250195534Sscottl 2251203108Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 2252195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 2253195534Sscottl xpt_action((union ccb *)&cpi); 2254195534Sscottl 2255195534Sscottl if (cpi.ccb_h.status != CAM_REQ_CMP) { 2256195534Sscottl if (request_ccb != NULL) { 2257195534Sscottl request_ccb->ccb_h.status = cpi.ccb_h.status; 2258195534Sscottl xpt_done(request_ccb); 2259195534Sscottl } 2260195534Sscottl return; 2261195534Sscottl } 2262195534Sscottl 2263195534Sscottl if ((cpi.hba_misc & PIM_NOINITIATOR) != 0) { 2264195534Sscottl /* 2265195534Sscottl * Can't scan the bus on an adapter that 2266195534Sscottl * cannot perform the initiator role. 2267195534Sscottl */ 2268195534Sscottl if (request_ccb != NULL) { 2269195534Sscottl request_ccb->ccb_h.status = CAM_REQ_CMP; 2270195534Sscottl xpt_done(request_ccb); 2271195534Sscottl } 2272195534Sscottl return; 2273195534Sscottl } 2274195534Sscottl 2275195534Sscottl if (request_ccb == NULL) { 2276241455Smav request_ccb = xpt_alloc_ccb_nowait(); 2277195534Sscottl if (request_ccb == NULL) { 2278195688Semaste xpt_print(path, "scsi_scan_lun: can't allocate CCB, " 2279195534Sscottl "can't continue\n"); 2280195534Sscottl return; 2281195534Sscottl } 2282249468Smav status = xpt_create_path(&new_path, NULL, 2283195534Sscottl path->bus->path_id, 2284195534Sscottl path->target->target_id, 2285195534Sscottl path->device->lun_id); 2286195534Sscottl if (status != CAM_REQ_CMP) { 2287241455Smav xpt_print(path, "scsi_scan_lun: can't create path, " 2288195534Sscottl "can't continue\n"); 2289241455Smav xpt_free_ccb(request_ccb); 2290195534Sscottl return; 2291195534Sscottl } 2292203108Smav xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_XPT); 2293195534Sscottl request_ccb->ccb_h.cbfcnp = xptscandone; 2294195534Sscottl request_ccb->ccb_h.func_code = XPT_SCAN_LUN; 2295260387Sscottl request_ccb->ccb_h.flags |= CAM_UNLOCKED; 2296195534Sscottl request_ccb->crcn.flags = flags; 2297195534Sscottl } 2298195534Sscottl 2299260387Sscottl lock = (xpt_path_owned(path) == 0); 2300260387Sscottl if (lock) 2301260387Sscottl xpt_path_lock(path); 2302195534Sscottl if ((old_periph = cam_periph_find(path, "probe")) != NULL) { 2303236228Smav if ((old_periph->flags & CAM_PERIPH_INVALID) == 0) { 2304236228Smav probe_softc *softc; 2305195534Sscottl 2306236228Smav softc = (probe_softc *)old_periph->softc; 2307236228Smav TAILQ_INSERT_TAIL(&softc->request_ccbs, 2308236228Smav &request_ccb->ccb_h, periph_links.tqe); 2309236228Smav } else { 2310236228Smav request_ccb->ccb_h.status = CAM_REQ_CMP_ERR; 2311236228Smav xpt_done(request_ccb); 2312236228Smav } 2313195534Sscottl } else { 2314195534Sscottl status = cam_periph_alloc(proberegister, NULL, probecleanup, 2315195534Sscottl probestart, "probe", 2316195534Sscottl CAM_PERIPH_BIO, 2317195534Sscottl request_ccb->ccb_h.path, NULL, 0, 2318195534Sscottl request_ccb); 2319195534Sscottl 2320195534Sscottl if (status != CAM_REQ_CMP) { 2321195688Semaste xpt_print(path, "scsi_scan_lun: cam_alloc_periph " 2322195534Sscottl "returned an error, can't continue probe\n"); 2323195534Sscottl request_ccb->ccb_h.status = status; 2324195534Sscottl xpt_done(request_ccb); 2325195534Sscottl } 2326195534Sscottl } 2327260387Sscottl if (lock) 2328260387Sscottl xpt_path_unlock(path); 2329195534Sscottl} 2330195534Sscottl 2331195534Sscottlstatic void 2332195534Sscottlxptscandone(struct cam_periph *periph, union ccb *done_ccb) 2333195534Sscottl{ 2334241455Smav 2335241455Smav xpt_free_path(done_ccb->ccb_h.path); 2336241455Smav xpt_free_ccb(done_ccb); 2337195534Sscottl} 2338195534Sscottl 2339195534Sscottlstatic struct cam_ed * 2340195534Sscottlscsi_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id) 2341195534Sscottl{ 2342195534Sscottl struct scsi_quirk_entry *quirk; 2343195534Sscottl struct cam_ed *device; 2344195534Sscottl 2345195534Sscottl device = xpt_alloc_device(bus, target, lun_id); 2346195534Sscottl if (device == NULL) 2347195534Sscottl return (NULL); 2348195534Sscottl 2349195534Sscottl /* 2350195534Sscottl * Take the default quirk entry until we have inquiry 2351195534Sscottl * data and can determine a better quirk to use. 2352195534Sscottl */ 2353195534Sscottl quirk = &scsi_quirk_table[scsi_quirk_table_size - 1]; 2354195534Sscottl device->quirk = (void *)quirk; 2355195534Sscottl device->mintags = quirk->mintags; 2356195534Sscottl device->maxtags = quirk->maxtags; 2357195534Sscottl bzero(&device->inq_data, sizeof(device->inq_data)); 2358195534Sscottl device->inq_flags = 0; 2359195534Sscottl device->queue_flags = 0; 2360195534Sscottl device->serial_num = NULL; 2361195534Sscottl device->serial_num_len = 0; 2362216088Sken device->device_id = NULL; 2363216088Sken device->device_id_len = 0; 2364216088Sken device->supported_vpds = NULL; 2365216088Sken device->supported_vpds_len = 0; 2366195534Sscottl return (device); 2367195534Sscottl} 2368195534Sscottl 2369195534Sscottlstatic void 2370195534Sscottlscsi_devise_transport(struct cam_path *path) 2371195534Sscottl{ 2372195534Sscottl struct ccb_pathinq cpi; 2373195534Sscottl struct ccb_trans_settings cts; 2374195534Sscottl struct scsi_inquiry_data *inq_buf; 2375195534Sscottl 2376195534Sscottl /* Get transport information from the SIM */ 2377203108Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 2378195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 2379195534Sscottl xpt_action((union ccb *)&cpi); 2380195534Sscottl 2381195534Sscottl inq_buf = NULL; 2382195534Sscottl if ((path->device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0) 2383195534Sscottl inq_buf = &path->device->inq_data; 2384195534Sscottl path->device->protocol = PROTO_SCSI; 2385195534Sscottl path->device->protocol_version = 2386195534Sscottl inq_buf != NULL ? SID_ANSI_REV(inq_buf) : cpi.protocol_version; 2387195534Sscottl path->device->transport = cpi.transport; 2388195534Sscottl path->device->transport_version = cpi.transport_version; 2389195534Sscottl 2390195534Sscottl /* 2391195534Sscottl * Any device not using SPI3 features should 2392195534Sscottl * be considered SPI2 or lower. 2393195534Sscottl */ 2394195534Sscottl if (inq_buf != NULL) { 2395195534Sscottl if (path->device->transport == XPORT_SPI 2396195534Sscottl && (inq_buf->spi3data & SID_SPI_MASK) == 0 2397195534Sscottl && path->device->transport_version > 2) 2398195534Sscottl path->device->transport_version = 2; 2399195534Sscottl } else { 2400195534Sscottl struct cam_ed* otherdev; 2401195534Sscottl 2402195534Sscottl for (otherdev = TAILQ_FIRST(&path->target->ed_entries); 2403195534Sscottl otherdev != NULL; 2404195534Sscottl otherdev = TAILQ_NEXT(otherdev, links)) { 2405195534Sscottl if (otherdev != path->device) 2406195534Sscottl break; 2407195534Sscottl } 2408195534Sscottl 2409195534Sscottl if (otherdev != NULL) { 2410195534Sscottl /* 2411195534Sscottl * Initially assume the same versioning as 2412195534Sscottl * prior luns for this target. 2413195534Sscottl */ 2414195534Sscottl path->device->protocol_version = 2415195534Sscottl otherdev->protocol_version; 2416195534Sscottl path->device->transport_version = 2417195534Sscottl otherdev->transport_version; 2418195534Sscottl } else { 2419195534Sscottl /* Until we know better, opt for safty */ 2420195534Sscottl path->device->protocol_version = 2; 2421195534Sscottl if (path->device->transport == XPORT_SPI) 2422195534Sscottl path->device->transport_version = 2; 2423195534Sscottl else 2424195534Sscottl path->device->transport_version = 0; 2425195534Sscottl } 2426195534Sscottl } 2427195534Sscottl 2428195534Sscottl /* 2429195534Sscottl * XXX 2430195534Sscottl * For a device compliant with SPC-2 we should be able 2431195534Sscottl * to determine the transport version supported by 2432195534Sscottl * scrutinizing the version descriptors in the 2433195534Sscottl * inquiry buffer. 2434195534Sscottl */ 2435195534Sscottl 2436195534Sscottl /* Tell the controller what we think */ 2437203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 2438195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 2439195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 2440195534Sscottl cts.transport = path->device->transport; 2441195534Sscottl cts.transport_version = path->device->transport_version; 2442195534Sscottl cts.protocol = path->device->protocol; 2443195534Sscottl cts.protocol_version = path->device->protocol_version; 2444195534Sscottl cts.proto_specific.valid = 0; 2445195534Sscottl cts.xport_specific.valid = 0; 2446195534Sscottl xpt_action((union ccb *)&cts); 2447195534Sscottl} 2448195534Sscottl 2449195534Sscottlstatic void 2450223081Sgibbsscsi_dev_advinfo(union ccb *start_ccb) 2451216088Sken{ 2452216088Sken struct cam_ed *device; 2453223081Sgibbs struct ccb_dev_advinfo *cdai; 2454216088Sken off_t amt; 2455216088Sken 2456223448Swill start_ccb->ccb_h.status = CAM_REQ_INVALID; 2457216088Sken device = start_ccb->ccb_h.path->device; 2458223081Sgibbs cdai = &start_ccb->cdai; 2459223081Sgibbs switch(cdai->buftype) { 2460223081Sgibbs case CDAI_TYPE_SCSI_DEVID: 2461223081Sgibbs if (cdai->flags & CDAI_FLAG_STORE) 2462223448Swill return; 2463223081Sgibbs cdai->provsiz = device->device_id_len; 2464216088Sken if (device->device_id_len == 0) 2465216088Sken break; 2466216088Sken amt = device->device_id_len; 2467223081Sgibbs if (cdai->provsiz > cdai->bufsiz) 2468223081Sgibbs amt = cdai->bufsiz; 2469223081Sgibbs memcpy(cdai->buf, device->device_id, amt); 2470216088Sken break; 2471223081Sgibbs case CDAI_TYPE_SERIAL_NUM: 2472223081Sgibbs if (cdai->flags & CDAI_FLAG_STORE) 2473223448Swill return; 2474223081Sgibbs cdai->provsiz = device->serial_num_len; 2475223081Sgibbs if (device->serial_num_len == 0) 2476223081Sgibbs break; 2477223081Sgibbs amt = device->serial_num_len; 2478223081Sgibbs if (cdai->provsiz > cdai->bufsiz) 2479223081Sgibbs amt = cdai->bufsiz; 2480223081Sgibbs memcpy(cdai->buf, device->serial_num, amt); 2481223081Sgibbs break; 2482223081Sgibbs case CDAI_TYPE_PHYS_PATH: 2483223081Sgibbs if (cdai->flags & CDAI_FLAG_STORE) { 2484230590Sken if (device->physpath != NULL) { 2485223081Sgibbs free(device->physpath, M_CAMXPT); 2486230590Sken device->physpath = NULL; 2487230590Sken } 2488223081Sgibbs device->physpath_len = cdai->bufsiz; 2489223081Sgibbs /* Clear existing buffer if zero length */ 2490223081Sgibbs if (cdai->bufsiz == 0) 2491223081Sgibbs break; 2492223081Sgibbs device->physpath = malloc(cdai->bufsiz, M_CAMXPT, M_NOWAIT); 2493223081Sgibbs if (device->physpath == NULL) { 2494223081Sgibbs start_ccb->ccb_h.status = CAM_REQ_ABORTED; 2495223081Sgibbs return; 2496223081Sgibbs } 2497223081Sgibbs memcpy(device->physpath, cdai->buf, cdai->bufsiz); 2498223081Sgibbs } else { 2499223081Sgibbs cdai->provsiz = device->physpath_len; 2500223081Sgibbs if (device->physpath_len == 0) 2501223081Sgibbs break; 2502223081Sgibbs amt = device->physpath_len; 2503223081Sgibbs if (cdai->provsiz > cdai->bufsiz) 2504223081Sgibbs amt = cdai->bufsiz; 2505223081Sgibbs memcpy(cdai->buf, device->physpath, amt); 2506223081Sgibbs } 2507223081Sgibbs break; 2508230590Sken case CDAI_TYPE_RCAPLONG: 2509230590Sken if (cdai->flags & CDAI_FLAG_STORE) { 2510230590Sken if (device->rcap_buf != NULL) { 2511230590Sken free(device->rcap_buf, M_CAMXPT); 2512230590Sken device->rcap_buf = NULL; 2513230590Sken } 2514230590Sken 2515230590Sken device->rcap_len = cdai->bufsiz; 2516230590Sken /* Clear existing buffer if zero length */ 2517230590Sken if (cdai->bufsiz == 0) 2518230590Sken break; 2519230590Sken 2520230590Sken device->rcap_buf = malloc(cdai->bufsiz, M_CAMXPT, 2521230590Sken M_NOWAIT); 2522230590Sken if (device->rcap_buf == NULL) { 2523230590Sken start_ccb->ccb_h.status = CAM_REQ_ABORTED; 2524230590Sken return; 2525230590Sken } 2526230590Sken 2527230590Sken memcpy(device->rcap_buf, cdai->buf, cdai->bufsiz); 2528230590Sken } else { 2529230590Sken cdai->provsiz = device->rcap_len; 2530230590Sken if (device->rcap_len == 0) 2531230590Sken break; 2532230590Sken amt = device->rcap_len; 2533230590Sken if (cdai->provsiz > cdai->bufsiz) 2534230590Sken amt = cdai->bufsiz; 2535230590Sken memcpy(cdai->buf, device->rcap_buf, amt); 2536230590Sken } 2537230590Sken break; 2538216088Sken default: 2539223448Swill return; 2540216088Sken } 2541216088Sken start_ccb->ccb_h.status = CAM_REQ_CMP; 2542223081Sgibbs 2543223081Sgibbs if (cdai->flags & CDAI_FLAG_STORE) { 2544223081Sgibbs xpt_async(AC_ADVINFO_CHANGED, start_ccb->ccb_h.path, 2545223081Sgibbs (void *)(uintptr_t)cdai->buftype); 2546223081Sgibbs } 2547216088Sken} 2548216088Sken 2549216088Skenstatic void 2550195534Sscottlscsi_action(union ccb *start_ccb) 2551195534Sscottl{ 2552195534Sscottl 2553195534Sscottl switch (start_ccb->ccb_h.func_code) { 2554195534Sscottl case XPT_SET_TRAN_SETTINGS: 2555195534Sscottl { 2556195534Sscottl scsi_set_transfer_settings(&start_ccb->cts, 2557260387Sscottl start_ccb->ccb_h.path, 2558195534Sscottl /*async_update*/FALSE); 2559195534Sscottl break; 2560195534Sscottl } 2561195534Sscottl case XPT_SCAN_BUS: 2562208582Smjacob case XPT_SCAN_TGT: 2563195534Sscottl scsi_scan_bus(start_ccb->ccb_h.path->periph, start_ccb); 2564195534Sscottl break; 2565195534Sscottl case XPT_SCAN_LUN: 2566195534Sscottl scsi_scan_lun(start_ccb->ccb_h.path->periph, 2567195534Sscottl start_ccb->ccb_h.path, start_ccb->crcn.flags, 2568195534Sscottl start_ccb); 2569195534Sscottl break; 2570223081Sgibbs case XPT_DEV_ADVINFO: 2571216088Sken { 2572223081Sgibbs scsi_dev_advinfo(start_ccb); 2573216088Sken break; 2574216088Sken } 2575195534Sscottl default: 2576195534Sscottl xpt_action_default(start_ccb); 2577195534Sscottl break; 2578195534Sscottl } 2579195534Sscottl} 2580195534Sscottl 2581195534Sscottlstatic void 2582260387Sscottlscsi_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_path *path, 2583195534Sscottl int async_update) 2584195534Sscottl{ 2585195534Sscottl struct ccb_pathinq cpi; 2586195534Sscottl struct ccb_trans_settings cur_cts; 2587195534Sscottl struct ccb_trans_settings_scsi *scsi; 2588195534Sscottl struct ccb_trans_settings_scsi *cur_scsi; 2589195534Sscottl struct scsi_inquiry_data *inq_data; 2590260387Sscottl struct cam_ed *device; 2591195534Sscottl 2592260387Sscottl if (path == NULL || (device = path->device) == NULL) { 2593195534Sscottl cts->ccb_h.status = CAM_PATH_INVALID; 2594195534Sscottl xpt_done((union ccb *)cts); 2595195534Sscottl return; 2596195534Sscottl } 2597195534Sscottl 2598195534Sscottl if (cts->protocol == PROTO_UNKNOWN 2599195534Sscottl || cts->protocol == PROTO_UNSPECIFIED) { 2600195534Sscottl cts->protocol = device->protocol; 2601195534Sscottl cts->protocol_version = device->protocol_version; 2602195534Sscottl } 2603195534Sscottl 2604195534Sscottl if (cts->protocol_version == PROTO_VERSION_UNKNOWN 2605195534Sscottl || cts->protocol_version == PROTO_VERSION_UNSPECIFIED) 2606195534Sscottl cts->protocol_version = device->protocol_version; 2607195534Sscottl 2608195534Sscottl if (cts->protocol != device->protocol) { 2609260387Sscottl xpt_print(path, "Uninitialized Protocol %x:%x?\n", 2610195534Sscottl cts->protocol, device->protocol); 2611195534Sscottl cts->protocol = device->protocol; 2612195534Sscottl } 2613195534Sscottl 2614195534Sscottl if (cts->protocol_version > device->protocol_version) { 2615195534Sscottl if (bootverbose) { 2616260387Sscottl xpt_print(path, "Down reving Protocol " 2617195534Sscottl "Version from %d to %d?\n", cts->protocol_version, 2618195534Sscottl device->protocol_version); 2619195534Sscottl } 2620195534Sscottl cts->protocol_version = device->protocol_version; 2621195534Sscottl } 2622195534Sscottl 2623195534Sscottl if (cts->transport == XPORT_UNKNOWN 2624195534Sscottl || cts->transport == XPORT_UNSPECIFIED) { 2625195534Sscottl cts->transport = device->transport; 2626195534Sscottl cts->transport_version = device->transport_version; 2627195534Sscottl } 2628195534Sscottl 2629195534Sscottl if (cts->transport_version == XPORT_VERSION_UNKNOWN 2630195534Sscottl || cts->transport_version == XPORT_VERSION_UNSPECIFIED) 2631195534Sscottl cts->transport_version = device->transport_version; 2632195534Sscottl 2633195534Sscottl if (cts->transport != device->transport) { 2634260387Sscottl xpt_print(path, "Uninitialized Transport %x:%x?\n", 2635195534Sscottl cts->transport, device->transport); 2636195534Sscottl cts->transport = device->transport; 2637195534Sscottl } 2638195534Sscottl 2639195534Sscottl if (cts->transport_version > device->transport_version) { 2640195534Sscottl if (bootverbose) { 2641260387Sscottl xpt_print(path, "Down reving Transport " 2642195534Sscottl "Version from %d to %d?\n", cts->transport_version, 2643195534Sscottl device->transport_version); 2644195534Sscottl } 2645195534Sscottl cts->transport_version = device->transport_version; 2646195534Sscottl } 2647195534Sscottl 2648195534Sscottl /* 2649195534Sscottl * Nothing more of interest to do unless 2650195534Sscottl * this is a device connected via the 2651195534Sscottl * SCSI protocol. 2652195534Sscottl */ 2653195534Sscottl if (cts->protocol != PROTO_SCSI) { 2654195534Sscottl if (async_update == FALSE) 2655260387Sscottl xpt_action_default((union ccb *)cts); 2656195534Sscottl return; 2657195534Sscottl } 2658195534Sscottl 2659195534Sscottl inq_data = &device->inq_data; 2660195534Sscottl scsi = &cts->proto_specific.scsi; 2661260387Sscottl xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 2662195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 2663195534Sscottl xpt_action((union ccb *)&cpi); 2664195534Sscottl 2665195534Sscottl /* SCSI specific sanity checking */ 2666195534Sscottl if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0 2667195534Sscottl || (INQ_DATA_TQ_ENABLED(inq_data)) == 0 2668195534Sscottl || (device->queue_flags & SCP_QUEUE_DQUE) != 0 2669195534Sscottl || (device->mintags == 0)) { 2670195534Sscottl /* 2671195534Sscottl * Can't tag on hardware that doesn't support tags, 2672195534Sscottl * doesn't have it enabled, or has broken tag support. 2673195534Sscottl */ 2674195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 2675195534Sscottl } 2676195534Sscottl 2677195534Sscottl if (async_update == FALSE) { 2678195534Sscottl /* 2679195534Sscottl * Perform sanity checking against what the 2680195534Sscottl * controller and device can do. 2681195534Sscottl */ 2682260387Sscottl xpt_setup_ccb(&cur_cts.ccb_h, path, CAM_PRIORITY_NONE); 2683195534Sscottl cur_cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 2684195534Sscottl cur_cts.type = cts->type; 2685195534Sscottl xpt_action((union ccb *)&cur_cts); 2686252382Sscottl if (cam_ccb_status((union ccb *)&cur_cts) != CAM_REQ_CMP) { 2687195534Sscottl return; 2688195534Sscottl } 2689195534Sscottl cur_scsi = &cur_cts.proto_specific.scsi; 2690195534Sscottl if ((scsi->valid & CTS_SCSI_VALID_TQ) == 0) { 2691195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 2692195534Sscottl scsi->flags |= cur_scsi->flags & CTS_SCSI_FLAGS_TAG_ENB; 2693195534Sscottl } 2694195534Sscottl if ((cur_scsi->valid & CTS_SCSI_VALID_TQ) == 0) 2695195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 2696195534Sscottl } 2697195534Sscottl 2698195534Sscottl /* SPI specific sanity checking */ 2699195534Sscottl if (cts->transport == XPORT_SPI && async_update == FALSE) { 2700195534Sscottl u_int spi3caps; 2701195534Sscottl struct ccb_trans_settings_spi *spi; 2702195534Sscottl struct ccb_trans_settings_spi *cur_spi; 2703195534Sscottl 2704195534Sscottl spi = &cts->xport_specific.spi; 2705195534Sscottl 2706195534Sscottl cur_spi = &cur_cts.xport_specific.spi; 2707195534Sscottl 2708195534Sscottl /* Fill in any gaps in what the user gave us */ 2709195534Sscottl if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) 2710195534Sscottl spi->sync_period = cur_spi->sync_period; 2711195534Sscottl if ((cur_spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) 2712195534Sscottl spi->sync_period = 0; 2713195534Sscottl if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0) 2714195534Sscottl spi->sync_offset = cur_spi->sync_offset; 2715195534Sscottl if ((cur_spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0) 2716195534Sscottl spi->sync_offset = 0; 2717195534Sscottl if ((spi->valid & CTS_SPI_VALID_PPR_OPTIONS) == 0) 2718195534Sscottl spi->ppr_options = cur_spi->ppr_options; 2719195534Sscottl if ((cur_spi->valid & CTS_SPI_VALID_PPR_OPTIONS) == 0) 2720195534Sscottl spi->ppr_options = 0; 2721195534Sscottl if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) == 0) 2722195534Sscottl spi->bus_width = cur_spi->bus_width; 2723195534Sscottl if ((cur_spi->valid & CTS_SPI_VALID_BUS_WIDTH) == 0) 2724195534Sscottl spi->bus_width = 0; 2725195534Sscottl if ((spi->valid & CTS_SPI_VALID_DISC) == 0) { 2726195534Sscottl spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; 2727195534Sscottl spi->flags |= cur_spi->flags & CTS_SPI_FLAGS_DISC_ENB; 2728195534Sscottl } 2729195534Sscottl if ((cur_spi->valid & CTS_SPI_VALID_DISC) == 0) 2730195534Sscottl spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; 2731195534Sscottl if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0 2732195534Sscottl && (inq_data->flags & SID_Sync) == 0 2733195534Sscottl && cts->type == CTS_TYPE_CURRENT_SETTINGS) 2734195534Sscottl || ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0)) { 2735195534Sscottl /* Force async */ 2736195534Sscottl spi->sync_period = 0; 2737195534Sscottl spi->sync_offset = 0; 2738195534Sscottl } 2739195534Sscottl 2740195534Sscottl switch (spi->bus_width) { 2741195534Sscottl case MSG_EXT_WDTR_BUS_32_BIT: 2742195534Sscottl if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) == 0 2743195534Sscottl || (inq_data->flags & SID_WBus32) != 0 2744195534Sscottl || cts->type == CTS_TYPE_USER_SETTINGS) 2745195534Sscottl && (cpi.hba_inquiry & PI_WIDE_32) != 0) 2746195534Sscottl break; 2747195534Sscottl /* Fall Through to 16-bit */ 2748195534Sscottl case MSG_EXT_WDTR_BUS_16_BIT: 2749195534Sscottl if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) == 0 2750195534Sscottl || (inq_data->flags & SID_WBus16) != 0 2751195534Sscottl || cts->type == CTS_TYPE_USER_SETTINGS) 2752195534Sscottl && (cpi.hba_inquiry & PI_WIDE_16) != 0) { 2753195534Sscottl spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT; 2754195534Sscottl break; 2755195534Sscottl } 2756195534Sscottl /* Fall Through to 8-bit */ 2757195534Sscottl default: /* New bus width?? */ 2758195534Sscottl case MSG_EXT_WDTR_BUS_8_BIT: 2759195534Sscottl /* All targets can do this */ 2760195534Sscottl spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT; 2761195534Sscottl break; 2762195534Sscottl } 2763195534Sscottl 2764195534Sscottl spi3caps = cpi.xport_specific.spi.ppr_options; 2765195534Sscottl if ((device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0 2766195534Sscottl && cts->type == CTS_TYPE_CURRENT_SETTINGS) 2767195534Sscottl spi3caps &= inq_data->spi3data; 2768195534Sscottl 2769195534Sscottl if ((spi3caps & SID_SPI_CLOCK_DT) == 0) 2770195534Sscottl spi->ppr_options &= ~MSG_EXT_PPR_DT_REQ; 2771195534Sscottl 2772195534Sscottl if ((spi3caps & SID_SPI_IUS) == 0) 2773195534Sscottl spi->ppr_options &= ~MSG_EXT_PPR_IU_REQ; 2774195534Sscottl 2775195534Sscottl if ((spi3caps & SID_SPI_QAS) == 0) 2776195534Sscottl spi->ppr_options &= ~MSG_EXT_PPR_QAS_REQ; 2777195534Sscottl 2778195534Sscottl /* No SPI Transfer settings are allowed unless we are wide */ 2779195534Sscottl if (spi->bus_width == 0) 2780195534Sscottl spi->ppr_options = 0; 2781195534Sscottl 2782195534Sscottl if ((spi->valid & CTS_SPI_VALID_DISC) 2783195534Sscottl && ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) == 0)) { 2784195534Sscottl /* 2785195534Sscottl * Can't tag queue without disconnection. 2786195534Sscottl */ 2787195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 2788195534Sscottl scsi->valid |= CTS_SCSI_VALID_TQ; 2789195534Sscottl } 2790195534Sscottl 2791195534Sscottl /* 2792195534Sscottl * If we are currently performing tagged transactions to 2793195534Sscottl * this device and want to change its negotiation parameters, 2794195534Sscottl * go non-tagged for a bit to give the controller a chance to 2795195534Sscottl * negotiate unhampered by tag messages. 2796195534Sscottl */ 2797195534Sscottl if (cts->type == CTS_TYPE_CURRENT_SETTINGS 2798195534Sscottl && (device->inq_flags & SID_CmdQue) != 0 2799195534Sscottl && (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0 2800195534Sscottl && (spi->flags & (CTS_SPI_VALID_SYNC_RATE| 2801195534Sscottl CTS_SPI_VALID_SYNC_OFFSET| 2802195534Sscottl CTS_SPI_VALID_BUS_WIDTH)) != 0) 2803260387Sscottl scsi_toggle_tags(path); 2804195534Sscottl } 2805195534Sscottl 2806195534Sscottl if (cts->type == CTS_TYPE_CURRENT_SETTINGS 2807195534Sscottl && (scsi->valid & CTS_SCSI_VALID_TQ) != 0) { 2808195534Sscottl int device_tagenb; 2809195534Sscottl 2810195534Sscottl /* 2811195534Sscottl * If we are transitioning from tags to no-tags or 2812195534Sscottl * vice-versa, we need to carefully freeze and restart 2813195534Sscottl * the queue so that we don't overlap tagged and non-tagged 2814195534Sscottl * commands. We also temporarily stop tags if there is 2815195534Sscottl * a change in transfer negotiation settings to allow 2816195534Sscottl * "tag-less" negotiation. 2817195534Sscottl */ 2818195534Sscottl if ((device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 2819195534Sscottl || (device->inq_flags & SID_CmdQue) != 0) 2820195534Sscottl device_tagenb = TRUE; 2821195534Sscottl else 2822195534Sscottl device_tagenb = FALSE; 2823195534Sscottl 2824195534Sscottl if (((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0 2825195534Sscottl && device_tagenb == FALSE) 2826195534Sscottl || ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) == 0 2827195534Sscottl && device_tagenb == TRUE)) { 2828195534Sscottl 2829195534Sscottl if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) { 2830195534Sscottl /* 2831195534Sscottl * Delay change to use tags until after a 2832195534Sscottl * few commands have gone to this device so 2833195534Sscottl * the controller has time to perform transfer 2834195534Sscottl * negotiations without tagged messages getting 2835195534Sscottl * in the way. 2836195534Sscottl */ 2837195534Sscottl device->tag_delay_count = CAM_TAG_DELAY_COUNT; 2838195534Sscottl device->flags |= CAM_DEV_TAG_AFTER_COUNT; 2839195534Sscottl } else { 2840260387Sscottl xpt_stop_tags(path); 2841195534Sscottl } 2842195534Sscottl } 2843195534Sscottl } 2844195534Sscottl if (async_update == FALSE) 2845260387Sscottl xpt_action_default((union ccb *)cts); 2846195534Sscottl} 2847195534Sscottl 2848195534Sscottlstatic void 2849195534Sscottlscsi_toggle_tags(struct cam_path *path) 2850195534Sscottl{ 2851195534Sscottl struct cam_ed *dev; 2852195534Sscottl 2853195534Sscottl /* 2854195534Sscottl * Give controllers a chance to renegotiate 2855195534Sscottl * before starting tag operations. We 2856195534Sscottl * "toggle" tagged queuing off then on 2857195534Sscottl * which causes the tag enable command delay 2858195534Sscottl * counter to come into effect. 2859195534Sscottl */ 2860195534Sscottl dev = path->device; 2861195534Sscottl if ((dev->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 2862195534Sscottl || ((dev->inq_flags & SID_CmdQue) != 0 2863195534Sscottl && (dev->inq_flags & (SID_Sync|SID_WBus16|SID_WBus32)) != 0)) { 2864195534Sscottl struct ccb_trans_settings cts; 2865195534Sscottl 2866203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 2867195534Sscottl cts.protocol = PROTO_SCSI; 2868195534Sscottl cts.protocol_version = PROTO_VERSION_UNSPECIFIED; 2869195534Sscottl cts.transport = XPORT_UNSPECIFIED; 2870195534Sscottl cts.transport_version = XPORT_VERSION_UNSPECIFIED; 2871195534Sscottl cts.proto_specific.scsi.flags = 0; 2872195534Sscottl cts.proto_specific.scsi.valid = CTS_SCSI_VALID_TQ; 2873260387Sscottl scsi_set_transfer_settings(&cts, path, 2874195534Sscottl /*async_update*/TRUE); 2875195534Sscottl cts.proto_specific.scsi.flags = CTS_SCSI_FLAGS_TAG_ENB; 2876260387Sscottl scsi_set_transfer_settings(&cts, path, 2877195534Sscottl /*async_update*/TRUE); 2878195534Sscottl } 2879195534Sscottl} 2880195534Sscottl 2881195534Sscottl/* 2882195534Sscottl * Handle any per-device event notifications that require action by the XPT. 2883195534Sscottl */ 2884195534Sscottlstatic void 2885195534Sscottlscsi_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target, 2886195534Sscottl struct cam_ed *device, void *async_arg) 2887195534Sscottl{ 2888195534Sscottl cam_status status; 2889195534Sscottl struct cam_path newpath; 2890195534Sscottl 2891195534Sscottl /* 2892195534Sscottl * We only need to handle events for real devices. 2893195534Sscottl */ 2894195534Sscottl if (target->target_id == CAM_TARGET_WILDCARD 2895195534Sscottl || device->lun_id == CAM_LUN_WILDCARD) 2896195534Sscottl return; 2897195534Sscottl 2898195534Sscottl /* 2899195534Sscottl * We need our own path with wildcards expanded to 2900195534Sscottl * handle certain types of events. 2901195534Sscottl */ 2902195534Sscottl if ((async_code == AC_SENT_BDR) 2903195534Sscottl || (async_code == AC_BUS_RESET) 2904195534Sscottl || (async_code == AC_INQ_CHANGED)) 2905195534Sscottl status = xpt_compile_path(&newpath, NULL, 2906195534Sscottl bus->path_id, 2907195534Sscottl target->target_id, 2908195534Sscottl device->lun_id); 2909195534Sscottl else 2910195534Sscottl status = CAM_REQ_CMP_ERR; 2911195534Sscottl 2912195534Sscottl if (status == CAM_REQ_CMP) { 2913195534Sscottl 2914195534Sscottl /* 2915195534Sscottl * Allow transfer negotiation to occur in a 2916203108Smav * tag free environment and after settle delay. 2917195534Sscottl */ 2918195534Sscottl if (async_code == AC_SENT_BDR 2919203108Smav || async_code == AC_BUS_RESET) { 2920203108Smav cam_freeze_devq(&newpath); 2921203108Smav cam_release_devq(&newpath, 2922203108Smav RELSIM_RELEASE_AFTER_TIMEOUT, 2923203108Smav /*reduction*/0, 2924203108Smav /*timeout*/scsi_delay, 2925203108Smav /*getcount_only*/0); 2926195534Sscottl scsi_toggle_tags(&newpath); 2927203108Smav } 2928195534Sscottl 2929195534Sscottl if (async_code == AC_INQ_CHANGED) { 2930195534Sscottl /* 2931195534Sscottl * We've sent a start unit command, or 2932195534Sscottl * something similar to a device that 2933195534Sscottl * may have caused its inquiry data to 2934195534Sscottl * change. So we re-scan the device to 2935195534Sscottl * refresh the inquiry data for it. 2936195534Sscottl */ 2937195534Sscottl scsi_scan_lun(newpath.periph, &newpath, 2938195534Sscottl CAM_EXPECT_INQ_CHANGE, NULL); 2939195534Sscottl } 2940195534Sscottl xpt_release_path(&newpath); 2941198748Smav } else if (async_code == AC_LOST_DEVICE && 2942198748Smav (device->flags & CAM_DEV_UNCONFIGURED) == 0) { 2943195534Sscottl device->flags |= CAM_DEV_UNCONFIGURED; 2944198748Smav xpt_release_device(device); 2945195534Sscottl } else if (async_code == AC_TRANSFER_NEG) { 2946195534Sscottl struct ccb_trans_settings *settings; 2947260387Sscottl struct cam_path path; 2948195534Sscottl 2949195534Sscottl settings = (struct ccb_trans_settings *)async_arg; 2950260387Sscottl xpt_compile_path(&path, NULL, bus->path_id, target->target_id, 2951260387Sscottl device->lun_id); 2952260387Sscottl scsi_set_transfer_settings(settings, &path, 2953195534Sscottl /*async_update*/TRUE); 2954260387Sscottl xpt_release_path(&path); 2955195534Sscottl } 2956195534Sscottl} 2957195534Sscottl 2958204220Smavstatic void 2959204220Smavscsi_announce_periph(struct cam_periph *periph) 2960204220Smav{ 2961204220Smav struct ccb_pathinq cpi; 2962204220Smav struct ccb_trans_settings cts; 2963204220Smav struct cam_path *path = periph->path; 2964204220Smav u_int speed; 2965204220Smav u_int freq; 2966204220Smav u_int mb; 2967204220Smav 2968260387Sscottl cam_periph_assert(periph, MA_OWNED); 2969204220Smav 2970204220Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); 2971204220Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 2972204220Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 2973204220Smav xpt_action((union ccb*)&cts); 2974252382Sscottl if (cam_ccb_status((union ccb *)&cts) != CAM_REQ_CMP) 2975204220Smav return; 2976204220Smav /* Ask the SIM for its base transfer speed */ 2977204220Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL); 2978204220Smav cpi.ccb_h.func_code = XPT_PATH_INQ; 2979204220Smav xpt_action((union ccb *)&cpi); 2980204220Smav /* Report connection speed */ 2981204220Smav speed = cpi.base_transfer_speed; 2982204220Smav freq = 0; 2983204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SPI) { 2984204220Smav struct ccb_trans_settings_spi *spi = 2985204220Smav &cts.xport_specific.spi; 2986204220Smav 2987204220Smav if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0 2988204220Smav && spi->sync_offset != 0) { 2989204220Smav freq = scsi_calc_syncsrate(spi->sync_period); 2990204220Smav speed = freq; 2991204220Smav } 2992204220Smav if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) 2993204220Smav speed *= (0x01 << spi->bus_width); 2994204220Smav } 2995204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_FC) { 2996204220Smav struct ccb_trans_settings_fc *fc = 2997204220Smav &cts.xport_specific.fc; 2998204220Smav 2999204220Smav if (fc->valid & CTS_FC_VALID_SPEED) 3000204220Smav speed = fc->bitrate; 3001204220Smav } 3002204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SAS) { 3003204220Smav struct ccb_trans_settings_sas *sas = 3004204220Smav &cts.xport_specific.sas; 3005204220Smav 3006204220Smav if (sas->valid & CTS_SAS_VALID_SPEED) 3007204220Smav speed = sas->bitrate; 3008204220Smav } 3009204220Smav mb = speed / 1000; 3010204220Smav if (mb > 0) 3011204220Smav printf("%s%d: %d.%03dMB/s transfers", 3012204220Smav periph->periph_name, periph->unit_number, 3013204220Smav mb, speed % 1000); 3014204220Smav else 3015204220Smav printf("%s%d: %dKB/s transfers", periph->periph_name, 3016204220Smav periph->unit_number, speed); 3017204220Smav /* Report additional information about SPI connections */ 3018204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SPI) { 3019204220Smav struct ccb_trans_settings_spi *spi; 3020204220Smav 3021204220Smav spi = &cts.xport_specific.spi; 3022204220Smav if (freq != 0) { 3023204220Smav printf(" (%d.%03dMHz%s, offset %d", freq / 1000, 3024204220Smav freq % 1000, 3025204220Smav (spi->ppr_options & MSG_EXT_PPR_DT_REQ) != 0 3026204220Smav ? " DT" : "", 3027204220Smav spi->sync_offset); 3028204220Smav } 3029204220Smav if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0 3030204220Smav && spi->bus_width > 0) { 3031204220Smav if (freq != 0) { 3032204220Smav printf(", "); 3033204220Smav } else { 3034204220Smav printf(" ("); 3035204220Smav } 3036204220Smav printf("%dbit)", 8 * (0x01 << spi->bus_width)); 3037204220Smav } else if (freq != 0) { 3038204220Smav printf(")"); 3039204220Smav } 3040204220Smav } 3041204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_FC) { 3042204220Smav struct ccb_trans_settings_fc *fc; 3043204220Smav 3044204220Smav fc = &cts.xport_specific.fc; 3045204220Smav if (fc->valid & CTS_FC_VALID_WWNN) 3046204220Smav printf(" WWNN 0x%llx", (long long) fc->wwnn); 3047204220Smav if (fc->valid & CTS_FC_VALID_WWPN) 3048204220Smav printf(" WWPN 0x%llx", (long long) fc->wwpn); 3049204220Smav if (fc->valid & CTS_FC_VALID_PORT) 3050204220Smav printf(" PortID 0x%x", fc->port); 3051204220Smav } 3052204220Smav printf("\n"); 3053204220Smav} 3054204220Smav 3055