ata_xpt.c revision 220886
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 220886 2011-04-20 13:27:50Z 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, 90220602Smav PROBE_SETAN, 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", 102203421Smav "PROBE_SPINUP", 103195534Sscottl "PROBE_SETMODE", 104207499Smav "PROBE_SETPM", 105207499Smav "PROBE_SETAPST", 106207499Smav "PROBE_SETDMAAA", 107220602Smav "PROBE_SETAN", 108198708Smav "PROBE_SET_MULTI", 109195534Sscottl "PROBE_INQUIRY", 110195534Sscottl "PROBE_FULL_INQUIRY", 111195534Sscottl "PROBE_PM_PID", 112195534Sscottl "PROBE_PM_PRV", 113195534Sscottl "PROBE_INVALID" 114195534Sscottl}; 115195534Sscottl 116195534Sscottl#define PROBE_SET_ACTION(softc, newaction) \ 117195534Sscottldo { \ 118195534Sscottl char **text; \ 119195534Sscottl text = probe_action_text; \ 120195534Sscottl CAM_DEBUG((softc)->periph->path, CAM_DEBUG_INFO, \ 121195534Sscottl ("Probe %s to %s\n", text[(softc)->action], \ 122195534Sscottl text[(newaction)])); \ 123195534Sscottl (softc)->action = (newaction); \ 124195534Sscottl} while(0) 125195534Sscottl 126195534Sscottltypedef enum { 127195534Sscottl PROBE_NO_ANNOUNCE = 0x04 128195534Sscottl} probe_flags; 129195534Sscottl 130195534Sscottltypedef struct { 131195534Sscottl TAILQ_HEAD(, ccb_hdr) request_ccbs; 132203385Smav struct ata_params ident_data; 133195534Sscottl probe_action action; 134195534Sscottl probe_flags flags; 135195534Sscottl uint32_t pm_pid; 136195534Sscottl uint32_t pm_prv; 137203108Smav int restart; 138203421Smav int spinup; 139209744Smav int faults; 140207499Smav u_int caps; 141195534Sscottl struct cam_periph *periph; 142195534Sscottl} probe_softc; 143195534Sscottl 144199178Smavstatic struct ata_quirk_entry ata_quirk_table[] = 145195534Sscottl{ 146195534Sscottl { 147195534Sscottl /* Default tagged queuing parameters for all devices */ 148195534Sscottl { 149195534Sscottl T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED, 150195534Sscottl /*vendor*/"*", /*product*/"*", /*revision*/"*" 151195534Sscottl }, 152199178Smav /*quirks*/0, /*maxtags*/0 153195534Sscottl }, 154195534Sscottl}; 155195534Sscottl 156199178Smavstatic const int ata_quirk_table_size = 157199178Smav sizeof(ata_quirk_table) / sizeof(*ata_quirk_table); 158195534Sscottl 159195534Sscottlstatic cam_status proberegister(struct cam_periph *periph, 160195534Sscottl void *arg); 161195534Sscottlstatic void probeschedule(struct cam_periph *probe_periph); 162195534Sscottlstatic void probestart(struct cam_periph *periph, union ccb *start_ccb); 163195534Sscottl//static void proberequestdefaultnegotiation(struct cam_periph *periph); 164195534Sscottl//static int proberequestbackoff(struct cam_periph *periph, 165195534Sscottl// struct cam_ed *device); 166195534Sscottlstatic void probedone(struct cam_periph *periph, union ccb *done_ccb); 167195534Sscottlstatic void probecleanup(struct cam_periph *periph); 168199178Smavstatic void ata_find_quirk(struct cam_ed *device); 169195534Sscottlstatic void ata_scan_bus(struct cam_periph *periph, union ccb *ccb); 170195534Sscottlstatic void ata_scan_lun(struct cam_periph *periph, 171195534Sscottl struct cam_path *path, cam_flags flags, 172195534Sscottl union ccb *ccb); 173195534Sscottlstatic void xptscandone(struct cam_periph *periph, union ccb *done_ccb); 174195534Sscottlstatic struct cam_ed * 175195534Sscottl ata_alloc_device(struct cam_eb *bus, struct cam_et *target, 176195534Sscottl lun_id_t lun_id); 177195534Sscottlstatic void ata_device_transport(struct cam_path *path); 178199178Smavstatic void ata_set_transfer_settings(struct ccb_trans_settings *cts, 179195534Sscottl struct cam_ed *device, 180195534Sscottl int async_update); 181195534Sscottlstatic void ata_dev_async(u_int32_t async_code, 182195534Sscottl struct cam_eb *bus, 183195534Sscottl struct cam_et *target, 184195534Sscottl struct cam_ed *device, 185195534Sscottl void *async_arg); 186195534Sscottlstatic void ata_action(union ccb *start_ccb); 187204220Smavstatic void ata_announce_periph(struct cam_periph *periph); 188195534Sscottl 189195534Sscottlstatic struct xpt_xport ata_xport = { 190195534Sscottl .alloc_device = ata_alloc_device, 191195534Sscottl .action = ata_action, 192195534Sscottl .async = ata_dev_async, 193204220Smav .announce = ata_announce_periph, 194195534Sscottl}; 195195534Sscottl 196195534Sscottlstruct xpt_xport * 197195534Sscottlata_get_xport(void) 198195534Sscottl{ 199195534Sscottl return (&ata_xport); 200195534Sscottl} 201195534Sscottl 202195534Sscottlstatic void 203195534Sscottlprobe_periph_init() 204195534Sscottl{ 205195534Sscottl} 206195534Sscottl 207195534Sscottlstatic cam_status 208195534Sscottlproberegister(struct cam_periph *periph, void *arg) 209195534Sscottl{ 210195534Sscottl union ccb *request_ccb; /* CCB representing the probe request */ 211195534Sscottl cam_status status; 212195534Sscottl probe_softc *softc; 213195534Sscottl 214195534Sscottl request_ccb = (union ccb *)arg; 215195534Sscottl if (periph == NULL) { 216195534Sscottl printf("proberegister: periph was NULL!!\n"); 217195534Sscottl return(CAM_REQ_CMP_ERR); 218195534Sscottl } 219195534Sscottl 220195534Sscottl if (request_ccb == NULL) { 221195534Sscottl printf("proberegister: no probe CCB, " 222195534Sscottl "can't register device\n"); 223195534Sscottl return(CAM_REQ_CMP_ERR); 224195534Sscottl } 225195534Sscottl 226203421Smav softc = (probe_softc *)malloc(sizeof(*softc), M_CAMXPT, M_ZERO | M_NOWAIT); 227195534Sscottl 228195534Sscottl if (softc == NULL) { 229195534Sscottl printf("proberegister: Unable to probe new device. " 230195534Sscottl "Unable to allocate softc\n"); 231195534Sscottl return(CAM_REQ_CMP_ERR); 232195534Sscottl } 233195534Sscottl TAILQ_INIT(&softc->request_ccbs); 234195534Sscottl TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h, 235195534Sscottl periph_links.tqe); 236195534Sscottl softc->flags = 0; 237195534Sscottl periph->softc = softc; 238195534Sscottl softc->periph = periph; 239195534Sscottl softc->action = PROBE_INVALID; 240195534Sscottl status = cam_periph_acquire(periph); 241195534Sscottl if (status != CAM_REQ_CMP) { 242195534Sscottl return (status); 243195534Sscottl } 244195534Sscottl /* 245203108Smav * Ensure nobody slip in until probe finish. 246195534Sscottl */ 247203108Smav cam_freeze_devq_arg(periph->path, 248203108Smav RELSIM_RELEASE_RUNLEVEL, CAM_RL_XPT + 1); 249195534Sscottl probeschedule(periph); 250195534Sscottl return(CAM_REQ_CMP); 251195534Sscottl} 252195534Sscottl 253195534Sscottlstatic void 254195534Sscottlprobeschedule(struct cam_periph *periph) 255195534Sscottl{ 256195534Sscottl union ccb *ccb; 257195534Sscottl probe_softc *softc; 258195534Sscottl 259195534Sscottl softc = (probe_softc *)periph->softc; 260195534Sscottl ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs); 261195534Sscottl 262198389Smav if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) || 263198389Smav periph->path->device->protocol == PROTO_SATAPM) 264195534Sscottl PROBE_SET_ACTION(softc, PROBE_RESET); 265195534Sscottl else 266195534Sscottl PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 267195534Sscottl 268195534Sscottl if (ccb->crcn.flags & CAM_EXPECT_INQ_CHANGE) 269195534Sscottl softc->flags |= PROBE_NO_ANNOUNCE; 270195534Sscottl else 271195534Sscottl softc->flags &= ~PROBE_NO_ANNOUNCE; 272195534Sscottl 273203108Smav xpt_schedule(periph, CAM_PRIORITY_XPT); 274195534Sscottl} 275195534Sscottl 276195534Sscottlstatic void 277195534Sscottlprobestart(struct cam_periph *periph, union ccb *start_ccb) 278195534Sscottl{ 279199747Smav struct ccb_trans_settings cts; 280195534Sscottl struct ccb_ataio *ataio; 281195534Sscottl struct ccb_scsiio *csio; 282195534Sscottl probe_softc *softc; 283198708Smav struct cam_path *path; 284198708Smav struct ata_params *ident_buf; 285195534Sscottl 286195534Sscottl CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probestart\n")); 287195534Sscottl 288195534Sscottl softc = (probe_softc *)periph->softc; 289198708Smav path = start_ccb->ccb_h.path; 290195534Sscottl ataio = &start_ccb->ataio; 291195534Sscottl csio = &start_ccb->csio; 292198708Smav ident_buf = &periph->path->device->ident_data; 293195534Sscottl 294203108Smav if (softc->restart) { 295203108Smav softc->restart = 0; 296203108Smav if ((path->device->flags & CAM_DEV_UNCONFIGURED) || 297203108Smav path->device->protocol == PROTO_SATAPM) 298203108Smav softc->action = PROBE_RESET; 299203108Smav else 300203108Smav softc->action = PROBE_IDENTIFY; 301203108Smav } 302195534Sscottl switch (softc->action) { 303195534Sscottl case PROBE_RESET: 304195534Sscottl cam_fill_ataio(ataio, 305195534Sscottl 0, 306195534Sscottl probedone, 307195534Sscottl /*flags*/CAM_DIR_NONE, 308198389Smav 0, 309195534Sscottl /*data_ptr*/NULL, 310195534Sscottl /*dxfer_len*/0, 311203108Smav 15 * 1000); 312195534Sscottl ata_reset_cmd(ataio); 313195534Sscottl break; 314195534Sscottl case PROBE_IDENTIFY: 315195534Sscottl cam_fill_ataio(ataio, 316195534Sscottl 1, 317195534Sscottl probedone, 318195534Sscottl /*flags*/CAM_DIR_IN, 319198389Smav 0, 320203385Smav /*data_ptr*/(u_int8_t *)&softc->ident_data, 321203385Smav /*dxfer_len*/sizeof(softc->ident_data), 322195534Sscottl 30 * 1000); 323195534Sscottl if (periph->path->device->protocol == PROTO_ATA) 324196659Smav ata_28bit_cmd(ataio, ATA_ATA_IDENTIFY, 0, 0, 0); 325195534Sscottl else 326196659Smav ata_28bit_cmd(ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0); 327195534Sscottl break; 328203421Smav case PROBE_SPINUP: 329203421Smav if (bootverbose) 330203421Smav xpt_print(path, "Spinning up device\n"); 331203421Smav cam_fill_ataio(ataio, 332203421Smav 1, 333203421Smav probedone, 334203421Smav /*flags*/CAM_DIR_NONE | CAM_HIGH_POWER, 335203421Smav 0, 336203421Smav /*data_ptr*/NULL, 337203421Smav /*dxfer_len*/0, 338203421Smav 30 * 1000); 339203421Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_PUIS_SPINUP, 0, 0); 340203421Smav break; 341195534Sscottl case PROBE_SETMODE: 342199747Smav { 343199747Smav int mode, wantmode; 344199747Smav 345199747Smav mode = 0; 346199747Smav /* Fetch user modes from SIM. */ 347199747Smav bzero(&cts, sizeof(cts)); 348203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 349199747Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 350199747Smav cts.type = CTS_TYPE_USER_SETTINGS; 351199747Smav xpt_action((union ccb *)&cts); 352199747Smav if (path->device->transport == XPORT_ATA) { 353199747Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_MODE) 354199747Smav mode = cts.xport_specific.ata.mode; 355199747Smav } else { 356199799Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_MODE) 357199747Smav mode = cts.xport_specific.sata.mode; 358199747Smav } 359199747Smavnegotiate: 360199747Smav /* Honor device capabilities. */ 361199747Smav wantmode = mode = ata_max_mode(ident_buf, mode); 362199747Smav /* Report modes to SIM. */ 363199747Smav bzero(&cts, sizeof(cts)); 364203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 365199747Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 366199747Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 367199747Smav if (path->device->transport == XPORT_ATA) { 368199747Smav cts.xport_specific.ata.mode = mode; 369199747Smav cts.xport_specific.ata.valid = CTS_ATA_VALID_MODE; 370199747Smav } else { 371199747Smav cts.xport_specific.sata.mode = mode; 372199747Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_MODE; 373199747Smav } 374199747Smav xpt_action((union ccb *)&cts); 375200171Smav /* Fetch current modes from SIM. */ 376199747Smav bzero(&cts, sizeof(cts)); 377203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 378199747Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 379199747Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 380199747Smav xpt_action((union ccb *)&cts); 381199747Smav if (path->device->transport == XPORT_ATA) { 382199747Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_MODE) 383199747Smav mode = cts.xport_specific.ata.mode; 384199747Smav } else { 385199747Smav if (cts.xport_specific.ata.valid & CTS_SATA_VALID_MODE) 386199747Smav mode = cts.xport_specific.sata.mode; 387199747Smav } 388199747Smav /* If SIM disagree - renegotiate. */ 389199747Smav if (mode != wantmode) 390199747Smav goto negotiate; 391220886Smav /* Remember what transport thinks about DMA. */ 392220886Smav if (mode < ATA_DMA) 393220886Smav path->device->inq_flags &= ~SID_DMA; 394220886Smav else 395220886Smav path->device->inq_flags |= SID_DMA; 396195534Sscottl cam_fill_ataio(ataio, 397195534Sscottl 1, 398195534Sscottl probedone, 399196353Smav /*flags*/CAM_DIR_NONE, 400196353Smav 0, 401196353Smav /*data_ptr*/NULL, 402196353Smav /*dxfer_len*/0, 403195534Sscottl 30 * 1000); 404199747Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); 405195534Sscottl break; 406199747Smav } 407207499Smav case PROBE_SETPM: 408207499Smav cam_fill_ataio(ataio, 409207499Smav 1, 410207499Smav probedone, 411207499Smav CAM_DIR_NONE, 412207499Smav 0, 413207499Smav NULL, 414207499Smav 0, 415207499Smav 30*1000); 416207499Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, 417207499Smav (softc->caps & CTS_SATA_CAPS_H_PMREQ) ? 0x10 : 0x90, 418207499Smav 0, 0x03); 419207499Smav break; 420207499Smav case PROBE_SETAPST: 421207499Smav cam_fill_ataio(ataio, 422207499Smav 1, 423207499Smav probedone, 424207499Smav CAM_DIR_NONE, 425207499Smav 0, 426207499Smav NULL, 427207499Smav 0, 428207499Smav 30*1000); 429207499Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, 430207499Smav (softc->caps & CTS_SATA_CAPS_H_APST) ? 0x10 : 0x90, 431207499Smav 0, 0x07); 432207499Smav break; 433207499Smav case PROBE_SETDMAAA: 434207499Smav cam_fill_ataio(ataio, 435207499Smav 1, 436207499Smav probedone, 437207499Smav CAM_DIR_NONE, 438207499Smav 0, 439207499Smav NULL, 440207499Smav 0, 441207499Smav 30*1000); 442207499Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, 443207499Smav (softc->caps & CTS_SATA_CAPS_H_DMAAA) ? 0x10 : 0x90, 444207499Smav 0, 0x02); 445207499Smav break; 446220602Smav case PROBE_SETAN: 447220602Smav cam_fill_ataio(ataio, 448220602Smav 1, 449220602Smav probedone, 450220602Smav CAM_DIR_NONE, 451220602Smav 0, 452220602Smav NULL, 453220602Smav 0, 454220602Smav 30*1000); 455220602Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, 456220602Smav (softc->caps & CTS_SATA_CAPS_H_AN) ? 0x10 : 0x90, 457220602Smav 0, 0x05); 458220602Smav break; 459198708Smav case PROBE_SET_MULTI: 460198708Smav { 461200171Smav u_int sectors, bytecount; 462198708Smav 463200171Smav bytecount = 8192; /* SATA maximum */ 464200171Smav /* Fetch user bytecount from SIM. */ 465200171Smav bzero(&cts, sizeof(cts)); 466203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 467200171Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 468200171Smav cts.type = CTS_TYPE_USER_SETTINGS; 469200171Smav xpt_action((union ccb *)&cts); 470200171Smav if (path->device->transport == XPORT_ATA) { 471200171Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 472200171Smav bytecount = cts.xport_specific.ata.bytecount; 473200171Smav } else { 474200171Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 475200171Smav bytecount = cts.xport_specific.sata.bytecount; 476200171Smav } 477200171Smav /* Honor device capabilities. */ 478200171Smav sectors = max(1, min(ident_buf->sectors_intr & 0xff, 479200171Smav bytecount / ata_logical_sector_size(ident_buf))); 480198708Smav /* Report bytecount to SIM. */ 481198708Smav bzero(&cts, sizeof(cts)); 482203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 483198708Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 484198708Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 485198708Smav if (path->device->transport == XPORT_ATA) { 486198897Smav cts.xport_specific.ata.bytecount = sectors * 487198897Smav ata_logical_sector_size(ident_buf); 488198708Smav cts.xport_specific.ata.valid = CTS_ATA_VALID_BYTECOUNT; 489198708Smav } else { 490198897Smav cts.xport_specific.sata.bytecount = sectors * 491198897Smav ata_logical_sector_size(ident_buf); 492198708Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_BYTECOUNT; 493198708Smav } 494198708Smav xpt_action((union ccb *)&cts); 495200171Smav /* Fetch current bytecount from SIM. */ 496200171Smav bzero(&cts, sizeof(cts)); 497203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 498200171Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 499200171Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 500200171Smav xpt_action((union ccb *)&cts); 501200171Smav if (path->device->transport == XPORT_ATA) { 502200171Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 503200171Smav bytecount = cts.xport_specific.ata.bytecount; 504200171Smav } else { 505200171Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 506200171Smav bytecount = cts.xport_specific.sata.bytecount; 507200171Smav } 508200171Smav sectors = bytecount / ata_logical_sector_size(ident_buf); 509198708Smav 510198708Smav cam_fill_ataio(ataio, 511198708Smav 1, 512198708Smav probedone, 513198708Smav CAM_DIR_NONE, 514198708Smav 0, 515198708Smav NULL, 516198708Smav 0, 517198708Smav 30*1000); 518198708Smav ata_28bit_cmd(ataio, ATA_SET_MULTI, 0, 0, sectors); 519198708Smav break; 520195534Sscottl } 521195534Sscottl case PROBE_INQUIRY: 522200171Smav { 523200171Smav u_int bytecount; 524200171Smav 525200171Smav bytecount = 8192; /* SATA maximum */ 526200171Smav /* Fetch user bytecount from SIM. */ 527200171Smav bzero(&cts, sizeof(cts)); 528203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 529200171Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 530200171Smav cts.type = CTS_TYPE_USER_SETTINGS; 531200171Smav xpt_action((union ccb *)&cts); 532200171Smav if (path->device->transport == XPORT_ATA) { 533200171Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 534200171Smav bytecount = cts.xport_specific.ata.bytecount; 535200171Smav } else { 536200171Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 537200171Smav bytecount = cts.xport_specific.sata.bytecount; 538200171Smav } 539200171Smav /* Honor device capabilities. */ 540200171Smav bytecount &= ~1; 541200171Smav bytecount = max(2, min(65534, bytecount)); 542200171Smav if (ident_buf->satacapabilities != 0x0000 && 543200171Smav ident_buf->satacapabilities != 0xffff) { 544200171Smav bytecount = min(8192, bytecount); 545200171Smav } 546200171Smav /* Report bytecount to SIM. */ 547200171Smav bzero(&cts, sizeof(cts)); 548203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 549200171Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 550200171Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 551200171Smav if (path->device->transport == XPORT_ATA) { 552200171Smav cts.xport_specific.ata.bytecount = bytecount; 553200171Smav cts.xport_specific.ata.valid = CTS_ATA_VALID_BYTECOUNT; 554200171Smav } else { 555200171Smav cts.xport_specific.sata.bytecount = bytecount; 556200171Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_BYTECOUNT; 557200171Smav } 558200171Smav xpt_action((union ccb *)&cts); 559200171Smav /* FALLTHROUGH */ 560200171Smav } 561195534Sscottl case PROBE_FULL_INQUIRY: 562195534Sscottl { 563195534Sscottl u_int inquiry_len; 564195534Sscottl struct scsi_inquiry_data *inq_buf = 565195534Sscottl &periph->path->device->inq_data; 566195534Sscottl 567195534Sscottl if (softc->action == PROBE_INQUIRY) 568195534Sscottl inquiry_len = SHORT_INQUIRY_LENGTH; 569195534Sscottl else 570195534Sscottl inquiry_len = SID_ADDITIONAL_LENGTH(inq_buf); 571195534Sscottl /* 572195534Sscottl * Some parallel SCSI devices fail to send an 573195534Sscottl * ignore wide residue message when dealing with 574195534Sscottl * odd length inquiry requests. Round up to be 575195534Sscottl * safe. 576195534Sscottl */ 577195534Sscottl inquiry_len = roundup2(inquiry_len, 2); 578195534Sscottl scsi_inquiry(csio, 579195534Sscottl /*retries*/1, 580195534Sscottl probedone, 581195534Sscottl MSG_SIMPLE_Q_TAG, 582195534Sscottl (u_int8_t *)inq_buf, 583195534Sscottl inquiry_len, 584195534Sscottl /*evpd*/FALSE, 585195534Sscottl /*page_code*/0, 586195534Sscottl SSD_MIN_SIZE, 587195534Sscottl /*timeout*/60 * 1000); 588195534Sscottl break; 589195534Sscottl } 590195534Sscottl case PROBE_PM_PID: 591195534Sscottl cam_fill_ataio(ataio, 592195534Sscottl 1, 593195534Sscottl probedone, 594195534Sscottl /*flags*/CAM_DIR_NONE, 595198389Smav 0, 596195534Sscottl /*data_ptr*/NULL, 597195534Sscottl /*dxfer_len*/0, 598195534Sscottl 10 * 1000); 599195534Sscottl ata_pm_read_cmd(ataio, 0, 15); 600195534Sscottl break; 601195534Sscottl case PROBE_PM_PRV: 602195534Sscottl cam_fill_ataio(ataio, 603195534Sscottl 1, 604195534Sscottl probedone, 605195534Sscottl /*flags*/CAM_DIR_NONE, 606198389Smav 0, 607195534Sscottl /*data_ptr*/NULL, 608195534Sscottl /*dxfer_len*/0, 609195534Sscottl 10 * 1000); 610195534Sscottl ata_pm_read_cmd(ataio, 1, 15); 611195534Sscottl break; 612195534Sscottl case PROBE_INVALID: 613198708Smav CAM_DEBUG(path, CAM_DEBUG_INFO, 614195534Sscottl ("probestart: invalid action state\n")); 615195534Sscottl default: 616195534Sscottl break; 617195534Sscottl } 618195534Sscottl xpt_action(start_ccb); 619195534Sscottl} 620195534Sscottl#if 0 621195534Sscottlstatic void 622195534Sscottlproberequestdefaultnegotiation(struct cam_periph *periph) 623195534Sscottl{ 624195534Sscottl struct ccb_trans_settings cts; 625195534Sscottl 626203108Smav xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE); 627195534Sscottl cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 628195534Sscottl cts.type = CTS_TYPE_USER_SETTINGS; 629195534Sscottl xpt_action((union ccb *)&cts); 630195534Sscottl if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 631195534Sscottl return; 632195534Sscottl } 633195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 634195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 635195534Sscottl xpt_action((union ccb *)&cts); 636195534Sscottl} 637195534Sscottl 638195534Sscottl/* 639195534Sscottl * Backoff Negotiation Code- only pertinent for SPI devices. 640195534Sscottl */ 641195534Sscottlstatic int 642195534Sscottlproberequestbackoff(struct cam_periph *periph, struct cam_ed *device) 643195534Sscottl{ 644195534Sscottl struct ccb_trans_settings cts; 645195534Sscottl struct ccb_trans_settings_spi *spi; 646195534Sscottl 647195534Sscottl memset(&cts, 0, sizeof (cts)); 648203108Smav xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE); 649195534Sscottl cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 650195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 651195534Sscottl xpt_action((union ccb *)&cts); 652195534Sscottl if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 653195534Sscottl if (bootverbose) { 654195534Sscottl xpt_print(periph->path, 655195534Sscottl "failed to get current device settings\n"); 656195534Sscottl } 657195534Sscottl return (0); 658195534Sscottl } 659195534Sscottl if (cts.transport != XPORT_SPI) { 660195534Sscottl if (bootverbose) { 661195534Sscottl xpt_print(periph->path, "not SPI transport\n"); 662195534Sscottl } 663195534Sscottl return (0); 664195534Sscottl } 665195534Sscottl spi = &cts.xport_specific.spi; 666195534Sscottl 667195534Sscottl /* 668195534Sscottl * We cannot renegotiate sync rate if we don't have one. 669195534Sscottl */ 670195534Sscottl if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) { 671195534Sscottl if (bootverbose) { 672195534Sscottl xpt_print(periph->path, "no sync rate known\n"); 673195534Sscottl } 674195534Sscottl return (0); 675195534Sscottl } 676195534Sscottl 677195534Sscottl /* 678195534Sscottl * We'll assert that we don't have to touch PPR options- the 679195534Sscottl * SIM will see what we do with period and offset and adjust 680195534Sscottl * the PPR options as appropriate. 681195534Sscottl */ 682195534Sscottl 683195534Sscottl /* 684195534Sscottl * A sync rate with unknown or zero offset is nonsensical. 685195534Sscottl * A sync period of zero means Async. 686195534Sscottl */ 687195534Sscottl if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0 688195534Sscottl || spi->sync_offset == 0 || spi->sync_period == 0) { 689195534Sscottl if (bootverbose) { 690195534Sscottl xpt_print(periph->path, "no sync rate available\n"); 691195534Sscottl } 692195534Sscottl return (0); 693195534Sscottl } 694195534Sscottl 695195534Sscottl if (device->flags & CAM_DEV_DV_HIT_BOTTOM) { 696195534Sscottl CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 697195534Sscottl ("hit async: giving up on DV\n")); 698195534Sscottl return (0); 699195534Sscottl } 700195534Sscottl 701195534Sscottl 702195534Sscottl /* 703195534Sscottl * Jump sync_period up by one, but stop at 5MHz and fall back to Async. 704195534Sscottl * We don't try to remember 'last' settings to see if the SIM actually 705195534Sscottl * gets into the speed we want to set. We check on the SIM telling 706195534Sscottl * us that a requested speed is bad, but otherwise don't try and 707195534Sscottl * check the speed due to the asynchronous and handshake nature 708195534Sscottl * of speed setting. 709195534Sscottl */ 710195534Sscottl spi->valid = CTS_SPI_VALID_SYNC_RATE | CTS_SPI_VALID_SYNC_OFFSET; 711195534Sscottl for (;;) { 712195534Sscottl spi->sync_period++; 713195534Sscottl if (spi->sync_period >= 0xf) { 714195534Sscottl spi->sync_period = 0; 715195534Sscottl spi->sync_offset = 0; 716195534Sscottl CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 717195534Sscottl ("setting to async for DV\n")); 718195534Sscottl /* 719195534Sscottl * Once we hit async, we don't want to try 720195534Sscottl * any more settings. 721195534Sscottl */ 722195534Sscottl device->flags |= CAM_DEV_DV_HIT_BOTTOM; 723195534Sscottl } else if (bootverbose) { 724195534Sscottl CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 725195534Sscottl ("DV: period 0x%x\n", spi->sync_period)); 726195534Sscottl printf("setting period to 0x%x\n", spi->sync_period); 727195534Sscottl } 728195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 729195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 730195534Sscottl xpt_action((union ccb *)&cts); 731195534Sscottl if ((cts.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { 732195534Sscottl break; 733195534Sscottl } 734195534Sscottl CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 735195534Sscottl ("DV: failed to set period 0x%x\n", spi->sync_period)); 736195534Sscottl if (spi->sync_period == 0) { 737195534Sscottl return (0); 738195534Sscottl } 739195534Sscottl } 740195534Sscottl return (1); 741195534Sscottl} 742195534Sscottl#endif 743195534Sscottlstatic void 744195534Sscottlprobedone(struct cam_periph *periph, union ccb *done_ccb) 745195534Sscottl{ 746199747Smav struct ccb_trans_settings cts; 747195534Sscottl struct ata_params *ident_buf; 748195534Sscottl probe_softc *softc; 749195534Sscottl struct cam_path *path; 750217444Smav cam_status status; 751195534Sscottl u_int32_t priority; 752207499Smav u_int caps; 753198389Smav int found = 1; 754195534Sscottl 755195534Sscottl CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probedone\n")); 756195534Sscottl 757195534Sscottl softc = (probe_softc *)periph->softc; 758195534Sscottl path = done_ccb->ccb_h.path; 759195534Sscottl priority = done_ccb->ccb_h.pinfo.priority; 760195534Sscottl ident_buf = &path->device->ident_data; 761195534Sscottl 762198708Smav if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 763209744Smav if (softc->restart) { 764209744Smav if (bootverbose) { 765209744Smav cam_error_print(done_ccb, 766209744Smav CAM_ESF_ALL, CAM_EPF_ALL); 767209744Smav } 768209744Smav } else if (cam_periph_error(done_ccb, 0, 0, NULL) == ERESTART) 769195534Sscottl return; 770209744Smav if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 771195534Sscottl /* Don't wedge the queue */ 772195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 773195534Sscottl /*run_queue*/TRUE); 774195534Sscottl } 775217444Smav status = done_ccb->ccb_h.status & CAM_STATUS_MASK; 776209744Smav if (softc->restart) { 777209744Smav softc->faults++; 778209744Smav if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == 779209744Smav CAM_CMD_TIMEOUT) 780209744Smav softc->faults += 4; 781209744Smav if (softc->faults < 10) 782209744Smav goto done; 783209744Smav else 784209744Smav softc->restart = 0; 785217444Smav 786198708Smav /* Old PIO2 devices may not support mode setting. */ 787217444Smav } else if (softc->action == PROBE_SETMODE && 788217444Smav status == CAM_ATA_STATUS_ERROR && 789198708Smav ata_max_pmode(ident_buf) <= ATA_PIO2 && 790217444Smav (ident_buf->capabilities1 & ATA_SUPPORT_IORDY) == 0) { 791198708Smav goto noerror; 792217444Smav 793198708Smav /* 794217444Smav * Some old WD SATA disks report supported and enabled 795217444Smav * device-initiated interface power management, but return 796217444Smav * ABORT on attempt to disable it. 797217444Smav */ 798217444Smav } else if (softc->action == PROBE_SETPM && 799217444Smav status == CAM_ATA_STATUS_ERROR) { 800217444Smav goto noerror; 801217875Smav 802217875Smav /* 803217875Smav * Some HP SATA disks report supported DMA Auto-Activation, 804217875Smav * but return ABORT on attempt to enable it. 805217875Smav */ 806217875Smav } else if (softc->action == PROBE_SETDMAAA && 807217875Smav status == CAM_ATA_STATUS_ERROR) { 808217875Smav goto noerror; 809217444Smav } 810217444Smav 811217444Smav /* 812198708Smav * If we get to this point, we got an error status back 813198708Smav * from the inquiry and the error status doesn't require 814198708Smav * automatically retrying the command. Therefore, the 815198708Smav * inquiry failed. If we had inquiry information before 816198708Smav * for this device, but this latest inquiry command failed, 817198708Smav * the device has probably gone away. If this device isn't 818198708Smav * already marked unconfigured, notify the peripheral 819198708Smav * drivers that this device is no more. 820198708Smav */ 821209744Smavdevice_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0) 822198708Smav xpt_async(AC_LOST_DEVICE, path, NULL); 823198708Smav found = 0; 824198708Smav goto done; 825198708Smav } 826198708Smavnoerror: 827203385Smav if (softc->restart) 828203385Smav goto done; 829198708Smav switch (softc->action) { 830198708Smav case PROBE_RESET: 831195534Sscottl { 832198708Smav int sign = (done_ccb->ataio.res.lba_high << 8) + 833198708Smav done_ccb->ataio.res.lba_mid; 834200218Smav if (bootverbose) 835200218Smav xpt_print(path, "SIGNATURE: %04x\n", sign); 836198708Smav if (sign == 0x0000 && 837198708Smav done_ccb->ccb_h.target_id != 15) { 838198708Smav path->device->protocol = PROTO_ATA; 839198708Smav PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 840198708Smav } else if (sign == 0x9669 && 841198708Smav done_ccb->ccb_h.target_id == 15) { 842199747Smav /* Report SIM that PM is present. */ 843198708Smav bzero(&cts, sizeof(cts)); 844203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 845198708Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 846198708Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 847198708Smav cts.xport_specific.sata.pm_present = 1; 848198708Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; 849198708Smav xpt_action((union ccb *)&cts); 850198708Smav path->device->protocol = PROTO_SATAPM; 851198708Smav PROBE_SET_ACTION(softc, PROBE_PM_PID); 852198708Smav } else if (sign == 0xeb14 && 853198708Smav done_ccb->ccb_h.target_id != 15) { 854198708Smav path->device->protocol = PROTO_SCSI; 855198708Smav PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 856198708Smav } else { 857198708Smav if (done_ccb->ccb_h.target_id != 15) { 858198708Smav xpt_print(path, 859198708Smav "Unexpected signature 0x%04x\n", sign); 860195534Sscottl } 861198708Smav goto device_fail; 862198708Smav } 863198708Smav xpt_release_ccb(done_ccb); 864198708Smav xpt_schedule(periph, priority); 865198708Smav return; 866198708Smav } 867198708Smav case PROBE_IDENTIFY: 868198708Smav { 869207222Smav struct ccb_pathinq cpi; 870198708Smav int16_t *ptr; 871207282Smav int changed = 1; 872195534Sscottl 873203385Smav ident_buf = &softc->ident_data; 874198708Smav for (ptr = (int16_t *)ident_buf; 875198708Smav ptr < (int16_t *)ident_buf + sizeof(struct ata_params)/2; ptr++) { 876198708Smav *ptr = le16toh(*ptr); 877198708Smav } 878198708Smav if (strncmp(ident_buf->model, "FX", 2) && 879198708Smav strncmp(ident_buf->model, "NEC", 3) && 880198708Smav strncmp(ident_buf->model, "Pioneer", 7) && 881198708Smav strncmp(ident_buf->model, "SHARP", 5)) { 882198708Smav ata_bswap(ident_buf->model, sizeof(ident_buf->model)); 883198708Smav ata_bswap(ident_buf->revision, sizeof(ident_buf->revision)); 884198708Smav ata_bswap(ident_buf->serial, sizeof(ident_buf->serial)); 885198708Smav } 886198708Smav ata_btrim(ident_buf->model, sizeof(ident_buf->model)); 887198708Smav ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model)); 888198708Smav ata_btrim(ident_buf->revision, sizeof(ident_buf->revision)); 889198708Smav ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision)); 890198708Smav ata_btrim(ident_buf->serial, sizeof(ident_buf->serial)); 891198708Smav ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial)); 892203421Smav /* Device may need spin-up before IDENTIFY become valid. */ 893204354Smav if ((ident_buf->specconf == 0x37c8 || 894204354Smav ident_buf->specconf == 0x738c) && 895204354Smav ((ident_buf->config & ATA_RESP_INCOMPLETE) || 896204354Smav softc->spinup == 0)) { 897203421Smav PROBE_SET_ACTION(softc, PROBE_SPINUP); 898203421Smav xpt_release_ccb(done_ccb); 899203421Smav xpt_schedule(periph, priority); 900203421Smav return; 901203421Smav } 902203385Smav ident_buf = &path->device->ident_data; 903198708Smav if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) { 904198708Smav /* Check that it is the same device. */ 905203385Smav if (bcmp(softc->ident_data.model, ident_buf->model, 906203385Smav sizeof(ident_buf->model)) || 907203385Smav bcmp(softc->ident_data.revision, ident_buf->revision, 908203385Smav sizeof(ident_buf->revision)) || 909203385Smav bcmp(softc->ident_data.serial, ident_buf->serial, 910203385Smav sizeof(ident_buf->serial))) { 911198708Smav /* Device changed. */ 912198708Smav xpt_async(AC_LOST_DEVICE, path, NULL); 913207282Smav } else { 914203385Smav bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 915207282Smav changed = 0; 916207282Smav } 917207282Smav } 918207282Smav if (changed) { 919203385Smav bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 920195534Sscottl /* Clean up from previous instance of this device */ 921195534Sscottl if (path->device->serial_num != NULL) { 922195534Sscottl free(path->device->serial_num, M_CAMXPT); 923195534Sscottl path->device->serial_num = NULL; 924195534Sscottl path->device->serial_num_len = 0; 925195534Sscottl } 926195534Sscottl path->device->serial_num = 927195534Sscottl (u_int8_t *)malloc((sizeof(ident_buf->serial) + 1), 928198708Smav M_CAMXPT, M_NOWAIT); 929195534Sscottl if (path->device->serial_num != NULL) { 930195534Sscottl bcopy(ident_buf->serial, 931195534Sscottl path->device->serial_num, 932195534Sscottl sizeof(ident_buf->serial)); 933195534Sscottl path->device->serial_num[sizeof(ident_buf->serial)] 934195534Sscottl = '\0'; 935195534Sscottl path->device->serial_num_len = 936195534Sscottl strlen(path->device->serial_num); 937195534Sscottl } 938195534Sscottl 939198331Smav path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 940195534Sscottl } 941199178Smav if (ident_buf->satacapabilities & ATA_SUPPORT_NCQ) { 942199178Smav path->device->mintags = path->device->maxtags = 943199178Smav ATA_QUEUE_LEN(ident_buf->queue) + 1; 944199178Smav } 945199178Smav ata_find_quirk(path->device); 946199263Smav if (path->device->mintags != 0 && 947199263Smav path->bus->sim->max_tagged_dev_openings != 0) { 948207222Smav /* Check if the SIM does not want queued commands. */ 949207222Smav bzero(&cpi, sizeof(cpi)); 950207222Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 951207222Smav cpi.ccb_h.func_code = XPT_PATH_INQ; 952207222Smav xpt_action((union ccb *)&cpi); 953207222Smav if (cpi.ccb_h.status == CAM_REQ_CMP && 954207222Smav (cpi.hba_inquiry & PI_TAG_ABLE)) { 955207222Smav /* Report SIM which tags are allowed. */ 956207222Smav bzero(&cts, sizeof(cts)); 957207222Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 958207222Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 959207222Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 960207222Smav cts.xport_specific.sata.tags = path->device->maxtags; 961207222Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_TAGS; 962207222Smav xpt_action((union ccb *)&cts); 963207222Smav /* Reconfigure queues for tagged queueing. */ 964207222Smav xpt_start_tags(path); 965207222Smav } 966199178Smav } 967198708Smav ata_device_transport(path); 968198708Smav PROBE_SET_ACTION(softc, PROBE_SETMODE); 969195534Sscottl xpt_release_ccb(done_ccb); 970198708Smav xpt_schedule(periph, priority); 971198708Smav return; 972195534Sscottl } 973203421Smav case PROBE_SPINUP: 974203421Smav if (bootverbose) 975203421Smav xpt_print(path, "Spin-up done\n"); 976203421Smav softc->spinup = 1; 977203421Smav PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 978203421Smav xpt_release_ccb(done_ccb); 979203421Smav xpt_schedule(periph, priority); 980203421Smav return; 981195534Sscottl case PROBE_SETMODE: 982207499Smav if (path->device->transport != XPORT_SATA) 983207499Smav goto notsata; 984207499Smav /* Set supported bits. */ 985207499Smav bzero(&cts, sizeof(cts)); 986207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 987207499Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 988207499Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 989207499Smav xpt_action((union ccb *)&cts); 990207499Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 991207499Smav caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H; 992207499Smav else 993207499Smav caps = 0; 994207499Smav if (ident_buf->satacapabilities != 0xffff) { 995207499Smav if (ident_buf->satacapabilities & ATA_SUPPORT_IFPWRMNGTRCV) 996207499Smav caps |= CTS_SATA_CAPS_D_PMREQ; 997207499Smav if (ident_buf->satacapabilities & ATA_SUPPORT_HAPST) 998207499Smav caps |= CTS_SATA_CAPS_D_APST; 999207499Smav } 1000207499Smav /* Mask unwanted bits. */ 1001207499Smav bzero(&cts, sizeof(cts)); 1002207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1003207499Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1004207499Smav cts.type = CTS_TYPE_USER_SETTINGS; 1005207499Smav xpt_action((union ccb *)&cts); 1006207499Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1007207499Smav caps &= cts.xport_specific.sata.caps; 1008215454Smav else 1009215454Smav caps = 0; 1010207499Smav /* Store result to SIM. */ 1011207499Smav bzero(&cts, sizeof(cts)); 1012207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1013207499Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1014207499Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 1015207499Smav cts.xport_specific.sata.caps = caps; 1016207499Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS; 1017207499Smav xpt_action((union ccb *)&cts); 1018207499Smav softc->caps = caps; 1019217874Smav if ((ident_buf->satasupport & ATA_SUPPORT_IFPWRMNGT) && 1020217874Smav (!(softc->caps & CTS_SATA_CAPS_H_PMREQ)) != 1021217874Smav (!(ident_buf->sataenabled & ATA_SUPPORT_IFPWRMNGT))) { 1022207499Smav PROBE_SET_ACTION(softc, PROBE_SETPM); 1023207499Smav xpt_release_ccb(done_ccb); 1024207499Smav xpt_schedule(periph, priority); 1025207499Smav return; 1026207499Smav } 1027207499Smav /* FALLTHROUGH */ 1028207499Smav case PROBE_SETPM: 1029207499Smav if (ident_buf->satacapabilities != 0xffff && 1030217874Smav (ident_buf->satacapabilities & ATA_SUPPORT_DAPST) && 1031217874Smav (!(softc->caps & CTS_SATA_CAPS_H_APST)) != 1032217874Smav (!(ident_buf->sataenabled & ATA_ENABLED_DAPST))) { 1033207499Smav PROBE_SET_ACTION(softc, PROBE_SETAPST); 1034207499Smav xpt_release_ccb(done_ccb); 1035207499Smav xpt_schedule(periph, priority); 1036207499Smav return; 1037207499Smav } 1038207499Smav /* FALLTHROUGH */ 1039207499Smav case PROBE_SETAPST: 1040217874Smav if ((ident_buf->satasupport & ATA_SUPPORT_AUTOACTIVATE) && 1041217874Smav (!(softc->caps & CTS_SATA_CAPS_H_DMAAA)) != 1042217874Smav (!(ident_buf->sataenabled & ATA_SUPPORT_AUTOACTIVATE))) { 1043207499Smav PROBE_SET_ACTION(softc, PROBE_SETDMAAA); 1044207499Smav xpt_release_ccb(done_ccb); 1045207499Smav xpt_schedule(periph, priority); 1046207499Smav return; 1047207499Smav } 1048207499Smav /* FALLTHROUGH */ 1049207499Smav case PROBE_SETDMAAA: 1050220602Smav if ((ident_buf->satasupport & ATA_SUPPORT_ASYNCNOTIF) && 1051220602Smav (!(softc->caps & CTS_SATA_CAPS_H_AN)) != 1052220602Smav (!(ident_buf->sataenabled & ATA_SUPPORT_ASYNCNOTIF))) { 1053220602Smav PROBE_SET_ACTION(softc, PROBE_SETAN); 1054220602Smav xpt_release_ccb(done_ccb); 1055220602Smav xpt_schedule(periph, priority); 1056220602Smav return; 1057220602Smav } 1058220602Smav /* FALLTHROUGH */ 1059220602Smav case PROBE_SETAN: 1060207499Smavnotsata: 1061198708Smav if (path->device->protocol == PROTO_ATA) { 1062198708Smav PROBE_SET_ACTION(softc, PROBE_SET_MULTI); 1063198708Smav } else { 1064198708Smav PROBE_SET_ACTION(softc, PROBE_INQUIRY); 1065195534Sscottl } 1066198708Smav xpt_release_ccb(done_ccb); 1067198708Smav xpt_schedule(periph, priority); 1068198708Smav return; 1069198708Smav case PROBE_SET_MULTI: 1070198708Smav if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 1071198708Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1072198748Smav xpt_acquire_device(path->device); 1073198708Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1074198708Smav xpt_action(done_ccb); 1075198708Smav xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, 1076198708Smav done_ccb); 1077198708Smav } 1078198708Smav break; 1079195534Sscottl case PROBE_INQUIRY: 1080195534Sscottl case PROBE_FULL_INQUIRY: 1081195534Sscottl { 1082198708Smav struct scsi_inquiry_data *inq_buf; 1083198708Smav u_int8_t periph_qual, len; 1084195534Sscottl 1085198708Smav path->device->flags |= CAM_DEV_INQUIRY_DATA_VALID; 1086198708Smav inq_buf = &path->device->inq_data; 1087195534Sscottl 1088198708Smav periph_qual = SID_QUAL(inq_buf); 1089195534Sscottl 1090198708Smav if (periph_qual != SID_QUAL_LU_CONNECTED) 1091198708Smav break; 1092195534Sscottl 1093198708Smav /* 1094198708Smav * We conservatively request only 1095198708Smav * SHORT_INQUIRY_LEN bytes of inquiry 1096198708Smav * information during our first try 1097198708Smav * at sending an INQUIRY. If the device 1098198708Smav * has more information to give, 1099198708Smav * perform a second request specifying 1100198708Smav * the amount of information the device 1101198708Smav * is willing to give. 1102198708Smav */ 1103198708Smav len = inq_buf->additional_length 1104198708Smav + offsetof(struct scsi_inquiry_data, additional_length) + 1; 1105198708Smav if (softc->action == PROBE_INQUIRY 1106198708Smav && len > SHORT_INQUIRY_LENGTH) { 1107198708Smav PROBE_SET_ACTION(softc, PROBE_FULL_INQUIRY); 1108198708Smav xpt_release_ccb(done_ccb); 1109198708Smav xpt_schedule(periph, priority); 1110195534Sscottl return; 1111195534Sscottl } 1112198708Smav 1113198708Smav ata_device_transport(path); 1114198708Smav if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 1115198708Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1116198748Smav xpt_acquire_device(path->device); 1117198708Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1118198708Smav xpt_action(done_ccb); 1119198708Smav xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, done_ccb); 1120198708Smav } 1121198708Smav break; 1122195534Sscottl } 1123195534Sscottl case PROBE_PM_PID: 1124198708Smav if ((path->device->flags & CAM_DEV_IDENTIFY_DATA_VALID) == 0) 1125198708Smav bzero(ident_buf, sizeof(*ident_buf)); 1126198708Smav softc->pm_pid = (done_ccb->ataio.res.lba_high << 24) + 1127198708Smav (done_ccb->ataio.res.lba_mid << 16) + 1128198708Smav (done_ccb->ataio.res.lba_low << 8) + 1129198708Smav done_ccb->ataio.res.sector_count; 1130198708Smav ((uint32_t *)ident_buf)[0] = softc->pm_pid; 1131198708Smav snprintf(ident_buf->model, sizeof(ident_buf->model), 1132198708Smav "Port Multiplier %08x", softc->pm_pid); 1133198708Smav PROBE_SET_ACTION(softc, PROBE_PM_PRV); 1134198708Smav xpt_release_ccb(done_ccb); 1135198708Smav xpt_schedule(periph, priority); 1136198708Smav return; 1137195534Sscottl case PROBE_PM_PRV: 1138198708Smav softc->pm_prv = (done_ccb->ataio.res.lba_high << 24) + 1139198708Smav (done_ccb->ataio.res.lba_mid << 16) + 1140198708Smav (done_ccb->ataio.res.lba_low << 8) + 1141198708Smav done_ccb->ataio.res.sector_count; 1142198708Smav ((uint32_t *)ident_buf)[1] = softc->pm_prv; 1143198708Smav snprintf(ident_buf->revision, sizeof(ident_buf->revision), 1144198708Smav "%04x", softc->pm_prv); 1145198708Smav path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 1146207499Smav /* Set supported bits. */ 1147207499Smav bzero(&cts, sizeof(cts)); 1148207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1149207499Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1150207499Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 1151207499Smav xpt_action((union ccb *)&cts); 1152207499Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1153207499Smav caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H; 1154207499Smav else 1155207499Smav caps = 0; 1156207499Smav /* All PMPs must support PM requests. */ 1157207499Smav caps |= CTS_SATA_CAPS_D_PMREQ; 1158207499Smav /* Mask unwanted bits. */ 1159207499Smav bzero(&cts, sizeof(cts)); 1160207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1161207499Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1162207499Smav cts.type = CTS_TYPE_USER_SETTINGS; 1163207499Smav xpt_action((union ccb *)&cts); 1164207499Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1165207499Smav caps &= cts.xport_specific.sata.caps; 1166215454Smav else 1167215454Smav caps = 0; 1168207499Smav /* Store result to SIM. */ 1169207499Smav bzero(&cts, sizeof(cts)); 1170207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1171207499Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1172207499Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 1173207499Smav cts.xport_specific.sata.caps = caps; 1174207499Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS; 1175207499Smav xpt_action((union ccb *)&cts); 1176207499Smav softc->caps = caps; 1177198708Smav if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 1178198708Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1179198748Smav xpt_acquire_device(path->device); 1180198708Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1181198708Smav xpt_action(done_ccb); 1182198708Smav xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, 1183198708Smav done_ccb); 1184198708Smav } else { 1185198708Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1186198708Smav xpt_action(done_ccb); 1187198708Smav xpt_async(AC_SCSI_AEN, done_ccb->ccb_h.path, done_ccb); 1188195534Sscottl } 1189198708Smav break; 1190195534Sscottl case PROBE_INVALID: 1191195534Sscottl CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_INFO, 1192195534Sscottl ("probedone: invalid action state\n")); 1193195534Sscottl default: 1194195534Sscottl break; 1195195534Sscottl } 1196198708Smavdone: 1197203108Smav if (softc->restart) { 1198203108Smav softc->restart = 0; 1199203108Smav xpt_release_ccb(done_ccb); 1200195534Sscottl probeschedule(periph); 1201203108Smav return; 1202195534Sscottl } 1203203108Smav xpt_release_ccb(done_ccb); 1204203108Smav while ((done_ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs))) { 1205203108Smav TAILQ_REMOVE(&softc->request_ccbs, 1206203108Smav &done_ccb->ccb_h, periph_links.tqe); 1207203108Smav done_ccb->ccb_h.status = found ? CAM_REQ_CMP : CAM_REQ_CMP_ERR; 1208203108Smav xpt_done(done_ccb); 1209203108Smav } 1210203108Smav cam_release_devq(periph->path, 1211203108Smav RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_XPT + 1, FALSE); 1212203108Smav cam_periph_invalidate(periph); 1213203108Smav cam_periph_release_locked(periph); 1214195534Sscottl} 1215195534Sscottl 1216195534Sscottlstatic void 1217195534Sscottlprobecleanup(struct cam_periph *periph) 1218195534Sscottl{ 1219195534Sscottl free(periph->softc, M_CAMXPT); 1220195534Sscottl} 1221195534Sscottl 1222195534Sscottlstatic void 1223199178Smavata_find_quirk(struct cam_ed *device) 1224195534Sscottl{ 1225199178Smav struct ata_quirk_entry *quirk; 1226195534Sscottl caddr_t match; 1227195534Sscottl 1228199178Smav match = cam_quirkmatch((caddr_t)&device->ident_data, 1229199178Smav (caddr_t)ata_quirk_table, 1230199178Smav ata_quirk_table_size, 1231199178Smav sizeof(*ata_quirk_table), ata_identify_match); 1232195534Sscottl 1233195534Sscottl if (match == NULL) 1234195534Sscottl panic("xpt_find_quirk: device didn't match wildcard entry!!"); 1235195534Sscottl 1236199178Smav quirk = (struct ata_quirk_entry *)match; 1237195534Sscottl device->quirk = quirk; 1238199178Smav if (quirk->quirks & CAM_QUIRK_MAXTAGS) 1239199178Smav device->mintags = device->maxtags = quirk->maxtags; 1240195534Sscottl} 1241195534Sscottl 1242195534Sscottltypedef struct { 1243195534Sscottl union ccb *request_ccb; 1244195534Sscottl struct ccb_pathinq *cpi; 1245195534Sscottl int counter; 1246195534Sscottl} ata_scan_bus_info; 1247195534Sscottl 1248195534Sscottl/* 1249195534Sscottl * To start a scan, request_ccb is an XPT_SCAN_BUS ccb. 1250195534Sscottl * As the scan progresses, xpt_scan_bus is used as the 1251195534Sscottl * callback on completion function. 1252195534Sscottl */ 1253195534Sscottlstatic void 1254195534Sscottlata_scan_bus(struct cam_periph *periph, union ccb *request_ccb) 1255195534Sscottl{ 1256195534Sscottl struct cam_path *path; 1257195534Sscottl ata_scan_bus_info *scan_info; 1258203108Smav union ccb *work_ccb, *reset_ccb; 1259195534Sscottl cam_status status; 1260195534Sscottl 1261195534Sscottl CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE, 1262195534Sscottl ("xpt_scan_bus\n")); 1263195534Sscottl switch (request_ccb->ccb_h.func_code) { 1264195534Sscottl case XPT_SCAN_BUS: 1265208582Smjacob case XPT_SCAN_TGT: 1266195534Sscottl /* Find out the characteristics of the bus */ 1267195534Sscottl work_ccb = xpt_alloc_ccb_nowait(); 1268195534Sscottl if (work_ccb == NULL) { 1269195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1270195534Sscottl xpt_done(request_ccb); 1271195534Sscottl return; 1272195534Sscottl } 1273195534Sscottl xpt_setup_ccb(&work_ccb->ccb_h, request_ccb->ccb_h.path, 1274195534Sscottl request_ccb->ccb_h.pinfo.priority); 1275195534Sscottl work_ccb->ccb_h.func_code = XPT_PATH_INQ; 1276195534Sscottl xpt_action(work_ccb); 1277195534Sscottl if (work_ccb->ccb_h.status != CAM_REQ_CMP) { 1278195534Sscottl request_ccb->ccb_h.status = work_ccb->ccb_h.status; 1279195534Sscottl xpt_free_ccb(work_ccb); 1280195534Sscottl xpt_done(request_ccb); 1281195534Sscottl return; 1282195534Sscottl } 1283195534Sscottl 1284203108Smav /* We may need to reset bus first, if we haven't done it yet. */ 1285203108Smav if ((work_ccb->cpi.hba_inquiry & 1286203108Smav (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE)) && 1287203108Smav !(work_ccb->cpi.hba_misc & PIM_NOBUSRESET) && 1288203108Smav !timevalisset(&request_ccb->ccb_h.path->bus->last_reset)) { 1289203108Smav reset_ccb = xpt_alloc_ccb_nowait(); 1290208823Smav if (reset_ccb == NULL) { 1291208823Smav request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1292208823Smav xpt_free_ccb(work_ccb); 1293208823Smav xpt_done(request_ccb); 1294208823Smav return; 1295208823Smav } 1296203108Smav xpt_setup_ccb(&reset_ccb->ccb_h, request_ccb->ccb_h.path, 1297203108Smav CAM_PRIORITY_NONE); 1298203108Smav reset_ccb->ccb_h.func_code = XPT_RESET_BUS; 1299203108Smav xpt_action(reset_ccb); 1300203108Smav if (reset_ccb->ccb_h.status != CAM_REQ_CMP) { 1301203108Smav request_ccb->ccb_h.status = reset_ccb->ccb_h.status; 1302203108Smav xpt_free_ccb(reset_ccb); 1303203108Smav xpt_free_ccb(work_ccb); 1304203108Smav xpt_done(request_ccb); 1305203108Smav return; 1306203108Smav } 1307203108Smav xpt_free_ccb(reset_ccb); 1308203108Smav } 1309203108Smav 1310195534Sscottl /* Save some state for use while we probe for devices */ 1311195534Sscottl scan_info = (ata_scan_bus_info *) 1312195534Sscottl malloc(sizeof(ata_scan_bus_info), M_CAMXPT, M_NOWAIT); 1313195534Sscottl if (scan_info == NULL) { 1314195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1315208823Smav xpt_free_ccb(work_ccb); 1316195534Sscottl xpt_done(request_ccb); 1317195534Sscottl return; 1318195534Sscottl } 1319195534Sscottl scan_info->request_ccb = request_ccb; 1320195534Sscottl scan_info->cpi = &work_ccb->cpi; 1321195534Sscottl /* If PM supported, probe it first. */ 1322195534Sscottl if (scan_info->cpi->hba_inquiry & PI_SATAPM) 1323201990Smav scan_info->counter = scan_info->cpi->max_target; 1324201990Smav else 1325201990Smav scan_info->counter = 0; 1326195534Sscottl 1327195534Sscottl work_ccb = xpt_alloc_ccb_nowait(); 1328195534Sscottl if (work_ccb == NULL) { 1329195534Sscottl free(scan_info, M_CAMXPT); 1330195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1331195534Sscottl xpt_done(request_ccb); 1332195534Sscottl break; 1333195534Sscottl } 1334195534Sscottl goto scan_next; 1335195534Sscottl case XPT_SCAN_LUN: 1336195534Sscottl work_ccb = request_ccb; 1337195534Sscottl /* Reuse the same CCB to query if a device was really found */ 1338195534Sscottl scan_info = (ata_scan_bus_info *)work_ccb->ccb_h.ppriv_ptr0; 1339198389Smav /* If there is PMP... */ 1340201990Smav if ((scan_info->cpi->hba_inquiry & PI_SATAPM) && 1341201990Smav (scan_info->counter == scan_info->cpi->max_target)) { 1342203108Smav if (work_ccb->ccb_h.status == CAM_REQ_CMP) { 1343207428Smav /* everything else will be probed by it */ 1344207428Smav /* Free the current request path- we're done with it. */ 1345207428Smav xpt_free_path(work_ccb->ccb_h.path); 1346201990Smav goto done; 1347195534Sscottl } else { 1348195534Sscottl struct ccb_trans_settings cts; 1349195534Sscottl 1350195534Sscottl /* Report SIM that PM is absent. */ 1351195534Sscottl bzero(&cts, sizeof(cts)); 1352195534Sscottl xpt_setup_ccb(&cts.ccb_h, 1353207428Smav work_ccb->ccb_h.path, CAM_PRIORITY_NONE); 1354195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1355195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 1356195665Smav cts.xport_specific.sata.pm_present = 0; 1357195534Sscottl cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; 1358195534Sscottl xpt_action((union ccb *)&cts); 1359195534Sscottl } 1360195534Sscottl } 1361207428Smav /* Free the current request path- we're done with it. */ 1362207428Smav xpt_free_path(work_ccb->ccb_h.path); 1363201990Smav if (scan_info->counter == 1364201990Smav ((scan_info->cpi->hba_inquiry & PI_SATAPM) ? 1365201990Smav 0 : scan_info->cpi->max_target)) { 1366201990Smavdone: 1367195534Sscottl xpt_free_ccb(work_ccb); 1368195534Sscottl xpt_free_ccb((union ccb *)scan_info->cpi); 1369195534Sscottl request_ccb = scan_info->request_ccb; 1370195534Sscottl free(scan_info, M_CAMXPT); 1371195534Sscottl request_ccb->ccb_h.status = CAM_REQ_CMP; 1372195534Sscottl xpt_done(request_ccb); 1373195534Sscottl break; 1374195534Sscottl } 1375201990Smav /* Take next device. Wrap from max (PMP) to 0. */ 1376201990Smav scan_info->counter = (scan_info->counter + 1 ) % 1377201990Smav (scan_info->cpi->max_target + 1); 1378195534Sscottlscan_next: 1379195534Sscottl status = xpt_create_path(&path, xpt_periph, 1380195534Sscottl scan_info->request_ccb->ccb_h.path_id, 1381195534Sscottl scan_info->counter, 0); 1382195534Sscottl if (status != CAM_REQ_CMP) { 1383195534Sscottl printf("xpt_scan_bus: xpt_create_path failed" 1384195534Sscottl " with status %#x, bus scan halted\n", 1385195534Sscottl status); 1386195534Sscottl xpt_free_ccb(work_ccb); 1387195534Sscottl xpt_free_ccb((union ccb *)scan_info->cpi); 1388195534Sscottl request_ccb = scan_info->request_ccb; 1389195534Sscottl free(scan_info, M_CAMXPT); 1390195534Sscottl request_ccb->ccb_h.status = status; 1391195534Sscottl xpt_done(request_ccb); 1392195534Sscottl break; 1393195534Sscottl } 1394195534Sscottl xpt_setup_ccb(&work_ccb->ccb_h, path, 1395195534Sscottl scan_info->request_ccb->ccb_h.pinfo.priority); 1396195534Sscottl work_ccb->ccb_h.func_code = XPT_SCAN_LUN; 1397195534Sscottl work_ccb->ccb_h.cbfcnp = ata_scan_bus; 1398195534Sscottl work_ccb->ccb_h.ppriv_ptr0 = scan_info; 1399195534Sscottl work_ccb->crcn.flags = scan_info->request_ccb->crcn.flags; 1400195534Sscottl xpt_action(work_ccb); 1401195534Sscottl break; 1402195534Sscottl default: 1403195534Sscottl break; 1404195534Sscottl } 1405195534Sscottl} 1406195534Sscottl 1407195534Sscottlstatic void 1408195534Sscottlata_scan_lun(struct cam_periph *periph, struct cam_path *path, 1409195534Sscottl cam_flags flags, union ccb *request_ccb) 1410195534Sscottl{ 1411195534Sscottl struct ccb_pathinq cpi; 1412195534Sscottl cam_status status; 1413195534Sscottl struct cam_path *new_path; 1414195534Sscottl struct cam_periph *old_periph; 1415195534Sscottl 1416203108Smav CAM_DEBUG(path, CAM_DEBUG_TRACE, ("xpt_scan_lun\n")); 1417195534Sscottl 1418203108Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 1419195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 1420195534Sscottl xpt_action((union ccb *)&cpi); 1421195534Sscottl 1422195534Sscottl if (cpi.ccb_h.status != CAM_REQ_CMP) { 1423195534Sscottl if (request_ccb != NULL) { 1424195534Sscottl request_ccb->ccb_h.status = cpi.ccb_h.status; 1425195534Sscottl xpt_done(request_ccb); 1426195534Sscottl } 1427195534Sscottl return; 1428195534Sscottl } 1429195534Sscottl 1430195534Sscottl if (request_ccb == NULL) { 1431195534Sscottl request_ccb = malloc(sizeof(union ccb), M_CAMXPT, M_NOWAIT); 1432195534Sscottl if (request_ccb == NULL) { 1433195534Sscottl xpt_print(path, "xpt_scan_lun: can't allocate CCB, " 1434195534Sscottl "can't continue\n"); 1435195534Sscottl return; 1436195534Sscottl } 1437195534Sscottl new_path = malloc(sizeof(*new_path), M_CAMXPT, M_NOWAIT); 1438195534Sscottl if (new_path == NULL) { 1439195534Sscottl xpt_print(path, "xpt_scan_lun: can't allocate path, " 1440195534Sscottl "can't continue\n"); 1441195534Sscottl free(request_ccb, M_CAMXPT); 1442195534Sscottl return; 1443195534Sscottl } 1444195534Sscottl status = xpt_compile_path(new_path, xpt_periph, 1445195534Sscottl path->bus->path_id, 1446195534Sscottl path->target->target_id, 1447195534Sscottl path->device->lun_id); 1448195534Sscottl 1449195534Sscottl if (status != CAM_REQ_CMP) { 1450195534Sscottl xpt_print(path, "xpt_scan_lun: can't compile path, " 1451195534Sscottl "can't continue\n"); 1452195534Sscottl free(request_ccb, M_CAMXPT); 1453195534Sscottl free(new_path, M_CAMXPT); 1454195534Sscottl return; 1455195534Sscottl } 1456203108Smav xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_XPT); 1457195534Sscottl request_ccb->ccb_h.cbfcnp = xptscandone; 1458195534Sscottl request_ccb->ccb_h.func_code = XPT_SCAN_LUN; 1459195534Sscottl request_ccb->crcn.flags = flags; 1460195534Sscottl } 1461195534Sscottl 1462195653Smav if ((old_periph = cam_periph_find(path, "aprobe")) != NULL) { 1463195534Sscottl probe_softc *softc; 1464195534Sscottl 1465195534Sscottl softc = (probe_softc *)old_periph->softc; 1466195534Sscottl TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h, 1467195534Sscottl periph_links.tqe); 1468203108Smav softc->restart = 1; 1469195534Sscottl } else { 1470195534Sscottl status = cam_periph_alloc(proberegister, NULL, probecleanup, 1471195653Smav probestart, "aprobe", 1472195534Sscottl CAM_PERIPH_BIO, 1473195534Sscottl request_ccb->ccb_h.path, NULL, 0, 1474195534Sscottl request_ccb); 1475195534Sscottl 1476195534Sscottl if (status != CAM_REQ_CMP) { 1477195534Sscottl xpt_print(path, "xpt_scan_lun: cam_alloc_periph " 1478195534Sscottl "returned an error, can't continue probe\n"); 1479195534Sscottl request_ccb->ccb_h.status = status; 1480195534Sscottl xpt_done(request_ccb); 1481195534Sscottl } 1482195534Sscottl } 1483195534Sscottl} 1484195534Sscottl 1485195534Sscottlstatic void 1486195534Sscottlxptscandone(struct cam_periph *periph, union ccb *done_ccb) 1487195534Sscottl{ 1488195534Sscottl xpt_release_path(done_ccb->ccb_h.path); 1489195534Sscottl free(done_ccb->ccb_h.path, M_CAMXPT); 1490195534Sscottl free(done_ccb, M_CAMXPT); 1491195534Sscottl} 1492195534Sscottl 1493195534Sscottlstatic struct cam_ed * 1494195534Sscottlata_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id) 1495195534Sscottl{ 1496195534Sscottl struct cam_path path; 1497199178Smav struct ata_quirk_entry *quirk; 1498195534Sscottl struct cam_ed *device; 1499195534Sscottl struct cam_ed *cur_device; 1500195534Sscottl 1501195534Sscottl device = xpt_alloc_device(bus, target, lun_id); 1502195534Sscottl if (device == NULL) 1503195534Sscottl return (NULL); 1504195534Sscottl 1505195534Sscottl /* 1506195534Sscottl * Take the default quirk entry until we have inquiry 1507195534Sscottl * data and can determine a better quirk to use. 1508195534Sscottl */ 1509199178Smav quirk = &ata_quirk_table[ata_quirk_table_size - 1]; 1510195534Sscottl device->quirk = (void *)quirk; 1511199178Smav device->mintags = 0; 1512199178Smav device->maxtags = 0; 1513195534Sscottl bzero(&device->inq_data, sizeof(device->inq_data)); 1514195534Sscottl device->inq_flags = 0; 1515195534Sscottl device->queue_flags = 0; 1516195534Sscottl device->serial_num = NULL; 1517195534Sscottl device->serial_num_len = 0; 1518195534Sscottl 1519195534Sscottl /* 1520195534Sscottl * XXX should be limited by number of CCBs this bus can 1521195534Sscottl * do. 1522195534Sscottl */ 1523195534Sscottl bus->sim->max_ccbs += device->ccbq.devq_openings; 1524195534Sscottl /* Insertion sort into our target's device list */ 1525195534Sscottl cur_device = TAILQ_FIRST(&target->ed_entries); 1526195534Sscottl while (cur_device != NULL && cur_device->lun_id < lun_id) 1527195534Sscottl cur_device = TAILQ_NEXT(cur_device, links); 1528195534Sscottl if (cur_device != NULL) { 1529195534Sscottl TAILQ_INSERT_BEFORE(cur_device, device, links); 1530195534Sscottl } else { 1531195534Sscottl TAILQ_INSERT_TAIL(&target->ed_entries, device, links); 1532195534Sscottl } 1533195534Sscottl target->generation++; 1534195534Sscottl if (lun_id != CAM_LUN_WILDCARD) { 1535195534Sscottl xpt_compile_path(&path, 1536195534Sscottl NULL, 1537195534Sscottl bus->path_id, 1538195534Sscottl target->target_id, 1539195534Sscottl lun_id); 1540195534Sscottl ata_device_transport(&path); 1541195534Sscottl xpt_release_path(&path); 1542195534Sscottl } 1543195534Sscottl 1544195534Sscottl return (device); 1545195534Sscottl} 1546195534Sscottl 1547195534Sscottlstatic void 1548195534Sscottlata_device_transport(struct cam_path *path) 1549195534Sscottl{ 1550195534Sscottl struct ccb_pathinq cpi; 1551198331Smav struct ccb_trans_settings cts; 1552198331Smav struct scsi_inquiry_data *inq_buf = NULL; 1553198331Smav struct ata_params *ident_buf = NULL; 1554195534Sscottl 1555195534Sscottl /* Get transport information from the SIM */ 1556203108Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 1557195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 1558195534Sscottl xpt_action((union ccb *)&cpi); 1559195534Sscottl 1560195534Sscottl path->device->transport = cpi.transport; 1561198331Smav if ((path->device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0) 1562198331Smav inq_buf = &path->device->inq_data; 1563198331Smav if ((path->device->flags & CAM_DEV_IDENTIFY_DATA_VALID) != 0) 1564198331Smav ident_buf = &path->device->ident_data; 1565198331Smav if (path->device->protocol == PROTO_ATA) { 1566198331Smav path->device->protocol_version = ident_buf ? 1567198331Smav ata_version(ident_buf->version_major) : cpi.protocol_version; 1568198331Smav } else if (path->device->protocol == PROTO_SCSI) { 1569198331Smav path->device->protocol_version = inq_buf ? 1570198331Smav SID_ANSI_REV(inq_buf) : cpi.protocol_version; 1571195534Sscottl } 1572198331Smav path->device->transport_version = ident_buf ? 1573198331Smav ata_version(ident_buf->version_major) : cpi.transport_version; 1574195534Sscottl 1575195534Sscottl /* Tell the controller what we think */ 1576203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1577195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1578195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 1579195534Sscottl cts.transport = path->device->transport; 1580195534Sscottl cts.transport_version = path->device->transport_version; 1581195534Sscottl cts.protocol = path->device->protocol; 1582195534Sscottl cts.protocol_version = path->device->protocol_version; 1583195534Sscottl cts.proto_specific.valid = 0; 1584203376Smav if (ident_buf) { 1585203376Smav if (path->device->transport == XPORT_ATA) { 1586203376Smav cts.xport_specific.ata.atapi = 1587203376Smav ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_16) ? 16 : 1588203376Smav ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) ? 12 : 0; 1589203376Smav cts.xport_specific.ata.valid = CTS_ATA_VALID_ATAPI; 1590203376Smav } else { 1591203376Smav cts.xport_specific.sata.atapi = 1592203376Smav ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_16) ? 16 : 1593203376Smav ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) ? 12 : 0; 1594203376Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_ATAPI; 1595203376Smav } 1596203376Smav } else 1597203376Smav cts.xport_specific.valid = 0; 1598195534Sscottl xpt_action((union ccb *)&cts); 1599195534Sscottl} 1600195534Sscottl 1601195534Sscottlstatic void 1602195534Sscottlata_action(union ccb *start_ccb) 1603195534Sscottl{ 1604195534Sscottl 1605195534Sscottl switch (start_ccb->ccb_h.func_code) { 1606195534Sscottl case XPT_SET_TRAN_SETTINGS: 1607195534Sscottl { 1608199178Smav ata_set_transfer_settings(&start_ccb->cts, 1609195534Sscottl start_ccb->ccb_h.path->device, 1610195534Sscottl /*async_update*/FALSE); 1611195534Sscottl break; 1612195534Sscottl } 1613195534Sscottl case XPT_SCAN_BUS: 1614208582Smjacob case XPT_SCAN_TGT: 1615195534Sscottl ata_scan_bus(start_ccb->ccb_h.path->periph, start_ccb); 1616195534Sscottl break; 1617195534Sscottl case XPT_SCAN_LUN: 1618195534Sscottl ata_scan_lun(start_ccb->ccb_h.path->periph, 1619195534Sscottl start_ccb->ccb_h.path, start_ccb->crcn.flags, 1620195534Sscottl start_ccb); 1621195534Sscottl break; 1622195534Sscottl case XPT_GET_TRAN_SETTINGS: 1623195534Sscottl { 1624195534Sscottl struct cam_sim *sim; 1625195534Sscottl 1626195534Sscottl sim = start_ccb->ccb_h.path->bus->sim; 1627195534Sscottl (*(sim->sim_action))(sim, start_ccb); 1628195534Sscottl break; 1629195534Sscottl } 1630203376Smav case XPT_SCSI_IO: 1631203376Smav { 1632203376Smav struct cam_ed *device; 1633203376Smav u_int maxlen = 0; 1634203376Smav 1635203376Smav device = start_ccb->ccb_h.path->device; 1636203376Smav if (device->protocol == PROTO_SCSI && 1637203376Smav (device->flags & CAM_DEV_IDENTIFY_DATA_VALID)) { 1638203376Smav uint16_t p = 1639203376Smav device->ident_data.config & ATA_PROTO_MASK; 1640203376Smav 1641203376Smav maxlen = (p == ATA_PROTO_ATAPI_16) ? 16 : 1642203376Smav (p == ATA_PROTO_ATAPI_12) ? 12 : 0; 1643203376Smav } 1644203376Smav if (start_ccb->csio.cdb_len > maxlen) { 1645203376Smav start_ccb->ccb_h.status = CAM_REQ_INVALID; 1646203376Smav xpt_done(start_ccb); 1647203376Smav break; 1648203376Smav } 1649203376Smav /* FALLTHROUGH */ 1650203376Smav } 1651195534Sscottl default: 1652195534Sscottl xpt_action_default(start_ccb); 1653195534Sscottl break; 1654195534Sscottl } 1655195534Sscottl} 1656195534Sscottl 1657195534Sscottlstatic void 1658199178Smavata_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device, 1659195534Sscottl int async_update) 1660195534Sscottl{ 1661195534Sscottl struct ccb_pathinq cpi; 1662195534Sscottl struct ccb_trans_settings cur_cts; 1663195534Sscottl struct ccb_trans_settings_scsi *scsi; 1664195534Sscottl struct ccb_trans_settings_scsi *cur_scsi; 1665195534Sscottl struct cam_sim *sim; 1666195534Sscottl struct scsi_inquiry_data *inq_data; 1667195534Sscottl 1668195534Sscottl if (device == NULL) { 1669195534Sscottl cts->ccb_h.status = CAM_PATH_INVALID; 1670195534Sscottl xpt_done((union ccb *)cts); 1671195534Sscottl return; 1672195534Sscottl } 1673195534Sscottl 1674195534Sscottl if (cts->protocol == PROTO_UNKNOWN 1675195534Sscottl || cts->protocol == PROTO_UNSPECIFIED) { 1676195534Sscottl cts->protocol = device->protocol; 1677195534Sscottl cts->protocol_version = device->protocol_version; 1678195534Sscottl } 1679195534Sscottl 1680195534Sscottl if (cts->protocol_version == PROTO_VERSION_UNKNOWN 1681195534Sscottl || cts->protocol_version == PROTO_VERSION_UNSPECIFIED) 1682195534Sscottl cts->protocol_version = device->protocol_version; 1683195534Sscottl 1684195534Sscottl if (cts->protocol != device->protocol) { 1685195534Sscottl xpt_print(cts->ccb_h.path, "Uninitialized Protocol %x:%x?\n", 1686195534Sscottl cts->protocol, device->protocol); 1687195534Sscottl cts->protocol = device->protocol; 1688195534Sscottl } 1689195534Sscottl 1690195534Sscottl if (cts->protocol_version > device->protocol_version) { 1691195534Sscottl if (bootverbose) { 1692195534Sscottl xpt_print(cts->ccb_h.path, "Down reving Protocol " 1693195534Sscottl "Version from %d to %d?\n", cts->protocol_version, 1694195534Sscottl device->protocol_version); 1695195534Sscottl } 1696195534Sscottl cts->protocol_version = device->protocol_version; 1697195534Sscottl } 1698195534Sscottl 1699195534Sscottl if (cts->transport == XPORT_UNKNOWN 1700195534Sscottl || cts->transport == XPORT_UNSPECIFIED) { 1701195534Sscottl cts->transport = device->transport; 1702195534Sscottl cts->transport_version = device->transport_version; 1703195534Sscottl } 1704195534Sscottl 1705195534Sscottl if (cts->transport_version == XPORT_VERSION_UNKNOWN 1706195534Sscottl || cts->transport_version == XPORT_VERSION_UNSPECIFIED) 1707195534Sscottl cts->transport_version = device->transport_version; 1708195534Sscottl 1709195534Sscottl if (cts->transport != device->transport) { 1710195534Sscottl xpt_print(cts->ccb_h.path, "Uninitialized Transport %x:%x?\n", 1711195534Sscottl cts->transport, device->transport); 1712195534Sscottl cts->transport = device->transport; 1713195534Sscottl } 1714195534Sscottl 1715195534Sscottl if (cts->transport_version > device->transport_version) { 1716195534Sscottl if (bootverbose) { 1717195534Sscottl xpt_print(cts->ccb_h.path, "Down reving Transport " 1718195534Sscottl "Version from %d to %d?\n", cts->transport_version, 1719195534Sscottl device->transport_version); 1720195534Sscottl } 1721195534Sscottl cts->transport_version = device->transport_version; 1722195534Sscottl } 1723195534Sscottl 1724195534Sscottl sim = cts->ccb_h.path->bus->sim; 1725195534Sscottl 1726195534Sscottl /* 1727195534Sscottl * Nothing more of interest to do unless 1728195534Sscottl * this is a device connected via the 1729195534Sscottl * SCSI protocol. 1730195534Sscottl */ 1731195534Sscottl if (cts->protocol != PROTO_SCSI) { 1732195534Sscottl if (async_update == FALSE) 1733195534Sscottl (*(sim->sim_action))(sim, (union ccb *)cts); 1734195534Sscottl return; 1735195534Sscottl } 1736195534Sscottl 1737195534Sscottl inq_data = &device->inq_data; 1738195534Sscottl scsi = &cts->proto_specific.scsi; 1739203108Smav xpt_setup_ccb(&cpi.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NONE); 1740195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 1741195534Sscottl xpt_action((union ccb *)&cpi); 1742195534Sscottl 1743195534Sscottl /* SCSI specific sanity checking */ 1744195534Sscottl if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0 1745195534Sscottl || (INQ_DATA_TQ_ENABLED(inq_data)) == 0 1746195534Sscottl || (device->queue_flags & SCP_QUEUE_DQUE) != 0 1747195534Sscottl || (device->mintags == 0)) { 1748195534Sscottl /* 1749195534Sscottl * Can't tag on hardware that doesn't support tags, 1750195534Sscottl * doesn't have it enabled, or has broken tag support. 1751195534Sscottl */ 1752195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 1753195534Sscottl } 1754195534Sscottl 1755195534Sscottl if (async_update == FALSE) { 1756195534Sscottl /* 1757195534Sscottl * Perform sanity checking against what the 1758195534Sscottl * controller and device can do. 1759195534Sscottl */ 1760203108Smav xpt_setup_ccb(&cur_cts.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NONE); 1761195534Sscottl cur_cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1762195534Sscottl cur_cts.type = cts->type; 1763195534Sscottl xpt_action((union ccb *)&cur_cts); 1764195534Sscottl if ((cur_cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1765195534Sscottl return; 1766195534Sscottl } 1767195534Sscottl cur_scsi = &cur_cts.proto_specific.scsi; 1768195534Sscottl if ((scsi->valid & CTS_SCSI_VALID_TQ) == 0) { 1769195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 1770195534Sscottl scsi->flags |= cur_scsi->flags & CTS_SCSI_FLAGS_TAG_ENB; 1771195534Sscottl } 1772195534Sscottl if ((cur_scsi->valid & CTS_SCSI_VALID_TQ) == 0) 1773195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 1774195534Sscottl } 1775195534Sscottl 1776195534Sscottl if (cts->type == CTS_TYPE_CURRENT_SETTINGS 1777195534Sscottl && (scsi->valid & CTS_SCSI_VALID_TQ) != 0) { 1778195534Sscottl int device_tagenb; 1779195534Sscottl 1780195534Sscottl /* 1781195534Sscottl * If we are transitioning from tags to no-tags or 1782195534Sscottl * vice-versa, we need to carefully freeze and restart 1783195534Sscottl * the queue so that we don't overlap tagged and non-tagged 1784195534Sscottl * commands. We also temporarily stop tags if there is 1785195534Sscottl * a change in transfer negotiation settings to allow 1786195534Sscottl * "tag-less" negotiation. 1787195534Sscottl */ 1788195534Sscottl if ((device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 1789195534Sscottl || (device->inq_flags & SID_CmdQue) != 0) 1790195534Sscottl device_tagenb = TRUE; 1791195534Sscottl else 1792195534Sscottl device_tagenb = FALSE; 1793195534Sscottl 1794195534Sscottl if (((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0 1795195534Sscottl && device_tagenb == FALSE) 1796195534Sscottl || ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) == 0 1797195534Sscottl && device_tagenb == TRUE)) { 1798195534Sscottl 1799195534Sscottl if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) { 1800195534Sscottl /* 1801195534Sscottl * Delay change to use tags until after a 1802195534Sscottl * few commands have gone to this device so 1803195534Sscottl * the controller has time to perform transfer 1804195534Sscottl * negotiations without tagged messages getting 1805195534Sscottl * in the way. 1806195534Sscottl */ 1807195534Sscottl device->tag_delay_count = CAM_TAG_DELAY_COUNT; 1808195534Sscottl device->flags |= CAM_DEV_TAG_AFTER_COUNT; 1809195534Sscottl } else { 1810199178Smav xpt_stop_tags(cts->ccb_h.path); 1811195534Sscottl } 1812195534Sscottl } 1813195534Sscottl } 1814195534Sscottl if (async_update == FALSE) 1815195534Sscottl (*(sim->sim_action))(sim, (union ccb *)cts); 1816195534Sscottl} 1817195534Sscottl 1818195534Sscottl/* 1819195534Sscottl * Handle any per-device event notifications that require action by the XPT. 1820195534Sscottl */ 1821195534Sscottlstatic void 1822195534Sscottlata_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target, 1823195534Sscottl struct cam_ed *device, void *async_arg) 1824195534Sscottl{ 1825195534Sscottl cam_status status; 1826195534Sscottl struct cam_path newpath; 1827195534Sscottl 1828195534Sscottl /* 1829195534Sscottl * We only need to handle events for real devices. 1830195534Sscottl */ 1831195534Sscottl if (target->target_id == CAM_TARGET_WILDCARD 1832195534Sscottl || device->lun_id == CAM_LUN_WILDCARD) 1833195534Sscottl return; 1834195534Sscottl 1835195534Sscottl /* 1836195534Sscottl * We need our own path with wildcards expanded to 1837195534Sscottl * handle certain types of events. 1838195534Sscottl */ 1839195534Sscottl if ((async_code == AC_SENT_BDR) 1840195534Sscottl || (async_code == AC_BUS_RESET) 1841195534Sscottl || (async_code == AC_INQ_CHANGED)) 1842195534Sscottl status = xpt_compile_path(&newpath, NULL, 1843195534Sscottl bus->path_id, 1844195534Sscottl target->target_id, 1845195534Sscottl device->lun_id); 1846195534Sscottl else 1847195534Sscottl status = CAM_REQ_CMP_ERR; 1848195534Sscottl 1849195534Sscottl if (status == CAM_REQ_CMP) { 1850195534Sscottl if (async_code == AC_INQ_CHANGED) { 1851195534Sscottl /* 1852195534Sscottl * We've sent a start unit command, or 1853195534Sscottl * something similar to a device that 1854195534Sscottl * may have caused its inquiry data to 1855195534Sscottl * change. So we re-scan the device to 1856195534Sscottl * refresh the inquiry data for it. 1857195534Sscottl */ 1858195534Sscottl ata_scan_lun(newpath.periph, &newpath, 1859195534Sscottl CAM_EXPECT_INQ_CHANGE, NULL); 1860203108Smav } else { 1861203108Smav /* We need to reinitialize device after reset. */ 1862203108Smav ata_scan_lun(newpath.periph, &newpath, 1863203108Smav 0, NULL); 1864195534Sscottl } 1865195534Sscottl xpt_release_path(&newpath); 1866198748Smav } else if (async_code == AC_LOST_DEVICE && 1867198748Smav (device->flags & CAM_DEV_UNCONFIGURED) == 0) { 1868195534Sscottl device->flags |= CAM_DEV_UNCONFIGURED; 1869198748Smav xpt_release_device(device); 1870195534Sscottl } else if (async_code == AC_TRANSFER_NEG) { 1871195534Sscottl struct ccb_trans_settings *settings; 1872195534Sscottl 1873195534Sscottl settings = (struct ccb_trans_settings *)async_arg; 1874199178Smav ata_set_transfer_settings(settings, device, 1875195534Sscottl /*async_update*/TRUE); 1876195534Sscottl } 1877195534Sscottl} 1878195534Sscottl 1879204220Smavstatic void 1880204220Smavata_announce_periph(struct cam_periph *periph) 1881204220Smav{ 1882204220Smav struct ccb_pathinq cpi; 1883204220Smav struct ccb_trans_settings cts; 1884204220Smav struct cam_path *path = periph->path; 1885204220Smav u_int speed; 1886204220Smav u_int mb; 1887204220Smav 1888204220Smav mtx_assert(periph->sim->mtx, MA_OWNED); 1889204220Smav 1890204220Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); 1891204220Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1892204220Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 1893204220Smav xpt_action((union ccb*)&cts); 1894204220Smav if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 1895204220Smav return; 1896204220Smav /* Ask the SIM for its base transfer speed */ 1897204220Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL); 1898204220Smav cpi.ccb_h.func_code = XPT_PATH_INQ; 1899204220Smav xpt_action((union ccb *)&cpi); 1900204220Smav /* Report connection speed */ 1901204220Smav speed = cpi.base_transfer_speed; 1902204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_ATA) { 1903204220Smav struct ccb_trans_settings_ata *ata = 1904204220Smav &cts.xport_specific.ata; 1905204220Smav 1906204220Smav if (ata->valid & CTS_ATA_VALID_MODE) 1907204220Smav speed = ata_mode2speed(ata->mode); 1908204220Smav } 1909204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SATA) { 1910204220Smav struct ccb_trans_settings_sata *sata = 1911204220Smav &cts.xport_specific.sata; 1912204220Smav 1913204220Smav if (sata->valid & CTS_SATA_VALID_REVISION) 1914204220Smav speed = ata_revision2speed(sata->revision); 1915204220Smav } 1916204220Smav mb = speed / 1000; 1917204220Smav if (mb > 0) 1918204220Smav printf("%s%d: %d.%03dMB/s transfers", 1919204220Smav periph->periph_name, periph->unit_number, 1920204220Smav mb, speed % 1000); 1921204220Smav else 1922204220Smav printf("%s%d: %dKB/s transfers", periph->periph_name, 1923204220Smav periph->unit_number, speed); 1924204220Smav /* Report additional information about connection */ 1925204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_ATA) { 1926204220Smav struct ccb_trans_settings_ata *ata = 1927204220Smav &cts.xport_specific.ata; 1928204220Smav 1929204220Smav printf(" ("); 1930204220Smav if (ata->valid & CTS_ATA_VALID_MODE) 1931204220Smav printf("%s, ", ata_mode2string(ata->mode)); 1932204220Smav if ((ata->valid & CTS_ATA_VALID_ATAPI) && ata->atapi != 0) 1933204220Smav printf("ATAPI %dbytes, ", ata->atapi); 1934204220Smav if (ata->valid & CTS_ATA_VALID_BYTECOUNT) 1935204220Smav printf("PIO %dbytes", ata->bytecount); 1936204220Smav printf(")"); 1937204220Smav } 1938204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SATA) { 1939204220Smav struct ccb_trans_settings_sata *sata = 1940204220Smav &cts.xport_specific.sata; 1941204220Smav 1942204220Smav printf(" ("); 1943204220Smav if (sata->valid & CTS_SATA_VALID_REVISION) 1944204220Smav printf("SATA %d.x, ", sata->revision); 1945204220Smav else 1946204220Smav printf("SATA, "); 1947204220Smav if (sata->valid & CTS_SATA_VALID_MODE) 1948204220Smav printf("%s, ", ata_mode2string(sata->mode)); 1949204220Smav if ((sata->valid & CTS_ATA_VALID_ATAPI) && sata->atapi != 0) 1950204220Smav printf("ATAPI %dbytes, ", sata->atapi); 1951204220Smav if (sata->valid & CTS_SATA_VALID_BYTECOUNT) 1952204220Smav printf("PIO %dbytes", sata->bytecount); 1953204220Smav printf(")"); 1954204220Smav } 1955204220Smav printf("\n"); 1956204220Smav} 1957204220Smav 1958