scsi_xpt.c revision 256843
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: head/sys/cam/scsi/scsi_xpt.c 256843 2013-10-21 12:00:26Z mav $"); 32195534Sscottl 33195534Sscottl#include <sys/param.h> 34195534Sscottl#include <sys/bus.h> 35195534Sscottl#include <sys/systm.h> 36195534Sscottl#include <sys/types.h> 37195534Sscottl#include <sys/malloc.h> 38195534Sscottl#include <sys/kernel.h> 39195534Sscottl#include <sys/time.h> 40195534Sscottl#include <sys/conf.h> 41195534Sscottl#include <sys/fcntl.h> 42195534Sscottl#include <sys/md5.h> 43195534Sscottl#include <sys/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, 580256843Smav struct cam_path *path, 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")); 642256843Smav scsi_devise_transport(periph->path); 643195534Sscottl 644195534Sscottl /* 645195534Sscottl * Ensure we've waited at least a bus settle 646195534Sscottl * delay before attempting to probe the device. 647195534Sscottl * For HBAs that don't do bus resets, this won't make a difference. 648195534Sscottl */ 649195534Sscottl cam_periph_freeze_after_event(periph, &periph->path->bus->last_reset, 650195534Sscottl scsi_delay); 651195534Sscottl probeschedule(periph); 652195534Sscottl return(CAM_REQ_CMP); 653195534Sscottl} 654195534Sscottl 655195534Sscottlstatic void 656195534Sscottlprobeschedule(struct cam_periph *periph) 657195534Sscottl{ 658195534Sscottl struct ccb_pathinq cpi; 659195534Sscottl union ccb *ccb; 660195534Sscottl probe_softc *softc; 661195534Sscottl 662195534Sscottl softc = (probe_softc *)periph->softc; 663195534Sscottl ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs); 664195534Sscottl 665203108Smav xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NONE); 666195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 667195534Sscottl xpt_action((union ccb *)&cpi); 668195534Sscottl 669195534Sscottl /* 670195534Sscottl * If a device has gone away and another device, or the same one, 671195534Sscottl * is back in the same place, it should have a unit attention 672195534Sscottl * condition pending. It will not report the unit attention in 673195534Sscottl * response to an inquiry, which may leave invalid transfer 674195534Sscottl * negotiations in effect. The TUR will reveal the unit attention 675195534Sscottl * condition. Only send the TUR for lun 0, since some devices 676195534Sscottl * will get confused by commands other than inquiry to non-existent 677195534Sscottl * luns. If you think a device has gone away start your scan from 678195534Sscottl * lun 0. This will insure that any bogus transfer settings are 679195534Sscottl * invalidated. 680195534Sscottl * 681195534Sscottl * If we haven't seen the device before and the controller supports 682195534Sscottl * some kind of transfer negotiation, negotiate with the first 683195534Sscottl * sent command if no bus reset was performed at startup. This 684195534Sscottl * ensures that the device is not confused by transfer negotiation 685195534Sscottl * settings left over by loader or BIOS action. 686195534Sscottl */ 687195534Sscottl if (((ccb->ccb_h.path->device->flags & CAM_DEV_UNCONFIGURED) == 0) 688195534Sscottl && (ccb->ccb_h.target_lun == 0)) { 689195534Sscottl PROBE_SET_ACTION(softc, PROBE_TUR); 690195534Sscottl } else if ((cpi.hba_inquiry & (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE)) != 0 691195534Sscottl && (cpi.hba_misc & PIM_NOBUSRESET) != 0) { 692195534Sscottl proberequestdefaultnegotiation(periph); 693195534Sscottl PROBE_SET_ACTION(softc, PROBE_INQUIRY); 694195534Sscottl } else { 695195534Sscottl PROBE_SET_ACTION(softc, PROBE_INQUIRY); 696195534Sscottl } 697195534Sscottl 698195534Sscottl if (ccb->crcn.flags & CAM_EXPECT_INQ_CHANGE) 699195534Sscottl softc->flags |= PROBE_NO_ANNOUNCE; 700195534Sscottl else 701195534Sscottl softc->flags &= ~PROBE_NO_ANNOUNCE; 702195534Sscottl 703203108Smav xpt_schedule(periph, CAM_PRIORITY_XPT); 704195534Sscottl} 705195534Sscottl 706195534Sscottlstatic void 707195534Sscottlprobestart(struct cam_periph *periph, union ccb *start_ccb) 708195534Sscottl{ 709195534Sscottl /* Probe the device that our peripheral driver points to */ 710195534Sscottl struct ccb_scsiio *csio; 711195534Sscottl probe_softc *softc; 712195534Sscottl 713195534Sscottl CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probestart\n")); 714195534Sscottl 715195534Sscottl softc = (probe_softc *)periph->softc; 716195534Sscottl csio = &start_ccb->csio; 717208911Smjacobagain: 718195534Sscottl 719195534Sscottl switch (softc->action) { 720195534Sscottl case PROBE_TUR: 721195534Sscottl case PROBE_TUR_FOR_NEGOTIATION: 722195534Sscottl case PROBE_DV_EXIT: 723195534Sscottl { 724195534Sscottl scsi_test_unit_ready(csio, 725236814Smav /*retries*/4, 726195534Sscottl probedone, 727195534Sscottl MSG_SIMPLE_Q_TAG, 728195534Sscottl SSD_FULL_SIZE, 729195534Sscottl /*timeout*/60000); 730195534Sscottl break; 731195534Sscottl } 732195534Sscottl case PROBE_INQUIRY: 733195534Sscottl case PROBE_FULL_INQUIRY: 734195534Sscottl case PROBE_INQUIRY_BASIC_DV1: 735195534Sscottl case PROBE_INQUIRY_BASIC_DV2: 736195534Sscottl { 737195534Sscottl u_int inquiry_len; 738195534Sscottl struct scsi_inquiry_data *inq_buf; 739195534Sscottl 740195534Sscottl inq_buf = &periph->path->device->inq_data; 741195534Sscottl 742195534Sscottl /* 743195534Sscottl * If the device is currently configured, we calculate an 744195534Sscottl * MD5 checksum of the inquiry data, and if the serial number 745195534Sscottl * length is greater than 0, add the serial number data 746195534Sscottl * into the checksum as well. Once the inquiry and the 747195534Sscottl * serial number check finish, we attempt to figure out 748195534Sscottl * whether we still have the same device. 749195534Sscottl */ 750195534Sscottl if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) { 751195534Sscottl 752195534Sscottl MD5Init(&softc->context); 753195534Sscottl MD5Update(&softc->context, (unsigned char *)inq_buf, 754195534Sscottl sizeof(struct scsi_inquiry_data)); 755195534Sscottl softc->flags |= PROBE_INQUIRY_CKSUM; 756195534Sscottl if (periph->path->device->serial_num_len > 0) { 757195534Sscottl MD5Update(&softc->context, 758195534Sscottl periph->path->device->serial_num, 759195534Sscottl periph->path->device->serial_num_len); 760195534Sscottl softc->flags |= PROBE_SERIAL_CKSUM; 761195534Sscottl } 762195534Sscottl MD5Final(softc->digest, &softc->context); 763195534Sscottl } 764195534Sscottl 765195534Sscottl if (softc->action == PROBE_INQUIRY) 766195534Sscottl inquiry_len = SHORT_INQUIRY_LENGTH; 767195534Sscottl else 768195534Sscottl inquiry_len = SID_ADDITIONAL_LENGTH(inq_buf); 769195534Sscottl 770195534Sscottl /* 771195534Sscottl * Some parallel SCSI devices fail to send an 772195534Sscottl * ignore wide residue message when dealing with 773195534Sscottl * odd length inquiry requests. Round up to be 774195534Sscottl * safe. 775195534Sscottl */ 776195534Sscottl inquiry_len = roundup2(inquiry_len, 2); 777195534Sscottl 778195534Sscottl if (softc->action == PROBE_INQUIRY_BASIC_DV1 779195534Sscottl || softc->action == PROBE_INQUIRY_BASIC_DV2) { 780195534Sscottl inq_buf = malloc(inquiry_len, M_CAMXPT, M_NOWAIT); 781195534Sscottl } 782195534Sscottl if (inq_buf == NULL) { 783195534Sscottl xpt_print(periph->path, "malloc failure- skipping Basic" 784195534Sscottl "Domain Validation\n"); 785195534Sscottl PROBE_SET_ACTION(softc, PROBE_DV_EXIT); 786195534Sscottl scsi_test_unit_ready(csio, 787195534Sscottl /*retries*/4, 788195534Sscottl probedone, 789195534Sscottl MSG_SIMPLE_Q_TAG, 790195534Sscottl SSD_FULL_SIZE, 791195534Sscottl /*timeout*/60000); 792195534Sscottl break; 793195534Sscottl } 794195534Sscottl scsi_inquiry(csio, 795195534Sscottl /*retries*/4, 796195534Sscottl probedone, 797195534Sscottl MSG_SIMPLE_Q_TAG, 798195534Sscottl (u_int8_t *)inq_buf, 799195534Sscottl inquiry_len, 800195534Sscottl /*evpd*/FALSE, 801195534Sscottl /*page_code*/0, 802195534Sscottl SSD_MIN_SIZE, 803195534Sscottl /*timeout*/60 * 1000); 804195534Sscottl break; 805195534Sscottl } 806208911Smjacob case PROBE_REPORT_LUNS: 807208911Smjacob { 808208911Smjacob void *rp; 809208911Smjacob 810208911Smjacob rp = malloc(periph->path->target->rpl_size, 811208911Smjacob M_CAMXPT, M_NOWAIT | M_ZERO); 812208911Smjacob if (rp == NULL) { 813208911Smjacob struct scsi_inquiry_data *inq_buf; 814208911Smjacob inq_buf = &periph->path->device->inq_data; 815208911Smjacob xpt_print(periph->path, 816208911Smjacob "Unable to alloc report luns storage\n"); 817208911Smjacob if (INQ_DATA_TQ_ENABLED(inq_buf)) 818208911Smjacob PROBE_SET_ACTION(softc, PROBE_MODE_SENSE); 819208911Smjacob else 820216088Sken PROBE_SET_ACTION(softc, 821216088Sken PROBE_SUPPORTED_VPD_LIST); 822208911Smjacob goto again; 823208911Smjacob } 824208911Smjacob scsi_report_luns(csio, 5, probedone, MSG_SIMPLE_Q_TAG, 825208911Smjacob RPL_REPORT_DEFAULT, rp, periph->path->target->rpl_size, 826208911Smjacob SSD_FULL_SIZE, 60000); break; 827208911Smjacob break; 828208911Smjacob } 829195534Sscottl case PROBE_MODE_SENSE: 830195534Sscottl { 831195534Sscottl void *mode_buf; 832195534Sscottl int mode_buf_len; 833195534Sscottl 834195534Sscottl mode_buf_len = sizeof(struct scsi_mode_header_6) 835195534Sscottl + sizeof(struct scsi_mode_blk_desc) 836195534Sscottl + sizeof(struct scsi_control_page); 837195534Sscottl mode_buf = malloc(mode_buf_len, M_CAMXPT, M_NOWAIT); 838195534Sscottl if (mode_buf != NULL) { 839195534Sscottl scsi_mode_sense(csio, 840195534Sscottl /*retries*/4, 841195534Sscottl probedone, 842195534Sscottl MSG_SIMPLE_Q_TAG, 843195534Sscottl /*dbd*/FALSE, 844195534Sscottl SMS_PAGE_CTRL_CURRENT, 845195534Sscottl SMS_CONTROL_MODE_PAGE, 846195534Sscottl mode_buf, 847195534Sscottl mode_buf_len, 848195534Sscottl SSD_FULL_SIZE, 849195534Sscottl /*timeout*/60000); 850195534Sscottl break; 851195534Sscottl } 852195534Sscottl xpt_print(periph->path, "Unable to mode sense control page - " 853195534Sscottl "malloc failure\n"); 854216088Sken PROBE_SET_ACTION(softc, PROBE_SUPPORTED_VPD_LIST); 855195534Sscottl } 856195534Sscottl /* FALLTHROUGH */ 857216088Sken case PROBE_SUPPORTED_VPD_LIST: 858195534Sscottl { 859216088Sken struct scsi_vpd_supported_page_list *vpd_list; 860195534Sscottl struct cam_ed *device; 861195534Sscottl 862216088Sken vpd_list = NULL; 863195534Sscottl device = periph->path->device; 864216088Sken 865216088Sken if ((SCSI_QUIRK(device)->quirks & CAM_QUIRK_NOVPDS) == 0) 866195534Sscottl vpd_list = malloc(sizeof(*vpd_list), M_CAMXPT, 867195534Sscottl M_NOWAIT | M_ZERO); 868195534Sscottl 869195534Sscottl if (vpd_list != NULL) { 870195534Sscottl scsi_inquiry(csio, 871195534Sscottl /*retries*/4, 872195534Sscottl probedone, 873195534Sscottl MSG_SIMPLE_Q_TAG, 874195534Sscottl (u_int8_t *)vpd_list, 875195534Sscottl sizeof(*vpd_list), 876195534Sscottl /*evpd*/TRUE, 877195534Sscottl SVPD_SUPPORTED_PAGE_LIST, 878195534Sscottl SSD_MIN_SIZE, 879195534Sscottl /*timeout*/60 * 1000); 880195534Sscottl break; 881195534Sscottl } 882195534Sscottl /* 883195534Sscottl * We'll have to do without, let our probedone 884195534Sscottl * routine finish up for us. 885195534Sscottl */ 886195534Sscottl start_ccb->csio.data_ptr = NULL; 887250025Smav cam_freeze_devq(periph->path); 888195534Sscottl probedone(periph, start_ccb); 889195534Sscottl return; 890195534Sscottl } 891216088Sken case PROBE_DEVICE_ID: 892195534Sscottl { 893216088Sken struct scsi_vpd_device_id *devid; 894216088Sken 895216088Sken devid = NULL; 896249937Ssmh if (scsi_vpd_supported_page(periph, SVPD_DEVICE_ID)) 897216088Sken devid = malloc(SVPD_DEVICE_ID_MAX_SIZE, M_CAMXPT, 898216088Sken M_NOWAIT | M_ZERO); 899216088Sken 900216088Sken if (devid != NULL) { 901216088Sken scsi_inquiry(csio, 902216088Sken /*retries*/4, 903216088Sken probedone, 904216088Sken MSG_SIMPLE_Q_TAG, 905216088Sken (uint8_t *)devid, 906216088Sken SVPD_DEVICE_ID_MAX_SIZE, 907216088Sken /*evpd*/TRUE, 908216088Sken SVPD_DEVICE_ID, 909216088Sken SSD_MIN_SIZE, 910216088Sken /*timeout*/60 * 1000); 911216088Sken break; 912216088Sken } 913216088Sken /* 914216088Sken * We'll have to do without, let our probedone 915216088Sken * routine finish up for us. 916216088Sken */ 917216088Sken start_ccb->csio.data_ptr = NULL; 918250025Smav cam_freeze_devq(periph->path); 919216088Sken probedone(periph, start_ccb); 920216088Sken return; 921216088Sken } 922216088Sken case PROBE_SERIAL_NUM: 923216088Sken { 924195534Sscottl struct scsi_vpd_unit_serial_number *serial_buf; 925195534Sscottl struct cam_ed* device; 926195534Sscottl 927195534Sscottl serial_buf = NULL; 928195534Sscottl device = periph->path->device; 929195685Semaste if (device->serial_num != NULL) { 930195685Semaste free(device->serial_num, M_CAMXPT); 931195685Semaste device->serial_num = NULL; 932195685Semaste device->serial_num_len = 0; 933195685Semaste } 934195534Sscottl 935249937Ssmh if (scsi_vpd_supported_page(periph, SVPD_UNIT_SERIAL_NUMBER)) 936216088Sken serial_buf = (struct scsi_vpd_unit_serial_number *) 937216088Sken malloc(sizeof(*serial_buf), M_CAMXPT, 938216088Sken M_NOWAIT|M_ZERO); 939195534Sscottl 940195534Sscottl if (serial_buf != NULL) { 941195534Sscottl scsi_inquiry(csio, 942195534Sscottl /*retries*/4, 943195534Sscottl probedone, 944195534Sscottl MSG_SIMPLE_Q_TAG, 945195534Sscottl (u_int8_t *)serial_buf, 946195534Sscottl sizeof(*serial_buf), 947195534Sscottl /*evpd*/TRUE, 948195534Sscottl SVPD_UNIT_SERIAL_NUMBER, 949195534Sscottl SSD_MIN_SIZE, 950195534Sscottl /*timeout*/60 * 1000); 951195534Sscottl break; 952195534Sscottl } 953195534Sscottl /* 954195534Sscottl * We'll have to do without, let our probedone 955195534Sscottl * routine finish up for us. 956195534Sscottl */ 957195534Sscottl start_ccb->csio.data_ptr = NULL; 958250025Smav cam_freeze_devq(periph->path); 959195534Sscottl probedone(periph, start_ccb); 960195534Sscottl return; 961195534Sscottl } 962195534Sscottl default: 963236613Smav panic("probestart: invalid action state 0x%x\n", softc->action); 964195534Sscottl } 965249466Smav start_ccb->ccb_h.flags |= CAM_DEV_QFREEZE; 966195534Sscottl xpt_action(start_ccb); 967195534Sscottl} 968195534Sscottl 969195534Sscottlstatic void 970195534Sscottlproberequestdefaultnegotiation(struct cam_periph *periph) 971195534Sscottl{ 972195534Sscottl struct ccb_trans_settings cts; 973195534Sscottl 974203108Smav xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE); 975195534Sscottl cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 976195534Sscottl cts.type = CTS_TYPE_USER_SETTINGS; 977195534Sscottl xpt_action((union ccb *)&cts); 978252382Sscottl if (cam_ccb_status((union ccb *)&cts) != CAM_REQ_CMP) { 979195534Sscottl return; 980195534Sscottl } 981195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 982195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 983195534Sscottl xpt_action((union ccb *)&cts); 984195534Sscottl} 985195534Sscottl 986195534Sscottl/* 987195534Sscottl * Backoff Negotiation Code- only pertinent for SPI devices. 988195534Sscottl */ 989195534Sscottlstatic int 990195534Sscottlproberequestbackoff(struct cam_periph *periph, struct cam_ed *device) 991195534Sscottl{ 992195534Sscottl struct ccb_trans_settings cts; 993195534Sscottl struct ccb_trans_settings_spi *spi; 994195534Sscottl 995195534Sscottl memset(&cts, 0, sizeof (cts)); 996203108Smav xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE); 997195534Sscottl cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 998195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 999195534Sscottl xpt_action((union ccb *)&cts); 1000252382Sscottl if (cam_ccb_status((union ccb *)&cts) != CAM_REQ_CMP) { 1001195534Sscottl if (bootverbose) { 1002195534Sscottl xpt_print(periph->path, 1003195534Sscottl "failed to get current device settings\n"); 1004195534Sscottl } 1005195534Sscottl return (0); 1006195534Sscottl } 1007195534Sscottl if (cts.transport != XPORT_SPI) { 1008195534Sscottl if (bootverbose) { 1009195534Sscottl xpt_print(periph->path, "not SPI transport\n"); 1010195534Sscottl } 1011195534Sscottl return (0); 1012195534Sscottl } 1013195534Sscottl spi = &cts.xport_specific.spi; 1014195534Sscottl 1015195534Sscottl /* 1016195534Sscottl * We cannot renegotiate sync rate if we don't have one. 1017195534Sscottl */ 1018195534Sscottl if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) { 1019195534Sscottl if (bootverbose) { 1020195534Sscottl xpt_print(periph->path, "no sync rate known\n"); 1021195534Sscottl } 1022195534Sscottl return (0); 1023195534Sscottl } 1024195534Sscottl 1025195534Sscottl /* 1026195534Sscottl * We'll assert that we don't have to touch PPR options- the 1027195534Sscottl * SIM will see what we do with period and offset and adjust 1028195534Sscottl * the PPR options as appropriate. 1029195534Sscottl */ 1030195534Sscottl 1031195534Sscottl /* 1032195534Sscottl * A sync rate with unknown or zero offset is nonsensical. 1033195534Sscottl * A sync period of zero means Async. 1034195534Sscottl */ 1035195534Sscottl if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0 1036195534Sscottl || spi->sync_offset == 0 || spi->sync_period == 0) { 1037195534Sscottl if (bootverbose) { 1038195534Sscottl xpt_print(periph->path, "no sync rate available\n"); 1039195534Sscottl } 1040195534Sscottl return (0); 1041195534Sscottl } 1042195534Sscottl 1043195534Sscottl if (device->flags & CAM_DEV_DV_HIT_BOTTOM) { 1044236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, 1045195534Sscottl ("hit async: giving up on DV\n")); 1046195534Sscottl return (0); 1047195534Sscottl } 1048195534Sscottl 1049195534Sscottl 1050195534Sscottl /* 1051195534Sscottl * Jump sync_period up by one, but stop at 5MHz and fall back to Async. 1052195534Sscottl * We don't try to remember 'last' settings to see if the SIM actually 1053195534Sscottl * gets into the speed we want to set. We check on the SIM telling 1054195534Sscottl * us that a requested speed is bad, but otherwise don't try and 1055195534Sscottl * check the speed due to the asynchronous and handshake nature 1056195534Sscottl * of speed setting. 1057195534Sscottl */ 1058195534Sscottl spi->valid = CTS_SPI_VALID_SYNC_RATE | CTS_SPI_VALID_SYNC_OFFSET; 1059195534Sscottl for (;;) { 1060195534Sscottl spi->sync_period++; 1061195534Sscottl if (spi->sync_period >= 0xf) { 1062195534Sscottl spi->sync_period = 0; 1063195534Sscottl spi->sync_offset = 0; 1064236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, 1065195534Sscottl ("setting to async for DV\n")); 1066195534Sscottl /* 1067195534Sscottl * Once we hit async, we don't want to try 1068195534Sscottl * any more settings. 1069195534Sscottl */ 1070195534Sscottl device->flags |= CAM_DEV_DV_HIT_BOTTOM; 1071195534Sscottl } else if (bootverbose) { 1072236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, 1073195534Sscottl ("DV: period 0x%x\n", spi->sync_period)); 1074195534Sscottl printf("setting period to 0x%x\n", spi->sync_period); 1075195534Sscottl } 1076195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1077195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 1078195534Sscottl xpt_action((union ccb *)&cts); 1079252382Sscottl if (cam_ccb_status((union ccb *)&cts) != CAM_REQ_CMP) { 1080195534Sscottl break; 1081195534Sscottl } 1082236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, 1083195534Sscottl ("DV: failed to set period 0x%x\n", spi->sync_period)); 1084195534Sscottl if (spi->sync_period == 0) { 1085195534Sscottl return (0); 1086195534Sscottl } 1087195534Sscottl } 1088195534Sscottl return (1); 1089195534Sscottl} 1090195534Sscottl 1091216088Sken#define CCB_COMPLETED_OK(ccb) (((ccb).status & CAM_STATUS_MASK) == CAM_REQ_CMP) 1092216088Sken 1093195534Sscottlstatic void 1094195534Sscottlprobedone(struct cam_periph *periph, union ccb *done_ccb) 1095195534Sscottl{ 1096195534Sscottl probe_softc *softc; 1097195534Sscottl struct cam_path *path; 1098195534Sscottl u_int32_t priority; 1099195534Sscottl 1100195534Sscottl CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probedone\n")); 1101195534Sscottl 1102195534Sscottl softc = (probe_softc *)periph->softc; 1103195534Sscottl path = done_ccb->ccb_h.path; 1104195534Sscottl priority = done_ccb->ccb_h.pinfo.priority; 1105195534Sscottl 1106195534Sscottl switch (softc->action) { 1107195534Sscottl case PROBE_TUR: 1108195534Sscottl { 1109252382Sscottl if (cam_ccb_status(done_ccb) != CAM_REQ_CMP) { 1110195534Sscottl 1111195534Sscottl if (cam_periph_error(done_ccb, 0, 1112249466Smav SF_NO_PRINT, NULL) == ERESTART) { 1113249466Smavout: 1114249466Smav /* Drop freeze taken due to CAM_DEV_QFREEZE */ 1115249466Smav cam_release_devq(path, 0, 0, 0, FALSE); 1116195534Sscottl return; 1117249466Smav } 1118195534Sscottl else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 1119195534Sscottl /* Don't wedge the queue */ 1120195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, 1121195534Sscottl /*count*/1, 1122195534Sscottl /*run_queue*/TRUE); 1123195534Sscottl } 1124195534Sscottl PROBE_SET_ACTION(softc, PROBE_INQUIRY); 1125195534Sscottl xpt_release_ccb(done_ccb); 1126195534Sscottl xpt_schedule(periph, priority); 1127249466Smav goto out; 1128195534Sscottl } 1129195534Sscottl case PROBE_INQUIRY: 1130195534Sscottl case PROBE_FULL_INQUIRY: 1131195534Sscottl { 1132252382Sscottl if (cam_ccb_status(done_ccb) == CAM_REQ_CMP) { 1133195534Sscottl struct scsi_inquiry_data *inq_buf; 1134195534Sscottl u_int8_t periph_qual; 1135195534Sscottl 1136195534Sscottl path->device->flags |= CAM_DEV_INQUIRY_DATA_VALID; 1137195534Sscottl inq_buf = &path->device->inq_data; 1138195534Sscottl 1139195534Sscottl periph_qual = SID_QUAL(inq_buf); 1140195534Sscottl 1141208911Smjacob if (periph_qual == SID_QUAL_LU_CONNECTED) { 1142195534Sscottl u_int8_t len; 1143195534Sscottl 1144195534Sscottl /* 1145195534Sscottl * We conservatively request only 1146195534Sscottl * SHORT_INQUIRY_LEN bytes of inquiry 1147195534Sscottl * information during our first try 1148195534Sscottl * at sending an INQUIRY. If the device 1149195534Sscottl * has more information to give, 1150195534Sscottl * perform a second request specifying 1151195534Sscottl * the amount of information the device 1152195534Sscottl * is willing to give. 1153195534Sscottl */ 1154195534Sscottl len = inq_buf->additional_length 1155195534Sscottl + offsetof(struct scsi_inquiry_data, 1156195534Sscottl additional_length) + 1; 1157195534Sscottl if (softc->action == PROBE_INQUIRY 1158195534Sscottl && len > SHORT_INQUIRY_LENGTH) { 1159195534Sscottl PROBE_SET_ACTION(softc, PROBE_FULL_INQUIRY); 1160195534Sscottl xpt_release_ccb(done_ccb); 1161195534Sscottl xpt_schedule(periph, priority); 1162249466Smav goto out; 1163195534Sscottl } 1164195534Sscottl 1165195534Sscottl scsi_find_quirk(path->device); 1166195534Sscottl 1167195534Sscottl scsi_devise_transport(path); 1168208911Smjacob 1169208911Smjacob if (path->device->lun_id == 0 && 1170208911Smjacob SID_ANSI_REV(inq_buf) > SCSI_REV_SPC2 && 1171208911Smjacob (SCSI_QUIRK(path->device)->quirks & 1172208911Smjacob CAM_QUIRK_NORPTLUNS) == 0) { 1173208911Smjacob PROBE_SET_ACTION(softc, 1174208911Smjacob PROBE_REPORT_LUNS); 1175208911Smjacob /* 1176208911Smjacob * Start with room for *one* lun. 1177208911Smjacob */ 1178208911Smjacob periph->path->target->rpl_size = 16; 1179208911Smjacob } else if (INQ_DATA_TQ_ENABLED(inq_buf)) 1180208911Smjacob PROBE_SET_ACTION(softc, 1181208911Smjacob PROBE_MODE_SENSE); 1182195534Sscottl else 1183208911Smjacob PROBE_SET_ACTION(softc, 1184216088Sken PROBE_SUPPORTED_VPD_LIST); 1185195534Sscottl 1186198748Smav if (path->device->flags & CAM_DEV_UNCONFIGURED) { 1187198748Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1188198748Smav xpt_acquire_device(path->device); 1189198748Smav } 1190195534Sscottl xpt_release_ccb(done_ccb); 1191195534Sscottl xpt_schedule(periph, priority); 1192249466Smav goto out; 1193208911Smjacob } else if (path->device->lun_id == 0 && 1194208911Smjacob SID_ANSI_REV(inq_buf) > SCSI_REV_SPC2 && 1195208911Smjacob (SCSI_QUIRK(path->device)->quirks & 1196208911Smjacob CAM_QUIRK_NORPTLUNS) == 0) { 1197208911Smjacob if (path->device->flags & 1198208911Smjacob CAM_DEV_UNCONFIGURED) { 1199208911Smjacob path->device->flags &= 1200208911Smjacob ~CAM_DEV_UNCONFIGURED; 1201208911Smjacob xpt_acquire_device(path->device); 1202208911Smjacob } 1203208911Smjacob PROBE_SET_ACTION(softc, PROBE_REPORT_LUNS); 1204208911Smjacob periph->path->target->rpl_size = 16; 1205208911Smjacob xpt_release_ccb(done_ccb); 1206208911Smjacob xpt_schedule(periph, priority); 1207249466Smav goto out; 1208195534Sscottl } 1209195534Sscottl } else if (cam_periph_error(done_ccb, 0, 1210195534Sscottl done_ccb->ccb_h.target_lun > 0 1211195534Sscottl ? SF_RETRY_UA|SF_QUIET_IR 1212195534Sscottl : SF_RETRY_UA, 1213195534Sscottl &softc->saved_ccb) == ERESTART) { 1214249466Smav goto out; 1215195534Sscottl } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1216195534Sscottl /* Don't wedge the queue */ 1217195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 1218195534Sscottl /*run_queue*/TRUE); 1219195534Sscottl } 1220195534Sscottl /* 1221195534Sscottl * If we get to this point, we got an error status back 1222195534Sscottl * from the inquiry and the error status doesn't require 1223195534Sscottl * automatically retrying the command. Therefore, the 1224195534Sscottl * inquiry failed. If we had inquiry information before 1225195534Sscottl * for this device, but this latest inquiry command failed, 1226195534Sscottl * the device has probably gone away. If this device isn't 1227195534Sscottl * already marked unconfigured, notify the peripheral 1228195534Sscottl * drivers that this device is no more. 1229195534Sscottl */ 1230195534Sscottl if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0) 1231195534Sscottl /* Send the async notification. */ 1232195534Sscottl xpt_async(AC_LOST_DEVICE, path, NULL); 1233236613Smav PROBE_SET_ACTION(softc, PROBE_INVALID); 1234195534Sscottl 1235195534Sscottl xpt_release_ccb(done_ccb); 1236195534Sscottl break; 1237195534Sscottl } 1238208911Smjacob case PROBE_REPORT_LUNS: 1239208911Smjacob { 1240208911Smjacob struct ccb_scsiio *csio; 1241208911Smjacob struct scsi_report_luns_data *lp; 1242208911Smjacob u_int nlun, maxlun; 1243208911Smjacob 1244208911Smjacob csio = &done_ccb->csio; 1245208911Smjacob 1246208911Smjacob lp = (struct scsi_report_luns_data *)csio->data_ptr; 1247208911Smjacob nlun = scsi_4btoul(lp->length) / 8; 1248208911Smjacob maxlun = (csio->dxfer_len / 8) - 1; 1249208911Smjacob 1250252382Sscottl if (cam_ccb_status(done_ccb) != CAM_REQ_CMP) { 1251208911Smjacob if (cam_periph_error(done_ccb, 0, 1252208911Smjacob done_ccb->ccb_h.target_lun > 0 ? 1253208911Smjacob SF_RETRY_UA|SF_QUIET_IR : SF_RETRY_UA, 1254208911Smjacob &softc->saved_ccb) == ERESTART) { 1255249466Smav goto out; 1256208911Smjacob } 1257208911Smjacob if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1258208911Smjacob xpt_release_devq(done_ccb->ccb_h.path, 1, 1259208911Smjacob TRUE); 1260208911Smjacob } 1261208911Smjacob free(lp, M_CAMXPT); 1262208911Smjacob lp = NULL; 1263208911Smjacob } else if (nlun > maxlun) { 1264208911Smjacob /* 1265208911Smjacob * Reallocate and retry to cover all luns 1266208911Smjacob */ 1267236613Smav CAM_DEBUG(path, CAM_DEBUG_PROBE, 1268236613Smav ("Probe: reallocating REPORT_LUNS for %u luns\n", 1269236613Smav nlun)); 1270208911Smjacob free(lp, M_CAMXPT); 1271208911Smjacob path->target->rpl_size = (nlun << 3) + 8; 1272208911Smjacob xpt_release_ccb(done_ccb); 1273208911Smjacob xpt_schedule(periph, priority); 1274249466Smav goto out; 1275208911Smjacob } else if (nlun == 0) { 1276208911Smjacob /* 1277208911Smjacob * If there don't appear to be any luns, bail. 1278208911Smjacob */ 1279208911Smjacob free(lp, M_CAMXPT); 1280208911Smjacob lp = NULL; 1281208911Smjacob } else if (probe_strange_rpl_data(lp, maxlun)) { 1282208911Smjacob /* 1283208911Smjacob * If we can't understand the lun format 1284208911Smjacob * of any entry, bail. 1285208911Smjacob */ 1286208911Smjacob free(lp, M_CAMXPT); 1287208911Smjacob lp = NULL; 1288208911Smjacob } else { 1289208911Smjacob lun_id_t lun; 1290208911Smjacob int idx; 1291208911Smjacob 1292236613Smav CAM_DEBUG(path, CAM_DEBUG_PROBE, 1293236613Smav ("Probe: %u lun(s) reported\n", nlun)); 1294208911Smjacob 1295208911Smjacob CAM_GET_SIMPLE_LUN(lp, 0, lun); 1296208911Smjacob /* 1297208911Smjacob * If the first lun is not lun 0, then either there 1298208911Smjacob * is no lun 0 in the list, or the list is unsorted. 1299208911Smjacob */ 1300208911Smjacob if (lun != 0) { 1301208911Smjacob for (idx = 0; idx < nlun; idx++) { 1302208911Smjacob CAM_GET_SIMPLE_LUN(lp, idx, lun); 1303208911Smjacob if (lun == 0) { 1304208911Smjacob break; 1305208911Smjacob } 1306208911Smjacob } 1307208911Smjacob if (idx != nlun) { 1308208911Smjacob uint8_t tlun[8]; 1309208911Smjacob memcpy(tlun, 1310208911Smjacob lp->luns[0].lundata, 8); 1311208911Smjacob memcpy(lp->luns[0].lundata, 1312208911Smjacob lp->luns[idx].lundata, 8); 1313208911Smjacob memcpy(lp->luns[idx].lundata, 1314208911Smjacob tlun, 8); 1315236613Smav CAM_DEBUG(path, CAM_DEBUG_PROBE, 1316236613Smav ("lun 0 in position %u\n", idx)); 1317208911Smjacob } else { 1318208911Smjacob /* 1319208911Smjacob * There is no lun 0 in our list. Destroy 1320208911Smjacob * the validity of the inquiry data so we 1321208911Smjacob * bail here and now. 1322208911Smjacob */ 1323208911Smjacob path->device->flags &= 1324208911Smjacob ~CAM_DEV_INQUIRY_DATA_VALID; 1325208911Smjacob } 1326208911Smjacob } 1327208911Smjacob /* 1328208911Smjacob * If we have an old lun list, We can either 1329208911Smjacob * retest luns that appear to have been dropped, 1330208911Smjacob * or just nuke them. We'll opt for the latter. 1331208911Smjacob * This function will also install the new list 1332208911Smjacob * in the target structure. 1333208911Smjacob */ 1334208911Smjacob probe_purge_old(path, lp); 1335208911Smjacob lp = NULL; 1336208911Smjacob } 1337208911Smjacob if (path->device->flags & CAM_DEV_INQUIRY_DATA_VALID) { 1338208911Smjacob struct scsi_inquiry_data *inq_buf; 1339208911Smjacob inq_buf = &path->device->inq_data; 1340208911Smjacob if (INQ_DATA_TQ_ENABLED(inq_buf)) 1341208911Smjacob PROBE_SET_ACTION(softc, PROBE_MODE_SENSE); 1342208911Smjacob else 1343216088Sken PROBE_SET_ACTION(softc, 1344216088Sken PROBE_SUPPORTED_VPD_LIST); 1345208911Smjacob xpt_release_ccb(done_ccb); 1346208911Smjacob xpt_schedule(periph, priority); 1347249466Smav goto out; 1348208911Smjacob } 1349208911Smjacob if (lp) { 1350208911Smjacob free(lp, M_CAMXPT); 1351208911Smjacob } 1352208911Smjacob break; 1353208911Smjacob } 1354195534Sscottl case PROBE_MODE_SENSE: 1355195534Sscottl { 1356195534Sscottl struct ccb_scsiio *csio; 1357195534Sscottl struct scsi_mode_header_6 *mode_hdr; 1358195534Sscottl 1359195534Sscottl csio = &done_ccb->csio; 1360195534Sscottl mode_hdr = (struct scsi_mode_header_6 *)csio->data_ptr; 1361252382Sscottl if (cam_ccb_status(done_ccb) == CAM_REQ_CMP) { 1362195534Sscottl struct scsi_control_page *page; 1363195534Sscottl u_int8_t *offset; 1364195534Sscottl 1365195534Sscottl offset = ((u_int8_t *)&mode_hdr[1]) 1366195534Sscottl + mode_hdr->blk_desc_len; 1367195534Sscottl page = (struct scsi_control_page *)offset; 1368195534Sscottl path->device->queue_flags = page->queue_flags; 1369195534Sscottl } else if (cam_periph_error(done_ccb, 0, 1370195534Sscottl SF_RETRY_UA|SF_NO_PRINT, 1371195534Sscottl &softc->saved_ccb) == ERESTART) { 1372249466Smav goto out; 1373195534Sscottl } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1374195534Sscottl /* Don't wedge the queue */ 1375195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, 1376195534Sscottl /*count*/1, /*run_queue*/TRUE); 1377195534Sscottl } 1378195534Sscottl xpt_release_ccb(done_ccb); 1379195534Sscottl free(mode_hdr, M_CAMXPT); 1380216088Sken PROBE_SET_ACTION(softc, PROBE_SUPPORTED_VPD_LIST); 1381195534Sscottl xpt_schedule(periph, priority); 1382249466Smav goto out; 1383195534Sscottl } 1384216088Sken case PROBE_SUPPORTED_VPD_LIST: 1385195534Sscottl { 1386195534Sscottl struct ccb_scsiio *csio; 1387195534Sscottl struct scsi_vpd_supported_page_list *page_list; 1388195534Sscottl 1389195534Sscottl csio = &done_ccb->csio; 1390195534Sscottl page_list = 1391195534Sscottl (struct scsi_vpd_supported_page_list *)csio->data_ptr; 1392195534Sscottl 1393216088Sken if (path->device->supported_vpds != NULL) { 1394216088Sken free(path->device->supported_vpds, M_CAMXPT); 1395216088Sken path->device->supported_vpds = NULL; 1396216088Sken path->device->supported_vpds_len = 0; 1397216088Sken } 1398216088Sken 1399195534Sscottl if (page_list == NULL) { 1400195534Sscottl /* 1401195534Sscottl * Don't process the command as it was never sent 1402195534Sscottl */ 1403216088Sken } else if (CCB_COMPLETED_OK(csio->ccb_h)) { 1404216088Sken /* Got vpd list */ 1405216088Sken path->device->supported_vpds_len = page_list->length + 1406216088Sken SVPD_SUPPORTED_PAGES_HDR_LEN; 1407216088Sken path->device->supported_vpds = (uint8_t *)page_list; 1408216088Sken xpt_release_ccb(done_ccb); 1409216088Sken PROBE_SET_ACTION(softc, PROBE_DEVICE_ID); 1410216088Sken xpt_schedule(periph, priority); 1411249466Smav goto out; 1412195534Sscottl } else if (cam_periph_error(done_ccb, 0, 1413195534Sscottl SF_RETRY_UA|SF_NO_PRINT, 1414195534Sscottl &softc->saved_ccb) == ERESTART) { 1415249466Smav goto out; 1416195534Sscottl } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1417195534Sscottl /* Don't wedge the queue */ 1418195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 1419195534Sscottl /*run_queue*/TRUE); 1420195534Sscottl } 1421195534Sscottl 1422216088Sken if (page_list) 1423195685Semaste free(page_list, M_CAMXPT); 1424216088Sken /* No VPDs available, skip to device check. */ 1425216088Sken csio->data_ptr = NULL; 1426216088Sken goto probe_device_check; 1427216088Sken } 1428216088Sken case PROBE_DEVICE_ID: 1429216088Sken { 1430216088Sken struct scsi_vpd_device_id *devid; 1431216088Sken struct ccb_scsiio *csio; 1432216088Sken uint32_t length = 0; 1433195534Sscottl 1434216088Sken csio = &done_ccb->csio; 1435216088Sken devid = (struct scsi_vpd_device_id *)csio->data_ptr; 1436216088Sken 1437216088Sken /* Clean up from previous instance of this device */ 1438216088Sken if (path->device->device_id != NULL) { 1439216088Sken path->device->device_id_len = 0; 1440216088Sken free(path->device->device_id, M_CAMXPT); 1441216088Sken path->device->device_id = NULL; 1442216088Sken } 1443216088Sken 1444216088Sken if (devid == NULL) { 1445216088Sken /* Don't process the command as it was never sent */ 1446216088Sken } else if (CCB_COMPLETED_OK(csio->ccb_h)) { 1447216088Sken length = scsi_2btoul(devid->length); 1448216088Sken if (length != 0) { 1449216088Sken /* 1450216088Sken * NB: device_id_len is actual response 1451216088Sken * size, not buffer size. 1452216088Sken */ 1453216088Sken path->device->device_id_len = length + 1454216088Sken SVPD_DEVICE_ID_HDR_LEN; 1455216088Sken path->device->device_id = (uint8_t *)devid; 1456216088Sken } 1457216088Sken } else if (cam_periph_error(done_ccb, 0, 1458223081Sgibbs SF_RETRY_UA, 1459216088Sken &softc->saved_ccb) == ERESTART) { 1460249466Smav goto out; 1461216088Sken } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1462216088Sken /* Don't wedge the queue */ 1463216088Sken xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 1464216088Sken /*run_queue*/TRUE); 1465195534Sscottl } 1466195534Sscottl 1467216088Sken /* Free the device id space if we don't use it */ 1468216088Sken if (devid && length == 0) 1469216088Sken free(devid, M_CAMXPT); 1470216088Sken xpt_release_ccb(done_ccb); 1471216088Sken PROBE_SET_ACTION(softc, PROBE_SERIAL_NUM); 1472216088Sken xpt_schedule(periph, priority); 1473249466Smav goto out; 1474195534Sscottl } 1475195534Sscottl 1476216088Skenprobe_device_check: 1477216088Sken case PROBE_SERIAL_NUM: 1478195534Sscottl { 1479195534Sscottl struct ccb_scsiio *csio; 1480195534Sscottl struct scsi_vpd_unit_serial_number *serial_buf; 1481195534Sscottl u_int32_t priority; 1482195534Sscottl int changed; 1483195534Sscottl int have_serialnum; 1484195534Sscottl 1485195534Sscottl changed = 1; 1486195534Sscottl have_serialnum = 0; 1487195534Sscottl csio = &done_ccb->csio; 1488195534Sscottl priority = done_ccb->ccb_h.pinfo.priority; 1489195534Sscottl serial_buf = 1490195534Sscottl (struct scsi_vpd_unit_serial_number *)csio->data_ptr; 1491195534Sscottl 1492195534Sscottl if (serial_buf == NULL) { 1493195534Sscottl /* 1494195534Sscottl * Don't process the command as it was never sent 1495195534Sscottl */ 1496252382Sscottl } else if (cam_ccb_status(done_ccb) == CAM_REQ_CMP 1497195534Sscottl && (serial_buf->length > 0)) { 1498195534Sscottl 1499195534Sscottl have_serialnum = 1; 1500195534Sscottl path->device->serial_num = 1501195534Sscottl (u_int8_t *)malloc((serial_buf->length + 1), 1502195534Sscottl M_CAMXPT, M_NOWAIT); 1503195534Sscottl if (path->device->serial_num != NULL) { 1504223081Sgibbs memcpy(path->device->serial_num, 1505223081Sgibbs serial_buf->serial_num, 1506223081Sgibbs serial_buf->length); 1507195534Sscottl path->device->serial_num_len = 1508195534Sscottl serial_buf->length; 1509195534Sscottl path->device->serial_num[serial_buf->length] 1510195534Sscottl = '\0'; 1511195534Sscottl } 1512195534Sscottl } else if (cam_periph_error(done_ccb, 0, 1513195534Sscottl SF_RETRY_UA|SF_NO_PRINT, 1514195534Sscottl &softc->saved_ccb) == ERESTART) { 1515249466Smav goto out; 1516195534Sscottl } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1517195534Sscottl /* Don't wedge the queue */ 1518195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 1519195534Sscottl /*run_queue*/TRUE); 1520195534Sscottl } 1521195534Sscottl 1522195534Sscottl /* 1523195534Sscottl * Let's see if we have seen this device before. 1524195534Sscottl */ 1525195534Sscottl if ((softc->flags & PROBE_INQUIRY_CKSUM) != 0) { 1526195534Sscottl MD5_CTX context; 1527195534Sscottl u_int8_t digest[16]; 1528195534Sscottl 1529195534Sscottl MD5Init(&context); 1530195534Sscottl 1531195534Sscottl MD5Update(&context, 1532195534Sscottl (unsigned char *)&path->device->inq_data, 1533195534Sscottl sizeof(struct scsi_inquiry_data)); 1534195534Sscottl 1535195534Sscottl if (have_serialnum) 1536195534Sscottl MD5Update(&context, serial_buf->serial_num, 1537195534Sscottl serial_buf->length); 1538195534Sscottl 1539195534Sscottl MD5Final(digest, &context); 1540195534Sscottl if (bcmp(softc->digest, digest, 16) == 0) 1541195534Sscottl changed = 0; 1542195534Sscottl 1543195534Sscottl /* 1544195534Sscottl * XXX Do we need to do a TUR in order to ensure 1545195534Sscottl * that the device really hasn't changed??? 1546195534Sscottl */ 1547195534Sscottl if ((changed != 0) 1548195534Sscottl && ((softc->flags & PROBE_NO_ANNOUNCE) == 0)) 1549195534Sscottl xpt_async(AC_LOST_DEVICE, path, NULL); 1550195534Sscottl } 1551195534Sscottl if (serial_buf != NULL) 1552195534Sscottl free(serial_buf, M_CAMXPT); 1553195534Sscottl 1554195534Sscottl if (changed != 0) { 1555195534Sscottl /* 1556195534Sscottl * Now that we have all the necessary 1557195534Sscottl * information to safely perform transfer 1558195534Sscottl * negotiations... Controllers don't perform 1559195534Sscottl * any negotiation or tagged queuing until 1560195534Sscottl * after the first XPT_SET_TRAN_SETTINGS ccb is 1561195534Sscottl * received. So, on a new device, just retrieve 1562195534Sscottl * the user settings, and set them as the current 1563195534Sscottl * settings to set the device up. 1564195534Sscottl */ 1565195534Sscottl proberequestdefaultnegotiation(periph); 1566195534Sscottl xpt_release_ccb(done_ccb); 1567195534Sscottl 1568195534Sscottl /* 1569195534Sscottl * Perform a TUR to allow the controller to 1570195534Sscottl * perform any necessary transfer negotiation. 1571195534Sscottl */ 1572195534Sscottl PROBE_SET_ACTION(softc, PROBE_TUR_FOR_NEGOTIATION); 1573195534Sscottl xpt_schedule(periph, priority); 1574249466Smav goto out; 1575195534Sscottl } 1576195534Sscottl xpt_release_ccb(done_ccb); 1577195534Sscottl break; 1578195534Sscottl } 1579195534Sscottl case PROBE_TUR_FOR_NEGOTIATION: 1580236814Smav case PROBE_DV_EXIT: 1581252382Sscottl if (cam_ccb_status(done_ccb) != CAM_REQ_CMP) { 1582236814Smav cam_periph_error(done_ccb, 0, 1583236814Smav SF_NO_PRINT | SF_NO_RECOVERY | SF_NO_RETRY, NULL); 1584195534Sscottl } 1585195534Sscottl if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1586195534Sscottl /* Don't wedge the queue */ 1587195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 1588195534Sscottl /*run_queue*/TRUE); 1589195534Sscottl } 1590195534Sscottl /* 1591195534Sscottl * Do Domain Validation for lun 0 on devices that claim 1592195534Sscottl * to support Synchronous Transfer modes. 1593195534Sscottl */ 1594195534Sscottl if (softc->action == PROBE_TUR_FOR_NEGOTIATION 1595195534Sscottl && done_ccb->ccb_h.target_lun == 0 1596195534Sscottl && (path->device->inq_data.flags & SID_Sync) != 0 1597195534Sscottl && (path->device->flags & CAM_DEV_IN_DV) == 0) { 1598236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, 1599195534Sscottl ("Begin Domain Validation\n")); 1600195534Sscottl path->device->flags |= CAM_DEV_IN_DV; 1601195534Sscottl xpt_release_ccb(done_ccb); 1602195534Sscottl PROBE_SET_ACTION(softc, PROBE_INQUIRY_BASIC_DV1); 1603195534Sscottl xpt_schedule(periph, priority); 1604249466Smav goto out; 1605195534Sscottl } 1606195534Sscottl if (softc->action == PROBE_DV_EXIT) { 1607236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, 1608195534Sscottl ("Leave Domain Validation\n")); 1609195534Sscottl } 1610198748Smav if (path->device->flags & CAM_DEV_UNCONFIGURED) { 1611198748Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1612198748Smav xpt_acquire_device(path->device); 1613198748Smav } 1614195534Sscottl path->device->flags &= 1615198748Smav ~(CAM_DEV_IN_DV|CAM_DEV_DV_HIT_BOTTOM); 1616195534Sscottl if ((softc->flags & PROBE_NO_ANNOUNCE) == 0) { 1617195534Sscottl /* Inform the XPT that a new device has been found */ 1618195534Sscottl done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1619195534Sscottl xpt_action(done_ccb); 1620195534Sscottl xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, 1621195534Sscottl done_ccb); 1622195534Sscottl } 1623236613Smav PROBE_SET_ACTION(softc, PROBE_DONE); 1624195534Sscottl xpt_release_ccb(done_ccb); 1625195534Sscottl break; 1626195534Sscottl case PROBE_INQUIRY_BASIC_DV1: 1627195534Sscottl case PROBE_INQUIRY_BASIC_DV2: 1628195534Sscottl { 1629195534Sscottl struct scsi_inquiry_data *nbuf; 1630195534Sscottl struct ccb_scsiio *csio; 1631195534Sscottl 1632252382Sscottl if (cam_ccb_status(done_ccb) != CAM_REQ_CMP) { 1633236814Smav cam_periph_error(done_ccb, 0, 1634236814Smav SF_NO_PRINT | SF_NO_RECOVERY | SF_NO_RETRY, NULL); 1635236814Smav } 1636195534Sscottl if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1637195534Sscottl /* Don't wedge the queue */ 1638195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 1639195534Sscottl /*run_queue*/TRUE); 1640195534Sscottl } 1641195534Sscottl csio = &done_ccb->csio; 1642195534Sscottl nbuf = (struct scsi_inquiry_data *)csio->data_ptr; 1643195534Sscottl if (bcmp(nbuf, &path->device->inq_data, SHORT_INQUIRY_LENGTH)) { 1644195534Sscottl xpt_print(path, 1645195534Sscottl "inquiry data fails comparison at DV%d step\n", 1646195534Sscottl softc->action == PROBE_INQUIRY_BASIC_DV1 ? 1 : 2); 1647195534Sscottl if (proberequestbackoff(periph, path->device)) { 1648195534Sscottl path->device->flags &= ~CAM_DEV_IN_DV; 1649195534Sscottl PROBE_SET_ACTION(softc, PROBE_TUR_FOR_NEGOTIATION); 1650195534Sscottl } else { 1651195534Sscottl /* give up */ 1652195534Sscottl PROBE_SET_ACTION(softc, PROBE_DV_EXIT); 1653195534Sscottl } 1654195534Sscottl free(nbuf, M_CAMXPT); 1655195534Sscottl xpt_release_ccb(done_ccb); 1656195534Sscottl xpt_schedule(periph, priority); 1657249466Smav goto out; 1658195534Sscottl } 1659195534Sscottl free(nbuf, M_CAMXPT); 1660195534Sscottl if (softc->action == PROBE_INQUIRY_BASIC_DV1) { 1661195534Sscottl PROBE_SET_ACTION(softc, PROBE_INQUIRY_BASIC_DV2); 1662195534Sscottl xpt_release_ccb(done_ccb); 1663195534Sscottl xpt_schedule(periph, priority); 1664249466Smav goto out; 1665195534Sscottl } 1666195534Sscottl if (softc->action == PROBE_INQUIRY_BASIC_DV2) { 1667236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, 1668195534Sscottl ("Leave Domain Validation Successfully\n")); 1669195534Sscottl } 1670198748Smav if (path->device->flags & CAM_DEV_UNCONFIGURED) { 1671198748Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1672198748Smav xpt_acquire_device(path->device); 1673198748Smav } 1674195534Sscottl path->device->flags &= 1675198748Smav ~(CAM_DEV_IN_DV|CAM_DEV_DV_HIT_BOTTOM); 1676195534Sscottl if ((softc->flags & PROBE_NO_ANNOUNCE) == 0) { 1677195534Sscottl /* Inform the XPT that a new device has been found */ 1678195534Sscottl done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1679195534Sscottl xpt_action(done_ccb); 1680195534Sscottl xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, 1681195534Sscottl done_ccb); 1682195534Sscottl } 1683236613Smav PROBE_SET_ACTION(softc, PROBE_DONE); 1684195534Sscottl xpt_release_ccb(done_ccb); 1685195534Sscottl break; 1686195534Sscottl } 1687195534Sscottl default: 1688236613Smav panic("probedone: invalid action state 0x%x\n", softc->action); 1689195534Sscottl } 1690195534Sscottl done_ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs); 1691195534Sscottl TAILQ_REMOVE(&softc->request_ccbs, &done_ccb->ccb_h, periph_links.tqe); 1692195534Sscottl done_ccb->ccb_h.status = CAM_REQ_CMP; 1693195534Sscottl xpt_done(done_ccb); 1694195534Sscottl if (TAILQ_FIRST(&softc->request_ccbs) == NULL) { 1695236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe completed\n")); 1696249466Smav /* Drop freeze taken due to CAM_DEV_QFREEZE flag set. */ 1697249466Smav cam_release_devq(path, 0, 0, 0, FALSE); 1698236228Smav cam_periph_invalidate(periph); 1699195534Sscottl cam_periph_release_locked(periph); 1700195534Sscottl } else { 1701195534Sscottl probeschedule(periph); 1702249466Smav goto out; 1703195534Sscottl } 1704195534Sscottl} 1705195534Sscottl 1706208911Smjacobstatic int 1707208911Smjacobprobe_strange_rpl_data(struct scsi_report_luns_data *rp, uint32_t maxlun) 1708208911Smjacob{ 1709208911Smjacob uint32_t idx; 1710208911Smjacob uint32_t nlun = MIN(maxlun, (scsi_4btoul(rp->length) / 8)); 1711208911Smjacob 1712208911Smjacob for (idx = 0; idx < nlun; idx++) { 1713208911Smjacob if (!CAM_CAN_GET_SIMPLE_LUN(rp, idx)) { 1714208911Smjacob return (-1); 1715208911Smjacob } 1716208911Smjacob } 1717208911Smjacob return (0); 1718208911Smjacob} 1719208911Smjacob 1720195534Sscottlstatic void 1721208911Smjacobprobe_purge_old(struct cam_path *path, struct scsi_report_luns_data *new) 1722208911Smjacob{ 1723208911Smjacob struct cam_path *tp; 1724208911Smjacob struct scsi_report_luns_data *old; 1725208911Smjacob u_int idx1, idx2, nlun_old, nlun_new, this_lun; 1726208911Smjacob u_int8_t *ol, *nl; 1727208911Smjacob 1728208911Smjacob if (path->target == NULL) { 1729208911Smjacob return; 1730208911Smjacob } 1731256843Smav mtx_lock(&path->target->luns_mtx); 1732256843Smav old = path->target->luns; 1733256843Smav path->target->luns = new; 1734256843Smav mtx_unlock(&path->target->luns_mtx); 1735256843Smav if (old == NULL) 1736208911Smjacob return; 1737208911Smjacob nlun_old = scsi_4btoul(old->length) / 8; 1738208911Smjacob nlun_new = scsi_4btoul(new->length) / 8; 1739208911Smjacob 1740208911Smjacob /* 1741208911Smjacob * We are not going to assume sorted lists. Deal. 1742208911Smjacob */ 1743208911Smjacob for (idx1 = 0; idx1 < nlun_old; idx1++) { 1744208911Smjacob ol = old->luns[idx1].lundata; 1745208911Smjacob for (idx2 = 0; idx2 < nlun_new; idx2++) { 1746208911Smjacob nl = new->luns[idx2].lundata; 1747208911Smjacob if (memcmp(nl, ol, 8) == 0) { 1748208911Smjacob break; 1749208911Smjacob } 1750208911Smjacob } 1751208911Smjacob if (idx2 < nlun_new) { 1752208911Smjacob continue; 1753208911Smjacob } 1754208911Smjacob /* 1755208911Smjacob * An 'old' item not in the 'new' list. 1756208911Smjacob * Nuke it. Except that if it is lun 0, 1757208911Smjacob * that would be what the probe state 1758208911Smjacob * machine is currently working on, 1759208911Smjacob * so we won't do that. 1760208911Smjacob * 1761208911Smjacob * We also cannot nuke it if it is 1762208911Smjacob * not in a lun format we understand. 1763208911Smjacob */ 1764208911Smjacob if (!CAM_CAN_GET_SIMPLE_LUN(old, idx1)) { 1765208911Smjacob continue; 1766208911Smjacob } 1767208911Smjacob CAM_GET_SIMPLE_LUN(old, idx1, this_lun); 1768208911Smjacob if (this_lun == 0) { 1769208911Smjacob continue; 1770208911Smjacob } 1771208911Smjacob if (xpt_create_path(&tp, NULL, xpt_path_path_id(path), 1772208911Smjacob xpt_path_target_id(path), this_lun) == CAM_REQ_CMP) { 1773208911Smjacob xpt_async(AC_LOST_DEVICE, tp, NULL); 1774208911Smjacob xpt_free_path(tp); 1775208911Smjacob } 1776208911Smjacob } 1777208911Smjacob free(old, M_CAMXPT); 1778208911Smjacob} 1779208911Smjacob 1780208911Smjacobstatic void 1781195534Sscottlprobecleanup(struct cam_periph *periph) 1782195534Sscottl{ 1783195534Sscottl free(periph->softc, M_CAMXPT); 1784195534Sscottl} 1785195534Sscottl 1786195534Sscottlstatic void 1787195534Sscottlscsi_find_quirk(struct cam_ed *device) 1788195534Sscottl{ 1789195534Sscottl struct scsi_quirk_entry *quirk; 1790195534Sscottl caddr_t match; 1791195534Sscottl 1792195534Sscottl match = cam_quirkmatch((caddr_t)&device->inq_data, 1793195534Sscottl (caddr_t)scsi_quirk_table, 1794195534Sscottl sizeof(scsi_quirk_table) / 1795195534Sscottl sizeof(*scsi_quirk_table), 1796195534Sscottl sizeof(*scsi_quirk_table), scsi_inquiry_match); 1797195534Sscottl 1798195534Sscottl if (match == NULL) 1799195534Sscottl panic("xpt_find_quirk: device didn't match wildcard entry!!"); 1800195534Sscottl 1801195534Sscottl quirk = (struct scsi_quirk_entry *)match; 1802195534Sscottl device->quirk = quirk; 1803195534Sscottl device->mintags = quirk->mintags; 1804195534Sscottl device->maxtags = quirk->maxtags; 1805195534Sscottl} 1806195534Sscottl 1807195534Sscottlstatic int 1808195534Sscottlsysctl_cam_search_luns(SYSCTL_HANDLER_ARGS) 1809195534Sscottl{ 1810228442Smdf int error, val; 1811195534Sscottl 1812228442Smdf val = cam_srch_hi; 1813228442Smdf error = sysctl_handle_int(oidp, &val, 0, req); 1814195534Sscottl if (error != 0 || req->newptr == NULL) 1815195534Sscottl return (error); 1816228442Smdf if (val == 0 || val == 1) { 1817228442Smdf cam_srch_hi = val; 1818195534Sscottl return (0); 1819195534Sscottl } else { 1820195534Sscottl return (EINVAL); 1821195534Sscottl } 1822195534Sscottl} 1823195534Sscottl 1824195534Sscottltypedef struct { 1825195534Sscottl union ccb *request_ccb; 1826195534Sscottl struct ccb_pathinq *cpi; 1827195534Sscottl int counter; 1828208911Smjacob int lunindex[0]; 1829195534Sscottl} scsi_scan_bus_info; 1830195534Sscottl 1831195534Sscottl/* 1832195534Sscottl * To start a scan, request_ccb is an XPT_SCAN_BUS ccb. 1833195688Semaste * As the scan progresses, scsi_scan_bus is used as the 1834195534Sscottl * callback on completion function. 1835195534Sscottl */ 1836195534Sscottlstatic void 1837195534Sscottlscsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb) 1838195534Sscottl{ 1839256843Smav struct mtx *mtx; 1840256843Smav 1841195534Sscottl CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE, 1842195688Semaste ("scsi_scan_bus\n")); 1843195534Sscottl switch (request_ccb->ccb_h.func_code) { 1844195534Sscottl case XPT_SCAN_BUS: 1845208582Smjacob case XPT_SCAN_TGT: 1846195534Sscottl { 1847195534Sscottl scsi_scan_bus_info *scan_info; 1848203108Smav union ccb *work_ccb, *reset_ccb; 1849195534Sscottl struct cam_path *path; 1850195534Sscottl u_int i; 1851208582Smjacob u_int low_target, max_target; 1852195534Sscottl u_int initiator_id; 1853195534Sscottl 1854195534Sscottl /* Find out the characteristics of the bus */ 1855195534Sscottl work_ccb = xpt_alloc_ccb_nowait(); 1856195534Sscottl if (work_ccb == NULL) { 1857195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1858195534Sscottl xpt_done(request_ccb); 1859195534Sscottl return; 1860195534Sscottl } 1861195534Sscottl xpt_setup_ccb(&work_ccb->ccb_h, request_ccb->ccb_h.path, 1862195534Sscottl request_ccb->ccb_h.pinfo.priority); 1863195534Sscottl work_ccb->ccb_h.func_code = XPT_PATH_INQ; 1864195534Sscottl xpt_action(work_ccb); 1865195534Sscottl if (work_ccb->ccb_h.status != CAM_REQ_CMP) { 1866195534Sscottl request_ccb->ccb_h.status = work_ccb->ccb_h.status; 1867195534Sscottl xpt_free_ccb(work_ccb); 1868195534Sscottl xpt_done(request_ccb); 1869195534Sscottl return; 1870195534Sscottl } 1871195534Sscottl 1872195534Sscottl if ((work_ccb->cpi.hba_misc & PIM_NOINITIATOR) != 0) { 1873195534Sscottl /* 1874195534Sscottl * Can't scan the bus on an adapter that 1875195534Sscottl * cannot perform the initiator role. 1876195534Sscottl */ 1877195534Sscottl request_ccb->ccb_h.status = CAM_REQ_CMP; 1878195534Sscottl xpt_free_ccb(work_ccb); 1879195534Sscottl xpt_done(request_ccb); 1880195534Sscottl return; 1881195534Sscottl } 1882195534Sscottl 1883203108Smav /* We may need to reset bus first, if we haven't done it yet. */ 1884203108Smav if ((work_ccb->cpi.hba_inquiry & 1885203108Smav (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE)) && 1886203108Smav !(work_ccb->cpi.hba_misc & PIM_NOBUSRESET) && 1887253370Smav !timevalisset(&request_ccb->ccb_h.path->bus->last_reset) && 1888253370Smav (reset_ccb = xpt_alloc_ccb_nowait()) != NULL) { 1889203108Smav xpt_setup_ccb(&reset_ccb->ccb_h, request_ccb->ccb_h.path, 1890203108Smav CAM_PRIORITY_NONE); 1891203108Smav reset_ccb->ccb_h.func_code = XPT_RESET_BUS; 1892203108Smav xpt_action(reset_ccb); 1893203108Smav if (reset_ccb->ccb_h.status != CAM_REQ_CMP) { 1894203108Smav request_ccb->ccb_h.status = reset_ccb->ccb_h.status; 1895203108Smav xpt_free_ccb(reset_ccb); 1896203108Smav xpt_free_ccb(work_ccb); 1897203108Smav xpt_done(request_ccb); 1898203108Smav return; 1899203108Smav } 1900203108Smav xpt_free_ccb(reset_ccb); 1901203108Smav } 1902203108Smav 1903195534Sscottl /* Save some state for use while we probe for devices */ 1904208911Smjacob scan_info = (scsi_scan_bus_info *) malloc(sizeof(scsi_scan_bus_info) + 1905208911Smjacob (work_ccb->cpi.max_target * sizeof (u_int)), M_CAMXPT, M_ZERO|M_NOWAIT); 1906195534Sscottl if (scan_info == NULL) { 1907195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1908256843Smav xpt_free_ccb(work_ccb); 1909195534Sscottl xpt_done(request_ccb); 1910195534Sscottl return; 1911195534Sscottl } 1912236613Smav CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE, 1913208911Smjacob ("SCAN start for %p\n", scan_info)); 1914195534Sscottl scan_info->request_ccb = request_ccb; 1915195534Sscottl scan_info->cpi = &work_ccb->cpi; 1916195534Sscottl 1917195534Sscottl /* Cache on our stack so we can work asynchronously */ 1918195534Sscottl max_target = scan_info->cpi->max_target; 1919208582Smjacob low_target = 0; 1920195534Sscottl initiator_id = scan_info->cpi->initiator_id; 1921195534Sscottl 1922195534Sscottl 1923195534Sscottl /* 1924195534Sscottl * We can scan all targets in parallel, or do it sequentially. 1925195534Sscottl */ 1926208582Smjacob 1927208582Smjacob if (request_ccb->ccb_h.func_code == XPT_SCAN_TGT) { 1928208582Smjacob max_target = low_target = request_ccb->ccb_h.target_id; 1929208582Smjacob scan_info->counter = 0; 1930208582Smjacob } else if (scan_info->cpi->hba_misc & PIM_SEQSCAN) { 1931195534Sscottl max_target = 0; 1932195534Sscottl scan_info->counter = 0; 1933195534Sscottl } else { 1934195534Sscottl scan_info->counter = scan_info->cpi->max_target + 1; 1935195534Sscottl if (scan_info->cpi->initiator_id < scan_info->counter) { 1936195534Sscottl scan_info->counter--; 1937195534Sscottl } 1938195534Sscottl } 1939256843Smav mtx = xpt_path_mtx(scan_info->request_ccb->ccb_h.path); 1940256843Smav mtx_unlock(mtx); 1941195534Sscottl 1942208582Smjacob for (i = low_target; i <= max_target; i++) { 1943195534Sscottl cam_status status; 1944195534Sscottl if (i == initiator_id) 1945195534Sscottl continue; 1946195534Sscottl 1947249468Smav status = xpt_create_path(&path, NULL, 1948195534Sscottl request_ccb->ccb_h.path_id, 1949195534Sscottl i, 0); 1950195534Sscottl if (status != CAM_REQ_CMP) { 1951195688Semaste printf("scsi_scan_bus: xpt_create_path failed" 1952195534Sscottl " with status %#x, bus scan halted\n", 1953195534Sscottl status); 1954195534Sscottl free(scan_info, M_CAMXPT); 1955195534Sscottl request_ccb->ccb_h.status = status; 1956195534Sscottl xpt_free_ccb(work_ccb); 1957195534Sscottl xpt_done(request_ccb); 1958195534Sscottl break; 1959195534Sscottl } 1960195534Sscottl work_ccb = xpt_alloc_ccb_nowait(); 1961195534Sscottl if (work_ccb == NULL) { 1962195685Semaste xpt_free_ccb((union ccb *)scan_info->cpi); 1963195534Sscottl free(scan_info, M_CAMXPT); 1964195534Sscottl xpt_free_path(path); 1965195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1966195534Sscottl xpt_done(request_ccb); 1967195534Sscottl break; 1968195534Sscottl } 1969195534Sscottl xpt_setup_ccb(&work_ccb->ccb_h, path, 1970195534Sscottl request_ccb->ccb_h.pinfo.priority); 1971195534Sscottl work_ccb->ccb_h.func_code = XPT_SCAN_LUN; 1972195534Sscottl work_ccb->ccb_h.cbfcnp = scsi_scan_bus; 1973256843Smav work_ccb->ccb_h.flags |= CAM_UNLOCKED; 1974195534Sscottl work_ccb->ccb_h.ppriv_ptr0 = scan_info; 1975195534Sscottl work_ccb->crcn.flags = request_ccb->crcn.flags; 1976195534Sscottl xpt_action(work_ccb); 1977195534Sscottl } 1978256843Smav 1979256843Smav mtx_lock(mtx); 1980195534Sscottl break; 1981195534Sscottl } 1982195534Sscottl case XPT_SCAN_LUN: 1983195534Sscottl { 1984195534Sscottl cam_status status; 1985208911Smjacob struct cam_path *path, *oldpath; 1986195534Sscottl scsi_scan_bus_info *scan_info; 1987208911Smjacob struct cam_et *target; 1988208911Smjacob struct cam_ed *device; 1989208911Smjacob int next_target; 1990195534Sscottl path_id_t path_id; 1991195534Sscottl target_id_t target_id; 1992195534Sscottl lun_id_t lun_id; 1993195534Sscottl 1994208911Smjacob oldpath = request_ccb->ccb_h.path; 1995208911Smjacob 1996252382Sscottl status = cam_ccb_status(request_ccb); 1997195534Sscottl /* Reuse the same CCB to query if a device was really found */ 1998195534Sscottl scan_info = (scsi_scan_bus_info *)request_ccb->ccb_h.ppriv_ptr0; 1999195534Sscottl xpt_setup_ccb(&request_ccb->ccb_h, request_ccb->ccb_h.path, 2000195534Sscottl request_ccb->ccb_h.pinfo.priority); 2001195534Sscottl request_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 2002195534Sscottl 2003208911Smjacob 2004195534Sscottl path_id = request_ccb->ccb_h.path_id; 2005195534Sscottl target_id = request_ccb->ccb_h.target_id; 2006195534Sscottl lun_id = request_ccb->ccb_h.target_lun; 2007195534Sscottl xpt_action(request_ccb); 2008195534Sscottl 2009208911Smjacob target = request_ccb->ccb_h.path->target; 2010208911Smjacob next_target = 1; 2011208911Smjacob 2012256843Smav mtx = xpt_path_mtx(scan_info->request_ccb->ccb_h.path); 2013256843Smav mtx_lock(mtx); 2014256843Smav mtx_lock(&target->luns_mtx); 2015208911Smjacob if (target->luns) { 2016208911Smjacob uint32_t first; 2017208911Smjacob u_int nluns = scsi_4btoul(target->luns->length) / 8; 2018208911Smjacob 2019208911Smjacob /* 2020208911Smjacob * Make sure we skip over lun 0 if it's the first member 2021208911Smjacob * of the list as we've actually just finished probing 2022208911Smjacob * it. 2023208911Smjacob */ 2024208911Smjacob CAM_GET_SIMPLE_LUN(target->luns, 0, first); 2025208911Smjacob if (first == 0 && scan_info->lunindex[target_id] == 0) { 2026208911Smjacob scan_info->lunindex[target_id]++; 2027208911Smjacob } 2028208911Smjacob 2029208911Smjacob if (scan_info->lunindex[target_id] < nluns) { 2030208911Smjacob CAM_GET_SIMPLE_LUN(target->luns, 2031208911Smjacob scan_info->lunindex[target_id], lun_id); 2032256843Smav mtx_unlock(&target->luns_mtx); 2033208911Smjacob next_target = 0; 2034236613Smav CAM_DEBUG(request_ccb->ccb_h.path, 2035236613Smav CAM_DEBUG_PROBE, 2036208911Smjacob ("next lun to try at index %u is %u\n", 2037208911Smjacob scan_info->lunindex[target_id], lun_id)); 2038208911Smjacob scan_info->lunindex[target_id]++; 2039208911Smjacob } else { 2040256843Smav mtx_unlock(&target->luns_mtx); 2041208911Smjacob /* 2042208911Smjacob * We're done with scanning all luns. 2043208911Smjacob * 2044208911Smjacob * Nuke the bogus device for lun 0 if lun 0 2045208911Smjacob * wasn't on the list. 2046208911Smjacob */ 2047208911Smjacob if (first != 0) { 2048208911Smjacob TAILQ_FOREACH(device, 2049208911Smjacob &target->ed_entries, links) { 2050208911Smjacob if (device->lun_id == 0) { 2051208911Smjacob break; 2052208911Smjacob } 2053208911Smjacob } 2054208911Smjacob if (device) { 2055208911Smjacob xpt_release_device(device); 2056208911Smjacob } 2057208911Smjacob } 2058208911Smjacob } 2059256843Smav } else { 2060256843Smav mtx_unlock(&target->luns_mtx); 2061256843Smav if (request_ccb->ccb_h.status != CAM_REQ_CMP) { 2062195534Sscottl int phl; 2063195534Sscottl 2064195534Sscottl /* 2065195534Sscottl * If we already probed lun 0 successfully, or 2066195534Sscottl * we have additional configured luns on this 2067195534Sscottl * target that might have "gone away", go onto 2068195534Sscottl * the next lun. 2069195534Sscottl */ 2070195534Sscottl /* 2071195534Sscottl * We may touch devices that we don't 2072195534Sscottl * hold references too, so ensure they 2073195534Sscottl * don't disappear out from under us. 2074195534Sscottl * The target above is referenced by the 2075195534Sscottl * path in the request ccb. 2076195534Sscottl */ 2077195534Sscottl phl = 0; 2078195534Sscottl device = TAILQ_FIRST(&target->ed_entries); 2079195534Sscottl if (device != NULL) { 2080195534Sscottl phl = CAN_SRCH_HI_SPARSE(device); 2081195534Sscottl if (device->lun_id == 0) 2082195534Sscottl device = TAILQ_NEXT(device, links); 2083195534Sscottl } 2084195534Sscottl if ((lun_id != 0) || (device != NULL)) { 2085208911Smjacob if (lun_id < (CAM_SCSI2_MAXLUN-1) || phl) { 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; 2093256843Smav } else { 2094195534Sscottl 2095195534Sscottl device = request_ccb->ccb_h.path->device; 2096195534Sscottl 2097195534Sscottl if ((SCSI_QUIRK(device)->quirks & 2098195534Sscottl CAM_QUIRK_NOLUNS) == 0) { 2099195534Sscottl /* Try the next lun */ 2100195534Sscottl if (lun_id < (CAM_SCSI2_MAXLUN-1) 2101208911Smjacob || CAN_SRCH_HI_DENSE(device)) { 2102195534Sscottl lun_id++; 2103208911Smjacob next_target = 0; 2104208911Smjacob } 2105195534Sscottl } 2106208911Smjacob if (lun_id == request_ccb->ccb_h.target_lun 2107208911Smjacob || lun_id > scan_info->cpi->max_lun) 2108208911Smjacob next_target = 1; 2109256843Smav } 2110195534Sscottl } 2111195534Sscottl 2112195534Sscottl /* 2113195534Sscottl * Check to see if we scan any further luns. 2114195534Sscottl */ 2115208911Smjacob if (next_target) { 2116195534Sscottl int done; 2117195534Sscottl 2118208911Smjacob /* 2119208911Smjacob * Free the current request path- we're done with it. 2120208911Smjacob */ 2121208911Smjacob xpt_free_path(oldpath); 2122195534Sscottl hop_again: 2123195534Sscottl done = 0; 2124208582Smjacob if (scan_info->request_ccb->ccb_h.func_code == XPT_SCAN_TGT) { 2125208582Smjacob done = 1; 2126208582Smjacob } else if (scan_info->cpi->hba_misc & PIM_SEQSCAN) { 2127195534Sscottl scan_info->counter++; 2128195534Sscottl if (scan_info->counter == 2129195534Sscottl scan_info->cpi->initiator_id) { 2130195534Sscottl scan_info->counter++; 2131195534Sscottl } 2132195534Sscottl if (scan_info->counter >= 2133195534Sscottl scan_info->cpi->max_target+1) { 2134195534Sscottl done = 1; 2135195534Sscottl } 2136195534Sscottl } else { 2137195534Sscottl scan_info->counter--; 2138195534Sscottl if (scan_info->counter == 0) { 2139195534Sscottl done = 1; 2140195534Sscottl } 2141195534Sscottl } 2142195534Sscottl if (done) { 2143256843Smav mtx_unlock(mtx); 2144195534Sscottl xpt_free_ccb(request_ccb); 2145195534Sscottl xpt_free_ccb((union ccb *)scan_info->cpi); 2146195534Sscottl request_ccb = scan_info->request_ccb; 2147236613Smav CAM_DEBUG(request_ccb->ccb_h.path, 2148236613Smav CAM_DEBUG_TRACE, 2149208911Smjacob ("SCAN done for %p\n", scan_info)); 2150195534Sscottl free(scan_info, M_CAMXPT); 2151195534Sscottl request_ccb->ccb_h.status = CAM_REQ_CMP; 2152195534Sscottl xpt_done(request_ccb); 2153195534Sscottl break; 2154195534Sscottl } 2155195534Sscottl 2156195534Sscottl if ((scan_info->cpi->hba_misc & PIM_SEQSCAN) == 0) { 2157256843Smav mtx_unlock(mtx); 2158195685Semaste xpt_free_ccb(request_ccb); 2159195534Sscottl break; 2160195534Sscottl } 2161249468Smav status = xpt_create_path(&path, NULL, 2162195534Sscottl scan_info->request_ccb->ccb_h.path_id, 2163195534Sscottl scan_info->counter, 0); 2164195534Sscottl if (status != CAM_REQ_CMP) { 2165256843Smav mtx_unlock(mtx); 2166195688Semaste printf("scsi_scan_bus: xpt_create_path failed" 2167195534Sscottl " with status %#x, bus scan halted\n", 2168195534Sscottl status); 2169195534Sscottl xpt_free_ccb(request_ccb); 2170195534Sscottl xpt_free_ccb((union ccb *)scan_info->cpi); 2171195534Sscottl request_ccb = scan_info->request_ccb; 2172195534Sscottl free(scan_info, M_CAMXPT); 2173195534Sscottl request_ccb->ccb_h.status = status; 2174195534Sscottl xpt_done(request_ccb); 2175195534Sscottl break; 2176195534Sscottl } 2177195534Sscottl xpt_setup_ccb(&request_ccb->ccb_h, path, 2178195534Sscottl request_ccb->ccb_h.pinfo.priority); 2179195534Sscottl request_ccb->ccb_h.func_code = XPT_SCAN_LUN; 2180195534Sscottl request_ccb->ccb_h.cbfcnp = scsi_scan_bus; 2181256843Smav request_ccb->ccb_h.flags |= CAM_UNLOCKED; 2182195534Sscottl request_ccb->ccb_h.ppriv_ptr0 = scan_info; 2183195534Sscottl request_ccb->crcn.flags = 2184195534Sscottl scan_info->request_ccb->crcn.flags; 2185195534Sscottl } else { 2186249468Smav status = xpt_create_path(&path, NULL, 2187195534Sscottl path_id, target_id, lun_id); 2188208911Smjacob /* 2189208911Smjacob * Free the old request path- we're done with it. We 2190208911Smjacob * do this *after* creating the new path so that 2191208911Smjacob * we don't remove a target that has our lun list 2192208911Smjacob * in the case that lun 0 is not present. 2193208911Smjacob */ 2194208911Smjacob xpt_free_path(oldpath); 2195195534Sscottl if (status != CAM_REQ_CMP) { 2196195688Semaste printf("scsi_scan_bus: xpt_create_path failed " 2197195534Sscottl "with status %#x, halting LUN scan\n", 2198195534Sscottl status); 2199195534Sscottl goto hop_again; 2200195534Sscottl } 2201195534Sscottl xpt_setup_ccb(&request_ccb->ccb_h, path, 2202195534Sscottl request_ccb->ccb_h.pinfo.priority); 2203195534Sscottl request_ccb->ccb_h.func_code = XPT_SCAN_LUN; 2204195534Sscottl request_ccb->ccb_h.cbfcnp = scsi_scan_bus; 2205256843Smav request_ccb->ccb_h.flags |= CAM_UNLOCKED; 2206195534Sscottl request_ccb->ccb_h.ppriv_ptr0 = scan_info; 2207195534Sscottl request_ccb->crcn.flags = 2208195534Sscottl scan_info->request_ccb->crcn.flags; 2209195534Sscottl } 2210256843Smav mtx_unlock(mtx); 2211195534Sscottl xpt_action(request_ccb); 2212195534Sscottl break; 2213195534Sscottl } 2214195534Sscottl default: 2215195534Sscottl break; 2216195534Sscottl } 2217195534Sscottl} 2218195534Sscottl 2219195534Sscottlstatic void 2220195534Sscottlscsi_scan_lun(struct cam_periph *periph, struct cam_path *path, 2221195534Sscottl cam_flags flags, union ccb *request_ccb) 2222195534Sscottl{ 2223195534Sscottl struct ccb_pathinq cpi; 2224195534Sscottl cam_status status; 2225195534Sscottl struct cam_path *new_path; 2226195534Sscottl struct cam_periph *old_periph; 2227256843Smav int lock; 2228195534Sscottl 2229203108Smav CAM_DEBUG(path, CAM_DEBUG_TRACE, ("scsi_scan_lun\n")); 2230195534Sscottl 2231203108Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 2232195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 2233195534Sscottl xpt_action((union ccb *)&cpi); 2234195534Sscottl 2235195534Sscottl if (cpi.ccb_h.status != CAM_REQ_CMP) { 2236195534Sscottl if (request_ccb != NULL) { 2237195534Sscottl request_ccb->ccb_h.status = cpi.ccb_h.status; 2238195534Sscottl xpt_done(request_ccb); 2239195534Sscottl } 2240195534Sscottl return; 2241195534Sscottl } 2242195534Sscottl 2243195534Sscottl if ((cpi.hba_misc & PIM_NOINITIATOR) != 0) { 2244195534Sscottl /* 2245195534Sscottl * Can't scan the bus on an adapter that 2246195534Sscottl * cannot perform the initiator role. 2247195534Sscottl */ 2248195534Sscottl if (request_ccb != NULL) { 2249195534Sscottl request_ccb->ccb_h.status = CAM_REQ_CMP; 2250195534Sscottl xpt_done(request_ccb); 2251195534Sscottl } 2252195534Sscottl return; 2253195534Sscottl } 2254195534Sscottl 2255195534Sscottl if (request_ccb == NULL) { 2256241455Smav request_ccb = xpt_alloc_ccb_nowait(); 2257195534Sscottl if (request_ccb == NULL) { 2258195688Semaste xpt_print(path, "scsi_scan_lun: can't allocate CCB, " 2259195534Sscottl "can't continue\n"); 2260195534Sscottl return; 2261195534Sscottl } 2262249468Smav status = xpt_create_path(&new_path, NULL, 2263195534Sscottl path->bus->path_id, 2264195534Sscottl path->target->target_id, 2265195534Sscottl path->device->lun_id); 2266195534Sscottl if (status != CAM_REQ_CMP) { 2267241455Smav xpt_print(path, "scsi_scan_lun: can't create path, " 2268195534Sscottl "can't continue\n"); 2269241455Smav xpt_free_ccb(request_ccb); 2270195534Sscottl return; 2271195534Sscottl } 2272203108Smav xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_XPT); 2273195534Sscottl request_ccb->ccb_h.cbfcnp = xptscandone; 2274195534Sscottl request_ccb->ccb_h.func_code = XPT_SCAN_LUN; 2275256843Smav request_ccb->ccb_h.flags |= CAM_UNLOCKED; 2276195534Sscottl request_ccb->crcn.flags = flags; 2277195534Sscottl } 2278195534Sscottl 2279256843Smav lock = (xpt_path_owned(path) == 0); 2280256843Smav if (lock) 2281256843Smav xpt_path_lock(path); 2282195534Sscottl if ((old_periph = cam_periph_find(path, "probe")) != NULL) { 2283236228Smav if ((old_periph->flags & CAM_PERIPH_INVALID) == 0) { 2284236228Smav probe_softc *softc; 2285195534Sscottl 2286236228Smav softc = (probe_softc *)old_periph->softc; 2287236228Smav TAILQ_INSERT_TAIL(&softc->request_ccbs, 2288236228Smav &request_ccb->ccb_h, periph_links.tqe); 2289236228Smav } else { 2290236228Smav request_ccb->ccb_h.status = CAM_REQ_CMP_ERR; 2291236228Smav xpt_done(request_ccb); 2292236228Smav } 2293195534Sscottl } else { 2294195534Sscottl status = cam_periph_alloc(proberegister, NULL, probecleanup, 2295195534Sscottl probestart, "probe", 2296195534Sscottl CAM_PERIPH_BIO, 2297195534Sscottl request_ccb->ccb_h.path, NULL, 0, 2298195534Sscottl request_ccb); 2299195534Sscottl 2300195534Sscottl if (status != CAM_REQ_CMP) { 2301195688Semaste xpt_print(path, "scsi_scan_lun: cam_alloc_periph " 2302195534Sscottl "returned an error, can't continue probe\n"); 2303195534Sscottl request_ccb->ccb_h.status = status; 2304195534Sscottl xpt_done(request_ccb); 2305195534Sscottl } 2306195534Sscottl } 2307256843Smav if (lock) 2308256843Smav xpt_path_unlock(path); 2309195534Sscottl} 2310195534Sscottl 2311195534Sscottlstatic void 2312195534Sscottlxptscandone(struct cam_periph *periph, union ccb *done_ccb) 2313195534Sscottl{ 2314241455Smav 2315241455Smav xpt_free_path(done_ccb->ccb_h.path); 2316241455Smav xpt_free_ccb(done_ccb); 2317195534Sscottl} 2318195534Sscottl 2319195534Sscottlstatic struct cam_ed * 2320195534Sscottlscsi_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id) 2321195534Sscottl{ 2322195534Sscottl struct scsi_quirk_entry *quirk; 2323195534Sscottl struct cam_ed *device; 2324195534Sscottl 2325195534Sscottl device = xpt_alloc_device(bus, target, lun_id); 2326195534Sscottl if (device == NULL) 2327195534Sscottl return (NULL); 2328195534Sscottl 2329195534Sscottl /* 2330195534Sscottl * Take the default quirk entry until we have inquiry 2331195534Sscottl * data and can determine a better quirk to use. 2332195534Sscottl */ 2333195534Sscottl quirk = &scsi_quirk_table[scsi_quirk_table_size - 1]; 2334195534Sscottl device->quirk = (void *)quirk; 2335195534Sscottl device->mintags = quirk->mintags; 2336195534Sscottl device->maxtags = quirk->maxtags; 2337195534Sscottl bzero(&device->inq_data, sizeof(device->inq_data)); 2338195534Sscottl device->inq_flags = 0; 2339195534Sscottl device->queue_flags = 0; 2340195534Sscottl device->serial_num = NULL; 2341195534Sscottl device->serial_num_len = 0; 2342216088Sken device->device_id = NULL; 2343216088Sken device->device_id_len = 0; 2344216088Sken device->supported_vpds = NULL; 2345216088Sken device->supported_vpds_len = 0; 2346195534Sscottl return (device); 2347195534Sscottl} 2348195534Sscottl 2349195534Sscottlstatic void 2350195534Sscottlscsi_devise_transport(struct cam_path *path) 2351195534Sscottl{ 2352195534Sscottl struct ccb_pathinq cpi; 2353195534Sscottl struct ccb_trans_settings cts; 2354195534Sscottl struct scsi_inquiry_data *inq_buf; 2355195534Sscottl 2356195534Sscottl /* Get transport information from the SIM */ 2357203108Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 2358195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 2359195534Sscottl xpt_action((union ccb *)&cpi); 2360195534Sscottl 2361195534Sscottl inq_buf = NULL; 2362195534Sscottl if ((path->device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0) 2363195534Sscottl inq_buf = &path->device->inq_data; 2364195534Sscottl path->device->protocol = PROTO_SCSI; 2365195534Sscottl path->device->protocol_version = 2366195534Sscottl inq_buf != NULL ? SID_ANSI_REV(inq_buf) : cpi.protocol_version; 2367195534Sscottl path->device->transport = cpi.transport; 2368195534Sscottl path->device->transport_version = cpi.transport_version; 2369195534Sscottl 2370195534Sscottl /* 2371195534Sscottl * Any device not using SPI3 features should 2372195534Sscottl * be considered SPI2 or lower. 2373195534Sscottl */ 2374195534Sscottl if (inq_buf != NULL) { 2375195534Sscottl if (path->device->transport == XPORT_SPI 2376195534Sscottl && (inq_buf->spi3data & SID_SPI_MASK) == 0 2377195534Sscottl && path->device->transport_version > 2) 2378195534Sscottl path->device->transport_version = 2; 2379195534Sscottl } else { 2380195534Sscottl struct cam_ed* otherdev; 2381195534Sscottl 2382195534Sscottl for (otherdev = TAILQ_FIRST(&path->target->ed_entries); 2383195534Sscottl otherdev != NULL; 2384195534Sscottl otherdev = TAILQ_NEXT(otherdev, links)) { 2385195534Sscottl if (otherdev != path->device) 2386195534Sscottl break; 2387195534Sscottl } 2388195534Sscottl 2389195534Sscottl if (otherdev != NULL) { 2390195534Sscottl /* 2391195534Sscottl * Initially assume the same versioning as 2392195534Sscottl * prior luns for this target. 2393195534Sscottl */ 2394195534Sscottl path->device->protocol_version = 2395195534Sscottl otherdev->protocol_version; 2396195534Sscottl path->device->transport_version = 2397195534Sscottl otherdev->transport_version; 2398195534Sscottl } else { 2399195534Sscottl /* Until we know better, opt for safty */ 2400195534Sscottl path->device->protocol_version = 2; 2401195534Sscottl if (path->device->transport == XPORT_SPI) 2402195534Sscottl path->device->transport_version = 2; 2403195534Sscottl else 2404195534Sscottl path->device->transport_version = 0; 2405195534Sscottl } 2406195534Sscottl } 2407195534Sscottl 2408195534Sscottl /* 2409195534Sscottl * XXX 2410195534Sscottl * For a device compliant with SPC-2 we should be able 2411195534Sscottl * to determine the transport version supported by 2412195534Sscottl * scrutinizing the version descriptors in the 2413195534Sscottl * inquiry buffer. 2414195534Sscottl */ 2415195534Sscottl 2416195534Sscottl /* Tell the controller what we think */ 2417203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 2418195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 2419195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 2420195534Sscottl cts.transport = path->device->transport; 2421195534Sscottl cts.transport_version = path->device->transport_version; 2422195534Sscottl cts.protocol = path->device->protocol; 2423195534Sscottl cts.protocol_version = path->device->protocol_version; 2424195534Sscottl cts.proto_specific.valid = 0; 2425195534Sscottl cts.xport_specific.valid = 0; 2426195534Sscottl xpt_action((union ccb *)&cts); 2427195534Sscottl} 2428195534Sscottl 2429195534Sscottlstatic void 2430223081Sgibbsscsi_dev_advinfo(union ccb *start_ccb) 2431216088Sken{ 2432216088Sken struct cam_ed *device; 2433223081Sgibbs struct ccb_dev_advinfo *cdai; 2434216088Sken off_t amt; 2435216088Sken 2436223448Swill start_ccb->ccb_h.status = CAM_REQ_INVALID; 2437216088Sken device = start_ccb->ccb_h.path->device; 2438223081Sgibbs cdai = &start_ccb->cdai; 2439223081Sgibbs switch(cdai->buftype) { 2440223081Sgibbs case CDAI_TYPE_SCSI_DEVID: 2441223081Sgibbs if (cdai->flags & CDAI_FLAG_STORE) 2442223448Swill return; 2443223081Sgibbs cdai->provsiz = device->device_id_len; 2444216088Sken if (device->device_id_len == 0) 2445216088Sken break; 2446216088Sken amt = device->device_id_len; 2447223081Sgibbs if (cdai->provsiz > cdai->bufsiz) 2448223081Sgibbs amt = cdai->bufsiz; 2449223081Sgibbs memcpy(cdai->buf, device->device_id, amt); 2450216088Sken break; 2451223081Sgibbs case CDAI_TYPE_SERIAL_NUM: 2452223081Sgibbs if (cdai->flags & CDAI_FLAG_STORE) 2453223448Swill return; 2454223081Sgibbs cdai->provsiz = device->serial_num_len; 2455223081Sgibbs if (device->serial_num_len == 0) 2456223081Sgibbs break; 2457223081Sgibbs amt = device->serial_num_len; 2458223081Sgibbs if (cdai->provsiz > cdai->bufsiz) 2459223081Sgibbs amt = cdai->bufsiz; 2460223081Sgibbs memcpy(cdai->buf, device->serial_num, amt); 2461223081Sgibbs break; 2462223081Sgibbs case CDAI_TYPE_PHYS_PATH: 2463223081Sgibbs if (cdai->flags & CDAI_FLAG_STORE) { 2464230590Sken if (device->physpath != NULL) { 2465223081Sgibbs free(device->physpath, M_CAMXPT); 2466230590Sken device->physpath = NULL; 2467230590Sken } 2468223081Sgibbs device->physpath_len = cdai->bufsiz; 2469223081Sgibbs /* Clear existing buffer if zero length */ 2470223081Sgibbs if (cdai->bufsiz == 0) 2471223081Sgibbs break; 2472223081Sgibbs device->physpath = malloc(cdai->bufsiz, M_CAMXPT, M_NOWAIT); 2473223081Sgibbs if (device->physpath == NULL) { 2474223081Sgibbs start_ccb->ccb_h.status = CAM_REQ_ABORTED; 2475223081Sgibbs return; 2476223081Sgibbs } 2477223081Sgibbs memcpy(device->physpath, cdai->buf, cdai->bufsiz); 2478223081Sgibbs } else { 2479223081Sgibbs cdai->provsiz = device->physpath_len; 2480223081Sgibbs if (device->physpath_len == 0) 2481223081Sgibbs break; 2482223081Sgibbs amt = device->physpath_len; 2483223081Sgibbs if (cdai->provsiz > cdai->bufsiz) 2484223081Sgibbs amt = cdai->bufsiz; 2485223081Sgibbs memcpy(cdai->buf, device->physpath, amt); 2486223081Sgibbs } 2487223081Sgibbs break; 2488230590Sken case CDAI_TYPE_RCAPLONG: 2489230590Sken if (cdai->flags & CDAI_FLAG_STORE) { 2490230590Sken if (device->rcap_buf != NULL) { 2491230590Sken free(device->rcap_buf, M_CAMXPT); 2492230590Sken device->rcap_buf = NULL; 2493230590Sken } 2494230590Sken 2495230590Sken device->rcap_len = cdai->bufsiz; 2496230590Sken /* Clear existing buffer if zero length */ 2497230590Sken if (cdai->bufsiz == 0) 2498230590Sken break; 2499230590Sken 2500230590Sken device->rcap_buf = malloc(cdai->bufsiz, M_CAMXPT, 2501230590Sken M_NOWAIT); 2502230590Sken if (device->rcap_buf == NULL) { 2503230590Sken start_ccb->ccb_h.status = CAM_REQ_ABORTED; 2504230590Sken return; 2505230590Sken } 2506230590Sken 2507230590Sken memcpy(device->rcap_buf, cdai->buf, cdai->bufsiz); 2508230590Sken } else { 2509230590Sken cdai->provsiz = device->rcap_len; 2510230590Sken if (device->rcap_len == 0) 2511230590Sken break; 2512230590Sken amt = device->rcap_len; 2513230590Sken if (cdai->provsiz > cdai->bufsiz) 2514230590Sken amt = cdai->bufsiz; 2515230590Sken memcpy(cdai->buf, device->rcap_buf, amt); 2516230590Sken } 2517230590Sken break; 2518216088Sken default: 2519223448Swill return; 2520216088Sken } 2521216088Sken start_ccb->ccb_h.status = CAM_REQ_CMP; 2522223081Sgibbs 2523223081Sgibbs if (cdai->flags & CDAI_FLAG_STORE) { 2524223081Sgibbs xpt_async(AC_ADVINFO_CHANGED, start_ccb->ccb_h.path, 2525223081Sgibbs (void *)(uintptr_t)cdai->buftype); 2526223081Sgibbs } 2527216088Sken} 2528216088Sken 2529216088Skenstatic void 2530195534Sscottlscsi_action(union ccb *start_ccb) 2531195534Sscottl{ 2532195534Sscottl 2533195534Sscottl switch (start_ccb->ccb_h.func_code) { 2534195534Sscottl case XPT_SET_TRAN_SETTINGS: 2535195534Sscottl { 2536195534Sscottl scsi_set_transfer_settings(&start_ccb->cts, 2537256843Smav start_ccb->ccb_h.path, 2538195534Sscottl /*async_update*/FALSE); 2539195534Sscottl break; 2540195534Sscottl } 2541195534Sscottl case XPT_SCAN_BUS: 2542208582Smjacob case XPT_SCAN_TGT: 2543195534Sscottl scsi_scan_bus(start_ccb->ccb_h.path->periph, start_ccb); 2544195534Sscottl break; 2545195534Sscottl case XPT_SCAN_LUN: 2546195534Sscottl scsi_scan_lun(start_ccb->ccb_h.path->periph, 2547195534Sscottl start_ccb->ccb_h.path, start_ccb->crcn.flags, 2548195534Sscottl start_ccb); 2549195534Sscottl break; 2550223081Sgibbs case XPT_DEV_ADVINFO: 2551216088Sken { 2552223081Sgibbs scsi_dev_advinfo(start_ccb); 2553216088Sken break; 2554216088Sken } 2555195534Sscottl default: 2556195534Sscottl xpt_action_default(start_ccb); 2557195534Sscottl break; 2558195534Sscottl } 2559195534Sscottl} 2560195534Sscottl 2561195534Sscottlstatic void 2562256843Smavscsi_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_path *path, 2563195534Sscottl int async_update) 2564195534Sscottl{ 2565195534Sscottl struct ccb_pathinq cpi; 2566195534Sscottl struct ccb_trans_settings cur_cts; 2567195534Sscottl struct ccb_trans_settings_scsi *scsi; 2568195534Sscottl struct ccb_trans_settings_scsi *cur_scsi; 2569195534Sscottl struct scsi_inquiry_data *inq_data; 2570256843Smav struct cam_ed *device; 2571195534Sscottl 2572256843Smav if (path == NULL || (device = path->device) == NULL) { 2573195534Sscottl cts->ccb_h.status = CAM_PATH_INVALID; 2574195534Sscottl xpt_done((union ccb *)cts); 2575195534Sscottl return; 2576195534Sscottl } 2577195534Sscottl 2578195534Sscottl if (cts->protocol == PROTO_UNKNOWN 2579195534Sscottl || cts->protocol == PROTO_UNSPECIFIED) { 2580195534Sscottl cts->protocol = device->protocol; 2581195534Sscottl cts->protocol_version = device->protocol_version; 2582195534Sscottl } 2583195534Sscottl 2584195534Sscottl if (cts->protocol_version == PROTO_VERSION_UNKNOWN 2585195534Sscottl || cts->protocol_version == PROTO_VERSION_UNSPECIFIED) 2586195534Sscottl cts->protocol_version = device->protocol_version; 2587195534Sscottl 2588195534Sscottl if (cts->protocol != device->protocol) { 2589256843Smav xpt_print(path, "Uninitialized Protocol %x:%x?\n", 2590195534Sscottl cts->protocol, device->protocol); 2591195534Sscottl cts->protocol = device->protocol; 2592195534Sscottl } 2593195534Sscottl 2594195534Sscottl if (cts->protocol_version > device->protocol_version) { 2595195534Sscottl if (bootverbose) { 2596256843Smav xpt_print(path, "Down reving Protocol " 2597195534Sscottl "Version from %d to %d?\n", cts->protocol_version, 2598195534Sscottl device->protocol_version); 2599195534Sscottl } 2600195534Sscottl cts->protocol_version = device->protocol_version; 2601195534Sscottl } 2602195534Sscottl 2603195534Sscottl if (cts->transport == XPORT_UNKNOWN 2604195534Sscottl || cts->transport == XPORT_UNSPECIFIED) { 2605195534Sscottl cts->transport = device->transport; 2606195534Sscottl cts->transport_version = device->transport_version; 2607195534Sscottl } 2608195534Sscottl 2609195534Sscottl if (cts->transport_version == XPORT_VERSION_UNKNOWN 2610195534Sscottl || cts->transport_version == XPORT_VERSION_UNSPECIFIED) 2611195534Sscottl cts->transport_version = device->transport_version; 2612195534Sscottl 2613195534Sscottl if (cts->transport != device->transport) { 2614256843Smav xpt_print(path, "Uninitialized Transport %x:%x?\n", 2615195534Sscottl cts->transport, device->transport); 2616195534Sscottl cts->transport = device->transport; 2617195534Sscottl } 2618195534Sscottl 2619195534Sscottl if (cts->transport_version > device->transport_version) { 2620195534Sscottl if (bootverbose) { 2621256843Smav xpt_print(path, "Down reving Transport " 2622195534Sscottl "Version from %d to %d?\n", cts->transport_version, 2623195534Sscottl device->transport_version); 2624195534Sscottl } 2625195534Sscottl cts->transport_version = device->transport_version; 2626195534Sscottl } 2627195534Sscottl 2628195534Sscottl /* 2629195534Sscottl * Nothing more of interest to do unless 2630195534Sscottl * this is a device connected via the 2631195534Sscottl * SCSI protocol. 2632195534Sscottl */ 2633195534Sscottl if (cts->protocol != PROTO_SCSI) { 2634195534Sscottl if (async_update == FALSE) 2635256843Smav xpt_action_default((union ccb *)cts); 2636195534Sscottl return; 2637195534Sscottl } 2638195534Sscottl 2639195534Sscottl inq_data = &device->inq_data; 2640195534Sscottl scsi = &cts->proto_specific.scsi; 2641256843Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 2642195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 2643195534Sscottl xpt_action((union ccb *)&cpi); 2644195534Sscottl 2645195534Sscottl /* SCSI specific sanity checking */ 2646195534Sscottl if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0 2647195534Sscottl || (INQ_DATA_TQ_ENABLED(inq_data)) == 0 2648195534Sscottl || (device->queue_flags & SCP_QUEUE_DQUE) != 0 2649195534Sscottl || (device->mintags == 0)) { 2650195534Sscottl /* 2651195534Sscottl * Can't tag on hardware that doesn't support tags, 2652195534Sscottl * doesn't have it enabled, or has broken tag support. 2653195534Sscottl */ 2654195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 2655195534Sscottl } 2656195534Sscottl 2657195534Sscottl if (async_update == FALSE) { 2658195534Sscottl /* 2659195534Sscottl * Perform sanity checking against what the 2660195534Sscottl * controller and device can do. 2661195534Sscottl */ 2662256843Smav xpt_setup_ccb(&cur_cts.ccb_h, path, CAM_PRIORITY_NONE); 2663195534Sscottl cur_cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 2664195534Sscottl cur_cts.type = cts->type; 2665195534Sscottl xpt_action((union ccb *)&cur_cts); 2666252382Sscottl if (cam_ccb_status((union ccb *)&cur_cts) != CAM_REQ_CMP) { 2667195534Sscottl return; 2668195534Sscottl } 2669195534Sscottl cur_scsi = &cur_cts.proto_specific.scsi; 2670195534Sscottl if ((scsi->valid & CTS_SCSI_VALID_TQ) == 0) { 2671195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 2672195534Sscottl scsi->flags |= cur_scsi->flags & CTS_SCSI_FLAGS_TAG_ENB; 2673195534Sscottl } 2674195534Sscottl if ((cur_scsi->valid & CTS_SCSI_VALID_TQ) == 0) 2675195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 2676195534Sscottl } 2677195534Sscottl 2678195534Sscottl /* SPI specific sanity checking */ 2679195534Sscottl if (cts->transport == XPORT_SPI && async_update == FALSE) { 2680195534Sscottl u_int spi3caps; 2681195534Sscottl struct ccb_trans_settings_spi *spi; 2682195534Sscottl struct ccb_trans_settings_spi *cur_spi; 2683195534Sscottl 2684195534Sscottl spi = &cts->xport_specific.spi; 2685195534Sscottl 2686195534Sscottl cur_spi = &cur_cts.xport_specific.spi; 2687195534Sscottl 2688195534Sscottl /* Fill in any gaps in what the user gave us */ 2689195534Sscottl if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) 2690195534Sscottl spi->sync_period = cur_spi->sync_period; 2691195534Sscottl if ((cur_spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) 2692195534Sscottl spi->sync_period = 0; 2693195534Sscottl if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0) 2694195534Sscottl spi->sync_offset = cur_spi->sync_offset; 2695195534Sscottl if ((cur_spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0) 2696195534Sscottl spi->sync_offset = 0; 2697195534Sscottl if ((spi->valid & CTS_SPI_VALID_PPR_OPTIONS) == 0) 2698195534Sscottl spi->ppr_options = cur_spi->ppr_options; 2699195534Sscottl if ((cur_spi->valid & CTS_SPI_VALID_PPR_OPTIONS) == 0) 2700195534Sscottl spi->ppr_options = 0; 2701195534Sscottl if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) == 0) 2702195534Sscottl spi->bus_width = cur_spi->bus_width; 2703195534Sscottl if ((cur_spi->valid & CTS_SPI_VALID_BUS_WIDTH) == 0) 2704195534Sscottl spi->bus_width = 0; 2705195534Sscottl if ((spi->valid & CTS_SPI_VALID_DISC) == 0) { 2706195534Sscottl spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; 2707195534Sscottl spi->flags |= cur_spi->flags & CTS_SPI_FLAGS_DISC_ENB; 2708195534Sscottl } 2709195534Sscottl if ((cur_spi->valid & CTS_SPI_VALID_DISC) == 0) 2710195534Sscottl spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; 2711195534Sscottl if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0 2712195534Sscottl && (inq_data->flags & SID_Sync) == 0 2713195534Sscottl && cts->type == CTS_TYPE_CURRENT_SETTINGS) 2714195534Sscottl || ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0)) { 2715195534Sscottl /* Force async */ 2716195534Sscottl spi->sync_period = 0; 2717195534Sscottl spi->sync_offset = 0; 2718195534Sscottl } 2719195534Sscottl 2720195534Sscottl switch (spi->bus_width) { 2721195534Sscottl case MSG_EXT_WDTR_BUS_32_BIT: 2722195534Sscottl if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) == 0 2723195534Sscottl || (inq_data->flags & SID_WBus32) != 0 2724195534Sscottl || cts->type == CTS_TYPE_USER_SETTINGS) 2725195534Sscottl && (cpi.hba_inquiry & PI_WIDE_32) != 0) 2726195534Sscottl break; 2727195534Sscottl /* Fall Through to 16-bit */ 2728195534Sscottl case MSG_EXT_WDTR_BUS_16_BIT: 2729195534Sscottl if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) == 0 2730195534Sscottl || (inq_data->flags & SID_WBus16) != 0 2731195534Sscottl || cts->type == CTS_TYPE_USER_SETTINGS) 2732195534Sscottl && (cpi.hba_inquiry & PI_WIDE_16) != 0) { 2733195534Sscottl spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT; 2734195534Sscottl break; 2735195534Sscottl } 2736195534Sscottl /* Fall Through to 8-bit */ 2737195534Sscottl default: /* New bus width?? */ 2738195534Sscottl case MSG_EXT_WDTR_BUS_8_BIT: 2739195534Sscottl /* All targets can do this */ 2740195534Sscottl spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT; 2741195534Sscottl break; 2742195534Sscottl } 2743195534Sscottl 2744195534Sscottl spi3caps = cpi.xport_specific.spi.ppr_options; 2745195534Sscottl if ((device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0 2746195534Sscottl && cts->type == CTS_TYPE_CURRENT_SETTINGS) 2747195534Sscottl spi3caps &= inq_data->spi3data; 2748195534Sscottl 2749195534Sscottl if ((spi3caps & SID_SPI_CLOCK_DT) == 0) 2750195534Sscottl spi->ppr_options &= ~MSG_EXT_PPR_DT_REQ; 2751195534Sscottl 2752195534Sscottl if ((spi3caps & SID_SPI_IUS) == 0) 2753195534Sscottl spi->ppr_options &= ~MSG_EXT_PPR_IU_REQ; 2754195534Sscottl 2755195534Sscottl if ((spi3caps & SID_SPI_QAS) == 0) 2756195534Sscottl spi->ppr_options &= ~MSG_EXT_PPR_QAS_REQ; 2757195534Sscottl 2758195534Sscottl /* No SPI Transfer settings are allowed unless we are wide */ 2759195534Sscottl if (spi->bus_width == 0) 2760195534Sscottl spi->ppr_options = 0; 2761195534Sscottl 2762195534Sscottl if ((spi->valid & CTS_SPI_VALID_DISC) 2763195534Sscottl && ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) == 0)) { 2764195534Sscottl /* 2765195534Sscottl * Can't tag queue without disconnection. 2766195534Sscottl */ 2767195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 2768195534Sscottl scsi->valid |= CTS_SCSI_VALID_TQ; 2769195534Sscottl } 2770195534Sscottl 2771195534Sscottl /* 2772195534Sscottl * If we are currently performing tagged transactions to 2773195534Sscottl * this device and want to change its negotiation parameters, 2774195534Sscottl * go non-tagged for a bit to give the controller a chance to 2775195534Sscottl * negotiate unhampered by tag messages. 2776195534Sscottl */ 2777195534Sscottl if (cts->type == CTS_TYPE_CURRENT_SETTINGS 2778195534Sscottl && (device->inq_flags & SID_CmdQue) != 0 2779195534Sscottl && (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0 2780195534Sscottl && (spi->flags & (CTS_SPI_VALID_SYNC_RATE| 2781195534Sscottl CTS_SPI_VALID_SYNC_OFFSET| 2782195534Sscottl CTS_SPI_VALID_BUS_WIDTH)) != 0) 2783256843Smav scsi_toggle_tags(path); 2784195534Sscottl } 2785195534Sscottl 2786195534Sscottl if (cts->type == CTS_TYPE_CURRENT_SETTINGS 2787195534Sscottl && (scsi->valid & CTS_SCSI_VALID_TQ) != 0) { 2788195534Sscottl int device_tagenb; 2789195534Sscottl 2790195534Sscottl /* 2791195534Sscottl * If we are transitioning from tags to no-tags or 2792195534Sscottl * vice-versa, we need to carefully freeze and restart 2793195534Sscottl * the queue so that we don't overlap tagged and non-tagged 2794195534Sscottl * commands. We also temporarily stop tags if there is 2795195534Sscottl * a change in transfer negotiation settings to allow 2796195534Sscottl * "tag-less" negotiation. 2797195534Sscottl */ 2798195534Sscottl if ((device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 2799195534Sscottl || (device->inq_flags & SID_CmdQue) != 0) 2800195534Sscottl device_tagenb = TRUE; 2801195534Sscottl else 2802195534Sscottl device_tagenb = FALSE; 2803195534Sscottl 2804195534Sscottl if (((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0 2805195534Sscottl && device_tagenb == FALSE) 2806195534Sscottl || ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) == 0 2807195534Sscottl && device_tagenb == TRUE)) { 2808195534Sscottl 2809195534Sscottl if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) { 2810195534Sscottl /* 2811195534Sscottl * Delay change to use tags until after a 2812195534Sscottl * few commands have gone to this device so 2813195534Sscottl * the controller has time to perform transfer 2814195534Sscottl * negotiations without tagged messages getting 2815195534Sscottl * in the way. 2816195534Sscottl */ 2817195534Sscottl device->tag_delay_count = CAM_TAG_DELAY_COUNT; 2818195534Sscottl device->flags |= CAM_DEV_TAG_AFTER_COUNT; 2819195534Sscottl } else { 2820256843Smav xpt_stop_tags(path); 2821195534Sscottl } 2822195534Sscottl } 2823195534Sscottl } 2824195534Sscottl if (async_update == FALSE) 2825256843Smav xpt_action_default((union ccb *)cts); 2826195534Sscottl} 2827195534Sscottl 2828195534Sscottlstatic void 2829195534Sscottlscsi_toggle_tags(struct cam_path *path) 2830195534Sscottl{ 2831195534Sscottl struct cam_ed *dev; 2832195534Sscottl 2833195534Sscottl /* 2834195534Sscottl * Give controllers a chance to renegotiate 2835195534Sscottl * before starting tag operations. We 2836195534Sscottl * "toggle" tagged queuing off then on 2837195534Sscottl * which causes the tag enable command delay 2838195534Sscottl * counter to come into effect. 2839195534Sscottl */ 2840195534Sscottl dev = path->device; 2841195534Sscottl if ((dev->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 2842195534Sscottl || ((dev->inq_flags & SID_CmdQue) != 0 2843195534Sscottl && (dev->inq_flags & (SID_Sync|SID_WBus16|SID_WBus32)) != 0)) { 2844195534Sscottl struct ccb_trans_settings cts; 2845195534Sscottl 2846203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 2847195534Sscottl cts.protocol = PROTO_SCSI; 2848195534Sscottl cts.protocol_version = PROTO_VERSION_UNSPECIFIED; 2849195534Sscottl cts.transport = XPORT_UNSPECIFIED; 2850195534Sscottl cts.transport_version = XPORT_VERSION_UNSPECIFIED; 2851195534Sscottl cts.proto_specific.scsi.flags = 0; 2852195534Sscottl cts.proto_specific.scsi.valid = CTS_SCSI_VALID_TQ; 2853256843Smav scsi_set_transfer_settings(&cts, path, 2854195534Sscottl /*async_update*/TRUE); 2855195534Sscottl cts.proto_specific.scsi.flags = CTS_SCSI_FLAGS_TAG_ENB; 2856256843Smav scsi_set_transfer_settings(&cts, path, 2857195534Sscottl /*async_update*/TRUE); 2858195534Sscottl } 2859195534Sscottl} 2860195534Sscottl 2861195534Sscottl/* 2862195534Sscottl * Handle any per-device event notifications that require action by the XPT. 2863195534Sscottl */ 2864195534Sscottlstatic void 2865195534Sscottlscsi_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target, 2866195534Sscottl struct cam_ed *device, void *async_arg) 2867195534Sscottl{ 2868195534Sscottl cam_status status; 2869195534Sscottl struct cam_path newpath; 2870195534Sscottl 2871195534Sscottl /* 2872195534Sscottl * We only need to handle events for real devices. 2873195534Sscottl */ 2874195534Sscottl if (target->target_id == CAM_TARGET_WILDCARD 2875195534Sscottl || device->lun_id == CAM_LUN_WILDCARD) 2876195534Sscottl return; 2877195534Sscottl 2878195534Sscottl /* 2879195534Sscottl * We need our own path with wildcards expanded to 2880195534Sscottl * handle certain types of events. 2881195534Sscottl */ 2882195534Sscottl if ((async_code == AC_SENT_BDR) 2883195534Sscottl || (async_code == AC_BUS_RESET) 2884195534Sscottl || (async_code == AC_INQ_CHANGED)) 2885195534Sscottl status = xpt_compile_path(&newpath, NULL, 2886195534Sscottl bus->path_id, 2887195534Sscottl target->target_id, 2888195534Sscottl device->lun_id); 2889195534Sscottl else 2890195534Sscottl status = CAM_REQ_CMP_ERR; 2891195534Sscottl 2892195534Sscottl if (status == CAM_REQ_CMP) { 2893195534Sscottl 2894195534Sscottl /* 2895195534Sscottl * Allow transfer negotiation to occur in a 2896203108Smav * tag free environment and after settle delay. 2897195534Sscottl */ 2898195534Sscottl if (async_code == AC_SENT_BDR 2899203108Smav || async_code == AC_BUS_RESET) { 2900203108Smav cam_freeze_devq(&newpath); 2901203108Smav cam_release_devq(&newpath, 2902203108Smav RELSIM_RELEASE_AFTER_TIMEOUT, 2903203108Smav /*reduction*/0, 2904203108Smav /*timeout*/scsi_delay, 2905203108Smav /*getcount_only*/0); 2906195534Sscottl scsi_toggle_tags(&newpath); 2907203108Smav } 2908195534Sscottl 2909195534Sscottl if (async_code == AC_INQ_CHANGED) { 2910195534Sscottl /* 2911195534Sscottl * We've sent a start unit command, or 2912195534Sscottl * something similar to a device that 2913195534Sscottl * may have caused its inquiry data to 2914195534Sscottl * change. So we re-scan the device to 2915195534Sscottl * refresh the inquiry data for it. 2916195534Sscottl */ 2917195534Sscottl scsi_scan_lun(newpath.periph, &newpath, 2918195534Sscottl CAM_EXPECT_INQ_CHANGE, NULL); 2919195534Sscottl } 2920195534Sscottl xpt_release_path(&newpath); 2921198748Smav } else if (async_code == AC_LOST_DEVICE && 2922198748Smav (device->flags & CAM_DEV_UNCONFIGURED) == 0) { 2923195534Sscottl device->flags |= CAM_DEV_UNCONFIGURED; 2924198748Smav xpt_release_device(device); 2925195534Sscottl } else if (async_code == AC_TRANSFER_NEG) { 2926195534Sscottl struct ccb_trans_settings *settings; 2927256843Smav struct cam_path path; 2928195534Sscottl 2929195534Sscottl settings = (struct ccb_trans_settings *)async_arg; 2930256843Smav xpt_compile_path(&path, NULL, bus->path_id, target->target_id, 2931256843Smav device->lun_id); 2932256843Smav scsi_set_transfer_settings(settings, &path, 2933195534Sscottl /*async_update*/TRUE); 2934256843Smav xpt_release_path(&path); 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 2948256843Smav cam_periph_assert(periph, 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