ata_xpt.c revision 307606
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: stable/11/sys/cam/ata/ata_xpt.c 307606 2016-10-19 06:15:27Z sephe $"); 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 43307606Ssephe#include <sys/eventhandler.h> 44195534Sscottl#include <sys/lock.h> 45195534Sscottl#include <sys/mutex.h> 46195534Sscottl#include <sys/sysctl.h> 47195534Sscottl 48195534Sscottl#include <cam/cam.h> 49195534Sscottl#include <cam/cam_ccb.h> 50195534Sscottl#include <cam/cam_queue.h> 51195534Sscottl#include <cam/cam_periph.h> 52195534Sscottl#include <cam/cam_sim.h> 53195534Sscottl#include <cam/cam_xpt.h> 54195534Sscottl#include <cam/cam_xpt_sim.h> 55195534Sscottl#include <cam/cam_xpt_periph.h> 56195534Sscottl#include <cam/cam_xpt_internal.h> 57195534Sscottl#include <cam/cam_debug.h> 58195534Sscottl 59195534Sscottl#include <cam/scsi/scsi_all.h> 60195534Sscottl#include <cam/scsi/scsi_message.h> 61195534Sscottl#include <cam/ata/ata_all.h> 62195534Sscottl#include <machine/stdarg.h> /* for xpt_print below */ 63195534Sscottl#include "opt_cam.h" 64195534Sscottl 65199178Smavstruct ata_quirk_entry { 66195534Sscottl struct scsi_inquiry_pattern inq_pat; 67195534Sscottl u_int8_t quirks; 68199178Smav#define CAM_QUIRK_MAXTAGS 0x01 69236234Smav u_int mintags; 70195534Sscottl u_int maxtags; 71195534Sscottl}; 72195534Sscottl 73195534Sscottlstatic periph_init_t probe_periph_init; 74195534Sscottl 75195534Sscottlstatic struct periph_driver probe_driver = 76195534Sscottl{ 77195653Smav probe_periph_init, "aprobe", 78198708Smav TAILQ_HEAD_INITIALIZER(probe_driver.units), /* generation */ 0, 79198708Smav CAM_PERIPH_DRV_EARLY 80195534Sscottl}; 81195534Sscottl 82195653SmavPERIPHDRIVER_DECLARE(aprobe, probe_driver); 83195534Sscottl 84195534Sscottltypedef enum { 85195534Sscottl PROBE_RESET, 86195534Sscottl PROBE_IDENTIFY, 87203421Smav PROBE_SPINUP, 88195534Sscottl PROBE_SETMODE, 89207499Smav PROBE_SETPM, 90207499Smav PROBE_SETAPST, 91207499Smav PROBE_SETDMAAA, 92220602Smav PROBE_SETAN, 93198708Smav PROBE_SET_MULTI, 94195534Sscottl PROBE_INQUIRY, 95195534Sscottl PROBE_FULL_INQUIRY, 96195534Sscottl PROBE_PM_PID, 97195534Sscottl PROBE_PM_PRV, 98235897Smav PROBE_IDENTIFY_SES, 99235897Smav PROBE_IDENTIFY_SAFTE, 100236613Smav PROBE_DONE, 101195534Sscottl PROBE_INVALID 102195534Sscottl} probe_action; 103195534Sscottl 104195534Sscottlstatic char *probe_action_text[] = { 105195534Sscottl "PROBE_RESET", 106195534Sscottl "PROBE_IDENTIFY", 107203421Smav "PROBE_SPINUP", 108195534Sscottl "PROBE_SETMODE", 109207499Smav "PROBE_SETPM", 110207499Smav "PROBE_SETAPST", 111207499Smav "PROBE_SETDMAAA", 112220602Smav "PROBE_SETAN", 113198708Smav "PROBE_SET_MULTI", 114195534Sscottl "PROBE_INQUIRY", 115195534Sscottl "PROBE_FULL_INQUIRY", 116195534Sscottl "PROBE_PM_PID", 117195534Sscottl "PROBE_PM_PRV", 118235897Smav "PROBE_IDENTIFY_SES", 119235897Smav "PROBE_IDENTIFY_SAFTE", 120236613Smav "PROBE_DONE", 121195534Sscottl "PROBE_INVALID" 122195534Sscottl}; 123195534Sscottl 124195534Sscottl#define PROBE_SET_ACTION(softc, newaction) \ 125195534Sscottldo { \ 126195534Sscottl char **text; \ 127195534Sscottl text = probe_action_text; \ 128236613Smav CAM_DEBUG((softc)->periph->path, CAM_DEBUG_PROBE, \ 129195534Sscottl ("Probe %s to %s\n", text[(softc)->action], \ 130195534Sscottl text[(newaction)])); \ 131195534Sscottl (softc)->action = (newaction); \ 132195534Sscottl} while(0) 133195534Sscottl 134195534Sscottltypedef enum { 135195534Sscottl PROBE_NO_ANNOUNCE = 0x04 136195534Sscottl} probe_flags; 137195534Sscottl 138195534Sscottltypedef struct { 139195534Sscottl TAILQ_HEAD(, ccb_hdr) request_ccbs; 140203385Smav struct ata_params ident_data; 141195534Sscottl probe_action action; 142195534Sscottl probe_flags flags; 143195534Sscottl uint32_t pm_pid; 144195534Sscottl uint32_t pm_prv; 145203108Smav int restart; 146203421Smav int spinup; 147209744Smav int faults; 148207499Smav u_int caps; 149195534Sscottl struct cam_periph *periph; 150195534Sscottl} probe_softc; 151195534Sscottl 152199178Smavstatic struct ata_quirk_entry ata_quirk_table[] = 153195534Sscottl{ 154195534Sscottl { 155195534Sscottl /* Default tagged queuing parameters for all devices */ 156195534Sscottl { 157195534Sscottl T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED, 158195534Sscottl /*vendor*/"*", /*product*/"*", /*revision*/"*" 159195534Sscottl }, 160236234Smav /*quirks*/0, /*mintags*/0, /*maxtags*/0 161195534Sscottl }, 162195534Sscottl}; 163195534Sscottl 164195534Sscottlstatic cam_status proberegister(struct cam_periph *periph, 165195534Sscottl void *arg); 166195534Sscottlstatic void probeschedule(struct cam_periph *probe_periph); 167195534Sscottlstatic void probestart(struct cam_periph *periph, union ccb *start_ccb); 168236437Smavstatic void proberequestdefaultnegotiation(struct cam_periph *periph); 169195534Sscottlstatic void probedone(struct cam_periph *periph, union ccb *done_ccb); 170195534Sscottlstatic void probecleanup(struct cam_periph *periph); 171199178Smavstatic void ata_find_quirk(struct cam_ed *device); 172195534Sscottlstatic void ata_scan_bus(struct cam_periph *periph, union ccb *ccb); 173195534Sscottlstatic void ata_scan_lun(struct cam_periph *periph, 174195534Sscottl struct cam_path *path, cam_flags flags, 175195534Sscottl union ccb *ccb); 176195534Sscottlstatic void xptscandone(struct cam_periph *periph, union ccb *done_ccb); 177195534Sscottlstatic struct cam_ed * 178195534Sscottl ata_alloc_device(struct cam_eb *bus, struct cam_et *target, 179195534Sscottl lun_id_t lun_id); 180195534Sscottlstatic void ata_device_transport(struct cam_path *path); 181236437Smavstatic void ata_get_transfer_settings(struct ccb_trans_settings *cts); 182199178Smavstatic void ata_set_transfer_settings(struct ccb_trans_settings *cts, 183256843Smav struct cam_path *path, 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 (request_ccb == NULL) { 226195534Sscottl printf("proberegister: no probe CCB, " 227195534Sscottl "can't register device\n"); 228195534Sscottl return(CAM_REQ_CMP_ERR); 229195534Sscottl } 230195534Sscottl 231203421Smav softc = (probe_softc *)malloc(sizeof(*softc), M_CAMXPT, M_ZERO | M_NOWAIT); 232195534Sscottl 233195534Sscottl if (softc == NULL) { 234195534Sscottl printf("proberegister: Unable to probe new device. " 235195534Sscottl "Unable to allocate softc\n"); 236195534Sscottl return(CAM_REQ_CMP_ERR); 237195534Sscottl } 238195534Sscottl TAILQ_INIT(&softc->request_ccbs); 239195534Sscottl TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h, 240195534Sscottl periph_links.tqe); 241195534Sscottl softc->flags = 0; 242195534Sscottl periph->softc = softc; 243195534Sscottl softc->periph = periph; 244195534Sscottl softc->action = PROBE_INVALID; 245195534Sscottl status = cam_periph_acquire(periph); 246195534Sscottl if (status != CAM_REQ_CMP) { 247195534Sscottl return (status); 248195534Sscottl } 249236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe started\n")); 250256843Smav ata_device_transport(periph->path); 251195534Sscottl probeschedule(periph); 252195534Sscottl return(CAM_REQ_CMP); 253195534Sscottl} 254195534Sscottl 255195534Sscottlstatic void 256195534Sscottlprobeschedule(struct cam_periph *periph) 257195534Sscottl{ 258195534Sscottl union ccb *ccb; 259195534Sscottl probe_softc *softc; 260195534Sscottl 261195534Sscottl softc = (probe_softc *)periph->softc; 262195534Sscottl ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs); 263195534Sscottl 264198389Smav if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) || 265235897Smav periph->path->device->protocol == PROTO_SATAPM || 266235897Smav periph->path->device->protocol == PROTO_SEMB) 267195534Sscottl PROBE_SET_ACTION(softc, PROBE_RESET); 268195534Sscottl else 269195534Sscottl PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 270195534Sscottl 271195534Sscottl if (ccb->crcn.flags & CAM_EXPECT_INQ_CHANGE) 272195534Sscottl softc->flags |= PROBE_NO_ANNOUNCE; 273195534Sscottl else 274195534Sscottl softc->flags &= ~PROBE_NO_ANNOUNCE; 275195534Sscottl 276203108Smav xpt_schedule(periph, CAM_PRIORITY_XPT); 277195534Sscottl} 278195534Sscottl 279195534Sscottlstatic void 280195534Sscottlprobestart(struct cam_periph *periph, union ccb *start_ccb) 281195534Sscottl{ 282199747Smav struct ccb_trans_settings cts; 283195534Sscottl struct ccb_ataio *ataio; 284195534Sscottl struct ccb_scsiio *csio; 285195534Sscottl probe_softc *softc; 286198708Smav struct cam_path *path; 287198708Smav struct ata_params *ident_buf; 288195534Sscottl 289195534Sscottl CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probestart\n")); 290195534Sscottl 291195534Sscottl softc = (probe_softc *)periph->softc; 292198708Smav path = start_ccb->ccb_h.path; 293195534Sscottl ataio = &start_ccb->ataio; 294195534Sscottl csio = &start_ccb->csio; 295198708Smav ident_buf = &periph->path->device->ident_data; 296195534Sscottl 297203108Smav if (softc->restart) { 298203108Smav softc->restart = 0; 299203108Smav if ((path->device->flags & CAM_DEV_UNCONFIGURED) || 300235897Smav path->device->protocol == PROTO_SATAPM || 301235897Smav path->device->protocol == PROTO_SEMB) 302203108Smav softc->action = PROBE_RESET; 303203108Smav else 304203108Smav softc->action = PROBE_IDENTIFY; 305203108Smav } 306195534Sscottl switch (softc->action) { 307195534Sscottl case PROBE_RESET: 308195534Sscottl cam_fill_ataio(ataio, 309195534Sscottl 0, 310195534Sscottl probedone, 311195534Sscottl /*flags*/CAM_DIR_NONE, 312198389Smav 0, 313195534Sscottl /*data_ptr*/NULL, 314195534Sscottl /*dxfer_len*/0, 315203108Smav 15 * 1000); 316195534Sscottl ata_reset_cmd(ataio); 317195534Sscottl break; 318195534Sscottl case PROBE_IDENTIFY: 319195534Sscottl cam_fill_ataio(ataio, 320195534Sscottl 1, 321195534Sscottl probedone, 322195534Sscottl /*flags*/CAM_DIR_IN, 323198389Smav 0, 324203385Smav /*data_ptr*/(u_int8_t *)&softc->ident_data, 325203385Smav /*dxfer_len*/sizeof(softc->ident_data), 326195534Sscottl 30 * 1000); 327195534Sscottl if (periph->path->device->protocol == PROTO_ATA) 328196659Smav ata_28bit_cmd(ataio, ATA_ATA_IDENTIFY, 0, 0, 0); 329195534Sscottl else 330196659Smav ata_28bit_cmd(ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0); 331195534Sscottl break; 332203421Smav case PROBE_SPINUP: 333203421Smav if (bootverbose) 334203421Smav xpt_print(path, "Spinning up device\n"); 335203421Smav cam_fill_ataio(ataio, 336203421Smav 1, 337203421Smav probedone, 338203421Smav /*flags*/CAM_DIR_NONE | CAM_HIGH_POWER, 339203421Smav 0, 340203421Smav /*data_ptr*/NULL, 341203421Smav /*dxfer_len*/0, 342203421Smav 30 * 1000); 343203421Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_PUIS_SPINUP, 0, 0); 344203421Smav break; 345195534Sscottl case PROBE_SETMODE: 346199747Smav { 347199747Smav int mode, wantmode; 348199747Smav 349199747Smav mode = 0; 350199747Smav /* Fetch user modes from SIM. */ 351199747Smav bzero(&cts, sizeof(cts)); 352203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 353199747Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 354199747Smav cts.type = CTS_TYPE_USER_SETTINGS; 355199747Smav xpt_action((union ccb *)&cts); 356199747Smav if (path->device->transport == XPORT_ATA) { 357199747Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_MODE) 358199747Smav mode = cts.xport_specific.ata.mode; 359199747Smav } else { 360199799Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_MODE) 361199747Smav mode = cts.xport_specific.sata.mode; 362199747Smav } 363230912Smav if (periph->path->device->protocol == PROTO_ATA) { 364230912Smav if (ata_dma == 0 && (mode == 0 || mode > ATA_PIO_MAX)) 365230912Smav mode = ATA_PIO_MAX; 366230912Smav } else { 367230912Smav if (atapi_dma == 0 && (mode == 0 || mode > ATA_PIO_MAX)) 368230912Smav mode = ATA_PIO_MAX; 369230912Smav } 370199747Smavnegotiate: 371199747Smav /* Honor device capabilities. */ 372199747Smav wantmode = mode = ata_max_mode(ident_buf, mode); 373199747Smav /* Report modes to SIM. */ 374199747Smav bzero(&cts, sizeof(cts)); 375203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 376199747Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 377199747Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 378199747Smav if (path->device->transport == XPORT_ATA) { 379199747Smav cts.xport_specific.ata.mode = mode; 380199747Smav cts.xport_specific.ata.valid = CTS_ATA_VALID_MODE; 381199747Smav } else { 382199747Smav cts.xport_specific.sata.mode = mode; 383199747Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_MODE; 384199747Smav } 385199747Smav xpt_action((union ccb *)&cts); 386200171Smav /* Fetch current modes from SIM. */ 387199747Smav bzero(&cts, sizeof(cts)); 388203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 389199747Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 390199747Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 391199747Smav xpt_action((union ccb *)&cts); 392199747Smav if (path->device->transport == XPORT_ATA) { 393199747Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_MODE) 394199747Smav mode = cts.xport_specific.ata.mode; 395199747Smav } else { 396199747Smav if (cts.xport_specific.ata.valid & CTS_SATA_VALID_MODE) 397199747Smav mode = cts.xport_specific.sata.mode; 398199747Smav } 399199747Smav /* If SIM disagree - renegotiate. */ 400199747Smav if (mode != wantmode) 401199747Smav goto negotiate; 402220886Smav /* Remember what transport thinks about DMA. */ 403220886Smav if (mode < ATA_DMA) 404220886Smav path->device->inq_flags &= ~SID_DMA; 405220886Smav else 406220886Smav path->device->inq_flags |= SID_DMA; 407236393Smav xpt_async(AC_GETDEV_CHANGED, path, NULL); 408195534Sscottl cam_fill_ataio(ataio, 409195534Sscottl 1, 410195534Sscottl probedone, 411196353Smav /*flags*/CAM_DIR_NONE, 412196353Smav 0, 413196353Smav /*data_ptr*/NULL, 414196353Smav /*dxfer_len*/0, 415195534Sscottl 30 * 1000); 416199747Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); 417195534Sscottl break; 418199747Smav } 419207499Smav case PROBE_SETPM: 420207499Smav cam_fill_ataio(ataio, 421207499Smav 1, 422207499Smav probedone, 423207499Smav CAM_DIR_NONE, 424207499Smav 0, 425207499Smav NULL, 426207499Smav 0, 427207499Smav 30*1000); 428207499Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, 429207499Smav (softc->caps & CTS_SATA_CAPS_H_PMREQ) ? 0x10 : 0x90, 430207499Smav 0, 0x03); 431207499Smav break; 432207499Smav case PROBE_SETAPST: 433207499Smav cam_fill_ataio(ataio, 434207499Smav 1, 435207499Smav probedone, 436207499Smav CAM_DIR_NONE, 437207499Smav 0, 438207499Smav NULL, 439207499Smav 0, 440207499Smav 30*1000); 441207499Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, 442207499Smav (softc->caps & CTS_SATA_CAPS_H_APST) ? 0x10 : 0x90, 443207499Smav 0, 0x07); 444207499Smav break; 445207499Smav case PROBE_SETDMAAA: 446207499Smav cam_fill_ataio(ataio, 447207499Smav 1, 448207499Smav probedone, 449207499Smav CAM_DIR_NONE, 450207499Smav 0, 451207499Smav NULL, 452207499Smav 0, 453207499Smav 30*1000); 454207499Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, 455207499Smav (softc->caps & CTS_SATA_CAPS_H_DMAAA) ? 0x10 : 0x90, 456207499Smav 0, 0x02); 457207499Smav break; 458220602Smav case PROBE_SETAN: 459270327Simp /* Remember what transport thinks about AEN. */ 460270327Simp if (softc->caps & CTS_SATA_CAPS_H_AN) 461238886Smav path->device->inq_flags |= SID_AEN; 462238886Smav else 463238886Smav path->device->inq_flags &= ~SID_AEN; 464238886Smav xpt_async(AC_GETDEV_CHANGED, path, NULL); 465220602Smav cam_fill_ataio(ataio, 466220602Smav 1, 467220602Smav probedone, 468220602Smav CAM_DIR_NONE, 469220602Smav 0, 470220602Smav NULL, 471220602Smav 0, 472220602Smav 30*1000); 473220602Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, 474220602Smav (softc->caps & CTS_SATA_CAPS_H_AN) ? 0x10 : 0x90, 475220602Smav 0, 0x05); 476220602Smav break; 477198708Smav case PROBE_SET_MULTI: 478198708Smav { 479200171Smav u_int sectors, bytecount; 480198708Smav 481200171Smav bytecount = 8192; /* SATA maximum */ 482200171Smav /* Fetch user bytecount from SIM. */ 483200171Smav bzero(&cts, sizeof(cts)); 484203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 485200171Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 486200171Smav cts.type = CTS_TYPE_USER_SETTINGS; 487200171Smav xpt_action((union ccb *)&cts); 488200171Smav if (path->device->transport == XPORT_ATA) { 489200171Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 490200171Smav bytecount = cts.xport_specific.ata.bytecount; 491200171Smav } else { 492200171Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 493200171Smav bytecount = cts.xport_specific.sata.bytecount; 494200171Smav } 495200171Smav /* Honor device capabilities. */ 496200171Smav sectors = max(1, min(ident_buf->sectors_intr & 0xff, 497200171Smav bytecount / ata_logical_sector_size(ident_buf))); 498198708Smav /* Report bytecount to SIM. */ 499198708Smav bzero(&cts, sizeof(cts)); 500203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 501198708Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 502198708Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 503198708Smav if (path->device->transport == XPORT_ATA) { 504198897Smav cts.xport_specific.ata.bytecount = sectors * 505198897Smav ata_logical_sector_size(ident_buf); 506198708Smav cts.xport_specific.ata.valid = CTS_ATA_VALID_BYTECOUNT; 507198708Smav } else { 508198897Smav cts.xport_specific.sata.bytecount = sectors * 509198897Smav ata_logical_sector_size(ident_buf); 510198708Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_BYTECOUNT; 511198708Smav } 512198708Smav xpt_action((union ccb *)&cts); 513200171Smav /* Fetch current bytecount from SIM. */ 514200171Smav bzero(&cts, sizeof(cts)); 515203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 516200171Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 517200171Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 518200171Smav xpt_action((union ccb *)&cts); 519200171Smav if (path->device->transport == XPORT_ATA) { 520200171Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 521200171Smav bytecount = cts.xport_specific.ata.bytecount; 522200171Smav } else { 523200171Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 524200171Smav bytecount = cts.xport_specific.sata.bytecount; 525200171Smav } 526200171Smav sectors = bytecount / ata_logical_sector_size(ident_buf); 527198708Smav 528198708Smav cam_fill_ataio(ataio, 529198708Smav 1, 530198708Smav probedone, 531198708Smav CAM_DIR_NONE, 532198708Smav 0, 533198708Smav NULL, 534198708Smav 0, 535198708Smav 30*1000); 536198708Smav ata_28bit_cmd(ataio, ATA_SET_MULTI, 0, 0, sectors); 537198708Smav break; 538195534Sscottl } 539195534Sscottl case PROBE_INQUIRY: 540200171Smav { 541200171Smav u_int bytecount; 542200171Smav 543200171Smav bytecount = 8192; /* SATA maximum */ 544200171Smav /* Fetch user bytecount from SIM. */ 545200171Smav bzero(&cts, sizeof(cts)); 546203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 547200171Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 548200171Smav cts.type = CTS_TYPE_USER_SETTINGS; 549200171Smav xpt_action((union ccb *)&cts); 550200171Smav if (path->device->transport == XPORT_ATA) { 551200171Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 552200171Smav bytecount = cts.xport_specific.ata.bytecount; 553200171Smav } else { 554200171Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 555200171Smav bytecount = cts.xport_specific.sata.bytecount; 556200171Smav } 557200171Smav /* Honor device capabilities. */ 558200171Smav bytecount &= ~1; 559200171Smav bytecount = max(2, min(65534, bytecount)); 560200171Smav if (ident_buf->satacapabilities != 0x0000 && 561200171Smav ident_buf->satacapabilities != 0xffff) { 562200171Smav bytecount = min(8192, bytecount); 563200171Smav } 564200171Smav /* Report bytecount to SIM. */ 565200171Smav bzero(&cts, sizeof(cts)); 566203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 567200171Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 568200171Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 569200171Smav if (path->device->transport == XPORT_ATA) { 570200171Smav cts.xport_specific.ata.bytecount = bytecount; 571200171Smav cts.xport_specific.ata.valid = CTS_ATA_VALID_BYTECOUNT; 572200171Smav } else { 573200171Smav cts.xport_specific.sata.bytecount = bytecount; 574200171Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_BYTECOUNT; 575200171Smav } 576200171Smav xpt_action((union ccb *)&cts); 577200171Smav /* FALLTHROUGH */ 578200171Smav } 579195534Sscottl case PROBE_FULL_INQUIRY: 580195534Sscottl { 581195534Sscottl u_int inquiry_len; 582195534Sscottl struct scsi_inquiry_data *inq_buf = 583195534Sscottl &periph->path->device->inq_data; 584195534Sscottl 585195534Sscottl if (softc->action == PROBE_INQUIRY) 586195534Sscottl inquiry_len = SHORT_INQUIRY_LENGTH; 587195534Sscottl else 588195534Sscottl inquiry_len = SID_ADDITIONAL_LENGTH(inq_buf); 589195534Sscottl /* 590195534Sscottl * Some parallel SCSI devices fail to send an 591195534Sscottl * ignore wide residue message when dealing with 592195534Sscottl * odd length inquiry requests. Round up to be 593195534Sscottl * safe. 594195534Sscottl */ 595195534Sscottl inquiry_len = roundup2(inquiry_len, 2); 596195534Sscottl scsi_inquiry(csio, 597195534Sscottl /*retries*/1, 598195534Sscottl probedone, 599195534Sscottl MSG_SIMPLE_Q_TAG, 600195534Sscottl (u_int8_t *)inq_buf, 601195534Sscottl inquiry_len, 602195534Sscottl /*evpd*/FALSE, 603195534Sscottl /*page_code*/0, 604195534Sscottl SSD_MIN_SIZE, 605195534Sscottl /*timeout*/60 * 1000); 606195534Sscottl break; 607195534Sscottl } 608195534Sscottl case PROBE_PM_PID: 609195534Sscottl cam_fill_ataio(ataio, 610195534Sscottl 1, 611195534Sscottl probedone, 612195534Sscottl /*flags*/CAM_DIR_NONE, 613198389Smav 0, 614195534Sscottl /*data_ptr*/NULL, 615195534Sscottl /*dxfer_len*/0, 616195534Sscottl 10 * 1000); 617195534Sscottl ata_pm_read_cmd(ataio, 0, 15); 618195534Sscottl break; 619195534Sscottl case PROBE_PM_PRV: 620195534Sscottl cam_fill_ataio(ataio, 621195534Sscottl 1, 622195534Sscottl probedone, 623195534Sscottl /*flags*/CAM_DIR_NONE, 624198389Smav 0, 625195534Sscottl /*data_ptr*/NULL, 626195534Sscottl /*dxfer_len*/0, 627195534Sscottl 10 * 1000); 628195534Sscottl ata_pm_read_cmd(ataio, 1, 15); 629195534Sscottl break; 630235897Smav case PROBE_IDENTIFY_SES: 631235897Smav cam_fill_ataio(ataio, 632235897Smav 1, 633235897Smav probedone, 634235897Smav /*flags*/CAM_DIR_IN, 635235897Smav 0, 636235897Smav /*data_ptr*/(u_int8_t *)&softc->ident_data, 637235897Smav /*dxfer_len*/sizeof(softc->ident_data), 638235897Smav 30 * 1000); 639235897Smav ata_28bit_cmd(ataio, ATA_SEP_ATTN, 0xEC, 0x02, 640235897Smav sizeof(softc->ident_data) / 4); 641235897Smav break; 642235897Smav case PROBE_IDENTIFY_SAFTE: 643235897Smav cam_fill_ataio(ataio, 644235897Smav 1, 645235897Smav probedone, 646235897Smav /*flags*/CAM_DIR_IN, 647235897Smav 0, 648235897Smav /*data_ptr*/(u_int8_t *)&softc->ident_data, 649235897Smav /*dxfer_len*/sizeof(softc->ident_data), 650235897Smav 30 * 1000); 651235897Smav ata_28bit_cmd(ataio, ATA_SEP_ATTN, 0xEC, 0x00, 652235897Smav sizeof(softc->ident_data) / 4); 653235897Smav break; 654195534Sscottl default: 655236613Smav panic("probestart: invalid action state 0x%x\n", softc->action); 656195534Sscottl } 657249466Smav start_ccb->ccb_h.flags |= CAM_DEV_QFREEZE; 658195534Sscottl xpt_action(start_ccb); 659195534Sscottl} 660236437Smav 661195534Sscottlstatic void 662195534Sscottlproberequestdefaultnegotiation(struct cam_periph *periph) 663195534Sscottl{ 664195534Sscottl struct ccb_trans_settings cts; 665195534Sscottl 666203108Smav xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE); 667195534Sscottl cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 668195534Sscottl cts.type = CTS_TYPE_USER_SETTINGS; 669195534Sscottl xpt_action((union ccb *)&cts); 670236437Smav if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 671195534Sscottl return; 672236437Smav cts.xport_specific.valid = 0; 673195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 674195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 675195534Sscottl xpt_action((union ccb *)&cts); 676195534Sscottl} 677195534Sscottl 678195534Sscottlstatic void 679195534Sscottlprobedone(struct cam_periph *periph, union ccb *done_ccb) 680195534Sscottl{ 681199747Smav struct ccb_trans_settings cts; 682195534Sscottl struct ata_params *ident_buf; 683235897Smav struct scsi_inquiry_data *inq_buf; 684195534Sscottl probe_softc *softc; 685195534Sscottl struct cam_path *path; 686217444Smav cam_status status; 687195534Sscottl u_int32_t priority; 688207499Smav u_int caps; 689235897Smav int changed = 1, found = 1; 690235897Smav static const uint8_t fake_device_id_hdr[8] = 691235897Smav {0, SVPD_DEVICE_ID, 0, 12, 692235897Smav SVPD_ID_CODESET_BINARY, SVPD_ID_TYPE_NAA, 0, 8}; 693195534Sscottl 694195534Sscottl CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probedone\n")); 695195534Sscottl 696195534Sscottl softc = (probe_softc *)periph->softc; 697195534Sscottl path = done_ccb->ccb_h.path; 698195534Sscottl priority = done_ccb->ccb_h.pinfo.priority; 699195534Sscottl ident_buf = &path->device->ident_data; 700235897Smav inq_buf = &path->device->inq_data; 701195534Sscottl 702198708Smav if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 703236814Smav if (cam_periph_error(done_ccb, 704236814Smav 0, softc->restart ? (SF_NO_RECOVERY | SF_NO_RETRY) : 0, 705249466Smav NULL) == ERESTART) { 706249466Smavout: 707249466Smav /* Drop freeze taken due to CAM_DEV_QFREEZE flag set. */ 708249466Smav cam_release_devq(path, 0, 0, 0, FALSE); 709195534Sscottl return; 710249466Smav } 711209744Smav if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 712195534Sscottl /* Don't wedge the queue */ 713249466Smav xpt_release_devq(path, /*count*/1, /*run_queue*/TRUE); 714195534Sscottl } 715217444Smav status = done_ccb->ccb_h.status & CAM_STATUS_MASK; 716209744Smav if (softc->restart) { 717209744Smav softc->faults++; 718209744Smav if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == 719209744Smav CAM_CMD_TIMEOUT) 720209744Smav softc->faults += 4; 721209744Smav if (softc->faults < 10) 722209744Smav goto done; 723209744Smav else 724209744Smav softc->restart = 0; 725217444Smav 726198708Smav /* Old PIO2 devices may not support mode setting. */ 727217444Smav } else if (softc->action == PROBE_SETMODE && 728217444Smav status == CAM_ATA_STATUS_ERROR && 729198708Smav ata_max_pmode(ident_buf) <= ATA_PIO2 && 730217444Smav (ident_buf->capabilities1 & ATA_SUPPORT_IORDY) == 0) { 731198708Smav goto noerror; 732217444Smav 733198708Smav /* 734217444Smav * Some old WD SATA disks report supported and enabled 735217444Smav * device-initiated interface power management, but return 736217444Smav * ABORT on attempt to disable it. 737217444Smav */ 738217444Smav } else if (softc->action == PROBE_SETPM && 739217444Smav status == CAM_ATA_STATUS_ERROR) { 740217444Smav goto noerror; 741217875Smav 742217875Smav /* 743217875Smav * Some HP SATA disks report supported DMA Auto-Activation, 744217875Smav * but return ABORT on attempt to enable it. 745217875Smav */ 746217875Smav } else if (softc->action == PROBE_SETDMAAA && 747217875Smav status == CAM_ATA_STATUS_ERROR) { 748217875Smav goto noerror; 749235897Smav 750235897Smav /* 751235897Smav * SES and SAF-TE SEPs have different IDENTIFY commands, 752235897Smav * but SATA specification doesn't tell how to identify them. 753235897Smav * Until better way found, just try another if first fail. 754235897Smav */ 755235897Smav } else if (softc->action == PROBE_IDENTIFY_SES && 756235897Smav status == CAM_ATA_STATUS_ERROR) { 757235897Smav PROBE_SET_ACTION(softc, PROBE_IDENTIFY_SAFTE); 758235897Smav xpt_release_ccb(done_ccb); 759235897Smav xpt_schedule(periph, priority); 760249466Smav goto out; 761217444Smav } 762217444Smav 763217444Smav /* 764198708Smav * If we get to this point, we got an error status back 765198708Smav * from the inquiry and the error status doesn't require 766198708Smav * automatically retrying the command. Therefore, the 767198708Smav * inquiry failed. If we had inquiry information before 768198708Smav * for this device, but this latest inquiry command failed, 769198708Smav * the device has probably gone away. If this device isn't 770198708Smav * already marked unconfigured, notify the peripheral 771198708Smav * drivers that this device is no more. 772198708Smav */ 773209744Smavdevice_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0) 774198708Smav xpt_async(AC_LOST_DEVICE, path, NULL); 775236613Smav PROBE_SET_ACTION(softc, PROBE_INVALID); 776198708Smav found = 0; 777198708Smav goto done; 778198708Smav } 779198708Smavnoerror: 780203385Smav if (softc->restart) 781203385Smav goto done; 782198708Smav switch (softc->action) { 783198708Smav case PROBE_RESET: 784195534Sscottl { 785198708Smav int sign = (done_ccb->ataio.res.lba_high << 8) + 786198708Smav done_ccb->ataio.res.lba_mid; 787236613Smav CAM_DEBUG(path, CAM_DEBUG_PROBE, 788236613Smav ("SIGNATURE: %04x\n", sign)); 789198708Smav if (sign == 0x0000 && 790198708Smav done_ccb->ccb_h.target_id != 15) { 791198708Smav path->device->protocol = PROTO_ATA; 792198708Smav PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 793198708Smav } else if (sign == 0x9669 && 794198708Smav done_ccb->ccb_h.target_id == 15) { 795199747Smav /* Report SIM that PM is present. */ 796198708Smav bzero(&cts, sizeof(cts)); 797203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 798198708Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 799198708Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 800198708Smav cts.xport_specific.sata.pm_present = 1; 801198708Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; 802198708Smav xpt_action((union ccb *)&cts); 803198708Smav path->device->protocol = PROTO_SATAPM; 804198708Smav PROBE_SET_ACTION(softc, PROBE_PM_PID); 805235897Smav } else if (sign == 0xc33c && 806235897Smav done_ccb->ccb_h.target_id != 15) { 807235897Smav path->device->protocol = PROTO_SEMB; 808235897Smav PROBE_SET_ACTION(softc, PROBE_IDENTIFY_SES); 809198708Smav } else if (sign == 0xeb14 && 810198708Smav done_ccb->ccb_h.target_id != 15) { 811198708Smav path->device->protocol = PROTO_SCSI; 812198708Smav PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 813198708Smav } else { 814198708Smav if (done_ccb->ccb_h.target_id != 15) { 815198708Smav xpt_print(path, 816198708Smav "Unexpected signature 0x%04x\n", sign); 817195534Sscottl } 818198708Smav goto device_fail; 819198708Smav } 820198708Smav xpt_release_ccb(done_ccb); 821198708Smav xpt_schedule(periph, priority); 822249466Smav goto out; 823198708Smav } 824198708Smav case PROBE_IDENTIFY: 825198708Smav { 826207222Smav struct ccb_pathinq cpi; 827198708Smav int16_t *ptr; 828307606Ssephe int veto = 0; 829195534Sscottl 830203385Smav ident_buf = &softc->ident_data; 831198708Smav for (ptr = (int16_t *)ident_buf; 832198708Smav ptr < (int16_t *)ident_buf + sizeof(struct ata_params)/2; ptr++) { 833198708Smav *ptr = le16toh(*ptr); 834198708Smav } 835307606Ssephe 836307606Ssephe /* 837307606Ssephe * Allow others to veto this ATA disk attachment. This 838307606Ssephe * is mainly used by VMs, whose disk controllers may 839307606Ssephe * share the disks with the simulated ATA controllers. 840307606Ssephe */ 841307606Ssephe EVENTHANDLER_INVOKE(ada_probe_veto, path, ident_buf, &veto); 842307606Ssephe if (veto) { 843307606Ssephe goto device_fail; 844307606Ssephe } 845307606Ssephe 846198708Smav if (strncmp(ident_buf->model, "FX", 2) && 847198708Smav strncmp(ident_buf->model, "NEC", 3) && 848198708Smav strncmp(ident_buf->model, "Pioneer", 7) && 849198708Smav strncmp(ident_buf->model, "SHARP", 5)) { 850198708Smav ata_bswap(ident_buf->model, sizeof(ident_buf->model)); 851198708Smav ata_bswap(ident_buf->revision, sizeof(ident_buf->revision)); 852198708Smav ata_bswap(ident_buf->serial, sizeof(ident_buf->serial)); 853198708Smav } 854198708Smav ata_btrim(ident_buf->model, sizeof(ident_buf->model)); 855198708Smav ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model)); 856198708Smav ata_btrim(ident_buf->revision, sizeof(ident_buf->revision)); 857198708Smav ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision)); 858198708Smav ata_btrim(ident_buf->serial, sizeof(ident_buf->serial)); 859198708Smav ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial)); 860203421Smav /* Device may need spin-up before IDENTIFY become valid. */ 861204354Smav if ((ident_buf->specconf == 0x37c8 || 862204354Smav ident_buf->specconf == 0x738c) && 863204354Smav ((ident_buf->config & ATA_RESP_INCOMPLETE) || 864204354Smav softc->spinup == 0)) { 865203421Smav PROBE_SET_ACTION(softc, PROBE_SPINUP); 866203421Smav xpt_release_ccb(done_ccb); 867203421Smav xpt_schedule(periph, priority); 868249466Smav goto out; 869203421Smav } 870203385Smav ident_buf = &path->device->ident_data; 871198708Smav if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) { 872198708Smav /* Check that it is the same device. */ 873203385Smav if (bcmp(softc->ident_data.model, ident_buf->model, 874203385Smav sizeof(ident_buf->model)) || 875203385Smav bcmp(softc->ident_data.revision, ident_buf->revision, 876203385Smav sizeof(ident_buf->revision)) || 877203385Smav bcmp(softc->ident_data.serial, ident_buf->serial, 878203385Smav sizeof(ident_buf->serial))) { 879198708Smav /* Device changed. */ 880198708Smav xpt_async(AC_LOST_DEVICE, path, NULL); 881207282Smav } else { 882203385Smav bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 883207282Smav changed = 0; 884207282Smav } 885207282Smav } 886207282Smav if (changed) { 887203385Smav bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 888195534Sscottl /* Clean up from previous instance of this device */ 889195534Sscottl if (path->device->serial_num != NULL) { 890195534Sscottl free(path->device->serial_num, M_CAMXPT); 891195534Sscottl path->device->serial_num = NULL; 892195534Sscottl path->device->serial_num_len = 0; 893195534Sscottl } 894235897Smav if (path->device->device_id != NULL) { 895235897Smav free(path->device->device_id, M_CAMXPT); 896235897Smav path->device->device_id = NULL; 897235897Smav path->device->device_id_len = 0; 898235897Smav } 899195534Sscottl path->device->serial_num = 900195534Sscottl (u_int8_t *)malloc((sizeof(ident_buf->serial) + 1), 901198708Smav M_CAMXPT, M_NOWAIT); 902195534Sscottl if (path->device->serial_num != NULL) { 903195534Sscottl bcopy(ident_buf->serial, 904195534Sscottl path->device->serial_num, 905195534Sscottl sizeof(ident_buf->serial)); 906195534Sscottl path->device->serial_num[sizeof(ident_buf->serial)] 907195534Sscottl = '\0'; 908195534Sscottl path->device->serial_num_len = 909195534Sscottl strlen(path->device->serial_num); 910195534Sscottl } 911235897Smav if (ident_buf->enabled.extension & 912235897Smav ATA_SUPPORT_64BITWWN) { 913235897Smav path->device->device_id = 914235897Smav malloc(16, M_CAMXPT, M_NOWAIT); 915235897Smav if (path->device->device_id != NULL) { 916235897Smav path->device->device_id_len = 16; 917235897Smav bcopy(&fake_device_id_hdr, 918235897Smav path->device->device_id, 8); 919250301Smav bcopy(ident_buf->wwn, 920250301Smav path->device->device_id + 8, 8); 921250301Smav ata_bswap(path->device->device_id + 8, 8); 922235897Smav } 923235897Smav } 924195534Sscottl 925198331Smav path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 926236393Smav xpt_async(AC_GETDEV_CHANGED, path, NULL); 927195534Sscottl } 928199178Smav if (ident_buf->satacapabilities & ATA_SUPPORT_NCQ) { 929236234Smav path->device->mintags = 2; 930236234Smav path->device->maxtags = 931199178Smav ATA_QUEUE_LEN(ident_buf->queue) + 1; 932199178Smav } 933199178Smav ata_find_quirk(path->device); 934199263Smav if (path->device->mintags != 0 && 935199263Smav path->bus->sim->max_tagged_dev_openings != 0) { 936207222Smav /* Check if the SIM does not want queued commands. */ 937207222Smav bzero(&cpi, sizeof(cpi)); 938207222Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 939207222Smav cpi.ccb_h.func_code = XPT_PATH_INQ; 940207222Smav xpt_action((union ccb *)&cpi); 941207222Smav if (cpi.ccb_h.status == CAM_REQ_CMP && 942207222Smav (cpi.hba_inquiry & PI_TAG_ABLE)) { 943207222Smav /* Report SIM which tags are allowed. */ 944207222Smav bzero(&cts, sizeof(cts)); 945207222Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 946207222Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 947207222Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 948207222Smav cts.xport_specific.sata.tags = path->device->maxtags; 949207222Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_TAGS; 950207222Smav xpt_action((union ccb *)&cts); 951207222Smav } 952199178Smav } 953236666Smav ata_device_transport(path); 954236437Smav if (changed) 955236437Smav proberequestdefaultnegotiation(periph); 956198708Smav PROBE_SET_ACTION(softc, PROBE_SETMODE); 957195534Sscottl xpt_release_ccb(done_ccb); 958198708Smav xpt_schedule(periph, priority); 959249466Smav goto out; 960195534Sscottl } 961203421Smav case PROBE_SPINUP: 962203421Smav if (bootverbose) 963203421Smav xpt_print(path, "Spin-up done\n"); 964203421Smav softc->spinup = 1; 965203421Smav PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 966203421Smav xpt_release_ccb(done_ccb); 967203421Smav xpt_schedule(periph, priority); 968249466Smav goto out; 969195534Sscottl case PROBE_SETMODE: 970207499Smav /* Set supported bits. */ 971207499Smav bzero(&cts, sizeof(cts)); 972207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 973207499Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 974207499Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 975207499Smav xpt_action((union ccb *)&cts); 976249199Smarius if (path->device->transport == XPORT_SATA && 977249199Smarius cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 978207499Smav caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H; 979249199Smarius else if (path->device->transport == XPORT_ATA && 980249199Smarius cts.xport_specific.ata.valid & CTS_ATA_VALID_CAPS) 981249199Smarius caps = cts.xport_specific.ata.caps & CTS_ATA_CAPS_H; 982207499Smav else 983207499Smav caps = 0; 984249199Smarius if (path->device->transport == XPORT_SATA && 985249199Smarius ident_buf->satacapabilities != 0xffff) { 986207499Smav if (ident_buf->satacapabilities & ATA_SUPPORT_IFPWRMNGTRCV) 987207499Smav caps |= CTS_SATA_CAPS_D_PMREQ; 988207499Smav if (ident_buf->satacapabilities & ATA_SUPPORT_HAPST) 989207499Smav caps |= CTS_SATA_CAPS_D_APST; 990207499Smav } 991207499Smav /* Mask unwanted bits. */ 992207499Smav bzero(&cts, sizeof(cts)); 993207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 994207499Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 995207499Smav cts.type = CTS_TYPE_USER_SETTINGS; 996207499Smav xpt_action((union ccb *)&cts); 997249199Smarius if (path->device->transport == XPORT_SATA && 998249199Smarius cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 999207499Smav caps &= cts.xport_specific.sata.caps; 1000249199Smarius else if (path->device->transport == XPORT_ATA && 1001249199Smarius cts.xport_specific.ata.valid & CTS_ATA_VALID_CAPS) 1002249199Smarius caps &= cts.xport_specific.ata.caps; 1003215454Smav else 1004215454Smav caps = 0; 1005249199Smarius /* 1006249199Smarius * Remember what transport thinks about 48-bit DMA. If 1007249199Smarius * capability information is not provided or transport is 1008249199Smarius * SATA, we take support for granted. 1009249199Smarius */ 1010249199Smarius if (!(path->device->inq_flags & SID_DMA) || 1011249199Smarius (path->device->transport == XPORT_ATA && 1012249199Smarius (cts.xport_specific.ata.valid & CTS_ATA_VALID_CAPS) && 1013249199Smarius !(caps & CTS_ATA_CAPS_H_DMA48))) 1014249199Smarius path->device->inq_flags &= ~SID_DMA48; 1015249199Smarius else 1016249199Smarius path->device->inq_flags |= SID_DMA48; 1017207499Smav /* Store result to SIM. */ 1018207499Smav bzero(&cts, sizeof(cts)); 1019207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1020207499Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1021207499Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 1022249199Smarius if (path->device->transport == XPORT_SATA) { 1023249199Smarius cts.xport_specific.sata.caps = caps; 1024249199Smarius cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS; 1025249199Smarius } else { 1026249199Smarius cts.xport_specific.ata.caps = caps; 1027249199Smarius cts.xport_specific.ata.valid = CTS_ATA_VALID_CAPS; 1028249199Smarius } 1029207499Smav xpt_action((union ccb *)&cts); 1030207499Smav softc->caps = caps; 1031249199Smarius if (path->device->transport != XPORT_SATA) 1032249199Smarius goto notsata; 1033217874Smav if ((ident_buf->satasupport & ATA_SUPPORT_IFPWRMNGT) && 1034217874Smav (!(softc->caps & CTS_SATA_CAPS_H_PMREQ)) != 1035217874Smav (!(ident_buf->sataenabled & ATA_SUPPORT_IFPWRMNGT))) { 1036207499Smav PROBE_SET_ACTION(softc, PROBE_SETPM); 1037207499Smav xpt_release_ccb(done_ccb); 1038207499Smav xpt_schedule(periph, priority); 1039249466Smav goto out; 1040207499Smav } 1041207499Smav /* FALLTHROUGH */ 1042207499Smav case PROBE_SETPM: 1043207499Smav if (ident_buf->satacapabilities != 0xffff && 1044217874Smav (ident_buf->satacapabilities & ATA_SUPPORT_DAPST) && 1045217874Smav (!(softc->caps & CTS_SATA_CAPS_H_APST)) != 1046217874Smav (!(ident_buf->sataenabled & ATA_ENABLED_DAPST))) { 1047207499Smav PROBE_SET_ACTION(softc, PROBE_SETAPST); 1048207499Smav xpt_release_ccb(done_ccb); 1049207499Smav xpt_schedule(periph, priority); 1050249466Smav goto out; 1051207499Smav } 1052207499Smav /* FALLTHROUGH */ 1053207499Smav case PROBE_SETAPST: 1054217874Smav if ((ident_buf->satasupport & ATA_SUPPORT_AUTOACTIVATE) && 1055217874Smav (!(softc->caps & CTS_SATA_CAPS_H_DMAAA)) != 1056217874Smav (!(ident_buf->sataenabled & ATA_SUPPORT_AUTOACTIVATE))) { 1057207499Smav PROBE_SET_ACTION(softc, PROBE_SETDMAAA); 1058207499Smav xpt_release_ccb(done_ccb); 1059207499Smav xpt_schedule(periph, priority); 1060249466Smav goto out; 1061207499Smav } 1062207499Smav /* FALLTHROUGH */ 1063207499Smav case PROBE_SETDMAAA: 1064270327Simp if (path->device->protocol != PROTO_ATA && 1065270327Simp (ident_buf->satasupport & ATA_SUPPORT_ASYNCNOTIF) && 1066220602Smav (!(softc->caps & CTS_SATA_CAPS_H_AN)) != 1067220602Smav (!(ident_buf->sataenabled & ATA_SUPPORT_ASYNCNOTIF))) { 1068220602Smav PROBE_SET_ACTION(softc, PROBE_SETAN); 1069220602Smav xpt_release_ccb(done_ccb); 1070220602Smav xpt_schedule(periph, priority); 1071249466Smav goto out; 1072220602Smav } 1073220602Smav /* FALLTHROUGH */ 1074220602Smav case PROBE_SETAN: 1075207499Smavnotsata: 1076198708Smav if (path->device->protocol == PROTO_ATA) { 1077198708Smav PROBE_SET_ACTION(softc, PROBE_SET_MULTI); 1078198708Smav } else { 1079198708Smav PROBE_SET_ACTION(softc, PROBE_INQUIRY); 1080195534Sscottl } 1081198708Smav xpt_release_ccb(done_ccb); 1082198708Smav xpt_schedule(periph, priority); 1083249466Smav goto out; 1084198708Smav case PROBE_SET_MULTI: 1085198708Smav if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 1086198708Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1087198748Smav xpt_acquire_device(path->device); 1088198708Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1089198708Smav xpt_action(done_ccb); 1090249466Smav xpt_async(AC_FOUND_DEVICE, path, done_ccb); 1091198708Smav } 1092236613Smav PROBE_SET_ACTION(softc, PROBE_DONE); 1093198708Smav break; 1094195534Sscottl case PROBE_INQUIRY: 1095195534Sscottl case PROBE_FULL_INQUIRY: 1096195534Sscottl { 1097198708Smav u_int8_t periph_qual, len; 1098195534Sscottl 1099198708Smav path->device->flags |= CAM_DEV_INQUIRY_DATA_VALID; 1100195534Sscottl 1101198708Smav periph_qual = SID_QUAL(inq_buf); 1102195534Sscottl 1103287289Smav if (periph_qual != SID_QUAL_LU_CONNECTED && 1104287289Smav periph_qual != SID_QUAL_LU_OFFLINE) 1105198708Smav break; 1106195534Sscottl 1107198708Smav /* 1108198708Smav * We conservatively request only 1109198708Smav * SHORT_INQUIRY_LEN bytes of inquiry 1110198708Smav * information during our first try 1111198708Smav * at sending an INQUIRY. If the device 1112198708Smav * has more information to give, 1113198708Smav * perform a second request specifying 1114198708Smav * the amount of information the device 1115198708Smav * is willing to give. 1116198708Smav */ 1117198708Smav len = inq_buf->additional_length 1118198708Smav + offsetof(struct scsi_inquiry_data, additional_length) + 1; 1119198708Smav if (softc->action == PROBE_INQUIRY 1120198708Smav && len > SHORT_INQUIRY_LENGTH) { 1121198708Smav PROBE_SET_ACTION(softc, PROBE_FULL_INQUIRY); 1122198708Smav xpt_release_ccb(done_ccb); 1123198708Smav xpt_schedule(periph, priority); 1124249466Smav goto out; 1125195534Sscottl } 1126198708Smav 1127198708Smav ata_device_transport(path); 1128198708Smav if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 1129198708Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1130198748Smav xpt_acquire_device(path->device); 1131198708Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1132198708Smav xpt_action(done_ccb); 1133249466Smav xpt_async(AC_FOUND_DEVICE, path, done_ccb); 1134198708Smav } 1135236613Smav PROBE_SET_ACTION(softc, PROBE_DONE); 1136198708Smav break; 1137195534Sscottl } 1138195534Sscottl case PROBE_PM_PID: 1139198708Smav if ((path->device->flags & CAM_DEV_IDENTIFY_DATA_VALID) == 0) 1140198708Smav bzero(ident_buf, sizeof(*ident_buf)); 1141198708Smav softc->pm_pid = (done_ccb->ataio.res.lba_high << 24) + 1142198708Smav (done_ccb->ataio.res.lba_mid << 16) + 1143198708Smav (done_ccb->ataio.res.lba_low << 8) + 1144198708Smav done_ccb->ataio.res.sector_count; 1145198708Smav ((uint32_t *)ident_buf)[0] = softc->pm_pid; 1146198708Smav snprintf(ident_buf->model, sizeof(ident_buf->model), 1147198708Smav "Port Multiplier %08x", softc->pm_pid); 1148198708Smav PROBE_SET_ACTION(softc, PROBE_PM_PRV); 1149198708Smav xpt_release_ccb(done_ccb); 1150198708Smav xpt_schedule(periph, priority); 1151249466Smav goto out; 1152195534Sscottl case PROBE_PM_PRV: 1153198708Smav softc->pm_prv = (done_ccb->ataio.res.lba_high << 24) + 1154198708Smav (done_ccb->ataio.res.lba_mid << 16) + 1155198708Smav (done_ccb->ataio.res.lba_low << 8) + 1156198708Smav done_ccb->ataio.res.sector_count; 1157198708Smav ((uint32_t *)ident_buf)[1] = softc->pm_prv; 1158198708Smav snprintf(ident_buf->revision, sizeof(ident_buf->revision), 1159198708Smav "%04x", softc->pm_prv); 1160198708Smav path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 1161236666Smav ata_device_transport(path); 1162236666Smav if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) 1163236666Smav proberequestdefaultnegotiation(periph); 1164207499Smav /* Set supported bits. */ 1165207499Smav bzero(&cts, sizeof(cts)); 1166207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1167207499Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1168207499Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 1169207499Smav xpt_action((union ccb *)&cts); 1170207499Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1171207499Smav caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H; 1172207499Smav else 1173207499Smav caps = 0; 1174207499Smav /* All PMPs must support PM requests. */ 1175207499Smav caps |= CTS_SATA_CAPS_D_PMREQ; 1176207499Smav /* Mask unwanted bits. */ 1177207499Smav bzero(&cts, sizeof(cts)); 1178207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1179207499Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1180207499Smav cts.type = CTS_TYPE_USER_SETTINGS; 1181207499Smav xpt_action((union ccb *)&cts); 1182207499Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1183207499Smav caps &= cts.xport_specific.sata.caps; 1184215454Smav else 1185215454Smav caps = 0; 1186249199Smarius /* Remember what transport thinks about AEN. */ 1187270327Simp if ((caps & CTS_SATA_CAPS_H_AN) && path->device->protocol != PROTO_ATA) 1188249199Smarius path->device->inq_flags |= SID_AEN; 1189249199Smarius else 1190249199Smarius path->device->inq_flags &= ~SID_AEN; 1191207499Smav /* Store result to SIM. */ 1192207499Smav bzero(&cts, sizeof(cts)); 1193207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1194207499Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1195207499Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 1196207499Smav cts.xport_specific.sata.caps = caps; 1197207499Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS; 1198207499Smav xpt_action((union ccb *)&cts); 1199207499Smav softc->caps = caps; 1200238886Smav xpt_async(AC_GETDEV_CHANGED, path, NULL); 1201198708Smav if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 1202198708Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1203198748Smav xpt_acquire_device(path->device); 1204198708Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1205198708Smav xpt_action(done_ccb); 1206249466Smav xpt_async(AC_FOUND_DEVICE, path, done_ccb); 1207198708Smav } else { 1208198708Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1209198708Smav xpt_action(done_ccb); 1210249466Smav xpt_async(AC_SCSI_AEN, path, done_ccb); 1211195534Sscottl } 1212236613Smav PROBE_SET_ACTION(softc, PROBE_DONE); 1213198708Smav break; 1214235897Smav case PROBE_IDENTIFY_SES: 1215235897Smav case PROBE_IDENTIFY_SAFTE: 1216235897Smav if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) { 1217235897Smav /* Check that it is the same device. */ 1218235897Smav if (bcmp(&softc->ident_data, ident_buf, 53)) { 1219235897Smav /* Device changed. */ 1220235897Smav xpt_async(AC_LOST_DEVICE, path, NULL); 1221235897Smav } else { 1222235897Smav bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 1223235897Smav changed = 0; 1224235897Smav } 1225235897Smav } 1226235897Smav if (changed) { 1227235897Smav bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 1228235897Smav /* Clean up from previous instance of this device */ 1229235897Smav if (path->device->device_id != NULL) { 1230235897Smav free(path->device->device_id, M_CAMXPT); 1231235897Smav path->device->device_id = NULL; 1232235897Smav path->device->device_id_len = 0; 1233235897Smav } 1234235897Smav path->device->device_id = 1235235897Smav malloc(16, M_CAMXPT, M_NOWAIT); 1236235897Smav if (path->device->device_id != NULL) { 1237235897Smav path->device->device_id_len = 16; 1238235897Smav bcopy(&fake_device_id_hdr, 1239235897Smav path->device->device_id, 8); 1240235897Smav bcopy(((uint8_t*)ident_buf) + 2, 1241235897Smav path->device->device_id + 8, 8); 1242235897Smav } 1243235897Smav 1244235897Smav path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 1245235897Smav } 1246236666Smav ata_device_transport(path); 1247236666Smav if (changed) 1248236666Smav proberequestdefaultnegotiation(periph); 1249235897Smav 1250235897Smav if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 1251235897Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1252235897Smav xpt_acquire_device(path->device); 1253235897Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1254235897Smav xpt_action(done_ccb); 1255249466Smav xpt_async(AC_FOUND_DEVICE, path, done_ccb); 1256235897Smav } 1257236613Smav PROBE_SET_ACTION(softc, PROBE_DONE); 1258235897Smav break; 1259195534Sscottl default: 1260236613Smav panic("probedone: invalid action state 0x%x\n", softc->action); 1261195534Sscottl } 1262198708Smavdone: 1263203108Smav if (softc->restart) { 1264203108Smav softc->restart = 0; 1265203108Smav xpt_release_ccb(done_ccb); 1266195534Sscottl probeschedule(periph); 1267249466Smav goto out; 1268195534Sscottl } 1269203108Smav xpt_release_ccb(done_ccb); 1270236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe completed\n")); 1271203108Smav while ((done_ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs))) { 1272203108Smav TAILQ_REMOVE(&softc->request_ccbs, 1273203108Smav &done_ccb->ccb_h, periph_links.tqe); 1274203108Smav done_ccb->ccb_h.status = found ? CAM_REQ_CMP : CAM_REQ_CMP_ERR; 1275203108Smav xpt_done(done_ccb); 1276203108Smav } 1277249466Smav /* Drop freeze taken due to CAM_DEV_QFREEZE flag set. */ 1278249466Smav cam_release_devq(path, 0, 0, 0, FALSE); 1279236228Smav cam_periph_invalidate(periph); 1280203108Smav cam_periph_release_locked(periph); 1281195534Sscottl} 1282195534Sscottl 1283195534Sscottlstatic void 1284195534Sscottlprobecleanup(struct cam_periph *periph) 1285195534Sscottl{ 1286195534Sscottl free(periph->softc, M_CAMXPT); 1287195534Sscottl} 1288195534Sscottl 1289195534Sscottlstatic void 1290199178Smavata_find_quirk(struct cam_ed *device) 1291195534Sscottl{ 1292199178Smav struct ata_quirk_entry *quirk; 1293195534Sscottl caddr_t match; 1294195534Sscottl 1295199178Smav match = cam_quirkmatch((caddr_t)&device->ident_data, 1296199178Smav (caddr_t)ata_quirk_table, 1297298411Spfg nitems(ata_quirk_table), 1298199178Smav sizeof(*ata_quirk_table), ata_identify_match); 1299195534Sscottl 1300195534Sscottl if (match == NULL) 1301195534Sscottl panic("xpt_find_quirk: device didn't match wildcard entry!!"); 1302195534Sscottl 1303199178Smav quirk = (struct ata_quirk_entry *)match; 1304195534Sscottl device->quirk = quirk; 1305236234Smav if (quirk->quirks & CAM_QUIRK_MAXTAGS) { 1306236234Smav device->mintags = quirk->mintags; 1307236234Smav device->maxtags = quirk->maxtags; 1308236234Smav } 1309195534Sscottl} 1310195534Sscottl 1311195534Sscottltypedef struct { 1312195534Sscottl union ccb *request_ccb; 1313195534Sscottl struct ccb_pathinq *cpi; 1314195534Sscottl int counter; 1315195534Sscottl} ata_scan_bus_info; 1316195534Sscottl 1317195534Sscottl/* 1318195534Sscottl * To start a scan, request_ccb is an XPT_SCAN_BUS ccb. 1319195534Sscottl * As the scan progresses, xpt_scan_bus is used as the 1320195534Sscottl * callback on completion function. 1321195534Sscottl */ 1322195534Sscottlstatic void 1323195534Sscottlata_scan_bus(struct cam_periph *periph, union ccb *request_ccb) 1324195534Sscottl{ 1325195534Sscottl struct cam_path *path; 1326195534Sscottl ata_scan_bus_info *scan_info; 1327203108Smav union ccb *work_ccb, *reset_ccb; 1328256843Smav struct mtx *mtx; 1329195534Sscottl cam_status status; 1330195534Sscottl 1331195534Sscottl CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE, 1332195534Sscottl ("xpt_scan_bus\n")); 1333195534Sscottl switch (request_ccb->ccb_h.func_code) { 1334195534Sscottl case XPT_SCAN_BUS: 1335208582Smjacob case XPT_SCAN_TGT: 1336195534Sscottl /* Find out the characteristics of the bus */ 1337195534Sscottl work_ccb = xpt_alloc_ccb_nowait(); 1338195534Sscottl if (work_ccb == NULL) { 1339195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1340195534Sscottl xpt_done(request_ccb); 1341195534Sscottl return; 1342195534Sscottl } 1343195534Sscottl xpt_setup_ccb(&work_ccb->ccb_h, request_ccb->ccb_h.path, 1344195534Sscottl request_ccb->ccb_h.pinfo.priority); 1345195534Sscottl work_ccb->ccb_h.func_code = XPT_PATH_INQ; 1346195534Sscottl xpt_action(work_ccb); 1347195534Sscottl if (work_ccb->ccb_h.status != CAM_REQ_CMP) { 1348195534Sscottl request_ccb->ccb_h.status = work_ccb->ccb_h.status; 1349195534Sscottl xpt_free_ccb(work_ccb); 1350195534Sscottl xpt_done(request_ccb); 1351195534Sscottl return; 1352195534Sscottl } 1353195534Sscottl 1354203108Smav /* We may need to reset bus first, if we haven't done it yet. */ 1355203108Smav if ((work_ccb->cpi.hba_inquiry & 1356203108Smav (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE)) && 1357203108Smav !(work_ccb->cpi.hba_misc & PIM_NOBUSRESET) && 1358203108Smav !timevalisset(&request_ccb->ccb_h.path->bus->last_reset)) { 1359203108Smav reset_ccb = xpt_alloc_ccb_nowait(); 1360208823Smav if (reset_ccb == NULL) { 1361208823Smav request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1362208823Smav xpt_free_ccb(work_ccb); 1363208823Smav xpt_done(request_ccb); 1364208823Smav return; 1365208823Smav } 1366203108Smav xpt_setup_ccb(&reset_ccb->ccb_h, request_ccb->ccb_h.path, 1367203108Smav CAM_PRIORITY_NONE); 1368203108Smav reset_ccb->ccb_h.func_code = XPT_RESET_BUS; 1369203108Smav xpt_action(reset_ccb); 1370203108Smav if (reset_ccb->ccb_h.status != CAM_REQ_CMP) { 1371203108Smav request_ccb->ccb_h.status = reset_ccb->ccb_h.status; 1372203108Smav xpt_free_ccb(reset_ccb); 1373203108Smav xpt_free_ccb(work_ccb); 1374203108Smav xpt_done(request_ccb); 1375203108Smav return; 1376203108Smav } 1377203108Smav xpt_free_ccb(reset_ccb); 1378203108Smav } 1379203108Smav 1380195534Sscottl /* Save some state for use while we probe for devices */ 1381195534Sscottl scan_info = (ata_scan_bus_info *) 1382195534Sscottl malloc(sizeof(ata_scan_bus_info), M_CAMXPT, M_NOWAIT); 1383195534Sscottl if (scan_info == NULL) { 1384195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1385208823Smav xpt_free_ccb(work_ccb); 1386195534Sscottl xpt_done(request_ccb); 1387195534Sscottl return; 1388195534Sscottl } 1389195534Sscottl scan_info->request_ccb = request_ccb; 1390195534Sscottl scan_info->cpi = &work_ccb->cpi; 1391195534Sscottl /* If PM supported, probe it first. */ 1392195534Sscottl if (scan_info->cpi->hba_inquiry & PI_SATAPM) 1393201990Smav scan_info->counter = scan_info->cpi->max_target; 1394201990Smav else 1395201990Smav scan_info->counter = 0; 1396195534Sscottl 1397195534Sscottl work_ccb = xpt_alloc_ccb_nowait(); 1398195534Sscottl if (work_ccb == NULL) { 1399195534Sscottl free(scan_info, M_CAMXPT); 1400195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1401195534Sscottl xpt_done(request_ccb); 1402195534Sscottl break; 1403195534Sscottl } 1404256843Smav mtx = xpt_path_mtx(scan_info->request_ccb->ccb_h.path); 1405195534Sscottl goto scan_next; 1406195534Sscottl case XPT_SCAN_LUN: 1407195534Sscottl work_ccb = request_ccb; 1408195534Sscottl /* Reuse the same CCB to query if a device was really found */ 1409195534Sscottl scan_info = (ata_scan_bus_info *)work_ccb->ccb_h.ppriv_ptr0; 1410256843Smav mtx = xpt_path_mtx(scan_info->request_ccb->ccb_h.path); 1411256843Smav mtx_lock(mtx); 1412198389Smav /* If there is PMP... */ 1413201990Smav if ((scan_info->cpi->hba_inquiry & PI_SATAPM) && 1414201990Smav (scan_info->counter == scan_info->cpi->max_target)) { 1415203108Smav if (work_ccb->ccb_h.status == CAM_REQ_CMP) { 1416207428Smav /* everything else will be probed by it */ 1417207428Smav /* Free the current request path- we're done with it. */ 1418207428Smav xpt_free_path(work_ccb->ccb_h.path); 1419201990Smav goto done; 1420195534Sscottl } else { 1421195534Sscottl struct ccb_trans_settings cts; 1422195534Sscottl 1423195534Sscottl /* Report SIM that PM is absent. */ 1424195534Sscottl bzero(&cts, sizeof(cts)); 1425195534Sscottl xpt_setup_ccb(&cts.ccb_h, 1426207428Smav work_ccb->ccb_h.path, CAM_PRIORITY_NONE); 1427195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1428195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 1429195665Smav cts.xport_specific.sata.pm_present = 0; 1430195534Sscottl cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; 1431195534Sscottl xpt_action((union ccb *)&cts); 1432195534Sscottl } 1433195534Sscottl } 1434207428Smav /* Free the current request path- we're done with it. */ 1435207428Smav xpt_free_path(work_ccb->ccb_h.path); 1436201990Smav if (scan_info->counter == 1437201990Smav ((scan_info->cpi->hba_inquiry & PI_SATAPM) ? 1438201990Smav 0 : scan_info->cpi->max_target)) { 1439201990Smavdone: 1440256843Smav mtx_unlock(mtx); 1441195534Sscottl xpt_free_ccb(work_ccb); 1442195534Sscottl xpt_free_ccb((union ccb *)scan_info->cpi); 1443195534Sscottl request_ccb = scan_info->request_ccb; 1444195534Sscottl free(scan_info, M_CAMXPT); 1445195534Sscottl request_ccb->ccb_h.status = CAM_REQ_CMP; 1446195534Sscottl xpt_done(request_ccb); 1447195534Sscottl break; 1448195534Sscottl } 1449201990Smav /* Take next device. Wrap from max (PMP) to 0. */ 1450201990Smav scan_info->counter = (scan_info->counter + 1 ) % 1451201990Smav (scan_info->cpi->max_target + 1); 1452195534Sscottlscan_next: 1453249468Smav status = xpt_create_path(&path, NULL, 1454195534Sscottl scan_info->request_ccb->ccb_h.path_id, 1455195534Sscottl scan_info->counter, 0); 1456195534Sscottl if (status != CAM_REQ_CMP) { 1457256843Smav if (request_ccb->ccb_h.func_code == XPT_SCAN_LUN) 1458256843Smav mtx_unlock(mtx); 1459195534Sscottl printf("xpt_scan_bus: xpt_create_path failed" 1460195534Sscottl " with status %#x, bus scan halted\n", 1461195534Sscottl status); 1462195534Sscottl xpt_free_ccb(work_ccb); 1463195534Sscottl xpt_free_ccb((union ccb *)scan_info->cpi); 1464195534Sscottl request_ccb = scan_info->request_ccb; 1465195534Sscottl free(scan_info, M_CAMXPT); 1466195534Sscottl request_ccb->ccb_h.status = status; 1467195534Sscottl xpt_done(request_ccb); 1468195534Sscottl break; 1469195534Sscottl } 1470195534Sscottl xpt_setup_ccb(&work_ccb->ccb_h, path, 1471195534Sscottl scan_info->request_ccb->ccb_h.pinfo.priority); 1472195534Sscottl work_ccb->ccb_h.func_code = XPT_SCAN_LUN; 1473195534Sscottl work_ccb->ccb_h.cbfcnp = ata_scan_bus; 1474256843Smav work_ccb->ccb_h.flags |= CAM_UNLOCKED; 1475195534Sscottl work_ccb->ccb_h.ppriv_ptr0 = scan_info; 1476195534Sscottl work_ccb->crcn.flags = scan_info->request_ccb->crcn.flags; 1477256843Smav mtx_unlock(mtx); 1478256843Smav if (request_ccb->ccb_h.func_code == XPT_SCAN_LUN) 1479256843Smav mtx = NULL; 1480195534Sscottl xpt_action(work_ccb); 1481256843Smav if (mtx != NULL) 1482256843Smav mtx_lock(mtx); 1483195534Sscottl break; 1484195534Sscottl default: 1485195534Sscottl break; 1486195534Sscottl } 1487195534Sscottl} 1488195534Sscottl 1489195534Sscottlstatic void 1490195534Sscottlata_scan_lun(struct cam_periph *periph, struct cam_path *path, 1491195534Sscottl cam_flags flags, union ccb *request_ccb) 1492195534Sscottl{ 1493195534Sscottl struct ccb_pathinq cpi; 1494195534Sscottl cam_status status; 1495195534Sscottl struct cam_path *new_path; 1496195534Sscottl struct cam_periph *old_periph; 1497256843Smav int lock; 1498195534Sscottl 1499203108Smav CAM_DEBUG(path, CAM_DEBUG_TRACE, ("xpt_scan_lun\n")); 1500195534Sscottl 1501203108Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 1502195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 1503195534Sscottl xpt_action((union ccb *)&cpi); 1504195534Sscottl 1505195534Sscottl if (cpi.ccb_h.status != CAM_REQ_CMP) { 1506195534Sscottl if (request_ccb != NULL) { 1507195534Sscottl request_ccb->ccb_h.status = cpi.ccb_h.status; 1508195534Sscottl xpt_done(request_ccb); 1509195534Sscottl } 1510195534Sscottl return; 1511195534Sscottl } 1512195534Sscottl 1513195534Sscottl if (request_ccb == NULL) { 1514241455Smav request_ccb = xpt_alloc_ccb_nowait(); 1515195534Sscottl if (request_ccb == NULL) { 1516195534Sscottl xpt_print(path, "xpt_scan_lun: can't allocate CCB, " 1517195534Sscottl "can't continue\n"); 1518195534Sscottl return; 1519195534Sscottl } 1520249468Smav status = xpt_create_path(&new_path, NULL, 1521195534Sscottl path->bus->path_id, 1522195534Sscottl path->target->target_id, 1523195534Sscottl path->device->lun_id); 1524195534Sscottl if (status != CAM_REQ_CMP) { 1525241455Smav xpt_print(path, "xpt_scan_lun: can't create path, " 1526195534Sscottl "can't continue\n"); 1527241455Smav xpt_free_ccb(request_ccb); 1528195534Sscottl return; 1529195534Sscottl } 1530203108Smav xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_XPT); 1531195534Sscottl request_ccb->ccb_h.cbfcnp = xptscandone; 1532256843Smav request_ccb->ccb_h.flags |= CAM_UNLOCKED; 1533195534Sscottl request_ccb->ccb_h.func_code = XPT_SCAN_LUN; 1534195534Sscottl request_ccb->crcn.flags = flags; 1535195534Sscottl } 1536195534Sscottl 1537256843Smav lock = (xpt_path_owned(path) == 0); 1538256843Smav if (lock) 1539256843Smav xpt_path_lock(path); 1540195653Smav if ((old_periph = cam_periph_find(path, "aprobe")) != NULL) { 1541236228Smav if ((old_periph->flags & CAM_PERIPH_INVALID) == 0) { 1542236228Smav probe_softc *softc; 1543195534Sscottl 1544236228Smav softc = (probe_softc *)old_periph->softc; 1545236228Smav TAILQ_INSERT_TAIL(&softc->request_ccbs, 1546236228Smav &request_ccb->ccb_h, periph_links.tqe); 1547236228Smav softc->restart = 1; 1548236228Smav } else { 1549236228Smav request_ccb->ccb_h.status = CAM_REQ_CMP_ERR; 1550236228Smav xpt_done(request_ccb); 1551236228Smav } 1552195534Sscottl } else { 1553195534Sscottl status = cam_periph_alloc(proberegister, NULL, probecleanup, 1554195653Smav probestart, "aprobe", 1555195534Sscottl CAM_PERIPH_BIO, 1556195534Sscottl request_ccb->ccb_h.path, NULL, 0, 1557195534Sscottl request_ccb); 1558195534Sscottl 1559195534Sscottl if (status != CAM_REQ_CMP) { 1560195534Sscottl xpt_print(path, "xpt_scan_lun: cam_alloc_periph " 1561195534Sscottl "returned an error, can't continue probe\n"); 1562195534Sscottl request_ccb->ccb_h.status = status; 1563195534Sscottl xpt_done(request_ccb); 1564195534Sscottl } 1565195534Sscottl } 1566256843Smav if (lock) 1567256843Smav xpt_path_unlock(path); 1568195534Sscottl} 1569195534Sscottl 1570195534Sscottlstatic void 1571195534Sscottlxptscandone(struct cam_periph *periph, union ccb *done_ccb) 1572195534Sscottl{ 1573241455Smav 1574241455Smav xpt_free_path(done_ccb->ccb_h.path); 1575241455Smav xpt_free_ccb(done_ccb); 1576195534Sscottl} 1577195534Sscottl 1578195534Sscottlstatic struct cam_ed * 1579195534Sscottlata_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id) 1580195534Sscottl{ 1581199178Smav struct ata_quirk_entry *quirk; 1582195534Sscottl struct cam_ed *device; 1583195534Sscottl 1584195534Sscottl device = xpt_alloc_device(bus, target, lun_id); 1585195534Sscottl if (device == NULL) 1586195534Sscottl return (NULL); 1587195534Sscottl 1588195534Sscottl /* 1589195534Sscottl * Take the default quirk entry until we have inquiry 1590195534Sscottl * data and can determine a better quirk to use. 1591195534Sscottl */ 1592298411Spfg quirk = &ata_quirk_table[nitems(ata_quirk_table) - 1]; 1593195534Sscottl device->quirk = (void *)quirk; 1594199178Smav device->mintags = 0; 1595199178Smav device->maxtags = 0; 1596195534Sscottl bzero(&device->inq_data, sizeof(device->inq_data)); 1597195534Sscottl device->inq_flags = 0; 1598195534Sscottl device->queue_flags = 0; 1599195534Sscottl device->serial_num = NULL; 1600195534Sscottl device->serial_num_len = 0; 1601195534Sscottl return (device); 1602195534Sscottl} 1603195534Sscottl 1604195534Sscottlstatic void 1605195534Sscottlata_device_transport(struct cam_path *path) 1606195534Sscottl{ 1607195534Sscottl struct ccb_pathinq cpi; 1608198331Smav struct ccb_trans_settings cts; 1609198331Smav struct scsi_inquiry_data *inq_buf = NULL; 1610198331Smav struct ata_params *ident_buf = NULL; 1611195534Sscottl 1612195534Sscottl /* Get transport information from the SIM */ 1613203108Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 1614195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 1615195534Sscottl xpt_action((union ccb *)&cpi); 1616195534Sscottl 1617195534Sscottl path->device->transport = cpi.transport; 1618198331Smav if ((path->device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0) 1619198331Smav inq_buf = &path->device->inq_data; 1620198331Smav if ((path->device->flags & CAM_DEV_IDENTIFY_DATA_VALID) != 0) 1621198331Smav ident_buf = &path->device->ident_data; 1622198331Smav if (path->device->protocol == PROTO_ATA) { 1623198331Smav path->device->protocol_version = ident_buf ? 1624198331Smav ata_version(ident_buf->version_major) : cpi.protocol_version; 1625198331Smav } else if (path->device->protocol == PROTO_SCSI) { 1626198331Smav path->device->protocol_version = inq_buf ? 1627198331Smav SID_ANSI_REV(inq_buf) : cpi.protocol_version; 1628195534Sscottl } 1629198331Smav path->device->transport_version = ident_buf ? 1630198331Smav ata_version(ident_buf->version_major) : cpi.transport_version; 1631195534Sscottl 1632195534Sscottl /* Tell the controller what we think */ 1633203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1634195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1635195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 1636195534Sscottl cts.transport = path->device->transport; 1637195534Sscottl cts.transport_version = path->device->transport_version; 1638195534Sscottl cts.protocol = path->device->protocol; 1639195534Sscottl cts.protocol_version = path->device->protocol_version; 1640195534Sscottl cts.proto_specific.valid = 0; 1641203376Smav if (ident_buf) { 1642203376Smav if (path->device->transport == XPORT_ATA) { 1643223019Smav cts.xport_specific.ata.atapi = 1644223019Smav (ident_buf->config == ATA_PROTO_CFA) ? 0 : 1645203376Smav ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_16) ? 16 : 1646203376Smav ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) ? 12 : 0; 1647203376Smav cts.xport_specific.ata.valid = CTS_ATA_VALID_ATAPI; 1648203376Smav } else { 1649223019Smav cts.xport_specific.sata.atapi = 1650223019Smav (ident_buf->config == ATA_PROTO_CFA) ? 0 : 1651203376Smav ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_16) ? 16 : 1652203376Smav ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) ? 12 : 0; 1653203376Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_ATAPI; 1654203376Smav } 1655203376Smav } else 1656203376Smav cts.xport_specific.valid = 0; 1657195534Sscottl xpt_action((union ccb *)&cts); 1658195534Sscottl} 1659195534Sscottl 1660195534Sscottlstatic void 1661223443Swillata_dev_advinfo(union ccb *start_ccb) 1662223443Swill{ 1663223443Swill struct cam_ed *device; 1664223443Swill struct ccb_dev_advinfo *cdai; 1665223443Swill off_t amt; 1666223443Swill 1667223443Swill start_ccb->ccb_h.status = CAM_REQ_INVALID; 1668223443Swill device = start_ccb->ccb_h.path->device; 1669223443Swill cdai = &start_ccb->cdai; 1670223443Swill switch(cdai->buftype) { 1671235897Smav case CDAI_TYPE_SCSI_DEVID: 1672235897Smav if (cdai->flags & CDAI_FLAG_STORE) 1673235897Smav return; 1674235897Smav cdai->provsiz = device->device_id_len; 1675235897Smav if (device->device_id_len == 0) 1676235897Smav break; 1677235897Smav amt = device->device_id_len; 1678235897Smav if (cdai->provsiz > cdai->bufsiz) 1679235897Smav amt = cdai->bufsiz; 1680235897Smav memcpy(cdai->buf, device->device_id, amt); 1681235897Smav break; 1682223443Swill case CDAI_TYPE_SERIAL_NUM: 1683223443Swill if (cdai->flags & CDAI_FLAG_STORE) 1684235897Smav return; 1685223443Swill cdai->provsiz = device->serial_num_len; 1686223443Swill if (device->serial_num_len == 0) 1687223443Swill break; 1688223443Swill amt = device->serial_num_len; 1689223443Swill if (cdai->provsiz > cdai->bufsiz) 1690223443Swill amt = cdai->bufsiz; 1691223443Swill memcpy(cdai->buf, device->serial_num, amt); 1692223443Swill break; 1693235897Smav case CDAI_TYPE_PHYS_PATH: 1694235897Smav if (cdai->flags & CDAI_FLAG_STORE) { 1695235897Smav if (device->physpath != NULL) 1696235897Smav free(device->physpath, M_CAMXPT); 1697235897Smav device->physpath_len = cdai->bufsiz; 1698235897Smav /* Clear existing buffer if zero length */ 1699235897Smav if (cdai->bufsiz == 0) 1700235897Smav break; 1701235897Smav device->physpath = malloc(cdai->bufsiz, M_CAMXPT, M_NOWAIT); 1702235897Smav if (device->physpath == NULL) { 1703235897Smav start_ccb->ccb_h.status = CAM_REQ_ABORTED; 1704235897Smav return; 1705235897Smav } 1706235897Smav memcpy(device->physpath, cdai->buf, cdai->bufsiz); 1707235897Smav } else { 1708235897Smav cdai->provsiz = device->physpath_len; 1709235897Smav if (device->physpath_len == 0) 1710235897Smav break; 1711235897Smav amt = device->physpath_len; 1712235897Smav if (cdai->provsiz > cdai->bufsiz) 1713235897Smav amt = cdai->bufsiz; 1714235897Smav memcpy(cdai->buf, device->physpath, amt); 1715235897Smav } 1716235897Smav break; 1717223443Swill default: 1718235897Smav return; 1719223443Swill } 1720235897Smav start_ccb->ccb_h.status = CAM_REQ_CMP; 1721235897Smav 1722235897Smav if (cdai->flags & CDAI_FLAG_STORE) { 1723235897Smav xpt_async(AC_ADVINFO_CHANGED, start_ccb->ccb_h.path, 1724235897Smav (void *)(uintptr_t)cdai->buftype); 1725235897Smav } 1726223443Swill} 1727223443Swill 1728223443Swillstatic void 1729195534Sscottlata_action(union ccb *start_ccb) 1730195534Sscottl{ 1731195534Sscottl 1732195534Sscottl switch (start_ccb->ccb_h.func_code) { 1733195534Sscottl case XPT_SET_TRAN_SETTINGS: 1734195534Sscottl { 1735199178Smav ata_set_transfer_settings(&start_ccb->cts, 1736256843Smav start_ccb->ccb_h.path, 1737195534Sscottl /*async_update*/FALSE); 1738195534Sscottl break; 1739195534Sscottl } 1740195534Sscottl case XPT_SCAN_BUS: 1741208582Smjacob case XPT_SCAN_TGT: 1742195534Sscottl ata_scan_bus(start_ccb->ccb_h.path->periph, start_ccb); 1743195534Sscottl break; 1744195534Sscottl case XPT_SCAN_LUN: 1745195534Sscottl ata_scan_lun(start_ccb->ccb_h.path->periph, 1746195534Sscottl start_ccb->ccb_h.path, start_ccb->crcn.flags, 1747195534Sscottl start_ccb); 1748195534Sscottl break; 1749195534Sscottl case XPT_GET_TRAN_SETTINGS: 1750195534Sscottl { 1751236437Smav ata_get_transfer_settings(&start_ccb->cts); 1752195534Sscottl break; 1753195534Sscottl } 1754203376Smav case XPT_SCSI_IO: 1755203376Smav { 1756203376Smav struct cam_ed *device; 1757203376Smav u_int maxlen = 0; 1758203376Smav 1759203376Smav device = start_ccb->ccb_h.path->device; 1760203376Smav if (device->protocol == PROTO_SCSI && 1761203376Smav (device->flags & CAM_DEV_IDENTIFY_DATA_VALID)) { 1762203376Smav uint16_t p = 1763203376Smav device->ident_data.config & ATA_PROTO_MASK; 1764203376Smav 1765223019Smav maxlen = 1766223019Smav (device->ident_data.config == ATA_PROTO_CFA) ? 0 : 1767223019Smav (p == ATA_PROTO_ATAPI_16) ? 16 : 1768203376Smav (p == ATA_PROTO_ATAPI_12) ? 12 : 0; 1769203376Smav } 1770203376Smav if (start_ccb->csio.cdb_len > maxlen) { 1771203376Smav start_ccb->ccb_h.status = CAM_REQ_INVALID; 1772203376Smav xpt_done(start_ccb); 1773203376Smav break; 1774203376Smav } 1775223475Smav xpt_action_default(start_ccb); 1776223475Smav break; 1777203376Smav } 1778223443Swill case XPT_DEV_ADVINFO: 1779223443Swill { 1780223443Swill ata_dev_advinfo(start_ccb); 1781223443Swill break; 1782223443Swill } 1783195534Sscottl default: 1784195534Sscottl xpt_action_default(start_ccb); 1785195534Sscottl break; 1786195534Sscottl } 1787195534Sscottl} 1788195534Sscottl 1789195534Sscottlstatic void 1790236437Smavata_get_transfer_settings(struct ccb_trans_settings *cts) 1791236437Smav{ 1792236437Smav struct ccb_trans_settings_ata *ata; 1793236437Smav struct ccb_trans_settings_scsi *scsi; 1794236437Smav struct cam_ed *device; 1795236437Smav 1796236437Smav device = cts->ccb_h.path->device; 1797256843Smav xpt_action_default((union ccb *)cts); 1798236437Smav 1799236666Smav if (cts->protocol == PROTO_UNKNOWN || 1800236666Smav cts->protocol == PROTO_UNSPECIFIED) { 1801236666Smav cts->protocol = device->protocol; 1802236666Smav cts->protocol_version = device->protocol_version; 1803236666Smav } 1804236666Smav 1805236437Smav if (cts->protocol == PROTO_ATA) { 1806236437Smav ata = &cts->proto_specific.ata; 1807236437Smav if ((ata->valid & CTS_ATA_VALID_TQ) == 0) { 1808236437Smav ata->valid |= CTS_ATA_VALID_TQ; 1809236437Smav if (cts->type == CTS_TYPE_USER_SETTINGS || 1810236437Smav (device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 || 1811236437Smav (device->inq_flags & SID_CmdQue) != 0) 1812236437Smav ata->flags |= CTS_ATA_FLAGS_TAG_ENB; 1813236437Smav } 1814236437Smav } 1815236437Smav if (cts->protocol == PROTO_SCSI) { 1816236437Smav scsi = &cts->proto_specific.scsi; 1817236437Smav if ((scsi->valid & CTS_SCSI_VALID_TQ) == 0) { 1818236437Smav scsi->valid |= CTS_SCSI_VALID_TQ; 1819236437Smav if (cts->type == CTS_TYPE_USER_SETTINGS || 1820236437Smav (device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 || 1821236437Smav (device->inq_flags & SID_CmdQue) != 0) 1822236437Smav scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 1823236437Smav } 1824236437Smav } 1825236666Smav 1826236666Smav if (cts->transport == XPORT_UNKNOWN || 1827236666Smav cts->transport == XPORT_UNSPECIFIED) { 1828236666Smav cts->transport = device->transport; 1829236666Smav cts->transport_version = device->transport_version; 1830236666Smav } 1831236437Smav} 1832236437Smav 1833236437Smavstatic void 1834256843Smavata_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_path *path, 1835195534Sscottl int async_update) 1836195534Sscottl{ 1837195534Sscottl struct ccb_pathinq cpi; 1838236437Smav struct ccb_trans_settings_ata *ata; 1839195534Sscottl struct ccb_trans_settings_scsi *scsi; 1840236437Smav struct ata_params *ident_data; 1841195534Sscottl struct scsi_inquiry_data *inq_data; 1842256843Smav struct cam_ed *device; 1843195534Sscottl 1844256843Smav if (path == NULL || (device = path->device) == NULL) { 1845195534Sscottl cts->ccb_h.status = CAM_PATH_INVALID; 1846195534Sscottl xpt_done((union ccb *)cts); 1847195534Sscottl return; 1848195534Sscottl } 1849195534Sscottl 1850195534Sscottl if (cts->protocol == PROTO_UNKNOWN 1851195534Sscottl || cts->protocol == PROTO_UNSPECIFIED) { 1852195534Sscottl cts->protocol = device->protocol; 1853195534Sscottl cts->protocol_version = device->protocol_version; 1854195534Sscottl } 1855195534Sscottl 1856195534Sscottl if (cts->protocol_version == PROTO_VERSION_UNKNOWN 1857195534Sscottl || cts->protocol_version == PROTO_VERSION_UNSPECIFIED) 1858195534Sscottl cts->protocol_version = device->protocol_version; 1859195534Sscottl 1860195534Sscottl if (cts->protocol != device->protocol) { 1861256843Smav xpt_print(path, "Uninitialized Protocol %x:%x?\n", 1862195534Sscottl cts->protocol, device->protocol); 1863195534Sscottl cts->protocol = device->protocol; 1864195534Sscottl } 1865195534Sscottl 1866195534Sscottl if (cts->protocol_version > device->protocol_version) { 1867195534Sscottl if (bootverbose) { 1868256843Smav xpt_print(path, "Down reving Protocol " 1869195534Sscottl "Version from %d to %d?\n", cts->protocol_version, 1870195534Sscottl device->protocol_version); 1871195534Sscottl } 1872195534Sscottl cts->protocol_version = device->protocol_version; 1873195534Sscottl } 1874195534Sscottl 1875195534Sscottl if (cts->transport == XPORT_UNKNOWN 1876195534Sscottl || cts->transport == XPORT_UNSPECIFIED) { 1877195534Sscottl cts->transport = device->transport; 1878195534Sscottl cts->transport_version = device->transport_version; 1879195534Sscottl } 1880195534Sscottl 1881195534Sscottl if (cts->transport_version == XPORT_VERSION_UNKNOWN 1882195534Sscottl || cts->transport_version == XPORT_VERSION_UNSPECIFIED) 1883195534Sscottl cts->transport_version = device->transport_version; 1884195534Sscottl 1885195534Sscottl if (cts->transport != device->transport) { 1886256843Smav xpt_print(path, "Uninitialized Transport %x:%x?\n", 1887195534Sscottl cts->transport, device->transport); 1888195534Sscottl cts->transport = device->transport; 1889195534Sscottl } 1890195534Sscottl 1891195534Sscottl if (cts->transport_version > device->transport_version) { 1892195534Sscottl if (bootverbose) { 1893256843Smav xpt_print(path, "Down reving Transport " 1894195534Sscottl "Version from %d to %d?\n", cts->transport_version, 1895195534Sscottl device->transport_version); 1896195534Sscottl } 1897195534Sscottl cts->transport_version = device->transport_version; 1898195534Sscottl } 1899195534Sscottl 1900236437Smav ident_data = &device->ident_data; 1901195534Sscottl inq_data = &device->inq_data; 1902236437Smav if (cts->protocol == PROTO_ATA) 1903236437Smav ata = &cts->proto_specific.ata; 1904236437Smav else 1905236437Smav ata = NULL; 1906236437Smav if (cts->protocol == PROTO_SCSI) 1907236437Smav scsi = &cts->proto_specific.scsi; 1908236437Smav else 1909236437Smav scsi = NULL; 1910256843Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 1911195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 1912195534Sscottl xpt_action((union ccb *)&cpi); 1913195534Sscottl 1914236437Smav /* Sanity checking */ 1915195534Sscottl if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0 1916236437Smav || (ata && (ident_data->satacapabilities & ATA_SUPPORT_NCQ) == 0) 1917236437Smav || (scsi && (INQ_DATA_TQ_ENABLED(inq_data)) == 0) 1918195534Sscottl || (device->queue_flags & SCP_QUEUE_DQUE) != 0 1919195534Sscottl || (device->mintags == 0)) { 1920195534Sscottl /* 1921195534Sscottl * Can't tag on hardware that doesn't support tags, 1922195534Sscottl * doesn't have it enabled, or has broken tag support. 1923195534Sscottl */ 1924236437Smav if (ata) 1925236437Smav ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB; 1926236437Smav if (scsi) 1927195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 1928195534Sscottl } 1929195534Sscottl 1930236437Smav /* Start/stop tags use. */ 1931236437Smav if (cts->type == CTS_TYPE_CURRENT_SETTINGS && 1932236437Smav ((ata && (ata->valid & CTS_ATA_VALID_TQ) != 0) || 1933236437Smav (scsi && (scsi->valid & CTS_SCSI_VALID_TQ) != 0))) { 1934236437Smav int nowt, newt = 0; 1935195534Sscottl 1936236437Smav nowt = ((device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 || 1937236437Smav (device->inq_flags & SID_CmdQue) != 0); 1938236437Smav if (ata) 1939236437Smav newt = (ata->flags & CTS_ATA_FLAGS_TAG_ENB) != 0; 1940236437Smav if (scsi) 1941236437Smav newt = (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0; 1942195534Sscottl 1943236437Smav if (newt && !nowt) { 1944236437Smav /* 1945236437Smav * Delay change to use tags until after a 1946236437Smav * few commands have gone to this device so 1947236437Smav * the controller has time to perform transfer 1948236437Smav * negotiations without tagged messages getting 1949236437Smav * in the way. 1950236437Smav */ 1951236437Smav device->tag_delay_count = CAM_TAG_DELAY_COUNT; 1952236437Smav device->flags |= CAM_DEV_TAG_AFTER_COUNT; 1953236437Smav } else if (nowt && !newt) 1954256843Smav xpt_stop_tags(path); 1955236437Smav } 1956195534Sscottl 1957195534Sscottl if (async_update == FALSE) 1958256843Smav xpt_action_default((union ccb *)cts); 1959195534Sscottl} 1960195534Sscottl 1961195534Sscottl/* 1962195534Sscottl * Handle any per-device event notifications that require action by the XPT. 1963195534Sscottl */ 1964195534Sscottlstatic void 1965195534Sscottlata_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target, 1966195534Sscottl struct cam_ed *device, void *async_arg) 1967195534Sscottl{ 1968195534Sscottl cam_status status; 1969195534Sscottl struct cam_path newpath; 1970195534Sscottl 1971195534Sscottl /* 1972195534Sscottl * We only need to handle events for real devices. 1973195534Sscottl */ 1974195534Sscottl if (target->target_id == CAM_TARGET_WILDCARD 1975195534Sscottl || device->lun_id == CAM_LUN_WILDCARD) 1976195534Sscottl return; 1977195534Sscottl 1978195534Sscottl /* 1979195534Sscottl * We need our own path with wildcards expanded to 1980195534Sscottl * handle certain types of events. 1981195534Sscottl */ 1982195534Sscottl if ((async_code == AC_SENT_BDR) 1983195534Sscottl || (async_code == AC_BUS_RESET) 1984195534Sscottl || (async_code == AC_INQ_CHANGED)) 1985195534Sscottl status = xpt_compile_path(&newpath, NULL, 1986195534Sscottl bus->path_id, 1987195534Sscottl target->target_id, 1988195534Sscottl device->lun_id); 1989195534Sscottl else 1990195534Sscottl status = CAM_REQ_CMP_ERR; 1991195534Sscottl 1992195534Sscottl if (status == CAM_REQ_CMP) { 1993195534Sscottl if (async_code == AC_INQ_CHANGED) { 1994195534Sscottl /* 1995195534Sscottl * We've sent a start unit command, or 1996195534Sscottl * something similar to a device that 1997195534Sscottl * may have caused its inquiry data to 1998195534Sscottl * change. So we re-scan the device to 1999195534Sscottl * refresh the inquiry data for it. 2000195534Sscottl */ 2001195534Sscottl ata_scan_lun(newpath.periph, &newpath, 2002195534Sscottl CAM_EXPECT_INQ_CHANGE, NULL); 2003203108Smav } else { 2004203108Smav /* We need to reinitialize device after reset. */ 2005203108Smav ata_scan_lun(newpath.periph, &newpath, 2006203108Smav 0, NULL); 2007195534Sscottl } 2008195534Sscottl xpt_release_path(&newpath); 2009198748Smav } else if (async_code == AC_LOST_DEVICE && 2010198748Smav (device->flags & CAM_DEV_UNCONFIGURED) == 0) { 2011195534Sscottl device->flags |= CAM_DEV_UNCONFIGURED; 2012198748Smav xpt_release_device(device); 2013195534Sscottl } else if (async_code == AC_TRANSFER_NEG) { 2014195534Sscottl struct ccb_trans_settings *settings; 2015256843Smav struct cam_path path; 2016195534Sscottl 2017195534Sscottl settings = (struct ccb_trans_settings *)async_arg; 2018256843Smav xpt_compile_path(&path, NULL, bus->path_id, target->target_id, 2019256843Smav device->lun_id); 2020256843Smav ata_set_transfer_settings(settings, &path, 2021195534Sscottl /*async_update*/TRUE); 2022256843Smav xpt_release_path(&path); 2023195534Sscottl } 2024195534Sscottl} 2025195534Sscottl 2026204220Smavstatic void 2027204220Smavata_announce_periph(struct cam_periph *periph) 2028204220Smav{ 2029204220Smav struct ccb_pathinq cpi; 2030204220Smav struct ccb_trans_settings cts; 2031204220Smav struct cam_path *path = periph->path; 2032204220Smav u_int speed; 2033204220Smav u_int mb; 2034204220Smav 2035256843Smav cam_periph_assert(periph, MA_OWNED); 2036204220Smav 2037204220Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); 2038204220Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 2039204220Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 2040204220Smav xpt_action((union ccb*)&cts); 2041204220Smav if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 2042204220Smav return; 2043204220Smav /* Ask the SIM for its base transfer speed */ 2044204220Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL); 2045204220Smav cpi.ccb_h.func_code = XPT_PATH_INQ; 2046204220Smav xpt_action((union ccb *)&cpi); 2047204220Smav /* Report connection speed */ 2048204220Smav speed = cpi.base_transfer_speed; 2049204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_ATA) { 2050236437Smav struct ccb_trans_settings_pata *pata = 2051204220Smav &cts.xport_specific.ata; 2052204220Smav 2053236437Smav if (pata->valid & CTS_ATA_VALID_MODE) 2054236437Smav speed = ata_mode2speed(pata->mode); 2055204220Smav } 2056204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SATA) { 2057204220Smav struct ccb_trans_settings_sata *sata = 2058204220Smav &cts.xport_specific.sata; 2059204220Smav 2060204220Smav if (sata->valid & CTS_SATA_VALID_REVISION) 2061204220Smav speed = ata_revision2speed(sata->revision); 2062204220Smav } 2063204220Smav mb = speed / 1000; 2064204220Smav if (mb > 0) 2065204220Smav printf("%s%d: %d.%03dMB/s transfers", 2066204220Smav periph->periph_name, periph->unit_number, 2067204220Smav mb, speed % 1000); 2068204220Smav else 2069204220Smav printf("%s%d: %dKB/s transfers", periph->periph_name, 2070204220Smav periph->unit_number, speed); 2071204220Smav /* Report additional information about connection */ 2072204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_ATA) { 2073236437Smav struct ccb_trans_settings_pata *pata = 2074204220Smav &cts.xport_specific.ata; 2075204220Smav 2076204220Smav printf(" ("); 2077236437Smav if (pata->valid & CTS_ATA_VALID_MODE) 2078236437Smav printf("%s, ", ata_mode2string(pata->mode)); 2079236437Smav if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0) 2080236437Smav printf("ATAPI %dbytes, ", pata->atapi); 2081236437Smav if (pata->valid & CTS_ATA_VALID_BYTECOUNT) 2082236437Smav printf("PIO %dbytes", pata->bytecount); 2083204220Smav printf(")"); 2084204220Smav } 2085204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SATA) { 2086204220Smav struct ccb_trans_settings_sata *sata = 2087204220Smav &cts.xport_specific.sata; 2088204220Smav 2089204220Smav printf(" ("); 2090204220Smav if (sata->valid & CTS_SATA_VALID_REVISION) 2091204220Smav printf("SATA %d.x, ", sata->revision); 2092204220Smav else 2093204220Smav printf("SATA, "); 2094204220Smav if (sata->valid & CTS_SATA_VALID_MODE) 2095204220Smav printf("%s, ", ata_mode2string(sata->mode)); 2096204220Smav if ((sata->valid & CTS_ATA_VALID_ATAPI) && sata->atapi != 0) 2097204220Smav printf("ATAPI %dbytes, ", sata->atapi); 2098204220Smav if (sata->valid & CTS_SATA_VALID_BYTECOUNT) 2099204220Smav printf("PIO %dbytes", sata->bytecount); 2100204220Smav printf(")"); 2101204220Smav } 2102204220Smav printf("\n"); 2103204220Smav} 2104