152c9ce25SScott Long /*- 252c9ce25SScott Long * Copyright (c) 2009 Alexander Motin <mav@FreeBSD.org> 352c9ce25SScott Long * All rights reserved. 452c9ce25SScott Long * 552c9ce25SScott Long * Redistribution and use in source and binary forms, with or without 652c9ce25SScott Long * modification, are permitted provided that the following conditions 752c9ce25SScott Long * are met: 852c9ce25SScott Long * 1. Redistributions of source code must retain the above copyright 952c9ce25SScott Long * notice, this list of conditions and the following disclaimer, 1052c9ce25SScott Long * without modification, immediately at the beginning of the file. 1152c9ce25SScott Long * 2. Redistributions in binary form must reproduce the above copyright 1252c9ce25SScott Long * notice, this list of conditions and the following disclaimer in the 1352c9ce25SScott Long * documentation and/or other materials provided with the distribution. 1452c9ce25SScott Long * 1552c9ce25SScott Long * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1652c9ce25SScott Long * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1752c9ce25SScott Long * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1852c9ce25SScott Long * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1952c9ce25SScott Long * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2052c9ce25SScott Long * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2152c9ce25SScott Long * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2252c9ce25SScott Long * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2352c9ce25SScott Long * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2452c9ce25SScott Long * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2552c9ce25SScott Long */ 2652c9ce25SScott Long 2752c9ce25SScott Long #include <sys/cdefs.h> 2852c9ce25SScott Long __FBSDID("$FreeBSD$"); 2952c9ce25SScott Long 3052c9ce25SScott Long #include <sys/param.h> 3152c9ce25SScott Long #include <sys/bus.h> 3252c9ce25SScott Long #include <sys/endian.h> 3352c9ce25SScott Long #include <sys/systm.h> 3452c9ce25SScott Long #include <sys/types.h> 3552c9ce25SScott Long #include <sys/malloc.h> 3652c9ce25SScott Long #include <sys/kernel.h> 3752c9ce25SScott Long #include <sys/time.h> 3852c9ce25SScott Long #include <sys/conf.h> 3952c9ce25SScott Long #include <sys/fcntl.h> 4052c9ce25SScott Long #include <sys/interrupt.h> 4152c9ce25SScott Long #include <sys/sbuf.h> 4252c9ce25SScott Long 4352c9ce25SScott Long #include <sys/lock.h> 4452c9ce25SScott Long #include <sys/mutex.h> 4552c9ce25SScott Long #include <sys/sysctl.h> 4652c9ce25SScott Long 4752c9ce25SScott Long #include <cam/cam.h> 4852c9ce25SScott Long #include <cam/cam_ccb.h> 4952c9ce25SScott Long #include <cam/cam_queue.h> 5052c9ce25SScott Long #include <cam/cam_periph.h> 5152c9ce25SScott Long #include <cam/cam_sim.h> 5252c9ce25SScott Long #include <cam/cam_xpt.h> 5352c9ce25SScott Long #include <cam/cam_xpt_sim.h> 5452c9ce25SScott Long #include <cam/cam_xpt_periph.h> 5552c9ce25SScott Long #include <cam/cam_xpt_internal.h> 5652c9ce25SScott Long #include <cam/cam_debug.h> 5752c9ce25SScott Long 5852c9ce25SScott Long #include <cam/scsi/scsi_all.h> 5952c9ce25SScott Long #include <cam/scsi/scsi_message.h> 6052c9ce25SScott Long #include <cam/ata/ata_all.h> 6152c9ce25SScott Long #include <machine/stdarg.h> /* for xpt_print below */ 6252c9ce25SScott Long #include "opt_cam.h" 6352c9ce25SScott Long 6430a4094fSAlexander Motin struct ata_quirk_entry { 6552c9ce25SScott Long struct scsi_inquiry_pattern inq_pat; 6652c9ce25SScott Long u_int8_t quirks; 6730a4094fSAlexander Motin #define CAM_QUIRK_MAXTAGS 0x01 687dc3213dSAlexander Motin u_int mintags; 6952c9ce25SScott Long u_int maxtags; 7052c9ce25SScott Long }; 7152c9ce25SScott Long 7252c9ce25SScott Long static periph_init_t probe_periph_init; 7352c9ce25SScott Long 7452c9ce25SScott Long static struct periph_driver probe_driver = 7552c9ce25SScott Long { 76f09f8e3eSAlexander Motin probe_periph_init, "aprobe", 771e637ba6SAlexander Motin TAILQ_HEAD_INITIALIZER(probe_driver.units), /* generation */ 0, 781e637ba6SAlexander Motin CAM_PERIPH_DRV_EARLY 7952c9ce25SScott Long }; 8052c9ce25SScott Long 81f09f8e3eSAlexander Motin PERIPHDRIVER_DECLARE(aprobe, probe_driver); 8252c9ce25SScott Long 8352c9ce25SScott Long typedef enum { 8452c9ce25SScott Long PROBE_RESET, 8552c9ce25SScott Long PROBE_IDENTIFY, 864ef08dc5SAlexander Motin PROBE_SPINUP, 8752c9ce25SScott Long PROBE_SETMODE, 88da6808c1SAlexander Motin PROBE_SETPM, 89da6808c1SAlexander Motin PROBE_SETAPST, 90da6808c1SAlexander Motin PROBE_SETDMAAA, 918d169381SAlexander Motin PROBE_SETAN, 921e637ba6SAlexander Motin PROBE_SET_MULTI, 9352c9ce25SScott Long PROBE_INQUIRY, 9452c9ce25SScott Long PROBE_FULL_INQUIRY, 9552c9ce25SScott Long PROBE_PM_PID, 9652c9ce25SScott Long PROBE_PM_PRV, 973089bb2eSAlexander Motin PROBE_IDENTIFY_SES, 983089bb2eSAlexander Motin PROBE_IDENTIFY_SAFTE, 99a4d953c4SAlexander Motin PROBE_DONE, 10052c9ce25SScott Long PROBE_INVALID 10152c9ce25SScott Long } probe_action; 10252c9ce25SScott Long 10352c9ce25SScott Long static char *probe_action_text[] = { 10452c9ce25SScott Long "PROBE_RESET", 10552c9ce25SScott Long "PROBE_IDENTIFY", 1064ef08dc5SAlexander Motin "PROBE_SPINUP", 10752c9ce25SScott Long "PROBE_SETMODE", 108da6808c1SAlexander Motin "PROBE_SETPM", 109da6808c1SAlexander Motin "PROBE_SETAPST", 110da6808c1SAlexander Motin "PROBE_SETDMAAA", 1118d169381SAlexander Motin "PROBE_SETAN", 1121e637ba6SAlexander Motin "PROBE_SET_MULTI", 11352c9ce25SScott Long "PROBE_INQUIRY", 11452c9ce25SScott Long "PROBE_FULL_INQUIRY", 11552c9ce25SScott Long "PROBE_PM_PID", 11652c9ce25SScott Long "PROBE_PM_PRV", 1173089bb2eSAlexander Motin "PROBE_IDENTIFY_SES", 1183089bb2eSAlexander Motin "PROBE_IDENTIFY_SAFTE", 119a4d953c4SAlexander Motin "PROBE_DONE", 12052c9ce25SScott Long "PROBE_INVALID" 12152c9ce25SScott Long }; 12252c9ce25SScott Long 12352c9ce25SScott Long #define PROBE_SET_ACTION(softc, newaction) \ 12452c9ce25SScott Long do { \ 12552c9ce25SScott Long char **text; \ 12652c9ce25SScott Long text = probe_action_text; \ 127a4d953c4SAlexander Motin CAM_DEBUG((softc)->periph->path, CAM_DEBUG_PROBE, \ 12852c9ce25SScott Long ("Probe %s to %s\n", text[(softc)->action], \ 12952c9ce25SScott Long text[(newaction)])); \ 13052c9ce25SScott Long (softc)->action = (newaction); \ 13152c9ce25SScott Long } while(0) 13252c9ce25SScott Long 13352c9ce25SScott Long typedef enum { 13452c9ce25SScott Long PROBE_NO_ANNOUNCE = 0x04 13552c9ce25SScott Long } probe_flags; 13652c9ce25SScott Long 13752c9ce25SScott Long typedef struct { 13852c9ce25SScott Long TAILQ_HEAD(, ccb_hdr) request_ccbs; 139a9b8edb1SAlexander Motin struct ata_params ident_data; 14052c9ce25SScott Long probe_action action; 14152c9ce25SScott Long probe_flags flags; 14252c9ce25SScott Long uint32_t pm_pid; 14352c9ce25SScott Long uint32_t pm_prv; 14483c5d981SAlexander Motin int restart; 1454ef08dc5SAlexander Motin int spinup; 14625a519a9SAlexander Motin int faults; 147da6808c1SAlexander Motin u_int caps; 14852c9ce25SScott Long struct cam_periph *periph; 14952c9ce25SScott Long } probe_softc; 15052c9ce25SScott Long 15130a4094fSAlexander Motin static struct ata_quirk_entry ata_quirk_table[] = 15252c9ce25SScott Long { 15352c9ce25SScott Long { 15452c9ce25SScott Long /* Default tagged queuing parameters for all devices */ 15552c9ce25SScott Long { 15652c9ce25SScott Long T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED, 15752c9ce25SScott Long /*vendor*/"*", /*product*/"*", /*revision*/"*" 15852c9ce25SScott Long }, 1597dc3213dSAlexander Motin /*quirks*/0, /*mintags*/0, /*maxtags*/0 16052c9ce25SScott Long }, 16152c9ce25SScott Long }; 16252c9ce25SScott Long 16352c9ce25SScott Long static cam_status proberegister(struct cam_periph *periph, 16452c9ce25SScott Long void *arg); 16552c9ce25SScott Long static void probeschedule(struct cam_periph *probe_periph); 16652c9ce25SScott Long static void probestart(struct cam_periph *periph, union ccb *start_ccb); 167b9c473b2SAlexander Motin static void proberequestdefaultnegotiation(struct cam_periph *periph); 16852c9ce25SScott Long static void probedone(struct cam_periph *periph, union ccb *done_ccb); 16952c9ce25SScott Long static void probecleanup(struct cam_periph *periph); 17030a4094fSAlexander Motin static void ata_find_quirk(struct cam_ed *device); 17152c9ce25SScott Long static void ata_scan_bus(struct cam_periph *periph, union ccb *ccb); 17252c9ce25SScott Long static void ata_scan_lun(struct cam_periph *periph, 17352c9ce25SScott Long struct cam_path *path, cam_flags flags, 17452c9ce25SScott Long union ccb *ccb); 17552c9ce25SScott Long static void xptscandone(struct cam_periph *periph, union ccb *done_ccb); 17652c9ce25SScott Long static struct cam_ed * 17752c9ce25SScott Long ata_alloc_device(struct cam_eb *bus, struct cam_et *target, 17852c9ce25SScott Long lun_id_t lun_id); 17952c9ce25SScott Long static void ata_device_transport(struct cam_path *path); 180b9c473b2SAlexander Motin static void ata_get_transfer_settings(struct ccb_trans_settings *cts); 18130a4094fSAlexander Motin static void ata_set_transfer_settings(struct ccb_trans_settings *cts, 182227d67aaSAlexander Motin struct cam_path *path, 18352c9ce25SScott Long int async_update); 18452c9ce25SScott Long static void ata_dev_async(u_int32_t async_code, 18552c9ce25SScott Long struct cam_eb *bus, 18652c9ce25SScott Long struct cam_et *target, 18752c9ce25SScott Long struct cam_ed *device, 18852c9ce25SScott Long void *async_arg); 18952c9ce25SScott Long static void ata_action(union ccb *start_ccb); 19057079b17SAlexander Motin static void ata_announce_periph(struct cam_periph *periph); 19152c9ce25SScott Long 1922121d8a5SAlexander Motin static int ata_dma = 1; 1932121d8a5SAlexander Motin static int atapi_dma = 1; 1942121d8a5SAlexander Motin 1952121d8a5SAlexander Motin TUNABLE_INT("hw.ata.ata_dma", &ata_dma); 1962121d8a5SAlexander Motin TUNABLE_INT("hw.ata.atapi_dma", &atapi_dma); 1972121d8a5SAlexander Motin 198ded2b706SWarner Losh static struct xpt_xport_ops ata_xport_ops = { 19952c9ce25SScott Long .alloc_device = ata_alloc_device, 20052c9ce25SScott Long .action = ata_action, 20152c9ce25SScott Long .async = ata_dev_async, 20257079b17SAlexander Motin .announce = ata_announce_periph, 20352c9ce25SScott Long }; 204ded2b706SWarner Losh #define ATA_XPT_XPORT(x, X) \ 205ded2b706SWarner Losh static struct xpt_xport ata_xport_ ## x = { \ 206ded2b706SWarner Losh .xport = XPORT_ ## X, \ 207ded2b706SWarner Losh .name = #x, \ 208ded2b706SWarner Losh .ops = &ata_xport_ops, \ 209ded2b706SWarner Losh }; \ 210ded2b706SWarner Losh CAM_XPT_XPORT(ata_xport_ ## x); 21152c9ce25SScott Long 212ded2b706SWarner Losh ATA_XPT_XPORT(ata, ATA); 213ded2b706SWarner Losh ATA_XPT_XPORT(sata, SATA); 214ded2b706SWarner Losh 215ded2b706SWarner Losh #undef ATA_XPORT_XPORT 21652c9ce25SScott Long 21752c9ce25SScott Long static void 21852c9ce25SScott Long probe_periph_init() 21952c9ce25SScott Long { 22052c9ce25SScott Long } 22152c9ce25SScott Long 22252c9ce25SScott Long static cam_status 22352c9ce25SScott Long proberegister(struct cam_periph *periph, void *arg) 22452c9ce25SScott Long { 22552c9ce25SScott Long union ccb *request_ccb; /* CCB representing the probe request */ 22652c9ce25SScott Long cam_status status; 22752c9ce25SScott Long probe_softc *softc; 22852c9ce25SScott Long 22952c9ce25SScott Long request_ccb = (union ccb *)arg; 23052c9ce25SScott Long if (request_ccb == NULL) { 23152c9ce25SScott Long printf("proberegister: no probe CCB, " 23252c9ce25SScott Long "can't register device\n"); 23352c9ce25SScott Long return(CAM_REQ_CMP_ERR); 23452c9ce25SScott Long } 23552c9ce25SScott Long 2364ef08dc5SAlexander Motin softc = (probe_softc *)malloc(sizeof(*softc), M_CAMXPT, M_ZERO | M_NOWAIT); 23752c9ce25SScott Long 23852c9ce25SScott Long if (softc == NULL) { 23952c9ce25SScott Long printf("proberegister: Unable to probe new device. " 24052c9ce25SScott Long "Unable to allocate softc\n"); 24152c9ce25SScott Long return(CAM_REQ_CMP_ERR); 24252c9ce25SScott Long } 24352c9ce25SScott Long TAILQ_INIT(&softc->request_ccbs); 24452c9ce25SScott Long TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h, 24552c9ce25SScott Long periph_links.tqe); 24652c9ce25SScott Long softc->flags = 0; 24752c9ce25SScott Long periph->softc = softc; 24852c9ce25SScott Long softc->periph = periph; 24952c9ce25SScott Long softc->action = PROBE_INVALID; 25052c9ce25SScott Long status = cam_periph_acquire(periph); 25152c9ce25SScott Long if (status != CAM_REQ_CMP) { 25252c9ce25SScott Long return (status); 25352c9ce25SScott Long } 254a4d953c4SAlexander Motin CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe started\n")); 255227d67aaSAlexander Motin ata_device_transport(periph->path); 25652c9ce25SScott Long probeschedule(periph); 25752c9ce25SScott Long return(CAM_REQ_CMP); 25852c9ce25SScott Long } 25952c9ce25SScott Long 26052c9ce25SScott Long static void 26152c9ce25SScott Long probeschedule(struct cam_periph *periph) 26252c9ce25SScott Long { 26352c9ce25SScott Long union ccb *ccb; 26452c9ce25SScott Long probe_softc *softc; 26552c9ce25SScott Long 26652c9ce25SScott Long softc = (probe_softc *)periph->softc; 26752c9ce25SScott Long ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs); 26852c9ce25SScott Long 26965d0fb03SAlexander Motin if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) || 2703089bb2eSAlexander Motin periph->path->device->protocol == PROTO_SATAPM || 2713089bb2eSAlexander Motin periph->path->device->protocol == PROTO_SEMB) 27252c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_RESET); 27352c9ce25SScott Long else 27452c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 27552c9ce25SScott Long 27652c9ce25SScott Long if (ccb->crcn.flags & CAM_EXPECT_INQ_CHANGE) 27752c9ce25SScott Long softc->flags |= PROBE_NO_ANNOUNCE; 27852c9ce25SScott Long else 27952c9ce25SScott Long softc->flags &= ~PROBE_NO_ANNOUNCE; 28052c9ce25SScott Long 28183c5d981SAlexander Motin xpt_schedule(periph, CAM_PRIORITY_XPT); 28252c9ce25SScott Long } 28352c9ce25SScott Long 28452c9ce25SScott Long static void 28552c9ce25SScott Long probestart(struct cam_periph *periph, union ccb *start_ccb) 28652c9ce25SScott Long { 287c8039fc6SAlexander Motin struct ccb_trans_settings cts; 28852c9ce25SScott Long struct ccb_ataio *ataio; 28952c9ce25SScott Long struct ccb_scsiio *csio; 29052c9ce25SScott Long probe_softc *softc; 2911e637ba6SAlexander Motin struct cam_path *path; 2921e637ba6SAlexander Motin struct ata_params *ident_buf; 29352c9ce25SScott Long 29452c9ce25SScott Long CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probestart\n")); 29552c9ce25SScott Long 29652c9ce25SScott Long softc = (probe_softc *)periph->softc; 2971e637ba6SAlexander Motin path = start_ccb->ccb_h.path; 29852c9ce25SScott Long ataio = &start_ccb->ataio; 29952c9ce25SScott Long csio = &start_ccb->csio; 3001e637ba6SAlexander Motin ident_buf = &periph->path->device->ident_data; 30152c9ce25SScott Long 30283c5d981SAlexander Motin if (softc->restart) { 30383c5d981SAlexander Motin softc->restart = 0; 30483c5d981SAlexander Motin if ((path->device->flags & CAM_DEV_UNCONFIGURED) || 3053089bb2eSAlexander Motin path->device->protocol == PROTO_SATAPM || 3063089bb2eSAlexander Motin path->device->protocol == PROTO_SEMB) 30783c5d981SAlexander Motin softc->action = PROBE_RESET; 30883c5d981SAlexander Motin else 30983c5d981SAlexander Motin softc->action = PROBE_IDENTIFY; 31083c5d981SAlexander Motin } 31152c9ce25SScott Long switch (softc->action) { 31252c9ce25SScott Long case PROBE_RESET: 31352c9ce25SScott Long cam_fill_ataio(ataio, 31452c9ce25SScott Long 0, 31552c9ce25SScott Long probedone, 31652c9ce25SScott Long /*flags*/CAM_DIR_NONE, 31765d0fb03SAlexander Motin 0, 31852c9ce25SScott Long /*data_ptr*/NULL, 31952c9ce25SScott Long /*dxfer_len*/0, 32083c5d981SAlexander Motin 15 * 1000); 32152c9ce25SScott Long ata_reset_cmd(ataio); 32252c9ce25SScott Long break; 32352c9ce25SScott Long case PROBE_IDENTIFY: 32452c9ce25SScott Long cam_fill_ataio(ataio, 32552c9ce25SScott Long 1, 32652c9ce25SScott Long probedone, 32752c9ce25SScott Long /*flags*/CAM_DIR_IN, 32865d0fb03SAlexander Motin 0, 329a9b8edb1SAlexander Motin /*data_ptr*/(u_int8_t *)&softc->ident_data, 330a9b8edb1SAlexander Motin /*dxfer_len*/sizeof(softc->ident_data), 33152c9ce25SScott Long 30 * 1000); 33252c9ce25SScott Long if (periph->path->device->protocol == PROTO_ATA) 3337606b445SAlexander Motin ata_28bit_cmd(ataio, ATA_ATA_IDENTIFY, 0, 0, 0); 33452c9ce25SScott Long else 3357606b445SAlexander Motin ata_28bit_cmd(ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0); 33652c9ce25SScott Long break; 3374ef08dc5SAlexander Motin case PROBE_SPINUP: 3384ef08dc5SAlexander Motin if (bootverbose) 3394ef08dc5SAlexander Motin xpt_print(path, "Spinning up device\n"); 3404ef08dc5SAlexander Motin cam_fill_ataio(ataio, 3414ef08dc5SAlexander Motin 1, 3424ef08dc5SAlexander Motin probedone, 3434ef08dc5SAlexander Motin /*flags*/CAM_DIR_NONE | CAM_HIGH_POWER, 3444ef08dc5SAlexander Motin 0, 3454ef08dc5SAlexander Motin /*data_ptr*/NULL, 3464ef08dc5SAlexander Motin /*dxfer_len*/0, 3474ef08dc5SAlexander Motin 30 * 1000); 3484ef08dc5SAlexander Motin ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_PUIS_SPINUP, 0, 0); 3494ef08dc5SAlexander Motin break; 35052c9ce25SScott Long case PROBE_SETMODE: 351c8039fc6SAlexander Motin { 352c8039fc6SAlexander Motin int mode, wantmode; 353c8039fc6SAlexander Motin 354c8039fc6SAlexander Motin mode = 0; 355c8039fc6SAlexander Motin /* Fetch user modes from SIM. */ 356c8039fc6SAlexander Motin bzero(&cts, sizeof(cts)); 35783c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 358c8039fc6SAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 359c8039fc6SAlexander Motin cts.type = CTS_TYPE_USER_SETTINGS; 360c8039fc6SAlexander Motin xpt_action((union ccb *)&cts); 361c8039fc6SAlexander Motin if (path->device->transport == XPORT_ATA) { 362c8039fc6SAlexander Motin if (cts.xport_specific.ata.valid & CTS_ATA_VALID_MODE) 363c8039fc6SAlexander Motin mode = cts.xport_specific.ata.mode; 364c8039fc6SAlexander Motin } else { 3651a6f09b8SAlexander Motin if (cts.xport_specific.sata.valid & CTS_SATA_VALID_MODE) 366c8039fc6SAlexander Motin mode = cts.xport_specific.sata.mode; 367c8039fc6SAlexander Motin } 3682121d8a5SAlexander Motin if (periph->path->device->protocol == PROTO_ATA) { 3692121d8a5SAlexander Motin if (ata_dma == 0 && (mode == 0 || mode > ATA_PIO_MAX)) 3702121d8a5SAlexander Motin mode = ATA_PIO_MAX; 3712121d8a5SAlexander Motin } else { 3722121d8a5SAlexander Motin if (atapi_dma == 0 && (mode == 0 || mode > ATA_PIO_MAX)) 3732121d8a5SAlexander Motin mode = ATA_PIO_MAX; 3742121d8a5SAlexander Motin } 375c8039fc6SAlexander Motin negotiate: 376c8039fc6SAlexander Motin /* Honor device capabilities. */ 377c8039fc6SAlexander Motin wantmode = mode = ata_max_mode(ident_buf, mode); 378c8039fc6SAlexander Motin /* Report modes to SIM. */ 379c8039fc6SAlexander Motin bzero(&cts, sizeof(cts)); 38083c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 381c8039fc6SAlexander Motin cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 382c8039fc6SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 383c8039fc6SAlexander Motin if (path->device->transport == XPORT_ATA) { 384c8039fc6SAlexander Motin cts.xport_specific.ata.mode = mode; 385c8039fc6SAlexander Motin cts.xport_specific.ata.valid = CTS_ATA_VALID_MODE; 386c8039fc6SAlexander Motin } else { 387c8039fc6SAlexander Motin cts.xport_specific.sata.mode = mode; 388c8039fc6SAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_MODE; 389c8039fc6SAlexander Motin } 390c8039fc6SAlexander Motin xpt_action((union ccb *)&cts); 391066f913aSAlexander Motin /* Fetch current modes from SIM. */ 392c8039fc6SAlexander Motin bzero(&cts, sizeof(cts)); 39383c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 394c8039fc6SAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 395c8039fc6SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 396c8039fc6SAlexander Motin xpt_action((union ccb *)&cts); 397c8039fc6SAlexander Motin if (path->device->transport == XPORT_ATA) { 398c8039fc6SAlexander Motin if (cts.xport_specific.ata.valid & CTS_ATA_VALID_MODE) 399c8039fc6SAlexander Motin mode = cts.xport_specific.ata.mode; 400c8039fc6SAlexander Motin } else { 401c8039fc6SAlexander Motin if (cts.xport_specific.ata.valid & CTS_SATA_VALID_MODE) 402c8039fc6SAlexander Motin mode = cts.xport_specific.sata.mode; 403c8039fc6SAlexander Motin } 404c8039fc6SAlexander Motin /* If SIM disagree - renegotiate. */ 405c8039fc6SAlexander Motin if (mode != wantmode) 406c8039fc6SAlexander Motin goto negotiate; 407cf2b9a5fSAlexander Motin /* Remember what transport thinks about DMA. */ 408cf2b9a5fSAlexander Motin if (mode < ATA_DMA) 409cf2b9a5fSAlexander Motin path->device->inq_flags &= ~SID_DMA; 410cf2b9a5fSAlexander Motin else 411cf2b9a5fSAlexander Motin path->device->inq_flags |= SID_DMA; 412581b2e78SAlexander Motin xpt_async(AC_GETDEV_CHANGED, path, NULL); 41352c9ce25SScott Long cam_fill_ataio(ataio, 41452c9ce25SScott Long 1, 41552c9ce25SScott Long probedone, 4165daa555dSAlexander Motin /*flags*/CAM_DIR_NONE, 4175daa555dSAlexander Motin 0, 4185daa555dSAlexander Motin /*data_ptr*/NULL, 4195daa555dSAlexander Motin /*dxfer_len*/0, 42052c9ce25SScott Long 30 * 1000); 421c8039fc6SAlexander Motin ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); 42252c9ce25SScott Long break; 423c8039fc6SAlexander Motin } 424da6808c1SAlexander Motin case PROBE_SETPM: 425da6808c1SAlexander Motin cam_fill_ataio(ataio, 426da6808c1SAlexander Motin 1, 427da6808c1SAlexander Motin probedone, 428da6808c1SAlexander Motin CAM_DIR_NONE, 429da6808c1SAlexander Motin 0, 430da6808c1SAlexander Motin NULL, 431da6808c1SAlexander Motin 0, 432da6808c1SAlexander Motin 30*1000); 433da6808c1SAlexander Motin ata_28bit_cmd(ataio, ATA_SETFEATURES, 434da6808c1SAlexander Motin (softc->caps & CTS_SATA_CAPS_H_PMREQ) ? 0x10 : 0x90, 435da6808c1SAlexander Motin 0, 0x03); 436da6808c1SAlexander Motin break; 437da6808c1SAlexander Motin case PROBE_SETAPST: 438da6808c1SAlexander Motin cam_fill_ataio(ataio, 439da6808c1SAlexander Motin 1, 440da6808c1SAlexander Motin probedone, 441da6808c1SAlexander Motin CAM_DIR_NONE, 442da6808c1SAlexander Motin 0, 443da6808c1SAlexander Motin NULL, 444da6808c1SAlexander Motin 0, 445da6808c1SAlexander Motin 30*1000); 446da6808c1SAlexander Motin ata_28bit_cmd(ataio, ATA_SETFEATURES, 447da6808c1SAlexander Motin (softc->caps & CTS_SATA_CAPS_H_APST) ? 0x10 : 0x90, 448da6808c1SAlexander Motin 0, 0x07); 449da6808c1SAlexander Motin break; 450da6808c1SAlexander Motin case PROBE_SETDMAAA: 451da6808c1SAlexander Motin cam_fill_ataio(ataio, 452da6808c1SAlexander Motin 1, 453da6808c1SAlexander Motin probedone, 454da6808c1SAlexander Motin CAM_DIR_NONE, 455da6808c1SAlexander Motin 0, 456da6808c1SAlexander Motin NULL, 457da6808c1SAlexander Motin 0, 458da6808c1SAlexander Motin 30*1000); 459da6808c1SAlexander Motin ata_28bit_cmd(ataio, ATA_SETFEATURES, 460da6808c1SAlexander Motin (softc->caps & CTS_SATA_CAPS_H_DMAAA) ? 0x10 : 0x90, 461da6808c1SAlexander Motin 0, 0x02); 462da6808c1SAlexander Motin break; 4638d169381SAlexander Motin case PROBE_SETAN: 464e4bed0b4SWarner Losh /* Remember what transport thinks about AEN. */ 465e4bed0b4SWarner Losh if (softc->caps & CTS_SATA_CAPS_H_AN) 4663631c638SAlexander Motin path->device->inq_flags |= SID_AEN; 4673631c638SAlexander Motin else 4683631c638SAlexander Motin path->device->inq_flags &= ~SID_AEN; 4693631c638SAlexander Motin xpt_async(AC_GETDEV_CHANGED, path, NULL); 4708d169381SAlexander Motin cam_fill_ataio(ataio, 4718d169381SAlexander Motin 1, 4728d169381SAlexander Motin probedone, 4738d169381SAlexander Motin CAM_DIR_NONE, 4748d169381SAlexander Motin 0, 4758d169381SAlexander Motin NULL, 4768d169381SAlexander Motin 0, 4778d169381SAlexander Motin 30*1000); 4788d169381SAlexander Motin ata_28bit_cmd(ataio, ATA_SETFEATURES, 4798d169381SAlexander Motin (softc->caps & CTS_SATA_CAPS_H_AN) ? 0x10 : 0x90, 4808d169381SAlexander Motin 0, 0x05); 4818d169381SAlexander Motin break; 4821e637ba6SAlexander Motin case PROBE_SET_MULTI: 4831e637ba6SAlexander Motin { 484066f913aSAlexander Motin u_int sectors, bytecount; 4851e637ba6SAlexander Motin 486066f913aSAlexander Motin bytecount = 8192; /* SATA maximum */ 487066f913aSAlexander Motin /* Fetch user bytecount from SIM. */ 488066f913aSAlexander Motin bzero(&cts, sizeof(cts)); 48983c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 490066f913aSAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 491066f913aSAlexander Motin cts.type = CTS_TYPE_USER_SETTINGS; 492066f913aSAlexander Motin xpt_action((union ccb *)&cts); 493066f913aSAlexander Motin if (path->device->transport == XPORT_ATA) { 494066f913aSAlexander Motin if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 495066f913aSAlexander Motin bytecount = cts.xport_specific.ata.bytecount; 496066f913aSAlexander Motin } else { 497066f913aSAlexander Motin if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 498066f913aSAlexander Motin bytecount = cts.xport_specific.sata.bytecount; 499066f913aSAlexander Motin } 500066f913aSAlexander Motin /* Honor device capabilities. */ 501066f913aSAlexander Motin sectors = max(1, min(ident_buf->sectors_intr & 0xff, 502066f913aSAlexander Motin bytecount / ata_logical_sector_size(ident_buf))); 5031e637ba6SAlexander Motin /* Report bytecount to SIM. */ 5041e637ba6SAlexander Motin bzero(&cts, sizeof(cts)); 50583c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 5061e637ba6SAlexander Motin cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 5071e637ba6SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 5081e637ba6SAlexander Motin if (path->device->transport == XPORT_ATA) { 509c1bd46c2SAlexander Motin cts.xport_specific.ata.bytecount = sectors * 510c1bd46c2SAlexander Motin ata_logical_sector_size(ident_buf); 5111e637ba6SAlexander Motin cts.xport_specific.ata.valid = CTS_ATA_VALID_BYTECOUNT; 5121e637ba6SAlexander Motin } else { 513c1bd46c2SAlexander Motin cts.xport_specific.sata.bytecount = sectors * 514c1bd46c2SAlexander Motin ata_logical_sector_size(ident_buf); 5151e637ba6SAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_BYTECOUNT; 5161e637ba6SAlexander Motin } 5171e637ba6SAlexander Motin xpt_action((union ccb *)&cts); 518066f913aSAlexander Motin /* Fetch current bytecount from SIM. */ 519066f913aSAlexander Motin bzero(&cts, sizeof(cts)); 52083c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 521066f913aSAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 522066f913aSAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 523066f913aSAlexander Motin xpt_action((union ccb *)&cts); 524066f913aSAlexander Motin if (path->device->transport == XPORT_ATA) { 525066f913aSAlexander Motin if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 526066f913aSAlexander Motin bytecount = cts.xport_specific.ata.bytecount; 527066f913aSAlexander Motin } else { 528066f913aSAlexander Motin if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 529066f913aSAlexander Motin bytecount = cts.xport_specific.sata.bytecount; 530066f913aSAlexander Motin } 531066f913aSAlexander Motin sectors = bytecount / ata_logical_sector_size(ident_buf); 5321e637ba6SAlexander Motin 5331e637ba6SAlexander Motin cam_fill_ataio(ataio, 5341e637ba6SAlexander Motin 1, 5351e637ba6SAlexander Motin probedone, 5361e637ba6SAlexander Motin CAM_DIR_NONE, 5371e637ba6SAlexander Motin 0, 5381e637ba6SAlexander Motin NULL, 5391e637ba6SAlexander Motin 0, 5401e637ba6SAlexander Motin 30*1000); 5411e637ba6SAlexander Motin ata_28bit_cmd(ataio, ATA_SET_MULTI, 0, 0, sectors); 5421e637ba6SAlexander Motin break; 54352c9ce25SScott Long } 54452c9ce25SScott Long case PROBE_INQUIRY: 545066f913aSAlexander Motin { 546066f913aSAlexander Motin u_int bytecount; 547066f913aSAlexander Motin 548066f913aSAlexander Motin bytecount = 8192; /* SATA maximum */ 549066f913aSAlexander Motin /* Fetch user bytecount from SIM. */ 550066f913aSAlexander Motin bzero(&cts, sizeof(cts)); 55183c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 552066f913aSAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 553066f913aSAlexander Motin cts.type = CTS_TYPE_USER_SETTINGS; 554066f913aSAlexander Motin xpt_action((union ccb *)&cts); 555066f913aSAlexander Motin if (path->device->transport == XPORT_ATA) { 556066f913aSAlexander Motin if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 557066f913aSAlexander Motin bytecount = cts.xport_specific.ata.bytecount; 558066f913aSAlexander Motin } else { 559066f913aSAlexander Motin if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 560066f913aSAlexander Motin bytecount = cts.xport_specific.sata.bytecount; 561066f913aSAlexander Motin } 562066f913aSAlexander Motin /* Honor device capabilities. */ 563066f913aSAlexander Motin bytecount &= ~1; 564066f913aSAlexander Motin bytecount = max(2, min(65534, bytecount)); 565066f913aSAlexander Motin if (ident_buf->satacapabilities != 0x0000 && 566066f913aSAlexander Motin ident_buf->satacapabilities != 0xffff) { 567066f913aSAlexander Motin bytecount = min(8192, bytecount); 568066f913aSAlexander Motin } 569066f913aSAlexander Motin /* Report bytecount to SIM. */ 570066f913aSAlexander Motin bzero(&cts, sizeof(cts)); 57183c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 572066f913aSAlexander Motin cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 573066f913aSAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 574066f913aSAlexander Motin if (path->device->transport == XPORT_ATA) { 575066f913aSAlexander Motin cts.xport_specific.ata.bytecount = bytecount; 576066f913aSAlexander Motin cts.xport_specific.ata.valid = CTS_ATA_VALID_BYTECOUNT; 577066f913aSAlexander Motin } else { 578066f913aSAlexander Motin cts.xport_specific.sata.bytecount = bytecount; 579066f913aSAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_BYTECOUNT; 580066f913aSAlexander Motin } 581066f913aSAlexander Motin xpt_action((union ccb *)&cts); 582066f913aSAlexander Motin /* FALLTHROUGH */ 583066f913aSAlexander Motin } 58452c9ce25SScott Long case PROBE_FULL_INQUIRY: 58552c9ce25SScott Long { 58652c9ce25SScott Long u_int inquiry_len; 58752c9ce25SScott Long struct scsi_inquiry_data *inq_buf = 58852c9ce25SScott Long &periph->path->device->inq_data; 58952c9ce25SScott Long 59052c9ce25SScott Long if (softc->action == PROBE_INQUIRY) 59152c9ce25SScott Long inquiry_len = SHORT_INQUIRY_LENGTH; 59252c9ce25SScott Long else 59352c9ce25SScott Long inquiry_len = SID_ADDITIONAL_LENGTH(inq_buf); 59452c9ce25SScott Long /* 59552c9ce25SScott Long * Some parallel SCSI devices fail to send an 59652c9ce25SScott Long * ignore wide residue message when dealing with 59752c9ce25SScott Long * odd length inquiry requests. Round up to be 59852c9ce25SScott Long * safe. 59952c9ce25SScott Long */ 60052c9ce25SScott Long inquiry_len = roundup2(inquiry_len, 2); 60152c9ce25SScott Long scsi_inquiry(csio, 60252c9ce25SScott Long /*retries*/1, 60352c9ce25SScott Long probedone, 60452c9ce25SScott Long MSG_SIMPLE_Q_TAG, 60552c9ce25SScott Long (u_int8_t *)inq_buf, 60652c9ce25SScott Long inquiry_len, 60752c9ce25SScott Long /*evpd*/FALSE, 60852c9ce25SScott Long /*page_code*/0, 60952c9ce25SScott Long SSD_MIN_SIZE, 61052c9ce25SScott Long /*timeout*/60 * 1000); 61152c9ce25SScott Long break; 61252c9ce25SScott Long } 61352c9ce25SScott Long case PROBE_PM_PID: 61452c9ce25SScott Long cam_fill_ataio(ataio, 61552c9ce25SScott Long 1, 61652c9ce25SScott Long probedone, 61752c9ce25SScott Long /*flags*/CAM_DIR_NONE, 61865d0fb03SAlexander Motin 0, 61952c9ce25SScott Long /*data_ptr*/NULL, 62052c9ce25SScott Long /*dxfer_len*/0, 62152c9ce25SScott Long 10 * 1000); 62252c9ce25SScott Long ata_pm_read_cmd(ataio, 0, 15); 62352c9ce25SScott Long break; 62452c9ce25SScott Long case PROBE_PM_PRV: 62552c9ce25SScott Long cam_fill_ataio(ataio, 62652c9ce25SScott Long 1, 62752c9ce25SScott Long probedone, 62852c9ce25SScott Long /*flags*/CAM_DIR_NONE, 62965d0fb03SAlexander Motin 0, 63052c9ce25SScott Long /*data_ptr*/NULL, 63152c9ce25SScott Long /*dxfer_len*/0, 63252c9ce25SScott Long 10 * 1000); 63352c9ce25SScott Long ata_pm_read_cmd(ataio, 1, 15); 63452c9ce25SScott Long break; 6353089bb2eSAlexander Motin case PROBE_IDENTIFY_SES: 6363089bb2eSAlexander Motin cam_fill_ataio(ataio, 6373089bb2eSAlexander Motin 1, 6383089bb2eSAlexander Motin probedone, 6393089bb2eSAlexander Motin /*flags*/CAM_DIR_IN, 6403089bb2eSAlexander Motin 0, 6413089bb2eSAlexander Motin /*data_ptr*/(u_int8_t *)&softc->ident_data, 6423089bb2eSAlexander Motin /*dxfer_len*/sizeof(softc->ident_data), 6433089bb2eSAlexander Motin 30 * 1000); 6443089bb2eSAlexander Motin ata_28bit_cmd(ataio, ATA_SEP_ATTN, 0xEC, 0x02, 6453089bb2eSAlexander Motin sizeof(softc->ident_data) / 4); 6463089bb2eSAlexander Motin break; 6473089bb2eSAlexander Motin case PROBE_IDENTIFY_SAFTE: 6483089bb2eSAlexander Motin cam_fill_ataio(ataio, 6493089bb2eSAlexander Motin 1, 6503089bb2eSAlexander Motin probedone, 6513089bb2eSAlexander Motin /*flags*/CAM_DIR_IN, 6523089bb2eSAlexander Motin 0, 6533089bb2eSAlexander Motin /*data_ptr*/(u_int8_t *)&softc->ident_data, 6543089bb2eSAlexander Motin /*dxfer_len*/sizeof(softc->ident_data), 6553089bb2eSAlexander Motin 30 * 1000); 6563089bb2eSAlexander Motin ata_28bit_cmd(ataio, ATA_SEP_ATTN, 0xEC, 0x00, 6573089bb2eSAlexander Motin sizeof(softc->ident_data) / 4); 6583089bb2eSAlexander Motin break; 65952c9ce25SScott Long default: 660a4d953c4SAlexander Motin panic("probestart: invalid action state 0x%x\n", softc->action); 66152c9ce25SScott Long } 662cccf4220SAlexander Motin start_ccb->ccb_h.flags |= CAM_DEV_QFREEZE; 66352c9ce25SScott Long xpt_action(start_ccb); 66452c9ce25SScott Long } 665b9c473b2SAlexander Motin 66652c9ce25SScott Long static void 66752c9ce25SScott Long proberequestdefaultnegotiation(struct cam_periph *periph) 66852c9ce25SScott Long { 66952c9ce25SScott Long struct ccb_trans_settings cts; 67052c9ce25SScott Long 67183c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE); 67252c9ce25SScott Long cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 67352c9ce25SScott Long cts.type = CTS_TYPE_USER_SETTINGS; 67452c9ce25SScott Long xpt_action((union ccb *)&cts); 675b9c473b2SAlexander Motin if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 67652c9ce25SScott Long return; 677b9c473b2SAlexander Motin cts.xport_specific.valid = 0; 67852c9ce25SScott Long cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 67952c9ce25SScott Long cts.type = CTS_TYPE_CURRENT_SETTINGS; 68052c9ce25SScott Long xpt_action((union ccb *)&cts); 68152c9ce25SScott Long } 68252c9ce25SScott Long 68352c9ce25SScott Long static void 68452c9ce25SScott Long probedone(struct cam_periph *periph, union ccb *done_ccb) 68552c9ce25SScott Long { 686c8039fc6SAlexander Motin struct ccb_trans_settings cts; 68752c9ce25SScott Long struct ata_params *ident_buf; 6883089bb2eSAlexander Motin struct scsi_inquiry_data *inq_buf; 68952c9ce25SScott Long probe_softc *softc; 69052c9ce25SScott Long struct cam_path *path; 69126bdaeddSAlexander Motin cam_status status; 69252c9ce25SScott Long u_int32_t priority; 693da6808c1SAlexander Motin u_int caps; 6943089bb2eSAlexander Motin int changed = 1, found = 1; 6953089bb2eSAlexander Motin static const uint8_t fake_device_id_hdr[8] = 6963089bb2eSAlexander Motin {0, SVPD_DEVICE_ID, 0, 12, 6973089bb2eSAlexander Motin SVPD_ID_CODESET_BINARY, SVPD_ID_TYPE_NAA, 0, 8}; 69852c9ce25SScott Long 69952c9ce25SScott Long CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probedone\n")); 70052c9ce25SScott Long 70152c9ce25SScott Long softc = (probe_softc *)periph->softc; 70252c9ce25SScott Long path = done_ccb->ccb_h.path; 70352c9ce25SScott Long priority = done_ccb->ccb_h.pinfo.priority; 70452c9ce25SScott Long ident_buf = &path->device->ident_data; 7053089bb2eSAlexander Motin inq_buf = &path->device->inq_data; 70652c9ce25SScott Long 7071e637ba6SAlexander Motin if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 7080191d9b3SAlexander Motin if (cam_periph_error(done_ccb, 7090191d9b3SAlexander Motin 0, softc->restart ? (SF_NO_RECOVERY | SF_NO_RETRY) : 0, 710cccf4220SAlexander Motin NULL) == ERESTART) { 711cccf4220SAlexander Motin out: 712cccf4220SAlexander Motin /* Drop freeze taken due to CAM_DEV_QFREEZE flag set. */ 713cccf4220SAlexander Motin cam_release_devq(path, 0, 0, 0, FALSE); 7141e637ba6SAlexander Motin return; 715cccf4220SAlexander Motin } 71625a519a9SAlexander Motin if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 7171e637ba6SAlexander Motin /* Don't wedge the queue */ 718cccf4220SAlexander Motin xpt_release_devq(path, /*count*/1, /*run_queue*/TRUE); 7191e637ba6SAlexander Motin } 72026bdaeddSAlexander Motin status = done_ccb->ccb_h.status & CAM_STATUS_MASK; 72125a519a9SAlexander Motin if (softc->restart) { 72225a519a9SAlexander Motin softc->faults++; 72325a519a9SAlexander Motin if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == 72425a519a9SAlexander Motin CAM_CMD_TIMEOUT) 72525a519a9SAlexander Motin softc->faults += 4; 72625a519a9SAlexander Motin if (softc->faults < 10) 72725a519a9SAlexander Motin goto done; 72825a519a9SAlexander Motin else 72925a519a9SAlexander Motin softc->restart = 0; 73026bdaeddSAlexander Motin 7311e637ba6SAlexander Motin /* Old PIO2 devices may not support mode setting. */ 73226bdaeddSAlexander Motin } else if (softc->action == PROBE_SETMODE && 73326bdaeddSAlexander Motin status == CAM_ATA_STATUS_ERROR && 7341e637ba6SAlexander Motin ata_max_pmode(ident_buf) <= ATA_PIO2 && 73526bdaeddSAlexander Motin (ident_buf->capabilities1 & ATA_SUPPORT_IORDY) == 0) { 7361e637ba6SAlexander Motin goto noerror; 73726bdaeddSAlexander Motin 73826bdaeddSAlexander Motin /* 73926bdaeddSAlexander Motin * Some old WD SATA disks report supported and enabled 74026bdaeddSAlexander Motin * device-initiated interface power management, but return 74126bdaeddSAlexander Motin * ABORT on attempt to disable it. 74226bdaeddSAlexander Motin */ 74326bdaeddSAlexander Motin } else if (softc->action == PROBE_SETPM && 74426bdaeddSAlexander Motin status == CAM_ATA_STATUS_ERROR) { 74526bdaeddSAlexander Motin goto noerror; 746025e2c12SAlexander Motin 747025e2c12SAlexander Motin /* 748025e2c12SAlexander Motin * Some HP SATA disks report supported DMA Auto-Activation, 749025e2c12SAlexander Motin * but return ABORT on attempt to enable it. 750025e2c12SAlexander Motin */ 751025e2c12SAlexander Motin } else if (softc->action == PROBE_SETDMAAA && 752025e2c12SAlexander Motin status == CAM_ATA_STATUS_ERROR) { 753025e2c12SAlexander Motin goto noerror; 7543089bb2eSAlexander Motin 7553089bb2eSAlexander Motin /* 7563089bb2eSAlexander Motin * SES and SAF-TE SEPs have different IDENTIFY commands, 7573089bb2eSAlexander Motin * but SATA specification doesn't tell how to identify them. 7583089bb2eSAlexander Motin * Until better way found, just try another if first fail. 7593089bb2eSAlexander Motin */ 7603089bb2eSAlexander Motin } else if (softc->action == PROBE_IDENTIFY_SES && 7613089bb2eSAlexander Motin status == CAM_ATA_STATUS_ERROR) { 7623089bb2eSAlexander Motin PROBE_SET_ACTION(softc, PROBE_IDENTIFY_SAFTE); 7633089bb2eSAlexander Motin xpt_release_ccb(done_ccb); 7643089bb2eSAlexander Motin xpt_schedule(periph, priority); 765cccf4220SAlexander Motin goto out; 76626bdaeddSAlexander Motin } 76726bdaeddSAlexander Motin 7681e637ba6SAlexander Motin /* 7691e637ba6SAlexander Motin * If we get to this point, we got an error status back 7701e637ba6SAlexander Motin * from the inquiry and the error status doesn't require 7711e637ba6SAlexander Motin * automatically retrying the command. Therefore, the 7721e637ba6SAlexander Motin * inquiry failed. If we had inquiry information before 7731e637ba6SAlexander Motin * for this device, but this latest inquiry command failed, 7741e637ba6SAlexander Motin * the device has probably gone away. If this device isn't 7751e637ba6SAlexander Motin * already marked unconfigured, notify the peripheral 7761e637ba6SAlexander Motin * drivers that this device is no more. 7771e637ba6SAlexander Motin */ 77825a519a9SAlexander Motin device_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0) 7791e637ba6SAlexander Motin xpt_async(AC_LOST_DEVICE, path, NULL); 780a4d953c4SAlexander Motin PROBE_SET_ACTION(softc, PROBE_INVALID); 7811e637ba6SAlexander Motin found = 0; 7821e637ba6SAlexander Motin goto done; 7831e637ba6SAlexander Motin } 7841e637ba6SAlexander Motin noerror: 785a9b8edb1SAlexander Motin if (softc->restart) 786a9b8edb1SAlexander Motin goto done; 78752c9ce25SScott Long switch (softc->action) { 78852c9ce25SScott Long case PROBE_RESET: 7891e637ba6SAlexander Motin { 79052c9ce25SScott Long int sign = (done_ccb->ataio.res.lba_high << 8) + 79152c9ce25SScott Long done_ccb->ataio.res.lba_mid; 792a4d953c4SAlexander Motin CAM_DEBUG(path, CAM_DEBUG_PROBE, 793a4d953c4SAlexander Motin ("SIGNATURE: %04x\n", sign)); 79452c9ce25SScott Long if (sign == 0x0000 && 79552c9ce25SScott Long done_ccb->ccb_h.target_id != 15) { 79652c9ce25SScott Long path->device->protocol = PROTO_ATA; 79752c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 79852c9ce25SScott Long } else if (sign == 0x9669 && 79952c9ce25SScott Long done_ccb->ccb_h.target_id == 15) { 80052c9ce25SScott Long /* Report SIM that PM is present. */ 80152c9ce25SScott Long bzero(&cts, sizeof(cts)); 80283c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 80352c9ce25SScott Long cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 80452c9ce25SScott Long cts.type = CTS_TYPE_CURRENT_SETTINGS; 80552c9ce25SScott Long cts.xport_specific.sata.pm_present = 1; 80652c9ce25SScott Long cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; 80752c9ce25SScott Long xpt_action((union ccb *)&cts); 80852c9ce25SScott Long path->device->protocol = PROTO_SATAPM; 80952c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_PM_PID); 8103089bb2eSAlexander Motin } else if (sign == 0xc33c && 8113089bb2eSAlexander Motin done_ccb->ccb_h.target_id != 15) { 8123089bb2eSAlexander Motin path->device->protocol = PROTO_SEMB; 8133089bb2eSAlexander Motin PROBE_SET_ACTION(softc, PROBE_IDENTIFY_SES); 81452c9ce25SScott Long } else if (sign == 0xeb14 && 81552c9ce25SScott Long done_ccb->ccb_h.target_id != 15) { 81652c9ce25SScott Long path->device->protocol = PROTO_SCSI; 81752c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 81852c9ce25SScott Long } else { 81952c9ce25SScott Long if (done_ccb->ccb_h.target_id != 15) { 82052c9ce25SScott Long xpt_print(path, 82152c9ce25SScott Long "Unexpected signature 0x%04x\n", sign); 82252c9ce25SScott Long } 82365d0fb03SAlexander Motin goto device_fail; 82452c9ce25SScott Long } 82552c9ce25SScott Long xpt_release_ccb(done_ccb); 82652c9ce25SScott Long xpt_schedule(periph, priority); 827cccf4220SAlexander Motin goto out; 82852c9ce25SScott Long } 82952c9ce25SScott Long case PROBE_IDENTIFY: 83052c9ce25SScott Long { 831699f853bSAlexander Motin struct ccb_pathinq cpi; 83252c9ce25SScott Long int16_t *ptr; 83352c9ce25SScott Long 834a9b8edb1SAlexander Motin ident_buf = &softc->ident_data; 83552c9ce25SScott Long for (ptr = (int16_t *)ident_buf; 83652c9ce25SScott Long ptr < (int16_t *)ident_buf + sizeof(struct ata_params)/2; ptr++) { 83752c9ce25SScott Long *ptr = le16toh(*ptr); 83852c9ce25SScott Long } 83952c9ce25SScott Long if (strncmp(ident_buf->model, "FX", 2) && 84052c9ce25SScott Long strncmp(ident_buf->model, "NEC", 3) && 84152c9ce25SScott Long strncmp(ident_buf->model, "Pioneer", 7) && 84252c9ce25SScott Long strncmp(ident_buf->model, "SHARP", 5)) { 84352c9ce25SScott Long ata_bswap(ident_buf->model, sizeof(ident_buf->model)); 84452c9ce25SScott Long ata_bswap(ident_buf->revision, sizeof(ident_buf->revision)); 84552c9ce25SScott Long ata_bswap(ident_buf->serial, sizeof(ident_buf->serial)); 84652c9ce25SScott Long } 84752c9ce25SScott Long ata_btrim(ident_buf->model, sizeof(ident_buf->model)); 84852c9ce25SScott Long ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model)); 84952c9ce25SScott Long ata_btrim(ident_buf->revision, sizeof(ident_buf->revision)); 85052c9ce25SScott Long ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision)); 85152c9ce25SScott Long ata_btrim(ident_buf->serial, sizeof(ident_buf->serial)); 85252c9ce25SScott Long ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial)); 8534ef08dc5SAlexander Motin /* Device may need spin-up before IDENTIFY become valid. */ 8541254b680SAlexander Motin if ((ident_buf->specconf == 0x37c8 || 8551254b680SAlexander Motin ident_buf->specconf == 0x738c) && 8561254b680SAlexander Motin ((ident_buf->config & ATA_RESP_INCOMPLETE) || 8574ef08dc5SAlexander Motin softc->spinup == 0)) { 8584ef08dc5SAlexander Motin PROBE_SET_ACTION(softc, PROBE_SPINUP); 8594ef08dc5SAlexander Motin xpt_release_ccb(done_ccb); 8604ef08dc5SAlexander Motin xpt_schedule(periph, priority); 861cccf4220SAlexander Motin goto out; 8624ef08dc5SAlexander Motin } 863a9b8edb1SAlexander Motin ident_buf = &path->device->ident_data; 86452c9ce25SScott Long if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) { 86552c9ce25SScott Long /* Check that it is the same device. */ 866a9b8edb1SAlexander Motin if (bcmp(softc->ident_data.model, ident_buf->model, 867a9b8edb1SAlexander Motin sizeof(ident_buf->model)) || 868a9b8edb1SAlexander Motin bcmp(softc->ident_data.revision, ident_buf->revision, 869a9b8edb1SAlexander Motin sizeof(ident_buf->revision)) || 870a9b8edb1SAlexander Motin bcmp(softc->ident_data.serial, ident_buf->serial, 871a9b8edb1SAlexander Motin sizeof(ident_buf->serial))) { 87252c9ce25SScott Long /* Device changed. */ 87352c9ce25SScott Long xpt_async(AC_LOST_DEVICE, path, NULL); 8741e637ba6SAlexander Motin } else { 875a9b8edb1SAlexander Motin bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 8762eb4a8dcSAlexander Motin changed = 0; 8772eb4a8dcSAlexander Motin } 8782eb4a8dcSAlexander Motin } 8792eb4a8dcSAlexander Motin if (changed) { 8802eb4a8dcSAlexander Motin bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 88152c9ce25SScott Long /* Clean up from previous instance of this device */ 88252c9ce25SScott Long if (path->device->serial_num != NULL) { 88352c9ce25SScott Long free(path->device->serial_num, M_CAMXPT); 88452c9ce25SScott Long path->device->serial_num = NULL; 88552c9ce25SScott Long path->device->serial_num_len = 0; 88652c9ce25SScott Long } 8873089bb2eSAlexander Motin if (path->device->device_id != NULL) { 8883089bb2eSAlexander Motin free(path->device->device_id, M_CAMXPT); 8893089bb2eSAlexander Motin path->device->device_id = NULL; 8903089bb2eSAlexander Motin path->device->device_id_len = 0; 8913089bb2eSAlexander Motin } 89252c9ce25SScott Long path->device->serial_num = 89352c9ce25SScott Long (u_int8_t *)malloc((sizeof(ident_buf->serial) + 1), 89452c9ce25SScott Long M_CAMXPT, M_NOWAIT); 89552c9ce25SScott Long if (path->device->serial_num != NULL) { 89652c9ce25SScott Long bcopy(ident_buf->serial, 89752c9ce25SScott Long path->device->serial_num, 89852c9ce25SScott Long sizeof(ident_buf->serial)); 89952c9ce25SScott Long path->device->serial_num[sizeof(ident_buf->serial)] 90052c9ce25SScott Long = '\0'; 90152c9ce25SScott Long path->device->serial_num_len = 90252c9ce25SScott Long strlen(path->device->serial_num); 90352c9ce25SScott Long } 9043089bb2eSAlexander Motin if (ident_buf->enabled.extension & 9053089bb2eSAlexander Motin ATA_SUPPORT_64BITWWN) { 9063089bb2eSAlexander Motin path->device->device_id = 9073089bb2eSAlexander Motin malloc(16, M_CAMXPT, M_NOWAIT); 9083089bb2eSAlexander Motin if (path->device->device_id != NULL) { 9093089bb2eSAlexander Motin path->device->device_id_len = 16; 9103089bb2eSAlexander Motin bcopy(&fake_device_id_hdr, 9113089bb2eSAlexander Motin path->device->device_id, 8); 9123d6dd54eSAlexander Motin bcopy(ident_buf->wwn, 9133d6dd54eSAlexander Motin path->device->device_id + 8, 8); 9143d6dd54eSAlexander Motin ata_bswap(path->device->device_id + 8, 8); 9153089bb2eSAlexander Motin } 9163089bb2eSAlexander Motin } 91752c9ce25SScott Long 9184b997c49SAlexander Motin path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 919581b2e78SAlexander Motin xpt_async(AC_GETDEV_CHANGED, path, NULL); 9201e637ba6SAlexander Motin } 92130a4094fSAlexander Motin if (ident_buf->satacapabilities & ATA_SUPPORT_NCQ) { 9227dc3213dSAlexander Motin path->device->mintags = 2; 9237dc3213dSAlexander Motin path->device->maxtags = 92430a4094fSAlexander Motin ATA_QUEUE_LEN(ident_buf->queue) + 1; 92530a4094fSAlexander Motin } 92630a4094fSAlexander Motin ata_find_quirk(path->device); 927507e5811SAlexander Motin if (path->device->mintags != 0 && 928507e5811SAlexander Motin path->bus->sim->max_tagged_dev_openings != 0) { 929699f853bSAlexander Motin /* Check if the SIM does not want queued commands. */ 930699f853bSAlexander Motin bzero(&cpi, sizeof(cpi)); 931699f853bSAlexander Motin xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 932699f853bSAlexander Motin cpi.ccb_h.func_code = XPT_PATH_INQ; 933699f853bSAlexander Motin xpt_action((union ccb *)&cpi); 934699f853bSAlexander Motin if (cpi.ccb_h.status == CAM_REQ_CMP && 935699f853bSAlexander Motin (cpi.hba_inquiry & PI_TAG_ABLE)) { 936c8039fc6SAlexander Motin /* Report SIM which tags are allowed. */ 937c8039fc6SAlexander Motin bzero(&cts, sizeof(cts)); 93883c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 939c8039fc6SAlexander Motin cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 940c8039fc6SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 941c8039fc6SAlexander Motin cts.xport_specific.sata.tags = path->device->maxtags; 942c8039fc6SAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_TAGS; 943c8039fc6SAlexander Motin xpt_action((union ccb *)&cts); 94430a4094fSAlexander Motin } 945699f853bSAlexander Motin } 946bc1bf6e8SAlexander Motin ata_device_transport(path); 947b9c473b2SAlexander Motin if (changed) 948b9c473b2SAlexander Motin proberequestdefaultnegotiation(periph); 94952c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_SETMODE); 95052c9ce25SScott Long xpt_release_ccb(done_ccb); 95152c9ce25SScott Long xpt_schedule(periph, priority); 952cccf4220SAlexander Motin goto out; 95352c9ce25SScott Long } 9544ef08dc5SAlexander Motin case PROBE_SPINUP: 9554ef08dc5SAlexander Motin if (bootverbose) 9564ef08dc5SAlexander Motin xpt_print(path, "Spin-up done\n"); 9574ef08dc5SAlexander Motin softc->spinup = 1; 9584ef08dc5SAlexander Motin PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 9594ef08dc5SAlexander Motin xpt_release_ccb(done_ccb); 9604ef08dc5SAlexander Motin xpt_schedule(periph, priority); 961cccf4220SAlexander Motin goto out; 96252c9ce25SScott Long case PROBE_SETMODE: 963da6808c1SAlexander Motin /* Set supported bits. */ 964da6808c1SAlexander Motin bzero(&cts, sizeof(cts)); 965da6808c1SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 966da6808c1SAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 967da6808c1SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 968da6808c1SAlexander Motin xpt_action((union ccb *)&cts); 9692e1eb332SMarius Strobl if (path->device->transport == XPORT_SATA && 9702e1eb332SMarius Strobl cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 971da6808c1SAlexander Motin caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H; 9722e1eb332SMarius Strobl else if (path->device->transport == XPORT_ATA && 9732e1eb332SMarius Strobl cts.xport_specific.ata.valid & CTS_ATA_VALID_CAPS) 9742e1eb332SMarius Strobl caps = cts.xport_specific.ata.caps & CTS_ATA_CAPS_H; 975da6808c1SAlexander Motin else 976da6808c1SAlexander Motin caps = 0; 9772e1eb332SMarius Strobl if (path->device->transport == XPORT_SATA && 9782e1eb332SMarius Strobl ident_buf->satacapabilities != 0xffff) { 979da6808c1SAlexander Motin if (ident_buf->satacapabilities & ATA_SUPPORT_IFPWRMNGTRCV) 980da6808c1SAlexander Motin caps |= CTS_SATA_CAPS_D_PMREQ; 981da6808c1SAlexander Motin if (ident_buf->satacapabilities & ATA_SUPPORT_HAPST) 982da6808c1SAlexander Motin caps |= CTS_SATA_CAPS_D_APST; 983da6808c1SAlexander Motin } 984da6808c1SAlexander Motin /* Mask unwanted bits. */ 985da6808c1SAlexander Motin bzero(&cts, sizeof(cts)); 986da6808c1SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 987da6808c1SAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 988da6808c1SAlexander Motin cts.type = CTS_TYPE_USER_SETTINGS; 989da6808c1SAlexander Motin xpt_action((union ccb *)&cts); 9902e1eb332SMarius Strobl if (path->device->transport == XPORT_SATA && 9912e1eb332SMarius Strobl cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 992da6808c1SAlexander Motin caps &= cts.xport_specific.sata.caps; 9932e1eb332SMarius Strobl else if (path->device->transport == XPORT_ATA && 9942e1eb332SMarius Strobl cts.xport_specific.ata.valid & CTS_ATA_VALID_CAPS) 9952e1eb332SMarius Strobl caps &= cts.xport_specific.ata.caps; 996c2b82f3eSAlexander Motin else 997c2b82f3eSAlexander Motin caps = 0; 9982e1eb332SMarius Strobl /* 9992e1eb332SMarius Strobl * Remember what transport thinks about 48-bit DMA. If 10002e1eb332SMarius Strobl * capability information is not provided or transport is 10012e1eb332SMarius Strobl * SATA, we take support for granted. 10022e1eb332SMarius Strobl */ 10032e1eb332SMarius Strobl if (!(path->device->inq_flags & SID_DMA) || 10042e1eb332SMarius Strobl (path->device->transport == XPORT_ATA && 10052e1eb332SMarius Strobl (cts.xport_specific.ata.valid & CTS_ATA_VALID_CAPS) && 10062e1eb332SMarius Strobl !(caps & CTS_ATA_CAPS_H_DMA48))) 10072e1eb332SMarius Strobl path->device->inq_flags &= ~SID_DMA48; 10082e1eb332SMarius Strobl else 10092e1eb332SMarius Strobl path->device->inq_flags |= SID_DMA48; 1010da6808c1SAlexander Motin /* Store result to SIM. */ 1011da6808c1SAlexander Motin bzero(&cts, sizeof(cts)); 1012da6808c1SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1013da6808c1SAlexander Motin cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1014da6808c1SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 10152e1eb332SMarius Strobl if (path->device->transport == XPORT_SATA) { 1016da6808c1SAlexander Motin cts.xport_specific.sata.caps = caps; 1017da6808c1SAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS; 10182e1eb332SMarius Strobl } else { 10192e1eb332SMarius Strobl cts.xport_specific.ata.caps = caps; 10202e1eb332SMarius Strobl cts.xport_specific.ata.valid = CTS_ATA_VALID_CAPS; 10212e1eb332SMarius Strobl } 1022da6808c1SAlexander Motin xpt_action((union ccb *)&cts); 1023da6808c1SAlexander Motin softc->caps = caps; 10242e1eb332SMarius Strobl if (path->device->transport != XPORT_SATA) 10252e1eb332SMarius Strobl goto notsata; 1026958e4a69SAlexander Motin if ((ident_buf->satasupport & ATA_SUPPORT_IFPWRMNGT) && 1027958e4a69SAlexander Motin (!(softc->caps & CTS_SATA_CAPS_H_PMREQ)) != 1028958e4a69SAlexander Motin (!(ident_buf->sataenabled & ATA_SUPPORT_IFPWRMNGT))) { 1029da6808c1SAlexander Motin PROBE_SET_ACTION(softc, PROBE_SETPM); 1030da6808c1SAlexander Motin xpt_release_ccb(done_ccb); 1031da6808c1SAlexander Motin xpt_schedule(periph, priority); 1032cccf4220SAlexander Motin goto out; 1033da6808c1SAlexander Motin } 1034da6808c1SAlexander Motin /* FALLTHROUGH */ 1035da6808c1SAlexander Motin case PROBE_SETPM: 1036da6808c1SAlexander Motin if (ident_buf->satacapabilities != 0xffff && 1037958e4a69SAlexander Motin (ident_buf->satacapabilities & ATA_SUPPORT_DAPST) && 1038958e4a69SAlexander Motin (!(softc->caps & CTS_SATA_CAPS_H_APST)) != 1039958e4a69SAlexander Motin (!(ident_buf->sataenabled & ATA_ENABLED_DAPST))) { 1040da6808c1SAlexander Motin PROBE_SET_ACTION(softc, PROBE_SETAPST); 1041da6808c1SAlexander Motin xpt_release_ccb(done_ccb); 1042da6808c1SAlexander Motin xpt_schedule(periph, priority); 1043cccf4220SAlexander Motin goto out; 1044da6808c1SAlexander Motin } 1045da6808c1SAlexander Motin /* FALLTHROUGH */ 1046da6808c1SAlexander Motin case PROBE_SETAPST: 1047958e4a69SAlexander Motin if ((ident_buf->satasupport & ATA_SUPPORT_AUTOACTIVATE) && 1048958e4a69SAlexander Motin (!(softc->caps & CTS_SATA_CAPS_H_DMAAA)) != 1049958e4a69SAlexander Motin (!(ident_buf->sataenabled & ATA_SUPPORT_AUTOACTIVATE))) { 1050da6808c1SAlexander Motin PROBE_SET_ACTION(softc, PROBE_SETDMAAA); 1051da6808c1SAlexander Motin xpt_release_ccb(done_ccb); 1052da6808c1SAlexander Motin xpt_schedule(periph, priority); 1053cccf4220SAlexander Motin goto out; 1054da6808c1SAlexander Motin } 1055da6808c1SAlexander Motin /* FALLTHROUGH */ 1056da6808c1SAlexander Motin case PROBE_SETDMAAA: 1057e4bed0b4SWarner Losh if (path->device->protocol != PROTO_ATA && 1058e4bed0b4SWarner Losh (ident_buf->satasupport & ATA_SUPPORT_ASYNCNOTIF) && 10598d169381SAlexander Motin (!(softc->caps & CTS_SATA_CAPS_H_AN)) != 10608d169381SAlexander Motin (!(ident_buf->sataenabled & ATA_SUPPORT_ASYNCNOTIF))) { 10618d169381SAlexander Motin PROBE_SET_ACTION(softc, PROBE_SETAN); 10628d169381SAlexander Motin xpt_release_ccb(done_ccb); 10638d169381SAlexander Motin xpt_schedule(periph, priority); 1064cccf4220SAlexander Motin goto out; 10658d169381SAlexander Motin } 10668d169381SAlexander Motin /* FALLTHROUGH */ 10678d169381SAlexander Motin case PROBE_SETAN: 1068da6808c1SAlexander Motin notsata: 10691e637ba6SAlexander Motin if (path->device->protocol == PROTO_ATA) { 10701e637ba6SAlexander Motin PROBE_SET_ACTION(softc, PROBE_SET_MULTI); 10711e637ba6SAlexander Motin } else { 10721e637ba6SAlexander Motin PROBE_SET_ACTION(softc, PROBE_INQUIRY); 10731e637ba6SAlexander Motin } 10741e637ba6SAlexander Motin xpt_release_ccb(done_ccb); 10751e637ba6SAlexander Motin xpt_schedule(periph, priority); 1076cccf4220SAlexander Motin goto out; 10771e637ba6SAlexander Motin case PROBE_SET_MULTI: 10781e637ba6SAlexander Motin if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 107952c9ce25SScott Long path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1080f98d7a47SAlexander Motin xpt_acquire_device(path->device); 108152c9ce25SScott Long done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 108252c9ce25SScott Long xpt_action(done_ccb); 1083cccf4220SAlexander Motin xpt_async(AC_FOUND_DEVICE, path, done_ccb); 10841e637ba6SAlexander Motin } 1085a4d953c4SAlexander Motin PROBE_SET_ACTION(softc, PROBE_DONE); 108652c9ce25SScott Long break; 108752c9ce25SScott Long case PROBE_INQUIRY: 108852c9ce25SScott Long case PROBE_FULL_INQUIRY: 108952c9ce25SScott Long { 10901e637ba6SAlexander Motin u_int8_t periph_qual, len; 109152c9ce25SScott Long 109252c9ce25SScott Long path->device->flags |= CAM_DEV_INQUIRY_DATA_VALID; 109352c9ce25SScott Long 109452c9ce25SScott Long periph_qual = SID_QUAL(inq_buf); 109552c9ce25SScott Long 109692024858SAlexander Motin if (periph_qual != SID_QUAL_LU_CONNECTED && 109792024858SAlexander Motin periph_qual != SID_QUAL_LU_OFFLINE) 10981e637ba6SAlexander Motin break; 109952c9ce25SScott Long 110052c9ce25SScott Long /* 110152c9ce25SScott Long * We conservatively request only 110252c9ce25SScott Long * SHORT_INQUIRY_LEN bytes of inquiry 110352c9ce25SScott Long * information during our first try 110452c9ce25SScott Long * at sending an INQUIRY. If the device 110552c9ce25SScott Long * has more information to give, 110652c9ce25SScott Long * perform a second request specifying 110752c9ce25SScott Long * the amount of information the device 110852c9ce25SScott Long * is willing to give. 110952c9ce25SScott Long */ 111052c9ce25SScott Long len = inq_buf->additional_length 11111e637ba6SAlexander Motin + offsetof(struct scsi_inquiry_data, additional_length) + 1; 111252c9ce25SScott Long if (softc->action == PROBE_INQUIRY 111352c9ce25SScott Long && len > SHORT_INQUIRY_LENGTH) { 111452c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_FULL_INQUIRY); 111552c9ce25SScott Long xpt_release_ccb(done_ccb); 111652c9ce25SScott Long xpt_schedule(periph, priority); 1117cccf4220SAlexander Motin goto out; 111852c9ce25SScott Long } 111952c9ce25SScott Long 11204b997c49SAlexander Motin ata_device_transport(path); 11211e637ba6SAlexander Motin if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 112252c9ce25SScott Long path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1123f98d7a47SAlexander Motin xpt_acquire_device(path->device); 112452c9ce25SScott Long done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 112552c9ce25SScott Long xpt_action(done_ccb); 1126cccf4220SAlexander Motin xpt_async(AC_FOUND_DEVICE, path, done_ccb); 11271e637ba6SAlexander Motin } 1128a4d953c4SAlexander Motin PROBE_SET_ACTION(softc, PROBE_DONE); 112952c9ce25SScott Long break; 113052c9ce25SScott Long } 113152c9ce25SScott Long case PROBE_PM_PID: 11324b997c49SAlexander Motin if ((path->device->flags & CAM_DEV_IDENTIFY_DATA_VALID) == 0) 113352c9ce25SScott Long bzero(ident_buf, sizeof(*ident_buf)); 113452c9ce25SScott Long softc->pm_pid = (done_ccb->ataio.res.lba_high << 24) + 113552c9ce25SScott Long (done_ccb->ataio.res.lba_mid << 16) + 113652c9ce25SScott Long (done_ccb->ataio.res.lba_low << 8) + 113752c9ce25SScott Long done_ccb->ataio.res.sector_count; 113865d0fb03SAlexander Motin ((uint32_t *)ident_buf)[0] = softc->pm_pid; 113952c9ce25SScott Long snprintf(ident_buf->model, sizeof(ident_buf->model), 114052c9ce25SScott Long "Port Multiplier %08x", softc->pm_pid); 114152c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_PM_PRV); 114252c9ce25SScott Long xpt_release_ccb(done_ccb); 114352c9ce25SScott Long xpt_schedule(periph, priority); 1144cccf4220SAlexander Motin goto out; 114552c9ce25SScott Long case PROBE_PM_PRV: 114652c9ce25SScott Long softc->pm_prv = (done_ccb->ataio.res.lba_high << 24) + 114752c9ce25SScott Long (done_ccb->ataio.res.lba_mid << 16) + 114852c9ce25SScott Long (done_ccb->ataio.res.lba_low << 8) + 114952c9ce25SScott Long done_ccb->ataio.res.sector_count; 115065d0fb03SAlexander Motin ((uint32_t *)ident_buf)[1] = softc->pm_prv; 115152c9ce25SScott Long snprintf(ident_buf->revision, sizeof(ident_buf->revision), 115252c9ce25SScott Long "%04x", softc->pm_prv); 11534b997c49SAlexander Motin path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 1154bc1bf6e8SAlexander Motin ata_device_transport(path); 1155bc1bf6e8SAlexander Motin if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) 1156bc1bf6e8SAlexander Motin proberequestdefaultnegotiation(periph); 1157da6808c1SAlexander Motin /* Set supported bits. */ 1158da6808c1SAlexander Motin bzero(&cts, sizeof(cts)); 1159da6808c1SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1160da6808c1SAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1161da6808c1SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 1162da6808c1SAlexander Motin xpt_action((union ccb *)&cts); 1163da6808c1SAlexander Motin if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1164da6808c1SAlexander Motin caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H; 1165da6808c1SAlexander Motin else 1166da6808c1SAlexander Motin caps = 0; 1167da6808c1SAlexander Motin /* All PMPs must support PM requests. */ 1168da6808c1SAlexander Motin caps |= CTS_SATA_CAPS_D_PMREQ; 1169da6808c1SAlexander Motin /* Mask unwanted bits. */ 1170da6808c1SAlexander Motin bzero(&cts, sizeof(cts)); 1171da6808c1SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1172da6808c1SAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1173da6808c1SAlexander Motin cts.type = CTS_TYPE_USER_SETTINGS; 1174da6808c1SAlexander Motin xpt_action((union ccb *)&cts); 1175da6808c1SAlexander Motin if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1176da6808c1SAlexander Motin caps &= cts.xport_specific.sata.caps; 1177c2b82f3eSAlexander Motin else 1178c2b82f3eSAlexander Motin caps = 0; 11792e1eb332SMarius Strobl /* Remember what transport thinks about AEN. */ 1180e4bed0b4SWarner Losh if ((caps & CTS_SATA_CAPS_H_AN) && path->device->protocol != PROTO_ATA) 11812e1eb332SMarius Strobl path->device->inq_flags |= SID_AEN; 11822e1eb332SMarius Strobl else 11832e1eb332SMarius Strobl path->device->inq_flags &= ~SID_AEN; 1184da6808c1SAlexander Motin /* Store result to SIM. */ 1185da6808c1SAlexander Motin bzero(&cts, sizeof(cts)); 1186da6808c1SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1187da6808c1SAlexander Motin cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1188da6808c1SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 1189da6808c1SAlexander Motin cts.xport_specific.sata.caps = caps; 1190da6808c1SAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS; 1191da6808c1SAlexander Motin xpt_action((union ccb *)&cts); 1192da6808c1SAlexander Motin softc->caps = caps; 11933631c638SAlexander Motin xpt_async(AC_GETDEV_CHANGED, path, NULL); 119465d0fb03SAlexander Motin if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 119552c9ce25SScott Long path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1196f98d7a47SAlexander Motin xpt_acquire_device(path->device); 119752c9ce25SScott Long done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 119852c9ce25SScott Long xpt_action(done_ccb); 1199cccf4220SAlexander Motin xpt_async(AC_FOUND_DEVICE, path, done_ccb); 120065d0fb03SAlexander Motin } else { 120165d0fb03SAlexander Motin done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 120265d0fb03SAlexander Motin xpt_action(done_ccb); 1203cccf4220SAlexander Motin xpt_async(AC_SCSI_AEN, path, done_ccb); 120452c9ce25SScott Long } 1205a4d953c4SAlexander Motin PROBE_SET_ACTION(softc, PROBE_DONE); 120652c9ce25SScott Long break; 12073089bb2eSAlexander Motin case PROBE_IDENTIFY_SES: 12083089bb2eSAlexander Motin case PROBE_IDENTIFY_SAFTE: 12093089bb2eSAlexander Motin if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) { 12103089bb2eSAlexander Motin /* Check that it is the same device. */ 12113089bb2eSAlexander Motin if (bcmp(&softc->ident_data, ident_buf, 53)) { 12123089bb2eSAlexander Motin /* Device changed. */ 12133089bb2eSAlexander Motin xpt_async(AC_LOST_DEVICE, path, NULL); 12143089bb2eSAlexander Motin } else { 12153089bb2eSAlexander Motin bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 12163089bb2eSAlexander Motin changed = 0; 12173089bb2eSAlexander Motin } 12183089bb2eSAlexander Motin } 12193089bb2eSAlexander Motin if (changed) { 12203089bb2eSAlexander Motin bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 12213089bb2eSAlexander Motin /* Clean up from previous instance of this device */ 12223089bb2eSAlexander Motin if (path->device->device_id != NULL) { 12233089bb2eSAlexander Motin free(path->device->device_id, M_CAMXPT); 12243089bb2eSAlexander Motin path->device->device_id = NULL; 12253089bb2eSAlexander Motin path->device->device_id_len = 0; 12263089bb2eSAlexander Motin } 12273089bb2eSAlexander Motin path->device->device_id = 12283089bb2eSAlexander Motin malloc(16, M_CAMXPT, M_NOWAIT); 12293089bb2eSAlexander Motin if (path->device->device_id != NULL) { 12303089bb2eSAlexander Motin path->device->device_id_len = 16; 12313089bb2eSAlexander Motin bcopy(&fake_device_id_hdr, 12323089bb2eSAlexander Motin path->device->device_id, 8); 12333089bb2eSAlexander Motin bcopy(((uint8_t*)ident_buf) + 2, 12343089bb2eSAlexander Motin path->device->device_id + 8, 8); 12353089bb2eSAlexander Motin } 12363089bb2eSAlexander Motin 12373089bb2eSAlexander Motin path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 12383089bb2eSAlexander Motin } 1239bc1bf6e8SAlexander Motin ata_device_transport(path); 1240bc1bf6e8SAlexander Motin if (changed) 1241bc1bf6e8SAlexander Motin proberequestdefaultnegotiation(periph); 12423089bb2eSAlexander Motin 12433089bb2eSAlexander Motin if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 12443089bb2eSAlexander Motin path->device->flags &= ~CAM_DEV_UNCONFIGURED; 12453089bb2eSAlexander Motin xpt_acquire_device(path->device); 12463089bb2eSAlexander Motin done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 12473089bb2eSAlexander Motin xpt_action(done_ccb); 1248cccf4220SAlexander Motin xpt_async(AC_FOUND_DEVICE, path, done_ccb); 12493089bb2eSAlexander Motin } 1250a4d953c4SAlexander Motin PROBE_SET_ACTION(softc, PROBE_DONE); 12513089bb2eSAlexander Motin break; 125252c9ce25SScott Long default: 1253a4d953c4SAlexander Motin panic("probedone: invalid action state 0x%x\n", softc->action); 125452c9ce25SScott Long } 12551e637ba6SAlexander Motin done: 125683c5d981SAlexander Motin if (softc->restart) { 125783c5d981SAlexander Motin softc->restart = 0; 12581e637ba6SAlexander Motin xpt_release_ccb(done_ccb); 125983c5d981SAlexander Motin probeschedule(periph); 1260cccf4220SAlexander Motin goto out; 126183c5d981SAlexander Motin } 126283c5d981SAlexander Motin xpt_release_ccb(done_ccb); 1263a4d953c4SAlexander Motin CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe completed\n")); 126483c5d981SAlexander Motin while ((done_ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs))) { 126583c5d981SAlexander Motin TAILQ_REMOVE(&softc->request_ccbs, 126683c5d981SAlexander Motin &done_ccb->ccb_h, periph_links.tqe); 126783c5d981SAlexander Motin done_ccb->ccb_h.status = found ? CAM_REQ_CMP : CAM_REQ_CMP_ERR; 126852c9ce25SScott Long xpt_done(done_ccb); 126983c5d981SAlexander Motin } 1270cccf4220SAlexander Motin /* Drop freeze taken due to CAM_DEV_QFREEZE flag set. */ 1271cccf4220SAlexander Motin cam_release_devq(path, 0, 0, 0, FALSE); 12722e3f592bSAlexander Motin cam_periph_invalidate(periph); 127352c9ce25SScott Long cam_periph_release_locked(periph); 127452c9ce25SScott Long } 127552c9ce25SScott Long 127652c9ce25SScott Long static void 127752c9ce25SScott Long probecleanup(struct cam_periph *periph) 127852c9ce25SScott Long { 127952c9ce25SScott Long free(periph->softc, M_CAMXPT); 128052c9ce25SScott Long } 128152c9ce25SScott Long 128252c9ce25SScott Long static void 128330a4094fSAlexander Motin ata_find_quirk(struct cam_ed *device) 128452c9ce25SScott Long { 128530a4094fSAlexander Motin struct ata_quirk_entry *quirk; 128652c9ce25SScott Long caddr_t match; 128752c9ce25SScott Long 128830a4094fSAlexander Motin match = cam_quirkmatch((caddr_t)&device->ident_data, 128930a4094fSAlexander Motin (caddr_t)ata_quirk_table, 12908dfea464SPedro F. Giffuni nitems(ata_quirk_table), 129130a4094fSAlexander Motin sizeof(*ata_quirk_table), ata_identify_match); 129252c9ce25SScott Long 129352c9ce25SScott Long if (match == NULL) 129452c9ce25SScott Long panic("xpt_find_quirk: device didn't match wildcard entry!!"); 129552c9ce25SScott Long 129630a4094fSAlexander Motin quirk = (struct ata_quirk_entry *)match; 129752c9ce25SScott Long device->quirk = quirk; 12987dc3213dSAlexander Motin if (quirk->quirks & CAM_QUIRK_MAXTAGS) { 12997dc3213dSAlexander Motin device->mintags = quirk->mintags; 13007dc3213dSAlexander Motin device->maxtags = quirk->maxtags; 13017dc3213dSAlexander Motin } 130252c9ce25SScott Long } 130352c9ce25SScott Long 130452c9ce25SScott Long typedef struct { 130552c9ce25SScott Long union ccb *request_ccb; 130652c9ce25SScott Long struct ccb_pathinq *cpi; 130752c9ce25SScott Long int counter; 130852c9ce25SScott Long } ata_scan_bus_info; 130952c9ce25SScott Long 131052c9ce25SScott Long /* 131152c9ce25SScott Long * To start a scan, request_ccb is an XPT_SCAN_BUS ccb. 131252c9ce25SScott Long * As the scan progresses, xpt_scan_bus is used as the 131352c9ce25SScott Long * callback on completion function. 131452c9ce25SScott Long */ 131552c9ce25SScott Long static void 131652c9ce25SScott Long ata_scan_bus(struct cam_periph *periph, union ccb *request_ccb) 131752c9ce25SScott Long { 131852c9ce25SScott Long struct cam_path *path; 131952c9ce25SScott Long ata_scan_bus_info *scan_info; 132083c5d981SAlexander Motin union ccb *work_ccb, *reset_ccb; 1321227d67aaSAlexander Motin struct mtx *mtx; 132252c9ce25SScott Long cam_status status; 132352c9ce25SScott Long 132452c9ce25SScott Long CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE, 132552c9ce25SScott Long ("xpt_scan_bus\n")); 132652c9ce25SScott Long switch (request_ccb->ccb_h.func_code) { 132752c9ce25SScott Long case XPT_SCAN_BUS: 13280e85f214SMatt Jacob case XPT_SCAN_TGT: 132952c9ce25SScott Long /* Find out the characteristics of the bus */ 133052c9ce25SScott Long work_ccb = xpt_alloc_ccb_nowait(); 133152c9ce25SScott Long if (work_ccb == NULL) { 133252c9ce25SScott Long request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 133352c9ce25SScott Long xpt_done(request_ccb); 133452c9ce25SScott Long return; 133552c9ce25SScott Long } 133652c9ce25SScott Long xpt_setup_ccb(&work_ccb->ccb_h, request_ccb->ccb_h.path, 133752c9ce25SScott Long request_ccb->ccb_h.pinfo.priority); 133852c9ce25SScott Long work_ccb->ccb_h.func_code = XPT_PATH_INQ; 133952c9ce25SScott Long xpt_action(work_ccb); 134052c9ce25SScott Long if (work_ccb->ccb_h.status != CAM_REQ_CMP) { 134152c9ce25SScott Long request_ccb->ccb_h.status = work_ccb->ccb_h.status; 134252c9ce25SScott Long xpt_free_ccb(work_ccb); 134352c9ce25SScott Long xpt_done(request_ccb); 134452c9ce25SScott Long return; 134552c9ce25SScott Long } 134652c9ce25SScott Long 134783c5d981SAlexander Motin /* We may need to reset bus first, if we haven't done it yet. */ 134883c5d981SAlexander Motin if ((work_ccb->cpi.hba_inquiry & 134983c5d981SAlexander Motin (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE)) && 135083c5d981SAlexander Motin !(work_ccb->cpi.hba_misc & PIM_NOBUSRESET) && 135183c5d981SAlexander Motin !timevalisset(&request_ccb->ccb_h.path->bus->last_reset)) { 135283c5d981SAlexander Motin reset_ccb = xpt_alloc_ccb_nowait(); 1353f1893540SAlexander Motin if (reset_ccb == NULL) { 1354f1893540SAlexander Motin request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1355f1893540SAlexander Motin xpt_free_ccb(work_ccb); 1356f1893540SAlexander Motin xpt_done(request_ccb); 1357f1893540SAlexander Motin return; 1358f1893540SAlexander Motin } 135983c5d981SAlexander Motin xpt_setup_ccb(&reset_ccb->ccb_h, request_ccb->ccb_h.path, 136083c5d981SAlexander Motin CAM_PRIORITY_NONE); 136183c5d981SAlexander Motin reset_ccb->ccb_h.func_code = XPT_RESET_BUS; 136283c5d981SAlexander Motin xpt_action(reset_ccb); 136383c5d981SAlexander Motin if (reset_ccb->ccb_h.status != CAM_REQ_CMP) { 136483c5d981SAlexander Motin request_ccb->ccb_h.status = reset_ccb->ccb_h.status; 136583c5d981SAlexander Motin xpt_free_ccb(reset_ccb); 136683c5d981SAlexander Motin xpt_free_ccb(work_ccb); 136783c5d981SAlexander Motin xpt_done(request_ccb); 136883c5d981SAlexander Motin return; 136983c5d981SAlexander Motin } 137083c5d981SAlexander Motin xpt_free_ccb(reset_ccb); 137183c5d981SAlexander Motin } 137283c5d981SAlexander Motin 137352c9ce25SScott Long /* Save some state for use while we probe for devices */ 137452c9ce25SScott Long scan_info = (ata_scan_bus_info *) 137552c9ce25SScott Long malloc(sizeof(ata_scan_bus_info), M_CAMXPT, M_NOWAIT); 137652c9ce25SScott Long if (scan_info == NULL) { 137752c9ce25SScott Long request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1378f1893540SAlexander Motin xpt_free_ccb(work_ccb); 137952c9ce25SScott Long xpt_done(request_ccb); 138052c9ce25SScott Long return; 138152c9ce25SScott Long } 138252c9ce25SScott Long scan_info->request_ccb = request_ccb; 138352c9ce25SScott Long scan_info->cpi = &work_ccb->cpi; 138452c9ce25SScott Long /* If PM supported, probe it first. */ 138552c9ce25SScott Long if (scan_info->cpi->hba_inquiry & PI_SATAPM) 13860025eb12SAlexander Motin scan_info->counter = scan_info->cpi->max_target; 13870025eb12SAlexander Motin else 13880025eb12SAlexander Motin scan_info->counter = 0; 138952c9ce25SScott Long 139052c9ce25SScott Long work_ccb = xpt_alloc_ccb_nowait(); 139152c9ce25SScott Long if (work_ccb == NULL) { 139252c9ce25SScott Long free(scan_info, M_CAMXPT); 139352c9ce25SScott Long request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 139452c9ce25SScott Long xpt_done(request_ccb); 139552c9ce25SScott Long break; 139652c9ce25SScott Long } 1397227d67aaSAlexander Motin mtx = xpt_path_mtx(scan_info->request_ccb->ccb_h.path); 139852c9ce25SScott Long goto scan_next; 139952c9ce25SScott Long case XPT_SCAN_LUN: 140052c9ce25SScott Long work_ccb = request_ccb; 140152c9ce25SScott Long /* Reuse the same CCB to query if a device was really found */ 140252c9ce25SScott Long scan_info = (ata_scan_bus_info *)work_ccb->ccb_h.ppriv_ptr0; 1403227d67aaSAlexander Motin mtx = xpt_path_mtx(scan_info->request_ccb->ccb_h.path); 1404227d67aaSAlexander Motin mtx_lock(mtx); 140565d0fb03SAlexander Motin /* If there is PMP... */ 14060025eb12SAlexander Motin if ((scan_info->cpi->hba_inquiry & PI_SATAPM) && 14070025eb12SAlexander Motin (scan_info->counter == scan_info->cpi->max_target)) { 140883c5d981SAlexander Motin if (work_ccb->ccb_h.status == CAM_REQ_CMP) { 140965d0fb03SAlexander Motin /* everything else will be probed by it */ 1410e2a75189SAlexander Motin /* Free the current request path- we're done with it. */ 1411e2a75189SAlexander Motin xpt_free_path(work_ccb->ccb_h.path); 14120025eb12SAlexander Motin goto done; 141352c9ce25SScott Long } else { 141452c9ce25SScott Long struct ccb_trans_settings cts; 141552c9ce25SScott Long 141652c9ce25SScott Long /* Report SIM that PM is absent. */ 141752c9ce25SScott Long bzero(&cts, sizeof(cts)); 141852c9ce25SScott Long xpt_setup_ccb(&cts.ccb_h, 1419e2a75189SAlexander Motin work_ccb->ccb_h.path, CAM_PRIORITY_NONE); 142052c9ce25SScott Long cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 142152c9ce25SScott Long cts.type = CTS_TYPE_CURRENT_SETTINGS; 14223ccda2f3SAlexander Motin cts.xport_specific.sata.pm_present = 0; 142352c9ce25SScott Long cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; 142452c9ce25SScott Long xpt_action((union ccb *)&cts); 142552c9ce25SScott Long } 142652c9ce25SScott Long } 1427e2a75189SAlexander Motin /* Free the current request path- we're done with it. */ 1428e2a75189SAlexander Motin xpt_free_path(work_ccb->ccb_h.path); 14290025eb12SAlexander Motin if (scan_info->counter == 14300025eb12SAlexander Motin ((scan_info->cpi->hba_inquiry & PI_SATAPM) ? 14310025eb12SAlexander Motin 0 : scan_info->cpi->max_target)) { 14320025eb12SAlexander Motin done: 1433227d67aaSAlexander Motin mtx_unlock(mtx); 143452c9ce25SScott Long xpt_free_ccb(work_ccb); 143552c9ce25SScott Long xpt_free_ccb((union ccb *)scan_info->cpi); 143652c9ce25SScott Long request_ccb = scan_info->request_ccb; 143752c9ce25SScott Long free(scan_info, M_CAMXPT); 143852c9ce25SScott Long request_ccb->ccb_h.status = CAM_REQ_CMP; 143952c9ce25SScott Long xpt_done(request_ccb); 144052c9ce25SScott Long break; 144152c9ce25SScott Long } 14420025eb12SAlexander Motin /* Take next device. Wrap from max (PMP) to 0. */ 14430025eb12SAlexander Motin scan_info->counter = (scan_info->counter + 1 ) % 14440025eb12SAlexander Motin (scan_info->cpi->max_target + 1); 144552c9ce25SScott Long scan_next: 1446e5dfa058SAlexander Motin status = xpt_create_path(&path, NULL, 144752c9ce25SScott Long scan_info->request_ccb->ccb_h.path_id, 144852c9ce25SScott Long scan_info->counter, 0); 144952c9ce25SScott Long if (status != CAM_REQ_CMP) { 1450227d67aaSAlexander Motin if (request_ccb->ccb_h.func_code == XPT_SCAN_LUN) 1451227d67aaSAlexander Motin mtx_unlock(mtx); 145252c9ce25SScott Long printf("xpt_scan_bus: xpt_create_path failed" 145352c9ce25SScott Long " with status %#x, bus scan halted\n", 145452c9ce25SScott Long status); 145552c9ce25SScott Long xpt_free_ccb(work_ccb); 145652c9ce25SScott Long xpt_free_ccb((union ccb *)scan_info->cpi); 145752c9ce25SScott Long request_ccb = scan_info->request_ccb; 145852c9ce25SScott Long free(scan_info, M_CAMXPT); 145952c9ce25SScott Long request_ccb->ccb_h.status = status; 146052c9ce25SScott Long xpt_done(request_ccb); 146152c9ce25SScott Long break; 146252c9ce25SScott Long } 146352c9ce25SScott Long xpt_setup_ccb(&work_ccb->ccb_h, path, 146452c9ce25SScott Long scan_info->request_ccb->ccb_h.pinfo.priority); 146552c9ce25SScott Long work_ccb->ccb_h.func_code = XPT_SCAN_LUN; 146652c9ce25SScott Long work_ccb->ccb_h.cbfcnp = ata_scan_bus; 1467227d67aaSAlexander Motin work_ccb->ccb_h.flags |= CAM_UNLOCKED; 146852c9ce25SScott Long work_ccb->ccb_h.ppriv_ptr0 = scan_info; 146952c9ce25SScott Long work_ccb->crcn.flags = scan_info->request_ccb->crcn.flags; 1470227d67aaSAlexander Motin mtx_unlock(mtx); 1471227d67aaSAlexander Motin if (request_ccb->ccb_h.func_code == XPT_SCAN_LUN) 1472227d67aaSAlexander Motin mtx = NULL; 147352c9ce25SScott Long xpt_action(work_ccb); 1474227d67aaSAlexander Motin if (mtx != NULL) 1475227d67aaSAlexander Motin mtx_lock(mtx); 147652c9ce25SScott Long break; 147752c9ce25SScott Long default: 147852c9ce25SScott Long break; 147952c9ce25SScott Long } 148052c9ce25SScott Long } 148152c9ce25SScott Long 148252c9ce25SScott Long static void 148352c9ce25SScott Long ata_scan_lun(struct cam_periph *periph, struct cam_path *path, 148452c9ce25SScott Long cam_flags flags, union ccb *request_ccb) 148552c9ce25SScott Long { 148652c9ce25SScott Long struct ccb_pathinq cpi; 148752c9ce25SScott Long cam_status status; 148852c9ce25SScott Long struct cam_path *new_path; 148952c9ce25SScott Long struct cam_periph *old_periph; 1490227d67aaSAlexander Motin int lock; 149152c9ce25SScott Long 149283c5d981SAlexander Motin CAM_DEBUG(path, CAM_DEBUG_TRACE, ("xpt_scan_lun\n")); 149352c9ce25SScott Long 149483c5d981SAlexander Motin xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 149552c9ce25SScott Long cpi.ccb_h.func_code = XPT_PATH_INQ; 149652c9ce25SScott Long xpt_action((union ccb *)&cpi); 149752c9ce25SScott Long 149852c9ce25SScott Long if (cpi.ccb_h.status != CAM_REQ_CMP) { 149952c9ce25SScott Long if (request_ccb != NULL) { 150052c9ce25SScott Long request_ccb->ccb_h.status = cpi.ccb_h.status; 150152c9ce25SScott Long xpt_done(request_ccb); 150252c9ce25SScott Long } 150352c9ce25SScott Long return; 150452c9ce25SScott Long } 150552c9ce25SScott Long 150652c9ce25SScott Long if (request_ccb == NULL) { 150732aa80a6SAlexander Motin request_ccb = xpt_alloc_ccb_nowait(); 150852c9ce25SScott Long if (request_ccb == NULL) { 150952c9ce25SScott Long xpt_print(path, "xpt_scan_lun: can't allocate CCB, " 151052c9ce25SScott Long "can't continue\n"); 151152c9ce25SScott Long return; 151252c9ce25SScott Long } 1513e5dfa058SAlexander Motin status = xpt_create_path(&new_path, NULL, 151452c9ce25SScott Long path->bus->path_id, 151552c9ce25SScott Long path->target->target_id, 151652c9ce25SScott Long path->device->lun_id); 151752c9ce25SScott Long if (status != CAM_REQ_CMP) { 151832aa80a6SAlexander Motin xpt_print(path, "xpt_scan_lun: can't create path, " 151952c9ce25SScott Long "can't continue\n"); 152032aa80a6SAlexander Motin xpt_free_ccb(request_ccb); 152152c9ce25SScott Long return; 152252c9ce25SScott Long } 152383c5d981SAlexander Motin xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_XPT); 152452c9ce25SScott Long request_ccb->ccb_h.cbfcnp = xptscandone; 1525227d67aaSAlexander Motin request_ccb->ccb_h.flags |= CAM_UNLOCKED; 152652c9ce25SScott Long request_ccb->ccb_h.func_code = XPT_SCAN_LUN; 152752c9ce25SScott Long request_ccb->crcn.flags = flags; 152852c9ce25SScott Long } 152952c9ce25SScott Long 1530227d67aaSAlexander Motin lock = (xpt_path_owned(path) == 0); 1531227d67aaSAlexander Motin if (lock) 1532227d67aaSAlexander Motin xpt_path_lock(path); 1533f09f8e3eSAlexander Motin if ((old_periph = cam_periph_find(path, "aprobe")) != NULL) { 15342e3f592bSAlexander Motin if ((old_periph->flags & CAM_PERIPH_INVALID) == 0) { 153552c9ce25SScott Long probe_softc *softc; 153652c9ce25SScott Long 153752c9ce25SScott Long softc = (probe_softc *)old_periph->softc; 15382e3f592bSAlexander Motin TAILQ_INSERT_TAIL(&softc->request_ccbs, 15392e3f592bSAlexander Motin &request_ccb->ccb_h, periph_links.tqe); 154083c5d981SAlexander Motin softc->restart = 1; 154152c9ce25SScott Long } else { 15422e3f592bSAlexander Motin request_ccb->ccb_h.status = CAM_REQ_CMP_ERR; 15432e3f592bSAlexander Motin xpt_done(request_ccb); 15442e3f592bSAlexander Motin } 15452e3f592bSAlexander Motin } else { 154652c9ce25SScott Long status = cam_periph_alloc(proberegister, NULL, probecleanup, 1547f09f8e3eSAlexander Motin probestart, "aprobe", 154852c9ce25SScott Long CAM_PERIPH_BIO, 154952c9ce25SScott Long request_ccb->ccb_h.path, NULL, 0, 155052c9ce25SScott Long request_ccb); 155152c9ce25SScott Long 155252c9ce25SScott Long if (status != CAM_REQ_CMP) { 155352c9ce25SScott Long xpt_print(path, "xpt_scan_lun: cam_alloc_periph " 155452c9ce25SScott Long "returned an error, can't continue probe\n"); 155552c9ce25SScott Long request_ccb->ccb_h.status = status; 155652c9ce25SScott Long xpt_done(request_ccb); 155752c9ce25SScott Long } 155852c9ce25SScott Long } 1559227d67aaSAlexander Motin if (lock) 1560227d67aaSAlexander Motin xpt_path_unlock(path); 156152c9ce25SScott Long } 156252c9ce25SScott Long 156352c9ce25SScott Long static void 156452c9ce25SScott Long xptscandone(struct cam_periph *periph, union ccb *done_ccb) 156552c9ce25SScott Long { 156632aa80a6SAlexander Motin 156732aa80a6SAlexander Motin xpt_free_path(done_ccb->ccb_h.path); 156832aa80a6SAlexander Motin xpt_free_ccb(done_ccb); 156952c9ce25SScott Long } 157052c9ce25SScott Long 157152c9ce25SScott Long static struct cam_ed * 157252c9ce25SScott Long ata_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id) 157352c9ce25SScott Long { 157430a4094fSAlexander Motin struct ata_quirk_entry *quirk; 157552c9ce25SScott Long struct cam_ed *device; 157652c9ce25SScott Long 157752c9ce25SScott Long device = xpt_alloc_device(bus, target, lun_id); 157852c9ce25SScott Long if (device == NULL) 157952c9ce25SScott Long return (NULL); 158052c9ce25SScott Long 158152c9ce25SScott Long /* 158252c9ce25SScott Long * Take the default quirk entry until we have inquiry 158352c9ce25SScott Long * data and can determine a better quirk to use. 158452c9ce25SScott Long */ 15858dfea464SPedro F. Giffuni quirk = &ata_quirk_table[nitems(ata_quirk_table) - 1]; 158652c9ce25SScott Long device->quirk = (void *)quirk; 158730a4094fSAlexander Motin device->mintags = 0; 158830a4094fSAlexander Motin device->maxtags = 0; 158952c9ce25SScott Long bzero(&device->inq_data, sizeof(device->inq_data)); 159052c9ce25SScott Long device->inq_flags = 0; 159152c9ce25SScott Long device->queue_flags = 0; 159252c9ce25SScott Long device->serial_num = NULL; 159352c9ce25SScott Long device->serial_num_len = 0; 159452c9ce25SScott Long return (device); 159552c9ce25SScott Long } 159652c9ce25SScott Long 159752c9ce25SScott Long static void 159852c9ce25SScott Long ata_device_transport(struct cam_path *path) 159952c9ce25SScott Long { 160052c9ce25SScott Long struct ccb_pathinq cpi; 16014b997c49SAlexander Motin struct ccb_trans_settings cts; 16024b997c49SAlexander Motin struct scsi_inquiry_data *inq_buf = NULL; 16034b997c49SAlexander Motin struct ata_params *ident_buf = NULL; 160452c9ce25SScott Long 160552c9ce25SScott Long /* Get transport information from the SIM */ 160683c5d981SAlexander Motin xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 160752c9ce25SScott Long cpi.ccb_h.func_code = XPT_PATH_INQ; 160852c9ce25SScott Long xpt_action((union ccb *)&cpi); 160952c9ce25SScott Long 161052c9ce25SScott Long path->device->transport = cpi.transport; 16114b997c49SAlexander Motin if ((path->device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0) 16124b997c49SAlexander Motin inq_buf = &path->device->inq_data; 16134b997c49SAlexander Motin if ((path->device->flags & CAM_DEV_IDENTIFY_DATA_VALID) != 0) 16144b997c49SAlexander Motin ident_buf = &path->device->ident_data; 16154b997c49SAlexander Motin if (path->device->protocol == PROTO_ATA) { 16164b997c49SAlexander Motin path->device->protocol_version = ident_buf ? 16174b997c49SAlexander Motin ata_version(ident_buf->version_major) : cpi.protocol_version; 16184b997c49SAlexander Motin } else if (path->device->protocol == PROTO_SCSI) { 16194b997c49SAlexander Motin path->device->protocol_version = inq_buf ? 16204b997c49SAlexander Motin SID_ANSI_REV(inq_buf) : cpi.protocol_version; 162152c9ce25SScott Long } 16224b997c49SAlexander Motin path->device->transport_version = ident_buf ? 16234b997c49SAlexander Motin ata_version(ident_buf->version_major) : cpi.transport_version; 162452c9ce25SScott Long 162552c9ce25SScott Long /* Tell the controller what we think */ 162683c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 162752c9ce25SScott Long cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 162852c9ce25SScott Long cts.type = CTS_TYPE_CURRENT_SETTINGS; 162952c9ce25SScott Long cts.transport = path->device->transport; 163052c9ce25SScott Long cts.transport_version = path->device->transport_version; 163152c9ce25SScott Long cts.protocol = path->device->protocol; 163252c9ce25SScott Long cts.protocol_version = path->device->protocol_version; 163352c9ce25SScott Long cts.proto_specific.valid = 0; 16344cca1530SAlexander Motin if (ident_buf) { 16354cca1530SAlexander Motin if (path->device->transport == XPORT_ATA) { 16364cca1530SAlexander Motin cts.xport_specific.ata.atapi = 16378e6cab54SAlexander Motin (ident_buf->config == ATA_PROTO_CFA) ? 0 : 16384cca1530SAlexander Motin ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_16) ? 16 : 16394cca1530SAlexander Motin ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) ? 12 : 0; 16404cca1530SAlexander Motin cts.xport_specific.ata.valid = CTS_ATA_VALID_ATAPI; 16414cca1530SAlexander Motin } else { 16424cca1530SAlexander Motin cts.xport_specific.sata.atapi = 16438e6cab54SAlexander Motin (ident_buf->config == ATA_PROTO_CFA) ? 0 : 16444cca1530SAlexander Motin ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_16) ? 16 : 16454cca1530SAlexander Motin ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) ? 12 : 0; 16464cca1530SAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_ATAPI; 16474cca1530SAlexander Motin } 16484cca1530SAlexander Motin } else 164952c9ce25SScott Long cts.xport_specific.valid = 0; 165052c9ce25SScott Long xpt_action((union ccb *)&cts); 165152c9ce25SScott Long } 165252c9ce25SScott Long 165352c9ce25SScott Long static void 165414f900e2SWill Andrews ata_dev_advinfo(union ccb *start_ccb) 165514f900e2SWill Andrews { 165614f900e2SWill Andrews struct cam_ed *device; 165714f900e2SWill Andrews struct ccb_dev_advinfo *cdai; 165814f900e2SWill Andrews off_t amt; 165914f900e2SWill Andrews 166014f900e2SWill Andrews start_ccb->ccb_h.status = CAM_REQ_INVALID; 166114f900e2SWill Andrews device = start_ccb->ccb_h.path->device; 166214f900e2SWill Andrews cdai = &start_ccb->cdai; 166314f900e2SWill Andrews switch(cdai->buftype) { 16643089bb2eSAlexander Motin case CDAI_TYPE_SCSI_DEVID: 16653089bb2eSAlexander Motin if (cdai->flags & CDAI_FLAG_STORE) 16663089bb2eSAlexander Motin return; 16673089bb2eSAlexander Motin cdai->provsiz = device->device_id_len; 16683089bb2eSAlexander Motin if (device->device_id_len == 0) 16693089bb2eSAlexander Motin break; 16703089bb2eSAlexander Motin amt = device->device_id_len; 16713089bb2eSAlexander Motin if (cdai->provsiz > cdai->bufsiz) 16723089bb2eSAlexander Motin amt = cdai->bufsiz; 16733089bb2eSAlexander Motin memcpy(cdai->buf, device->device_id, amt); 16743089bb2eSAlexander Motin break; 167514f900e2SWill Andrews case CDAI_TYPE_SERIAL_NUM: 167614f900e2SWill Andrews if (cdai->flags & CDAI_FLAG_STORE) 16773089bb2eSAlexander Motin return; 167814f900e2SWill Andrews cdai->provsiz = device->serial_num_len; 167914f900e2SWill Andrews if (device->serial_num_len == 0) 168014f900e2SWill Andrews break; 168114f900e2SWill Andrews amt = device->serial_num_len; 168214f900e2SWill Andrews if (cdai->provsiz > cdai->bufsiz) 168314f900e2SWill Andrews amt = cdai->bufsiz; 168414f900e2SWill Andrews memcpy(cdai->buf, device->serial_num, amt); 168514f900e2SWill Andrews break; 16863089bb2eSAlexander Motin case CDAI_TYPE_PHYS_PATH: 16873089bb2eSAlexander Motin if (cdai->flags & CDAI_FLAG_STORE) { 16883089bb2eSAlexander Motin if (device->physpath != NULL) 16893089bb2eSAlexander Motin free(device->physpath, M_CAMXPT); 16903089bb2eSAlexander Motin device->physpath_len = cdai->bufsiz; 16913089bb2eSAlexander Motin /* Clear existing buffer if zero length */ 16923089bb2eSAlexander Motin if (cdai->bufsiz == 0) 169314f900e2SWill Andrews break; 16943089bb2eSAlexander Motin device->physpath = malloc(cdai->bufsiz, M_CAMXPT, M_NOWAIT); 16953089bb2eSAlexander Motin if (device->physpath == NULL) { 16963089bb2eSAlexander Motin start_ccb->ccb_h.status = CAM_REQ_ABORTED; 16973089bb2eSAlexander Motin return; 16983089bb2eSAlexander Motin } 16993089bb2eSAlexander Motin memcpy(device->physpath, cdai->buf, cdai->bufsiz); 17003089bb2eSAlexander Motin } else { 17013089bb2eSAlexander Motin cdai->provsiz = device->physpath_len; 17023089bb2eSAlexander Motin if (device->physpath_len == 0) 17033089bb2eSAlexander Motin break; 17043089bb2eSAlexander Motin amt = device->physpath_len; 17053089bb2eSAlexander Motin if (cdai->provsiz > cdai->bufsiz) 17063089bb2eSAlexander Motin amt = cdai->bufsiz; 17073089bb2eSAlexander Motin memcpy(cdai->buf, device->physpath, amt); 17083089bb2eSAlexander Motin } 17093089bb2eSAlexander Motin break; 17103089bb2eSAlexander Motin default: 17113089bb2eSAlexander Motin return; 17123089bb2eSAlexander Motin } 17133089bb2eSAlexander Motin start_ccb->ccb_h.status = CAM_REQ_CMP; 17143089bb2eSAlexander Motin 17153089bb2eSAlexander Motin if (cdai->flags & CDAI_FLAG_STORE) { 17163089bb2eSAlexander Motin xpt_async(AC_ADVINFO_CHANGED, start_ccb->ccb_h.path, 17173089bb2eSAlexander Motin (void *)(uintptr_t)cdai->buftype); 171814f900e2SWill Andrews } 171914f900e2SWill Andrews } 172014f900e2SWill Andrews 172114f900e2SWill Andrews static void 172252c9ce25SScott Long ata_action(union ccb *start_ccb) 172352c9ce25SScott Long { 172452c9ce25SScott Long 172552c9ce25SScott Long switch (start_ccb->ccb_h.func_code) { 172652c9ce25SScott Long case XPT_SET_TRAN_SETTINGS: 172752c9ce25SScott Long { 172830a4094fSAlexander Motin ata_set_transfer_settings(&start_ccb->cts, 1729227d67aaSAlexander Motin start_ccb->ccb_h.path, 173052c9ce25SScott Long /*async_update*/FALSE); 173152c9ce25SScott Long break; 173252c9ce25SScott Long } 173352c9ce25SScott Long case XPT_SCAN_BUS: 17340e85f214SMatt Jacob case XPT_SCAN_TGT: 173552c9ce25SScott Long ata_scan_bus(start_ccb->ccb_h.path->periph, start_ccb); 173652c9ce25SScott Long break; 173752c9ce25SScott Long case XPT_SCAN_LUN: 173852c9ce25SScott Long ata_scan_lun(start_ccb->ccb_h.path->periph, 173952c9ce25SScott Long start_ccb->ccb_h.path, start_ccb->crcn.flags, 174052c9ce25SScott Long start_ccb); 174152c9ce25SScott Long break; 174252c9ce25SScott Long case XPT_GET_TRAN_SETTINGS: 174352c9ce25SScott Long { 1744b9c473b2SAlexander Motin ata_get_transfer_settings(&start_ccb->cts); 174552c9ce25SScott Long break; 174652c9ce25SScott Long } 17474cca1530SAlexander Motin case XPT_SCSI_IO: 17484cca1530SAlexander Motin { 17494cca1530SAlexander Motin struct cam_ed *device; 17504cca1530SAlexander Motin u_int maxlen = 0; 17514cca1530SAlexander Motin 17524cca1530SAlexander Motin device = start_ccb->ccb_h.path->device; 17534cca1530SAlexander Motin if (device->protocol == PROTO_SCSI && 17544cca1530SAlexander Motin (device->flags & CAM_DEV_IDENTIFY_DATA_VALID)) { 17554cca1530SAlexander Motin uint16_t p = 17564cca1530SAlexander Motin device->ident_data.config & ATA_PROTO_MASK; 17574cca1530SAlexander Motin 17588e6cab54SAlexander Motin maxlen = 17598e6cab54SAlexander Motin (device->ident_data.config == ATA_PROTO_CFA) ? 0 : 17608e6cab54SAlexander Motin (p == ATA_PROTO_ATAPI_16) ? 16 : 17614cca1530SAlexander Motin (p == ATA_PROTO_ATAPI_12) ? 12 : 0; 17624cca1530SAlexander Motin } 17634cca1530SAlexander Motin if (start_ccb->csio.cdb_len > maxlen) { 17644cca1530SAlexander Motin start_ccb->ccb_h.status = CAM_REQ_INVALID; 17654cca1530SAlexander Motin xpt_done(start_ccb); 17664cca1530SAlexander Motin break; 17674cca1530SAlexander Motin } 1768ee2b236bSAlexander Motin xpt_action_default(start_ccb); 1769ee2b236bSAlexander Motin break; 17704cca1530SAlexander Motin } 177114f900e2SWill Andrews case XPT_DEV_ADVINFO: 177214f900e2SWill Andrews { 177314f900e2SWill Andrews ata_dev_advinfo(start_ccb); 177414f900e2SWill Andrews break; 177514f900e2SWill Andrews } 177652c9ce25SScott Long default: 177752c9ce25SScott Long xpt_action_default(start_ccb); 177852c9ce25SScott Long break; 177952c9ce25SScott Long } 178052c9ce25SScott Long } 178152c9ce25SScott Long 178252c9ce25SScott Long static void 1783b9c473b2SAlexander Motin ata_get_transfer_settings(struct ccb_trans_settings *cts) 1784b9c473b2SAlexander Motin { 1785b9c473b2SAlexander Motin struct ccb_trans_settings_ata *ata; 1786b9c473b2SAlexander Motin struct ccb_trans_settings_scsi *scsi; 1787b9c473b2SAlexander Motin struct cam_ed *device; 1788b9c473b2SAlexander Motin 1789b9c473b2SAlexander Motin device = cts->ccb_h.path->device; 1790227d67aaSAlexander Motin xpt_action_default((union ccb *)cts); 1791b9c473b2SAlexander Motin 1792bc1bf6e8SAlexander Motin if (cts->protocol == PROTO_UNKNOWN || 1793bc1bf6e8SAlexander Motin cts->protocol == PROTO_UNSPECIFIED) { 1794bc1bf6e8SAlexander Motin cts->protocol = device->protocol; 1795bc1bf6e8SAlexander Motin cts->protocol_version = device->protocol_version; 1796bc1bf6e8SAlexander Motin } 1797bc1bf6e8SAlexander Motin 1798b9c473b2SAlexander Motin if (cts->protocol == PROTO_ATA) { 1799b9c473b2SAlexander Motin ata = &cts->proto_specific.ata; 1800b9c473b2SAlexander Motin if ((ata->valid & CTS_ATA_VALID_TQ) == 0) { 1801b9c473b2SAlexander Motin ata->valid |= CTS_ATA_VALID_TQ; 1802b9c473b2SAlexander Motin if (cts->type == CTS_TYPE_USER_SETTINGS || 1803b9c473b2SAlexander Motin (device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 || 1804b9c473b2SAlexander Motin (device->inq_flags & SID_CmdQue) != 0) 1805b9c473b2SAlexander Motin ata->flags |= CTS_ATA_FLAGS_TAG_ENB; 1806b9c473b2SAlexander Motin } 1807b9c473b2SAlexander Motin } 1808b9c473b2SAlexander Motin if (cts->protocol == PROTO_SCSI) { 1809b9c473b2SAlexander Motin scsi = &cts->proto_specific.scsi; 1810b9c473b2SAlexander Motin if ((scsi->valid & CTS_SCSI_VALID_TQ) == 0) { 1811b9c473b2SAlexander Motin scsi->valid |= CTS_SCSI_VALID_TQ; 1812b9c473b2SAlexander Motin if (cts->type == CTS_TYPE_USER_SETTINGS || 1813b9c473b2SAlexander Motin (device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 || 1814b9c473b2SAlexander Motin (device->inq_flags & SID_CmdQue) != 0) 1815b9c473b2SAlexander Motin scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 1816b9c473b2SAlexander Motin } 1817b9c473b2SAlexander Motin } 1818bc1bf6e8SAlexander Motin 1819bc1bf6e8SAlexander Motin if (cts->transport == XPORT_UNKNOWN || 1820bc1bf6e8SAlexander Motin cts->transport == XPORT_UNSPECIFIED) { 1821bc1bf6e8SAlexander Motin cts->transport = device->transport; 1822bc1bf6e8SAlexander Motin cts->transport_version = device->transport_version; 1823bc1bf6e8SAlexander Motin } 1824b9c473b2SAlexander Motin } 1825b9c473b2SAlexander Motin 1826b9c473b2SAlexander Motin static void 1827227d67aaSAlexander Motin ata_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_path *path, 182852c9ce25SScott Long int async_update) 182952c9ce25SScott Long { 183052c9ce25SScott Long struct ccb_pathinq cpi; 1831b9c473b2SAlexander Motin struct ccb_trans_settings_ata *ata; 183252c9ce25SScott Long struct ccb_trans_settings_scsi *scsi; 1833b9c473b2SAlexander Motin struct ata_params *ident_data; 183452c9ce25SScott Long struct scsi_inquiry_data *inq_data; 1835227d67aaSAlexander Motin struct cam_ed *device; 183652c9ce25SScott Long 1837227d67aaSAlexander Motin if (path == NULL || (device = path->device) == NULL) { 183852c9ce25SScott Long cts->ccb_h.status = CAM_PATH_INVALID; 183952c9ce25SScott Long xpt_done((union ccb *)cts); 184052c9ce25SScott Long return; 184152c9ce25SScott Long } 184252c9ce25SScott Long 184352c9ce25SScott Long if (cts->protocol == PROTO_UNKNOWN 184452c9ce25SScott Long || cts->protocol == PROTO_UNSPECIFIED) { 184552c9ce25SScott Long cts->protocol = device->protocol; 184652c9ce25SScott Long cts->protocol_version = device->protocol_version; 184752c9ce25SScott Long } 184852c9ce25SScott Long 184952c9ce25SScott Long if (cts->protocol_version == PROTO_VERSION_UNKNOWN 185052c9ce25SScott Long || cts->protocol_version == PROTO_VERSION_UNSPECIFIED) 185152c9ce25SScott Long cts->protocol_version = device->protocol_version; 185252c9ce25SScott Long 185352c9ce25SScott Long if (cts->protocol != device->protocol) { 1854227d67aaSAlexander Motin xpt_print(path, "Uninitialized Protocol %x:%x?\n", 185552c9ce25SScott Long cts->protocol, device->protocol); 185652c9ce25SScott Long cts->protocol = device->protocol; 185752c9ce25SScott Long } 185852c9ce25SScott Long 185952c9ce25SScott Long if (cts->protocol_version > device->protocol_version) { 186052c9ce25SScott Long if (bootverbose) { 1861227d67aaSAlexander Motin xpt_print(path, "Down reving Protocol " 186252c9ce25SScott Long "Version from %d to %d?\n", cts->protocol_version, 186352c9ce25SScott Long device->protocol_version); 186452c9ce25SScott Long } 186552c9ce25SScott Long cts->protocol_version = device->protocol_version; 186652c9ce25SScott Long } 186752c9ce25SScott Long 186852c9ce25SScott Long if (cts->transport == XPORT_UNKNOWN 186952c9ce25SScott Long || cts->transport == XPORT_UNSPECIFIED) { 187052c9ce25SScott Long cts->transport = device->transport; 187152c9ce25SScott Long cts->transport_version = device->transport_version; 187252c9ce25SScott Long } 187352c9ce25SScott Long 187452c9ce25SScott Long if (cts->transport_version == XPORT_VERSION_UNKNOWN 187552c9ce25SScott Long || cts->transport_version == XPORT_VERSION_UNSPECIFIED) 187652c9ce25SScott Long cts->transport_version = device->transport_version; 187752c9ce25SScott Long 187852c9ce25SScott Long if (cts->transport != device->transport) { 1879227d67aaSAlexander Motin xpt_print(path, "Uninitialized Transport %x:%x?\n", 188052c9ce25SScott Long cts->transport, device->transport); 188152c9ce25SScott Long cts->transport = device->transport; 188252c9ce25SScott Long } 188352c9ce25SScott Long 188452c9ce25SScott Long if (cts->transport_version > device->transport_version) { 188552c9ce25SScott Long if (bootverbose) { 1886227d67aaSAlexander Motin xpt_print(path, "Down reving Transport " 188752c9ce25SScott Long "Version from %d to %d?\n", cts->transport_version, 188852c9ce25SScott Long device->transport_version); 188952c9ce25SScott Long } 189052c9ce25SScott Long cts->transport_version = device->transport_version; 189152c9ce25SScott Long } 189252c9ce25SScott Long 1893b9c473b2SAlexander Motin ident_data = &device->ident_data; 189452c9ce25SScott Long inq_data = &device->inq_data; 1895b9c473b2SAlexander Motin if (cts->protocol == PROTO_ATA) 1896b9c473b2SAlexander Motin ata = &cts->proto_specific.ata; 1897b9c473b2SAlexander Motin else 1898b9c473b2SAlexander Motin ata = NULL; 1899b9c473b2SAlexander Motin if (cts->protocol == PROTO_SCSI) 190052c9ce25SScott Long scsi = &cts->proto_specific.scsi; 1901b9c473b2SAlexander Motin else 1902b9c473b2SAlexander Motin scsi = NULL; 1903227d67aaSAlexander Motin xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 190452c9ce25SScott Long cpi.ccb_h.func_code = XPT_PATH_INQ; 190552c9ce25SScott Long xpt_action((union ccb *)&cpi); 190652c9ce25SScott Long 1907b9c473b2SAlexander Motin /* Sanity checking */ 190852c9ce25SScott Long if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0 1909b9c473b2SAlexander Motin || (ata && (ident_data->satacapabilities & ATA_SUPPORT_NCQ) == 0) 1910b9c473b2SAlexander Motin || (scsi && (INQ_DATA_TQ_ENABLED(inq_data)) == 0) 191152c9ce25SScott Long || (device->queue_flags & SCP_QUEUE_DQUE) != 0 191252c9ce25SScott Long || (device->mintags == 0)) { 191352c9ce25SScott Long /* 191452c9ce25SScott Long * Can't tag on hardware that doesn't support tags, 191552c9ce25SScott Long * doesn't have it enabled, or has broken tag support. 191652c9ce25SScott Long */ 1917b9c473b2SAlexander Motin if (ata) 1918b9c473b2SAlexander Motin ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB; 1919b9c473b2SAlexander Motin if (scsi) 192052c9ce25SScott Long scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 192152c9ce25SScott Long } 192252c9ce25SScott Long 1923b9c473b2SAlexander Motin /* Start/stop tags use. */ 1924b9c473b2SAlexander Motin if (cts->type == CTS_TYPE_CURRENT_SETTINGS && 1925b9c473b2SAlexander Motin ((ata && (ata->valid & CTS_ATA_VALID_TQ) != 0) || 1926b9c473b2SAlexander Motin (scsi && (scsi->valid & CTS_SCSI_VALID_TQ) != 0))) { 1927b9c473b2SAlexander Motin int nowt, newt = 0; 192852c9ce25SScott Long 1929b9c473b2SAlexander Motin nowt = ((device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 || 1930b9c473b2SAlexander Motin (device->inq_flags & SID_CmdQue) != 0); 1931b9c473b2SAlexander Motin if (ata) 1932b9c473b2SAlexander Motin newt = (ata->flags & CTS_ATA_FLAGS_TAG_ENB) != 0; 1933b9c473b2SAlexander Motin if (scsi) 1934b9c473b2SAlexander Motin newt = (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0; 193552c9ce25SScott Long 1936b9c473b2SAlexander Motin if (newt && !nowt) { 193752c9ce25SScott Long /* 193852c9ce25SScott Long * Delay change to use tags until after a 193952c9ce25SScott Long * few commands have gone to this device so 194052c9ce25SScott Long * the controller has time to perform transfer 194152c9ce25SScott Long * negotiations without tagged messages getting 194252c9ce25SScott Long * in the way. 194352c9ce25SScott Long */ 194452c9ce25SScott Long device->tag_delay_count = CAM_TAG_DELAY_COUNT; 194552c9ce25SScott Long device->flags |= CAM_DEV_TAG_AFTER_COUNT; 1946b9c473b2SAlexander Motin } else if (nowt && !newt) 1947227d67aaSAlexander Motin xpt_stop_tags(path); 194852c9ce25SScott Long } 1949b9c473b2SAlexander Motin 195052c9ce25SScott Long if (async_update == FALSE) 1951227d67aaSAlexander Motin xpt_action_default((union ccb *)cts); 195252c9ce25SScott Long } 195352c9ce25SScott Long 195452c9ce25SScott Long /* 195552c9ce25SScott Long * Handle any per-device event notifications that require action by the XPT. 195652c9ce25SScott Long */ 195752c9ce25SScott Long static void 195852c9ce25SScott Long ata_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target, 195952c9ce25SScott Long struct cam_ed *device, void *async_arg) 196052c9ce25SScott Long { 196152c9ce25SScott Long cam_status status; 196252c9ce25SScott Long struct cam_path newpath; 196352c9ce25SScott Long 196452c9ce25SScott Long /* 196552c9ce25SScott Long * We only need to handle events for real devices. 196652c9ce25SScott Long */ 196752c9ce25SScott Long if (target->target_id == CAM_TARGET_WILDCARD 196852c9ce25SScott Long || device->lun_id == CAM_LUN_WILDCARD) 196952c9ce25SScott Long return; 197052c9ce25SScott Long 197152c9ce25SScott Long /* 197252c9ce25SScott Long * We need our own path with wildcards expanded to 197352c9ce25SScott Long * handle certain types of events. 197452c9ce25SScott Long */ 197552c9ce25SScott Long if ((async_code == AC_SENT_BDR) 197652c9ce25SScott Long || (async_code == AC_BUS_RESET) 197752c9ce25SScott Long || (async_code == AC_INQ_CHANGED)) 197852c9ce25SScott Long status = xpt_compile_path(&newpath, NULL, 197952c9ce25SScott Long bus->path_id, 198052c9ce25SScott Long target->target_id, 198152c9ce25SScott Long device->lun_id); 198252c9ce25SScott Long else 198352c9ce25SScott Long status = CAM_REQ_CMP_ERR; 198452c9ce25SScott Long 198552c9ce25SScott Long if (status == CAM_REQ_CMP) { 198652c9ce25SScott Long if (async_code == AC_INQ_CHANGED) { 198752c9ce25SScott Long /* 198852c9ce25SScott Long * We've sent a start unit command, or 198952c9ce25SScott Long * something similar to a device that 199052c9ce25SScott Long * may have caused its inquiry data to 199152c9ce25SScott Long * change. So we re-scan the device to 199252c9ce25SScott Long * refresh the inquiry data for it. 199352c9ce25SScott Long */ 199452c9ce25SScott Long ata_scan_lun(newpath.periph, &newpath, 199552c9ce25SScott Long CAM_EXPECT_INQ_CHANGE, NULL); 199683c5d981SAlexander Motin } else { 199783c5d981SAlexander Motin /* We need to reinitialize device after reset. */ 199883c5d981SAlexander Motin ata_scan_lun(newpath.periph, &newpath, 199983c5d981SAlexander Motin 0, NULL); 200052c9ce25SScott Long } 200152c9ce25SScott Long xpt_release_path(&newpath); 2002f98d7a47SAlexander Motin } else if (async_code == AC_LOST_DEVICE && 2003f98d7a47SAlexander Motin (device->flags & CAM_DEV_UNCONFIGURED) == 0) { 200452c9ce25SScott Long device->flags |= CAM_DEV_UNCONFIGURED; 2005f98d7a47SAlexander Motin xpt_release_device(device); 200652c9ce25SScott Long } else if (async_code == AC_TRANSFER_NEG) { 200752c9ce25SScott Long struct ccb_trans_settings *settings; 2008227d67aaSAlexander Motin struct cam_path path; 200952c9ce25SScott Long 201052c9ce25SScott Long settings = (struct ccb_trans_settings *)async_arg; 2011227d67aaSAlexander Motin xpt_compile_path(&path, NULL, bus->path_id, target->target_id, 2012227d67aaSAlexander Motin device->lun_id); 2013227d67aaSAlexander Motin ata_set_transfer_settings(settings, &path, 201452c9ce25SScott Long /*async_update*/TRUE); 2015227d67aaSAlexander Motin xpt_release_path(&path); 201652c9ce25SScott Long } 201752c9ce25SScott Long } 201852c9ce25SScott Long 201957079b17SAlexander Motin static void 202057079b17SAlexander Motin ata_announce_periph(struct cam_periph *periph) 202157079b17SAlexander Motin { 202257079b17SAlexander Motin struct ccb_pathinq cpi; 202357079b17SAlexander Motin struct ccb_trans_settings cts; 202457079b17SAlexander Motin struct cam_path *path = periph->path; 202557079b17SAlexander Motin u_int speed; 202657079b17SAlexander Motin u_int mb; 202757079b17SAlexander Motin 2028227d67aaSAlexander Motin cam_periph_assert(periph, MA_OWNED); 202957079b17SAlexander Motin 203057079b17SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); 203157079b17SAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 203257079b17SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 203357079b17SAlexander Motin xpt_action((union ccb*)&cts); 203457079b17SAlexander Motin if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 203557079b17SAlexander Motin return; 203657079b17SAlexander Motin /* Ask the SIM for its base transfer speed */ 203757079b17SAlexander Motin xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL); 203857079b17SAlexander Motin cpi.ccb_h.func_code = XPT_PATH_INQ; 203957079b17SAlexander Motin xpt_action((union ccb *)&cpi); 204057079b17SAlexander Motin /* Report connection speed */ 204157079b17SAlexander Motin speed = cpi.base_transfer_speed; 204257079b17SAlexander Motin if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_ATA) { 2043b9c473b2SAlexander Motin struct ccb_trans_settings_pata *pata = 204457079b17SAlexander Motin &cts.xport_specific.ata; 204557079b17SAlexander Motin 2046b9c473b2SAlexander Motin if (pata->valid & CTS_ATA_VALID_MODE) 2047b9c473b2SAlexander Motin speed = ata_mode2speed(pata->mode); 204857079b17SAlexander Motin } 204957079b17SAlexander Motin if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SATA) { 205057079b17SAlexander Motin struct ccb_trans_settings_sata *sata = 205157079b17SAlexander Motin &cts.xport_specific.sata; 205257079b17SAlexander Motin 205357079b17SAlexander Motin if (sata->valid & CTS_SATA_VALID_REVISION) 205457079b17SAlexander Motin speed = ata_revision2speed(sata->revision); 205557079b17SAlexander Motin } 205657079b17SAlexander Motin mb = speed / 1000; 205757079b17SAlexander Motin if (mb > 0) 205857079b17SAlexander Motin printf("%s%d: %d.%03dMB/s transfers", 205957079b17SAlexander Motin periph->periph_name, periph->unit_number, 206057079b17SAlexander Motin mb, speed % 1000); 206157079b17SAlexander Motin else 206257079b17SAlexander Motin printf("%s%d: %dKB/s transfers", periph->periph_name, 206357079b17SAlexander Motin periph->unit_number, speed); 206457079b17SAlexander Motin /* Report additional information about connection */ 206557079b17SAlexander Motin if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_ATA) { 2066b9c473b2SAlexander Motin struct ccb_trans_settings_pata *pata = 206757079b17SAlexander Motin &cts.xport_specific.ata; 206857079b17SAlexander Motin 206957079b17SAlexander Motin printf(" ("); 2070b9c473b2SAlexander Motin if (pata->valid & CTS_ATA_VALID_MODE) 2071b9c473b2SAlexander Motin printf("%s, ", ata_mode2string(pata->mode)); 2072b9c473b2SAlexander Motin if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0) 2073b9c473b2SAlexander Motin printf("ATAPI %dbytes, ", pata->atapi); 2074b9c473b2SAlexander Motin if (pata->valid & CTS_ATA_VALID_BYTECOUNT) 2075b9c473b2SAlexander Motin printf("PIO %dbytes", pata->bytecount); 207657079b17SAlexander Motin printf(")"); 207757079b17SAlexander Motin } 207857079b17SAlexander Motin if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SATA) { 207957079b17SAlexander Motin struct ccb_trans_settings_sata *sata = 208057079b17SAlexander Motin &cts.xport_specific.sata; 208157079b17SAlexander Motin 208257079b17SAlexander Motin printf(" ("); 208357079b17SAlexander Motin if (sata->valid & CTS_SATA_VALID_REVISION) 208457079b17SAlexander Motin printf("SATA %d.x, ", sata->revision); 208557079b17SAlexander Motin else 208657079b17SAlexander Motin printf("SATA, "); 208757079b17SAlexander Motin if (sata->valid & CTS_SATA_VALID_MODE) 208857079b17SAlexander Motin printf("%s, ", ata_mode2string(sata->mode)); 208957079b17SAlexander Motin if ((sata->valid & CTS_ATA_VALID_ATAPI) && sata->atapi != 0) 209057079b17SAlexander Motin printf("ATAPI %dbytes, ", sata->atapi); 209157079b17SAlexander Motin if (sata->valid & CTS_SATA_VALID_BYTECOUNT) 209257079b17SAlexander Motin printf("PIO %dbytes", sata->bytecount); 209357079b17SAlexander Motin printf(")"); 209457079b17SAlexander Motin } 209557079b17SAlexander Motin printf("\n"); 209657079b17SAlexander Motin } 2097