ata_xpt.c revision 208823
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 208823 2010-06-05 09:31:13Z 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/interrupt.h> 41195534Sscottl#include <sys/sbuf.h> 42195534Sscottl 43195534Sscottl#include <sys/lock.h> 44195534Sscottl#include <sys/mutex.h> 45195534Sscottl#include <sys/sysctl.h> 46195534Sscottl 47195534Sscottl#include <cam/cam.h> 48195534Sscottl#include <cam/cam_ccb.h> 49195534Sscottl#include <cam/cam_queue.h> 50195534Sscottl#include <cam/cam_periph.h> 51195534Sscottl#include <cam/cam_sim.h> 52195534Sscottl#include <cam/cam_xpt.h> 53195534Sscottl#include <cam/cam_xpt_sim.h> 54195534Sscottl#include <cam/cam_xpt_periph.h> 55195534Sscottl#include <cam/cam_xpt_internal.h> 56195534Sscottl#include <cam/cam_debug.h> 57195534Sscottl 58195534Sscottl#include <cam/scsi/scsi_all.h> 59195534Sscottl#include <cam/scsi/scsi_message.h> 60195534Sscottl#include <cam/ata/ata_all.h> 61195534Sscottl#include <machine/stdarg.h> /* for xpt_print below */ 62195534Sscottl#include "opt_cam.h" 63195534Sscottl 64199178Smavstruct ata_quirk_entry { 65195534Sscottl struct scsi_inquiry_pattern inq_pat; 66195534Sscottl u_int8_t quirks; 67199178Smav#define CAM_QUIRK_MAXTAGS 0x01 68195534Sscottl u_int maxtags; 69195534Sscottl}; 70195534Sscottl 71195534Sscottlstatic periph_init_t probe_periph_init; 72195534Sscottl 73195534Sscottlstatic struct periph_driver probe_driver = 74195534Sscottl{ 75195653Smav probe_periph_init, "aprobe", 76198708Smav TAILQ_HEAD_INITIALIZER(probe_driver.units), /* generation */ 0, 77198708Smav CAM_PERIPH_DRV_EARLY 78195534Sscottl}; 79195534Sscottl 80195653SmavPERIPHDRIVER_DECLARE(aprobe, probe_driver); 81195534Sscottl 82195534Sscottltypedef enum { 83195534Sscottl PROBE_RESET, 84195534Sscottl PROBE_IDENTIFY, 85203421Smav PROBE_SPINUP, 86195534Sscottl PROBE_SETMODE, 87207499Smav PROBE_SETPM, 88207499Smav PROBE_SETAPST, 89207499Smav PROBE_SETDMAAA, 90198708Smav PROBE_SET_MULTI, 91195534Sscottl PROBE_INQUIRY, 92195534Sscottl PROBE_FULL_INQUIRY, 93195534Sscottl PROBE_PM_PID, 94195534Sscottl PROBE_PM_PRV, 95195534Sscottl PROBE_INVALID 96195534Sscottl} probe_action; 97195534Sscottl 98195534Sscottlstatic char *probe_action_text[] = { 99195534Sscottl "PROBE_RESET", 100195534Sscottl "PROBE_IDENTIFY", 101203421Smav "PROBE_SPINUP", 102195534Sscottl "PROBE_SETMODE", 103207499Smav "PROBE_SETPM", 104207499Smav "PROBE_SETAPST", 105207499Smav "PROBE_SETDMAAA", 106198708Smav "PROBE_SET_MULTI", 107195534Sscottl "PROBE_INQUIRY", 108195534Sscottl "PROBE_FULL_INQUIRY", 109195534Sscottl "PROBE_PM_PID", 110195534Sscottl "PROBE_PM_PRV", 111195534Sscottl "PROBE_INVALID" 112195534Sscottl}; 113195534Sscottl 114195534Sscottl#define PROBE_SET_ACTION(softc, newaction) \ 115195534Sscottldo { \ 116195534Sscottl char **text; \ 117195534Sscottl text = probe_action_text; \ 118195534Sscottl CAM_DEBUG((softc)->periph->path, CAM_DEBUG_INFO, \ 119195534Sscottl ("Probe %s to %s\n", text[(softc)->action], \ 120195534Sscottl text[(newaction)])); \ 121195534Sscottl (softc)->action = (newaction); \ 122195534Sscottl} while(0) 123195534Sscottl 124195534Sscottltypedef enum { 125195534Sscottl PROBE_NO_ANNOUNCE = 0x04 126195534Sscottl} probe_flags; 127195534Sscottl 128195534Sscottltypedef struct { 129195534Sscottl TAILQ_HEAD(, ccb_hdr) request_ccbs; 130203385Smav struct ata_params ident_data; 131195534Sscottl probe_action action; 132195534Sscottl probe_flags flags; 133195534Sscottl uint32_t pm_pid; 134195534Sscottl uint32_t pm_prv; 135203108Smav int restart; 136203421Smav int spinup; 137207499Smav u_int caps; 138195534Sscottl struct cam_periph *periph; 139195534Sscottl} probe_softc; 140195534Sscottl 141199178Smavstatic struct ata_quirk_entry ata_quirk_table[] = 142195534Sscottl{ 143195534Sscottl { 144195534Sscottl /* Default tagged queuing parameters for all devices */ 145195534Sscottl { 146195534Sscottl T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED, 147195534Sscottl /*vendor*/"*", /*product*/"*", /*revision*/"*" 148195534Sscottl }, 149199178Smav /*quirks*/0, /*maxtags*/0 150195534Sscottl }, 151195534Sscottl}; 152195534Sscottl 153199178Smavstatic const int ata_quirk_table_size = 154199178Smav sizeof(ata_quirk_table) / sizeof(*ata_quirk_table); 155195534Sscottl 156195534Sscottlstatic cam_status proberegister(struct cam_periph *periph, 157195534Sscottl void *arg); 158195534Sscottlstatic void probeschedule(struct cam_periph *probe_periph); 159195534Sscottlstatic void probestart(struct cam_periph *periph, union ccb *start_ccb); 160195534Sscottl//static void proberequestdefaultnegotiation(struct cam_periph *periph); 161195534Sscottl//static int proberequestbackoff(struct cam_periph *periph, 162195534Sscottl// struct cam_ed *device); 163195534Sscottlstatic void probedone(struct cam_periph *periph, union ccb *done_ccb); 164195534Sscottlstatic void probecleanup(struct cam_periph *periph); 165199178Smavstatic void ata_find_quirk(struct cam_ed *device); 166195534Sscottlstatic void ata_scan_bus(struct cam_periph *periph, union ccb *ccb); 167195534Sscottlstatic void ata_scan_lun(struct cam_periph *periph, 168195534Sscottl struct cam_path *path, cam_flags flags, 169195534Sscottl union ccb *ccb); 170195534Sscottlstatic void xptscandone(struct cam_periph *periph, union ccb *done_ccb); 171195534Sscottlstatic struct cam_ed * 172195534Sscottl ata_alloc_device(struct cam_eb *bus, struct cam_et *target, 173195534Sscottl lun_id_t lun_id); 174195534Sscottlstatic void ata_device_transport(struct cam_path *path); 175199178Smavstatic void ata_set_transfer_settings(struct ccb_trans_settings *cts, 176195534Sscottl struct cam_ed *device, 177195534Sscottl int async_update); 178195534Sscottlstatic void ata_dev_async(u_int32_t async_code, 179195534Sscottl struct cam_eb *bus, 180195534Sscottl struct cam_et *target, 181195534Sscottl struct cam_ed *device, 182195534Sscottl void *async_arg); 183195534Sscottlstatic void ata_action(union ccb *start_ccb); 184204220Smavstatic void ata_announce_periph(struct cam_periph *periph); 185195534Sscottl 186195534Sscottlstatic struct xpt_xport ata_xport = { 187195534Sscottl .alloc_device = ata_alloc_device, 188195534Sscottl .action = ata_action, 189195534Sscottl .async = ata_dev_async, 190204220Smav .announce = ata_announce_periph, 191195534Sscottl}; 192195534Sscottl 193195534Sscottlstruct xpt_xport * 194195534Sscottlata_get_xport(void) 195195534Sscottl{ 196195534Sscottl return (&ata_xport); 197195534Sscottl} 198195534Sscottl 199195534Sscottlstatic void 200195534Sscottlprobe_periph_init() 201195534Sscottl{ 202195534Sscottl} 203195534Sscottl 204195534Sscottlstatic cam_status 205195534Sscottlproberegister(struct cam_periph *periph, void *arg) 206195534Sscottl{ 207195534Sscottl union ccb *request_ccb; /* CCB representing the probe request */ 208195534Sscottl cam_status status; 209195534Sscottl probe_softc *softc; 210195534Sscottl 211195534Sscottl request_ccb = (union ccb *)arg; 212195534Sscottl if (periph == NULL) { 213195534Sscottl printf("proberegister: periph was NULL!!\n"); 214195534Sscottl return(CAM_REQ_CMP_ERR); 215195534Sscottl } 216195534Sscottl 217195534Sscottl if (request_ccb == NULL) { 218195534Sscottl printf("proberegister: no probe CCB, " 219195534Sscottl "can't register device\n"); 220195534Sscottl return(CAM_REQ_CMP_ERR); 221195534Sscottl } 222195534Sscottl 223203421Smav softc = (probe_softc *)malloc(sizeof(*softc), M_CAMXPT, M_ZERO | M_NOWAIT); 224195534Sscottl 225195534Sscottl if (softc == NULL) { 226195534Sscottl printf("proberegister: Unable to probe new device. " 227195534Sscottl "Unable to allocate softc\n"); 228195534Sscottl return(CAM_REQ_CMP_ERR); 229195534Sscottl } 230195534Sscottl TAILQ_INIT(&softc->request_ccbs); 231195534Sscottl TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h, 232195534Sscottl periph_links.tqe); 233195534Sscottl softc->flags = 0; 234195534Sscottl periph->softc = softc; 235195534Sscottl softc->periph = periph; 236195534Sscottl softc->action = PROBE_INVALID; 237195534Sscottl status = cam_periph_acquire(periph); 238195534Sscottl if (status != CAM_REQ_CMP) { 239195534Sscottl return (status); 240195534Sscottl } 241195534Sscottl /* 242203108Smav * Ensure nobody slip in until probe finish. 243195534Sscottl */ 244203108Smav cam_freeze_devq_arg(periph->path, 245203108Smav RELSIM_RELEASE_RUNLEVEL, CAM_RL_XPT + 1); 246195534Sscottl probeschedule(periph); 247195534Sscottl return(CAM_REQ_CMP); 248195534Sscottl} 249195534Sscottl 250195534Sscottlstatic void 251195534Sscottlprobeschedule(struct cam_periph *periph) 252195534Sscottl{ 253195534Sscottl union ccb *ccb; 254195534Sscottl probe_softc *softc; 255195534Sscottl 256195534Sscottl softc = (probe_softc *)periph->softc; 257195534Sscottl ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs); 258195534Sscottl 259198389Smav if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) || 260198389Smav periph->path->device->protocol == PROTO_SATAPM) 261195534Sscottl PROBE_SET_ACTION(softc, PROBE_RESET); 262195534Sscottl else 263195534Sscottl PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 264195534Sscottl 265195534Sscottl if (ccb->crcn.flags & CAM_EXPECT_INQ_CHANGE) 266195534Sscottl softc->flags |= PROBE_NO_ANNOUNCE; 267195534Sscottl else 268195534Sscottl softc->flags &= ~PROBE_NO_ANNOUNCE; 269195534Sscottl 270203108Smav xpt_schedule(periph, CAM_PRIORITY_XPT); 271195534Sscottl} 272195534Sscottl 273195534Sscottlstatic void 274195534Sscottlprobestart(struct cam_periph *periph, union ccb *start_ccb) 275195534Sscottl{ 276199747Smav struct ccb_trans_settings cts; 277195534Sscottl struct ccb_ataio *ataio; 278195534Sscottl struct ccb_scsiio *csio; 279195534Sscottl probe_softc *softc; 280198708Smav struct cam_path *path; 281198708Smav struct ata_params *ident_buf; 282195534Sscottl 283195534Sscottl CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probestart\n")); 284195534Sscottl 285195534Sscottl softc = (probe_softc *)periph->softc; 286198708Smav path = start_ccb->ccb_h.path; 287195534Sscottl ataio = &start_ccb->ataio; 288195534Sscottl csio = &start_ccb->csio; 289198708Smav ident_buf = &periph->path->device->ident_data; 290195534Sscottl 291203108Smav if (softc->restart) { 292203108Smav softc->restart = 0; 293203108Smav if ((path->device->flags & CAM_DEV_UNCONFIGURED) || 294203108Smav path->device->protocol == PROTO_SATAPM) 295203108Smav softc->action = PROBE_RESET; 296203108Smav else 297203108Smav softc->action = PROBE_IDENTIFY; 298203108Smav } 299195534Sscottl switch (softc->action) { 300195534Sscottl case PROBE_RESET: 301195534Sscottl cam_fill_ataio(ataio, 302195534Sscottl 0, 303195534Sscottl probedone, 304195534Sscottl /*flags*/CAM_DIR_NONE, 305198389Smav 0, 306195534Sscottl /*data_ptr*/NULL, 307195534Sscottl /*dxfer_len*/0, 308203108Smav 15 * 1000); 309195534Sscottl ata_reset_cmd(ataio); 310195534Sscottl break; 311195534Sscottl case PROBE_IDENTIFY: 312195534Sscottl cam_fill_ataio(ataio, 313195534Sscottl 1, 314195534Sscottl probedone, 315195534Sscottl /*flags*/CAM_DIR_IN, 316198389Smav 0, 317203385Smav /*data_ptr*/(u_int8_t *)&softc->ident_data, 318203385Smav /*dxfer_len*/sizeof(softc->ident_data), 319195534Sscottl 30 * 1000); 320195534Sscottl if (periph->path->device->protocol == PROTO_ATA) 321196659Smav ata_28bit_cmd(ataio, ATA_ATA_IDENTIFY, 0, 0, 0); 322195534Sscottl else 323196659Smav ata_28bit_cmd(ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0); 324195534Sscottl break; 325203421Smav case PROBE_SPINUP: 326203421Smav if (bootverbose) 327203421Smav xpt_print(path, "Spinning up device\n"); 328203421Smav cam_fill_ataio(ataio, 329203421Smav 1, 330203421Smav probedone, 331203421Smav /*flags*/CAM_DIR_NONE | CAM_HIGH_POWER, 332203421Smav 0, 333203421Smav /*data_ptr*/NULL, 334203421Smav /*dxfer_len*/0, 335203421Smav 30 * 1000); 336203421Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_PUIS_SPINUP, 0, 0); 337203421Smav break; 338195534Sscottl case PROBE_SETMODE: 339199747Smav { 340199747Smav int mode, wantmode; 341199747Smav 342199747Smav mode = 0; 343199747Smav /* Fetch user modes from SIM. */ 344199747Smav bzero(&cts, sizeof(cts)); 345203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 346199747Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 347199747Smav cts.type = CTS_TYPE_USER_SETTINGS; 348199747Smav xpt_action((union ccb *)&cts); 349199747Smav if (path->device->transport == XPORT_ATA) { 350199747Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_MODE) 351199747Smav mode = cts.xport_specific.ata.mode; 352199747Smav } else { 353199799Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_MODE) 354199747Smav mode = cts.xport_specific.sata.mode; 355199747Smav } 356199747Smavnegotiate: 357199747Smav /* Honor device capabilities. */ 358199747Smav wantmode = mode = ata_max_mode(ident_buf, mode); 359199747Smav /* Report modes to SIM. */ 360199747Smav bzero(&cts, sizeof(cts)); 361203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 362199747Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 363199747Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 364199747Smav if (path->device->transport == XPORT_ATA) { 365199747Smav cts.xport_specific.ata.mode = mode; 366199747Smav cts.xport_specific.ata.valid = CTS_ATA_VALID_MODE; 367199747Smav } else { 368199747Smav cts.xport_specific.sata.mode = mode; 369199747Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_MODE; 370199747Smav } 371199747Smav xpt_action((union ccb *)&cts); 372200171Smav /* Fetch current modes from SIM. */ 373199747Smav bzero(&cts, sizeof(cts)); 374203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 375199747Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 376199747Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 377199747Smav xpt_action((union ccb *)&cts); 378199747Smav if (path->device->transport == XPORT_ATA) { 379199747Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_MODE) 380199747Smav mode = cts.xport_specific.ata.mode; 381199747Smav } else { 382199747Smav if (cts.xport_specific.ata.valid & CTS_SATA_VALID_MODE) 383199747Smav mode = cts.xport_specific.sata.mode; 384199747Smav } 385199747Smav /* If SIM disagree - renegotiate. */ 386199747Smav if (mode != wantmode) 387199747Smav goto negotiate; 388195534Sscottl cam_fill_ataio(ataio, 389195534Sscottl 1, 390195534Sscottl probedone, 391196353Smav /*flags*/CAM_DIR_NONE, 392196353Smav 0, 393196353Smav /*data_ptr*/NULL, 394196353Smav /*dxfer_len*/0, 395195534Sscottl 30 * 1000); 396199747Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); 397195534Sscottl break; 398199747Smav } 399207499Smav case PROBE_SETPM: 400207499Smav cam_fill_ataio(ataio, 401207499Smav 1, 402207499Smav probedone, 403207499Smav CAM_DIR_NONE, 404207499Smav 0, 405207499Smav NULL, 406207499Smav 0, 407207499Smav 30*1000); 408207499Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, 409207499Smav (softc->caps & CTS_SATA_CAPS_H_PMREQ) ? 0x10 : 0x90, 410207499Smav 0, 0x03); 411207499Smav break; 412207499Smav case PROBE_SETAPST: 413207499Smav cam_fill_ataio(ataio, 414207499Smav 1, 415207499Smav probedone, 416207499Smav CAM_DIR_NONE, 417207499Smav 0, 418207499Smav NULL, 419207499Smav 0, 420207499Smav 30*1000); 421207499Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, 422207499Smav (softc->caps & CTS_SATA_CAPS_H_APST) ? 0x10 : 0x90, 423207499Smav 0, 0x07); 424207499Smav break; 425207499Smav case PROBE_SETDMAAA: 426207499Smav cam_fill_ataio(ataio, 427207499Smav 1, 428207499Smav probedone, 429207499Smav CAM_DIR_NONE, 430207499Smav 0, 431207499Smav NULL, 432207499Smav 0, 433207499Smav 30*1000); 434207499Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, 435207499Smav (softc->caps & CTS_SATA_CAPS_H_DMAAA) ? 0x10 : 0x90, 436207499Smav 0, 0x02); 437207499Smav break; 438198708Smav case PROBE_SET_MULTI: 439198708Smav { 440200171Smav u_int sectors, bytecount; 441198708Smav 442200171Smav bytecount = 8192; /* SATA maximum */ 443200171Smav /* Fetch user bytecount from SIM. */ 444200171Smav bzero(&cts, sizeof(cts)); 445203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 446200171Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 447200171Smav cts.type = CTS_TYPE_USER_SETTINGS; 448200171Smav xpt_action((union ccb *)&cts); 449200171Smav if (path->device->transport == XPORT_ATA) { 450200171Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 451200171Smav bytecount = cts.xport_specific.ata.bytecount; 452200171Smav } else { 453200171Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 454200171Smav bytecount = cts.xport_specific.sata.bytecount; 455200171Smav } 456200171Smav /* Honor device capabilities. */ 457200171Smav sectors = max(1, min(ident_buf->sectors_intr & 0xff, 458200171Smav bytecount / ata_logical_sector_size(ident_buf))); 459198708Smav /* Report bytecount to SIM. */ 460198708Smav bzero(&cts, sizeof(cts)); 461203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 462198708Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 463198708Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 464198708Smav if (path->device->transport == XPORT_ATA) { 465198897Smav cts.xport_specific.ata.bytecount = sectors * 466198897Smav ata_logical_sector_size(ident_buf); 467198708Smav cts.xport_specific.ata.valid = CTS_ATA_VALID_BYTECOUNT; 468198708Smav } else { 469198897Smav cts.xport_specific.sata.bytecount = sectors * 470198897Smav ata_logical_sector_size(ident_buf); 471198708Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_BYTECOUNT; 472198708Smav } 473198708Smav xpt_action((union ccb *)&cts); 474200171Smav /* Fetch current bytecount from SIM. */ 475200171Smav bzero(&cts, sizeof(cts)); 476203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 477200171Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 478200171Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 479200171Smav xpt_action((union ccb *)&cts); 480200171Smav if (path->device->transport == XPORT_ATA) { 481200171Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 482200171Smav bytecount = cts.xport_specific.ata.bytecount; 483200171Smav } else { 484200171Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 485200171Smav bytecount = cts.xport_specific.sata.bytecount; 486200171Smav } 487200171Smav sectors = bytecount / ata_logical_sector_size(ident_buf); 488198708Smav 489198708Smav cam_fill_ataio(ataio, 490198708Smav 1, 491198708Smav probedone, 492198708Smav CAM_DIR_NONE, 493198708Smav 0, 494198708Smav NULL, 495198708Smav 0, 496198708Smav 30*1000); 497198708Smav ata_28bit_cmd(ataio, ATA_SET_MULTI, 0, 0, sectors); 498198708Smav break; 499195534Sscottl } 500195534Sscottl case PROBE_INQUIRY: 501200171Smav { 502200171Smav u_int bytecount; 503200171Smav 504200171Smav bytecount = 8192; /* SATA maximum */ 505200171Smav /* Fetch user bytecount from SIM. */ 506200171Smav bzero(&cts, sizeof(cts)); 507203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 508200171Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 509200171Smav cts.type = CTS_TYPE_USER_SETTINGS; 510200171Smav xpt_action((union ccb *)&cts); 511200171Smav if (path->device->transport == XPORT_ATA) { 512200171Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 513200171Smav bytecount = cts.xport_specific.ata.bytecount; 514200171Smav } else { 515200171Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 516200171Smav bytecount = cts.xport_specific.sata.bytecount; 517200171Smav } 518200171Smav /* Honor device capabilities. */ 519200171Smav bytecount &= ~1; 520200171Smav bytecount = max(2, min(65534, bytecount)); 521200171Smav if (ident_buf->satacapabilities != 0x0000 && 522200171Smav ident_buf->satacapabilities != 0xffff) { 523200171Smav bytecount = min(8192, bytecount); 524200171Smav } 525200171Smav /* Report bytecount to SIM. */ 526200171Smav bzero(&cts, sizeof(cts)); 527203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 528200171Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 529200171Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 530200171Smav if (path->device->transport == XPORT_ATA) { 531200171Smav cts.xport_specific.ata.bytecount = bytecount; 532200171Smav cts.xport_specific.ata.valid = CTS_ATA_VALID_BYTECOUNT; 533200171Smav } else { 534200171Smav cts.xport_specific.sata.bytecount = bytecount; 535200171Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_BYTECOUNT; 536200171Smav } 537200171Smav xpt_action((union ccb *)&cts); 538200171Smav /* FALLTHROUGH */ 539200171Smav } 540195534Sscottl case PROBE_FULL_INQUIRY: 541195534Sscottl { 542195534Sscottl u_int inquiry_len; 543195534Sscottl struct scsi_inquiry_data *inq_buf = 544195534Sscottl &periph->path->device->inq_data; 545195534Sscottl 546195534Sscottl if (softc->action == PROBE_INQUIRY) 547195534Sscottl inquiry_len = SHORT_INQUIRY_LENGTH; 548195534Sscottl else 549195534Sscottl inquiry_len = SID_ADDITIONAL_LENGTH(inq_buf); 550195534Sscottl /* 551195534Sscottl * Some parallel SCSI devices fail to send an 552195534Sscottl * ignore wide residue message when dealing with 553195534Sscottl * odd length inquiry requests. Round up to be 554195534Sscottl * safe. 555195534Sscottl */ 556195534Sscottl inquiry_len = roundup2(inquiry_len, 2); 557195534Sscottl scsi_inquiry(csio, 558195534Sscottl /*retries*/1, 559195534Sscottl probedone, 560195534Sscottl MSG_SIMPLE_Q_TAG, 561195534Sscottl (u_int8_t *)inq_buf, 562195534Sscottl inquiry_len, 563195534Sscottl /*evpd*/FALSE, 564195534Sscottl /*page_code*/0, 565195534Sscottl SSD_MIN_SIZE, 566195534Sscottl /*timeout*/60 * 1000); 567195534Sscottl break; 568195534Sscottl } 569195534Sscottl case PROBE_PM_PID: 570195534Sscottl cam_fill_ataio(ataio, 571195534Sscottl 1, 572195534Sscottl probedone, 573195534Sscottl /*flags*/CAM_DIR_NONE, 574198389Smav 0, 575195534Sscottl /*data_ptr*/NULL, 576195534Sscottl /*dxfer_len*/0, 577195534Sscottl 10 * 1000); 578195534Sscottl ata_pm_read_cmd(ataio, 0, 15); 579195534Sscottl break; 580195534Sscottl case PROBE_PM_PRV: 581195534Sscottl cam_fill_ataio(ataio, 582195534Sscottl 1, 583195534Sscottl probedone, 584195534Sscottl /*flags*/CAM_DIR_NONE, 585198389Smav 0, 586195534Sscottl /*data_ptr*/NULL, 587195534Sscottl /*dxfer_len*/0, 588195534Sscottl 10 * 1000); 589195534Sscottl ata_pm_read_cmd(ataio, 1, 15); 590195534Sscottl break; 591195534Sscottl case PROBE_INVALID: 592198708Smav CAM_DEBUG(path, CAM_DEBUG_INFO, 593195534Sscottl ("probestart: invalid action state\n")); 594195534Sscottl default: 595195534Sscottl break; 596195534Sscottl } 597195534Sscottl xpt_action(start_ccb); 598195534Sscottl} 599195534Sscottl#if 0 600195534Sscottlstatic void 601195534Sscottlproberequestdefaultnegotiation(struct cam_periph *periph) 602195534Sscottl{ 603195534Sscottl struct ccb_trans_settings cts; 604195534Sscottl 605203108Smav xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE); 606195534Sscottl cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 607195534Sscottl cts.type = CTS_TYPE_USER_SETTINGS; 608195534Sscottl xpt_action((union ccb *)&cts); 609195534Sscottl if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 610195534Sscottl return; 611195534Sscottl } 612195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 613195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 614195534Sscottl xpt_action((union ccb *)&cts); 615195534Sscottl} 616195534Sscottl 617195534Sscottl/* 618195534Sscottl * Backoff Negotiation Code- only pertinent for SPI devices. 619195534Sscottl */ 620195534Sscottlstatic int 621195534Sscottlproberequestbackoff(struct cam_periph *periph, struct cam_ed *device) 622195534Sscottl{ 623195534Sscottl struct ccb_trans_settings cts; 624195534Sscottl struct ccb_trans_settings_spi *spi; 625195534Sscottl 626195534Sscottl memset(&cts, 0, sizeof (cts)); 627203108Smav xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE); 628195534Sscottl cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 629195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 630195534Sscottl xpt_action((union ccb *)&cts); 631195534Sscottl if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 632195534Sscottl if (bootverbose) { 633195534Sscottl xpt_print(periph->path, 634195534Sscottl "failed to get current device settings\n"); 635195534Sscottl } 636195534Sscottl return (0); 637195534Sscottl } 638195534Sscottl if (cts.transport != XPORT_SPI) { 639195534Sscottl if (bootverbose) { 640195534Sscottl xpt_print(periph->path, "not SPI transport\n"); 641195534Sscottl } 642195534Sscottl return (0); 643195534Sscottl } 644195534Sscottl spi = &cts.xport_specific.spi; 645195534Sscottl 646195534Sscottl /* 647195534Sscottl * We cannot renegotiate sync rate if we don't have one. 648195534Sscottl */ 649195534Sscottl if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) { 650195534Sscottl if (bootverbose) { 651195534Sscottl xpt_print(periph->path, "no sync rate known\n"); 652195534Sscottl } 653195534Sscottl return (0); 654195534Sscottl } 655195534Sscottl 656195534Sscottl /* 657195534Sscottl * We'll assert that we don't have to touch PPR options- the 658195534Sscottl * SIM will see what we do with period and offset and adjust 659195534Sscottl * the PPR options as appropriate. 660195534Sscottl */ 661195534Sscottl 662195534Sscottl /* 663195534Sscottl * A sync rate with unknown or zero offset is nonsensical. 664195534Sscottl * A sync period of zero means Async. 665195534Sscottl */ 666195534Sscottl if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0 667195534Sscottl || spi->sync_offset == 0 || spi->sync_period == 0) { 668195534Sscottl if (bootverbose) { 669195534Sscottl xpt_print(periph->path, "no sync rate available\n"); 670195534Sscottl } 671195534Sscottl return (0); 672195534Sscottl } 673195534Sscottl 674195534Sscottl if (device->flags & CAM_DEV_DV_HIT_BOTTOM) { 675195534Sscottl CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 676195534Sscottl ("hit async: giving up on DV\n")); 677195534Sscottl return (0); 678195534Sscottl } 679195534Sscottl 680195534Sscottl 681195534Sscottl /* 682195534Sscottl * Jump sync_period up by one, but stop at 5MHz and fall back to Async. 683195534Sscottl * We don't try to remember 'last' settings to see if the SIM actually 684195534Sscottl * gets into the speed we want to set. We check on the SIM telling 685195534Sscottl * us that a requested speed is bad, but otherwise don't try and 686195534Sscottl * check the speed due to the asynchronous and handshake nature 687195534Sscottl * of speed setting. 688195534Sscottl */ 689195534Sscottl spi->valid = CTS_SPI_VALID_SYNC_RATE | CTS_SPI_VALID_SYNC_OFFSET; 690195534Sscottl for (;;) { 691195534Sscottl spi->sync_period++; 692195534Sscottl if (spi->sync_period >= 0xf) { 693195534Sscottl spi->sync_period = 0; 694195534Sscottl spi->sync_offset = 0; 695195534Sscottl CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 696195534Sscottl ("setting to async for DV\n")); 697195534Sscottl /* 698195534Sscottl * Once we hit async, we don't want to try 699195534Sscottl * any more settings. 700195534Sscottl */ 701195534Sscottl device->flags |= CAM_DEV_DV_HIT_BOTTOM; 702195534Sscottl } else if (bootverbose) { 703195534Sscottl CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 704195534Sscottl ("DV: period 0x%x\n", spi->sync_period)); 705195534Sscottl printf("setting period to 0x%x\n", spi->sync_period); 706195534Sscottl } 707195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 708195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 709195534Sscottl xpt_action((union ccb *)&cts); 710195534Sscottl if ((cts.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { 711195534Sscottl break; 712195534Sscottl } 713195534Sscottl CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 714195534Sscottl ("DV: failed to set period 0x%x\n", spi->sync_period)); 715195534Sscottl if (spi->sync_period == 0) { 716195534Sscottl return (0); 717195534Sscottl } 718195534Sscottl } 719195534Sscottl return (1); 720195534Sscottl} 721195534Sscottl#endif 722195534Sscottlstatic void 723195534Sscottlprobedone(struct cam_periph *periph, union ccb *done_ccb) 724195534Sscottl{ 725199747Smav struct ccb_trans_settings cts; 726195534Sscottl struct ata_params *ident_buf; 727195534Sscottl probe_softc *softc; 728195534Sscottl struct cam_path *path; 729195534Sscottl u_int32_t priority; 730207499Smav u_int caps; 731198389Smav int found = 1; 732195534Sscottl 733195534Sscottl CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probedone\n")); 734195534Sscottl 735195534Sscottl softc = (probe_softc *)periph->softc; 736195534Sscottl path = done_ccb->ccb_h.path; 737195534Sscottl priority = done_ccb->ccb_h.pinfo.priority; 738195534Sscottl ident_buf = &path->device->ident_data; 739195534Sscottl 740198708Smav if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 741203499Smavdevice_fail: if ((!softc->restart) && 742203499Smav cam_periph_error(done_ccb, 0, 0, NULL) == ERESTART) { 743195534Sscottl return; 744195534Sscottl } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 745195534Sscottl /* Don't wedge the queue */ 746195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 747195534Sscottl /*run_queue*/TRUE); 748195534Sscottl } 749198708Smav /* Old PIO2 devices may not support mode setting. */ 750198708Smav if (softc->action == PROBE_SETMODE && 751198708Smav ata_max_pmode(ident_buf) <= ATA_PIO2 && 752198708Smav (ident_buf->capabilities1 & ATA_SUPPORT_IORDY) == 0) 753198708Smav goto noerror; 754198708Smav /* 755198708Smav * If we get to this point, we got an error status back 756198708Smav * from the inquiry and the error status doesn't require 757198708Smav * automatically retrying the command. Therefore, the 758198708Smav * inquiry failed. If we had inquiry information before 759198708Smav * for this device, but this latest inquiry command failed, 760198708Smav * the device has probably gone away. If this device isn't 761198708Smav * already marked unconfigured, notify the peripheral 762198708Smav * drivers that this device is no more. 763198708Smav */ 764198708Smav if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0) 765198708Smav xpt_async(AC_LOST_DEVICE, path, NULL); 766198708Smav found = 0; 767198708Smav goto done; 768198708Smav } 769198708Smavnoerror: 770203385Smav if (softc->restart) 771203385Smav goto done; 772198708Smav switch (softc->action) { 773198708Smav case PROBE_RESET: 774195534Sscottl { 775198708Smav int sign = (done_ccb->ataio.res.lba_high << 8) + 776198708Smav done_ccb->ataio.res.lba_mid; 777200218Smav if (bootverbose) 778200218Smav xpt_print(path, "SIGNATURE: %04x\n", sign); 779198708Smav if (sign == 0x0000 && 780198708Smav done_ccb->ccb_h.target_id != 15) { 781198708Smav path->device->protocol = PROTO_ATA; 782198708Smav PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 783198708Smav } else if (sign == 0x9669 && 784198708Smav done_ccb->ccb_h.target_id == 15) { 785199747Smav /* Report SIM that PM is present. */ 786198708Smav bzero(&cts, sizeof(cts)); 787203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 788198708Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 789198708Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 790198708Smav cts.xport_specific.sata.pm_present = 1; 791198708Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; 792198708Smav xpt_action((union ccb *)&cts); 793198708Smav path->device->protocol = PROTO_SATAPM; 794198708Smav PROBE_SET_ACTION(softc, PROBE_PM_PID); 795198708Smav } else if (sign == 0xeb14 && 796198708Smav done_ccb->ccb_h.target_id != 15) { 797198708Smav path->device->protocol = PROTO_SCSI; 798198708Smav PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 799198708Smav } else { 800198708Smav if (done_ccb->ccb_h.target_id != 15) { 801198708Smav xpt_print(path, 802198708Smav "Unexpected signature 0x%04x\n", sign); 803195534Sscottl } 804198708Smav goto device_fail; 805198708Smav } 806198708Smav xpt_release_ccb(done_ccb); 807198708Smav xpt_schedule(periph, priority); 808198708Smav return; 809198708Smav } 810198708Smav case PROBE_IDENTIFY: 811198708Smav { 812207222Smav struct ccb_pathinq cpi; 813198708Smav int16_t *ptr; 814207282Smav int changed = 1; 815195534Sscottl 816203385Smav ident_buf = &softc->ident_data; 817198708Smav for (ptr = (int16_t *)ident_buf; 818198708Smav ptr < (int16_t *)ident_buf + sizeof(struct ata_params)/2; ptr++) { 819198708Smav *ptr = le16toh(*ptr); 820198708Smav } 821198708Smav if (strncmp(ident_buf->model, "FX", 2) && 822198708Smav strncmp(ident_buf->model, "NEC", 3) && 823198708Smav strncmp(ident_buf->model, "Pioneer", 7) && 824198708Smav strncmp(ident_buf->model, "SHARP", 5)) { 825198708Smav ata_bswap(ident_buf->model, sizeof(ident_buf->model)); 826198708Smav ata_bswap(ident_buf->revision, sizeof(ident_buf->revision)); 827198708Smav ata_bswap(ident_buf->serial, sizeof(ident_buf->serial)); 828198708Smav } 829198708Smav ata_btrim(ident_buf->model, sizeof(ident_buf->model)); 830198708Smav ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model)); 831198708Smav ata_btrim(ident_buf->revision, sizeof(ident_buf->revision)); 832198708Smav ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision)); 833198708Smav ata_btrim(ident_buf->serial, sizeof(ident_buf->serial)); 834198708Smav ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial)); 835203421Smav /* Device may need spin-up before IDENTIFY become valid. */ 836204354Smav if ((ident_buf->specconf == 0x37c8 || 837204354Smav ident_buf->specconf == 0x738c) && 838204354Smav ((ident_buf->config & ATA_RESP_INCOMPLETE) || 839204354Smav softc->spinup == 0)) { 840203421Smav PROBE_SET_ACTION(softc, PROBE_SPINUP); 841203421Smav xpt_release_ccb(done_ccb); 842203421Smav xpt_schedule(periph, priority); 843203421Smav return; 844203421Smav } 845203385Smav ident_buf = &path->device->ident_data; 846198708Smav if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) { 847198708Smav /* Check that it is the same device. */ 848203385Smav if (bcmp(softc->ident_data.model, ident_buf->model, 849203385Smav sizeof(ident_buf->model)) || 850203385Smav bcmp(softc->ident_data.revision, ident_buf->revision, 851203385Smav sizeof(ident_buf->revision)) || 852203385Smav bcmp(softc->ident_data.serial, ident_buf->serial, 853203385Smav sizeof(ident_buf->serial))) { 854198708Smav /* Device changed. */ 855198708Smav xpt_async(AC_LOST_DEVICE, path, NULL); 856207282Smav } else { 857203385Smav bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 858207282Smav changed = 0; 859207282Smav } 860207282Smav } 861207282Smav if (changed) { 862203385Smav bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 863195534Sscottl /* Clean up from previous instance of this device */ 864195534Sscottl if (path->device->serial_num != NULL) { 865195534Sscottl free(path->device->serial_num, M_CAMXPT); 866195534Sscottl path->device->serial_num = NULL; 867195534Sscottl path->device->serial_num_len = 0; 868195534Sscottl } 869195534Sscottl path->device->serial_num = 870195534Sscottl (u_int8_t *)malloc((sizeof(ident_buf->serial) + 1), 871198708Smav M_CAMXPT, M_NOWAIT); 872195534Sscottl if (path->device->serial_num != NULL) { 873195534Sscottl bcopy(ident_buf->serial, 874195534Sscottl path->device->serial_num, 875195534Sscottl sizeof(ident_buf->serial)); 876195534Sscottl path->device->serial_num[sizeof(ident_buf->serial)] 877195534Sscottl = '\0'; 878195534Sscottl path->device->serial_num_len = 879195534Sscottl strlen(path->device->serial_num); 880195534Sscottl } 881195534Sscottl 882198331Smav path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 883195534Sscottl } 884199178Smav if (ident_buf->satacapabilities & ATA_SUPPORT_NCQ) { 885199178Smav path->device->mintags = path->device->maxtags = 886199178Smav ATA_QUEUE_LEN(ident_buf->queue) + 1; 887199178Smav } 888199178Smav ata_find_quirk(path->device); 889199263Smav if (path->device->mintags != 0 && 890199263Smav path->bus->sim->max_tagged_dev_openings != 0) { 891207222Smav /* Check if the SIM does not want queued commands. */ 892207222Smav bzero(&cpi, sizeof(cpi)); 893207222Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 894207222Smav cpi.ccb_h.func_code = XPT_PATH_INQ; 895207222Smav xpt_action((union ccb *)&cpi); 896207222Smav if (cpi.ccb_h.status == CAM_REQ_CMP && 897207222Smav (cpi.hba_inquiry & PI_TAG_ABLE)) { 898207222Smav /* Report SIM which tags are allowed. */ 899207222Smav bzero(&cts, sizeof(cts)); 900207222Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 901207222Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 902207222Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 903207222Smav cts.xport_specific.sata.tags = path->device->maxtags; 904207222Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_TAGS; 905207222Smav xpt_action((union ccb *)&cts); 906207222Smav /* Reconfigure queues for tagged queueing. */ 907207222Smav xpt_start_tags(path); 908207222Smav } 909199178Smav } 910198708Smav ata_device_transport(path); 911198708Smav PROBE_SET_ACTION(softc, PROBE_SETMODE); 912195534Sscottl xpt_release_ccb(done_ccb); 913198708Smav xpt_schedule(periph, priority); 914198708Smav return; 915195534Sscottl } 916203421Smav case PROBE_SPINUP: 917203421Smav if (bootverbose) 918203421Smav xpt_print(path, "Spin-up done\n"); 919203421Smav softc->spinup = 1; 920203421Smav PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 921203421Smav xpt_release_ccb(done_ccb); 922203421Smav xpt_schedule(periph, priority); 923203421Smav return; 924195534Sscottl case PROBE_SETMODE: 925207499Smav if (path->device->transport != XPORT_SATA) 926207499Smav goto notsata; 927207499Smav /* Set supported bits. */ 928207499Smav bzero(&cts, sizeof(cts)); 929207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 930207499Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 931207499Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 932207499Smav xpt_action((union ccb *)&cts); 933207499Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 934207499Smav caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H; 935207499Smav else 936207499Smav caps = 0; 937207499Smav if (ident_buf->satacapabilities != 0xffff) { 938207499Smav if (ident_buf->satacapabilities & ATA_SUPPORT_IFPWRMNGTRCV) 939207499Smav caps |= CTS_SATA_CAPS_D_PMREQ; 940207499Smav if (ident_buf->satacapabilities & ATA_SUPPORT_HAPST) 941207499Smav caps |= CTS_SATA_CAPS_D_APST; 942207499Smav } 943207499Smav /* Mask unwanted bits. */ 944207499Smav bzero(&cts, sizeof(cts)); 945207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 946207499Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 947207499Smav cts.type = CTS_TYPE_USER_SETTINGS; 948207499Smav xpt_action((union ccb *)&cts); 949207499Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 950207499Smav caps &= cts.xport_specific.sata.caps; 951207499Smav /* Store result to SIM. */ 952207499Smav bzero(&cts, sizeof(cts)); 953207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 954207499Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 955207499Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 956207499Smav cts.xport_specific.sata.caps = caps; 957207499Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS; 958207499Smav xpt_action((union ccb *)&cts); 959207499Smav softc->caps = caps; 960207499Smav if (ident_buf->satasupport & ATA_SUPPORT_IFPWRMNGT) { 961207499Smav PROBE_SET_ACTION(softc, PROBE_SETPM); 962207499Smav xpt_release_ccb(done_ccb); 963207499Smav xpt_schedule(periph, priority); 964207499Smav return; 965207499Smav } 966207499Smav /* FALLTHROUGH */ 967207499Smav case PROBE_SETPM: 968207499Smav if (ident_buf->satacapabilities != 0xffff && 969207499Smav ident_buf->satacapabilities & ATA_SUPPORT_DAPST) { 970207499Smav PROBE_SET_ACTION(softc, PROBE_SETAPST); 971207499Smav xpt_release_ccb(done_ccb); 972207499Smav xpt_schedule(periph, priority); 973207499Smav return; 974207499Smav } 975207499Smav /* FALLTHROUGH */ 976207499Smav case PROBE_SETAPST: 977207499Smav if (ident_buf->satasupport & ATA_SUPPORT_AUTOACTIVATE) { 978207499Smav PROBE_SET_ACTION(softc, PROBE_SETDMAAA); 979207499Smav xpt_release_ccb(done_ccb); 980207499Smav xpt_schedule(periph, priority); 981207499Smav return; 982207499Smav } 983207499Smav /* FALLTHROUGH */ 984207499Smav case PROBE_SETDMAAA: 985207499Smavnotsata: 986198708Smav if (path->device->protocol == PROTO_ATA) { 987198708Smav PROBE_SET_ACTION(softc, PROBE_SET_MULTI); 988198708Smav } else { 989198708Smav PROBE_SET_ACTION(softc, PROBE_INQUIRY); 990195534Sscottl } 991198708Smav xpt_release_ccb(done_ccb); 992198708Smav xpt_schedule(periph, priority); 993198708Smav return; 994198708Smav case PROBE_SET_MULTI: 995198708Smav if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 996198708Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 997198748Smav xpt_acquire_device(path->device); 998198708Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 999198708Smav xpt_action(done_ccb); 1000198708Smav xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, 1001198708Smav done_ccb); 1002198708Smav } 1003198708Smav break; 1004195534Sscottl case PROBE_INQUIRY: 1005195534Sscottl case PROBE_FULL_INQUIRY: 1006195534Sscottl { 1007198708Smav struct scsi_inquiry_data *inq_buf; 1008198708Smav u_int8_t periph_qual, len; 1009195534Sscottl 1010198708Smav path->device->flags |= CAM_DEV_INQUIRY_DATA_VALID; 1011198708Smav inq_buf = &path->device->inq_data; 1012195534Sscottl 1013198708Smav periph_qual = SID_QUAL(inq_buf); 1014195534Sscottl 1015198708Smav if (periph_qual != SID_QUAL_LU_CONNECTED) 1016198708Smav break; 1017195534Sscottl 1018198708Smav /* 1019198708Smav * We conservatively request only 1020198708Smav * SHORT_INQUIRY_LEN bytes of inquiry 1021198708Smav * information during our first try 1022198708Smav * at sending an INQUIRY. If the device 1023198708Smav * has more information to give, 1024198708Smav * perform a second request specifying 1025198708Smav * the amount of information the device 1026198708Smav * is willing to give. 1027198708Smav */ 1028198708Smav len = inq_buf->additional_length 1029198708Smav + offsetof(struct scsi_inquiry_data, additional_length) + 1; 1030198708Smav if (softc->action == PROBE_INQUIRY 1031198708Smav && len > SHORT_INQUIRY_LENGTH) { 1032198708Smav PROBE_SET_ACTION(softc, PROBE_FULL_INQUIRY); 1033198708Smav xpt_release_ccb(done_ccb); 1034198708Smav xpt_schedule(periph, priority); 1035195534Sscottl return; 1036195534Sscottl } 1037198708Smav 1038198708Smav ata_device_transport(path); 1039198708Smav if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 1040198708Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1041198748Smav xpt_acquire_device(path->device); 1042198708Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1043198708Smav xpt_action(done_ccb); 1044198708Smav xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, done_ccb); 1045198708Smav } 1046198708Smav break; 1047195534Sscottl } 1048195534Sscottl case PROBE_PM_PID: 1049198708Smav if ((path->device->flags & CAM_DEV_IDENTIFY_DATA_VALID) == 0) 1050198708Smav bzero(ident_buf, sizeof(*ident_buf)); 1051198708Smav softc->pm_pid = (done_ccb->ataio.res.lba_high << 24) + 1052198708Smav (done_ccb->ataio.res.lba_mid << 16) + 1053198708Smav (done_ccb->ataio.res.lba_low << 8) + 1054198708Smav done_ccb->ataio.res.sector_count; 1055198708Smav ((uint32_t *)ident_buf)[0] = softc->pm_pid; 1056198708Smav snprintf(ident_buf->model, sizeof(ident_buf->model), 1057198708Smav "Port Multiplier %08x", softc->pm_pid); 1058198708Smav PROBE_SET_ACTION(softc, PROBE_PM_PRV); 1059198708Smav xpt_release_ccb(done_ccb); 1060198708Smav xpt_schedule(periph, priority); 1061198708Smav return; 1062195534Sscottl case PROBE_PM_PRV: 1063198708Smav softc->pm_prv = (done_ccb->ataio.res.lba_high << 24) + 1064198708Smav (done_ccb->ataio.res.lba_mid << 16) + 1065198708Smav (done_ccb->ataio.res.lba_low << 8) + 1066198708Smav done_ccb->ataio.res.sector_count; 1067198708Smav ((uint32_t *)ident_buf)[1] = softc->pm_prv; 1068198708Smav snprintf(ident_buf->revision, sizeof(ident_buf->revision), 1069198708Smav "%04x", softc->pm_prv); 1070198708Smav path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 1071207499Smav /* Set supported bits. */ 1072207499Smav bzero(&cts, sizeof(cts)); 1073207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1074207499Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1075207499Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 1076207499Smav xpt_action((union ccb *)&cts); 1077207499Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1078207499Smav caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H; 1079207499Smav else 1080207499Smav caps = 0; 1081207499Smav /* All PMPs must support PM requests. */ 1082207499Smav caps |= CTS_SATA_CAPS_D_PMREQ; 1083207499Smav /* Mask unwanted bits. */ 1084207499Smav bzero(&cts, sizeof(cts)); 1085207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1086207499Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1087207499Smav cts.type = CTS_TYPE_USER_SETTINGS; 1088207499Smav xpt_action((union ccb *)&cts); 1089207499Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1090207499Smav caps &= cts.xport_specific.sata.caps; 1091207499Smav /* Store result to SIM. */ 1092207499Smav bzero(&cts, sizeof(cts)); 1093207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1094207499Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1095207499Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 1096207499Smav cts.xport_specific.sata.caps = caps; 1097207499Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS; 1098207499Smav xpt_action((union ccb *)&cts); 1099207499Smav softc->caps = caps; 1100198708Smav if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 1101198708Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1102198748Smav xpt_acquire_device(path->device); 1103198708Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1104198708Smav xpt_action(done_ccb); 1105198708Smav xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, 1106198708Smav done_ccb); 1107198708Smav } else { 1108198708Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1109198708Smav xpt_action(done_ccb); 1110198708Smav xpt_async(AC_SCSI_AEN, done_ccb->ccb_h.path, done_ccb); 1111195534Sscottl } 1112198708Smav break; 1113195534Sscottl case PROBE_INVALID: 1114195534Sscottl CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_INFO, 1115195534Sscottl ("probedone: invalid action state\n")); 1116195534Sscottl default: 1117195534Sscottl break; 1118195534Sscottl } 1119198708Smavdone: 1120203108Smav if (softc->restart) { 1121203108Smav softc->restart = 0; 1122203108Smav xpt_release_ccb(done_ccb); 1123195534Sscottl probeschedule(periph); 1124203108Smav return; 1125195534Sscottl } 1126203108Smav xpt_release_ccb(done_ccb); 1127203108Smav while ((done_ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs))) { 1128203108Smav TAILQ_REMOVE(&softc->request_ccbs, 1129203108Smav &done_ccb->ccb_h, periph_links.tqe); 1130203108Smav done_ccb->ccb_h.status = found ? CAM_REQ_CMP : CAM_REQ_CMP_ERR; 1131203108Smav xpt_done(done_ccb); 1132203108Smav } 1133203108Smav cam_release_devq(periph->path, 1134203108Smav RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_XPT + 1, FALSE); 1135203108Smav cam_periph_invalidate(periph); 1136203108Smav cam_periph_release_locked(periph); 1137195534Sscottl} 1138195534Sscottl 1139195534Sscottlstatic void 1140195534Sscottlprobecleanup(struct cam_periph *periph) 1141195534Sscottl{ 1142195534Sscottl free(periph->softc, M_CAMXPT); 1143195534Sscottl} 1144195534Sscottl 1145195534Sscottlstatic void 1146199178Smavata_find_quirk(struct cam_ed *device) 1147195534Sscottl{ 1148199178Smav struct ata_quirk_entry *quirk; 1149195534Sscottl caddr_t match; 1150195534Sscottl 1151199178Smav match = cam_quirkmatch((caddr_t)&device->ident_data, 1152199178Smav (caddr_t)ata_quirk_table, 1153199178Smav ata_quirk_table_size, 1154199178Smav sizeof(*ata_quirk_table), ata_identify_match); 1155195534Sscottl 1156195534Sscottl if (match == NULL) 1157195534Sscottl panic("xpt_find_quirk: device didn't match wildcard entry!!"); 1158195534Sscottl 1159199178Smav quirk = (struct ata_quirk_entry *)match; 1160195534Sscottl device->quirk = quirk; 1161199178Smav if (quirk->quirks & CAM_QUIRK_MAXTAGS) 1162199178Smav device->mintags = device->maxtags = quirk->maxtags; 1163195534Sscottl} 1164195534Sscottl 1165195534Sscottltypedef struct { 1166195534Sscottl union ccb *request_ccb; 1167195534Sscottl struct ccb_pathinq *cpi; 1168195534Sscottl int counter; 1169195534Sscottl} ata_scan_bus_info; 1170195534Sscottl 1171195534Sscottl/* 1172195534Sscottl * To start a scan, request_ccb is an XPT_SCAN_BUS ccb. 1173195534Sscottl * As the scan progresses, xpt_scan_bus is used as the 1174195534Sscottl * callback on completion function. 1175195534Sscottl */ 1176195534Sscottlstatic void 1177195534Sscottlata_scan_bus(struct cam_periph *periph, union ccb *request_ccb) 1178195534Sscottl{ 1179195534Sscottl struct cam_path *path; 1180195534Sscottl ata_scan_bus_info *scan_info; 1181203108Smav union ccb *work_ccb, *reset_ccb; 1182195534Sscottl cam_status status; 1183195534Sscottl 1184195534Sscottl CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE, 1185195534Sscottl ("xpt_scan_bus\n")); 1186195534Sscottl switch (request_ccb->ccb_h.func_code) { 1187195534Sscottl case XPT_SCAN_BUS: 1188208582Smjacob case XPT_SCAN_TGT: 1189195534Sscottl /* Find out the characteristics of the bus */ 1190195534Sscottl work_ccb = xpt_alloc_ccb_nowait(); 1191195534Sscottl if (work_ccb == NULL) { 1192195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1193195534Sscottl xpt_done(request_ccb); 1194195534Sscottl return; 1195195534Sscottl } 1196195534Sscottl xpt_setup_ccb(&work_ccb->ccb_h, request_ccb->ccb_h.path, 1197195534Sscottl request_ccb->ccb_h.pinfo.priority); 1198195534Sscottl work_ccb->ccb_h.func_code = XPT_PATH_INQ; 1199195534Sscottl xpt_action(work_ccb); 1200195534Sscottl if (work_ccb->ccb_h.status != CAM_REQ_CMP) { 1201195534Sscottl request_ccb->ccb_h.status = work_ccb->ccb_h.status; 1202195534Sscottl xpt_free_ccb(work_ccb); 1203195534Sscottl xpt_done(request_ccb); 1204195534Sscottl return; 1205195534Sscottl } 1206195534Sscottl 1207203108Smav /* We may need to reset bus first, if we haven't done it yet. */ 1208203108Smav if ((work_ccb->cpi.hba_inquiry & 1209203108Smav (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE)) && 1210203108Smav !(work_ccb->cpi.hba_misc & PIM_NOBUSRESET) && 1211203108Smav !timevalisset(&request_ccb->ccb_h.path->bus->last_reset)) { 1212203108Smav reset_ccb = xpt_alloc_ccb_nowait(); 1213208823Smav if (reset_ccb == NULL) { 1214208823Smav request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1215208823Smav xpt_free_ccb(work_ccb); 1216208823Smav xpt_done(request_ccb); 1217208823Smav return; 1218208823Smav } 1219203108Smav xpt_setup_ccb(&reset_ccb->ccb_h, request_ccb->ccb_h.path, 1220203108Smav CAM_PRIORITY_NONE); 1221203108Smav reset_ccb->ccb_h.func_code = XPT_RESET_BUS; 1222203108Smav xpt_action(reset_ccb); 1223203108Smav if (reset_ccb->ccb_h.status != CAM_REQ_CMP) { 1224203108Smav request_ccb->ccb_h.status = reset_ccb->ccb_h.status; 1225203108Smav xpt_free_ccb(reset_ccb); 1226203108Smav xpt_free_ccb(work_ccb); 1227203108Smav xpt_done(request_ccb); 1228203108Smav return; 1229203108Smav } 1230203108Smav xpt_free_ccb(reset_ccb); 1231203108Smav } 1232203108Smav 1233195534Sscottl /* Save some state for use while we probe for devices */ 1234195534Sscottl scan_info = (ata_scan_bus_info *) 1235195534Sscottl malloc(sizeof(ata_scan_bus_info), M_CAMXPT, M_NOWAIT); 1236195534Sscottl if (scan_info == NULL) { 1237195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1238208823Smav xpt_free_ccb(work_ccb); 1239195534Sscottl xpt_done(request_ccb); 1240195534Sscottl return; 1241195534Sscottl } 1242195534Sscottl scan_info->request_ccb = request_ccb; 1243195534Sscottl scan_info->cpi = &work_ccb->cpi; 1244195534Sscottl /* If PM supported, probe it first. */ 1245195534Sscottl if (scan_info->cpi->hba_inquiry & PI_SATAPM) 1246201990Smav scan_info->counter = scan_info->cpi->max_target; 1247201990Smav else 1248201990Smav scan_info->counter = 0; 1249195534Sscottl 1250195534Sscottl work_ccb = xpt_alloc_ccb_nowait(); 1251195534Sscottl if (work_ccb == NULL) { 1252195534Sscottl free(scan_info, M_CAMXPT); 1253195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1254195534Sscottl xpt_done(request_ccb); 1255195534Sscottl break; 1256195534Sscottl } 1257195534Sscottl goto scan_next; 1258195534Sscottl case XPT_SCAN_LUN: 1259195534Sscottl work_ccb = request_ccb; 1260195534Sscottl /* Reuse the same CCB to query if a device was really found */ 1261195534Sscottl scan_info = (ata_scan_bus_info *)work_ccb->ccb_h.ppriv_ptr0; 1262198389Smav /* If there is PMP... */ 1263201990Smav if ((scan_info->cpi->hba_inquiry & PI_SATAPM) && 1264201990Smav (scan_info->counter == scan_info->cpi->max_target)) { 1265203108Smav if (work_ccb->ccb_h.status == CAM_REQ_CMP) { 1266207428Smav /* everything else will be probed by it */ 1267207428Smav /* Free the current request path- we're done with it. */ 1268207428Smav xpt_free_path(work_ccb->ccb_h.path); 1269201990Smav goto done; 1270195534Sscottl } else { 1271195534Sscottl struct ccb_trans_settings cts; 1272195534Sscottl 1273195534Sscottl /* Report SIM that PM is absent. */ 1274195534Sscottl bzero(&cts, sizeof(cts)); 1275195534Sscottl xpt_setup_ccb(&cts.ccb_h, 1276207428Smav work_ccb->ccb_h.path, CAM_PRIORITY_NONE); 1277195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1278195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 1279195665Smav cts.xport_specific.sata.pm_present = 0; 1280195534Sscottl cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; 1281195534Sscottl xpt_action((union ccb *)&cts); 1282195534Sscottl } 1283195534Sscottl } 1284207428Smav /* Free the current request path- we're done with it. */ 1285207428Smav xpt_free_path(work_ccb->ccb_h.path); 1286201990Smav if (scan_info->counter == 1287201990Smav ((scan_info->cpi->hba_inquiry & PI_SATAPM) ? 1288201990Smav 0 : scan_info->cpi->max_target)) { 1289201990Smavdone: 1290195534Sscottl xpt_free_ccb(work_ccb); 1291195534Sscottl xpt_free_ccb((union ccb *)scan_info->cpi); 1292195534Sscottl request_ccb = scan_info->request_ccb; 1293195534Sscottl free(scan_info, M_CAMXPT); 1294195534Sscottl request_ccb->ccb_h.status = CAM_REQ_CMP; 1295195534Sscottl xpt_done(request_ccb); 1296195534Sscottl break; 1297195534Sscottl } 1298201990Smav /* Take next device. Wrap from max (PMP) to 0. */ 1299201990Smav scan_info->counter = (scan_info->counter + 1 ) % 1300201990Smav (scan_info->cpi->max_target + 1); 1301195534Sscottlscan_next: 1302195534Sscottl status = xpt_create_path(&path, xpt_periph, 1303195534Sscottl scan_info->request_ccb->ccb_h.path_id, 1304195534Sscottl scan_info->counter, 0); 1305195534Sscottl if (status != CAM_REQ_CMP) { 1306195534Sscottl printf("xpt_scan_bus: xpt_create_path failed" 1307195534Sscottl " with status %#x, bus scan halted\n", 1308195534Sscottl status); 1309195534Sscottl xpt_free_ccb(work_ccb); 1310195534Sscottl xpt_free_ccb((union ccb *)scan_info->cpi); 1311195534Sscottl request_ccb = scan_info->request_ccb; 1312195534Sscottl free(scan_info, M_CAMXPT); 1313195534Sscottl request_ccb->ccb_h.status = status; 1314195534Sscottl xpt_done(request_ccb); 1315195534Sscottl break; 1316195534Sscottl } 1317195534Sscottl xpt_setup_ccb(&work_ccb->ccb_h, path, 1318195534Sscottl scan_info->request_ccb->ccb_h.pinfo.priority); 1319195534Sscottl work_ccb->ccb_h.func_code = XPT_SCAN_LUN; 1320195534Sscottl work_ccb->ccb_h.cbfcnp = ata_scan_bus; 1321195534Sscottl work_ccb->ccb_h.ppriv_ptr0 = scan_info; 1322195534Sscottl work_ccb->crcn.flags = scan_info->request_ccb->crcn.flags; 1323195534Sscottl xpt_action(work_ccb); 1324195534Sscottl break; 1325195534Sscottl default: 1326195534Sscottl break; 1327195534Sscottl } 1328195534Sscottl} 1329195534Sscottl 1330195534Sscottlstatic void 1331195534Sscottlata_scan_lun(struct cam_periph *periph, struct cam_path *path, 1332195534Sscottl cam_flags flags, union ccb *request_ccb) 1333195534Sscottl{ 1334195534Sscottl struct ccb_pathinq cpi; 1335195534Sscottl cam_status status; 1336195534Sscottl struct cam_path *new_path; 1337195534Sscottl struct cam_periph *old_periph; 1338195534Sscottl 1339203108Smav CAM_DEBUG(path, CAM_DEBUG_TRACE, ("xpt_scan_lun\n")); 1340195534Sscottl 1341203108Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 1342195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 1343195534Sscottl xpt_action((union ccb *)&cpi); 1344195534Sscottl 1345195534Sscottl if (cpi.ccb_h.status != CAM_REQ_CMP) { 1346195534Sscottl if (request_ccb != NULL) { 1347195534Sscottl request_ccb->ccb_h.status = cpi.ccb_h.status; 1348195534Sscottl xpt_done(request_ccb); 1349195534Sscottl } 1350195534Sscottl return; 1351195534Sscottl } 1352195534Sscottl 1353195534Sscottl if (request_ccb == NULL) { 1354195534Sscottl request_ccb = malloc(sizeof(union ccb), M_CAMXPT, M_NOWAIT); 1355195534Sscottl if (request_ccb == NULL) { 1356195534Sscottl xpt_print(path, "xpt_scan_lun: can't allocate CCB, " 1357195534Sscottl "can't continue\n"); 1358195534Sscottl return; 1359195534Sscottl } 1360195534Sscottl new_path = malloc(sizeof(*new_path), M_CAMXPT, M_NOWAIT); 1361195534Sscottl if (new_path == NULL) { 1362195534Sscottl xpt_print(path, "xpt_scan_lun: can't allocate path, " 1363195534Sscottl "can't continue\n"); 1364195534Sscottl free(request_ccb, M_CAMXPT); 1365195534Sscottl return; 1366195534Sscottl } 1367195534Sscottl status = xpt_compile_path(new_path, xpt_periph, 1368195534Sscottl path->bus->path_id, 1369195534Sscottl path->target->target_id, 1370195534Sscottl path->device->lun_id); 1371195534Sscottl 1372195534Sscottl if (status != CAM_REQ_CMP) { 1373195534Sscottl xpt_print(path, "xpt_scan_lun: can't compile path, " 1374195534Sscottl "can't continue\n"); 1375195534Sscottl free(request_ccb, M_CAMXPT); 1376195534Sscottl free(new_path, M_CAMXPT); 1377195534Sscottl return; 1378195534Sscottl } 1379203108Smav xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_XPT); 1380195534Sscottl request_ccb->ccb_h.cbfcnp = xptscandone; 1381195534Sscottl request_ccb->ccb_h.func_code = XPT_SCAN_LUN; 1382195534Sscottl request_ccb->crcn.flags = flags; 1383195534Sscottl } 1384195534Sscottl 1385195653Smav if ((old_periph = cam_periph_find(path, "aprobe")) != NULL) { 1386195534Sscottl probe_softc *softc; 1387195534Sscottl 1388195534Sscottl softc = (probe_softc *)old_periph->softc; 1389195534Sscottl TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h, 1390195534Sscottl periph_links.tqe); 1391203108Smav softc->restart = 1; 1392195534Sscottl } else { 1393195534Sscottl status = cam_periph_alloc(proberegister, NULL, probecleanup, 1394195653Smav probestart, "aprobe", 1395195534Sscottl CAM_PERIPH_BIO, 1396195534Sscottl request_ccb->ccb_h.path, NULL, 0, 1397195534Sscottl request_ccb); 1398195534Sscottl 1399195534Sscottl if (status != CAM_REQ_CMP) { 1400195534Sscottl xpt_print(path, "xpt_scan_lun: cam_alloc_periph " 1401195534Sscottl "returned an error, can't continue probe\n"); 1402195534Sscottl request_ccb->ccb_h.status = status; 1403195534Sscottl xpt_done(request_ccb); 1404195534Sscottl } 1405195534Sscottl } 1406195534Sscottl} 1407195534Sscottl 1408195534Sscottlstatic void 1409195534Sscottlxptscandone(struct cam_periph *periph, union ccb *done_ccb) 1410195534Sscottl{ 1411195534Sscottl xpt_release_path(done_ccb->ccb_h.path); 1412195534Sscottl free(done_ccb->ccb_h.path, M_CAMXPT); 1413195534Sscottl free(done_ccb, M_CAMXPT); 1414195534Sscottl} 1415195534Sscottl 1416195534Sscottlstatic struct cam_ed * 1417195534Sscottlata_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id) 1418195534Sscottl{ 1419195534Sscottl struct cam_path path; 1420199178Smav struct ata_quirk_entry *quirk; 1421195534Sscottl struct cam_ed *device; 1422195534Sscottl struct cam_ed *cur_device; 1423195534Sscottl 1424195534Sscottl device = xpt_alloc_device(bus, target, lun_id); 1425195534Sscottl if (device == NULL) 1426195534Sscottl return (NULL); 1427195534Sscottl 1428195534Sscottl /* 1429195534Sscottl * Take the default quirk entry until we have inquiry 1430195534Sscottl * data and can determine a better quirk to use. 1431195534Sscottl */ 1432199178Smav quirk = &ata_quirk_table[ata_quirk_table_size - 1]; 1433195534Sscottl device->quirk = (void *)quirk; 1434199178Smav device->mintags = 0; 1435199178Smav device->maxtags = 0; 1436195534Sscottl bzero(&device->inq_data, sizeof(device->inq_data)); 1437195534Sscottl device->inq_flags = 0; 1438195534Sscottl device->queue_flags = 0; 1439195534Sscottl device->serial_num = NULL; 1440195534Sscottl device->serial_num_len = 0; 1441195534Sscottl 1442195534Sscottl /* 1443195534Sscottl * XXX should be limited by number of CCBs this bus can 1444195534Sscottl * do. 1445195534Sscottl */ 1446195534Sscottl bus->sim->max_ccbs += device->ccbq.devq_openings; 1447195534Sscottl /* Insertion sort into our target's device list */ 1448195534Sscottl cur_device = TAILQ_FIRST(&target->ed_entries); 1449195534Sscottl while (cur_device != NULL && cur_device->lun_id < lun_id) 1450195534Sscottl cur_device = TAILQ_NEXT(cur_device, links); 1451195534Sscottl if (cur_device != NULL) { 1452195534Sscottl TAILQ_INSERT_BEFORE(cur_device, device, links); 1453195534Sscottl } else { 1454195534Sscottl TAILQ_INSERT_TAIL(&target->ed_entries, device, links); 1455195534Sscottl } 1456195534Sscottl target->generation++; 1457195534Sscottl if (lun_id != CAM_LUN_WILDCARD) { 1458195534Sscottl xpt_compile_path(&path, 1459195534Sscottl NULL, 1460195534Sscottl bus->path_id, 1461195534Sscottl target->target_id, 1462195534Sscottl lun_id); 1463195534Sscottl ata_device_transport(&path); 1464195534Sscottl xpt_release_path(&path); 1465195534Sscottl } 1466195534Sscottl 1467195534Sscottl return (device); 1468195534Sscottl} 1469195534Sscottl 1470195534Sscottlstatic void 1471195534Sscottlata_device_transport(struct cam_path *path) 1472195534Sscottl{ 1473195534Sscottl struct ccb_pathinq cpi; 1474198331Smav struct ccb_trans_settings cts; 1475198331Smav struct scsi_inquiry_data *inq_buf = NULL; 1476198331Smav struct ata_params *ident_buf = NULL; 1477195534Sscottl 1478195534Sscottl /* Get transport information from the SIM */ 1479203108Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 1480195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 1481195534Sscottl xpt_action((union ccb *)&cpi); 1482195534Sscottl 1483195534Sscottl path->device->transport = cpi.transport; 1484198331Smav if ((path->device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0) 1485198331Smav inq_buf = &path->device->inq_data; 1486198331Smav if ((path->device->flags & CAM_DEV_IDENTIFY_DATA_VALID) != 0) 1487198331Smav ident_buf = &path->device->ident_data; 1488198331Smav if (path->device->protocol == PROTO_ATA) { 1489198331Smav path->device->protocol_version = ident_buf ? 1490198331Smav ata_version(ident_buf->version_major) : cpi.protocol_version; 1491198331Smav } else if (path->device->protocol == PROTO_SCSI) { 1492198331Smav path->device->protocol_version = inq_buf ? 1493198331Smav SID_ANSI_REV(inq_buf) : cpi.protocol_version; 1494195534Sscottl } 1495198331Smav path->device->transport_version = ident_buf ? 1496198331Smav ata_version(ident_buf->version_major) : cpi.transport_version; 1497195534Sscottl 1498195534Sscottl /* Tell the controller what we think */ 1499203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1500195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1501195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 1502195534Sscottl cts.transport = path->device->transport; 1503195534Sscottl cts.transport_version = path->device->transport_version; 1504195534Sscottl cts.protocol = path->device->protocol; 1505195534Sscottl cts.protocol_version = path->device->protocol_version; 1506195534Sscottl cts.proto_specific.valid = 0; 1507203376Smav if (ident_buf) { 1508203376Smav if (path->device->transport == XPORT_ATA) { 1509203376Smav cts.xport_specific.ata.atapi = 1510203376Smav ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_16) ? 16 : 1511203376Smav ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) ? 12 : 0; 1512203376Smav cts.xport_specific.ata.valid = CTS_ATA_VALID_ATAPI; 1513203376Smav } else { 1514203376Smav cts.xport_specific.sata.atapi = 1515203376Smav ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_16) ? 16 : 1516203376Smav ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) ? 12 : 0; 1517203376Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_ATAPI; 1518203376Smav } 1519203376Smav } else 1520203376Smav cts.xport_specific.valid = 0; 1521195534Sscottl xpt_action((union ccb *)&cts); 1522195534Sscottl} 1523195534Sscottl 1524195534Sscottlstatic void 1525195534Sscottlata_action(union ccb *start_ccb) 1526195534Sscottl{ 1527195534Sscottl 1528195534Sscottl switch (start_ccb->ccb_h.func_code) { 1529195534Sscottl case XPT_SET_TRAN_SETTINGS: 1530195534Sscottl { 1531199178Smav ata_set_transfer_settings(&start_ccb->cts, 1532195534Sscottl start_ccb->ccb_h.path->device, 1533195534Sscottl /*async_update*/FALSE); 1534195534Sscottl break; 1535195534Sscottl } 1536195534Sscottl case XPT_SCAN_BUS: 1537208582Smjacob case XPT_SCAN_TGT: 1538195534Sscottl ata_scan_bus(start_ccb->ccb_h.path->periph, start_ccb); 1539195534Sscottl break; 1540195534Sscottl case XPT_SCAN_LUN: 1541195534Sscottl ata_scan_lun(start_ccb->ccb_h.path->periph, 1542195534Sscottl start_ccb->ccb_h.path, start_ccb->crcn.flags, 1543195534Sscottl start_ccb); 1544195534Sscottl break; 1545195534Sscottl case XPT_GET_TRAN_SETTINGS: 1546195534Sscottl { 1547195534Sscottl struct cam_sim *sim; 1548195534Sscottl 1549195534Sscottl sim = start_ccb->ccb_h.path->bus->sim; 1550195534Sscottl (*(sim->sim_action))(sim, start_ccb); 1551195534Sscottl break; 1552195534Sscottl } 1553203376Smav case XPT_SCSI_IO: 1554203376Smav { 1555203376Smav struct cam_ed *device; 1556203376Smav u_int maxlen = 0; 1557203376Smav 1558203376Smav device = start_ccb->ccb_h.path->device; 1559203376Smav if (device->protocol == PROTO_SCSI && 1560203376Smav (device->flags & CAM_DEV_IDENTIFY_DATA_VALID)) { 1561203376Smav uint16_t p = 1562203376Smav device->ident_data.config & ATA_PROTO_MASK; 1563203376Smav 1564203376Smav maxlen = (p == ATA_PROTO_ATAPI_16) ? 16 : 1565203376Smav (p == ATA_PROTO_ATAPI_12) ? 12 : 0; 1566203376Smav } 1567203376Smav if (start_ccb->csio.cdb_len > maxlen) { 1568203376Smav start_ccb->ccb_h.status = CAM_REQ_INVALID; 1569203376Smav xpt_done(start_ccb); 1570203376Smav break; 1571203376Smav } 1572203376Smav /* FALLTHROUGH */ 1573203376Smav } 1574195534Sscottl default: 1575195534Sscottl xpt_action_default(start_ccb); 1576195534Sscottl break; 1577195534Sscottl } 1578195534Sscottl} 1579195534Sscottl 1580195534Sscottlstatic void 1581199178Smavata_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device, 1582195534Sscottl int async_update) 1583195534Sscottl{ 1584195534Sscottl struct ccb_pathinq cpi; 1585195534Sscottl struct ccb_trans_settings cur_cts; 1586195534Sscottl struct ccb_trans_settings_scsi *scsi; 1587195534Sscottl struct ccb_trans_settings_scsi *cur_scsi; 1588195534Sscottl struct cam_sim *sim; 1589195534Sscottl struct scsi_inquiry_data *inq_data; 1590195534Sscottl 1591195534Sscottl if (device == NULL) { 1592195534Sscottl cts->ccb_h.status = CAM_PATH_INVALID; 1593195534Sscottl xpt_done((union ccb *)cts); 1594195534Sscottl return; 1595195534Sscottl } 1596195534Sscottl 1597195534Sscottl if (cts->protocol == PROTO_UNKNOWN 1598195534Sscottl || cts->protocol == PROTO_UNSPECIFIED) { 1599195534Sscottl cts->protocol = device->protocol; 1600195534Sscottl cts->protocol_version = device->protocol_version; 1601195534Sscottl } 1602195534Sscottl 1603195534Sscottl if (cts->protocol_version == PROTO_VERSION_UNKNOWN 1604195534Sscottl || cts->protocol_version == PROTO_VERSION_UNSPECIFIED) 1605195534Sscottl cts->protocol_version = device->protocol_version; 1606195534Sscottl 1607195534Sscottl if (cts->protocol != device->protocol) { 1608195534Sscottl xpt_print(cts->ccb_h.path, "Uninitialized Protocol %x:%x?\n", 1609195534Sscottl cts->protocol, device->protocol); 1610195534Sscottl cts->protocol = device->protocol; 1611195534Sscottl } 1612195534Sscottl 1613195534Sscottl if (cts->protocol_version > device->protocol_version) { 1614195534Sscottl if (bootverbose) { 1615195534Sscottl xpt_print(cts->ccb_h.path, "Down reving Protocol " 1616195534Sscottl "Version from %d to %d?\n", cts->protocol_version, 1617195534Sscottl device->protocol_version); 1618195534Sscottl } 1619195534Sscottl cts->protocol_version = device->protocol_version; 1620195534Sscottl } 1621195534Sscottl 1622195534Sscottl if (cts->transport == XPORT_UNKNOWN 1623195534Sscottl || cts->transport == XPORT_UNSPECIFIED) { 1624195534Sscottl cts->transport = device->transport; 1625195534Sscottl cts->transport_version = device->transport_version; 1626195534Sscottl } 1627195534Sscottl 1628195534Sscottl if (cts->transport_version == XPORT_VERSION_UNKNOWN 1629195534Sscottl || cts->transport_version == XPORT_VERSION_UNSPECIFIED) 1630195534Sscottl cts->transport_version = device->transport_version; 1631195534Sscottl 1632195534Sscottl if (cts->transport != device->transport) { 1633195534Sscottl xpt_print(cts->ccb_h.path, "Uninitialized Transport %x:%x?\n", 1634195534Sscottl cts->transport, device->transport); 1635195534Sscottl cts->transport = device->transport; 1636195534Sscottl } 1637195534Sscottl 1638195534Sscottl if (cts->transport_version > device->transport_version) { 1639195534Sscottl if (bootverbose) { 1640195534Sscottl xpt_print(cts->ccb_h.path, "Down reving Transport " 1641195534Sscottl "Version from %d to %d?\n", cts->transport_version, 1642195534Sscottl device->transport_version); 1643195534Sscottl } 1644195534Sscottl cts->transport_version = device->transport_version; 1645195534Sscottl } 1646195534Sscottl 1647195534Sscottl sim = cts->ccb_h.path->bus->sim; 1648195534Sscottl 1649195534Sscottl /* 1650195534Sscottl * Nothing more of interest to do unless 1651195534Sscottl * this is a device connected via the 1652195534Sscottl * SCSI protocol. 1653195534Sscottl */ 1654195534Sscottl if (cts->protocol != PROTO_SCSI) { 1655195534Sscottl if (async_update == FALSE) 1656195534Sscottl (*(sim->sim_action))(sim, (union ccb *)cts); 1657195534Sscottl return; 1658195534Sscottl } 1659195534Sscottl 1660195534Sscottl inq_data = &device->inq_data; 1661195534Sscottl scsi = &cts->proto_specific.scsi; 1662203108Smav xpt_setup_ccb(&cpi.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NONE); 1663195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 1664195534Sscottl xpt_action((union ccb *)&cpi); 1665195534Sscottl 1666195534Sscottl /* SCSI specific sanity checking */ 1667195534Sscottl if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0 1668195534Sscottl || (INQ_DATA_TQ_ENABLED(inq_data)) == 0 1669195534Sscottl || (device->queue_flags & SCP_QUEUE_DQUE) != 0 1670195534Sscottl || (device->mintags == 0)) { 1671195534Sscottl /* 1672195534Sscottl * Can't tag on hardware that doesn't support tags, 1673195534Sscottl * doesn't have it enabled, or has broken tag support. 1674195534Sscottl */ 1675195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 1676195534Sscottl } 1677195534Sscottl 1678195534Sscottl if (async_update == FALSE) { 1679195534Sscottl /* 1680195534Sscottl * Perform sanity checking against what the 1681195534Sscottl * controller and device can do. 1682195534Sscottl */ 1683203108Smav xpt_setup_ccb(&cur_cts.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NONE); 1684195534Sscottl cur_cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1685195534Sscottl cur_cts.type = cts->type; 1686195534Sscottl xpt_action((union ccb *)&cur_cts); 1687195534Sscottl if ((cur_cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1688195534Sscottl return; 1689195534Sscottl } 1690195534Sscottl cur_scsi = &cur_cts.proto_specific.scsi; 1691195534Sscottl if ((scsi->valid & CTS_SCSI_VALID_TQ) == 0) { 1692195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 1693195534Sscottl scsi->flags |= cur_scsi->flags & CTS_SCSI_FLAGS_TAG_ENB; 1694195534Sscottl } 1695195534Sscottl if ((cur_scsi->valid & CTS_SCSI_VALID_TQ) == 0) 1696195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 1697195534Sscottl } 1698195534Sscottl 1699195534Sscottl if (cts->type == CTS_TYPE_CURRENT_SETTINGS 1700195534Sscottl && (scsi->valid & CTS_SCSI_VALID_TQ) != 0) { 1701195534Sscottl int device_tagenb; 1702195534Sscottl 1703195534Sscottl /* 1704195534Sscottl * If we are transitioning from tags to no-tags or 1705195534Sscottl * vice-versa, we need to carefully freeze and restart 1706195534Sscottl * the queue so that we don't overlap tagged and non-tagged 1707195534Sscottl * commands. We also temporarily stop tags if there is 1708195534Sscottl * a change in transfer negotiation settings to allow 1709195534Sscottl * "tag-less" negotiation. 1710195534Sscottl */ 1711195534Sscottl if ((device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 1712195534Sscottl || (device->inq_flags & SID_CmdQue) != 0) 1713195534Sscottl device_tagenb = TRUE; 1714195534Sscottl else 1715195534Sscottl device_tagenb = FALSE; 1716195534Sscottl 1717195534Sscottl if (((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0 1718195534Sscottl && device_tagenb == FALSE) 1719195534Sscottl || ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) == 0 1720195534Sscottl && device_tagenb == TRUE)) { 1721195534Sscottl 1722195534Sscottl if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) { 1723195534Sscottl /* 1724195534Sscottl * Delay change to use tags until after a 1725195534Sscottl * few commands have gone to this device so 1726195534Sscottl * the controller has time to perform transfer 1727195534Sscottl * negotiations without tagged messages getting 1728195534Sscottl * in the way. 1729195534Sscottl */ 1730195534Sscottl device->tag_delay_count = CAM_TAG_DELAY_COUNT; 1731195534Sscottl device->flags |= CAM_DEV_TAG_AFTER_COUNT; 1732195534Sscottl } else { 1733199178Smav xpt_stop_tags(cts->ccb_h.path); 1734195534Sscottl } 1735195534Sscottl } 1736195534Sscottl } 1737195534Sscottl if (async_update == FALSE) 1738195534Sscottl (*(sim->sim_action))(sim, (union ccb *)cts); 1739195534Sscottl} 1740195534Sscottl 1741195534Sscottl/* 1742195534Sscottl * Handle any per-device event notifications that require action by the XPT. 1743195534Sscottl */ 1744195534Sscottlstatic void 1745195534Sscottlata_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target, 1746195534Sscottl struct cam_ed *device, void *async_arg) 1747195534Sscottl{ 1748195534Sscottl cam_status status; 1749195534Sscottl struct cam_path newpath; 1750195534Sscottl 1751195534Sscottl /* 1752195534Sscottl * We only need to handle events for real devices. 1753195534Sscottl */ 1754195534Sscottl if (target->target_id == CAM_TARGET_WILDCARD 1755195534Sscottl || device->lun_id == CAM_LUN_WILDCARD) 1756195534Sscottl return; 1757195534Sscottl 1758195534Sscottl /* 1759195534Sscottl * We need our own path with wildcards expanded to 1760195534Sscottl * handle certain types of events. 1761195534Sscottl */ 1762195534Sscottl if ((async_code == AC_SENT_BDR) 1763195534Sscottl || (async_code == AC_BUS_RESET) 1764195534Sscottl || (async_code == AC_INQ_CHANGED)) 1765195534Sscottl status = xpt_compile_path(&newpath, NULL, 1766195534Sscottl bus->path_id, 1767195534Sscottl target->target_id, 1768195534Sscottl device->lun_id); 1769195534Sscottl else 1770195534Sscottl status = CAM_REQ_CMP_ERR; 1771195534Sscottl 1772195534Sscottl if (status == CAM_REQ_CMP) { 1773195534Sscottl if (async_code == AC_INQ_CHANGED) { 1774195534Sscottl /* 1775195534Sscottl * We've sent a start unit command, or 1776195534Sscottl * something similar to a device that 1777195534Sscottl * may have caused its inquiry data to 1778195534Sscottl * change. So we re-scan the device to 1779195534Sscottl * refresh the inquiry data for it. 1780195534Sscottl */ 1781195534Sscottl ata_scan_lun(newpath.periph, &newpath, 1782195534Sscottl CAM_EXPECT_INQ_CHANGE, NULL); 1783203108Smav } else { 1784203108Smav /* We need to reinitialize device after reset. */ 1785203108Smav ata_scan_lun(newpath.periph, &newpath, 1786203108Smav 0, NULL); 1787195534Sscottl } 1788195534Sscottl xpt_release_path(&newpath); 1789198748Smav } else if (async_code == AC_LOST_DEVICE && 1790198748Smav (device->flags & CAM_DEV_UNCONFIGURED) == 0) { 1791195534Sscottl device->flags |= CAM_DEV_UNCONFIGURED; 1792198748Smav xpt_release_device(device); 1793195534Sscottl } else if (async_code == AC_TRANSFER_NEG) { 1794195534Sscottl struct ccb_trans_settings *settings; 1795195534Sscottl 1796195534Sscottl settings = (struct ccb_trans_settings *)async_arg; 1797199178Smav ata_set_transfer_settings(settings, device, 1798195534Sscottl /*async_update*/TRUE); 1799195534Sscottl } 1800195534Sscottl} 1801195534Sscottl 1802204220Smavstatic void 1803204220Smavata_announce_periph(struct cam_periph *periph) 1804204220Smav{ 1805204220Smav struct ccb_pathinq cpi; 1806204220Smav struct ccb_trans_settings cts; 1807204220Smav struct cam_path *path = periph->path; 1808204220Smav u_int speed; 1809204220Smav u_int mb; 1810204220Smav 1811204220Smav mtx_assert(periph->sim->mtx, MA_OWNED); 1812204220Smav 1813204220Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); 1814204220Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1815204220Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 1816204220Smav xpt_action((union ccb*)&cts); 1817204220Smav if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 1818204220Smav return; 1819204220Smav /* Ask the SIM for its base transfer speed */ 1820204220Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL); 1821204220Smav cpi.ccb_h.func_code = XPT_PATH_INQ; 1822204220Smav xpt_action((union ccb *)&cpi); 1823204220Smav /* Report connection speed */ 1824204220Smav speed = cpi.base_transfer_speed; 1825204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_ATA) { 1826204220Smav struct ccb_trans_settings_ata *ata = 1827204220Smav &cts.xport_specific.ata; 1828204220Smav 1829204220Smav if (ata->valid & CTS_ATA_VALID_MODE) 1830204220Smav speed = ata_mode2speed(ata->mode); 1831204220Smav } 1832204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SATA) { 1833204220Smav struct ccb_trans_settings_sata *sata = 1834204220Smav &cts.xport_specific.sata; 1835204220Smav 1836204220Smav if (sata->valid & CTS_SATA_VALID_REVISION) 1837204220Smav speed = ata_revision2speed(sata->revision); 1838204220Smav } 1839204220Smav mb = speed / 1000; 1840204220Smav if (mb > 0) 1841204220Smav printf("%s%d: %d.%03dMB/s transfers", 1842204220Smav periph->periph_name, periph->unit_number, 1843204220Smav mb, speed % 1000); 1844204220Smav else 1845204220Smav printf("%s%d: %dKB/s transfers", periph->periph_name, 1846204220Smav periph->unit_number, speed); 1847204220Smav /* Report additional information about connection */ 1848204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_ATA) { 1849204220Smav struct ccb_trans_settings_ata *ata = 1850204220Smav &cts.xport_specific.ata; 1851204220Smav 1852204220Smav printf(" ("); 1853204220Smav if (ata->valid & CTS_ATA_VALID_MODE) 1854204220Smav printf("%s, ", ata_mode2string(ata->mode)); 1855204220Smav if ((ata->valid & CTS_ATA_VALID_ATAPI) && ata->atapi != 0) 1856204220Smav printf("ATAPI %dbytes, ", ata->atapi); 1857204220Smav if (ata->valid & CTS_ATA_VALID_BYTECOUNT) 1858204220Smav printf("PIO %dbytes", ata->bytecount); 1859204220Smav printf(")"); 1860204220Smav } 1861204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SATA) { 1862204220Smav struct ccb_trans_settings_sata *sata = 1863204220Smav &cts.xport_specific.sata; 1864204220Smav 1865204220Smav printf(" ("); 1866204220Smav if (sata->valid & CTS_SATA_VALID_REVISION) 1867204220Smav printf("SATA %d.x, ", sata->revision); 1868204220Smav else 1869204220Smav printf("SATA, "); 1870204220Smav if (sata->valid & CTS_SATA_VALID_MODE) 1871204220Smav printf("%s, ", ata_mode2string(sata->mode)); 1872204220Smav if ((sata->valid & CTS_ATA_VALID_ATAPI) && sata->atapi != 0) 1873204220Smav printf("ATAPI %dbytes, ", sata->atapi); 1874204220Smav if (sata->valid & CTS_SATA_VALID_BYTECOUNT) 1875204220Smav printf("PIO %dbytes", sata->bytecount); 1876204220Smav printf(")"); 1877204220Smav } 1878204220Smav printf("\n"); 1879204220Smav} 1880204220Smav 1881