ata_xpt.c revision 199799
1195534Sscottl/*- 2195534Sscottl * Copyright (c) 2009 Alexander Motin <mav@FreeBSD.org> 3195534Sscottl * All rights reserved. 4195534Sscottl * 5195534Sscottl * Redistribution and use in source and binary forms, with or without 6195534Sscottl * modification, are permitted provided that the following conditions 7195534Sscottl * are met: 8195534Sscottl * 1. Redistributions of source code must retain the above copyright 9195534Sscottl * notice, this list of conditions and the following disclaimer, 10195534Sscottl * without modification, immediately at the beginning of the file. 11195534Sscottl * 2. Redistributions in binary form must reproduce the above copyright 12195534Sscottl * notice, this list of conditions and the following disclaimer in the 13195534Sscottl * documentation and/or other materials provided with the distribution. 14195534Sscottl * 15195534Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16195534Sscottl * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17195534Sscottl * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18195534Sscottl * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19195534Sscottl * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20195534Sscottl * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21195534Sscottl * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22195534Sscottl * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23195534Sscottl * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24195534Sscottl * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25195534Sscottl */ 26195534Sscottl 27195534Sscottl#include <sys/cdefs.h> 28195534Sscottl__FBSDID("$FreeBSD: head/sys/cam/ata/ata_xpt.c 199799 2009-11-25 14:24:14Z mav $"); 29195534Sscottl 30195534Sscottl#include <sys/param.h> 31195534Sscottl#include <sys/bus.h> 32195534Sscottl#include <sys/endian.h> 33195534Sscottl#include <sys/systm.h> 34195534Sscottl#include <sys/types.h> 35195534Sscottl#include <sys/malloc.h> 36195534Sscottl#include <sys/kernel.h> 37195534Sscottl#include <sys/time.h> 38195534Sscottl#include <sys/conf.h> 39195534Sscottl#include <sys/fcntl.h> 40195534Sscottl#include <sys/md5.h> 41195534Sscottl#include <sys/interrupt.h> 42195534Sscottl#include <sys/sbuf.h> 43195534Sscottl 44195534Sscottl#include <sys/lock.h> 45195534Sscottl#include <sys/mutex.h> 46195534Sscottl#include <sys/sysctl.h> 47195534Sscottl 48195534Sscottl#ifdef PC98 49195534Sscottl#include <pc98/pc98/pc98_machdep.h> /* geometry translation */ 50195534Sscottl#endif 51195534Sscottl 52195534Sscottl#include <cam/cam.h> 53195534Sscottl#include <cam/cam_ccb.h> 54195534Sscottl#include <cam/cam_queue.h> 55195534Sscottl#include <cam/cam_periph.h> 56195534Sscottl#include <cam/cam_sim.h> 57195534Sscottl#include <cam/cam_xpt.h> 58195534Sscottl#include <cam/cam_xpt_sim.h> 59195534Sscottl#include <cam/cam_xpt_periph.h> 60195534Sscottl#include <cam/cam_xpt_internal.h> 61195534Sscottl#include <cam/cam_debug.h> 62195534Sscottl 63195534Sscottl#include <cam/scsi/scsi_all.h> 64195534Sscottl#include <cam/scsi/scsi_message.h> 65195534Sscottl#include <cam/ata/ata_all.h> 66195534Sscottl#include <machine/stdarg.h> /* for xpt_print below */ 67195534Sscottl#include "opt_cam.h" 68195534Sscottl 69199178Smavstruct ata_quirk_entry { 70195534Sscottl struct scsi_inquiry_pattern inq_pat; 71195534Sscottl u_int8_t quirks; 72199178Smav#define CAM_QUIRK_MAXTAGS 0x01 73195534Sscottl u_int maxtags; 74195534Sscottl}; 75195534Sscottl 76195534Sscottlstatic periph_init_t probe_periph_init; 77195534Sscottl 78195534Sscottlstatic struct periph_driver probe_driver = 79195534Sscottl{ 80195653Smav probe_periph_init, "aprobe", 81198708Smav TAILQ_HEAD_INITIALIZER(probe_driver.units), /* generation */ 0, 82198708Smav CAM_PERIPH_DRV_EARLY 83195534Sscottl}; 84195534Sscottl 85195653SmavPERIPHDRIVER_DECLARE(aprobe, probe_driver); 86195534Sscottl 87195534Sscottltypedef enum { 88195534Sscottl PROBE_RESET, 89195534Sscottl PROBE_IDENTIFY, 90195534Sscottl PROBE_SETMODE, 91198708Smav PROBE_SET_MULTI, 92195534Sscottl PROBE_INQUIRY, 93195534Sscottl PROBE_FULL_INQUIRY, 94195534Sscottl PROBE_PM_PID, 95195534Sscottl PROBE_PM_PRV, 96195534Sscottl PROBE_INVALID 97195534Sscottl} probe_action; 98195534Sscottl 99195534Sscottlstatic char *probe_action_text[] = { 100195534Sscottl "PROBE_RESET", 101195534Sscottl "PROBE_IDENTIFY", 102195534Sscottl "PROBE_SETMODE", 103198708Smav "PROBE_SET_MULTI", 104195534Sscottl "PROBE_INQUIRY", 105195534Sscottl "PROBE_FULL_INQUIRY", 106195534Sscottl "PROBE_PM_PID", 107195534Sscottl "PROBE_PM_PRV", 108195534Sscottl "PROBE_INVALID" 109195534Sscottl}; 110195534Sscottl 111195534Sscottl#define PROBE_SET_ACTION(softc, newaction) \ 112195534Sscottldo { \ 113195534Sscottl char **text; \ 114195534Sscottl text = probe_action_text; \ 115195534Sscottl CAM_DEBUG((softc)->periph->path, CAM_DEBUG_INFO, \ 116195534Sscottl ("Probe %s to %s\n", text[(softc)->action], \ 117195534Sscottl text[(newaction)])); \ 118195534Sscottl (softc)->action = (newaction); \ 119195534Sscottl} while(0) 120195534Sscottl 121195534Sscottltypedef enum { 122195534Sscottl PROBE_NO_ANNOUNCE = 0x04 123195534Sscottl} probe_flags; 124195534Sscottl 125195534Sscottltypedef struct { 126195534Sscottl TAILQ_HEAD(, ccb_hdr) request_ccbs; 127195534Sscottl probe_action action; 128195534Sscottl union ccb saved_ccb; 129195534Sscottl probe_flags flags; 130195534Sscottl u_int8_t digest[16]; 131195534Sscottl uint32_t pm_pid; 132195534Sscottl uint32_t pm_prv; 133195534Sscottl struct cam_periph *periph; 134195534Sscottl} probe_softc; 135195534Sscottl 136199178Smavstatic struct ata_quirk_entry ata_quirk_table[] = 137195534Sscottl{ 138195534Sscottl { 139195534Sscottl /* Default tagged queuing parameters for all devices */ 140195534Sscottl { 141195534Sscottl T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED, 142195534Sscottl /*vendor*/"*", /*product*/"*", /*revision*/"*" 143195534Sscottl }, 144199178Smav /*quirks*/0, /*maxtags*/0 145195534Sscottl }, 146195534Sscottl}; 147195534Sscottl 148199178Smavstatic const int ata_quirk_table_size = 149199178Smav sizeof(ata_quirk_table) / sizeof(*ata_quirk_table); 150195534Sscottl 151195534Sscottlstatic cam_status proberegister(struct cam_periph *periph, 152195534Sscottl void *arg); 153195534Sscottlstatic void probeschedule(struct cam_periph *probe_periph); 154195534Sscottlstatic void probestart(struct cam_periph *periph, union ccb *start_ccb); 155195534Sscottl//static void proberequestdefaultnegotiation(struct cam_periph *periph); 156195534Sscottl//static int proberequestbackoff(struct cam_periph *periph, 157195534Sscottl// struct cam_ed *device); 158195534Sscottlstatic void probedone(struct cam_periph *periph, union ccb *done_ccb); 159195534Sscottlstatic void probecleanup(struct cam_periph *periph); 160199178Smavstatic void ata_find_quirk(struct cam_ed *device); 161195534Sscottlstatic void ata_scan_bus(struct cam_periph *periph, union ccb *ccb); 162195534Sscottlstatic void ata_scan_lun(struct cam_periph *periph, 163195534Sscottl struct cam_path *path, cam_flags flags, 164195534Sscottl union ccb *ccb); 165195534Sscottlstatic void xptscandone(struct cam_periph *periph, union ccb *done_ccb); 166195534Sscottlstatic struct cam_ed * 167195534Sscottl ata_alloc_device(struct cam_eb *bus, struct cam_et *target, 168195534Sscottl lun_id_t lun_id); 169195534Sscottlstatic void ata_device_transport(struct cam_path *path); 170199178Smavstatic void ata_set_transfer_settings(struct ccb_trans_settings *cts, 171195534Sscottl struct cam_ed *device, 172195534Sscottl int async_update); 173195534Sscottlstatic void ata_dev_async(u_int32_t async_code, 174195534Sscottl struct cam_eb *bus, 175195534Sscottl struct cam_et *target, 176195534Sscottl struct cam_ed *device, 177195534Sscottl void *async_arg); 178195534Sscottlstatic void ata_action(union ccb *start_ccb); 179195534Sscottl 180195534Sscottlstatic struct xpt_xport ata_xport = { 181195534Sscottl .alloc_device = ata_alloc_device, 182195534Sscottl .action = ata_action, 183195534Sscottl .async = ata_dev_async, 184195534Sscottl}; 185195534Sscottl 186195534Sscottlstruct xpt_xport * 187195534Sscottlata_get_xport(void) 188195534Sscottl{ 189195534Sscottl return (&ata_xport); 190195534Sscottl} 191195534Sscottl 192195534Sscottlstatic void 193195534Sscottlprobe_periph_init() 194195534Sscottl{ 195195534Sscottl} 196195534Sscottl 197195534Sscottlstatic cam_status 198195534Sscottlproberegister(struct cam_periph *periph, void *arg) 199195534Sscottl{ 200195534Sscottl union ccb *request_ccb; /* CCB representing the probe request */ 201195534Sscottl cam_status status; 202195534Sscottl probe_softc *softc; 203195534Sscottl 204195534Sscottl request_ccb = (union ccb *)arg; 205195534Sscottl if (periph == NULL) { 206195534Sscottl printf("proberegister: periph was NULL!!\n"); 207195534Sscottl return(CAM_REQ_CMP_ERR); 208195534Sscottl } 209195534Sscottl 210195534Sscottl if (request_ccb == NULL) { 211195534Sscottl printf("proberegister: no probe CCB, " 212195534Sscottl "can't register device\n"); 213195534Sscottl return(CAM_REQ_CMP_ERR); 214195534Sscottl } 215195534Sscottl 216195534Sscottl softc = (probe_softc *)malloc(sizeof(*softc), M_CAMXPT, M_NOWAIT); 217195534Sscottl 218195534Sscottl if (softc == NULL) { 219195534Sscottl printf("proberegister: Unable to probe new device. " 220195534Sscottl "Unable to allocate softc\n"); 221195534Sscottl return(CAM_REQ_CMP_ERR); 222195534Sscottl } 223195534Sscottl TAILQ_INIT(&softc->request_ccbs); 224195534Sscottl TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h, 225195534Sscottl periph_links.tqe); 226195534Sscottl softc->flags = 0; 227195534Sscottl periph->softc = softc; 228195534Sscottl softc->periph = periph; 229195534Sscottl softc->action = PROBE_INVALID; 230195534Sscottl status = cam_periph_acquire(periph); 231195534Sscottl if (status != CAM_REQ_CMP) { 232195534Sscottl return (status); 233195534Sscottl } 234195534Sscottl 235195534Sscottl 236195534Sscottl /* 237195534Sscottl * Ensure we've waited at least a bus settle 238195534Sscottl * delay before attempting to probe the device. 239195534Sscottl * For HBAs that don't do bus resets, this won't make a difference. 240195534Sscottl */ 241195534Sscottl cam_periph_freeze_after_event(periph, &periph->path->bus->last_reset, 242195534Sscottl scsi_delay); 243195534Sscottl probeschedule(periph); 244195534Sscottl return(CAM_REQ_CMP); 245195534Sscottl} 246195534Sscottl 247195534Sscottlstatic void 248195534Sscottlprobeschedule(struct cam_periph *periph) 249195534Sscottl{ 250195534Sscottl struct ccb_pathinq cpi; 251195534Sscottl union ccb *ccb; 252195534Sscottl probe_softc *softc; 253195534Sscottl 254195534Sscottl softc = (probe_softc *)periph->softc; 255195534Sscottl ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs); 256195534Sscottl 257198382Smav xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 258195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 259195534Sscottl xpt_action((union ccb *)&cpi); 260195534Sscottl 261198389Smav if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) || 262198389Smav periph->path->device->protocol == PROTO_SATAPM) 263195534Sscottl PROBE_SET_ACTION(softc, PROBE_RESET); 264195534Sscottl else 265195534Sscottl PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 266195534Sscottl 267195534Sscottl if (ccb->crcn.flags & CAM_EXPECT_INQ_CHANGE) 268195534Sscottl softc->flags |= PROBE_NO_ANNOUNCE; 269195534Sscottl else 270195534Sscottl softc->flags &= ~PROBE_NO_ANNOUNCE; 271195534Sscottl 272195534Sscottl xpt_schedule(periph, ccb->ccb_h.pinfo.priority); 273195534Sscottl} 274195534Sscottl 275195534Sscottlstatic void 276195534Sscottlprobestart(struct cam_periph *periph, union ccb *start_ccb) 277195534Sscottl{ 278199747Smav struct ccb_trans_settings cts; 279195534Sscottl struct ccb_ataio *ataio; 280195534Sscottl struct ccb_scsiio *csio; 281195534Sscottl probe_softc *softc; 282198708Smav struct cam_path *path; 283198708Smav struct ata_params *ident_buf; 284195534Sscottl 285195534Sscottl CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probestart\n")); 286195534Sscottl 287195534Sscottl softc = (probe_softc *)periph->softc; 288198708Smav path = start_ccb->ccb_h.path; 289195534Sscottl ataio = &start_ccb->ataio; 290195534Sscottl csio = &start_ccb->csio; 291198708Smav ident_buf = &periph->path->device->ident_data; 292195534Sscottl 293195534Sscottl switch (softc->action) { 294195534Sscottl case PROBE_RESET: 295195534Sscottl cam_fill_ataio(ataio, 296195534Sscottl 0, 297195534Sscottl probedone, 298195534Sscottl /*flags*/CAM_DIR_NONE, 299198389Smav 0, 300195534Sscottl /*data_ptr*/NULL, 301195534Sscottl /*dxfer_len*/0, 302195534Sscottl (start_ccb->ccb_h.target_id == 15 ? 3 : 15) * 1000); 303195534Sscottl ata_reset_cmd(ataio); 304195534Sscottl break; 305195534Sscottl case PROBE_IDENTIFY: 306195534Sscottl if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) { 307195534Sscottl /* Prepare check that it is the same device. */ 308195534Sscottl MD5_CTX context; 309195534Sscottl 310195534Sscottl MD5Init(&context); 311195534Sscottl MD5Update(&context, 312195534Sscottl (unsigned char *)ident_buf->model, 313195534Sscottl sizeof(ident_buf->model)); 314195534Sscottl MD5Update(&context, 315195534Sscottl (unsigned char *)ident_buf->revision, 316195534Sscottl sizeof(ident_buf->revision)); 317195534Sscottl MD5Update(&context, 318195534Sscottl (unsigned char *)ident_buf->serial, 319195534Sscottl sizeof(ident_buf->serial)); 320195534Sscottl MD5Final(softc->digest, &context); 321195534Sscottl } 322195534Sscottl cam_fill_ataio(ataio, 323195534Sscottl 1, 324195534Sscottl probedone, 325195534Sscottl /*flags*/CAM_DIR_IN, 326198389Smav 0, 327195534Sscottl /*data_ptr*/(u_int8_t *)ident_buf, 328195534Sscottl /*dxfer_len*/sizeof(struct ata_params), 329195534Sscottl 30 * 1000); 330195534Sscottl if (periph->path->device->protocol == PROTO_ATA) 331196659Smav ata_28bit_cmd(ataio, ATA_ATA_IDENTIFY, 0, 0, 0); 332195534Sscottl else 333196659Smav ata_28bit_cmd(ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0); 334195534Sscottl break; 335195534Sscottl case PROBE_SETMODE: 336199747Smav { 337199747Smav int mode, wantmode; 338199747Smav 339199747Smav mode = 0; 340199747Smav /* Fetch user modes from SIM. */ 341199747Smav bzero(&cts, sizeof(cts)); 342199747Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); 343199747Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 344199747Smav cts.type = CTS_TYPE_USER_SETTINGS; 345199747Smav xpt_action((union ccb *)&cts); 346199747Smav if (path->device->transport == XPORT_ATA) { 347199747Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_MODE) 348199747Smav mode = cts.xport_specific.ata.mode; 349199747Smav } else { 350199799Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_MODE) 351199747Smav mode = cts.xport_specific.sata.mode; 352199747Smav } 353199747Smavnegotiate: 354199747Smav /* Honor device capabilities. */ 355199747Smav wantmode = mode = ata_max_mode(ident_buf, mode); 356199747Smav /* Report modes to SIM. */ 357199747Smav bzero(&cts, sizeof(cts)); 358199747Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); 359199747Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 360199747Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 361199747Smav if (path->device->transport == XPORT_ATA) { 362199747Smav cts.xport_specific.ata.mode = mode; 363199747Smav cts.xport_specific.ata.valid = CTS_ATA_VALID_MODE; 364199747Smav } else { 365199747Smav cts.xport_specific.sata.mode = mode; 366199747Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_MODE; 367199747Smav } 368199747Smav xpt_action((union ccb *)&cts); 369199747Smav /* Fetch user modes from SIM. */ 370199747Smav bzero(&cts, sizeof(cts)); 371199747Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); 372199747Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 373199747Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 374199747Smav xpt_action((union ccb *)&cts); 375199747Smav if (path->device->transport == XPORT_ATA) { 376199747Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_MODE) 377199747Smav mode = cts.xport_specific.ata.mode; 378199747Smav } else { 379199747Smav if (cts.xport_specific.ata.valid & CTS_SATA_VALID_MODE) 380199747Smav mode = cts.xport_specific.sata.mode; 381199747Smav } 382199747Smav /* If SIM disagree - renegotiate. */ 383199747Smav if (mode != wantmode) 384199747Smav goto negotiate; 385195534Sscottl cam_fill_ataio(ataio, 386195534Sscottl 1, 387195534Sscottl probedone, 388196353Smav /*flags*/CAM_DIR_NONE, 389196353Smav 0, 390196353Smav /*data_ptr*/NULL, 391196353Smav /*dxfer_len*/0, 392195534Sscottl 30 * 1000); 393199747Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); 394195534Sscottl break; 395199747Smav } 396198708Smav case PROBE_SET_MULTI: 397198708Smav { 398198708Smav u_int sectors; 399198708Smav 400198708Smav sectors = max(1, min(ident_buf->sectors_intr & 0xff, 16)); 401198708Smav 402198708Smav /* Report bytecount to SIM. */ 403198708Smav bzero(&cts, sizeof(cts)); 404198708Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); 405198708Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 406198708Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 407198708Smav if (path->device->transport == XPORT_ATA) { 408198897Smav cts.xport_specific.ata.bytecount = sectors * 409198897Smav ata_logical_sector_size(ident_buf); 410198708Smav cts.xport_specific.ata.valid = CTS_ATA_VALID_BYTECOUNT; 411198708Smav } else { 412198897Smav cts.xport_specific.sata.bytecount = sectors * 413198897Smav ata_logical_sector_size(ident_buf); 414198708Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_BYTECOUNT; 415198708Smav } 416198708Smav xpt_action((union ccb *)&cts); 417198708Smav 418198708Smav cam_fill_ataio(ataio, 419198708Smav 1, 420198708Smav probedone, 421198708Smav CAM_DIR_NONE, 422198708Smav 0, 423198708Smav NULL, 424198708Smav 0, 425198708Smav 30*1000); 426198708Smav ata_28bit_cmd(ataio, ATA_SET_MULTI, 0, 0, sectors); 427198708Smav break; 428195534Sscottl } 429195534Sscottl case PROBE_INQUIRY: 430195534Sscottl case PROBE_FULL_INQUIRY: 431195534Sscottl { 432195534Sscottl u_int inquiry_len; 433195534Sscottl struct scsi_inquiry_data *inq_buf = 434195534Sscottl &periph->path->device->inq_data; 435195534Sscottl 436195534Sscottl if (softc->action == PROBE_INQUIRY) 437195534Sscottl inquiry_len = SHORT_INQUIRY_LENGTH; 438195534Sscottl else 439195534Sscottl inquiry_len = SID_ADDITIONAL_LENGTH(inq_buf); 440195534Sscottl /* 441195534Sscottl * Some parallel SCSI devices fail to send an 442195534Sscottl * ignore wide residue message when dealing with 443195534Sscottl * odd length inquiry requests. Round up to be 444195534Sscottl * safe. 445195534Sscottl */ 446195534Sscottl inquiry_len = roundup2(inquiry_len, 2); 447195534Sscottl scsi_inquiry(csio, 448195534Sscottl /*retries*/1, 449195534Sscottl probedone, 450195534Sscottl MSG_SIMPLE_Q_TAG, 451195534Sscottl (u_int8_t *)inq_buf, 452195534Sscottl inquiry_len, 453195534Sscottl /*evpd*/FALSE, 454195534Sscottl /*page_code*/0, 455195534Sscottl SSD_MIN_SIZE, 456195534Sscottl /*timeout*/60 * 1000); 457195534Sscottl break; 458195534Sscottl } 459195534Sscottl case PROBE_PM_PID: 460195534Sscottl cam_fill_ataio(ataio, 461195534Sscottl 1, 462195534Sscottl probedone, 463195534Sscottl /*flags*/CAM_DIR_NONE, 464198389Smav 0, 465195534Sscottl /*data_ptr*/NULL, 466195534Sscottl /*dxfer_len*/0, 467195534Sscottl 10 * 1000); 468195534Sscottl ata_pm_read_cmd(ataio, 0, 15); 469195534Sscottl break; 470195534Sscottl case PROBE_PM_PRV: 471195534Sscottl cam_fill_ataio(ataio, 472195534Sscottl 1, 473195534Sscottl probedone, 474195534Sscottl /*flags*/CAM_DIR_NONE, 475198389Smav 0, 476195534Sscottl /*data_ptr*/NULL, 477195534Sscottl /*dxfer_len*/0, 478195534Sscottl 10 * 1000); 479195534Sscottl ata_pm_read_cmd(ataio, 1, 15); 480195534Sscottl break; 481195534Sscottl case PROBE_INVALID: 482198708Smav CAM_DEBUG(path, CAM_DEBUG_INFO, 483195534Sscottl ("probestart: invalid action state\n")); 484195534Sscottl default: 485195534Sscottl break; 486195534Sscottl } 487195534Sscottl xpt_action(start_ccb); 488195534Sscottl} 489195534Sscottl#if 0 490195534Sscottlstatic void 491195534Sscottlproberequestdefaultnegotiation(struct cam_periph *periph) 492195534Sscottl{ 493195534Sscottl struct ccb_trans_settings cts; 494195534Sscottl 495198382Smav xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 496195534Sscottl cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 497195534Sscottl cts.type = CTS_TYPE_USER_SETTINGS; 498195534Sscottl xpt_action((union ccb *)&cts); 499195534Sscottl if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 500195534Sscottl return; 501195534Sscottl } 502195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 503195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 504195534Sscottl xpt_action((union ccb *)&cts); 505195534Sscottl} 506195534Sscottl 507195534Sscottl/* 508195534Sscottl * Backoff Negotiation Code- only pertinent for SPI devices. 509195534Sscottl */ 510195534Sscottlstatic int 511195534Sscottlproberequestbackoff(struct cam_periph *periph, struct cam_ed *device) 512195534Sscottl{ 513195534Sscottl struct ccb_trans_settings cts; 514195534Sscottl struct ccb_trans_settings_spi *spi; 515195534Sscottl 516195534Sscottl memset(&cts, 0, sizeof (cts)); 517198382Smav xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 518195534Sscottl cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 519195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 520195534Sscottl xpt_action((union ccb *)&cts); 521195534Sscottl if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 522195534Sscottl if (bootverbose) { 523195534Sscottl xpt_print(periph->path, 524195534Sscottl "failed to get current device settings\n"); 525195534Sscottl } 526195534Sscottl return (0); 527195534Sscottl } 528195534Sscottl if (cts.transport != XPORT_SPI) { 529195534Sscottl if (bootverbose) { 530195534Sscottl xpt_print(periph->path, "not SPI transport\n"); 531195534Sscottl } 532195534Sscottl return (0); 533195534Sscottl } 534195534Sscottl spi = &cts.xport_specific.spi; 535195534Sscottl 536195534Sscottl /* 537195534Sscottl * We cannot renegotiate sync rate if we don't have one. 538195534Sscottl */ 539195534Sscottl if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) { 540195534Sscottl if (bootverbose) { 541195534Sscottl xpt_print(periph->path, "no sync rate known\n"); 542195534Sscottl } 543195534Sscottl return (0); 544195534Sscottl } 545195534Sscottl 546195534Sscottl /* 547195534Sscottl * We'll assert that we don't have to touch PPR options- the 548195534Sscottl * SIM will see what we do with period and offset and adjust 549195534Sscottl * the PPR options as appropriate. 550195534Sscottl */ 551195534Sscottl 552195534Sscottl /* 553195534Sscottl * A sync rate with unknown or zero offset is nonsensical. 554195534Sscottl * A sync period of zero means Async. 555195534Sscottl */ 556195534Sscottl if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0 557195534Sscottl || spi->sync_offset == 0 || spi->sync_period == 0) { 558195534Sscottl if (bootverbose) { 559195534Sscottl xpt_print(periph->path, "no sync rate available\n"); 560195534Sscottl } 561195534Sscottl return (0); 562195534Sscottl } 563195534Sscottl 564195534Sscottl if (device->flags & CAM_DEV_DV_HIT_BOTTOM) { 565195534Sscottl CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 566195534Sscottl ("hit async: giving up on DV\n")); 567195534Sscottl return (0); 568195534Sscottl } 569195534Sscottl 570195534Sscottl 571195534Sscottl /* 572195534Sscottl * Jump sync_period up by one, but stop at 5MHz and fall back to Async. 573195534Sscottl * We don't try to remember 'last' settings to see if the SIM actually 574195534Sscottl * gets into the speed we want to set. We check on the SIM telling 575195534Sscottl * us that a requested speed is bad, but otherwise don't try and 576195534Sscottl * check the speed due to the asynchronous and handshake nature 577195534Sscottl * of speed setting. 578195534Sscottl */ 579195534Sscottl spi->valid = CTS_SPI_VALID_SYNC_RATE | CTS_SPI_VALID_SYNC_OFFSET; 580195534Sscottl for (;;) { 581195534Sscottl spi->sync_period++; 582195534Sscottl if (spi->sync_period >= 0xf) { 583195534Sscottl spi->sync_period = 0; 584195534Sscottl spi->sync_offset = 0; 585195534Sscottl CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 586195534Sscottl ("setting to async for DV\n")); 587195534Sscottl /* 588195534Sscottl * Once we hit async, we don't want to try 589195534Sscottl * any more settings. 590195534Sscottl */ 591195534Sscottl device->flags |= CAM_DEV_DV_HIT_BOTTOM; 592195534Sscottl } else if (bootverbose) { 593195534Sscottl CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 594195534Sscottl ("DV: period 0x%x\n", spi->sync_period)); 595195534Sscottl printf("setting period to 0x%x\n", spi->sync_period); 596195534Sscottl } 597195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 598195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 599195534Sscottl xpt_action((union ccb *)&cts); 600195534Sscottl if ((cts.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { 601195534Sscottl break; 602195534Sscottl } 603195534Sscottl CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 604195534Sscottl ("DV: failed to set period 0x%x\n", spi->sync_period)); 605195534Sscottl if (spi->sync_period == 0) { 606195534Sscottl return (0); 607195534Sscottl } 608195534Sscottl } 609195534Sscottl return (1); 610195534Sscottl} 611195534Sscottl#endif 612195534Sscottlstatic void 613195534Sscottlprobedone(struct cam_periph *periph, union ccb *done_ccb) 614195534Sscottl{ 615199747Smav struct ccb_trans_settings cts; 616195534Sscottl struct ata_params *ident_buf; 617195534Sscottl probe_softc *softc; 618195534Sscottl struct cam_path *path; 619195534Sscottl u_int32_t priority; 620198389Smav int found = 1; 621195534Sscottl 622195534Sscottl CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probedone\n")); 623195534Sscottl 624195534Sscottl softc = (probe_softc *)periph->softc; 625195534Sscottl path = done_ccb->ccb_h.path; 626195534Sscottl priority = done_ccb->ccb_h.pinfo.priority; 627195534Sscottl ident_buf = &path->device->ident_data; 628195534Sscottl 629198708Smav if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 630198708Smavdevice_fail: if (cam_periph_error(done_ccb, 0, 0, 631198708Smav &softc->saved_ccb) == ERESTART) { 632195534Sscottl return; 633195534Sscottl } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 634195534Sscottl /* Don't wedge the queue */ 635195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 636195534Sscottl /*run_queue*/TRUE); 637195534Sscottl } 638198708Smav /* Old PIO2 devices may not support mode setting. */ 639198708Smav if (softc->action == PROBE_SETMODE && 640198708Smav ata_max_pmode(ident_buf) <= ATA_PIO2 && 641198708Smav (ident_buf->capabilities1 & ATA_SUPPORT_IORDY) == 0) 642198708Smav goto noerror; 643198708Smav /* 644198708Smav * If we get to this point, we got an error status back 645198708Smav * from the inquiry and the error status doesn't require 646198708Smav * automatically retrying the command. Therefore, the 647198708Smav * inquiry failed. If we had inquiry information before 648198708Smav * for this device, but this latest inquiry command failed, 649198708Smav * the device has probably gone away. If this device isn't 650198708Smav * already marked unconfigured, notify the peripheral 651198708Smav * drivers that this device is no more. 652198708Smav */ 653198708Smav if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0) 654198708Smav xpt_async(AC_LOST_DEVICE, path, NULL); 655198708Smav found = 0; 656198708Smav goto done; 657198708Smav } 658198708Smavnoerror: 659198708Smav switch (softc->action) { 660198708Smav case PROBE_RESET: 661195534Sscottl { 662198708Smav int sign = (done_ccb->ataio.res.lba_high << 8) + 663198708Smav done_ccb->ataio.res.lba_mid; 664198708Smav xpt_print(path, "SIGNATURE: %04x\n", sign); 665198708Smav if (sign == 0x0000 && 666198708Smav done_ccb->ccb_h.target_id != 15) { 667198708Smav path->device->protocol = PROTO_ATA; 668198708Smav PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 669198708Smav } else if (sign == 0x9669 && 670198708Smav done_ccb->ccb_h.target_id == 15) { 671199747Smav /* Report SIM that PM is present. */ 672198708Smav bzero(&cts, sizeof(cts)); 673198708Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); 674198708Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 675198708Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 676198708Smav cts.xport_specific.sata.pm_present = 1; 677198708Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; 678198708Smav xpt_action((union ccb *)&cts); 679198708Smav path->device->protocol = PROTO_SATAPM; 680198708Smav PROBE_SET_ACTION(softc, PROBE_PM_PID); 681198708Smav } else if (sign == 0xeb14 && 682198708Smav done_ccb->ccb_h.target_id != 15) { 683198708Smav path->device->protocol = PROTO_SCSI; 684198708Smav PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 685198708Smav } else { 686198708Smav if (done_ccb->ccb_h.target_id != 15) { 687198708Smav xpt_print(path, 688198708Smav "Unexpected signature 0x%04x\n", sign); 689195534Sscottl } 690198708Smav goto device_fail; 691198708Smav } 692198708Smav xpt_release_ccb(done_ccb); 693198708Smav xpt_schedule(periph, priority); 694198708Smav return; 695198708Smav } 696198708Smav case PROBE_IDENTIFY: 697198708Smav { 698198708Smav int16_t *ptr; 699195534Sscottl 700198708Smav for (ptr = (int16_t *)ident_buf; 701198708Smav ptr < (int16_t *)ident_buf + sizeof(struct ata_params)/2; ptr++) { 702198708Smav *ptr = le16toh(*ptr); 703198708Smav } 704198708Smav if (strncmp(ident_buf->model, "FX", 2) && 705198708Smav strncmp(ident_buf->model, "NEC", 3) && 706198708Smav strncmp(ident_buf->model, "Pioneer", 7) && 707198708Smav strncmp(ident_buf->model, "SHARP", 5)) { 708198708Smav ata_bswap(ident_buf->model, sizeof(ident_buf->model)); 709198708Smav ata_bswap(ident_buf->revision, sizeof(ident_buf->revision)); 710198708Smav ata_bswap(ident_buf->serial, sizeof(ident_buf->serial)); 711198708Smav } 712198708Smav ata_btrim(ident_buf->model, sizeof(ident_buf->model)); 713198708Smav ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model)); 714198708Smav ata_btrim(ident_buf->revision, sizeof(ident_buf->revision)); 715198708Smav ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision)); 716198708Smav ata_btrim(ident_buf->serial, sizeof(ident_buf->serial)); 717198708Smav ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial)); 718195534Sscottl 719198708Smav if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) { 720198708Smav /* Check that it is the same device. */ 721198708Smav MD5_CTX context; 722198708Smav u_int8_t digest[16]; 723198708Smav 724198708Smav MD5Init(&context); 725198708Smav MD5Update(&context, 726198708Smav (unsigned char *)ident_buf->model, 727198708Smav sizeof(ident_buf->model)); 728198708Smav MD5Update(&context, 729198708Smav (unsigned char *)ident_buf->revision, 730198708Smav sizeof(ident_buf->revision)); 731198708Smav MD5Update(&context, 732198708Smav (unsigned char *)ident_buf->serial, 733198708Smav sizeof(ident_buf->serial)); 734198708Smav MD5Final(digest, &context); 735198708Smav if (bcmp(digest, softc->digest, sizeof(digest))) { 736198708Smav /* Device changed. */ 737198708Smav xpt_async(AC_LOST_DEVICE, path, NULL); 738195534Sscottl } 739198708Smav } else { 740195534Sscottl /* Clean up from previous instance of this device */ 741195534Sscottl if (path->device->serial_num != NULL) { 742195534Sscottl free(path->device->serial_num, M_CAMXPT); 743195534Sscottl path->device->serial_num = NULL; 744195534Sscottl path->device->serial_num_len = 0; 745195534Sscottl } 746195534Sscottl path->device->serial_num = 747195534Sscottl (u_int8_t *)malloc((sizeof(ident_buf->serial) + 1), 748198708Smav M_CAMXPT, M_NOWAIT); 749195534Sscottl if (path->device->serial_num != NULL) { 750195534Sscottl bcopy(ident_buf->serial, 751195534Sscottl path->device->serial_num, 752195534Sscottl sizeof(ident_buf->serial)); 753195534Sscottl path->device->serial_num[sizeof(ident_buf->serial)] 754195534Sscottl = '\0'; 755195534Sscottl path->device->serial_num_len = 756195534Sscottl strlen(path->device->serial_num); 757195534Sscottl } 758195534Sscottl 759198331Smav path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 760195534Sscottl } 761199178Smav if (ident_buf->satacapabilities & ATA_SUPPORT_NCQ) { 762199178Smav path->device->mintags = path->device->maxtags = 763199178Smav ATA_QUEUE_LEN(ident_buf->queue) + 1; 764199178Smav } 765199178Smav ata_find_quirk(path->device); 766199263Smav if (path->device->mintags != 0 && 767199263Smav path->bus->sim->max_tagged_dev_openings != 0) { 768199747Smav /* Report SIM which tags are allowed. */ 769199747Smav bzero(&cts, sizeof(cts)); 770199747Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); 771199747Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 772199747Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 773199747Smav cts.xport_specific.sata.tags = path->device->maxtags; 774199747Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_TAGS; 775199747Smav xpt_action((union ccb *)&cts); 776199747Smav /* Reconfigure queues for tagged queueing. */ 777199178Smav xpt_start_tags(path); 778199178Smav } 779198708Smav ata_device_transport(path); 780198708Smav PROBE_SET_ACTION(softc, PROBE_SETMODE); 781195534Sscottl xpt_release_ccb(done_ccb); 782198708Smav xpt_schedule(periph, priority); 783198708Smav return; 784195534Sscottl } 785195534Sscottl case PROBE_SETMODE: 786198708Smav if (path->device->protocol == PROTO_ATA) { 787198708Smav PROBE_SET_ACTION(softc, PROBE_SET_MULTI); 788198708Smav } else { 789198708Smav PROBE_SET_ACTION(softc, PROBE_INQUIRY); 790195534Sscottl } 791198708Smav xpt_release_ccb(done_ccb); 792198708Smav xpt_schedule(periph, priority); 793198708Smav return; 794198708Smav case PROBE_SET_MULTI: 795198708Smav if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 796198708Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 797198748Smav xpt_acquire_device(path->device); 798198708Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 799198708Smav xpt_action(done_ccb); 800198708Smav xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, 801198708Smav done_ccb); 802198708Smav } 803198708Smav break; 804195534Sscottl case PROBE_INQUIRY: 805195534Sscottl case PROBE_FULL_INQUIRY: 806195534Sscottl { 807198708Smav struct scsi_inquiry_data *inq_buf; 808198708Smav u_int8_t periph_qual, len; 809195534Sscottl 810198708Smav path->device->flags |= CAM_DEV_INQUIRY_DATA_VALID; 811198708Smav inq_buf = &path->device->inq_data; 812195534Sscottl 813198708Smav periph_qual = SID_QUAL(inq_buf); 814195534Sscottl 815198708Smav if (periph_qual != SID_QUAL_LU_CONNECTED) 816198708Smav break; 817195534Sscottl 818198708Smav /* 819198708Smav * We conservatively request only 820198708Smav * SHORT_INQUIRY_LEN bytes of inquiry 821198708Smav * information during our first try 822198708Smav * at sending an INQUIRY. If the device 823198708Smav * has more information to give, 824198708Smav * perform a second request specifying 825198708Smav * the amount of information the device 826198708Smav * is willing to give. 827198708Smav */ 828198708Smav len = inq_buf->additional_length 829198708Smav + offsetof(struct scsi_inquiry_data, additional_length) + 1; 830198708Smav if (softc->action == PROBE_INQUIRY 831198708Smav && len > SHORT_INQUIRY_LENGTH) { 832198708Smav PROBE_SET_ACTION(softc, PROBE_FULL_INQUIRY); 833198708Smav xpt_release_ccb(done_ccb); 834198708Smav xpt_schedule(periph, priority); 835195534Sscottl return; 836195534Sscottl } 837198708Smav 838198708Smav ata_device_transport(path); 839198708Smav if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 840198708Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 841198748Smav xpt_acquire_device(path->device); 842198708Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 843198708Smav xpt_action(done_ccb); 844198708Smav xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, done_ccb); 845198708Smav } 846198708Smav break; 847195534Sscottl } 848195534Sscottl case PROBE_PM_PID: 849198708Smav if ((path->device->flags & CAM_DEV_IDENTIFY_DATA_VALID) == 0) 850198708Smav bzero(ident_buf, sizeof(*ident_buf)); 851198708Smav softc->pm_pid = (done_ccb->ataio.res.lba_high << 24) + 852198708Smav (done_ccb->ataio.res.lba_mid << 16) + 853198708Smav (done_ccb->ataio.res.lba_low << 8) + 854198708Smav done_ccb->ataio.res.sector_count; 855198708Smav ((uint32_t *)ident_buf)[0] = softc->pm_pid; 856198708Smav printf("PM Product ID: %08x\n", softc->pm_pid); 857198708Smav snprintf(ident_buf->model, sizeof(ident_buf->model), 858198708Smav "Port Multiplier %08x", softc->pm_pid); 859198708Smav PROBE_SET_ACTION(softc, PROBE_PM_PRV); 860198708Smav xpt_release_ccb(done_ccb); 861198708Smav xpt_schedule(periph, priority); 862198708Smav return; 863195534Sscottl case PROBE_PM_PRV: 864198708Smav softc->pm_prv = (done_ccb->ataio.res.lba_high << 24) + 865198708Smav (done_ccb->ataio.res.lba_mid << 16) + 866198708Smav (done_ccb->ataio.res.lba_low << 8) + 867198708Smav done_ccb->ataio.res.sector_count; 868198708Smav ((uint32_t *)ident_buf)[1] = softc->pm_prv; 869198708Smav printf("PM Revision: %08x\n", softc->pm_prv); 870198708Smav snprintf(ident_buf->revision, sizeof(ident_buf->revision), 871198708Smav "%04x", softc->pm_prv); 872198708Smav path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 873198708Smav if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 874198708Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 875198748Smav xpt_acquire_device(path->device); 876198708Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 877198708Smav xpt_action(done_ccb); 878198708Smav xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, 879198708Smav done_ccb); 880198708Smav } else { 881198708Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 882198708Smav xpt_action(done_ccb); 883198708Smav xpt_async(AC_SCSI_AEN, done_ccb->ccb_h.path, done_ccb); 884195534Sscottl } 885198708Smav break; 886195534Sscottl case PROBE_INVALID: 887195534Sscottl CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_INFO, 888195534Sscottl ("probedone: invalid action state\n")); 889195534Sscottl default: 890195534Sscottl break; 891195534Sscottl } 892198708Smavdone: 893198708Smav xpt_release_ccb(done_ccb); 894195534Sscottl done_ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs); 895195534Sscottl TAILQ_REMOVE(&softc->request_ccbs, &done_ccb->ccb_h, periph_links.tqe); 896195534Sscottl done_ccb->ccb_h.status = CAM_REQ_CMP; 897195534Sscottl done_ccb->ccb_h.ppriv_field1 = found; 898195534Sscottl xpt_done(done_ccb); 899195534Sscottl if (TAILQ_FIRST(&softc->request_ccbs) == NULL) { 900195534Sscottl cam_periph_invalidate(periph); 901195534Sscottl cam_periph_release_locked(periph); 902195534Sscottl } else { 903195534Sscottl probeschedule(periph); 904195534Sscottl } 905195534Sscottl} 906195534Sscottl 907195534Sscottlstatic void 908195534Sscottlprobecleanup(struct cam_periph *periph) 909195534Sscottl{ 910195534Sscottl free(periph->softc, M_CAMXPT); 911195534Sscottl} 912195534Sscottl 913195534Sscottlstatic void 914199178Smavata_find_quirk(struct cam_ed *device) 915195534Sscottl{ 916199178Smav struct ata_quirk_entry *quirk; 917195534Sscottl caddr_t match; 918195534Sscottl 919199178Smav match = cam_quirkmatch((caddr_t)&device->ident_data, 920199178Smav (caddr_t)ata_quirk_table, 921199178Smav ata_quirk_table_size, 922199178Smav sizeof(*ata_quirk_table), ata_identify_match); 923195534Sscottl 924195534Sscottl if (match == NULL) 925195534Sscottl panic("xpt_find_quirk: device didn't match wildcard entry!!"); 926195534Sscottl 927199178Smav quirk = (struct ata_quirk_entry *)match; 928195534Sscottl device->quirk = quirk; 929199178Smav if (quirk->quirks & CAM_QUIRK_MAXTAGS) 930199178Smav device->mintags = device->maxtags = quirk->maxtags; 931195534Sscottl} 932195534Sscottl 933195534Sscottltypedef struct { 934195534Sscottl union ccb *request_ccb; 935195534Sscottl struct ccb_pathinq *cpi; 936195534Sscottl int counter; 937195534Sscottl int found; 938195534Sscottl} ata_scan_bus_info; 939195534Sscottl 940195534Sscottl/* 941195534Sscottl * To start a scan, request_ccb is an XPT_SCAN_BUS ccb. 942195534Sscottl * As the scan progresses, xpt_scan_bus is used as the 943195534Sscottl * callback on completion function. 944195534Sscottl */ 945195534Sscottlstatic void 946195534Sscottlata_scan_bus(struct cam_periph *periph, union ccb *request_ccb) 947195534Sscottl{ 948195534Sscottl struct cam_path *path; 949195534Sscottl ata_scan_bus_info *scan_info; 950195534Sscottl union ccb *work_ccb; 951195534Sscottl cam_status status; 952195534Sscottl 953195534Sscottl CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE, 954195534Sscottl ("xpt_scan_bus\n")); 955195534Sscottl switch (request_ccb->ccb_h.func_code) { 956195534Sscottl case XPT_SCAN_BUS: 957195534Sscottl /* Find out the characteristics of the bus */ 958195534Sscottl work_ccb = xpt_alloc_ccb_nowait(); 959195534Sscottl if (work_ccb == NULL) { 960195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 961195534Sscottl xpt_done(request_ccb); 962195534Sscottl return; 963195534Sscottl } 964195534Sscottl xpt_setup_ccb(&work_ccb->ccb_h, request_ccb->ccb_h.path, 965195534Sscottl request_ccb->ccb_h.pinfo.priority); 966195534Sscottl work_ccb->ccb_h.func_code = XPT_PATH_INQ; 967195534Sscottl xpt_action(work_ccb); 968195534Sscottl if (work_ccb->ccb_h.status != CAM_REQ_CMP) { 969195534Sscottl request_ccb->ccb_h.status = work_ccb->ccb_h.status; 970195534Sscottl xpt_free_ccb(work_ccb); 971195534Sscottl xpt_done(request_ccb); 972195534Sscottl return; 973195534Sscottl } 974195534Sscottl 975195534Sscottl /* Save some state for use while we probe for devices */ 976195534Sscottl scan_info = (ata_scan_bus_info *) 977195534Sscottl malloc(sizeof(ata_scan_bus_info), M_CAMXPT, M_NOWAIT); 978195534Sscottl if (scan_info == NULL) { 979195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 980195534Sscottl xpt_done(request_ccb); 981195534Sscottl return; 982195534Sscottl } 983195534Sscottl scan_info->request_ccb = request_ccb; 984195534Sscottl scan_info->cpi = &work_ccb->cpi; 985198331Smav if (scan_info->cpi->transport == XPORT_ATA) 986198331Smav scan_info->found = 0x0003; 987198331Smav else 988198331Smav scan_info->found = 0x8001; 989195534Sscottl scan_info->counter = 0; 990195534Sscottl /* If PM supported, probe it first. */ 991195534Sscottl if (scan_info->cpi->hba_inquiry & PI_SATAPM) 992195534Sscottl scan_info->counter = 15; 993195534Sscottl 994195534Sscottl work_ccb = xpt_alloc_ccb_nowait(); 995195534Sscottl if (work_ccb == NULL) { 996195534Sscottl free(scan_info, M_CAMXPT); 997195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 998195534Sscottl xpt_done(request_ccb); 999195534Sscottl break; 1000195534Sscottl } 1001195534Sscottl goto scan_next; 1002195534Sscottl case XPT_SCAN_LUN: 1003195534Sscottl work_ccb = request_ccb; 1004195534Sscottl /* Reuse the same CCB to query if a device was really found */ 1005195534Sscottl scan_info = (ata_scan_bus_info *)work_ccb->ccb_h.ppriv_ptr0; 1006195534Sscottl /* Free the current request path- we're done with it. */ 1007195534Sscottl xpt_free_path(work_ccb->ccb_h.path); 1008198389Smav /* If there is PMP... */ 1009195534Sscottl if (scan_info->counter == 15) { 1010195534Sscottl if (work_ccb->ccb_h.ppriv_field1 != 0) { 1011198389Smav /* everything else willbe probed by it */ 1012198389Smav scan_info->found = 0x8000; 1013195534Sscottl } else { 1014195534Sscottl struct ccb_trans_settings cts; 1015195534Sscottl 1016195534Sscottl /* Report SIM that PM is absent. */ 1017195534Sscottl bzero(&cts, sizeof(cts)); 1018195534Sscottl xpt_setup_ccb(&cts.ccb_h, 1019195534Sscottl scan_info->request_ccb->ccb_h.path, 1); 1020195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1021195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 1022195665Smav cts.xport_specific.sata.pm_present = 0; 1023195534Sscottl cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; 1024195534Sscottl xpt_action((union ccb *)&cts); 1025195534Sscottl } 1026195534Sscottl } 1027195534Sscottltake_next: 1028195534Sscottl /* Take next device. Wrap from 15 (PM) to 0. */ 1029195534Sscottl scan_info->counter = (scan_info->counter + 1 ) & 0x0f; 1030198322Smav if (scan_info->counter > scan_info->cpi->max_target - 1031198322Smav ((scan_info->cpi->hba_inquiry & PI_SATAPM) ? 1 : 0)) { 1032195534Sscottl xpt_free_ccb(work_ccb); 1033195534Sscottl xpt_free_ccb((union ccb *)scan_info->cpi); 1034195534Sscottl request_ccb = scan_info->request_ccb; 1035195534Sscottl free(scan_info, M_CAMXPT); 1036195534Sscottl request_ccb->ccb_h.status = CAM_REQ_CMP; 1037195534Sscottl xpt_done(request_ccb); 1038195534Sscottl break; 1039195534Sscottl } 1040195534Sscottlscan_next: 1041198389Smav if ((scan_info->found & (1 << scan_info->counter)) == 0) 1042198389Smav goto take_next; 1043195534Sscottl status = xpt_create_path(&path, xpt_periph, 1044195534Sscottl scan_info->request_ccb->ccb_h.path_id, 1045195534Sscottl scan_info->counter, 0); 1046195534Sscottl if (status != CAM_REQ_CMP) { 1047195534Sscottl printf("xpt_scan_bus: xpt_create_path failed" 1048195534Sscottl " with status %#x, bus scan halted\n", 1049195534Sscottl status); 1050195534Sscottl xpt_free_ccb(work_ccb); 1051195534Sscottl xpt_free_ccb((union ccb *)scan_info->cpi); 1052195534Sscottl request_ccb = scan_info->request_ccb; 1053195534Sscottl free(scan_info, M_CAMXPT); 1054195534Sscottl request_ccb->ccb_h.status = status; 1055195534Sscottl xpt_done(request_ccb); 1056195534Sscottl break; 1057195534Sscottl } 1058195534Sscottl xpt_setup_ccb(&work_ccb->ccb_h, path, 1059195534Sscottl scan_info->request_ccb->ccb_h.pinfo.priority); 1060195534Sscottl work_ccb->ccb_h.func_code = XPT_SCAN_LUN; 1061195534Sscottl work_ccb->ccb_h.cbfcnp = ata_scan_bus; 1062195534Sscottl work_ccb->ccb_h.ppriv_ptr0 = scan_info; 1063195534Sscottl work_ccb->crcn.flags = scan_info->request_ccb->crcn.flags; 1064195534Sscottl xpt_action(work_ccb); 1065195534Sscottl break; 1066195534Sscottl default: 1067195534Sscottl break; 1068195534Sscottl } 1069195534Sscottl} 1070195534Sscottl 1071195534Sscottlstatic void 1072195534Sscottlata_scan_lun(struct cam_periph *periph, struct cam_path *path, 1073195534Sscottl cam_flags flags, union ccb *request_ccb) 1074195534Sscottl{ 1075195534Sscottl struct ccb_pathinq cpi; 1076195534Sscottl cam_status status; 1077195534Sscottl struct cam_path *new_path; 1078195534Sscottl struct cam_periph *old_periph; 1079195534Sscottl 1080195534Sscottl CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE, 1081195534Sscottl ("xpt_scan_lun\n")); 1082195534Sscottl 1083198382Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL); 1084195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 1085195534Sscottl xpt_action((union ccb *)&cpi); 1086195534Sscottl 1087195534Sscottl if (cpi.ccb_h.status != CAM_REQ_CMP) { 1088195534Sscottl if (request_ccb != NULL) { 1089195534Sscottl request_ccb->ccb_h.status = cpi.ccb_h.status; 1090195534Sscottl xpt_done(request_ccb); 1091195534Sscottl } 1092195534Sscottl return; 1093195534Sscottl } 1094195534Sscottl 1095195534Sscottl if (request_ccb == NULL) { 1096195534Sscottl request_ccb = malloc(sizeof(union ccb), M_CAMXPT, M_NOWAIT); 1097195534Sscottl if (request_ccb == NULL) { 1098195534Sscottl xpt_print(path, "xpt_scan_lun: can't allocate CCB, " 1099195534Sscottl "can't continue\n"); 1100195534Sscottl return; 1101195534Sscottl } 1102195534Sscottl new_path = malloc(sizeof(*new_path), M_CAMXPT, M_NOWAIT); 1103195534Sscottl if (new_path == NULL) { 1104195534Sscottl xpt_print(path, "xpt_scan_lun: can't allocate path, " 1105195534Sscottl "can't continue\n"); 1106195534Sscottl free(request_ccb, M_CAMXPT); 1107195534Sscottl return; 1108195534Sscottl } 1109195534Sscottl status = xpt_compile_path(new_path, xpt_periph, 1110195534Sscottl path->bus->path_id, 1111195534Sscottl path->target->target_id, 1112195534Sscottl path->device->lun_id); 1113195534Sscottl 1114195534Sscottl if (status != CAM_REQ_CMP) { 1115195534Sscottl xpt_print(path, "xpt_scan_lun: can't compile path, " 1116195534Sscottl "can't continue\n"); 1117195534Sscottl free(request_ccb, M_CAMXPT); 1118195534Sscottl free(new_path, M_CAMXPT); 1119195534Sscottl return; 1120195534Sscottl } 1121198382Smav xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_NORMAL); 1122195534Sscottl request_ccb->ccb_h.cbfcnp = xptscandone; 1123195534Sscottl request_ccb->ccb_h.func_code = XPT_SCAN_LUN; 1124195534Sscottl request_ccb->crcn.flags = flags; 1125195534Sscottl } 1126195534Sscottl 1127195653Smav if ((old_periph = cam_periph_find(path, "aprobe")) != NULL) { 1128195534Sscottl probe_softc *softc; 1129195534Sscottl 1130195534Sscottl softc = (probe_softc *)old_periph->softc; 1131195534Sscottl TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h, 1132195534Sscottl periph_links.tqe); 1133195534Sscottl } else { 1134195534Sscottl status = cam_periph_alloc(proberegister, NULL, probecleanup, 1135195653Smav probestart, "aprobe", 1136195534Sscottl CAM_PERIPH_BIO, 1137195534Sscottl request_ccb->ccb_h.path, NULL, 0, 1138195534Sscottl request_ccb); 1139195534Sscottl 1140195534Sscottl if (status != CAM_REQ_CMP) { 1141195534Sscottl xpt_print(path, "xpt_scan_lun: cam_alloc_periph " 1142195534Sscottl "returned an error, can't continue probe\n"); 1143195534Sscottl request_ccb->ccb_h.status = status; 1144195534Sscottl xpt_done(request_ccb); 1145195534Sscottl } 1146195534Sscottl } 1147195534Sscottl} 1148195534Sscottl 1149195534Sscottlstatic void 1150195534Sscottlxptscandone(struct cam_periph *periph, union ccb *done_ccb) 1151195534Sscottl{ 1152195534Sscottl xpt_release_path(done_ccb->ccb_h.path); 1153195534Sscottl free(done_ccb->ccb_h.path, M_CAMXPT); 1154195534Sscottl free(done_ccb, M_CAMXPT); 1155195534Sscottl} 1156195534Sscottl 1157195534Sscottlstatic struct cam_ed * 1158195534Sscottlata_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id) 1159195534Sscottl{ 1160195534Sscottl struct cam_path path; 1161199178Smav struct ata_quirk_entry *quirk; 1162195534Sscottl struct cam_ed *device; 1163195534Sscottl struct cam_ed *cur_device; 1164195534Sscottl 1165195534Sscottl device = xpt_alloc_device(bus, target, lun_id); 1166195534Sscottl if (device == NULL) 1167195534Sscottl return (NULL); 1168195534Sscottl 1169195534Sscottl /* 1170195534Sscottl * Take the default quirk entry until we have inquiry 1171195534Sscottl * data and can determine a better quirk to use. 1172195534Sscottl */ 1173199178Smav quirk = &ata_quirk_table[ata_quirk_table_size - 1]; 1174195534Sscottl device->quirk = (void *)quirk; 1175199178Smav device->mintags = 0; 1176199178Smav device->maxtags = 0; 1177195534Sscottl bzero(&device->inq_data, sizeof(device->inq_data)); 1178195534Sscottl device->inq_flags = 0; 1179195534Sscottl device->queue_flags = 0; 1180195534Sscottl device->serial_num = NULL; 1181195534Sscottl device->serial_num_len = 0; 1182195534Sscottl 1183195534Sscottl /* 1184195534Sscottl * XXX should be limited by number of CCBs this bus can 1185195534Sscottl * do. 1186195534Sscottl */ 1187195534Sscottl bus->sim->max_ccbs += device->ccbq.devq_openings; 1188195534Sscottl /* Insertion sort into our target's device list */ 1189195534Sscottl cur_device = TAILQ_FIRST(&target->ed_entries); 1190195534Sscottl while (cur_device != NULL && cur_device->lun_id < lun_id) 1191195534Sscottl cur_device = TAILQ_NEXT(cur_device, links); 1192195534Sscottl if (cur_device != NULL) { 1193195534Sscottl TAILQ_INSERT_BEFORE(cur_device, device, links); 1194195534Sscottl } else { 1195195534Sscottl TAILQ_INSERT_TAIL(&target->ed_entries, device, links); 1196195534Sscottl } 1197195534Sscottl target->generation++; 1198195534Sscottl if (lun_id != CAM_LUN_WILDCARD) { 1199195534Sscottl xpt_compile_path(&path, 1200195534Sscottl NULL, 1201195534Sscottl bus->path_id, 1202195534Sscottl target->target_id, 1203195534Sscottl lun_id); 1204195534Sscottl ata_device_transport(&path); 1205195534Sscottl xpt_release_path(&path); 1206195534Sscottl } 1207195534Sscottl 1208195534Sscottl return (device); 1209195534Sscottl} 1210195534Sscottl 1211195534Sscottlstatic void 1212195534Sscottlata_device_transport(struct cam_path *path) 1213195534Sscottl{ 1214195534Sscottl struct ccb_pathinq cpi; 1215198331Smav struct ccb_trans_settings cts; 1216198331Smav struct scsi_inquiry_data *inq_buf = NULL; 1217198331Smav struct ata_params *ident_buf = NULL; 1218195534Sscottl 1219195534Sscottl /* Get transport information from the SIM */ 1220198382Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL); 1221195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 1222195534Sscottl xpt_action((union ccb *)&cpi); 1223195534Sscottl 1224195534Sscottl path->device->transport = cpi.transport; 1225198331Smav if ((path->device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0) 1226198331Smav inq_buf = &path->device->inq_data; 1227198331Smav if ((path->device->flags & CAM_DEV_IDENTIFY_DATA_VALID) != 0) 1228198331Smav ident_buf = &path->device->ident_data; 1229198331Smav if (path->device->protocol == PROTO_ATA) { 1230198331Smav path->device->protocol_version = ident_buf ? 1231198331Smav ata_version(ident_buf->version_major) : cpi.protocol_version; 1232198331Smav } else if (path->device->protocol == PROTO_SCSI) { 1233198331Smav path->device->protocol_version = inq_buf ? 1234198331Smav SID_ANSI_REV(inq_buf) : cpi.protocol_version; 1235195534Sscottl } 1236198331Smav path->device->transport_version = ident_buf ? 1237198331Smav ata_version(ident_buf->version_major) : cpi.transport_version; 1238195534Sscottl 1239195534Sscottl /* Tell the controller what we think */ 1240198382Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); 1241195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1242195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 1243195534Sscottl cts.transport = path->device->transport; 1244195534Sscottl cts.transport_version = path->device->transport_version; 1245195534Sscottl cts.protocol = path->device->protocol; 1246195534Sscottl cts.protocol_version = path->device->protocol_version; 1247195534Sscottl cts.proto_specific.valid = 0; 1248195534Sscottl cts.xport_specific.valid = 0; 1249195534Sscottl xpt_action((union ccb *)&cts); 1250195534Sscottl} 1251195534Sscottl 1252195534Sscottlstatic void 1253195534Sscottlata_action(union ccb *start_ccb) 1254195534Sscottl{ 1255195534Sscottl 1256195534Sscottl switch (start_ccb->ccb_h.func_code) { 1257195534Sscottl case XPT_SET_TRAN_SETTINGS: 1258195534Sscottl { 1259199178Smav ata_set_transfer_settings(&start_ccb->cts, 1260195534Sscottl start_ccb->ccb_h.path->device, 1261195534Sscottl /*async_update*/FALSE); 1262195534Sscottl break; 1263195534Sscottl } 1264195534Sscottl case XPT_SCAN_BUS: 1265195534Sscottl ata_scan_bus(start_ccb->ccb_h.path->periph, start_ccb); 1266195534Sscottl break; 1267195534Sscottl case XPT_SCAN_LUN: 1268195534Sscottl ata_scan_lun(start_ccb->ccb_h.path->periph, 1269195534Sscottl start_ccb->ccb_h.path, start_ccb->crcn.flags, 1270195534Sscottl start_ccb); 1271195534Sscottl break; 1272195534Sscottl case XPT_GET_TRAN_SETTINGS: 1273195534Sscottl { 1274195534Sscottl struct cam_sim *sim; 1275195534Sscottl 1276195534Sscottl sim = start_ccb->ccb_h.path->bus->sim; 1277195534Sscottl (*(sim->sim_action))(sim, start_ccb); 1278195534Sscottl break; 1279195534Sscottl } 1280195534Sscottl default: 1281195534Sscottl xpt_action_default(start_ccb); 1282195534Sscottl break; 1283195534Sscottl } 1284195534Sscottl} 1285195534Sscottl 1286195534Sscottlstatic void 1287199178Smavata_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device, 1288195534Sscottl int async_update) 1289195534Sscottl{ 1290195534Sscottl struct ccb_pathinq cpi; 1291195534Sscottl struct ccb_trans_settings cur_cts; 1292195534Sscottl struct ccb_trans_settings_scsi *scsi; 1293195534Sscottl struct ccb_trans_settings_scsi *cur_scsi; 1294195534Sscottl struct cam_sim *sim; 1295195534Sscottl struct scsi_inquiry_data *inq_data; 1296195534Sscottl 1297195534Sscottl if (device == NULL) { 1298195534Sscottl cts->ccb_h.status = CAM_PATH_INVALID; 1299195534Sscottl xpt_done((union ccb *)cts); 1300195534Sscottl return; 1301195534Sscottl } 1302195534Sscottl 1303195534Sscottl if (cts->protocol == PROTO_UNKNOWN 1304195534Sscottl || cts->protocol == PROTO_UNSPECIFIED) { 1305195534Sscottl cts->protocol = device->protocol; 1306195534Sscottl cts->protocol_version = device->protocol_version; 1307195534Sscottl } 1308195534Sscottl 1309195534Sscottl if (cts->protocol_version == PROTO_VERSION_UNKNOWN 1310195534Sscottl || cts->protocol_version == PROTO_VERSION_UNSPECIFIED) 1311195534Sscottl cts->protocol_version = device->protocol_version; 1312195534Sscottl 1313195534Sscottl if (cts->protocol != device->protocol) { 1314195534Sscottl xpt_print(cts->ccb_h.path, "Uninitialized Protocol %x:%x?\n", 1315195534Sscottl cts->protocol, device->protocol); 1316195534Sscottl cts->protocol = device->protocol; 1317195534Sscottl } 1318195534Sscottl 1319195534Sscottl if (cts->protocol_version > device->protocol_version) { 1320195534Sscottl if (bootverbose) { 1321195534Sscottl xpt_print(cts->ccb_h.path, "Down reving Protocol " 1322195534Sscottl "Version from %d to %d?\n", cts->protocol_version, 1323195534Sscottl device->protocol_version); 1324195534Sscottl } 1325195534Sscottl cts->protocol_version = device->protocol_version; 1326195534Sscottl } 1327195534Sscottl 1328195534Sscottl if (cts->transport == XPORT_UNKNOWN 1329195534Sscottl || cts->transport == XPORT_UNSPECIFIED) { 1330195534Sscottl cts->transport = device->transport; 1331195534Sscottl cts->transport_version = device->transport_version; 1332195534Sscottl } 1333195534Sscottl 1334195534Sscottl if (cts->transport_version == XPORT_VERSION_UNKNOWN 1335195534Sscottl || cts->transport_version == XPORT_VERSION_UNSPECIFIED) 1336195534Sscottl cts->transport_version = device->transport_version; 1337195534Sscottl 1338195534Sscottl if (cts->transport != device->transport) { 1339195534Sscottl xpt_print(cts->ccb_h.path, "Uninitialized Transport %x:%x?\n", 1340195534Sscottl cts->transport, device->transport); 1341195534Sscottl cts->transport = device->transport; 1342195534Sscottl } 1343195534Sscottl 1344195534Sscottl if (cts->transport_version > device->transport_version) { 1345195534Sscottl if (bootverbose) { 1346195534Sscottl xpt_print(cts->ccb_h.path, "Down reving Transport " 1347195534Sscottl "Version from %d to %d?\n", cts->transport_version, 1348195534Sscottl device->transport_version); 1349195534Sscottl } 1350195534Sscottl cts->transport_version = device->transport_version; 1351195534Sscottl } 1352195534Sscottl 1353195534Sscottl sim = cts->ccb_h.path->bus->sim; 1354195534Sscottl 1355195534Sscottl /* 1356195534Sscottl * Nothing more of interest to do unless 1357195534Sscottl * this is a device connected via the 1358195534Sscottl * SCSI protocol. 1359195534Sscottl */ 1360195534Sscottl if (cts->protocol != PROTO_SCSI) { 1361195534Sscottl if (async_update == FALSE) 1362195534Sscottl (*(sim->sim_action))(sim, (union ccb *)cts); 1363195534Sscottl return; 1364195534Sscottl } 1365195534Sscottl 1366195534Sscottl inq_data = &device->inq_data; 1367195534Sscottl scsi = &cts->proto_specific.scsi; 1368198382Smav xpt_setup_ccb(&cpi.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NORMAL); 1369195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 1370195534Sscottl xpt_action((union ccb *)&cpi); 1371195534Sscottl 1372195534Sscottl /* SCSI specific sanity checking */ 1373195534Sscottl if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0 1374195534Sscottl || (INQ_DATA_TQ_ENABLED(inq_data)) == 0 1375195534Sscottl || (device->queue_flags & SCP_QUEUE_DQUE) != 0 1376195534Sscottl || (device->mintags == 0)) { 1377195534Sscottl /* 1378195534Sscottl * Can't tag on hardware that doesn't support tags, 1379195534Sscottl * doesn't have it enabled, or has broken tag support. 1380195534Sscottl */ 1381195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 1382195534Sscottl } 1383195534Sscottl 1384195534Sscottl if (async_update == FALSE) { 1385195534Sscottl /* 1386195534Sscottl * Perform sanity checking against what the 1387195534Sscottl * controller and device can do. 1388195534Sscottl */ 1389198382Smav xpt_setup_ccb(&cur_cts.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NORMAL); 1390195534Sscottl cur_cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1391195534Sscottl cur_cts.type = cts->type; 1392195534Sscottl xpt_action((union ccb *)&cur_cts); 1393195534Sscottl if ((cur_cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1394195534Sscottl return; 1395195534Sscottl } 1396195534Sscottl cur_scsi = &cur_cts.proto_specific.scsi; 1397195534Sscottl if ((scsi->valid & CTS_SCSI_VALID_TQ) == 0) { 1398195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 1399195534Sscottl scsi->flags |= cur_scsi->flags & CTS_SCSI_FLAGS_TAG_ENB; 1400195534Sscottl } 1401195534Sscottl if ((cur_scsi->valid & CTS_SCSI_VALID_TQ) == 0) 1402195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 1403195534Sscottl } 1404195534Sscottl 1405195534Sscottl if (cts->type == CTS_TYPE_CURRENT_SETTINGS 1406195534Sscottl && (scsi->valid & CTS_SCSI_VALID_TQ) != 0) { 1407195534Sscottl int device_tagenb; 1408195534Sscottl 1409195534Sscottl /* 1410195534Sscottl * If we are transitioning from tags to no-tags or 1411195534Sscottl * vice-versa, we need to carefully freeze and restart 1412195534Sscottl * the queue so that we don't overlap tagged and non-tagged 1413195534Sscottl * commands. We also temporarily stop tags if there is 1414195534Sscottl * a change in transfer negotiation settings to allow 1415195534Sscottl * "tag-less" negotiation. 1416195534Sscottl */ 1417195534Sscottl if ((device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 1418195534Sscottl || (device->inq_flags & SID_CmdQue) != 0) 1419195534Sscottl device_tagenb = TRUE; 1420195534Sscottl else 1421195534Sscottl device_tagenb = FALSE; 1422195534Sscottl 1423195534Sscottl if (((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0 1424195534Sscottl && device_tagenb == FALSE) 1425195534Sscottl || ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) == 0 1426195534Sscottl && device_tagenb == TRUE)) { 1427195534Sscottl 1428195534Sscottl if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) { 1429195534Sscottl /* 1430195534Sscottl * Delay change to use tags until after a 1431195534Sscottl * few commands have gone to this device so 1432195534Sscottl * the controller has time to perform transfer 1433195534Sscottl * negotiations without tagged messages getting 1434195534Sscottl * in the way. 1435195534Sscottl */ 1436195534Sscottl device->tag_delay_count = CAM_TAG_DELAY_COUNT; 1437195534Sscottl device->flags |= CAM_DEV_TAG_AFTER_COUNT; 1438195534Sscottl } else { 1439199178Smav xpt_stop_tags(cts->ccb_h.path); 1440195534Sscottl } 1441195534Sscottl } 1442195534Sscottl } 1443195534Sscottl if (async_update == FALSE) 1444195534Sscottl (*(sim->sim_action))(sim, (union ccb *)cts); 1445195534Sscottl} 1446195534Sscottl 1447195534Sscottl/* 1448195534Sscottl * Handle any per-device event notifications that require action by the XPT. 1449195534Sscottl */ 1450195534Sscottlstatic void 1451195534Sscottlata_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target, 1452195534Sscottl struct cam_ed *device, void *async_arg) 1453195534Sscottl{ 1454195534Sscottl cam_status status; 1455195534Sscottl struct cam_path newpath; 1456195534Sscottl 1457195534Sscottl /* 1458195534Sscottl * We only need to handle events for real devices. 1459195534Sscottl */ 1460195534Sscottl if (target->target_id == CAM_TARGET_WILDCARD 1461195534Sscottl || device->lun_id == CAM_LUN_WILDCARD) 1462195534Sscottl return; 1463195534Sscottl 1464195534Sscottl /* 1465195534Sscottl * We need our own path with wildcards expanded to 1466195534Sscottl * handle certain types of events. 1467195534Sscottl */ 1468195534Sscottl if ((async_code == AC_SENT_BDR) 1469195534Sscottl || (async_code == AC_BUS_RESET) 1470195534Sscottl || (async_code == AC_INQ_CHANGED)) 1471195534Sscottl status = xpt_compile_path(&newpath, NULL, 1472195534Sscottl bus->path_id, 1473195534Sscottl target->target_id, 1474195534Sscottl device->lun_id); 1475195534Sscottl else 1476195534Sscottl status = CAM_REQ_CMP_ERR; 1477195534Sscottl 1478195534Sscottl if (status == CAM_REQ_CMP) { 1479195534Sscottl if (async_code == AC_INQ_CHANGED) { 1480195534Sscottl /* 1481195534Sscottl * We've sent a start unit command, or 1482195534Sscottl * something similar to a device that 1483195534Sscottl * may have caused its inquiry data to 1484195534Sscottl * change. So we re-scan the device to 1485195534Sscottl * refresh the inquiry data for it. 1486195534Sscottl */ 1487195534Sscottl ata_scan_lun(newpath.periph, &newpath, 1488195534Sscottl CAM_EXPECT_INQ_CHANGE, NULL); 1489195534Sscottl } 1490195534Sscottl xpt_release_path(&newpath); 1491198748Smav } else if (async_code == AC_LOST_DEVICE && 1492198748Smav (device->flags & CAM_DEV_UNCONFIGURED) == 0) { 1493195534Sscottl device->flags |= CAM_DEV_UNCONFIGURED; 1494198748Smav xpt_release_device(device); 1495195534Sscottl } else if (async_code == AC_TRANSFER_NEG) { 1496195534Sscottl struct ccb_trans_settings *settings; 1497195534Sscottl 1498195534Sscottl settings = (struct ccb_trans_settings *)async_arg; 1499199178Smav ata_set_transfer_settings(settings, device, 1500195534Sscottl /*async_update*/TRUE); 1501195534Sscottl } 1502195534Sscottl} 1503195534Sscottl 1504