152c9ce25SScott Long /*- 2bec9534dSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3bec9534dSPedro F. Giffuni * 452c9ce25SScott Long * Copyright (c) 2009 Alexander Motin <mav@FreeBSD.org> 552c9ce25SScott Long * All rights reserved. 652c9ce25SScott Long * 752c9ce25SScott Long * Redistribution and use in source and binary forms, with or without 852c9ce25SScott Long * modification, are permitted provided that the following conditions 952c9ce25SScott Long * are met: 1052c9ce25SScott Long * 1. Redistributions of source code must retain the above copyright 1152c9ce25SScott Long * notice, this list of conditions and the following disclaimer, 1252c9ce25SScott Long * without modification, immediately at the beginning of the file. 1352c9ce25SScott Long * 2. Redistributions in binary form must reproduce the above copyright 1452c9ce25SScott Long * notice, this list of conditions and the following disclaimer in the 1552c9ce25SScott Long * documentation and/or other materials provided with the distribution. 1652c9ce25SScott Long * 1752c9ce25SScott Long * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1852c9ce25SScott Long * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1952c9ce25SScott Long * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2052c9ce25SScott Long * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2152c9ce25SScott Long * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2252c9ce25SScott Long * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2352c9ce25SScott Long * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2452c9ce25SScott Long * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2552c9ce25SScott Long * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2652c9ce25SScott Long * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2752c9ce25SScott Long */ 2852c9ce25SScott Long 2952c9ce25SScott Long #include <sys/cdefs.h> 3052c9ce25SScott Long __FBSDID("$FreeBSD$"); 3152c9ce25SScott Long 3252c9ce25SScott Long #include <sys/param.h> 3352c9ce25SScott Long #include <sys/bus.h> 3452c9ce25SScott Long #include <sys/endian.h> 3552c9ce25SScott Long #include <sys/systm.h> 3652c9ce25SScott Long #include <sys/types.h> 3752c9ce25SScott Long #include <sys/malloc.h> 3852c9ce25SScott Long #include <sys/kernel.h> 3952c9ce25SScott Long #include <sys/time.h> 4052c9ce25SScott Long #include <sys/conf.h> 4152c9ce25SScott Long #include <sys/fcntl.h> 4252c9ce25SScott Long #include <sys/interrupt.h> 4352c9ce25SScott Long #include <sys/sbuf.h> 4452c9ce25SScott Long 45a11463fdSSepherosa Ziehau #include <sys/eventhandler.h> 4652c9ce25SScott Long #include <sys/lock.h> 4752c9ce25SScott Long #include <sys/mutex.h> 4852c9ce25SScott Long #include <sys/sysctl.h> 4952c9ce25SScott Long 5052c9ce25SScott Long #include <cam/cam.h> 5152c9ce25SScott Long #include <cam/cam_ccb.h> 5252c9ce25SScott Long #include <cam/cam_queue.h> 5352c9ce25SScott Long #include <cam/cam_periph.h> 5452c9ce25SScott Long #include <cam/cam_sim.h> 5552c9ce25SScott Long #include <cam/cam_xpt.h> 5652c9ce25SScott Long #include <cam/cam_xpt_sim.h> 5752c9ce25SScott Long #include <cam/cam_xpt_periph.h> 5852c9ce25SScott Long #include <cam/cam_xpt_internal.h> 5952c9ce25SScott Long #include <cam/cam_debug.h> 6052c9ce25SScott Long 6152c9ce25SScott Long #include <cam/scsi/scsi_all.h> 6252c9ce25SScott Long #include <cam/scsi/scsi_message.h> 6352c9ce25SScott Long #include <cam/ata/ata_all.h> 6452c9ce25SScott Long #include <machine/stdarg.h> /* for xpt_print below */ 6552c9ce25SScott Long #include "opt_cam.h" 6652c9ce25SScott Long 6730a4094fSAlexander Motin struct ata_quirk_entry { 6852c9ce25SScott Long struct scsi_inquiry_pattern inq_pat; 6952c9ce25SScott Long u_int8_t quirks; 7030a4094fSAlexander Motin #define CAM_QUIRK_MAXTAGS 0x01 717dc3213dSAlexander Motin u_int mintags; 7252c9ce25SScott Long u_int maxtags; 7352c9ce25SScott Long }; 7452c9ce25SScott Long 7552c9ce25SScott Long static periph_init_t probe_periph_init; 7652c9ce25SScott Long 7752c9ce25SScott Long static struct periph_driver probe_driver = 7852c9ce25SScott Long { 79f09f8e3eSAlexander Motin probe_periph_init, "aprobe", 801e637ba6SAlexander Motin TAILQ_HEAD_INITIALIZER(probe_driver.units), /* generation */ 0, 811e637ba6SAlexander Motin CAM_PERIPH_DRV_EARLY 8252c9ce25SScott Long }; 8352c9ce25SScott Long 84f09f8e3eSAlexander Motin PERIPHDRIVER_DECLARE(aprobe, probe_driver); 8552c9ce25SScott Long 8652c9ce25SScott Long typedef enum { 8752c9ce25SScott Long PROBE_RESET, 8852c9ce25SScott Long PROBE_IDENTIFY, 894ef08dc5SAlexander Motin PROBE_SPINUP, 9052c9ce25SScott Long PROBE_SETMODE, 91da6808c1SAlexander Motin PROBE_SETPM, 92da6808c1SAlexander Motin PROBE_SETAPST, 93da6808c1SAlexander Motin PROBE_SETDMAAA, 948d169381SAlexander Motin PROBE_SETAN, 951e637ba6SAlexander Motin PROBE_SET_MULTI, 9652c9ce25SScott Long PROBE_INQUIRY, 9752c9ce25SScott Long PROBE_FULL_INQUIRY, 9852c9ce25SScott Long PROBE_PM_PID, 9952c9ce25SScott Long PROBE_PM_PRV, 1003089bb2eSAlexander Motin PROBE_IDENTIFY_SES, 1013089bb2eSAlexander Motin PROBE_IDENTIFY_SAFTE, 102a4d953c4SAlexander Motin PROBE_DONE, 10352c9ce25SScott Long PROBE_INVALID 10452c9ce25SScott Long } probe_action; 10552c9ce25SScott Long 10652c9ce25SScott Long static char *probe_action_text[] = { 10752c9ce25SScott Long "PROBE_RESET", 10852c9ce25SScott Long "PROBE_IDENTIFY", 1094ef08dc5SAlexander Motin "PROBE_SPINUP", 11052c9ce25SScott Long "PROBE_SETMODE", 111da6808c1SAlexander Motin "PROBE_SETPM", 112da6808c1SAlexander Motin "PROBE_SETAPST", 113da6808c1SAlexander Motin "PROBE_SETDMAAA", 1148d169381SAlexander Motin "PROBE_SETAN", 1151e637ba6SAlexander Motin "PROBE_SET_MULTI", 11652c9ce25SScott Long "PROBE_INQUIRY", 11752c9ce25SScott Long "PROBE_FULL_INQUIRY", 11852c9ce25SScott Long "PROBE_PM_PID", 11952c9ce25SScott Long "PROBE_PM_PRV", 1203089bb2eSAlexander Motin "PROBE_IDENTIFY_SES", 1213089bb2eSAlexander Motin "PROBE_IDENTIFY_SAFTE", 122a4d953c4SAlexander Motin "PROBE_DONE", 12352c9ce25SScott Long "PROBE_INVALID" 12452c9ce25SScott Long }; 12552c9ce25SScott Long 12652c9ce25SScott Long #define PROBE_SET_ACTION(softc, newaction) \ 12752c9ce25SScott Long do { \ 12852c9ce25SScott Long char **text; \ 12952c9ce25SScott Long text = probe_action_text; \ 130a4d953c4SAlexander Motin CAM_DEBUG((softc)->periph->path, CAM_DEBUG_PROBE, \ 13152c9ce25SScott Long ("Probe %s to %s\n", text[(softc)->action], \ 13252c9ce25SScott Long text[(newaction)])); \ 13352c9ce25SScott Long (softc)->action = (newaction); \ 13452c9ce25SScott Long } while(0) 13552c9ce25SScott Long 13652c9ce25SScott Long typedef enum { 13752c9ce25SScott Long PROBE_NO_ANNOUNCE = 0x04 13852c9ce25SScott Long } probe_flags; 13952c9ce25SScott Long 14052c9ce25SScott Long typedef struct { 14152c9ce25SScott Long TAILQ_HEAD(, ccb_hdr) request_ccbs; 142a9b8edb1SAlexander Motin struct ata_params ident_data; 14352c9ce25SScott Long probe_action action; 14452c9ce25SScott Long probe_flags flags; 14552c9ce25SScott Long uint32_t pm_pid; 14652c9ce25SScott Long uint32_t pm_prv; 14783c5d981SAlexander Motin int restart; 1484ef08dc5SAlexander Motin int spinup; 14925a519a9SAlexander Motin int faults; 150da6808c1SAlexander Motin u_int caps; 15152c9ce25SScott Long struct cam_periph *periph; 15252c9ce25SScott Long } probe_softc; 15352c9ce25SScott Long 15430a4094fSAlexander Motin static struct ata_quirk_entry ata_quirk_table[] = 15552c9ce25SScott Long { 15652c9ce25SScott Long { 15752c9ce25SScott Long /* Default tagged queuing parameters for all devices */ 15852c9ce25SScott Long { 15952c9ce25SScott Long T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED, 16052c9ce25SScott Long /*vendor*/"*", /*product*/"*", /*revision*/"*" 16152c9ce25SScott Long }, 1627dc3213dSAlexander Motin /*quirks*/0, /*mintags*/0, /*maxtags*/0 16352c9ce25SScott Long }, 16452c9ce25SScott Long }; 16552c9ce25SScott Long 16652c9ce25SScott Long static cam_status proberegister(struct cam_periph *periph, 16752c9ce25SScott Long void *arg); 16852c9ce25SScott Long static void probeschedule(struct cam_periph *probe_periph); 16952c9ce25SScott Long static void probestart(struct cam_periph *periph, union ccb *start_ccb); 170b9c473b2SAlexander Motin static void proberequestdefaultnegotiation(struct cam_periph *periph); 17152c9ce25SScott Long static void probedone(struct cam_periph *periph, union ccb *done_ccb); 17252c9ce25SScott Long static void probecleanup(struct cam_periph *periph); 17330a4094fSAlexander Motin static void ata_find_quirk(struct cam_ed *device); 17452c9ce25SScott Long static void ata_scan_bus(struct cam_periph *periph, union ccb *ccb); 17552c9ce25SScott Long static void ata_scan_lun(struct cam_periph *periph, 17652c9ce25SScott Long struct cam_path *path, cam_flags flags, 17752c9ce25SScott Long union ccb *ccb); 17852c9ce25SScott Long static void xptscandone(struct cam_periph *periph, union ccb *done_ccb); 17952c9ce25SScott Long static struct cam_ed * 18052c9ce25SScott Long ata_alloc_device(struct cam_eb *bus, struct cam_et *target, 18152c9ce25SScott Long lun_id_t lun_id); 18252c9ce25SScott Long static void ata_device_transport(struct cam_path *path); 183b9c473b2SAlexander Motin static void ata_get_transfer_settings(struct ccb_trans_settings *cts); 18430a4094fSAlexander Motin static void ata_set_transfer_settings(struct ccb_trans_settings *cts, 185227d67aaSAlexander Motin struct cam_path *path, 18652c9ce25SScott Long int async_update); 18752c9ce25SScott Long static void ata_dev_async(u_int32_t async_code, 18852c9ce25SScott Long struct cam_eb *bus, 18952c9ce25SScott Long struct cam_et *target, 19052c9ce25SScott Long struct cam_ed *device, 19152c9ce25SScott Long void *async_arg); 19252c9ce25SScott Long static void ata_action(union ccb *start_ccb); 19357079b17SAlexander Motin static void ata_announce_periph(struct cam_periph *periph); 1945d01277fSScott Long static void ata_announce_periph_sbuf(struct cam_periph *periph, struct sbuf *sb); 19508f13879SWarner Losh static void ata_proto_announce(struct cam_ed *device); 1965d01277fSScott Long static void ata_proto_announce_sbuf(struct cam_ed *device, struct sbuf *sb); 19708f13879SWarner Losh static void ata_proto_denounce(struct cam_ed *device); 1985d01277fSScott Long static void ata_proto_denounce_sbuf(struct cam_ed *device, struct sbuf *sb); 19908f13879SWarner Losh static void ata_proto_debug_out(union ccb *ccb); 20008f13879SWarner Losh static void semb_proto_announce(struct cam_ed *device); 2015d01277fSScott Long static void semb_proto_announce_sbuf(struct cam_ed *device, struct sbuf *sb); 20208f13879SWarner Losh static void semb_proto_denounce(struct cam_ed *device); 2035d01277fSScott Long static void semb_proto_denounce_sbuf(struct cam_ed *device, struct sbuf *sb); 20452c9ce25SScott Long 2052121d8a5SAlexander Motin static int ata_dma = 1; 2062121d8a5SAlexander Motin static int atapi_dma = 1; 2072121d8a5SAlexander Motin 2082121d8a5SAlexander Motin TUNABLE_INT("hw.ata.ata_dma", &ata_dma); 2092121d8a5SAlexander Motin TUNABLE_INT("hw.ata.atapi_dma", &atapi_dma); 2102121d8a5SAlexander Motin 211ded2b706SWarner Losh static struct xpt_xport_ops ata_xport_ops = { 21252c9ce25SScott Long .alloc_device = ata_alloc_device, 21352c9ce25SScott Long .action = ata_action, 21452c9ce25SScott Long .async = ata_dev_async, 21557079b17SAlexander Motin .announce = ata_announce_periph, 2165d01277fSScott Long .announce_sbuf = ata_announce_periph_sbuf, 21752c9ce25SScott Long }; 218ded2b706SWarner Losh #define ATA_XPT_XPORT(x, X) \ 219ded2b706SWarner Losh static struct xpt_xport ata_xport_ ## x = { \ 220ded2b706SWarner Losh .xport = XPORT_ ## X, \ 221ded2b706SWarner Losh .name = #x, \ 222ded2b706SWarner Losh .ops = &ata_xport_ops, \ 223ded2b706SWarner Losh }; \ 224ded2b706SWarner Losh CAM_XPT_XPORT(ata_xport_ ## x); 22552c9ce25SScott Long 226ded2b706SWarner Losh ATA_XPT_XPORT(ata, ATA); 227ded2b706SWarner Losh ATA_XPT_XPORT(sata, SATA); 228ded2b706SWarner Losh 229ded2b706SWarner Losh #undef ATA_XPORT_XPORT 23052c9ce25SScott Long 23108f13879SWarner Losh static struct xpt_proto_ops ata_proto_ops_ata = { 23208f13879SWarner Losh .announce = ata_proto_announce, 2335d01277fSScott Long .announce_sbuf = ata_proto_announce_sbuf, 23408f13879SWarner Losh .denounce = ata_proto_denounce, 2355d01277fSScott Long .denounce_sbuf = ata_proto_denounce_sbuf, 23608f13879SWarner Losh .debug_out = ata_proto_debug_out, 23708f13879SWarner Losh }; 23808f13879SWarner Losh static struct xpt_proto ata_proto_ata = { 23908f13879SWarner Losh .proto = PROTO_ATA, 24008f13879SWarner Losh .name = "ata", 24108f13879SWarner Losh .ops = &ata_proto_ops_ata, 24208f13879SWarner Losh }; 24308f13879SWarner Losh 24408f13879SWarner Losh static struct xpt_proto_ops ata_proto_ops_satapm = { 24508f13879SWarner Losh .announce = ata_proto_announce, 2465d01277fSScott Long .announce_sbuf = ata_proto_announce_sbuf, 24708f13879SWarner Losh .denounce = ata_proto_denounce, 2485d01277fSScott Long .denounce_sbuf = ata_proto_denounce_sbuf, 24908f13879SWarner Losh .debug_out = ata_proto_debug_out, 25008f13879SWarner Losh }; 25108f13879SWarner Losh static struct xpt_proto ata_proto_satapm = { 25208f13879SWarner Losh .proto = PROTO_SATAPM, 25308f13879SWarner Losh .name = "satapm", 25408f13879SWarner Losh .ops = &ata_proto_ops_satapm, 25508f13879SWarner Losh }; 25608f13879SWarner Losh 25708f13879SWarner Losh static struct xpt_proto_ops ata_proto_ops_semb = { 25808f13879SWarner Losh .announce = semb_proto_announce, 2595d01277fSScott Long .announce_sbuf = semb_proto_announce_sbuf, 26008f13879SWarner Losh .denounce = semb_proto_denounce, 2615d01277fSScott Long .denounce_sbuf = semb_proto_denounce_sbuf, 26208f13879SWarner Losh .debug_out = ata_proto_debug_out, 26308f13879SWarner Losh }; 26408f13879SWarner Losh static struct xpt_proto ata_proto_semb = { 26508f13879SWarner Losh .proto = PROTO_SEMB, 26608f13879SWarner Losh .name = "semb", 26708f13879SWarner Losh .ops = &ata_proto_ops_semb, 26808f13879SWarner Losh }; 26908f13879SWarner Losh 27008f13879SWarner Losh CAM_XPT_PROTO(ata_proto_ata); 27108f13879SWarner Losh CAM_XPT_PROTO(ata_proto_satapm); 27208f13879SWarner Losh CAM_XPT_PROTO(ata_proto_semb); 27308f13879SWarner Losh 27452c9ce25SScott Long static void 27552c9ce25SScott Long probe_periph_init() 27652c9ce25SScott Long { 27752c9ce25SScott Long } 27852c9ce25SScott Long 27952c9ce25SScott Long static cam_status 28052c9ce25SScott Long proberegister(struct cam_periph *periph, void *arg) 28152c9ce25SScott Long { 28252c9ce25SScott Long union ccb *request_ccb; /* CCB representing the probe request */ 28352c9ce25SScott Long probe_softc *softc; 28452c9ce25SScott Long 28552c9ce25SScott Long request_ccb = (union ccb *)arg; 28652c9ce25SScott Long if (request_ccb == NULL) { 28752c9ce25SScott Long printf("proberegister: no probe CCB, " 28852c9ce25SScott Long "can't register device\n"); 28952c9ce25SScott Long return(CAM_REQ_CMP_ERR); 29052c9ce25SScott Long } 29152c9ce25SScott Long 2924ef08dc5SAlexander Motin softc = (probe_softc *)malloc(sizeof(*softc), M_CAMXPT, M_ZERO | M_NOWAIT); 29352c9ce25SScott Long 29452c9ce25SScott Long if (softc == NULL) { 29552c9ce25SScott Long printf("proberegister: Unable to probe new device. " 29652c9ce25SScott Long "Unable to allocate softc\n"); 29752c9ce25SScott Long return(CAM_REQ_CMP_ERR); 29852c9ce25SScott Long } 29952c9ce25SScott Long TAILQ_INIT(&softc->request_ccbs); 30052c9ce25SScott Long TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h, 30152c9ce25SScott Long periph_links.tqe); 30252c9ce25SScott Long softc->flags = 0; 30352c9ce25SScott Long periph->softc = softc; 30452c9ce25SScott Long softc->periph = periph; 30552c9ce25SScott Long softc->action = PROBE_INVALID; 306*99e7a4adSScott Long if (cam_periph_acquire(periph) != 0) 307*99e7a4adSScott Long return (CAM_REQ_CMP_ERR); 308*99e7a4adSScott Long 309a4d953c4SAlexander Motin CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe started\n")); 310227d67aaSAlexander Motin ata_device_transport(periph->path); 31152c9ce25SScott Long probeschedule(periph); 31252c9ce25SScott Long return(CAM_REQ_CMP); 31352c9ce25SScott Long } 31452c9ce25SScott Long 31552c9ce25SScott Long static void 31652c9ce25SScott Long probeschedule(struct cam_periph *periph) 31752c9ce25SScott Long { 31852c9ce25SScott Long union ccb *ccb; 31952c9ce25SScott Long probe_softc *softc; 32052c9ce25SScott Long 32152c9ce25SScott Long softc = (probe_softc *)periph->softc; 32252c9ce25SScott Long ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs); 32352c9ce25SScott Long 32465d0fb03SAlexander Motin if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) || 3253089bb2eSAlexander Motin periph->path->device->protocol == PROTO_SATAPM || 3263089bb2eSAlexander Motin periph->path->device->protocol == PROTO_SEMB) 32752c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_RESET); 32852c9ce25SScott Long else 32952c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 33052c9ce25SScott Long 33152c9ce25SScott Long if (ccb->crcn.flags & CAM_EXPECT_INQ_CHANGE) 33252c9ce25SScott Long softc->flags |= PROBE_NO_ANNOUNCE; 33352c9ce25SScott Long else 33452c9ce25SScott Long softc->flags &= ~PROBE_NO_ANNOUNCE; 33552c9ce25SScott Long 33683c5d981SAlexander Motin xpt_schedule(periph, CAM_PRIORITY_XPT); 33752c9ce25SScott Long } 33852c9ce25SScott Long 33952c9ce25SScott Long static void 34052c9ce25SScott Long probestart(struct cam_periph *periph, union ccb *start_ccb) 34152c9ce25SScott Long { 342c8039fc6SAlexander Motin struct ccb_trans_settings cts; 34352c9ce25SScott Long struct ccb_ataio *ataio; 34452c9ce25SScott Long struct ccb_scsiio *csio; 34552c9ce25SScott Long probe_softc *softc; 3461e637ba6SAlexander Motin struct cam_path *path; 3471e637ba6SAlexander Motin struct ata_params *ident_buf; 34852c9ce25SScott Long 34952c9ce25SScott Long CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probestart\n")); 35052c9ce25SScott Long 35152c9ce25SScott Long softc = (probe_softc *)periph->softc; 3521e637ba6SAlexander Motin path = start_ccb->ccb_h.path; 35352c9ce25SScott Long ataio = &start_ccb->ataio; 35452c9ce25SScott Long csio = &start_ccb->csio; 3551e637ba6SAlexander Motin ident_buf = &periph->path->device->ident_data; 35652c9ce25SScott Long 35783c5d981SAlexander Motin if (softc->restart) { 35883c5d981SAlexander Motin softc->restart = 0; 35983c5d981SAlexander Motin if ((path->device->flags & CAM_DEV_UNCONFIGURED) || 3603089bb2eSAlexander Motin path->device->protocol == PROTO_SATAPM || 3613089bb2eSAlexander Motin path->device->protocol == PROTO_SEMB) 36283c5d981SAlexander Motin softc->action = PROBE_RESET; 36383c5d981SAlexander Motin else 36483c5d981SAlexander Motin softc->action = PROBE_IDENTIFY; 36583c5d981SAlexander Motin } 36652c9ce25SScott Long switch (softc->action) { 36752c9ce25SScott Long case PROBE_RESET: 36852c9ce25SScott Long cam_fill_ataio(ataio, 36952c9ce25SScott Long 0, 37052c9ce25SScott Long probedone, 37152c9ce25SScott Long /*flags*/CAM_DIR_NONE, 37265d0fb03SAlexander Motin 0, 37352c9ce25SScott Long /*data_ptr*/NULL, 37452c9ce25SScott Long /*dxfer_len*/0, 37583c5d981SAlexander Motin 15 * 1000); 37652c9ce25SScott Long ata_reset_cmd(ataio); 37752c9ce25SScott Long break; 37852c9ce25SScott Long case PROBE_IDENTIFY: 37952c9ce25SScott Long cam_fill_ataio(ataio, 38052c9ce25SScott Long 1, 38152c9ce25SScott Long probedone, 38252c9ce25SScott Long /*flags*/CAM_DIR_IN, 38365d0fb03SAlexander Motin 0, 384a9b8edb1SAlexander Motin /*data_ptr*/(u_int8_t *)&softc->ident_data, 385a9b8edb1SAlexander Motin /*dxfer_len*/sizeof(softc->ident_data), 38652c9ce25SScott Long 30 * 1000); 38752c9ce25SScott Long if (periph->path->device->protocol == PROTO_ATA) 3887606b445SAlexander Motin ata_28bit_cmd(ataio, ATA_ATA_IDENTIFY, 0, 0, 0); 38952c9ce25SScott Long else 3907606b445SAlexander Motin ata_28bit_cmd(ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0); 39152c9ce25SScott Long break; 3924ef08dc5SAlexander Motin case PROBE_SPINUP: 3934ef08dc5SAlexander Motin if (bootverbose) 3944ef08dc5SAlexander Motin xpt_print(path, "Spinning up device\n"); 3954ef08dc5SAlexander Motin cam_fill_ataio(ataio, 3964ef08dc5SAlexander Motin 1, 3974ef08dc5SAlexander Motin probedone, 3984ef08dc5SAlexander Motin /*flags*/CAM_DIR_NONE | CAM_HIGH_POWER, 3994ef08dc5SAlexander Motin 0, 4004ef08dc5SAlexander Motin /*data_ptr*/NULL, 4014ef08dc5SAlexander Motin /*dxfer_len*/0, 4024ef08dc5SAlexander Motin 30 * 1000); 4034ef08dc5SAlexander Motin ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_PUIS_SPINUP, 0, 0); 4044ef08dc5SAlexander Motin break; 40552c9ce25SScott Long case PROBE_SETMODE: 406c8039fc6SAlexander Motin { 407c8039fc6SAlexander Motin int mode, wantmode; 408c8039fc6SAlexander Motin 409c8039fc6SAlexander Motin mode = 0; 410c8039fc6SAlexander Motin /* Fetch user modes from SIM. */ 411c8039fc6SAlexander Motin bzero(&cts, sizeof(cts)); 41283c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 413c8039fc6SAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 414c8039fc6SAlexander Motin cts.type = CTS_TYPE_USER_SETTINGS; 415c8039fc6SAlexander Motin xpt_action((union ccb *)&cts); 416c8039fc6SAlexander Motin if (path->device->transport == XPORT_ATA) { 417c8039fc6SAlexander Motin if (cts.xport_specific.ata.valid & CTS_ATA_VALID_MODE) 418c8039fc6SAlexander Motin mode = cts.xport_specific.ata.mode; 419c8039fc6SAlexander Motin } else { 4201a6f09b8SAlexander Motin if (cts.xport_specific.sata.valid & CTS_SATA_VALID_MODE) 421c8039fc6SAlexander Motin mode = cts.xport_specific.sata.mode; 422c8039fc6SAlexander Motin } 4232121d8a5SAlexander Motin if (periph->path->device->protocol == PROTO_ATA) { 4242121d8a5SAlexander Motin if (ata_dma == 0 && (mode == 0 || mode > ATA_PIO_MAX)) 4252121d8a5SAlexander Motin mode = ATA_PIO_MAX; 4262121d8a5SAlexander Motin } else { 4272121d8a5SAlexander Motin if (atapi_dma == 0 && (mode == 0 || mode > ATA_PIO_MAX)) 4282121d8a5SAlexander Motin mode = ATA_PIO_MAX; 4292121d8a5SAlexander Motin } 430c8039fc6SAlexander Motin negotiate: 431c8039fc6SAlexander Motin /* Honor device capabilities. */ 432c8039fc6SAlexander Motin wantmode = mode = ata_max_mode(ident_buf, mode); 433c8039fc6SAlexander Motin /* Report modes to SIM. */ 434c8039fc6SAlexander Motin bzero(&cts, sizeof(cts)); 43583c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 436c8039fc6SAlexander Motin cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 437c8039fc6SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 438c8039fc6SAlexander Motin if (path->device->transport == XPORT_ATA) { 439c8039fc6SAlexander Motin cts.xport_specific.ata.mode = mode; 440c8039fc6SAlexander Motin cts.xport_specific.ata.valid = CTS_ATA_VALID_MODE; 441c8039fc6SAlexander Motin } else { 442c8039fc6SAlexander Motin cts.xport_specific.sata.mode = mode; 443c8039fc6SAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_MODE; 444c8039fc6SAlexander Motin } 445c8039fc6SAlexander Motin xpt_action((union ccb *)&cts); 446066f913aSAlexander Motin /* Fetch current modes from SIM. */ 447c8039fc6SAlexander Motin bzero(&cts, sizeof(cts)); 44883c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 449c8039fc6SAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 450c8039fc6SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 451c8039fc6SAlexander Motin xpt_action((union ccb *)&cts); 452c8039fc6SAlexander Motin if (path->device->transport == XPORT_ATA) { 453c8039fc6SAlexander Motin if (cts.xport_specific.ata.valid & CTS_ATA_VALID_MODE) 454c8039fc6SAlexander Motin mode = cts.xport_specific.ata.mode; 455c8039fc6SAlexander Motin } else { 456c8039fc6SAlexander Motin if (cts.xport_specific.ata.valid & CTS_SATA_VALID_MODE) 457c8039fc6SAlexander Motin mode = cts.xport_specific.sata.mode; 458c8039fc6SAlexander Motin } 459c8039fc6SAlexander Motin /* If SIM disagree - renegotiate. */ 460c8039fc6SAlexander Motin if (mode != wantmode) 461c8039fc6SAlexander Motin goto negotiate; 462cf2b9a5fSAlexander Motin /* Remember what transport thinks about DMA. */ 463cf2b9a5fSAlexander Motin if (mode < ATA_DMA) 464cf2b9a5fSAlexander Motin path->device->inq_flags &= ~SID_DMA; 465cf2b9a5fSAlexander Motin else 466cf2b9a5fSAlexander Motin path->device->inq_flags |= SID_DMA; 467581b2e78SAlexander Motin xpt_async(AC_GETDEV_CHANGED, path, NULL); 46852c9ce25SScott Long cam_fill_ataio(ataio, 46952c9ce25SScott Long 1, 47052c9ce25SScott Long probedone, 4715daa555dSAlexander Motin /*flags*/CAM_DIR_NONE, 4725daa555dSAlexander Motin 0, 4735daa555dSAlexander Motin /*data_ptr*/NULL, 4745daa555dSAlexander Motin /*dxfer_len*/0, 47552c9ce25SScott Long 30 * 1000); 476c8039fc6SAlexander Motin ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); 47752c9ce25SScott Long break; 478c8039fc6SAlexander Motin } 479da6808c1SAlexander Motin case PROBE_SETPM: 480da6808c1SAlexander Motin cam_fill_ataio(ataio, 481da6808c1SAlexander Motin 1, 482da6808c1SAlexander Motin probedone, 483da6808c1SAlexander Motin CAM_DIR_NONE, 484da6808c1SAlexander Motin 0, 485da6808c1SAlexander Motin NULL, 486da6808c1SAlexander Motin 0, 487da6808c1SAlexander Motin 30*1000); 488da6808c1SAlexander Motin ata_28bit_cmd(ataio, ATA_SETFEATURES, 489da6808c1SAlexander Motin (softc->caps & CTS_SATA_CAPS_H_PMREQ) ? 0x10 : 0x90, 490da6808c1SAlexander Motin 0, 0x03); 491da6808c1SAlexander Motin break; 492da6808c1SAlexander Motin case PROBE_SETAPST: 493da6808c1SAlexander Motin cam_fill_ataio(ataio, 494da6808c1SAlexander Motin 1, 495da6808c1SAlexander Motin probedone, 496da6808c1SAlexander Motin CAM_DIR_NONE, 497da6808c1SAlexander Motin 0, 498da6808c1SAlexander Motin NULL, 499da6808c1SAlexander Motin 0, 500da6808c1SAlexander Motin 30*1000); 501da6808c1SAlexander Motin ata_28bit_cmd(ataio, ATA_SETFEATURES, 502da6808c1SAlexander Motin (softc->caps & CTS_SATA_CAPS_H_APST) ? 0x10 : 0x90, 503da6808c1SAlexander Motin 0, 0x07); 504da6808c1SAlexander Motin break; 505da6808c1SAlexander Motin case PROBE_SETDMAAA: 506da6808c1SAlexander Motin cam_fill_ataio(ataio, 507da6808c1SAlexander Motin 1, 508da6808c1SAlexander Motin probedone, 509da6808c1SAlexander Motin CAM_DIR_NONE, 510da6808c1SAlexander Motin 0, 511da6808c1SAlexander Motin NULL, 512da6808c1SAlexander Motin 0, 513da6808c1SAlexander Motin 30*1000); 514da6808c1SAlexander Motin ata_28bit_cmd(ataio, ATA_SETFEATURES, 515da6808c1SAlexander Motin (softc->caps & CTS_SATA_CAPS_H_DMAAA) ? 0x10 : 0x90, 516da6808c1SAlexander Motin 0, 0x02); 517da6808c1SAlexander Motin break; 5188d169381SAlexander Motin case PROBE_SETAN: 519e4bed0b4SWarner Losh /* Remember what transport thinks about AEN. */ 520e4bed0b4SWarner Losh if (softc->caps & CTS_SATA_CAPS_H_AN) 5213631c638SAlexander Motin path->device->inq_flags |= SID_AEN; 5223631c638SAlexander Motin else 5233631c638SAlexander Motin path->device->inq_flags &= ~SID_AEN; 5243631c638SAlexander Motin xpt_async(AC_GETDEV_CHANGED, path, NULL); 5258d169381SAlexander Motin cam_fill_ataio(ataio, 5268d169381SAlexander Motin 1, 5278d169381SAlexander Motin probedone, 5288d169381SAlexander Motin CAM_DIR_NONE, 5298d169381SAlexander Motin 0, 5308d169381SAlexander Motin NULL, 5318d169381SAlexander Motin 0, 5328d169381SAlexander Motin 30*1000); 5338d169381SAlexander Motin ata_28bit_cmd(ataio, ATA_SETFEATURES, 5348d169381SAlexander Motin (softc->caps & CTS_SATA_CAPS_H_AN) ? 0x10 : 0x90, 5358d169381SAlexander Motin 0, 0x05); 5368d169381SAlexander Motin break; 5371e637ba6SAlexander Motin case PROBE_SET_MULTI: 5381e637ba6SAlexander Motin { 539066f913aSAlexander Motin u_int sectors, bytecount; 5401e637ba6SAlexander Motin 541066f913aSAlexander Motin bytecount = 8192; /* SATA maximum */ 542066f913aSAlexander Motin /* Fetch user bytecount from SIM. */ 543066f913aSAlexander Motin bzero(&cts, sizeof(cts)); 54483c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 545066f913aSAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 546066f913aSAlexander Motin cts.type = CTS_TYPE_USER_SETTINGS; 547066f913aSAlexander Motin xpt_action((union ccb *)&cts); 548066f913aSAlexander Motin if (path->device->transport == XPORT_ATA) { 549066f913aSAlexander Motin if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 550066f913aSAlexander Motin bytecount = cts.xport_specific.ata.bytecount; 551066f913aSAlexander Motin } else { 552066f913aSAlexander Motin if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 553066f913aSAlexander Motin bytecount = cts.xport_specific.sata.bytecount; 554066f913aSAlexander Motin } 555066f913aSAlexander Motin /* Honor device capabilities. */ 556066f913aSAlexander Motin sectors = max(1, min(ident_buf->sectors_intr & 0xff, 557066f913aSAlexander Motin bytecount / ata_logical_sector_size(ident_buf))); 5581e637ba6SAlexander Motin /* Report bytecount to SIM. */ 5591e637ba6SAlexander Motin bzero(&cts, sizeof(cts)); 56083c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 5611e637ba6SAlexander Motin cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 5621e637ba6SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 5631e637ba6SAlexander Motin if (path->device->transport == XPORT_ATA) { 564c1bd46c2SAlexander Motin cts.xport_specific.ata.bytecount = sectors * 565c1bd46c2SAlexander Motin ata_logical_sector_size(ident_buf); 5661e637ba6SAlexander Motin cts.xport_specific.ata.valid = CTS_ATA_VALID_BYTECOUNT; 5671e637ba6SAlexander Motin } else { 568c1bd46c2SAlexander Motin cts.xport_specific.sata.bytecount = sectors * 569c1bd46c2SAlexander Motin ata_logical_sector_size(ident_buf); 5701e637ba6SAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_BYTECOUNT; 5711e637ba6SAlexander Motin } 5721e637ba6SAlexander Motin xpt_action((union ccb *)&cts); 573066f913aSAlexander Motin /* Fetch current bytecount from SIM. */ 574066f913aSAlexander Motin bzero(&cts, sizeof(cts)); 57583c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 576066f913aSAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 577066f913aSAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 578066f913aSAlexander Motin xpt_action((union ccb *)&cts); 579066f913aSAlexander Motin if (path->device->transport == XPORT_ATA) { 580066f913aSAlexander Motin if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 581066f913aSAlexander Motin bytecount = cts.xport_specific.ata.bytecount; 582066f913aSAlexander Motin } else { 583066f913aSAlexander Motin if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 584066f913aSAlexander Motin bytecount = cts.xport_specific.sata.bytecount; 585066f913aSAlexander Motin } 586066f913aSAlexander Motin sectors = bytecount / ata_logical_sector_size(ident_buf); 5871e637ba6SAlexander Motin 5881e637ba6SAlexander Motin cam_fill_ataio(ataio, 5891e637ba6SAlexander Motin 1, 5901e637ba6SAlexander Motin probedone, 5911e637ba6SAlexander Motin CAM_DIR_NONE, 5921e637ba6SAlexander Motin 0, 5931e637ba6SAlexander Motin NULL, 5941e637ba6SAlexander Motin 0, 5951e637ba6SAlexander Motin 30*1000); 5961e637ba6SAlexander Motin ata_28bit_cmd(ataio, ATA_SET_MULTI, 0, 0, sectors); 5971e637ba6SAlexander Motin break; 59852c9ce25SScott Long } 59952c9ce25SScott Long case PROBE_INQUIRY: 600066f913aSAlexander Motin { 601066f913aSAlexander Motin u_int bytecount; 602066f913aSAlexander Motin 603066f913aSAlexander Motin bytecount = 8192; /* SATA maximum */ 604066f913aSAlexander Motin /* Fetch user bytecount from SIM. */ 605066f913aSAlexander Motin bzero(&cts, sizeof(cts)); 60683c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 607066f913aSAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 608066f913aSAlexander Motin cts.type = CTS_TYPE_USER_SETTINGS; 609066f913aSAlexander Motin xpt_action((union ccb *)&cts); 610066f913aSAlexander Motin if (path->device->transport == XPORT_ATA) { 611066f913aSAlexander Motin if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 612066f913aSAlexander Motin bytecount = cts.xport_specific.ata.bytecount; 613066f913aSAlexander Motin } else { 614066f913aSAlexander Motin if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 615066f913aSAlexander Motin bytecount = cts.xport_specific.sata.bytecount; 616066f913aSAlexander Motin } 617066f913aSAlexander Motin /* Honor device capabilities. */ 618066f913aSAlexander Motin bytecount &= ~1; 619066f913aSAlexander Motin bytecount = max(2, min(65534, bytecount)); 620066f913aSAlexander Motin if (ident_buf->satacapabilities != 0x0000 && 621066f913aSAlexander Motin ident_buf->satacapabilities != 0xffff) { 622066f913aSAlexander Motin bytecount = min(8192, bytecount); 623066f913aSAlexander Motin } 624066f913aSAlexander Motin /* Report bytecount to SIM. */ 625066f913aSAlexander Motin bzero(&cts, sizeof(cts)); 62683c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 627066f913aSAlexander Motin cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 628066f913aSAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 629066f913aSAlexander Motin if (path->device->transport == XPORT_ATA) { 630066f913aSAlexander Motin cts.xport_specific.ata.bytecount = bytecount; 631066f913aSAlexander Motin cts.xport_specific.ata.valid = CTS_ATA_VALID_BYTECOUNT; 632066f913aSAlexander Motin } else { 633066f913aSAlexander Motin cts.xport_specific.sata.bytecount = bytecount; 634066f913aSAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_BYTECOUNT; 635066f913aSAlexander Motin } 636066f913aSAlexander Motin xpt_action((union ccb *)&cts); 637066f913aSAlexander Motin /* FALLTHROUGH */ 638066f913aSAlexander Motin } 63952c9ce25SScott Long case PROBE_FULL_INQUIRY: 64052c9ce25SScott Long { 64152c9ce25SScott Long u_int inquiry_len; 64252c9ce25SScott Long struct scsi_inquiry_data *inq_buf = 64352c9ce25SScott Long &periph->path->device->inq_data; 64452c9ce25SScott Long 64552c9ce25SScott Long if (softc->action == PROBE_INQUIRY) 64652c9ce25SScott Long inquiry_len = SHORT_INQUIRY_LENGTH; 64752c9ce25SScott Long else 64852c9ce25SScott Long inquiry_len = SID_ADDITIONAL_LENGTH(inq_buf); 64952c9ce25SScott Long /* 65052c9ce25SScott Long * Some parallel SCSI devices fail to send an 65152c9ce25SScott Long * ignore wide residue message when dealing with 65252c9ce25SScott Long * odd length inquiry requests. Round up to be 65352c9ce25SScott Long * safe. 65452c9ce25SScott Long */ 65552c9ce25SScott Long inquiry_len = roundup2(inquiry_len, 2); 65652c9ce25SScott Long scsi_inquiry(csio, 65752c9ce25SScott Long /*retries*/1, 65852c9ce25SScott Long probedone, 65952c9ce25SScott Long MSG_SIMPLE_Q_TAG, 66052c9ce25SScott Long (u_int8_t *)inq_buf, 66152c9ce25SScott Long inquiry_len, 66252c9ce25SScott Long /*evpd*/FALSE, 66352c9ce25SScott Long /*page_code*/0, 66452c9ce25SScott Long SSD_MIN_SIZE, 66552c9ce25SScott Long /*timeout*/60 * 1000); 66652c9ce25SScott Long break; 66752c9ce25SScott Long } 66852c9ce25SScott Long case PROBE_PM_PID: 66952c9ce25SScott Long cam_fill_ataio(ataio, 67052c9ce25SScott Long 1, 67152c9ce25SScott Long probedone, 67252c9ce25SScott Long /*flags*/CAM_DIR_NONE, 67365d0fb03SAlexander Motin 0, 67452c9ce25SScott Long /*data_ptr*/NULL, 67552c9ce25SScott Long /*dxfer_len*/0, 67652c9ce25SScott Long 10 * 1000); 67752c9ce25SScott Long ata_pm_read_cmd(ataio, 0, 15); 67852c9ce25SScott Long break; 67952c9ce25SScott Long case PROBE_PM_PRV: 68052c9ce25SScott Long cam_fill_ataio(ataio, 68152c9ce25SScott Long 1, 68252c9ce25SScott Long probedone, 68352c9ce25SScott Long /*flags*/CAM_DIR_NONE, 68465d0fb03SAlexander Motin 0, 68552c9ce25SScott Long /*data_ptr*/NULL, 68652c9ce25SScott Long /*dxfer_len*/0, 68752c9ce25SScott Long 10 * 1000); 68852c9ce25SScott Long ata_pm_read_cmd(ataio, 1, 15); 68952c9ce25SScott Long break; 6903089bb2eSAlexander Motin case PROBE_IDENTIFY_SES: 6913089bb2eSAlexander Motin cam_fill_ataio(ataio, 6923089bb2eSAlexander Motin 1, 6933089bb2eSAlexander Motin probedone, 6943089bb2eSAlexander Motin /*flags*/CAM_DIR_IN, 6953089bb2eSAlexander Motin 0, 6963089bb2eSAlexander Motin /*data_ptr*/(u_int8_t *)&softc->ident_data, 6973089bb2eSAlexander Motin /*dxfer_len*/sizeof(softc->ident_data), 6983089bb2eSAlexander Motin 30 * 1000); 6993089bb2eSAlexander Motin ata_28bit_cmd(ataio, ATA_SEP_ATTN, 0xEC, 0x02, 7003089bb2eSAlexander Motin sizeof(softc->ident_data) / 4); 7013089bb2eSAlexander Motin break; 7023089bb2eSAlexander Motin case PROBE_IDENTIFY_SAFTE: 7033089bb2eSAlexander Motin cam_fill_ataio(ataio, 7043089bb2eSAlexander Motin 1, 7053089bb2eSAlexander Motin probedone, 7063089bb2eSAlexander Motin /*flags*/CAM_DIR_IN, 7073089bb2eSAlexander Motin 0, 7083089bb2eSAlexander Motin /*data_ptr*/(u_int8_t *)&softc->ident_data, 7093089bb2eSAlexander Motin /*dxfer_len*/sizeof(softc->ident_data), 7103089bb2eSAlexander Motin 30 * 1000); 7113089bb2eSAlexander Motin ata_28bit_cmd(ataio, ATA_SEP_ATTN, 0xEC, 0x00, 7123089bb2eSAlexander Motin sizeof(softc->ident_data) / 4); 7133089bb2eSAlexander Motin break; 71452c9ce25SScott Long default: 715a4d953c4SAlexander Motin panic("probestart: invalid action state 0x%x\n", softc->action); 71652c9ce25SScott Long } 717cccf4220SAlexander Motin start_ccb->ccb_h.flags |= CAM_DEV_QFREEZE; 71852c9ce25SScott Long xpt_action(start_ccb); 71952c9ce25SScott Long } 720b9c473b2SAlexander Motin 72152c9ce25SScott Long static void 72252c9ce25SScott Long proberequestdefaultnegotiation(struct cam_periph *periph) 72352c9ce25SScott Long { 72452c9ce25SScott Long struct ccb_trans_settings cts; 72552c9ce25SScott Long 72683c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE); 72752c9ce25SScott Long cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 72852c9ce25SScott Long cts.type = CTS_TYPE_USER_SETTINGS; 72952c9ce25SScott Long xpt_action((union ccb *)&cts); 730b9c473b2SAlexander Motin if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 73152c9ce25SScott Long return; 732b9c473b2SAlexander Motin cts.xport_specific.valid = 0; 73352c9ce25SScott Long cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 73452c9ce25SScott Long cts.type = CTS_TYPE_CURRENT_SETTINGS; 73552c9ce25SScott Long xpt_action((union ccb *)&cts); 73652c9ce25SScott Long } 73752c9ce25SScott Long 73852c9ce25SScott Long static void 73952c9ce25SScott Long probedone(struct cam_periph *periph, union ccb *done_ccb) 74052c9ce25SScott Long { 741c8039fc6SAlexander Motin struct ccb_trans_settings cts; 74252c9ce25SScott Long struct ata_params *ident_buf; 7433089bb2eSAlexander Motin struct scsi_inquiry_data *inq_buf; 74452c9ce25SScott Long probe_softc *softc; 74552c9ce25SScott Long struct cam_path *path; 74626bdaeddSAlexander Motin cam_status status; 74752c9ce25SScott Long u_int32_t priority; 748da6808c1SAlexander Motin u_int caps; 7493089bb2eSAlexander Motin int changed = 1, found = 1; 7503089bb2eSAlexander Motin static const uint8_t fake_device_id_hdr[8] = 7513089bb2eSAlexander Motin {0, SVPD_DEVICE_ID, 0, 12, 7523089bb2eSAlexander Motin SVPD_ID_CODESET_BINARY, SVPD_ID_TYPE_NAA, 0, 8}; 75352c9ce25SScott Long 75452c9ce25SScott Long CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probedone\n")); 75552c9ce25SScott Long 75652c9ce25SScott Long softc = (probe_softc *)periph->softc; 75752c9ce25SScott Long path = done_ccb->ccb_h.path; 75852c9ce25SScott Long priority = done_ccb->ccb_h.pinfo.priority; 75952c9ce25SScott Long ident_buf = &path->device->ident_data; 7603089bb2eSAlexander Motin inq_buf = &path->device->inq_data; 76152c9ce25SScott Long 7621e637ba6SAlexander Motin if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 7630191d9b3SAlexander Motin if (cam_periph_error(done_ccb, 764553484aeSWarner Losh 0, softc->restart ? (SF_NO_RECOVERY | SF_NO_RETRY) : 0 765553484aeSWarner Losh ) == ERESTART) { 766cccf4220SAlexander Motin out: 767cccf4220SAlexander Motin /* Drop freeze taken due to CAM_DEV_QFREEZE flag set. */ 768cccf4220SAlexander Motin cam_release_devq(path, 0, 0, 0, FALSE); 7691e637ba6SAlexander Motin return; 770cccf4220SAlexander Motin } 77125a519a9SAlexander Motin if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 7721e637ba6SAlexander Motin /* Don't wedge the queue */ 773cccf4220SAlexander Motin xpt_release_devq(path, /*count*/1, /*run_queue*/TRUE); 7741e637ba6SAlexander Motin } 77526bdaeddSAlexander Motin status = done_ccb->ccb_h.status & CAM_STATUS_MASK; 77625a519a9SAlexander Motin if (softc->restart) { 77725a519a9SAlexander Motin softc->faults++; 77825a519a9SAlexander Motin if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == 77925a519a9SAlexander Motin CAM_CMD_TIMEOUT) 78025a519a9SAlexander Motin softc->faults += 4; 78125a519a9SAlexander Motin if (softc->faults < 10) 78225a519a9SAlexander Motin goto done; 78325a519a9SAlexander Motin else 78425a519a9SAlexander Motin softc->restart = 0; 78526bdaeddSAlexander Motin 7861e637ba6SAlexander Motin /* Old PIO2 devices may not support mode setting. */ 78726bdaeddSAlexander Motin } else if (softc->action == PROBE_SETMODE && 78826bdaeddSAlexander Motin status == CAM_ATA_STATUS_ERROR && 7891e637ba6SAlexander Motin ata_max_pmode(ident_buf) <= ATA_PIO2 && 79026bdaeddSAlexander Motin (ident_buf->capabilities1 & ATA_SUPPORT_IORDY) == 0) { 7911e637ba6SAlexander Motin goto noerror; 79226bdaeddSAlexander Motin 79326bdaeddSAlexander Motin /* 79426bdaeddSAlexander Motin * Some old WD SATA disks report supported and enabled 79526bdaeddSAlexander Motin * device-initiated interface power management, but return 79626bdaeddSAlexander Motin * ABORT on attempt to disable it. 79726bdaeddSAlexander Motin */ 79826bdaeddSAlexander Motin } else if (softc->action == PROBE_SETPM && 79926bdaeddSAlexander Motin status == CAM_ATA_STATUS_ERROR) { 80026bdaeddSAlexander Motin goto noerror; 801025e2c12SAlexander Motin 802025e2c12SAlexander Motin /* 803b5617df5SAndriy Gapon * Some old WD SATA disks have broken SPINUP handling. 804b5617df5SAndriy Gapon * If we really fail to spin up the disk, then there will be 805b5617df5SAndriy Gapon * some media access errors later on, but at least we will 806b5617df5SAndriy Gapon * have a device to interact with for recovery attempts. 807b5617df5SAndriy Gapon */ 808b5617df5SAndriy Gapon } else if (softc->action == PROBE_SPINUP && 809b5617df5SAndriy Gapon status == CAM_ATA_STATUS_ERROR) { 810b5617df5SAndriy Gapon goto noerror; 811b5617df5SAndriy Gapon 812b5617df5SAndriy Gapon /* 813025e2c12SAlexander Motin * Some HP SATA disks report supported DMA Auto-Activation, 814025e2c12SAlexander Motin * but return ABORT on attempt to enable it. 815025e2c12SAlexander Motin */ 816025e2c12SAlexander Motin } else if (softc->action == PROBE_SETDMAAA && 817025e2c12SAlexander Motin status == CAM_ATA_STATUS_ERROR) { 818025e2c12SAlexander Motin goto noerror; 8193089bb2eSAlexander Motin 8203089bb2eSAlexander Motin /* 8213089bb2eSAlexander Motin * SES and SAF-TE SEPs have different IDENTIFY commands, 8223089bb2eSAlexander Motin * but SATA specification doesn't tell how to identify them. 8233089bb2eSAlexander Motin * Until better way found, just try another if first fail. 8243089bb2eSAlexander Motin */ 8253089bb2eSAlexander Motin } else if (softc->action == PROBE_IDENTIFY_SES && 8263089bb2eSAlexander Motin status == CAM_ATA_STATUS_ERROR) { 8273089bb2eSAlexander Motin PROBE_SET_ACTION(softc, PROBE_IDENTIFY_SAFTE); 8283089bb2eSAlexander Motin xpt_release_ccb(done_ccb); 8293089bb2eSAlexander Motin xpt_schedule(periph, priority); 830cccf4220SAlexander Motin goto out; 83126bdaeddSAlexander Motin } 83226bdaeddSAlexander Motin 8331e637ba6SAlexander Motin /* 8341e637ba6SAlexander Motin * If we get to this point, we got an error status back 8351e637ba6SAlexander Motin * from the inquiry and the error status doesn't require 8361e637ba6SAlexander Motin * automatically retrying the command. Therefore, the 8371e637ba6SAlexander Motin * inquiry failed. If we had inquiry information before 8381e637ba6SAlexander Motin * for this device, but this latest inquiry command failed, 8391e637ba6SAlexander Motin * the device has probably gone away. If this device isn't 8401e637ba6SAlexander Motin * already marked unconfigured, notify the peripheral 8411e637ba6SAlexander Motin * drivers that this device is no more. 8421e637ba6SAlexander Motin */ 84325a519a9SAlexander Motin device_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0) 8441e637ba6SAlexander Motin xpt_async(AC_LOST_DEVICE, path, NULL); 845a4d953c4SAlexander Motin PROBE_SET_ACTION(softc, PROBE_INVALID); 8461e637ba6SAlexander Motin found = 0; 8471e637ba6SAlexander Motin goto done; 8481e637ba6SAlexander Motin } 8491e637ba6SAlexander Motin noerror: 850a9b8edb1SAlexander Motin if (softc->restart) 851a9b8edb1SAlexander Motin goto done; 85252c9ce25SScott Long switch (softc->action) { 85352c9ce25SScott Long case PROBE_RESET: 8541e637ba6SAlexander Motin { 85552c9ce25SScott Long int sign = (done_ccb->ataio.res.lba_high << 8) + 85652c9ce25SScott Long done_ccb->ataio.res.lba_mid; 857a4d953c4SAlexander Motin CAM_DEBUG(path, CAM_DEBUG_PROBE, 858a4d953c4SAlexander Motin ("SIGNATURE: %04x\n", sign)); 85952c9ce25SScott Long if (sign == 0x0000 && 86052c9ce25SScott Long done_ccb->ccb_h.target_id != 15) { 86152c9ce25SScott Long path->device->protocol = PROTO_ATA; 86252c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 86352c9ce25SScott Long } else if (sign == 0x9669 && 86452c9ce25SScott Long done_ccb->ccb_h.target_id == 15) { 86552c9ce25SScott Long /* Report SIM that PM is present. */ 86652c9ce25SScott Long bzero(&cts, sizeof(cts)); 86783c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 86852c9ce25SScott Long cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 86952c9ce25SScott Long cts.type = CTS_TYPE_CURRENT_SETTINGS; 87052c9ce25SScott Long cts.xport_specific.sata.pm_present = 1; 87152c9ce25SScott Long cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; 87252c9ce25SScott Long xpt_action((union ccb *)&cts); 87352c9ce25SScott Long path->device->protocol = PROTO_SATAPM; 87452c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_PM_PID); 8753089bb2eSAlexander Motin } else if (sign == 0xc33c && 8763089bb2eSAlexander Motin done_ccb->ccb_h.target_id != 15) { 8773089bb2eSAlexander Motin path->device->protocol = PROTO_SEMB; 8783089bb2eSAlexander Motin PROBE_SET_ACTION(softc, PROBE_IDENTIFY_SES); 87952c9ce25SScott Long } else if (sign == 0xeb14 && 88052c9ce25SScott Long done_ccb->ccb_h.target_id != 15) { 88152c9ce25SScott Long path->device->protocol = PROTO_SCSI; 88252c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 88352c9ce25SScott Long } else { 88452c9ce25SScott Long if (done_ccb->ccb_h.target_id != 15) { 88552c9ce25SScott Long xpt_print(path, 88652c9ce25SScott Long "Unexpected signature 0x%04x\n", sign); 88752c9ce25SScott Long } 88865d0fb03SAlexander Motin goto device_fail; 88952c9ce25SScott Long } 89052c9ce25SScott Long xpt_release_ccb(done_ccb); 89152c9ce25SScott Long xpt_schedule(periph, priority); 892cccf4220SAlexander Motin goto out; 89352c9ce25SScott Long } 89452c9ce25SScott Long case PROBE_IDENTIFY: 89552c9ce25SScott Long { 896699f853bSAlexander Motin struct ccb_pathinq cpi; 89752c9ce25SScott Long int16_t *ptr; 898a11463fdSSepherosa Ziehau int veto = 0; 89952c9ce25SScott Long 900a9b8edb1SAlexander Motin ident_buf = &softc->ident_data; 90152c9ce25SScott Long for (ptr = (int16_t *)ident_buf; 90252c9ce25SScott Long ptr < (int16_t *)ident_buf + sizeof(struct ata_params)/2; ptr++) { 90352c9ce25SScott Long *ptr = le16toh(*ptr); 90452c9ce25SScott Long } 905a11463fdSSepherosa Ziehau 906a11463fdSSepherosa Ziehau /* 907a11463fdSSepherosa Ziehau * Allow others to veto this ATA disk attachment. This 908a11463fdSSepherosa Ziehau * is mainly used by VMs, whose disk controllers may 909a11463fdSSepherosa Ziehau * share the disks with the simulated ATA controllers. 910a11463fdSSepherosa Ziehau */ 911a11463fdSSepherosa Ziehau EVENTHANDLER_INVOKE(ada_probe_veto, path, ident_buf, &veto); 912a11463fdSSepherosa Ziehau if (veto) { 913a11463fdSSepherosa Ziehau goto device_fail; 914a11463fdSSepherosa Ziehau } 915a11463fdSSepherosa Ziehau 91652c9ce25SScott Long if (strncmp(ident_buf->model, "FX", 2) && 91752c9ce25SScott Long strncmp(ident_buf->model, "NEC", 3) && 91852c9ce25SScott Long strncmp(ident_buf->model, "Pioneer", 7) && 91952c9ce25SScott Long strncmp(ident_buf->model, "SHARP", 5)) { 92052c9ce25SScott Long ata_bswap(ident_buf->model, sizeof(ident_buf->model)); 92152c9ce25SScott Long ata_bswap(ident_buf->revision, sizeof(ident_buf->revision)); 92252c9ce25SScott Long ata_bswap(ident_buf->serial, sizeof(ident_buf->serial)); 92352c9ce25SScott Long } 92452c9ce25SScott Long ata_btrim(ident_buf->model, sizeof(ident_buf->model)); 92552c9ce25SScott Long ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model)); 92652c9ce25SScott Long ata_btrim(ident_buf->revision, sizeof(ident_buf->revision)); 92752c9ce25SScott Long ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision)); 92852c9ce25SScott Long ata_btrim(ident_buf->serial, sizeof(ident_buf->serial)); 92952c9ce25SScott Long ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial)); 9304ef08dc5SAlexander Motin /* Device may need spin-up before IDENTIFY become valid. */ 9311254b680SAlexander Motin if ((ident_buf->specconf == 0x37c8 || 9321254b680SAlexander Motin ident_buf->specconf == 0x738c) && 9331254b680SAlexander Motin ((ident_buf->config & ATA_RESP_INCOMPLETE) || 9344ef08dc5SAlexander Motin softc->spinup == 0)) { 9354ef08dc5SAlexander Motin PROBE_SET_ACTION(softc, PROBE_SPINUP); 9364ef08dc5SAlexander Motin xpt_release_ccb(done_ccb); 9374ef08dc5SAlexander Motin xpt_schedule(periph, priority); 938cccf4220SAlexander Motin goto out; 9394ef08dc5SAlexander Motin } 940a9b8edb1SAlexander Motin ident_buf = &path->device->ident_data; 94152c9ce25SScott Long if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) { 94252c9ce25SScott Long /* Check that it is the same device. */ 943a9b8edb1SAlexander Motin if (bcmp(softc->ident_data.model, ident_buf->model, 944a9b8edb1SAlexander Motin sizeof(ident_buf->model)) || 945a9b8edb1SAlexander Motin bcmp(softc->ident_data.revision, ident_buf->revision, 946a9b8edb1SAlexander Motin sizeof(ident_buf->revision)) || 947a9b8edb1SAlexander Motin bcmp(softc->ident_data.serial, ident_buf->serial, 948a9b8edb1SAlexander Motin sizeof(ident_buf->serial))) { 94952c9ce25SScott Long /* Device changed. */ 95052c9ce25SScott Long xpt_async(AC_LOST_DEVICE, path, NULL); 9511e637ba6SAlexander Motin } else { 952a9b8edb1SAlexander Motin bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 9532eb4a8dcSAlexander Motin changed = 0; 9542eb4a8dcSAlexander Motin } 9552eb4a8dcSAlexander Motin } 9562eb4a8dcSAlexander Motin if (changed) { 9572eb4a8dcSAlexander Motin bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 95852c9ce25SScott Long /* Clean up from previous instance of this device */ 95952c9ce25SScott Long if (path->device->serial_num != NULL) { 96052c9ce25SScott Long free(path->device->serial_num, M_CAMXPT); 96152c9ce25SScott Long path->device->serial_num = NULL; 96252c9ce25SScott Long path->device->serial_num_len = 0; 96352c9ce25SScott Long } 9643089bb2eSAlexander Motin if (path->device->device_id != NULL) { 9653089bb2eSAlexander Motin free(path->device->device_id, M_CAMXPT); 9663089bb2eSAlexander Motin path->device->device_id = NULL; 9673089bb2eSAlexander Motin path->device->device_id_len = 0; 9683089bb2eSAlexander Motin } 96952c9ce25SScott Long path->device->serial_num = 97052c9ce25SScott Long (u_int8_t *)malloc((sizeof(ident_buf->serial) + 1), 97152c9ce25SScott Long M_CAMXPT, M_NOWAIT); 97252c9ce25SScott Long if (path->device->serial_num != NULL) { 97352c9ce25SScott Long bcopy(ident_buf->serial, 97452c9ce25SScott Long path->device->serial_num, 97552c9ce25SScott Long sizeof(ident_buf->serial)); 97652c9ce25SScott Long path->device->serial_num[sizeof(ident_buf->serial)] 97752c9ce25SScott Long = '\0'; 97852c9ce25SScott Long path->device->serial_num_len = 97952c9ce25SScott Long strlen(path->device->serial_num); 98052c9ce25SScott Long } 9813089bb2eSAlexander Motin if (ident_buf->enabled.extension & 9823089bb2eSAlexander Motin ATA_SUPPORT_64BITWWN) { 9833089bb2eSAlexander Motin path->device->device_id = 9843089bb2eSAlexander Motin malloc(16, M_CAMXPT, M_NOWAIT); 9853089bb2eSAlexander Motin if (path->device->device_id != NULL) { 9863089bb2eSAlexander Motin path->device->device_id_len = 16; 9873089bb2eSAlexander Motin bcopy(&fake_device_id_hdr, 9883089bb2eSAlexander Motin path->device->device_id, 8); 9893d6dd54eSAlexander Motin bcopy(ident_buf->wwn, 9903d6dd54eSAlexander Motin path->device->device_id + 8, 8); 9913d6dd54eSAlexander Motin ata_bswap(path->device->device_id + 8, 8); 9923089bb2eSAlexander Motin } 9933089bb2eSAlexander Motin } 99452c9ce25SScott Long 9954b997c49SAlexander Motin path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 996581b2e78SAlexander Motin xpt_async(AC_GETDEV_CHANGED, path, NULL); 9971e637ba6SAlexander Motin } 99830a4094fSAlexander Motin if (ident_buf->satacapabilities & ATA_SUPPORT_NCQ) { 9997dc3213dSAlexander Motin path->device->mintags = 2; 10007dc3213dSAlexander Motin path->device->maxtags = 100130a4094fSAlexander Motin ATA_QUEUE_LEN(ident_buf->queue) + 1; 100230a4094fSAlexander Motin } 100330a4094fSAlexander Motin ata_find_quirk(path->device); 1004507e5811SAlexander Motin if (path->device->mintags != 0 && 1005507e5811SAlexander Motin path->bus->sim->max_tagged_dev_openings != 0) { 1006699f853bSAlexander Motin /* Check if the SIM does not want queued commands. */ 1007762a7f4fSWarner Losh xpt_path_inq(&cpi, path); 1008699f853bSAlexander Motin if (cpi.ccb_h.status == CAM_REQ_CMP && 1009699f853bSAlexander Motin (cpi.hba_inquiry & PI_TAG_ABLE)) { 1010c8039fc6SAlexander Motin /* Report SIM which tags are allowed. */ 1011c8039fc6SAlexander Motin bzero(&cts, sizeof(cts)); 101283c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1013c8039fc6SAlexander Motin cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1014c8039fc6SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 1015c8039fc6SAlexander Motin cts.xport_specific.sata.tags = path->device->maxtags; 1016c8039fc6SAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_TAGS; 1017c8039fc6SAlexander Motin xpt_action((union ccb *)&cts); 101830a4094fSAlexander Motin } 1019699f853bSAlexander Motin } 1020bc1bf6e8SAlexander Motin ata_device_transport(path); 1021b9c473b2SAlexander Motin if (changed) 1022b9c473b2SAlexander Motin proberequestdefaultnegotiation(periph); 102352c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_SETMODE); 102452c9ce25SScott Long xpt_release_ccb(done_ccb); 102552c9ce25SScott Long xpt_schedule(periph, priority); 1026cccf4220SAlexander Motin goto out; 102752c9ce25SScott Long } 10284ef08dc5SAlexander Motin case PROBE_SPINUP: 10294ef08dc5SAlexander Motin if (bootverbose) 10304ef08dc5SAlexander Motin xpt_print(path, "Spin-up done\n"); 10314ef08dc5SAlexander Motin softc->spinup = 1; 10324ef08dc5SAlexander Motin PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 10334ef08dc5SAlexander Motin xpt_release_ccb(done_ccb); 10344ef08dc5SAlexander Motin xpt_schedule(periph, priority); 1035cccf4220SAlexander Motin goto out; 103652c9ce25SScott Long case PROBE_SETMODE: 1037da6808c1SAlexander Motin /* Set supported bits. */ 1038da6808c1SAlexander Motin bzero(&cts, sizeof(cts)); 1039da6808c1SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1040da6808c1SAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1041da6808c1SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 1042da6808c1SAlexander Motin xpt_action((union ccb *)&cts); 10432e1eb332SMarius Strobl if (path->device->transport == XPORT_SATA && 10442e1eb332SMarius Strobl cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1045da6808c1SAlexander Motin caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H; 10462e1eb332SMarius Strobl else if (path->device->transport == XPORT_ATA && 10472e1eb332SMarius Strobl cts.xport_specific.ata.valid & CTS_ATA_VALID_CAPS) 10482e1eb332SMarius Strobl caps = cts.xport_specific.ata.caps & CTS_ATA_CAPS_H; 1049da6808c1SAlexander Motin else 1050da6808c1SAlexander Motin caps = 0; 10512e1eb332SMarius Strobl if (path->device->transport == XPORT_SATA && 10522e1eb332SMarius Strobl ident_buf->satacapabilities != 0xffff) { 1053da6808c1SAlexander Motin if (ident_buf->satacapabilities & ATA_SUPPORT_IFPWRMNGTRCV) 1054da6808c1SAlexander Motin caps |= CTS_SATA_CAPS_D_PMREQ; 1055da6808c1SAlexander Motin if (ident_buf->satacapabilities & ATA_SUPPORT_HAPST) 1056da6808c1SAlexander Motin caps |= CTS_SATA_CAPS_D_APST; 1057da6808c1SAlexander Motin } 1058da6808c1SAlexander Motin /* Mask unwanted bits. */ 1059da6808c1SAlexander Motin bzero(&cts, sizeof(cts)); 1060da6808c1SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1061da6808c1SAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1062da6808c1SAlexander Motin cts.type = CTS_TYPE_USER_SETTINGS; 1063da6808c1SAlexander Motin xpt_action((union ccb *)&cts); 10642e1eb332SMarius Strobl if (path->device->transport == XPORT_SATA && 10652e1eb332SMarius Strobl cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1066da6808c1SAlexander Motin caps &= cts.xport_specific.sata.caps; 10672e1eb332SMarius Strobl else if (path->device->transport == XPORT_ATA && 10682e1eb332SMarius Strobl cts.xport_specific.ata.valid & CTS_ATA_VALID_CAPS) 10692e1eb332SMarius Strobl caps &= cts.xport_specific.ata.caps; 1070c2b82f3eSAlexander Motin else 1071c2b82f3eSAlexander Motin caps = 0; 10722e1eb332SMarius Strobl /* 10732e1eb332SMarius Strobl * Remember what transport thinks about 48-bit DMA. If 10742e1eb332SMarius Strobl * capability information is not provided or transport is 10752e1eb332SMarius Strobl * SATA, we take support for granted. 10762e1eb332SMarius Strobl */ 10772e1eb332SMarius Strobl if (!(path->device->inq_flags & SID_DMA) || 10782e1eb332SMarius Strobl (path->device->transport == XPORT_ATA && 10792e1eb332SMarius Strobl (cts.xport_specific.ata.valid & CTS_ATA_VALID_CAPS) && 10802e1eb332SMarius Strobl !(caps & CTS_ATA_CAPS_H_DMA48))) 10812e1eb332SMarius Strobl path->device->inq_flags &= ~SID_DMA48; 10822e1eb332SMarius Strobl else 10832e1eb332SMarius Strobl path->device->inq_flags |= SID_DMA48; 1084da6808c1SAlexander Motin /* Store result to SIM. */ 1085da6808c1SAlexander Motin bzero(&cts, sizeof(cts)); 1086da6808c1SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1087da6808c1SAlexander Motin cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1088da6808c1SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 10892e1eb332SMarius Strobl if (path->device->transport == XPORT_SATA) { 1090da6808c1SAlexander Motin cts.xport_specific.sata.caps = caps; 1091da6808c1SAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS; 10922e1eb332SMarius Strobl } else { 10932e1eb332SMarius Strobl cts.xport_specific.ata.caps = caps; 10942e1eb332SMarius Strobl cts.xport_specific.ata.valid = CTS_ATA_VALID_CAPS; 10952e1eb332SMarius Strobl } 1096da6808c1SAlexander Motin xpt_action((union ccb *)&cts); 1097da6808c1SAlexander Motin softc->caps = caps; 10982e1eb332SMarius Strobl if (path->device->transport != XPORT_SATA) 10992e1eb332SMarius Strobl goto notsata; 1100958e4a69SAlexander Motin if ((ident_buf->satasupport & ATA_SUPPORT_IFPWRMNGT) && 1101958e4a69SAlexander Motin (!(softc->caps & CTS_SATA_CAPS_H_PMREQ)) != 1102958e4a69SAlexander Motin (!(ident_buf->sataenabled & ATA_SUPPORT_IFPWRMNGT))) { 1103da6808c1SAlexander Motin PROBE_SET_ACTION(softc, PROBE_SETPM); 1104da6808c1SAlexander Motin xpt_release_ccb(done_ccb); 1105da6808c1SAlexander Motin xpt_schedule(periph, priority); 1106cccf4220SAlexander Motin goto out; 1107da6808c1SAlexander Motin } 1108da6808c1SAlexander Motin /* FALLTHROUGH */ 1109da6808c1SAlexander Motin case PROBE_SETPM: 1110da6808c1SAlexander Motin if (ident_buf->satacapabilities != 0xffff && 1111958e4a69SAlexander Motin (ident_buf->satacapabilities & ATA_SUPPORT_DAPST) && 1112958e4a69SAlexander Motin (!(softc->caps & CTS_SATA_CAPS_H_APST)) != 1113958e4a69SAlexander Motin (!(ident_buf->sataenabled & ATA_ENABLED_DAPST))) { 1114da6808c1SAlexander Motin PROBE_SET_ACTION(softc, PROBE_SETAPST); 1115da6808c1SAlexander Motin xpt_release_ccb(done_ccb); 1116da6808c1SAlexander Motin xpt_schedule(periph, priority); 1117cccf4220SAlexander Motin goto out; 1118da6808c1SAlexander Motin } 1119da6808c1SAlexander Motin /* FALLTHROUGH */ 1120da6808c1SAlexander Motin case PROBE_SETAPST: 1121958e4a69SAlexander Motin if ((ident_buf->satasupport & ATA_SUPPORT_AUTOACTIVATE) && 1122958e4a69SAlexander Motin (!(softc->caps & CTS_SATA_CAPS_H_DMAAA)) != 1123958e4a69SAlexander Motin (!(ident_buf->sataenabled & ATA_SUPPORT_AUTOACTIVATE))) { 1124da6808c1SAlexander Motin PROBE_SET_ACTION(softc, PROBE_SETDMAAA); 1125da6808c1SAlexander Motin xpt_release_ccb(done_ccb); 1126da6808c1SAlexander Motin xpt_schedule(periph, priority); 1127cccf4220SAlexander Motin goto out; 1128da6808c1SAlexander Motin } 1129da6808c1SAlexander Motin /* FALLTHROUGH */ 1130da6808c1SAlexander Motin case PROBE_SETDMAAA: 1131e4bed0b4SWarner Losh if (path->device->protocol != PROTO_ATA && 1132e4bed0b4SWarner Losh (ident_buf->satasupport & ATA_SUPPORT_ASYNCNOTIF) && 11338d169381SAlexander Motin (!(softc->caps & CTS_SATA_CAPS_H_AN)) != 11348d169381SAlexander Motin (!(ident_buf->sataenabled & ATA_SUPPORT_ASYNCNOTIF))) { 11358d169381SAlexander Motin PROBE_SET_ACTION(softc, PROBE_SETAN); 11368d169381SAlexander Motin xpt_release_ccb(done_ccb); 11378d169381SAlexander Motin xpt_schedule(periph, priority); 1138cccf4220SAlexander Motin goto out; 11398d169381SAlexander Motin } 11408d169381SAlexander Motin /* FALLTHROUGH */ 11418d169381SAlexander Motin case PROBE_SETAN: 1142da6808c1SAlexander Motin notsata: 11431e637ba6SAlexander Motin if (path->device->protocol == PROTO_ATA) { 11441e637ba6SAlexander Motin PROBE_SET_ACTION(softc, PROBE_SET_MULTI); 11451e637ba6SAlexander Motin } else { 11461e637ba6SAlexander Motin PROBE_SET_ACTION(softc, PROBE_INQUIRY); 11471e637ba6SAlexander Motin } 11481e637ba6SAlexander Motin xpt_release_ccb(done_ccb); 11491e637ba6SAlexander Motin xpt_schedule(periph, priority); 1150cccf4220SAlexander Motin goto out; 11511e637ba6SAlexander Motin case PROBE_SET_MULTI: 11521e637ba6SAlexander Motin if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 115352c9ce25SScott Long path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1154f98d7a47SAlexander Motin xpt_acquire_device(path->device); 115552c9ce25SScott Long done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 115652c9ce25SScott Long xpt_action(done_ccb); 1157cccf4220SAlexander Motin xpt_async(AC_FOUND_DEVICE, path, done_ccb); 11581e637ba6SAlexander Motin } 1159a4d953c4SAlexander Motin PROBE_SET_ACTION(softc, PROBE_DONE); 116052c9ce25SScott Long break; 116152c9ce25SScott Long case PROBE_INQUIRY: 116252c9ce25SScott Long case PROBE_FULL_INQUIRY: 116352c9ce25SScott Long { 11641e637ba6SAlexander Motin u_int8_t periph_qual, len; 116552c9ce25SScott Long 116652c9ce25SScott Long path->device->flags |= CAM_DEV_INQUIRY_DATA_VALID; 116752c9ce25SScott Long 116852c9ce25SScott Long periph_qual = SID_QUAL(inq_buf); 116952c9ce25SScott Long 117092024858SAlexander Motin if (periph_qual != SID_QUAL_LU_CONNECTED && 117192024858SAlexander Motin periph_qual != SID_QUAL_LU_OFFLINE) 11721e637ba6SAlexander Motin break; 117352c9ce25SScott Long 117452c9ce25SScott Long /* 117552c9ce25SScott Long * We conservatively request only 117652c9ce25SScott Long * SHORT_INQUIRY_LEN bytes of inquiry 117752c9ce25SScott Long * information during our first try 117852c9ce25SScott Long * at sending an INQUIRY. If the device 117952c9ce25SScott Long * has more information to give, 118052c9ce25SScott Long * perform a second request specifying 118152c9ce25SScott Long * the amount of information the device 118252c9ce25SScott Long * is willing to give. 118352c9ce25SScott Long */ 118452c9ce25SScott Long len = inq_buf->additional_length 11851e637ba6SAlexander Motin + offsetof(struct scsi_inquiry_data, additional_length) + 1; 118652c9ce25SScott Long if (softc->action == PROBE_INQUIRY 118752c9ce25SScott Long && len > SHORT_INQUIRY_LENGTH) { 118852c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_FULL_INQUIRY); 118952c9ce25SScott Long xpt_release_ccb(done_ccb); 119052c9ce25SScott Long xpt_schedule(periph, priority); 1191cccf4220SAlexander Motin goto out; 119252c9ce25SScott Long } 119352c9ce25SScott Long 11944b997c49SAlexander Motin ata_device_transport(path); 11951e637ba6SAlexander Motin if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 119652c9ce25SScott Long path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1197f98d7a47SAlexander Motin xpt_acquire_device(path->device); 119852c9ce25SScott Long done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 119952c9ce25SScott Long xpt_action(done_ccb); 1200cccf4220SAlexander Motin xpt_async(AC_FOUND_DEVICE, path, done_ccb); 12011e637ba6SAlexander Motin } 1202a4d953c4SAlexander Motin PROBE_SET_ACTION(softc, PROBE_DONE); 120352c9ce25SScott Long break; 120452c9ce25SScott Long } 120552c9ce25SScott Long case PROBE_PM_PID: 12064b997c49SAlexander Motin if ((path->device->flags & CAM_DEV_IDENTIFY_DATA_VALID) == 0) 120752c9ce25SScott Long bzero(ident_buf, sizeof(*ident_buf)); 120852c9ce25SScott Long softc->pm_pid = (done_ccb->ataio.res.lba_high << 24) + 120952c9ce25SScott Long (done_ccb->ataio.res.lba_mid << 16) + 121052c9ce25SScott Long (done_ccb->ataio.res.lba_low << 8) + 121152c9ce25SScott Long done_ccb->ataio.res.sector_count; 121265d0fb03SAlexander Motin ((uint32_t *)ident_buf)[0] = softc->pm_pid; 121352c9ce25SScott Long snprintf(ident_buf->model, sizeof(ident_buf->model), 121452c9ce25SScott Long "Port Multiplier %08x", softc->pm_pid); 121552c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_PM_PRV); 121652c9ce25SScott Long xpt_release_ccb(done_ccb); 121752c9ce25SScott Long xpt_schedule(periph, priority); 1218cccf4220SAlexander Motin goto out; 121952c9ce25SScott Long case PROBE_PM_PRV: 122052c9ce25SScott Long softc->pm_prv = (done_ccb->ataio.res.lba_high << 24) + 122152c9ce25SScott Long (done_ccb->ataio.res.lba_mid << 16) + 122252c9ce25SScott Long (done_ccb->ataio.res.lba_low << 8) + 122352c9ce25SScott Long done_ccb->ataio.res.sector_count; 122465d0fb03SAlexander Motin ((uint32_t *)ident_buf)[1] = softc->pm_prv; 122552c9ce25SScott Long snprintf(ident_buf->revision, sizeof(ident_buf->revision), 122652c9ce25SScott Long "%04x", softc->pm_prv); 12274b997c49SAlexander Motin path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 1228bc1bf6e8SAlexander Motin ata_device_transport(path); 1229bc1bf6e8SAlexander Motin if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) 1230bc1bf6e8SAlexander Motin proberequestdefaultnegotiation(periph); 1231da6808c1SAlexander Motin /* Set supported bits. */ 1232da6808c1SAlexander Motin bzero(&cts, sizeof(cts)); 1233da6808c1SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1234da6808c1SAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1235da6808c1SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 1236da6808c1SAlexander Motin xpt_action((union ccb *)&cts); 1237da6808c1SAlexander Motin if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1238da6808c1SAlexander Motin caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H; 1239da6808c1SAlexander Motin else 1240da6808c1SAlexander Motin caps = 0; 1241da6808c1SAlexander Motin /* All PMPs must support PM requests. */ 1242da6808c1SAlexander Motin caps |= CTS_SATA_CAPS_D_PMREQ; 1243da6808c1SAlexander Motin /* Mask unwanted bits. */ 1244da6808c1SAlexander Motin bzero(&cts, sizeof(cts)); 1245da6808c1SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1246da6808c1SAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1247da6808c1SAlexander Motin cts.type = CTS_TYPE_USER_SETTINGS; 1248da6808c1SAlexander Motin xpt_action((union ccb *)&cts); 1249da6808c1SAlexander Motin if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1250da6808c1SAlexander Motin caps &= cts.xport_specific.sata.caps; 1251c2b82f3eSAlexander Motin else 1252c2b82f3eSAlexander Motin caps = 0; 12532e1eb332SMarius Strobl /* Remember what transport thinks about AEN. */ 1254e4bed0b4SWarner Losh if ((caps & CTS_SATA_CAPS_H_AN) && path->device->protocol != PROTO_ATA) 12552e1eb332SMarius Strobl path->device->inq_flags |= SID_AEN; 12562e1eb332SMarius Strobl else 12572e1eb332SMarius Strobl path->device->inq_flags &= ~SID_AEN; 1258da6808c1SAlexander Motin /* Store result to SIM. */ 1259da6808c1SAlexander Motin bzero(&cts, sizeof(cts)); 1260da6808c1SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1261da6808c1SAlexander Motin cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1262da6808c1SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 1263da6808c1SAlexander Motin cts.xport_specific.sata.caps = caps; 1264da6808c1SAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS; 1265da6808c1SAlexander Motin xpt_action((union ccb *)&cts); 1266da6808c1SAlexander Motin softc->caps = caps; 12673631c638SAlexander Motin xpt_async(AC_GETDEV_CHANGED, path, NULL); 126865d0fb03SAlexander Motin if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 126952c9ce25SScott Long path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1270f98d7a47SAlexander Motin xpt_acquire_device(path->device); 127152c9ce25SScott Long done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 127252c9ce25SScott Long xpt_action(done_ccb); 1273cccf4220SAlexander Motin xpt_async(AC_FOUND_DEVICE, path, done_ccb); 127465d0fb03SAlexander Motin } else { 127565d0fb03SAlexander Motin done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 127665d0fb03SAlexander Motin xpt_action(done_ccb); 1277cccf4220SAlexander Motin xpt_async(AC_SCSI_AEN, path, done_ccb); 127852c9ce25SScott Long } 1279a4d953c4SAlexander Motin PROBE_SET_ACTION(softc, PROBE_DONE); 128052c9ce25SScott Long break; 12813089bb2eSAlexander Motin case PROBE_IDENTIFY_SES: 12823089bb2eSAlexander Motin case PROBE_IDENTIFY_SAFTE: 12833089bb2eSAlexander Motin if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) { 12843089bb2eSAlexander Motin /* Check that it is the same device. */ 12853089bb2eSAlexander Motin if (bcmp(&softc->ident_data, ident_buf, 53)) { 12863089bb2eSAlexander Motin /* Device changed. */ 12873089bb2eSAlexander Motin xpt_async(AC_LOST_DEVICE, path, NULL); 12883089bb2eSAlexander Motin } else { 12893089bb2eSAlexander Motin bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 12903089bb2eSAlexander Motin changed = 0; 12913089bb2eSAlexander Motin } 12923089bb2eSAlexander Motin } 12933089bb2eSAlexander Motin if (changed) { 12943089bb2eSAlexander Motin bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 12953089bb2eSAlexander Motin /* Clean up from previous instance of this device */ 12963089bb2eSAlexander Motin if (path->device->device_id != NULL) { 12973089bb2eSAlexander Motin free(path->device->device_id, M_CAMXPT); 12983089bb2eSAlexander Motin path->device->device_id = NULL; 12993089bb2eSAlexander Motin path->device->device_id_len = 0; 13003089bb2eSAlexander Motin } 13013089bb2eSAlexander Motin path->device->device_id = 13023089bb2eSAlexander Motin malloc(16, M_CAMXPT, M_NOWAIT); 13033089bb2eSAlexander Motin if (path->device->device_id != NULL) { 13043089bb2eSAlexander Motin path->device->device_id_len = 16; 13053089bb2eSAlexander Motin bcopy(&fake_device_id_hdr, 13063089bb2eSAlexander Motin path->device->device_id, 8); 13073089bb2eSAlexander Motin bcopy(((uint8_t*)ident_buf) + 2, 13083089bb2eSAlexander Motin path->device->device_id + 8, 8); 13093089bb2eSAlexander Motin } 13103089bb2eSAlexander Motin 13113089bb2eSAlexander Motin path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 13123089bb2eSAlexander Motin } 1313bc1bf6e8SAlexander Motin ata_device_transport(path); 1314bc1bf6e8SAlexander Motin if (changed) 1315bc1bf6e8SAlexander Motin proberequestdefaultnegotiation(periph); 13163089bb2eSAlexander Motin 13173089bb2eSAlexander Motin if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 13183089bb2eSAlexander Motin path->device->flags &= ~CAM_DEV_UNCONFIGURED; 13193089bb2eSAlexander Motin xpt_acquire_device(path->device); 13203089bb2eSAlexander Motin done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 13213089bb2eSAlexander Motin xpt_action(done_ccb); 1322cccf4220SAlexander Motin xpt_async(AC_FOUND_DEVICE, path, done_ccb); 13233089bb2eSAlexander Motin } 1324a4d953c4SAlexander Motin PROBE_SET_ACTION(softc, PROBE_DONE); 13253089bb2eSAlexander Motin break; 132652c9ce25SScott Long default: 1327a4d953c4SAlexander Motin panic("probedone: invalid action state 0x%x\n", softc->action); 132852c9ce25SScott Long } 13291e637ba6SAlexander Motin done: 133083c5d981SAlexander Motin if (softc->restart) { 133183c5d981SAlexander Motin softc->restart = 0; 13321e637ba6SAlexander Motin xpt_release_ccb(done_ccb); 133383c5d981SAlexander Motin probeschedule(periph); 1334cccf4220SAlexander Motin goto out; 133583c5d981SAlexander Motin } 133683c5d981SAlexander Motin xpt_release_ccb(done_ccb); 1337a4d953c4SAlexander Motin CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe completed\n")); 133883c5d981SAlexander Motin while ((done_ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs))) { 133983c5d981SAlexander Motin TAILQ_REMOVE(&softc->request_ccbs, 134083c5d981SAlexander Motin &done_ccb->ccb_h, periph_links.tqe); 134183c5d981SAlexander Motin done_ccb->ccb_h.status = found ? CAM_REQ_CMP : CAM_REQ_CMP_ERR; 134252c9ce25SScott Long xpt_done(done_ccb); 134383c5d981SAlexander Motin } 1344cccf4220SAlexander Motin /* Drop freeze taken due to CAM_DEV_QFREEZE flag set. */ 1345cccf4220SAlexander Motin cam_release_devq(path, 0, 0, 0, FALSE); 13462e3f592bSAlexander Motin cam_periph_invalidate(periph); 134752c9ce25SScott Long cam_periph_release_locked(periph); 134852c9ce25SScott Long } 134952c9ce25SScott Long 135052c9ce25SScott Long static void 135152c9ce25SScott Long probecleanup(struct cam_periph *periph) 135252c9ce25SScott Long { 135352c9ce25SScott Long free(periph->softc, M_CAMXPT); 135452c9ce25SScott Long } 135552c9ce25SScott Long 135652c9ce25SScott Long static void 135730a4094fSAlexander Motin ata_find_quirk(struct cam_ed *device) 135852c9ce25SScott Long { 135930a4094fSAlexander Motin struct ata_quirk_entry *quirk; 136052c9ce25SScott Long caddr_t match; 136152c9ce25SScott Long 136230a4094fSAlexander Motin match = cam_quirkmatch((caddr_t)&device->ident_data, 136330a4094fSAlexander Motin (caddr_t)ata_quirk_table, 13648dfea464SPedro F. Giffuni nitems(ata_quirk_table), 136530a4094fSAlexander Motin sizeof(*ata_quirk_table), ata_identify_match); 136652c9ce25SScott Long 136752c9ce25SScott Long if (match == NULL) 136852c9ce25SScott Long panic("xpt_find_quirk: device didn't match wildcard entry!!"); 136952c9ce25SScott Long 137030a4094fSAlexander Motin quirk = (struct ata_quirk_entry *)match; 137152c9ce25SScott Long device->quirk = quirk; 13727dc3213dSAlexander Motin if (quirk->quirks & CAM_QUIRK_MAXTAGS) { 13737dc3213dSAlexander Motin device->mintags = quirk->mintags; 13747dc3213dSAlexander Motin device->maxtags = quirk->maxtags; 13757dc3213dSAlexander Motin } 137652c9ce25SScott Long } 137752c9ce25SScott Long 137852c9ce25SScott Long typedef struct { 137952c9ce25SScott Long union ccb *request_ccb; 138052c9ce25SScott Long struct ccb_pathinq *cpi; 138152c9ce25SScott Long int counter; 138252c9ce25SScott Long } ata_scan_bus_info; 138352c9ce25SScott Long 138452c9ce25SScott Long /* 138552c9ce25SScott Long * To start a scan, request_ccb is an XPT_SCAN_BUS ccb. 138652c9ce25SScott Long * As the scan progresses, xpt_scan_bus is used as the 138752c9ce25SScott Long * callback on completion function. 138852c9ce25SScott Long */ 138952c9ce25SScott Long static void 139052c9ce25SScott Long ata_scan_bus(struct cam_periph *periph, union ccb *request_ccb) 139152c9ce25SScott Long { 139252c9ce25SScott Long struct cam_path *path; 139352c9ce25SScott Long ata_scan_bus_info *scan_info; 139483c5d981SAlexander Motin union ccb *work_ccb, *reset_ccb; 1395227d67aaSAlexander Motin struct mtx *mtx; 139652c9ce25SScott Long cam_status status; 139752c9ce25SScott Long 139852c9ce25SScott Long CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE, 139952c9ce25SScott Long ("xpt_scan_bus\n")); 140052c9ce25SScott Long switch (request_ccb->ccb_h.func_code) { 140152c9ce25SScott Long case XPT_SCAN_BUS: 14020e85f214SMatt Jacob case XPT_SCAN_TGT: 140352c9ce25SScott Long /* Find out the characteristics of the bus */ 140452c9ce25SScott Long work_ccb = xpt_alloc_ccb_nowait(); 140552c9ce25SScott Long if (work_ccb == NULL) { 140652c9ce25SScott Long request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 140752c9ce25SScott Long xpt_done(request_ccb); 140852c9ce25SScott Long return; 140952c9ce25SScott Long } 1410762a7f4fSWarner Losh xpt_path_inq(&work_ccb->cpi, request_ccb->ccb_h.path); 141152c9ce25SScott Long if (work_ccb->ccb_h.status != CAM_REQ_CMP) { 141252c9ce25SScott Long request_ccb->ccb_h.status = work_ccb->ccb_h.status; 141352c9ce25SScott Long xpt_free_ccb(work_ccb); 141452c9ce25SScott Long xpt_done(request_ccb); 141552c9ce25SScott Long return; 141652c9ce25SScott Long } 141752c9ce25SScott Long 141883c5d981SAlexander Motin /* We may need to reset bus first, if we haven't done it yet. */ 141983c5d981SAlexander Motin if ((work_ccb->cpi.hba_inquiry & 142083c5d981SAlexander Motin (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE)) && 142183c5d981SAlexander Motin !(work_ccb->cpi.hba_misc & PIM_NOBUSRESET) && 142283c5d981SAlexander Motin !timevalisset(&request_ccb->ccb_h.path->bus->last_reset)) { 142383c5d981SAlexander Motin reset_ccb = xpt_alloc_ccb_nowait(); 1424f1893540SAlexander Motin if (reset_ccb == NULL) { 1425f1893540SAlexander Motin request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1426f1893540SAlexander Motin xpt_free_ccb(work_ccb); 1427f1893540SAlexander Motin xpt_done(request_ccb); 1428f1893540SAlexander Motin return; 1429f1893540SAlexander Motin } 143083c5d981SAlexander Motin xpt_setup_ccb(&reset_ccb->ccb_h, request_ccb->ccb_h.path, 143183c5d981SAlexander Motin CAM_PRIORITY_NONE); 143283c5d981SAlexander Motin reset_ccb->ccb_h.func_code = XPT_RESET_BUS; 143383c5d981SAlexander Motin xpt_action(reset_ccb); 143483c5d981SAlexander Motin if (reset_ccb->ccb_h.status != CAM_REQ_CMP) { 143583c5d981SAlexander Motin request_ccb->ccb_h.status = reset_ccb->ccb_h.status; 143683c5d981SAlexander Motin xpt_free_ccb(reset_ccb); 143783c5d981SAlexander Motin xpt_free_ccb(work_ccb); 143883c5d981SAlexander Motin xpt_done(request_ccb); 143983c5d981SAlexander Motin return; 144083c5d981SAlexander Motin } 144183c5d981SAlexander Motin xpt_free_ccb(reset_ccb); 144283c5d981SAlexander Motin } 144383c5d981SAlexander Motin 144452c9ce25SScott Long /* Save some state for use while we probe for devices */ 144552c9ce25SScott Long scan_info = (ata_scan_bus_info *) 144652c9ce25SScott Long malloc(sizeof(ata_scan_bus_info), M_CAMXPT, M_NOWAIT); 144752c9ce25SScott Long if (scan_info == NULL) { 144852c9ce25SScott Long request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1449f1893540SAlexander Motin xpt_free_ccb(work_ccb); 145052c9ce25SScott Long xpt_done(request_ccb); 145152c9ce25SScott Long return; 145252c9ce25SScott Long } 145352c9ce25SScott Long scan_info->request_ccb = request_ccb; 145452c9ce25SScott Long scan_info->cpi = &work_ccb->cpi; 145552c9ce25SScott Long /* If PM supported, probe it first. */ 145652c9ce25SScott Long if (scan_info->cpi->hba_inquiry & PI_SATAPM) 14570025eb12SAlexander Motin scan_info->counter = scan_info->cpi->max_target; 14580025eb12SAlexander Motin else 14590025eb12SAlexander Motin scan_info->counter = 0; 146052c9ce25SScott Long 146152c9ce25SScott Long work_ccb = xpt_alloc_ccb_nowait(); 146252c9ce25SScott Long if (work_ccb == NULL) { 146352c9ce25SScott Long free(scan_info, M_CAMXPT); 146452c9ce25SScott Long request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 146552c9ce25SScott Long xpt_done(request_ccb); 146652c9ce25SScott Long break; 146752c9ce25SScott Long } 1468227d67aaSAlexander Motin mtx = xpt_path_mtx(scan_info->request_ccb->ccb_h.path); 146952c9ce25SScott Long goto scan_next; 147052c9ce25SScott Long case XPT_SCAN_LUN: 147152c9ce25SScott Long work_ccb = request_ccb; 147252c9ce25SScott Long /* Reuse the same CCB to query if a device was really found */ 147352c9ce25SScott Long scan_info = (ata_scan_bus_info *)work_ccb->ccb_h.ppriv_ptr0; 1474227d67aaSAlexander Motin mtx = xpt_path_mtx(scan_info->request_ccb->ccb_h.path); 1475227d67aaSAlexander Motin mtx_lock(mtx); 147665d0fb03SAlexander Motin /* If there is PMP... */ 14770025eb12SAlexander Motin if ((scan_info->cpi->hba_inquiry & PI_SATAPM) && 14780025eb12SAlexander Motin (scan_info->counter == scan_info->cpi->max_target)) { 147983c5d981SAlexander Motin if (work_ccb->ccb_h.status == CAM_REQ_CMP) { 148065d0fb03SAlexander Motin /* everything else will be probed by it */ 1481e2a75189SAlexander Motin /* Free the current request path- we're done with it. */ 1482e2a75189SAlexander Motin xpt_free_path(work_ccb->ccb_h.path); 14830025eb12SAlexander Motin goto done; 148452c9ce25SScott Long } else { 148552c9ce25SScott Long struct ccb_trans_settings cts; 148652c9ce25SScott Long 148752c9ce25SScott Long /* Report SIM that PM is absent. */ 148852c9ce25SScott Long bzero(&cts, sizeof(cts)); 148952c9ce25SScott Long xpt_setup_ccb(&cts.ccb_h, 1490e2a75189SAlexander Motin work_ccb->ccb_h.path, CAM_PRIORITY_NONE); 149152c9ce25SScott Long cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 149252c9ce25SScott Long cts.type = CTS_TYPE_CURRENT_SETTINGS; 14933ccda2f3SAlexander Motin cts.xport_specific.sata.pm_present = 0; 149452c9ce25SScott Long cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; 149552c9ce25SScott Long xpt_action((union ccb *)&cts); 149652c9ce25SScott Long } 149752c9ce25SScott Long } 1498e2a75189SAlexander Motin /* Free the current request path- we're done with it. */ 1499e2a75189SAlexander Motin xpt_free_path(work_ccb->ccb_h.path); 15000025eb12SAlexander Motin if (scan_info->counter == 15010025eb12SAlexander Motin ((scan_info->cpi->hba_inquiry & PI_SATAPM) ? 15020025eb12SAlexander Motin 0 : scan_info->cpi->max_target)) { 15030025eb12SAlexander Motin done: 1504227d67aaSAlexander Motin mtx_unlock(mtx); 150552c9ce25SScott Long xpt_free_ccb(work_ccb); 150652c9ce25SScott Long xpt_free_ccb((union ccb *)scan_info->cpi); 150752c9ce25SScott Long request_ccb = scan_info->request_ccb; 150852c9ce25SScott Long free(scan_info, M_CAMXPT); 150952c9ce25SScott Long request_ccb->ccb_h.status = CAM_REQ_CMP; 151052c9ce25SScott Long xpt_done(request_ccb); 151152c9ce25SScott Long break; 151252c9ce25SScott Long } 15130025eb12SAlexander Motin /* Take next device. Wrap from max (PMP) to 0. */ 15140025eb12SAlexander Motin scan_info->counter = (scan_info->counter + 1 ) % 15150025eb12SAlexander Motin (scan_info->cpi->max_target + 1); 151652c9ce25SScott Long scan_next: 1517e5dfa058SAlexander Motin status = xpt_create_path(&path, NULL, 151852c9ce25SScott Long scan_info->request_ccb->ccb_h.path_id, 151952c9ce25SScott Long scan_info->counter, 0); 152052c9ce25SScott Long if (status != CAM_REQ_CMP) { 1521227d67aaSAlexander Motin if (request_ccb->ccb_h.func_code == XPT_SCAN_LUN) 1522227d67aaSAlexander Motin mtx_unlock(mtx); 152352c9ce25SScott Long printf("xpt_scan_bus: xpt_create_path failed" 152452c9ce25SScott Long " with status %#x, bus scan halted\n", 152552c9ce25SScott Long status); 152652c9ce25SScott Long xpt_free_ccb(work_ccb); 152752c9ce25SScott Long xpt_free_ccb((union ccb *)scan_info->cpi); 152852c9ce25SScott Long request_ccb = scan_info->request_ccb; 152952c9ce25SScott Long free(scan_info, M_CAMXPT); 153052c9ce25SScott Long request_ccb->ccb_h.status = status; 153152c9ce25SScott Long xpt_done(request_ccb); 153252c9ce25SScott Long break; 153352c9ce25SScott Long } 153452c9ce25SScott Long xpt_setup_ccb(&work_ccb->ccb_h, path, 153552c9ce25SScott Long scan_info->request_ccb->ccb_h.pinfo.priority); 153652c9ce25SScott Long work_ccb->ccb_h.func_code = XPT_SCAN_LUN; 153752c9ce25SScott Long work_ccb->ccb_h.cbfcnp = ata_scan_bus; 1538227d67aaSAlexander Motin work_ccb->ccb_h.flags |= CAM_UNLOCKED; 153952c9ce25SScott Long work_ccb->ccb_h.ppriv_ptr0 = scan_info; 154052c9ce25SScott Long work_ccb->crcn.flags = scan_info->request_ccb->crcn.flags; 1541227d67aaSAlexander Motin mtx_unlock(mtx); 1542227d67aaSAlexander Motin if (request_ccb->ccb_h.func_code == XPT_SCAN_LUN) 1543227d67aaSAlexander Motin mtx = NULL; 154452c9ce25SScott Long xpt_action(work_ccb); 1545227d67aaSAlexander Motin if (mtx != NULL) 1546227d67aaSAlexander Motin mtx_lock(mtx); 154752c9ce25SScott Long break; 154852c9ce25SScott Long default: 154952c9ce25SScott Long break; 155052c9ce25SScott Long } 155152c9ce25SScott Long } 155252c9ce25SScott Long 155352c9ce25SScott Long static void 155452c9ce25SScott Long ata_scan_lun(struct cam_periph *periph, struct cam_path *path, 155552c9ce25SScott Long cam_flags flags, union ccb *request_ccb) 155652c9ce25SScott Long { 155752c9ce25SScott Long struct ccb_pathinq cpi; 155852c9ce25SScott Long cam_status status; 155952c9ce25SScott Long struct cam_path *new_path; 156052c9ce25SScott Long struct cam_periph *old_periph; 1561227d67aaSAlexander Motin int lock; 156252c9ce25SScott Long 156383c5d981SAlexander Motin CAM_DEBUG(path, CAM_DEBUG_TRACE, ("xpt_scan_lun\n")); 156452c9ce25SScott Long 1565762a7f4fSWarner Losh xpt_path_inq(&cpi, path); 156652c9ce25SScott Long if (cpi.ccb_h.status != CAM_REQ_CMP) { 156752c9ce25SScott Long if (request_ccb != NULL) { 156852c9ce25SScott Long request_ccb->ccb_h.status = cpi.ccb_h.status; 156952c9ce25SScott Long xpt_done(request_ccb); 157052c9ce25SScott Long } 157152c9ce25SScott Long return; 157252c9ce25SScott Long } 157352c9ce25SScott Long 157452c9ce25SScott Long if (request_ccb == NULL) { 157532aa80a6SAlexander Motin request_ccb = xpt_alloc_ccb_nowait(); 157652c9ce25SScott Long if (request_ccb == NULL) { 157752c9ce25SScott Long xpt_print(path, "xpt_scan_lun: can't allocate CCB, " 157852c9ce25SScott Long "can't continue\n"); 157952c9ce25SScott Long return; 158052c9ce25SScott Long } 1581e5dfa058SAlexander Motin status = xpt_create_path(&new_path, NULL, 158252c9ce25SScott Long path->bus->path_id, 158352c9ce25SScott Long path->target->target_id, 158452c9ce25SScott Long path->device->lun_id); 158552c9ce25SScott Long if (status != CAM_REQ_CMP) { 158632aa80a6SAlexander Motin xpt_print(path, "xpt_scan_lun: can't create path, " 158752c9ce25SScott Long "can't continue\n"); 158832aa80a6SAlexander Motin xpt_free_ccb(request_ccb); 158952c9ce25SScott Long return; 159052c9ce25SScott Long } 159183c5d981SAlexander Motin xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_XPT); 159252c9ce25SScott Long request_ccb->ccb_h.cbfcnp = xptscandone; 1593227d67aaSAlexander Motin request_ccb->ccb_h.flags |= CAM_UNLOCKED; 159452c9ce25SScott Long request_ccb->ccb_h.func_code = XPT_SCAN_LUN; 159552c9ce25SScott Long request_ccb->crcn.flags = flags; 159652c9ce25SScott Long } 159752c9ce25SScott Long 1598227d67aaSAlexander Motin lock = (xpt_path_owned(path) == 0); 1599227d67aaSAlexander Motin if (lock) 1600227d67aaSAlexander Motin xpt_path_lock(path); 1601f09f8e3eSAlexander Motin if ((old_periph = cam_periph_find(path, "aprobe")) != NULL) { 16022e3f592bSAlexander Motin if ((old_periph->flags & CAM_PERIPH_INVALID) == 0) { 160352c9ce25SScott Long probe_softc *softc; 160452c9ce25SScott Long 160552c9ce25SScott Long softc = (probe_softc *)old_periph->softc; 16062e3f592bSAlexander Motin TAILQ_INSERT_TAIL(&softc->request_ccbs, 16072e3f592bSAlexander Motin &request_ccb->ccb_h, periph_links.tqe); 160883c5d981SAlexander Motin softc->restart = 1; 160952c9ce25SScott Long } else { 16102e3f592bSAlexander Motin request_ccb->ccb_h.status = CAM_REQ_CMP_ERR; 16112e3f592bSAlexander Motin xpt_done(request_ccb); 16122e3f592bSAlexander Motin } 16132e3f592bSAlexander Motin } else { 161452c9ce25SScott Long status = cam_periph_alloc(proberegister, NULL, probecleanup, 1615f09f8e3eSAlexander Motin probestart, "aprobe", 161652c9ce25SScott Long CAM_PERIPH_BIO, 161752c9ce25SScott Long request_ccb->ccb_h.path, NULL, 0, 161852c9ce25SScott Long request_ccb); 161952c9ce25SScott Long 162052c9ce25SScott Long if (status != CAM_REQ_CMP) { 162152c9ce25SScott Long xpt_print(path, "xpt_scan_lun: cam_alloc_periph " 162252c9ce25SScott Long "returned an error, can't continue probe\n"); 162352c9ce25SScott Long request_ccb->ccb_h.status = status; 162452c9ce25SScott Long xpt_done(request_ccb); 162552c9ce25SScott Long } 162652c9ce25SScott Long } 1627227d67aaSAlexander Motin if (lock) 1628227d67aaSAlexander Motin xpt_path_unlock(path); 162952c9ce25SScott Long } 163052c9ce25SScott Long 163152c9ce25SScott Long static void 163252c9ce25SScott Long xptscandone(struct cam_periph *periph, union ccb *done_ccb) 163352c9ce25SScott Long { 163432aa80a6SAlexander Motin 163532aa80a6SAlexander Motin xpt_free_path(done_ccb->ccb_h.path); 163632aa80a6SAlexander Motin xpt_free_ccb(done_ccb); 163752c9ce25SScott Long } 163852c9ce25SScott Long 163952c9ce25SScott Long static struct cam_ed * 164052c9ce25SScott Long ata_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id) 164152c9ce25SScott Long { 164230a4094fSAlexander Motin struct ata_quirk_entry *quirk; 164352c9ce25SScott Long struct cam_ed *device; 164452c9ce25SScott Long 164552c9ce25SScott Long device = xpt_alloc_device(bus, target, lun_id); 164652c9ce25SScott Long if (device == NULL) 164752c9ce25SScott Long return (NULL); 164852c9ce25SScott Long 164952c9ce25SScott Long /* 165052c9ce25SScott Long * Take the default quirk entry until we have inquiry 165152c9ce25SScott Long * data and can determine a better quirk to use. 165252c9ce25SScott Long */ 16538dfea464SPedro F. Giffuni quirk = &ata_quirk_table[nitems(ata_quirk_table) - 1]; 165452c9ce25SScott Long device->quirk = (void *)quirk; 165530a4094fSAlexander Motin device->mintags = 0; 165630a4094fSAlexander Motin device->maxtags = 0; 165752c9ce25SScott Long bzero(&device->inq_data, sizeof(device->inq_data)); 165852c9ce25SScott Long device->inq_flags = 0; 165952c9ce25SScott Long device->queue_flags = 0; 166052c9ce25SScott Long device->serial_num = NULL; 166152c9ce25SScott Long device->serial_num_len = 0; 166252c9ce25SScott Long return (device); 166352c9ce25SScott Long } 166452c9ce25SScott Long 166552c9ce25SScott Long static void 166652c9ce25SScott Long ata_device_transport(struct cam_path *path) 166752c9ce25SScott Long { 166852c9ce25SScott Long struct ccb_pathinq cpi; 16694b997c49SAlexander Motin struct ccb_trans_settings cts; 16704b997c49SAlexander Motin struct scsi_inquiry_data *inq_buf = NULL; 16714b997c49SAlexander Motin struct ata_params *ident_buf = NULL; 167252c9ce25SScott Long 167352c9ce25SScott Long /* Get transport information from the SIM */ 1674762a7f4fSWarner Losh xpt_path_inq(&cpi, path); 167552c9ce25SScott Long 167652c9ce25SScott Long path->device->transport = cpi.transport; 16774b997c49SAlexander Motin if ((path->device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0) 16784b997c49SAlexander Motin inq_buf = &path->device->inq_data; 16794b997c49SAlexander Motin if ((path->device->flags & CAM_DEV_IDENTIFY_DATA_VALID) != 0) 16804b997c49SAlexander Motin ident_buf = &path->device->ident_data; 16814b997c49SAlexander Motin if (path->device->protocol == PROTO_ATA) { 16824b997c49SAlexander Motin path->device->protocol_version = ident_buf ? 16834b997c49SAlexander Motin ata_version(ident_buf->version_major) : cpi.protocol_version; 16844b997c49SAlexander Motin } else if (path->device->protocol == PROTO_SCSI) { 16854b997c49SAlexander Motin path->device->protocol_version = inq_buf ? 16864b997c49SAlexander Motin SID_ANSI_REV(inq_buf) : cpi.protocol_version; 168752c9ce25SScott Long } 16884b997c49SAlexander Motin path->device->transport_version = ident_buf ? 16894b997c49SAlexander Motin ata_version(ident_buf->version_major) : cpi.transport_version; 169052c9ce25SScott Long 169152c9ce25SScott Long /* Tell the controller what we think */ 169283c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 169352c9ce25SScott Long cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 169452c9ce25SScott Long cts.type = CTS_TYPE_CURRENT_SETTINGS; 169552c9ce25SScott Long cts.transport = path->device->transport; 169652c9ce25SScott Long cts.transport_version = path->device->transport_version; 169752c9ce25SScott Long cts.protocol = path->device->protocol; 169852c9ce25SScott Long cts.protocol_version = path->device->protocol_version; 169952c9ce25SScott Long cts.proto_specific.valid = 0; 17004cca1530SAlexander Motin if (ident_buf) { 17014cca1530SAlexander Motin if (path->device->transport == XPORT_ATA) { 17024cca1530SAlexander Motin cts.xport_specific.ata.atapi = 17038e6cab54SAlexander Motin (ident_buf->config == ATA_PROTO_CFA) ? 0 : 17044cca1530SAlexander Motin ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_16) ? 16 : 17054cca1530SAlexander Motin ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) ? 12 : 0; 17064cca1530SAlexander Motin cts.xport_specific.ata.valid = CTS_ATA_VALID_ATAPI; 17074cca1530SAlexander Motin } else { 17084cca1530SAlexander Motin cts.xport_specific.sata.atapi = 17098e6cab54SAlexander Motin (ident_buf->config == ATA_PROTO_CFA) ? 0 : 17104cca1530SAlexander Motin ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_16) ? 16 : 17114cca1530SAlexander Motin ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) ? 12 : 0; 17124cca1530SAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_ATAPI; 17134cca1530SAlexander Motin } 17144cca1530SAlexander Motin } else 171552c9ce25SScott Long cts.xport_specific.valid = 0; 171652c9ce25SScott Long xpt_action((union ccb *)&cts); 171752c9ce25SScott Long } 171852c9ce25SScott Long 171952c9ce25SScott Long static void 172014f900e2SWill Andrews ata_dev_advinfo(union ccb *start_ccb) 172114f900e2SWill Andrews { 172214f900e2SWill Andrews struct cam_ed *device; 172314f900e2SWill Andrews struct ccb_dev_advinfo *cdai; 172414f900e2SWill Andrews off_t amt; 172514f900e2SWill Andrews 172614f900e2SWill Andrews start_ccb->ccb_h.status = CAM_REQ_INVALID; 172714f900e2SWill Andrews device = start_ccb->ccb_h.path->device; 172814f900e2SWill Andrews cdai = &start_ccb->cdai; 172914f900e2SWill Andrews switch(cdai->buftype) { 17303089bb2eSAlexander Motin case CDAI_TYPE_SCSI_DEVID: 17313089bb2eSAlexander Motin if (cdai->flags & CDAI_FLAG_STORE) 17323089bb2eSAlexander Motin return; 17333089bb2eSAlexander Motin cdai->provsiz = device->device_id_len; 17343089bb2eSAlexander Motin if (device->device_id_len == 0) 17353089bb2eSAlexander Motin break; 17363089bb2eSAlexander Motin amt = device->device_id_len; 17373089bb2eSAlexander Motin if (cdai->provsiz > cdai->bufsiz) 17383089bb2eSAlexander Motin amt = cdai->bufsiz; 17393089bb2eSAlexander Motin memcpy(cdai->buf, device->device_id, amt); 17403089bb2eSAlexander Motin break; 174114f900e2SWill Andrews case CDAI_TYPE_SERIAL_NUM: 174214f900e2SWill Andrews if (cdai->flags & CDAI_FLAG_STORE) 17433089bb2eSAlexander Motin return; 174414f900e2SWill Andrews cdai->provsiz = device->serial_num_len; 174514f900e2SWill Andrews if (device->serial_num_len == 0) 174614f900e2SWill Andrews break; 174714f900e2SWill Andrews amt = device->serial_num_len; 174814f900e2SWill Andrews if (cdai->provsiz > cdai->bufsiz) 174914f900e2SWill Andrews amt = cdai->bufsiz; 175014f900e2SWill Andrews memcpy(cdai->buf, device->serial_num, amt); 175114f900e2SWill Andrews break; 17523089bb2eSAlexander Motin case CDAI_TYPE_PHYS_PATH: 17533089bb2eSAlexander Motin if (cdai->flags & CDAI_FLAG_STORE) { 17543089bb2eSAlexander Motin if (device->physpath != NULL) 17553089bb2eSAlexander Motin free(device->physpath, M_CAMXPT); 17563089bb2eSAlexander Motin device->physpath_len = cdai->bufsiz; 17573089bb2eSAlexander Motin /* Clear existing buffer if zero length */ 17583089bb2eSAlexander Motin if (cdai->bufsiz == 0) 175914f900e2SWill Andrews break; 17603089bb2eSAlexander Motin device->physpath = malloc(cdai->bufsiz, M_CAMXPT, M_NOWAIT); 17613089bb2eSAlexander Motin if (device->physpath == NULL) { 17623089bb2eSAlexander Motin start_ccb->ccb_h.status = CAM_REQ_ABORTED; 17633089bb2eSAlexander Motin return; 17643089bb2eSAlexander Motin } 17653089bb2eSAlexander Motin memcpy(device->physpath, cdai->buf, cdai->bufsiz); 17663089bb2eSAlexander Motin } else { 17673089bb2eSAlexander Motin cdai->provsiz = device->physpath_len; 17683089bb2eSAlexander Motin if (device->physpath_len == 0) 17693089bb2eSAlexander Motin break; 17703089bb2eSAlexander Motin amt = device->physpath_len; 17713089bb2eSAlexander Motin if (cdai->provsiz > cdai->bufsiz) 17723089bb2eSAlexander Motin amt = cdai->bufsiz; 17733089bb2eSAlexander Motin memcpy(cdai->buf, device->physpath, amt); 17743089bb2eSAlexander Motin } 17753089bb2eSAlexander Motin break; 17763089bb2eSAlexander Motin default: 17773089bb2eSAlexander Motin return; 17783089bb2eSAlexander Motin } 17793089bb2eSAlexander Motin start_ccb->ccb_h.status = CAM_REQ_CMP; 17803089bb2eSAlexander Motin 17813089bb2eSAlexander Motin if (cdai->flags & CDAI_FLAG_STORE) { 17823089bb2eSAlexander Motin xpt_async(AC_ADVINFO_CHANGED, start_ccb->ccb_h.path, 17833089bb2eSAlexander Motin (void *)(uintptr_t)cdai->buftype); 178414f900e2SWill Andrews } 178514f900e2SWill Andrews } 178614f900e2SWill Andrews 178714f900e2SWill Andrews static void 178852c9ce25SScott Long ata_action(union ccb *start_ccb) 178952c9ce25SScott Long { 179052c9ce25SScott Long 179152c9ce25SScott Long switch (start_ccb->ccb_h.func_code) { 179252c9ce25SScott Long case XPT_SET_TRAN_SETTINGS: 179352c9ce25SScott Long { 179430a4094fSAlexander Motin ata_set_transfer_settings(&start_ccb->cts, 1795227d67aaSAlexander Motin start_ccb->ccb_h.path, 179652c9ce25SScott Long /*async_update*/FALSE); 179752c9ce25SScott Long break; 179852c9ce25SScott Long } 179952c9ce25SScott Long case XPT_SCAN_BUS: 18000e85f214SMatt Jacob case XPT_SCAN_TGT: 180152c9ce25SScott Long ata_scan_bus(start_ccb->ccb_h.path->periph, start_ccb); 180252c9ce25SScott Long break; 180352c9ce25SScott Long case XPT_SCAN_LUN: 180452c9ce25SScott Long ata_scan_lun(start_ccb->ccb_h.path->periph, 180552c9ce25SScott Long start_ccb->ccb_h.path, start_ccb->crcn.flags, 180652c9ce25SScott Long start_ccb); 180752c9ce25SScott Long break; 180852c9ce25SScott Long case XPT_GET_TRAN_SETTINGS: 180952c9ce25SScott Long { 1810b9c473b2SAlexander Motin ata_get_transfer_settings(&start_ccb->cts); 181152c9ce25SScott Long break; 181252c9ce25SScott Long } 18134cca1530SAlexander Motin case XPT_SCSI_IO: 18144cca1530SAlexander Motin { 18154cca1530SAlexander Motin struct cam_ed *device; 18164cca1530SAlexander Motin u_int maxlen = 0; 18174cca1530SAlexander Motin 18184cca1530SAlexander Motin device = start_ccb->ccb_h.path->device; 18194cca1530SAlexander Motin if (device->protocol == PROTO_SCSI && 18204cca1530SAlexander Motin (device->flags & CAM_DEV_IDENTIFY_DATA_VALID)) { 18214cca1530SAlexander Motin uint16_t p = 18224cca1530SAlexander Motin device->ident_data.config & ATA_PROTO_MASK; 18234cca1530SAlexander Motin 18248e6cab54SAlexander Motin maxlen = 18258e6cab54SAlexander Motin (device->ident_data.config == ATA_PROTO_CFA) ? 0 : 18268e6cab54SAlexander Motin (p == ATA_PROTO_ATAPI_16) ? 16 : 18274cca1530SAlexander Motin (p == ATA_PROTO_ATAPI_12) ? 12 : 0; 18284cca1530SAlexander Motin } 18294cca1530SAlexander Motin if (start_ccb->csio.cdb_len > maxlen) { 18304cca1530SAlexander Motin start_ccb->ccb_h.status = CAM_REQ_INVALID; 18314cca1530SAlexander Motin xpt_done(start_ccb); 18324cca1530SAlexander Motin break; 18334cca1530SAlexander Motin } 1834ee2b236bSAlexander Motin xpt_action_default(start_ccb); 1835ee2b236bSAlexander Motin break; 18364cca1530SAlexander Motin } 183714f900e2SWill Andrews case XPT_DEV_ADVINFO: 183814f900e2SWill Andrews { 183914f900e2SWill Andrews ata_dev_advinfo(start_ccb); 184014f900e2SWill Andrews break; 184114f900e2SWill Andrews } 184252c9ce25SScott Long default: 184352c9ce25SScott Long xpt_action_default(start_ccb); 184452c9ce25SScott Long break; 184552c9ce25SScott Long } 184652c9ce25SScott Long } 184752c9ce25SScott Long 184852c9ce25SScott Long static void 1849b9c473b2SAlexander Motin ata_get_transfer_settings(struct ccb_trans_settings *cts) 1850b9c473b2SAlexander Motin { 1851b9c473b2SAlexander Motin struct ccb_trans_settings_ata *ata; 1852b9c473b2SAlexander Motin struct ccb_trans_settings_scsi *scsi; 1853b9c473b2SAlexander Motin struct cam_ed *device; 1854b9c473b2SAlexander Motin 1855b9c473b2SAlexander Motin device = cts->ccb_h.path->device; 1856227d67aaSAlexander Motin xpt_action_default((union ccb *)cts); 1857b9c473b2SAlexander Motin 1858bc1bf6e8SAlexander Motin if (cts->protocol == PROTO_UNKNOWN || 1859bc1bf6e8SAlexander Motin cts->protocol == PROTO_UNSPECIFIED) { 1860bc1bf6e8SAlexander Motin cts->protocol = device->protocol; 1861bc1bf6e8SAlexander Motin cts->protocol_version = device->protocol_version; 1862bc1bf6e8SAlexander Motin } 1863bc1bf6e8SAlexander Motin 1864b9c473b2SAlexander Motin if (cts->protocol == PROTO_ATA) { 1865b9c473b2SAlexander Motin ata = &cts->proto_specific.ata; 1866b9c473b2SAlexander Motin if ((ata->valid & CTS_ATA_VALID_TQ) == 0) { 1867b9c473b2SAlexander Motin ata->valid |= CTS_ATA_VALID_TQ; 1868b9c473b2SAlexander Motin if (cts->type == CTS_TYPE_USER_SETTINGS || 1869b9c473b2SAlexander Motin (device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 || 1870b9c473b2SAlexander Motin (device->inq_flags & SID_CmdQue) != 0) 1871b9c473b2SAlexander Motin ata->flags |= CTS_ATA_FLAGS_TAG_ENB; 1872b9c473b2SAlexander Motin } 1873b9c473b2SAlexander Motin } 1874b9c473b2SAlexander Motin if (cts->protocol == PROTO_SCSI) { 1875b9c473b2SAlexander Motin scsi = &cts->proto_specific.scsi; 1876b9c473b2SAlexander Motin if ((scsi->valid & CTS_SCSI_VALID_TQ) == 0) { 1877b9c473b2SAlexander Motin scsi->valid |= CTS_SCSI_VALID_TQ; 1878b9c473b2SAlexander Motin if (cts->type == CTS_TYPE_USER_SETTINGS || 1879b9c473b2SAlexander Motin (device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 || 1880b9c473b2SAlexander Motin (device->inq_flags & SID_CmdQue) != 0) 1881b9c473b2SAlexander Motin scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 1882b9c473b2SAlexander Motin } 1883b9c473b2SAlexander Motin } 1884bc1bf6e8SAlexander Motin 1885bc1bf6e8SAlexander Motin if (cts->transport == XPORT_UNKNOWN || 1886bc1bf6e8SAlexander Motin cts->transport == XPORT_UNSPECIFIED) { 1887bc1bf6e8SAlexander Motin cts->transport = device->transport; 1888bc1bf6e8SAlexander Motin cts->transport_version = device->transport_version; 1889bc1bf6e8SAlexander Motin } 1890b9c473b2SAlexander Motin } 1891b9c473b2SAlexander Motin 1892b9c473b2SAlexander Motin static void 1893227d67aaSAlexander Motin ata_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_path *path, 189452c9ce25SScott Long int async_update) 189552c9ce25SScott Long { 189652c9ce25SScott Long struct ccb_pathinq cpi; 1897b9c473b2SAlexander Motin struct ccb_trans_settings_ata *ata; 189852c9ce25SScott Long struct ccb_trans_settings_scsi *scsi; 1899b9c473b2SAlexander Motin struct ata_params *ident_data; 190052c9ce25SScott Long struct scsi_inquiry_data *inq_data; 1901227d67aaSAlexander Motin struct cam_ed *device; 190252c9ce25SScott Long 1903227d67aaSAlexander Motin if (path == NULL || (device = path->device) == NULL) { 190452c9ce25SScott Long cts->ccb_h.status = CAM_PATH_INVALID; 190552c9ce25SScott Long xpt_done((union ccb *)cts); 190652c9ce25SScott Long return; 190752c9ce25SScott Long } 190852c9ce25SScott Long 190952c9ce25SScott Long if (cts->protocol == PROTO_UNKNOWN 191052c9ce25SScott Long || cts->protocol == PROTO_UNSPECIFIED) { 191152c9ce25SScott Long cts->protocol = device->protocol; 191252c9ce25SScott Long cts->protocol_version = device->protocol_version; 191352c9ce25SScott Long } 191452c9ce25SScott Long 191552c9ce25SScott Long if (cts->protocol_version == PROTO_VERSION_UNKNOWN 191652c9ce25SScott Long || cts->protocol_version == PROTO_VERSION_UNSPECIFIED) 191752c9ce25SScott Long cts->protocol_version = device->protocol_version; 191852c9ce25SScott Long 191952c9ce25SScott Long if (cts->protocol != device->protocol) { 1920227d67aaSAlexander Motin xpt_print(path, "Uninitialized Protocol %x:%x?\n", 192152c9ce25SScott Long cts->protocol, device->protocol); 192252c9ce25SScott Long cts->protocol = device->protocol; 192352c9ce25SScott Long } 192452c9ce25SScott Long 192552c9ce25SScott Long if (cts->protocol_version > device->protocol_version) { 192652c9ce25SScott Long if (bootverbose) { 1927227d67aaSAlexander Motin xpt_print(path, "Down reving Protocol " 192852c9ce25SScott Long "Version from %d to %d?\n", cts->protocol_version, 192952c9ce25SScott Long device->protocol_version); 193052c9ce25SScott Long } 193152c9ce25SScott Long cts->protocol_version = device->protocol_version; 193252c9ce25SScott Long } 193352c9ce25SScott Long 193452c9ce25SScott Long if (cts->transport == XPORT_UNKNOWN 193552c9ce25SScott Long || cts->transport == XPORT_UNSPECIFIED) { 193652c9ce25SScott Long cts->transport = device->transport; 193752c9ce25SScott Long cts->transport_version = device->transport_version; 193852c9ce25SScott Long } 193952c9ce25SScott Long 194052c9ce25SScott Long if (cts->transport_version == XPORT_VERSION_UNKNOWN 194152c9ce25SScott Long || cts->transport_version == XPORT_VERSION_UNSPECIFIED) 194252c9ce25SScott Long cts->transport_version = device->transport_version; 194352c9ce25SScott Long 194452c9ce25SScott Long if (cts->transport != device->transport) { 1945227d67aaSAlexander Motin xpt_print(path, "Uninitialized Transport %x:%x?\n", 194652c9ce25SScott Long cts->transport, device->transport); 194752c9ce25SScott Long cts->transport = device->transport; 194852c9ce25SScott Long } 194952c9ce25SScott Long 195052c9ce25SScott Long if (cts->transport_version > device->transport_version) { 195152c9ce25SScott Long if (bootverbose) { 1952227d67aaSAlexander Motin xpt_print(path, "Down reving Transport " 195352c9ce25SScott Long "Version from %d to %d?\n", cts->transport_version, 195452c9ce25SScott Long device->transport_version); 195552c9ce25SScott Long } 195652c9ce25SScott Long cts->transport_version = device->transport_version; 195752c9ce25SScott Long } 195852c9ce25SScott Long 1959b9c473b2SAlexander Motin ident_data = &device->ident_data; 196052c9ce25SScott Long inq_data = &device->inq_data; 1961b9c473b2SAlexander Motin if (cts->protocol == PROTO_ATA) 1962b9c473b2SAlexander Motin ata = &cts->proto_specific.ata; 1963b9c473b2SAlexander Motin else 1964b9c473b2SAlexander Motin ata = NULL; 1965b9c473b2SAlexander Motin if (cts->protocol == PROTO_SCSI) 196652c9ce25SScott Long scsi = &cts->proto_specific.scsi; 1967b9c473b2SAlexander Motin else 1968b9c473b2SAlexander Motin scsi = NULL; 1969762a7f4fSWarner Losh xpt_path_inq(&cpi, path); 197052c9ce25SScott Long 1971b9c473b2SAlexander Motin /* Sanity checking */ 197252c9ce25SScott Long if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0 1973b9c473b2SAlexander Motin || (ata && (ident_data->satacapabilities & ATA_SUPPORT_NCQ) == 0) 1974b9c473b2SAlexander Motin || (scsi && (INQ_DATA_TQ_ENABLED(inq_data)) == 0) 197552c9ce25SScott Long || (device->queue_flags & SCP_QUEUE_DQUE) != 0 197652c9ce25SScott Long || (device->mintags == 0)) { 197752c9ce25SScott Long /* 197852c9ce25SScott Long * Can't tag on hardware that doesn't support tags, 197952c9ce25SScott Long * doesn't have it enabled, or has broken tag support. 198052c9ce25SScott Long */ 1981b9c473b2SAlexander Motin if (ata) 1982b9c473b2SAlexander Motin ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB; 1983b9c473b2SAlexander Motin if (scsi) 198452c9ce25SScott Long scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 198552c9ce25SScott Long } 198652c9ce25SScott Long 1987b9c473b2SAlexander Motin /* Start/stop tags use. */ 1988b9c473b2SAlexander Motin if (cts->type == CTS_TYPE_CURRENT_SETTINGS && 1989b9c473b2SAlexander Motin ((ata && (ata->valid & CTS_ATA_VALID_TQ) != 0) || 1990b9c473b2SAlexander Motin (scsi && (scsi->valid & CTS_SCSI_VALID_TQ) != 0))) { 1991b9c473b2SAlexander Motin int nowt, newt = 0; 199252c9ce25SScott Long 1993b9c473b2SAlexander Motin nowt = ((device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 || 1994b9c473b2SAlexander Motin (device->inq_flags & SID_CmdQue) != 0); 1995b9c473b2SAlexander Motin if (ata) 1996b9c473b2SAlexander Motin newt = (ata->flags & CTS_ATA_FLAGS_TAG_ENB) != 0; 1997b9c473b2SAlexander Motin if (scsi) 1998b9c473b2SAlexander Motin newt = (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0; 199952c9ce25SScott Long 2000b9c473b2SAlexander Motin if (newt && !nowt) { 200152c9ce25SScott Long /* 200252c9ce25SScott Long * Delay change to use tags until after a 200352c9ce25SScott Long * few commands have gone to this device so 200452c9ce25SScott Long * the controller has time to perform transfer 200552c9ce25SScott Long * negotiations without tagged messages getting 200652c9ce25SScott Long * in the way. 200752c9ce25SScott Long */ 200852c9ce25SScott Long device->tag_delay_count = CAM_TAG_DELAY_COUNT; 200952c9ce25SScott Long device->flags |= CAM_DEV_TAG_AFTER_COUNT; 2010b9c473b2SAlexander Motin } else if (nowt && !newt) 2011227d67aaSAlexander Motin xpt_stop_tags(path); 201252c9ce25SScott Long } 2013b9c473b2SAlexander Motin 201452c9ce25SScott Long if (async_update == FALSE) 2015227d67aaSAlexander Motin xpt_action_default((union ccb *)cts); 201652c9ce25SScott Long } 201752c9ce25SScott Long 201852c9ce25SScott Long /* 201952c9ce25SScott Long * Handle any per-device event notifications that require action by the XPT. 202052c9ce25SScott Long */ 202152c9ce25SScott Long static void 202252c9ce25SScott Long ata_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target, 202352c9ce25SScott Long struct cam_ed *device, void *async_arg) 202452c9ce25SScott Long { 202552c9ce25SScott Long cam_status status; 202652c9ce25SScott Long struct cam_path newpath; 202752c9ce25SScott Long 202852c9ce25SScott Long /* 202952c9ce25SScott Long * We only need to handle events for real devices. 203052c9ce25SScott Long */ 203152c9ce25SScott Long if (target->target_id == CAM_TARGET_WILDCARD 203252c9ce25SScott Long || device->lun_id == CAM_LUN_WILDCARD) 203352c9ce25SScott Long return; 203452c9ce25SScott Long 203552c9ce25SScott Long /* 203652c9ce25SScott Long * We need our own path with wildcards expanded to 203752c9ce25SScott Long * handle certain types of events. 203852c9ce25SScott Long */ 203952c9ce25SScott Long if ((async_code == AC_SENT_BDR) 204052c9ce25SScott Long || (async_code == AC_BUS_RESET) 204152c9ce25SScott Long || (async_code == AC_INQ_CHANGED)) 204252c9ce25SScott Long status = xpt_compile_path(&newpath, NULL, 204352c9ce25SScott Long bus->path_id, 204452c9ce25SScott Long target->target_id, 204552c9ce25SScott Long device->lun_id); 204652c9ce25SScott Long else 204752c9ce25SScott Long status = CAM_REQ_CMP_ERR; 204852c9ce25SScott Long 204952c9ce25SScott Long if (status == CAM_REQ_CMP) { 205052c9ce25SScott Long if (async_code == AC_INQ_CHANGED) { 205152c9ce25SScott Long /* 205252c9ce25SScott Long * We've sent a start unit command, or 205352c9ce25SScott Long * something similar to a device that 205452c9ce25SScott Long * may have caused its inquiry data to 205552c9ce25SScott Long * change. So we re-scan the device to 205652c9ce25SScott Long * refresh the inquiry data for it. 205752c9ce25SScott Long */ 205852c9ce25SScott Long ata_scan_lun(newpath.periph, &newpath, 205952c9ce25SScott Long CAM_EXPECT_INQ_CHANGE, NULL); 206083c5d981SAlexander Motin } else { 206183c5d981SAlexander Motin /* We need to reinitialize device after reset. */ 206283c5d981SAlexander Motin ata_scan_lun(newpath.periph, &newpath, 206383c5d981SAlexander Motin 0, NULL); 206452c9ce25SScott Long } 206552c9ce25SScott Long xpt_release_path(&newpath); 2066f98d7a47SAlexander Motin } else if (async_code == AC_LOST_DEVICE && 2067f98d7a47SAlexander Motin (device->flags & CAM_DEV_UNCONFIGURED) == 0) { 206852c9ce25SScott Long device->flags |= CAM_DEV_UNCONFIGURED; 2069f98d7a47SAlexander Motin xpt_release_device(device); 207052c9ce25SScott Long } else if (async_code == AC_TRANSFER_NEG) { 207152c9ce25SScott Long struct ccb_trans_settings *settings; 2072227d67aaSAlexander Motin struct cam_path path; 207352c9ce25SScott Long 207452c9ce25SScott Long settings = (struct ccb_trans_settings *)async_arg; 2075227d67aaSAlexander Motin xpt_compile_path(&path, NULL, bus->path_id, target->target_id, 2076227d67aaSAlexander Motin device->lun_id); 2077227d67aaSAlexander Motin ata_set_transfer_settings(settings, &path, 207852c9ce25SScott Long /*async_update*/TRUE); 2079227d67aaSAlexander Motin xpt_release_path(&path); 208052c9ce25SScott Long } 208152c9ce25SScott Long } 208252c9ce25SScott Long 208357079b17SAlexander Motin static void 20845d01277fSScott Long _ata_announce_periph(struct cam_periph *periph, struct ccb_trans_settings *cts, u_int *speed) 208557079b17SAlexander Motin { 208657079b17SAlexander Motin struct ccb_pathinq cpi; 208757079b17SAlexander Motin struct cam_path *path = periph->path; 208857079b17SAlexander Motin 2089227d67aaSAlexander Motin cam_periph_assert(periph, MA_OWNED); 209057079b17SAlexander Motin 20915d01277fSScott Long xpt_setup_ccb(&cts->ccb_h, path, CAM_PRIORITY_NORMAL); 20925d01277fSScott Long cts->ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 20935d01277fSScott Long cts->type = CTS_TYPE_CURRENT_SETTINGS; 20945d01277fSScott Long xpt_action((union ccb*)cts); 20955d01277fSScott Long if ((cts->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 209657079b17SAlexander Motin return; 209757079b17SAlexander Motin /* Ask the SIM for its base transfer speed */ 2098762a7f4fSWarner Losh xpt_path_inq(&cpi, path); 209957079b17SAlexander Motin /* Report connection speed */ 21005d01277fSScott Long *speed = cpi.base_transfer_speed; 21015d01277fSScott Long if (cts->transport == XPORT_ATA) { 2102b9c473b2SAlexander Motin struct ccb_trans_settings_pata *pata = 21035d01277fSScott Long &cts->xport_specific.ata; 210457079b17SAlexander Motin 2105b9c473b2SAlexander Motin if (pata->valid & CTS_ATA_VALID_MODE) 21065d01277fSScott Long *speed = ata_mode2speed(pata->mode); 210757079b17SAlexander Motin } 21085d01277fSScott Long if (cts->transport == XPORT_SATA) { 210957079b17SAlexander Motin struct ccb_trans_settings_sata *sata = 21105d01277fSScott Long &cts->xport_specific.sata; 211157079b17SAlexander Motin 211257079b17SAlexander Motin if (sata->valid & CTS_SATA_VALID_REVISION) 21135d01277fSScott Long *speed = ata_revision2speed(sata->revision); 211457079b17SAlexander Motin } 21155d01277fSScott Long } 21165d01277fSScott Long 21175d01277fSScott Long static void 21185d01277fSScott Long ata_announce_periph(struct cam_periph *periph) 21195d01277fSScott Long { 21205d01277fSScott Long struct ccb_trans_settings cts; 21215d01277fSScott Long u_int speed, mb; 21225d01277fSScott Long 21235d01277fSScott Long _ata_announce_periph(periph, &cts, &speed); 21245d01277fSScott Long if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 21255d01277fSScott Long return; 21265d01277fSScott Long 212757079b17SAlexander Motin mb = speed / 1000; 212857079b17SAlexander Motin if (mb > 0) 212957079b17SAlexander Motin printf("%s%d: %d.%03dMB/s transfers", 213057079b17SAlexander Motin periph->periph_name, periph->unit_number, 213157079b17SAlexander Motin mb, speed % 1000); 213257079b17SAlexander Motin else 213357079b17SAlexander Motin printf("%s%d: %dKB/s transfers", periph->periph_name, 213457079b17SAlexander Motin periph->unit_number, speed); 213557079b17SAlexander Motin /* Report additional information about connection */ 21365d01277fSScott Long if (cts.transport == XPORT_ATA) { 2137b9c473b2SAlexander Motin struct ccb_trans_settings_pata *pata = 213857079b17SAlexander Motin &cts.xport_specific.ata; 213957079b17SAlexander Motin 214057079b17SAlexander Motin printf(" ("); 2141b9c473b2SAlexander Motin if (pata->valid & CTS_ATA_VALID_MODE) 2142b9c473b2SAlexander Motin printf("%s, ", ata_mode2string(pata->mode)); 2143b9c473b2SAlexander Motin if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0) 2144b9c473b2SAlexander Motin printf("ATAPI %dbytes, ", pata->atapi); 2145b9c473b2SAlexander Motin if (pata->valid & CTS_ATA_VALID_BYTECOUNT) 2146b9c473b2SAlexander Motin printf("PIO %dbytes", pata->bytecount); 214757079b17SAlexander Motin printf(")"); 214857079b17SAlexander Motin } 21495d01277fSScott Long if (cts.transport == XPORT_SATA) { 215057079b17SAlexander Motin struct ccb_trans_settings_sata *sata = 215157079b17SAlexander Motin &cts.xport_specific.sata; 215257079b17SAlexander Motin 215357079b17SAlexander Motin printf(" ("); 215457079b17SAlexander Motin if (sata->valid & CTS_SATA_VALID_REVISION) 215557079b17SAlexander Motin printf("SATA %d.x, ", sata->revision); 215657079b17SAlexander Motin else 215757079b17SAlexander Motin printf("SATA, "); 215857079b17SAlexander Motin if (sata->valid & CTS_SATA_VALID_MODE) 215957079b17SAlexander Motin printf("%s, ", ata_mode2string(sata->mode)); 216057079b17SAlexander Motin if ((sata->valid & CTS_ATA_VALID_ATAPI) && sata->atapi != 0) 216157079b17SAlexander Motin printf("ATAPI %dbytes, ", sata->atapi); 216257079b17SAlexander Motin if (sata->valid & CTS_SATA_VALID_BYTECOUNT) 216357079b17SAlexander Motin printf("PIO %dbytes", sata->bytecount); 216457079b17SAlexander Motin printf(")"); 216557079b17SAlexander Motin } 216657079b17SAlexander Motin printf("\n"); 216757079b17SAlexander Motin } 216808f13879SWarner Losh 216908f13879SWarner Losh static void 21705d01277fSScott Long ata_announce_periph_sbuf(struct cam_periph *periph, struct sbuf *sb) 21715d01277fSScott Long { 21725d01277fSScott Long struct ccb_trans_settings cts; 21735d01277fSScott Long u_int speed, mb; 21745d01277fSScott Long 21755d01277fSScott Long _ata_announce_periph(periph, &cts, &speed); 21765d01277fSScott Long if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 21775d01277fSScott Long return; 21785d01277fSScott Long 21795d01277fSScott Long mb = speed / 1000; 21805d01277fSScott Long if (mb > 0) 21815d01277fSScott Long sbuf_printf(sb, "%s%d: %d.%03dMB/s transfers", 21825d01277fSScott Long periph->periph_name, periph->unit_number, 21835d01277fSScott Long mb, speed % 1000); 21845d01277fSScott Long else 21855d01277fSScott Long sbuf_printf(sb, "%s%d: %dKB/s transfers", periph->periph_name, 21865d01277fSScott Long periph->unit_number, speed); 21875d01277fSScott Long /* Report additional information about connection */ 21885d01277fSScott Long if (cts.transport == XPORT_ATA) { 21895d01277fSScott Long struct ccb_trans_settings_pata *pata = 21905d01277fSScott Long &cts.xport_specific.ata; 21915d01277fSScott Long 21925d01277fSScott Long sbuf_printf(sb, " ("); 21935d01277fSScott Long if (pata->valid & CTS_ATA_VALID_MODE) 21945d01277fSScott Long sbuf_printf(sb, "%s, ", ata_mode2string(pata->mode)); 21955d01277fSScott Long if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0) 21965d01277fSScott Long sbuf_printf(sb, "ATAPI %dbytes, ", pata->atapi); 21975d01277fSScott Long if (pata->valid & CTS_ATA_VALID_BYTECOUNT) 21985d01277fSScott Long sbuf_printf(sb, "PIO %dbytes", pata->bytecount); 21995d01277fSScott Long sbuf_printf(sb, ")"); 22005d01277fSScott Long } 22015d01277fSScott Long if (cts.transport == XPORT_SATA) { 22025d01277fSScott Long struct ccb_trans_settings_sata *sata = 22035d01277fSScott Long &cts.xport_specific.sata; 22045d01277fSScott Long 22055d01277fSScott Long sbuf_printf(sb, " ("); 22065d01277fSScott Long if (sata->valid & CTS_SATA_VALID_REVISION) 22075d01277fSScott Long sbuf_printf(sb, "SATA %d.x, ", sata->revision); 22085d01277fSScott Long else 22095d01277fSScott Long sbuf_printf(sb, "SATA, "); 22105d01277fSScott Long if (sata->valid & CTS_SATA_VALID_MODE) 22115d01277fSScott Long sbuf_printf(sb, "%s, ", ata_mode2string(sata->mode)); 22125d01277fSScott Long if ((sata->valid & CTS_ATA_VALID_ATAPI) && sata->atapi != 0) 22135d01277fSScott Long sbuf_printf(sb, "ATAPI %dbytes, ", sata->atapi); 22145d01277fSScott Long if (sata->valid & CTS_SATA_VALID_BYTECOUNT) 22155d01277fSScott Long sbuf_printf(sb, "PIO %dbytes", sata->bytecount); 22165d01277fSScott Long sbuf_printf(sb, ")"); 22175d01277fSScott Long } 22185d01277fSScott Long sbuf_printf(sb, "\n"); 22195d01277fSScott Long } 22205d01277fSScott Long 22215d01277fSScott Long static void 22225d01277fSScott Long ata_proto_announce_sbuf(struct cam_ed *device, struct sbuf *sb) 22235d01277fSScott Long { 22245d01277fSScott Long ata_print_ident_sbuf(&device->ident_data, sb); 22255d01277fSScott Long } 22265d01277fSScott Long 22275d01277fSScott Long static void 222808f13879SWarner Losh ata_proto_announce(struct cam_ed *device) 222908f13879SWarner Losh { 223008f13879SWarner Losh ata_print_ident(&device->ident_data); 223108f13879SWarner Losh } 223208f13879SWarner Losh 223308f13879SWarner Losh static void 223408f13879SWarner Losh ata_proto_denounce(struct cam_ed *device) 223508f13879SWarner Losh { 223608f13879SWarner Losh ata_print_ident_short(&device->ident_data); 223708f13879SWarner Losh } 223808f13879SWarner Losh 223908f13879SWarner Losh static void 22405d01277fSScott Long ata_proto_denounce_sbuf(struct cam_ed *device, struct sbuf *sb) 22415d01277fSScott Long { 22425d01277fSScott Long ata_print_ident_short_sbuf(&device->ident_data, sb); 22435d01277fSScott Long } 22445d01277fSScott Long 22455d01277fSScott Long static void 22465d01277fSScott Long semb_proto_announce_sbuf(struct cam_ed *device, struct sbuf *sb) 22475d01277fSScott Long { 22485d01277fSScott Long semb_print_ident_sbuf((struct sep_identify_data *)&device->ident_data, sb); 22495d01277fSScott Long } 22505d01277fSScott Long 22515d01277fSScott Long static void 225208f13879SWarner Losh semb_proto_announce(struct cam_ed *device) 225308f13879SWarner Losh { 225408f13879SWarner Losh semb_print_ident((struct sep_identify_data *)&device->ident_data); 225508f13879SWarner Losh } 225608f13879SWarner Losh 225708f13879SWarner Losh static void 225808f13879SWarner Losh semb_proto_denounce(struct cam_ed *device) 225908f13879SWarner Losh { 226008f13879SWarner Losh semb_print_ident_short((struct sep_identify_data *)&device->ident_data); 226108f13879SWarner Losh } 226208f13879SWarner Losh 226308f13879SWarner Losh static void 22645d01277fSScott Long semb_proto_denounce_sbuf(struct cam_ed *device, struct sbuf *sb) 22655d01277fSScott Long { 22665d01277fSScott Long semb_print_ident_short_sbuf((struct sep_identify_data *)&device->ident_data, sb); 22675d01277fSScott Long } 22685d01277fSScott Long 22695d01277fSScott Long static void 227008f13879SWarner Losh ata_proto_debug_out(union ccb *ccb) 227108f13879SWarner Losh { 227208f13879SWarner Losh char cdb_str[(sizeof(struct ata_cmd) * 3) + 1]; 227308f13879SWarner Losh 227408f13879SWarner Losh if (ccb->ccb_h.func_code != XPT_ATA_IO) 227508f13879SWarner Losh return; 227608f13879SWarner Losh 227708f13879SWarner Losh CAM_DEBUG(ccb->ccb_h.path, 227808f13879SWarner Losh CAM_DEBUG_CDB,("%s. ACB: %s\n", ata_op_string(&ccb->ataio.cmd), 227908f13879SWarner Losh ata_cmd_string(&ccb->ataio.cmd, cdb_str, sizeof(cdb_str)))); 228008f13879SWarner Losh } 2281