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 351754 2019-09-03 16:24:44Z 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/sbuf.h> 41195534Sscottl 42307606Ssephe#include <sys/eventhandler.h> 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 68236234Smav u_int mintags; 69195534Sscottl u_int maxtags; 70195534Sscottl}; 71195534Sscottl 72195534Sscottlstatic periph_init_t probe_periph_init; 73195534Sscottl 74195534Sscottlstatic struct periph_driver probe_driver = 75195534Sscottl{ 76195653Smav probe_periph_init, "aprobe", 77198708Smav TAILQ_HEAD_INITIALIZER(probe_driver.units), /* generation */ 0, 78198708Smav CAM_PERIPH_DRV_EARLY 79195534Sscottl}; 80195534Sscottl 81195653SmavPERIPHDRIVER_DECLARE(aprobe, probe_driver); 82195534Sscottl 83195534Sscottltypedef enum { 84195534Sscottl PROBE_RESET, 85195534Sscottl PROBE_IDENTIFY, 86203421Smav PROBE_SPINUP, 87195534Sscottl PROBE_SETMODE, 88207499Smav PROBE_SETPM, 89207499Smav PROBE_SETAPST, 90207499Smav PROBE_SETDMAAA, 91220602Smav PROBE_SETAN, 92198708Smav PROBE_SET_MULTI, 93195534Sscottl PROBE_INQUIRY, 94195534Sscottl PROBE_FULL_INQUIRY, 95195534Sscottl PROBE_PM_PID, 96195534Sscottl PROBE_PM_PRV, 97235897Smav PROBE_IDENTIFY_SES, 98235897Smav PROBE_IDENTIFY_SAFTE, 99236613Smav PROBE_DONE, 100195534Sscottl PROBE_INVALID 101195534Sscottl} probe_action; 102195534Sscottl 103195534Sscottlstatic char *probe_action_text[] = { 104195534Sscottl "PROBE_RESET", 105195534Sscottl "PROBE_IDENTIFY", 106203421Smav "PROBE_SPINUP", 107195534Sscottl "PROBE_SETMODE", 108207499Smav "PROBE_SETPM", 109207499Smav "PROBE_SETAPST", 110207499Smav "PROBE_SETDMAAA", 111220602Smav "PROBE_SETAN", 112198708Smav "PROBE_SET_MULTI", 113195534Sscottl "PROBE_INQUIRY", 114195534Sscottl "PROBE_FULL_INQUIRY", 115195534Sscottl "PROBE_PM_PID", 116195534Sscottl "PROBE_PM_PRV", 117235897Smav "PROBE_IDENTIFY_SES", 118235897Smav "PROBE_IDENTIFY_SAFTE", 119236613Smav "PROBE_DONE", 120195534Sscottl "PROBE_INVALID" 121195534Sscottl}; 122195534Sscottl 123195534Sscottl#define PROBE_SET_ACTION(softc, newaction) \ 124195534Sscottldo { \ 125195534Sscottl char **text; \ 126195534Sscottl text = probe_action_text; \ 127236613Smav CAM_DEBUG((softc)->periph->path, CAM_DEBUG_PROBE, \ 128195534Sscottl ("Probe %s to %s\n", text[(softc)->action], \ 129195534Sscottl text[(newaction)])); \ 130195534Sscottl (softc)->action = (newaction); \ 131195534Sscottl} while(0) 132195534Sscottl 133195534Sscottltypedef enum { 134195534Sscottl PROBE_NO_ANNOUNCE = 0x04 135195534Sscottl} probe_flags; 136195534Sscottl 137195534Sscottltypedef struct { 138195534Sscottl TAILQ_HEAD(, ccb_hdr) request_ccbs; 139203385Smav struct ata_params ident_data; 140195534Sscottl probe_action action; 141195534Sscottl probe_flags flags; 142195534Sscottl uint32_t pm_pid; 143195534Sscottl uint32_t pm_prv; 144203108Smav int restart; 145203421Smav int spinup; 146209744Smav int faults; 147207499Smav u_int caps; 148195534Sscottl struct cam_periph *periph; 149195534Sscottl} probe_softc; 150195534Sscottl 151199178Smavstatic struct ata_quirk_entry ata_quirk_table[] = 152195534Sscottl{ 153195534Sscottl { 154195534Sscottl /* Default tagged queuing parameters for all devices */ 155195534Sscottl { 156195534Sscottl T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED, 157195534Sscottl /*vendor*/"*", /*product*/"*", /*revision*/"*" 158195534Sscottl }, 159236234Smav /*quirks*/0, /*mintags*/0, /*maxtags*/0 160195534Sscottl }, 161195534Sscottl}; 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); 167236437Smavstatic void proberequestdefaultnegotiation(struct cam_periph *periph); 168195534Sscottlstatic void probedone(struct cam_periph *periph, union ccb *done_ccb); 169195534Sscottlstatic void probecleanup(struct cam_periph *periph); 170199178Smavstatic void ata_find_quirk(struct cam_ed *device); 171195534Sscottlstatic void ata_scan_bus(struct cam_periph *periph, union ccb *ccb); 172195534Sscottlstatic void ata_scan_lun(struct cam_periph *periph, 173195534Sscottl struct cam_path *path, cam_flags flags, 174195534Sscottl union ccb *ccb); 175195534Sscottlstatic void xptscandone(struct cam_periph *periph, union ccb *done_ccb); 176195534Sscottlstatic struct cam_ed * 177195534Sscottl ata_alloc_device(struct cam_eb *bus, struct cam_et *target, 178195534Sscottl lun_id_t lun_id); 179195534Sscottlstatic void ata_device_transport(struct cam_path *path); 180236437Smavstatic void ata_get_transfer_settings(struct ccb_trans_settings *cts); 181199178Smavstatic void ata_set_transfer_settings(struct ccb_trans_settings *cts, 182256843Smav struct cam_path *path, 183195534Sscottl int async_update); 184195534Sscottlstatic void ata_dev_async(u_int32_t async_code, 185195534Sscottl struct cam_eb *bus, 186195534Sscottl struct cam_et *target, 187195534Sscottl struct cam_ed *device, 188195534Sscottl void *async_arg); 189195534Sscottlstatic void ata_action(union ccb *start_ccb); 190204220Smavstatic void ata_announce_periph(struct cam_periph *periph); 191328820Smavstatic void ata_proto_announce(struct cam_ed *device); 192328820Smavstatic void ata_proto_denounce(struct cam_ed *device); 193328820Smavstatic void ata_proto_debug_out(union ccb *ccb); 194328820Smavstatic void semb_proto_announce(struct cam_ed *device); 195328820Smavstatic void semb_proto_denounce(struct cam_ed *device); 196195534Sscottl 197230912Smavstatic int ata_dma = 1; 198230912Smavstatic int atapi_dma = 1; 199230912Smav 200230912SmavTUNABLE_INT("hw.ata.ata_dma", &ata_dma); 201230912SmavTUNABLE_INT("hw.ata.atapi_dma", &atapi_dma); 202230912Smav 203328819Smavstatic struct xpt_xport_ops ata_xport_ops = { 204195534Sscottl .alloc_device = ata_alloc_device, 205195534Sscottl .action = ata_action, 206195534Sscottl .async = ata_dev_async, 207204220Smav .announce = ata_announce_periph, 208195534Sscottl}; 209328819Smav#define ATA_XPT_XPORT(x, X) \ 210328819Smavstatic struct xpt_xport ata_xport_ ## x = { \ 211328819Smav .xport = XPORT_ ## X, \ 212328819Smav .name = #x, \ 213328819Smav .ops = &ata_xport_ops, \ 214328819Smav}; \ 215328819SmavCAM_XPT_XPORT(ata_xport_ ## x); 216195534Sscottl 217328819SmavATA_XPT_XPORT(ata, ATA); 218328819SmavATA_XPT_XPORT(sata, SATA); 219195534Sscottl 220328819Smav#undef ATA_XPORT_XPORT 221328819Smav 222328820Smavstatic struct xpt_proto_ops ata_proto_ops_ata = { 223328820Smav .announce = ata_proto_announce, 224328820Smav .denounce = ata_proto_denounce, 225328820Smav .debug_out = ata_proto_debug_out, 226328820Smav}; 227328820Smavstatic struct xpt_proto ata_proto_ata = { 228328820Smav .proto = PROTO_ATA, 229328820Smav .name = "ata", 230328820Smav .ops = &ata_proto_ops_ata, 231328820Smav}; 232328820Smav 233328820Smavstatic struct xpt_proto_ops ata_proto_ops_satapm = { 234328820Smav .announce = ata_proto_announce, 235328820Smav .denounce = ata_proto_denounce, 236328820Smav .debug_out = ata_proto_debug_out, 237328820Smav}; 238328820Smavstatic struct xpt_proto ata_proto_satapm = { 239328820Smav .proto = PROTO_SATAPM, 240328820Smav .name = "satapm", 241328820Smav .ops = &ata_proto_ops_satapm, 242328820Smav}; 243328820Smav 244328820Smavstatic struct xpt_proto_ops ata_proto_ops_semb = { 245328820Smav .announce = semb_proto_announce, 246328820Smav .denounce = semb_proto_denounce, 247328820Smav .debug_out = ata_proto_debug_out, 248328820Smav}; 249328820Smavstatic struct xpt_proto ata_proto_semb = { 250328820Smav .proto = PROTO_SEMB, 251328820Smav .name = "semb", 252328820Smav .ops = &ata_proto_ops_semb, 253328820Smav}; 254328820Smav 255328820SmavCAM_XPT_PROTO(ata_proto_ata); 256328820SmavCAM_XPT_PROTO(ata_proto_satapm); 257328820SmavCAM_XPT_PROTO(ata_proto_semb); 258328820Smav 259195534Sscottlstatic void 260195534Sscottlprobe_periph_init() 261195534Sscottl{ 262195534Sscottl} 263195534Sscottl 264195534Sscottlstatic cam_status 265195534Sscottlproberegister(struct cam_periph *periph, void *arg) 266195534Sscottl{ 267195534Sscottl union ccb *request_ccb; /* CCB representing the probe request */ 268195534Sscottl cam_status status; 269195534Sscottl probe_softc *softc; 270195534Sscottl 271195534Sscottl request_ccb = (union ccb *)arg; 272195534Sscottl if (request_ccb == NULL) { 273195534Sscottl printf("proberegister: no probe CCB, " 274195534Sscottl "can't register device\n"); 275195534Sscottl return(CAM_REQ_CMP_ERR); 276195534Sscottl } 277195534Sscottl 278203421Smav softc = (probe_softc *)malloc(sizeof(*softc), M_CAMXPT, M_ZERO | M_NOWAIT); 279195534Sscottl 280195534Sscottl if (softc == NULL) { 281195534Sscottl printf("proberegister: Unable to probe new device. " 282195534Sscottl "Unable to allocate softc\n"); 283195534Sscottl return(CAM_REQ_CMP_ERR); 284195534Sscottl } 285195534Sscottl TAILQ_INIT(&softc->request_ccbs); 286195534Sscottl TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h, 287195534Sscottl periph_links.tqe); 288195534Sscottl softc->flags = 0; 289195534Sscottl periph->softc = softc; 290195534Sscottl softc->periph = periph; 291195534Sscottl softc->action = PROBE_INVALID; 292195534Sscottl status = cam_periph_acquire(periph); 293195534Sscottl if (status != CAM_REQ_CMP) { 294195534Sscottl return (status); 295195534Sscottl } 296236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe started\n")); 297256843Smav ata_device_transport(periph->path); 298195534Sscottl probeschedule(periph); 299195534Sscottl return(CAM_REQ_CMP); 300195534Sscottl} 301195534Sscottl 302195534Sscottlstatic void 303195534Sscottlprobeschedule(struct cam_periph *periph) 304195534Sscottl{ 305195534Sscottl union ccb *ccb; 306195534Sscottl probe_softc *softc; 307195534Sscottl 308195534Sscottl softc = (probe_softc *)periph->softc; 309195534Sscottl ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs); 310195534Sscottl 311198389Smav if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) || 312235897Smav periph->path->device->protocol == PROTO_SATAPM || 313235897Smav periph->path->device->protocol == PROTO_SEMB) 314195534Sscottl PROBE_SET_ACTION(softc, PROBE_RESET); 315195534Sscottl else 316195534Sscottl PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 317195534Sscottl 318195534Sscottl if (ccb->crcn.flags & CAM_EXPECT_INQ_CHANGE) 319195534Sscottl softc->flags |= PROBE_NO_ANNOUNCE; 320195534Sscottl else 321195534Sscottl softc->flags &= ~PROBE_NO_ANNOUNCE; 322195534Sscottl 323203108Smav xpt_schedule(periph, CAM_PRIORITY_XPT); 324195534Sscottl} 325195534Sscottl 326195534Sscottlstatic void 327195534Sscottlprobestart(struct cam_periph *periph, union ccb *start_ccb) 328195534Sscottl{ 329199747Smav struct ccb_trans_settings cts; 330195534Sscottl struct ccb_ataio *ataio; 331195534Sscottl struct ccb_scsiio *csio; 332195534Sscottl probe_softc *softc; 333198708Smav struct cam_path *path; 334198708Smav struct ata_params *ident_buf; 335350805Smav u_int oif; 336195534Sscottl 337195534Sscottl CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probestart\n")); 338195534Sscottl 339195534Sscottl softc = (probe_softc *)periph->softc; 340198708Smav path = start_ccb->ccb_h.path; 341195534Sscottl ataio = &start_ccb->ataio; 342195534Sscottl csio = &start_ccb->csio; 343198708Smav ident_buf = &periph->path->device->ident_data; 344195534Sscottl 345203108Smav if (softc->restart) { 346203108Smav softc->restart = 0; 347203108Smav if ((path->device->flags & CAM_DEV_UNCONFIGURED) || 348235897Smav path->device->protocol == PROTO_SATAPM || 349235897Smav path->device->protocol == PROTO_SEMB) 350203108Smav softc->action = PROBE_RESET; 351203108Smav else 352203108Smav softc->action = PROBE_IDENTIFY; 353203108Smav } 354195534Sscottl switch (softc->action) { 355195534Sscottl case PROBE_RESET: 356195534Sscottl cam_fill_ataio(ataio, 357195534Sscottl 0, 358195534Sscottl probedone, 359195534Sscottl /*flags*/CAM_DIR_NONE, 360198389Smav 0, 361195534Sscottl /*data_ptr*/NULL, 362195534Sscottl /*dxfer_len*/0, 363203108Smav 15 * 1000); 364195534Sscottl ata_reset_cmd(ataio); 365195534Sscottl break; 366195534Sscottl case PROBE_IDENTIFY: 367195534Sscottl cam_fill_ataio(ataio, 368195534Sscottl 1, 369195534Sscottl probedone, 370195534Sscottl /*flags*/CAM_DIR_IN, 371198389Smav 0, 372203385Smav /*data_ptr*/(u_int8_t *)&softc->ident_data, 373203385Smav /*dxfer_len*/sizeof(softc->ident_data), 374195534Sscottl 30 * 1000); 375350805Smav if (path->device->protocol == PROTO_ATA) 376196659Smav ata_28bit_cmd(ataio, ATA_ATA_IDENTIFY, 0, 0, 0); 377195534Sscottl else 378196659Smav ata_28bit_cmd(ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0); 379195534Sscottl break; 380203421Smav case PROBE_SPINUP: 381203421Smav if (bootverbose) 382203421Smav xpt_print(path, "Spinning up device\n"); 383203421Smav cam_fill_ataio(ataio, 384203421Smav 1, 385203421Smav probedone, 386203421Smav /*flags*/CAM_DIR_NONE | CAM_HIGH_POWER, 387203421Smav 0, 388203421Smav /*data_ptr*/NULL, 389203421Smav /*dxfer_len*/0, 390203421Smav 30 * 1000); 391203421Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_PUIS_SPINUP, 0, 0); 392203421Smav break; 393195534Sscottl case PROBE_SETMODE: 394199747Smav { 395199747Smav int mode, wantmode; 396199747Smav 397199747Smav mode = 0; 398199747Smav /* Fetch user modes from SIM. */ 399199747Smav bzero(&cts, sizeof(cts)); 400203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 401199747Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 402199747Smav cts.type = CTS_TYPE_USER_SETTINGS; 403199747Smav xpt_action((union ccb *)&cts); 404199747Smav if (path->device->transport == XPORT_ATA) { 405199747Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_MODE) 406199747Smav mode = cts.xport_specific.ata.mode; 407199747Smav } else { 408199799Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_MODE) 409199747Smav mode = cts.xport_specific.sata.mode; 410199747Smav } 411350805Smav if (path->device->protocol == PROTO_ATA) { 412230912Smav if (ata_dma == 0 && (mode == 0 || mode > ATA_PIO_MAX)) 413230912Smav mode = ATA_PIO_MAX; 414230912Smav } else { 415230912Smav if (atapi_dma == 0 && (mode == 0 || mode > ATA_PIO_MAX)) 416230912Smav mode = ATA_PIO_MAX; 417230912Smav } 418199747Smavnegotiate: 419199747Smav /* Honor device capabilities. */ 420199747Smav wantmode = mode = ata_max_mode(ident_buf, mode); 421199747Smav /* Report modes to SIM. */ 422199747Smav bzero(&cts, sizeof(cts)); 423203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 424199747Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 425199747Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 426199747Smav if (path->device->transport == XPORT_ATA) { 427199747Smav cts.xport_specific.ata.mode = mode; 428199747Smav cts.xport_specific.ata.valid = CTS_ATA_VALID_MODE; 429199747Smav } else { 430199747Smav cts.xport_specific.sata.mode = mode; 431199747Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_MODE; 432199747Smav } 433199747Smav xpt_action((union ccb *)&cts); 434200171Smav /* Fetch current modes from SIM. */ 435199747Smav bzero(&cts, sizeof(cts)); 436203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 437199747Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 438199747Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 439199747Smav xpt_action((union ccb *)&cts); 440199747Smav if (path->device->transport == XPORT_ATA) { 441199747Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_MODE) 442199747Smav mode = cts.xport_specific.ata.mode; 443199747Smav } else { 444350545Sbrooks if (cts.xport_specific.sata.valid & CTS_SATA_VALID_MODE) 445199747Smav mode = cts.xport_specific.sata.mode; 446199747Smav } 447199747Smav /* If SIM disagree - renegotiate. */ 448199747Smav if (mode != wantmode) 449199747Smav goto negotiate; 450220886Smav /* Remember what transport thinks about DMA. */ 451350805Smav oif = path->device->inq_flags; 452220886Smav if (mode < ATA_DMA) 453220886Smav path->device->inq_flags &= ~SID_DMA; 454220886Smav else 455220886Smav path->device->inq_flags |= SID_DMA; 456350805Smav if (path->device->inq_flags != oif) 457350805Smav xpt_async(AC_GETDEV_CHANGED, path, NULL); 458195534Sscottl cam_fill_ataio(ataio, 459195534Sscottl 1, 460195534Sscottl probedone, 461196353Smav /*flags*/CAM_DIR_NONE, 462196353Smav 0, 463196353Smav /*data_ptr*/NULL, 464196353Smav /*dxfer_len*/0, 465195534Sscottl 30 * 1000); 466199747Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); 467195534Sscottl break; 468199747Smav } 469207499Smav case PROBE_SETPM: 470207499Smav cam_fill_ataio(ataio, 471207499Smav 1, 472207499Smav probedone, 473207499Smav CAM_DIR_NONE, 474207499Smav 0, 475207499Smav NULL, 476207499Smav 0, 477207499Smav 30*1000); 478207499Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, 479207499Smav (softc->caps & CTS_SATA_CAPS_H_PMREQ) ? 0x10 : 0x90, 480207499Smav 0, 0x03); 481207499Smav break; 482207499Smav case PROBE_SETAPST: 483207499Smav cam_fill_ataio(ataio, 484207499Smav 1, 485207499Smav probedone, 486207499Smav CAM_DIR_NONE, 487207499Smav 0, 488207499Smav NULL, 489207499Smav 0, 490207499Smav 30*1000); 491207499Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, 492207499Smav (softc->caps & CTS_SATA_CAPS_H_APST) ? 0x10 : 0x90, 493207499Smav 0, 0x07); 494207499Smav break; 495207499Smav case PROBE_SETDMAAA: 496207499Smav cam_fill_ataio(ataio, 497207499Smav 1, 498207499Smav probedone, 499207499Smav CAM_DIR_NONE, 500207499Smav 0, 501207499Smav NULL, 502207499Smav 0, 503207499Smav 30*1000); 504207499Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, 505207499Smav (softc->caps & CTS_SATA_CAPS_H_DMAAA) ? 0x10 : 0x90, 506207499Smav 0, 0x02); 507207499Smav break; 508220602Smav case PROBE_SETAN: 509270327Simp /* Remember what transport thinks about AEN. */ 510350805Smav oif = path->device->inq_flags; 511270327Simp if (softc->caps & CTS_SATA_CAPS_H_AN) 512238886Smav path->device->inq_flags |= SID_AEN; 513238886Smav else 514238886Smav path->device->inq_flags &= ~SID_AEN; 515350805Smav if (path->device->inq_flags != oif) 516350805Smav xpt_async(AC_GETDEV_CHANGED, path, NULL); 517220602Smav cam_fill_ataio(ataio, 518220602Smav 1, 519220602Smav probedone, 520220602Smav CAM_DIR_NONE, 521220602Smav 0, 522220602Smav NULL, 523220602Smav 0, 524220602Smav 30*1000); 525220602Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, 526220602Smav (softc->caps & CTS_SATA_CAPS_H_AN) ? 0x10 : 0x90, 527220602Smav 0, 0x05); 528220602Smav break; 529198708Smav case PROBE_SET_MULTI: 530198708Smav { 531200171Smav u_int sectors, bytecount; 532198708Smav 533200171Smav bytecount = 8192; /* SATA maximum */ 534200171Smav /* Fetch user bytecount from SIM. */ 535200171Smav bzero(&cts, sizeof(cts)); 536203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 537200171Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 538200171Smav cts.type = CTS_TYPE_USER_SETTINGS; 539200171Smav xpt_action((union ccb *)&cts); 540200171Smav if (path->device->transport == XPORT_ATA) { 541200171Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 542200171Smav bytecount = cts.xport_specific.ata.bytecount; 543200171Smav } else { 544200171Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 545200171Smav bytecount = cts.xport_specific.sata.bytecount; 546200171Smav } 547200171Smav /* Honor device capabilities. */ 548200171Smav sectors = max(1, min(ident_buf->sectors_intr & 0xff, 549200171Smav bytecount / ata_logical_sector_size(ident_buf))); 550198708Smav /* Report bytecount to SIM. */ 551198708Smav bzero(&cts, sizeof(cts)); 552203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 553198708Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 554198708Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 555198708Smav if (path->device->transport == XPORT_ATA) { 556198897Smav cts.xport_specific.ata.bytecount = sectors * 557198897Smav ata_logical_sector_size(ident_buf); 558198708Smav cts.xport_specific.ata.valid = CTS_ATA_VALID_BYTECOUNT; 559198708Smav } else { 560198897Smav cts.xport_specific.sata.bytecount = sectors * 561198897Smav ata_logical_sector_size(ident_buf); 562198708Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_BYTECOUNT; 563198708Smav } 564198708Smav xpt_action((union ccb *)&cts); 565200171Smav /* Fetch current bytecount from SIM. */ 566200171Smav bzero(&cts, sizeof(cts)); 567203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 568200171Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 569200171Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 570200171Smav xpt_action((union ccb *)&cts); 571200171Smav if (path->device->transport == XPORT_ATA) { 572200171Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 573200171Smav bytecount = cts.xport_specific.ata.bytecount; 574200171Smav } else { 575200171Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 576200171Smav bytecount = cts.xport_specific.sata.bytecount; 577200171Smav } 578200171Smav sectors = bytecount / ata_logical_sector_size(ident_buf); 579198708Smav 580198708Smav cam_fill_ataio(ataio, 581198708Smav 1, 582198708Smav probedone, 583198708Smav CAM_DIR_NONE, 584198708Smav 0, 585198708Smav NULL, 586198708Smav 0, 587198708Smav 30*1000); 588198708Smav ata_28bit_cmd(ataio, ATA_SET_MULTI, 0, 0, sectors); 589198708Smav break; 590195534Sscottl } 591195534Sscottl case PROBE_INQUIRY: 592200171Smav { 593200171Smav u_int bytecount; 594200171Smav 595200171Smav bytecount = 8192; /* SATA maximum */ 596200171Smav /* Fetch user bytecount from SIM. */ 597200171Smav bzero(&cts, sizeof(cts)); 598203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 599200171Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 600200171Smav cts.type = CTS_TYPE_USER_SETTINGS; 601200171Smav xpt_action((union ccb *)&cts); 602200171Smav if (path->device->transport == XPORT_ATA) { 603200171Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 604200171Smav bytecount = cts.xport_specific.ata.bytecount; 605200171Smav } else { 606200171Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 607200171Smav bytecount = cts.xport_specific.sata.bytecount; 608200171Smav } 609200171Smav /* Honor device capabilities. */ 610200171Smav bytecount &= ~1; 611200171Smav bytecount = max(2, min(65534, bytecount)); 612200171Smav if (ident_buf->satacapabilities != 0x0000 && 613200171Smav ident_buf->satacapabilities != 0xffff) { 614200171Smav bytecount = min(8192, bytecount); 615200171Smav } 616200171Smav /* Report bytecount to SIM. */ 617200171Smav bzero(&cts, sizeof(cts)); 618203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 619200171Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 620200171Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 621200171Smav if (path->device->transport == XPORT_ATA) { 622200171Smav cts.xport_specific.ata.bytecount = bytecount; 623200171Smav cts.xport_specific.ata.valid = CTS_ATA_VALID_BYTECOUNT; 624200171Smav } else { 625200171Smav cts.xport_specific.sata.bytecount = bytecount; 626200171Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_BYTECOUNT; 627200171Smav } 628200171Smav xpt_action((union ccb *)&cts); 629200171Smav /* FALLTHROUGH */ 630200171Smav } 631195534Sscottl case PROBE_FULL_INQUIRY: 632195534Sscottl { 633195534Sscottl u_int inquiry_len; 634195534Sscottl struct scsi_inquiry_data *inq_buf = 635350805Smav &path->device->inq_data; 636195534Sscottl 637195534Sscottl if (softc->action == PROBE_INQUIRY) 638195534Sscottl inquiry_len = SHORT_INQUIRY_LENGTH; 639195534Sscottl else 640195534Sscottl inquiry_len = SID_ADDITIONAL_LENGTH(inq_buf); 641195534Sscottl /* 642195534Sscottl * Some parallel SCSI devices fail to send an 643195534Sscottl * ignore wide residue message when dealing with 644195534Sscottl * odd length inquiry requests. Round up to be 645195534Sscottl * safe. 646195534Sscottl */ 647195534Sscottl inquiry_len = roundup2(inquiry_len, 2); 648195534Sscottl scsi_inquiry(csio, 649195534Sscottl /*retries*/1, 650195534Sscottl probedone, 651195534Sscottl MSG_SIMPLE_Q_TAG, 652195534Sscottl (u_int8_t *)inq_buf, 653195534Sscottl inquiry_len, 654195534Sscottl /*evpd*/FALSE, 655195534Sscottl /*page_code*/0, 656195534Sscottl SSD_MIN_SIZE, 657195534Sscottl /*timeout*/60 * 1000); 658195534Sscottl break; 659195534Sscottl } 660195534Sscottl case PROBE_PM_PID: 661195534Sscottl cam_fill_ataio(ataio, 662195534Sscottl 1, 663195534Sscottl probedone, 664195534Sscottl /*flags*/CAM_DIR_NONE, 665198389Smav 0, 666195534Sscottl /*data_ptr*/NULL, 667195534Sscottl /*dxfer_len*/0, 668195534Sscottl 10 * 1000); 669195534Sscottl ata_pm_read_cmd(ataio, 0, 15); 670195534Sscottl break; 671195534Sscottl case PROBE_PM_PRV: 672195534Sscottl cam_fill_ataio(ataio, 673195534Sscottl 1, 674195534Sscottl probedone, 675195534Sscottl /*flags*/CAM_DIR_NONE, 676198389Smav 0, 677195534Sscottl /*data_ptr*/NULL, 678195534Sscottl /*dxfer_len*/0, 679195534Sscottl 10 * 1000); 680195534Sscottl ata_pm_read_cmd(ataio, 1, 15); 681195534Sscottl break; 682235897Smav case PROBE_IDENTIFY_SES: 683235897Smav cam_fill_ataio(ataio, 684235897Smav 1, 685235897Smav probedone, 686235897Smav /*flags*/CAM_DIR_IN, 687235897Smav 0, 688235897Smav /*data_ptr*/(u_int8_t *)&softc->ident_data, 689235897Smav /*dxfer_len*/sizeof(softc->ident_data), 690235897Smav 30 * 1000); 691235897Smav ata_28bit_cmd(ataio, ATA_SEP_ATTN, 0xEC, 0x02, 692235897Smav sizeof(softc->ident_data) / 4); 693235897Smav break; 694235897Smav case PROBE_IDENTIFY_SAFTE: 695235897Smav cam_fill_ataio(ataio, 696235897Smav 1, 697235897Smav probedone, 698235897Smav /*flags*/CAM_DIR_IN, 699235897Smav 0, 700235897Smav /*data_ptr*/(u_int8_t *)&softc->ident_data, 701235897Smav /*dxfer_len*/sizeof(softc->ident_data), 702235897Smav 30 * 1000); 703235897Smav ata_28bit_cmd(ataio, ATA_SEP_ATTN, 0xEC, 0x00, 704235897Smav sizeof(softc->ident_data) / 4); 705235897Smav break; 706195534Sscottl default: 707236613Smav panic("probestart: invalid action state 0x%x\n", softc->action); 708195534Sscottl } 709249466Smav start_ccb->ccb_h.flags |= CAM_DEV_QFREEZE; 710195534Sscottl xpt_action(start_ccb); 711195534Sscottl} 712236437Smav 713195534Sscottlstatic void 714195534Sscottlproberequestdefaultnegotiation(struct cam_periph *periph) 715195534Sscottl{ 716195534Sscottl struct ccb_trans_settings cts; 717195534Sscottl 718203108Smav xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE); 719195534Sscottl cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 720195534Sscottl cts.type = CTS_TYPE_USER_SETTINGS; 721195534Sscottl xpt_action((union ccb *)&cts); 722236437Smav if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 723195534Sscottl return; 724236437Smav cts.xport_specific.valid = 0; 725195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 726195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 727195534Sscottl xpt_action((union ccb *)&cts); 728195534Sscottl} 729195534Sscottl 730195534Sscottlstatic void 731195534Sscottlprobedone(struct cam_periph *periph, union ccb *done_ccb) 732195534Sscottl{ 733199747Smav struct ccb_trans_settings cts; 734195534Sscottl struct ata_params *ident_buf; 735235897Smav struct scsi_inquiry_data *inq_buf; 736195534Sscottl probe_softc *softc; 737195534Sscottl struct cam_path *path; 738217444Smav cam_status status; 739195534Sscottl u_int32_t priority; 740350805Smav u_int caps, oif; 741350805Smav int changed, found = 1; 742235897Smav static const uint8_t fake_device_id_hdr[8] = 743235897Smav {0, SVPD_DEVICE_ID, 0, 12, 744235897Smav SVPD_ID_CODESET_BINARY, SVPD_ID_TYPE_NAA, 0, 8}; 745195534Sscottl 746195534Sscottl CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probedone\n")); 747195534Sscottl 748195534Sscottl softc = (probe_softc *)periph->softc; 749195534Sscottl path = done_ccb->ccb_h.path; 750195534Sscottl priority = done_ccb->ccb_h.pinfo.priority; 751195534Sscottl ident_buf = &path->device->ident_data; 752235897Smav inq_buf = &path->device->inq_data; 753195534Sscottl 754198708Smav if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 755236814Smav if (cam_periph_error(done_ccb, 756236814Smav 0, softc->restart ? (SF_NO_RECOVERY | SF_NO_RETRY) : 0, 757249466Smav NULL) == ERESTART) { 758249466Smavout: 759249466Smav /* Drop freeze taken due to CAM_DEV_QFREEZE flag set. */ 760249466Smav cam_release_devq(path, 0, 0, 0, FALSE); 761195534Sscottl return; 762249466Smav } 763209744Smav if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 764195534Sscottl /* Don't wedge the queue */ 765249466Smav xpt_release_devq(path, /*count*/1, /*run_queue*/TRUE); 766195534Sscottl } 767217444Smav status = done_ccb->ccb_h.status & CAM_STATUS_MASK; 768209744Smav if (softc->restart) { 769209744Smav softc->faults++; 770209744Smav if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == 771209744Smav CAM_CMD_TIMEOUT) 772209744Smav softc->faults += 4; 773209744Smav if (softc->faults < 10) 774209744Smav goto done; 775209744Smav else 776209744Smav softc->restart = 0; 777217444Smav 778198708Smav /* Old PIO2 devices may not support mode setting. */ 779217444Smav } else if (softc->action == PROBE_SETMODE && 780217444Smav status == CAM_ATA_STATUS_ERROR && 781198708Smav ata_max_pmode(ident_buf) <= ATA_PIO2 && 782217444Smav (ident_buf->capabilities1 & ATA_SUPPORT_IORDY) == 0) { 783198708Smav goto noerror; 784217444Smav 785198708Smav /* 786217444Smav * Some old WD SATA disks report supported and enabled 787217444Smav * device-initiated interface power management, but return 788217444Smav * ABORT on attempt to disable it. 789217444Smav */ 790217444Smav } else if (softc->action == PROBE_SETPM && 791217444Smav status == CAM_ATA_STATUS_ERROR) { 792217444Smav goto noerror; 793217875Smav 794217875Smav /* 795323736Savg * Some old WD SATA disks have broken SPINUP handling. 796323736Savg * If we really fail to spin up the disk, then there will be 797323736Savg * some media access errors later on, but at least we will 798323736Savg * have a device to interact with for recovery attempts. 799323736Savg */ 800323736Savg } else if (softc->action == PROBE_SPINUP && 801323736Savg status == CAM_ATA_STATUS_ERROR) { 802323736Savg goto noerror; 803323736Savg 804323736Savg /* 805217875Smav * Some HP SATA disks report supported DMA Auto-Activation, 806217875Smav * but return ABORT on attempt to enable it. 807217875Smav */ 808217875Smav } else if (softc->action == PROBE_SETDMAAA && 809217875Smav status == CAM_ATA_STATUS_ERROR) { 810217875Smav goto noerror; 811235897Smav 812235897Smav /* 813235897Smav * SES and SAF-TE SEPs have different IDENTIFY commands, 814235897Smav * but SATA specification doesn't tell how to identify them. 815235897Smav * Until better way found, just try another if first fail. 816235897Smav */ 817235897Smav } else if (softc->action == PROBE_IDENTIFY_SES && 818235897Smav status == CAM_ATA_STATUS_ERROR) { 819235897Smav PROBE_SET_ACTION(softc, PROBE_IDENTIFY_SAFTE); 820235897Smav xpt_release_ccb(done_ccb); 821235897Smav xpt_schedule(periph, priority); 822249466Smav goto out; 823217444Smav } 824217444Smav 825217444Smav /* 826198708Smav * If we get to this point, we got an error status back 827198708Smav * from the inquiry and the error status doesn't require 828198708Smav * automatically retrying the command. Therefore, the 829198708Smav * inquiry failed. If we had inquiry information before 830198708Smav * for this device, but this latest inquiry command failed, 831198708Smav * the device has probably gone away. If this device isn't 832198708Smav * already marked unconfigured, notify the peripheral 833198708Smav * drivers that this device is no more. 834198708Smav */ 835209744Smavdevice_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0) 836198708Smav xpt_async(AC_LOST_DEVICE, path, NULL); 837236613Smav PROBE_SET_ACTION(softc, PROBE_INVALID); 838198708Smav found = 0; 839198708Smav goto done; 840198708Smav } 841198708Smavnoerror: 842203385Smav if (softc->restart) 843203385Smav goto done; 844198708Smav switch (softc->action) { 845198708Smav case PROBE_RESET: 846195534Sscottl { 847198708Smav int sign = (done_ccb->ataio.res.lba_high << 8) + 848198708Smav done_ccb->ataio.res.lba_mid; 849236613Smav CAM_DEBUG(path, CAM_DEBUG_PROBE, 850236613Smav ("SIGNATURE: %04x\n", sign)); 851198708Smav if (sign == 0x0000 && 852198708Smav done_ccb->ccb_h.target_id != 15) { 853198708Smav path->device->protocol = PROTO_ATA; 854198708Smav PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 855198708Smav } else if (sign == 0x9669 && 856198708Smav done_ccb->ccb_h.target_id == 15) { 857199747Smav /* Report SIM that PM is present. */ 858198708Smav bzero(&cts, sizeof(cts)); 859203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 860198708Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 861198708Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 862198708Smav cts.xport_specific.sata.pm_present = 1; 863198708Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; 864198708Smav xpt_action((union ccb *)&cts); 865198708Smav path->device->protocol = PROTO_SATAPM; 866198708Smav PROBE_SET_ACTION(softc, PROBE_PM_PID); 867235897Smav } else if (sign == 0xc33c && 868235897Smav done_ccb->ccb_h.target_id != 15) { 869235897Smav path->device->protocol = PROTO_SEMB; 870235897Smav PROBE_SET_ACTION(softc, PROBE_IDENTIFY_SES); 871198708Smav } else if (sign == 0xeb14 && 872198708Smav done_ccb->ccb_h.target_id != 15) { 873198708Smav path->device->protocol = PROTO_SCSI; 874198708Smav PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 875198708Smav } else { 876198708Smav if (done_ccb->ccb_h.target_id != 15) { 877198708Smav xpt_print(path, 878198708Smav "Unexpected signature 0x%04x\n", sign); 879195534Sscottl } 880198708Smav goto device_fail; 881198708Smav } 882198708Smav xpt_release_ccb(done_ccb); 883198708Smav xpt_schedule(periph, priority); 884249466Smav goto out; 885198708Smav } 886198708Smav case PROBE_IDENTIFY: 887198708Smav { 888207222Smav struct ccb_pathinq cpi; 889198708Smav int16_t *ptr; 890307606Ssephe int veto = 0; 891195534Sscottl 892350794Smav /* 893350794Smav * Convert to host byte order, and fix the strings. 894350794Smav */ 895203385Smav ident_buf = &softc->ident_data; 896198708Smav for (ptr = (int16_t *)ident_buf; 897198708Smav ptr < (int16_t *)ident_buf + sizeof(struct ata_params)/2; ptr++) { 898198708Smav *ptr = le16toh(*ptr); 899198708Smav } 900198708Smav if (strncmp(ident_buf->model, "FX", 2) && 901198708Smav strncmp(ident_buf->model, "NEC", 3) && 902198708Smav strncmp(ident_buf->model, "Pioneer", 7) && 903198708Smav strncmp(ident_buf->model, "SHARP", 5)) { 904198708Smav ata_bswap(ident_buf->model, sizeof(ident_buf->model)); 905198708Smav ata_bswap(ident_buf->revision, sizeof(ident_buf->revision)); 906198708Smav ata_bswap(ident_buf->serial, sizeof(ident_buf->serial)); 907198708Smav } 908198708Smav ata_btrim(ident_buf->model, sizeof(ident_buf->model)); 909198708Smav ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model)); 910198708Smav ata_btrim(ident_buf->revision, sizeof(ident_buf->revision)); 911198708Smav ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision)); 912198708Smav ata_btrim(ident_buf->serial, sizeof(ident_buf->serial)); 913198708Smav ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial)); 914350794Smav 915350794Smav /* 916350794Smav * Allow others to veto this ATA disk attachment. This 917350794Smav * is mainly used by VMs, whose disk controllers may 918350794Smav * share the disks with the simulated ATA controllers. 919350794Smav */ 920350794Smav EVENTHANDLER_INVOKE(ada_probe_veto, path, ident_buf, &veto); 921350794Smav if (veto) { 922350794Smav goto device_fail; 923350794Smav } 924350794Smav 925203421Smav /* Device may need spin-up before IDENTIFY become valid. */ 926204354Smav if ((ident_buf->specconf == 0x37c8 || 927204354Smav ident_buf->specconf == 0x738c) && 928204354Smav ((ident_buf->config & ATA_RESP_INCOMPLETE) || 929204354Smav softc->spinup == 0)) { 930203421Smav PROBE_SET_ACTION(softc, PROBE_SPINUP); 931203421Smav xpt_release_ccb(done_ccb); 932203421Smav xpt_schedule(periph, priority); 933249466Smav goto out; 934203421Smav } 935203385Smav ident_buf = &path->device->ident_data; 936350805Smav 937350805Smav /* Check that it is the same device as we know. */ 938198708Smav if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) { 939203385Smav if (bcmp(softc->ident_data.model, ident_buf->model, 940203385Smav sizeof(ident_buf->model)) || 941203385Smav bcmp(softc->ident_data.serial, ident_buf->serial, 942203385Smav sizeof(ident_buf->serial))) { 943350805Smav /* The device was replaced. */ 944350805Smav changed = 2; 945198708Smav xpt_async(AC_LOST_DEVICE, path, NULL); 946350805Smav } else if (bcmp(&softc->ident_data, ident_buf, 947350805Smav sizeof(*ident_buf))) { 948350805Smav /* The device is the same, but has changed. */ 949350805Smav changed = 1; 950207282Smav } else { 951350805Smav /* Nothing has changed. */ 952207282Smav changed = 0; 953207282Smav } 954350805Smav } else { 955350805Smav /* This is a new device. */ 956350805Smav changed = 2; 957207282Smav } 958350805Smav 959350805Smav if (changed != 0) 960203385Smav bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 961350805Smav if (changed == 2) { 962195534Sscottl /* Clean up from previous instance of this device */ 963195534Sscottl if (path->device->serial_num != NULL) { 964195534Sscottl free(path->device->serial_num, M_CAMXPT); 965195534Sscottl path->device->serial_num = NULL; 966195534Sscottl path->device->serial_num_len = 0; 967195534Sscottl } 968235897Smav if (path->device->device_id != NULL) { 969235897Smav free(path->device->device_id, M_CAMXPT); 970235897Smav path->device->device_id = NULL; 971235897Smav path->device->device_id_len = 0; 972235897Smav } 973195534Sscottl path->device->serial_num = 974195534Sscottl (u_int8_t *)malloc((sizeof(ident_buf->serial) + 1), 975198708Smav M_CAMXPT, M_NOWAIT); 976195534Sscottl if (path->device->serial_num != NULL) { 977195534Sscottl bcopy(ident_buf->serial, 978195534Sscottl path->device->serial_num, 979195534Sscottl sizeof(ident_buf->serial)); 980195534Sscottl path->device->serial_num[sizeof(ident_buf->serial)] 981195534Sscottl = '\0'; 982195534Sscottl path->device->serial_num_len = 983195534Sscottl strlen(path->device->serial_num); 984195534Sscottl } 985235897Smav if (ident_buf->enabled.extension & 986235897Smav ATA_SUPPORT_64BITWWN) { 987235897Smav path->device->device_id = 988235897Smav malloc(16, M_CAMXPT, M_NOWAIT); 989235897Smav if (path->device->device_id != NULL) { 990235897Smav path->device->device_id_len = 16; 991235897Smav bcopy(&fake_device_id_hdr, 992235897Smav path->device->device_id, 8); 993250301Smav bcopy(ident_buf->wwn, 994250301Smav path->device->device_id + 8, 8); 995250301Smav ata_bswap(path->device->device_id + 8, 8); 996235897Smav } 997235897Smav } 998198331Smav path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 999350805Smav } 1000350805Smav if (changed == 1) 1001236393Smav xpt_async(AC_GETDEV_CHANGED, path, NULL); 1002199178Smav if (ident_buf->satacapabilities & ATA_SUPPORT_NCQ) { 1003236234Smav path->device->mintags = 2; 1004236234Smav path->device->maxtags = 1005199178Smav ATA_QUEUE_LEN(ident_buf->queue) + 1; 1006199178Smav } 1007199178Smav ata_find_quirk(path->device); 1008199263Smav if (path->device->mintags != 0 && 1009199263Smav path->bus->sim->max_tagged_dev_openings != 0) { 1010207222Smav /* Check if the SIM does not want queued commands. */ 1011350804Smav xpt_path_inq(&cpi, path); 1012207222Smav if (cpi.ccb_h.status == CAM_REQ_CMP && 1013207222Smav (cpi.hba_inquiry & PI_TAG_ABLE)) { 1014207222Smav /* Report SIM which tags are allowed. */ 1015207222Smav bzero(&cts, sizeof(cts)); 1016207222Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1017207222Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1018207222Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 1019207222Smav cts.xport_specific.sata.tags = path->device->maxtags; 1020207222Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_TAGS; 1021207222Smav xpt_action((union ccb *)&cts); 1022207222Smav } 1023199178Smav } 1024236666Smav ata_device_transport(path); 1025350805Smav if (changed == 2) 1026236437Smav proberequestdefaultnegotiation(periph); 1027198708Smav PROBE_SET_ACTION(softc, PROBE_SETMODE); 1028195534Sscottl xpt_release_ccb(done_ccb); 1029198708Smav xpt_schedule(periph, priority); 1030249466Smav goto out; 1031195534Sscottl } 1032203421Smav case PROBE_SPINUP: 1033203421Smav if (bootverbose) 1034203421Smav xpt_print(path, "Spin-up done\n"); 1035203421Smav softc->spinup = 1; 1036203421Smav PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 1037203421Smav xpt_release_ccb(done_ccb); 1038203421Smav xpt_schedule(periph, priority); 1039249466Smav goto out; 1040195534Sscottl case PROBE_SETMODE: 1041207499Smav /* Set supported bits. */ 1042207499Smav bzero(&cts, sizeof(cts)); 1043207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1044207499Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1045207499Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 1046207499Smav xpt_action((union ccb *)&cts); 1047249199Smarius if (path->device->transport == XPORT_SATA && 1048249199Smarius cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1049207499Smav caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H; 1050249199Smarius else if (path->device->transport == XPORT_ATA && 1051249199Smarius cts.xport_specific.ata.valid & CTS_ATA_VALID_CAPS) 1052249199Smarius caps = cts.xport_specific.ata.caps & CTS_ATA_CAPS_H; 1053207499Smav else 1054207499Smav caps = 0; 1055249199Smarius if (path->device->transport == XPORT_SATA && 1056249199Smarius ident_buf->satacapabilities != 0xffff) { 1057207499Smav if (ident_buf->satacapabilities & ATA_SUPPORT_IFPWRMNGTRCV) 1058207499Smav caps |= CTS_SATA_CAPS_D_PMREQ; 1059207499Smav if (ident_buf->satacapabilities & ATA_SUPPORT_HAPST) 1060207499Smav caps |= CTS_SATA_CAPS_D_APST; 1061207499Smav } 1062207499Smav /* Mask unwanted bits. */ 1063207499Smav bzero(&cts, sizeof(cts)); 1064207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1065207499Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1066207499Smav cts.type = CTS_TYPE_USER_SETTINGS; 1067207499Smav xpt_action((union ccb *)&cts); 1068249199Smarius if (path->device->transport == XPORT_SATA && 1069249199Smarius cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1070207499Smav caps &= cts.xport_specific.sata.caps; 1071249199Smarius else if (path->device->transport == XPORT_ATA && 1072249199Smarius cts.xport_specific.ata.valid & CTS_ATA_VALID_CAPS) 1073249199Smarius caps &= cts.xport_specific.ata.caps; 1074215454Smav else 1075215454Smav caps = 0; 1076249199Smarius /* 1077249199Smarius * Remember what transport thinks about 48-bit DMA. If 1078249199Smarius * capability information is not provided or transport is 1079249199Smarius * SATA, we take support for granted. 1080249199Smarius */ 1081350805Smav oif = path->device->inq_flags; 1082249199Smarius if (!(path->device->inq_flags & SID_DMA) || 1083249199Smarius (path->device->transport == XPORT_ATA && 1084249199Smarius (cts.xport_specific.ata.valid & CTS_ATA_VALID_CAPS) && 1085249199Smarius !(caps & CTS_ATA_CAPS_H_DMA48))) 1086249199Smarius path->device->inq_flags &= ~SID_DMA48; 1087249199Smarius else 1088249199Smarius path->device->inq_flags |= SID_DMA48; 1089350805Smav if (path->device->inq_flags != oif) 1090350805Smav xpt_async(AC_GETDEV_CHANGED, path, NULL); 1091207499Smav /* Store result to SIM. */ 1092207499Smav bzero(&cts, sizeof(cts)); 1093207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1094207499Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1095207499Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 1096249199Smarius if (path->device->transport == XPORT_SATA) { 1097249199Smarius cts.xport_specific.sata.caps = caps; 1098249199Smarius cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS; 1099249199Smarius } else { 1100249199Smarius cts.xport_specific.ata.caps = caps; 1101249199Smarius cts.xport_specific.ata.valid = CTS_ATA_VALID_CAPS; 1102249199Smarius } 1103207499Smav xpt_action((union ccb *)&cts); 1104207499Smav softc->caps = caps; 1105249199Smarius if (path->device->transport != XPORT_SATA) 1106249199Smarius goto notsata; 1107217874Smav if ((ident_buf->satasupport & ATA_SUPPORT_IFPWRMNGT) && 1108217874Smav (!(softc->caps & CTS_SATA_CAPS_H_PMREQ)) != 1109217874Smav (!(ident_buf->sataenabled & ATA_SUPPORT_IFPWRMNGT))) { 1110207499Smav PROBE_SET_ACTION(softc, PROBE_SETPM); 1111207499Smav xpt_release_ccb(done_ccb); 1112207499Smav xpt_schedule(periph, priority); 1113249466Smav goto out; 1114207499Smav } 1115207499Smav /* FALLTHROUGH */ 1116207499Smav case PROBE_SETPM: 1117207499Smav if (ident_buf->satacapabilities != 0xffff && 1118217874Smav (ident_buf->satacapabilities & ATA_SUPPORT_DAPST) && 1119217874Smav (!(softc->caps & CTS_SATA_CAPS_H_APST)) != 1120217874Smav (!(ident_buf->sataenabled & ATA_ENABLED_DAPST))) { 1121207499Smav PROBE_SET_ACTION(softc, PROBE_SETAPST); 1122207499Smav xpt_release_ccb(done_ccb); 1123207499Smav xpt_schedule(periph, priority); 1124249466Smav goto out; 1125207499Smav } 1126207499Smav /* FALLTHROUGH */ 1127207499Smav case PROBE_SETAPST: 1128217874Smav if ((ident_buf->satasupport & ATA_SUPPORT_AUTOACTIVATE) && 1129217874Smav (!(softc->caps & CTS_SATA_CAPS_H_DMAAA)) != 1130217874Smav (!(ident_buf->sataenabled & ATA_SUPPORT_AUTOACTIVATE))) { 1131207499Smav PROBE_SET_ACTION(softc, PROBE_SETDMAAA); 1132207499Smav xpt_release_ccb(done_ccb); 1133207499Smav xpt_schedule(periph, priority); 1134249466Smav goto out; 1135207499Smav } 1136207499Smav /* FALLTHROUGH */ 1137207499Smav case PROBE_SETDMAAA: 1138270327Simp if (path->device->protocol != PROTO_ATA && 1139270327Simp (ident_buf->satasupport & ATA_SUPPORT_ASYNCNOTIF) && 1140220602Smav (!(softc->caps & CTS_SATA_CAPS_H_AN)) != 1141220602Smav (!(ident_buf->sataenabled & ATA_SUPPORT_ASYNCNOTIF))) { 1142220602Smav PROBE_SET_ACTION(softc, PROBE_SETAN); 1143220602Smav xpt_release_ccb(done_ccb); 1144220602Smav xpt_schedule(periph, priority); 1145249466Smav goto out; 1146220602Smav } 1147220602Smav /* FALLTHROUGH */ 1148220602Smav case PROBE_SETAN: 1149207499Smavnotsata: 1150198708Smav if (path->device->protocol == PROTO_ATA) { 1151198708Smav PROBE_SET_ACTION(softc, PROBE_SET_MULTI); 1152198708Smav } else { 1153198708Smav PROBE_SET_ACTION(softc, PROBE_INQUIRY); 1154195534Sscottl } 1155198708Smav xpt_release_ccb(done_ccb); 1156198708Smav xpt_schedule(periph, priority); 1157249466Smav goto out; 1158198708Smav case PROBE_SET_MULTI: 1159198708Smav if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 1160198708Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1161198748Smav xpt_acquire_device(path->device); 1162198708Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1163198708Smav xpt_action(done_ccb); 1164249466Smav xpt_async(AC_FOUND_DEVICE, path, done_ccb); 1165198708Smav } 1166236613Smav PROBE_SET_ACTION(softc, PROBE_DONE); 1167198708Smav break; 1168195534Sscottl case PROBE_INQUIRY: 1169195534Sscottl case PROBE_FULL_INQUIRY: 1170195534Sscottl { 1171198708Smav u_int8_t periph_qual, len; 1172195534Sscottl 1173198708Smav path->device->flags |= CAM_DEV_INQUIRY_DATA_VALID; 1174195534Sscottl 1175198708Smav periph_qual = SID_QUAL(inq_buf); 1176195534Sscottl 1177287289Smav if (periph_qual != SID_QUAL_LU_CONNECTED && 1178287289Smav periph_qual != SID_QUAL_LU_OFFLINE) 1179198708Smav break; 1180195534Sscottl 1181198708Smav /* 1182198708Smav * We conservatively request only 1183198708Smav * SHORT_INQUIRY_LEN bytes of inquiry 1184198708Smav * information during our first try 1185198708Smav * at sending an INQUIRY. If the device 1186198708Smav * has more information to give, 1187198708Smav * perform a second request specifying 1188198708Smav * the amount of information the device 1189198708Smav * is willing to give. 1190198708Smav */ 1191198708Smav len = inq_buf->additional_length 1192198708Smav + offsetof(struct scsi_inquiry_data, additional_length) + 1; 1193198708Smav if (softc->action == PROBE_INQUIRY 1194198708Smav && len > SHORT_INQUIRY_LENGTH) { 1195198708Smav PROBE_SET_ACTION(softc, PROBE_FULL_INQUIRY); 1196198708Smav xpt_release_ccb(done_ccb); 1197198708Smav xpt_schedule(periph, priority); 1198249466Smav goto out; 1199195534Sscottl } 1200198708Smav 1201198708Smav ata_device_transport(path); 1202198708Smav if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 1203198708Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1204198748Smav xpt_acquire_device(path->device); 1205198708Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1206198708Smav xpt_action(done_ccb); 1207249466Smav xpt_async(AC_FOUND_DEVICE, path, done_ccb); 1208198708Smav } 1209236613Smav PROBE_SET_ACTION(softc, PROBE_DONE); 1210198708Smav break; 1211195534Sscottl } 1212195534Sscottl case PROBE_PM_PID: 1213198708Smav if ((path->device->flags & CAM_DEV_IDENTIFY_DATA_VALID) == 0) 1214198708Smav bzero(ident_buf, sizeof(*ident_buf)); 1215198708Smav softc->pm_pid = (done_ccb->ataio.res.lba_high << 24) + 1216198708Smav (done_ccb->ataio.res.lba_mid << 16) + 1217198708Smav (done_ccb->ataio.res.lba_low << 8) + 1218198708Smav done_ccb->ataio.res.sector_count; 1219198708Smav ((uint32_t *)ident_buf)[0] = softc->pm_pid; 1220198708Smav snprintf(ident_buf->model, sizeof(ident_buf->model), 1221198708Smav "Port Multiplier %08x", softc->pm_pid); 1222198708Smav PROBE_SET_ACTION(softc, PROBE_PM_PRV); 1223198708Smav xpt_release_ccb(done_ccb); 1224198708Smav xpt_schedule(periph, priority); 1225249466Smav goto out; 1226195534Sscottl case PROBE_PM_PRV: 1227198708Smav softc->pm_prv = (done_ccb->ataio.res.lba_high << 24) + 1228198708Smav (done_ccb->ataio.res.lba_mid << 16) + 1229198708Smav (done_ccb->ataio.res.lba_low << 8) + 1230198708Smav done_ccb->ataio.res.sector_count; 1231198708Smav ((uint32_t *)ident_buf)[1] = softc->pm_prv; 1232198708Smav snprintf(ident_buf->revision, sizeof(ident_buf->revision), 1233198708Smav "%04x", softc->pm_prv); 1234198708Smav path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 1235236666Smav ata_device_transport(path); 1236236666Smav if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) 1237236666Smav proberequestdefaultnegotiation(periph); 1238207499Smav /* Set supported bits. */ 1239207499Smav bzero(&cts, sizeof(cts)); 1240207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1241207499Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1242207499Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 1243207499Smav xpt_action((union ccb *)&cts); 1244207499Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1245207499Smav caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H; 1246207499Smav else 1247207499Smav caps = 0; 1248207499Smav /* All PMPs must support PM requests. */ 1249207499Smav caps |= CTS_SATA_CAPS_D_PMREQ; 1250207499Smav /* Mask unwanted bits. */ 1251207499Smav bzero(&cts, sizeof(cts)); 1252207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1253207499Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1254207499Smav cts.type = CTS_TYPE_USER_SETTINGS; 1255207499Smav xpt_action((union ccb *)&cts); 1256207499Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1257207499Smav caps &= cts.xport_specific.sata.caps; 1258215454Smav else 1259215454Smav caps = 0; 1260249199Smarius /* Remember what transport thinks about AEN. */ 1261350805Smav oif = path->device->inq_flags; 1262270327Simp if ((caps & CTS_SATA_CAPS_H_AN) && path->device->protocol != PROTO_ATA) 1263249199Smarius path->device->inq_flags |= SID_AEN; 1264249199Smarius else 1265249199Smarius path->device->inq_flags &= ~SID_AEN; 1266207499Smav /* Store result to SIM. */ 1267207499Smav bzero(&cts, sizeof(cts)); 1268207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1269207499Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1270207499Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 1271207499Smav cts.xport_specific.sata.caps = caps; 1272207499Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS; 1273207499Smav xpt_action((union ccb *)&cts); 1274207499Smav softc->caps = caps; 1275198708Smav if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 1276198708Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1277198748Smav xpt_acquire_device(path->device); 1278198708Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1279198708Smav xpt_action(done_ccb); 1280249466Smav xpt_async(AC_FOUND_DEVICE, path, done_ccb); 1281198708Smav } else { 1282350805Smav if (path->device->inq_flags != oif) 1283350805Smav xpt_async(AC_GETDEV_CHANGED, path, NULL); 1284198708Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1285198708Smav xpt_action(done_ccb); 1286249466Smav xpt_async(AC_SCSI_AEN, path, done_ccb); 1287195534Sscottl } 1288236613Smav PROBE_SET_ACTION(softc, PROBE_DONE); 1289198708Smav break; 1290235897Smav case PROBE_IDENTIFY_SES: 1291235897Smav case PROBE_IDENTIFY_SAFTE: 1292235897Smav if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) { 1293235897Smav /* Check that it is the same device. */ 1294235897Smav if (bcmp(&softc->ident_data, ident_buf, 53)) { 1295235897Smav /* Device changed. */ 1296350805Smav changed = 2; 1297235897Smav xpt_async(AC_LOST_DEVICE, path, NULL); 1298235897Smav } else { 1299235897Smav bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 1300235897Smav changed = 0; 1301235897Smav } 1302350805Smav } else 1303350805Smav changed = 2; 1304235897Smav if (changed) { 1305235897Smav bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 1306235897Smav /* Clean up from previous instance of this device */ 1307235897Smav if (path->device->device_id != NULL) { 1308235897Smav free(path->device->device_id, M_CAMXPT); 1309235897Smav path->device->device_id = NULL; 1310235897Smav path->device->device_id_len = 0; 1311235897Smav } 1312235897Smav path->device->device_id = 1313235897Smav malloc(16, M_CAMXPT, M_NOWAIT); 1314235897Smav if (path->device->device_id != NULL) { 1315235897Smav path->device->device_id_len = 16; 1316235897Smav bcopy(&fake_device_id_hdr, 1317235897Smav path->device->device_id, 8); 1318235897Smav bcopy(((uint8_t*)ident_buf) + 2, 1319235897Smav path->device->device_id + 8, 8); 1320235897Smav } 1321235897Smav 1322235897Smav path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 1323235897Smav } 1324236666Smav ata_device_transport(path); 1325236666Smav if (changed) 1326236666Smav proberequestdefaultnegotiation(periph); 1327235897Smav 1328235897Smav if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 1329235897Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1330235897Smav xpt_acquire_device(path->device); 1331235897Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1332235897Smav xpt_action(done_ccb); 1333249466Smav xpt_async(AC_FOUND_DEVICE, path, done_ccb); 1334235897Smav } 1335236613Smav PROBE_SET_ACTION(softc, PROBE_DONE); 1336235897Smav break; 1337195534Sscottl default: 1338236613Smav panic("probedone: invalid action state 0x%x\n", softc->action); 1339195534Sscottl } 1340198708Smavdone: 1341203108Smav if (softc->restart) { 1342203108Smav softc->restart = 0; 1343203108Smav xpt_release_ccb(done_ccb); 1344195534Sscottl probeschedule(periph); 1345249466Smav goto out; 1346195534Sscottl } 1347203108Smav xpt_release_ccb(done_ccb); 1348236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe completed\n")); 1349203108Smav while ((done_ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs))) { 1350203108Smav TAILQ_REMOVE(&softc->request_ccbs, 1351203108Smav &done_ccb->ccb_h, periph_links.tqe); 1352203108Smav done_ccb->ccb_h.status = found ? CAM_REQ_CMP : CAM_REQ_CMP_ERR; 1353203108Smav xpt_done(done_ccb); 1354203108Smav } 1355249466Smav /* Drop freeze taken due to CAM_DEV_QFREEZE flag set. */ 1356249466Smav cam_release_devq(path, 0, 0, 0, FALSE); 1357236228Smav cam_periph_invalidate(periph); 1358203108Smav cam_periph_release_locked(periph); 1359195534Sscottl} 1360195534Sscottl 1361195534Sscottlstatic void 1362195534Sscottlprobecleanup(struct cam_periph *periph) 1363195534Sscottl{ 1364195534Sscottl free(periph->softc, M_CAMXPT); 1365195534Sscottl} 1366195534Sscottl 1367195534Sscottlstatic void 1368199178Smavata_find_quirk(struct cam_ed *device) 1369195534Sscottl{ 1370199178Smav struct ata_quirk_entry *quirk; 1371195534Sscottl caddr_t match; 1372195534Sscottl 1373199178Smav match = cam_quirkmatch((caddr_t)&device->ident_data, 1374199178Smav (caddr_t)ata_quirk_table, 1375298411Spfg nitems(ata_quirk_table), 1376199178Smav sizeof(*ata_quirk_table), ata_identify_match); 1377195534Sscottl 1378195534Sscottl if (match == NULL) 1379195534Sscottl panic("xpt_find_quirk: device didn't match wildcard entry!!"); 1380195534Sscottl 1381199178Smav quirk = (struct ata_quirk_entry *)match; 1382195534Sscottl device->quirk = quirk; 1383236234Smav if (quirk->quirks & CAM_QUIRK_MAXTAGS) { 1384236234Smav device->mintags = quirk->mintags; 1385236234Smav device->maxtags = quirk->maxtags; 1386236234Smav } 1387195534Sscottl} 1388195534Sscottl 1389195534Sscottltypedef struct { 1390195534Sscottl union ccb *request_ccb; 1391195534Sscottl struct ccb_pathinq *cpi; 1392195534Sscottl int counter; 1393195534Sscottl} ata_scan_bus_info; 1394195534Sscottl 1395195534Sscottl/* 1396195534Sscottl * To start a scan, request_ccb is an XPT_SCAN_BUS ccb. 1397195534Sscottl * As the scan progresses, xpt_scan_bus is used as the 1398195534Sscottl * callback on completion function. 1399195534Sscottl */ 1400195534Sscottlstatic void 1401195534Sscottlata_scan_bus(struct cam_periph *periph, union ccb *request_ccb) 1402195534Sscottl{ 1403195534Sscottl struct cam_path *path; 1404195534Sscottl ata_scan_bus_info *scan_info; 1405203108Smav union ccb *work_ccb, *reset_ccb; 1406256843Smav struct mtx *mtx; 1407195534Sscottl cam_status status; 1408195534Sscottl 1409195534Sscottl CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE, 1410195534Sscottl ("xpt_scan_bus\n")); 1411195534Sscottl switch (request_ccb->ccb_h.func_code) { 1412195534Sscottl case XPT_SCAN_BUS: 1413208582Smjacob case XPT_SCAN_TGT: 1414195534Sscottl /* Find out the characteristics of the bus */ 1415195534Sscottl work_ccb = xpt_alloc_ccb_nowait(); 1416195534Sscottl if (work_ccb == NULL) { 1417195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1418195534Sscottl xpt_done(request_ccb); 1419195534Sscottl return; 1420195534Sscottl } 1421350804Smav xpt_path_inq(&work_ccb->cpi, request_ccb->ccb_h.path); 1422195534Sscottl if (work_ccb->ccb_h.status != CAM_REQ_CMP) { 1423195534Sscottl request_ccb->ccb_h.status = work_ccb->ccb_h.status; 1424195534Sscottl xpt_free_ccb(work_ccb); 1425195534Sscottl xpt_done(request_ccb); 1426195534Sscottl return; 1427195534Sscottl } 1428195534Sscottl 1429203108Smav /* We may need to reset bus first, if we haven't done it yet. */ 1430203108Smav if ((work_ccb->cpi.hba_inquiry & 1431203108Smav (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE)) && 1432203108Smav !(work_ccb->cpi.hba_misc & PIM_NOBUSRESET) && 1433203108Smav !timevalisset(&request_ccb->ccb_h.path->bus->last_reset)) { 1434203108Smav reset_ccb = xpt_alloc_ccb_nowait(); 1435208823Smav if (reset_ccb == NULL) { 1436208823Smav request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1437208823Smav xpt_free_ccb(work_ccb); 1438208823Smav xpt_done(request_ccb); 1439208823Smav return; 1440208823Smav } 1441203108Smav xpt_setup_ccb(&reset_ccb->ccb_h, request_ccb->ccb_h.path, 1442203108Smav CAM_PRIORITY_NONE); 1443203108Smav reset_ccb->ccb_h.func_code = XPT_RESET_BUS; 1444203108Smav xpt_action(reset_ccb); 1445203108Smav if (reset_ccb->ccb_h.status != CAM_REQ_CMP) { 1446203108Smav request_ccb->ccb_h.status = reset_ccb->ccb_h.status; 1447203108Smav xpt_free_ccb(reset_ccb); 1448203108Smav xpt_free_ccb(work_ccb); 1449203108Smav xpt_done(request_ccb); 1450203108Smav return; 1451203108Smav } 1452203108Smav xpt_free_ccb(reset_ccb); 1453203108Smav } 1454203108Smav 1455195534Sscottl /* Save some state for use while we probe for devices */ 1456195534Sscottl scan_info = (ata_scan_bus_info *) 1457195534Sscottl malloc(sizeof(ata_scan_bus_info), M_CAMXPT, M_NOWAIT); 1458195534Sscottl if (scan_info == NULL) { 1459195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1460208823Smav xpt_free_ccb(work_ccb); 1461195534Sscottl xpt_done(request_ccb); 1462195534Sscottl return; 1463195534Sscottl } 1464195534Sscottl scan_info->request_ccb = request_ccb; 1465195534Sscottl scan_info->cpi = &work_ccb->cpi; 1466195534Sscottl /* If PM supported, probe it first. */ 1467195534Sscottl if (scan_info->cpi->hba_inquiry & PI_SATAPM) 1468201990Smav scan_info->counter = scan_info->cpi->max_target; 1469201990Smav else 1470201990Smav scan_info->counter = 0; 1471195534Sscottl 1472195534Sscottl work_ccb = xpt_alloc_ccb_nowait(); 1473195534Sscottl if (work_ccb == NULL) { 1474195534Sscottl free(scan_info, M_CAMXPT); 1475195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1476195534Sscottl xpt_done(request_ccb); 1477195534Sscottl break; 1478195534Sscottl } 1479256843Smav mtx = xpt_path_mtx(scan_info->request_ccb->ccb_h.path); 1480195534Sscottl goto scan_next; 1481195534Sscottl case XPT_SCAN_LUN: 1482195534Sscottl work_ccb = request_ccb; 1483195534Sscottl /* Reuse the same CCB to query if a device was really found */ 1484195534Sscottl scan_info = (ata_scan_bus_info *)work_ccb->ccb_h.ppriv_ptr0; 1485256843Smav mtx = xpt_path_mtx(scan_info->request_ccb->ccb_h.path); 1486256843Smav mtx_lock(mtx); 1487198389Smav /* If there is PMP... */ 1488201990Smav if ((scan_info->cpi->hba_inquiry & PI_SATAPM) && 1489201990Smav (scan_info->counter == scan_info->cpi->max_target)) { 1490203108Smav if (work_ccb->ccb_h.status == CAM_REQ_CMP) { 1491207428Smav /* everything else will be probed by it */ 1492207428Smav /* Free the current request path- we're done with it. */ 1493207428Smav xpt_free_path(work_ccb->ccb_h.path); 1494201990Smav goto done; 1495195534Sscottl } else { 1496195534Sscottl struct ccb_trans_settings cts; 1497195534Sscottl 1498195534Sscottl /* Report SIM that PM is absent. */ 1499195534Sscottl bzero(&cts, sizeof(cts)); 1500195534Sscottl xpt_setup_ccb(&cts.ccb_h, 1501207428Smav work_ccb->ccb_h.path, CAM_PRIORITY_NONE); 1502195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1503195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 1504195665Smav cts.xport_specific.sata.pm_present = 0; 1505195534Sscottl cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; 1506195534Sscottl xpt_action((union ccb *)&cts); 1507195534Sscottl } 1508195534Sscottl } 1509207428Smav /* Free the current request path- we're done with it. */ 1510207428Smav xpt_free_path(work_ccb->ccb_h.path); 1511201990Smav if (scan_info->counter == 1512201990Smav ((scan_info->cpi->hba_inquiry & PI_SATAPM) ? 1513201990Smav 0 : scan_info->cpi->max_target)) { 1514201990Smavdone: 1515256843Smav mtx_unlock(mtx); 1516195534Sscottl xpt_free_ccb(work_ccb); 1517195534Sscottl xpt_free_ccb((union ccb *)scan_info->cpi); 1518195534Sscottl request_ccb = scan_info->request_ccb; 1519195534Sscottl free(scan_info, M_CAMXPT); 1520195534Sscottl request_ccb->ccb_h.status = CAM_REQ_CMP; 1521195534Sscottl xpt_done(request_ccb); 1522195534Sscottl break; 1523195534Sscottl } 1524201990Smav /* Take next device. Wrap from max (PMP) to 0. */ 1525201990Smav scan_info->counter = (scan_info->counter + 1 ) % 1526201990Smav (scan_info->cpi->max_target + 1); 1527195534Sscottlscan_next: 1528249468Smav status = xpt_create_path(&path, NULL, 1529195534Sscottl scan_info->request_ccb->ccb_h.path_id, 1530195534Sscottl scan_info->counter, 0); 1531195534Sscottl if (status != CAM_REQ_CMP) { 1532256843Smav if (request_ccb->ccb_h.func_code == XPT_SCAN_LUN) 1533256843Smav mtx_unlock(mtx); 1534195534Sscottl printf("xpt_scan_bus: xpt_create_path failed" 1535195534Sscottl " with status %#x, bus scan halted\n", 1536195534Sscottl status); 1537195534Sscottl xpt_free_ccb(work_ccb); 1538195534Sscottl xpt_free_ccb((union ccb *)scan_info->cpi); 1539195534Sscottl request_ccb = scan_info->request_ccb; 1540195534Sscottl free(scan_info, M_CAMXPT); 1541195534Sscottl request_ccb->ccb_h.status = status; 1542195534Sscottl xpt_done(request_ccb); 1543195534Sscottl break; 1544195534Sscottl } 1545195534Sscottl xpt_setup_ccb(&work_ccb->ccb_h, path, 1546195534Sscottl scan_info->request_ccb->ccb_h.pinfo.priority); 1547195534Sscottl work_ccb->ccb_h.func_code = XPT_SCAN_LUN; 1548195534Sscottl work_ccb->ccb_h.cbfcnp = ata_scan_bus; 1549256843Smav work_ccb->ccb_h.flags |= CAM_UNLOCKED; 1550195534Sscottl work_ccb->ccb_h.ppriv_ptr0 = scan_info; 1551195534Sscottl work_ccb->crcn.flags = scan_info->request_ccb->crcn.flags; 1552256843Smav mtx_unlock(mtx); 1553256843Smav if (request_ccb->ccb_h.func_code == XPT_SCAN_LUN) 1554256843Smav mtx = NULL; 1555195534Sscottl xpt_action(work_ccb); 1556256843Smav if (mtx != NULL) 1557256843Smav mtx_lock(mtx); 1558195534Sscottl break; 1559195534Sscottl default: 1560195534Sscottl break; 1561195534Sscottl } 1562195534Sscottl} 1563195534Sscottl 1564195534Sscottlstatic void 1565195534Sscottlata_scan_lun(struct cam_periph *periph, struct cam_path *path, 1566195534Sscottl cam_flags flags, union ccb *request_ccb) 1567195534Sscottl{ 1568195534Sscottl struct ccb_pathinq cpi; 1569195534Sscottl cam_status status; 1570195534Sscottl struct cam_path *new_path; 1571195534Sscottl struct cam_periph *old_periph; 1572256843Smav int lock; 1573195534Sscottl 1574203108Smav CAM_DEBUG(path, CAM_DEBUG_TRACE, ("xpt_scan_lun\n")); 1575195534Sscottl 1576350804Smav xpt_path_inq(&cpi, path); 1577195534Sscottl if (cpi.ccb_h.status != CAM_REQ_CMP) { 1578195534Sscottl if (request_ccb != NULL) { 1579195534Sscottl request_ccb->ccb_h.status = cpi.ccb_h.status; 1580195534Sscottl xpt_done(request_ccb); 1581195534Sscottl } 1582195534Sscottl return; 1583195534Sscottl } 1584195534Sscottl 1585195534Sscottl if (request_ccb == NULL) { 1586241455Smav request_ccb = xpt_alloc_ccb_nowait(); 1587195534Sscottl if (request_ccb == NULL) { 1588195534Sscottl xpt_print(path, "xpt_scan_lun: can't allocate CCB, " 1589195534Sscottl "can't continue\n"); 1590195534Sscottl return; 1591195534Sscottl } 1592249468Smav status = xpt_create_path(&new_path, NULL, 1593195534Sscottl path->bus->path_id, 1594195534Sscottl path->target->target_id, 1595195534Sscottl path->device->lun_id); 1596195534Sscottl if (status != CAM_REQ_CMP) { 1597241455Smav xpt_print(path, "xpt_scan_lun: can't create path, " 1598195534Sscottl "can't continue\n"); 1599241455Smav xpt_free_ccb(request_ccb); 1600195534Sscottl return; 1601195534Sscottl } 1602203108Smav xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_XPT); 1603195534Sscottl request_ccb->ccb_h.cbfcnp = xptscandone; 1604256843Smav request_ccb->ccb_h.flags |= CAM_UNLOCKED; 1605195534Sscottl request_ccb->ccb_h.func_code = XPT_SCAN_LUN; 1606195534Sscottl request_ccb->crcn.flags = flags; 1607195534Sscottl } 1608195534Sscottl 1609256843Smav lock = (xpt_path_owned(path) == 0); 1610256843Smav if (lock) 1611256843Smav xpt_path_lock(path); 1612195653Smav if ((old_periph = cam_periph_find(path, "aprobe")) != NULL) { 1613236228Smav if ((old_periph->flags & CAM_PERIPH_INVALID) == 0) { 1614236228Smav probe_softc *softc; 1615195534Sscottl 1616236228Smav softc = (probe_softc *)old_periph->softc; 1617236228Smav TAILQ_INSERT_TAIL(&softc->request_ccbs, 1618236228Smav &request_ccb->ccb_h, periph_links.tqe); 1619236228Smav softc->restart = 1; 1620236228Smav } else { 1621236228Smav request_ccb->ccb_h.status = CAM_REQ_CMP_ERR; 1622236228Smav xpt_done(request_ccb); 1623236228Smav } 1624195534Sscottl } else { 1625195534Sscottl status = cam_periph_alloc(proberegister, NULL, probecleanup, 1626195653Smav probestart, "aprobe", 1627195534Sscottl CAM_PERIPH_BIO, 1628195534Sscottl request_ccb->ccb_h.path, NULL, 0, 1629195534Sscottl request_ccb); 1630195534Sscottl 1631195534Sscottl if (status != CAM_REQ_CMP) { 1632195534Sscottl xpt_print(path, "xpt_scan_lun: cam_alloc_periph " 1633195534Sscottl "returned an error, can't continue probe\n"); 1634195534Sscottl request_ccb->ccb_h.status = status; 1635195534Sscottl xpt_done(request_ccb); 1636195534Sscottl } 1637195534Sscottl } 1638256843Smav if (lock) 1639256843Smav xpt_path_unlock(path); 1640195534Sscottl} 1641195534Sscottl 1642195534Sscottlstatic void 1643195534Sscottlxptscandone(struct cam_periph *periph, union ccb *done_ccb) 1644195534Sscottl{ 1645241455Smav 1646241455Smav xpt_free_path(done_ccb->ccb_h.path); 1647241455Smav xpt_free_ccb(done_ccb); 1648195534Sscottl} 1649195534Sscottl 1650195534Sscottlstatic struct cam_ed * 1651195534Sscottlata_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id) 1652195534Sscottl{ 1653199178Smav struct ata_quirk_entry *quirk; 1654195534Sscottl struct cam_ed *device; 1655195534Sscottl 1656195534Sscottl device = xpt_alloc_device(bus, target, lun_id); 1657195534Sscottl if (device == NULL) 1658195534Sscottl return (NULL); 1659195534Sscottl 1660195534Sscottl /* 1661195534Sscottl * Take the default quirk entry until we have inquiry 1662195534Sscottl * data and can determine a better quirk to use. 1663195534Sscottl */ 1664298411Spfg quirk = &ata_quirk_table[nitems(ata_quirk_table) - 1]; 1665195534Sscottl device->quirk = (void *)quirk; 1666199178Smav device->mintags = 0; 1667199178Smav device->maxtags = 0; 1668195534Sscottl bzero(&device->inq_data, sizeof(device->inq_data)); 1669195534Sscottl device->inq_flags = 0; 1670195534Sscottl device->queue_flags = 0; 1671195534Sscottl device->serial_num = NULL; 1672195534Sscottl device->serial_num_len = 0; 1673195534Sscottl return (device); 1674195534Sscottl} 1675195534Sscottl 1676195534Sscottlstatic void 1677195534Sscottlata_device_transport(struct cam_path *path) 1678195534Sscottl{ 1679195534Sscottl struct ccb_pathinq cpi; 1680198331Smav struct ccb_trans_settings cts; 1681198331Smav struct scsi_inquiry_data *inq_buf = NULL; 1682198331Smav struct ata_params *ident_buf = NULL; 1683195534Sscottl 1684195534Sscottl /* Get transport information from the SIM */ 1685350804Smav xpt_path_inq(&cpi, path); 1686195534Sscottl 1687195534Sscottl path->device->transport = cpi.transport; 1688198331Smav if ((path->device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0) 1689198331Smav inq_buf = &path->device->inq_data; 1690198331Smav if ((path->device->flags & CAM_DEV_IDENTIFY_DATA_VALID) != 0) 1691198331Smav ident_buf = &path->device->ident_data; 1692198331Smav if (path->device->protocol == PROTO_ATA) { 1693198331Smav path->device->protocol_version = ident_buf ? 1694198331Smav ata_version(ident_buf->version_major) : cpi.protocol_version; 1695198331Smav } else if (path->device->protocol == PROTO_SCSI) { 1696198331Smav path->device->protocol_version = inq_buf ? 1697198331Smav SID_ANSI_REV(inq_buf) : cpi.protocol_version; 1698195534Sscottl } 1699198331Smav path->device->transport_version = ident_buf ? 1700198331Smav ata_version(ident_buf->version_major) : cpi.transport_version; 1701195534Sscottl 1702195534Sscottl /* Tell the controller what we think */ 1703203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1704195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1705195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 1706195534Sscottl cts.transport = path->device->transport; 1707195534Sscottl cts.transport_version = path->device->transport_version; 1708195534Sscottl cts.protocol = path->device->protocol; 1709195534Sscottl cts.protocol_version = path->device->protocol_version; 1710195534Sscottl cts.proto_specific.valid = 0; 1711203376Smav if (ident_buf) { 1712203376Smav if (path->device->transport == XPORT_ATA) { 1713223019Smav cts.xport_specific.ata.atapi = 1714223019Smav (ident_buf->config == ATA_PROTO_CFA) ? 0 : 1715203376Smav ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_16) ? 16 : 1716203376Smav ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) ? 12 : 0; 1717203376Smav cts.xport_specific.ata.valid = CTS_ATA_VALID_ATAPI; 1718203376Smav } else { 1719223019Smav cts.xport_specific.sata.atapi = 1720223019Smav (ident_buf->config == ATA_PROTO_CFA) ? 0 : 1721203376Smav ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_16) ? 16 : 1722203376Smav ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) ? 12 : 0; 1723203376Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_ATAPI; 1724203376Smav } 1725203376Smav } else 1726203376Smav cts.xport_specific.valid = 0; 1727195534Sscottl xpt_action((union ccb *)&cts); 1728195534Sscottl} 1729195534Sscottl 1730195534Sscottlstatic void 1731223443Swillata_dev_advinfo(union ccb *start_ccb) 1732223443Swill{ 1733223443Swill struct cam_ed *device; 1734223443Swill struct ccb_dev_advinfo *cdai; 1735351754Smav off_t amt; 1736223443Swill 1737351754Smav xpt_path_assert(start_ccb->ccb_h.path, MA_OWNED); 1738223443Swill start_ccb->ccb_h.status = CAM_REQ_INVALID; 1739223443Swill device = start_ccb->ccb_h.path->device; 1740223443Swill cdai = &start_ccb->cdai; 1741223443Swill switch(cdai->buftype) { 1742235897Smav case CDAI_TYPE_SCSI_DEVID: 1743235897Smav if (cdai->flags & CDAI_FLAG_STORE) 1744235897Smav return; 1745235897Smav cdai->provsiz = device->device_id_len; 1746235897Smav if (device->device_id_len == 0) 1747235897Smav break; 1748235897Smav amt = device->device_id_len; 1749235897Smav if (cdai->provsiz > cdai->bufsiz) 1750235897Smav amt = cdai->bufsiz; 1751235897Smav memcpy(cdai->buf, device->device_id, amt); 1752235897Smav break; 1753223443Swill case CDAI_TYPE_SERIAL_NUM: 1754223443Swill if (cdai->flags & CDAI_FLAG_STORE) 1755235897Smav return; 1756223443Swill cdai->provsiz = device->serial_num_len; 1757223443Swill if (device->serial_num_len == 0) 1758223443Swill break; 1759223443Swill amt = device->serial_num_len; 1760223443Swill if (cdai->provsiz > cdai->bufsiz) 1761223443Swill amt = cdai->bufsiz; 1762223443Swill memcpy(cdai->buf, device->serial_num, amt); 1763223443Swill break; 1764235897Smav case CDAI_TYPE_PHYS_PATH: 1765235897Smav if (cdai->flags & CDAI_FLAG_STORE) { 1766235897Smav if (device->physpath != NULL) 1767235897Smav free(device->physpath, M_CAMXPT); 1768235897Smav device->physpath_len = cdai->bufsiz; 1769235897Smav /* Clear existing buffer if zero length */ 1770235897Smav if (cdai->bufsiz == 0) 1771235897Smav break; 1772235897Smav device->physpath = malloc(cdai->bufsiz, M_CAMXPT, M_NOWAIT); 1773235897Smav if (device->physpath == NULL) { 1774235897Smav start_ccb->ccb_h.status = CAM_REQ_ABORTED; 1775235897Smav return; 1776235897Smav } 1777235897Smav memcpy(device->physpath, cdai->buf, cdai->bufsiz); 1778235897Smav } else { 1779235897Smav cdai->provsiz = device->physpath_len; 1780235897Smav if (device->physpath_len == 0) 1781235897Smav break; 1782235897Smav amt = device->physpath_len; 1783235897Smav if (cdai->provsiz > cdai->bufsiz) 1784235897Smav amt = cdai->bufsiz; 1785235897Smav memcpy(cdai->buf, device->physpath, amt); 1786235897Smav } 1787235897Smav break; 1788223443Swill default: 1789235897Smav return; 1790223443Swill } 1791235897Smav start_ccb->ccb_h.status = CAM_REQ_CMP; 1792235897Smav 1793235897Smav if (cdai->flags & CDAI_FLAG_STORE) { 1794235897Smav xpt_async(AC_ADVINFO_CHANGED, start_ccb->ccb_h.path, 1795235897Smav (void *)(uintptr_t)cdai->buftype); 1796235897Smav } 1797223443Swill} 1798223443Swill 1799223443Swillstatic void 1800195534Sscottlata_action(union ccb *start_ccb) 1801195534Sscottl{ 1802195534Sscottl 1803195534Sscottl switch (start_ccb->ccb_h.func_code) { 1804195534Sscottl case XPT_SET_TRAN_SETTINGS: 1805195534Sscottl { 1806199178Smav ata_set_transfer_settings(&start_ccb->cts, 1807256843Smav start_ccb->ccb_h.path, 1808195534Sscottl /*async_update*/FALSE); 1809195534Sscottl break; 1810195534Sscottl } 1811195534Sscottl case XPT_SCAN_BUS: 1812208582Smjacob case XPT_SCAN_TGT: 1813195534Sscottl ata_scan_bus(start_ccb->ccb_h.path->periph, start_ccb); 1814195534Sscottl break; 1815195534Sscottl case XPT_SCAN_LUN: 1816195534Sscottl ata_scan_lun(start_ccb->ccb_h.path->periph, 1817195534Sscottl start_ccb->ccb_h.path, start_ccb->crcn.flags, 1818195534Sscottl start_ccb); 1819195534Sscottl break; 1820195534Sscottl case XPT_GET_TRAN_SETTINGS: 1821195534Sscottl { 1822236437Smav ata_get_transfer_settings(&start_ccb->cts); 1823195534Sscottl break; 1824195534Sscottl } 1825203376Smav case XPT_SCSI_IO: 1826203376Smav { 1827203376Smav struct cam_ed *device; 1828203376Smav u_int maxlen = 0; 1829203376Smav 1830203376Smav device = start_ccb->ccb_h.path->device; 1831203376Smav if (device->protocol == PROTO_SCSI && 1832203376Smav (device->flags & CAM_DEV_IDENTIFY_DATA_VALID)) { 1833203376Smav uint16_t p = 1834203376Smav device->ident_data.config & ATA_PROTO_MASK; 1835203376Smav 1836223019Smav maxlen = 1837223019Smav (device->ident_data.config == ATA_PROTO_CFA) ? 0 : 1838223019Smav (p == ATA_PROTO_ATAPI_16) ? 16 : 1839203376Smav (p == ATA_PROTO_ATAPI_12) ? 12 : 0; 1840203376Smav } 1841203376Smav if (start_ccb->csio.cdb_len > maxlen) { 1842203376Smav start_ccb->ccb_h.status = CAM_REQ_INVALID; 1843203376Smav xpt_done(start_ccb); 1844203376Smav break; 1845203376Smav } 1846223475Smav xpt_action_default(start_ccb); 1847223475Smav break; 1848203376Smav } 1849223443Swill case XPT_DEV_ADVINFO: 1850223443Swill { 1851223443Swill ata_dev_advinfo(start_ccb); 1852223443Swill break; 1853223443Swill } 1854195534Sscottl default: 1855195534Sscottl xpt_action_default(start_ccb); 1856195534Sscottl break; 1857195534Sscottl } 1858195534Sscottl} 1859195534Sscottl 1860195534Sscottlstatic void 1861236437Smavata_get_transfer_settings(struct ccb_trans_settings *cts) 1862236437Smav{ 1863236437Smav struct ccb_trans_settings_ata *ata; 1864236437Smav struct ccb_trans_settings_scsi *scsi; 1865236437Smav struct cam_ed *device; 1866236437Smav 1867236437Smav device = cts->ccb_h.path->device; 1868256843Smav xpt_action_default((union ccb *)cts); 1869236437Smav 1870236666Smav if (cts->protocol == PROTO_UNKNOWN || 1871236666Smav cts->protocol == PROTO_UNSPECIFIED) { 1872236666Smav cts->protocol = device->protocol; 1873236666Smav cts->protocol_version = device->protocol_version; 1874236666Smav } 1875236666Smav 1876236437Smav if (cts->protocol == PROTO_ATA) { 1877236437Smav ata = &cts->proto_specific.ata; 1878236437Smav if ((ata->valid & CTS_ATA_VALID_TQ) == 0) { 1879236437Smav ata->valid |= CTS_ATA_VALID_TQ; 1880236437Smav if (cts->type == CTS_TYPE_USER_SETTINGS || 1881236437Smav (device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 || 1882236437Smav (device->inq_flags & SID_CmdQue) != 0) 1883236437Smav ata->flags |= CTS_ATA_FLAGS_TAG_ENB; 1884236437Smav } 1885236437Smav } 1886236437Smav if (cts->protocol == PROTO_SCSI) { 1887236437Smav scsi = &cts->proto_specific.scsi; 1888236437Smav if ((scsi->valid & CTS_SCSI_VALID_TQ) == 0) { 1889236437Smav scsi->valid |= CTS_SCSI_VALID_TQ; 1890236437Smav if (cts->type == CTS_TYPE_USER_SETTINGS || 1891236437Smav (device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 || 1892236437Smav (device->inq_flags & SID_CmdQue) != 0) 1893236437Smav scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 1894236437Smav } 1895236437Smav } 1896236666Smav 1897236666Smav if (cts->transport == XPORT_UNKNOWN || 1898236666Smav cts->transport == XPORT_UNSPECIFIED) { 1899236666Smav cts->transport = device->transport; 1900236666Smav cts->transport_version = device->transport_version; 1901236666Smav } 1902236437Smav} 1903236437Smav 1904236437Smavstatic void 1905256843Smavata_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_path *path, 1906195534Sscottl int async_update) 1907195534Sscottl{ 1908195534Sscottl struct ccb_pathinq cpi; 1909236437Smav struct ccb_trans_settings_ata *ata; 1910195534Sscottl struct ccb_trans_settings_scsi *scsi; 1911236437Smav struct ata_params *ident_data; 1912195534Sscottl struct scsi_inquiry_data *inq_data; 1913256843Smav struct cam_ed *device; 1914195534Sscottl 1915256843Smav if (path == NULL || (device = path->device) == NULL) { 1916195534Sscottl cts->ccb_h.status = CAM_PATH_INVALID; 1917195534Sscottl xpt_done((union ccb *)cts); 1918195534Sscottl return; 1919195534Sscottl } 1920195534Sscottl 1921195534Sscottl if (cts->protocol == PROTO_UNKNOWN 1922195534Sscottl || cts->protocol == PROTO_UNSPECIFIED) { 1923195534Sscottl cts->protocol = device->protocol; 1924195534Sscottl cts->protocol_version = device->protocol_version; 1925195534Sscottl } 1926195534Sscottl 1927195534Sscottl if (cts->protocol_version == PROTO_VERSION_UNKNOWN 1928195534Sscottl || cts->protocol_version == PROTO_VERSION_UNSPECIFIED) 1929195534Sscottl cts->protocol_version = device->protocol_version; 1930195534Sscottl 1931195534Sscottl if (cts->protocol != device->protocol) { 1932256843Smav xpt_print(path, "Uninitialized Protocol %x:%x?\n", 1933195534Sscottl cts->protocol, device->protocol); 1934195534Sscottl cts->protocol = device->protocol; 1935195534Sscottl } 1936195534Sscottl 1937195534Sscottl if (cts->protocol_version > device->protocol_version) { 1938195534Sscottl if (bootverbose) { 1939256843Smav xpt_print(path, "Down reving Protocol " 1940195534Sscottl "Version from %d to %d?\n", cts->protocol_version, 1941195534Sscottl device->protocol_version); 1942195534Sscottl } 1943195534Sscottl cts->protocol_version = device->protocol_version; 1944195534Sscottl } 1945195534Sscottl 1946195534Sscottl if (cts->transport == XPORT_UNKNOWN 1947195534Sscottl || cts->transport == XPORT_UNSPECIFIED) { 1948195534Sscottl cts->transport = device->transport; 1949195534Sscottl cts->transport_version = device->transport_version; 1950195534Sscottl } 1951195534Sscottl 1952195534Sscottl if (cts->transport_version == XPORT_VERSION_UNKNOWN 1953195534Sscottl || cts->transport_version == XPORT_VERSION_UNSPECIFIED) 1954195534Sscottl cts->transport_version = device->transport_version; 1955195534Sscottl 1956195534Sscottl if (cts->transport != device->transport) { 1957256843Smav xpt_print(path, "Uninitialized Transport %x:%x?\n", 1958195534Sscottl cts->transport, device->transport); 1959195534Sscottl cts->transport = device->transport; 1960195534Sscottl } 1961195534Sscottl 1962195534Sscottl if (cts->transport_version > device->transport_version) { 1963195534Sscottl if (bootverbose) { 1964256843Smav xpt_print(path, "Down reving Transport " 1965195534Sscottl "Version from %d to %d?\n", cts->transport_version, 1966195534Sscottl device->transport_version); 1967195534Sscottl } 1968195534Sscottl cts->transport_version = device->transport_version; 1969195534Sscottl } 1970195534Sscottl 1971236437Smav ident_data = &device->ident_data; 1972195534Sscottl inq_data = &device->inq_data; 1973236437Smav if (cts->protocol == PROTO_ATA) 1974236437Smav ata = &cts->proto_specific.ata; 1975236437Smav else 1976236437Smav ata = NULL; 1977236437Smav if (cts->protocol == PROTO_SCSI) 1978236437Smav scsi = &cts->proto_specific.scsi; 1979236437Smav else 1980236437Smav scsi = NULL; 1981350804Smav xpt_path_inq(&cpi, path); 1982195534Sscottl 1983236437Smav /* Sanity checking */ 1984195534Sscottl if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0 1985236437Smav || (ata && (ident_data->satacapabilities & ATA_SUPPORT_NCQ) == 0) 1986236437Smav || (scsi && (INQ_DATA_TQ_ENABLED(inq_data)) == 0) 1987195534Sscottl || (device->queue_flags & SCP_QUEUE_DQUE) != 0 1988195534Sscottl || (device->mintags == 0)) { 1989195534Sscottl /* 1990195534Sscottl * Can't tag on hardware that doesn't support tags, 1991195534Sscottl * doesn't have it enabled, or has broken tag support. 1992195534Sscottl */ 1993236437Smav if (ata) 1994236437Smav ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB; 1995236437Smav if (scsi) 1996195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 1997195534Sscottl } 1998195534Sscottl 1999236437Smav /* Start/stop tags use. */ 2000236437Smav if (cts->type == CTS_TYPE_CURRENT_SETTINGS && 2001236437Smav ((ata && (ata->valid & CTS_ATA_VALID_TQ) != 0) || 2002236437Smav (scsi && (scsi->valid & CTS_SCSI_VALID_TQ) != 0))) { 2003236437Smav int nowt, newt = 0; 2004195534Sscottl 2005236437Smav nowt = ((device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 || 2006236437Smav (device->inq_flags & SID_CmdQue) != 0); 2007236437Smav if (ata) 2008236437Smav newt = (ata->flags & CTS_ATA_FLAGS_TAG_ENB) != 0; 2009236437Smav if (scsi) 2010236437Smav newt = (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0; 2011195534Sscottl 2012236437Smav if (newt && !nowt) { 2013236437Smav /* 2014236437Smav * Delay change to use tags until after a 2015236437Smav * few commands have gone to this device so 2016236437Smav * the controller has time to perform transfer 2017236437Smav * negotiations without tagged messages getting 2018236437Smav * in the way. 2019236437Smav */ 2020236437Smav device->tag_delay_count = CAM_TAG_DELAY_COUNT; 2021236437Smav device->flags |= CAM_DEV_TAG_AFTER_COUNT; 2022236437Smav } else if (nowt && !newt) 2023256843Smav xpt_stop_tags(path); 2024236437Smav } 2025195534Sscottl 2026195534Sscottl if (async_update == FALSE) 2027256843Smav xpt_action_default((union ccb *)cts); 2028195534Sscottl} 2029195534Sscottl 2030195534Sscottl/* 2031195534Sscottl * Handle any per-device event notifications that require action by the XPT. 2032195534Sscottl */ 2033195534Sscottlstatic void 2034195534Sscottlata_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target, 2035195534Sscottl struct cam_ed *device, void *async_arg) 2036195534Sscottl{ 2037195534Sscottl cam_status status; 2038195534Sscottl struct cam_path newpath; 2039195534Sscottl 2040195534Sscottl /* 2041195534Sscottl * We only need to handle events for real devices. 2042195534Sscottl */ 2043195534Sscottl if (target->target_id == CAM_TARGET_WILDCARD 2044195534Sscottl || device->lun_id == CAM_LUN_WILDCARD) 2045195534Sscottl return; 2046195534Sscottl 2047195534Sscottl /* 2048195534Sscottl * We need our own path with wildcards expanded to 2049195534Sscottl * handle certain types of events. 2050195534Sscottl */ 2051195534Sscottl if ((async_code == AC_SENT_BDR) 2052195534Sscottl || (async_code == AC_BUS_RESET) 2053195534Sscottl || (async_code == AC_INQ_CHANGED)) 2054195534Sscottl status = xpt_compile_path(&newpath, NULL, 2055195534Sscottl bus->path_id, 2056195534Sscottl target->target_id, 2057195534Sscottl device->lun_id); 2058195534Sscottl else 2059195534Sscottl status = CAM_REQ_CMP_ERR; 2060195534Sscottl 2061195534Sscottl if (status == CAM_REQ_CMP) { 2062195534Sscottl if (async_code == AC_INQ_CHANGED) { 2063195534Sscottl /* 2064195534Sscottl * We've sent a start unit command, or 2065195534Sscottl * something similar to a device that 2066195534Sscottl * may have caused its inquiry data to 2067195534Sscottl * change. So we re-scan the device to 2068195534Sscottl * refresh the inquiry data for it. 2069195534Sscottl */ 2070195534Sscottl ata_scan_lun(newpath.periph, &newpath, 2071195534Sscottl CAM_EXPECT_INQ_CHANGE, NULL); 2072203108Smav } else { 2073203108Smav /* We need to reinitialize device after reset. */ 2074203108Smav ata_scan_lun(newpath.periph, &newpath, 2075203108Smav 0, NULL); 2076195534Sscottl } 2077195534Sscottl xpt_release_path(&newpath); 2078198748Smav } else if (async_code == AC_LOST_DEVICE && 2079198748Smav (device->flags & CAM_DEV_UNCONFIGURED) == 0) { 2080195534Sscottl device->flags |= CAM_DEV_UNCONFIGURED; 2081198748Smav xpt_release_device(device); 2082195534Sscottl } else if (async_code == AC_TRANSFER_NEG) { 2083195534Sscottl struct ccb_trans_settings *settings; 2084256843Smav struct cam_path path; 2085195534Sscottl 2086195534Sscottl settings = (struct ccb_trans_settings *)async_arg; 2087256843Smav xpt_compile_path(&path, NULL, bus->path_id, target->target_id, 2088256843Smav device->lun_id); 2089256843Smav ata_set_transfer_settings(settings, &path, 2090195534Sscottl /*async_update*/TRUE); 2091256843Smav xpt_release_path(&path); 2092195534Sscottl } 2093195534Sscottl} 2094195534Sscottl 2095204220Smavstatic void 2096204220Smavata_announce_periph(struct cam_periph *periph) 2097204220Smav{ 2098204220Smav struct ccb_pathinq cpi; 2099204220Smav struct ccb_trans_settings cts; 2100204220Smav struct cam_path *path = periph->path; 2101204220Smav u_int speed; 2102204220Smav u_int mb; 2103204220Smav 2104256843Smav cam_periph_assert(periph, MA_OWNED); 2105204220Smav 2106204220Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); 2107204220Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 2108204220Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 2109204220Smav xpt_action((union ccb*)&cts); 2110204220Smav if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 2111204220Smav return; 2112204220Smav /* Ask the SIM for its base transfer speed */ 2113350804Smav xpt_path_inq(&cpi, path); 2114204220Smav /* Report connection speed */ 2115204220Smav speed = cpi.base_transfer_speed; 2116204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_ATA) { 2117236437Smav struct ccb_trans_settings_pata *pata = 2118204220Smav &cts.xport_specific.ata; 2119204220Smav 2120236437Smav if (pata->valid & CTS_ATA_VALID_MODE) 2121236437Smav speed = ata_mode2speed(pata->mode); 2122204220Smav } 2123204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SATA) { 2124204220Smav struct ccb_trans_settings_sata *sata = 2125204220Smav &cts.xport_specific.sata; 2126204220Smav 2127204220Smav if (sata->valid & CTS_SATA_VALID_REVISION) 2128204220Smav speed = ata_revision2speed(sata->revision); 2129204220Smav } 2130204220Smav mb = speed / 1000; 2131204220Smav if (mb > 0) 2132204220Smav printf("%s%d: %d.%03dMB/s transfers", 2133204220Smav periph->periph_name, periph->unit_number, 2134204220Smav mb, speed % 1000); 2135204220Smav else 2136204220Smav printf("%s%d: %dKB/s transfers", periph->periph_name, 2137204220Smav periph->unit_number, speed); 2138204220Smav /* Report additional information about connection */ 2139204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_ATA) { 2140236437Smav struct ccb_trans_settings_pata *pata = 2141204220Smav &cts.xport_specific.ata; 2142204220Smav 2143204220Smav printf(" ("); 2144236437Smav if (pata->valid & CTS_ATA_VALID_MODE) 2145236437Smav printf("%s, ", ata_mode2string(pata->mode)); 2146236437Smav if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0) 2147236437Smav printf("ATAPI %dbytes, ", pata->atapi); 2148236437Smav if (pata->valid & CTS_ATA_VALID_BYTECOUNT) 2149236437Smav printf("PIO %dbytes", pata->bytecount); 2150204220Smav printf(")"); 2151204220Smav } 2152204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SATA) { 2153204220Smav struct ccb_trans_settings_sata *sata = 2154204220Smav &cts.xport_specific.sata; 2155204220Smav 2156204220Smav printf(" ("); 2157204220Smav if (sata->valid & CTS_SATA_VALID_REVISION) 2158204220Smav printf("SATA %d.x, ", sata->revision); 2159204220Smav else 2160204220Smav printf("SATA, "); 2161204220Smav if (sata->valid & CTS_SATA_VALID_MODE) 2162204220Smav printf("%s, ", ata_mode2string(sata->mode)); 2163204220Smav if ((sata->valid & CTS_ATA_VALID_ATAPI) && sata->atapi != 0) 2164204220Smav printf("ATAPI %dbytes, ", sata->atapi); 2165204220Smav if (sata->valid & CTS_SATA_VALID_BYTECOUNT) 2166204220Smav printf("PIO %dbytes", sata->bytecount); 2167204220Smav printf(")"); 2168204220Smav } 2169204220Smav printf("\n"); 2170204220Smav} 2171328820Smav 2172328820Smavstatic void 2173328820Smavata_proto_announce(struct cam_ed *device) 2174328820Smav{ 2175328820Smav ata_print_ident(&device->ident_data); 2176328820Smav} 2177328820Smav 2178328820Smavstatic void 2179328820Smavata_proto_denounce(struct cam_ed *device) 2180328820Smav{ 2181328820Smav ata_print_ident_short(&device->ident_data); 2182328820Smav} 2183328820Smav 2184328820Smavstatic void 2185328820Smavsemb_proto_announce(struct cam_ed *device) 2186328820Smav{ 2187328820Smav semb_print_ident((struct sep_identify_data *)&device->ident_data); 2188328820Smav} 2189328820Smav 2190328820Smavstatic void 2191328820Smavsemb_proto_denounce(struct cam_ed *device) 2192328820Smav{ 2193328820Smav semb_print_ident_short((struct sep_identify_data *)&device->ident_data); 2194328820Smav} 2195328820Smav 2196328820Smavstatic void 2197328820Smavata_proto_debug_out(union ccb *ccb) 2198328820Smav{ 2199328820Smav char cdb_str[(sizeof(struct ata_cmd) * 3) + 1]; 2200328820Smav 2201328820Smav if (ccb->ccb_h.func_code != XPT_ATA_IO) 2202328820Smav return; 2203328820Smav 2204328820Smav CAM_DEBUG(ccb->ccb_h.path, 2205328820Smav CAM_DEBUG_CDB,("%s. ACB: %s\n", ata_op_string(&ccb->ataio.cmd), 2206328820Smav ata_cmd_string(&ccb->ataio.cmd, cdb_str, sizeof(cdb_str)))); 2207328820Smav} 2208