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 } 103195534Sscottl/* 104195534Sscottl * If we're not quirked to search <= the first 8 luns 105195534Sscottl * and we are either quirked to search above lun 8, 106195534Sscottl * or we're > SCSI-2 and we've enabled hilun searching, 107195534Sscottl * or we're > SCSI-2 and the last lun was a success, 108195534Sscottl * we can look for luns above lun 8. 109195534Sscottl */ 110195534Sscottl#define CAN_SRCH_HI_SPARSE(dv) \ 111195534Sscottl (((SCSI_QUIRK(dv)->quirks & CAM_QUIRK_NOHILUNS) == 0) \ 112195534Sscottl && ((SCSI_QUIRK(dv)->quirks & CAM_QUIRK_HILUNS) \ 113195534Sscottl || (SID_ANSI_REV(&dv->inq_data) > SCSI_REV_2 && cam_srch_hi))) 114195534Sscottl 115195534Sscottl#define CAN_SRCH_HI_DENSE(dv) \ 116195534Sscottl (((SCSI_QUIRK(dv)->quirks & CAM_QUIRK_NOHILUNS) == 0) \ 117195534Sscottl && ((SCSI_QUIRK(dv)->quirks & CAM_QUIRK_HILUNS) \ 118195534Sscottl || (SID_ANSI_REV(&dv->inq_data) > SCSI_REV_2))) 119195534Sscottl 120195534Sscottlstatic periph_init_t probe_periph_init; 121195534Sscottl 122195534Sscottlstatic struct periph_driver probe_driver = 123195534Sscottl{ 124195534Sscottl probe_periph_init, "probe", 125198708Smav TAILQ_HEAD_INITIALIZER(probe_driver.units), /* generation */ 0, 126198708Smav CAM_PERIPH_DRV_EARLY 127195534Sscottl}; 128195534Sscottl 129195534SscottlPERIPHDRIVER_DECLARE(probe, probe_driver); 130195534Sscottl 131195534Sscottltypedef enum { 132195534Sscottl PROBE_TUR, 133195534Sscottl PROBE_INQUIRY, /* this counts as DV0 for Basic Domain Validation */ 134195534Sscottl PROBE_FULL_INQUIRY, 135208911Smjacob PROBE_REPORT_LUNS, 136195534Sscottl PROBE_MODE_SENSE, 137216088Sken PROBE_SUPPORTED_VPD_LIST, 138216088Sken PROBE_DEVICE_ID, 139216088Sken PROBE_SERIAL_NUM, 140195534Sscottl PROBE_TUR_FOR_NEGOTIATION, 141195534Sscottl PROBE_INQUIRY_BASIC_DV1, 142195534Sscottl PROBE_INQUIRY_BASIC_DV2, 143195534Sscottl PROBE_DV_EXIT, 144236613Smav PROBE_DONE, 145195534Sscottl PROBE_INVALID 146195534Sscottl} probe_action; 147195534Sscottl 148195534Sscottlstatic char *probe_action_text[] = { 149195534Sscottl "PROBE_TUR", 150195534Sscottl "PROBE_INQUIRY", 151195534Sscottl "PROBE_FULL_INQUIRY", 152208911Smjacob "PROBE_REPORT_LUNS", 153195534Sscottl "PROBE_MODE_SENSE", 154216088Sken "PROBE_SUPPORTED_VPD_LIST", 155216088Sken "PROBE_DEVICE_ID", 156216088Sken "PROBE_SERIAL_NUM", 157195534Sscottl "PROBE_TUR_FOR_NEGOTIATION", 158195534Sscottl "PROBE_INQUIRY_BASIC_DV1", 159195534Sscottl "PROBE_INQUIRY_BASIC_DV2", 160195534Sscottl "PROBE_DV_EXIT", 161236613Smav "PROBE_DONE", 162195534Sscottl "PROBE_INVALID" 163195534Sscottl}; 164195534Sscottl 165195534Sscottl#define PROBE_SET_ACTION(softc, newaction) \ 166195534Sscottldo { \ 167195534Sscottl char **text; \ 168195534Sscottl text = probe_action_text; \ 169236613Smav CAM_DEBUG((softc)->periph->path, CAM_DEBUG_PROBE, \ 170195534Sscottl ("Probe %s to %s\n", text[(softc)->action], \ 171195534Sscottl text[(newaction)])); \ 172195534Sscottl (softc)->action = (newaction); \ 173195534Sscottl} while(0) 174195534Sscottl 175195534Sscottltypedef enum { 176195534Sscottl PROBE_INQUIRY_CKSUM = 0x01, 177195534Sscottl PROBE_SERIAL_CKSUM = 0x02, 178195534Sscottl PROBE_NO_ANNOUNCE = 0x04 179195534Sscottl} probe_flags; 180195534Sscottl 181195534Sscottltypedef struct { 182195534Sscottl TAILQ_HEAD(, ccb_hdr) request_ccbs; 183195534Sscottl probe_action action; 184195534Sscottl union ccb saved_ccb; 185195534Sscottl probe_flags flags; 186195534Sscottl MD5_CTX context; 187195534Sscottl u_int8_t digest[16]; 188195534Sscottl struct cam_periph *periph; 189195534Sscottl} probe_softc; 190195534Sscottl 191195534Sscottlstatic const char quantum[] = "QUANTUM"; 192195534Sscottlstatic const char sony[] = "SONY"; 193195534Sscottlstatic const char west_digital[] = "WDIGTL"; 194195534Sscottlstatic const char samsung[] = "SAMSUNG"; 195195534Sscottlstatic const char seagate[] = "SEAGATE"; 196195534Sscottlstatic const char microp[] = "MICROP"; 197195534Sscottl 198195534Sscottlstatic struct scsi_quirk_entry scsi_quirk_table[] = 199195534Sscottl{ 200195534Sscottl { 201195534Sscottl /* Reports QUEUE FULL for temporary resource shortages */ 202195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, quantum, "XP39100*", "*" }, 203195534Sscottl /*quirks*/0, /*mintags*/24, /*maxtags*/32 204195534Sscottl }, 205195534Sscottl { 206195534Sscottl /* Reports QUEUE FULL for temporary resource shortages */ 207195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, quantum, "XP34550*", "*" }, 208195534Sscottl /*quirks*/0, /*mintags*/24, /*maxtags*/32 209195534Sscottl }, 210195534Sscottl { 211195534Sscottl /* Reports QUEUE FULL for temporary resource shortages */ 212195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, quantum, "XP32275*", "*" }, 213195534Sscottl /*quirks*/0, /*mintags*/24, /*maxtags*/32 214195534Sscottl }, 215195534Sscottl { 216195534Sscottl /* Broken tagged queuing drive */ 217195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, microp, "4421-07*", "*" }, 218195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 219195534Sscottl }, 220195534Sscottl { 221195534Sscottl /* Broken tagged queuing drive */ 222195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "HP", "C372*", "*" }, 223195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 224195534Sscottl }, 225195534Sscottl { 226195534Sscottl /* Broken tagged queuing drive */ 227195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, microp, "3391*", "x43h" }, 228195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 229195534Sscottl }, 230195534Sscottl { 231195534Sscottl /* 232195534Sscottl * Unfortunately, the Quantum Atlas III has the same 233195534Sscottl * problem as the Atlas II drives above. 234195534Sscottl * Reported by: "Johan Granlund" <johan@granlund.nu> 235195534Sscottl * 236195534Sscottl * For future reference, the drive with the problem was: 237195534Sscottl * QUANTUM QM39100TD-SW N1B0 238195534Sscottl * 239195534Sscottl * It's possible that Quantum will fix the problem in later 240195534Sscottl * firmware revisions. If that happens, the quirk entry 241195534Sscottl * will need to be made specific to the firmware revisions 242195534Sscottl * with the problem. 243195534Sscottl * 244195534Sscottl */ 245195534Sscottl /* Reports QUEUE FULL for temporary resource shortages */ 246195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, quantum, "QM39100*", "*" }, 247195534Sscottl /*quirks*/0, /*mintags*/24, /*maxtags*/32 248195534Sscottl }, 249195534Sscottl { 250195534Sscottl /* 251195534Sscottl * 18 Gig Atlas III, same problem as the 9G version. 252195534Sscottl * Reported by: Andre Albsmeier 253195534Sscottl * <andre.albsmeier@mchp.siemens.de> 254195534Sscottl * 255195534Sscottl * For future reference, the drive with the problem was: 256195534Sscottl * QUANTUM QM318000TD-S N491 257195534Sscottl */ 258195534Sscottl /* Reports QUEUE FULL for temporary resource shortages */ 259195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, quantum, "QM318000*", "*" }, 260195534Sscottl /*quirks*/0, /*mintags*/24, /*maxtags*/32 261195534Sscottl }, 262195534Sscottl { 263195534Sscottl /* 264195534Sscottl * Broken tagged queuing drive 265195534Sscottl * Reported by: Bret Ford <bford@uop.cs.uop.edu> 266195534Sscottl * and: Martin Renters <martin@tdc.on.ca> 267195534Sscottl */ 268195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST410800*", "71*" }, 269195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 270195534Sscottl }, 271195534Sscottl /* 272195534Sscottl * The Seagate Medalist Pro drives have very poor write 273195534Sscottl * performance with anything more than 2 tags. 274195534Sscottl * 275195534Sscottl * Reported by: Paul van der Zwan <paulz@trantor.xs4all.nl> 276195534Sscottl * Drive: <SEAGATE ST36530N 1444> 277195534Sscottl * 278195534Sscottl * Reported by: Jeremy Lea <reg@shale.csir.co.za> 279195534Sscottl * Drive: <SEAGATE ST34520W 1281> 280195534Sscottl * 281195534Sscottl * No one has actually reported that the 9G version 282195534Sscottl * (ST39140*) of the Medalist Pro has the same problem, but 283195534Sscottl * we're assuming that it does because the 4G and 6.5G 284195534Sscottl * versions of the drive are broken. 285195534Sscottl */ 286195534Sscottl { 287195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST34520*", "*"}, 288195534Sscottl /*quirks*/0, /*mintags*/2, /*maxtags*/2 289195534Sscottl }, 290195534Sscottl { 291195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST36530*", "*"}, 292195534Sscottl /*quirks*/0, /*mintags*/2, /*maxtags*/2 293195534Sscottl }, 294195534Sscottl { 295195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST39140*", "*"}, 296195534Sscottl /*quirks*/0, /*mintags*/2, /*maxtags*/2 297195534Sscottl }, 298195534Sscottl { 299195534Sscottl /* 300231745Sgibbs * Experiences command timeouts under load with a 301231745Sgibbs * tag count higher than 55. 302231745Sgibbs */ 303231745Sgibbs { T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST3146855LW", "*"}, 304231745Sgibbs /*quirks*/0, /*mintags*/2, /*maxtags*/55 305231745Sgibbs }, 306231745Sgibbs { 307231745Sgibbs /* 308195534Sscottl * Slow when tagged queueing is enabled. Write performance 309195534Sscottl * steadily drops off with more and more concurrent 310195534Sscottl * transactions. Best sequential write performance with 311195534Sscottl * tagged queueing turned off and write caching turned on. 312195534Sscottl * 313195534Sscottl * PR: kern/10398 314195534Sscottl * Submitted by: Hideaki Okada <hokada@isl.melco.co.jp> 315195534Sscottl * Drive: DCAS-34330 w/ "S65A" firmware. 316195534Sscottl * 317195534Sscottl * The drive with the problem had the "S65A" firmware 318195534Sscottl * revision, and has also been reported (by Stephen J. 319195534Sscottl * Roznowski <sjr@home.net>) for a drive with the "S61A" 320195534Sscottl * firmware revision. 321195534Sscottl * 322195534Sscottl * Although no one has reported problems with the 2 gig 323195534Sscottl * version of the DCAS drive, the assumption is that it 324195534Sscottl * has the same problems as the 4 gig version. Therefore 325195534Sscottl * this quirk entries disables tagged queueing for all 326195534Sscottl * DCAS drives. 327195534Sscottl */ 328195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "IBM", "DCAS*", "*" }, 329195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 330195534Sscottl }, 331195534Sscottl { 332195534Sscottl /* Broken tagged queuing drive */ 333195534Sscottl { T_DIRECT, SIP_MEDIA_REMOVABLE, "iomega", "jaz*", "*" }, 334195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 335195534Sscottl }, 336195534Sscottl { 337195534Sscottl /* Broken tagged queuing drive */ 338195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "CONNER", "CFP2107*", "*" }, 339195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 340195534Sscottl }, 341195534Sscottl { 342195534Sscottl /* This does not support other than LUN 0 */ 343195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "VMware*", "*", "*" }, 344195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/2, /*maxtags*/255 345195534Sscottl }, 346195534Sscottl { 347195534Sscottl /* 348195534Sscottl * Broken tagged queuing drive. 349195534Sscottl * Submitted by: 350195534Sscottl * NAKAJI Hiroyuki <nakaji@zeisei.dpri.kyoto-u.ac.jp> 351195534Sscottl * in PR kern/9535 352195534Sscottl */ 353195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, samsung, "WN34324U*", "*" }, 354195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 355195534Sscottl }, 356195534Sscottl { 357195534Sscottl /* 358195534Sscottl * Slow when tagged queueing is enabled. (1.5MB/sec versus 359195534Sscottl * 8MB/sec.) 360195534Sscottl * Submitted by: Andrew Gallatin <gallatin@cs.duke.edu> 361195534Sscottl * Best performance with these drives is achieved with 362195534Sscottl * tagged queueing turned off, and write caching turned on. 363195534Sscottl */ 364195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, west_digital, "WDE*", "*" }, 365195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 366195534Sscottl }, 367195534Sscottl { 368195534Sscottl /* 369195534Sscottl * Slow when tagged queueing is enabled. (1.5MB/sec versus 370195534Sscottl * 8MB/sec.) 371195534Sscottl * Submitted by: Andrew Gallatin <gallatin@cs.duke.edu> 372195534Sscottl * Best performance with these drives is achieved with 373195534Sscottl * tagged queueing turned off, and write caching turned on. 374195534Sscottl */ 375195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, west_digital, "ENTERPRISE", "*" }, 376195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 377195534Sscottl }, 378195534Sscottl { 379195534Sscottl /* 380195534Sscottl * Doesn't handle queue full condition correctly, 381195534Sscottl * so we need to limit maxtags to what the device 382195534Sscottl * can handle instead of determining this automatically. 383195534Sscottl */ 384195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, samsung, "WN321010S*", "*" }, 385195534Sscottl /*quirks*/0, /*mintags*/2, /*maxtags*/32 386195534Sscottl }, 387195534Sscottl { 388195534Sscottl /* Really only one LUN */ 389195534Sscottl { T_ENCLOSURE, SIP_MEDIA_FIXED, "SUN", "SENA", "*" }, 390195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 391195534Sscottl }, 392195534Sscottl { 393195534Sscottl /* I can't believe we need a quirk for DPT volumes. */ 394195534Sscottl { T_ANY, SIP_MEDIA_FIXED|SIP_MEDIA_REMOVABLE, "DPT", "*", "*" }, 395195534Sscottl CAM_QUIRK_NOLUNS, 396195534Sscottl /*mintags*/0, /*maxtags*/255 397195534Sscottl }, 398195534Sscottl { 399195534Sscottl /* 400195534Sscottl * Many Sony CDROM drives don't like multi-LUN probing. 401195534Sscottl */ 402195534Sscottl { T_CDROM, SIP_MEDIA_REMOVABLE, sony, "CD-ROM CDU*", "*" }, 403195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 404195534Sscottl }, 405195534Sscottl { 406195534Sscottl /* 407195534Sscottl * This drive doesn't like multiple LUN probing. 408195534Sscottl * Submitted by: Parag Patel <parag@cgt.com> 409195534Sscottl */ 410195534Sscottl { T_WORM, SIP_MEDIA_REMOVABLE, sony, "CD-R CDU9*", "*" }, 411195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 412195534Sscottl }, 413195534Sscottl { 414195534Sscottl { T_WORM, SIP_MEDIA_REMOVABLE, "YAMAHA", "CDR100*", "*" }, 415195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 416195534Sscottl }, 417195534Sscottl { 418195534Sscottl /* 419195534Sscottl * The 8200 doesn't like multi-lun probing, and probably 420195534Sscottl * don't like serial number requests either. 421195534Sscottl */ 422195534Sscottl { 423195534Sscottl T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "EXABYTE", 424195534Sscottl "EXB-8200*", "*" 425195534Sscottl }, 426195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 427195534Sscottl }, 428195534Sscottl { 429195534Sscottl /* 430195534Sscottl * Let's try the same as above, but for a drive that says 431195534Sscottl * it's an IPL-6860 but is actually an EXB 8200. 432195534Sscottl */ 433195534Sscottl { 434195534Sscottl T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "EXABYTE", 435195534Sscottl "IPL-6860*", "*" 436195534Sscottl }, 437195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 438195534Sscottl }, 439195534Sscottl { 440195534Sscottl /* 441195534Sscottl * These Hitachi drives don't like multi-lun probing. 442195534Sscottl * The PR submitter has a DK319H, but says that the Linux 443195534Sscottl * kernel has a similar work-around for the DK312 and DK314, 444195534Sscottl * so all DK31* drives are quirked here. 445195534Sscottl * PR: misc/18793 446195534Sscottl * Submitted by: Paul Haddad <paul@pth.com> 447195534Sscottl */ 448195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "HITACHI", "DK31*", "*" }, 449195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/2, /*maxtags*/255 450195534Sscottl }, 451195534Sscottl { 452195534Sscottl /* 453195534Sscottl * The Hitachi CJ series with J8A8 firmware apparantly has 454195534Sscottl * problems with tagged commands. 455195534Sscottl * PR: 23536 456195534Sscottl * Reported by: amagai@nue.org 457195534Sscottl */ 458195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "HITACHI", "DK32CJ*", "J8A8" }, 459195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 460195534Sscottl }, 461195534Sscottl { 462195534Sscottl /* 463195534Sscottl * These are the large storage arrays. 464195534Sscottl * Submitted by: William Carrel <william.carrel@infospace.com> 465195534Sscottl */ 466195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "HITACHI", "OPEN*", "*" }, 467195534Sscottl CAM_QUIRK_HILUNS, 2, 1024 468195534Sscottl }, 469195534Sscottl { 470195534Sscottl /* 471195534Sscottl * This old revision of the TDC3600 is also SCSI-1, and 472195534Sscottl * hangs upon serial number probing. 473195534Sscottl */ 474195534Sscottl { 475195534Sscottl T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG", 476195534Sscottl " TDC 3600", "U07:" 477195534Sscottl }, 478216088Sken CAM_QUIRK_NOVPDS, /*mintags*/0, /*maxtags*/0 479195534Sscottl }, 480195534Sscottl { 481195534Sscottl /* 482195534Sscottl * Would repond to all LUNs if asked for. 483195534Sscottl */ 484195534Sscottl { 485195534Sscottl T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "CALIPER", 486195534Sscottl "CP150", "*" 487195534Sscottl }, 488195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 489195534Sscottl }, 490195534Sscottl { 491195534Sscottl /* 492195534Sscottl * Would repond to all LUNs if asked for. 493195534Sscottl */ 494195534Sscottl { 495195534Sscottl T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "KENNEDY", 496195534Sscottl "96X2*", "*" 497195534Sscottl }, 498195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 499195534Sscottl }, 500195534Sscottl { 501195534Sscottl /* Submitted by: Matthew Dodd <winter@jurai.net> */ 502195534Sscottl { T_PROCESSOR, SIP_MEDIA_FIXED, "Cabletrn", "EA41*", "*" }, 503195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 504195534Sscottl }, 505195534Sscottl { 506195534Sscottl /* Submitted by: Matthew Dodd <winter@jurai.net> */ 507195534Sscottl { T_PROCESSOR, SIP_MEDIA_FIXED, "CABLETRN", "EA41*", "*" }, 508195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 509195534Sscottl }, 510195534Sscottl { 511195534Sscottl /* TeraSolutions special settings for TRC-22 RAID */ 512195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "TERASOLU", "TRC-22", "*" }, 513195534Sscottl /*quirks*/0, /*mintags*/55, /*maxtags*/255 514195534Sscottl }, 515195534Sscottl { 516195534Sscottl /* Veritas Storage Appliance */ 517195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "VERITAS", "*", "*" }, 518195534Sscottl CAM_QUIRK_HILUNS, /*mintags*/2, /*maxtags*/1024 519195534Sscottl }, 520195534Sscottl { 521195534Sscottl /* 522195534Sscottl * Would respond to all LUNs. Device type and removable 523195534Sscottl * flag are jumper-selectable. 524195534Sscottl */ 525195534Sscottl { T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED, "MaxOptix", 526195534Sscottl "Tahiti 1", "*" 527195534Sscottl }, 528195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 529195534Sscottl }, 530195534Sscottl { 531195534Sscottl /* EasyRAID E5A aka. areca ARC-6010 */ 532195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "easyRAID", "*", "*" }, 533195534Sscottl CAM_QUIRK_NOHILUNS, /*mintags*/2, /*maxtags*/255 534195534Sscottl }, 535195534Sscottl { 536195534Sscottl { T_ENCLOSURE, SIP_MEDIA_FIXED, "DP", "BACKPLANE", "*" }, 537195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 538195534Sscottl }, 539195534Sscottl { 540236283Seadler { T_DIRECT, SIP_MEDIA_REMOVABLE, "Garmin", "*", "*" }, 541236283Seadler CAM_QUIRK_NORPTLUNS, /*mintags*/2, /*maxtags*/255 542236283Seadler }, 543236283Seadler { 544195534Sscottl /* Default tagged queuing parameters for all devices */ 545195534Sscottl { 546195534Sscottl T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED, 547195534Sscottl /*vendor*/"*", /*product*/"*", /*revision*/"*" 548195534Sscottl }, 549195534Sscottl /*quirks*/0, /*mintags*/2, /*maxtags*/255 550195534Sscottl }, 551195534Sscottl}; 552195534Sscottl 553195534Sscottlstatic const int scsi_quirk_table_size = 554195534Sscottl sizeof(scsi_quirk_table) / sizeof(*scsi_quirk_table); 555195534Sscottl 556195534Sscottlstatic cam_status proberegister(struct cam_periph *periph, 557195534Sscottl void *arg); 558195534Sscottlstatic void probeschedule(struct cam_periph *probe_periph); 559195534Sscottlstatic void probestart(struct cam_periph *periph, union ccb *start_ccb); 560195534Sscottlstatic void proberequestdefaultnegotiation(struct cam_periph *periph); 561195534Sscottlstatic int proberequestbackoff(struct cam_periph *periph, 562195534Sscottl struct cam_ed *device); 563195534Sscottlstatic void probedone(struct cam_periph *periph, union ccb *done_ccb); 564208911Smjacobstatic int probe_strange_rpl_data(struct scsi_report_luns_data *rp, 565208911Smjacob uint32_t maxlun); 566208911Smjacobstatic void probe_purge_old(struct cam_path *path, 567208911Smjacob struct scsi_report_luns_data *new); 568195534Sscottlstatic void probecleanup(struct cam_periph *periph); 569195534Sscottlstatic void scsi_find_quirk(struct cam_ed *device); 570195534Sscottlstatic void scsi_scan_bus(struct cam_periph *periph, union ccb *ccb); 571195534Sscottlstatic void scsi_scan_lun(struct cam_periph *periph, 572195534Sscottl struct cam_path *path, cam_flags flags, 573195534Sscottl union ccb *ccb); 574195534Sscottlstatic void xptscandone(struct cam_periph *periph, union ccb *done_ccb); 575195534Sscottlstatic struct cam_ed * 576195534Sscottl scsi_alloc_device(struct cam_eb *bus, struct cam_et *target, 577195534Sscottl lun_id_t lun_id); 578195534Sscottlstatic void scsi_devise_transport(struct cam_path *path); 579195534Sscottlstatic void scsi_set_transfer_settings(struct ccb_trans_settings *cts, 580195534Sscottl struct cam_ed *device, 581195534Sscottl int async_update); 582195534Sscottlstatic void scsi_toggle_tags(struct cam_path *path); 583195534Sscottlstatic void scsi_dev_async(u_int32_t async_code, 584195534Sscottl struct cam_eb *bus, 585195534Sscottl struct cam_et *target, 586195534Sscottl struct cam_ed *device, 587195534Sscottl void *async_arg); 588195534Sscottlstatic void scsi_action(union ccb *start_ccb); 589204220Smavstatic void scsi_announce_periph(struct cam_periph *periph); 590195534Sscottl 591195534Sscottlstatic struct xpt_xport scsi_xport = { 592195534Sscottl .alloc_device = scsi_alloc_device, 593195534Sscottl .action = scsi_action, 594195534Sscottl .async = scsi_dev_async, 595204220Smav .announce = scsi_announce_periph, 596195534Sscottl}; 597195534Sscottl 598195534Sscottlstruct xpt_xport * 599195534Sscottlscsi_get_xport(void) 600195534Sscottl{ 601195534Sscottl return (&scsi_xport); 602195534Sscottl} 603195534Sscottl 604195534Sscottlstatic void 605195534Sscottlprobe_periph_init() 606195534Sscottl{ 607195534Sscottl} 608195534Sscottl 609195534Sscottlstatic cam_status 610195534Sscottlproberegister(struct cam_periph *periph, void *arg) 611195534Sscottl{ 612195534Sscottl union ccb *request_ccb; /* CCB representing the probe request */ 613195534Sscottl cam_status status; 614195534Sscottl probe_softc *softc; 615195534Sscottl 616195534Sscottl request_ccb = (union ccb *)arg; 617195534Sscottl if (request_ccb == NULL) { 618195534Sscottl printf("proberegister: no probe CCB, " 619195534Sscottl "can't register device\n"); 620195534Sscottl return(CAM_REQ_CMP_ERR); 621195534Sscottl } 622195534Sscottl 623195534Sscottl softc = (probe_softc *)malloc(sizeof(*softc), M_CAMXPT, M_NOWAIT); 624195534Sscottl 625195534Sscottl if (softc == NULL) { 626195534Sscottl printf("proberegister: Unable to probe new device. " 627195534Sscottl "Unable to allocate softc\n"); 628195534Sscottl return(CAM_REQ_CMP_ERR); 629195534Sscottl } 630195534Sscottl TAILQ_INIT(&softc->request_ccbs); 631195534Sscottl TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h, 632195534Sscottl periph_links.tqe); 633195534Sscottl softc->flags = 0; 634195534Sscottl periph->softc = softc; 635195534Sscottl softc->periph = periph; 636195534Sscottl softc->action = PROBE_INVALID; 637195534Sscottl status = cam_periph_acquire(periph); 638195534Sscottl if (status != CAM_REQ_CMP) { 639195534Sscottl return (status); 640195534Sscottl } 641236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe started\n")); 642195534Sscottl 643195534Sscottl /* 644195534Sscottl * Ensure we've waited at least a bus settle 645195534Sscottl * delay before attempting to probe the device. 646195534Sscottl * For HBAs that don't do bus resets, this won't make a difference. 647195534Sscottl */ 648195534Sscottl cam_periph_freeze_after_event(periph, &periph->path->bus->last_reset, 649195534Sscottl scsi_delay); 650195534Sscottl probeschedule(periph); 651195534Sscottl return(CAM_REQ_CMP); 652195534Sscottl} 653195534Sscottl 654195534Sscottlstatic void 655195534Sscottlprobeschedule(struct cam_periph *periph) 656195534Sscottl{ 657195534Sscottl struct ccb_pathinq cpi; 658195534Sscottl union ccb *ccb; 659195534Sscottl probe_softc *softc; 660195534Sscottl 661195534Sscottl softc = (probe_softc *)periph->softc; 662195534Sscottl ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs); 663195534Sscottl 664203108Smav xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NONE); 665195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 666195534Sscottl xpt_action((union ccb *)&cpi); 667195534Sscottl 668195534Sscottl /* 669195534Sscottl * If a device has gone away and another device, or the same one, 670195534Sscottl * is back in the same place, it should have a unit attention 671195534Sscottl * condition pending. It will not report the unit attention in 672195534Sscottl * response to an inquiry, which may leave invalid transfer 673195534Sscottl * negotiations in effect. The TUR will reveal the unit attention 674195534Sscottl * condition. Only send the TUR for lun 0, since some devices 675195534Sscottl * will get confused by commands other than inquiry to non-existent 676195534Sscottl * luns. If you think a device has gone away start your scan from 677195534Sscottl * lun 0. This will insure that any bogus transfer settings are 678195534Sscottl * invalidated. 679195534Sscottl * 680195534Sscottl * If we haven't seen the device before and the controller supports 681195534Sscottl * some kind of transfer negotiation, negotiate with the first 682195534Sscottl * sent command if no bus reset was performed at startup. This 683195534Sscottl * ensures that the device is not confused by transfer negotiation 684195534Sscottl * settings left over by loader or BIOS action. 685195534Sscottl */ 686195534Sscottl if (((ccb->ccb_h.path->device->flags & CAM_DEV_UNCONFIGURED) == 0) 687195534Sscottl && (ccb->ccb_h.target_lun == 0)) { 688195534Sscottl PROBE_SET_ACTION(softc, PROBE_TUR); 689195534Sscottl } else if ((cpi.hba_inquiry & (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE)) != 0 690195534Sscottl && (cpi.hba_misc & PIM_NOBUSRESET) != 0) { 691195534Sscottl proberequestdefaultnegotiation(periph); 692195534Sscottl PROBE_SET_ACTION(softc, PROBE_INQUIRY); 693195534Sscottl } else { 694195534Sscottl PROBE_SET_ACTION(softc, PROBE_INQUIRY); 695195534Sscottl } 696195534Sscottl 697195534Sscottl if (ccb->crcn.flags & CAM_EXPECT_INQ_CHANGE) 698195534Sscottl softc->flags |= PROBE_NO_ANNOUNCE; 699195534Sscottl else 700195534Sscottl softc->flags &= ~PROBE_NO_ANNOUNCE; 701195534Sscottl 702203108Smav xpt_schedule(periph, CAM_PRIORITY_XPT); 703195534Sscottl} 704195534Sscottl 705195534Sscottlstatic void 706195534Sscottlprobestart(struct cam_periph *periph, union ccb *start_ccb) 707195534Sscottl{ 708195534Sscottl /* Probe the device that our peripheral driver points to */ 709195534Sscottl struct ccb_scsiio *csio; 710195534Sscottl probe_softc *softc; 711195534Sscottl 712195534Sscottl CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probestart\n")); 713195534Sscottl 714195534Sscottl softc = (probe_softc *)periph->softc; 715195534Sscottl csio = &start_ccb->csio; 716208911Smjacobagain: 717195534Sscottl 718195534Sscottl switch (softc->action) { 719195534Sscottl case PROBE_TUR: 720195534Sscottl case PROBE_TUR_FOR_NEGOTIATION: 721195534Sscottl case PROBE_DV_EXIT: 722195534Sscottl { 723195534Sscottl scsi_test_unit_ready(csio, 724236814Smav /*retries*/4, 725195534Sscottl probedone, 726195534Sscottl MSG_SIMPLE_Q_TAG, 727195534Sscottl SSD_FULL_SIZE, 728195534Sscottl /*timeout*/60000); 729195534Sscottl break; 730195534Sscottl } 731195534Sscottl case PROBE_INQUIRY: 732195534Sscottl case PROBE_FULL_INQUIRY: 733195534Sscottl case PROBE_INQUIRY_BASIC_DV1: 734195534Sscottl case PROBE_INQUIRY_BASIC_DV2: 735195534Sscottl { 736195534Sscottl u_int inquiry_len; 737195534Sscottl struct scsi_inquiry_data *inq_buf; 738195534Sscottl 739195534Sscottl inq_buf = &periph->path->device->inq_data; 740195534Sscottl 741195534Sscottl /* 742195534Sscottl * If the device is currently configured, we calculate an 743195534Sscottl * MD5 checksum of the inquiry data, and if the serial number 744195534Sscottl * length is greater than 0, add the serial number data 745195534Sscottl * into the checksum as well. Once the inquiry and the 746195534Sscottl * serial number check finish, we attempt to figure out 747195534Sscottl * whether we still have the same device. 748195534Sscottl */ 749195534Sscottl if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) { 750195534Sscottl 751195534Sscottl MD5Init(&softc->context); 752195534Sscottl MD5Update(&softc->context, (unsigned char *)inq_buf, 753195534Sscottl sizeof(struct scsi_inquiry_data)); 754195534Sscottl softc->flags |= PROBE_INQUIRY_CKSUM; 755195534Sscottl if (periph->path->device->serial_num_len > 0) { 756195534Sscottl MD5Update(&softc->context, 757195534Sscottl periph->path->device->serial_num, 758195534Sscottl periph->path->device->serial_num_len); 759195534Sscottl softc->flags |= PROBE_SERIAL_CKSUM; 760195534Sscottl } 761195534Sscottl MD5Final(softc->digest, &softc->context); 762195534Sscottl } 763195534Sscottl 764195534Sscottl if (softc->action == PROBE_INQUIRY) 765195534Sscottl inquiry_len = SHORT_INQUIRY_LENGTH; 766195534Sscottl else 767195534Sscottl inquiry_len = SID_ADDITIONAL_LENGTH(inq_buf); 768195534Sscottl 769195534Sscottl /* 770195534Sscottl * Some parallel SCSI devices fail to send an 771195534Sscottl * ignore wide residue message when dealing with 772195534Sscottl * odd length inquiry requests. Round up to be 773195534Sscottl * safe. 774195534Sscottl */ 775195534Sscottl inquiry_len = roundup2(inquiry_len, 2); 776195534Sscottl 777195534Sscottl if (softc->action == PROBE_INQUIRY_BASIC_DV1 778195534Sscottl || softc->action == PROBE_INQUIRY_BASIC_DV2) { 779195534Sscottl inq_buf = malloc(inquiry_len, M_CAMXPT, M_NOWAIT); 780195534Sscottl } 781195534Sscottl if (inq_buf == NULL) { 782195534Sscottl xpt_print(periph->path, "malloc failure- skipping Basic" 783195534Sscottl "Domain Validation\n"); 784195534Sscottl PROBE_SET_ACTION(softc, PROBE_DV_EXIT); 785195534Sscottl scsi_test_unit_ready(csio, 786195534Sscottl /*retries*/4, 787195534Sscottl probedone, 788195534Sscottl MSG_SIMPLE_Q_TAG, 789195534Sscottl SSD_FULL_SIZE, 790195534Sscottl /*timeout*/60000); 791195534Sscottl break; 792195534Sscottl } 793195534Sscottl scsi_inquiry(csio, 794195534Sscottl /*retries*/4, 795195534Sscottl probedone, 796195534Sscottl MSG_SIMPLE_Q_TAG, 797195534Sscottl (u_int8_t *)inq_buf, 798195534Sscottl inquiry_len, 799195534Sscottl /*evpd*/FALSE, 800195534Sscottl /*page_code*/0, 801195534Sscottl SSD_MIN_SIZE, 802195534Sscottl /*timeout*/60 * 1000); 803195534Sscottl break; 804195534Sscottl } 805208911Smjacob case PROBE_REPORT_LUNS: 806208911Smjacob { 807208911Smjacob void *rp; 808208911Smjacob 809208911Smjacob rp = malloc(periph->path->target->rpl_size, 810208911Smjacob M_CAMXPT, M_NOWAIT | M_ZERO); 811208911Smjacob if (rp == NULL) { 812208911Smjacob struct scsi_inquiry_data *inq_buf; 813208911Smjacob inq_buf = &periph->path->device->inq_data; 814208911Smjacob xpt_print(periph->path, 815208911Smjacob "Unable to alloc report luns storage\n"); 816208911Smjacob if (INQ_DATA_TQ_ENABLED(inq_buf)) 817208911Smjacob PROBE_SET_ACTION(softc, PROBE_MODE_SENSE); 818208911Smjacob else 819216088Sken PROBE_SET_ACTION(softc, 820216088Sken PROBE_SUPPORTED_VPD_LIST); 821208911Smjacob goto again; 822208911Smjacob } 823208911Smjacob scsi_report_luns(csio, 5, probedone, MSG_SIMPLE_Q_TAG, 824208911Smjacob RPL_REPORT_DEFAULT, rp, periph->path->target->rpl_size, 825208911Smjacob SSD_FULL_SIZE, 60000); break; 826208911Smjacob break; 827208911Smjacob } 828195534Sscottl case PROBE_MODE_SENSE: 829195534Sscottl { 830195534Sscottl void *mode_buf; 831195534Sscottl int mode_buf_len; 832195534Sscottl 833195534Sscottl mode_buf_len = sizeof(struct scsi_mode_header_6) 834195534Sscottl + sizeof(struct scsi_mode_blk_desc) 835195534Sscottl + sizeof(struct scsi_control_page); 836195534Sscottl mode_buf = malloc(mode_buf_len, M_CAMXPT, M_NOWAIT); 837195534Sscottl if (mode_buf != NULL) { 838195534Sscottl scsi_mode_sense(csio, 839195534Sscottl /*retries*/4, 840195534Sscottl probedone, 841195534Sscottl MSG_SIMPLE_Q_TAG, 842195534Sscottl /*dbd*/FALSE, 843195534Sscottl SMS_PAGE_CTRL_CURRENT, 844195534Sscottl SMS_CONTROL_MODE_PAGE, 845195534Sscottl mode_buf, 846195534Sscottl mode_buf_len, 847195534Sscottl SSD_FULL_SIZE, 848195534Sscottl /*timeout*/60000); 849195534Sscottl break; 850195534Sscottl } 851195534Sscottl xpt_print(periph->path, "Unable to mode sense control page - " 852195534Sscottl "malloc failure\n"); 853216088Sken PROBE_SET_ACTION(softc, PROBE_SUPPORTED_VPD_LIST); 854195534Sscottl } 855195534Sscottl /* FALLTHROUGH */ 856216088Sken case PROBE_SUPPORTED_VPD_LIST: 857195534Sscottl { 858216088Sken struct scsi_vpd_supported_page_list *vpd_list; 859195534Sscottl struct cam_ed *device; 860195534Sscottl 861216088Sken vpd_list = NULL; 862195534Sscottl device = periph->path->device; 863216088Sken 864216088Sken if ((SCSI_QUIRK(device)->quirks & CAM_QUIRK_NOVPDS) == 0) 865195534Sscottl vpd_list = malloc(sizeof(*vpd_list), M_CAMXPT, 866195534Sscottl M_NOWAIT | M_ZERO); 867195534Sscottl 868195534Sscottl if (vpd_list != NULL) { 869195534Sscottl scsi_inquiry(csio, 870195534Sscottl /*retries*/4, 871195534Sscottl probedone, 872195534Sscottl MSG_SIMPLE_Q_TAG, 873195534Sscottl (u_int8_t *)vpd_list, 874195534Sscottl sizeof(*vpd_list), 875195534Sscottl /*evpd*/TRUE, 876195534Sscottl SVPD_SUPPORTED_PAGE_LIST, 877195534Sscottl SSD_MIN_SIZE, 878195534Sscottl /*timeout*/60 * 1000); 879195534Sscottl break; 880195534Sscottl } 881195534Sscottl /* 882195534Sscottl * We'll have to do without, let our probedone 883195534Sscottl * routine finish up for us. 884195534Sscottl */ 885195534Sscottl start_ccb->csio.data_ptr = NULL; 886250025Smav cam_freeze_devq(periph->path); 887195534Sscottl probedone(periph, start_ccb); 888195534Sscottl return; 889195534Sscottl } 890216088Sken case PROBE_DEVICE_ID: 891195534Sscottl { 892216088Sken struct scsi_vpd_device_id *devid; 893216088Sken 894216088Sken devid = NULL; 895249937Ssmh if (scsi_vpd_supported_page(periph, SVPD_DEVICE_ID)) 896216088Sken devid = malloc(SVPD_DEVICE_ID_MAX_SIZE, M_CAMXPT, 897216088Sken M_NOWAIT | M_ZERO); 898216088Sken 899216088Sken if (devid != NULL) { 900216088Sken scsi_inquiry(csio, 901216088Sken /*retries*/4, 902216088Sken probedone, 903216088Sken MSG_SIMPLE_Q_TAG, 904216088Sken (uint8_t *)devid, 905216088Sken SVPD_DEVICE_ID_MAX_SIZE, 906216088Sken /*evpd*/TRUE, 907216088Sken SVPD_DEVICE_ID, 908216088Sken SSD_MIN_SIZE, 909216088Sken /*timeout*/60 * 1000); 910216088Sken break; 911216088Sken } 912216088Sken /* 913216088Sken * We'll have to do without, let our probedone 914216088Sken * routine finish up for us. 915216088Sken */ 916216088Sken start_ccb->csio.data_ptr = NULL; 917250025Smav cam_freeze_devq(periph->path); 918216088Sken probedone(periph, start_ccb); 919216088Sken return; 920216088Sken } 921216088Sken case PROBE_SERIAL_NUM: 922216088Sken { 923195534Sscottl struct scsi_vpd_unit_serial_number *serial_buf; 924195534Sscottl struct cam_ed* device; 925195534Sscottl 926195534Sscottl serial_buf = NULL; 927195534Sscottl device = periph->path->device; 928195685Semaste if (device->serial_num != NULL) { 929195685Semaste free(device->serial_num, M_CAMXPT); 930195685Semaste device->serial_num = NULL; 931195685Semaste device->serial_num_len = 0; 932195685Semaste } 933195534Sscottl 934249937Ssmh if (scsi_vpd_supported_page(periph, SVPD_UNIT_SERIAL_NUMBER)) 935216088Sken serial_buf = (struct scsi_vpd_unit_serial_number *) 936216088Sken malloc(sizeof(*serial_buf), M_CAMXPT, 937216088Sken M_NOWAIT|M_ZERO); 938195534Sscottl 939195534Sscottl if (serial_buf != NULL) { 940195534Sscottl scsi_inquiry(csio, 941195534Sscottl /*retries*/4, 942195534Sscottl probedone, 943195534Sscottl MSG_SIMPLE_Q_TAG, 944195534Sscottl (u_int8_t *)serial_buf, 945195534Sscottl sizeof(*serial_buf), 946195534Sscottl /*evpd*/TRUE, 947195534Sscottl SVPD_UNIT_SERIAL_NUMBER, 948195534Sscottl SSD_MIN_SIZE, 949195534Sscottl /*timeout*/60 * 1000); 950195534Sscottl break; 951195534Sscottl } 952195534Sscottl /* 953195534Sscottl * We'll have to do without, let our probedone 954195534Sscottl * routine finish up for us. 955195534Sscottl */ 956195534Sscottl start_ccb->csio.data_ptr = NULL; 957250025Smav cam_freeze_devq(periph->path); 958195534Sscottl probedone(periph, start_ccb); 959195534Sscottl return; 960195534Sscottl } 961195534Sscottl default: 962236613Smav panic("probestart: invalid action state 0x%x\n", softc->action); 963195534Sscottl } 964249466Smav start_ccb->ccb_h.flags |= CAM_DEV_QFREEZE; 965195534Sscottl xpt_action(start_ccb); 966195534Sscottl} 967195534Sscottl 968195534Sscottlstatic void 969195534Sscottlproberequestdefaultnegotiation(struct cam_periph *periph) 970195534Sscottl{ 971195534Sscottl struct ccb_trans_settings cts; 972195534Sscottl 973203108Smav xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE); 974195534Sscottl cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 975195534Sscottl cts.type = CTS_TYPE_USER_SETTINGS; 976195534Sscottl xpt_action((union ccb *)&cts); 977252382Sscottl if (cam_ccb_status((union ccb *)&cts) != CAM_REQ_CMP) { 978195534Sscottl return; 979195534Sscottl } 980195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 981195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 982195534Sscottl xpt_action((union ccb *)&cts); 983195534Sscottl} 984195534Sscottl 985195534Sscottl/* 986195534Sscottl * Backoff Negotiation Code- only pertinent for SPI devices. 987195534Sscottl */ 988195534Sscottlstatic int 989195534Sscottlproberequestbackoff(struct cam_periph *periph, struct cam_ed *device) 990195534Sscottl{ 991195534Sscottl struct ccb_trans_settings cts; 992195534Sscottl struct ccb_trans_settings_spi *spi; 993195534Sscottl 994195534Sscottl memset(&cts, 0, sizeof (cts)); 995203108Smav xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE); 996195534Sscottl cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 997195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 998195534Sscottl xpt_action((union ccb *)&cts); 999252382Sscottl if (cam_ccb_status((union ccb *)&cts) != CAM_REQ_CMP) { 1000195534Sscottl if (bootverbose) { 1001195534Sscottl xpt_print(periph->path, 1002195534Sscottl "failed to get current device settings\n"); 1003195534Sscottl } 1004195534Sscottl return (0); 1005195534Sscottl } 1006195534Sscottl if (cts.transport != XPORT_SPI) { 1007195534Sscottl if (bootverbose) { 1008195534Sscottl xpt_print(periph->path, "not SPI transport\n"); 1009195534Sscottl } 1010195534Sscottl return (0); 1011195534Sscottl } 1012195534Sscottl spi = &cts.xport_specific.spi; 1013195534Sscottl 1014195534Sscottl /* 1015195534Sscottl * We cannot renegotiate sync rate if we don't have one. 1016195534Sscottl */ 1017195534Sscottl if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) { 1018195534Sscottl if (bootverbose) { 1019195534Sscottl xpt_print(periph->path, "no sync rate known\n"); 1020195534Sscottl } 1021195534Sscottl return (0); 1022195534Sscottl } 1023195534Sscottl 1024195534Sscottl /* 1025195534Sscottl * We'll assert that we don't have to touch PPR options- the 1026195534Sscottl * SIM will see what we do with period and offset and adjust 1027195534Sscottl * the PPR options as appropriate. 1028195534Sscottl */ 1029195534Sscottl 1030195534Sscottl /* 1031195534Sscottl * A sync rate with unknown or zero offset is nonsensical. 1032195534Sscottl * A sync period of zero means Async. 1033195534Sscottl */ 1034195534Sscottl if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0 1035195534Sscottl || spi->sync_offset == 0 || spi->sync_period == 0) { 1036195534Sscottl if (bootverbose) { 1037195534Sscottl xpt_print(periph->path, "no sync rate available\n"); 1038195534Sscottl } 1039195534Sscottl return (0); 1040195534Sscottl } 1041195534Sscottl 1042195534Sscottl if (device->flags & CAM_DEV_DV_HIT_BOTTOM) { 1043236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, 1044195534Sscottl ("hit async: giving up on DV\n")); 1045195534Sscottl return (0); 1046195534Sscottl } 1047195534Sscottl 1048195534Sscottl 1049195534Sscottl /* 1050195534Sscottl * Jump sync_period up by one, but stop at 5MHz and fall back to Async. 1051195534Sscottl * We don't try to remember 'last' settings to see if the SIM actually 1052195534Sscottl * gets into the speed we want to set. We check on the SIM telling 1053195534Sscottl * us that a requested speed is bad, but otherwise don't try and 1054195534Sscottl * check the speed due to the asynchronous and handshake nature 1055195534Sscottl * of speed setting. 1056195534Sscottl */ 1057195534Sscottl spi->valid = CTS_SPI_VALID_SYNC_RATE | CTS_SPI_VALID_SYNC_OFFSET; 1058195534Sscottl for (;;) { 1059195534Sscottl spi->sync_period++; 1060195534Sscottl if (spi->sync_period >= 0xf) { 1061195534Sscottl spi->sync_period = 0; 1062195534Sscottl spi->sync_offset = 0; 1063236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, 1064195534Sscottl ("setting to async for DV\n")); 1065195534Sscottl /* 1066195534Sscottl * Once we hit async, we don't want to try 1067195534Sscottl * any more settings. 1068195534Sscottl */ 1069195534Sscottl device->flags |= CAM_DEV_DV_HIT_BOTTOM; 1070195534Sscottl } else if (bootverbose) { 1071236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, 1072195534Sscottl ("DV: period 0x%x\n", spi->sync_period)); 1073195534Sscottl printf("setting period to 0x%x\n", spi->sync_period); 1074195534Sscottl } 1075195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1076195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 1077195534Sscottl xpt_action((union ccb *)&cts); 1078252382Sscottl if (cam_ccb_status((union ccb *)&cts) != CAM_REQ_CMP) { 1079195534Sscottl break; 1080195534Sscottl } 1081236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, 1082195534Sscottl ("DV: failed to set period 0x%x\n", spi->sync_period)); 1083195534Sscottl if (spi->sync_period == 0) { 1084195534Sscottl return (0); 1085195534Sscottl } 1086195534Sscottl } 1087195534Sscottl return (1); 1088195534Sscottl} 1089195534Sscottl 1090216088Sken#define CCB_COMPLETED_OK(ccb) (((ccb).status & CAM_STATUS_MASK) == CAM_REQ_CMP) 1091216088Sken 1092195534Sscottlstatic void 1093195534Sscottlprobedone(struct cam_periph *periph, union ccb *done_ccb) 1094195534Sscottl{ 1095195534Sscottl probe_softc *softc; 1096195534Sscottl struct cam_path *path; 1097195534Sscottl u_int32_t priority; 1098195534Sscottl 1099195534Sscottl CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probedone\n")); 1100195534Sscottl 1101195534Sscottl softc = (probe_softc *)periph->softc; 1102195534Sscottl path = done_ccb->ccb_h.path; 1103195534Sscottl priority = done_ccb->ccb_h.pinfo.priority; 1104195534Sscottl 1105195534Sscottl switch (softc->action) { 1106195534Sscottl case PROBE_TUR: 1107195534Sscottl { 1108252382Sscottl if (cam_ccb_status(done_ccb) != CAM_REQ_CMP) { 1109195534Sscottl 1110195534Sscottl if (cam_periph_error(done_ccb, 0, 1111249466Smav SF_NO_PRINT, NULL) == ERESTART) { 1112249466Smavout: 1113249466Smav /* Drop freeze taken due to CAM_DEV_QFREEZE */ 1114249466Smav cam_release_devq(path, 0, 0, 0, FALSE); 1115195534Sscottl return; 1116249466Smav } 1117195534Sscottl else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 1118195534Sscottl /* Don't wedge the queue */ 1119195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, 1120195534Sscottl /*count*/1, 1121195534Sscottl /*run_queue*/TRUE); 1122195534Sscottl } 1123195534Sscottl PROBE_SET_ACTION(softc, PROBE_INQUIRY); 1124195534Sscottl xpt_release_ccb(done_ccb); 1125195534Sscottl xpt_schedule(periph, priority); 1126249466Smav goto out; 1127195534Sscottl } 1128195534Sscottl case PROBE_INQUIRY: 1129195534Sscottl case PROBE_FULL_INQUIRY: 1130195534Sscottl { 1131252382Sscottl if (cam_ccb_status(done_ccb) == CAM_REQ_CMP) { 1132195534Sscottl struct scsi_inquiry_data *inq_buf; 1133195534Sscottl u_int8_t periph_qual; 1134195534Sscottl 1135195534Sscottl path->device->flags |= CAM_DEV_INQUIRY_DATA_VALID; 1136195534Sscottl inq_buf = &path->device->inq_data; 1137195534Sscottl 1138195534Sscottl periph_qual = SID_QUAL(inq_buf); 1139195534Sscottl 1140208911Smjacob if (periph_qual == SID_QUAL_LU_CONNECTED) { 1141195534Sscottl u_int8_t len; 1142195534Sscottl 1143195534Sscottl /* 1144195534Sscottl * We conservatively request only 1145195534Sscottl * SHORT_INQUIRY_LEN bytes of inquiry 1146195534Sscottl * information during our first try 1147195534Sscottl * at sending an INQUIRY. If the device 1148195534Sscottl * has more information to give, 1149195534Sscottl * perform a second request specifying 1150195534Sscottl * the amount of information the device 1151195534Sscottl * is willing to give. 1152195534Sscottl */ 1153195534Sscottl len = inq_buf->additional_length 1154195534Sscottl + offsetof(struct scsi_inquiry_data, 1155195534Sscottl additional_length) + 1; 1156195534Sscottl if (softc->action == PROBE_INQUIRY 1157195534Sscottl && len > SHORT_INQUIRY_LENGTH) { 1158195534Sscottl PROBE_SET_ACTION(softc, PROBE_FULL_INQUIRY); 1159195534Sscottl xpt_release_ccb(done_ccb); 1160195534Sscottl xpt_schedule(periph, priority); 1161249466Smav goto out; 1162195534Sscottl } 1163195534Sscottl 1164195534Sscottl scsi_find_quirk(path->device); 1165195534Sscottl 1166195534Sscottl scsi_devise_transport(path); 1167208911Smjacob 1168208911Smjacob if (path->device->lun_id == 0 && 1169208911Smjacob SID_ANSI_REV(inq_buf) > SCSI_REV_SPC2 && 1170208911Smjacob (SCSI_QUIRK(path->device)->quirks & 1171208911Smjacob CAM_QUIRK_NORPTLUNS) == 0) { 1172208911Smjacob PROBE_SET_ACTION(softc, 1173208911Smjacob PROBE_REPORT_LUNS); 1174208911Smjacob /* 1175208911Smjacob * Start with room for *one* lun. 1176208911Smjacob */ 1177208911Smjacob periph->path->target->rpl_size = 16; 1178208911Smjacob } else if (INQ_DATA_TQ_ENABLED(inq_buf)) 1179208911Smjacob PROBE_SET_ACTION(softc, 1180208911Smjacob PROBE_MODE_SENSE); 1181195534Sscottl else 1182208911Smjacob PROBE_SET_ACTION(softc, 1183216088Sken PROBE_SUPPORTED_VPD_LIST); 1184195534Sscottl 1185198748Smav if (path->device->flags & CAM_DEV_UNCONFIGURED) { 1186198748Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1187198748Smav xpt_acquire_device(path->device); 1188198748Smav } 1189195534Sscottl xpt_release_ccb(done_ccb); 1190195534Sscottl xpt_schedule(periph, priority); 1191249466Smav goto out; 1192208911Smjacob } else if (path->device->lun_id == 0 && 1193208911Smjacob SID_ANSI_REV(inq_buf) > SCSI_REV_SPC2 && 1194208911Smjacob (SCSI_QUIRK(path->device)->quirks & 1195208911Smjacob CAM_QUIRK_NORPTLUNS) == 0) { 1196208911Smjacob if (path->device->flags & 1197208911Smjacob CAM_DEV_UNCONFIGURED) { 1198208911Smjacob path->device->flags &= 1199208911Smjacob ~CAM_DEV_UNCONFIGURED; 1200208911Smjacob xpt_acquire_device(path->device); 1201208911Smjacob } 1202208911Smjacob PROBE_SET_ACTION(softc, PROBE_REPORT_LUNS); 1203208911Smjacob periph->path->target->rpl_size = 16; 1204208911Smjacob xpt_release_ccb(done_ccb); 1205208911Smjacob xpt_schedule(periph, priority); 1206249466Smav goto out; 1207195534Sscottl } 1208195534Sscottl } else if (cam_periph_error(done_ccb, 0, 1209195534Sscottl done_ccb->ccb_h.target_lun > 0 1210195534Sscottl ? SF_RETRY_UA|SF_QUIET_IR 1211195534Sscottl : SF_RETRY_UA, 1212195534Sscottl &softc->saved_ccb) == ERESTART) { 1213249466Smav goto out; 1214195534Sscottl } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1215195534Sscottl /* Don't wedge the queue */ 1216195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 1217195534Sscottl /*run_queue*/TRUE); 1218195534Sscottl } 1219195534Sscottl /* 1220195534Sscottl * If we get to this point, we got an error status back 1221195534Sscottl * from the inquiry and the error status doesn't require 1222195534Sscottl * automatically retrying the command. Therefore, the 1223195534Sscottl * inquiry failed. If we had inquiry information before 1224195534Sscottl * for this device, but this latest inquiry command failed, 1225195534Sscottl * the device has probably gone away. If this device isn't 1226195534Sscottl * already marked unconfigured, notify the peripheral 1227195534Sscottl * drivers that this device is no more. 1228195534Sscottl */ 1229195534Sscottl if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0) 1230195534Sscottl /* Send the async notification. */ 1231195534Sscottl xpt_async(AC_LOST_DEVICE, path, NULL); 1232236613Smav PROBE_SET_ACTION(softc, PROBE_INVALID); 1233195534Sscottl 1234195534Sscottl xpt_release_ccb(done_ccb); 1235195534Sscottl break; 1236195534Sscottl } 1237208911Smjacob case PROBE_REPORT_LUNS: 1238208911Smjacob { 1239208911Smjacob struct ccb_scsiio *csio; 1240208911Smjacob struct scsi_report_luns_data *lp; 1241208911Smjacob u_int nlun, maxlun; 1242208911Smjacob 1243208911Smjacob csio = &done_ccb->csio; 1244208911Smjacob 1245208911Smjacob lp = (struct scsi_report_luns_data *)csio->data_ptr; 1246208911Smjacob nlun = scsi_4btoul(lp->length) / 8; 1247208911Smjacob maxlun = (csio->dxfer_len / 8) - 1; 1248208911Smjacob 1249252382Sscottl if (cam_ccb_status(done_ccb) != CAM_REQ_CMP) { 1250208911Smjacob if (cam_periph_error(done_ccb, 0, 1251208911Smjacob done_ccb->ccb_h.target_lun > 0 ? 1252208911Smjacob SF_RETRY_UA|SF_QUIET_IR : SF_RETRY_UA, 1253208911Smjacob &softc->saved_ccb) == ERESTART) { 1254249466Smav goto out; 1255208911Smjacob } 1256208911Smjacob if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1257208911Smjacob xpt_release_devq(done_ccb->ccb_h.path, 1, 1258208911Smjacob TRUE); 1259208911Smjacob } 1260208911Smjacob free(lp, M_CAMXPT); 1261208911Smjacob lp = NULL; 1262208911Smjacob } else if (nlun > maxlun) { 1263208911Smjacob /* 1264208911Smjacob * Reallocate and retry to cover all luns 1265208911Smjacob */ 1266236613Smav CAM_DEBUG(path, CAM_DEBUG_PROBE, 1267236613Smav ("Probe: reallocating REPORT_LUNS for %u luns\n", 1268236613Smav nlun)); 1269208911Smjacob free(lp, M_CAMXPT); 1270208911Smjacob path->target->rpl_size = (nlun << 3) + 8; 1271208911Smjacob xpt_release_ccb(done_ccb); 1272208911Smjacob xpt_schedule(periph, priority); 1273249466Smav goto out; 1274208911Smjacob } else if (nlun == 0) { 1275208911Smjacob /* 1276208911Smjacob * If there don't appear to be any luns, bail. 1277208911Smjacob */ 1278208911Smjacob free(lp, M_CAMXPT); 1279208911Smjacob lp = NULL; 1280208911Smjacob } else if (probe_strange_rpl_data(lp, maxlun)) { 1281208911Smjacob /* 1282208911Smjacob * If we can't understand the lun format 1283208911Smjacob * of any entry, bail. 1284208911Smjacob */ 1285208911Smjacob free(lp, M_CAMXPT); 1286208911Smjacob lp = NULL; 1287208911Smjacob } else { 1288208911Smjacob lun_id_t lun; 1289208911Smjacob int idx; 1290208911Smjacob 1291236613Smav CAM_DEBUG(path, CAM_DEBUG_PROBE, 1292236613Smav ("Probe: %u lun(s) reported\n", nlun)); 1293208911Smjacob 1294208911Smjacob CAM_GET_SIMPLE_LUN(lp, 0, lun); 1295208911Smjacob /* 1296208911Smjacob * If the first lun is not lun 0, then either there 1297208911Smjacob * is no lun 0 in the list, or the list is unsorted. 1298208911Smjacob */ 1299208911Smjacob if (lun != 0) { 1300208911Smjacob for (idx = 0; idx < nlun; idx++) { 1301208911Smjacob CAM_GET_SIMPLE_LUN(lp, idx, lun); 1302208911Smjacob if (lun == 0) { 1303208911Smjacob break; 1304208911Smjacob } 1305208911Smjacob } 1306208911Smjacob if (idx != nlun) { 1307208911Smjacob uint8_t tlun[8]; 1308208911Smjacob memcpy(tlun, 1309208911Smjacob lp->luns[0].lundata, 8); 1310208911Smjacob memcpy(lp->luns[0].lundata, 1311208911Smjacob lp->luns[idx].lundata, 8); 1312208911Smjacob memcpy(lp->luns[idx].lundata, 1313208911Smjacob tlun, 8); 1314236613Smav CAM_DEBUG(path, CAM_DEBUG_PROBE, 1315236613Smav ("lun 0 in position %u\n", idx)); 1316208911Smjacob } else { 1317208911Smjacob /* 1318208911Smjacob * There is no lun 0 in our list. Destroy 1319208911Smjacob * the validity of the inquiry data so we 1320208911Smjacob * bail here and now. 1321208911Smjacob */ 1322208911Smjacob path->device->flags &= 1323208911Smjacob ~CAM_DEV_INQUIRY_DATA_VALID; 1324208911Smjacob } 1325208911Smjacob } 1326208911Smjacob /* 1327208911Smjacob * If we have an old lun list, We can either 1328208911Smjacob * retest luns that appear to have been dropped, 1329208911Smjacob * or just nuke them. We'll opt for the latter. 1330208911Smjacob * This function will also install the new list 1331208911Smjacob * in the target structure. 1332208911Smjacob */ 1333208911Smjacob probe_purge_old(path, lp); 1334208911Smjacob lp = NULL; 1335208911Smjacob } 1336208911Smjacob if (path->device->flags & CAM_DEV_INQUIRY_DATA_VALID) { 1337208911Smjacob struct scsi_inquiry_data *inq_buf; 1338208911Smjacob inq_buf = &path->device->inq_data; 1339208911Smjacob if (INQ_DATA_TQ_ENABLED(inq_buf)) 1340208911Smjacob PROBE_SET_ACTION(softc, PROBE_MODE_SENSE); 1341208911Smjacob else 1342216088Sken PROBE_SET_ACTION(softc, 1343216088Sken PROBE_SUPPORTED_VPD_LIST); 1344208911Smjacob xpt_release_ccb(done_ccb); 1345208911Smjacob xpt_schedule(periph, priority); 1346249466Smav goto out; 1347208911Smjacob } 1348208911Smjacob if (lp) { 1349208911Smjacob free(lp, M_CAMXPT); 1350208911Smjacob } 1351208911Smjacob break; 1352208911Smjacob } 1353195534Sscottl case PROBE_MODE_SENSE: 1354195534Sscottl { 1355195534Sscottl struct ccb_scsiio *csio; 1356195534Sscottl struct scsi_mode_header_6 *mode_hdr; 1357195534Sscottl 1358195534Sscottl csio = &done_ccb->csio; 1359195534Sscottl mode_hdr = (struct scsi_mode_header_6 *)csio->data_ptr; 1360252382Sscottl if (cam_ccb_status(done_ccb) == CAM_REQ_CMP) { 1361195534Sscottl struct scsi_control_page *page; 1362195534Sscottl u_int8_t *offset; 1363195534Sscottl 1364195534Sscottl offset = ((u_int8_t *)&mode_hdr[1]) 1365195534Sscottl + mode_hdr->blk_desc_len; 1366195534Sscottl page = (struct scsi_control_page *)offset; 1367195534Sscottl path->device->queue_flags = page->queue_flags; 1368195534Sscottl } else if (cam_periph_error(done_ccb, 0, 1369195534Sscottl SF_RETRY_UA|SF_NO_PRINT, 1370195534Sscottl &softc->saved_ccb) == ERESTART) { 1371249466Smav goto out; 1372195534Sscottl } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1373195534Sscottl /* Don't wedge the queue */ 1374195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, 1375195534Sscottl /*count*/1, /*run_queue*/TRUE); 1376195534Sscottl } 1377195534Sscottl xpt_release_ccb(done_ccb); 1378195534Sscottl free(mode_hdr, M_CAMXPT); 1379216088Sken PROBE_SET_ACTION(softc, PROBE_SUPPORTED_VPD_LIST); 1380195534Sscottl xpt_schedule(periph, priority); 1381249466Smav goto out; 1382195534Sscottl } 1383216088Sken case PROBE_SUPPORTED_VPD_LIST: 1384195534Sscottl { 1385195534Sscottl struct ccb_scsiio *csio; 1386195534Sscottl struct scsi_vpd_supported_page_list *page_list; 1387195534Sscottl 1388195534Sscottl csio = &done_ccb->csio; 1389195534Sscottl page_list = 1390195534Sscottl (struct scsi_vpd_supported_page_list *)csio->data_ptr; 1391195534Sscottl 1392216088Sken if (path->device->supported_vpds != NULL) { 1393216088Sken free(path->device->supported_vpds, M_CAMXPT); 1394216088Sken path->device->supported_vpds = NULL; 1395216088Sken path->device->supported_vpds_len = 0; 1396216088Sken } 1397216088Sken 1398195534Sscottl if (page_list == NULL) { 1399195534Sscottl /* 1400195534Sscottl * Don't process the command as it was never sent 1401195534Sscottl */ 1402216088Sken } else if (CCB_COMPLETED_OK(csio->ccb_h)) { 1403216088Sken /* Got vpd list */ 1404216088Sken path->device->supported_vpds_len = page_list->length + 1405216088Sken SVPD_SUPPORTED_PAGES_HDR_LEN; 1406216088Sken path->device->supported_vpds = (uint8_t *)page_list; 1407216088Sken xpt_release_ccb(done_ccb); 1408216088Sken PROBE_SET_ACTION(softc, PROBE_DEVICE_ID); 1409216088Sken xpt_schedule(periph, priority); 1410249466Smav goto out; 1411195534Sscottl } else if (cam_periph_error(done_ccb, 0, 1412195534Sscottl SF_RETRY_UA|SF_NO_PRINT, 1413195534Sscottl &softc->saved_ccb) == ERESTART) { 1414249466Smav goto out; 1415195534Sscottl } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1416195534Sscottl /* Don't wedge the queue */ 1417195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 1418195534Sscottl /*run_queue*/TRUE); 1419195534Sscottl } 1420195534Sscottl 1421216088Sken if (page_list) 1422195685Semaste free(page_list, M_CAMXPT); 1423216088Sken /* No VPDs available, skip to device check. */ 1424216088Sken csio->data_ptr = NULL; 1425216088Sken goto probe_device_check; 1426216088Sken } 1427216088Sken case PROBE_DEVICE_ID: 1428216088Sken { 1429216088Sken struct scsi_vpd_device_id *devid; 1430216088Sken struct ccb_scsiio *csio; 1431216088Sken uint32_t length = 0; 1432195534Sscottl 1433216088Sken csio = &done_ccb->csio; 1434216088Sken devid = (struct scsi_vpd_device_id *)csio->data_ptr; 1435216088Sken 1436216088Sken /* Clean up from previous instance of this device */ 1437216088Sken if (path->device->device_id != NULL) { 1438216088Sken path->device->device_id_len = 0; 1439216088Sken free(path->device->device_id, M_CAMXPT); 1440216088Sken path->device->device_id = NULL; 1441216088Sken } 1442216088Sken 1443216088Sken if (devid == NULL) { 1444216088Sken /* Don't process the command as it was never sent */ 1445216088Sken } else if (CCB_COMPLETED_OK(csio->ccb_h)) { 1446216088Sken length = scsi_2btoul(devid->length); 1447216088Sken if (length != 0) { 1448216088Sken /* 1449216088Sken * NB: device_id_len is actual response 1450216088Sken * size, not buffer size. 1451216088Sken */ 1452216088Sken path->device->device_id_len = length + 1453216088Sken SVPD_DEVICE_ID_HDR_LEN; 1454216088Sken path->device->device_id = (uint8_t *)devid; 1455216088Sken } 1456216088Sken } else if (cam_periph_error(done_ccb, 0, 1457223081Sgibbs SF_RETRY_UA, 1458216088Sken &softc->saved_ccb) == ERESTART) { 1459249466Smav goto out; 1460216088Sken } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1461216088Sken /* Don't wedge the queue */ 1462216088Sken xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 1463216088Sken /*run_queue*/TRUE); 1464195534Sscottl } 1465195534Sscottl 1466216088Sken /* Free the device id space if we don't use it */ 1467216088Sken if (devid && length == 0) 1468216088Sken free(devid, M_CAMXPT); 1469216088Sken xpt_release_ccb(done_ccb); 1470216088Sken PROBE_SET_ACTION(softc, PROBE_SERIAL_NUM); 1471216088Sken xpt_schedule(periph, priority); 1472249466Smav goto out; 1473195534Sscottl } 1474195534Sscottl 1475216088Skenprobe_device_check: 1476216088Sken case PROBE_SERIAL_NUM: 1477195534Sscottl { 1478195534Sscottl struct ccb_scsiio *csio; 1479195534Sscottl struct scsi_vpd_unit_serial_number *serial_buf; 1480195534Sscottl u_int32_t priority; 1481195534Sscottl int changed; 1482195534Sscottl int have_serialnum; 1483195534Sscottl 1484195534Sscottl changed = 1; 1485195534Sscottl have_serialnum = 0; 1486195534Sscottl csio = &done_ccb->csio; 1487195534Sscottl priority = done_ccb->ccb_h.pinfo.priority; 1488195534Sscottl serial_buf = 1489195534Sscottl (struct scsi_vpd_unit_serial_number *)csio->data_ptr; 1490195534Sscottl 1491195534Sscottl if (serial_buf == NULL) { 1492195534Sscottl /* 1493195534Sscottl * Don't process the command as it was never sent 1494195534Sscottl */ 1495252382Sscottl } else if (cam_ccb_status(done_ccb) == CAM_REQ_CMP 1496195534Sscottl && (serial_buf->length > 0)) { 1497195534Sscottl 1498195534Sscottl have_serialnum = 1; 1499195534Sscottl path->device->serial_num = 1500195534Sscottl (u_int8_t *)malloc((serial_buf->length + 1), 1501195534Sscottl M_CAMXPT, M_NOWAIT); 1502195534Sscottl if (path->device->serial_num != NULL) { 1503223081Sgibbs memcpy(path->device->serial_num, 1504223081Sgibbs serial_buf->serial_num, 1505223081Sgibbs serial_buf->length); 1506195534Sscottl path->device->serial_num_len = 1507195534Sscottl serial_buf->length; 1508195534Sscottl path->device->serial_num[serial_buf->length] 1509195534Sscottl = '\0'; 1510195534Sscottl } 1511195534Sscottl } else if (cam_periph_error(done_ccb, 0, 1512195534Sscottl SF_RETRY_UA|SF_NO_PRINT, 1513195534Sscottl &softc->saved_ccb) == ERESTART) { 1514249466Smav goto out; 1515195534Sscottl } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1516195534Sscottl /* Don't wedge the queue */ 1517195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 1518195534Sscottl /*run_queue*/TRUE); 1519195534Sscottl } 1520195534Sscottl 1521195534Sscottl /* 1522195534Sscottl * Let's see if we have seen this device before. 1523195534Sscottl */ 1524195534Sscottl if ((softc->flags & PROBE_INQUIRY_CKSUM) != 0) { 1525195534Sscottl MD5_CTX context; 1526195534Sscottl u_int8_t digest[16]; 1527195534Sscottl 1528195534Sscottl MD5Init(&context); 1529195534Sscottl 1530195534Sscottl MD5Update(&context, 1531195534Sscottl (unsigned char *)&path->device->inq_data, 1532195534Sscottl sizeof(struct scsi_inquiry_data)); 1533195534Sscottl 1534195534Sscottl if (have_serialnum) 1535195534Sscottl MD5Update(&context, serial_buf->serial_num, 1536195534Sscottl serial_buf->length); 1537195534Sscottl 1538195534Sscottl MD5Final(digest, &context); 1539195534Sscottl if (bcmp(softc->digest, digest, 16) == 0) 1540195534Sscottl changed = 0; 1541195534Sscottl 1542195534Sscottl /* 1543195534Sscottl * XXX Do we need to do a TUR in order to ensure 1544195534Sscottl * that the device really hasn't changed??? 1545195534Sscottl */ 1546195534Sscottl if ((changed != 0) 1547195534Sscottl && ((softc->flags & PROBE_NO_ANNOUNCE) == 0)) 1548195534Sscottl xpt_async(AC_LOST_DEVICE, path, NULL); 1549195534Sscottl } 1550195534Sscottl if (serial_buf != NULL) 1551195534Sscottl free(serial_buf, M_CAMXPT); 1552195534Sscottl 1553195534Sscottl if (changed != 0) { 1554195534Sscottl /* 1555195534Sscottl * Now that we have all the necessary 1556195534Sscottl * information to safely perform transfer 1557195534Sscottl * negotiations... Controllers don't perform 1558195534Sscottl * any negotiation or tagged queuing until 1559195534Sscottl * after the first XPT_SET_TRAN_SETTINGS ccb is 1560195534Sscottl * received. So, on a new device, just retrieve 1561195534Sscottl * the user settings, and set them as the current 1562195534Sscottl * settings to set the device up. 1563195534Sscottl */ 1564195534Sscottl proberequestdefaultnegotiation(periph); 1565195534Sscottl xpt_release_ccb(done_ccb); 1566195534Sscottl 1567195534Sscottl /* 1568195534Sscottl * Perform a TUR to allow the controller to 1569195534Sscottl * perform any necessary transfer negotiation. 1570195534Sscottl */ 1571195534Sscottl PROBE_SET_ACTION(softc, PROBE_TUR_FOR_NEGOTIATION); 1572195534Sscottl xpt_schedule(periph, priority); 1573249466Smav goto out; 1574195534Sscottl } 1575195534Sscottl xpt_release_ccb(done_ccb); 1576195534Sscottl break; 1577195534Sscottl } 1578195534Sscottl case PROBE_TUR_FOR_NEGOTIATION: 1579236814Smav case PROBE_DV_EXIT: 1580252382Sscottl if (cam_ccb_status(done_ccb) != CAM_REQ_CMP) { 1581236814Smav cam_periph_error(done_ccb, 0, 1582236814Smav SF_NO_PRINT | SF_NO_RECOVERY | SF_NO_RETRY, NULL); 1583195534Sscottl } 1584195534Sscottl if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1585195534Sscottl /* Don't wedge the queue */ 1586195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 1587195534Sscottl /*run_queue*/TRUE); 1588195534Sscottl } 1589195534Sscottl /* 1590195534Sscottl * Do Domain Validation for lun 0 on devices that claim 1591195534Sscottl * to support Synchronous Transfer modes. 1592195534Sscottl */ 1593195534Sscottl if (softc->action == PROBE_TUR_FOR_NEGOTIATION 1594195534Sscottl && done_ccb->ccb_h.target_lun == 0 1595195534Sscottl && (path->device->inq_data.flags & SID_Sync) != 0 1596195534Sscottl && (path->device->flags & CAM_DEV_IN_DV) == 0) { 1597236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, 1598195534Sscottl ("Begin Domain Validation\n")); 1599195534Sscottl path->device->flags |= CAM_DEV_IN_DV; 1600195534Sscottl xpt_release_ccb(done_ccb); 1601195534Sscottl PROBE_SET_ACTION(softc, PROBE_INQUIRY_BASIC_DV1); 1602195534Sscottl xpt_schedule(periph, priority); 1603249466Smav goto out; 1604195534Sscottl } 1605195534Sscottl if (softc->action == PROBE_DV_EXIT) { 1606236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, 1607195534Sscottl ("Leave Domain Validation\n")); 1608195534Sscottl } 1609198748Smav if (path->device->flags & CAM_DEV_UNCONFIGURED) { 1610198748Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1611198748Smav xpt_acquire_device(path->device); 1612198748Smav } 1613195534Sscottl path->device->flags &= 1614198748Smav ~(CAM_DEV_IN_DV|CAM_DEV_DV_HIT_BOTTOM); 1615195534Sscottl if ((softc->flags & PROBE_NO_ANNOUNCE) == 0) { 1616195534Sscottl /* Inform the XPT that a new device has been found */ 1617195534Sscottl done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1618195534Sscottl xpt_action(done_ccb); 1619195534Sscottl xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, 1620195534Sscottl done_ccb); 1621195534Sscottl } 1622236613Smav PROBE_SET_ACTION(softc, PROBE_DONE); 1623195534Sscottl xpt_release_ccb(done_ccb); 1624195534Sscottl break; 1625195534Sscottl case PROBE_INQUIRY_BASIC_DV1: 1626195534Sscottl case PROBE_INQUIRY_BASIC_DV2: 1627195534Sscottl { 1628195534Sscottl struct scsi_inquiry_data *nbuf; 1629195534Sscottl struct ccb_scsiio *csio; 1630195534Sscottl 1631252382Sscottl if (cam_ccb_status(done_ccb) != CAM_REQ_CMP) { 1632236814Smav cam_periph_error(done_ccb, 0, 1633236814Smav SF_NO_PRINT | SF_NO_RECOVERY | SF_NO_RETRY, NULL); 1634236814Smav } 1635195534Sscottl if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1636195534Sscottl /* Don't wedge the queue */ 1637195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 1638195534Sscottl /*run_queue*/TRUE); 1639195534Sscottl } 1640195534Sscottl csio = &done_ccb->csio; 1641195534Sscottl nbuf = (struct scsi_inquiry_data *)csio->data_ptr; 1642195534Sscottl if (bcmp(nbuf, &path->device->inq_data, SHORT_INQUIRY_LENGTH)) { 1643195534Sscottl xpt_print(path, 1644195534Sscottl "inquiry data fails comparison at DV%d step\n", 1645195534Sscottl softc->action == PROBE_INQUIRY_BASIC_DV1 ? 1 : 2); 1646195534Sscottl if (proberequestbackoff(periph, path->device)) { 1647195534Sscottl path->device->flags &= ~CAM_DEV_IN_DV; 1648195534Sscottl PROBE_SET_ACTION(softc, PROBE_TUR_FOR_NEGOTIATION); 1649195534Sscottl } else { 1650195534Sscottl /* give up */ 1651195534Sscottl PROBE_SET_ACTION(softc, PROBE_DV_EXIT); 1652195534Sscottl } 1653195534Sscottl free(nbuf, M_CAMXPT); 1654195534Sscottl xpt_release_ccb(done_ccb); 1655195534Sscottl xpt_schedule(periph, priority); 1656249466Smav goto out; 1657195534Sscottl } 1658195534Sscottl free(nbuf, M_CAMXPT); 1659195534Sscottl if (softc->action == PROBE_INQUIRY_BASIC_DV1) { 1660195534Sscottl PROBE_SET_ACTION(softc, PROBE_INQUIRY_BASIC_DV2); 1661195534Sscottl xpt_release_ccb(done_ccb); 1662195534Sscottl xpt_schedule(periph, priority); 1663249466Smav goto out; 1664195534Sscottl } 1665195534Sscottl if (softc->action == PROBE_INQUIRY_BASIC_DV2) { 1666236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, 1667195534Sscottl ("Leave Domain Validation Successfully\n")); 1668195534Sscottl } 1669198748Smav if (path->device->flags & CAM_DEV_UNCONFIGURED) { 1670198748Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1671198748Smav xpt_acquire_device(path->device); 1672198748Smav } 1673195534Sscottl path->device->flags &= 1674198748Smav ~(CAM_DEV_IN_DV|CAM_DEV_DV_HIT_BOTTOM); 1675195534Sscottl if ((softc->flags & PROBE_NO_ANNOUNCE) == 0) { 1676195534Sscottl /* Inform the XPT that a new device has been found */ 1677195534Sscottl done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1678195534Sscottl xpt_action(done_ccb); 1679195534Sscottl xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, 1680195534Sscottl done_ccb); 1681195534Sscottl } 1682236613Smav PROBE_SET_ACTION(softc, PROBE_DONE); 1683195534Sscottl xpt_release_ccb(done_ccb); 1684195534Sscottl break; 1685195534Sscottl } 1686195534Sscottl default: 1687236613Smav panic("probedone: invalid action state 0x%x\n", softc->action); 1688195534Sscottl } 1689195534Sscottl done_ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs); 1690195534Sscottl TAILQ_REMOVE(&softc->request_ccbs, &done_ccb->ccb_h, periph_links.tqe); 1691195534Sscottl done_ccb->ccb_h.status = CAM_REQ_CMP; 1692195534Sscottl xpt_done(done_ccb); 1693195534Sscottl if (TAILQ_FIRST(&softc->request_ccbs) == NULL) { 1694236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe completed\n")); 1695249466Smav /* Drop freeze taken due to CAM_DEV_QFREEZE flag set. */ 1696249466Smav cam_release_devq(path, 0, 0, 0, FALSE); 1697236228Smav cam_periph_invalidate(periph); 1698195534Sscottl cam_periph_release_locked(periph); 1699195534Sscottl } else { 1700195534Sscottl probeschedule(periph); 1701249466Smav goto out; 1702195534Sscottl } 1703195534Sscottl} 1704195534Sscottl 1705208911Smjacobstatic int 1706208911Smjacobprobe_strange_rpl_data(struct scsi_report_luns_data *rp, uint32_t maxlun) 1707208911Smjacob{ 1708208911Smjacob uint32_t idx; 1709208911Smjacob uint32_t nlun = MIN(maxlun, (scsi_4btoul(rp->length) / 8)); 1710208911Smjacob 1711208911Smjacob for (idx = 0; idx < nlun; idx++) { 1712208911Smjacob if (!CAM_CAN_GET_SIMPLE_LUN(rp, idx)) { 1713208911Smjacob return (-1); 1714208911Smjacob } 1715208911Smjacob } 1716208911Smjacob return (0); 1717208911Smjacob} 1718208911Smjacob 1719195534Sscottlstatic void 1720208911Smjacobprobe_purge_old(struct cam_path *path, struct scsi_report_luns_data *new) 1721208911Smjacob{ 1722208911Smjacob struct cam_path *tp; 1723208911Smjacob struct scsi_report_luns_data *old; 1724208911Smjacob u_int idx1, idx2, nlun_old, nlun_new, this_lun; 1725208911Smjacob u_int8_t *ol, *nl; 1726208911Smjacob 1727208911Smjacob if (path->target == NULL) { 1728208911Smjacob return; 1729208911Smjacob } 1730208911Smjacob if (path->target->luns == NULL) { 1731208911Smjacob path->target->luns = new; 1732208911Smjacob return; 1733208911Smjacob } 1734208911Smjacob old = path->target->luns; 1735208911Smjacob nlun_old = scsi_4btoul(old->length) / 8; 1736208911Smjacob nlun_new = scsi_4btoul(new->length) / 8; 1737208911Smjacob 1738208911Smjacob /* 1739208911Smjacob * We are not going to assume sorted lists. Deal. 1740208911Smjacob */ 1741208911Smjacob for (idx1 = 0; idx1 < nlun_old; idx1++) { 1742208911Smjacob ol = old->luns[idx1].lundata; 1743208911Smjacob for (idx2 = 0; idx2 < nlun_new; idx2++) { 1744208911Smjacob nl = new->luns[idx2].lundata; 1745208911Smjacob if (memcmp(nl, ol, 8) == 0) { 1746208911Smjacob break; 1747208911Smjacob } 1748208911Smjacob } 1749208911Smjacob if (idx2 < nlun_new) { 1750208911Smjacob continue; 1751208911Smjacob } 1752208911Smjacob /* 1753208911Smjacob * An 'old' item not in the 'new' list. 1754208911Smjacob * Nuke it. Except that if it is lun 0, 1755208911Smjacob * that would be what the probe state 1756208911Smjacob * machine is currently working on, 1757208911Smjacob * so we won't do that. 1758208911Smjacob * 1759208911Smjacob * We also cannot nuke it if it is 1760208911Smjacob * not in a lun format we understand. 1761208911Smjacob */ 1762208911Smjacob if (!CAM_CAN_GET_SIMPLE_LUN(old, idx1)) { 1763208911Smjacob continue; 1764208911Smjacob } 1765208911Smjacob CAM_GET_SIMPLE_LUN(old, idx1, this_lun); 1766208911Smjacob if (this_lun == 0) { 1767208911Smjacob continue; 1768208911Smjacob } 1769208911Smjacob if (xpt_create_path(&tp, NULL, xpt_path_path_id(path), 1770208911Smjacob xpt_path_target_id(path), this_lun) == CAM_REQ_CMP) { 1771208911Smjacob xpt_async(AC_LOST_DEVICE, tp, NULL); 1772208911Smjacob xpt_free_path(tp); 1773208911Smjacob } 1774208911Smjacob } 1775208911Smjacob free(old, M_CAMXPT); 1776208911Smjacob path->target->luns = new; 1777208911Smjacob} 1778208911Smjacob 1779208911Smjacobstatic void 1780195534Sscottlprobecleanup(struct cam_periph *periph) 1781195534Sscottl{ 1782195534Sscottl free(periph->softc, M_CAMXPT); 1783195534Sscottl} 1784195534Sscottl 1785195534Sscottlstatic void 1786195534Sscottlscsi_find_quirk(struct cam_ed *device) 1787195534Sscottl{ 1788195534Sscottl struct scsi_quirk_entry *quirk; 1789195534Sscottl caddr_t match; 1790195534Sscottl 1791195534Sscottl match = cam_quirkmatch((caddr_t)&device->inq_data, 1792195534Sscottl (caddr_t)scsi_quirk_table, 1793195534Sscottl sizeof(scsi_quirk_table) / 1794195534Sscottl sizeof(*scsi_quirk_table), 1795195534Sscottl sizeof(*scsi_quirk_table), scsi_inquiry_match); 1796195534Sscottl 1797195534Sscottl if (match == NULL) 1798195534Sscottl panic("xpt_find_quirk: device didn't match wildcard entry!!"); 1799195534Sscottl 1800195534Sscottl quirk = (struct scsi_quirk_entry *)match; 1801195534Sscottl device->quirk = quirk; 1802195534Sscottl device->mintags = quirk->mintags; 1803195534Sscottl device->maxtags = quirk->maxtags; 1804195534Sscottl} 1805195534Sscottl 1806195534Sscottlstatic int 1807195534Sscottlsysctl_cam_search_luns(SYSCTL_HANDLER_ARGS) 1808195534Sscottl{ 1809228442Smdf int error, val; 1810195534Sscottl 1811228442Smdf val = cam_srch_hi; 1812228442Smdf error = sysctl_handle_int(oidp, &val, 0, req); 1813195534Sscottl if (error != 0 || req->newptr == NULL) 1814195534Sscottl return (error); 1815228442Smdf if (val == 0 || val == 1) { 1816228442Smdf cam_srch_hi = val; 1817195534Sscottl return (0); 1818195534Sscottl } else { 1819195534Sscottl return (EINVAL); 1820195534Sscottl } 1821195534Sscottl} 1822195534Sscottl 1823195534Sscottltypedef struct { 1824195534Sscottl union ccb *request_ccb; 1825195534Sscottl struct ccb_pathinq *cpi; 1826195534Sscottl int counter; 1827208911Smjacob int lunindex[0]; 1828195534Sscottl} scsi_scan_bus_info; 1829195534Sscottl 1830195534Sscottl/* 1831195534Sscottl * To start a scan, request_ccb is an XPT_SCAN_BUS ccb. 1832195688Semaste * As the scan progresses, scsi_scan_bus is used as the 1833195534Sscottl * callback on completion function. 1834195534Sscottl */ 1835195534Sscottlstatic void 1836195534Sscottlscsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb) 1837195534Sscottl{ 1838195534Sscottl CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE, 1839195688Semaste ("scsi_scan_bus\n")); 1840195534Sscottl switch (request_ccb->ccb_h.func_code) { 1841195534Sscottl case XPT_SCAN_BUS: 1842208582Smjacob case XPT_SCAN_TGT: 1843195534Sscottl { 1844195534Sscottl scsi_scan_bus_info *scan_info; 1845203108Smav union ccb *work_ccb, *reset_ccb; 1846195534Sscottl struct cam_path *path; 1847195534Sscottl u_int i; 1848208582Smjacob u_int low_target, max_target; 1849195534Sscottl u_int initiator_id; 1850195534Sscottl 1851195534Sscottl /* Find out the characteristics of the bus */ 1852195534Sscottl work_ccb = xpt_alloc_ccb_nowait(); 1853195534Sscottl if (work_ccb == NULL) { 1854195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1855195534Sscottl xpt_done(request_ccb); 1856195534Sscottl return; 1857195534Sscottl } 1858195534Sscottl xpt_setup_ccb(&work_ccb->ccb_h, request_ccb->ccb_h.path, 1859195534Sscottl request_ccb->ccb_h.pinfo.priority); 1860195534Sscottl work_ccb->ccb_h.func_code = XPT_PATH_INQ; 1861195534Sscottl xpt_action(work_ccb); 1862195534Sscottl if (work_ccb->ccb_h.status != CAM_REQ_CMP) { 1863195534Sscottl request_ccb->ccb_h.status = work_ccb->ccb_h.status; 1864195534Sscottl xpt_free_ccb(work_ccb); 1865195534Sscottl xpt_done(request_ccb); 1866195534Sscottl return; 1867195534Sscottl } 1868195534Sscottl 1869195534Sscottl if ((work_ccb->cpi.hba_misc & PIM_NOINITIATOR) != 0) { 1870195534Sscottl /* 1871195534Sscottl * Can't scan the bus on an adapter that 1872195534Sscottl * cannot perform the initiator role. 1873195534Sscottl */ 1874195534Sscottl request_ccb->ccb_h.status = CAM_REQ_CMP; 1875195534Sscottl xpt_free_ccb(work_ccb); 1876195534Sscottl xpt_done(request_ccb); 1877195534Sscottl return; 1878195534Sscottl } 1879195534Sscottl 1880203108Smav /* We may need to reset bus first, if we haven't done it yet. */ 1881203108Smav if ((work_ccb->cpi.hba_inquiry & 1882203108Smav (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE)) && 1883203108Smav !(work_ccb->cpi.hba_misc & PIM_NOBUSRESET) && 1884253370Smav !timevalisset(&request_ccb->ccb_h.path->bus->last_reset) && 1885253370Smav (reset_ccb = xpt_alloc_ccb_nowait()) != NULL) { 1886203108Smav xpt_setup_ccb(&reset_ccb->ccb_h, request_ccb->ccb_h.path, 1887203108Smav CAM_PRIORITY_NONE); 1888203108Smav reset_ccb->ccb_h.func_code = XPT_RESET_BUS; 1889203108Smav xpt_action(reset_ccb); 1890203108Smav if (reset_ccb->ccb_h.status != CAM_REQ_CMP) { 1891203108Smav request_ccb->ccb_h.status = reset_ccb->ccb_h.status; 1892203108Smav xpt_free_ccb(reset_ccb); 1893203108Smav xpt_free_ccb(work_ccb); 1894203108Smav xpt_done(request_ccb); 1895203108Smav return; 1896203108Smav } 1897203108Smav xpt_free_ccb(reset_ccb); 1898203108Smav } 1899203108Smav 1900195534Sscottl /* Save some state for use while we probe for devices */ 1901208911Smjacob scan_info = (scsi_scan_bus_info *) malloc(sizeof(scsi_scan_bus_info) + 1902208911Smjacob (work_ccb->cpi.max_target * sizeof (u_int)), M_CAMXPT, M_ZERO|M_NOWAIT); 1903195534Sscottl if (scan_info == NULL) { 1904195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1905195534Sscottl xpt_done(request_ccb); 1906195534Sscottl return; 1907195534Sscottl } 1908236613Smav CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE, 1909208911Smjacob ("SCAN start for %p\n", scan_info)); 1910195534Sscottl scan_info->request_ccb = request_ccb; 1911195534Sscottl scan_info->cpi = &work_ccb->cpi; 1912195534Sscottl 1913195534Sscottl /* Cache on our stack so we can work asynchronously */ 1914195534Sscottl max_target = scan_info->cpi->max_target; 1915208582Smjacob low_target = 0; 1916195534Sscottl initiator_id = scan_info->cpi->initiator_id; 1917195534Sscottl 1918195534Sscottl 1919195534Sscottl /* 1920195534Sscottl * We can scan all targets in parallel, or do it sequentially. 1921195534Sscottl */ 1922208582Smjacob 1923208582Smjacob if (request_ccb->ccb_h.func_code == XPT_SCAN_TGT) { 1924208582Smjacob max_target = low_target = request_ccb->ccb_h.target_id; 1925208582Smjacob scan_info->counter = 0; 1926208582Smjacob } else if (scan_info->cpi->hba_misc & PIM_SEQSCAN) { 1927195534Sscottl max_target = 0; 1928195534Sscottl scan_info->counter = 0; 1929195534Sscottl } else { 1930195534Sscottl scan_info->counter = scan_info->cpi->max_target + 1; 1931195534Sscottl if (scan_info->cpi->initiator_id < scan_info->counter) { 1932195534Sscottl scan_info->counter--; 1933195534Sscottl } 1934195534Sscottl } 1935195534Sscottl 1936208582Smjacob for (i = low_target; i <= max_target; i++) { 1937195534Sscottl cam_status status; 1938195534Sscottl if (i == initiator_id) 1939195534Sscottl continue; 1940195534Sscottl 1941249468Smav status = xpt_create_path(&path, NULL, 1942195534Sscottl request_ccb->ccb_h.path_id, 1943195534Sscottl i, 0); 1944195534Sscottl if (status != CAM_REQ_CMP) { 1945195688Semaste printf("scsi_scan_bus: xpt_create_path failed" 1946195534Sscottl " with status %#x, bus scan halted\n", 1947195534Sscottl status); 1948195534Sscottl free(scan_info, M_CAMXPT); 1949195534Sscottl request_ccb->ccb_h.status = status; 1950195534Sscottl xpt_free_ccb(work_ccb); 1951195534Sscottl xpt_done(request_ccb); 1952195534Sscottl break; 1953195534Sscottl } 1954195534Sscottl work_ccb = xpt_alloc_ccb_nowait(); 1955195534Sscottl if (work_ccb == NULL) { 1956195685Semaste xpt_free_ccb((union ccb *)scan_info->cpi); 1957195534Sscottl free(scan_info, M_CAMXPT); 1958195534Sscottl xpt_free_path(path); 1959195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1960195534Sscottl xpt_done(request_ccb); 1961195534Sscottl break; 1962195534Sscottl } 1963195534Sscottl xpt_setup_ccb(&work_ccb->ccb_h, path, 1964195534Sscottl request_ccb->ccb_h.pinfo.priority); 1965195534Sscottl work_ccb->ccb_h.func_code = XPT_SCAN_LUN; 1966195534Sscottl work_ccb->ccb_h.cbfcnp = scsi_scan_bus; 1967195534Sscottl work_ccb->ccb_h.ppriv_ptr0 = scan_info; 1968195534Sscottl work_ccb->crcn.flags = request_ccb->crcn.flags; 1969195534Sscottl xpt_action(work_ccb); 1970195534Sscottl } 1971195534Sscottl break; 1972195534Sscottl } 1973195534Sscottl case XPT_SCAN_LUN: 1974195534Sscottl { 1975195534Sscottl cam_status status; 1976208911Smjacob struct cam_path *path, *oldpath; 1977195534Sscottl scsi_scan_bus_info *scan_info; 1978208911Smjacob struct cam_et *target; 1979208911Smjacob struct cam_ed *device; 1980208911Smjacob int next_target; 1981195534Sscottl path_id_t path_id; 1982195534Sscottl target_id_t target_id; 1983195534Sscottl lun_id_t lun_id; 1984195534Sscottl 1985208911Smjacob oldpath = request_ccb->ccb_h.path; 1986208911Smjacob 1987252382Sscottl status = cam_ccb_status(request_ccb); 1988195534Sscottl /* Reuse the same CCB to query if a device was really found */ 1989195534Sscottl scan_info = (scsi_scan_bus_info *)request_ccb->ccb_h.ppriv_ptr0; 1990195534Sscottl xpt_setup_ccb(&request_ccb->ccb_h, request_ccb->ccb_h.path, 1991195534Sscottl request_ccb->ccb_h.pinfo.priority); 1992195534Sscottl request_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1993195534Sscottl 1994208911Smjacob 1995195534Sscottl path_id = request_ccb->ccb_h.path_id; 1996195534Sscottl target_id = request_ccb->ccb_h.target_id; 1997195534Sscottl lun_id = request_ccb->ccb_h.target_lun; 1998195534Sscottl xpt_action(request_ccb); 1999195534Sscottl 2000208911Smjacob target = request_ccb->ccb_h.path->target; 2001208911Smjacob next_target = 1; 2002208911Smjacob 2003208911Smjacob if (target->luns) { 2004208911Smjacob uint32_t first; 2005208911Smjacob u_int nluns = scsi_4btoul(target->luns->length) / 8; 2006208911Smjacob 2007208911Smjacob /* 2008208911Smjacob * Make sure we skip over lun 0 if it's the first member 2009208911Smjacob * of the list as we've actually just finished probing 2010208911Smjacob * it. 2011208911Smjacob */ 2012208911Smjacob CAM_GET_SIMPLE_LUN(target->luns, 0, first); 2013208911Smjacob if (first == 0 && scan_info->lunindex[target_id] == 0) { 2014208911Smjacob scan_info->lunindex[target_id]++; 2015208911Smjacob } 2016208911Smjacob 2017208911Smjacob if (scan_info->lunindex[target_id] < nluns) { 2018208911Smjacob CAM_GET_SIMPLE_LUN(target->luns, 2019208911Smjacob scan_info->lunindex[target_id], lun_id); 2020208911Smjacob next_target = 0; 2021236613Smav CAM_DEBUG(request_ccb->ccb_h.path, 2022236613Smav CAM_DEBUG_PROBE, 2023208911Smjacob ("next lun to try at index %u is %u\n", 2024208911Smjacob scan_info->lunindex[target_id], lun_id)); 2025208911Smjacob scan_info->lunindex[target_id]++; 2026208911Smjacob } else { 2027208911Smjacob /* 2028208911Smjacob * We're done with scanning all luns. 2029208911Smjacob * 2030208911Smjacob * Nuke the bogus device for lun 0 if lun 0 2031208911Smjacob * wasn't on the list. 2032208911Smjacob */ 2033208911Smjacob if (first != 0) { 2034208911Smjacob TAILQ_FOREACH(device, 2035208911Smjacob &target->ed_entries, links) { 2036208911Smjacob if (device->lun_id == 0) { 2037208911Smjacob break; 2038208911Smjacob } 2039208911Smjacob } 2040208911Smjacob if (device) { 2041208911Smjacob xpt_release_device(device); 2042208911Smjacob } 2043208911Smjacob } 2044208911Smjacob } 2045208911Smjacob } else if (request_ccb->ccb_h.status != CAM_REQ_CMP) { 2046195534Sscottl int phl; 2047195534Sscottl 2048195534Sscottl /* 2049195534Sscottl * If we already probed lun 0 successfully, or 2050195534Sscottl * we have additional configured luns on this 2051195534Sscottl * target that might have "gone away", go onto 2052195534Sscottl * the next lun. 2053195534Sscottl */ 2054195534Sscottl /* 2055195534Sscottl * We may touch devices that we don't 2056195534Sscottl * hold references too, so ensure they 2057195534Sscottl * don't disappear out from under us. 2058195534Sscottl * The target above is referenced by the 2059195534Sscottl * path in the request ccb. 2060195534Sscottl */ 2061195534Sscottl phl = 0; 2062195534Sscottl device = TAILQ_FIRST(&target->ed_entries); 2063195534Sscottl if (device != NULL) { 2064195534Sscottl phl = CAN_SRCH_HI_SPARSE(device); 2065195534Sscottl if (device->lun_id == 0) 2066195534Sscottl device = TAILQ_NEXT(device, links); 2067195534Sscottl } 2068195534Sscottl if ((lun_id != 0) || (device != NULL)) { 2069208911Smjacob if (lun_id < (CAM_SCSI2_MAXLUN-1) || phl) { 2070195534Sscottl lun_id++; 2071208911Smjacob next_target = 0; 2072208911Smjacob } 2073195534Sscottl } 2074208911Smjacob if (lun_id == request_ccb->ccb_h.target_lun 2075208911Smjacob || lun_id > scan_info->cpi->max_lun) 2076208911Smjacob next_target = 1; 2077195534Sscottl } else { 2078195534Sscottl 2079195534Sscottl device = request_ccb->ccb_h.path->device; 2080195534Sscottl 2081195534Sscottl if ((SCSI_QUIRK(device)->quirks & 2082195534Sscottl CAM_QUIRK_NOLUNS) == 0) { 2083195534Sscottl /* Try the next lun */ 2084195534Sscottl if (lun_id < (CAM_SCSI2_MAXLUN-1) 2085208911Smjacob || CAN_SRCH_HI_DENSE(device)) { 2086195534Sscottl lun_id++; 2087208911Smjacob next_target = 0; 2088208911Smjacob } 2089195534Sscottl } 2090208911Smjacob if (lun_id == request_ccb->ccb_h.target_lun 2091208911Smjacob || lun_id > scan_info->cpi->max_lun) 2092208911Smjacob next_target = 1; 2093195534Sscottl } 2094195534Sscottl 2095195534Sscottl /* 2096195534Sscottl * Check to see if we scan any further luns. 2097195534Sscottl */ 2098208911Smjacob if (next_target) { 2099195534Sscottl int done; 2100195534Sscottl 2101208911Smjacob /* 2102208911Smjacob * Free the current request path- we're done with it. 2103208911Smjacob */ 2104208911Smjacob xpt_free_path(oldpath); 2105195534Sscottl hop_again: 2106195534Sscottl done = 0; 2107208582Smjacob if (scan_info->request_ccb->ccb_h.func_code == XPT_SCAN_TGT) { 2108208582Smjacob done = 1; 2109208582Smjacob } else if (scan_info->cpi->hba_misc & PIM_SEQSCAN) { 2110195534Sscottl scan_info->counter++; 2111195534Sscottl if (scan_info->counter == 2112195534Sscottl scan_info->cpi->initiator_id) { 2113195534Sscottl scan_info->counter++; 2114195534Sscottl } 2115195534Sscottl if (scan_info->counter >= 2116195534Sscottl scan_info->cpi->max_target+1) { 2117195534Sscottl done = 1; 2118195534Sscottl } 2119195534Sscottl } else { 2120195534Sscottl scan_info->counter--; 2121195534Sscottl if (scan_info->counter == 0) { 2122195534Sscottl done = 1; 2123195534Sscottl } 2124195534Sscottl } 2125195534Sscottl if (done) { 2126195534Sscottl xpt_free_ccb(request_ccb); 2127195534Sscottl xpt_free_ccb((union ccb *)scan_info->cpi); 2128195534Sscottl request_ccb = scan_info->request_ccb; 2129236613Smav CAM_DEBUG(request_ccb->ccb_h.path, 2130236613Smav CAM_DEBUG_TRACE, 2131208911Smjacob ("SCAN done for %p\n", scan_info)); 2132195534Sscottl free(scan_info, M_CAMXPT); 2133195534Sscottl request_ccb->ccb_h.status = CAM_REQ_CMP; 2134195534Sscottl xpt_done(request_ccb); 2135195534Sscottl break; 2136195534Sscottl } 2137195534Sscottl 2138195534Sscottl if ((scan_info->cpi->hba_misc & PIM_SEQSCAN) == 0) { 2139195685Semaste xpt_free_ccb(request_ccb); 2140195534Sscottl break; 2141195534Sscottl } 2142249468Smav status = xpt_create_path(&path, NULL, 2143195534Sscottl scan_info->request_ccb->ccb_h.path_id, 2144195534Sscottl scan_info->counter, 0); 2145195534Sscottl if (status != CAM_REQ_CMP) { 2146195688Semaste printf("scsi_scan_bus: xpt_create_path failed" 2147195534Sscottl " with status %#x, bus scan halted\n", 2148195534Sscottl status); 2149195534Sscottl xpt_free_ccb(request_ccb); 2150195534Sscottl xpt_free_ccb((union ccb *)scan_info->cpi); 2151195534Sscottl request_ccb = scan_info->request_ccb; 2152195534Sscottl free(scan_info, M_CAMXPT); 2153195534Sscottl request_ccb->ccb_h.status = status; 2154195534Sscottl xpt_done(request_ccb); 2155195534Sscottl break; 2156195534Sscottl } 2157195534Sscottl xpt_setup_ccb(&request_ccb->ccb_h, path, 2158195534Sscottl request_ccb->ccb_h.pinfo.priority); 2159195534Sscottl request_ccb->ccb_h.func_code = XPT_SCAN_LUN; 2160195534Sscottl request_ccb->ccb_h.cbfcnp = scsi_scan_bus; 2161195534Sscottl request_ccb->ccb_h.ppriv_ptr0 = scan_info; 2162195534Sscottl request_ccb->crcn.flags = 2163195534Sscottl scan_info->request_ccb->crcn.flags; 2164195534Sscottl } else { 2165249468Smav status = xpt_create_path(&path, NULL, 2166195534Sscottl path_id, target_id, lun_id); 2167208911Smjacob /* 2168208911Smjacob * Free the old request path- we're done with it. We 2169208911Smjacob * do this *after* creating the new path so that 2170208911Smjacob * we don't remove a target that has our lun list 2171208911Smjacob * in the case that lun 0 is not present. 2172208911Smjacob */ 2173208911Smjacob xpt_free_path(oldpath); 2174195534Sscottl if (status != CAM_REQ_CMP) { 2175195688Semaste printf("scsi_scan_bus: xpt_create_path failed " 2176195534Sscottl "with status %#x, halting LUN scan\n", 2177195534Sscottl status); 2178195534Sscottl goto hop_again; 2179195534Sscottl } 2180195534Sscottl xpt_setup_ccb(&request_ccb->ccb_h, path, 2181195534Sscottl request_ccb->ccb_h.pinfo.priority); 2182195534Sscottl request_ccb->ccb_h.func_code = XPT_SCAN_LUN; 2183195534Sscottl request_ccb->ccb_h.cbfcnp = scsi_scan_bus; 2184195534Sscottl request_ccb->ccb_h.ppriv_ptr0 = scan_info; 2185195534Sscottl request_ccb->crcn.flags = 2186195534Sscottl scan_info->request_ccb->crcn.flags; 2187195534Sscottl } 2188195534Sscottl xpt_action(request_ccb); 2189195534Sscottl break; 2190195534Sscottl } 2191195534Sscottl default: 2192195534Sscottl break; 2193195534Sscottl } 2194195534Sscottl} 2195195534Sscottl 2196195534Sscottlstatic void 2197195534Sscottlscsi_scan_lun(struct cam_periph *periph, struct cam_path *path, 2198195534Sscottl cam_flags flags, union ccb *request_ccb) 2199195534Sscottl{ 2200195534Sscottl struct ccb_pathinq cpi; 2201195534Sscottl cam_status status; 2202195534Sscottl struct cam_path *new_path; 2203195534Sscottl struct cam_periph *old_periph; 2204195534Sscottl 2205203108Smav CAM_DEBUG(path, CAM_DEBUG_TRACE, ("scsi_scan_lun\n")); 2206195534Sscottl 2207203108Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 2208195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 2209195534Sscottl xpt_action((union ccb *)&cpi); 2210195534Sscottl 2211195534Sscottl if (cpi.ccb_h.status != CAM_REQ_CMP) { 2212195534Sscottl if (request_ccb != NULL) { 2213195534Sscottl request_ccb->ccb_h.status = cpi.ccb_h.status; 2214195534Sscottl xpt_done(request_ccb); 2215195534Sscottl } 2216195534Sscottl return; 2217195534Sscottl } 2218195534Sscottl 2219195534Sscottl if ((cpi.hba_misc & PIM_NOINITIATOR) != 0) { 2220195534Sscottl /* 2221195534Sscottl * Can't scan the bus on an adapter that 2222195534Sscottl * cannot perform the initiator role. 2223195534Sscottl */ 2224195534Sscottl if (request_ccb != NULL) { 2225195534Sscottl request_ccb->ccb_h.status = CAM_REQ_CMP; 2226195534Sscottl xpt_done(request_ccb); 2227195534Sscottl } 2228195534Sscottl return; 2229195534Sscottl } 2230195534Sscottl 2231195534Sscottl if (request_ccb == NULL) { 2232241455Smav request_ccb = xpt_alloc_ccb_nowait(); 2233195534Sscottl if (request_ccb == NULL) { 2234195688Semaste xpt_print(path, "scsi_scan_lun: can't allocate CCB, " 2235195534Sscottl "can't continue\n"); 2236195534Sscottl return; 2237195534Sscottl } 2238249468Smav status = xpt_create_path(&new_path, NULL, 2239195534Sscottl path->bus->path_id, 2240195534Sscottl path->target->target_id, 2241195534Sscottl path->device->lun_id); 2242195534Sscottl if (status != CAM_REQ_CMP) { 2243241455Smav xpt_print(path, "scsi_scan_lun: can't create path, " 2244195534Sscottl "can't continue\n"); 2245241455Smav xpt_free_ccb(request_ccb); 2246195534Sscottl return; 2247195534Sscottl } 2248203108Smav xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_XPT); 2249195534Sscottl request_ccb->ccb_h.cbfcnp = xptscandone; 2250195534Sscottl request_ccb->ccb_h.func_code = XPT_SCAN_LUN; 2251195534Sscottl request_ccb->crcn.flags = flags; 2252195534Sscottl } 2253195534Sscottl 2254195534Sscottl if ((old_periph = cam_periph_find(path, "probe")) != NULL) { 2255236228Smav if ((old_periph->flags & CAM_PERIPH_INVALID) == 0) { 2256236228Smav probe_softc *softc; 2257195534Sscottl 2258236228Smav softc = (probe_softc *)old_periph->softc; 2259236228Smav TAILQ_INSERT_TAIL(&softc->request_ccbs, 2260236228Smav &request_ccb->ccb_h, periph_links.tqe); 2261236228Smav } else { 2262236228Smav request_ccb->ccb_h.status = CAM_REQ_CMP_ERR; 2263236228Smav xpt_done(request_ccb); 2264236228Smav } 2265195534Sscottl } else { 2266195534Sscottl status = cam_periph_alloc(proberegister, NULL, probecleanup, 2267195534Sscottl probestart, "probe", 2268195534Sscottl CAM_PERIPH_BIO, 2269195534Sscottl request_ccb->ccb_h.path, NULL, 0, 2270195534Sscottl request_ccb); 2271195534Sscottl 2272195534Sscottl if (status != CAM_REQ_CMP) { 2273195688Semaste xpt_print(path, "scsi_scan_lun: cam_alloc_periph " 2274195534Sscottl "returned an error, can't continue probe\n"); 2275195534Sscottl request_ccb->ccb_h.status = status; 2276195534Sscottl xpt_done(request_ccb); 2277195534Sscottl } 2278195534Sscottl } 2279195534Sscottl} 2280195534Sscottl 2281195534Sscottlstatic void 2282195534Sscottlxptscandone(struct cam_periph *periph, union ccb *done_ccb) 2283195534Sscottl{ 2284241455Smav 2285241455Smav xpt_free_path(done_ccb->ccb_h.path); 2286241455Smav xpt_free_ccb(done_ccb); 2287195534Sscottl} 2288195534Sscottl 2289195534Sscottlstatic struct cam_ed * 2290195534Sscottlscsi_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id) 2291195534Sscottl{ 2292195534Sscottl struct cam_path path; 2293195534Sscottl struct scsi_quirk_entry *quirk; 2294195534Sscottl struct cam_ed *device; 2295195534Sscottl 2296195534Sscottl device = xpt_alloc_device(bus, target, lun_id); 2297195534Sscottl if (device == NULL) 2298195534Sscottl return (NULL); 2299195534Sscottl 2300195534Sscottl /* 2301195534Sscottl * Take the default quirk entry until we have inquiry 2302195534Sscottl * data and can determine a better quirk to use. 2303195534Sscottl */ 2304195534Sscottl quirk = &scsi_quirk_table[scsi_quirk_table_size - 1]; 2305195534Sscottl device->quirk = (void *)quirk; 2306195534Sscottl device->mintags = quirk->mintags; 2307195534Sscottl device->maxtags = quirk->maxtags; 2308195534Sscottl bzero(&device->inq_data, sizeof(device->inq_data)); 2309195534Sscottl device->inq_flags = 0; 2310195534Sscottl device->queue_flags = 0; 2311195534Sscottl device->serial_num = NULL; 2312195534Sscottl device->serial_num_len = 0; 2313216088Sken device->device_id = NULL; 2314216088Sken device->device_id_len = 0; 2315216088Sken device->supported_vpds = NULL; 2316216088Sken device->supported_vpds_len = 0; 2317195534Sscottl 2318195534Sscottl /* 2319195534Sscottl * XXX should be limited by number of CCBs this bus can 2320195534Sscottl * do. 2321195534Sscottl */ 2322195534Sscottl bus->sim->max_ccbs += device->ccbq.devq_openings; 2323195534Sscottl if (lun_id != CAM_LUN_WILDCARD) { 2324195534Sscottl xpt_compile_path(&path, 2325195534Sscottl NULL, 2326195534Sscottl bus->path_id, 2327195534Sscottl target->target_id, 2328195534Sscottl lun_id); 2329195534Sscottl scsi_devise_transport(&path); 2330195534Sscottl xpt_release_path(&path); 2331195534Sscottl } 2332195534Sscottl 2333195534Sscottl return (device); 2334195534Sscottl} 2335195534Sscottl 2336195534Sscottlstatic void 2337195534Sscottlscsi_devise_transport(struct cam_path *path) 2338195534Sscottl{ 2339195534Sscottl struct ccb_pathinq cpi; 2340195534Sscottl struct ccb_trans_settings cts; 2341195534Sscottl struct scsi_inquiry_data *inq_buf; 2342195534Sscottl 2343195534Sscottl /* Get transport information from the SIM */ 2344203108Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 2345195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 2346195534Sscottl xpt_action((union ccb *)&cpi); 2347195534Sscottl 2348195534Sscottl inq_buf = NULL; 2349195534Sscottl if ((path->device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0) 2350195534Sscottl inq_buf = &path->device->inq_data; 2351195534Sscottl path->device->protocol = PROTO_SCSI; 2352195534Sscottl path->device->protocol_version = 2353195534Sscottl inq_buf != NULL ? SID_ANSI_REV(inq_buf) : cpi.protocol_version; 2354195534Sscottl path->device->transport = cpi.transport; 2355195534Sscottl path->device->transport_version = cpi.transport_version; 2356195534Sscottl 2357195534Sscottl /* 2358195534Sscottl * Any device not using SPI3 features should 2359195534Sscottl * be considered SPI2 or lower. 2360195534Sscottl */ 2361195534Sscottl if (inq_buf != NULL) { 2362195534Sscottl if (path->device->transport == XPORT_SPI 2363195534Sscottl && (inq_buf->spi3data & SID_SPI_MASK) == 0 2364195534Sscottl && path->device->transport_version > 2) 2365195534Sscottl path->device->transport_version = 2; 2366195534Sscottl } else { 2367195534Sscottl struct cam_ed* otherdev; 2368195534Sscottl 2369195534Sscottl for (otherdev = TAILQ_FIRST(&path->target->ed_entries); 2370195534Sscottl otherdev != NULL; 2371195534Sscottl otherdev = TAILQ_NEXT(otherdev, links)) { 2372195534Sscottl if (otherdev != path->device) 2373195534Sscottl break; 2374195534Sscottl } 2375195534Sscottl 2376195534Sscottl if (otherdev != NULL) { 2377195534Sscottl /* 2378195534Sscottl * Initially assume the same versioning as 2379195534Sscottl * prior luns for this target. 2380195534Sscottl */ 2381195534Sscottl path->device->protocol_version = 2382195534Sscottl otherdev->protocol_version; 2383195534Sscottl path->device->transport_version = 2384195534Sscottl otherdev->transport_version; 2385195534Sscottl } else { 2386195534Sscottl /* Until we know better, opt for safty */ 2387195534Sscottl path->device->protocol_version = 2; 2388195534Sscottl if (path->device->transport == XPORT_SPI) 2389195534Sscottl path->device->transport_version = 2; 2390195534Sscottl else 2391195534Sscottl path->device->transport_version = 0; 2392195534Sscottl } 2393195534Sscottl } 2394195534Sscottl 2395195534Sscottl /* 2396195534Sscottl * XXX 2397195534Sscottl * For a device compliant with SPC-2 we should be able 2398195534Sscottl * to determine the transport version supported by 2399195534Sscottl * scrutinizing the version descriptors in the 2400195534Sscottl * inquiry buffer. 2401195534Sscottl */ 2402195534Sscottl 2403195534Sscottl /* Tell the controller what we think */ 2404203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 2405195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 2406195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 2407195534Sscottl cts.transport = path->device->transport; 2408195534Sscottl cts.transport_version = path->device->transport_version; 2409195534Sscottl cts.protocol = path->device->protocol; 2410195534Sscottl cts.protocol_version = path->device->protocol_version; 2411195534Sscottl cts.proto_specific.valid = 0; 2412195534Sscottl cts.xport_specific.valid = 0; 2413195534Sscottl xpt_action((union ccb *)&cts); 2414195534Sscottl} 2415195534Sscottl 2416195534Sscottlstatic void 2417223081Sgibbsscsi_dev_advinfo(union ccb *start_ccb) 2418216088Sken{ 2419216088Sken struct cam_ed *device; 2420223081Sgibbs struct ccb_dev_advinfo *cdai; 2421216088Sken off_t amt; 2422216088Sken 2423223448Swill start_ccb->ccb_h.status = CAM_REQ_INVALID; 2424216088Sken device = start_ccb->ccb_h.path->device; 2425223081Sgibbs cdai = &start_ccb->cdai; 2426223081Sgibbs switch(cdai->buftype) { 2427223081Sgibbs case CDAI_TYPE_SCSI_DEVID: 2428223081Sgibbs if (cdai->flags & CDAI_FLAG_STORE) 2429223448Swill return; 2430223081Sgibbs cdai->provsiz = device->device_id_len; 2431216088Sken if (device->device_id_len == 0) 2432216088Sken break; 2433216088Sken amt = device->device_id_len; 2434223081Sgibbs if (cdai->provsiz > cdai->bufsiz) 2435223081Sgibbs amt = cdai->bufsiz; 2436223081Sgibbs memcpy(cdai->buf, device->device_id, amt); 2437216088Sken break; 2438223081Sgibbs case CDAI_TYPE_SERIAL_NUM: 2439223081Sgibbs if (cdai->flags & CDAI_FLAG_STORE) 2440223448Swill return; 2441223081Sgibbs cdai->provsiz = device->serial_num_len; 2442223081Sgibbs if (device->serial_num_len == 0) 2443223081Sgibbs break; 2444223081Sgibbs amt = device->serial_num_len; 2445223081Sgibbs if (cdai->provsiz > cdai->bufsiz) 2446223081Sgibbs amt = cdai->bufsiz; 2447223081Sgibbs memcpy(cdai->buf, device->serial_num, amt); 2448223081Sgibbs break; 2449223081Sgibbs case CDAI_TYPE_PHYS_PATH: 2450223081Sgibbs if (cdai->flags & CDAI_FLAG_STORE) { 2451230590Sken if (device->physpath != NULL) { 2452223081Sgibbs free(device->physpath, M_CAMXPT); 2453230590Sken device->physpath = NULL; 2454230590Sken } 2455223081Sgibbs device->physpath_len = cdai->bufsiz; 2456223081Sgibbs /* Clear existing buffer if zero length */ 2457223081Sgibbs if (cdai->bufsiz == 0) 2458223081Sgibbs break; 2459223081Sgibbs device->physpath = malloc(cdai->bufsiz, M_CAMXPT, M_NOWAIT); 2460223081Sgibbs if (device->physpath == NULL) { 2461223081Sgibbs start_ccb->ccb_h.status = CAM_REQ_ABORTED; 2462223081Sgibbs return; 2463223081Sgibbs } 2464223081Sgibbs memcpy(device->physpath, cdai->buf, cdai->bufsiz); 2465223081Sgibbs } else { 2466223081Sgibbs cdai->provsiz = device->physpath_len; 2467223081Sgibbs if (device->physpath_len == 0) 2468223081Sgibbs break; 2469223081Sgibbs amt = device->physpath_len; 2470223081Sgibbs if (cdai->provsiz > cdai->bufsiz) 2471223081Sgibbs amt = cdai->bufsiz; 2472223081Sgibbs memcpy(cdai->buf, device->physpath, amt); 2473223081Sgibbs } 2474223081Sgibbs break; 2475230590Sken case CDAI_TYPE_RCAPLONG: 2476230590Sken if (cdai->flags & CDAI_FLAG_STORE) { 2477230590Sken if (device->rcap_buf != NULL) { 2478230590Sken free(device->rcap_buf, M_CAMXPT); 2479230590Sken device->rcap_buf = NULL; 2480230590Sken } 2481230590Sken 2482230590Sken device->rcap_len = cdai->bufsiz; 2483230590Sken /* Clear existing buffer if zero length */ 2484230590Sken if (cdai->bufsiz == 0) 2485230590Sken break; 2486230590Sken 2487230590Sken device->rcap_buf = malloc(cdai->bufsiz, M_CAMXPT, 2488230590Sken M_NOWAIT); 2489230590Sken if (device->rcap_buf == NULL) { 2490230590Sken start_ccb->ccb_h.status = CAM_REQ_ABORTED; 2491230590Sken return; 2492230590Sken } 2493230590Sken 2494230590Sken memcpy(device->rcap_buf, cdai->buf, cdai->bufsiz); 2495230590Sken } else { 2496230590Sken cdai->provsiz = device->rcap_len; 2497230590Sken if (device->rcap_len == 0) 2498230590Sken break; 2499230590Sken amt = device->rcap_len; 2500230590Sken if (cdai->provsiz > cdai->bufsiz) 2501230590Sken amt = cdai->bufsiz; 2502230590Sken memcpy(cdai->buf, device->rcap_buf, amt); 2503230590Sken } 2504230590Sken break; 2505216088Sken default: 2506223448Swill return; 2507216088Sken } 2508216088Sken start_ccb->ccb_h.status = CAM_REQ_CMP; 2509223081Sgibbs 2510223081Sgibbs if (cdai->flags & CDAI_FLAG_STORE) { 2511223081Sgibbs int owned; 2512223081Sgibbs 2513223081Sgibbs owned = mtx_owned(start_ccb->ccb_h.path->bus->sim->mtx); 2514223081Sgibbs if (owned == 0) 2515223081Sgibbs mtx_lock(start_ccb->ccb_h.path->bus->sim->mtx); 2516223081Sgibbs xpt_async(AC_ADVINFO_CHANGED, start_ccb->ccb_h.path, 2517223081Sgibbs (void *)(uintptr_t)cdai->buftype); 2518223081Sgibbs if (owned == 0) 2519223081Sgibbs mtx_unlock(start_ccb->ccb_h.path->bus->sim->mtx); 2520223081Sgibbs } 2521216088Sken} 2522216088Sken 2523216088Skenstatic void 2524195534Sscottlscsi_action(union ccb *start_ccb) 2525195534Sscottl{ 2526195534Sscottl 2527195534Sscottl switch (start_ccb->ccb_h.func_code) { 2528195534Sscottl case XPT_SET_TRAN_SETTINGS: 2529195534Sscottl { 2530195534Sscottl scsi_set_transfer_settings(&start_ccb->cts, 2531195534Sscottl start_ccb->ccb_h.path->device, 2532195534Sscottl /*async_update*/FALSE); 2533195534Sscottl break; 2534195534Sscottl } 2535195534Sscottl case XPT_SCAN_BUS: 2536208582Smjacob case XPT_SCAN_TGT: 2537195534Sscottl scsi_scan_bus(start_ccb->ccb_h.path->periph, start_ccb); 2538195534Sscottl break; 2539195534Sscottl case XPT_SCAN_LUN: 2540195534Sscottl scsi_scan_lun(start_ccb->ccb_h.path->periph, 2541195534Sscottl start_ccb->ccb_h.path, start_ccb->crcn.flags, 2542195534Sscottl start_ccb); 2543195534Sscottl break; 2544195534Sscottl case XPT_GET_TRAN_SETTINGS: 2545195534Sscottl { 2546195534Sscottl struct cam_sim *sim; 2547195534Sscottl 2548195534Sscottl sim = start_ccb->ccb_h.path->bus->sim; 2549195534Sscottl (*(sim->sim_action))(sim, start_ccb); 2550195534Sscottl break; 2551195534Sscottl } 2552223081Sgibbs case XPT_DEV_ADVINFO: 2553216088Sken { 2554223081Sgibbs scsi_dev_advinfo(start_ccb); 2555216088Sken break; 2556216088Sken } 2557195534Sscottl default: 2558195534Sscottl xpt_action_default(start_ccb); 2559195534Sscottl break; 2560195534Sscottl } 2561195534Sscottl} 2562195534Sscottl 2563195534Sscottlstatic void 2564195534Sscottlscsi_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device, 2565195534Sscottl int async_update) 2566195534Sscottl{ 2567195534Sscottl struct ccb_pathinq cpi; 2568195534Sscottl struct ccb_trans_settings cur_cts; 2569195534Sscottl struct ccb_trans_settings_scsi *scsi; 2570195534Sscottl struct ccb_trans_settings_scsi *cur_scsi; 2571195534Sscottl struct cam_sim *sim; 2572195534Sscottl struct scsi_inquiry_data *inq_data; 2573195534Sscottl 2574195534Sscottl if (device == NULL) { 2575195534Sscottl cts->ccb_h.status = CAM_PATH_INVALID; 2576195534Sscottl xpt_done((union ccb *)cts); 2577195534Sscottl return; 2578195534Sscottl } 2579195534Sscottl 2580195534Sscottl if (cts->protocol == PROTO_UNKNOWN 2581195534Sscottl || cts->protocol == PROTO_UNSPECIFIED) { 2582195534Sscottl cts->protocol = device->protocol; 2583195534Sscottl cts->protocol_version = device->protocol_version; 2584195534Sscottl } 2585195534Sscottl 2586195534Sscottl if (cts->protocol_version == PROTO_VERSION_UNKNOWN 2587195534Sscottl || cts->protocol_version == PROTO_VERSION_UNSPECIFIED) 2588195534Sscottl cts->protocol_version = device->protocol_version; 2589195534Sscottl 2590195534Sscottl if (cts->protocol != device->protocol) { 2591195534Sscottl xpt_print(cts->ccb_h.path, "Uninitialized Protocol %x:%x?\n", 2592195534Sscottl cts->protocol, device->protocol); 2593195534Sscottl cts->protocol = device->protocol; 2594195534Sscottl } 2595195534Sscottl 2596195534Sscottl if (cts->protocol_version > device->protocol_version) { 2597195534Sscottl if (bootverbose) { 2598195534Sscottl xpt_print(cts->ccb_h.path, "Down reving Protocol " 2599195534Sscottl "Version from %d to %d?\n", cts->protocol_version, 2600195534Sscottl device->protocol_version); 2601195534Sscottl } 2602195534Sscottl cts->protocol_version = device->protocol_version; 2603195534Sscottl } 2604195534Sscottl 2605195534Sscottl if (cts->transport == XPORT_UNKNOWN 2606195534Sscottl || cts->transport == XPORT_UNSPECIFIED) { 2607195534Sscottl cts->transport = device->transport; 2608195534Sscottl cts->transport_version = device->transport_version; 2609195534Sscottl } 2610195534Sscottl 2611195534Sscottl if (cts->transport_version == XPORT_VERSION_UNKNOWN 2612195534Sscottl || cts->transport_version == XPORT_VERSION_UNSPECIFIED) 2613195534Sscottl cts->transport_version = device->transport_version; 2614195534Sscottl 2615195534Sscottl if (cts->transport != device->transport) { 2616195534Sscottl xpt_print(cts->ccb_h.path, "Uninitialized Transport %x:%x?\n", 2617195534Sscottl cts->transport, device->transport); 2618195534Sscottl cts->transport = device->transport; 2619195534Sscottl } 2620195534Sscottl 2621195534Sscottl if (cts->transport_version > device->transport_version) { 2622195534Sscottl if (bootverbose) { 2623195534Sscottl xpt_print(cts->ccb_h.path, "Down reving Transport " 2624195534Sscottl "Version from %d to %d?\n", cts->transport_version, 2625195534Sscottl device->transport_version); 2626195534Sscottl } 2627195534Sscottl cts->transport_version = device->transport_version; 2628195534Sscottl } 2629195534Sscottl 2630195534Sscottl sim = cts->ccb_h.path->bus->sim; 2631195534Sscottl 2632195534Sscottl /* 2633195534Sscottl * Nothing more of interest to do unless 2634195534Sscottl * this is a device connected via the 2635195534Sscottl * SCSI protocol. 2636195534Sscottl */ 2637195534Sscottl if (cts->protocol != PROTO_SCSI) { 2638195534Sscottl if (async_update == FALSE) 2639195534Sscottl (*(sim->sim_action))(sim, (union ccb *)cts); 2640195534Sscottl return; 2641195534Sscottl } 2642195534Sscottl 2643195534Sscottl inq_data = &device->inq_data; 2644195534Sscottl scsi = &cts->proto_specific.scsi; 2645203108Smav xpt_setup_ccb(&cpi.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NONE); 2646195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 2647195534Sscottl xpt_action((union ccb *)&cpi); 2648195534Sscottl 2649195534Sscottl /* SCSI specific sanity checking */ 2650195534Sscottl if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0 2651195534Sscottl || (INQ_DATA_TQ_ENABLED(inq_data)) == 0 2652195534Sscottl || (device->queue_flags & SCP_QUEUE_DQUE) != 0 2653195534Sscottl || (device->mintags == 0)) { 2654195534Sscottl /* 2655195534Sscottl * Can't tag on hardware that doesn't support tags, 2656195534Sscottl * doesn't have it enabled, or has broken tag support. 2657195534Sscottl */ 2658195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 2659195534Sscottl } 2660195534Sscottl 2661195534Sscottl if (async_update == FALSE) { 2662195534Sscottl /* 2663195534Sscottl * Perform sanity checking against what the 2664195534Sscottl * controller and device can do. 2665195534Sscottl */ 2666203108Smav xpt_setup_ccb(&cur_cts.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NONE); 2667195534Sscottl cur_cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 2668195534Sscottl cur_cts.type = cts->type; 2669195534Sscottl xpt_action((union ccb *)&cur_cts); 2670252382Sscottl if (cam_ccb_status((union ccb *)&cur_cts) != CAM_REQ_CMP) { 2671195534Sscottl return; 2672195534Sscottl } 2673195534Sscottl cur_scsi = &cur_cts.proto_specific.scsi; 2674195534Sscottl if ((scsi->valid & CTS_SCSI_VALID_TQ) == 0) { 2675195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 2676195534Sscottl scsi->flags |= cur_scsi->flags & CTS_SCSI_FLAGS_TAG_ENB; 2677195534Sscottl } 2678195534Sscottl if ((cur_scsi->valid & CTS_SCSI_VALID_TQ) == 0) 2679195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 2680195534Sscottl } 2681195534Sscottl 2682195534Sscottl /* SPI specific sanity checking */ 2683195534Sscottl if (cts->transport == XPORT_SPI && async_update == FALSE) { 2684195534Sscottl u_int spi3caps; 2685195534Sscottl struct ccb_trans_settings_spi *spi; 2686195534Sscottl struct ccb_trans_settings_spi *cur_spi; 2687195534Sscottl 2688195534Sscottl spi = &cts->xport_specific.spi; 2689195534Sscottl 2690195534Sscottl cur_spi = &cur_cts.xport_specific.spi; 2691195534Sscottl 2692195534Sscottl /* Fill in any gaps in what the user gave us */ 2693195534Sscottl if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) 2694195534Sscottl spi->sync_period = cur_spi->sync_period; 2695195534Sscottl if ((cur_spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) 2696195534Sscottl spi->sync_period = 0; 2697195534Sscottl if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0) 2698195534Sscottl spi->sync_offset = cur_spi->sync_offset; 2699195534Sscottl if ((cur_spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0) 2700195534Sscottl spi->sync_offset = 0; 2701195534Sscottl if ((spi->valid & CTS_SPI_VALID_PPR_OPTIONS) == 0) 2702195534Sscottl spi->ppr_options = cur_spi->ppr_options; 2703195534Sscottl if ((cur_spi->valid & CTS_SPI_VALID_PPR_OPTIONS) == 0) 2704195534Sscottl spi->ppr_options = 0; 2705195534Sscottl if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) == 0) 2706195534Sscottl spi->bus_width = cur_spi->bus_width; 2707195534Sscottl if ((cur_spi->valid & CTS_SPI_VALID_BUS_WIDTH) == 0) 2708195534Sscottl spi->bus_width = 0; 2709195534Sscottl if ((spi->valid & CTS_SPI_VALID_DISC) == 0) { 2710195534Sscottl spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; 2711195534Sscottl spi->flags |= cur_spi->flags & CTS_SPI_FLAGS_DISC_ENB; 2712195534Sscottl } 2713195534Sscottl if ((cur_spi->valid & CTS_SPI_VALID_DISC) == 0) 2714195534Sscottl spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; 2715195534Sscottl if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0 2716195534Sscottl && (inq_data->flags & SID_Sync) == 0 2717195534Sscottl && cts->type == CTS_TYPE_CURRENT_SETTINGS) 2718195534Sscottl || ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0)) { 2719195534Sscottl /* Force async */ 2720195534Sscottl spi->sync_period = 0; 2721195534Sscottl spi->sync_offset = 0; 2722195534Sscottl } 2723195534Sscottl 2724195534Sscottl switch (spi->bus_width) { 2725195534Sscottl case MSG_EXT_WDTR_BUS_32_BIT: 2726195534Sscottl if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) == 0 2727195534Sscottl || (inq_data->flags & SID_WBus32) != 0 2728195534Sscottl || cts->type == CTS_TYPE_USER_SETTINGS) 2729195534Sscottl && (cpi.hba_inquiry & PI_WIDE_32) != 0) 2730195534Sscottl break; 2731195534Sscottl /* Fall Through to 16-bit */ 2732195534Sscottl case MSG_EXT_WDTR_BUS_16_BIT: 2733195534Sscottl if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) == 0 2734195534Sscottl || (inq_data->flags & SID_WBus16) != 0 2735195534Sscottl || cts->type == CTS_TYPE_USER_SETTINGS) 2736195534Sscottl && (cpi.hba_inquiry & PI_WIDE_16) != 0) { 2737195534Sscottl spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT; 2738195534Sscottl break; 2739195534Sscottl } 2740195534Sscottl /* Fall Through to 8-bit */ 2741195534Sscottl default: /* New bus width?? */ 2742195534Sscottl case MSG_EXT_WDTR_BUS_8_BIT: 2743195534Sscottl /* All targets can do this */ 2744195534Sscottl spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT; 2745195534Sscottl break; 2746195534Sscottl } 2747195534Sscottl 2748195534Sscottl spi3caps = cpi.xport_specific.spi.ppr_options; 2749195534Sscottl if ((device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0 2750195534Sscottl && cts->type == CTS_TYPE_CURRENT_SETTINGS) 2751195534Sscottl spi3caps &= inq_data->spi3data; 2752195534Sscottl 2753195534Sscottl if ((spi3caps & SID_SPI_CLOCK_DT) == 0) 2754195534Sscottl spi->ppr_options &= ~MSG_EXT_PPR_DT_REQ; 2755195534Sscottl 2756195534Sscottl if ((spi3caps & SID_SPI_IUS) == 0) 2757195534Sscottl spi->ppr_options &= ~MSG_EXT_PPR_IU_REQ; 2758195534Sscottl 2759195534Sscottl if ((spi3caps & SID_SPI_QAS) == 0) 2760195534Sscottl spi->ppr_options &= ~MSG_EXT_PPR_QAS_REQ; 2761195534Sscottl 2762195534Sscottl /* No SPI Transfer settings are allowed unless we are wide */ 2763195534Sscottl if (spi->bus_width == 0) 2764195534Sscottl spi->ppr_options = 0; 2765195534Sscottl 2766195534Sscottl if ((spi->valid & CTS_SPI_VALID_DISC) 2767195534Sscottl && ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) == 0)) { 2768195534Sscottl /* 2769195534Sscottl * Can't tag queue without disconnection. 2770195534Sscottl */ 2771195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 2772195534Sscottl scsi->valid |= CTS_SCSI_VALID_TQ; 2773195534Sscottl } 2774195534Sscottl 2775195534Sscottl /* 2776195534Sscottl * If we are currently performing tagged transactions to 2777195534Sscottl * this device and want to change its negotiation parameters, 2778195534Sscottl * go non-tagged for a bit to give the controller a chance to 2779195534Sscottl * negotiate unhampered by tag messages. 2780195534Sscottl */ 2781195534Sscottl if (cts->type == CTS_TYPE_CURRENT_SETTINGS 2782195534Sscottl && (device->inq_flags & SID_CmdQue) != 0 2783195534Sscottl && (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0 2784195534Sscottl && (spi->flags & (CTS_SPI_VALID_SYNC_RATE| 2785195534Sscottl CTS_SPI_VALID_SYNC_OFFSET| 2786195534Sscottl CTS_SPI_VALID_BUS_WIDTH)) != 0) 2787195534Sscottl scsi_toggle_tags(cts->ccb_h.path); 2788195534Sscottl } 2789195534Sscottl 2790195534Sscottl if (cts->type == CTS_TYPE_CURRENT_SETTINGS 2791195534Sscottl && (scsi->valid & CTS_SCSI_VALID_TQ) != 0) { 2792195534Sscottl int device_tagenb; 2793195534Sscottl 2794195534Sscottl /* 2795195534Sscottl * If we are transitioning from tags to no-tags or 2796195534Sscottl * vice-versa, we need to carefully freeze and restart 2797195534Sscottl * the queue so that we don't overlap tagged and non-tagged 2798195534Sscottl * commands. We also temporarily stop tags if there is 2799195534Sscottl * a change in transfer negotiation settings to allow 2800195534Sscottl * "tag-less" negotiation. 2801195534Sscottl */ 2802195534Sscottl if ((device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 2803195534Sscottl || (device->inq_flags & SID_CmdQue) != 0) 2804195534Sscottl device_tagenb = TRUE; 2805195534Sscottl else 2806195534Sscottl device_tagenb = FALSE; 2807195534Sscottl 2808195534Sscottl if (((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0 2809195534Sscottl && device_tagenb == FALSE) 2810195534Sscottl || ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) == 0 2811195534Sscottl && device_tagenb == TRUE)) { 2812195534Sscottl 2813195534Sscottl if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) { 2814195534Sscottl /* 2815195534Sscottl * Delay change to use tags until after a 2816195534Sscottl * few commands have gone to this device so 2817195534Sscottl * the controller has time to perform transfer 2818195534Sscottl * negotiations without tagged messages getting 2819195534Sscottl * in the way. 2820195534Sscottl */ 2821195534Sscottl device->tag_delay_count = CAM_TAG_DELAY_COUNT; 2822195534Sscottl device->flags |= CAM_DEV_TAG_AFTER_COUNT; 2823195534Sscottl } else { 2824199178Smav xpt_stop_tags(cts->ccb_h.path); 2825195534Sscottl } 2826195534Sscottl } 2827195534Sscottl } 2828195534Sscottl if (async_update == FALSE) 2829195534Sscottl (*(sim->sim_action))(sim, (union ccb *)cts); 2830195534Sscottl} 2831195534Sscottl 2832195534Sscottlstatic void 2833195534Sscottlscsi_toggle_tags(struct cam_path *path) 2834195534Sscottl{ 2835195534Sscottl struct cam_ed *dev; 2836195534Sscottl 2837195534Sscottl /* 2838195534Sscottl * Give controllers a chance to renegotiate 2839195534Sscottl * before starting tag operations. We 2840195534Sscottl * "toggle" tagged queuing off then on 2841195534Sscottl * which causes the tag enable command delay 2842195534Sscottl * counter to come into effect. 2843195534Sscottl */ 2844195534Sscottl dev = path->device; 2845195534Sscottl if ((dev->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 2846195534Sscottl || ((dev->inq_flags & SID_CmdQue) != 0 2847195534Sscottl && (dev->inq_flags & (SID_Sync|SID_WBus16|SID_WBus32)) != 0)) { 2848195534Sscottl struct ccb_trans_settings cts; 2849195534Sscottl 2850203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 2851195534Sscottl cts.protocol = PROTO_SCSI; 2852195534Sscottl cts.protocol_version = PROTO_VERSION_UNSPECIFIED; 2853195534Sscottl cts.transport = XPORT_UNSPECIFIED; 2854195534Sscottl cts.transport_version = XPORT_VERSION_UNSPECIFIED; 2855195534Sscottl cts.proto_specific.scsi.flags = 0; 2856195534Sscottl cts.proto_specific.scsi.valid = CTS_SCSI_VALID_TQ; 2857195534Sscottl scsi_set_transfer_settings(&cts, path->device, 2858195534Sscottl /*async_update*/TRUE); 2859195534Sscottl cts.proto_specific.scsi.flags = CTS_SCSI_FLAGS_TAG_ENB; 2860195534Sscottl scsi_set_transfer_settings(&cts, path->device, 2861195534Sscottl /*async_update*/TRUE); 2862195534Sscottl } 2863195534Sscottl} 2864195534Sscottl 2865195534Sscottl/* 2866195534Sscottl * Handle any per-device event notifications that require action by the XPT. 2867195534Sscottl */ 2868195534Sscottlstatic void 2869195534Sscottlscsi_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target, 2870195534Sscottl struct cam_ed *device, void *async_arg) 2871195534Sscottl{ 2872195534Sscottl cam_status status; 2873195534Sscottl struct cam_path newpath; 2874195534Sscottl 2875195534Sscottl /* 2876195534Sscottl * We only need to handle events for real devices. 2877195534Sscottl */ 2878195534Sscottl if (target->target_id == CAM_TARGET_WILDCARD 2879195534Sscottl || device->lun_id == CAM_LUN_WILDCARD) 2880195534Sscottl return; 2881195534Sscottl 2882195534Sscottl /* 2883195534Sscottl * We need our own path with wildcards expanded to 2884195534Sscottl * handle certain types of events. 2885195534Sscottl */ 2886195534Sscottl if ((async_code == AC_SENT_BDR) 2887195534Sscottl || (async_code == AC_BUS_RESET) 2888195534Sscottl || (async_code == AC_INQ_CHANGED)) 2889195534Sscottl status = xpt_compile_path(&newpath, NULL, 2890195534Sscottl bus->path_id, 2891195534Sscottl target->target_id, 2892195534Sscottl device->lun_id); 2893195534Sscottl else 2894195534Sscottl status = CAM_REQ_CMP_ERR; 2895195534Sscottl 2896195534Sscottl if (status == CAM_REQ_CMP) { 2897195534Sscottl 2898195534Sscottl /* 2899195534Sscottl * Allow transfer negotiation to occur in a 2900203108Smav * tag free environment and after settle delay. 2901195534Sscottl */ 2902195534Sscottl if (async_code == AC_SENT_BDR 2903203108Smav || async_code == AC_BUS_RESET) { 2904203108Smav cam_freeze_devq(&newpath); 2905203108Smav cam_release_devq(&newpath, 2906203108Smav RELSIM_RELEASE_AFTER_TIMEOUT, 2907203108Smav /*reduction*/0, 2908203108Smav /*timeout*/scsi_delay, 2909203108Smav /*getcount_only*/0); 2910195534Sscottl scsi_toggle_tags(&newpath); 2911203108Smav } 2912195534Sscottl 2913195534Sscottl if (async_code == AC_INQ_CHANGED) { 2914195534Sscottl /* 2915195534Sscottl * We've sent a start unit command, or 2916195534Sscottl * something similar to a device that 2917195534Sscottl * may have caused its inquiry data to 2918195534Sscottl * change. So we re-scan the device to 2919195534Sscottl * refresh the inquiry data for it. 2920195534Sscottl */ 2921195534Sscottl scsi_scan_lun(newpath.periph, &newpath, 2922195534Sscottl CAM_EXPECT_INQ_CHANGE, NULL); 2923195534Sscottl } 2924195534Sscottl xpt_release_path(&newpath); 2925198748Smav } else if (async_code == AC_LOST_DEVICE && 2926198748Smav (device->flags & CAM_DEV_UNCONFIGURED) == 0) { 2927195534Sscottl device->flags |= CAM_DEV_UNCONFIGURED; 2928198748Smav xpt_release_device(device); 2929195534Sscottl } else if (async_code == AC_TRANSFER_NEG) { 2930195534Sscottl struct ccb_trans_settings *settings; 2931195534Sscottl 2932195534Sscottl settings = (struct ccb_trans_settings *)async_arg; 2933195534Sscottl scsi_set_transfer_settings(settings, device, 2934195534Sscottl /*async_update*/TRUE); 2935195534Sscottl } 2936195534Sscottl} 2937195534Sscottl 2938204220Smavstatic void 2939204220Smavscsi_announce_periph(struct cam_periph *periph) 2940204220Smav{ 2941204220Smav struct ccb_pathinq cpi; 2942204220Smav struct ccb_trans_settings cts; 2943204220Smav struct cam_path *path = periph->path; 2944204220Smav u_int speed; 2945204220Smav u_int freq; 2946204220Smav u_int mb; 2947204220Smav 2948204220Smav mtx_assert(periph->sim->mtx, MA_OWNED); 2949204220Smav 2950204220Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); 2951204220Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 2952204220Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 2953204220Smav xpt_action((union ccb*)&cts); 2954252382Sscottl if (cam_ccb_status((union ccb *)&cts) != CAM_REQ_CMP) 2955204220Smav return; 2956204220Smav /* Ask the SIM for its base transfer speed */ 2957204220Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL); 2958204220Smav cpi.ccb_h.func_code = XPT_PATH_INQ; 2959204220Smav xpt_action((union ccb *)&cpi); 2960204220Smav /* Report connection speed */ 2961204220Smav speed = cpi.base_transfer_speed; 2962204220Smav freq = 0; 2963204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SPI) { 2964204220Smav struct ccb_trans_settings_spi *spi = 2965204220Smav &cts.xport_specific.spi; 2966204220Smav 2967204220Smav if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0 2968204220Smav && spi->sync_offset != 0) { 2969204220Smav freq = scsi_calc_syncsrate(spi->sync_period); 2970204220Smav speed = freq; 2971204220Smav } 2972204220Smav if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) 2973204220Smav speed *= (0x01 << spi->bus_width); 2974204220Smav } 2975204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_FC) { 2976204220Smav struct ccb_trans_settings_fc *fc = 2977204220Smav &cts.xport_specific.fc; 2978204220Smav 2979204220Smav if (fc->valid & CTS_FC_VALID_SPEED) 2980204220Smav speed = fc->bitrate; 2981204220Smav } 2982204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SAS) { 2983204220Smav struct ccb_trans_settings_sas *sas = 2984204220Smav &cts.xport_specific.sas; 2985204220Smav 2986204220Smav if (sas->valid & CTS_SAS_VALID_SPEED) 2987204220Smav speed = sas->bitrate; 2988204220Smav } 2989204220Smav mb = speed / 1000; 2990204220Smav if (mb > 0) 2991204220Smav printf("%s%d: %d.%03dMB/s transfers", 2992204220Smav periph->periph_name, periph->unit_number, 2993204220Smav mb, speed % 1000); 2994204220Smav else 2995204220Smav printf("%s%d: %dKB/s transfers", periph->periph_name, 2996204220Smav periph->unit_number, speed); 2997204220Smav /* Report additional information about SPI connections */ 2998204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SPI) { 2999204220Smav struct ccb_trans_settings_spi *spi; 3000204220Smav 3001204220Smav spi = &cts.xport_specific.spi; 3002204220Smav if (freq != 0) { 3003204220Smav printf(" (%d.%03dMHz%s, offset %d", freq / 1000, 3004204220Smav freq % 1000, 3005204220Smav (spi->ppr_options & MSG_EXT_PPR_DT_REQ) != 0 3006204220Smav ? " DT" : "", 3007204220Smav spi->sync_offset); 3008204220Smav } 3009204220Smav if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0 3010204220Smav && spi->bus_width > 0) { 3011204220Smav if (freq != 0) { 3012204220Smav printf(", "); 3013204220Smav } else { 3014204220Smav printf(" ("); 3015204220Smav } 3016204220Smav printf("%dbit)", 8 * (0x01 << spi->bus_width)); 3017204220Smav } else if (freq != 0) { 3018204220Smav printf(")"); 3019204220Smav } 3020204220Smav } 3021204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_FC) { 3022204220Smav struct ccb_trans_settings_fc *fc; 3023204220Smav 3024204220Smav fc = &cts.xport_specific.fc; 3025204220Smav if (fc->valid & CTS_FC_VALID_WWNN) 3026204220Smav printf(" WWNN 0x%llx", (long long) fc->wwnn); 3027204220Smav if (fc->valid & CTS_FC_VALID_WWPN) 3028204220Smav printf(" WWPN 0x%llx", (long long) fc->wwpn); 3029204220Smav if (fc->valid & CTS_FC_VALID_PORT) 3030204220Smav printf(" PortID 0x%x", fc->port); 3031204220Smav } 3032204220Smav printf("\n"); 3033204220Smav} 3034204220Smav 3035