scsi_xpt.c revision 195685
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 195685 2009-07-14 17:26:37Z emaste $"); 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#ifdef PC98 51195534Sscottl#include <pc98/pc98/pc98_machdep.h> /* geometry translation */ 52195534Sscottl#endif 53195534Sscottl 54195534Sscottl#include <cam/cam.h> 55195534Sscottl#include <cam/cam_ccb.h> 56195534Sscottl#include <cam/cam_queue.h> 57195534Sscottl#include <cam/cam_periph.h> 58195534Sscottl#include <cam/cam_sim.h> 59195534Sscottl#include <cam/cam_xpt.h> 60195534Sscottl#include <cam/cam_xpt_sim.h> 61195534Sscottl#include <cam/cam_xpt_periph.h> 62195534Sscottl#include <cam/cam_xpt_internal.h> 63195534Sscottl#include <cam/cam_debug.h> 64195534Sscottl 65195534Sscottl#include <cam/scsi/scsi_all.h> 66195534Sscottl#include <cam/scsi/scsi_message.h> 67195534Sscottl#include <cam/scsi/scsi_pass.h> 68195534Sscottl#include <machine/stdarg.h> /* for xpt_print below */ 69195534Sscottl#include "opt_cam.h" 70195534Sscottl 71195534Sscottlstruct scsi_quirk_entry { 72195534Sscottl struct scsi_inquiry_pattern inq_pat; 73195534Sscottl u_int8_t quirks; 74195534Sscottl#define CAM_QUIRK_NOLUNS 0x01 75195534Sscottl#define CAM_QUIRK_NOSERIAL 0x02 76195534Sscottl#define CAM_QUIRK_HILUNS 0x04 77195534Sscottl#define CAM_QUIRK_NOHILUNS 0x08 78195534Sscottl u_int mintags; 79195534Sscottl u_int maxtags; 80195534Sscottl}; 81195534Sscottl#define SCSI_QUIRK(dev) ((struct scsi_quirk_entry *)((dev)->quirk)) 82195534Sscottl 83195534Sscottlstatic int cam_srch_hi = 0; 84195534SscottlTUNABLE_INT("kern.cam.cam_srch_hi", &cam_srch_hi); 85195534Sscottlstatic int sysctl_cam_search_luns(SYSCTL_HANDLER_ARGS); 86195534SscottlSYSCTL_PROC(_kern_cam, OID_AUTO, cam_srch_hi, CTLTYPE_INT|CTLFLAG_RW, 0, 0, 87195534Sscottl sysctl_cam_search_luns, "I", 88195534Sscottl "allow search above LUN 7 for SCSI3 and greater devices"); 89195534Sscottl 90195534Sscottl#define CAM_SCSI2_MAXLUN 8 91195534Sscottl/* 92195534Sscottl * If we're not quirked to search <= the first 8 luns 93195534Sscottl * and we are either quirked to search above lun 8, 94195534Sscottl * or we're > SCSI-2 and we've enabled hilun searching, 95195534Sscottl * or we're > SCSI-2 and the last lun was a success, 96195534Sscottl * we can look for luns above lun 8. 97195534Sscottl */ 98195534Sscottl#define CAN_SRCH_HI_SPARSE(dv) \ 99195534Sscottl (((SCSI_QUIRK(dv)->quirks & CAM_QUIRK_NOHILUNS) == 0) \ 100195534Sscottl && ((SCSI_QUIRK(dv)->quirks & CAM_QUIRK_HILUNS) \ 101195534Sscottl || (SID_ANSI_REV(&dv->inq_data) > SCSI_REV_2 && cam_srch_hi))) 102195534Sscottl 103195534Sscottl#define CAN_SRCH_HI_DENSE(dv) \ 104195534Sscottl (((SCSI_QUIRK(dv)->quirks & CAM_QUIRK_NOHILUNS) == 0) \ 105195534Sscottl && ((SCSI_QUIRK(dv)->quirks & CAM_QUIRK_HILUNS) \ 106195534Sscottl || (SID_ANSI_REV(&dv->inq_data) > SCSI_REV_2))) 107195534Sscottl 108195534Sscottlstatic periph_init_t probe_periph_init; 109195534Sscottl 110195534Sscottlstatic struct periph_driver probe_driver = 111195534Sscottl{ 112195534Sscottl probe_periph_init, "probe", 113195534Sscottl TAILQ_HEAD_INITIALIZER(probe_driver.units) 114195534Sscottl}; 115195534Sscottl 116195534SscottlPERIPHDRIVER_DECLARE(probe, probe_driver); 117195534Sscottl 118195534Sscottltypedef enum { 119195534Sscottl PROBE_TUR, 120195534Sscottl PROBE_INQUIRY, /* this counts as DV0 for Basic Domain Validation */ 121195534Sscottl PROBE_FULL_INQUIRY, 122195534Sscottl PROBE_MODE_SENSE, 123195534Sscottl PROBE_SERIAL_NUM_0, 124195534Sscottl PROBE_SERIAL_NUM_1, 125195534Sscottl PROBE_TUR_FOR_NEGOTIATION, 126195534Sscottl PROBE_INQUIRY_BASIC_DV1, 127195534Sscottl PROBE_INQUIRY_BASIC_DV2, 128195534Sscottl PROBE_DV_EXIT, 129195534Sscottl PROBE_INVALID 130195534Sscottl} probe_action; 131195534Sscottl 132195534Sscottlstatic char *probe_action_text[] = { 133195534Sscottl "PROBE_TUR", 134195534Sscottl "PROBE_INQUIRY", 135195534Sscottl "PROBE_FULL_INQUIRY", 136195534Sscottl "PROBE_MODE_SENSE", 137195534Sscottl "PROBE_SERIAL_NUM_0", 138195534Sscottl "PROBE_SERIAL_NUM_1", 139195534Sscottl "PROBE_TUR_FOR_NEGOTIATION", 140195534Sscottl "PROBE_INQUIRY_BASIC_DV1", 141195534Sscottl "PROBE_INQUIRY_BASIC_DV2", 142195534Sscottl "PROBE_DV_EXIT", 143195534Sscottl "PROBE_INVALID" 144195534Sscottl}; 145195534Sscottl 146195534Sscottl#define PROBE_SET_ACTION(softc, newaction) \ 147195534Sscottldo { \ 148195534Sscottl char **text; \ 149195534Sscottl text = probe_action_text; \ 150195534Sscottl CAM_DEBUG((softc)->periph->path, CAM_DEBUG_INFO, \ 151195534Sscottl ("Probe %s to %s\n", text[(softc)->action], \ 152195534Sscottl text[(newaction)])); \ 153195534Sscottl (softc)->action = (newaction); \ 154195534Sscottl} while(0) 155195534Sscottl 156195534Sscottltypedef enum { 157195534Sscottl PROBE_INQUIRY_CKSUM = 0x01, 158195534Sscottl PROBE_SERIAL_CKSUM = 0x02, 159195534Sscottl PROBE_NO_ANNOUNCE = 0x04 160195534Sscottl} probe_flags; 161195534Sscottl 162195534Sscottltypedef struct { 163195534Sscottl TAILQ_HEAD(, ccb_hdr) request_ccbs; 164195534Sscottl probe_action action; 165195534Sscottl union ccb saved_ccb; 166195534Sscottl probe_flags flags; 167195534Sscottl MD5_CTX context; 168195534Sscottl u_int8_t digest[16]; 169195534Sscottl struct cam_periph *periph; 170195534Sscottl} probe_softc; 171195534Sscottl 172195534Sscottlstatic const char quantum[] = "QUANTUM"; 173195534Sscottlstatic const char sony[] = "SONY"; 174195534Sscottlstatic const char west_digital[] = "WDIGTL"; 175195534Sscottlstatic const char samsung[] = "SAMSUNG"; 176195534Sscottlstatic const char seagate[] = "SEAGATE"; 177195534Sscottlstatic const char microp[] = "MICROP"; 178195534Sscottl 179195534Sscottlstatic struct scsi_quirk_entry scsi_quirk_table[] = 180195534Sscottl{ 181195534Sscottl { 182195534Sscottl /* Reports QUEUE FULL for temporary resource shortages */ 183195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, quantum, "XP39100*", "*" }, 184195534Sscottl /*quirks*/0, /*mintags*/24, /*maxtags*/32 185195534Sscottl }, 186195534Sscottl { 187195534Sscottl /* Reports QUEUE FULL for temporary resource shortages */ 188195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, quantum, "XP34550*", "*" }, 189195534Sscottl /*quirks*/0, /*mintags*/24, /*maxtags*/32 190195534Sscottl }, 191195534Sscottl { 192195534Sscottl /* Reports QUEUE FULL for temporary resource shortages */ 193195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, quantum, "XP32275*", "*" }, 194195534Sscottl /*quirks*/0, /*mintags*/24, /*maxtags*/32 195195534Sscottl }, 196195534Sscottl { 197195534Sscottl /* Broken tagged queuing drive */ 198195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, microp, "4421-07*", "*" }, 199195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 200195534Sscottl }, 201195534Sscottl { 202195534Sscottl /* Broken tagged queuing drive */ 203195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "HP", "C372*", "*" }, 204195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 205195534Sscottl }, 206195534Sscottl { 207195534Sscottl /* Broken tagged queuing drive */ 208195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, microp, "3391*", "x43h" }, 209195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 210195534Sscottl }, 211195534Sscottl { 212195534Sscottl /* 213195534Sscottl * Unfortunately, the Quantum Atlas III has the same 214195534Sscottl * problem as the Atlas II drives above. 215195534Sscottl * Reported by: "Johan Granlund" <johan@granlund.nu> 216195534Sscottl * 217195534Sscottl * For future reference, the drive with the problem was: 218195534Sscottl * QUANTUM QM39100TD-SW N1B0 219195534Sscottl * 220195534Sscottl * It's possible that Quantum will fix the problem in later 221195534Sscottl * firmware revisions. If that happens, the quirk entry 222195534Sscottl * will need to be made specific to the firmware revisions 223195534Sscottl * with the problem. 224195534Sscottl * 225195534Sscottl */ 226195534Sscottl /* Reports QUEUE FULL for temporary resource shortages */ 227195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, quantum, "QM39100*", "*" }, 228195534Sscottl /*quirks*/0, /*mintags*/24, /*maxtags*/32 229195534Sscottl }, 230195534Sscottl { 231195534Sscottl /* 232195534Sscottl * 18 Gig Atlas III, same problem as the 9G version. 233195534Sscottl * Reported by: Andre Albsmeier 234195534Sscottl * <andre.albsmeier@mchp.siemens.de> 235195534Sscottl * 236195534Sscottl * For future reference, the drive with the problem was: 237195534Sscottl * QUANTUM QM318000TD-S N491 238195534Sscottl */ 239195534Sscottl /* Reports QUEUE FULL for temporary resource shortages */ 240195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, quantum, "QM318000*", "*" }, 241195534Sscottl /*quirks*/0, /*mintags*/24, /*maxtags*/32 242195534Sscottl }, 243195534Sscottl { 244195534Sscottl /* 245195534Sscottl * Broken tagged queuing drive 246195534Sscottl * Reported by: Bret Ford <bford@uop.cs.uop.edu> 247195534Sscottl * and: Martin Renters <martin@tdc.on.ca> 248195534Sscottl */ 249195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST410800*", "71*" }, 250195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 251195534Sscottl }, 252195534Sscottl /* 253195534Sscottl * The Seagate Medalist Pro drives have very poor write 254195534Sscottl * performance with anything more than 2 tags. 255195534Sscottl * 256195534Sscottl * Reported by: Paul van der Zwan <paulz@trantor.xs4all.nl> 257195534Sscottl * Drive: <SEAGATE ST36530N 1444> 258195534Sscottl * 259195534Sscottl * Reported by: Jeremy Lea <reg@shale.csir.co.za> 260195534Sscottl * Drive: <SEAGATE ST34520W 1281> 261195534Sscottl * 262195534Sscottl * No one has actually reported that the 9G version 263195534Sscottl * (ST39140*) of the Medalist Pro has the same problem, but 264195534Sscottl * we're assuming that it does because the 4G and 6.5G 265195534Sscottl * versions of the drive are broken. 266195534Sscottl */ 267195534Sscottl { 268195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST34520*", "*"}, 269195534Sscottl /*quirks*/0, /*mintags*/2, /*maxtags*/2 270195534Sscottl }, 271195534Sscottl { 272195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST36530*", "*"}, 273195534Sscottl /*quirks*/0, /*mintags*/2, /*maxtags*/2 274195534Sscottl }, 275195534Sscottl { 276195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST39140*", "*"}, 277195534Sscottl /*quirks*/0, /*mintags*/2, /*maxtags*/2 278195534Sscottl }, 279195534Sscottl { 280195534Sscottl /* 281195534Sscottl * Slow when tagged queueing is enabled. Write performance 282195534Sscottl * steadily drops off with more and more concurrent 283195534Sscottl * transactions. Best sequential write performance with 284195534Sscottl * tagged queueing turned off and write caching turned on. 285195534Sscottl * 286195534Sscottl * PR: kern/10398 287195534Sscottl * Submitted by: Hideaki Okada <hokada@isl.melco.co.jp> 288195534Sscottl * Drive: DCAS-34330 w/ "S65A" firmware. 289195534Sscottl * 290195534Sscottl * The drive with the problem had the "S65A" firmware 291195534Sscottl * revision, and has also been reported (by Stephen J. 292195534Sscottl * Roznowski <sjr@home.net>) for a drive with the "S61A" 293195534Sscottl * firmware revision. 294195534Sscottl * 295195534Sscottl * Although no one has reported problems with the 2 gig 296195534Sscottl * version of the DCAS drive, the assumption is that it 297195534Sscottl * has the same problems as the 4 gig version. Therefore 298195534Sscottl * this quirk entries disables tagged queueing for all 299195534Sscottl * DCAS drives. 300195534Sscottl */ 301195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "IBM", "DCAS*", "*" }, 302195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 303195534Sscottl }, 304195534Sscottl { 305195534Sscottl /* Broken tagged queuing drive */ 306195534Sscottl { T_DIRECT, SIP_MEDIA_REMOVABLE, "iomega", "jaz*", "*" }, 307195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 308195534Sscottl }, 309195534Sscottl { 310195534Sscottl /* Broken tagged queuing drive */ 311195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "CONNER", "CFP2107*", "*" }, 312195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 313195534Sscottl }, 314195534Sscottl { 315195534Sscottl /* This does not support other than LUN 0 */ 316195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "VMware*", "*", "*" }, 317195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/2, /*maxtags*/255 318195534Sscottl }, 319195534Sscottl { 320195534Sscottl /* 321195534Sscottl * Broken tagged queuing drive. 322195534Sscottl * Submitted by: 323195534Sscottl * NAKAJI Hiroyuki <nakaji@zeisei.dpri.kyoto-u.ac.jp> 324195534Sscottl * in PR kern/9535 325195534Sscottl */ 326195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, samsung, "WN34324U*", "*" }, 327195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 328195534Sscottl }, 329195534Sscottl { 330195534Sscottl /* 331195534Sscottl * Slow when tagged queueing is enabled. (1.5MB/sec versus 332195534Sscottl * 8MB/sec.) 333195534Sscottl * Submitted by: Andrew Gallatin <gallatin@cs.duke.edu> 334195534Sscottl * Best performance with these drives is achieved with 335195534Sscottl * tagged queueing turned off, and write caching turned on. 336195534Sscottl */ 337195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, west_digital, "WDE*", "*" }, 338195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 339195534Sscottl }, 340195534Sscottl { 341195534Sscottl /* 342195534Sscottl * Slow when tagged queueing is enabled. (1.5MB/sec versus 343195534Sscottl * 8MB/sec.) 344195534Sscottl * Submitted by: Andrew Gallatin <gallatin@cs.duke.edu> 345195534Sscottl * Best performance with these drives is achieved with 346195534Sscottl * tagged queueing turned off, and write caching turned on. 347195534Sscottl */ 348195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, west_digital, "ENTERPRISE", "*" }, 349195534Sscottl /*quirks*/0, /*mintags*/0, /*maxtags*/0 350195534Sscottl }, 351195534Sscottl { 352195534Sscottl /* 353195534Sscottl * Doesn't handle queue full condition correctly, 354195534Sscottl * so we need to limit maxtags to what the device 355195534Sscottl * can handle instead of determining this automatically. 356195534Sscottl */ 357195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, samsung, "WN321010S*", "*" }, 358195534Sscottl /*quirks*/0, /*mintags*/2, /*maxtags*/32 359195534Sscottl }, 360195534Sscottl { 361195534Sscottl /* Really only one LUN */ 362195534Sscottl { T_ENCLOSURE, SIP_MEDIA_FIXED, "SUN", "SENA", "*" }, 363195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 364195534Sscottl }, 365195534Sscottl { 366195534Sscottl /* I can't believe we need a quirk for DPT volumes. */ 367195534Sscottl { T_ANY, SIP_MEDIA_FIXED|SIP_MEDIA_REMOVABLE, "DPT", "*", "*" }, 368195534Sscottl CAM_QUIRK_NOLUNS, 369195534Sscottl /*mintags*/0, /*maxtags*/255 370195534Sscottl }, 371195534Sscottl { 372195534Sscottl /* 373195534Sscottl * Many Sony CDROM drives don't like multi-LUN probing. 374195534Sscottl */ 375195534Sscottl { T_CDROM, SIP_MEDIA_REMOVABLE, sony, "CD-ROM CDU*", "*" }, 376195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 377195534Sscottl }, 378195534Sscottl { 379195534Sscottl /* 380195534Sscottl * This drive doesn't like multiple LUN probing. 381195534Sscottl * Submitted by: Parag Patel <parag@cgt.com> 382195534Sscottl */ 383195534Sscottl { T_WORM, SIP_MEDIA_REMOVABLE, sony, "CD-R CDU9*", "*" }, 384195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 385195534Sscottl }, 386195534Sscottl { 387195534Sscottl { T_WORM, SIP_MEDIA_REMOVABLE, "YAMAHA", "CDR100*", "*" }, 388195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 389195534Sscottl }, 390195534Sscottl { 391195534Sscottl /* 392195534Sscottl * The 8200 doesn't like multi-lun probing, and probably 393195534Sscottl * don't like serial number requests either. 394195534Sscottl */ 395195534Sscottl { 396195534Sscottl T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "EXABYTE", 397195534Sscottl "EXB-8200*", "*" 398195534Sscottl }, 399195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 400195534Sscottl }, 401195534Sscottl { 402195534Sscottl /* 403195534Sscottl * Let's try the same as above, but for a drive that says 404195534Sscottl * it's an IPL-6860 but is actually an EXB 8200. 405195534Sscottl */ 406195534Sscottl { 407195534Sscottl T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "EXABYTE", 408195534Sscottl "IPL-6860*", "*" 409195534Sscottl }, 410195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 411195534Sscottl }, 412195534Sscottl { 413195534Sscottl /* 414195534Sscottl * These Hitachi drives don't like multi-lun probing. 415195534Sscottl * The PR submitter has a DK319H, but says that the Linux 416195534Sscottl * kernel has a similar work-around for the DK312 and DK314, 417195534Sscottl * so all DK31* drives are quirked here. 418195534Sscottl * PR: misc/18793 419195534Sscottl * Submitted by: Paul Haddad <paul@pth.com> 420195534Sscottl */ 421195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "HITACHI", "DK31*", "*" }, 422195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/2, /*maxtags*/255 423195534Sscottl }, 424195534Sscottl { 425195534Sscottl /* 426195534Sscottl * The Hitachi CJ series with J8A8 firmware apparantly has 427195534Sscottl * problems with tagged commands. 428195534Sscottl * PR: 23536 429195534Sscottl * Reported by: amagai@nue.org 430195534Sscottl */ 431195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "HITACHI", "DK32CJ*", "J8A8" }, 432195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 433195534Sscottl }, 434195534Sscottl { 435195534Sscottl /* 436195534Sscottl * These are the large storage arrays. 437195534Sscottl * Submitted by: William Carrel <william.carrel@infospace.com> 438195534Sscottl */ 439195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "HITACHI", "OPEN*", "*" }, 440195534Sscottl CAM_QUIRK_HILUNS, 2, 1024 441195534Sscottl }, 442195534Sscottl { 443195534Sscottl /* 444195534Sscottl * This old revision of the TDC3600 is also SCSI-1, and 445195534Sscottl * hangs upon serial number probing. 446195534Sscottl */ 447195534Sscottl { 448195534Sscottl T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG", 449195534Sscottl " TDC 3600", "U07:" 450195534Sscottl }, 451195534Sscottl CAM_QUIRK_NOSERIAL, /*mintags*/0, /*maxtags*/0 452195534Sscottl }, 453195534Sscottl { 454195534Sscottl /* 455195534Sscottl * Would repond to all LUNs if asked for. 456195534Sscottl */ 457195534Sscottl { 458195534Sscottl T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "CALIPER", 459195534Sscottl "CP150", "*" 460195534Sscottl }, 461195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 462195534Sscottl }, 463195534Sscottl { 464195534Sscottl /* 465195534Sscottl * Would repond to all LUNs if asked for. 466195534Sscottl */ 467195534Sscottl { 468195534Sscottl T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "KENNEDY", 469195534Sscottl "96X2*", "*" 470195534Sscottl }, 471195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 472195534Sscottl }, 473195534Sscottl { 474195534Sscottl /* Submitted by: Matthew Dodd <winter@jurai.net> */ 475195534Sscottl { T_PROCESSOR, SIP_MEDIA_FIXED, "Cabletrn", "EA41*", "*" }, 476195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 477195534Sscottl }, 478195534Sscottl { 479195534Sscottl /* Submitted by: Matthew Dodd <winter@jurai.net> */ 480195534Sscottl { T_PROCESSOR, SIP_MEDIA_FIXED, "CABLETRN", "EA41*", "*" }, 481195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 482195534Sscottl }, 483195534Sscottl { 484195534Sscottl /* TeraSolutions special settings for TRC-22 RAID */ 485195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "TERASOLU", "TRC-22", "*" }, 486195534Sscottl /*quirks*/0, /*mintags*/55, /*maxtags*/255 487195534Sscottl }, 488195534Sscottl { 489195534Sscottl /* Veritas Storage Appliance */ 490195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "VERITAS", "*", "*" }, 491195534Sscottl CAM_QUIRK_HILUNS, /*mintags*/2, /*maxtags*/1024 492195534Sscottl }, 493195534Sscottl { 494195534Sscottl /* 495195534Sscottl * Would respond to all LUNs. Device type and removable 496195534Sscottl * flag are jumper-selectable. 497195534Sscottl */ 498195534Sscottl { T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED, "MaxOptix", 499195534Sscottl "Tahiti 1", "*" 500195534Sscottl }, 501195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 502195534Sscottl }, 503195534Sscottl { 504195534Sscottl /* EasyRAID E5A aka. areca ARC-6010 */ 505195534Sscottl { T_DIRECT, SIP_MEDIA_FIXED, "easyRAID", "*", "*" }, 506195534Sscottl CAM_QUIRK_NOHILUNS, /*mintags*/2, /*maxtags*/255 507195534Sscottl }, 508195534Sscottl { 509195534Sscottl { T_ENCLOSURE, SIP_MEDIA_FIXED, "DP", "BACKPLANE", "*" }, 510195534Sscottl CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 511195534Sscottl }, 512195534Sscottl { 513195534Sscottl /* Default tagged queuing parameters for all devices */ 514195534Sscottl { 515195534Sscottl T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED, 516195534Sscottl /*vendor*/"*", /*product*/"*", /*revision*/"*" 517195534Sscottl }, 518195534Sscottl /*quirks*/0, /*mintags*/2, /*maxtags*/255 519195534Sscottl }, 520195534Sscottl}; 521195534Sscottl 522195534Sscottlstatic const int scsi_quirk_table_size = 523195534Sscottl sizeof(scsi_quirk_table) / sizeof(*scsi_quirk_table); 524195534Sscottl 525195534Sscottlstatic cam_status proberegister(struct cam_periph *periph, 526195534Sscottl void *arg); 527195534Sscottlstatic void probeschedule(struct cam_periph *probe_periph); 528195534Sscottlstatic void probestart(struct cam_periph *periph, union ccb *start_ccb); 529195534Sscottlstatic void proberequestdefaultnegotiation(struct cam_periph *periph); 530195534Sscottlstatic int proberequestbackoff(struct cam_periph *periph, 531195534Sscottl struct cam_ed *device); 532195534Sscottlstatic void probedone(struct cam_periph *periph, union ccb *done_ccb); 533195534Sscottlstatic void probecleanup(struct cam_periph *periph); 534195534Sscottlstatic void scsi_find_quirk(struct cam_ed *device); 535195534Sscottlstatic void scsi_scan_bus(struct cam_periph *periph, union ccb *ccb); 536195534Sscottlstatic void scsi_scan_lun(struct cam_periph *periph, 537195534Sscottl struct cam_path *path, cam_flags flags, 538195534Sscottl union ccb *ccb); 539195534Sscottlstatic void xptscandone(struct cam_periph *periph, union ccb *done_ccb); 540195534Sscottlstatic struct cam_ed * 541195534Sscottl scsi_alloc_device(struct cam_eb *bus, struct cam_et *target, 542195534Sscottl lun_id_t lun_id); 543195534Sscottlstatic void scsi_devise_transport(struct cam_path *path); 544195534Sscottlstatic void scsi_set_transfer_settings(struct ccb_trans_settings *cts, 545195534Sscottl struct cam_ed *device, 546195534Sscottl int async_update); 547195534Sscottlstatic void scsi_toggle_tags(struct cam_path *path); 548195534Sscottlstatic void scsi_dev_async(u_int32_t async_code, 549195534Sscottl struct cam_eb *bus, 550195534Sscottl struct cam_et *target, 551195534Sscottl struct cam_ed *device, 552195534Sscottl void *async_arg); 553195534Sscottlstatic void scsi_action(union ccb *start_ccb); 554195534Sscottl 555195534Sscottlstatic struct xpt_xport scsi_xport = { 556195534Sscottl .alloc_device = scsi_alloc_device, 557195534Sscottl .action = scsi_action, 558195534Sscottl .async = scsi_dev_async, 559195534Sscottl}; 560195534Sscottl 561195534Sscottlstruct xpt_xport * 562195534Sscottlscsi_get_xport(void) 563195534Sscottl{ 564195534Sscottl return (&scsi_xport); 565195534Sscottl} 566195534Sscottl 567195534Sscottlstatic void 568195534Sscottlprobe_periph_init() 569195534Sscottl{ 570195534Sscottl} 571195534Sscottl 572195534Sscottlstatic cam_status 573195534Sscottlproberegister(struct cam_periph *periph, void *arg) 574195534Sscottl{ 575195534Sscottl union ccb *request_ccb; /* CCB representing the probe request */ 576195534Sscottl cam_status status; 577195534Sscottl probe_softc *softc; 578195534Sscottl 579195534Sscottl request_ccb = (union ccb *)arg; 580195534Sscottl if (periph == NULL) { 581195534Sscottl printf("proberegister: periph was NULL!!\n"); 582195534Sscottl return(CAM_REQ_CMP_ERR); 583195534Sscottl } 584195534Sscottl 585195534Sscottl if (request_ccb == NULL) { 586195534Sscottl printf("proberegister: no probe CCB, " 587195534Sscottl "can't register device\n"); 588195534Sscottl return(CAM_REQ_CMP_ERR); 589195534Sscottl } 590195534Sscottl 591195534Sscottl softc = (probe_softc *)malloc(sizeof(*softc), M_CAMXPT, M_NOWAIT); 592195534Sscottl 593195534Sscottl if (softc == NULL) { 594195534Sscottl printf("proberegister: Unable to probe new device. " 595195534Sscottl "Unable to allocate softc\n"); 596195534Sscottl return(CAM_REQ_CMP_ERR); 597195534Sscottl } 598195534Sscottl TAILQ_INIT(&softc->request_ccbs); 599195534Sscottl TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h, 600195534Sscottl periph_links.tqe); 601195534Sscottl softc->flags = 0; 602195534Sscottl periph->softc = softc; 603195534Sscottl softc->periph = periph; 604195534Sscottl softc->action = PROBE_INVALID; 605195534Sscottl status = cam_periph_acquire(periph); 606195534Sscottl if (status != CAM_REQ_CMP) { 607195534Sscottl return (status); 608195534Sscottl } 609195534Sscottl 610195534Sscottl 611195534Sscottl /* 612195534Sscottl * Ensure we've waited at least a bus settle 613195534Sscottl * delay before attempting to probe the device. 614195534Sscottl * For HBAs that don't do bus resets, this won't make a difference. 615195534Sscottl */ 616195534Sscottl cam_periph_freeze_after_event(periph, &periph->path->bus->last_reset, 617195534Sscottl scsi_delay); 618195534Sscottl probeschedule(periph); 619195534Sscottl return(CAM_REQ_CMP); 620195534Sscottl} 621195534Sscottl 622195534Sscottlstatic void 623195534Sscottlprobeschedule(struct cam_periph *periph) 624195534Sscottl{ 625195534Sscottl struct ccb_pathinq cpi; 626195534Sscottl union ccb *ccb; 627195534Sscottl probe_softc *softc; 628195534Sscottl 629195534Sscottl softc = (probe_softc *)periph->softc; 630195534Sscottl ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs); 631195534Sscottl 632195534Sscottl xpt_setup_ccb(&cpi.ccb_h, periph->path, /*priority*/1); 633195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 634195534Sscottl xpt_action((union ccb *)&cpi); 635195534Sscottl 636195534Sscottl /* 637195534Sscottl * If a device has gone away and another device, or the same one, 638195534Sscottl * is back in the same place, it should have a unit attention 639195534Sscottl * condition pending. It will not report the unit attention in 640195534Sscottl * response to an inquiry, which may leave invalid transfer 641195534Sscottl * negotiations in effect. The TUR will reveal the unit attention 642195534Sscottl * condition. Only send the TUR for lun 0, since some devices 643195534Sscottl * will get confused by commands other than inquiry to non-existent 644195534Sscottl * luns. If you think a device has gone away start your scan from 645195534Sscottl * lun 0. This will insure that any bogus transfer settings are 646195534Sscottl * invalidated. 647195534Sscottl * 648195534Sscottl * If we haven't seen the device before and the controller supports 649195534Sscottl * some kind of transfer negotiation, negotiate with the first 650195534Sscottl * sent command if no bus reset was performed at startup. This 651195534Sscottl * ensures that the device is not confused by transfer negotiation 652195534Sscottl * settings left over by loader or BIOS action. 653195534Sscottl */ 654195534Sscottl if (((ccb->ccb_h.path->device->flags & CAM_DEV_UNCONFIGURED) == 0) 655195534Sscottl && (ccb->ccb_h.target_lun == 0)) { 656195534Sscottl PROBE_SET_ACTION(softc, PROBE_TUR); 657195534Sscottl } else if ((cpi.hba_inquiry & (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE)) != 0 658195534Sscottl && (cpi.hba_misc & PIM_NOBUSRESET) != 0) { 659195534Sscottl proberequestdefaultnegotiation(periph); 660195534Sscottl PROBE_SET_ACTION(softc, PROBE_INQUIRY); 661195534Sscottl } else { 662195534Sscottl PROBE_SET_ACTION(softc, PROBE_INQUIRY); 663195534Sscottl } 664195534Sscottl 665195534Sscottl if (ccb->crcn.flags & CAM_EXPECT_INQ_CHANGE) 666195534Sscottl softc->flags |= PROBE_NO_ANNOUNCE; 667195534Sscottl else 668195534Sscottl softc->flags &= ~PROBE_NO_ANNOUNCE; 669195534Sscottl 670195534Sscottl xpt_schedule(periph, ccb->ccb_h.pinfo.priority); 671195534Sscottl} 672195534Sscottl 673195534Sscottlstatic void 674195534Sscottlprobestart(struct cam_periph *periph, union ccb *start_ccb) 675195534Sscottl{ 676195534Sscottl /* Probe the device that our peripheral driver points to */ 677195534Sscottl struct ccb_scsiio *csio; 678195534Sscottl probe_softc *softc; 679195534Sscottl 680195534Sscottl CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probestart\n")); 681195534Sscottl 682195534Sscottl softc = (probe_softc *)periph->softc; 683195534Sscottl csio = &start_ccb->csio; 684195534Sscottl 685195534Sscottl switch (softc->action) { 686195534Sscottl case PROBE_TUR: 687195534Sscottl case PROBE_TUR_FOR_NEGOTIATION: 688195534Sscottl case PROBE_DV_EXIT: 689195534Sscottl { 690195534Sscottl scsi_test_unit_ready(csio, 691195534Sscottl /*retries*/10, 692195534Sscottl probedone, 693195534Sscottl MSG_SIMPLE_Q_TAG, 694195534Sscottl SSD_FULL_SIZE, 695195534Sscottl /*timeout*/60000); 696195534Sscottl break; 697195534Sscottl } 698195534Sscottl case PROBE_INQUIRY: 699195534Sscottl case PROBE_FULL_INQUIRY: 700195534Sscottl case PROBE_INQUIRY_BASIC_DV1: 701195534Sscottl case PROBE_INQUIRY_BASIC_DV2: 702195534Sscottl { 703195534Sscottl u_int inquiry_len; 704195534Sscottl struct scsi_inquiry_data *inq_buf; 705195534Sscottl 706195534Sscottl inq_buf = &periph->path->device->inq_data; 707195534Sscottl 708195534Sscottl /* 709195534Sscottl * If the device is currently configured, we calculate an 710195534Sscottl * MD5 checksum of the inquiry data, and if the serial number 711195534Sscottl * length is greater than 0, add the serial number data 712195534Sscottl * into the checksum as well. Once the inquiry and the 713195534Sscottl * serial number check finish, we attempt to figure out 714195534Sscottl * whether we still have the same device. 715195534Sscottl */ 716195534Sscottl if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) { 717195534Sscottl 718195534Sscottl MD5Init(&softc->context); 719195534Sscottl MD5Update(&softc->context, (unsigned char *)inq_buf, 720195534Sscottl sizeof(struct scsi_inquiry_data)); 721195534Sscottl softc->flags |= PROBE_INQUIRY_CKSUM; 722195534Sscottl if (periph->path->device->serial_num_len > 0) { 723195534Sscottl MD5Update(&softc->context, 724195534Sscottl periph->path->device->serial_num, 725195534Sscottl periph->path->device->serial_num_len); 726195534Sscottl softc->flags |= PROBE_SERIAL_CKSUM; 727195534Sscottl } 728195534Sscottl MD5Final(softc->digest, &softc->context); 729195534Sscottl } 730195534Sscottl 731195534Sscottl if (softc->action == PROBE_INQUIRY) 732195534Sscottl inquiry_len = SHORT_INQUIRY_LENGTH; 733195534Sscottl else 734195534Sscottl inquiry_len = SID_ADDITIONAL_LENGTH(inq_buf); 735195534Sscottl 736195534Sscottl /* 737195534Sscottl * Some parallel SCSI devices fail to send an 738195534Sscottl * ignore wide residue message when dealing with 739195534Sscottl * odd length inquiry requests. Round up to be 740195534Sscottl * safe. 741195534Sscottl */ 742195534Sscottl inquiry_len = roundup2(inquiry_len, 2); 743195534Sscottl 744195534Sscottl if (softc->action == PROBE_INQUIRY_BASIC_DV1 745195534Sscottl || softc->action == PROBE_INQUIRY_BASIC_DV2) { 746195534Sscottl inq_buf = malloc(inquiry_len, M_CAMXPT, M_NOWAIT); 747195534Sscottl } 748195534Sscottl if (inq_buf == NULL) { 749195534Sscottl xpt_print(periph->path, "malloc failure- skipping Basic" 750195534Sscottl "Domain Validation\n"); 751195534Sscottl PROBE_SET_ACTION(softc, PROBE_DV_EXIT); 752195534Sscottl scsi_test_unit_ready(csio, 753195534Sscottl /*retries*/4, 754195534Sscottl probedone, 755195534Sscottl MSG_SIMPLE_Q_TAG, 756195534Sscottl SSD_FULL_SIZE, 757195534Sscottl /*timeout*/60000); 758195534Sscottl break; 759195534Sscottl } 760195534Sscottl scsi_inquiry(csio, 761195534Sscottl /*retries*/4, 762195534Sscottl probedone, 763195534Sscottl MSG_SIMPLE_Q_TAG, 764195534Sscottl (u_int8_t *)inq_buf, 765195534Sscottl inquiry_len, 766195534Sscottl /*evpd*/FALSE, 767195534Sscottl /*page_code*/0, 768195534Sscottl SSD_MIN_SIZE, 769195534Sscottl /*timeout*/60 * 1000); 770195534Sscottl break; 771195534Sscottl } 772195534Sscottl case PROBE_MODE_SENSE: 773195534Sscottl { 774195534Sscottl void *mode_buf; 775195534Sscottl int mode_buf_len; 776195534Sscottl 777195534Sscottl mode_buf_len = sizeof(struct scsi_mode_header_6) 778195534Sscottl + sizeof(struct scsi_mode_blk_desc) 779195534Sscottl + sizeof(struct scsi_control_page); 780195534Sscottl mode_buf = malloc(mode_buf_len, M_CAMXPT, M_NOWAIT); 781195534Sscottl if (mode_buf != NULL) { 782195534Sscottl scsi_mode_sense(csio, 783195534Sscottl /*retries*/4, 784195534Sscottl probedone, 785195534Sscottl MSG_SIMPLE_Q_TAG, 786195534Sscottl /*dbd*/FALSE, 787195534Sscottl SMS_PAGE_CTRL_CURRENT, 788195534Sscottl SMS_CONTROL_MODE_PAGE, 789195534Sscottl mode_buf, 790195534Sscottl mode_buf_len, 791195534Sscottl SSD_FULL_SIZE, 792195534Sscottl /*timeout*/60000); 793195534Sscottl break; 794195534Sscottl } 795195534Sscottl xpt_print(periph->path, "Unable to mode sense control page - " 796195534Sscottl "malloc failure\n"); 797195534Sscottl PROBE_SET_ACTION(softc, PROBE_SERIAL_NUM_0); 798195534Sscottl } 799195534Sscottl /* FALLTHROUGH */ 800195534Sscottl case PROBE_SERIAL_NUM_0: 801195534Sscottl { 802195534Sscottl struct scsi_vpd_supported_page_list *vpd_list = NULL; 803195534Sscottl struct cam_ed *device; 804195534Sscottl 805195534Sscottl device = periph->path->device; 806195534Sscottl if ((SCSI_QUIRK(device)->quirks & CAM_QUIRK_NOSERIAL) == 0) { 807195534Sscottl vpd_list = malloc(sizeof(*vpd_list), M_CAMXPT, 808195534Sscottl M_NOWAIT | M_ZERO); 809195534Sscottl } 810195534Sscottl 811195534Sscottl if (vpd_list != NULL) { 812195534Sscottl scsi_inquiry(csio, 813195534Sscottl /*retries*/4, 814195534Sscottl probedone, 815195534Sscottl MSG_SIMPLE_Q_TAG, 816195534Sscottl (u_int8_t *)vpd_list, 817195534Sscottl sizeof(*vpd_list), 818195534Sscottl /*evpd*/TRUE, 819195534Sscottl SVPD_SUPPORTED_PAGE_LIST, 820195534Sscottl SSD_MIN_SIZE, 821195534Sscottl /*timeout*/60 * 1000); 822195534Sscottl break; 823195534Sscottl } 824195534Sscottl /* 825195534Sscottl * We'll have to do without, let our probedone 826195534Sscottl * routine finish up for us. 827195534Sscottl */ 828195534Sscottl start_ccb->csio.data_ptr = NULL; 829195534Sscottl probedone(periph, start_ccb); 830195534Sscottl return; 831195534Sscottl } 832195534Sscottl case PROBE_SERIAL_NUM_1: 833195534Sscottl { 834195534Sscottl struct scsi_vpd_unit_serial_number *serial_buf; 835195534Sscottl struct cam_ed* device; 836195534Sscottl 837195534Sscottl serial_buf = NULL; 838195534Sscottl device = periph->path->device; 839195685Semaste if (device->serial_num != NULL) { 840195685Semaste free(device->serial_num, M_CAMXPT); 841195685Semaste device->serial_num = NULL; 842195685Semaste device->serial_num_len = 0; 843195685Semaste } 844195534Sscottl 845195534Sscottl serial_buf = (struct scsi_vpd_unit_serial_number *) 846195534Sscottl malloc(sizeof(*serial_buf), M_CAMXPT, M_NOWAIT|M_ZERO); 847195534Sscottl 848195534Sscottl if (serial_buf != NULL) { 849195534Sscottl scsi_inquiry(csio, 850195534Sscottl /*retries*/4, 851195534Sscottl probedone, 852195534Sscottl MSG_SIMPLE_Q_TAG, 853195534Sscottl (u_int8_t *)serial_buf, 854195534Sscottl sizeof(*serial_buf), 855195534Sscottl /*evpd*/TRUE, 856195534Sscottl SVPD_UNIT_SERIAL_NUMBER, 857195534Sscottl SSD_MIN_SIZE, 858195534Sscottl /*timeout*/60 * 1000); 859195534Sscottl break; 860195534Sscottl } 861195534Sscottl /* 862195534Sscottl * We'll have to do without, let our probedone 863195534Sscottl * routine finish up for us. 864195534Sscottl */ 865195534Sscottl start_ccb->csio.data_ptr = NULL; 866195534Sscottl probedone(periph, start_ccb); 867195534Sscottl return; 868195534Sscottl } 869195534Sscottl case PROBE_INVALID: 870195534Sscottl CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_INFO, 871195534Sscottl ("probestart: invalid action state\n")); 872195534Sscottl default: 873195534Sscottl break; 874195534Sscottl } 875195534Sscottl xpt_action(start_ccb); 876195534Sscottl} 877195534Sscottl 878195534Sscottlstatic void 879195534Sscottlproberequestdefaultnegotiation(struct cam_periph *periph) 880195534Sscottl{ 881195534Sscottl struct ccb_trans_settings cts; 882195534Sscottl 883195534Sscottl xpt_setup_ccb(&cts.ccb_h, periph->path, /*priority*/1); 884195534Sscottl cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 885195534Sscottl cts.type = CTS_TYPE_USER_SETTINGS; 886195534Sscottl xpt_action((union ccb *)&cts); 887195534Sscottl if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 888195534Sscottl return; 889195534Sscottl } 890195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 891195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 892195534Sscottl xpt_action((union ccb *)&cts); 893195534Sscottl} 894195534Sscottl 895195534Sscottl/* 896195534Sscottl * Backoff Negotiation Code- only pertinent for SPI devices. 897195534Sscottl */ 898195534Sscottlstatic int 899195534Sscottlproberequestbackoff(struct cam_periph *periph, struct cam_ed *device) 900195534Sscottl{ 901195534Sscottl struct ccb_trans_settings cts; 902195534Sscottl struct ccb_trans_settings_spi *spi; 903195534Sscottl 904195534Sscottl memset(&cts, 0, sizeof (cts)); 905195534Sscottl xpt_setup_ccb(&cts.ccb_h, periph->path, /*priority*/1); 906195534Sscottl cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 907195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 908195534Sscottl xpt_action((union ccb *)&cts); 909195534Sscottl if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 910195534Sscottl if (bootverbose) { 911195534Sscottl xpt_print(periph->path, 912195534Sscottl "failed to get current device settings\n"); 913195534Sscottl } 914195534Sscottl return (0); 915195534Sscottl } 916195534Sscottl if (cts.transport != XPORT_SPI) { 917195534Sscottl if (bootverbose) { 918195534Sscottl xpt_print(periph->path, "not SPI transport\n"); 919195534Sscottl } 920195534Sscottl return (0); 921195534Sscottl } 922195534Sscottl spi = &cts.xport_specific.spi; 923195534Sscottl 924195534Sscottl /* 925195534Sscottl * We cannot renegotiate sync rate if we don't have one. 926195534Sscottl */ 927195534Sscottl if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) { 928195534Sscottl if (bootverbose) { 929195534Sscottl xpt_print(periph->path, "no sync rate known\n"); 930195534Sscottl } 931195534Sscottl return (0); 932195534Sscottl } 933195534Sscottl 934195534Sscottl /* 935195534Sscottl * We'll assert that we don't have to touch PPR options- the 936195534Sscottl * SIM will see what we do with period and offset and adjust 937195534Sscottl * the PPR options as appropriate. 938195534Sscottl */ 939195534Sscottl 940195534Sscottl /* 941195534Sscottl * A sync rate with unknown or zero offset is nonsensical. 942195534Sscottl * A sync period of zero means Async. 943195534Sscottl */ 944195534Sscottl if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0 945195534Sscottl || spi->sync_offset == 0 || spi->sync_period == 0) { 946195534Sscottl if (bootverbose) { 947195534Sscottl xpt_print(periph->path, "no sync rate available\n"); 948195534Sscottl } 949195534Sscottl return (0); 950195534Sscottl } 951195534Sscottl 952195534Sscottl if (device->flags & CAM_DEV_DV_HIT_BOTTOM) { 953195534Sscottl CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 954195534Sscottl ("hit async: giving up on DV\n")); 955195534Sscottl return (0); 956195534Sscottl } 957195534Sscottl 958195534Sscottl 959195534Sscottl /* 960195534Sscottl * Jump sync_period up by one, but stop at 5MHz and fall back to Async. 961195534Sscottl * We don't try to remember 'last' settings to see if the SIM actually 962195534Sscottl * gets into the speed we want to set. We check on the SIM telling 963195534Sscottl * us that a requested speed is bad, but otherwise don't try and 964195534Sscottl * check the speed due to the asynchronous and handshake nature 965195534Sscottl * of speed setting. 966195534Sscottl */ 967195534Sscottl spi->valid = CTS_SPI_VALID_SYNC_RATE | CTS_SPI_VALID_SYNC_OFFSET; 968195534Sscottl for (;;) { 969195534Sscottl spi->sync_period++; 970195534Sscottl if (spi->sync_period >= 0xf) { 971195534Sscottl spi->sync_period = 0; 972195534Sscottl spi->sync_offset = 0; 973195534Sscottl CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 974195534Sscottl ("setting to async for DV\n")); 975195534Sscottl /* 976195534Sscottl * Once we hit async, we don't want to try 977195534Sscottl * any more settings. 978195534Sscottl */ 979195534Sscottl device->flags |= CAM_DEV_DV_HIT_BOTTOM; 980195534Sscottl } else if (bootverbose) { 981195534Sscottl CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 982195534Sscottl ("DV: period 0x%x\n", spi->sync_period)); 983195534Sscottl printf("setting period to 0x%x\n", spi->sync_period); 984195534Sscottl } 985195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 986195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 987195534Sscottl xpt_action((union ccb *)&cts); 988195534Sscottl if ((cts.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { 989195534Sscottl break; 990195534Sscottl } 991195534Sscottl CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 992195534Sscottl ("DV: failed to set period 0x%x\n", spi->sync_period)); 993195534Sscottl if (spi->sync_period == 0) { 994195534Sscottl return (0); 995195534Sscottl } 996195534Sscottl } 997195534Sscottl return (1); 998195534Sscottl} 999195534Sscottl 1000195534Sscottlstatic void 1001195534Sscottlprobedone(struct cam_periph *periph, union ccb *done_ccb) 1002195534Sscottl{ 1003195534Sscottl probe_softc *softc; 1004195534Sscottl struct cam_path *path; 1005195534Sscottl u_int32_t priority; 1006195534Sscottl 1007195534Sscottl CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probedone\n")); 1008195534Sscottl 1009195534Sscottl softc = (probe_softc *)periph->softc; 1010195534Sscottl path = done_ccb->ccb_h.path; 1011195534Sscottl priority = done_ccb->ccb_h.pinfo.priority; 1012195534Sscottl 1013195534Sscottl switch (softc->action) { 1014195534Sscottl case PROBE_TUR: 1015195534Sscottl { 1016195534Sscottl if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1017195534Sscottl 1018195534Sscottl if (cam_periph_error(done_ccb, 0, 1019195534Sscottl SF_NO_PRINT, NULL) == ERESTART) 1020195534Sscottl return; 1021195534Sscottl else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 1022195534Sscottl /* Don't wedge the queue */ 1023195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, 1024195534Sscottl /*count*/1, 1025195534Sscottl /*run_queue*/TRUE); 1026195534Sscottl } 1027195534Sscottl PROBE_SET_ACTION(softc, PROBE_INQUIRY); 1028195534Sscottl xpt_release_ccb(done_ccb); 1029195534Sscottl xpt_schedule(periph, priority); 1030195534Sscottl return; 1031195534Sscottl } 1032195534Sscottl case PROBE_INQUIRY: 1033195534Sscottl case PROBE_FULL_INQUIRY: 1034195534Sscottl { 1035195534Sscottl if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { 1036195534Sscottl struct scsi_inquiry_data *inq_buf; 1037195534Sscottl u_int8_t periph_qual; 1038195534Sscottl 1039195534Sscottl path->device->flags |= CAM_DEV_INQUIRY_DATA_VALID; 1040195534Sscottl inq_buf = &path->device->inq_data; 1041195534Sscottl 1042195534Sscottl periph_qual = SID_QUAL(inq_buf); 1043195534Sscottl 1044195534Sscottl switch(periph_qual) { 1045195534Sscottl case SID_QUAL_LU_CONNECTED: 1046195534Sscottl { 1047195534Sscottl u_int8_t len; 1048195534Sscottl 1049195534Sscottl /* 1050195534Sscottl * We conservatively request only 1051195534Sscottl * SHORT_INQUIRY_LEN bytes of inquiry 1052195534Sscottl * information during our first try 1053195534Sscottl * at sending an INQUIRY. If the device 1054195534Sscottl * has more information to give, 1055195534Sscottl * perform a second request specifying 1056195534Sscottl * the amount of information the device 1057195534Sscottl * is willing to give. 1058195534Sscottl */ 1059195534Sscottl len = inq_buf->additional_length 1060195534Sscottl + offsetof(struct scsi_inquiry_data, 1061195534Sscottl additional_length) + 1; 1062195534Sscottl if (softc->action == PROBE_INQUIRY 1063195534Sscottl && len > SHORT_INQUIRY_LENGTH) { 1064195534Sscottl PROBE_SET_ACTION(softc, PROBE_FULL_INQUIRY); 1065195534Sscottl xpt_release_ccb(done_ccb); 1066195534Sscottl xpt_schedule(periph, priority); 1067195534Sscottl return; 1068195534Sscottl } 1069195534Sscottl 1070195534Sscottl scsi_find_quirk(path->device); 1071195534Sscottl 1072195534Sscottl scsi_devise_transport(path); 1073195534Sscottl if (INQ_DATA_TQ_ENABLED(inq_buf)) 1074195534Sscottl PROBE_SET_ACTION(softc, PROBE_MODE_SENSE); 1075195534Sscottl else 1076195534Sscottl PROBE_SET_ACTION(softc, PROBE_SERIAL_NUM_0); 1077195534Sscottl 1078195534Sscottl path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1079195534Sscottl 1080195534Sscottl xpt_release_ccb(done_ccb); 1081195534Sscottl xpt_schedule(periph, priority); 1082195534Sscottl return; 1083195534Sscottl } 1084195534Sscottl default: 1085195534Sscottl break; 1086195534Sscottl } 1087195534Sscottl } else if (cam_periph_error(done_ccb, 0, 1088195534Sscottl done_ccb->ccb_h.target_lun > 0 1089195534Sscottl ? SF_RETRY_UA|SF_QUIET_IR 1090195534Sscottl : SF_RETRY_UA, 1091195534Sscottl &softc->saved_ccb) == ERESTART) { 1092195534Sscottl return; 1093195534Sscottl } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1094195534Sscottl /* Don't wedge the queue */ 1095195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 1096195534Sscottl /*run_queue*/TRUE); 1097195534Sscottl } 1098195534Sscottl /* 1099195534Sscottl * If we get to this point, we got an error status back 1100195534Sscottl * from the inquiry and the error status doesn't require 1101195534Sscottl * automatically retrying the command. Therefore, the 1102195534Sscottl * inquiry failed. If we had inquiry information before 1103195534Sscottl * for this device, but this latest inquiry command failed, 1104195534Sscottl * the device has probably gone away. If this device isn't 1105195534Sscottl * already marked unconfigured, notify the peripheral 1106195534Sscottl * drivers that this device is no more. 1107195534Sscottl */ 1108195534Sscottl if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0) 1109195534Sscottl /* Send the async notification. */ 1110195534Sscottl xpt_async(AC_LOST_DEVICE, path, NULL); 1111195534Sscottl 1112195534Sscottl xpt_release_ccb(done_ccb); 1113195534Sscottl break; 1114195534Sscottl } 1115195534Sscottl case PROBE_MODE_SENSE: 1116195534Sscottl { 1117195534Sscottl struct ccb_scsiio *csio; 1118195534Sscottl struct scsi_mode_header_6 *mode_hdr; 1119195534Sscottl 1120195534Sscottl csio = &done_ccb->csio; 1121195534Sscottl mode_hdr = (struct scsi_mode_header_6 *)csio->data_ptr; 1122195534Sscottl if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { 1123195534Sscottl struct scsi_control_page *page; 1124195534Sscottl u_int8_t *offset; 1125195534Sscottl 1126195534Sscottl offset = ((u_int8_t *)&mode_hdr[1]) 1127195534Sscottl + mode_hdr->blk_desc_len; 1128195534Sscottl page = (struct scsi_control_page *)offset; 1129195534Sscottl path->device->queue_flags = page->queue_flags; 1130195534Sscottl } else if (cam_periph_error(done_ccb, 0, 1131195534Sscottl SF_RETRY_UA|SF_NO_PRINT, 1132195534Sscottl &softc->saved_ccb) == ERESTART) { 1133195534Sscottl return; 1134195534Sscottl } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1135195534Sscottl /* Don't wedge the queue */ 1136195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, 1137195534Sscottl /*count*/1, /*run_queue*/TRUE); 1138195534Sscottl } 1139195534Sscottl xpt_release_ccb(done_ccb); 1140195534Sscottl free(mode_hdr, M_CAMXPT); 1141195534Sscottl PROBE_SET_ACTION(softc, PROBE_SERIAL_NUM_0); 1142195534Sscottl xpt_schedule(periph, priority); 1143195534Sscottl return; 1144195534Sscottl } 1145195534Sscottl case PROBE_SERIAL_NUM_0: 1146195534Sscottl { 1147195534Sscottl struct ccb_scsiio *csio; 1148195534Sscottl struct scsi_vpd_supported_page_list *page_list; 1149195534Sscottl int length, serialnum_supported, i; 1150195534Sscottl 1151195534Sscottl serialnum_supported = 0; 1152195534Sscottl csio = &done_ccb->csio; 1153195534Sscottl page_list = 1154195534Sscottl (struct scsi_vpd_supported_page_list *)csio->data_ptr; 1155195534Sscottl 1156195534Sscottl if (page_list == NULL) { 1157195534Sscottl /* 1158195534Sscottl * Don't process the command as it was never sent 1159195534Sscottl */ 1160195534Sscottl } else if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP 1161195534Sscottl && (page_list->length > 0)) { 1162195534Sscottl length = min(page_list->length, 1163195534Sscottl SVPD_SUPPORTED_PAGES_SIZE); 1164195534Sscottl for (i = 0; i < length; i++) { 1165195534Sscottl if (page_list->list[i] == 1166195534Sscottl SVPD_UNIT_SERIAL_NUMBER) { 1167195534Sscottl serialnum_supported = 1; 1168195534Sscottl break; 1169195534Sscottl } 1170195534Sscottl } 1171195534Sscottl } else if (cam_periph_error(done_ccb, 0, 1172195534Sscottl SF_RETRY_UA|SF_NO_PRINT, 1173195534Sscottl &softc->saved_ccb) == ERESTART) { 1174195534Sscottl return; 1175195534Sscottl } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1176195534Sscottl /* Don't wedge the queue */ 1177195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 1178195534Sscottl /*run_queue*/TRUE); 1179195534Sscottl } 1180195534Sscottl 1181195534Sscottl if (page_list != NULL) 1182195685Semaste free(page_list, M_CAMXPT); 1183195534Sscottl 1184195534Sscottl if (serialnum_supported) { 1185195534Sscottl xpt_release_ccb(done_ccb); 1186195534Sscottl PROBE_SET_ACTION(softc, PROBE_SERIAL_NUM_1); 1187195534Sscottl xpt_schedule(periph, priority); 1188195534Sscottl return; 1189195534Sscottl } 1190195534Sscottl 1191195534Sscottl csio->data_ptr = NULL; 1192195534Sscottl /* FALLTHROUGH */ 1193195534Sscottl } 1194195534Sscottl 1195195534Sscottl case PROBE_SERIAL_NUM_1: 1196195534Sscottl { 1197195534Sscottl struct ccb_scsiio *csio; 1198195534Sscottl struct scsi_vpd_unit_serial_number *serial_buf; 1199195534Sscottl u_int32_t priority; 1200195534Sscottl int changed; 1201195534Sscottl int have_serialnum; 1202195534Sscottl 1203195534Sscottl changed = 1; 1204195534Sscottl have_serialnum = 0; 1205195534Sscottl csio = &done_ccb->csio; 1206195534Sscottl priority = done_ccb->ccb_h.pinfo.priority; 1207195534Sscottl serial_buf = 1208195534Sscottl (struct scsi_vpd_unit_serial_number *)csio->data_ptr; 1209195534Sscottl 1210195534Sscottl /* Clean up from previous instance of this device */ 1211195534Sscottl if (path->device->serial_num != NULL) { 1212195534Sscottl free(path->device->serial_num, M_CAMXPT); 1213195534Sscottl path->device->serial_num = NULL; 1214195534Sscottl path->device->serial_num_len = 0; 1215195534Sscottl } 1216195534Sscottl 1217195534Sscottl if (serial_buf == NULL) { 1218195534Sscottl /* 1219195534Sscottl * Don't process the command as it was never sent 1220195534Sscottl */ 1221195534Sscottl } else if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP 1222195534Sscottl && (serial_buf->length > 0)) { 1223195534Sscottl 1224195534Sscottl have_serialnum = 1; 1225195534Sscottl path->device->serial_num = 1226195534Sscottl (u_int8_t *)malloc((serial_buf->length + 1), 1227195534Sscottl M_CAMXPT, M_NOWAIT); 1228195534Sscottl if (path->device->serial_num != NULL) { 1229195534Sscottl bcopy(serial_buf->serial_num, 1230195534Sscottl path->device->serial_num, 1231195534Sscottl serial_buf->length); 1232195534Sscottl path->device->serial_num_len = 1233195534Sscottl serial_buf->length; 1234195534Sscottl path->device->serial_num[serial_buf->length] 1235195534Sscottl = '\0'; 1236195534Sscottl } 1237195534Sscottl } else if (cam_periph_error(done_ccb, 0, 1238195534Sscottl SF_RETRY_UA|SF_NO_PRINT, 1239195534Sscottl &softc->saved_ccb) == ERESTART) { 1240195534Sscottl return; 1241195534Sscottl } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1242195534Sscottl /* Don't wedge the queue */ 1243195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 1244195534Sscottl /*run_queue*/TRUE); 1245195534Sscottl } 1246195534Sscottl 1247195534Sscottl /* 1248195534Sscottl * Let's see if we have seen this device before. 1249195534Sscottl */ 1250195534Sscottl if ((softc->flags & PROBE_INQUIRY_CKSUM) != 0) { 1251195534Sscottl MD5_CTX context; 1252195534Sscottl u_int8_t digest[16]; 1253195534Sscottl 1254195534Sscottl MD5Init(&context); 1255195534Sscottl 1256195534Sscottl MD5Update(&context, 1257195534Sscottl (unsigned char *)&path->device->inq_data, 1258195534Sscottl sizeof(struct scsi_inquiry_data)); 1259195534Sscottl 1260195534Sscottl if (have_serialnum) 1261195534Sscottl MD5Update(&context, serial_buf->serial_num, 1262195534Sscottl serial_buf->length); 1263195534Sscottl 1264195534Sscottl MD5Final(digest, &context); 1265195534Sscottl if (bcmp(softc->digest, digest, 16) == 0) 1266195534Sscottl changed = 0; 1267195534Sscottl 1268195534Sscottl /* 1269195534Sscottl * XXX Do we need to do a TUR in order to ensure 1270195534Sscottl * that the device really hasn't changed??? 1271195534Sscottl */ 1272195534Sscottl if ((changed != 0) 1273195534Sscottl && ((softc->flags & PROBE_NO_ANNOUNCE) == 0)) 1274195534Sscottl xpt_async(AC_LOST_DEVICE, path, NULL); 1275195534Sscottl } 1276195534Sscottl if (serial_buf != NULL) 1277195534Sscottl free(serial_buf, M_CAMXPT); 1278195534Sscottl 1279195534Sscottl if (changed != 0) { 1280195534Sscottl /* 1281195534Sscottl * Now that we have all the necessary 1282195534Sscottl * information to safely perform transfer 1283195534Sscottl * negotiations... Controllers don't perform 1284195534Sscottl * any negotiation or tagged queuing until 1285195534Sscottl * after the first XPT_SET_TRAN_SETTINGS ccb is 1286195534Sscottl * received. So, on a new device, just retrieve 1287195534Sscottl * the user settings, and set them as the current 1288195534Sscottl * settings to set the device up. 1289195534Sscottl */ 1290195534Sscottl proberequestdefaultnegotiation(periph); 1291195534Sscottl xpt_release_ccb(done_ccb); 1292195534Sscottl 1293195534Sscottl /* 1294195534Sscottl * Perform a TUR to allow the controller to 1295195534Sscottl * perform any necessary transfer negotiation. 1296195534Sscottl */ 1297195534Sscottl PROBE_SET_ACTION(softc, PROBE_TUR_FOR_NEGOTIATION); 1298195534Sscottl xpt_schedule(periph, priority); 1299195534Sscottl return; 1300195534Sscottl } 1301195534Sscottl xpt_release_ccb(done_ccb); 1302195534Sscottl break; 1303195534Sscottl } 1304195534Sscottl case PROBE_TUR_FOR_NEGOTIATION: 1305195534Sscottl if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1306195534Sscottl DELAY(500000); 1307195534Sscottl if (cam_periph_error(done_ccb, 0, SF_RETRY_UA, 1308195534Sscottl NULL) == ERESTART) 1309195534Sscottl return; 1310195534Sscottl } 1311195534Sscottl /* FALLTHROUGH */ 1312195534Sscottl case PROBE_DV_EXIT: 1313195534Sscottl if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1314195534Sscottl /* Don't wedge the queue */ 1315195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 1316195534Sscottl /*run_queue*/TRUE); 1317195534Sscottl } 1318195534Sscottl /* 1319195534Sscottl * Do Domain Validation for lun 0 on devices that claim 1320195534Sscottl * to support Synchronous Transfer modes. 1321195534Sscottl */ 1322195534Sscottl if (softc->action == PROBE_TUR_FOR_NEGOTIATION 1323195534Sscottl && done_ccb->ccb_h.target_lun == 0 1324195534Sscottl && (path->device->inq_data.flags & SID_Sync) != 0 1325195534Sscottl && (path->device->flags & CAM_DEV_IN_DV) == 0) { 1326195534Sscottl CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 1327195534Sscottl ("Begin Domain Validation\n")); 1328195534Sscottl path->device->flags |= CAM_DEV_IN_DV; 1329195534Sscottl xpt_release_ccb(done_ccb); 1330195534Sscottl PROBE_SET_ACTION(softc, PROBE_INQUIRY_BASIC_DV1); 1331195534Sscottl xpt_schedule(periph, priority); 1332195534Sscottl return; 1333195534Sscottl } 1334195534Sscottl if (softc->action == PROBE_DV_EXIT) { 1335195534Sscottl CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 1336195534Sscottl ("Leave Domain Validation\n")); 1337195534Sscottl } 1338195534Sscottl path->device->flags &= 1339195534Sscottl ~(CAM_DEV_UNCONFIGURED|CAM_DEV_IN_DV|CAM_DEV_DV_HIT_BOTTOM); 1340195534Sscottl if ((softc->flags & PROBE_NO_ANNOUNCE) == 0) { 1341195534Sscottl /* Inform the XPT that a new device has been found */ 1342195534Sscottl done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1343195534Sscottl xpt_action(done_ccb); 1344195534Sscottl xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, 1345195534Sscottl done_ccb); 1346195534Sscottl } 1347195534Sscottl xpt_release_ccb(done_ccb); 1348195534Sscottl break; 1349195534Sscottl case PROBE_INQUIRY_BASIC_DV1: 1350195534Sscottl case PROBE_INQUIRY_BASIC_DV2: 1351195534Sscottl { 1352195534Sscottl struct scsi_inquiry_data *nbuf; 1353195534Sscottl struct ccb_scsiio *csio; 1354195534Sscottl 1355195534Sscottl if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1356195534Sscottl /* Don't wedge the queue */ 1357195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 1358195534Sscottl /*run_queue*/TRUE); 1359195534Sscottl } 1360195534Sscottl csio = &done_ccb->csio; 1361195534Sscottl nbuf = (struct scsi_inquiry_data *)csio->data_ptr; 1362195534Sscottl if (bcmp(nbuf, &path->device->inq_data, SHORT_INQUIRY_LENGTH)) { 1363195534Sscottl xpt_print(path, 1364195534Sscottl "inquiry data fails comparison at DV%d step\n", 1365195534Sscottl softc->action == PROBE_INQUIRY_BASIC_DV1 ? 1 : 2); 1366195534Sscottl if (proberequestbackoff(periph, path->device)) { 1367195534Sscottl path->device->flags &= ~CAM_DEV_IN_DV; 1368195534Sscottl PROBE_SET_ACTION(softc, PROBE_TUR_FOR_NEGOTIATION); 1369195534Sscottl } else { 1370195534Sscottl /* give up */ 1371195534Sscottl PROBE_SET_ACTION(softc, PROBE_DV_EXIT); 1372195534Sscottl } 1373195534Sscottl free(nbuf, M_CAMXPT); 1374195534Sscottl xpt_release_ccb(done_ccb); 1375195534Sscottl xpt_schedule(periph, priority); 1376195534Sscottl return; 1377195534Sscottl } 1378195534Sscottl free(nbuf, M_CAMXPT); 1379195534Sscottl if (softc->action == PROBE_INQUIRY_BASIC_DV1) { 1380195534Sscottl PROBE_SET_ACTION(softc, PROBE_INQUIRY_BASIC_DV2); 1381195534Sscottl xpt_release_ccb(done_ccb); 1382195534Sscottl xpt_schedule(periph, priority); 1383195534Sscottl return; 1384195534Sscottl } 1385195534Sscottl if (softc->action == PROBE_INQUIRY_BASIC_DV2) { 1386195534Sscottl CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 1387195534Sscottl ("Leave Domain Validation Successfully\n")); 1388195534Sscottl } 1389195534Sscottl path->device->flags &= 1390195534Sscottl ~(CAM_DEV_UNCONFIGURED|CAM_DEV_IN_DV|CAM_DEV_DV_HIT_BOTTOM); 1391195534Sscottl if ((softc->flags & PROBE_NO_ANNOUNCE) == 0) { 1392195534Sscottl /* Inform the XPT that a new device has been found */ 1393195534Sscottl done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1394195534Sscottl xpt_action(done_ccb); 1395195534Sscottl xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, 1396195534Sscottl done_ccb); 1397195534Sscottl } 1398195534Sscottl xpt_release_ccb(done_ccb); 1399195534Sscottl break; 1400195534Sscottl } 1401195534Sscottl case PROBE_INVALID: 1402195534Sscottl CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_INFO, 1403195534Sscottl ("probedone: invalid action state\n")); 1404195534Sscottl default: 1405195534Sscottl break; 1406195534Sscottl } 1407195534Sscottl done_ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs); 1408195534Sscottl TAILQ_REMOVE(&softc->request_ccbs, &done_ccb->ccb_h, periph_links.tqe); 1409195534Sscottl done_ccb->ccb_h.status = CAM_REQ_CMP; 1410195534Sscottl xpt_done(done_ccb); 1411195534Sscottl if (TAILQ_FIRST(&softc->request_ccbs) == NULL) { 1412195534Sscottl cam_periph_invalidate(periph); 1413195534Sscottl cam_periph_release_locked(periph); 1414195534Sscottl } else { 1415195534Sscottl probeschedule(periph); 1416195534Sscottl } 1417195534Sscottl} 1418195534Sscottl 1419195534Sscottlstatic void 1420195534Sscottlprobecleanup(struct cam_periph *periph) 1421195534Sscottl{ 1422195534Sscottl free(periph->softc, M_CAMXPT); 1423195534Sscottl} 1424195534Sscottl 1425195534Sscottlstatic void 1426195534Sscottlscsi_find_quirk(struct cam_ed *device) 1427195534Sscottl{ 1428195534Sscottl struct scsi_quirk_entry *quirk; 1429195534Sscottl caddr_t match; 1430195534Sscottl 1431195534Sscottl match = cam_quirkmatch((caddr_t)&device->inq_data, 1432195534Sscottl (caddr_t)scsi_quirk_table, 1433195534Sscottl sizeof(scsi_quirk_table) / 1434195534Sscottl sizeof(*scsi_quirk_table), 1435195534Sscottl sizeof(*scsi_quirk_table), scsi_inquiry_match); 1436195534Sscottl 1437195534Sscottl if (match == NULL) 1438195534Sscottl panic("xpt_find_quirk: device didn't match wildcard entry!!"); 1439195534Sscottl 1440195534Sscottl quirk = (struct scsi_quirk_entry *)match; 1441195534Sscottl device->quirk = quirk; 1442195534Sscottl device->mintags = quirk->mintags; 1443195534Sscottl device->maxtags = quirk->maxtags; 1444195534Sscottl} 1445195534Sscottl 1446195534Sscottlstatic int 1447195534Sscottlsysctl_cam_search_luns(SYSCTL_HANDLER_ARGS) 1448195534Sscottl{ 1449195534Sscottl int error, bool; 1450195534Sscottl 1451195534Sscottl bool = cam_srch_hi; 1452195534Sscottl error = sysctl_handle_int(oidp, &bool, 0, req); 1453195534Sscottl if (error != 0 || req->newptr == NULL) 1454195534Sscottl return (error); 1455195534Sscottl if (bool == 0 || bool == 1) { 1456195534Sscottl cam_srch_hi = bool; 1457195534Sscottl return (0); 1458195534Sscottl } else { 1459195534Sscottl return (EINVAL); 1460195534Sscottl } 1461195534Sscottl} 1462195534Sscottl 1463195534Sscottltypedef struct { 1464195534Sscottl union ccb *request_ccb; 1465195534Sscottl struct ccb_pathinq *cpi; 1466195534Sscottl int counter; 1467195534Sscottl} scsi_scan_bus_info; 1468195534Sscottl 1469195534Sscottl/* 1470195534Sscottl * To start a scan, request_ccb is an XPT_SCAN_BUS ccb. 1471195534Sscottl * As the scan progresses, xpt_scan_bus is used as the 1472195534Sscottl * callback on completion function. 1473195534Sscottl */ 1474195534Sscottlstatic void 1475195534Sscottlscsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb) 1476195534Sscottl{ 1477195534Sscottl CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE, 1478195534Sscottl ("xpt_scan_bus\n")); 1479195534Sscottl switch (request_ccb->ccb_h.func_code) { 1480195534Sscottl case XPT_SCAN_BUS: 1481195534Sscottl { 1482195534Sscottl scsi_scan_bus_info *scan_info; 1483195534Sscottl union ccb *work_ccb; 1484195534Sscottl struct cam_path *path; 1485195534Sscottl u_int i; 1486195534Sscottl u_int max_target; 1487195534Sscottl u_int initiator_id; 1488195534Sscottl 1489195534Sscottl /* Find out the characteristics of the bus */ 1490195534Sscottl work_ccb = xpt_alloc_ccb_nowait(); 1491195534Sscottl if (work_ccb == NULL) { 1492195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1493195534Sscottl xpt_done(request_ccb); 1494195534Sscottl return; 1495195534Sscottl } 1496195534Sscottl xpt_setup_ccb(&work_ccb->ccb_h, request_ccb->ccb_h.path, 1497195534Sscottl request_ccb->ccb_h.pinfo.priority); 1498195534Sscottl work_ccb->ccb_h.func_code = XPT_PATH_INQ; 1499195534Sscottl xpt_action(work_ccb); 1500195534Sscottl if (work_ccb->ccb_h.status != CAM_REQ_CMP) { 1501195534Sscottl request_ccb->ccb_h.status = work_ccb->ccb_h.status; 1502195534Sscottl xpt_free_ccb(work_ccb); 1503195534Sscottl xpt_done(request_ccb); 1504195534Sscottl return; 1505195534Sscottl } 1506195534Sscottl 1507195534Sscottl if ((work_ccb->cpi.hba_misc & PIM_NOINITIATOR) != 0) { 1508195534Sscottl /* 1509195534Sscottl * Can't scan the bus on an adapter that 1510195534Sscottl * cannot perform the initiator role. 1511195534Sscottl */ 1512195534Sscottl request_ccb->ccb_h.status = CAM_REQ_CMP; 1513195534Sscottl xpt_free_ccb(work_ccb); 1514195534Sscottl xpt_done(request_ccb); 1515195534Sscottl return; 1516195534Sscottl } 1517195534Sscottl 1518195534Sscottl /* Save some state for use while we probe for devices */ 1519195534Sscottl scan_info = (scsi_scan_bus_info *) 1520195534Sscottl malloc(sizeof(scsi_scan_bus_info), M_CAMXPT, M_NOWAIT); 1521195534Sscottl if (scan_info == NULL) { 1522195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1523195534Sscottl xpt_done(request_ccb); 1524195534Sscottl return; 1525195534Sscottl } 1526195534Sscottl scan_info->request_ccb = request_ccb; 1527195534Sscottl scan_info->cpi = &work_ccb->cpi; 1528195534Sscottl 1529195534Sscottl /* Cache on our stack so we can work asynchronously */ 1530195534Sscottl max_target = scan_info->cpi->max_target; 1531195534Sscottl initiator_id = scan_info->cpi->initiator_id; 1532195534Sscottl 1533195534Sscottl 1534195534Sscottl /* 1535195534Sscottl * We can scan all targets in parallel, or do it sequentially. 1536195534Sscottl */ 1537195534Sscottl if (scan_info->cpi->hba_misc & PIM_SEQSCAN) { 1538195534Sscottl max_target = 0; 1539195534Sscottl scan_info->counter = 0; 1540195534Sscottl } else { 1541195534Sscottl scan_info->counter = scan_info->cpi->max_target + 1; 1542195534Sscottl if (scan_info->cpi->initiator_id < scan_info->counter) { 1543195534Sscottl scan_info->counter--; 1544195534Sscottl } 1545195534Sscottl } 1546195534Sscottl 1547195534Sscottl for (i = 0; i <= max_target; i++) { 1548195534Sscottl cam_status status; 1549195534Sscottl if (i == initiator_id) 1550195534Sscottl continue; 1551195534Sscottl 1552195534Sscottl status = xpt_create_path(&path, xpt_periph, 1553195534Sscottl request_ccb->ccb_h.path_id, 1554195534Sscottl i, 0); 1555195534Sscottl if (status != CAM_REQ_CMP) { 1556195534Sscottl printf("xpt_scan_bus: xpt_create_path failed" 1557195534Sscottl " with status %#x, bus scan halted\n", 1558195534Sscottl status); 1559195534Sscottl free(scan_info, M_CAMXPT); 1560195534Sscottl request_ccb->ccb_h.status = status; 1561195534Sscottl xpt_free_ccb(work_ccb); 1562195534Sscottl xpt_done(request_ccb); 1563195534Sscottl break; 1564195534Sscottl } 1565195534Sscottl work_ccb = xpt_alloc_ccb_nowait(); 1566195534Sscottl if (work_ccb == NULL) { 1567195685Semaste xpt_free_ccb((union ccb *)scan_info->cpi); 1568195534Sscottl free(scan_info, M_CAMXPT); 1569195534Sscottl xpt_free_path(path); 1570195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1571195534Sscottl xpt_done(request_ccb); 1572195534Sscottl break; 1573195534Sscottl } 1574195534Sscottl xpt_setup_ccb(&work_ccb->ccb_h, path, 1575195534Sscottl request_ccb->ccb_h.pinfo.priority); 1576195534Sscottl work_ccb->ccb_h.func_code = XPT_SCAN_LUN; 1577195534Sscottl work_ccb->ccb_h.cbfcnp = scsi_scan_bus; 1578195534Sscottl work_ccb->ccb_h.ppriv_ptr0 = scan_info; 1579195534Sscottl work_ccb->crcn.flags = request_ccb->crcn.flags; 1580195534Sscottl xpt_action(work_ccb); 1581195534Sscottl } 1582195534Sscottl break; 1583195534Sscottl } 1584195534Sscottl case XPT_SCAN_LUN: 1585195534Sscottl { 1586195534Sscottl cam_status status; 1587195534Sscottl struct cam_path *path; 1588195534Sscottl scsi_scan_bus_info *scan_info; 1589195534Sscottl path_id_t path_id; 1590195534Sscottl target_id_t target_id; 1591195534Sscottl lun_id_t lun_id; 1592195534Sscottl 1593195534Sscottl /* Reuse the same CCB to query if a device was really found */ 1594195534Sscottl scan_info = (scsi_scan_bus_info *)request_ccb->ccb_h.ppriv_ptr0; 1595195534Sscottl xpt_setup_ccb(&request_ccb->ccb_h, request_ccb->ccb_h.path, 1596195534Sscottl request_ccb->ccb_h.pinfo.priority); 1597195534Sscottl request_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1598195534Sscottl 1599195534Sscottl path_id = request_ccb->ccb_h.path_id; 1600195534Sscottl target_id = request_ccb->ccb_h.target_id; 1601195534Sscottl lun_id = request_ccb->ccb_h.target_lun; 1602195534Sscottl xpt_action(request_ccb); 1603195534Sscottl 1604195534Sscottl if (request_ccb->ccb_h.status != CAM_REQ_CMP) { 1605195534Sscottl struct cam_ed *device; 1606195534Sscottl struct cam_et *target; 1607195534Sscottl int phl; 1608195534Sscottl 1609195534Sscottl /* 1610195534Sscottl * If we already probed lun 0 successfully, or 1611195534Sscottl * we have additional configured luns on this 1612195534Sscottl * target that might have "gone away", go onto 1613195534Sscottl * the next lun. 1614195534Sscottl */ 1615195534Sscottl target = request_ccb->ccb_h.path->target; 1616195534Sscottl /* 1617195534Sscottl * We may touch devices that we don't 1618195534Sscottl * hold references too, so ensure they 1619195534Sscottl * don't disappear out from under us. 1620195534Sscottl * The target above is referenced by the 1621195534Sscottl * path in the request ccb. 1622195534Sscottl */ 1623195534Sscottl phl = 0; 1624195534Sscottl device = TAILQ_FIRST(&target->ed_entries); 1625195534Sscottl if (device != NULL) { 1626195534Sscottl phl = CAN_SRCH_HI_SPARSE(device); 1627195534Sscottl if (device->lun_id == 0) 1628195534Sscottl device = TAILQ_NEXT(device, links); 1629195534Sscottl } 1630195534Sscottl if ((lun_id != 0) || (device != NULL)) { 1631195534Sscottl if (lun_id < (CAM_SCSI2_MAXLUN-1) || phl) 1632195534Sscottl lun_id++; 1633195534Sscottl } 1634195534Sscottl } else { 1635195534Sscottl struct cam_ed *device; 1636195534Sscottl 1637195534Sscottl device = request_ccb->ccb_h.path->device; 1638195534Sscottl 1639195534Sscottl if ((SCSI_QUIRK(device)->quirks & 1640195534Sscottl CAM_QUIRK_NOLUNS) == 0) { 1641195534Sscottl /* Try the next lun */ 1642195534Sscottl if (lun_id < (CAM_SCSI2_MAXLUN-1) 1643195534Sscottl || CAN_SRCH_HI_DENSE(device)) 1644195534Sscottl lun_id++; 1645195534Sscottl } 1646195534Sscottl } 1647195534Sscottl 1648195534Sscottl /* 1649195534Sscottl * Free the current request path- we're done with it. 1650195534Sscottl */ 1651195534Sscottl xpt_free_path(request_ccb->ccb_h.path); 1652195534Sscottl 1653195534Sscottl /* 1654195534Sscottl * Check to see if we scan any further luns. 1655195534Sscottl */ 1656195534Sscottl if (lun_id == request_ccb->ccb_h.target_lun 1657195534Sscottl || lun_id > scan_info->cpi->max_lun) { 1658195534Sscottl int done; 1659195534Sscottl 1660195534Sscottl hop_again: 1661195534Sscottl done = 0; 1662195534Sscottl if (scan_info->cpi->hba_misc & PIM_SEQSCAN) { 1663195534Sscottl scan_info->counter++; 1664195534Sscottl if (scan_info->counter == 1665195534Sscottl scan_info->cpi->initiator_id) { 1666195534Sscottl scan_info->counter++; 1667195534Sscottl } 1668195534Sscottl if (scan_info->counter >= 1669195534Sscottl scan_info->cpi->max_target+1) { 1670195534Sscottl done = 1; 1671195534Sscottl } 1672195534Sscottl } else { 1673195534Sscottl scan_info->counter--; 1674195534Sscottl if (scan_info->counter == 0) { 1675195534Sscottl done = 1; 1676195534Sscottl } 1677195534Sscottl } 1678195534Sscottl if (done) { 1679195534Sscottl xpt_free_ccb(request_ccb); 1680195534Sscottl xpt_free_ccb((union ccb *)scan_info->cpi); 1681195534Sscottl request_ccb = scan_info->request_ccb; 1682195534Sscottl free(scan_info, M_CAMXPT); 1683195534Sscottl request_ccb->ccb_h.status = CAM_REQ_CMP; 1684195534Sscottl xpt_done(request_ccb); 1685195534Sscottl break; 1686195534Sscottl } 1687195534Sscottl 1688195534Sscottl if ((scan_info->cpi->hba_misc & PIM_SEQSCAN) == 0) { 1689195685Semaste xpt_free_ccb(request_ccb); 1690195534Sscottl break; 1691195534Sscottl } 1692195534Sscottl status = xpt_create_path(&path, xpt_periph, 1693195534Sscottl scan_info->request_ccb->ccb_h.path_id, 1694195534Sscottl scan_info->counter, 0); 1695195534Sscottl if (status != CAM_REQ_CMP) { 1696195534Sscottl printf("xpt_scan_bus: xpt_create_path failed" 1697195534Sscottl " with status %#x, bus scan halted\n", 1698195534Sscottl status); 1699195534Sscottl xpt_free_ccb(request_ccb); 1700195534Sscottl xpt_free_ccb((union ccb *)scan_info->cpi); 1701195534Sscottl request_ccb = scan_info->request_ccb; 1702195534Sscottl free(scan_info, M_CAMXPT); 1703195534Sscottl request_ccb->ccb_h.status = status; 1704195534Sscottl xpt_done(request_ccb); 1705195534Sscottl break; 1706195534Sscottl } 1707195534Sscottl xpt_setup_ccb(&request_ccb->ccb_h, path, 1708195534Sscottl request_ccb->ccb_h.pinfo.priority); 1709195534Sscottl request_ccb->ccb_h.func_code = XPT_SCAN_LUN; 1710195534Sscottl request_ccb->ccb_h.cbfcnp = scsi_scan_bus; 1711195534Sscottl request_ccb->ccb_h.ppriv_ptr0 = scan_info; 1712195534Sscottl request_ccb->crcn.flags = 1713195534Sscottl scan_info->request_ccb->crcn.flags; 1714195534Sscottl } else { 1715195534Sscottl status = xpt_create_path(&path, xpt_periph, 1716195534Sscottl path_id, target_id, lun_id); 1717195534Sscottl if (status != CAM_REQ_CMP) { 1718195534Sscottl printf("xpt_scan_bus: xpt_create_path failed " 1719195534Sscottl "with status %#x, halting LUN scan\n", 1720195534Sscottl status); 1721195534Sscottl goto hop_again; 1722195534Sscottl } 1723195534Sscottl xpt_setup_ccb(&request_ccb->ccb_h, path, 1724195534Sscottl request_ccb->ccb_h.pinfo.priority); 1725195534Sscottl request_ccb->ccb_h.func_code = XPT_SCAN_LUN; 1726195534Sscottl request_ccb->ccb_h.cbfcnp = scsi_scan_bus; 1727195534Sscottl request_ccb->ccb_h.ppriv_ptr0 = scan_info; 1728195534Sscottl request_ccb->crcn.flags = 1729195534Sscottl scan_info->request_ccb->crcn.flags; 1730195534Sscottl } 1731195534Sscottl xpt_action(request_ccb); 1732195534Sscottl break; 1733195534Sscottl } 1734195534Sscottl default: 1735195534Sscottl break; 1736195534Sscottl } 1737195534Sscottl} 1738195534Sscottl 1739195534Sscottlstatic void 1740195534Sscottlscsi_scan_lun(struct cam_periph *periph, struct cam_path *path, 1741195534Sscottl cam_flags flags, union ccb *request_ccb) 1742195534Sscottl{ 1743195534Sscottl struct ccb_pathinq cpi; 1744195534Sscottl cam_status status; 1745195534Sscottl struct cam_path *new_path; 1746195534Sscottl struct cam_periph *old_periph; 1747195534Sscottl 1748195534Sscottl CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE, 1749195534Sscottl ("xpt_scan_lun\n")); 1750195534Sscottl 1751195534Sscottl xpt_setup_ccb(&cpi.ccb_h, path, /*priority*/1); 1752195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 1753195534Sscottl xpt_action((union ccb *)&cpi); 1754195534Sscottl 1755195534Sscottl if (cpi.ccb_h.status != CAM_REQ_CMP) { 1756195534Sscottl if (request_ccb != NULL) { 1757195534Sscottl request_ccb->ccb_h.status = cpi.ccb_h.status; 1758195534Sscottl xpt_done(request_ccb); 1759195534Sscottl } 1760195534Sscottl return; 1761195534Sscottl } 1762195534Sscottl 1763195534Sscottl if ((cpi.hba_misc & PIM_NOINITIATOR) != 0) { 1764195534Sscottl /* 1765195534Sscottl * Can't scan the bus on an adapter that 1766195534Sscottl * cannot perform the initiator role. 1767195534Sscottl */ 1768195534Sscottl if (request_ccb != NULL) { 1769195534Sscottl request_ccb->ccb_h.status = CAM_REQ_CMP; 1770195534Sscottl xpt_done(request_ccb); 1771195534Sscottl } 1772195534Sscottl return; 1773195534Sscottl } 1774195534Sscottl 1775195534Sscottl if (request_ccb == NULL) { 1776195534Sscottl request_ccb = malloc(sizeof(union ccb), M_CAMXPT, M_NOWAIT); 1777195534Sscottl if (request_ccb == NULL) { 1778195534Sscottl xpt_print(path, "xpt_scan_lun: can't allocate CCB, " 1779195534Sscottl "can't continue\n"); 1780195534Sscottl return; 1781195534Sscottl } 1782195534Sscottl new_path = malloc(sizeof(*new_path), M_CAMXPT, M_NOWAIT); 1783195534Sscottl if (new_path == NULL) { 1784195534Sscottl xpt_print(path, "xpt_scan_lun: can't allocate path, " 1785195534Sscottl "can't continue\n"); 1786195534Sscottl free(request_ccb, M_CAMXPT); 1787195534Sscottl return; 1788195534Sscottl } 1789195534Sscottl status = xpt_compile_path(new_path, xpt_periph, 1790195534Sscottl path->bus->path_id, 1791195534Sscottl path->target->target_id, 1792195534Sscottl path->device->lun_id); 1793195534Sscottl 1794195534Sscottl if (status != CAM_REQ_CMP) { 1795195534Sscottl xpt_print(path, "xpt_scan_lun: can't compile path, " 1796195534Sscottl "can't continue\n"); 1797195534Sscottl free(request_ccb, M_CAMXPT); 1798195534Sscottl free(new_path, M_CAMXPT); 1799195534Sscottl return; 1800195534Sscottl } 1801195534Sscottl xpt_setup_ccb(&request_ccb->ccb_h, new_path, /*priority*/ 1); 1802195534Sscottl request_ccb->ccb_h.cbfcnp = xptscandone; 1803195534Sscottl request_ccb->ccb_h.func_code = XPT_SCAN_LUN; 1804195534Sscottl request_ccb->crcn.flags = flags; 1805195534Sscottl } 1806195534Sscottl 1807195534Sscottl if ((old_periph = cam_periph_find(path, "probe")) != NULL) { 1808195534Sscottl probe_softc *softc; 1809195534Sscottl 1810195534Sscottl softc = (probe_softc *)old_periph->softc; 1811195534Sscottl TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h, 1812195534Sscottl periph_links.tqe); 1813195534Sscottl } else { 1814195534Sscottl status = cam_periph_alloc(proberegister, NULL, probecleanup, 1815195534Sscottl probestart, "probe", 1816195534Sscottl CAM_PERIPH_BIO, 1817195534Sscottl request_ccb->ccb_h.path, NULL, 0, 1818195534Sscottl request_ccb); 1819195534Sscottl 1820195534Sscottl if (status != CAM_REQ_CMP) { 1821195534Sscottl xpt_print(path, "xpt_scan_lun: cam_alloc_periph " 1822195534Sscottl "returned an error, can't continue probe\n"); 1823195534Sscottl request_ccb->ccb_h.status = status; 1824195534Sscottl xpt_done(request_ccb); 1825195534Sscottl } 1826195534Sscottl } 1827195534Sscottl} 1828195534Sscottl 1829195534Sscottlstatic void 1830195534Sscottlxptscandone(struct cam_periph *periph, union ccb *done_ccb) 1831195534Sscottl{ 1832195534Sscottl xpt_release_path(done_ccb->ccb_h.path); 1833195534Sscottl free(done_ccb->ccb_h.path, M_CAMXPT); 1834195534Sscottl free(done_ccb, M_CAMXPT); 1835195534Sscottl} 1836195534Sscottl 1837195534Sscottlstatic struct cam_ed * 1838195534Sscottlscsi_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id) 1839195534Sscottl{ 1840195534Sscottl struct cam_path path; 1841195534Sscottl struct scsi_quirk_entry *quirk; 1842195534Sscottl struct cam_ed *device; 1843195534Sscottl struct cam_ed *cur_device; 1844195534Sscottl 1845195534Sscottl device = xpt_alloc_device(bus, target, lun_id); 1846195534Sscottl if (device == NULL) 1847195534Sscottl return (NULL); 1848195534Sscottl 1849195534Sscottl /* 1850195534Sscottl * Take the default quirk entry until we have inquiry 1851195534Sscottl * data and can determine a better quirk to use. 1852195534Sscottl */ 1853195534Sscottl quirk = &scsi_quirk_table[scsi_quirk_table_size - 1]; 1854195534Sscottl device->quirk = (void *)quirk; 1855195534Sscottl device->mintags = quirk->mintags; 1856195534Sscottl device->maxtags = quirk->maxtags; 1857195534Sscottl bzero(&device->inq_data, sizeof(device->inq_data)); 1858195534Sscottl device->inq_flags = 0; 1859195534Sscottl device->queue_flags = 0; 1860195534Sscottl device->serial_num = NULL; 1861195534Sscottl device->serial_num_len = 0; 1862195534Sscottl 1863195534Sscottl /* 1864195534Sscottl * XXX should be limited by number of CCBs this bus can 1865195534Sscottl * do. 1866195534Sscottl */ 1867195534Sscottl bus->sim->max_ccbs += device->ccbq.devq_openings; 1868195534Sscottl /* Insertion sort into our target's device list */ 1869195534Sscottl cur_device = TAILQ_FIRST(&target->ed_entries); 1870195534Sscottl while (cur_device != NULL && cur_device->lun_id < lun_id) 1871195534Sscottl cur_device = TAILQ_NEXT(cur_device, links); 1872195534Sscottl if (cur_device != NULL) { 1873195534Sscottl TAILQ_INSERT_BEFORE(cur_device, device, links); 1874195534Sscottl } else { 1875195534Sscottl TAILQ_INSERT_TAIL(&target->ed_entries, device, links); 1876195534Sscottl } 1877195534Sscottl target->generation++; 1878195534Sscottl if (lun_id != CAM_LUN_WILDCARD) { 1879195534Sscottl xpt_compile_path(&path, 1880195534Sscottl NULL, 1881195534Sscottl bus->path_id, 1882195534Sscottl target->target_id, 1883195534Sscottl lun_id); 1884195534Sscottl scsi_devise_transport(&path); 1885195534Sscottl xpt_release_path(&path); 1886195534Sscottl } 1887195534Sscottl 1888195534Sscottl return (device); 1889195534Sscottl} 1890195534Sscottl 1891195534Sscottlstatic void 1892195534Sscottlscsi_devise_transport(struct cam_path *path) 1893195534Sscottl{ 1894195534Sscottl struct ccb_pathinq cpi; 1895195534Sscottl struct ccb_trans_settings cts; 1896195534Sscottl struct scsi_inquiry_data *inq_buf; 1897195534Sscottl 1898195534Sscottl /* Get transport information from the SIM */ 1899195534Sscottl xpt_setup_ccb(&cpi.ccb_h, path, /*priority*/1); 1900195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 1901195534Sscottl xpt_action((union ccb *)&cpi); 1902195534Sscottl 1903195534Sscottl inq_buf = NULL; 1904195534Sscottl if ((path->device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0) 1905195534Sscottl inq_buf = &path->device->inq_data; 1906195534Sscottl path->device->protocol = PROTO_SCSI; 1907195534Sscottl path->device->protocol_version = 1908195534Sscottl inq_buf != NULL ? SID_ANSI_REV(inq_buf) : cpi.protocol_version; 1909195534Sscottl path->device->transport = cpi.transport; 1910195534Sscottl path->device->transport_version = cpi.transport_version; 1911195534Sscottl 1912195534Sscottl /* 1913195534Sscottl * Any device not using SPI3 features should 1914195534Sscottl * be considered SPI2 or lower. 1915195534Sscottl */ 1916195534Sscottl if (inq_buf != NULL) { 1917195534Sscottl if (path->device->transport == XPORT_SPI 1918195534Sscottl && (inq_buf->spi3data & SID_SPI_MASK) == 0 1919195534Sscottl && path->device->transport_version > 2) 1920195534Sscottl path->device->transport_version = 2; 1921195534Sscottl } else { 1922195534Sscottl struct cam_ed* otherdev; 1923195534Sscottl 1924195534Sscottl for (otherdev = TAILQ_FIRST(&path->target->ed_entries); 1925195534Sscottl otherdev != NULL; 1926195534Sscottl otherdev = TAILQ_NEXT(otherdev, links)) { 1927195534Sscottl if (otherdev != path->device) 1928195534Sscottl break; 1929195534Sscottl } 1930195534Sscottl 1931195534Sscottl if (otherdev != NULL) { 1932195534Sscottl /* 1933195534Sscottl * Initially assume the same versioning as 1934195534Sscottl * prior luns for this target. 1935195534Sscottl */ 1936195534Sscottl path->device->protocol_version = 1937195534Sscottl otherdev->protocol_version; 1938195534Sscottl path->device->transport_version = 1939195534Sscottl otherdev->transport_version; 1940195534Sscottl } else { 1941195534Sscottl /* Until we know better, opt for safty */ 1942195534Sscottl path->device->protocol_version = 2; 1943195534Sscottl if (path->device->transport == XPORT_SPI) 1944195534Sscottl path->device->transport_version = 2; 1945195534Sscottl else 1946195534Sscottl path->device->transport_version = 0; 1947195534Sscottl } 1948195534Sscottl } 1949195534Sscottl 1950195534Sscottl /* 1951195534Sscottl * XXX 1952195534Sscottl * For a device compliant with SPC-2 we should be able 1953195534Sscottl * to determine the transport version supported by 1954195534Sscottl * scrutinizing the version descriptors in the 1955195534Sscottl * inquiry buffer. 1956195534Sscottl */ 1957195534Sscottl 1958195534Sscottl /* Tell the controller what we think */ 1959195534Sscottl xpt_setup_ccb(&cts.ccb_h, path, /*priority*/1); 1960195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1961195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 1962195534Sscottl cts.transport = path->device->transport; 1963195534Sscottl cts.transport_version = path->device->transport_version; 1964195534Sscottl cts.protocol = path->device->protocol; 1965195534Sscottl cts.protocol_version = path->device->protocol_version; 1966195534Sscottl cts.proto_specific.valid = 0; 1967195534Sscottl cts.xport_specific.valid = 0; 1968195534Sscottl xpt_action((union ccb *)&cts); 1969195534Sscottl} 1970195534Sscottl 1971195534Sscottlstatic void 1972195534Sscottlscsi_action(union ccb *start_ccb) 1973195534Sscottl{ 1974195534Sscottl 1975195534Sscottl switch (start_ccb->ccb_h.func_code) { 1976195534Sscottl case XPT_SET_TRAN_SETTINGS: 1977195534Sscottl { 1978195534Sscottl scsi_set_transfer_settings(&start_ccb->cts, 1979195534Sscottl start_ccb->ccb_h.path->device, 1980195534Sscottl /*async_update*/FALSE); 1981195534Sscottl break; 1982195534Sscottl } 1983195534Sscottl case XPT_SCAN_BUS: 1984195534Sscottl scsi_scan_bus(start_ccb->ccb_h.path->periph, start_ccb); 1985195534Sscottl break; 1986195534Sscottl case XPT_SCAN_LUN: 1987195534Sscottl scsi_scan_lun(start_ccb->ccb_h.path->periph, 1988195534Sscottl start_ccb->ccb_h.path, start_ccb->crcn.flags, 1989195534Sscottl start_ccb); 1990195534Sscottl break; 1991195534Sscottl case XPT_GET_TRAN_SETTINGS: 1992195534Sscottl { 1993195534Sscottl struct cam_sim *sim; 1994195534Sscottl 1995195534Sscottl sim = start_ccb->ccb_h.path->bus->sim; 1996195534Sscottl (*(sim->sim_action))(sim, start_ccb); 1997195534Sscottl break; 1998195534Sscottl } 1999195534Sscottl default: 2000195534Sscottl xpt_action_default(start_ccb); 2001195534Sscottl break; 2002195534Sscottl } 2003195534Sscottl} 2004195534Sscottl 2005195534Sscottlstatic void 2006195534Sscottlscsi_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device, 2007195534Sscottl int async_update) 2008195534Sscottl{ 2009195534Sscottl struct ccb_pathinq cpi; 2010195534Sscottl struct ccb_trans_settings cur_cts; 2011195534Sscottl struct ccb_trans_settings_scsi *scsi; 2012195534Sscottl struct ccb_trans_settings_scsi *cur_scsi; 2013195534Sscottl struct cam_sim *sim; 2014195534Sscottl struct scsi_inquiry_data *inq_data; 2015195534Sscottl 2016195534Sscottl if (device == NULL) { 2017195534Sscottl cts->ccb_h.status = CAM_PATH_INVALID; 2018195534Sscottl xpt_done((union ccb *)cts); 2019195534Sscottl return; 2020195534Sscottl } 2021195534Sscottl 2022195534Sscottl if (cts->protocol == PROTO_UNKNOWN 2023195534Sscottl || cts->protocol == PROTO_UNSPECIFIED) { 2024195534Sscottl cts->protocol = device->protocol; 2025195534Sscottl cts->protocol_version = device->protocol_version; 2026195534Sscottl } 2027195534Sscottl 2028195534Sscottl if (cts->protocol_version == PROTO_VERSION_UNKNOWN 2029195534Sscottl || cts->protocol_version == PROTO_VERSION_UNSPECIFIED) 2030195534Sscottl cts->protocol_version = device->protocol_version; 2031195534Sscottl 2032195534Sscottl if (cts->protocol != device->protocol) { 2033195534Sscottl xpt_print(cts->ccb_h.path, "Uninitialized Protocol %x:%x?\n", 2034195534Sscottl cts->protocol, device->protocol); 2035195534Sscottl cts->protocol = device->protocol; 2036195534Sscottl } 2037195534Sscottl 2038195534Sscottl if (cts->protocol_version > device->protocol_version) { 2039195534Sscottl if (bootverbose) { 2040195534Sscottl xpt_print(cts->ccb_h.path, "Down reving Protocol " 2041195534Sscottl "Version from %d to %d?\n", cts->protocol_version, 2042195534Sscottl device->protocol_version); 2043195534Sscottl } 2044195534Sscottl cts->protocol_version = device->protocol_version; 2045195534Sscottl } 2046195534Sscottl 2047195534Sscottl if (cts->transport == XPORT_UNKNOWN 2048195534Sscottl || cts->transport == XPORT_UNSPECIFIED) { 2049195534Sscottl cts->transport = device->transport; 2050195534Sscottl cts->transport_version = device->transport_version; 2051195534Sscottl } 2052195534Sscottl 2053195534Sscottl if (cts->transport_version == XPORT_VERSION_UNKNOWN 2054195534Sscottl || cts->transport_version == XPORT_VERSION_UNSPECIFIED) 2055195534Sscottl cts->transport_version = device->transport_version; 2056195534Sscottl 2057195534Sscottl if (cts->transport != device->transport) { 2058195534Sscottl xpt_print(cts->ccb_h.path, "Uninitialized Transport %x:%x?\n", 2059195534Sscottl cts->transport, device->transport); 2060195534Sscottl cts->transport = device->transport; 2061195534Sscottl } 2062195534Sscottl 2063195534Sscottl if (cts->transport_version > device->transport_version) { 2064195534Sscottl if (bootverbose) { 2065195534Sscottl xpt_print(cts->ccb_h.path, "Down reving Transport " 2066195534Sscottl "Version from %d to %d?\n", cts->transport_version, 2067195534Sscottl device->transport_version); 2068195534Sscottl } 2069195534Sscottl cts->transport_version = device->transport_version; 2070195534Sscottl } 2071195534Sscottl 2072195534Sscottl sim = cts->ccb_h.path->bus->sim; 2073195534Sscottl 2074195534Sscottl /* 2075195534Sscottl * Nothing more of interest to do unless 2076195534Sscottl * this is a device connected via the 2077195534Sscottl * SCSI protocol. 2078195534Sscottl */ 2079195534Sscottl if (cts->protocol != PROTO_SCSI) { 2080195534Sscottl if (async_update == FALSE) 2081195534Sscottl (*(sim->sim_action))(sim, (union ccb *)cts); 2082195534Sscottl return; 2083195534Sscottl } 2084195534Sscottl 2085195534Sscottl inq_data = &device->inq_data; 2086195534Sscottl scsi = &cts->proto_specific.scsi; 2087195534Sscottl xpt_setup_ccb(&cpi.ccb_h, cts->ccb_h.path, /*priority*/1); 2088195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 2089195534Sscottl xpt_action((union ccb *)&cpi); 2090195534Sscottl 2091195534Sscottl /* SCSI specific sanity checking */ 2092195534Sscottl if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0 2093195534Sscottl || (INQ_DATA_TQ_ENABLED(inq_data)) == 0 2094195534Sscottl || (device->queue_flags & SCP_QUEUE_DQUE) != 0 2095195534Sscottl || (device->mintags == 0)) { 2096195534Sscottl /* 2097195534Sscottl * Can't tag on hardware that doesn't support tags, 2098195534Sscottl * doesn't have it enabled, or has broken tag support. 2099195534Sscottl */ 2100195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 2101195534Sscottl } 2102195534Sscottl 2103195534Sscottl if (async_update == FALSE) { 2104195534Sscottl /* 2105195534Sscottl * Perform sanity checking against what the 2106195534Sscottl * controller and device can do. 2107195534Sscottl */ 2108195534Sscottl xpt_setup_ccb(&cur_cts.ccb_h, cts->ccb_h.path, /*priority*/1); 2109195534Sscottl cur_cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 2110195534Sscottl cur_cts.type = cts->type; 2111195534Sscottl xpt_action((union ccb *)&cur_cts); 2112195534Sscottl if ((cur_cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 2113195534Sscottl return; 2114195534Sscottl } 2115195534Sscottl cur_scsi = &cur_cts.proto_specific.scsi; 2116195534Sscottl if ((scsi->valid & CTS_SCSI_VALID_TQ) == 0) { 2117195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 2118195534Sscottl scsi->flags |= cur_scsi->flags & CTS_SCSI_FLAGS_TAG_ENB; 2119195534Sscottl } 2120195534Sscottl if ((cur_scsi->valid & CTS_SCSI_VALID_TQ) == 0) 2121195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 2122195534Sscottl } 2123195534Sscottl 2124195534Sscottl /* SPI specific sanity checking */ 2125195534Sscottl if (cts->transport == XPORT_SPI && async_update == FALSE) { 2126195534Sscottl u_int spi3caps; 2127195534Sscottl struct ccb_trans_settings_spi *spi; 2128195534Sscottl struct ccb_trans_settings_spi *cur_spi; 2129195534Sscottl 2130195534Sscottl spi = &cts->xport_specific.spi; 2131195534Sscottl 2132195534Sscottl cur_spi = &cur_cts.xport_specific.spi; 2133195534Sscottl 2134195534Sscottl /* Fill in any gaps in what the user gave us */ 2135195534Sscottl if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) 2136195534Sscottl spi->sync_period = cur_spi->sync_period; 2137195534Sscottl if ((cur_spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) 2138195534Sscottl spi->sync_period = 0; 2139195534Sscottl if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0) 2140195534Sscottl spi->sync_offset = cur_spi->sync_offset; 2141195534Sscottl if ((cur_spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0) 2142195534Sscottl spi->sync_offset = 0; 2143195534Sscottl if ((spi->valid & CTS_SPI_VALID_PPR_OPTIONS) == 0) 2144195534Sscottl spi->ppr_options = cur_spi->ppr_options; 2145195534Sscottl if ((cur_spi->valid & CTS_SPI_VALID_PPR_OPTIONS) == 0) 2146195534Sscottl spi->ppr_options = 0; 2147195534Sscottl if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) == 0) 2148195534Sscottl spi->bus_width = cur_spi->bus_width; 2149195534Sscottl if ((cur_spi->valid & CTS_SPI_VALID_BUS_WIDTH) == 0) 2150195534Sscottl spi->bus_width = 0; 2151195534Sscottl if ((spi->valid & CTS_SPI_VALID_DISC) == 0) { 2152195534Sscottl spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; 2153195534Sscottl spi->flags |= cur_spi->flags & CTS_SPI_FLAGS_DISC_ENB; 2154195534Sscottl } 2155195534Sscottl if ((cur_spi->valid & CTS_SPI_VALID_DISC) == 0) 2156195534Sscottl spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; 2157195534Sscottl if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0 2158195534Sscottl && (inq_data->flags & SID_Sync) == 0 2159195534Sscottl && cts->type == CTS_TYPE_CURRENT_SETTINGS) 2160195534Sscottl || ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0)) { 2161195534Sscottl /* Force async */ 2162195534Sscottl spi->sync_period = 0; 2163195534Sscottl spi->sync_offset = 0; 2164195534Sscottl } 2165195534Sscottl 2166195534Sscottl switch (spi->bus_width) { 2167195534Sscottl case MSG_EXT_WDTR_BUS_32_BIT: 2168195534Sscottl if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) == 0 2169195534Sscottl || (inq_data->flags & SID_WBus32) != 0 2170195534Sscottl || cts->type == CTS_TYPE_USER_SETTINGS) 2171195534Sscottl && (cpi.hba_inquiry & PI_WIDE_32) != 0) 2172195534Sscottl break; 2173195534Sscottl /* Fall Through to 16-bit */ 2174195534Sscottl case MSG_EXT_WDTR_BUS_16_BIT: 2175195534Sscottl if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) == 0 2176195534Sscottl || (inq_data->flags & SID_WBus16) != 0 2177195534Sscottl || cts->type == CTS_TYPE_USER_SETTINGS) 2178195534Sscottl && (cpi.hba_inquiry & PI_WIDE_16) != 0) { 2179195534Sscottl spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT; 2180195534Sscottl break; 2181195534Sscottl } 2182195534Sscottl /* Fall Through to 8-bit */ 2183195534Sscottl default: /* New bus width?? */ 2184195534Sscottl case MSG_EXT_WDTR_BUS_8_BIT: 2185195534Sscottl /* All targets can do this */ 2186195534Sscottl spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT; 2187195534Sscottl break; 2188195534Sscottl } 2189195534Sscottl 2190195534Sscottl spi3caps = cpi.xport_specific.spi.ppr_options; 2191195534Sscottl if ((device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0 2192195534Sscottl && cts->type == CTS_TYPE_CURRENT_SETTINGS) 2193195534Sscottl spi3caps &= inq_data->spi3data; 2194195534Sscottl 2195195534Sscottl if ((spi3caps & SID_SPI_CLOCK_DT) == 0) 2196195534Sscottl spi->ppr_options &= ~MSG_EXT_PPR_DT_REQ; 2197195534Sscottl 2198195534Sscottl if ((spi3caps & SID_SPI_IUS) == 0) 2199195534Sscottl spi->ppr_options &= ~MSG_EXT_PPR_IU_REQ; 2200195534Sscottl 2201195534Sscottl if ((spi3caps & SID_SPI_QAS) == 0) 2202195534Sscottl spi->ppr_options &= ~MSG_EXT_PPR_QAS_REQ; 2203195534Sscottl 2204195534Sscottl /* No SPI Transfer settings are allowed unless we are wide */ 2205195534Sscottl if (spi->bus_width == 0) 2206195534Sscottl spi->ppr_options = 0; 2207195534Sscottl 2208195534Sscottl if ((spi->valid & CTS_SPI_VALID_DISC) 2209195534Sscottl && ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) == 0)) { 2210195534Sscottl /* 2211195534Sscottl * Can't tag queue without disconnection. 2212195534Sscottl */ 2213195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 2214195534Sscottl scsi->valid |= CTS_SCSI_VALID_TQ; 2215195534Sscottl } 2216195534Sscottl 2217195534Sscottl /* 2218195534Sscottl * If we are currently performing tagged transactions to 2219195534Sscottl * this device and want to change its negotiation parameters, 2220195534Sscottl * go non-tagged for a bit to give the controller a chance to 2221195534Sscottl * negotiate unhampered by tag messages. 2222195534Sscottl */ 2223195534Sscottl if (cts->type == CTS_TYPE_CURRENT_SETTINGS 2224195534Sscottl && (device->inq_flags & SID_CmdQue) != 0 2225195534Sscottl && (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0 2226195534Sscottl && (spi->flags & (CTS_SPI_VALID_SYNC_RATE| 2227195534Sscottl CTS_SPI_VALID_SYNC_OFFSET| 2228195534Sscottl CTS_SPI_VALID_BUS_WIDTH)) != 0) 2229195534Sscottl scsi_toggle_tags(cts->ccb_h.path); 2230195534Sscottl } 2231195534Sscottl 2232195534Sscottl if (cts->type == CTS_TYPE_CURRENT_SETTINGS 2233195534Sscottl && (scsi->valid & CTS_SCSI_VALID_TQ) != 0) { 2234195534Sscottl int device_tagenb; 2235195534Sscottl 2236195534Sscottl /* 2237195534Sscottl * If we are transitioning from tags to no-tags or 2238195534Sscottl * vice-versa, we need to carefully freeze and restart 2239195534Sscottl * the queue so that we don't overlap tagged and non-tagged 2240195534Sscottl * commands. We also temporarily stop tags if there is 2241195534Sscottl * a change in transfer negotiation settings to allow 2242195534Sscottl * "tag-less" negotiation. 2243195534Sscottl */ 2244195534Sscottl if ((device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 2245195534Sscottl || (device->inq_flags & SID_CmdQue) != 0) 2246195534Sscottl device_tagenb = TRUE; 2247195534Sscottl else 2248195534Sscottl device_tagenb = FALSE; 2249195534Sscottl 2250195534Sscottl if (((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0 2251195534Sscottl && device_tagenb == FALSE) 2252195534Sscottl || ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) == 0 2253195534Sscottl && device_tagenb == TRUE)) { 2254195534Sscottl 2255195534Sscottl if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) { 2256195534Sscottl /* 2257195534Sscottl * Delay change to use tags until after a 2258195534Sscottl * few commands have gone to this device so 2259195534Sscottl * the controller has time to perform transfer 2260195534Sscottl * negotiations without tagged messages getting 2261195534Sscottl * in the way. 2262195534Sscottl */ 2263195534Sscottl device->tag_delay_count = CAM_TAG_DELAY_COUNT; 2264195534Sscottl device->flags |= CAM_DEV_TAG_AFTER_COUNT; 2265195534Sscottl } else { 2266195534Sscottl struct ccb_relsim crs; 2267195534Sscottl 2268195534Sscottl xpt_freeze_devq(cts->ccb_h.path, /*count*/1); 2269195534Sscottl device->inq_flags &= ~SID_CmdQue; 2270195534Sscottl xpt_dev_ccbq_resize(cts->ccb_h.path, 2271195534Sscottl sim->max_dev_openings); 2272195534Sscottl device->flags &= ~CAM_DEV_TAG_AFTER_COUNT; 2273195534Sscottl device->tag_delay_count = 0; 2274195534Sscottl 2275195534Sscottl xpt_setup_ccb(&crs.ccb_h, cts->ccb_h.path, 2276195534Sscottl /*priority*/1); 2277195534Sscottl crs.ccb_h.func_code = XPT_REL_SIMQ; 2278195534Sscottl crs.release_flags = RELSIM_RELEASE_AFTER_QEMPTY; 2279195534Sscottl crs.openings 2280195534Sscottl = crs.release_timeout 2281195534Sscottl = crs.qfrozen_cnt 2282195534Sscottl = 0; 2283195534Sscottl xpt_action((union ccb *)&crs); 2284195534Sscottl } 2285195534Sscottl } 2286195534Sscottl } 2287195534Sscottl if (async_update == FALSE) 2288195534Sscottl (*(sim->sim_action))(sim, (union ccb *)cts); 2289195534Sscottl} 2290195534Sscottl 2291195534Sscottlstatic void 2292195534Sscottlscsi_toggle_tags(struct cam_path *path) 2293195534Sscottl{ 2294195534Sscottl struct cam_ed *dev; 2295195534Sscottl 2296195534Sscottl /* 2297195534Sscottl * Give controllers a chance to renegotiate 2298195534Sscottl * before starting tag operations. We 2299195534Sscottl * "toggle" tagged queuing off then on 2300195534Sscottl * which causes the tag enable command delay 2301195534Sscottl * counter to come into effect. 2302195534Sscottl */ 2303195534Sscottl dev = path->device; 2304195534Sscottl if ((dev->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 2305195534Sscottl || ((dev->inq_flags & SID_CmdQue) != 0 2306195534Sscottl && (dev->inq_flags & (SID_Sync|SID_WBus16|SID_WBus32)) != 0)) { 2307195534Sscottl struct ccb_trans_settings cts; 2308195534Sscottl 2309195534Sscottl xpt_setup_ccb(&cts.ccb_h, path, 1); 2310195534Sscottl cts.protocol = PROTO_SCSI; 2311195534Sscottl cts.protocol_version = PROTO_VERSION_UNSPECIFIED; 2312195534Sscottl cts.transport = XPORT_UNSPECIFIED; 2313195534Sscottl cts.transport_version = XPORT_VERSION_UNSPECIFIED; 2314195534Sscottl cts.proto_specific.scsi.flags = 0; 2315195534Sscottl cts.proto_specific.scsi.valid = CTS_SCSI_VALID_TQ; 2316195534Sscottl scsi_set_transfer_settings(&cts, path->device, 2317195534Sscottl /*async_update*/TRUE); 2318195534Sscottl cts.proto_specific.scsi.flags = CTS_SCSI_FLAGS_TAG_ENB; 2319195534Sscottl scsi_set_transfer_settings(&cts, path->device, 2320195534Sscottl /*async_update*/TRUE); 2321195534Sscottl } 2322195534Sscottl} 2323195534Sscottl 2324195534Sscottl/* 2325195534Sscottl * Handle any per-device event notifications that require action by the XPT. 2326195534Sscottl */ 2327195534Sscottlstatic void 2328195534Sscottlscsi_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target, 2329195534Sscottl struct cam_ed *device, void *async_arg) 2330195534Sscottl{ 2331195534Sscottl cam_status status; 2332195534Sscottl struct cam_path newpath; 2333195534Sscottl 2334195534Sscottl /* 2335195534Sscottl * We only need to handle events for real devices. 2336195534Sscottl */ 2337195534Sscottl if (target->target_id == CAM_TARGET_WILDCARD 2338195534Sscottl || device->lun_id == CAM_LUN_WILDCARD) 2339195534Sscottl return; 2340195534Sscottl 2341195534Sscottl /* 2342195534Sscottl * We need our own path with wildcards expanded to 2343195534Sscottl * handle certain types of events. 2344195534Sscottl */ 2345195534Sscottl if ((async_code == AC_SENT_BDR) 2346195534Sscottl || (async_code == AC_BUS_RESET) 2347195534Sscottl || (async_code == AC_INQ_CHANGED)) 2348195534Sscottl status = xpt_compile_path(&newpath, NULL, 2349195534Sscottl bus->path_id, 2350195534Sscottl target->target_id, 2351195534Sscottl device->lun_id); 2352195534Sscottl else 2353195534Sscottl status = CAM_REQ_CMP_ERR; 2354195534Sscottl 2355195534Sscottl if (status == CAM_REQ_CMP) { 2356195534Sscottl 2357195534Sscottl /* 2358195534Sscottl * Allow transfer negotiation to occur in a 2359195534Sscottl * tag free environment. 2360195534Sscottl */ 2361195534Sscottl if (async_code == AC_SENT_BDR 2362195534Sscottl || async_code == AC_BUS_RESET) 2363195534Sscottl scsi_toggle_tags(&newpath); 2364195534Sscottl 2365195534Sscottl if (async_code == AC_INQ_CHANGED) { 2366195534Sscottl /* 2367195534Sscottl * We've sent a start unit command, or 2368195534Sscottl * something similar to a device that 2369195534Sscottl * may have caused its inquiry data to 2370195534Sscottl * change. So we re-scan the device to 2371195534Sscottl * refresh the inquiry data for it. 2372195534Sscottl */ 2373195534Sscottl scsi_scan_lun(newpath.periph, &newpath, 2374195534Sscottl CAM_EXPECT_INQ_CHANGE, NULL); 2375195534Sscottl } 2376195534Sscottl xpt_release_path(&newpath); 2377195534Sscottl } else if (async_code == AC_LOST_DEVICE) { 2378195534Sscottl device->flags |= CAM_DEV_UNCONFIGURED; 2379195534Sscottl } else if (async_code == AC_TRANSFER_NEG) { 2380195534Sscottl struct ccb_trans_settings *settings; 2381195534Sscottl 2382195534Sscottl settings = (struct ccb_trans_settings *)async_arg; 2383195534Sscottl scsi_set_transfer_settings(settings, device, 2384195534Sscottl /*async_update*/TRUE); 2385195534Sscottl } 2386195534Sscottl} 2387195534Sscottl 2388