ata_xpt.c revision 235897
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 235897 2012-05-24 11:07:39Z 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, 96235897Smav PROBE_IDENTIFY_SES, 97235897Smav PROBE_IDENTIFY_SAFTE, 98195534Sscottl PROBE_INVALID 99195534Sscottl} probe_action; 100195534Sscottl 101195534Sscottlstatic char *probe_action_text[] = { 102195534Sscottl "PROBE_RESET", 103195534Sscottl "PROBE_IDENTIFY", 104203421Smav "PROBE_SPINUP", 105195534Sscottl "PROBE_SETMODE", 106207499Smav "PROBE_SETPM", 107207499Smav "PROBE_SETAPST", 108207499Smav "PROBE_SETDMAAA", 109220602Smav "PROBE_SETAN", 110198708Smav "PROBE_SET_MULTI", 111195534Sscottl "PROBE_INQUIRY", 112195534Sscottl "PROBE_FULL_INQUIRY", 113195534Sscottl "PROBE_PM_PID", 114195534Sscottl "PROBE_PM_PRV", 115235897Smav "PROBE_IDENTIFY_SES", 116235897Smav "PROBE_IDENTIFY_SAFTE", 117195534Sscottl "PROBE_INVALID" 118195534Sscottl}; 119195534Sscottl 120195534Sscottl#define PROBE_SET_ACTION(softc, newaction) \ 121195534Sscottldo { \ 122195534Sscottl char **text; \ 123195534Sscottl text = probe_action_text; \ 124195534Sscottl CAM_DEBUG((softc)->periph->path, CAM_DEBUG_INFO, \ 125195534Sscottl ("Probe %s to %s\n", text[(softc)->action], \ 126195534Sscottl text[(newaction)])); \ 127195534Sscottl (softc)->action = (newaction); \ 128195534Sscottl} while(0) 129195534Sscottl 130195534Sscottltypedef enum { 131195534Sscottl PROBE_NO_ANNOUNCE = 0x04 132195534Sscottl} probe_flags; 133195534Sscottl 134195534Sscottltypedef struct { 135195534Sscottl TAILQ_HEAD(, ccb_hdr) request_ccbs; 136203385Smav struct ata_params ident_data; 137195534Sscottl probe_action action; 138195534Sscottl probe_flags flags; 139195534Sscottl uint32_t pm_pid; 140195534Sscottl uint32_t pm_prv; 141203108Smav int restart; 142203421Smav int spinup; 143209744Smav int faults; 144207499Smav u_int caps; 145195534Sscottl struct cam_periph *periph; 146195534Sscottl} probe_softc; 147195534Sscottl 148199178Smavstatic struct ata_quirk_entry ata_quirk_table[] = 149195534Sscottl{ 150195534Sscottl { 151195534Sscottl /* Default tagged queuing parameters for all devices */ 152195534Sscottl { 153195534Sscottl T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED, 154195534Sscottl /*vendor*/"*", /*product*/"*", /*revision*/"*" 155195534Sscottl }, 156199178Smav /*quirks*/0, /*maxtags*/0 157195534Sscottl }, 158195534Sscottl}; 159195534Sscottl 160199178Smavstatic const int ata_quirk_table_size = 161199178Smav sizeof(ata_quirk_table) / sizeof(*ata_quirk_table); 162195534Sscottl 163195534Sscottlstatic cam_status proberegister(struct cam_periph *periph, 164195534Sscottl void *arg); 165195534Sscottlstatic void probeschedule(struct cam_periph *probe_periph); 166195534Sscottlstatic void probestart(struct cam_periph *periph, union ccb *start_ccb); 167195534Sscottl//static void proberequestdefaultnegotiation(struct cam_periph *periph); 168195534Sscottl//static int proberequestbackoff(struct cam_periph *periph, 169195534Sscottl// struct cam_ed *device); 170195534Sscottlstatic void probedone(struct cam_periph *periph, union ccb *done_ccb); 171195534Sscottlstatic void probecleanup(struct cam_periph *periph); 172199178Smavstatic void ata_find_quirk(struct cam_ed *device); 173195534Sscottlstatic void ata_scan_bus(struct cam_periph *periph, union ccb *ccb); 174195534Sscottlstatic void ata_scan_lun(struct cam_periph *periph, 175195534Sscottl struct cam_path *path, cam_flags flags, 176195534Sscottl union ccb *ccb); 177195534Sscottlstatic void xptscandone(struct cam_periph *periph, union ccb *done_ccb); 178195534Sscottlstatic struct cam_ed * 179195534Sscottl ata_alloc_device(struct cam_eb *bus, struct cam_et *target, 180195534Sscottl lun_id_t lun_id); 181195534Sscottlstatic void ata_device_transport(struct cam_path *path); 182199178Smavstatic void ata_set_transfer_settings(struct ccb_trans_settings *cts, 183195534Sscottl struct cam_ed *device, 184195534Sscottl int async_update); 185195534Sscottlstatic void ata_dev_async(u_int32_t async_code, 186195534Sscottl struct cam_eb *bus, 187195534Sscottl struct cam_et *target, 188195534Sscottl struct cam_ed *device, 189195534Sscottl void *async_arg); 190195534Sscottlstatic void ata_action(union ccb *start_ccb); 191204220Smavstatic void ata_announce_periph(struct cam_periph *periph); 192195534Sscottl 193230912Smavstatic int ata_dma = 1; 194230912Smavstatic int atapi_dma = 1; 195230912Smav 196230912SmavTUNABLE_INT("hw.ata.ata_dma", &ata_dma); 197230912SmavTUNABLE_INT("hw.ata.atapi_dma", &atapi_dma); 198230912Smav 199195534Sscottlstatic struct xpt_xport ata_xport = { 200195534Sscottl .alloc_device = ata_alloc_device, 201195534Sscottl .action = ata_action, 202195534Sscottl .async = ata_dev_async, 203204220Smav .announce = ata_announce_periph, 204195534Sscottl}; 205195534Sscottl 206195534Sscottlstruct xpt_xport * 207195534Sscottlata_get_xport(void) 208195534Sscottl{ 209195534Sscottl return (&ata_xport); 210195534Sscottl} 211195534Sscottl 212195534Sscottlstatic void 213195534Sscottlprobe_periph_init() 214195534Sscottl{ 215195534Sscottl} 216195534Sscottl 217195534Sscottlstatic cam_status 218195534Sscottlproberegister(struct cam_periph *periph, void *arg) 219195534Sscottl{ 220195534Sscottl union ccb *request_ccb; /* CCB representing the probe request */ 221195534Sscottl cam_status status; 222195534Sscottl probe_softc *softc; 223195534Sscottl 224195534Sscottl request_ccb = (union ccb *)arg; 225195534Sscottl if (periph == NULL) { 226195534Sscottl printf("proberegister: periph was NULL!!\n"); 227195534Sscottl return(CAM_REQ_CMP_ERR); 228195534Sscottl } 229195534Sscottl 230195534Sscottl if (request_ccb == NULL) { 231195534Sscottl printf("proberegister: no probe CCB, " 232195534Sscottl "can't register device\n"); 233195534Sscottl return(CAM_REQ_CMP_ERR); 234195534Sscottl } 235195534Sscottl 236203421Smav softc = (probe_softc *)malloc(sizeof(*softc), M_CAMXPT, M_ZERO | M_NOWAIT); 237195534Sscottl 238195534Sscottl if (softc == NULL) { 239195534Sscottl printf("proberegister: Unable to probe new device. " 240195534Sscottl "Unable to allocate softc\n"); 241195534Sscottl return(CAM_REQ_CMP_ERR); 242195534Sscottl } 243195534Sscottl TAILQ_INIT(&softc->request_ccbs); 244195534Sscottl TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h, 245195534Sscottl periph_links.tqe); 246195534Sscottl softc->flags = 0; 247195534Sscottl periph->softc = softc; 248195534Sscottl softc->periph = periph; 249195534Sscottl softc->action = PROBE_INVALID; 250195534Sscottl status = cam_periph_acquire(periph); 251195534Sscottl if (status != CAM_REQ_CMP) { 252195534Sscottl return (status); 253195534Sscottl } 254195534Sscottl /* 255203108Smav * Ensure nobody slip in until probe finish. 256195534Sscottl */ 257203108Smav cam_freeze_devq_arg(periph->path, 258203108Smav RELSIM_RELEASE_RUNLEVEL, CAM_RL_XPT + 1); 259195534Sscottl probeschedule(periph); 260195534Sscottl return(CAM_REQ_CMP); 261195534Sscottl} 262195534Sscottl 263195534Sscottlstatic void 264195534Sscottlprobeschedule(struct cam_periph *periph) 265195534Sscottl{ 266195534Sscottl union ccb *ccb; 267195534Sscottl probe_softc *softc; 268195534Sscottl 269195534Sscottl softc = (probe_softc *)periph->softc; 270195534Sscottl ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs); 271195534Sscottl 272198389Smav if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) || 273235897Smav periph->path->device->protocol == PROTO_SATAPM || 274235897Smav periph->path->device->protocol == PROTO_SEMB) 275195534Sscottl PROBE_SET_ACTION(softc, PROBE_RESET); 276195534Sscottl else 277195534Sscottl PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 278195534Sscottl 279195534Sscottl if (ccb->crcn.flags & CAM_EXPECT_INQ_CHANGE) 280195534Sscottl softc->flags |= PROBE_NO_ANNOUNCE; 281195534Sscottl else 282195534Sscottl softc->flags &= ~PROBE_NO_ANNOUNCE; 283195534Sscottl 284203108Smav xpt_schedule(periph, CAM_PRIORITY_XPT); 285195534Sscottl} 286195534Sscottl 287195534Sscottlstatic void 288195534Sscottlprobestart(struct cam_periph *periph, union ccb *start_ccb) 289195534Sscottl{ 290199747Smav struct ccb_trans_settings cts; 291195534Sscottl struct ccb_ataio *ataio; 292195534Sscottl struct ccb_scsiio *csio; 293195534Sscottl probe_softc *softc; 294198708Smav struct cam_path *path; 295198708Smav struct ata_params *ident_buf; 296195534Sscottl 297195534Sscottl CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probestart\n")); 298195534Sscottl 299195534Sscottl softc = (probe_softc *)periph->softc; 300198708Smav path = start_ccb->ccb_h.path; 301195534Sscottl ataio = &start_ccb->ataio; 302195534Sscottl csio = &start_ccb->csio; 303198708Smav ident_buf = &periph->path->device->ident_data; 304195534Sscottl 305203108Smav if (softc->restart) { 306203108Smav softc->restart = 0; 307203108Smav if ((path->device->flags & CAM_DEV_UNCONFIGURED) || 308235897Smav path->device->protocol == PROTO_SATAPM || 309235897Smav path->device->protocol == PROTO_SEMB) 310203108Smav softc->action = PROBE_RESET; 311203108Smav else 312203108Smav softc->action = PROBE_IDENTIFY; 313203108Smav } 314195534Sscottl switch (softc->action) { 315195534Sscottl case PROBE_RESET: 316195534Sscottl cam_fill_ataio(ataio, 317195534Sscottl 0, 318195534Sscottl probedone, 319195534Sscottl /*flags*/CAM_DIR_NONE, 320198389Smav 0, 321195534Sscottl /*data_ptr*/NULL, 322195534Sscottl /*dxfer_len*/0, 323203108Smav 15 * 1000); 324195534Sscottl ata_reset_cmd(ataio); 325195534Sscottl break; 326195534Sscottl case PROBE_IDENTIFY: 327195534Sscottl cam_fill_ataio(ataio, 328195534Sscottl 1, 329195534Sscottl probedone, 330195534Sscottl /*flags*/CAM_DIR_IN, 331198389Smav 0, 332203385Smav /*data_ptr*/(u_int8_t *)&softc->ident_data, 333203385Smav /*dxfer_len*/sizeof(softc->ident_data), 334195534Sscottl 30 * 1000); 335195534Sscottl if (periph->path->device->protocol == PROTO_ATA) 336196659Smav ata_28bit_cmd(ataio, ATA_ATA_IDENTIFY, 0, 0, 0); 337195534Sscottl else 338196659Smav ata_28bit_cmd(ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0); 339195534Sscottl break; 340203421Smav case PROBE_SPINUP: 341203421Smav if (bootverbose) 342203421Smav xpt_print(path, "Spinning up device\n"); 343203421Smav cam_fill_ataio(ataio, 344203421Smav 1, 345203421Smav probedone, 346203421Smav /*flags*/CAM_DIR_NONE | CAM_HIGH_POWER, 347203421Smav 0, 348203421Smav /*data_ptr*/NULL, 349203421Smav /*dxfer_len*/0, 350203421Smav 30 * 1000); 351203421Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_PUIS_SPINUP, 0, 0); 352203421Smav break; 353195534Sscottl case PROBE_SETMODE: 354199747Smav { 355199747Smav int mode, wantmode; 356199747Smav 357199747Smav mode = 0; 358199747Smav /* Fetch user modes from SIM. */ 359199747Smav bzero(&cts, sizeof(cts)); 360203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 361199747Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 362199747Smav cts.type = CTS_TYPE_USER_SETTINGS; 363199747Smav xpt_action((union ccb *)&cts); 364199747Smav if (path->device->transport == XPORT_ATA) { 365199747Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_MODE) 366199747Smav mode = cts.xport_specific.ata.mode; 367199747Smav } else { 368199799Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_MODE) 369199747Smav mode = cts.xport_specific.sata.mode; 370199747Smav } 371230912Smav if (periph->path->device->protocol == PROTO_ATA) { 372230912Smav if (ata_dma == 0 && (mode == 0 || mode > ATA_PIO_MAX)) 373230912Smav mode = ATA_PIO_MAX; 374230912Smav } else { 375230912Smav if (atapi_dma == 0 && (mode == 0 || mode > ATA_PIO_MAX)) 376230912Smav mode = ATA_PIO_MAX; 377230912Smav } 378199747Smavnegotiate: 379199747Smav /* Honor device capabilities. */ 380199747Smav wantmode = mode = ata_max_mode(ident_buf, mode); 381199747Smav /* Report modes to SIM. */ 382199747Smav bzero(&cts, sizeof(cts)); 383203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 384199747Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 385199747Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 386199747Smav if (path->device->transport == XPORT_ATA) { 387199747Smav cts.xport_specific.ata.mode = mode; 388199747Smav cts.xport_specific.ata.valid = CTS_ATA_VALID_MODE; 389199747Smav } else { 390199747Smav cts.xport_specific.sata.mode = mode; 391199747Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_MODE; 392199747Smav } 393199747Smav xpt_action((union ccb *)&cts); 394200171Smav /* Fetch current modes from SIM. */ 395199747Smav bzero(&cts, sizeof(cts)); 396203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 397199747Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 398199747Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 399199747Smav xpt_action((union ccb *)&cts); 400199747Smav if (path->device->transport == XPORT_ATA) { 401199747Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_MODE) 402199747Smav mode = cts.xport_specific.ata.mode; 403199747Smav } else { 404199747Smav if (cts.xport_specific.ata.valid & CTS_SATA_VALID_MODE) 405199747Smav mode = cts.xport_specific.sata.mode; 406199747Smav } 407199747Smav /* If SIM disagree - renegotiate. */ 408199747Smav if (mode != wantmode) 409199747Smav goto negotiate; 410220886Smav /* Remember what transport thinks about DMA. */ 411220886Smav if (mode < ATA_DMA) 412220886Smav path->device->inq_flags &= ~SID_DMA; 413220886Smav else 414220886Smav path->device->inq_flags |= SID_DMA; 415195534Sscottl cam_fill_ataio(ataio, 416195534Sscottl 1, 417195534Sscottl probedone, 418196353Smav /*flags*/CAM_DIR_NONE, 419196353Smav 0, 420196353Smav /*data_ptr*/NULL, 421196353Smav /*dxfer_len*/0, 422195534Sscottl 30 * 1000); 423199747Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); 424195534Sscottl break; 425199747Smav } 426207499Smav case PROBE_SETPM: 427207499Smav cam_fill_ataio(ataio, 428207499Smav 1, 429207499Smav probedone, 430207499Smav CAM_DIR_NONE, 431207499Smav 0, 432207499Smav NULL, 433207499Smav 0, 434207499Smav 30*1000); 435207499Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, 436207499Smav (softc->caps & CTS_SATA_CAPS_H_PMREQ) ? 0x10 : 0x90, 437207499Smav 0, 0x03); 438207499Smav break; 439207499Smav case PROBE_SETAPST: 440207499Smav cam_fill_ataio(ataio, 441207499Smav 1, 442207499Smav probedone, 443207499Smav CAM_DIR_NONE, 444207499Smav 0, 445207499Smav NULL, 446207499Smav 0, 447207499Smav 30*1000); 448207499Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, 449207499Smav (softc->caps & CTS_SATA_CAPS_H_APST) ? 0x10 : 0x90, 450207499Smav 0, 0x07); 451207499Smav break; 452207499Smav case PROBE_SETDMAAA: 453207499Smav cam_fill_ataio(ataio, 454207499Smav 1, 455207499Smav probedone, 456207499Smav CAM_DIR_NONE, 457207499Smav 0, 458207499Smav NULL, 459207499Smav 0, 460207499Smav 30*1000); 461207499Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, 462207499Smav (softc->caps & CTS_SATA_CAPS_H_DMAAA) ? 0x10 : 0x90, 463207499Smav 0, 0x02); 464207499Smav break; 465220602Smav case PROBE_SETAN: 466220602Smav cam_fill_ataio(ataio, 467220602Smav 1, 468220602Smav probedone, 469220602Smav CAM_DIR_NONE, 470220602Smav 0, 471220602Smav NULL, 472220602Smav 0, 473220602Smav 30*1000); 474220602Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, 475220602Smav (softc->caps & CTS_SATA_CAPS_H_AN) ? 0x10 : 0x90, 476220602Smav 0, 0x05); 477220602Smav break; 478198708Smav case PROBE_SET_MULTI: 479198708Smav { 480200171Smav u_int sectors, bytecount; 481198708Smav 482200171Smav bytecount = 8192; /* SATA maximum */ 483200171Smav /* Fetch user bytecount from SIM. */ 484200171Smav bzero(&cts, sizeof(cts)); 485203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 486200171Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 487200171Smav cts.type = CTS_TYPE_USER_SETTINGS; 488200171Smav xpt_action((union ccb *)&cts); 489200171Smav if (path->device->transport == XPORT_ATA) { 490200171Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 491200171Smav bytecount = cts.xport_specific.ata.bytecount; 492200171Smav } else { 493200171Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 494200171Smav bytecount = cts.xport_specific.sata.bytecount; 495200171Smav } 496200171Smav /* Honor device capabilities. */ 497200171Smav sectors = max(1, min(ident_buf->sectors_intr & 0xff, 498200171Smav bytecount / ata_logical_sector_size(ident_buf))); 499198708Smav /* Report bytecount to SIM. */ 500198708Smav bzero(&cts, sizeof(cts)); 501203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 502198708Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 503198708Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 504198708Smav if (path->device->transport == XPORT_ATA) { 505198897Smav cts.xport_specific.ata.bytecount = sectors * 506198897Smav ata_logical_sector_size(ident_buf); 507198708Smav cts.xport_specific.ata.valid = CTS_ATA_VALID_BYTECOUNT; 508198708Smav } else { 509198897Smav cts.xport_specific.sata.bytecount = sectors * 510198897Smav ata_logical_sector_size(ident_buf); 511198708Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_BYTECOUNT; 512198708Smav } 513198708Smav xpt_action((union ccb *)&cts); 514200171Smav /* Fetch current bytecount from SIM. */ 515200171Smav bzero(&cts, sizeof(cts)); 516203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 517200171Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 518200171Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 519200171Smav xpt_action((union ccb *)&cts); 520200171Smav if (path->device->transport == XPORT_ATA) { 521200171Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 522200171Smav bytecount = cts.xport_specific.ata.bytecount; 523200171Smav } else { 524200171Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 525200171Smav bytecount = cts.xport_specific.sata.bytecount; 526200171Smav } 527200171Smav sectors = bytecount / ata_logical_sector_size(ident_buf); 528198708Smav 529198708Smav cam_fill_ataio(ataio, 530198708Smav 1, 531198708Smav probedone, 532198708Smav CAM_DIR_NONE, 533198708Smav 0, 534198708Smav NULL, 535198708Smav 0, 536198708Smav 30*1000); 537198708Smav ata_28bit_cmd(ataio, ATA_SET_MULTI, 0, 0, sectors); 538198708Smav break; 539195534Sscottl } 540195534Sscottl case PROBE_INQUIRY: 541200171Smav { 542200171Smav u_int bytecount; 543200171Smav 544200171Smav bytecount = 8192; /* SATA maximum */ 545200171Smav /* Fetch user bytecount from SIM. */ 546200171Smav bzero(&cts, sizeof(cts)); 547203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 548200171Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 549200171Smav cts.type = CTS_TYPE_USER_SETTINGS; 550200171Smav xpt_action((union ccb *)&cts); 551200171Smav if (path->device->transport == XPORT_ATA) { 552200171Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 553200171Smav bytecount = cts.xport_specific.ata.bytecount; 554200171Smav } else { 555200171Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 556200171Smav bytecount = cts.xport_specific.sata.bytecount; 557200171Smav } 558200171Smav /* Honor device capabilities. */ 559200171Smav bytecount &= ~1; 560200171Smav bytecount = max(2, min(65534, bytecount)); 561200171Smav if (ident_buf->satacapabilities != 0x0000 && 562200171Smav ident_buf->satacapabilities != 0xffff) { 563200171Smav bytecount = min(8192, bytecount); 564200171Smav } 565200171Smav /* Report bytecount to SIM. */ 566200171Smav bzero(&cts, sizeof(cts)); 567203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 568200171Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 569200171Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 570200171Smav if (path->device->transport == XPORT_ATA) { 571200171Smav cts.xport_specific.ata.bytecount = bytecount; 572200171Smav cts.xport_specific.ata.valid = CTS_ATA_VALID_BYTECOUNT; 573200171Smav } else { 574200171Smav cts.xport_specific.sata.bytecount = bytecount; 575200171Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_BYTECOUNT; 576200171Smav } 577200171Smav xpt_action((union ccb *)&cts); 578200171Smav /* FALLTHROUGH */ 579200171Smav } 580195534Sscottl case PROBE_FULL_INQUIRY: 581195534Sscottl { 582195534Sscottl u_int inquiry_len; 583195534Sscottl struct scsi_inquiry_data *inq_buf = 584195534Sscottl &periph->path->device->inq_data; 585195534Sscottl 586195534Sscottl if (softc->action == PROBE_INQUIRY) 587195534Sscottl inquiry_len = SHORT_INQUIRY_LENGTH; 588195534Sscottl else 589195534Sscottl inquiry_len = SID_ADDITIONAL_LENGTH(inq_buf); 590195534Sscottl /* 591195534Sscottl * Some parallel SCSI devices fail to send an 592195534Sscottl * ignore wide residue message when dealing with 593195534Sscottl * odd length inquiry requests. Round up to be 594195534Sscottl * safe. 595195534Sscottl */ 596195534Sscottl inquiry_len = roundup2(inquiry_len, 2); 597195534Sscottl scsi_inquiry(csio, 598195534Sscottl /*retries*/1, 599195534Sscottl probedone, 600195534Sscottl MSG_SIMPLE_Q_TAG, 601195534Sscottl (u_int8_t *)inq_buf, 602195534Sscottl inquiry_len, 603195534Sscottl /*evpd*/FALSE, 604195534Sscottl /*page_code*/0, 605195534Sscottl SSD_MIN_SIZE, 606195534Sscottl /*timeout*/60 * 1000); 607195534Sscottl break; 608195534Sscottl } 609195534Sscottl case PROBE_PM_PID: 610195534Sscottl cam_fill_ataio(ataio, 611195534Sscottl 1, 612195534Sscottl probedone, 613195534Sscottl /*flags*/CAM_DIR_NONE, 614198389Smav 0, 615195534Sscottl /*data_ptr*/NULL, 616195534Sscottl /*dxfer_len*/0, 617195534Sscottl 10 * 1000); 618195534Sscottl ata_pm_read_cmd(ataio, 0, 15); 619195534Sscottl break; 620195534Sscottl case PROBE_PM_PRV: 621195534Sscottl cam_fill_ataio(ataio, 622195534Sscottl 1, 623195534Sscottl probedone, 624195534Sscottl /*flags*/CAM_DIR_NONE, 625198389Smav 0, 626195534Sscottl /*data_ptr*/NULL, 627195534Sscottl /*dxfer_len*/0, 628195534Sscottl 10 * 1000); 629195534Sscottl ata_pm_read_cmd(ataio, 1, 15); 630195534Sscottl break; 631235897Smav case PROBE_IDENTIFY_SES: 632235897Smav cam_fill_ataio(ataio, 633235897Smav 1, 634235897Smav probedone, 635235897Smav /*flags*/CAM_DIR_IN, 636235897Smav 0, 637235897Smav /*data_ptr*/(u_int8_t *)&softc->ident_data, 638235897Smav /*dxfer_len*/sizeof(softc->ident_data), 639235897Smav 30 * 1000); 640235897Smav ata_28bit_cmd(ataio, ATA_SEP_ATTN, 0xEC, 0x02, 641235897Smav sizeof(softc->ident_data) / 4); 642235897Smav break; 643235897Smav case PROBE_IDENTIFY_SAFTE: 644235897Smav cam_fill_ataio(ataio, 645235897Smav 1, 646235897Smav probedone, 647235897Smav /*flags*/CAM_DIR_IN, 648235897Smav 0, 649235897Smav /*data_ptr*/(u_int8_t *)&softc->ident_data, 650235897Smav /*dxfer_len*/sizeof(softc->ident_data), 651235897Smav 30 * 1000); 652235897Smav ata_28bit_cmd(ataio, ATA_SEP_ATTN, 0xEC, 0x00, 653235897Smav sizeof(softc->ident_data) / 4); 654235897Smav break; 655195534Sscottl case PROBE_INVALID: 656198708Smav CAM_DEBUG(path, CAM_DEBUG_INFO, 657195534Sscottl ("probestart: invalid action state\n")); 658195534Sscottl default: 659195534Sscottl break; 660195534Sscottl } 661195534Sscottl xpt_action(start_ccb); 662195534Sscottl} 663195534Sscottl#if 0 664195534Sscottlstatic void 665195534Sscottlproberequestdefaultnegotiation(struct cam_periph *periph) 666195534Sscottl{ 667195534Sscottl struct ccb_trans_settings cts; 668195534Sscottl 669203108Smav xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE); 670195534Sscottl cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 671195534Sscottl cts.type = CTS_TYPE_USER_SETTINGS; 672195534Sscottl xpt_action((union ccb *)&cts); 673195534Sscottl if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 674195534Sscottl return; 675195534Sscottl } 676195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 677195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 678195534Sscottl xpt_action((union ccb *)&cts); 679195534Sscottl} 680195534Sscottl 681195534Sscottl/* 682195534Sscottl * Backoff Negotiation Code- only pertinent for SPI devices. 683195534Sscottl */ 684195534Sscottlstatic int 685195534Sscottlproberequestbackoff(struct cam_periph *periph, struct cam_ed *device) 686195534Sscottl{ 687195534Sscottl struct ccb_trans_settings cts; 688195534Sscottl struct ccb_trans_settings_spi *spi; 689195534Sscottl 690195534Sscottl memset(&cts, 0, sizeof (cts)); 691203108Smav xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE); 692195534Sscottl cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 693195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 694195534Sscottl xpt_action((union ccb *)&cts); 695195534Sscottl if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 696195534Sscottl if (bootverbose) { 697195534Sscottl xpt_print(periph->path, 698195534Sscottl "failed to get current device settings\n"); 699195534Sscottl } 700195534Sscottl return (0); 701195534Sscottl } 702195534Sscottl if (cts.transport != XPORT_SPI) { 703195534Sscottl if (bootverbose) { 704195534Sscottl xpt_print(periph->path, "not SPI transport\n"); 705195534Sscottl } 706195534Sscottl return (0); 707195534Sscottl } 708195534Sscottl spi = &cts.xport_specific.spi; 709195534Sscottl 710195534Sscottl /* 711195534Sscottl * We cannot renegotiate sync rate if we don't have one. 712195534Sscottl */ 713195534Sscottl if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) { 714195534Sscottl if (bootverbose) { 715195534Sscottl xpt_print(periph->path, "no sync rate known\n"); 716195534Sscottl } 717195534Sscottl return (0); 718195534Sscottl } 719195534Sscottl 720195534Sscottl /* 721195534Sscottl * We'll assert that we don't have to touch PPR options- the 722195534Sscottl * SIM will see what we do with period and offset and adjust 723195534Sscottl * the PPR options as appropriate. 724195534Sscottl */ 725195534Sscottl 726195534Sscottl /* 727195534Sscottl * A sync rate with unknown or zero offset is nonsensical. 728195534Sscottl * A sync period of zero means Async. 729195534Sscottl */ 730195534Sscottl if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0 731195534Sscottl || spi->sync_offset == 0 || spi->sync_period == 0) { 732195534Sscottl if (bootverbose) { 733195534Sscottl xpt_print(periph->path, "no sync rate available\n"); 734195534Sscottl } 735195534Sscottl return (0); 736195534Sscottl } 737195534Sscottl 738195534Sscottl if (device->flags & CAM_DEV_DV_HIT_BOTTOM) { 739195534Sscottl CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 740195534Sscottl ("hit async: giving up on DV\n")); 741195534Sscottl return (0); 742195534Sscottl } 743195534Sscottl 744195534Sscottl 745195534Sscottl /* 746195534Sscottl * Jump sync_period up by one, but stop at 5MHz and fall back to Async. 747195534Sscottl * We don't try to remember 'last' settings to see if the SIM actually 748195534Sscottl * gets into the speed we want to set. We check on the SIM telling 749195534Sscottl * us that a requested speed is bad, but otherwise don't try and 750195534Sscottl * check the speed due to the asynchronous and handshake nature 751195534Sscottl * of speed setting. 752195534Sscottl */ 753195534Sscottl spi->valid = CTS_SPI_VALID_SYNC_RATE | CTS_SPI_VALID_SYNC_OFFSET; 754195534Sscottl for (;;) { 755195534Sscottl spi->sync_period++; 756195534Sscottl if (spi->sync_period >= 0xf) { 757195534Sscottl spi->sync_period = 0; 758195534Sscottl spi->sync_offset = 0; 759195534Sscottl CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 760195534Sscottl ("setting to async for DV\n")); 761195534Sscottl /* 762195534Sscottl * Once we hit async, we don't want to try 763195534Sscottl * any more settings. 764195534Sscottl */ 765195534Sscottl device->flags |= CAM_DEV_DV_HIT_BOTTOM; 766195534Sscottl } else if (bootverbose) { 767195534Sscottl CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 768195534Sscottl ("DV: period 0x%x\n", spi->sync_period)); 769195534Sscottl printf("setting period to 0x%x\n", spi->sync_period); 770195534Sscottl } 771195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 772195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 773195534Sscottl xpt_action((union ccb *)&cts); 774195534Sscottl if ((cts.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { 775195534Sscottl break; 776195534Sscottl } 777195534Sscottl CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 778195534Sscottl ("DV: failed to set period 0x%x\n", spi->sync_period)); 779195534Sscottl if (spi->sync_period == 0) { 780195534Sscottl return (0); 781195534Sscottl } 782195534Sscottl } 783195534Sscottl return (1); 784195534Sscottl} 785195534Sscottl#endif 786195534Sscottlstatic void 787195534Sscottlprobedone(struct cam_periph *periph, union ccb *done_ccb) 788195534Sscottl{ 789199747Smav struct ccb_trans_settings cts; 790195534Sscottl struct ata_params *ident_buf; 791235897Smav struct scsi_inquiry_data *inq_buf; 792195534Sscottl probe_softc *softc; 793195534Sscottl struct cam_path *path; 794217444Smav cam_status status; 795195534Sscottl u_int32_t priority; 796207499Smav u_int caps; 797235897Smav int changed = 1, found = 1; 798235897Smav static const uint8_t fake_device_id_hdr[8] = 799235897Smav {0, SVPD_DEVICE_ID, 0, 12, 800235897Smav SVPD_ID_CODESET_BINARY, SVPD_ID_TYPE_NAA, 0, 8}; 801195534Sscottl 802195534Sscottl CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probedone\n")); 803195534Sscottl 804195534Sscottl softc = (probe_softc *)periph->softc; 805195534Sscottl path = done_ccb->ccb_h.path; 806195534Sscottl priority = done_ccb->ccb_h.pinfo.priority; 807195534Sscottl ident_buf = &path->device->ident_data; 808235897Smav inq_buf = &path->device->inq_data; 809195534Sscottl 810198708Smav if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 811209744Smav if (softc->restart) { 812209744Smav if (bootverbose) { 813209744Smav cam_error_print(done_ccb, 814209744Smav CAM_ESF_ALL, CAM_EPF_ALL); 815209744Smav } 816209744Smav } else if (cam_periph_error(done_ccb, 0, 0, NULL) == ERESTART) 817195534Sscottl return; 818209744Smav if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 819195534Sscottl /* Don't wedge the queue */ 820195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 821195534Sscottl /*run_queue*/TRUE); 822195534Sscottl } 823217444Smav status = done_ccb->ccb_h.status & CAM_STATUS_MASK; 824209744Smav if (softc->restart) { 825209744Smav softc->faults++; 826209744Smav if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == 827209744Smav CAM_CMD_TIMEOUT) 828209744Smav softc->faults += 4; 829209744Smav if (softc->faults < 10) 830209744Smav goto done; 831209744Smav else 832209744Smav softc->restart = 0; 833217444Smav 834198708Smav /* Old PIO2 devices may not support mode setting. */ 835217444Smav } else if (softc->action == PROBE_SETMODE && 836217444Smav status == CAM_ATA_STATUS_ERROR && 837198708Smav ata_max_pmode(ident_buf) <= ATA_PIO2 && 838217444Smav (ident_buf->capabilities1 & ATA_SUPPORT_IORDY) == 0) { 839198708Smav goto noerror; 840217444Smav 841198708Smav /* 842217444Smav * Some old WD SATA disks report supported and enabled 843217444Smav * device-initiated interface power management, but return 844217444Smav * ABORT on attempt to disable it. 845217444Smav */ 846217444Smav } else if (softc->action == PROBE_SETPM && 847217444Smav status == CAM_ATA_STATUS_ERROR) { 848217444Smav goto noerror; 849217875Smav 850217875Smav /* 851217875Smav * Some HP SATA disks report supported DMA Auto-Activation, 852217875Smav * but return ABORT on attempt to enable it. 853217875Smav */ 854217875Smav } else if (softc->action == PROBE_SETDMAAA && 855217875Smav status == CAM_ATA_STATUS_ERROR) { 856217875Smav goto noerror; 857235897Smav 858235897Smav /* 859235897Smav * SES and SAF-TE SEPs have different IDENTIFY commands, 860235897Smav * but SATA specification doesn't tell how to identify them. 861235897Smav * Until better way found, just try another if first fail. 862235897Smav */ 863235897Smav } else if (softc->action == PROBE_IDENTIFY_SES && 864235897Smav status == CAM_ATA_STATUS_ERROR) { 865235897Smav PROBE_SET_ACTION(softc, PROBE_IDENTIFY_SAFTE); 866235897Smav xpt_release_ccb(done_ccb); 867235897Smav xpt_schedule(periph, priority); 868235897Smav return; 869217444Smav } 870217444Smav 871217444Smav /* 872198708Smav * If we get to this point, we got an error status back 873198708Smav * from the inquiry and the error status doesn't require 874198708Smav * automatically retrying the command. Therefore, the 875198708Smav * inquiry failed. If we had inquiry information before 876198708Smav * for this device, but this latest inquiry command failed, 877198708Smav * the device has probably gone away. If this device isn't 878198708Smav * already marked unconfigured, notify the peripheral 879198708Smav * drivers that this device is no more. 880198708Smav */ 881209744Smavdevice_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0) 882198708Smav xpt_async(AC_LOST_DEVICE, path, NULL); 883198708Smav found = 0; 884198708Smav goto done; 885198708Smav } 886198708Smavnoerror: 887203385Smav if (softc->restart) 888203385Smav goto done; 889198708Smav switch (softc->action) { 890198708Smav case PROBE_RESET: 891195534Sscottl { 892198708Smav int sign = (done_ccb->ataio.res.lba_high << 8) + 893198708Smav done_ccb->ataio.res.lba_mid; 894200218Smav if (bootverbose) 895200218Smav xpt_print(path, "SIGNATURE: %04x\n", sign); 896198708Smav if (sign == 0x0000 && 897198708Smav done_ccb->ccb_h.target_id != 15) { 898198708Smav path->device->protocol = PROTO_ATA; 899198708Smav PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 900198708Smav } else if (sign == 0x9669 && 901198708Smav done_ccb->ccb_h.target_id == 15) { 902199747Smav /* Report SIM that PM is present. */ 903198708Smav bzero(&cts, sizeof(cts)); 904203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 905198708Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 906198708Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 907198708Smav cts.xport_specific.sata.pm_present = 1; 908198708Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; 909198708Smav xpt_action((union ccb *)&cts); 910198708Smav path->device->protocol = PROTO_SATAPM; 911198708Smav PROBE_SET_ACTION(softc, PROBE_PM_PID); 912235897Smav } else if (sign == 0xc33c && 913235897Smav done_ccb->ccb_h.target_id != 15) { 914235897Smav path->device->protocol = PROTO_SEMB; 915235897Smav PROBE_SET_ACTION(softc, PROBE_IDENTIFY_SES); 916198708Smav } else if (sign == 0xeb14 && 917198708Smav done_ccb->ccb_h.target_id != 15) { 918198708Smav path->device->protocol = PROTO_SCSI; 919198708Smav PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 920198708Smav } else { 921198708Smav if (done_ccb->ccb_h.target_id != 15) { 922198708Smav xpt_print(path, 923198708Smav "Unexpected signature 0x%04x\n", sign); 924195534Sscottl } 925198708Smav goto device_fail; 926198708Smav } 927198708Smav xpt_release_ccb(done_ccb); 928198708Smav xpt_schedule(periph, priority); 929198708Smav return; 930198708Smav } 931198708Smav case PROBE_IDENTIFY: 932198708Smav { 933207222Smav struct ccb_pathinq cpi; 934198708Smav int16_t *ptr; 935195534Sscottl 936203385Smav ident_buf = &softc->ident_data; 937198708Smav for (ptr = (int16_t *)ident_buf; 938198708Smav ptr < (int16_t *)ident_buf + sizeof(struct ata_params)/2; ptr++) { 939198708Smav *ptr = le16toh(*ptr); 940198708Smav } 941198708Smav if (strncmp(ident_buf->model, "FX", 2) && 942198708Smav strncmp(ident_buf->model, "NEC", 3) && 943198708Smav strncmp(ident_buf->model, "Pioneer", 7) && 944198708Smav strncmp(ident_buf->model, "SHARP", 5)) { 945198708Smav ata_bswap(ident_buf->model, sizeof(ident_buf->model)); 946198708Smav ata_bswap(ident_buf->revision, sizeof(ident_buf->revision)); 947198708Smav ata_bswap(ident_buf->serial, sizeof(ident_buf->serial)); 948198708Smav } 949198708Smav ata_btrim(ident_buf->model, sizeof(ident_buf->model)); 950198708Smav ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model)); 951198708Smav ata_btrim(ident_buf->revision, sizeof(ident_buf->revision)); 952198708Smav ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision)); 953198708Smav ata_btrim(ident_buf->serial, sizeof(ident_buf->serial)); 954198708Smav ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial)); 955203421Smav /* Device may need spin-up before IDENTIFY become valid. */ 956204354Smav if ((ident_buf->specconf == 0x37c8 || 957204354Smav ident_buf->specconf == 0x738c) && 958204354Smav ((ident_buf->config & ATA_RESP_INCOMPLETE) || 959204354Smav softc->spinup == 0)) { 960203421Smav PROBE_SET_ACTION(softc, PROBE_SPINUP); 961203421Smav xpt_release_ccb(done_ccb); 962203421Smav xpt_schedule(periph, priority); 963203421Smav return; 964203421Smav } 965203385Smav ident_buf = &path->device->ident_data; 966198708Smav if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) { 967198708Smav /* Check that it is the same device. */ 968203385Smav if (bcmp(softc->ident_data.model, ident_buf->model, 969203385Smav sizeof(ident_buf->model)) || 970203385Smav bcmp(softc->ident_data.revision, ident_buf->revision, 971203385Smav sizeof(ident_buf->revision)) || 972203385Smav bcmp(softc->ident_data.serial, ident_buf->serial, 973203385Smav sizeof(ident_buf->serial))) { 974198708Smav /* Device changed. */ 975198708Smav xpt_async(AC_LOST_DEVICE, path, NULL); 976207282Smav } else { 977203385Smav bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 978207282Smav changed = 0; 979207282Smav } 980207282Smav } 981207282Smav if (changed) { 982203385Smav bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 983195534Sscottl /* Clean up from previous instance of this device */ 984195534Sscottl if (path->device->serial_num != NULL) { 985195534Sscottl free(path->device->serial_num, M_CAMXPT); 986195534Sscottl path->device->serial_num = NULL; 987195534Sscottl path->device->serial_num_len = 0; 988195534Sscottl } 989235897Smav if (path->device->device_id != NULL) { 990235897Smav free(path->device->device_id, M_CAMXPT); 991235897Smav path->device->device_id = NULL; 992235897Smav path->device->device_id_len = 0; 993235897Smav } 994195534Sscottl path->device->serial_num = 995195534Sscottl (u_int8_t *)malloc((sizeof(ident_buf->serial) + 1), 996198708Smav M_CAMXPT, M_NOWAIT); 997195534Sscottl if (path->device->serial_num != NULL) { 998195534Sscottl bcopy(ident_buf->serial, 999195534Sscottl path->device->serial_num, 1000195534Sscottl sizeof(ident_buf->serial)); 1001195534Sscottl path->device->serial_num[sizeof(ident_buf->serial)] 1002195534Sscottl = '\0'; 1003195534Sscottl path->device->serial_num_len = 1004195534Sscottl strlen(path->device->serial_num); 1005195534Sscottl } 1006235897Smav if (ident_buf->enabled.extension & 1007235897Smav ATA_SUPPORT_64BITWWN) { 1008235897Smav path->device->device_id = 1009235897Smav malloc(16, M_CAMXPT, M_NOWAIT); 1010235897Smav if (path->device->device_id != NULL) { 1011235897Smav path->device->device_id_len = 16; 1012235897Smav bcopy(&fake_device_id_hdr, 1013235897Smav path->device->device_id, 8); 1014235897Smav bcopy(ident_buf->wwn, 1015235897Smav path->device->device_id + 8, 8); 1016235897Smav } 1017235897Smav } 1018195534Sscottl 1019198331Smav path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 1020195534Sscottl } 1021199178Smav if (ident_buf->satacapabilities & ATA_SUPPORT_NCQ) { 1022199178Smav path->device->mintags = path->device->maxtags = 1023199178Smav ATA_QUEUE_LEN(ident_buf->queue) + 1; 1024199178Smav } 1025199178Smav ata_find_quirk(path->device); 1026199263Smav if (path->device->mintags != 0 && 1027199263Smav path->bus->sim->max_tagged_dev_openings != 0) { 1028207222Smav /* Check if the SIM does not want queued commands. */ 1029207222Smav bzero(&cpi, sizeof(cpi)); 1030207222Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 1031207222Smav cpi.ccb_h.func_code = XPT_PATH_INQ; 1032207222Smav xpt_action((union ccb *)&cpi); 1033207222Smav if (cpi.ccb_h.status == CAM_REQ_CMP && 1034207222Smav (cpi.hba_inquiry & PI_TAG_ABLE)) { 1035207222Smav /* Report SIM which tags are allowed. */ 1036207222Smav bzero(&cts, sizeof(cts)); 1037207222Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1038207222Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1039207222Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 1040207222Smav cts.xport_specific.sata.tags = path->device->maxtags; 1041207222Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_TAGS; 1042207222Smav xpt_action((union ccb *)&cts); 1043207222Smav /* Reconfigure queues for tagged queueing. */ 1044207222Smav xpt_start_tags(path); 1045207222Smav } 1046199178Smav } 1047198708Smav ata_device_transport(path); 1048198708Smav PROBE_SET_ACTION(softc, PROBE_SETMODE); 1049195534Sscottl xpt_release_ccb(done_ccb); 1050198708Smav xpt_schedule(periph, priority); 1051198708Smav return; 1052195534Sscottl } 1053203421Smav case PROBE_SPINUP: 1054203421Smav if (bootverbose) 1055203421Smav xpt_print(path, "Spin-up done\n"); 1056203421Smav softc->spinup = 1; 1057203421Smav PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 1058203421Smav xpt_release_ccb(done_ccb); 1059203421Smav xpt_schedule(periph, priority); 1060203421Smav return; 1061195534Sscottl case PROBE_SETMODE: 1062207499Smav if (path->device->transport != XPORT_SATA) 1063207499Smav goto notsata; 1064207499Smav /* Set supported bits. */ 1065207499Smav bzero(&cts, sizeof(cts)); 1066207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1067207499Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1068207499Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 1069207499Smav xpt_action((union ccb *)&cts); 1070207499Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1071207499Smav caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H; 1072207499Smav else 1073207499Smav caps = 0; 1074207499Smav if (ident_buf->satacapabilities != 0xffff) { 1075207499Smav if (ident_buf->satacapabilities & ATA_SUPPORT_IFPWRMNGTRCV) 1076207499Smav caps |= CTS_SATA_CAPS_D_PMREQ; 1077207499Smav if (ident_buf->satacapabilities & ATA_SUPPORT_HAPST) 1078207499Smav caps |= CTS_SATA_CAPS_D_APST; 1079207499Smav } 1080207499Smav /* Mask unwanted bits. */ 1081207499Smav bzero(&cts, sizeof(cts)); 1082207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1083207499Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1084207499Smav cts.type = CTS_TYPE_USER_SETTINGS; 1085207499Smav xpt_action((union ccb *)&cts); 1086207499Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1087207499Smav caps &= cts.xport_specific.sata.caps; 1088215454Smav else 1089215454Smav caps = 0; 1090207499Smav /* Store result to SIM. */ 1091207499Smav bzero(&cts, sizeof(cts)); 1092207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1093207499Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1094207499Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 1095207499Smav cts.xport_specific.sata.caps = caps; 1096207499Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS; 1097207499Smav xpt_action((union ccb *)&cts); 1098207499Smav softc->caps = caps; 1099217874Smav if ((ident_buf->satasupport & ATA_SUPPORT_IFPWRMNGT) && 1100217874Smav (!(softc->caps & CTS_SATA_CAPS_H_PMREQ)) != 1101217874Smav (!(ident_buf->sataenabled & ATA_SUPPORT_IFPWRMNGT))) { 1102207499Smav PROBE_SET_ACTION(softc, PROBE_SETPM); 1103207499Smav xpt_release_ccb(done_ccb); 1104207499Smav xpt_schedule(periph, priority); 1105207499Smav return; 1106207499Smav } 1107207499Smav /* FALLTHROUGH */ 1108207499Smav case PROBE_SETPM: 1109207499Smav if (ident_buf->satacapabilities != 0xffff && 1110217874Smav (ident_buf->satacapabilities & ATA_SUPPORT_DAPST) && 1111217874Smav (!(softc->caps & CTS_SATA_CAPS_H_APST)) != 1112217874Smav (!(ident_buf->sataenabled & ATA_ENABLED_DAPST))) { 1113207499Smav PROBE_SET_ACTION(softc, PROBE_SETAPST); 1114207499Smav xpt_release_ccb(done_ccb); 1115207499Smav xpt_schedule(periph, priority); 1116207499Smav return; 1117207499Smav } 1118207499Smav /* FALLTHROUGH */ 1119207499Smav case PROBE_SETAPST: 1120217874Smav if ((ident_buf->satasupport & ATA_SUPPORT_AUTOACTIVATE) && 1121217874Smav (!(softc->caps & CTS_SATA_CAPS_H_DMAAA)) != 1122217874Smav (!(ident_buf->sataenabled & ATA_SUPPORT_AUTOACTIVATE))) { 1123207499Smav PROBE_SET_ACTION(softc, PROBE_SETDMAAA); 1124207499Smav xpt_release_ccb(done_ccb); 1125207499Smav xpt_schedule(periph, priority); 1126207499Smav return; 1127207499Smav } 1128207499Smav /* FALLTHROUGH */ 1129207499Smav case PROBE_SETDMAAA: 1130220602Smav if ((ident_buf->satasupport & ATA_SUPPORT_ASYNCNOTIF) && 1131220602Smav (!(softc->caps & CTS_SATA_CAPS_H_AN)) != 1132220602Smav (!(ident_buf->sataenabled & ATA_SUPPORT_ASYNCNOTIF))) { 1133220602Smav PROBE_SET_ACTION(softc, PROBE_SETAN); 1134220602Smav xpt_release_ccb(done_ccb); 1135220602Smav xpt_schedule(periph, priority); 1136220602Smav return; 1137220602Smav } 1138220602Smav /* FALLTHROUGH */ 1139220602Smav case PROBE_SETAN: 1140207499Smavnotsata: 1141198708Smav if (path->device->protocol == PROTO_ATA) { 1142198708Smav PROBE_SET_ACTION(softc, PROBE_SET_MULTI); 1143198708Smav } else { 1144198708Smav PROBE_SET_ACTION(softc, PROBE_INQUIRY); 1145195534Sscottl } 1146198708Smav xpt_release_ccb(done_ccb); 1147198708Smav xpt_schedule(periph, priority); 1148198708Smav return; 1149198708Smav case PROBE_SET_MULTI: 1150198708Smav if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 1151198708Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1152198748Smav xpt_acquire_device(path->device); 1153198708Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1154198708Smav xpt_action(done_ccb); 1155198708Smav xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, 1156198708Smav done_ccb); 1157198708Smav } 1158198708Smav break; 1159195534Sscottl case PROBE_INQUIRY: 1160195534Sscottl case PROBE_FULL_INQUIRY: 1161195534Sscottl { 1162198708Smav u_int8_t periph_qual, len; 1163195534Sscottl 1164198708Smav path->device->flags |= CAM_DEV_INQUIRY_DATA_VALID; 1165195534Sscottl 1166198708Smav periph_qual = SID_QUAL(inq_buf); 1167195534Sscottl 1168198708Smav if (periph_qual != SID_QUAL_LU_CONNECTED) 1169198708Smav break; 1170195534Sscottl 1171198708Smav /* 1172198708Smav * We conservatively request only 1173198708Smav * SHORT_INQUIRY_LEN bytes of inquiry 1174198708Smav * information during our first try 1175198708Smav * at sending an INQUIRY. If the device 1176198708Smav * has more information to give, 1177198708Smav * perform a second request specifying 1178198708Smav * the amount of information the device 1179198708Smav * is willing to give. 1180198708Smav */ 1181198708Smav len = inq_buf->additional_length 1182198708Smav + offsetof(struct scsi_inquiry_data, additional_length) + 1; 1183198708Smav if (softc->action == PROBE_INQUIRY 1184198708Smav && len > SHORT_INQUIRY_LENGTH) { 1185198708Smav PROBE_SET_ACTION(softc, PROBE_FULL_INQUIRY); 1186198708Smav xpt_release_ccb(done_ccb); 1187198708Smav xpt_schedule(periph, priority); 1188195534Sscottl return; 1189195534Sscottl } 1190198708Smav 1191198708Smav ata_device_transport(path); 1192198708Smav if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 1193198708Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1194198748Smav xpt_acquire_device(path->device); 1195198708Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1196198708Smav xpt_action(done_ccb); 1197198708Smav xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, done_ccb); 1198198708Smav } 1199198708Smav break; 1200195534Sscottl } 1201195534Sscottl case PROBE_PM_PID: 1202198708Smav if ((path->device->flags & CAM_DEV_IDENTIFY_DATA_VALID) == 0) 1203198708Smav bzero(ident_buf, sizeof(*ident_buf)); 1204198708Smav softc->pm_pid = (done_ccb->ataio.res.lba_high << 24) + 1205198708Smav (done_ccb->ataio.res.lba_mid << 16) + 1206198708Smav (done_ccb->ataio.res.lba_low << 8) + 1207198708Smav done_ccb->ataio.res.sector_count; 1208198708Smav ((uint32_t *)ident_buf)[0] = softc->pm_pid; 1209198708Smav snprintf(ident_buf->model, sizeof(ident_buf->model), 1210198708Smav "Port Multiplier %08x", softc->pm_pid); 1211198708Smav PROBE_SET_ACTION(softc, PROBE_PM_PRV); 1212198708Smav xpt_release_ccb(done_ccb); 1213198708Smav xpt_schedule(periph, priority); 1214198708Smav return; 1215195534Sscottl case PROBE_PM_PRV: 1216198708Smav softc->pm_prv = (done_ccb->ataio.res.lba_high << 24) + 1217198708Smav (done_ccb->ataio.res.lba_mid << 16) + 1218198708Smav (done_ccb->ataio.res.lba_low << 8) + 1219198708Smav done_ccb->ataio.res.sector_count; 1220198708Smav ((uint32_t *)ident_buf)[1] = softc->pm_prv; 1221198708Smav snprintf(ident_buf->revision, sizeof(ident_buf->revision), 1222198708Smav "%04x", softc->pm_prv); 1223198708Smav path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 1224207499Smav /* Set supported bits. */ 1225207499Smav bzero(&cts, sizeof(cts)); 1226207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1227207499Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1228207499Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 1229207499Smav xpt_action((union ccb *)&cts); 1230207499Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1231207499Smav caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H; 1232207499Smav else 1233207499Smav caps = 0; 1234207499Smav /* All PMPs must support PM requests. */ 1235207499Smav caps |= CTS_SATA_CAPS_D_PMREQ; 1236207499Smav /* Mask unwanted bits. */ 1237207499Smav bzero(&cts, sizeof(cts)); 1238207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1239207499Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1240207499Smav cts.type = CTS_TYPE_USER_SETTINGS; 1241207499Smav xpt_action((union ccb *)&cts); 1242207499Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1243207499Smav caps &= cts.xport_specific.sata.caps; 1244215454Smav else 1245215454Smav caps = 0; 1246207499Smav /* Store result to SIM. */ 1247207499Smav bzero(&cts, sizeof(cts)); 1248207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1249207499Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1250207499Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 1251207499Smav cts.xport_specific.sata.caps = caps; 1252207499Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS; 1253207499Smav xpt_action((union ccb *)&cts); 1254207499Smav softc->caps = caps; 1255198708Smav if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 1256198708Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1257198748Smav xpt_acquire_device(path->device); 1258198708Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1259198708Smav xpt_action(done_ccb); 1260198708Smav xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, 1261198708Smav done_ccb); 1262198708Smav } else { 1263198708Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1264198708Smav xpt_action(done_ccb); 1265198708Smav xpt_async(AC_SCSI_AEN, done_ccb->ccb_h.path, done_ccb); 1266195534Sscottl } 1267198708Smav break; 1268235897Smav case PROBE_IDENTIFY_SES: 1269235897Smav case PROBE_IDENTIFY_SAFTE: 1270235897Smav if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) { 1271235897Smav /* Check that it is the same device. */ 1272235897Smav if (bcmp(&softc->ident_data, ident_buf, 53)) { 1273235897Smav /* Device changed. */ 1274235897Smav xpt_async(AC_LOST_DEVICE, path, NULL); 1275235897Smav } else { 1276235897Smav bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 1277235897Smav changed = 0; 1278235897Smav } 1279235897Smav } 1280235897Smav if (changed) { 1281235897Smav bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 1282235897Smav /* Clean up from previous instance of this device */ 1283235897Smav if (path->device->device_id != NULL) { 1284235897Smav free(path->device->device_id, M_CAMXPT); 1285235897Smav path->device->device_id = NULL; 1286235897Smav path->device->device_id_len = 0; 1287235897Smav } 1288235897Smav path->device->device_id = 1289235897Smav malloc(16, M_CAMXPT, M_NOWAIT); 1290235897Smav if (path->device->device_id != NULL) { 1291235897Smav path->device->device_id_len = 16; 1292235897Smav bcopy(&fake_device_id_hdr, 1293235897Smav path->device->device_id, 8); 1294235897Smav bcopy(((uint8_t*)ident_buf) + 2, 1295235897Smav path->device->device_id + 8, 8); 1296235897Smav } 1297235897Smav 1298235897Smav path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 1299235897Smav } 1300235897Smav 1301235897Smav if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 1302235897Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1303235897Smav xpt_acquire_device(path->device); 1304235897Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1305235897Smav xpt_action(done_ccb); 1306235897Smav xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, 1307235897Smav done_ccb); 1308235897Smav } 1309235897Smav break; 1310195534Sscottl case PROBE_INVALID: 1311195534Sscottl CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_INFO, 1312195534Sscottl ("probedone: invalid action state\n")); 1313195534Sscottl default: 1314195534Sscottl break; 1315195534Sscottl } 1316198708Smavdone: 1317203108Smav if (softc->restart) { 1318203108Smav softc->restart = 0; 1319203108Smav xpt_release_ccb(done_ccb); 1320195534Sscottl probeschedule(periph); 1321203108Smav return; 1322195534Sscottl } 1323203108Smav xpt_release_ccb(done_ccb); 1324203108Smav while ((done_ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs))) { 1325203108Smav TAILQ_REMOVE(&softc->request_ccbs, 1326203108Smav &done_ccb->ccb_h, periph_links.tqe); 1327203108Smav done_ccb->ccb_h.status = found ? CAM_REQ_CMP : CAM_REQ_CMP_ERR; 1328203108Smav xpt_done(done_ccb); 1329203108Smav } 1330203108Smav cam_release_devq(periph->path, 1331203108Smav RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_XPT + 1, FALSE); 1332203108Smav cam_periph_invalidate(periph); 1333203108Smav cam_periph_release_locked(periph); 1334195534Sscottl} 1335195534Sscottl 1336195534Sscottlstatic void 1337195534Sscottlprobecleanup(struct cam_periph *periph) 1338195534Sscottl{ 1339195534Sscottl free(periph->softc, M_CAMXPT); 1340195534Sscottl} 1341195534Sscottl 1342195534Sscottlstatic void 1343199178Smavata_find_quirk(struct cam_ed *device) 1344195534Sscottl{ 1345199178Smav struct ata_quirk_entry *quirk; 1346195534Sscottl caddr_t match; 1347195534Sscottl 1348199178Smav match = cam_quirkmatch((caddr_t)&device->ident_data, 1349199178Smav (caddr_t)ata_quirk_table, 1350199178Smav ata_quirk_table_size, 1351199178Smav sizeof(*ata_quirk_table), ata_identify_match); 1352195534Sscottl 1353195534Sscottl if (match == NULL) 1354195534Sscottl panic("xpt_find_quirk: device didn't match wildcard entry!!"); 1355195534Sscottl 1356199178Smav quirk = (struct ata_quirk_entry *)match; 1357195534Sscottl device->quirk = quirk; 1358199178Smav if (quirk->quirks & CAM_QUIRK_MAXTAGS) 1359199178Smav device->mintags = device->maxtags = quirk->maxtags; 1360195534Sscottl} 1361195534Sscottl 1362195534Sscottltypedef struct { 1363195534Sscottl union ccb *request_ccb; 1364195534Sscottl struct ccb_pathinq *cpi; 1365195534Sscottl int counter; 1366195534Sscottl} ata_scan_bus_info; 1367195534Sscottl 1368195534Sscottl/* 1369195534Sscottl * To start a scan, request_ccb is an XPT_SCAN_BUS ccb. 1370195534Sscottl * As the scan progresses, xpt_scan_bus is used as the 1371195534Sscottl * callback on completion function. 1372195534Sscottl */ 1373195534Sscottlstatic void 1374195534Sscottlata_scan_bus(struct cam_periph *periph, union ccb *request_ccb) 1375195534Sscottl{ 1376195534Sscottl struct cam_path *path; 1377195534Sscottl ata_scan_bus_info *scan_info; 1378203108Smav union ccb *work_ccb, *reset_ccb; 1379195534Sscottl cam_status status; 1380195534Sscottl 1381195534Sscottl CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE, 1382195534Sscottl ("xpt_scan_bus\n")); 1383195534Sscottl switch (request_ccb->ccb_h.func_code) { 1384195534Sscottl case XPT_SCAN_BUS: 1385208582Smjacob case XPT_SCAN_TGT: 1386195534Sscottl /* Find out the characteristics of the bus */ 1387195534Sscottl work_ccb = xpt_alloc_ccb_nowait(); 1388195534Sscottl if (work_ccb == NULL) { 1389195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1390195534Sscottl xpt_done(request_ccb); 1391195534Sscottl return; 1392195534Sscottl } 1393195534Sscottl xpt_setup_ccb(&work_ccb->ccb_h, request_ccb->ccb_h.path, 1394195534Sscottl request_ccb->ccb_h.pinfo.priority); 1395195534Sscottl work_ccb->ccb_h.func_code = XPT_PATH_INQ; 1396195534Sscottl xpt_action(work_ccb); 1397195534Sscottl if (work_ccb->ccb_h.status != CAM_REQ_CMP) { 1398195534Sscottl request_ccb->ccb_h.status = work_ccb->ccb_h.status; 1399195534Sscottl xpt_free_ccb(work_ccb); 1400195534Sscottl xpt_done(request_ccb); 1401195534Sscottl return; 1402195534Sscottl } 1403195534Sscottl 1404203108Smav /* We may need to reset bus first, if we haven't done it yet. */ 1405203108Smav if ((work_ccb->cpi.hba_inquiry & 1406203108Smav (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE)) && 1407203108Smav !(work_ccb->cpi.hba_misc & PIM_NOBUSRESET) && 1408203108Smav !timevalisset(&request_ccb->ccb_h.path->bus->last_reset)) { 1409203108Smav reset_ccb = xpt_alloc_ccb_nowait(); 1410208823Smav if (reset_ccb == NULL) { 1411208823Smav request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1412208823Smav xpt_free_ccb(work_ccb); 1413208823Smav xpt_done(request_ccb); 1414208823Smav return; 1415208823Smav } 1416203108Smav xpt_setup_ccb(&reset_ccb->ccb_h, request_ccb->ccb_h.path, 1417203108Smav CAM_PRIORITY_NONE); 1418203108Smav reset_ccb->ccb_h.func_code = XPT_RESET_BUS; 1419203108Smav xpt_action(reset_ccb); 1420203108Smav if (reset_ccb->ccb_h.status != CAM_REQ_CMP) { 1421203108Smav request_ccb->ccb_h.status = reset_ccb->ccb_h.status; 1422203108Smav xpt_free_ccb(reset_ccb); 1423203108Smav xpt_free_ccb(work_ccb); 1424203108Smav xpt_done(request_ccb); 1425203108Smav return; 1426203108Smav } 1427203108Smav xpt_free_ccb(reset_ccb); 1428203108Smav } 1429203108Smav 1430195534Sscottl /* Save some state for use while we probe for devices */ 1431195534Sscottl scan_info = (ata_scan_bus_info *) 1432195534Sscottl malloc(sizeof(ata_scan_bus_info), M_CAMXPT, M_NOWAIT); 1433195534Sscottl if (scan_info == NULL) { 1434195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1435208823Smav xpt_free_ccb(work_ccb); 1436195534Sscottl xpt_done(request_ccb); 1437195534Sscottl return; 1438195534Sscottl } 1439195534Sscottl scan_info->request_ccb = request_ccb; 1440195534Sscottl scan_info->cpi = &work_ccb->cpi; 1441195534Sscottl /* If PM supported, probe it first. */ 1442195534Sscottl if (scan_info->cpi->hba_inquiry & PI_SATAPM) 1443201990Smav scan_info->counter = scan_info->cpi->max_target; 1444201990Smav else 1445201990Smav scan_info->counter = 0; 1446195534Sscottl 1447195534Sscottl work_ccb = xpt_alloc_ccb_nowait(); 1448195534Sscottl if (work_ccb == NULL) { 1449195534Sscottl free(scan_info, M_CAMXPT); 1450195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1451195534Sscottl xpt_done(request_ccb); 1452195534Sscottl break; 1453195534Sscottl } 1454195534Sscottl goto scan_next; 1455195534Sscottl case XPT_SCAN_LUN: 1456195534Sscottl work_ccb = request_ccb; 1457195534Sscottl /* Reuse the same CCB to query if a device was really found */ 1458195534Sscottl scan_info = (ata_scan_bus_info *)work_ccb->ccb_h.ppriv_ptr0; 1459198389Smav /* If there is PMP... */ 1460201990Smav if ((scan_info->cpi->hba_inquiry & PI_SATAPM) && 1461201990Smav (scan_info->counter == scan_info->cpi->max_target)) { 1462203108Smav if (work_ccb->ccb_h.status == CAM_REQ_CMP) { 1463207428Smav /* everything else will be probed by it */ 1464207428Smav /* Free the current request path- we're done with it. */ 1465207428Smav xpt_free_path(work_ccb->ccb_h.path); 1466201990Smav goto done; 1467195534Sscottl } else { 1468195534Sscottl struct ccb_trans_settings cts; 1469195534Sscottl 1470195534Sscottl /* Report SIM that PM is absent. */ 1471195534Sscottl bzero(&cts, sizeof(cts)); 1472195534Sscottl xpt_setup_ccb(&cts.ccb_h, 1473207428Smav work_ccb->ccb_h.path, CAM_PRIORITY_NONE); 1474195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1475195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 1476195665Smav cts.xport_specific.sata.pm_present = 0; 1477195534Sscottl cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; 1478195534Sscottl xpt_action((union ccb *)&cts); 1479195534Sscottl } 1480195534Sscottl } 1481207428Smav /* Free the current request path- we're done with it. */ 1482207428Smav xpt_free_path(work_ccb->ccb_h.path); 1483201990Smav if (scan_info->counter == 1484201990Smav ((scan_info->cpi->hba_inquiry & PI_SATAPM) ? 1485201990Smav 0 : scan_info->cpi->max_target)) { 1486201990Smavdone: 1487195534Sscottl xpt_free_ccb(work_ccb); 1488195534Sscottl xpt_free_ccb((union ccb *)scan_info->cpi); 1489195534Sscottl request_ccb = scan_info->request_ccb; 1490195534Sscottl free(scan_info, M_CAMXPT); 1491195534Sscottl request_ccb->ccb_h.status = CAM_REQ_CMP; 1492195534Sscottl xpt_done(request_ccb); 1493195534Sscottl break; 1494195534Sscottl } 1495201990Smav /* Take next device. Wrap from max (PMP) to 0. */ 1496201990Smav scan_info->counter = (scan_info->counter + 1 ) % 1497201990Smav (scan_info->cpi->max_target + 1); 1498195534Sscottlscan_next: 1499195534Sscottl status = xpt_create_path(&path, xpt_periph, 1500195534Sscottl scan_info->request_ccb->ccb_h.path_id, 1501195534Sscottl scan_info->counter, 0); 1502195534Sscottl if (status != CAM_REQ_CMP) { 1503195534Sscottl printf("xpt_scan_bus: xpt_create_path failed" 1504195534Sscottl " with status %#x, bus scan halted\n", 1505195534Sscottl status); 1506195534Sscottl xpt_free_ccb(work_ccb); 1507195534Sscottl xpt_free_ccb((union ccb *)scan_info->cpi); 1508195534Sscottl request_ccb = scan_info->request_ccb; 1509195534Sscottl free(scan_info, M_CAMXPT); 1510195534Sscottl request_ccb->ccb_h.status = status; 1511195534Sscottl xpt_done(request_ccb); 1512195534Sscottl break; 1513195534Sscottl } 1514195534Sscottl xpt_setup_ccb(&work_ccb->ccb_h, path, 1515195534Sscottl scan_info->request_ccb->ccb_h.pinfo.priority); 1516195534Sscottl work_ccb->ccb_h.func_code = XPT_SCAN_LUN; 1517195534Sscottl work_ccb->ccb_h.cbfcnp = ata_scan_bus; 1518195534Sscottl work_ccb->ccb_h.ppriv_ptr0 = scan_info; 1519195534Sscottl work_ccb->crcn.flags = scan_info->request_ccb->crcn.flags; 1520195534Sscottl xpt_action(work_ccb); 1521195534Sscottl break; 1522195534Sscottl default: 1523195534Sscottl break; 1524195534Sscottl } 1525195534Sscottl} 1526195534Sscottl 1527195534Sscottlstatic void 1528195534Sscottlata_scan_lun(struct cam_periph *periph, struct cam_path *path, 1529195534Sscottl cam_flags flags, union ccb *request_ccb) 1530195534Sscottl{ 1531195534Sscottl struct ccb_pathinq cpi; 1532195534Sscottl cam_status status; 1533195534Sscottl struct cam_path *new_path; 1534195534Sscottl struct cam_periph *old_periph; 1535195534Sscottl 1536203108Smav CAM_DEBUG(path, CAM_DEBUG_TRACE, ("xpt_scan_lun\n")); 1537195534Sscottl 1538203108Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 1539195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 1540195534Sscottl xpt_action((union ccb *)&cpi); 1541195534Sscottl 1542195534Sscottl if (cpi.ccb_h.status != CAM_REQ_CMP) { 1543195534Sscottl if (request_ccb != NULL) { 1544195534Sscottl request_ccb->ccb_h.status = cpi.ccb_h.status; 1545195534Sscottl xpt_done(request_ccb); 1546195534Sscottl } 1547195534Sscottl return; 1548195534Sscottl } 1549195534Sscottl 1550195534Sscottl if (request_ccb == NULL) { 1551195534Sscottl request_ccb = malloc(sizeof(union ccb), M_CAMXPT, M_NOWAIT); 1552195534Sscottl if (request_ccb == NULL) { 1553195534Sscottl xpt_print(path, "xpt_scan_lun: can't allocate CCB, " 1554195534Sscottl "can't continue\n"); 1555195534Sscottl return; 1556195534Sscottl } 1557195534Sscottl new_path = malloc(sizeof(*new_path), M_CAMXPT, M_NOWAIT); 1558195534Sscottl if (new_path == NULL) { 1559195534Sscottl xpt_print(path, "xpt_scan_lun: can't allocate path, " 1560195534Sscottl "can't continue\n"); 1561195534Sscottl free(request_ccb, M_CAMXPT); 1562195534Sscottl return; 1563195534Sscottl } 1564195534Sscottl status = xpt_compile_path(new_path, xpt_periph, 1565195534Sscottl path->bus->path_id, 1566195534Sscottl path->target->target_id, 1567195534Sscottl path->device->lun_id); 1568195534Sscottl 1569195534Sscottl if (status != CAM_REQ_CMP) { 1570195534Sscottl xpt_print(path, "xpt_scan_lun: can't compile path, " 1571195534Sscottl "can't continue\n"); 1572195534Sscottl free(request_ccb, M_CAMXPT); 1573195534Sscottl free(new_path, M_CAMXPT); 1574195534Sscottl return; 1575195534Sscottl } 1576203108Smav xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_XPT); 1577195534Sscottl request_ccb->ccb_h.cbfcnp = xptscandone; 1578195534Sscottl request_ccb->ccb_h.func_code = XPT_SCAN_LUN; 1579195534Sscottl request_ccb->crcn.flags = flags; 1580195534Sscottl } 1581195534Sscottl 1582195653Smav if ((old_periph = cam_periph_find(path, "aprobe")) != NULL) { 1583195534Sscottl probe_softc *softc; 1584195534Sscottl 1585195534Sscottl softc = (probe_softc *)old_periph->softc; 1586195534Sscottl TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h, 1587195534Sscottl periph_links.tqe); 1588203108Smav softc->restart = 1; 1589195534Sscottl } else { 1590195534Sscottl status = cam_periph_alloc(proberegister, NULL, probecleanup, 1591195653Smav probestart, "aprobe", 1592195534Sscottl CAM_PERIPH_BIO, 1593195534Sscottl request_ccb->ccb_h.path, NULL, 0, 1594195534Sscottl request_ccb); 1595195534Sscottl 1596195534Sscottl if (status != CAM_REQ_CMP) { 1597195534Sscottl xpt_print(path, "xpt_scan_lun: cam_alloc_periph " 1598195534Sscottl "returned an error, can't continue probe\n"); 1599195534Sscottl request_ccb->ccb_h.status = status; 1600195534Sscottl xpt_done(request_ccb); 1601195534Sscottl } 1602195534Sscottl } 1603195534Sscottl} 1604195534Sscottl 1605195534Sscottlstatic void 1606195534Sscottlxptscandone(struct cam_periph *periph, union ccb *done_ccb) 1607195534Sscottl{ 1608195534Sscottl xpt_release_path(done_ccb->ccb_h.path); 1609195534Sscottl free(done_ccb->ccb_h.path, M_CAMXPT); 1610195534Sscottl free(done_ccb, M_CAMXPT); 1611195534Sscottl} 1612195534Sscottl 1613195534Sscottlstatic struct cam_ed * 1614195534Sscottlata_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id) 1615195534Sscottl{ 1616195534Sscottl struct cam_path path; 1617199178Smav struct ata_quirk_entry *quirk; 1618195534Sscottl struct cam_ed *device; 1619195534Sscottl struct cam_ed *cur_device; 1620195534Sscottl 1621195534Sscottl device = xpt_alloc_device(bus, target, lun_id); 1622195534Sscottl if (device == NULL) 1623195534Sscottl return (NULL); 1624195534Sscottl 1625195534Sscottl /* 1626195534Sscottl * Take the default quirk entry until we have inquiry 1627195534Sscottl * data and can determine a better quirk to use. 1628195534Sscottl */ 1629199178Smav quirk = &ata_quirk_table[ata_quirk_table_size - 1]; 1630195534Sscottl device->quirk = (void *)quirk; 1631199178Smav device->mintags = 0; 1632199178Smav device->maxtags = 0; 1633195534Sscottl bzero(&device->inq_data, sizeof(device->inq_data)); 1634195534Sscottl device->inq_flags = 0; 1635195534Sscottl device->queue_flags = 0; 1636195534Sscottl device->serial_num = NULL; 1637195534Sscottl device->serial_num_len = 0; 1638195534Sscottl 1639195534Sscottl /* 1640195534Sscottl * XXX should be limited by number of CCBs this bus can 1641195534Sscottl * do. 1642195534Sscottl */ 1643195534Sscottl bus->sim->max_ccbs += device->ccbq.devq_openings; 1644195534Sscottl /* Insertion sort into our target's device list */ 1645195534Sscottl cur_device = TAILQ_FIRST(&target->ed_entries); 1646195534Sscottl while (cur_device != NULL && cur_device->lun_id < lun_id) 1647195534Sscottl cur_device = TAILQ_NEXT(cur_device, links); 1648195534Sscottl if (cur_device != NULL) { 1649195534Sscottl TAILQ_INSERT_BEFORE(cur_device, device, links); 1650195534Sscottl } else { 1651195534Sscottl TAILQ_INSERT_TAIL(&target->ed_entries, device, links); 1652195534Sscottl } 1653195534Sscottl target->generation++; 1654195534Sscottl if (lun_id != CAM_LUN_WILDCARD) { 1655195534Sscottl xpt_compile_path(&path, 1656195534Sscottl NULL, 1657195534Sscottl bus->path_id, 1658195534Sscottl target->target_id, 1659195534Sscottl lun_id); 1660195534Sscottl ata_device_transport(&path); 1661195534Sscottl xpt_release_path(&path); 1662195534Sscottl } 1663195534Sscottl 1664195534Sscottl return (device); 1665195534Sscottl} 1666195534Sscottl 1667195534Sscottlstatic void 1668195534Sscottlata_device_transport(struct cam_path *path) 1669195534Sscottl{ 1670195534Sscottl struct ccb_pathinq cpi; 1671198331Smav struct ccb_trans_settings cts; 1672198331Smav struct scsi_inquiry_data *inq_buf = NULL; 1673198331Smav struct ata_params *ident_buf = NULL; 1674195534Sscottl 1675195534Sscottl /* Get transport information from the SIM */ 1676203108Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 1677195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 1678195534Sscottl xpt_action((union ccb *)&cpi); 1679195534Sscottl 1680195534Sscottl path->device->transport = cpi.transport; 1681198331Smav if ((path->device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0) 1682198331Smav inq_buf = &path->device->inq_data; 1683198331Smav if ((path->device->flags & CAM_DEV_IDENTIFY_DATA_VALID) != 0) 1684198331Smav ident_buf = &path->device->ident_data; 1685198331Smav if (path->device->protocol == PROTO_ATA) { 1686198331Smav path->device->protocol_version = ident_buf ? 1687198331Smav ata_version(ident_buf->version_major) : cpi.protocol_version; 1688198331Smav } else if (path->device->protocol == PROTO_SCSI) { 1689198331Smav path->device->protocol_version = inq_buf ? 1690198331Smav SID_ANSI_REV(inq_buf) : cpi.protocol_version; 1691195534Sscottl } 1692198331Smav path->device->transport_version = ident_buf ? 1693198331Smav ata_version(ident_buf->version_major) : cpi.transport_version; 1694195534Sscottl 1695195534Sscottl /* Tell the controller what we think */ 1696203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1697195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1698195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 1699195534Sscottl cts.transport = path->device->transport; 1700195534Sscottl cts.transport_version = path->device->transport_version; 1701195534Sscottl cts.protocol = path->device->protocol; 1702195534Sscottl cts.protocol_version = path->device->protocol_version; 1703195534Sscottl cts.proto_specific.valid = 0; 1704203376Smav if (ident_buf) { 1705203376Smav if (path->device->transport == XPORT_ATA) { 1706223019Smav cts.xport_specific.ata.atapi = 1707223019Smav (ident_buf->config == ATA_PROTO_CFA) ? 0 : 1708203376Smav ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_16) ? 16 : 1709203376Smav ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) ? 12 : 0; 1710203376Smav cts.xport_specific.ata.valid = CTS_ATA_VALID_ATAPI; 1711203376Smav } else { 1712223019Smav cts.xport_specific.sata.atapi = 1713223019Smav (ident_buf->config == ATA_PROTO_CFA) ? 0 : 1714203376Smav ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_16) ? 16 : 1715203376Smav ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) ? 12 : 0; 1716203376Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_ATAPI; 1717203376Smav } 1718203376Smav } else 1719203376Smav cts.xport_specific.valid = 0; 1720195534Sscottl xpt_action((union ccb *)&cts); 1721195534Sscottl} 1722195534Sscottl 1723195534Sscottlstatic void 1724223443Swillata_dev_advinfo(union ccb *start_ccb) 1725223443Swill{ 1726223443Swill struct cam_ed *device; 1727223443Swill struct ccb_dev_advinfo *cdai; 1728223443Swill off_t amt; 1729223443Swill 1730223443Swill start_ccb->ccb_h.status = CAM_REQ_INVALID; 1731223443Swill device = start_ccb->ccb_h.path->device; 1732223443Swill cdai = &start_ccb->cdai; 1733223443Swill switch(cdai->buftype) { 1734235897Smav case CDAI_TYPE_SCSI_DEVID: 1735235897Smav if (cdai->flags & CDAI_FLAG_STORE) 1736235897Smav return; 1737235897Smav cdai->provsiz = device->device_id_len; 1738235897Smav if (device->device_id_len == 0) 1739235897Smav break; 1740235897Smav amt = device->device_id_len; 1741235897Smav if (cdai->provsiz > cdai->bufsiz) 1742235897Smav amt = cdai->bufsiz; 1743235897Smav memcpy(cdai->buf, device->device_id, amt); 1744235897Smav break; 1745223443Swill case CDAI_TYPE_SERIAL_NUM: 1746223443Swill if (cdai->flags & CDAI_FLAG_STORE) 1747235897Smav return; 1748223443Swill cdai->provsiz = device->serial_num_len; 1749223443Swill if (device->serial_num_len == 0) 1750223443Swill break; 1751223443Swill amt = device->serial_num_len; 1752223443Swill if (cdai->provsiz > cdai->bufsiz) 1753223443Swill amt = cdai->bufsiz; 1754223443Swill memcpy(cdai->buf, device->serial_num, amt); 1755223443Swill break; 1756235897Smav case CDAI_TYPE_PHYS_PATH: 1757235897Smav if (cdai->flags & CDAI_FLAG_STORE) { 1758235897Smav if (device->physpath != NULL) 1759235897Smav free(device->physpath, M_CAMXPT); 1760235897Smav device->physpath_len = cdai->bufsiz; 1761235897Smav /* Clear existing buffer if zero length */ 1762235897Smav if (cdai->bufsiz == 0) 1763235897Smav break; 1764235897Smav device->physpath = malloc(cdai->bufsiz, M_CAMXPT, M_NOWAIT); 1765235897Smav if (device->physpath == NULL) { 1766235897Smav start_ccb->ccb_h.status = CAM_REQ_ABORTED; 1767235897Smav return; 1768235897Smav } 1769235897Smav memcpy(device->physpath, cdai->buf, cdai->bufsiz); 1770235897Smav } else { 1771235897Smav cdai->provsiz = device->physpath_len; 1772235897Smav if (device->physpath_len == 0) 1773235897Smav break; 1774235897Smav amt = device->physpath_len; 1775235897Smav if (cdai->provsiz > cdai->bufsiz) 1776235897Smav amt = cdai->bufsiz; 1777235897Smav memcpy(cdai->buf, device->physpath, amt); 1778235897Smav } 1779235897Smav break; 1780223443Swill default: 1781235897Smav return; 1782223443Swill } 1783235897Smav start_ccb->ccb_h.status = CAM_REQ_CMP; 1784235897Smav 1785235897Smav if (cdai->flags & CDAI_FLAG_STORE) { 1786235897Smav int owned; 1787235897Smav 1788235897Smav owned = mtx_owned(start_ccb->ccb_h.path->bus->sim->mtx); 1789235897Smav if (owned == 0) 1790235897Smav mtx_lock(start_ccb->ccb_h.path->bus->sim->mtx); 1791235897Smav xpt_async(AC_ADVINFO_CHANGED, start_ccb->ccb_h.path, 1792235897Smav (void *)(uintptr_t)cdai->buftype); 1793235897Smav if (owned == 0) 1794235897Smav mtx_unlock(start_ccb->ccb_h.path->bus->sim->mtx); 1795235897Smav } 1796223443Swill} 1797223443Swill 1798223443Swillstatic void 1799195534Sscottlata_action(union ccb *start_ccb) 1800195534Sscottl{ 1801195534Sscottl 1802195534Sscottl switch (start_ccb->ccb_h.func_code) { 1803195534Sscottl case XPT_SET_TRAN_SETTINGS: 1804195534Sscottl { 1805199178Smav ata_set_transfer_settings(&start_ccb->cts, 1806195534Sscottl start_ccb->ccb_h.path->device, 1807195534Sscottl /*async_update*/FALSE); 1808195534Sscottl break; 1809195534Sscottl } 1810195534Sscottl case XPT_SCAN_BUS: 1811208582Smjacob case XPT_SCAN_TGT: 1812195534Sscottl ata_scan_bus(start_ccb->ccb_h.path->periph, start_ccb); 1813195534Sscottl break; 1814195534Sscottl case XPT_SCAN_LUN: 1815195534Sscottl ata_scan_lun(start_ccb->ccb_h.path->periph, 1816195534Sscottl start_ccb->ccb_h.path, start_ccb->crcn.flags, 1817195534Sscottl start_ccb); 1818195534Sscottl break; 1819195534Sscottl case XPT_GET_TRAN_SETTINGS: 1820195534Sscottl { 1821195534Sscottl struct cam_sim *sim; 1822195534Sscottl 1823195534Sscottl sim = start_ccb->ccb_h.path->bus->sim; 1824195534Sscottl (*(sim->sim_action))(sim, start_ccb); 1825195534Sscottl break; 1826195534Sscottl } 1827203376Smav case XPT_SCSI_IO: 1828203376Smav { 1829203376Smav struct cam_ed *device; 1830203376Smav u_int maxlen = 0; 1831203376Smav 1832203376Smav device = start_ccb->ccb_h.path->device; 1833203376Smav if (device->protocol == PROTO_SCSI && 1834203376Smav (device->flags & CAM_DEV_IDENTIFY_DATA_VALID)) { 1835203376Smav uint16_t p = 1836203376Smav device->ident_data.config & ATA_PROTO_MASK; 1837203376Smav 1838223019Smav maxlen = 1839223019Smav (device->ident_data.config == ATA_PROTO_CFA) ? 0 : 1840223019Smav (p == ATA_PROTO_ATAPI_16) ? 16 : 1841203376Smav (p == ATA_PROTO_ATAPI_12) ? 12 : 0; 1842203376Smav } 1843203376Smav if (start_ccb->csio.cdb_len > maxlen) { 1844203376Smav start_ccb->ccb_h.status = CAM_REQ_INVALID; 1845203376Smav xpt_done(start_ccb); 1846203376Smav break; 1847203376Smav } 1848223475Smav xpt_action_default(start_ccb); 1849223475Smav break; 1850203376Smav } 1851223443Swill case XPT_DEV_ADVINFO: 1852223443Swill { 1853223443Swill ata_dev_advinfo(start_ccb); 1854223443Swill break; 1855223443Swill } 1856195534Sscottl default: 1857195534Sscottl xpt_action_default(start_ccb); 1858195534Sscottl break; 1859195534Sscottl } 1860195534Sscottl} 1861195534Sscottl 1862195534Sscottlstatic void 1863199178Smavata_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device, 1864195534Sscottl int async_update) 1865195534Sscottl{ 1866195534Sscottl struct ccb_pathinq cpi; 1867195534Sscottl struct ccb_trans_settings cur_cts; 1868195534Sscottl struct ccb_trans_settings_scsi *scsi; 1869195534Sscottl struct ccb_trans_settings_scsi *cur_scsi; 1870195534Sscottl struct cam_sim *sim; 1871195534Sscottl struct scsi_inquiry_data *inq_data; 1872195534Sscottl 1873195534Sscottl if (device == NULL) { 1874195534Sscottl cts->ccb_h.status = CAM_PATH_INVALID; 1875195534Sscottl xpt_done((union ccb *)cts); 1876195534Sscottl return; 1877195534Sscottl } 1878195534Sscottl 1879195534Sscottl if (cts->protocol == PROTO_UNKNOWN 1880195534Sscottl || cts->protocol == PROTO_UNSPECIFIED) { 1881195534Sscottl cts->protocol = device->protocol; 1882195534Sscottl cts->protocol_version = device->protocol_version; 1883195534Sscottl } 1884195534Sscottl 1885195534Sscottl if (cts->protocol_version == PROTO_VERSION_UNKNOWN 1886195534Sscottl || cts->protocol_version == PROTO_VERSION_UNSPECIFIED) 1887195534Sscottl cts->protocol_version = device->protocol_version; 1888195534Sscottl 1889195534Sscottl if (cts->protocol != device->protocol) { 1890195534Sscottl xpt_print(cts->ccb_h.path, "Uninitialized Protocol %x:%x?\n", 1891195534Sscottl cts->protocol, device->protocol); 1892195534Sscottl cts->protocol = device->protocol; 1893195534Sscottl } 1894195534Sscottl 1895195534Sscottl if (cts->protocol_version > device->protocol_version) { 1896195534Sscottl if (bootverbose) { 1897195534Sscottl xpt_print(cts->ccb_h.path, "Down reving Protocol " 1898195534Sscottl "Version from %d to %d?\n", cts->protocol_version, 1899195534Sscottl device->protocol_version); 1900195534Sscottl } 1901195534Sscottl cts->protocol_version = device->protocol_version; 1902195534Sscottl } 1903195534Sscottl 1904195534Sscottl if (cts->transport == XPORT_UNKNOWN 1905195534Sscottl || cts->transport == XPORT_UNSPECIFIED) { 1906195534Sscottl cts->transport = device->transport; 1907195534Sscottl cts->transport_version = device->transport_version; 1908195534Sscottl } 1909195534Sscottl 1910195534Sscottl if (cts->transport_version == XPORT_VERSION_UNKNOWN 1911195534Sscottl || cts->transport_version == XPORT_VERSION_UNSPECIFIED) 1912195534Sscottl cts->transport_version = device->transport_version; 1913195534Sscottl 1914195534Sscottl if (cts->transport != device->transport) { 1915195534Sscottl xpt_print(cts->ccb_h.path, "Uninitialized Transport %x:%x?\n", 1916195534Sscottl cts->transport, device->transport); 1917195534Sscottl cts->transport = device->transport; 1918195534Sscottl } 1919195534Sscottl 1920195534Sscottl if (cts->transport_version > device->transport_version) { 1921195534Sscottl if (bootverbose) { 1922195534Sscottl xpt_print(cts->ccb_h.path, "Down reving Transport " 1923195534Sscottl "Version from %d to %d?\n", cts->transport_version, 1924195534Sscottl device->transport_version); 1925195534Sscottl } 1926195534Sscottl cts->transport_version = device->transport_version; 1927195534Sscottl } 1928195534Sscottl 1929195534Sscottl sim = cts->ccb_h.path->bus->sim; 1930195534Sscottl 1931195534Sscottl /* 1932195534Sscottl * Nothing more of interest to do unless 1933195534Sscottl * this is a device connected via the 1934195534Sscottl * SCSI protocol. 1935195534Sscottl */ 1936195534Sscottl if (cts->protocol != PROTO_SCSI) { 1937195534Sscottl if (async_update == FALSE) 1938195534Sscottl (*(sim->sim_action))(sim, (union ccb *)cts); 1939195534Sscottl return; 1940195534Sscottl } 1941195534Sscottl 1942195534Sscottl inq_data = &device->inq_data; 1943195534Sscottl scsi = &cts->proto_specific.scsi; 1944203108Smav xpt_setup_ccb(&cpi.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NONE); 1945195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 1946195534Sscottl xpt_action((union ccb *)&cpi); 1947195534Sscottl 1948195534Sscottl /* SCSI specific sanity checking */ 1949195534Sscottl if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0 1950195534Sscottl || (INQ_DATA_TQ_ENABLED(inq_data)) == 0 1951195534Sscottl || (device->queue_flags & SCP_QUEUE_DQUE) != 0 1952195534Sscottl || (device->mintags == 0)) { 1953195534Sscottl /* 1954195534Sscottl * Can't tag on hardware that doesn't support tags, 1955195534Sscottl * doesn't have it enabled, or has broken tag support. 1956195534Sscottl */ 1957195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 1958195534Sscottl } 1959195534Sscottl 1960195534Sscottl if (async_update == FALSE) { 1961195534Sscottl /* 1962195534Sscottl * Perform sanity checking against what the 1963195534Sscottl * controller and device can do. 1964195534Sscottl */ 1965203108Smav xpt_setup_ccb(&cur_cts.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NONE); 1966195534Sscottl cur_cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1967195534Sscottl cur_cts.type = cts->type; 1968195534Sscottl xpt_action((union ccb *)&cur_cts); 1969195534Sscottl if ((cur_cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1970195534Sscottl return; 1971195534Sscottl } 1972195534Sscottl cur_scsi = &cur_cts.proto_specific.scsi; 1973195534Sscottl if ((scsi->valid & CTS_SCSI_VALID_TQ) == 0) { 1974195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 1975195534Sscottl scsi->flags |= cur_scsi->flags & CTS_SCSI_FLAGS_TAG_ENB; 1976195534Sscottl } 1977195534Sscottl if ((cur_scsi->valid & CTS_SCSI_VALID_TQ) == 0) 1978195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 1979195534Sscottl } 1980195534Sscottl 1981195534Sscottl if (cts->type == CTS_TYPE_CURRENT_SETTINGS 1982195534Sscottl && (scsi->valid & CTS_SCSI_VALID_TQ) != 0) { 1983195534Sscottl int device_tagenb; 1984195534Sscottl 1985195534Sscottl /* 1986195534Sscottl * If we are transitioning from tags to no-tags or 1987195534Sscottl * vice-versa, we need to carefully freeze and restart 1988195534Sscottl * the queue so that we don't overlap tagged and non-tagged 1989195534Sscottl * commands. We also temporarily stop tags if there is 1990195534Sscottl * a change in transfer negotiation settings to allow 1991195534Sscottl * "tag-less" negotiation. 1992195534Sscottl */ 1993195534Sscottl if ((device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 1994195534Sscottl || (device->inq_flags & SID_CmdQue) != 0) 1995195534Sscottl device_tagenb = TRUE; 1996195534Sscottl else 1997195534Sscottl device_tagenb = FALSE; 1998195534Sscottl 1999195534Sscottl if (((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0 2000195534Sscottl && device_tagenb == FALSE) 2001195534Sscottl || ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) == 0 2002195534Sscottl && device_tagenb == TRUE)) { 2003195534Sscottl 2004195534Sscottl if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) { 2005195534Sscottl /* 2006195534Sscottl * Delay change to use tags until after a 2007195534Sscottl * few commands have gone to this device so 2008195534Sscottl * the controller has time to perform transfer 2009195534Sscottl * negotiations without tagged messages getting 2010195534Sscottl * in the way. 2011195534Sscottl */ 2012195534Sscottl device->tag_delay_count = CAM_TAG_DELAY_COUNT; 2013195534Sscottl device->flags |= CAM_DEV_TAG_AFTER_COUNT; 2014195534Sscottl } else { 2015199178Smav xpt_stop_tags(cts->ccb_h.path); 2016195534Sscottl } 2017195534Sscottl } 2018195534Sscottl } 2019195534Sscottl if (async_update == FALSE) 2020195534Sscottl (*(sim->sim_action))(sim, (union ccb *)cts); 2021195534Sscottl} 2022195534Sscottl 2023195534Sscottl/* 2024195534Sscottl * Handle any per-device event notifications that require action by the XPT. 2025195534Sscottl */ 2026195534Sscottlstatic void 2027195534Sscottlata_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target, 2028195534Sscottl struct cam_ed *device, void *async_arg) 2029195534Sscottl{ 2030195534Sscottl cam_status status; 2031195534Sscottl struct cam_path newpath; 2032195534Sscottl 2033195534Sscottl /* 2034195534Sscottl * We only need to handle events for real devices. 2035195534Sscottl */ 2036195534Sscottl if (target->target_id == CAM_TARGET_WILDCARD 2037195534Sscottl || device->lun_id == CAM_LUN_WILDCARD) 2038195534Sscottl return; 2039195534Sscottl 2040195534Sscottl /* 2041195534Sscottl * We need our own path with wildcards expanded to 2042195534Sscottl * handle certain types of events. 2043195534Sscottl */ 2044195534Sscottl if ((async_code == AC_SENT_BDR) 2045195534Sscottl || (async_code == AC_BUS_RESET) 2046195534Sscottl || (async_code == AC_INQ_CHANGED)) 2047195534Sscottl status = xpt_compile_path(&newpath, NULL, 2048195534Sscottl bus->path_id, 2049195534Sscottl target->target_id, 2050195534Sscottl device->lun_id); 2051195534Sscottl else 2052195534Sscottl status = CAM_REQ_CMP_ERR; 2053195534Sscottl 2054195534Sscottl if (status == CAM_REQ_CMP) { 2055195534Sscottl if (async_code == AC_INQ_CHANGED) { 2056195534Sscottl /* 2057195534Sscottl * We've sent a start unit command, or 2058195534Sscottl * something similar to a device that 2059195534Sscottl * may have caused its inquiry data to 2060195534Sscottl * change. So we re-scan the device to 2061195534Sscottl * refresh the inquiry data for it. 2062195534Sscottl */ 2063195534Sscottl ata_scan_lun(newpath.periph, &newpath, 2064195534Sscottl CAM_EXPECT_INQ_CHANGE, NULL); 2065203108Smav } else { 2066203108Smav /* We need to reinitialize device after reset. */ 2067203108Smav ata_scan_lun(newpath.periph, &newpath, 2068203108Smav 0, NULL); 2069195534Sscottl } 2070195534Sscottl xpt_release_path(&newpath); 2071198748Smav } else if (async_code == AC_LOST_DEVICE && 2072198748Smav (device->flags & CAM_DEV_UNCONFIGURED) == 0) { 2073195534Sscottl device->flags |= CAM_DEV_UNCONFIGURED; 2074198748Smav xpt_release_device(device); 2075195534Sscottl } else if (async_code == AC_TRANSFER_NEG) { 2076195534Sscottl struct ccb_trans_settings *settings; 2077195534Sscottl 2078195534Sscottl settings = (struct ccb_trans_settings *)async_arg; 2079199178Smav ata_set_transfer_settings(settings, device, 2080195534Sscottl /*async_update*/TRUE); 2081195534Sscottl } 2082195534Sscottl} 2083195534Sscottl 2084204220Smavstatic void 2085204220Smavata_announce_periph(struct cam_periph *periph) 2086204220Smav{ 2087204220Smav struct ccb_pathinq cpi; 2088204220Smav struct ccb_trans_settings cts; 2089204220Smav struct cam_path *path = periph->path; 2090204220Smav u_int speed; 2091204220Smav u_int mb; 2092204220Smav 2093204220Smav mtx_assert(periph->sim->mtx, MA_OWNED); 2094204220Smav 2095204220Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); 2096204220Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 2097204220Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 2098204220Smav xpt_action((union ccb*)&cts); 2099204220Smav if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 2100204220Smav return; 2101204220Smav /* Ask the SIM for its base transfer speed */ 2102204220Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL); 2103204220Smav cpi.ccb_h.func_code = XPT_PATH_INQ; 2104204220Smav xpt_action((union ccb *)&cpi); 2105204220Smav /* Report connection speed */ 2106204220Smav speed = cpi.base_transfer_speed; 2107204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_ATA) { 2108204220Smav struct ccb_trans_settings_ata *ata = 2109204220Smav &cts.xport_specific.ata; 2110204220Smav 2111204220Smav if (ata->valid & CTS_ATA_VALID_MODE) 2112204220Smav speed = ata_mode2speed(ata->mode); 2113204220Smav } 2114204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SATA) { 2115204220Smav struct ccb_trans_settings_sata *sata = 2116204220Smav &cts.xport_specific.sata; 2117204220Smav 2118204220Smav if (sata->valid & CTS_SATA_VALID_REVISION) 2119204220Smav speed = ata_revision2speed(sata->revision); 2120204220Smav } 2121204220Smav mb = speed / 1000; 2122204220Smav if (mb > 0) 2123204220Smav printf("%s%d: %d.%03dMB/s transfers", 2124204220Smav periph->periph_name, periph->unit_number, 2125204220Smav mb, speed % 1000); 2126204220Smav else 2127204220Smav printf("%s%d: %dKB/s transfers", periph->periph_name, 2128204220Smav periph->unit_number, speed); 2129204220Smav /* Report additional information about connection */ 2130204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_ATA) { 2131204220Smav struct ccb_trans_settings_ata *ata = 2132204220Smav &cts.xport_specific.ata; 2133204220Smav 2134204220Smav printf(" ("); 2135204220Smav if (ata->valid & CTS_ATA_VALID_MODE) 2136204220Smav printf("%s, ", ata_mode2string(ata->mode)); 2137204220Smav if ((ata->valid & CTS_ATA_VALID_ATAPI) && ata->atapi != 0) 2138204220Smav printf("ATAPI %dbytes, ", ata->atapi); 2139204220Smav if (ata->valid & CTS_ATA_VALID_BYTECOUNT) 2140204220Smav printf("PIO %dbytes", ata->bytecount); 2141204220Smav printf(")"); 2142204220Smav } 2143204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SATA) { 2144204220Smav struct ccb_trans_settings_sata *sata = 2145204220Smav &cts.xport_specific.sata; 2146204220Smav 2147204220Smav printf(" ("); 2148204220Smav if (sata->valid & CTS_SATA_VALID_REVISION) 2149204220Smav printf("SATA %d.x, ", sata->revision); 2150204220Smav else 2151204220Smav printf("SATA, "); 2152204220Smav if (sata->valid & CTS_SATA_VALID_MODE) 2153204220Smav printf("%s, ", ata_mode2string(sata->mode)); 2154204220Smav if ((sata->valid & CTS_ATA_VALID_ATAPI) && sata->atapi != 0) 2155204220Smav printf("ATAPI %dbytes, ", sata->atapi); 2156204220Smav if (sata->valid & CTS_SATA_VALID_BYTECOUNT) 2157204220Smav printf("PIO %dbytes", sata->bytecount); 2158204220Smav printf(")"); 2159204220Smav } 2160204220Smav printf("\n"); 2161204220Smav} 2162204220Smav 2163