ata_xpt.c revision 238886
1195534Sscottl/*- 2195534Sscottl * Copyright (c) 2009 Alexander Motin <mav@FreeBSD.org> 3195534Sscottl * All rights reserved. 4195534Sscottl * 5195534Sscottl * Redistribution and use in source and binary forms, with or without 6195534Sscottl * modification, are permitted provided that the following conditions 7195534Sscottl * are met: 8195534Sscottl * 1. Redistributions of source code must retain the above copyright 9195534Sscottl * notice, this list of conditions and the following disclaimer, 10195534Sscottl * without modification, immediately at the beginning of the file. 11195534Sscottl * 2. Redistributions in binary form must reproduce the above copyright 12195534Sscottl * notice, this list of conditions and the following disclaimer in the 13195534Sscottl * documentation and/or other materials provided with the distribution. 14195534Sscottl * 15195534Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16195534Sscottl * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17195534Sscottl * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18195534Sscottl * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19195534Sscottl * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20195534Sscottl * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21195534Sscottl * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22195534Sscottl * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23195534Sscottl * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24195534Sscottl * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25195534Sscottl */ 26195534Sscottl 27195534Sscottl#include <sys/cdefs.h> 28195534Sscottl__FBSDID("$FreeBSD: head/sys/cam/ata/ata_xpt.c 238886 2012-07-29 11:51:48Z mav $"); 29195534Sscottl 30195534Sscottl#include <sys/param.h> 31195534Sscottl#include <sys/bus.h> 32195534Sscottl#include <sys/endian.h> 33195534Sscottl#include <sys/systm.h> 34195534Sscottl#include <sys/types.h> 35195534Sscottl#include <sys/malloc.h> 36195534Sscottl#include <sys/kernel.h> 37195534Sscottl#include <sys/time.h> 38195534Sscottl#include <sys/conf.h> 39195534Sscottl#include <sys/fcntl.h> 40195534Sscottl#include <sys/interrupt.h> 41195534Sscottl#include <sys/sbuf.h> 42195534Sscottl 43195534Sscottl#include <sys/lock.h> 44195534Sscottl#include <sys/mutex.h> 45195534Sscottl#include <sys/sysctl.h> 46195534Sscottl 47195534Sscottl#include <cam/cam.h> 48195534Sscottl#include <cam/cam_ccb.h> 49195534Sscottl#include <cam/cam_queue.h> 50195534Sscottl#include <cam/cam_periph.h> 51195534Sscottl#include <cam/cam_sim.h> 52195534Sscottl#include <cam/cam_xpt.h> 53195534Sscottl#include <cam/cam_xpt_sim.h> 54195534Sscottl#include <cam/cam_xpt_periph.h> 55195534Sscottl#include <cam/cam_xpt_internal.h> 56195534Sscottl#include <cam/cam_debug.h> 57195534Sscottl 58195534Sscottl#include <cam/scsi/scsi_all.h> 59195534Sscottl#include <cam/scsi/scsi_message.h> 60195534Sscottl#include <cam/ata/ata_all.h> 61195534Sscottl#include <machine/stdarg.h> /* for xpt_print below */ 62195534Sscottl#include "opt_cam.h" 63195534Sscottl 64199178Smavstruct ata_quirk_entry { 65195534Sscottl struct scsi_inquiry_pattern inq_pat; 66195534Sscottl u_int8_t quirks; 67199178Smav#define CAM_QUIRK_MAXTAGS 0x01 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 163199178Smavstatic const int ata_quirk_table_size = 164199178Smav sizeof(ata_quirk_table) / sizeof(*ata_quirk_table); 165195534Sscottl 166195534Sscottlstatic cam_status proberegister(struct cam_periph *periph, 167195534Sscottl void *arg); 168195534Sscottlstatic void probeschedule(struct cam_periph *probe_periph); 169195534Sscottlstatic void probestart(struct cam_periph *periph, union ccb *start_ccb); 170236437Smavstatic void proberequestdefaultnegotiation(struct cam_periph *periph); 171195534Sscottlstatic void probedone(struct cam_periph *periph, union ccb *done_ccb); 172195534Sscottlstatic void probecleanup(struct cam_periph *periph); 173199178Smavstatic void ata_find_quirk(struct cam_ed *device); 174195534Sscottlstatic void ata_scan_bus(struct cam_periph *periph, union ccb *ccb); 175195534Sscottlstatic void ata_scan_lun(struct cam_periph *periph, 176195534Sscottl struct cam_path *path, cam_flags flags, 177195534Sscottl union ccb *ccb); 178195534Sscottlstatic void xptscandone(struct cam_periph *periph, union ccb *done_ccb); 179195534Sscottlstatic struct cam_ed * 180195534Sscottl ata_alloc_device(struct cam_eb *bus, struct cam_et *target, 181195534Sscottl lun_id_t lun_id); 182195534Sscottlstatic void ata_device_transport(struct cam_path *path); 183236437Smavstatic void ata_get_transfer_settings(struct ccb_trans_settings *cts); 184199178Smavstatic void ata_set_transfer_settings(struct ccb_trans_settings *cts, 185195534Sscottl struct cam_ed *device, 186195534Sscottl int async_update); 187195534Sscottlstatic void ata_dev_async(u_int32_t async_code, 188195534Sscottl struct cam_eb *bus, 189195534Sscottl struct cam_et *target, 190195534Sscottl struct cam_ed *device, 191195534Sscottl void *async_arg); 192195534Sscottlstatic void ata_action(union ccb *start_ccb); 193204220Smavstatic void ata_announce_periph(struct cam_periph *periph); 194195534Sscottl 195230912Smavstatic int ata_dma = 1; 196230912Smavstatic int atapi_dma = 1; 197230912Smav 198230912SmavTUNABLE_INT("hw.ata.ata_dma", &ata_dma); 199230912SmavTUNABLE_INT("hw.ata.atapi_dma", &atapi_dma); 200230912Smav 201195534Sscottlstatic struct xpt_xport ata_xport = { 202195534Sscottl .alloc_device = ata_alloc_device, 203195534Sscottl .action = ata_action, 204195534Sscottl .async = ata_dev_async, 205204220Smav .announce = ata_announce_periph, 206195534Sscottl}; 207195534Sscottl 208195534Sscottlstruct xpt_xport * 209195534Sscottlata_get_xport(void) 210195534Sscottl{ 211195534Sscottl return (&ata_xport); 212195534Sscottl} 213195534Sscottl 214195534Sscottlstatic void 215195534Sscottlprobe_periph_init() 216195534Sscottl{ 217195534Sscottl} 218195534Sscottl 219195534Sscottlstatic cam_status 220195534Sscottlproberegister(struct cam_periph *periph, void *arg) 221195534Sscottl{ 222195534Sscottl union ccb *request_ccb; /* CCB representing the probe request */ 223195534Sscottl cam_status status; 224195534Sscottl probe_softc *softc; 225195534Sscottl 226195534Sscottl request_ccb = (union ccb *)arg; 227195534Sscottl if (periph == NULL) { 228195534Sscottl printf("proberegister: periph was NULL!!\n"); 229195534Sscottl return(CAM_REQ_CMP_ERR); 230195534Sscottl } 231195534Sscottl 232195534Sscottl if (request_ccb == NULL) { 233195534Sscottl printf("proberegister: no probe CCB, " 234195534Sscottl "can't register device\n"); 235195534Sscottl return(CAM_REQ_CMP_ERR); 236195534Sscottl } 237195534Sscottl 238203421Smav softc = (probe_softc *)malloc(sizeof(*softc), M_CAMXPT, M_ZERO | M_NOWAIT); 239195534Sscottl 240195534Sscottl if (softc == NULL) { 241195534Sscottl printf("proberegister: Unable to probe new device. " 242195534Sscottl "Unable to allocate softc\n"); 243195534Sscottl return(CAM_REQ_CMP_ERR); 244195534Sscottl } 245195534Sscottl TAILQ_INIT(&softc->request_ccbs); 246195534Sscottl TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h, 247195534Sscottl periph_links.tqe); 248195534Sscottl softc->flags = 0; 249195534Sscottl periph->softc = softc; 250195534Sscottl softc->periph = periph; 251195534Sscottl softc->action = PROBE_INVALID; 252195534Sscottl status = cam_periph_acquire(periph); 253195534Sscottl if (status != CAM_REQ_CMP) { 254195534Sscottl return (status); 255195534Sscottl } 256236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe started\n")); 257236613Smav 258195534Sscottl /* 259203108Smav * Ensure nobody slip in until probe finish. 260195534Sscottl */ 261203108Smav cam_freeze_devq_arg(periph->path, 262203108Smav RELSIM_RELEASE_RUNLEVEL, CAM_RL_XPT + 1); 263195534Sscottl probeschedule(periph); 264195534Sscottl return(CAM_REQ_CMP); 265195534Sscottl} 266195534Sscottl 267195534Sscottlstatic void 268195534Sscottlprobeschedule(struct cam_periph *periph) 269195534Sscottl{ 270195534Sscottl union ccb *ccb; 271195534Sscottl probe_softc *softc; 272195534Sscottl 273195534Sscottl softc = (probe_softc *)periph->softc; 274195534Sscottl ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs); 275195534Sscottl 276198389Smav if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) || 277235897Smav periph->path->device->protocol == PROTO_SATAPM || 278235897Smav periph->path->device->protocol == PROTO_SEMB) 279195534Sscottl PROBE_SET_ACTION(softc, PROBE_RESET); 280195534Sscottl else 281195534Sscottl PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 282195534Sscottl 283195534Sscottl if (ccb->crcn.flags & CAM_EXPECT_INQ_CHANGE) 284195534Sscottl softc->flags |= PROBE_NO_ANNOUNCE; 285195534Sscottl else 286195534Sscottl softc->flags &= ~PROBE_NO_ANNOUNCE; 287195534Sscottl 288203108Smav xpt_schedule(periph, CAM_PRIORITY_XPT); 289195534Sscottl} 290195534Sscottl 291195534Sscottlstatic void 292195534Sscottlprobestart(struct cam_periph *periph, union ccb *start_ccb) 293195534Sscottl{ 294199747Smav struct ccb_trans_settings cts; 295195534Sscottl struct ccb_ataio *ataio; 296195534Sscottl struct ccb_scsiio *csio; 297195534Sscottl probe_softc *softc; 298198708Smav struct cam_path *path; 299198708Smav struct ata_params *ident_buf; 300195534Sscottl 301195534Sscottl CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probestart\n")); 302195534Sscottl 303195534Sscottl softc = (probe_softc *)periph->softc; 304198708Smav path = start_ccb->ccb_h.path; 305195534Sscottl ataio = &start_ccb->ataio; 306195534Sscottl csio = &start_ccb->csio; 307198708Smav ident_buf = &periph->path->device->ident_data; 308195534Sscottl 309203108Smav if (softc->restart) { 310203108Smav softc->restart = 0; 311203108Smav if ((path->device->flags & CAM_DEV_UNCONFIGURED) || 312235897Smav path->device->protocol == PROTO_SATAPM || 313235897Smav path->device->protocol == PROTO_SEMB) 314203108Smav softc->action = PROBE_RESET; 315203108Smav else 316203108Smav softc->action = PROBE_IDENTIFY; 317203108Smav } 318195534Sscottl switch (softc->action) { 319195534Sscottl case PROBE_RESET: 320195534Sscottl cam_fill_ataio(ataio, 321195534Sscottl 0, 322195534Sscottl probedone, 323195534Sscottl /*flags*/CAM_DIR_NONE, 324198389Smav 0, 325195534Sscottl /*data_ptr*/NULL, 326195534Sscottl /*dxfer_len*/0, 327203108Smav 15 * 1000); 328195534Sscottl ata_reset_cmd(ataio); 329195534Sscottl break; 330195534Sscottl case PROBE_IDENTIFY: 331195534Sscottl cam_fill_ataio(ataio, 332195534Sscottl 1, 333195534Sscottl probedone, 334195534Sscottl /*flags*/CAM_DIR_IN, 335198389Smav 0, 336203385Smav /*data_ptr*/(u_int8_t *)&softc->ident_data, 337203385Smav /*dxfer_len*/sizeof(softc->ident_data), 338195534Sscottl 30 * 1000); 339195534Sscottl if (periph->path->device->protocol == PROTO_ATA) 340196659Smav ata_28bit_cmd(ataio, ATA_ATA_IDENTIFY, 0, 0, 0); 341195534Sscottl else 342196659Smav ata_28bit_cmd(ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0); 343195534Sscottl break; 344203421Smav case PROBE_SPINUP: 345203421Smav if (bootverbose) 346203421Smav xpt_print(path, "Spinning up device\n"); 347203421Smav cam_fill_ataio(ataio, 348203421Smav 1, 349203421Smav probedone, 350203421Smav /*flags*/CAM_DIR_NONE | CAM_HIGH_POWER, 351203421Smav 0, 352203421Smav /*data_ptr*/NULL, 353203421Smav /*dxfer_len*/0, 354203421Smav 30 * 1000); 355203421Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_PUIS_SPINUP, 0, 0); 356203421Smav break; 357195534Sscottl case PROBE_SETMODE: 358199747Smav { 359199747Smav int mode, wantmode; 360199747Smav 361199747Smav mode = 0; 362199747Smav /* Fetch user modes from SIM. */ 363199747Smav bzero(&cts, sizeof(cts)); 364203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 365199747Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 366199747Smav cts.type = CTS_TYPE_USER_SETTINGS; 367199747Smav xpt_action((union ccb *)&cts); 368199747Smav if (path->device->transport == XPORT_ATA) { 369199747Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_MODE) 370199747Smav mode = cts.xport_specific.ata.mode; 371199747Smav } else { 372199799Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_MODE) 373199747Smav mode = cts.xport_specific.sata.mode; 374199747Smav } 375230912Smav if (periph->path->device->protocol == PROTO_ATA) { 376230912Smav if (ata_dma == 0 && (mode == 0 || mode > ATA_PIO_MAX)) 377230912Smav mode = ATA_PIO_MAX; 378230912Smav } else { 379230912Smav if (atapi_dma == 0 && (mode == 0 || mode > ATA_PIO_MAX)) 380230912Smav mode = ATA_PIO_MAX; 381230912Smav } 382199747Smavnegotiate: 383199747Smav /* Honor device capabilities. */ 384199747Smav wantmode = mode = ata_max_mode(ident_buf, mode); 385199747Smav /* Report modes to SIM. */ 386199747Smav bzero(&cts, sizeof(cts)); 387203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 388199747Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 389199747Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 390199747Smav if (path->device->transport == XPORT_ATA) { 391199747Smav cts.xport_specific.ata.mode = mode; 392199747Smav cts.xport_specific.ata.valid = CTS_ATA_VALID_MODE; 393199747Smav } else { 394199747Smav cts.xport_specific.sata.mode = mode; 395199747Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_MODE; 396199747Smav } 397199747Smav xpt_action((union ccb *)&cts); 398200171Smav /* Fetch current 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_CURRENT_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 { 408199747Smav if (cts.xport_specific.ata.valid & CTS_SATA_VALID_MODE) 409199747Smav mode = cts.xport_specific.sata.mode; 410199747Smav } 411199747Smav /* If SIM disagree - renegotiate. */ 412199747Smav if (mode != wantmode) 413199747Smav goto negotiate; 414220886Smav /* Remember what transport thinks about DMA. */ 415220886Smav if (mode < ATA_DMA) 416220886Smav path->device->inq_flags &= ~SID_DMA; 417220886Smav else 418220886Smav path->device->inq_flags |= SID_DMA; 419236393Smav xpt_async(AC_GETDEV_CHANGED, path, NULL); 420195534Sscottl cam_fill_ataio(ataio, 421195534Sscottl 1, 422195534Sscottl probedone, 423196353Smav /*flags*/CAM_DIR_NONE, 424196353Smav 0, 425196353Smav /*data_ptr*/NULL, 426196353Smav /*dxfer_len*/0, 427195534Sscottl 30 * 1000); 428199747Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); 429195534Sscottl break; 430199747Smav } 431207499Smav case PROBE_SETPM: 432207499Smav cam_fill_ataio(ataio, 433207499Smav 1, 434207499Smav probedone, 435207499Smav CAM_DIR_NONE, 436207499Smav 0, 437207499Smav NULL, 438207499Smav 0, 439207499Smav 30*1000); 440207499Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, 441207499Smav (softc->caps & CTS_SATA_CAPS_H_PMREQ) ? 0x10 : 0x90, 442207499Smav 0, 0x03); 443207499Smav break; 444207499Smav case PROBE_SETAPST: 445207499Smav cam_fill_ataio(ataio, 446207499Smav 1, 447207499Smav probedone, 448207499Smav CAM_DIR_NONE, 449207499Smav 0, 450207499Smav NULL, 451207499Smav 0, 452207499Smav 30*1000); 453207499Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, 454207499Smav (softc->caps & CTS_SATA_CAPS_H_APST) ? 0x10 : 0x90, 455207499Smav 0, 0x07); 456207499Smav break; 457207499Smav case PROBE_SETDMAAA: 458207499Smav cam_fill_ataio(ataio, 459207499Smav 1, 460207499Smav probedone, 461207499Smav CAM_DIR_NONE, 462207499Smav 0, 463207499Smav NULL, 464207499Smav 0, 465207499Smav 30*1000); 466207499Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, 467207499Smav (softc->caps & CTS_SATA_CAPS_H_DMAAA) ? 0x10 : 0x90, 468207499Smav 0, 0x02); 469207499Smav break; 470220602Smav case PROBE_SETAN: 471238886Smav /* Remember what transport thinks about AEN. */ 472238886Smav if (softc->caps & CTS_SATA_CAPS_H_AN) 473238886Smav path->device->inq_flags |= SID_AEN; 474238886Smav else 475238886Smav path->device->inq_flags &= ~SID_AEN; 476238886Smav xpt_async(AC_GETDEV_CHANGED, path, NULL); 477220602Smav cam_fill_ataio(ataio, 478220602Smav 1, 479220602Smav probedone, 480220602Smav CAM_DIR_NONE, 481220602Smav 0, 482220602Smav NULL, 483220602Smav 0, 484220602Smav 30*1000); 485220602Smav ata_28bit_cmd(ataio, ATA_SETFEATURES, 486220602Smav (softc->caps & CTS_SATA_CAPS_H_AN) ? 0x10 : 0x90, 487220602Smav 0, 0x05); 488220602Smav break; 489198708Smav case PROBE_SET_MULTI: 490198708Smav { 491200171Smav u_int sectors, bytecount; 492198708Smav 493200171Smav bytecount = 8192; /* SATA maximum */ 494200171Smav /* Fetch user bytecount from SIM. */ 495200171Smav bzero(&cts, sizeof(cts)); 496203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 497200171Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 498200171Smav cts.type = CTS_TYPE_USER_SETTINGS; 499200171Smav xpt_action((union ccb *)&cts); 500200171Smav if (path->device->transport == XPORT_ATA) { 501200171Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 502200171Smav bytecount = cts.xport_specific.ata.bytecount; 503200171Smav } else { 504200171Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 505200171Smav bytecount = cts.xport_specific.sata.bytecount; 506200171Smav } 507200171Smav /* Honor device capabilities. */ 508200171Smav sectors = max(1, min(ident_buf->sectors_intr & 0xff, 509200171Smav bytecount / ata_logical_sector_size(ident_buf))); 510198708Smav /* Report bytecount to SIM. */ 511198708Smav bzero(&cts, sizeof(cts)); 512203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 513198708Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 514198708Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 515198708Smav if (path->device->transport == XPORT_ATA) { 516198897Smav cts.xport_specific.ata.bytecount = sectors * 517198897Smav ata_logical_sector_size(ident_buf); 518198708Smav cts.xport_specific.ata.valid = CTS_ATA_VALID_BYTECOUNT; 519198708Smav } else { 520198897Smav cts.xport_specific.sata.bytecount = sectors * 521198897Smav ata_logical_sector_size(ident_buf); 522198708Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_BYTECOUNT; 523198708Smav } 524198708Smav xpt_action((union ccb *)&cts); 525200171Smav /* Fetch current bytecount from SIM. */ 526200171Smav bzero(&cts, sizeof(cts)); 527203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 528200171Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 529200171Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 530200171Smav xpt_action((union ccb *)&cts); 531200171Smav if (path->device->transport == XPORT_ATA) { 532200171Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 533200171Smav bytecount = cts.xport_specific.ata.bytecount; 534200171Smav } else { 535200171Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 536200171Smav bytecount = cts.xport_specific.sata.bytecount; 537200171Smav } 538200171Smav sectors = bytecount / ata_logical_sector_size(ident_buf); 539198708Smav 540198708Smav cam_fill_ataio(ataio, 541198708Smav 1, 542198708Smav probedone, 543198708Smav CAM_DIR_NONE, 544198708Smav 0, 545198708Smav NULL, 546198708Smav 0, 547198708Smav 30*1000); 548198708Smav ata_28bit_cmd(ataio, ATA_SET_MULTI, 0, 0, sectors); 549198708Smav break; 550195534Sscottl } 551195534Sscottl case PROBE_INQUIRY: 552200171Smav { 553200171Smav u_int bytecount; 554200171Smav 555200171Smav bytecount = 8192; /* SATA maximum */ 556200171Smav /* Fetch user bytecount from SIM. */ 557200171Smav bzero(&cts, sizeof(cts)); 558203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 559200171Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 560200171Smav cts.type = CTS_TYPE_USER_SETTINGS; 561200171Smav xpt_action((union ccb *)&cts); 562200171Smav if (path->device->transport == XPORT_ATA) { 563200171Smav if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 564200171Smav bytecount = cts.xport_specific.ata.bytecount; 565200171Smav } else { 566200171Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 567200171Smav bytecount = cts.xport_specific.sata.bytecount; 568200171Smav } 569200171Smav /* Honor device capabilities. */ 570200171Smav bytecount &= ~1; 571200171Smav bytecount = max(2, min(65534, bytecount)); 572200171Smav if (ident_buf->satacapabilities != 0x0000 && 573200171Smav ident_buf->satacapabilities != 0xffff) { 574200171Smav bytecount = min(8192, bytecount); 575200171Smav } 576200171Smav /* Report bytecount to SIM. */ 577200171Smav bzero(&cts, sizeof(cts)); 578203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 579200171Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 580200171Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 581200171Smav if (path->device->transport == XPORT_ATA) { 582200171Smav cts.xport_specific.ata.bytecount = bytecount; 583200171Smav cts.xport_specific.ata.valid = CTS_ATA_VALID_BYTECOUNT; 584200171Smav } else { 585200171Smav cts.xport_specific.sata.bytecount = bytecount; 586200171Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_BYTECOUNT; 587200171Smav } 588200171Smav xpt_action((union ccb *)&cts); 589200171Smav /* FALLTHROUGH */ 590200171Smav } 591195534Sscottl case PROBE_FULL_INQUIRY: 592195534Sscottl { 593195534Sscottl u_int inquiry_len; 594195534Sscottl struct scsi_inquiry_data *inq_buf = 595195534Sscottl &periph->path->device->inq_data; 596195534Sscottl 597195534Sscottl if (softc->action == PROBE_INQUIRY) 598195534Sscottl inquiry_len = SHORT_INQUIRY_LENGTH; 599195534Sscottl else 600195534Sscottl inquiry_len = SID_ADDITIONAL_LENGTH(inq_buf); 601195534Sscottl /* 602195534Sscottl * Some parallel SCSI devices fail to send an 603195534Sscottl * ignore wide residue message when dealing with 604195534Sscottl * odd length inquiry requests. Round up to be 605195534Sscottl * safe. 606195534Sscottl */ 607195534Sscottl inquiry_len = roundup2(inquiry_len, 2); 608195534Sscottl scsi_inquiry(csio, 609195534Sscottl /*retries*/1, 610195534Sscottl probedone, 611195534Sscottl MSG_SIMPLE_Q_TAG, 612195534Sscottl (u_int8_t *)inq_buf, 613195534Sscottl inquiry_len, 614195534Sscottl /*evpd*/FALSE, 615195534Sscottl /*page_code*/0, 616195534Sscottl SSD_MIN_SIZE, 617195534Sscottl /*timeout*/60 * 1000); 618195534Sscottl break; 619195534Sscottl } 620195534Sscottl case PROBE_PM_PID: 621195534Sscottl cam_fill_ataio(ataio, 622195534Sscottl 1, 623195534Sscottl probedone, 624195534Sscottl /*flags*/CAM_DIR_NONE, 625198389Smav 0, 626195534Sscottl /*data_ptr*/NULL, 627195534Sscottl /*dxfer_len*/0, 628195534Sscottl 10 * 1000); 629195534Sscottl ata_pm_read_cmd(ataio, 0, 15); 630195534Sscottl break; 631195534Sscottl case PROBE_PM_PRV: 632195534Sscottl cam_fill_ataio(ataio, 633195534Sscottl 1, 634195534Sscottl probedone, 635195534Sscottl /*flags*/CAM_DIR_NONE, 636198389Smav 0, 637195534Sscottl /*data_ptr*/NULL, 638195534Sscottl /*dxfer_len*/0, 639195534Sscottl 10 * 1000); 640195534Sscottl ata_pm_read_cmd(ataio, 1, 15); 641195534Sscottl break; 642235897Smav case PROBE_IDENTIFY_SES: 643235897Smav cam_fill_ataio(ataio, 644235897Smav 1, 645235897Smav probedone, 646235897Smav /*flags*/CAM_DIR_IN, 647235897Smav 0, 648235897Smav /*data_ptr*/(u_int8_t *)&softc->ident_data, 649235897Smav /*dxfer_len*/sizeof(softc->ident_data), 650235897Smav 30 * 1000); 651235897Smav ata_28bit_cmd(ataio, ATA_SEP_ATTN, 0xEC, 0x02, 652235897Smav sizeof(softc->ident_data) / 4); 653235897Smav break; 654235897Smav case PROBE_IDENTIFY_SAFTE: 655235897Smav cam_fill_ataio(ataio, 656235897Smav 1, 657235897Smav probedone, 658235897Smav /*flags*/CAM_DIR_IN, 659235897Smav 0, 660235897Smav /*data_ptr*/(u_int8_t *)&softc->ident_data, 661235897Smav /*dxfer_len*/sizeof(softc->ident_data), 662235897Smav 30 * 1000); 663235897Smav ata_28bit_cmd(ataio, ATA_SEP_ATTN, 0xEC, 0x00, 664235897Smav sizeof(softc->ident_data) / 4); 665235897Smav break; 666195534Sscottl default: 667236613Smav panic("probestart: invalid action state 0x%x\n", softc->action); 668195534Sscottl } 669195534Sscottl xpt_action(start_ccb); 670195534Sscottl} 671236437Smav 672195534Sscottlstatic void 673195534Sscottlproberequestdefaultnegotiation(struct cam_periph *periph) 674195534Sscottl{ 675195534Sscottl struct ccb_trans_settings cts; 676195534Sscottl 677203108Smav xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE); 678195534Sscottl cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 679195534Sscottl cts.type = CTS_TYPE_USER_SETTINGS; 680195534Sscottl xpt_action((union ccb *)&cts); 681236437Smav if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 682195534Sscottl return; 683236437Smav cts.xport_specific.valid = 0; 684195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 685195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 686195534Sscottl xpt_action((union ccb *)&cts); 687195534Sscottl} 688195534Sscottl 689195534Sscottlstatic void 690195534Sscottlprobedone(struct cam_periph *periph, union ccb *done_ccb) 691195534Sscottl{ 692199747Smav struct ccb_trans_settings cts; 693195534Sscottl struct ata_params *ident_buf; 694235897Smav struct scsi_inquiry_data *inq_buf; 695195534Sscottl probe_softc *softc; 696195534Sscottl struct cam_path *path; 697217444Smav cam_status status; 698195534Sscottl u_int32_t priority; 699207499Smav u_int caps; 700235897Smav int changed = 1, found = 1; 701235897Smav static const uint8_t fake_device_id_hdr[8] = 702235897Smav {0, SVPD_DEVICE_ID, 0, 12, 703235897Smav SVPD_ID_CODESET_BINARY, SVPD_ID_TYPE_NAA, 0, 8}; 704195534Sscottl 705195534Sscottl CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probedone\n")); 706195534Sscottl 707195534Sscottl softc = (probe_softc *)periph->softc; 708195534Sscottl path = done_ccb->ccb_h.path; 709195534Sscottl priority = done_ccb->ccb_h.pinfo.priority; 710195534Sscottl ident_buf = &path->device->ident_data; 711235897Smav inq_buf = &path->device->inq_data; 712195534Sscottl 713198708Smav if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 714236814Smav if (cam_periph_error(done_ccb, 715236814Smav 0, softc->restart ? (SF_NO_RECOVERY | SF_NO_RETRY) : 0, 716236814Smav NULL) == ERESTART) 717195534Sscottl return; 718209744Smav if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 719195534Sscottl /* Don't wedge the queue */ 720195534Sscottl xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, 721195534Sscottl /*run_queue*/TRUE); 722195534Sscottl } 723217444Smav status = done_ccb->ccb_h.status & CAM_STATUS_MASK; 724209744Smav if (softc->restart) { 725209744Smav softc->faults++; 726209744Smav if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == 727209744Smav CAM_CMD_TIMEOUT) 728209744Smav softc->faults += 4; 729209744Smav if (softc->faults < 10) 730209744Smav goto done; 731209744Smav else 732209744Smav softc->restart = 0; 733217444Smav 734198708Smav /* Old PIO2 devices may not support mode setting. */ 735217444Smav } else if (softc->action == PROBE_SETMODE && 736217444Smav status == CAM_ATA_STATUS_ERROR && 737198708Smav ata_max_pmode(ident_buf) <= ATA_PIO2 && 738217444Smav (ident_buf->capabilities1 & ATA_SUPPORT_IORDY) == 0) { 739198708Smav goto noerror; 740217444Smav 741198708Smav /* 742217444Smav * Some old WD SATA disks report supported and enabled 743217444Smav * device-initiated interface power management, but return 744217444Smav * ABORT on attempt to disable it. 745217444Smav */ 746217444Smav } else if (softc->action == PROBE_SETPM && 747217444Smav status == CAM_ATA_STATUS_ERROR) { 748217444Smav goto noerror; 749217875Smav 750217875Smav /* 751217875Smav * Some HP SATA disks report supported DMA Auto-Activation, 752217875Smav * but return ABORT on attempt to enable it. 753217875Smav */ 754217875Smav } else if (softc->action == PROBE_SETDMAAA && 755217875Smav status == CAM_ATA_STATUS_ERROR) { 756217875Smav goto noerror; 757235897Smav 758235897Smav /* 759235897Smav * SES and SAF-TE SEPs have different IDENTIFY commands, 760235897Smav * but SATA specification doesn't tell how to identify them. 761235897Smav * Until better way found, just try another if first fail. 762235897Smav */ 763235897Smav } else if (softc->action == PROBE_IDENTIFY_SES && 764235897Smav status == CAM_ATA_STATUS_ERROR) { 765235897Smav PROBE_SET_ACTION(softc, PROBE_IDENTIFY_SAFTE); 766235897Smav xpt_release_ccb(done_ccb); 767235897Smav xpt_schedule(periph, priority); 768235897Smav return; 769217444Smav } 770217444Smav 771217444Smav /* 772198708Smav * If we get to this point, we got an error status back 773198708Smav * from the inquiry and the error status doesn't require 774198708Smav * automatically retrying the command. Therefore, the 775198708Smav * inquiry failed. If we had inquiry information before 776198708Smav * for this device, but this latest inquiry command failed, 777198708Smav * the device has probably gone away. If this device isn't 778198708Smav * already marked unconfigured, notify the peripheral 779198708Smav * drivers that this device is no more. 780198708Smav */ 781209744Smavdevice_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0) 782198708Smav xpt_async(AC_LOST_DEVICE, path, NULL); 783236613Smav PROBE_SET_ACTION(softc, PROBE_INVALID); 784198708Smav found = 0; 785198708Smav goto done; 786198708Smav } 787198708Smavnoerror: 788203385Smav if (softc->restart) 789203385Smav goto done; 790198708Smav switch (softc->action) { 791198708Smav case PROBE_RESET: 792195534Sscottl { 793198708Smav int sign = (done_ccb->ataio.res.lba_high << 8) + 794198708Smav done_ccb->ataio.res.lba_mid; 795236613Smav CAM_DEBUG(path, CAM_DEBUG_PROBE, 796236613Smav ("SIGNATURE: %04x\n", sign)); 797198708Smav if (sign == 0x0000 && 798198708Smav done_ccb->ccb_h.target_id != 15) { 799198708Smav path->device->protocol = PROTO_ATA; 800198708Smav PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 801198708Smav } else if (sign == 0x9669 && 802198708Smav done_ccb->ccb_h.target_id == 15) { 803199747Smav /* Report SIM that PM is present. */ 804198708Smav bzero(&cts, sizeof(cts)); 805203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 806198708Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 807198708Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 808198708Smav cts.xport_specific.sata.pm_present = 1; 809198708Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; 810198708Smav xpt_action((union ccb *)&cts); 811198708Smav path->device->protocol = PROTO_SATAPM; 812198708Smav PROBE_SET_ACTION(softc, PROBE_PM_PID); 813235897Smav } else if (sign == 0xc33c && 814235897Smav done_ccb->ccb_h.target_id != 15) { 815235897Smav path->device->protocol = PROTO_SEMB; 816235897Smav PROBE_SET_ACTION(softc, PROBE_IDENTIFY_SES); 817198708Smav } else if (sign == 0xeb14 && 818198708Smav done_ccb->ccb_h.target_id != 15) { 819198708Smav path->device->protocol = PROTO_SCSI; 820198708Smav PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 821198708Smav } else { 822198708Smav if (done_ccb->ccb_h.target_id != 15) { 823198708Smav xpt_print(path, 824198708Smav "Unexpected signature 0x%04x\n", sign); 825195534Sscottl } 826198708Smav goto device_fail; 827198708Smav } 828198708Smav xpt_release_ccb(done_ccb); 829198708Smav xpt_schedule(periph, priority); 830198708Smav return; 831198708Smav } 832198708Smav case PROBE_IDENTIFY: 833198708Smav { 834207222Smav struct ccb_pathinq cpi; 835198708Smav int16_t *ptr; 836195534Sscottl 837203385Smav ident_buf = &softc->ident_data; 838198708Smav for (ptr = (int16_t *)ident_buf; 839198708Smav ptr < (int16_t *)ident_buf + sizeof(struct ata_params)/2; ptr++) { 840198708Smav *ptr = le16toh(*ptr); 841198708Smav } 842198708Smav if (strncmp(ident_buf->model, "FX", 2) && 843198708Smav strncmp(ident_buf->model, "NEC", 3) && 844198708Smav strncmp(ident_buf->model, "Pioneer", 7) && 845198708Smav strncmp(ident_buf->model, "SHARP", 5)) { 846198708Smav ata_bswap(ident_buf->model, sizeof(ident_buf->model)); 847198708Smav ata_bswap(ident_buf->revision, sizeof(ident_buf->revision)); 848198708Smav ata_bswap(ident_buf->serial, sizeof(ident_buf->serial)); 849198708Smav } 850198708Smav ata_btrim(ident_buf->model, sizeof(ident_buf->model)); 851198708Smav ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model)); 852198708Smav ata_btrim(ident_buf->revision, sizeof(ident_buf->revision)); 853198708Smav ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision)); 854198708Smav ata_btrim(ident_buf->serial, sizeof(ident_buf->serial)); 855198708Smav ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial)); 856203421Smav /* Device may need spin-up before IDENTIFY become valid. */ 857204354Smav if ((ident_buf->specconf == 0x37c8 || 858204354Smav ident_buf->specconf == 0x738c) && 859204354Smav ((ident_buf->config & ATA_RESP_INCOMPLETE) || 860204354Smav softc->spinup == 0)) { 861203421Smav PROBE_SET_ACTION(softc, PROBE_SPINUP); 862203421Smav xpt_release_ccb(done_ccb); 863203421Smav xpt_schedule(periph, priority); 864203421Smav return; 865203421Smav } 866203385Smav ident_buf = &path->device->ident_data; 867198708Smav if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) { 868198708Smav /* Check that it is the same device. */ 869203385Smav if (bcmp(softc->ident_data.model, ident_buf->model, 870203385Smav sizeof(ident_buf->model)) || 871203385Smav bcmp(softc->ident_data.revision, ident_buf->revision, 872203385Smav sizeof(ident_buf->revision)) || 873203385Smav bcmp(softc->ident_data.serial, ident_buf->serial, 874203385Smav sizeof(ident_buf->serial))) { 875198708Smav /* Device changed. */ 876198708Smav xpt_async(AC_LOST_DEVICE, path, NULL); 877207282Smav } else { 878203385Smav bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 879207282Smav changed = 0; 880207282Smav } 881207282Smav } 882207282Smav if (changed) { 883203385Smav bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 884195534Sscottl /* Clean up from previous instance of this device */ 885195534Sscottl if (path->device->serial_num != NULL) { 886195534Sscottl free(path->device->serial_num, M_CAMXPT); 887195534Sscottl path->device->serial_num = NULL; 888195534Sscottl path->device->serial_num_len = 0; 889195534Sscottl } 890235897Smav if (path->device->device_id != NULL) { 891235897Smav free(path->device->device_id, M_CAMXPT); 892235897Smav path->device->device_id = NULL; 893235897Smav path->device->device_id_len = 0; 894235897Smav } 895195534Sscottl path->device->serial_num = 896195534Sscottl (u_int8_t *)malloc((sizeof(ident_buf->serial) + 1), 897198708Smav M_CAMXPT, M_NOWAIT); 898195534Sscottl if (path->device->serial_num != NULL) { 899195534Sscottl bcopy(ident_buf->serial, 900195534Sscottl path->device->serial_num, 901195534Sscottl sizeof(ident_buf->serial)); 902195534Sscottl path->device->serial_num[sizeof(ident_buf->serial)] 903195534Sscottl = '\0'; 904195534Sscottl path->device->serial_num_len = 905195534Sscottl strlen(path->device->serial_num); 906195534Sscottl } 907235897Smav if (ident_buf->enabled.extension & 908235897Smav ATA_SUPPORT_64BITWWN) { 909235897Smav path->device->device_id = 910235897Smav malloc(16, M_CAMXPT, M_NOWAIT); 911235897Smav if (path->device->device_id != NULL) { 912235897Smav path->device->device_id_len = 16; 913235897Smav bcopy(&fake_device_id_hdr, 914235897Smav path->device->device_id, 8); 915235897Smav bcopy(ident_buf->wwn, 916235897Smav path->device->device_id + 8, 8); 917235897Smav } 918235897Smav } 919195534Sscottl 920198331Smav path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 921236393Smav xpt_async(AC_GETDEV_CHANGED, path, NULL); 922195534Sscottl } 923199178Smav if (ident_buf->satacapabilities & ATA_SUPPORT_NCQ) { 924236234Smav path->device->mintags = 2; 925236234Smav path->device->maxtags = 926199178Smav ATA_QUEUE_LEN(ident_buf->queue) + 1; 927199178Smav } 928199178Smav ata_find_quirk(path->device); 929199263Smav if (path->device->mintags != 0 && 930199263Smav path->bus->sim->max_tagged_dev_openings != 0) { 931207222Smav /* Check if the SIM does not want queued commands. */ 932207222Smav bzero(&cpi, sizeof(cpi)); 933207222Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 934207222Smav cpi.ccb_h.func_code = XPT_PATH_INQ; 935207222Smav xpt_action((union ccb *)&cpi); 936207222Smav if (cpi.ccb_h.status == CAM_REQ_CMP && 937207222Smav (cpi.hba_inquiry & PI_TAG_ABLE)) { 938207222Smav /* Report SIM which tags are allowed. */ 939207222Smav bzero(&cts, sizeof(cts)); 940207222Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 941207222Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 942207222Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 943207222Smav cts.xport_specific.sata.tags = path->device->maxtags; 944207222Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_TAGS; 945207222Smav xpt_action((union ccb *)&cts); 946207222Smav } 947199178Smav } 948236666Smav ata_device_transport(path); 949236437Smav if (changed) 950236437Smav proberequestdefaultnegotiation(periph); 951198708Smav PROBE_SET_ACTION(softc, PROBE_SETMODE); 952195534Sscottl xpt_release_ccb(done_ccb); 953198708Smav xpt_schedule(periph, priority); 954198708Smav return; 955195534Sscottl } 956203421Smav case PROBE_SPINUP: 957203421Smav if (bootverbose) 958203421Smav xpt_print(path, "Spin-up done\n"); 959203421Smav softc->spinup = 1; 960203421Smav PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 961203421Smav xpt_release_ccb(done_ccb); 962203421Smav xpt_schedule(periph, priority); 963203421Smav return; 964195534Sscottl case PROBE_SETMODE: 965207499Smav if (path->device->transport != XPORT_SATA) 966207499Smav goto notsata; 967207499Smav /* Set supported bits. */ 968207499Smav bzero(&cts, sizeof(cts)); 969207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 970207499Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 971207499Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 972207499Smav xpt_action((union ccb *)&cts); 973207499Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 974207499Smav caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H; 975207499Smav else 976207499Smav caps = 0; 977207499Smav if (ident_buf->satacapabilities != 0xffff) { 978207499Smav if (ident_buf->satacapabilities & ATA_SUPPORT_IFPWRMNGTRCV) 979207499Smav caps |= CTS_SATA_CAPS_D_PMREQ; 980207499Smav if (ident_buf->satacapabilities & ATA_SUPPORT_HAPST) 981207499Smav caps |= CTS_SATA_CAPS_D_APST; 982207499Smav } 983207499Smav /* Mask unwanted bits. */ 984207499Smav bzero(&cts, sizeof(cts)); 985207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 986207499Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 987207499Smav cts.type = CTS_TYPE_USER_SETTINGS; 988207499Smav xpt_action((union ccb *)&cts); 989207499Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 990207499Smav caps &= cts.xport_specific.sata.caps; 991215454Smav else 992215454Smav caps = 0; 993207499Smav /* Store result to SIM. */ 994207499Smav bzero(&cts, sizeof(cts)); 995207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 996207499Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 997207499Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 998207499Smav cts.xport_specific.sata.caps = caps; 999207499Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS; 1000207499Smav xpt_action((union ccb *)&cts); 1001207499Smav softc->caps = caps; 1002217874Smav if ((ident_buf->satasupport & ATA_SUPPORT_IFPWRMNGT) && 1003217874Smav (!(softc->caps & CTS_SATA_CAPS_H_PMREQ)) != 1004217874Smav (!(ident_buf->sataenabled & ATA_SUPPORT_IFPWRMNGT))) { 1005207499Smav PROBE_SET_ACTION(softc, PROBE_SETPM); 1006207499Smav xpt_release_ccb(done_ccb); 1007207499Smav xpt_schedule(periph, priority); 1008207499Smav return; 1009207499Smav } 1010207499Smav /* FALLTHROUGH */ 1011207499Smav case PROBE_SETPM: 1012207499Smav if (ident_buf->satacapabilities != 0xffff && 1013217874Smav (ident_buf->satacapabilities & ATA_SUPPORT_DAPST) && 1014217874Smav (!(softc->caps & CTS_SATA_CAPS_H_APST)) != 1015217874Smav (!(ident_buf->sataenabled & ATA_ENABLED_DAPST))) { 1016207499Smav PROBE_SET_ACTION(softc, PROBE_SETAPST); 1017207499Smav xpt_release_ccb(done_ccb); 1018207499Smav xpt_schedule(periph, priority); 1019207499Smav return; 1020207499Smav } 1021207499Smav /* FALLTHROUGH */ 1022207499Smav case PROBE_SETAPST: 1023217874Smav if ((ident_buf->satasupport & ATA_SUPPORT_AUTOACTIVATE) && 1024217874Smav (!(softc->caps & CTS_SATA_CAPS_H_DMAAA)) != 1025217874Smav (!(ident_buf->sataenabled & ATA_SUPPORT_AUTOACTIVATE))) { 1026207499Smav PROBE_SET_ACTION(softc, PROBE_SETDMAAA); 1027207499Smav xpt_release_ccb(done_ccb); 1028207499Smav xpt_schedule(periph, priority); 1029207499Smav return; 1030207499Smav } 1031207499Smav /* FALLTHROUGH */ 1032207499Smav case PROBE_SETDMAAA: 1033220602Smav if ((ident_buf->satasupport & ATA_SUPPORT_ASYNCNOTIF) && 1034220602Smav (!(softc->caps & CTS_SATA_CAPS_H_AN)) != 1035220602Smav (!(ident_buf->sataenabled & ATA_SUPPORT_ASYNCNOTIF))) { 1036220602Smav PROBE_SET_ACTION(softc, PROBE_SETAN); 1037220602Smav xpt_release_ccb(done_ccb); 1038220602Smav xpt_schedule(periph, priority); 1039220602Smav return; 1040220602Smav } 1041220602Smav /* FALLTHROUGH */ 1042220602Smav case PROBE_SETAN: 1043207499Smavnotsata: 1044198708Smav if (path->device->protocol == PROTO_ATA) { 1045198708Smav PROBE_SET_ACTION(softc, PROBE_SET_MULTI); 1046198708Smav } else { 1047198708Smav PROBE_SET_ACTION(softc, PROBE_INQUIRY); 1048195534Sscottl } 1049198708Smav xpt_release_ccb(done_ccb); 1050198708Smav xpt_schedule(periph, priority); 1051198708Smav return; 1052198708Smav case PROBE_SET_MULTI: 1053198708Smav if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 1054198708Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1055198748Smav xpt_acquire_device(path->device); 1056198708Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1057198708Smav xpt_action(done_ccb); 1058198708Smav xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, 1059198708Smav done_ccb); 1060198708Smav } 1061236613Smav PROBE_SET_ACTION(softc, PROBE_DONE); 1062198708Smav break; 1063195534Sscottl case PROBE_INQUIRY: 1064195534Sscottl case PROBE_FULL_INQUIRY: 1065195534Sscottl { 1066198708Smav u_int8_t periph_qual, len; 1067195534Sscottl 1068198708Smav path->device->flags |= CAM_DEV_INQUIRY_DATA_VALID; 1069195534Sscottl 1070198708Smav periph_qual = SID_QUAL(inq_buf); 1071195534Sscottl 1072198708Smav if (periph_qual != SID_QUAL_LU_CONNECTED) 1073198708Smav break; 1074195534Sscottl 1075198708Smav /* 1076198708Smav * We conservatively request only 1077198708Smav * SHORT_INQUIRY_LEN bytes of inquiry 1078198708Smav * information during our first try 1079198708Smav * at sending an INQUIRY. If the device 1080198708Smav * has more information to give, 1081198708Smav * perform a second request specifying 1082198708Smav * the amount of information the device 1083198708Smav * is willing to give. 1084198708Smav */ 1085198708Smav len = inq_buf->additional_length 1086198708Smav + offsetof(struct scsi_inquiry_data, additional_length) + 1; 1087198708Smav if (softc->action == PROBE_INQUIRY 1088198708Smav && len > SHORT_INQUIRY_LENGTH) { 1089198708Smav PROBE_SET_ACTION(softc, PROBE_FULL_INQUIRY); 1090198708Smav xpt_release_ccb(done_ccb); 1091198708Smav xpt_schedule(periph, priority); 1092195534Sscottl return; 1093195534Sscottl } 1094198708Smav 1095198708Smav ata_device_transport(path); 1096198708Smav if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 1097198708Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1098198748Smav xpt_acquire_device(path->device); 1099198708Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1100198708Smav xpt_action(done_ccb); 1101198708Smav xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, done_ccb); 1102198708Smav } 1103236613Smav PROBE_SET_ACTION(softc, PROBE_DONE); 1104198708Smav break; 1105195534Sscottl } 1106195534Sscottl case PROBE_PM_PID: 1107198708Smav if ((path->device->flags & CAM_DEV_IDENTIFY_DATA_VALID) == 0) 1108198708Smav bzero(ident_buf, sizeof(*ident_buf)); 1109198708Smav softc->pm_pid = (done_ccb->ataio.res.lba_high << 24) + 1110198708Smav (done_ccb->ataio.res.lba_mid << 16) + 1111198708Smav (done_ccb->ataio.res.lba_low << 8) + 1112198708Smav done_ccb->ataio.res.sector_count; 1113198708Smav ((uint32_t *)ident_buf)[0] = softc->pm_pid; 1114198708Smav snprintf(ident_buf->model, sizeof(ident_buf->model), 1115198708Smav "Port Multiplier %08x", softc->pm_pid); 1116198708Smav PROBE_SET_ACTION(softc, PROBE_PM_PRV); 1117198708Smav xpt_release_ccb(done_ccb); 1118198708Smav xpt_schedule(periph, priority); 1119198708Smav return; 1120195534Sscottl case PROBE_PM_PRV: 1121198708Smav softc->pm_prv = (done_ccb->ataio.res.lba_high << 24) + 1122198708Smav (done_ccb->ataio.res.lba_mid << 16) + 1123198708Smav (done_ccb->ataio.res.lba_low << 8) + 1124198708Smav done_ccb->ataio.res.sector_count; 1125198708Smav ((uint32_t *)ident_buf)[1] = softc->pm_prv; 1126198708Smav snprintf(ident_buf->revision, sizeof(ident_buf->revision), 1127198708Smav "%04x", softc->pm_prv); 1128198708Smav path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 1129236666Smav ata_device_transport(path); 1130236666Smav if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) 1131236666Smav proberequestdefaultnegotiation(periph); 1132207499Smav /* Set supported bits. */ 1133207499Smav bzero(&cts, sizeof(cts)); 1134207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1135207499Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1136207499Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 1137207499Smav xpt_action((union ccb *)&cts); 1138207499Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1139207499Smav caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H; 1140207499Smav else 1141207499Smav caps = 0; 1142207499Smav /* All PMPs must support PM requests. */ 1143207499Smav caps |= CTS_SATA_CAPS_D_PMREQ; 1144207499Smav /* Mask unwanted bits. */ 1145207499Smav bzero(&cts, sizeof(cts)); 1146207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1147207499Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1148207499Smav cts.type = CTS_TYPE_USER_SETTINGS; 1149207499Smav xpt_action((union ccb *)&cts); 1150207499Smav if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1151207499Smav caps &= cts.xport_specific.sata.caps; 1152215454Smav else 1153215454Smav caps = 0; 1154207499Smav /* Store result to SIM. */ 1155207499Smav bzero(&cts, sizeof(cts)); 1156207499Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1157207499Smav cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1158207499Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 1159207499Smav cts.xport_specific.sata.caps = caps; 1160207499Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS; 1161207499Smav xpt_action((union ccb *)&cts); 1162207499Smav softc->caps = caps; 1163238886Smav /* Remember what transport thinks about AEN. */ 1164238886Smav if (softc->caps & CTS_SATA_CAPS_H_AN) 1165238886Smav path->device->inq_flags |= SID_AEN; 1166238886Smav else 1167238886Smav path->device->inq_flags &= ~SID_AEN; 1168238886Smav xpt_async(AC_GETDEV_CHANGED, path, NULL); 1169198708Smav if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 1170198708Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1171198748Smav xpt_acquire_device(path->device); 1172198708Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1173198708Smav xpt_action(done_ccb); 1174198708Smav xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, 1175198708Smav done_ccb); 1176198708Smav } else { 1177198708Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1178198708Smav xpt_action(done_ccb); 1179198708Smav xpt_async(AC_SCSI_AEN, done_ccb->ccb_h.path, done_ccb); 1180195534Sscottl } 1181236613Smav PROBE_SET_ACTION(softc, PROBE_DONE); 1182198708Smav break; 1183235897Smav case PROBE_IDENTIFY_SES: 1184235897Smav case PROBE_IDENTIFY_SAFTE: 1185235897Smav if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) { 1186235897Smav /* Check that it is the same device. */ 1187235897Smav if (bcmp(&softc->ident_data, ident_buf, 53)) { 1188235897Smav /* Device changed. */ 1189235897Smav xpt_async(AC_LOST_DEVICE, path, NULL); 1190235897Smav } else { 1191235897Smav bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 1192235897Smav changed = 0; 1193235897Smav } 1194235897Smav } 1195235897Smav if (changed) { 1196235897Smav bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 1197235897Smav /* Clean up from previous instance of this device */ 1198235897Smav if (path->device->device_id != NULL) { 1199235897Smav free(path->device->device_id, M_CAMXPT); 1200235897Smav path->device->device_id = NULL; 1201235897Smav path->device->device_id_len = 0; 1202235897Smav } 1203235897Smav path->device->device_id = 1204235897Smav malloc(16, M_CAMXPT, M_NOWAIT); 1205235897Smav if (path->device->device_id != NULL) { 1206235897Smav path->device->device_id_len = 16; 1207235897Smav bcopy(&fake_device_id_hdr, 1208235897Smav path->device->device_id, 8); 1209235897Smav bcopy(((uint8_t*)ident_buf) + 2, 1210235897Smav path->device->device_id + 8, 8); 1211235897Smav } 1212235897Smav 1213235897Smav path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 1214235897Smav } 1215236666Smav ata_device_transport(path); 1216236666Smav if (changed) 1217236666Smav proberequestdefaultnegotiation(periph); 1218235897Smav 1219235897Smav if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 1220235897Smav path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1221235897Smav xpt_acquire_device(path->device); 1222235897Smav done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 1223235897Smav xpt_action(done_ccb); 1224235897Smav xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, 1225235897Smav done_ccb); 1226235897Smav } 1227236613Smav PROBE_SET_ACTION(softc, PROBE_DONE); 1228235897Smav break; 1229195534Sscottl default: 1230236613Smav panic("probedone: invalid action state 0x%x\n", softc->action); 1231195534Sscottl } 1232198708Smavdone: 1233203108Smav if (softc->restart) { 1234203108Smav softc->restart = 0; 1235203108Smav xpt_release_ccb(done_ccb); 1236195534Sscottl probeschedule(periph); 1237203108Smav return; 1238195534Sscottl } 1239203108Smav xpt_release_ccb(done_ccb); 1240236613Smav CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe completed\n")); 1241203108Smav while ((done_ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs))) { 1242203108Smav TAILQ_REMOVE(&softc->request_ccbs, 1243203108Smav &done_ccb->ccb_h, periph_links.tqe); 1244203108Smav done_ccb->ccb_h.status = found ? CAM_REQ_CMP : CAM_REQ_CMP_ERR; 1245203108Smav xpt_done(done_ccb); 1246203108Smav } 1247236228Smav cam_periph_invalidate(periph); 1248203108Smav cam_release_devq(periph->path, 1249203108Smav RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_XPT + 1, FALSE); 1250203108Smav cam_periph_release_locked(periph); 1251195534Sscottl} 1252195534Sscottl 1253195534Sscottlstatic void 1254195534Sscottlprobecleanup(struct cam_periph *periph) 1255195534Sscottl{ 1256195534Sscottl free(periph->softc, M_CAMXPT); 1257195534Sscottl} 1258195534Sscottl 1259195534Sscottlstatic void 1260199178Smavata_find_quirk(struct cam_ed *device) 1261195534Sscottl{ 1262199178Smav struct ata_quirk_entry *quirk; 1263195534Sscottl caddr_t match; 1264195534Sscottl 1265199178Smav match = cam_quirkmatch((caddr_t)&device->ident_data, 1266199178Smav (caddr_t)ata_quirk_table, 1267199178Smav ata_quirk_table_size, 1268199178Smav sizeof(*ata_quirk_table), ata_identify_match); 1269195534Sscottl 1270195534Sscottl if (match == NULL) 1271195534Sscottl panic("xpt_find_quirk: device didn't match wildcard entry!!"); 1272195534Sscottl 1273199178Smav quirk = (struct ata_quirk_entry *)match; 1274195534Sscottl device->quirk = quirk; 1275236234Smav if (quirk->quirks & CAM_QUIRK_MAXTAGS) { 1276236234Smav device->mintags = quirk->mintags; 1277236234Smav device->maxtags = quirk->maxtags; 1278236234Smav } 1279195534Sscottl} 1280195534Sscottl 1281195534Sscottltypedef struct { 1282195534Sscottl union ccb *request_ccb; 1283195534Sscottl struct ccb_pathinq *cpi; 1284195534Sscottl int counter; 1285195534Sscottl} ata_scan_bus_info; 1286195534Sscottl 1287195534Sscottl/* 1288195534Sscottl * To start a scan, request_ccb is an XPT_SCAN_BUS ccb. 1289195534Sscottl * As the scan progresses, xpt_scan_bus is used as the 1290195534Sscottl * callback on completion function. 1291195534Sscottl */ 1292195534Sscottlstatic void 1293195534Sscottlata_scan_bus(struct cam_periph *periph, union ccb *request_ccb) 1294195534Sscottl{ 1295195534Sscottl struct cam_path *path; 1296195534Sscottl ata_scan_bus_info *scan_info; 1297203108Smav union ccb *work_ccb, *reset_ccb; 1298195534Sscottl cam_status status; 1299195534Sscottl 1300195534Sscottl CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE, 1301195534Sscottl ("xpt_scan_bus\n")); 1302195534Sscottl switch (request_ccb->ccb_h.func_code) { 1303195534Sscottl case XPT_SCAN_BUS: 1304208582Smjacob case XPT_SCAN_TGT: 1305195534Sscottl /* Find out the characteristics of the bus */ 1306195534Sscottl work_ccb = xpt_alloc_ccb_nowait(); 1307195534Sscottl if (work_ccb == NULL) { 1308195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1309195534Sscottl xpt_done(request_ccb); 1310195534Sscottl return; 1311195534Sscottl } 1312195534Sscottl xpt_setup_ccb(&work_ccb->ccb_h, request_ccb->ccb_h.path, 1313195534Sscottl request_ccb->ccb_h.pinfo.priority); 1314195534Sscottl work_ccb->ccb_h.func_code = XPT_PATH_INQ; 1315195534Sscottl xpt_action(work_ccb); 1316195534Sscottl if (work_ccb->ccb_h.status != CAM_REQ_CMP) { 1317195534Sscottl request_ccb->ccb_h.status = work_ccb->ccb_h.status; 1318195534Sscottl xpt_free_ccb(work_ccb); 1319195534Sscottl xpt_done(request_ccb); 1320195534Sscottl return; 1321195534Sscottl } 1322195534Sscottl 1323203108Smav /* We may need to reset bus first, if we haven't done it yet. */ 1324203108Smav if ((work_ccb->cpi.hba_inquiry & 1325203108Smav (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE)) && 1326203108Smav !(work_ccb->cpi.hba_misc & PIM_NOBUSRESET) && 1327203108Smav !timevalisset(&request_ccb->ccb_h.path->bus->last_reset)) { 1328203108Smav reset_ccb = xpt_alloc_ccb_nowait(); 1329208823Smav if (reset_ccb == NULL) { 1330208823Smav request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1331208823Smav xpt_free_ccb(work_ccb); 1332208823Smav xpt_done(request_ccb); 1333208823Smav return; 1334208823Smav } 1335203108Smav xpt_setup_ccb(&reset_ccb->ccb_h, request_ccb->ccb_h.path, 1336203108Smav CAM_PRIORITY_NONE); 1337203108Smav reset_ccb->ccb_h.func_code = XPT_RESET_BUS; 1338203108Smav xpt_action(reset_ccb); 1339203108Smav if (reset_ccb->ccb_h.status != CAM_REQ_CMP) { 1340203108Smav request_ccb->ccb_h.status = reset_ccb->ccb_h.status; 1341203108Smav xpt_free_ccb(reset_ccb); 1342203108Smav xpt_free_ccb(work_ccb); 1343203108Smav xpt_done(request_ccb); 1344203108Smav return; 1345203108Smav } 1346203108Smav xpt_free_ccb(reset_ccb); 1347203108Smav } 1348203108Smav 1349195534Sscottl /* Save some state for use while we probe for devices */ 1350195534Sscottl scan_info = (ata_scan_bus_info *) 1351195534Sscottl malloc(sizeof(ata_scan_bus_info), M_CAMXPT, M_NOWAIT); 1352195534Sscottl if (scan_info == NULL) { 1353195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1354208823Smav xpt_free_ccb(work_ccb); 1355195534Sscottl xpt_done(request_ccb); 1356195534Sscottl return; 1357195534Sscottl } 1358195534Sscottl scan_info->request_ccb = request_ccb; 1359195534Sscottl scan_info->cpi = &work_ccb->cpi; 1360195534Sscottl /* If PM supported, probe it first. */ 1361195534Sscottl if (scan_info->cpi->hba_inquiry & PI_SATAPM) 1362201990Smav scan_info->counter = scan_info->cpi->max_target; 1363201990Smav else 1364201990Smav scan_info->counter = 0; 1365195534Sscottl 1366195534Sscottl work_ccb = xpt_alloc_ccb_nowait(); 1367195534Sscottl if (work_ccb == NULL) { 1368195534Sscottl free(scan_info, M_CAMXPT); 1369195534Sscottl request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1370195534Sscottl xpt_done(request_ccb); 1371195534Sscottl break; 1372195534Sscottl } 1373195534Sscottl goto scan_next; 1374195534Sscottl case XPT_SCAN_LUN: 1375195534Sscottl work_ccb = request_ccb; 1376195534Sscottl /* Reuse the same CCB to query if a device was really found */ 1377195534Sscottl scan_info = (ata_scan_bus_info *)work_ccb->ccb_h.ppriv_ptr0; 1378198389Smav /* If there is PMP... */ 1379201990Smav if ((scan_info->cpi->hba_inquiry & PI_SATAPM) && 1380201990Smav (scan_info->counter == scan_info->cpi->max_target)) { 1381203108Smav if (work_ccb->ccb_h.status == CAM_REQ_CMP) { 1382207428Smav /* everything else will be probed by it */ 1383207428Smav /* Free the current request path- we're done with it. */ 1384207428Smav xpt_free_path(work_ccb->ccb_h.path); 1385201990Smav goto done; 1386195534Sscottl } else { 1387195534Sscottl struct ccb_trans_settings cts; 1388195534Sscottl 1389195534Sscottl /* Report SIM that PM is absent. */ 1390195534Sscottl bzero(&cts, sizeof(cts)); 1391195534Sscottl xpt_setup_ccb(&cts.ccb_h, 1392207428Smav work_ccb->ccb_h.path, CAM_PRIORITY_NONE); 1393195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1394195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 1395195665Smav cts.xport_specific.sata.pm_present = 0; 1396195534Sscottl cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; 1397195534Sscottl xpt_action((union ccb *)&cts); 1398195534Sscottl } 1399195534Sscottl } 1400207428Smav /* Free the current request path- we're done with it. */ 1401207428Smav xpt_free_path(work_ccb->ccb_h.path); 1402201990Smav if (scan_info->counter == 1403201990Smav ((scan_info->cpi->hba_inquiry & PI_SATAPM) ? 1404201990Smav 0 : scan_info->cpi->max_target)) { 1405201990Smavdone: 1406195534Sscottl xpt_free_ccb(work_ccb); 1407195534Sscottl xpt_free_ccb((union ccb *)scan_info->cpi); 1408195534Sscottl request_ccb = scan_info->request_ccb; 1409195534Sscottl free(scan_info, M_CAMXPT); 1410195534Sscottl request_ccb->ccb_h.status = CAM_REQ_CMP; 1411195534Sscottl xpt_done(request_ccb); 1412195534Sscottl break; 1413195534Sscottl } 1414201990Smav /* Take next device. Wrap from max (PMP) to 0. */ 1415201990Smav scan_info->counter = (scan_info->counter + 1 ) % 1416201990Smav (scan_info->cpi->max_target + 1); 1417195534Sscottlscan_next: 1418195534Sscottl status = xpt_create_path(&path, xpt_periph, 1419195534Sscottl scan_info->request_ccb->ccb_h.path_id, 1420195534Sscottl scan_info->counter, 0); 1421195534Sscottl if (status != CAM_REQ_CMP) { 1422195534Sscottl printf("xpt_scan_bus: xpt_create_path failed" 1423195534Sscottl " with status %#x, bus scan halted\n", 1424195534Sscottl status); 1425195534Sscottl xpt_free_ccb(work_ccb); 1426195534Sscottl xpt_free_ccb((union ccb *)scan_info->cpi); 1427195534Sscottl request_ccb = scan_info->request_ccb; 1428195534Sscottl free(scan_info, M_CAMXPT); 1429195534Sscottl request_ccb->ccb_h.status = status; 1430195534Sscottl xpt_done(request_ccb); 1431195534Sscottl break; 1432195534Sscottl } 1433195534Sscottl xpt_setup_ccb(&work_ccb->ccb_h, path, 1434195534Sscottl scan_info->request_ccb->ccb_h.pinfo.priority); 1435195534Sscottl work_ccb->ccb_h.func_code = XPT_SCAN_LUN; 1436195534Sscottl work_ccb->ccb_h.cbfcnp = ata_scan_bus; 1437195534Sscottl work_ccb->ccb_h.ppriv_ptr0 = scan_info; 1438195534Sscottl work_ccb->crcn.flags = scan_info->request_ccb->crcn.flags; 1439195534Sscottl xpt_action(work_ccb); 1440195534Sscottl break; 1441195534Sscottl default: 1442195534Sscottl break; 1443195534Sscottl } 1444195534Sscottl} 1445195534Sscottl 1446195534Sscottlstatic void 1447195534Sscottlata_scan_lun(struct cam_periph *periph, struct cam_path *path, 1448195534Sscottl cam_flags flags, union ccb *request_ccb) 1449195534Sscottl{ 1450195534Sscottl struct ccb_pathinq cpi; 1451195534Sscottl cam_status status; 1452195534Sscottl struct cam_path *new_path; 1453195534Sscottl struct cam_periph *old_periph; 1454195534Sscottl 1455203108Smav CAM_DEBUG(path, CAM_DEBUG_TRACE, ("xpt_scan_lun\n")); 1456195534Sscottl 1457203108Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 1458195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 1459195534Sscottl xpt_action((union ccb *)&cpi); 1460195534Sscottl 1461195534Sscottl if (cpi.ccb_h.status != CAM_REQ_CMP) { 1462195534Sscottl if (request_ccb != NULL) { 1463195534Sscottl request_ccb->ccb_h.status = cpi.ccb_h.status; 1464195534Sscottl xpt_done(request_ccb); 1465195534Sscottl } 1466195534Sscottl return; 1467195534Sscottl } 1468195534Sscottl 1469195534Sscottl if (request_ccb == NULL) { 1470195534Sscottl request_ccb = malloc(sizeof(union ccb), M_CAMXPT, M_NOWAIT); 1471195534Sscottl if (request_ccb == NULL) { 1472195534Sscottl xpt_print(path, "xpt_scan_lun: can't allocate CCB, " 1473195534Sscottl "can't continue\n"); 1474195534Sscottl return; 1475195534Sscottl } 1476195534Sscottl new_path = malloc(sizeof(*new_path), M_CAMXPT, M_NOWAIT); 1477195534Sscottl if (new_path == NULL) { 1478195534Sscottl xpt_print(path, "xpt_scan_lun: can't allocate path, " 1479195534Sscottl "can't continue\n"); 1480195534Sscottl free(request_ccb, M_CAMXPT); 1481195534Sscottl return; 1482195534Sscottl } 1483195534Sscottl status = xpt_compile_path(new_path, xpt_periph, 1484195534Sscottl path->bus->path_id, 1485195534Sscottl path->target->target_id, 1486195534Sscottl path->device->lun_id); 1487195534Sscottl 1488195534Sscottl if (status != CAM_REQ_CMP) { 1489195534Sscottl xpt_print(path, "xpt_scan_lun: can't compile path, " 1490195534Sscottl "can't continue\n"); 1491195534Sscottl free(request_ccb, M_CAMXPT); 1492195534Sscottl free(new_path, M_CAMXPT); 1493195534Sscottl return; 1494195534Sscottl } 1495203108Smav xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_XPT); 1496195534Sscottl request_ccb->ccb_h.cbfcnp = xptscandone; 1497195534Sscottl request_ccb->ccb_h.func_code = XPT_SCAN_LUN; 1498195534Sscottl request_ccb->crcn.flags = flags; 1499195534Sscottl } 1500195534Sscottl 1501195653Smav if ((old_periph = cam_periph_find(path, "aprobe")) != NULL) { 1502236228Smav if ((old_periph->flags & CAM_PERIPH_INVALID) == 0) { 1503236228Smav probe_softc *softc; 1504195534Sscottl 1505236228Smav softc = (probe_softc *)old_periph->softc; 1506236228Smav TAILQ_INSERT_TAIL(&softc->request_ccbs, 1507236228Smav &request_ccb->ccb_h, periph_links.tqe); 1508236228Smav softc->restart = 1; 1509236228Smav } else { 1510236228Smav request_ccb->ccb_h.status = CAM_REQ_CMP_ERR; 1511236228Smav xpt_done(request_ccb); 1512236228Smav } 1513195534Sscottl } else { 1514195534Sscottl status = cam_periph_alloc(proberegister, NULL, probecleanup, 1515195653Smav probestart, "aprobe", 1516195534Sscottl CAM_PERIPH_BIO, 1517195534Sscottl request_ccb->ccb_h.path, NULL, 0, 1518195534Sscottl request_ccb); 1519195534Sscottl 1520195534Sscottl if (status != CAM_REQ_CMP) { 1521195534Sscottl xpt_print(path, "xpt_scan_lun: cam_alloc_periph " 1522195534Sscottl "returned an error, can't continue probe\n"); 1523195534Sscottl request_ccb->ccb_h.status = status; 1524195534Sscottl xpt_done(request_ccb); 1525195534Sscottl } 1526195534Sscottl } 1527195534Sscottl} 1528195534Sscottl 1529195534Sscottlstatic void 1530195534Sscottlxptscandone(struct cam_periph *periph, union ccb *done_ccb) 1531195534Sscottl{ 1532195534Sscottl xpt_release_path(done_ccb->ccb_h.path); 1533195534Sscottl free(done_ccb->ccb_h.path, M_CAMXPT); 1534195534Sscottl free(done_ccb, M_CAMXPT); 1535195534Sscottl} 1536195534Sscottl 1537195534Sscottlstatic struct cam_ed * 1538195534Sscottlata_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id) 1539195534Sscottl{ 1540195534Sscottl struct cam_path path; 1541199178Smav struct ata_quirk_entry *quirk; 1542195534Sscottl struct cam_ed *device; 1543195534Sscottl struct cam_ed *cur_device; 1544195534Sscottl 1545195534Sscottl device = xpt_alloc_device(bus, target, lun_id); 1546195534Sscottl if (device == NULL) 1547195534Sscottl return (NULL); 1548195534Sscottl 1549195534Sscottl /* 1550195534Sscottl * Take the default quirk entry until we have inquiry 1551195534Sscottl * data and can determine a better quirk to use. 1552195534Sscottl */ 1553199178Smav quirk = &ata_quirk_table[ata_quirk_table_size - 1]; 1554195534Sscottl device->quirk = (void *)quirk; 1555199178Smav device->mintags = 0; 1556199178Smav device->maxtags = 0; 1557195534Sscottl bzero(&device->inq_data, sizeof(device->inq_data)); 1558195534Sscottl device->inq_flags = 0; 1559195534Sscottl device->queue_flags = 0; 1560195534Sscottl device->serial_num = NULL; 1561195534Sscottl device->serial_num_len = 0; 1562195534Sscottl 1563195534Sscottl /* 1564195534Sscottl * XXX should be limited by number of CCBs this bus can 1565195534Sscottl * do. 1566195534Sscottl */ 1567195534Sscottl bus->sim->max_ccbs += device->ccbq.devq_openings; 1568195534Sscottl /* Insertion sort into our target's device list */ 1569195534Sscottl cur_device = TAILQ_FIRST(&target->ed_entries); 1570195534Sscottl while (cur_device != NULL && cur_device->lun_id < lun_id) 1571195534Sscottl cur_device = TAILQ_NEXT(cur_device, links); 1572195534Sscottl if (cur_device != NULL) { 1573195534Sscottl TAILQ_INSERT_BEFORE(cur_device, device, links); 1574195534Sscottl } else { 1575195534Sscottl TAILQ_INSERT_TAIL(&target->ed_entries, device, links); 1576195534Sscottl } 1577195534Sscottl target->generation++; 1578195534Sscottl if (lun_id != CAM_LUN_WILDCARD) { 1579195534Sscottl xpt_compile_path(&path, 1580195534Sscottl NULL, 1581195534Sscottl bus->path_id, 1582195534Sscottl target->target_id, 1583195534Sscottl lun_id); 1584195534Sscottl ata_device_transport(&path); 1585195534Sscottl xpt_release_path(&path); 1586195534Sscottl } 1587195534Sscottl 1588195534Sscottl return (device); 1589195534Sscottl} 1590195534Sscottl 1591195534Sscottlstatic void 1592195534Sscottlata_device_transport(struct cam_path *path) 1593195534Sscottl{ 1594195534Sscottl struct ccb_pathinq cpi; 1595198331Smav struct ccb_trans_settings cts; 1596198331Smav struct scsi_inquiry_data *inq_buf = NULL; 1597198331Smav struct ata_params *ident_buf = NULL; 1598195534Sscottl 1599195534Sscottl /* Get transport information from the SIM */ 1600203108Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 1601195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 1602195534Sscottl xpt_action((union ccb *)&cpi); 1603195534Sscottl 1604195534Sscottl path->device->transport = cpi.transport; 1605198331Smav if ((path->device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0) 1606198331Smav inq_buf = &path->device->inq_data; 1607198331Smav if ((path->device->flags & CAM_DEV_IDENTIFY_DATA_VALID) != 0) 1608198331Smav ident_buf = &path->device->ident_data; 1609198331Smav if (path->device->protocol == PROTO_ATA) { 1610198331Smav path->device->protocol_version = ident_buf ? 1611198331Smav ata_version(ident_buf->version_major) : cpi.protocol_version; 1612198331Smav } else if (path->device->protocol == PROTO_SCSI) { 1613198331Smav path->device->protocol_version = inq_buf ? 1614198331Smav SID_ANSI_REV(inq_buf) : cpi.protocol_version; 1615195534Sscottl } 1616198331Smav path->device->transport_version = ident_buf ? 1617198331Smav ata_version(ident_buf->version_major) : cpi.transport_version; 1618195534Sscottl 1619195534Sscottl /* Tell the controller what we think */ 1620203108Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1621195534Sscottl cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1622195534Sscottl cts.type = CTS_TYPE_CURRENT_SETTINGS; 1623195534Sscottl cts.transport = path->device->transport; 1624195534Sscottl cts.transport_version = path->device->transport_version; 1625195534Sscottl cts.protocol = path->device->protocol; 1626195534Sscottl cts.protocol_version = path->device->protocol_version; 1627195534Sscottl cts.proto_specific.valid = 0; 1628203376Smav if (ident_buf) { 1629203376Smav if (path->device->transport == XPORT_ATA) { 1630223019Smav cts.xport_specific.ata.atapi = 1631223019Smav (ident_buf->config == ATA_PROTO_CFA) ? 0 : 1632203376Smav ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_16) ? 16 : 1633203376Smav ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) ? 12 : 0; 1634203376Smav cts.xport_specific.ata.valid = CTS_ATA_VALID_ATAPI; 1635203376Smav } else { 1636223019Smav cts.xport_specific.sata.atapi = 1637223019Smav (ident_buf->config == ATA_PROTO_CFA) ? 0 : 1638203376Smav ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_16) ? 16 : 1639203376Smav ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) ? 12 : 0; 1640203376Smav cts.xport_specific.sata.valid = CTS_SATA_VALID_ATAPI; 1641203376Smav } 1642203376Smav } else 1643203376Smav cts.xport_specific.valid = 0; 1644195534Sscottl xpt_action((union ccb *)&cts); 1645195534Sscottl} 1646195534Sscottl 1647195534Sscottlstatic void 1648223443Swillata_dev_advinfo(union ccb *start_ccb) 1649223443Swill{ 1650223443Swill struct cam_ed *device; 1651223443Swill struct ccb_dev_advinfo *cdai; 1652223443Swill off_t amt; 1653223443Swill 1654223443Swill start_ccb->ccb_h.status = CAM_REQ_INVALID; 1655223443Swill device = start_ccb->ccb_h.path->device; 1656223443Swill cdai = &start_ccb->cdai; 1657223443Swill switch(cdai->buftype) { 1658235897Smav case CDAI_TYPE_SCSI_DEVID: 1659235897Smav if (cdai->flags & CDAI_FLAG_STORE) 1660235897Smav return; 1661235897Smav cdai->provsiz = device->device_id_len; 1662235897Smav if (device->device_id_len == 0) 1663235897Smav break; 1664235897Smav amt = device->device_id_len; 1665235897Smav if (cdai->provsiz > cdai->bufsiz) 1666235897Smav amt = cdai->bufsiz; 1667235897Smav memcpy(cdai->buf, device->device_id, amt); 1668235897Smav break; 1669223443Swill case CDAI_TYPE_SERIAL_NUM: 1670223443Swill if (cdai->flags & CDAI_FLAG_STORE) 1671235897Smav return; 1672223443Swill cdai->provsiz = device->serial_num_len; 1673223443Swill if (device->serial_num_len == 0) 1674223443Swill break; 1675223443Swill amt = device->serial_num_len; 1676223443Swill if (cdai->provsiz > cdai->bufsiz) 1677223443Swill amt = cdai->bufsiz; 1678223443Swill memcpy(cdai->buf, device->serial_num, amt); 1679223443Swill break; 1680235897Smav case CDAI_TYPE_PHYS_PATH: 1681235897Smav if (cdai->flags & CDAI_FLAG_STORE) { 1682235897Smav if (device->physpath != NULL) 1683235897Smav free(device->physpath, M_CAMXPT); 1684235897Smav device->physpath_len = cdai->bufsiz; 1685235897Smav /* Clear existing buffer if zero length */ 1686235897Smav if (cdai->bufsiz == 0) 1687235897Smav break; 1688235897Smav device->physpath = malloc(cdai->bufsiz, M_CAMXPT, M_NOWAIT); 1689235897Smav if (device->physpath == NULL) { 1690235897Smav start_ccb->ccb_h.status = CAM_REQ_ABORTED; 1691235897Smav return; 1692235897Smav } 1693235897Smav memcpy(device->physpath, cdai->buf, cdai->bufsiz); 1694235897Smav } else { 1695235897Smav cdai->provsiz = device->physpath_len; 1696235897Smav if (device->physpath_len == 0) 1697235897Smav break; 1698235897Smav amt = device->physpath_len; 1699235897Smav if (cdai->provsiz > cdai->bufsiz) 1700235897Smav amt = cdai->bufsiz; 1701235897Smav memcpy(cdai->buf, device->physpath, amt); 1702235897Smav } 1703235897Smav break; 1704223443Swill default: 1705235897Smav return; 1706223443Swill } 1707235897Smav start_ccb->ccb_h.status = CAM_REQ_CMP; 1708235897Smav 1709235897Smav if (cdai->flags & CDAI_FLAG_STORE) { 1710235897Smav int owned; 1711235897Smav 1712235897Smav owned = mtx_owned(start_ccb->ccb_h.path->bus->sim->mtx); 1713235897Smav if (owned == 0) 1714235897Smav mtx_lock(start_ccb->ccb_h.path->bus->sim->mtx); 1715235897Smav xpt_async(AC_ADVINFO_CHANGED, start_ccb->ccb_h.path, 1716235897Smav (void *)(uintptr_t)cdai->buftype); 1717235897Smav if (owned == 0) 1718235897Smav mtx_unlock(start_ccb->ccb_h.path->bus->sim->mtx); 1719235897Smav } 1720223443Swill} 1721223443Swill 1722223443Swillstatic void 1723195534Sscottlata_action(union ccb *start_ccb) 1724195534Sscottl{ 1725195534Sscottl 1726195534Sscottl switch (start_ccb->ccb_h.func_code) { 1727195534Sscottl case XPT_SET_TRAN_SETTINGS: 1728195534Sscottl { 1729199178Smav ata_set_transfer_settings(&start_ccb->cts, 1730195534Sscottl start_ccb->ccb_h.path->device, 1731195534Sscottl /*async_update*/FALSE); 1732195534Sscottl break; 1733195534Sscottl } 1734195534Sscottl case XPT_SCAN_BUS: 1735208582Smjacob case XPT_SCAN_TGT: 1736195534Sscottl ata_scan_bus(start_ccb->ccb_h.path->periph, start_ccb); 1737195534Sscottl break; 1738195534Sscottl case XPT_SCAN_LUN: 1739195534Sscottl ata_scan_lun(start_ccb->ccb_h.path->periph, 1740195534Sscottl start_ccb->ccb_h.path, start_ccb->crcn.flags, 1741195534Sscottl start_ccb); 1742195534Sscottl break; 1743195534Sscottl case XPT_GET_TRAN_SETTINGS: 1744195534Sscottl { 1745236437Smav ata_get_transfer_settings(&start_ccb->cts); 1746195534Sscottl break; 1747195534Sscottl } 1748203376Smav case XPT_SCSI_IO: 1749203376Smav { 1750203376Smav struct cam_ed *device; 1751203376Smav u_int maxlen = 0; 1752203376Smav 1753203376Smav device = start_ccb->ccb_h.path->device; 1754203376Smav if (device->protocol == PROTO_SCSI && 1755203376Smav (device->flags & CAM_DEV_IDENTIFY_DATA_VALID)) { 1756203376Smav uint16_t p = 1757203376Smav device->ident_data.config & ATA_PROTO_MASK; 1758203376Smav 1759223019Smav maxlen = 1760223019Smav (device->ident_data.config == ATA_PROTO_CFA) ? 0 : 1761223019Smav (p == ATA_PROTO_ATAPI_16) ? 16 : 1762203376Smav (p == ATA_PROTO_ATAPI_12) ? 12 : 0; 1763203376Smav } 1764203376Smav if (start_ccb->csio.cdb_len > maxlen) { 1765203376Smav start_ccb->ccb_h.status = CAM_REQ_INVALID; 1766203376Smav xpt_done(start_ccb); 1767203376Smav break; 1768203376Smav } 1769223475Smav xpt_action_default(start_ccb); 1770223475Smav break; 1771203376Smav } 1772223443Swill case XPT_DEV_ADVINFO: 1773223443Swill { 1774223443Swill ata_dev_advinfo(start_ccb); 1775223443Swill break; 1776223443Swill } 1777195534Sscottl default: 1778195534Sscottl xpt_action_default(start_ccb); 1779195534Sscottl break; 1780195534Sscottl } 1781195534Sscottl} 1782195534Sscottl 1783195534Sscottlstatic void 1784236437Smavata_get_transfer_settings(struct ccb_trans_settings *cts) 1785236437Smav{ 1786236437Smav struct ccb_trans_settings_ata *ata; 1787236437Smav struct ccb_trans_settings_scsi *scsi; 1788236437Smav struct cam_ed *device; 1789236437Smav struct cam_sim *sim; 1790236437Smav 1791236437Smav device = cts->ccb_h.path->device; 1792236437Smav sim = cts->ccb_h.path->bus->sim; 1793236437Smav (*(sim->sim_action))(sim, (union ccb *)cts); 1794236437Smav 1795236666Smav if (cts->protocol == PROTO_UNKNOWN || 1796236666Smav cts->protocol == PROTO_UNSPECIFIED) { 1797236666Smav cts->protocol = device->protocol; 1798236666Smav cts->protocol_version = device->protocol_version; 1799236666Smav } 1800236666Smav 1801236437Smav if (cts->protocol == PROTO_ATA) { 1802236437Smav ata = &cts->proto_specific.ata; 1803236437Smav if ((ata->valid & CTS_ATA_VALID_TQ) == 0) { 1804236437Smav ata->valid |= CTS_ATA_VALID_TQ; 1805236437Smav if (cts->type == CTS_TYPE_USER_SETTINGS || 1806236437Smav (device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 || 1807236437Smav (device->inq_flags & SID_CmdQue) != 0) 1808236437Smav ata->flags |= CTS_ATA_FLAGS_TAG_ENB; 1809236437Smav } 1810236437Smav } 1811236437Smav if (cts->protocol == PROTO_SCSI) { 1812236437Smav scsi = &cts->proto_specific.scsi; 1813236437Smav if ((scsi->valid & CTS_SCSI_VALID_TQ) == 0) { 1814236437Smav scsi->valid |= CTS_SCSI_VALID_TQ; 1815236437Smav if (cts->type == CTS_TYPE_USER_SETTINGS || 1816236437Smav (device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 || 1817236437Smav (device->inq_flags & SID_CmdQue) != 0) 1818236437Smav scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 1819236437Smav } 1820236437Smav } 1821236666Smav 1822236666Smav if (cts->transport == XPORT_UNKNOWN || 1823236666Smav cts->transport == XPORT_UNSPECIFIED) { 1824236666Smav cts->transport = device->transport; 1825236666Smav cts->transport_version = device->transport_version; 1826236666Smav } 1827236437Smav} 1828236437Smav 1829236437Smavstatic void 1830199178Smavata_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device, 1831195534Sscottl int async_update) 1832195534Sscottl{ 1833195534Sscottl struct ccb_pathinq cpi; 1834236437Smav struct ccb_trans_settings_ata *ata; 1835195534Sscottl struct ccb_trans_settings_scsi *scsi; 1836195534Sscottl struct cam_sim *sim; 1837236437Smav struct ata_params *ident_data; 1838195534Sscottl struct scsi_inquiry_data *inq_data; 1839195534Sscottl 1840195534Sscottl if (device == NULL) { 1841195534Sscottl cts->ccb_h.status = CAM_PATH_INVALID; 1842195534Sscottl xpt_done((union ccb *)cts); 1843195534Sscottl return; 1844195534Sscottl } 1845195534Sscottl 1846195534Sscottl if (cts->protocol == PROTO_UNKNOWN 1847195534Sscottl || cts->protocol == PROTO_UNSPECIFIED) { 1848195534Sscottl cts->protocol = device->protocol; 1849195534Sscottl cts->protocol_version = device->protocol_version; 1850195534Sscottl } 1851195534Sscottl 1852195534Sscottl if (cts->protocol_version == PROTO_VERSION_UNKNOWN 1853195534Sscottl || cts->protocol_version == PROTO_VERSION_UNSPECIFIED) 1854195534Sscottl cts->protocol_version = device->protocol_version; 1855195534Sscottl 1856195534Sscottl if (cts->protocol != device->protocol) { 1857195534Sscottl xpt_print(cts->ccb_h.path, "Uninitialized Protocol %x:%x?\n", 1858195534Sscottl cts->protocol, device->protocol); 1859195534Sscottl cts->protocol = device->protocol; 1860195534Sscottl } 1861195534Sscottl 1862195534Sscottl if (cts->protocol_version > device->protocol_version) { 1863195534Sscottl if (bootverbose) { 1864195534Sscottl xpt_print(cts->ccb_h.path, "Down reving Protocol " 1865195534Sscottl "Version from %d to %d?\n", cts->protocol_version, 1866195534Sscottl device->protocol_version); 1867195534Sscottl } 1868195534Sscottl cts->protocol_version = device->protocol_version; 1869195534Sscottl } 1870195534Sscottl 1871195534Sscottl if (cts->transport == XPORT_UNKNOWN 1872195534Sscottl || cts->transport == XPORT_UNSPECIFIED) { 1873195534Sscottl cts->transport = device->transport; 1874195534Sscottl cts->transport_version = device->transport_version; 1875195534Sscottl } 1876195534Sscottl 1877195534Sscottl if (cts->transport_version == XPORT_VERSION_UNKNOWN 1878195534Sscottl || cts->transport_version == XPORT_VERSION_UNSPECIFIED) 1879195534Sscottl cts->transport_version = device->transport_version; 1880195534Sscottl 1881195534Sscottl if (cts->transport != device->transport) { 1882195534Sscottl xpt_print(cts->ccb_h.path, "Uninitialized Transport %x:%x?\n", 1883195534Sscottl cts->transport, device->transport); 1884195534Sscottl cts->transport = device->transport; 1885195534Sscottl } 1886195534Sscottl 1887195534Sscottl if (cts->transport_version > device->transport_version) { 1888195534Sscottl if (bootverbose) { 1889195534Sscottl xpt_print(cts->ccb_h.path, "Down reving Transport " 1890195534Sscottl "Version from %d to %d?\n", cts->transport_version, 1891195534Sscottl device->transport_version); 1892195534Sscottl } 1893195534Sscottl cts->transport_version = device->transport_version; 1894195534Sscottl } 1895195534Sscottl 1896195534Sscottl sim = cts->ccb_h.path->bus->sim; 1897236437Smav ident_data = &device->ident_data; 1898195534Sscottl inq_data = &device->inq_data; 1899236437Smav if (cts->protocol == PROTO_ATA) 1900236437Smav ata = &cts->proto_specific.ata; 1901236437Smav else 1902236437Smav ata = NULL; 1903236437Smav if (cts->protocol == PROTO_SCSI) 1904236437Smav scsi = &cts->proto_specific.scsi; 1905236437Smav else 1906236437Smav scsi = NULL; 1907203108Smav xpt_setup_ccb(&cpi.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NONE); 1908195534Sscottl cpi.ccb_h.func_code = XPT_PATH_INQ; 1909195534Sscottl xpt_action((union ccb *)&cpi); 1910195534Sscottl 1911236437Smav /* Sanity checking */ 1912195534Sscottl if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0 1913236437Smav || (ata && (ident_data->satacapabilities & ATA_SUPPORT_NCQ) == 0) 1914236437Smav || (scsi && (INQ_DATA_TQ_ENABLED(inq_data)) == 0) 1915195534Sscottl || (device->queue_flags & SCP_QUEUE_DQUE) != 0 1916195534Sscottl || (device->mintags == 0)) { 1917195534Sscottl /* 1918195534Sscottl * Can't tag on hardware that doesn't support tags, 1919195534Sscottl * doesn't have it enabled, or has broken tag support. 1920195534Sscottl */ 1921236437Smav if (ata) 1922236437Smav ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB; 1923236437Smav if (scsi) 1924195534Sscottl scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 1925195534Sscottl } 1926195534Sscottl 1927236437Smav /* Start/stop tags use. */ 1928236437Smav if (cts->type == CTS_TYPE_CURRENT_SETTINGS && 1929236437Smav ((ata && (ata->valid & CTS_ATA_VALID_TQ) != 0) || 1930236437Smav (scsi && (scsi->valid & CTS_SCSI_VALID_TQ) != 0))) { 1931236437Smav int nowt, newt = 0; 1932195534Sscottl 1933236437Smav nowt = ((device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 || 1934236437Smav (device->inq_flags & SID_CmdQue) != 0); 1935236437Smav if (ata) 1936236437Smav newt = (ata->flags & CTS_ATA_FLAGS_TAG_ENB) != 0; 1937236437Smav if (scsi) 1938236437Smav newt = (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0; 1939195534Sscottl 1940236437Smav if (newt && !nowt) { 1941236437Smav /* 1942236437Smav * Delay change to use tags until after a 1943236437Smav * few commands have gone to this device so 1944236437Smav * the controller has time to perform transfer 1945236437Smav * negotiations without tagged messages getting 1946236437Smav * in the way. 1947236437Smav */ 1948236437Smav device->tag_delay_count = CAM_TAG_DELAY_COUNT; 1949236437Smav device->flags |= CAM_DEV_TAG_AFTER_COUNT; 1950236437Smav } else if (nowt && !newt) 1951236437Smav xpt_stop_tags(cts->ccb_h.path); 1952236437Smav } 1953195534Sscottl 1954195534Sscottl if (async_update == FALSE) 1955195534Sscottl (*(sim->sim_action))(sim, (union ccb *)cts); 1956195534Sscottl} 1957195534Sscottl 1958195534Sscottl/* 1959195534Sscottl * Handle any per-device event notifications that require action by the XPT. 1960195534Sscottl */ 1961195534Sscottlstatic void 1962195534Sscottlata_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target, 1963195534Sscottl struct cam_ed *device, void *async_arg) 1964195534Sscottl{ 1965195534Sscottl cam_status status; 1966195534Sscottl struct cam_path newpath; 1967195534Sscottl 1968195534Sscottl /* 1969195534Sscottl * We only need to handle events for real devices. 1970195534Sscottl */ 1971195534Sscottl if (target->target_id == CAM_TARGET_WILDCARD 1972195534Sscottl || device->lun_id == CAM_LUN_WILDCARD) 1973195534Sscottl return; 1974195534Sscottl 1975195534Sscottl /* 1976195534Sscottl * We need our own path with wildcards expanded to 1977195534Sscottl * handle certain types of events. 1978195534Sscottl */ 1979195534Sscottl if ((async_code == AC_SENT_BDR) 1980195534Sscottl || (async_code == AC_BUS_RESET) 1981195534Sscottl || (async_code == AC_INQ_CHANGED)) 1982195534Sscottl status = xpt_compile_path(&newpath, NULL, 1983195534Sscottl bus->path_id, 1984195534Sscottl target->target_id, 1985195534Sscottl device->lun_id); 1986195534Sscottl else 1987195534Sscottl status = CAM_REQ_CMP_ERR; 1988195534Sscottl 1989195534Sscottl if (status == CAM_REQ_CMP) { 1990195534Sscottl if (async_code == AC_INQ_CHANGED) { 1991195534Sscottl /* 1992195534Sscottl * We've sent a start unit command, or 1993195534Sscottl * something similar to a device that 1994195534Sscottl * may have caused its inquiry data to 1995195534Sscottl * change. So we re-scan the device to 1996195534Sscottl * refresh the inquiry data for it. 1997195534Sscottl */ 1998195534Sscottl ata_scan_lun(newpath.periph, &newpath, 1999195534Sscottl CAM_EXPECT_INQ_CHANGE, NULL); 2000203108Smav } else { 2001203108Smav /* We need to reinitialize device after reset. */ 2002203108Smav ata_scan_lun(newpath.periph, &newpath, 2003203108Smav 0, NULL); 2004195534Sscottl } 2005195534Sscottl xpt_release_path(&newpath); 2006198748Smav } else if (async_code == AC_LOST_DEVICE && 2007198748Smav (device->flags & CAM_DEV_UNCONFIGURED) == 0) { 2008195534Sscottl device->flags |= CAM_DEV_UNCONFIGURED; 2009198748Smav xpt_release_device(device); 2010195534Sscottl } else if (async_code == AC_TRANSFER_NEG) { 2011195534Sscottl struct ccb_trans_settings *settings; 2012195534Sscottl 2013195534Sscottl settings = (struct ccb_trans_settings *)async_arg; 2014199178Smav ata_set_transfer_settings(settings, device, 2015195534Sscottl /*async_update*/TRUE); 2016195534Sscottl } 2017195534Sscottl} 2018195534Sscottl 2019204220Smavstatic void 2020204220Smavata_announce_periph(struct cam_periph *periph) 2021204220Smav{ 2022204220Smav struct ccb_pathinq cpi; 2023204220Smav struct ccb_trans_settings cts; 2024204220Smav struct cam_path *path = periph->path; 2025204220Smav u_int speed; 2026204220Smav u_int mb; 2027204220Smav 2028204220Smav mtx_assert(periph->sim->mtx, MA_OWNED); 2029204220Smav 2030204220Smav xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); 2031204220Smav cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 2032204220Smav cts.type = CTS_TYPE_CURRENT_SETTINGS; 2033204220Smav xpt_action((union ccb*)&cts); 2034204220Smav if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 2035204220Smav return; 2036204220Smav /* Ask the SIM for its base transfer speed */ 2037204220Smav xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL); 2038204220Smav cpi.ccb_h.func_code = XPT_PATH_INQ; 2039204220Smav xpt_action((union ccb *)&cpi); 2040204220Smav /* Report connection speed */ 2041204220Smav speed = cpi.base_transfer_speed; 2042204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_ATA) { 2043236437Smav struct ccb_trans_settings_pata *pata = 2044204220Smav &cts.xport_specific.ata; 2045204220Smav 2046236437Smav if (pata->valid & CTS_ATA_VALID_MODE) 2047236437Smav speed = ata_mode2speed(pata->mode); 2048204220Smav } 2049204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SATA) { 2050204220Smav struct ccb_trans_settings_sata *sata = 2051204220Smav &cts.xport_specific.sata; 2052204220Smav 2053204220Smav if (sata->valid & CTS_SATA_VALID_REVISION) 2054204220Smav speed = ata_revision2speed(sata->revision); 2055204220Smav } 2056204220Smav mb = speed / 1000; 2057204220Smav if (mb > 0) 2058204220Smav printf("%s%d: %d.%03dMB/s transfers", 2059204220Smav periph->periph_name, periph->unit_number, 2060204220Smav mb, speed % 1000); 2061204220Smav else 2062204220Smav printf("%s%d: %dKB/s transfers", periph->periph_name, 2063204220Smav periph->unit_number, speed); 2064204220Smav /* Report additional information about connection */ 2065204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_ATA) { 2066236437Smav struct ccb_trans_settings_pata *pata = 2067204220Smav &cts.xport_specific.ata; 2068204220Smav 2069204220Smav printf(" ("); 2070236437Smav if (pata->valid & CTS_ATA_VALID_MODE) 2071236437Smav printf("%s, ", ata_mode2string(pata->mode)); 2072236437Smav if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0) 2073236437Smav printf("ATAPI %dbytes, ", pata->atapi); 2074236437Smav if (pata->valid & CTS_ATA_VALID_BYTECOUNT) 2075236437Smav printf("PIO %dbytes", pata->bytecount); 2076204220Smav printf(")"); 2077204220Smav } 2078204220Smav if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SATA) { 2079204220Smav struct ccb_trans_settings_sata *sata = 2080204220Smav &cts.xport_specific.sata; 2081204220Smav 2082204220Smav printf(" ("); 2083204220Smav if (sata->valid & CTS_SATA_VALID_REVISION) 2084204220Smav printf("SATA %d.x, ", sata->revision); 2085204220Smav else 2086204220Smav printf("SATA, "); 2087204220Smav if (sata->valid & CTS_SATA_VALID_MODE) 2088204220Smav printf("%s, ", ata_mode2string(sata->mode)); 2089204220Smav if ((sata->valid & CTS_ATA_VALID_ATAPI) && sata->atapi != 0) 2090204220Smav printf("ATAPI %dbytes, ", sata->atapi); 2091204220Smav if (sata->valid & CTS_SATA_VALID_BYTECOUNT) 2092204220Smav printf("PIO %dbytes", sata->bytecount); 2093204220Smav printf(")"); 2094204220Smav } 2095204220Smav printf("\n"); 2096204220Smav} 2097204220Smav 2098