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/sbuf.h> 4352c9ce25SScott Long 44a11463fdSSepherosa Ziehau #include <sys/eventhandler.h> 4552c9ce25SScott Long #include <sys/lock.h> 4652c9ce25SScott Long #include <sys/mutex.h> 4752c9ce25SScott Long #include <sys/sysctl.h> 4852c9ce25SScott Long 4952c9ce25SScott Long #include <cam/cam.h> 5052c9ce25SScott Long #include <cam/cam_ccb.h> 5152c9ce25SScott Long #include <cam/cam_queue.h> 5252c9ce25SScott Long #include <cam/cam_periph.h> 5352c9ce25SScott Long #include <cam/cam_sim.h> 5452c9ce25SScott Long #include <cam/cam_xpt.h> 5552c9ce25SScott Long #include <cam/cam_xpt_sim.h> 5652c9ce25SScott Long #include <cam/cam_xpt_periph.h> 5752c9ce25SScott Long #include <cam/cam_xpt_internal.h> 5852c9ce25SScott Long #include <cam/cam_debug.h> 5952c9ce25SScott Long 6052c9ce25SScott Long #include <cam/scsi/scsi_all.h> 6152c9ce25SScott Long #include <cam/scsi/scsi_message.h> 6252c9ce25SScott Long #include <cam/ata/ata_all.h> 6352c9ce25SScott Long #include <machine/stdarg.h> /* for xpt_print below */ 6452c9ce25SScott Long #include "opt_cam.h" 6552c9ce25SScott Long 6630a4094fSAlexander Motin struct ata_quirk_entry { 6752c9ce25SScott Long struct scsi_inquiry_pattern inq_pat; 6852c9ce25SScott Long u_int8_t quirks; 6930a4094fSAlexander Motin #define CAM_QUIRK_MAXTAGS 0x01 707dc3213dSAlexander Motin u_int mintags; 7152c9ce25SScott Long u_int maxtags; 7252c9ce25SScott Long }; 7352c9ce25SScott Long 740f280cbdSWarner Losh static periph_init_t aprobe_periph_init; 7552c9ce25SScott Long 760f280cbdSWarner Losh static struct periph_driver aprobe_driver = 7752c9ce25SScott Long { 780f280cbdSWarner Losh aprobe_periph_init, "aprobe", 790f280cbdSWarner Losh TAILQ_HEAD_INITIALIZER(aprobe_driver.units), /* generation */ 0, 801e637ba6SAlexander Motin CAM_PERIPH_DRV_EARLY 8152c9ce25SScott Long }; 8252c9ce25SScott Long 830f280cbdSWarner Losh PERIPHDRIVER_DECLARE(aprobe, aprobe_driver); 8452c9ce25SScott Long 8552c9ce25SScott Long typedef enum { 8652c9ce25SScott Long PROBE_RESET, 8752c9ce25SScott Long PROBE_IDENTIFY, 884ef08dc5SAlexander Motin PROBE_SPINUP, 8952c9ce25SScott Long PROBE_SETMODE, 90da6808c1SAlexander Motin PROBE_SETPM, 91da6808c1SAlexander Motin PROBE_SETAPST, 92da6808c1SAlexander Motin PROBE_SETDMAAA, 938d169381SAlexander Motin PROBE_SETAN, 941e637ba6SAlexander Motin PROBE_SET_MULTI, 9552c9ce25SScott Long PROBE_INQUIRY, 9652c9ce25SScott Long PROBE_FULL_INQUIRY, 9752c9ce25SScott Long PROBE_PM_PID, 9852c9ce25SScott Long PROBE_PM_PRV, 993089bb2eSAlexander Motin PROBE_IDENTIFY_SES, 1003089bb2eSAlexander Motin PROBE_IDENTIFY_SAFTE, 101a4d953c4SAlexander Motin PROBE_DONE, 10252c9ce25SScott Long PROBE_INVALID 1030f280cbdSWarner Losh } aprobe_action; 10452c9ce25SScott Long 10552c9ce25SScott Long static char *probe_action_text[] = { 10652c9ce25SScott Long "PROBE_RESET", 10752c9ce25SScott Long "PROBE_IDENTIFY", 1084ef08dc5SAlexander Motin "PROBE_SPINUP", 10952c9ce25SScott Long "PROBE_SETMODE", 110da6808c1SAlexander Motin "PROBE_SETPM", 111da6808c1SAlexander Motin "PROBE_SETAPST", 112da6808c1SAlexander Motin "PROBE_SETDMAAA", 1138d169381SAlexander Motin "PROBE_SETAN", 1141e637ba6SAlexander Motin "PROBE_SET_MULTI", 11552c9ce25SScott Long "PROBE_INQUIRY", 11652c9ce25SScott Long "PROBE_FULL_INQUIRY", 11752c9ce25SScott Long "PROBE_PM_PID", 11852c9ce25SScott Long "PROBE_PM_PRV", 1193089bb2eSAlexander Motin "PROBE_IDENTIFY_SES", 1203089bb2eSAlexander Motin "PROBE_IDENTIFY_SAFTE", 121a4d953c4SAlexander Motin "PROBE_DONE", 12252c9ce25SScott Long "PROBE_INVALID" 12352c9ce25SScott Long }; 12452c9ce25SScott Long 12552c9ce25SScott Long #define PROBE_SET_ACTION(softc, newaction) \ 12652c9ce25SScott Long do { \ 12752c9ce25SScott Long char **text; \ 12852c9ce25SScott Long text = probe_action_text; \ 129a4d953c4SAlexander Motin CAM_DEBUG((softc)->periph->path, CAM_DEBUG_PROBE, \ 13052c9ce25SScott Long ("Probe %s to %s\n", text[(softc)->action], \ 13152c9ce25SScott Long text[(newaction)])); \ 13252c9ce25SScott Long (softc)->action = (newaction); \ 13352c9ce25SScott Long } while(0) 13452c9ce25SScott Long 13552c9ce25SScott Long typedef enum { 13652c9ce25SScott Long PROBE_NO_ANNOUNCE = 0x04 1370f280cbdSWarner Losh } aprobe_flags; 13852c9ce25SScott Long 13952c9ce25SScott Long typedef struct { 14052c9ce25SScott Long TAILQ_HEAD(, ccb_hdr) request_ccbs; 141a9b8edb1SAlexander Motin struct ata_params ident_data; 1420f280cbdSWarner Losh aprobe_action action; 1430f280cbdSWarner Losh aprobe_flags flags; 14452c9ce25SScott Long uint32_t pm_pid; 14552c9ce25SScott Long uint32_t pm_prv; 14683c5d981SAlexander Motin int restart; 1474ef08dc5SAlexander Motin int spinup; 14825a519a9SAlexander Motin int faults; 149da6808c1SAlexander Motin u_int caps; 15052c9ce25SScott Long struct cam_periph *periph; 15152c9ce25SScott Long } probe_softc; 15252c9ce25SScott Long 15330a4094fSAlexander Motin static struct ata_quirk_entry ata_quirk_table[] = 15452c9ce25SScott Long { 15552c9ce25SScott Long { 15652c9ce25SScott Long /* Default tagged queuing parameters for all devices */ 15752c9ce25SScott Long { 15852c9ce25SScott Long T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED, 15952c9ce25SScott Long /*vendor*/"*", /*product*/"*", /*revision*/"*" 16052c9ce25SScott Long }, 1617dc3213dSAlexander Motin /*quirks*/0, /*mintags*/0, /*maxtags*/0 16252c9ce25SScott Long }, 16352c9ce25SScott Long }; 16452c9ce25SScott Long 1650f280cbdSWarner Losh static cam_status aproberegister(struct cam_periph *periph, void *arg); 1660f280cbdSWarner Losh static void aprobeschedule(struct cam_periph *probe_periph); 1670f280cbdSWarner Losh static void aprobestart(struct cam_periph *periph, union ccb *start_ccb); 1680f280cbdSWarner Losh static void aproberequestdefaultnegotiation(struct cam_periph *periph); 1690f280cbdSWarner Losh static void aprobedone(struct cam_periph *periph, union ccb *done_ccb); 1700f280cbdSWarner Losh static void aprobecleanup(struct cam_periph *periph); 17130a4094fSAlexander Motin static void ata_find_quirk(struct cam_ed *device); 17252c9ce25SScott Long static void ata_scan_bus(struct cam_periph *periph, union ccb *ccb); 17352c9ce25SScott Long static void ata_scan_lun(struct cam_periph *periph, 17452c9ce25SScott Long struct cam_path *path, cam_flags flags, 17552c9ce25SScott Long union ccb *ccb); 1760f280cbdSWarner Losh static void axptscandone(struct cam_periph *periph, union ccb *done_ccb); 17752c9ce25SScott Long static struct cam_ed * 17852c9ce25SScott Long ata_alloc_device(struct cam_eb *bus, struct cam_et *target, 17952c9ce25SScott Long lun_id_t lun_id); 18052c9ce25SScott Long static void ata_device_transport(struct cam_path *path); 181b9c473b2SAlexander Motin static void ata_get_transfer_settings(struct ccb_trans_settings *cts); 18230a4094fSAlexander Motin static void ata_set_transfer_settings(struct ccb_trans_settings *cts, 183227d67aaSAlexander Motin struct cam_path *path, 18452c9ce25SScott Long int async_update); 18552c9ce25SScott Long static void ata_dev_async(u_int32_t async_code, 18652c9ce25SScott Long struct cam_eb *bus, 18752c9ce25SScott Long struct cam_et *target, 18852c9ce25SScott Long struct cam_ed *device, 18952c9ce25SScott Long void *async_arg); 19052c9ce25SScott Long static void ata_action(union ccb *start_ccb); 19157079b17SAlexander Motin static void ata_announce_periph(struct cam_periph *periph); 1925d01277fSScott Long static void ata_announce_periph_sbuf(struct cam_periph *periph, struct sbuf *sb); 19308f13879SWarner Losh static void ata_proto_announce(struct cam_ed *device); 1945d01277fSScott Long static void ata_proto_announce_sbuf(struct cam_ed *device, struct sbuf *sb); 19508f13879SWarner Losh static void ata_proto_denounce(struct cam_ed *device); 1965d01277fSScott Long static void ata_proto_denounce_sbuf(struct cam_ed *device, struct sbuf *sb); 19708f13879SWarner Losh static void ata_proto_debug_out(union ccb *ccb); 19808f13879SWarner Losh static void semb_proto_announce(struct cam_ed *device); 1995d01277fSScott Long static void semb_proto_announce_sbuf(struct cam_ed *device, struct sbuf *sb); 20008f13879SWarner Losh static void semb_proto_denounce(struct cam_ed *device); 2015d01277fSScott Long static void semb_proto_denounce_sbuf(struct cam_ed *device, struct sbuf *sb); 20252c9ce25SScott Long 2032121d8a5SAlexander Motin static int ata_dma = 1; 2042121d8a5SAlexander Motin static int atapi_dma = 1; 2052121d8a5SAlexander Motin 2062121d8a5SAlexander Motin TUNABLE_INT("hw.ata.ata_dma", &ata_dma); 2072121d8a5SAlexander Motin TUNABLE_INT("hw.ata.atapi_dma", &atapi_dma); 2082121d8a5SAlexander Motin 209ded2b706SWarner Losh static struct xpt_xport_ops ata_xport_ops = { 21052c9ce25SScott Long .alloc_device = ata_alloc_device, 21152c9ce25SScott Long .action = ata_action, 21252c9ce25SScott Long .async = ata_dev_async, 21357079b17SAlexander Motin .announce = ata_announce_periph, 2145d01277fSScott Long .announce_sbuf = ata_announce_periph_sbuf, 21552c9ce25SScott Long }; 216ded2b706SWarner Losh #define ATA_XPT_XPORT(x, X) \ 217ded2b706SWarner Losh static struct xpt_xport ata_xport_ ## x = { \ 218ded2b706SWarner Losh .xport = XPORT_ ## X, \ 219ded2b706SWarner Losh .name = #x, \ 220ded2b706SWarner Losh .ops = &ata_xport_ops, \ 221ded2b706SWarner Losh }; \ 222ded2b706SWarner Losh CAM_XPT_XPORT(ata_xport_ ## x); 22352c9ce25SScott Long 224ded2b706SWarner Losh ATA_XPT_XPORT(ata, ATA); 225ded2b706SWarner Losh ATA_XPT_XPORT(sata, SATA); 226ded2b706SWarner Losh 227ded2b706SWarner Losh #undef ATA_XPORT_XPORT 22852c9ce25SScott Long 22908f13879SWarner Losh static struct xpt_proto_ops ata_proto_ops_ata = { 23008f13879SWarner Losh .announce = ata_proto_announce, 2315d01277fSScott Long .announce_sbuf = ata_proto_announce_sbuf, 23208f13879SWarner Losh .denounce = ata_proto_denounce, 2335d01277fSScott Long .denounce_sbuf = ata_proto_denounce_sbuf, 23408f13879SWarner Losh .debug_out = ata_proto_debug_out, 23508f13879SWarner Losh }; 23608f13879SWarner Losh static struct xpt_proto ata_proto_ata = { 23708f13879SWarner Losh .proto = PROTO_ATA, 23808f13879SWarner Losh .name = "ata", 23908f13879SWarner Losh .ops = &ata_proto_ops_ata, 24008f13879SWarner Losh }; 24108f13879SWarner Losh 24208f13879SWarner Losh static struct xpt_proto_ops ata_proto_ops_satapm = { 24308f13879SWarner Losh .announce = ata_proto_announce, 2445d01277fSScott Long .announce_sbuf = ata_proto_announce_sbuf, 24508f13879SWarner Losh .denounce = ata_proto_denounce, 2465d01277fSScott Long .denounce_sbuf = ata_proto_denounce_sbuf, 24708f13879SWarner Losh .debug_out = ata_proto_debug_out, 24808f13879SWarner Losh }; 24908f13879SWarner Losh static struct xpt_proto ata_proto_satapm = { 25008f13879SWarner Losh .proto = PROTO_SATAPM, 25108f13879SWarner Losh .name = "satapm", 25208f13879SWarner Losh .ops = &ata_proto_ops_satapm, 25308f13879SWarner Losh }; 25408f13879SWarner Losh 25508f13879SWarner Losh static struct xpt_proto_ops ata_proto_ops_semb = { 25608f13879SWarner Losh .announce = semb_proto_announce, 2575d01277fSScott Long .announce_sbuf = semb_proto_announce_sbuf, 25808f13879SWarner Losh .denounce = semb_proto_denounce, 2595d01277fSScott Long .denounce_sbuf = semb_proto_denounce_sbuf, 26008f13879SWarner Losh .debug_out = ata_proto_debug_out, 26108f13879SWarner Losh }; 26208f13879SWarner Losh static struct xpt_proto ata_proto_semb = { 26308f13879SWarner Losh .proto = PROTO_SEMB, 26408f13879SWarner Losh .name = "semb", 26508f13879SWarner Losh .ops = &ata_proto_ops_semb, 26608f13879SWarner Losh }; 26708f13879SWarner Losh 26808f13879SWarner Losh CAM_XPT_PROTO(ata_proto_ata); 26908f13879SWarner Losh CAM_XPT_PROTO(ata_proto_satapm); 27008f13879SWarner Losh CAM_XPT_PROTO(ata_proto_semb); 27108f13879SWarner Losh 27252c9ce25SScott Long static void 2730f280cbdSWarner Losh aprobe_periph_init() 27452c9ce25SScott Long { 27552c9ce25SScott Long } 27652c9ce25SScott Long 27752c9ce25SScott Long static cam_status 2780f280cbdSWarner Losh aproberegister(struct cam_periph *periph, void *arg) 27952c9ce25SScott Long { 28052c9ce25SScott Long union ccb *request_ccb; /* CCB representing the probe request */ 28152c9ce25SScott Long probe_softc *softc; 28252c9ce25SScott Long 28352c9ce25SScott Long request_ccb = (union ccb *)arg; 28452c9ce25SScott Long if (request_ccb == NULL) { 28552c9ce25SScott Long printf("proberegister: no probe CCB, " 28652c9ce25SScott Long "can't register device\n"); 28752c9ce25SScott Long return(CAM_REQ_CMP_ERR); 28852c9ce25SScott Long } 28952c9ce25SScott Long 2904ef08dc5SAlexander Motin softc = (probe_softc *)malloc(sizeof(*softc), M_CAMXPT, M_ZERO | M_NOWAIT); 29152c9ce25SScott Long 29252c9ce25SScott Long if (softc == NULL) { 29352c9ce25SScott Long printf("proberegister: Unable to probe new device. " 29452c9ce25SScott Long "Unable to allocate softc\n"); 29552c9ce25SScott Long return(CAM_REQ_CMP_ERR); 29652c9ce25SScott Long } 29752c9ce25SScott Long TAILQ_INIT(&softc->request_ccbs); 29852c9ce25SScott Long TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h, 29952c9ce25SScott Long periph_links.tqe); 30052c9ce25SScott Long softc->flags = 0; 30152c9ce25SScott Long periph->softc = softc; 30252c9ce25SScott Long softc->periph = periph; 30352c9ce25SScott Long softc->action = PROBE_INVALID; 30499e7a4adSScott Long if (cam_periph_acquire(periph) != 0) 30599e7a4adSScott Long return (CAM_REQ_CMP_ERR); 30699e7a4adSScott Long 307a4d953c4SAlexander Motin CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe started\n")); 308227d67aaSAlexander Motin ata_device_transport(periph->path); 3090f280cbdSWarner Losh aprobeschedule(periph); 31052c9ce25SScott Long return(CAM_REQ_CMP); 31152c9ce25SScott Long } 31252c9ce25SScott Long 31352c9ce25SScott Long static void 3140f280cbdSWarner Losh aprobeschedule(struct cam_periph *periph) 31552c9ce25SScott Long { 31652c9ce25SScott Long union ccb *ccb; 31752c9ce25SScott Long probe_softc *softc; 31852c9ce25SScott Long 31952c9ce25SScott Long softc = (probe_softc *)periph->softc; 32052c9ce25SScott Long ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs); 32152c9ce25SScott Long 32265d0fb03SAlexander Motin if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) || 3233089bb2eSAlexander Motin periph->path->device->protocol == PROTO_SATAPM || 3243089bb2eSAlexander Motin periph->path->device->protocol == PROTO_SEMB) 32552c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_RESET); 32652c9ce25SScott Long else 32752c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 32852c9ce25SScott Long 32952c9ce25SScott Long if (ccb->crcn.flags & CAM_EXPECT_INQ_CHANGE) 33052c9ce25SScott Long softc->flags |= PROBE_NO_ANNOUNCE; 33152c9ce25SScott Long else 33252c9ce25SScott Long softc->flags &= ~PROBE_NO_ANNOUNCE; 33352c9ce25SScott Long 33483c5d981SAlexander Motin xpt_schedule(periph, CAM_PRIORITY_XPT); 33552c9ce25SScott Long } 33652c9ce25SScott Long 33752c9ce25SScott Long static void 3380f280cbdSWarner Losh aprobestart(struct cam_periph *periph, union ccb *start_ccb) 33952c9ce25SScott Long { 340c8039fc6SAlexander Motin struct ccb_trans_settings cts; 34152c9ce25SScott Long struct ccb_ataio *ataio; 34252c9ce25SScott Long struct ccb_scsiio *csio; 34352c9ce25SScott Long probe_softc *softc; 3441e637ba6SAlexander Motin struct cam_path *path; 3451e637ba6SAlexander Motin struct ata_params *ident_buf; 34676d843daSAlexander Motin u_int oif; 34752c9ce25SScott Long 3480f280cbdSWarner Losh CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("aprobestart\n")); 34952c9ce25SScott Long 35052c9ce25SScott Long softc = (probe_softc *)periph->softc; 3511e637ba6SAlexander Motin path = start_ccb->ccb_h.path; 35252c9ce25SScott Long ataio = &start_ccb->ataio; 35352c9ce25SScott Long csio = &start_ccb->csio; 3541e637ba6SAlexander Motin ident_buf = &periph->path->device->ident_data; 35552c9ce25SScott Long 35683c5d981SAlexander Motin if (softc->restart) { 35783c5d981SAlexander Motin softc->restart = 0; 35883c5d981SAlexander Motin if ((path->device->flags & CAM_DEV_UNCONFIGURED) || 3593089bb2eSAlexander Motin path->device->protocol == PROTO_SATAPM || 3603089bb2eSAlexander Motin path->device->protocol == PROTO_SEMB) 36183c5d981SAlexander Motin softc->action = PROBE_RESET; 36283c5d981SAlexander Motin else 36383c5d981SAlexander Motin softc->action = PROBE_IDENTIFY; 36483c5d981SAlexander Motin } 36552c9ce25SScott Long switch (softc->action) { 36652c9ce25SScott Long case PROBE_RESET: 36752c9ce25SScott Long cam_fill_ataio(ataio, 36852c9ce25SScott Long 0, 3690f280cbdSWarner Losh aprobedone, 37052c9ce25SScott Long /*flags*/CAM_DIR_NONE, 37165d0fb03SAlexander Motin 0, 37252c9ce25SScott Long /*data_ptr*/NULL, 37352c9ce25SScott Long /*dxfer_len*/0, 37483c5d981SAlexander Motin 15 * 1000); 37552c9ce25SScott Long ata_reset_cmd(ataio); 37652c9ce25SScott Long break; 37752c9ce25SScott Long case PROBE_IDENTIFY: 37852c9ce25SScott Long cam_fill_ataio(ataio, 37952c9ce25SScott Long 1, 3800f280cbdSWarner Losh aprobedone, 38152c9ce25SScott Long /*flags*/CAM_DIR_IN, 38265d0fb03SAlexander Motin 0, 383a9b8edb1SAlexander Motin /*data_ptr*/(u_int8_t *)&softc->ident_data, 384a9b8edb1SAlexander Motin /*dxfer_len*/sizeof(softc->ident_data), 38552c9ce25SScott Long 30 * 1000); 38676d843daSAlexander Motin if (path->device->protocol == PROTO_ATA) 3877606b445SAlexander Motin ata_28bit_cmd(ataio, ATA_ATA_IDENTIFY, 0, 0, 0); 38852c9ce25SScott Long else 3897606b445SAlexander Motin ata_28bit_cmd(ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0); 39052c9ce25SScott Long break; 3914ef08dc5SAlexander Motin case PROBE_SPINUP: 3924ef08dc5SAlexander Motin if (bootverbose) 3934ef08dc5SAlexander Motin xpt_print(path, "Spinning up device\n"); 3944ef08dc5SAlexander Motin cam_fill_ataio(ataio, 3954ef08dc5SAlexander Motin 1, 3960f280cbdSWarner Losh aprobedone, 3974ef08dc5SAlexander Motin /*flags*/CAM_DIR_NONE | CAM_HIGH_POWER, 3984ef08dc5SAlexander Motin 0, 3994ef08dc5SAlexander Motin /*data_ptr*/NULL, 4004ef08dc5SAlexander Motin /*dxfer_len*/0, 4014ef08dc5SAlexander Motin 30 * 1000); 4024ef08dc5SAlexander Motin ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_PUIS_SPINUP, 0, 0); 4034ef08dc5SAlexander Motin break; 40452c9ce25SScott Long case PROBE_SETMODE: 405c8039fc6SAlexander Motin { 406c8039fc6SAlexander Motin int mode, wantmode; 407c8039fc6SAlexander Motin 408c8039fc6SAlexander Motin mode = 0; 409c8039fc6SAlexander Motin /* Fetch user modes from SIM. */ 410c8039fc6SAlexander Motin bzero(&cts, sizeof(cts)); 41183c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 412c8039fc6SAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 413c8039fc6SAlexander Motin cts.type = CTS_TYPE_USER_SETTINGS; 414c8039fc6SAlexander Motin xpt_action((union ccb *)&cts); 415c8039fc6SAlexander Motin if (path->device->transport == XPORT_ATA) { 416c8039fc6SAlexander Motin if (cts.xport_specific.ata.valid & CTS_ATA_VALID_MODE) 417c8039fc6SAlexander Motin mode = cts.xport_specific.ata.mode; 418c8039fc6SAlexander Motin } else { 4191a6f09b8SAlexander Motin if (cts.xport_specific.sata.valid & CTS_SATA_VALID_MODE) 420c8039fc6SAlexander Motin mode = cts.xport_specific.sata.mode; 421c8039fc6SAlexander Motin } 42276d843daSAlexander Motin if (path->device->protocol == PROTO_ATA) { 4232121d8a5SAlexander Motin if (ata_dma == 0 && (mode == 0 || mode > ATA_PIO_MAX)) 4242121d8a5SAlexander Motin mode = ATA_PIO_MAX; 4252121d8a5SAlexander Motin } else { 4262121d8a5SAlexander Motin if (atapi_dma == 0 && (mode == 0 || mode > ATA_PIO_MAX)) 4272121d8a5SAlexander Motin mode = ATA_PIO_MAX; 4282121d8a5SAlexander Motin } 429c8039fc6SAlexander Motin negotiate: 430c8039fc6SAlexander Motin /* Honor device capabilities. */ 431c8039fc6SAlexander Motin wantmode = mode = ata_max_mode(ident_buf, mode); 432c8039fc6SAlexander Motin /* Report modes to SIM. */ 433c8039fc6SAlexander Motin bzero(&cts, sizeof(cts)); 43483c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 435c8039fc6SAlexander Motin cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 436c8039fc6SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 437c8039fc6SAlexander Motin if (path->device->transport == XPORT_ATA) { 438c8039fc6SAlexander Motin cts.xport_specific.ata.mode = mode; 439c8039fc6SAlexander Motin cts.xport_specific.ata.valid = CTS_ATA_VALID_MODE; 440c8039fc6SAlexander Motin } else { 441c8039fc6SAlexander Motin cts.xport_specific.sata.mode = mode; 442c8039fc6SAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_MODE; 443c8039fc6SAlexander Motin } 444c8039fc6SAlexander Motin xpt_action((union ccb *)&cts); 445066f913aSAlexander Motin /* Fetch current modes from SIM. */ 446c8039fc6SAlexander Motin bzero(&cts, sizeof(cts)); 44783c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 448c8039fc6SAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 449c8039fc6SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 450c8039fc6SAlexander Motin xpt_action((union ccb *)&cts); 451c8039fc6SAlexander Motin if (path->device->transport == XPORT_ATA) { 452c8039fc6SAlexander Motin if (cts.xport_specific.ata.valid & CTS_ATA_VALID_MODE) 453c8039fc6SAlexander Motin mode = cts.xport_specific.ata.mode; 454c8039fc6SAlexander Motin } else { 455c7bacdccSBrooks Davis if (cts.xport_specific.sata.valid & CTS_SATA_VALID_MODE) 456c8039fc6SAlexander Motin mode = cts.xport_specific.sata.mode; 457c8039fc6SAlexander Motin } 458c8039fc6SAlexander Motin /* If SIM disagree - renegotiate. */ 459c8039fc6SAlexander Motin if (mode != wantmode) 460c8039fc6SAlexander Motin goto negotiate; 461cf2b9a5fSAlexander Motin /* Remember what transport thinks about DMA. */ 46276d843daSAlexander Motin oif = path->device->inq_flags; 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; 46776d843daSAlexander Motin if (path->device->inq_flags != oif) 468581b2e78SAlexander Motin xpt_async(AC_GETDEV_CHANGED, path, NULL); 46952c9ce25SScott Long cam_fill_ataio(ataio, 47052c9ce25SScott Long 1, 4710f280cbdSWarner Losh aprobedone, 4725daa555dSAlexander Motin /*flags*/CAM_DIR_NONE, 4735daa555dSAlexander Motin 0, 4745daa555dSAlexander Motin /*data_ptr*/NULL, 4755daa555dSAlexander Motin /*dxfer_len*/0, 47652c9ce25SScott Long 30 * 1000); 477c8039fc6SAlexander Motin ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); 47852c9ce25SScott Long break; 479c8039fc6SAlexander Motin } 480da6808c1SAlexander Motin case PROBE_SETPM: 481da6808c1SAlexander Motin cam_fill_ataio(ataio, 482da6808c1SAlexander Motin 1, 4830f280cbdSWarner Losh aprobedone, 484da6808c1SAlexander Motin CAM_DIR_NONE, 485da6808c1SAlexander Motin 0, 486da6808c1SAlexander Motin NULL, 487da6808c1SAlexander Motin 0, 488da6808c1SAlexander Motin 30*1000); 489da6808c1SAlexander Motin ata_28bit_cmd(ataio, ATA_SETFEATURES, 490da6808c1SAlexander Motin (softc->caps & CTS_SATA_CAPS_H_PMREQ) ? 0x10 : 0x90, 491da6808c1SAlexander Motin 0, 0x03); 492da6808c1SAlexander Motin break; 493da6808c1SAlexander Motin case PROBE_SETAPST: 494da6808c1SAlexander Motin cam_fill_ataio(ataio, 495da6808c1SAlexander Motin 1, 4960f280cbdSWarner Losh aprobedone, 497da6808c1SAlexander Motin CAM_DIR_NONE, 498da6808c1SAlexander Motin 0, 499da6808c1SAlexander Motin NULL, 500da6808c1SAlexander Motin 0, 501da6808c1SAlexander Motin 30*1000); 502da6808c1SAlexander Motin ata_28bit_cmd(ataio, ATA_SETFEATURES, 503da6808c1SAlexander Motin (softc->caps & CTS_SATA_CAPS_H_APST) ? 0x10 : 0x90, 504da6808c1SAlexander Motin 0, 0x07); 505da6808c1SAlexander Motin break; 506da6808c1SAlexander Motin case PROBE_SETDMAAA: 507da6808c1SAlexander Motin cam_fill_ataio(ataio, 508da6808c1SAlexander Motin 1, 5090f280cbdSWarner Losh aprobedone, 510da6808c1SAlexander Motin CAM_DIR_NONE, 511da6808c1SAlexander Motin 0, 512da6808c1SAlexander Motin NULL, 513da6808c1SAlexander Motin 0, 514da6808c1SAlexander Motin 30*1000); 515da6808c1SAlexander Motin ata_28bit_cmd(ataio, ATA_SETFEATURES, 516da6808c1SAlexander Motin (softc->caps & CTS_SATA_CAPS_H_DMAAA) ? 0x10 : 0x90, 517da6808c1SAlexander Motin 0, 0x02); 518da6808c1SAlexander Motin break; 5198d169381SAlexander Motin case PROBE_SETAN: 520e4bed0b4SWarner Losh /* Remember what transport thinks about AEN. */ 52176d843daSAlexander Motin oif = path->device->inq_flags; 522e4bed0b4SWarner Losh if (softc->caps & CTS_SATA_CAPS_H_AN) 5233631c638SAlexander Motin path->device->inq_flags |= SID_AEN; 5243631c638SAlexander Motin else 5253631c638SAlexander Motin path->device->inq_flags &= ~SID_AEN; 52676d843daSAlexander Motin if (path->device->inq_flags != oif) 5273631c638SAlexander Motin xpt_async(AC_GETDEV_CHANGED, path, NULL); 5288d169381SAlexander Motin cam_fill_ataio(ataio, 5298d169381SAlexander Motin 1, 5300f280cbdSWarner Losh aprobedone, 5318d169381SAlexander Motin CAM_DIR_NONE, 5328d169381SAlexander Motin 0, 5338d169381SAlexander Motin NULL, 5348d169381SAlexander Motin 0, 5358d169381SAlexander Motin 30*1000); 5368d169381SAlexander Motin ata_28bit_cmd(ataio, ATA_SETFEATURES, 5378d169381SAlexander Motin (softc->caps & CTS_SATA_CAPS_H_AN) ? 0x10 : 0x90, 5388d169381SAlexander Motin 0, 0x05); 5398d169381SAlexander Motin break; 5401e637ba6SAlexander Motin case PROBE_SET_MULTI: 5411e637ba6SAlexander Motin { 542066f913aSAlexander Motin u_int sectors, bytecount; 5431e637ba6SAlexander Motin 544066f913aSAlexander Motin bytecount = 8192; /* SATA maximum */ 545066f913aSAlexander Motin /* Fetch user bytecount from SIM. */ 546066f913aSAlexander Motin bzero(&cts, sizeof(cts)); 54783c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 548066f913aSAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 549066f913aSAlexander Motin cts.type = CTS_TYPE_USER_SETTINGS; 550066f913aSAlexander Motin xpt_action((union ccb *)&cts); 551066f913aSAlexander Motin if (path->device->transport == XPORT_ATA) { 552066f913aSAlexander Motin if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 553066f913aSAlexander Motin bytecount = cts.xport_specific.ata.bytecount; 554066f913aSAlexander Motin } else { 555066f913aSAlexander Motin if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 556066f913aSAlexander Motin bytecount = cts.xport_specific.sata.bytecount; 557066f913aSAlexander Motin } 558066f913aSAlexander Motin /* Honor device capabilities. */ 559066f913aSAlexander Motin sectors = max(1, min(ident_buf->sectors_intr & 0xff, 560066f913aSAlexander Motin bytecount / ata_logical_sector_size(ident_buf))); 5611e637ba6SAlexander Motin /* Report bytecount to SIM. */ 5621e637ba6SAlexander Motin bzero(&cts, sizeof(cts)); 56383c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 5641e637ba6SAlexander Motin cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 5651e637ba6SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 5661e637ba6SAlexander Motin if (path->device->transport == XPORT_ATA) { 567c1bd46c2SAlexander Motin cts.xport_specific.ata.bytecount = sectors * 568c1bd46c2SAlexander Motin ata_logical_sector_size(ident_buf); 5691e637ba6SAlexander Motin cts.xport_specific.ata.valid = CTS_ATA_VALID_BYTECOUNT; 5701e637ba6SAlexander Motin } else { 571c1bd46c2SAlexander Motin cts.xport_specific.sata.bytecount = sectors * 572c1bd46c2SAlexander Motin ata_logical_sector_size(ident_buf); 5731e637ba6SAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_BYTECOUNT; 5741e637ba6SAlexander Motin } 5751e637ba6SAlexander Motin xpt_action((union ccb *)&cts); 576066f913aSAlexander Motin /* Fetch current bytecount from SIM. */ 577066f913aSAlexander Motin bzero(&cts, sizeof(cts)); 57883c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 579066f913aSAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 580066f913aSAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 581066f913aSAlexander Motin xpt_action((union ccb *)&cts); 582066f913aSAlexander Motin if (path->device->transport == XPORT_ATA) { 583066f913aSAlexander Motin if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 584066f913aSAlexander Motin bytecount = cts.xport_specific.ata.bytecount; 585066f913aSAlexander Motin } else { 586066f913aSAlexander Motin if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 587066f913aSAlexander Motin bytecount = cts.xport_specific.sata.bytecount; 588066f913aSAlexander Motin } 589066f913aSAlexander Motin sectors = bytecount / ata_logical_sector_size(ident_buf); 5901e637ba6SAlexander Motin 5911e637ba6SAlexander Motin cam_fill_ataio(ataio, 5921e637ba6SAlexander Motin 1, 5930f280cbdSWarner Losh aprobedone, 5941e637ba6SAlexander Motin CAM_DIR_NONE, 5951e637ba6SAlexander Motin 0, 5961e637ba6SAlexander Motin NULL, 5971e637ba6SAlexander Motin 0, 5981e637ba6SAlexander Motin 30*1000); 5991e637ba6SAlexander Motin ata_28bit_cmd(ataio, ATA_SET_MULTI, 0, 0, sectors); 6001e637ba6SAlexander Motin break; 60152c9ce25SScott Long } 60252c9ce25SScott Long case PROBE_INQUIRY: 603066f913aSAlexander Motin { 604066f913aSAlexander Motin u_int bytecount; 605066f913aSAlexander Motin 606066f913aSAlexander Motin bytecount = 8192; /* SATA maximum */ 607066f913aSAlexander Motin /* Fetch user bytecount from SIM. */ 608066f913aSAlexander Motin bzero(&cts, sizeof(cts)); 60983c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 610066f913aSAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 611066f913aSAlexander Motin cts.type = CTS_TYPE_USER_SETTINGS; 612066f913aSAlexander Motin xpt_action((union ccb *)&cts); 613066f913aSAlexander Motin if (path->device->transport == XPORT_ATA) { 614066f913aSAlexander Motin if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 615066f913aSAlexander Motin bytecount = cts.xport_specific.ata.bytecount; 616066f913aSAlexander Motin } else { 617066f913aSAlexander Motin if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 618066f913aSAlexander Motin bytecount = cts.xport_specific.sata.bytecount; 619066f913aSAlexander Motin } 620066f913aSAlexander Motin /* Honor device capabilities. */ 621066f913aSAlexander Motin bytecount &= ~1; 622066f913aSAlexander Motin bytecount = max(2, min(65534, bytecount)); 623066f913aSAlexander Motin if (ident_buf->satacapabilities != 0x0000 && 624066f913aSAlexander Motin ident_buf->satacapabilities != 0xffff) { 625066f913aSAlexander Motin bytecount = min(8192, bytecount); 626066f913aSAlexander Motin } 627066f913aSAlexander Motin /* Report bytecount to SIM. */ 628066f913aSAlexander Motin bzero(&cts, sizeof(cts)); 62983c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 630066f913aSAlexander Motin cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 631066f913aSAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 632066f913aSAlexander Motin if (path->device->transport == XPORT_ATA) { 633066f913aSAlexander Motin cts.xport_specific.ata.bytecount = bytecount; 634066f913aSAlexander Motin cts.xport_specific.ata.valid = CTS_ATA_VALID_BYTECOUNT; 635066f913aSAlexander Motin } else { 636066f913aSAlexander Motin cts.xport_specific.sata.bytecount = bytecount; 637066f913aSAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_BYTECOUNT; 638066f913aSAlexander Motin } 639066f913aSAlexander Motin xpt_action((union ccb *)&cts); 640066f913aSAlexander Motin /* FALLTHROUGH */ 641066f913aSAlexander Motin } 64252c9ce25SScott Long case PROBE_FULL_INQUIRY: 64352c9ce25SScott Long { 64452c9ce25SScott Long u_int inquiry_len; 64552c9ce25SScott Long struct scsi_inquiry_data *inq_buf = 64676d843daSAlexander Motin &path->device->inq_data; 64752c9ce25SScott Long 64852c9ce25SScott Long if (softc->action == PROBE_INQUIRY) 64952c9ce25SScott Long inquiry_len = SHORT_INQUIRY_LENGTH; 65052c9ce25SScott Long else 65152c9ce25SScott Long inquiry_len = SID_ADDITIONAL_LENGTH(inq_buf); 65252c9ce25SScott Long /* 65352c9ce25SScott Long * Some parallel SCSI devices fail to send an 65452c9ce25SScott Long * ignore wide residue message when dealing with 65552c9ce25SScott Long * odd length inquiry requests. Round up to be 65652c9ce25SScott Long * safe. 65752c9ce25SScott Long */ 65852c9ce25SScott Long inquiry_len = roundup2(inquiry_len, 2); 65952c9ce25SScott Long scsi_inquiry(csio, 66052c9ce25SScott Long /*retries*/1, 6610f280cbdSWarner Losh aprobedone, 66252c9ce25SScott Long MSG_SIMPLE_Q_TAG, 66352c9ce25SScott Long (u_int8_t *)inq_buf, 66452c9ce25SScott Long inquiry_len, 66552c9ce25SScott Long /*evpd*/FALSE, 66652c9ce25SScott Long /*page_code*/0, 66752c9ce25SScott Long SSD_MIN_SIZE, 66852c9ce25SScott Long /*timeout*/60 * 1000); 66952c9ce25SScott Long break; 67052c9ce25SScott Long } 67152c9ce25SScott Long case PROBE_PM_PID: 67252c9ce25SScott Long cam_fill_ataio(ataio, 67352c9ce25SScott Long 1, 6740f280cbdSWarner Losh aprobedone, 67552c9ce25SScott Long /*flags*/CAM_DIR_NONE, 67665d0fb03SAlexander Motin 0, 67752c9ce25SScott Long /*data_ptr*/NULL, 67852c9ce25SScott Long /*dxfer_len*/0, 67952c9ce25SScott Long 10 * 1000); 68052c9ce25SScott Long ata_pm_read_cmd(ataio, 0, 15); 68152c9ce25SScott Long break; 68252c9ce25SScott Long case PROBE_PM_PRV: 68352c9ce25SScott Long cam_fill_ataio(ataio, 68452c9ce25SScott Long 1, 6850f280cbdSWarner Losh aprobedone, 68652c9ce25SScott Long /*flags*/CAM_DIR_NONE, 68765d0fb03SAlexander Motin 0, 68852c9ce25SScott Long /*data_ptr*/NULL, 68952c9ce25SScott Long /*dxfer_len*/0, 69052c9ce25SScott Long 10 * 1000); 69152c9ce25SScott Long ata_pm_read_cmd(ataio, 1, 15); 69252c9ce25SScott Long break; 6933089bb2eSAlexander Motin case PROBE_IDENTIFY_SES: 6943089bb2eSAlexander Motin cam_fill_ataio(ataio, 6953089bb2eSAlexander Motin 1, 6960f280cbdSWarner Losh aprobedone, 6973089bb2eSAlexander Motin /*flags*/CAM_DIR_IN, 6983089bb2eSAlexander Motin 0, 6993089bb2eSAlexander Motin /*data_ptr*/(u_int8_t *)&softc->ident_data, 7003089bb2eSAlexander Motin /*dxfer_len*/sizeof(softc->ident_data), 7013089bb2eSAlexander Motin 30 * 1000); 7023089bb2eSAlexander Motin ata_28bit_cmd(ataio, ATA_SEP_ATTN, 0xEC, 0x02, 7033089bb2eSAlexander Motin sizeof(softc->ident_data) / 4); 7043089bb2eSAlexander Motin break; 7053089bb2eSAlexander Motin case PROBE_IDENTIFY_SAFTE: 7063089bb2eSAlexander Motin cam_fill_ataio(ataio, 7073089bb2eSAlexander Motin 1, 7080f280cbdSWarner Losh aprobedone, 7093089bb2eSAlexander Motin /*flags*/CAM_DIR_IN, 7103089bb2eSAlexander Motin 0, 7113089bb2eSAlexander Motin /*data_ptr*/(u_int8_t *)&softc->ident_data, 7123089bb2eSAlexander Motin /*dxfer_len*/sizeof(softc->ident_data), 7133089bb2eSAlexander Motin 30 * 1000); 7143089bb2eSAlexander Motin ata_28bit_cmd(ataio, ATA_SEP_ATTN, 0xEC, 0x00, 7153089bb2eSAlexander Motin sizeof(softc->ident_data) / 4); 7163089bb2eSAlexander Motin break; 71752c9ce25SScott Long default: 7180f280cbdSWarner Losh panic("aprobestart: invalid action state 0x%x\n", softc->action); 71952c9ce25SScott Long } 720cccf4220SAlexander Motin start_ccb->ccb_h.flags |= CAM_DEV_QFREEZE; 72152c9ce25SScott Long xpt_action(start_ccb); 72252c9ce25SScott Long } 723b9c473b2SAlexander Motin 72452c9ce25SScott Long static void 7250f280cbdSWarner Losh aproberequestdefaultnegotiation(struct cam_periph *periph) 72652c9ce25SScott Long { 72752c9ce25SScott Long struct ccb_trans_settings cts; 72852c9ce25SScott Long 72983c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE); 73052c9ce25SScott Long cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 73152c9ce25SScott Long cts.type = CTS_TYPE_USER_SETTINGS; 73252c9ce25SScott Long xpt_action((union ccb *)&cts); 733b9c473b2SAlexander Motin if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 73452c9ce25SScott Long return; 735b9c473b2SAlexander Motin cts.xport_specific.valid = 0; 73652c9ce25SScott Long cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 73752c9ce25SScott Long cts.type = CTS_TYPE_CURRENT_SETTINGS; 73852c9ce25SScott Long xpt_action((union ccb *)&cts); 73952c9ce25SScott Long } 74052c9ce25SScott Long 74152c9ce25SScott Long static void 7420f280cbdSWarner Losh aprobedone(struct cam_periph *periph, union ccb *done_ccb) 74352c9ce25SScott Long { 744c8039fc6SAlexander Motin struct ccb_trans_settings cts; 74552c9ce25SScott Long struct ata_params *ident_buf; 7463089bb2eSAlexander Motin struct scsi_inquiry_data *inq_buf; 74752c9ce25SScott Long probe_softc *softc; 74852c9ce25SScott Long struct cam_path *path; 74926bdaeddSAlexander Motin cam_status status; 75052c9ce25SScott Long u_int32_t priority; 75176d843daSAlexander Motin u_int caps, oif; 75276d843daSAlexander Motin int changed, found = 1; 7533089bb2eSAlexander Motin static const uint8_t fake_device_id_hdr[8] = 7543089bb2eSAlexander Motin {0, SVPD_DEVICE_ID, 0, 12, 7553089bb2eSAlexander Motin SVPD_ID_CODESET_BINARY, SVPD_ID_TYPE_NAA, 0, 8}; 75652c9ce25SScott Long 7570f280cbdSWarner Losh CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("aprobedone\n")); 75852c9ce25SScott Long 75952c9ce25SScott Long softc = (probe_softc *)periph->softc; 76052c9ce25SScott Long path = done_ccb->ccb_h.path; 76152c9ce25SScott Long priority = done_ccb->ccb_h.pinfo.priority; 76252c9ce25SScott Long ident_buf = &path->device->ident_data; 7633089bb2eSAlexander Motin inq_buf = &path->device->inq_data; 76452c9ce25SScott Long 7651e637ba6SAlexander Motin if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 7660191d9b3SAlexander Motin if (cam_periph_error(done_ccb, 767553484aeSWarner Losh 0, softc->restart ? (SF_NO_RECOVERY | SF_NO_RETRY) : 0 768553484aeSWarner Losh ) == ERESTART) { 769cccf4220SAlexander Motin out: 770cccf4220SAlexander Motin /* Drop freeze taken due to CAM_DEV_QFREEZE flag set. */ 771cccf4220SAlexander Motin cam_release_devq(path, 0, 0, 0, FALSE); 7721e637ba6SAlexander Motin return; 773cccf4220SAlexander Motin } 77425a519a9SAlexander Motin if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 7751e637ba6SAlexander Motin /* Don't wedge the queue */ 776cccf4220SAlexander Motin xpt_release_devq(path, /*count*/1, /*run_queue*/TRUE); 7771e637ba6SAlexander Motin } 77826bdaeddSAlexander Motin status = done_ccb->ccb_h.status & CAM_STATUS_MASK; 77925a519a9SAlexander Motin if (softc->restart) { 78025a519a9SAlexander Motin softc->faults++; 78125a519a9SAlexander Motin if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == 78225a519a9SAlexander Motin CAM_CMD_TIMEOUT) 78325a519a9SAlexander Motin softc->faults += 4; 78425a519a9SAlexander Motin if (softc->faults < 10) 78525a519a9SAlexander Motin goto done; 78625a519a9SAlexander Motin else 78725a519a9SAlexander Motin softc->restart = 0; 78826bdaeddSAlexander Motin 7891e637ba6SAlexander Motin /* Old PIO2 devices may not support mode setting. */ 79026bdaeddSAlexander Motin } else if (softc->action == PROBE_SETMODE && 79126bdaeddSAlexander Motin status == CAM_ATA_STATUS_ERROR && 7921e637ba6SAlexander Motin ata_max_pmode(ident_buf) <= ATA_PIO2 && 79326bdaeddSAlexander Motin (ident_buf->capabilities1 & ATA_SUPPORT_IORDY) == 0) { 7941e637ba6SAlexander Motin goto noerror; 79526bdaeddSAlexander Motin 79626bdaeddSAlexander Motin /* 79726bdaeddSAlexander Motin * Some old WD SATA disks report supported and enabled 79826bdaeddSAlexander Motin * device-initiated interface power management, but return 79926bdaeddSAlexander Motin * ABORT on attempt to disable it. 80026bdaeddSAlexander Motin */ 80126bdaeddSAlexander Motin } else if (softc->action == PROBE_SETPM && 80226bdaeddSAlexander Motin status == CAM_ATA_STATUS_ERROR) { 80326bdaeddSAlexander Motin goto noerror; 804025e2c12SAlexander Motin 805025e2c12SAlexander Motin /* 806b5617df5SAndriy Gapon * Some old WD SATA disks have broken SPINUP handling. 807b5617df5SAndriy Gapon * If we really fail to spin up the disk, then there will be 808b5617df5SAndriy Gapon * some media access errors later on, but at least we will 809b5617df5SAndriy Gapon * have a device to interact with for recovery attempts. 810b5617df5SAndriy Gapon */ 811b5617df5SAndriy Gapon } else if (softc->action == PROBE_SPINUP && 812b5617df5SAndriy Gapon status == CAM_ATA_STATUS_ERROR) { 813b5617df5SAndriy Gapon goto noerror; 814b5617df5SAndriy Gapon 815b5617df5SAndriy Gapon /* 816025e2c12SAlexander Motin * Some HP SATA disks report supported DMA Auto-Activation, 817025e2c12SAlexander Motin * but return ABORT on attempt to enable it. 818025e2c12SAlexander Motin */ 819025e2c12SAlexander Motin } else if (softc->action == PROBE_SETDMAAA && 820025e2c12SAlexander Motin status == CAM_ATA_STATUS_ERROR) { 821025e2c12SAlexander Motin goto noerror; 8223089bb2eSAlexander Motin 8233089bb2eSAlexander Motin /* 8243089bb2eSAlexander Motin * SES and SAF-TE SEPs have different IDENTIFY commands, 8253089bb2eSAlexander Motin * but SATA specification doesn't tell how to identify them. 8263089bb2eSAlexander Motin * Until better way found, just try another if first fail. 8273089bb2eSAlexander Motin */ 8283089bb2eSAlexander Motin } else if (softc->action == PROBE_IDENTIFY_SES && 8293089bb2eSAlexander Motin status == CAM_ATA_STATUS_ERROR) { 8303089bb2eSAlexander Motin PROBE_SET_ACTION(softc, PROBE_IDENTIFY_SAFTE); 8313089bb2eSAlexander Motin xpt_release_ccb(done_ccb); 8323089bb2eSAlexander Motin xpt_schedule(periph, priority); 833cccf4220SAlexander Motin goto out; 83426bdaeddSAlexander Motin } 83526bdaeddSAlexander Motin 8361e637ba6SAlexander Motin /* 8371e637ba6SAlexander Motin * If we get to this point, we got an error status back 8381e637ba6SAlexander Motin * from the inquiry and the error status doesn't require 8391e637ba6SAlexander Motin * automatically retrying the command. Therefore, the 8401e637ba6SAlexander Motin * inquiry failed. If we had inquiry information before 8411e637ba6SAlexander Motin * for this device, but this latest inquiry command failed, 8421e637ba6SAlexander Motin * the device has probably gone away. If this device isn't 8431e637ba6SAlexander Motin * already marked unconfigured, notify the peripheral 8441e637ba6SAlexander Motin * drivers that this device is no more. 8451e637ba6SAlexander Motin */ 84625a519a9SAlexander Motin device_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0) 8471e637ba6SAlexander Motin xpt_async(AC_LOST_DEVICE, path, NULL); 848a4d953c4SAlexander Motin PROBE_SET_ACTION(softc, PROBE_INVALID); 8491e637ba6SAlexander Motin found = 0; 8501e637ba6SAlexander Motin goto done; 8511e637ba6SAlexander Motin } 8521e637ba6SAlexander Motin noerror: 853a9b8edb1SAlexander Motin if (softc->restart) 854a9b8edb1SAlexander Motin goto done; 85552c9ce25SScott Long switch (softc->action) { 85652c9ce25SScott Long case PROBE_RESET: 8571e637ba6SAlexander Motin { 85852c9ce25SScott Long int sign = (done_ccb->ataio.res.lba_high << 8) + 85952c9ce25SScott Long done_ccb->ataio.res.lba_mid; 860a4d953c4SAlexander Motin CAM_DEBUG(path, CAM_DEBUG_PROBE, 861a4d953c4SAlexander Motin ("SIGNATURE: %04x\n", sign)); 86252c9ce25SScott Long if (sign == 0x0000 && 86352c9ce25SScott Long done_ccb->ccb_h.target_id != 15) { 86452c9ce25SScott Long path->device->protocol = PROTO_ATA; 86552c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 86652c9ce25SScott Long } else if (sign == 0x9669 && 86752c9ce25SScott Long done_ccb->ccb_h.target_id == 15) { 86852c9ce25SScott Long /* Report SIM that PM is present. */ 86952c9ce25SScott Long bzero(&cts, sizeof(cts)); 87083c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 87152c9ce25SScott Long cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 87252c9ce25SScott Long cts.type = CTS_TYPE_CURRENT_SETTINGS; 87352c9ce25SScott Long cts.xport_specific.sata.pm_present = 1; 87452c9ce25SScott Long cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; 87552c9ce25SScott Long xpt_action((union ccb *)&cts); 87652c9ce25SScott Long path->device->protocol = PROTO_SATAPM; 87752c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_PM_PID); 8783089bb2eSAlexander Motin } else if (sign == 0xc33c && 8793089bb2eSAlexander Motin done_ccb->ccb_h.target_id != 15) { 8803089bb2eSAlexander Motin path->device->protocol = PROTO_SEMB; 8813089bb2eSAlexander Motin PROBE_SET_ACTION(softc, PROBE_IDENTIFY_SES); 88252c9ce25SScott Long } else if (sign == 0xeb14 && 88352c9ce25SScott Long done_ccb->ccb_h.target_id != 15) { 88452c9ce25SScott Long path->device->protocol = PROTO_SCSI; 88552c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 88652c9ce25SScott Long } else { 88752c9ce25SScott Long if (done_ccb->ccb_h.target_id != 15) { 88852c9ce25SScott Long xpt_print(path, 88952c9ce25SScott Long "Unexpected signature 0x%04x\n", sign); 89052c9ce25SScott Long } 89165d0fb03SAlexander Motin goto device_fail; 89252c9ce25SScott Long } 89352c9ce25SScott Long xpt_release_ccb(done_ccb); 89452c9ce25SScott Long xpt_schedule(periph, priority); 895cccf4220SAlexander Motin goto out; 89652c9ce25SScott Long } 89752c9ce25SScott Long case PROBE_IDENTIFY: 89852c9ce25SScott Long { 899699f853bSAlexander Motin struct ccb_pathinq cpi; 900a11463fdSSepherosa Ziehau int veto = 0; 90152c9ce25SScott Long 90276769dc1SWarner Losh /* 90376769dc1SWarner Losh * Convert to host byte order, and fix the strings. 90476769dc1SWarner Losh */ 905a9b8edb1SAlexander Motin ident_buf = &softc->ident_data; 906296218d4SWarner Losh ata_param_fixup(ident_buf); 90776769dc1SWarner Losh 90876769dc1SWarner Losh /* 90976769dc1SWarner Losh * Allow others to veto this ATA disk attachment. This 91076769dc1SWarner Losh * is mainly used by VMs, whose disk controllers may 91176769dc1SWarner Losh * share the disks with the simulated ATA controllers. 91276769dc1SWarner Losh */ 91376769dc1SWarner Losh EVENTHANDLER_INVOKE(ada_probe_veto, path, ident_buf, &veto); 91476769dc1SWarner Losh if (veto) { 91576769dc1SWarner Losh goto device_fail; 91676769dc1SWarner Losh } 91776769dc1SWarner Losh 9184ef08dc5SAlexander Motin /* Device may need spin-up before IDENTIFY become valid. */ 9191254b680SAlexander Motin if ((ident_buf->specconf == 0x37c8 || 9201254b680SAlexander Motin ident_buf->specconf == 0x738c) && 9211254b680SAlexander Motin ((ident_buf->config & ATA_RESP_INCOMPLETE) || 9224ef08dc5SAlexander Motin softc->spinup == 0)) { 9234ef08dc5SAlexander Motin PROBE_SET_ACTION(softc, PROBE_SPINUP); 9244ef08dc5SAlexander Motin xpt_release_ccb(done_ccb); 9254ef08dc5SAlexander Motin xpt_schedule(periph, priority); 926cccf4220SAlexander Motin goto out; 9274ef08dc5SAlexander Motin } 928a9b8edb1SAlexander Motin ident_buf = &path->device->ident_data; 92976d843daSAlexander Motin 93076d843daSAlexander Motin /* Check that it is the same device as we know. */ 93152c9ce25SScott Long if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) { 932a9b8edb1SAlexander Motin if (bcmp(softc->ident_data.model, ident_buf->model, 933a9b8edb1SAlexander Motin sizeof(ident_buf->model)) || 934a9b8edb1SAlexander Motin bcmp(softc->ident_data.serial, ident_buf->serial, 935a9b8edb1SAlexander Motin sizeof(ident_buf->serial))) { 93676d843daSAlexander Motin /* The device was replaced. */ 93776d843daSAlexander Motin changed = 2; 93852c9ce25SScott Long xpt_async(AC_LOST_DEVICE, path, NULL); 93976d843daSAlexander Motin } else if (bcmp(&softc->ident_data, ident_buf, 94076d843daSAlexander Motin sizeof(*ident_buf))) { 94176d843daSAlexander Motin /* The device is the same, but has changed. */ 94276d843daSAlexander Motin changed = 1; 9431e637ba6SAlexander Motin } else { 94476d843daSAlexander Motin /* Nothing has changed. */ 9452eb4a8dcSAlexander Motin changed = 0; 9462eb4a8dcSAlexander Motin } 94776d843daSAlexander Motin } else { 94876d843daSAlexander Motin /* This is a new device. */ 94976d843daSAlexander Motin changed = 2; 9502eb4a8dcSAlexander Motin } 95176d843daSAlexander Motin 95276d843daSAlexander Motin if (changed != 0) 9532eb4a8dcSAlexander Motin bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 95476d843daSAlexander Motin if (changed == 2) { 95552c9ce25SScott Long /* Clean up from previous instance of this device */ 95652c9ce25SScott Long if (path->device->serial_num != NULL) { 95752c9ce25SScott Long free(path->device->serial_num, M_CAMXPT); 95852c9ce25SScott Long path->device->serial_num = NULL; 95952c9ce25SScott Long path->device->serial_num_len = 0; 96052c9ce25SScott Long } 9613089bb2eSAlexander Motin if (path->device->device_id != NULL) { 9623089bb2eSAlexander Motin free(path->device->device_id, M_CAMXPT); 9633089bb2eSAlexander Motin path->device->device_id = NULL; 9643089bb2eSAlexander Motin path->device->device_id_len = 0; 9653089bb2eSAlexander Motin } 96652c9ce25SScott Long path->device->serial_num = 96752c9ce25SScott Long (u_int8_t *)malloc((sizeof(ident_buf->serial) + 1), 96852c9ce25SScott Long M_CAMXPT, M_NOWAIT); 96952c9ce25SScott Long if (path->device->serial_num != NULL) { 97052c9ce25SScott Long bcopy(ident_buf->serial, 97152c9ce25SScott Long path->device->serial_num, 97252c9ce25SScott Long sizeof(ident_buf->serial)); 97352c9ce25SScott Long path->device->serial_num[sizeof(ident_buf->serial)] 97452c9ce25SScott Long = '\0'; 97552c9ce25SScott Long path->device->serial_num_len = 97652c9ce25SScott Long strlen(path->device->serial_num); 97752c9ce25SScott Long } 9783089bb2eSAlexander Motin if (ident_buf->enabled.extension & 9793089bb2eSAlexander Motin ATA_SUPPORT_64BITWWN) { 9803089bb2eSAlexander Motin path->device->device_id = 9813089bb2eSAlexander Motin malloc(16, M_CAMXPT, M_NOWAIT); 9823089bb2eSAlexander Motin if (path->device->device_id != NULL) { 9833089bb2eSAlexander Motin path->device->device_id_len = 16; 9843089bb2eSAlexander Motin bcopy(&fake_device_id_hdr, 9853089bb2eSAlexander Motin path->device->device_id, 8); 9863d6dd54eSAlexander Motin bcopy(ident_buf->wwn, 9873d6dd54eSAlexander Motin path->device->device_id + 8, 8); 9883d6dd54eSAlexander Motin ata_bswap(path->device->device_id + 8, 8); 9893089bb2eSAlexander Motin } 9903089bb2eSAlexander Motin } 9914b997c49SAlexander Motin path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 9921e637ba6SAlexander Motin } 99376d843daSAlexander Motin if (changed == 1) 99476d843daSAlexander Motin xpt_async(AC_GETDEV_CHANGED, path, NULL); 99530a4094fSAlexander Motin if (ident_buf->satacapabilities & ATA_SUPPORT_NCQ) { 9967dc3213dSAlexander Motin path->device->mintags = 2; 9977dc3213dSAlexander Motin path->device->maxtags = 99830a4094fSAlexander Motin ATA_QUEUE_LEN(ident_buf->queue) + 1; 99930a4094fSAlexander Motin } 100030a4094fSAlexander Motin ata_find_quirk(path->device); 1001507e5811SAlexander Motin if (path->device->mintags != 0 && 1002507e5811SAlexander Motin path->bus->sim->max_tagged_dev_openings != 0) { 1003699f853bSAlexander Motin /* Check if the SIM does not want queued commands. */ 1004762a7f4fSWarner Losh xpt_path_inq(&cpi, path); 1005699f853bSAlexander Motin if (cpi.ccb_h.status == CAM_REQ_CMP && 1006699f853bSAlexander Motin (cpi.hba_inquiry & PI_TAG_ABLE)) { 1007c8039fc6SAlexander Motin /* Report SIM which tags are allowed. */ 1008c8039fc6SAlexander Motin bzero(&cts, sizeof(cts)); 100983c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1010c8039fc6SAlexander Motin cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1011c8039fc6SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 1012c8039fc6SAlexander Motin cts.xport_specific.sata.tags = path->device->maxtags; 1013c8039fc6SAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_TAGS; 1014c8039fc6SAlexander Motin xpt_action((union ccb *)&cts); 101530a4094fSAlexander Motin } 1016699f853bSAlexander Motin } 1017bc1bf6e8SAlexander Motin ata_device_transport(path); 101876d843daSAlexander Motin if (changed == 2) 10190f280cbdSWarner Losh aproberequestdefaultnegotiation(periph); 102052c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_SETMODE); 102152c9ce25SScott Long xpt_release_ccb(done_ccb); 102252c9ce25SScott Long xpt_schedule(periph, priority); 1023cccf4220SAlexander Motin goto out; 102452c9ce25SScott Long } 10254ef08dc5SAlexander Motin case PROBE_SPINUP: 10264ef08dc5SAlexander Motin if (bootverbose) 10274ef08dc5SAlexander Motin xpt_print(path, "Spin-up done\n"); 10284ef08dc5SAlexander Motin softc->spinup = 1; 10294ef08dc5SAlexander Motin PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 10304ef08dc5SAlexander Motin xpt_release_ccb(done_ccb); 10314ef08dc5SAlexander Motin xpt_schedule(periph, priority); 1032cccf4220SAlexander Motin goto out; 103352c9ce25SScott Long case PROBE_SETMODE: 1034da6808c1SAlexander Motin /* Set supported bits. */ 1035da6808c1SAlexander Motin bzero(&cts, sizeof(cts)); 1036da6808c1SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1037da6808c1SAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1038da6808c1SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 1039da6808c1SAlexander Motin xpt_action((union ccb *)&cts); 10402e1eb332SMarius Strobl if (path->device->transport == XPORT_SATA && 10412e1eb332SMarius Strobl cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1042da6808c1SAlexander Motin caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H; 10432e1eb332SMarius Strobl else if (path->device->transport == XPORT_ATA && 10442e1eb332SMarius Strobl cts.xport_specific.ata.valid & CTS_ATA_VALID_CAPS) 10452e1eb332SMarius Strobl caps = cts.xport_specific.ata.caps & CTS_ATA_CAPS_H; 1046da6808c1SAlexander Motin else 1047da6808c1SAlexander Motin caps = 0; 10482e1eb332SMarius Strobl if (path->device->transport == XPORT_SATA && 10492e1eb332SMarius Strobl ident_buf->satacapabilities != 0xffff) { 1050da6808c1SAlexander Motin if (ident_buf->satacapabilities & ATA_SUPPORT_IFPWRMNGTRCV) 1051da6808c1SAlexander Motin caps |= CTS_SATA_CAPS_D_PMREQ; 1052da6808c1SAlexander Motin if (ident_buf->satacapabilities & ATA_SUPPORT_HAPST) 1053da6808c1SAlexander Motin caps |= CTS_SATA_CAPS_D_APST; 1054da6808c1SAlexander Motin } 1055da6808c1SAlexander Motin /* Mask unwanted bits. */ 1056da6808c1SAlexander Motin bzero(&cts, sizeof(cts)); 1057da6808c1SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1058da6808c1SAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1059da6808c1SAlexander Motin cts.type = CTS_TYPE_USER_SETTINGS; 1060da6808c1SAlexander Motin xpt_action((union ccb *)&cts); 10612e1eb332SMarius Strobl if (path->device->transport == XPORT_SATA && 10622e1eb332SMarius Strobl cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1063da6808c1SAlexander Motin caps &= cts.xport_specific.sata.caps; 10642e1eb332SMarius Strobl else if (path->device->transport == XPORT_ATA && 10652e1eb332SMarius Strobl cts.xport_specific.ata.valid & CTS_ATA_VALID_CAPS) 10662e1eb332SMarius Strobl caps &= cts.xport_specific.ata.caps; 1067c2b82f3eSAlexander Motin else 1068c2b82f3eSAlexander Motin caps = 0; 10692e1eb332SMarius Strobl /* 10702e1eb332SMarius Strobl * Remember what transport thinks about 48-bit DMA. If 10712e1eb332SMarius Strobl * capability information is not provided or transport is 10722e1eb332SMarius Strobl * SATA, we take support for granted. 10732e1eb332SMarius Strobl */ 107476d843daSAlexander Motin oif = path->device->inq_flags; 10752e1eb332SMarius Strobl if (!(path->device->inq_flags & SID_DMA) || 10762e1eb332SMarius Strobl (path->device->transport == XPORT_ATA && 10772e1eb332SMarius Strobl (cts.xport_specific.ata.valid & CTS_ATA_VALID_CAPS) && 10782e1eb332SMarius Strobl !(caps & CTS_ATA_CAPS_H_DMA48))) 10792e1eb332SMarius Strobl path->device->inq_flags &= ~SID_DMA48; 10802e1eb332SMarius Strobl else 10812e1eb332SMarius Strobl path->device->inq_flags |= SID_DMA48; 108276d843daSAlexander Motin if (path->device->inq_flags != oif) 108376d843daSAlexander Motin xpt_async(AC_GETDEV_CHANGED, path, NULL); 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) 12300f280cbdSWarner Losh aproberequestdefaultnegotiation(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. */ 125476d843daSAlexander Motin oif = path->device->inq_flags; 1255e4bed0b4SWarner Losh if ((caps & CTS_SATA_CAPS_H_AN) && path->device->protocol != PROTO_ATA) 12562e1eb332SMarius Strobl path->device->inq_flags |= SID_AEN; 12572e1eb332SMarius Strobl else 12582e1eb332SMarius Strobl path->device->inq_flags &= ~SID_AEN; 1259da6808c1SAlexander Motin /* Store result to SIM. */ 1260da6808c1SAlexander Motin bzero(&cts, sizeof(cts)); 1261da6808c1SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1262da6808c1SAlexander Motin cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1263da6808c1SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 1264da6808c1SAlexander Motin cts.xport_specific.sata.caps = caps; 1265da6808c1SAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS; 1266da6808c1SAlexander Motin xpt_action((union ccb *)&cts); 1267da6808c1SAlexander Motin softc->caps = caps; 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 { 127576d843daSAlexander Motin if (path->device->inq_flags != oif) 127676d843daSAlexander Motin xpt_async(AC_GETDEV_CHANGED, path, NULL); 127765d0fb03SAlexander Motin done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 127865d0fb03SAlexander Motin xpt_action(done_ccb); 1279cccf4220SAlexander Motin xpt_async(AC_SCSI_AEN, path, done_ccb); 128052c9ce25SScott Long } 1281a4d953c4SAlexander Motin PROBE_SET_ACTION(softc, PROBE_DONE); 128252c9ce25SScott Long break; 12833089bb2eSAlexander Motin case PROBE_IDENTIFY_SES: 12843089bb2eSAlexander Motin case PROBE_IDENTIFY_SAFTE: 12853089bb2eSAlexander Motin if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) { 12863089bb2eSAlexander Motin /* Check that it is the same device. */ 12873089bb2eSAlexander Motin if (bcmp(&softc->ident_data, ident_buf, 53)) { 12883089bb2eSAlexander Motin /* Device changed. */ 128976d843daSAlexander Motin changed = 2; 12903089bb2eSAlexander Motin xpt_async(AC_LOST_DEVICE, path, NULL); 12913089bb2eSAlexander Motin } else { 12923089bb2eSAlexander Motin bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 12933089bb2eSAlexander Motin changed = 0; 12943089bb2eSAlexander Motin } 129576d843daSAlexander Motin } else 129676d843daSAlexander Motin changed = 2; 12973089bb2eSAlexander Motin if (changed) { 12983089bb2eSAlexander Motin bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 12993089bb2eSAlexander Motin /* Clean up from previous instance of this device */ 13003089bb2eSAlexander Motin if (path->device->device_id != NULL) { 13013089bb2eSAlexander Motin free(path->device->device_id, M_CAMXPT); 13023089bb2eSAlexander Motin path->device->device_id = NULL; 13033089bb2eSAlexander Motin path->device->device_id_len = 0; 13043089bb2eSAlexander Motin } 13053089bb2eSAlexander Motin path->device->device_id = 13063089bb2eSAlexander Motin malloc(16, M_CAMXPT, M_NOWAIT); 13073089bb2eSAlexander Motin if (path->device->device_id != NULL) { 13083089bb2eSAlexander Motin path->device->device_id_len = 16; 13093089bb2eSAlexander Motin bcopy(&fake_device_id_hdr, 13103089bb2eSAlexander Motin path->device->device_id, 8); 13113089bb2eSAlexander Motin bcopy(((uint8_t*)ident_buf) + 2, 13123089bb2eSAlexander Motin path->device->device_id + 8, 8); 13133089bb2eSAlexander Motin } 13143089bb2eSAlexander Motin 13153089bb2eSAlexander Motin path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 13163089bb2eSAlexander Motin } 1317bc1bf6e8SAlexander Motin ata_device_transport(path); 1318bc1bf6e8SAlexander Motin if (changed) 13190f280cbdSWarner Losh aproberequestdefaultnegotiation(periph); 13203089bb2eSAlexander Motin 13213089bb2eSAlexander Motin if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 13223089bb2eSAlexander Motin path->device->flags &= ~CAM_DEV_UNCONFIGURED; 13233089bb2eSAlexander Motin xpt_acquire_device(path->device); 13243089bb2eSAlexander Motin done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 13253089bb2eSAlexander Motin xpt_action(done_ccb); 1326cccf4220SAlexander Motin xpt_async(AC_FOUND_DEVICE, path, done_ccb); 13273089bb2eSAlexander Motin } 1328a4d953c4SAlexander Motin PROBE_SET_ACTION(softc, PROBE_DONE); 13293089bb2eSAlexander Motin break; 133052c9ce25SScott Long default: 13310f280cbdSWarner Losh panic("aprobedone: invalid action state 0x%x\n", softc->action); 133252c9ce25SScott Long } 13331e637ba6SAlexander Motin done: 133483c5d981SAlexander Motin if (softc->restart) { 133583c5d981SAlexander Motin softc->restart = 0; 13361e637ba6SAlexander Motin xpt_release_ccb(done_ccb); 13370f280cbdSWarner Losh aprobeschedule(periph); 1338cccf4220SAlexander Motin goto out; 133983c5d981SAlexander Motin } 134083c5d981SAlexander Motin xpt_release_ccb(done_ccb); 1341a4d953c4SAlexander Motin CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe completed\n")); 134283c5d981SAlexander Motin while ((done_ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs))) { 134383c5d981SAlexander Motin TAILQ_REMOVE(&softc->request_ccbs, 134483c5d981SAlexander Motin &done_ccb->ccb_h, periph_links.tqe); 134583c5d981SAlexander Motin done_ccb->ccb_h.status = found ? CAM_REQ_CMP : CAM_REQ_CMP_ERR; 134652c9ce25SScott Long xpt_done(done_ccb); 134783c5d981SAlexander Motin } 1348cccf4220SAlexander Motin /* Drop freeze taken due to CAM_DEV_QFREEZE flag set. */ 1349cccf4220SAlexander Motin cam_release_devq(path, 0, 0, 0, FALSE); 13502e3f592bSAlexander Motin cam_periph_invalidate(periph); 135152c9ce25SScott Long cam_periph_release_locked(periph); 135252c9ce25SScott Long } 135352c9ce25SScott Long 135452c9ce25SScott Long static void 13550f280cbdSWarner Losh aprobecleanup(struct cam_periph *periph) 135652c9ce25SScott Long { 135752c9ce25SScott Long free(periph->softc, M_CAMXPT); 135852c9ce25SScott Long } 135952c9ce25SScott Long 136052c9ce25SScott Long static void 136130a4094fSAlexander Motin ata_find_quirk(struct cam_ed *device) 136252c9ce25SScott Long { 136330a4094fSAlexander Motin struct ata_quirk_entry *quirk; 136452c9ce25SScott Long caddr_t match; 136552c9ce25SScott Long 136630a4094fSAlexander Motin match = cam_quirkmatch((caddr_t)&device->ident_data, 136730a4094fSAlexander Motin (caddr_t)ata_quirk_table, 13688dfea464SPedro F. Giffuni nitems(ata_quirk_table), 136930a4094fSAlexander Motin sizeof(*ata_quirk_table), ata_identify_match); 137052c9ce25SScott Long 137152c9ce25SScott Long if (match == NULL) 137252c9ce25SScott Long panic("xpt_find_quirk: device didn't match wildcard entry!!"); 137352c9ce25SScott Long 137430a4094fSAlexander Motin quirk = (struct ata_quirk_entry *)match; 137552c9ce25SScott Long device->quirk = quirk; 13767dc3213dSAlexander Motin if (quirk->quirks & CAM_QUIRK_MAXTAGS) { 13777dc3213dSAlexander Motin device->mintags = quirk->mintags; 13787dc3213dSAlexander Motin device->maxtags = quirk->maxtags; 13797dc3213dSAlexander Motin } 138052c9ce25SScott Long } 138152c9ce25SScott Long 138252c9ce25SScott Long typedef struct { 138352c9ce25SScott Long union ccb *request_ccb; 138452c9ce25SScott Long struct ccb_pathinq *cpi; 138552c9ce25SScott Long int counter; 138652c9ce25SScott Long } ata_scan_bus_info; 138752c9ce25SScott Long 138852c9ce25SScott Long /* 138952c9ce25SScott Long * To start a scan, request_ccb is an XPT_SCAN_BUS ccb. 139052c9ce25SScott Long * As the scan progresses, xpt_scan_bus is used as the 139152c9ce25SScott Long * callback on completion function. 139252c9ce25SScott Long */ 139352c9ce25SScott Long static void 139452c9ce25SScott Long ata_scan_bus(struct cam_periph *periph, union ccb *request_ccb) 139552c9ce25SScott Long { 139652c9ce25SScott Long struct cam_path *path; 139752c9ce25SScott Long ata_scan_bus_info *scan_info; 139883c5d981SAlexander Motin union ccb *work_ccb, *reset_ccb; 1399227d67aaSAlexander Motin struct mtx *mtx; 140052c9ce25SScott Long cam_status status; 140152c9ce25SScott Long 140252c9ce25SScott Long CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE, 140352c9ce25SScott Long ("xpt_scan_bus\n")); 140452c9ce25SScott Long switch (request_ccb->ccb_h.func_code) { 140552c9ce25SScott Long case XPT_SCAN_BUS: 14060e85f214SMatt Jacob case XPT_SCAN_TGT: 140752c9ce25SScott Long /* Find out the characteristics of the bus */ 140852c9ce25SScott Long work_ccb = xpt_alloc_ccb_nowait(); 140952c9ce25SScott Long if (work_ccb == NULL) { 141052c9ce25SScott Long request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 141152c9ce25SScott Long xpt_done(request_ccb); 141252c9ce25SScott Long return; 141352c9ce25SScott Long } 1414762a7f4fSWarner Losh xpt_path_inq(&work_ccb->cpi, request_ccb->ccb_h.path); 141552c9ce25SScott Long if (work_ccb->ccb_h.status != CAM_REQ_CMP) { 141652c9ce25SScott Long request_ccb->ccb_h.status = work_ccb->ccb_h.status; 141752c9ce25SScott Long xpt_free_ccb(work_ccb); 141852c9ce25SScott Long xpt_done(request_ccb); 141952c9ce25SScott Long return; 142052c9ce25SScott Long } 142152c9ce25SScott Long 142283c5d981SAlexander Motin /* We may need to reset bus first, if we haven't done it yet. */ 142383c5d981SAlexander Motin if ((work_ccb->cpi.hba_inquiry & 142483c5d981SAlexander Motin (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE)) && 142583c5d981SAlexander Motin !(work_ccb->cpi.hba_misc & PIM_NOBUSRESET) && 142683c5d981SAlexander Motin !timevalisset(&request_ccb->ccb_h.path->bus->last_reset)) { 142783c5d981SAlexander Motin reset_ccb = xpt_alloc_ccb_nowait(); 1428f1893540SAlexander Motin if (reset_ccb == NULL) { 1429f1893540SAlexander Motin request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1430f1893540SAlexander Motin xpt_free_ccb(work_ccb); 1431f1893540SAlexander Motin xpt_done(request_ccb); 1432f1893540SAlexander Motin return; 1433f1893540SAlexander Motin } 143483c5d981SAlexander Motin xpt_setup_ccb(&reset_ccb->ccb_h, request_ccb->ccb_h.path, 143583c5d981SAlexander Motin CAM_PRIORITY_NONE); 143683c5d981SAlexander Motin reset_ccb->ccb_h.func_code = XPT_RESET_BUS; 143783c5d981SAlexander Motin xpt_action(reset_ccb); 143883c5d981SAlexander Motin if (reset_ccb->ccb_h.status != CAM_REQ_CMP) { 143983c5d981SAlexander Motin request_ccb->ccb_h.status = reset_ccb->ccb_h.status; 144083c5d981SAlexander Motin xpt_free_ccb(reset_ccb); 144183c5d981SAlexander Motin xpt_free_ccb(work_ccb); 144283c5d981SAlexander Motin xpt_done(request_ccb); 144383c5d981SAlexander Motin return; 144483c5d981SAlexander Motin } 144583c5d981SAlexander Motin xpt_free_ccb(reset_ccb); 144683c5d981SAlexander Motin } 144783c5d981SAlexander Motin 144852c9ce25SScott Long /* Save some state for use while we probe for devices */ 144952c9ce25SScott Long scan_info = (ata_scan_bus_info *) 145052c9ce25SScott Long malloc(sizeof(ata_scan_bus_info), M_CAMXPT, M_NOWAIT); 145152c9ce25SScott Long if (scan_info == NULL) { 145252c9ce25SScott Long request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1453f1893540SAlexander Motin xpt_free_ccb(work_ccb); 145452c9ce25SScott Long xpt_done(request_ccb); 145552c9ce25SScott Long return; 145652c9ce25SScott Long } 145752c9ce25SScott Long scan_info->request_ccb = request_ccb; 145852c9ce25SScott Long scan_info->cpi = &work_ccb->cpi; 145952c9ce25SScott Long /* If PM supported, probe it first. */ 146052c9ce25SScott Long if (scan_info->cpi->hba_inquiry & PI_SATAPM) 14610025eb12SAlexander Motin scan_info->counter = scan_info->cpi->max_target; 14620025eb12SAlexander Motin else 14630025eb12SAlexander Motin scan_info->counter = 0; 146452c9ce25SScott Long 146552c9ce25SScott Long work_ccb = xpt_alloc_ccb_nowait(); 146652c9ce25SScott Long if (work_ccb == NULL) { 146752c9ce25SScott Long free(scan_info, M_CAMXPT); 146852c9ce25SScott Long request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 146952c9ce25SScott Long xpt_done(request_ccb); 147052c9ce25SScott Long break; 147152c9ce25SScott Long } 1472227d67aaSAlexander Motin mtx = xpt_path_mtx(scan_info->request_ccb->ccb_h.path); 147352c9ce25SScott Long goto scan_next; 147452c9ce25SScott Long case XPT_SCAN_LUN: 147552c9ce25SScott Long work_ccb = request_ccb; 147652c9ce25SScott Long /* Reuse the same CCB to query if a device was really found */ 147752c9ce25SScott Long scan_info = (ata_scan_bus_info *)work_ccb->ccb_h.ppriv_ptr0; 1478227d67aaSAlexander Motin mtx = xpt_path_mtx(scan_info->request_ccb->ccb_h.path); 1479227d67aaSAlexander Motin mtx_lock(mtx); 148065d0fb03SAlexander Motin /* If there is PMP... */ 14810025eb12SAlexander Motin if ((scan_info->cpi->hba_inquiry & PI_SATAPM) && 14820025eb12SAlexander Motin (scan_info->counter == scan_info->cpi->max_target)) { 148383c5d981SAlexander Motin if (work_ccb->ccb_h.status == CAM_REQ_CMP) { 148465d0fb03SAlexander Motin /* everything else will be probed by it */ 1485e2a75189SAlexander Motin /* Free the current request path- we're done with it. */ 1486e2a75189SAlexander Motin xpt_free_path(work_ccb->ccb_h.path); 14870025eb12SAlexander Motin goto done; 148852c9ce25SScott Long } else { 148952c9ce25SScott Long struct ccb_trans_settings cts; 149052c9ce25SScott Long 149152c9ce25SScott Long /* Report SIM that PM is absent. */ 149252c9ce25SScott Long bzero(&cts, sizeof(cts)); 149352c9ce25SScott Long xpt_setup_ccb(&cts.ccb_h, 1494e2a75189SAlexander Motin work_ccb->ccb_h.path, CAM_PRIORITY_NONE); 149552c9ce25SScott Long cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 149652c9ce25SScott Long cts.type = CTS_TYPE_CURRENT_SETTINGS; 14973ccda2f3SAlexander Motin cts.xport_specific.sata.pm_present = 0; 149852c9ce25SScott Long cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; 149952c9ce25SScott Long xpt_action((union ccb *)&cts); 150052c9ce25SScott Long } 150152c9ce25SScott Long } 1502e2a75189SAlexander Motin /* Free the current request path- we're done with it. */ 1503e2a75189SAlexander Motin xpt_free_path(work_ccb->ccb_h.path); 15040025eb12SAlexander Motin if (scan_info->counter == 15050025eb12SAlexander Motin ((scan_info->cpi->hba_inquiry & PI_SATAPM) ? 15060025eb12SAlexander Motin 0 : scan_info->cpi->max_target)) { 15070025eb12SAlexander Motin done: 1508227d67aaSAlexander Motin mtx_unlock(mtx); 150952c9ce25SScott Long xpt_free_ccb(work_ccb); 151052c9ce25SScott Long xpt_free_ccb((union ccb *)scan_info->cpi); 151152c9ce25SScott Long request_ccb = scan_info->request_ccb; 151252c9ce25SScott Long free(scan_info, M_CAMXPT); 151352c9ce25SScott Long request_ccb->ccb_h.status = CAM_REQ_CMP; 151452c9ce25SScott Long xpt_done(request_ccb); 151552c9ce25SScott Long break; 151652c9ce25SScott Long } 15170025eb12SAlexander Motin /* Take next device. Wrap from max (PMP) to 0. */ 15180025eb12SAlexander Motin scan_info->counter = (scan_info->counter + 1 ) % 15190025eb12SAlexander Motin (scan_info->cpi->max_target + 1); 152052c9ce25SScott Long scan_next: 1521e5dfa058SAlexander Motin status = xpt_create_path(&path, NULL, 152252c9ce25SScott Long scan_info->request_ccb->ccb_h.path_id, 152352c9ce25SScott Long scan_info->counter, 0); 152452c9ce25SScott Long if (status != CAM_REQ_CMP) { 1525227d67aaSAlexander Motin if (request_ccb->ccb_h.func_code == XPT_SCAN_LUN) 1526227d67aaSAlexander Motin mtx_unlock(mtx); 152752c9ce25SScott Long printf("xpt_scan_bus: xpt_create_path failed" 152852c9ce25SScott Long " with status %#x, bus scan halted\n", 152952c9ce25SScott Long status); 153052c9ce25SScott Long xpt_free_ccb(work_ccb); 153152c9ce25SScott Long xpt_free_ccb((union ccb *)scan_info->cpi); 153252c9ce25SScott Long request_ccb = scan_info->request_ccb; 153352c9ce25SScott Long free(scan_info, M_CAMXPT); 153452c9ce25SScott Long request_ccb->ccb_h.status = status; 153552c9ce25SScott Long xpt_done(request_ccb); 153652c9ce25SScott Long break; 153752c9ce25SScott Long } 153852c9ce25SScott Long xpt_setup_ccb(&work_ccb->ccb_h, path, 153952c9ce25SScott Long scan_info->request_ccb->ccb_h.pinfo.priority); 154052c9ce25SScott Long work_ccb->ccb_h.func_code = XPT_SCAN_LUN; 154152c9ce25SScott Long work_ccb->ccb_h.cbfcnp = ata_scan_bus; 1542227d67aaSAlexander Motin work_ccb->ccb_h.flags |= CAM_UNLOCKED; 154352c9ce25SScott Long work_ccb->ccb_h.ppriv_ptr0 = scan_info; 154452c9ce25SScott Long work_ccb->crcn.flags = scan_info->request_ccb->crcn.flags; 1545227d67aaSAlexander Motin mtx_unlock(mtx); 1546227d67aaSAlexander Motin if (request_ccb->ccb_h.func_code == XPT_SCAN_LUN) 1547227d67aaSAlexander Motin mtx = NULL; 154852c9ce25SScott Long xpt_action(work_ccb); 1549227d67aaSAlexander Motin if (mtx != NULL) 1550227d67aaSAlexander Motin mtx_lock(mtx); 155152c9ce25SScott Long break; 155252c9ce25SScott Long default: 155352c9ce25SScott Long break; 155452c9ce25SScott Long } 155552c9ce25SScott Long } 155652c9ce25SScott Long 155752c9ce25SScott Long static void 155852c9ce25SScott Long ata_scan_lun(struct cam_periph *periph, struct cam_path *path, 155952c9ce25SScott Long cam_flags flags, union ccb *request_ccb) 156052c9ce25SScott Long { 156152c9ce25SScott Long struct ccb_pathinq cpi; 156252c9ce25SScott Long cam_status status; 156352c9ce25SScott Long struct cam_path *new_path; 156452c9ce25SScott Long struct cam_periph *old_periph; 1565227d67aaSAlexander Motin int lock; 156652c9ce25SScott Long 156783c5d981SAlexander Motin CAM_DEBUG(path, CAM_DEBUG_TRACE, ("xpt_scan_lun\n")); 156852c9ce25SScott Long 1569762a7f4fSWarner Losh xpt_path_inq(&cpi, path); 157052c9ce25SScott Long if (cpi.ccb_h.status != CAM_REQ_CMP) { 157152c9ce25SScott Long if (request_ccb != NULL) { 157252c9ce25SScott Long request_ccb->ccb_h.status = cpi.ccb_h.status; 157352c9ce25SScott Long xpt_done(request_ccb); 157452c9ce25SScott Long } 157552c9ce25SScott Long return; 157652c9ce25SScott Long } 157752c9ce25SScott Long 157852c9ce25SScott Long if (request_ccb == NULL) { 157932aa80a6SAlexander Motin request_ccb = xpt_alloc_ccb_nowait(); 158052c9ce25SScott Long if (request_ccb == NULL) { 158152c9ce25SScott Long xpt_print(path, "xpt_scan_lun: can't allocate CCB, " 158252c9ce25SScott Long "can't continue\n"); 158352c9ce25SScott Long return; 158452c9ce25SScott Long } 1585e5dfa058SAlexander Motin status = xpt_create_path(&new_path, NULL, 158652c9ce25SScott Long path->bus->path_id, 158752c9ce25SScott Long path->target->target_id, 158852c9ce25SScott Long path->device->lun_id); 158952c9ce25SScott Long if (status != CAM_REQ_CMP) { 159032aa80a6SAlexander Motin xpt_print(path, "xpt_scan_lun: can't create path, " 159152c9ce25SScott Long "can't continue\n"); 159232aa80a6SAlexander Motin xpt_free_ccb(request_ccb); 159352c9ce25SScott Long return; 159452c9ce25SScott Long } 159583c5d981SAlexander Motin xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_XPT); 15960f280cbdSWarner Losh request_ccb->ccb_h.cbfcnp = axptscandone; 1597227d67aaSAlexander Motin request_ccb->ccb_h.flags |= CAM_UNLOCKED; 159852c9ce25SScott Long request_ccb->ccb_h.func_code = XPT_SCAN_LUN; 159952c9ce25SScott Long request_ccb->crcn.flags = flags; 160052c9ce25SScott Long } 160152c9ce25SScott Long 1602227d67aaSAlexander Motin lock = (xpt_path_owned(path) == 0); 1603227d67aaSAlexander Motin if (lock) 1604227d67aaSAlexander Motin xpt_path_lock(path); 1605f09f8e3eSAlexander Motin if ((old_periph = cam_periph_find(path, "aprobe")) != NULL) { 16062e3f592bSAlexander Motin if ((old_periph->flags & CAM_PERIPH_INVALID) == 0) { 160752c9ce25SScott Long probe_softc *softc; 160852c9ce25SScott Long 160952c9ce25SScott Long softc = (probe_softc *)old_periph->softc; 16102e3f592bSAlexander Motin TAILQ_INSERT_TAIL(&softc->request_ccbs, 16112e3f592bSAlexander Motin &request_ccb->ccb_h, periph_links.tqe); 161283c5d981SAlexander Motin softc->restart = 1; 161352c9ce25SScott Long } else { 16142e3f592bSAlexander Motin request_ccb->ccb_h.status = CAM_REQ_CMP_ERR; 16152e3f592bSAlexander Motin xpt_done(request_ccb); 16162e3f592bSAlexander Motin } 16172e3f592bSAlexander Motin } else { 16180f280cbdSWarner Losh status = cam_periph_alloc(aproberegister, NULL, aprobecleanup, 16190f280cbdSWarner Losh aprobestart, "aprobe", 162052c9ce25SScott Long CAM_PERIPH_BIO, 162152c9ce25SScott Long request_ccb->ccb_h.path, NULL, 0, 162252c9ce25SScott Long request_ccb); 162352c9ce25SScott Long 162452c9ce25SScott Long if (status != CAM_REQ_CMP) { 162552c9ce25SScott Long xpt_print(path, "xpt_scan_lun: cam_alloc_periph " 162652c9ce25SScott Long "returned an error, can't continue probe\n"); 162752c9ce25SScott Long request_ccb->ccb_h.status = status; 162852c9ce25SScott Long xpt_done(request_ccb); 162952c9ce25SScott Long } 163052c9ce25SScott Long } 1631227d67aaSAlexander Motin if (lock) 1632227d67aaSAlexander Motin xpt_path_unlock(path); 163352c9ce25SScott Long } 163452c9ce25SScott Long 163552c9ce25SScott Long static void 16360f280cbdSWarner Losh axptscandone(struct cam_periph *periph, union ccb *done_ccb) 163752c9ce25SScott Long { 163832aa80a6SAlexander Motin 163932aa80a6SAlexander Motin xpt_free_path(done_ccb->ccb_h.path); 164032aa80a6SAlexander Motin xpt_free_ccb(done_ccb); 164152c9ce25SScott Long } 164252c9ce25SScott Long 164352c9ce25SScott Long static struct cam_ed * 164452c9ce25SScott Long ata_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id) 164552c9ce25SScott Long { 164630a4094fSAlexander Motin struct ata_quirk_entry *quirk; 164752c9ce25SScott Long struct cam_ed *device; 164852c9ce25SScott Long 164952c9ce25SScott Long device = xpt_alloc_device(bus, target, lun_id); 165052c9ce25SScott Long if (device == NULL) 165152c9ce25SScott Long return (NULL); 165252c9ce25SScott Long 165352c9ce25SScott Long /* 165452c9ce25SScott Long * Take the default quirk entry until we have inquiry 165552c9ce25SScott Long * data and can determine a better quirk to use. 165652c9ce25SScott Long */ 16578dfea464SPedro F. Giffuni quirk = &ata_quirk_table[nitems(ata_quirk_table) - 1]; 165852c9ce25SScott Long device->quirk = (void *)quirk; 165930a4094fSAlexander Motin device->mintags = 0; 166030a4094fSAlexander Motin device->maxtags = 0; 166152c9ce25SScott Long bzero(&device->inq_data, sizeof(device->inq_data)); 166252c9ce25SScott Long device->inq_flags = 0; 166352c9ce25SScott Long device->queue_flags = 0; 166452c9ce25SScott Long device->serial_num = NULL; 166552c9ce25SScott Long device->serial_num_len = 0; 166652c9ce25SScott Long return (device); 166752c9ce25SScott Long } 166852c9ce25SScott Long 166952c9ce25SScott Long static void 167052c9ce25SScott Long ata_device_transport(struct cam_path *path) 167152c9ce25SScott Long { 167252c9ce25SScott Long struct ccb_pathinq cpi; 16734b997c49SAlexander Motin struct ccb_trans_settings cts; 16744b997c49SAlexander Motin struct scsi_inquiry_data *inq_buf = NULL; 16754b997c49SAlexander Motin struct ata_params *ident_buf = NULL; 167652c9ce25SScott Long 167752c9ce25SScott Long /* Get transport information from the SIM */ 1678762a7f4fSWarner Losh xpt_path_inq(&cpi, path); 167952c9ce25SScott Long 168052c9ce25SScott Long path->device->transport = cpi.transport; 16814b997c49SAlexander Motin if ((path->device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0) 16824b997c49SAlexander Motin inq_buf = &path->device->inq_data; 16834b997c49SAlexander Motin if ((path->device->flags & CAM_DEV_IDENTIFY_DATA_VALID) != 0) 16844b997c49SAlexander Motin ident_buf = &path->device->ident_data; 16854b997c49SAlexander Motin if (path->device->protocol == PROTO_ATA) { 16864b997c49SAlexander Motin path->device->protocol_version = ident_buf ? 16874b997c49SAlexander Motin ata_version(ident_buf->version_major) : cpi.protocol_version; 16884b997c49SAlexander Motin } else if (path->device->protocol == PROTO_SCSI) { 16894b997c49SAlexander Motin path->device->protocol_version = inq_buf ? 16904b997c49SAlexander Motin SID_ANSI_REV(inq_buf) : cpi.protocol_version; 169152c9ce25SScott Long } 16924b997c49SAlexander Motin path->device->transport_version = ident_buf ? 16934b997c49SAlexander Motin ata_version(ident_buf->version_major) : cpi.transport_version; 169452c9ce25SScott Long 169552c9ce25SScott Long /* Tell the controller what we think */ 169683c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 169752c9ce25SScott Long cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 169852c9ce25SScott Long cts.type = CTS_TYPE_CURRENT_SETTINGS; 169952c9ce25SScott Long cts.transport = path->device->transport; 170052c9ce25SScott Long cts.transport_version = path->device->transport_version; 170152c9ce25SScott Long cts.protocol = path->device->protocol; 170252c9ce25SScott Long cts.protocol_version = path->device->protocol_version; 170352c9ce25SScott Long cts.proto_specific.valid = 0; 17044cca1530SAlexander Motin if (ident_buf) { 17054cca1530SAlexander Motin if (path->device->transport == XPORT_ATA) { 17064cca1530SAlexander Motin cts.xport_specific.ata.atapi = 17078e6cab54SAlexander Motin (ident_buf->config == ATA_PROTO_CFA) ? 0 : 17084cca1530SAlexander Motin ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_16) ? 16 : 17094cca1530SAlexander Motin ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) ? 12 : 0; 17104cca1530SAlexander Motin cts.xport_specific.ata.valid = CTS_ATA_VALID_ATAPI; 17114cca1530SAlexander Motin } else { 17124cca1530SAlexander Motin cts.xport_specific.sata.atapi = 17138e6cab54SAlexander Motin (ident_buf->config == ATA_PROTO_CFA) ? 0 : 17144cca1530SAlexander Motin ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_16) ? 16 : 17154cca1530SAlexander Motin ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) ? 12 : 0; 17164cca1530SAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_ATAPI; 17174cca1530SAlexander Motin } 17184cca1530SAlexander Motin } else 171952c9ce25SScott Long cts.xport_specific.valid = 0; 172052c9ce25SScott Long xpt_action((union ccb *)&cts); 172152c9ce25SScott Long } 172252c9ce25SScott Long 172352c9ce25SScott Long static void 172414f900e2SWill Andrews ata_dev_advinfo(union ccb *start_ccb) 172514f900e2SWill Andrews { 172614f900e2SWill Andrews struct cam_ed *device; 172714f900e2SWill Andrews struct ccb_dev_advinfo *cdai; 172814f900e2SWill Andrews off_t amt; 172914f900e2SWill Andrews 17306a216c0bSAlexander Motin xpt_path_assert(start_ccb->ccb_h.path, MA_OWNED); 173114f900e2SWill Andrews start_ccb->ccb_h.status = CAM_REQ_INVALID; 173214f900e2SWill Andrews device = start_ccb->ccb_h.path->device; 173314f900e2SWill Andrews cdai = &start_ccb->cdai; 173414f900e2SWill Andrews switch(cdai->buftype) { 17353089bb2eSAlexander Motin case CDAI_TYPE_SCSI_DEVID: 17363089bb2eSAlexander Motin if (cdai->flags & CDAI_FLAG_STORE) 17373089bb2eSAlexander Motin return; 17383089bb2eSAlexander Motin cdai->provsiz = device->device_id_len; 17393089bb2eSAlexander Motin if (device->device_id_len == 0) 17403089bb2eSAlexander Motin break; 17413089bb2eSAlexander Motin amt = device->device_id_len; 17423089bb2eSAlexander Motin if (cdai->provsiz > cdai->bufsiz) 17433089bb2eSAlexander Motin amt = cdai->bufsiz; 17443089bb2eSAlexander Motin memcpy(cdai->buf, device->device_id, amt); 17453089bb2eSAlexander Motin break; 174614f900e2SWill Andrews case CDAI_TYPE_SERIAL_NUM: 174714f900e2SWill Andrews if (cdai->flags & CDAI_FLAG_STORE) 17483089bb2eSAlexander Motin return; 174914f900e2SWill Andrews cdai->provsiz = device->serial_num_len; 175014f900e2SWill Andrews if (device->serial_num_len == 0) 175114f900e2SWill Andrews break; 175214f900e2SWill Andrews amt = device->serial_num_len; 175314f900e2SWill Andrews if (cdai->provsiz > cdai->bufsiz) 175414f900e2SWill Andrews amt = cdai->bufsiz; 175514f900e2SWill Andrews memcpy(cdai->buf, device->serial_num, amt); 175614f900e2SWill Andrews break; 17573089bb2eSAlexander Motin case CDAI_TYPE_PHYS_PATH: 17583089bb2eSAlexander Motin if (cdai->flags & CDAI_FLAG_STORE) { 17593089bb2eSAlexander Motin if (device->physpath != NULL) 17603089bb2eSAlexander Motin free(device->physpath, M_CAMXPT); 17613089bb2eSAlexander Motin device->physpath_len = cdai->bufsiz; 17623089bb2eSAlexander Motin /* Clear existing buffer if zero length */ 17633089bb2eSAlexander Motin if (cdai->bufsiz == 0) 176414f900e2SWill Andrews break; 17653089bb2eSAlexander Motin device->physpath = malloc(cdai->bufsiz, M_CAMXPT, M_NOWAIT); 17663089bb2eSAlexander Motin if (device->physpath == NULL) { 17673089bb2eSAlexander Motin start_ccb->ccb_h.status = CAM_REQ_ABORTED; 17683089bb2eSAlexander Motin return; 17693089bb2eSAlexander Motin } 17703089bb2eSAlexander Motin memcpy(device->physpath, cdai->buf, cdai->bufsiz); 17713089bb2eSAlexander Motin } else { 17723089bb2eSAlexander Motin cdai->provsiz = device->physpath_len; 17733089bb2eSAlexander Motin if (device->physpath_len == 0) 17743089bb2eSAlexander Motin break; 17753089bb2eSAlexander Motin amt = device->physpath_len; 17763089bb2eSAlexander Motin if (cdai->provsiz > cdai->bufsiz) 17773089bb2eSAlexander Motin amt = cdai->bufsiz; 17783089bb2eSAlexander Motin memcpy(cdai->buf, device->physpath, amt); 17793089bb2eSAlexander Motin } 17803089bb2eSAlexander Motin break; 17813089bb2eSAlexander Motin default: 17823089bb2eSAlexander Motin return; 17833089bb2eSAlexander Motin } 17843089bb2eSAlexander Motin start_ccb->ccb_h.status = CAM_REQ_CMP; 17853089bb2eSAlexander Motin 17863089bb2eSAlexander Motin if (cdai->flags & CDAI_FLAG_STORE) { 17873089bb2eSAlexander Motin xpt_async(AC_ADVINFO_CHANGED, start_ccb->ccb_h.path, 17883089bb2eSAlexander Motin (void *)(uintptr_t)cdai->buftype); 178914f900e2SWill Andrews } 179014f900e2SWill Andrews } 179114f900e2SWill Andrews 179214f900e2SWill Andrews static void 179352c9ce25SScott Long ata_action(union ccb *start_ccb) 179452c9ce25SScott Long { 179552c9ce25SScott Long 179652c9ce25SScott Long switch (start_ccb->ccb_h.func_code) { 179752c9ce25SScott Long case XPT_SET_TRAN_SETTINGS: 179852c9ce25SScott Long { 179930a4094fSAlexander Motin ata_set_transfer_settings(&start_ccb->cts, 1800227d67aaSAlexander Motin start_ccb->ccb_h.path, 180152c9ce25SScott Long /*async_update*/FALSE); 180252c9ce25SScott Long break; 180352c9ce25SScott Long } 180452c9ce25SScott Long case XPT_SCAN_BUS: 18050e85f214SMatt Jacob case XPT_SCAN_TGT: 180652c9ce25SScott Long ata_scan_bus(start_ccb->ccb_h.path->periph, start_ccb); 180752c9ce25SScott Long break; 180852c9ce25SScott Long case XPT_SCAN_LUN: 180952c9ce25SScott Long ata_scan_lun(start_ccb->ccb_h.path->periph, 181052c9ce25SScott Long start_ccb->ccb_h.path, start_ccb->crcn.flags, 181152c9ce25SScott Long start_ccb); 181252c9ce25SScott Long break; 181352c9ce25SScott Long case XPT_GET_TRAN_SETTINGS: 181452c9ce25SScott Long { 1815b9c473b2SAlexander Motin ata_get_transfer_settings(&start_ccb->cts); 181652c9ce25SScott Long break; 181752c9ce25SScott Long } 18184cca1530SAlexander Motin case XPT_SCSI_IO: 18194cca1530SAlexander Motin { 18204cca1530SAlexander Motin struct cam_ed *device; 18214cca1530SAlexander Motin u_int maxlen = 0; 18224cca1530SAlexander Motin 18234cca1530SAlexander Motin device = start_ccb->ccb_h.path->device; 18244cca1530SAlexander Motin if (device->protocol == PROTO_SCSI && 18254cca1530SAlexander Motin (device->flags & CAM_DEV_IDENTIFY_DATA_VALID)) { 18264cca1530SAlexander Motin uint16_t p = 18274cca1530SAlexander Motin device->ident_data.config & ATA_PROTO_MASK; 18284cca1530SAlexander Motin 18298e6cab54SAlexander Motin maxlen = 18308e6cab54SAlexander Motin (device->ident_data.config == ATA_PROTO_CFA) ? 0 : 18318e6cab54SAlexander Motin (p == ATA_PROTO_ATAPI_16) ? 16 : 18324cca1530SAlexander Motin (p == ATA_PROTO_ATAPI_12) ? 12 : 0; 18334cca1530SAlexander Motin } 18344cca1530SAlexander Motin if (start_ccb->csio.cdb_len > maxlen) { 18354cca1530SAlexander Motin start_ccb->ccb_h.status = CAM_REQ_INVALID; 18364cca1530SAlexander Motin xpt_done(start_ccb); 18374cca1530SAlexander Motin break; 18384cca1530SAlexander Motin } 1839ee2b236bSAlexander Motin xpt_action_default(start_ccb); 1840ee2b236bSAlexander Motin break; 18414cca1530SAlexander Motin } 184214f900e2SWill Andrews case XPT_DEV_ADVINFO: 184314f900e2SWill Andrews { 184414f900e2SWill Andrews ata_dev_advinfo(start_ccb); 184514f900e2SWill Andrews break; 184614f900e2SWill Andrews } 184752c9ce25SScott Long default: 184852c9ce25SScott Long xpt_action_default(start_ccb); 184952c9ce25SScott Long break; 185052c9ce25SScott Long } 185152c9ce25SScott Long } 185252c9ce25SScott Long 185352c9ce25SScott Long static void 1854b9c473b2SAlexander Motin ata_get_transfer_settings(struct ccb_trans_settings *cts) 1855b9c473b2SAlexander Motin { 1856b9c473b2SAlexander Motin struct ccb_trans_settings_ata *ata; 1857b9c473b2SAlexander Motin struct ccb_trans_settings_scsi *scsi; 1858b9c473b2SAlexander Motin struct cam_ed *device; 1859b9c473b2SAlexander Motin 1860b9c473b2SAlexander Motin device = cts->ccb_h.path->device; 1861227d67aaSAlexander Motin xpt_action_default((union ccb *)cts); 1862b9c473b2SAlexander Motin 1863bc1bf6e8SAlexander Motin if (cts->protocol == PROTO_UNKNOWN || 1864bc1bf6e8SAlexander Motin cts->protocol == PROTO_UNSPECIFIED) { 1865bc1bf6e8SAlexander Motin cts->protocol = device->protocol; 1866bc1bf6e8SAlexander Motin cts->protocol_version = device->protocol_version; 1867bc1bf6e8SAlexander Motin } 1868bc1bf6e8SAlexander Motin 1869b9c473b2SAlexander Motin if (cts->protocol == PROTO_ATA) { 1870b9c473b2SAlexander Motin ata = &cts->proto_specific.ata; 1871b9c473b2SAlexander Motin if ((ata->valid & CTS_ATA_VALID_TQ) == 0) { 1872b9c473b2SAlexander Motin ata->valid |= CTS_ATA_VALID_TQ; 1873b9c473b2SAlexander Motin if (cts->type == CTS_TYPE_USER_SETTINGS || 1874b9c473b2SAlexander Motin (device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 || 1875b9c473b2SAlexander Motin (device->inq_flags & SID_CmdQue) != 0) 1876b9c473b2SAlexander Motin ata->flags |= CTS_ATA_FLAGS_TAG_ENB; 1877b9c473b2SAlexander Motin } 1878b9c473b2SAlexander Motin } 1879b9c473b2SAlexander Motin if (cts->protocol == PROTO_SCSI) { 1880b9c473b2SAlexander Motin scsi = &cts->proto_specific.scsi; 1881b9c473b2SAlexander Motin if ((scsi->valid & CTS_SCSI_VALID_TQ) == 0) { 1882b9c473b2SAlexander Motin scsi->valid |= CTS_SCSI_VALID_TQ; 1883b9c473b2SAlexander Motin if (cts->type == CTS_TYPE_USER_SETTINGS || 1884b9c473b2SAlexander Motin (device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 || 1885b9c473b2SAlexander Motin (device->inq_flags & SID_CmdQue) != 0) 1886b9c473b2SAlexander Motin scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 1887b9c473b2SAlexander Motin } 1888b9c473b2SAlexander Motin } 1889bc1bf6e8SAlexander Motin 1890bc1bf6e8SAlexander Motin if (cts->transport == XPORT_UNKNOWN || 1891bc1bf6e8SAlexander Motin cts->transport == XPORT_UNSPECIFIED) { 1892bc1bf6e8SAlexander Motin cts->transport = device->transport; 1893bc1bf6e8SAlexander Motin cts->transport_version = device->transport_version; 1894bc1bf6e8SAlexander Motin } 1895b9c473b2SAlexander Motin } 1896b9c473b2SAlexander Motin 1897b9c473b2SAlexander Motin static void 1898227d67aaSAlexander Motin ata_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_path *path, 189952c9ce25SScott Long int async_update) 190052c9ce25SScott Long { 190152c9ce25SScott Long struct ccb_pathinq cpi; 1902b9c473b2SAlexander Motin struct ccb_trans_settings_ata *ata; 190352c9ce25SScott Long struct ccb_trans_settings_scsi *scsi; 1904b9c473b2SAlexander Motin struct ata_params *ident_data; 190552c9ce25SScott Long struct scsi_inquiry_data *inq_data; 1906227d67aaSAlexander Motin struct cam_ed *device; 190752c9ce25SScott Long 1908227d67aaSAlexander Motin if (path == NULL || (device = path->device) == NULL) { 190952c9ce25SScott Long cts->ccb_h.status = CAM_PATH_INVALID; 191052c9ce25SScott Long xpt_done((union ccb *)cts); 191152c9ce25SScott Long return; 191252c9ce25SScott Long } 191352c9ce25SScott Long 191452c9ce25SScott Long if (cts->protocol == PROTO_UNKNOWN 191552c9ce25SScott Long || cts->protocol == PROTO_UNSPECIFIED) { 191652c9ce25SScott Long cts->protocol = device->protocol; 191752c9ce25SScott Long cts->protocol_version = device->protocol_version; 191852c9ce25SScott Long } 191952c9ce25SScott Long 192052c9ce25SScott Long if (cts->protocol_version == PROTO_VERSION_UNKNOWN 192152c9ce25SScott Long || cts->protocol_version == PROTO_VERSION_UNSPECIFIED) 192252c9ce25SScott Long cts->protocol_version = device->protocol_version; 192352c9ce25SScott Long 192452c9ce25SScott Long if (cts->protocol != device->protocol) { 1925227d67aaSAlexander Motin xpt_print(path, "Uninitialized Protocol %x:%x?\n", 192652c9ce25SScott Long cts->protocol, device->protocol); 192752c9ce25SScott Long cts->protocol = device->protocol; 192852c9ce25SScott Long } 192952c9ce25SScott Long 193052c9ce25SScott Long if (cts->protocol_version > device->protocol_version) { 193152c9ce25SScott Long if (bootverbose) { 1932227d67aaSAlexander Motin xpt_print(path, "Down reving Protocol " 193352c9ce25SScott Long "Version from %d to %d?\n", cts->protocol_version, 193452c9ce25SScott Long device->protocol_version); 193552c9ce25SScott Long } 193652c9ce25SScott Long cts->protocol_version = device->protocol_version; 193752c9ce25SScott Long } 193852c9ce25SScott Long 193952c9ce25SScott Long if (cts->transport == XPORT_UNKNOWN 194052c9ce25SScott Long || cts->transport == XPORT_UNSPECIFIED) { 194152c9ce25SScott Long cts->transport = device->transport; 194252c9ce25SScott Long cts->transport_version = device->transport_version; 194352c9ce25SScott Long } 194452c9ce25SScott Long 194552c9ce25SScott Long if (cts->transport_version == XPORT_VERSION_UNKNOWN 194652c9ce25SScott Long || cts->transport_version == XPORT_VERSION_UNSPECIFIED) 194752c9ce25SScott Long cts->transport_version = device->transport_version; 194852c9ce25SScott Long 194952c9ce25SScott Long if (cts->transport != device->transport) { 1950227d67aaSAlexander Motin xpt_print(path, "Uninitialized Transport %x:%x?\n", 195152c9ce25SScott Long cts->transport, device->transport); 195252c9ce25SScott Long cts->transport = device->transport; 195352c9ce25SScott Long } 195452c9ce25SScott Long 195552c9ce25SScott Long if (cts->transport_version > device->transport_version) { 195652c9ce25SScott Long if (bootverbose) { 1957227d67aaSAlexander Motin xpt_print(path, "Down reving Transport " 195852c9ce25SScott Long "Version from %d to %d?\n", cts->transport_version, 195952c9ce25SScott Long device->transport_version); 196052c9ce25SScott Long } 196152c9ce25SScott Long cts->transport_version = device->transport_version; 196252c9ce25SScott Long } 196352c9ce25SScott Long 1964b9c473b2SAlexander Motin ident_data = &device->ident_data; 196552c9ce25SScott Long inq_data = &device->inq_data; 1966b9c473b2SAlexander Motin if (cts->protocol == PROTO_ATA) 1967b9c473b2SAlexander Motin ata = &cts->proto_specific.ata; 1968b9c473b2SAlexander Motin else 1969b9c473b2SAlexander Motin ata = NULL; 1970b9c473b2SAlexander Motin if (cts->protocol == PROTO_SCSI) 197152c9ce25SScott Long scsi = &cts->proto_specific.scsi; 1972b9c473b2SAlexander Motin else 1973b9c473b2SAlexander Motin scsi = NULL; 1974762a7f4fSWarner Losh xpt_path_inq(&cpi, path); 197552c9ce25SScott Long 1976b9c473b2SAlexander Motin /* Sanity checking */ 197752c9ce25SScott Long if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0 1978b9c473b2SAlexander Motin || (ata && (ident_data->satacapabilities & ATA_SUPPORT_NCQ) == 0) 1979b9c473b2SAlexander Motin || (scsi && (INQ_DATA_TQ_ENABLED(inq_data)) == 0) 198052c9ce25SScott Long || (device->queue_flags & SCP_QUEUE_DQUE) != 0 198152c9ce25SScott Long || (device->mintags == 0)) { 198252c9ce25SScott Long /* 198352c9ce25SScott Long * Can't tag on hardware that doesn't support tags, 198452c9ce25SScott Long * doesn't have it enabled, or has broken tag support. 198552c9ce25SScott Long */ 1986b9c473b2SAlexander Motin if (ata) 1987b9c473b2SAlexander Motin ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB; 1988b9c473b2SAlexander Motin if (scsi) 198952c9ce25SScott Long scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 199052c9ce25SScott Long } 199152c9ce25SScott Long 1992b9c473b2SAlexander Motin /* Start/stop tags use. */ 1993b9c473b2SAlexander Motin if (cts->type == CTS_TYPE_CURRENT_SETTINGS && 1994b9c473b2SAlexander Motin ((ata && (ata->valid & CTS_ATA_VALID_TQ) != 0) || 1995b9c473b2SAlexander Motin (scsi && (scsi->valid & CTS_SCSI_VALID_TQ) != 0))) { 1996b9c473b2SAlexander Motin int nowt, newt = 0; 199752c9ce25SScott Long 1998b9c473b2SAlexander Motin nowt = ((device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 || 1999b9c473b2SAlexander Motin (device->inq_flags & SID_CmdQue) != 0); 2000b9c473b2SAlexander Motin if (ata) 2001b9c473b2SAlexander Motin newt = (ata->flags & CTS_ATA_FLAGS_TAG_ENB) != 0; 2002b9c473b2SAlexander Motin if (scsi) 2003b9c473b2SAlexander Motin newt = (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0; 200452c9ce25SScott Long 2005b9c473b2SAlexander Motin if (newt && !nowt) { 200652c9ce25SScott Long /* 200752c9ce25SScott Long * Delay change to use tags until after a 200852c9ce25SScott Long * few commands have gone to this device so 200952c9ce25SScott Long * the controller has time to perform transfer 201052c9ce25SScott Long * negotiations without tagged messages getting 201152c9ce25SScott Long * in the way. 201252c9ce25SScott Long */ 201352c9ce25SScott Long device->tag_delay_count = CAM_TAG_DELAY_COUNT; 201452c9ce25SScott Long device->flags |= CAM_DEV_TAG_AFTER_COUNT; 2015b9c473b2SAlexander Motin } else if (nowt && !newt) 2016227d67aaSAlexander Motin xpt_stop_tags(path); 201752c9ce25SScott Long } 2018b9c473b2SAlexander Motin 201952c9ce25SScott Long if (async_update == FALSE) 2020227d67aaSAlexander Motin xpt_action_default((union ccb *)cts); 202152c9ce25SScott Long } 202252c9ce25SScott Long 202352c9ce25SScott Long /* 202452c9ce25SScott Long * Handle any per-device event notifications that require action by the XPT. 202552c9ce25SScott Long */ 202652c9ce25SScott Long static void 202752c9ce25SScott Long ata_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target, 202852c9ce25SScott Long struct cam_ed *device, void *async_arg) 202952c9ce25SScott Long { 203052c9ce25SScott Long cam_status status; 203152c9ce25SScott Long struct cam_path newpath; 203252c9ce25SScott Long 203352c9ce25SScott Long /* 203452c9ce25SScott Long * We only need to handle events for real devices. 203552c9ce25SScott Long */ 203652c9ce25SScott Long if (target->target_id == CAM_TARGET_WILDCARD 203752c9ce25SScott Long || device->lun_id == CAM_LUN_WILDCARD) 203852c9ce25SScott Long return; 203952c9ce25SScott Long 204052c9ce25SScott Long /* 204152c9ce25SScott Long * We need our own path with wildcards expanded to 204252c9ce25SScott Long * handle certain types of events. 204352c9ce25SScott Long */ 204452c9ce25SScott Long if ((async_code == AC_SENT_BDR) 204552c9ce25SScott Long || (async_code == AC_BUS_RESET) 204652c9ce25SScott Long || (async_code == AC_INQ_CHANGED)) 204752c9ce25SScott Long status = xpt_compile_path(&newpath, NULL, 204852c9ce25SScott Long bus->path_id, 204952c9ce25SScott Long target->target_id, 205052c9ce25SScott Long device->lun_id); 205152c9ce25SScott Long else 205252c9ce25SScott Long status = CAM_REQ_CMP_ERR; 205352c9ce25SScott Long 205452c9ce25SScott Long if (status == CAM_REQ_CMP) { 205552c9ce25SScott Long if (async_code == AC_INQ_CHANGED) { 205652c9ce25SScott Long /* 205752c9ce25SScott Long * We've sent a start unit command, or 205852c9ce25SScott Long * something similar to a device that 205952c9ce25SScott Long * may have caused its inquiry data to 206052c9ce25SScott Long * change. So we re-scan the device to 206152c9ce25SScott Long * refresh the inquiry data for it. 206252c9ce25SScott Long */ 206352c9ce25SScott Long ata_scan_lun(newpath.periph, &newpath, 206452c9ce25SScott Long CAM_EXPECT_INQ_CHANGE, NULL); 206583c5d981SAlexander Motin } else { 206683c5d981SAlexander Motin /* We need to reinitialize device after reset. */ 206783c5d981SAlexander Motin ata_scan_lun(newpath.periph, &newpath, 206883c5d981SAlexander Motin 0, NULL); 206952c9ce25SScott Long } 207052c9ce25SScott Long xpt_release_path(&newpath); 2071f98d7a47SAlexander Motin } else if (async_code == AC_LOST_DEVICE && 2072f98d7a47SAlexander Motin (device->flags & CAM_DEV_UNCONFIGURED) == 0) { 207352c9ce25SScott Long device->flags |= CAM_DEV_UNCONFIGURED; 2074f98d7a47SAlexander Motin xpt_release_device(device); 207552c9ce25SScott Long } else if (async_code == AC_TRANSFER_NEG) { 207652c9ce25SScott Long struct ccb_trans_settings *settings; 2077227d67aaSAlexander Motin struct cam_path path; 207852c9ce25SScott Long 207952c9ce25SScott Long settings = (struct ccb_trans_settings *)async_arg; 2080227d67aaSAlexander Motin xpt_compile_path(&path, NULL, bus->path_id, target->target_id, 2081227d67aaSAlexander Motin device->lun_id); 2082227d67aaSAlexander Motin ata_set_transfer_settings(settings, &path, 208352c9ce25SScott Long /*async_update*/TRUE); 2084227d67aaSAlexander Motin xpt_release_path(&path); 208552c9ce25SScott Long } 208652c9ce25SScott Long } 208752c9ce25SScott Long 208857079b17SAlexander Motin static void 20895d01277fSScott Long _ata_announce_periph(struct cam_periph *periph, struct ccb_trans_settings *cts, u_int *speed) 209057079b17SAlexander Motin { 209157079b17SAlexander Motin struct ccb_pathinq cpi; 209257079b17SAlexander Motin struct cam_path *path = periph->path; 209357079b17SAlexander Motin 2094227d67aaSAlexander Motin cam_periph_assert(periph, MA_OWNED); 209557079b17SAlexander Motin 20965d01277fSScott Long xpt_setup_ccb(&cts->ccb_h, path, CAM_PRIORITY_NORMAL); 20975d01277fSScott Long cts->ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 20985d01277fSScott Long cts->type = CTS_TYPE_CURRENT_SETTINGS; 20995d01277fSScott Long xpt_action((union ccb*)cts); 21005d01277fSScott Long if ((cts->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 210157079b17SAlexander Motin return; 210257079b17SAlexander Motin /* Ask the SIM for its base transfer speed */ 2103762a7f4fSWarner Losh xpt_path_inq(&cpi, path); 210457079b17SAlexander Motin /* Report connection speed */ 21055d01277fSScott Long *speed = cpi.base_transfer_speed; 21065d01277fSScott Long if (cts->transport == XPORT_ATA) { 2107b9c473b2SAlexander Motin struct ccb_trans_settings_pata *pata = 21085d01277fSScott Long &cts->xport_specific.ata; 210957079b17SAlexander Motin 2110b9c473b2SAlexander Motin if (pata->valid & CTS_ATA_VALID_MODE) 21115d01277fSScott Long *speed = ata_mode2speed(pata->mode); 211257079b17SAlexander Motin } 21135d01277fSScott Long if (cts->transport == XPORT_SATA) { 211457079b17SAlexander Motin struct ccb_trans_settings_sata *sata = 21155d01277fSScott Long &cts->xport_specific.sata; 211657079b17SAlexander Motin 211757079b17SAlexander Motin if (sata->valid & CTS_SATA_VALID_REVISION) 21185d01277fSScott Long *speed = ata_revision2speed(sata->revision); 211957079b17SAlexander Motin } 21205d01277fSScott Long } 21215d01277fSScott Long 21225d01277fSScott Long static void 21235d01277fSScott Long ata_announce_periph(struct cam_periph *periph) 21245d01277fSScott Long { 21255d01277fSScott Long struct ccb_trans_settings cts; 21265d01277fSScott Long u_int speed, mb; 21275d01277fSScott Long 21285d01277fSScott Long _ata_announce_periph(periph, &cts, &speed); 21295d01277fSScott Long if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 21305d01277fSScott Long return; 21315d01277fSScott Long 213257079b17SAlexander Motin mb = speed / 1000; 213357079b17SAlexander Motin if (mb > 0) 213457079b17SAlexander Motin printf("%s%d: %d.%03dMB/s transfers", 213557079b17SAlexander Motin periph->periph_name, periph->unit_number, 213657079b17SAlexander Motin mb, speed % 1000); 213757079b17SAlexander Motin else 213857079b17SAlexander Motin printf("%s%d: %dKB/s transfers", periph->periph_name, 213957079b17SAlexander Motin periph->unit_number, speed); 214057079b17SAlexander Motin /* Report additional information about connection */ 21415d01277fSScott Long if (cts.transport == XPORT_ATA) { 2142b9c473b2SAlexander Motin struct ccb_trans_settings_pata *pata = 214357079b17SAlexander Motin &cts.xport_specific.ata; 214457079b17SAlexander Motin 214557079b17SAlexander Motin printf(" ("); 2146b9c473b2SAlexander Motin if (pata->valid & CTS_ATA_VALID_MODE) 2147b9c473b2SAlexander Motin printf("%s, ", ata_mode2string(pata->mode)); 2148b9c473b2SAlexander Motin if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0) 2149b9c473b2SAlexander Motin printf("ATAPI %dbytes, ", pata->atapi); 2150b9c473b2SAlexander Motin if (pata->valid & CTS_ATA_VALID_BYTECOUNT) 2151b9c473b2SAlexander Motin printf("PIO %dbytes", pata->bytecount); 215257079b17SAlexander Motin printf(")"); 215357079b17SAlexander Motin } 21545d01277fSScott Long if (cts.transport == XPORT_SATA) { 215557079b17SAlexander Motin struct ccb_trans_settings_sata *sata = 215657079b17SAlexander Motin &cts.xport_specific.sata; 215757079b17SAlexander Motin 215857079b17SAlexander Motin printf(" ("); 215957079b17SAlexander Motin if (sata->valid & CTS_SATA_VALID_REVISION) 216057079b17SAlexander Motin printf("SATA %d.x, ", sata->revision); 216157079b17SAlexander Motin else 216257079b17SAlexander Motin printf("SATA, "); 216357079b17SAlexander Motin if (sata->valid & CTS_SATA_VALID_MODE) 216457079b17SAlexander Motin printf("%s, ", ata_mode2string(sata->mode)); 216557079b17SAlexander Motin if ((sata->valid & CTS_ATA_VALID_ATAPI) && sata->atapi != 0) 216657079b17SAlexander Motin printf("ATAPI %dbytes, ", sata->atapi); 216757079b17SAlexander Motin if (sata->valid & CTS_SATA_VALID_BYTECOUNT) 216857079b17SAlexander Motin printf("PIO %dbytes", sata->bytecount); 216957079b17SAlexander Motin printf(")"); 217057079b17SAlexander Motin } 217157079b17SAlexander Motin printf("\n"); 217257079b17SAlexander Motin } 217308f13879SWarner Losh 217408f13879SWarner Losh static void 21755d01277fSScott Long ata_announce_periph_sbuf(struct cam_periph *periph, struct sbuf *sb) 21765d01277fSScott Long { 21775d01277fSScott Long struct ccb_trans_settings cts; 21785d01277fSScott Long u_int speed, mb; 21795d01277fSScott Long 21805d01277fSScott Long _ata_announce_periph(periph, &cts, &speed); 21815d01277fSScott Long if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 21825d01277fSScott Long return; 21835d01277fSScott Long 21845d01277fSScott Long mb = speed / 1000; 21855d01277fSScott Long if (mb > 0) 21865d01277fSScott Long sbuf_printf(sb, "%s%d: %d.%03dMB/s transfers", 21875d01277fSScott Long periph->periph_name, periph->unit_number, 21885d01277fSScott Long mb, speed % 1000); 21895d01277fSScott Long else 21905d01277fSScott Long sbuf_printf(sb, "%s%d: %dKB/s transfers", periph->periph_name, 21915d01277fSScott Long periph->unit_number, speed); 21925d01277fSScott Long /* Report additional information about connection */ 21935d01277fSScott Long if (cts.transport == XPORT_ATA) { 21945d01277fSScott Long struct ccb_trans_settings_pata *pata = 21955d01277fSScott Long &cts.xport_specific.ata; 21965d01277fSScott Long 21975d01277fSScott Long sbuf_printf(sb, " ("); 21985d01277fSScott Long if (pata->valid & CTS_ATA_VALID_MODE) 21995d01277fSScott Long sbuf_printf(sb, "%s, ", ata_mode2string(pata->mode)); 22005d01277fSScott Long if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0) 22015d01277fSScott Long sbuf_printf(sb, "ATAPI %dbytes, ", pata->atapi); 22025d01277fSScott Long if (pata->valid & CTS_ATA_VALID_BYTECOUNT) 22035d01277fSScott Long sbuf_printf(sb, "PIO %dbytes", pata->bytecount); 22045d01277fSScott Long sbuf_printf(sb, ")"); 22055d01277fSScott Long } 22065d01277fSScott Long if (cts.transport == XPORT_SATA) { 22075d01277fSScott Long struct ccb_trans_settings_sata *sata = 22085d01277fSScott Long &cts.xport_specific.sata; 22095d01277fSScott Long 22105d01277fSScott Long sbuf_printf(sb, " ("); 22115d01277fSScott Long if (sata->valid & CTS_SATA_VALID_REVISION) 22125d01277fSScott Long sbuf_printf(sb, "SATA %d.x, ", sata->revision); 22135d01277fSScott Long else 22145d01277fSScott Long sbuf_printf(sb, "SATA, "); 22155d01277fSScott Long if (sata->valid & CTS_SATA_VALID_MODE) 22165d01277fSScott Long sbuf_printf(sb, "%s, ", ata_mode2string(sata->mode)); 22175d01277fSScott Long if ((sata->valid & CTS_ATA_VALID_ATAPI) && sata->atapi != 0) 22185d01277fSScott Long sbuf_printf(sb, "ATAPI %dbytes, ", sata->atapi); 22195d01277fSScott Long if (sata->valid & CTS_SATA_VALID_BYTECOUNT) 22205d01277fSScott Long sbuf_printf(sb, "PIO %dbytes", sata->bytecount); 22215d01277fSScott Long sbuf_printf(sb, ")"); 22225d01277fSScott Long } 22235d01277fSScott Long sbuf_printf(sb, "\n"); 22245d01277fSScott Long } 22255d01277fSScott Long 22265d01277fSScott Long static void 22275d01277fSScott Long ata_proto_announce_sbuf(struct cam_ed *device, struct sbuf *sb) 22285d01277fSScott Long { 22295d01277fSScott Long ata_print_ident_sbuf(&device->ident_data, sb); 22305d01277fSScott Long } 22315d01277fSScott Long 22325d01277fSScott Long static void 223308f13879SWarner Losh ata_proto_announce(struct cam_ed *device) 223408f13879SWarner Losh { 223508f13879SWarner Losh ata_print_ident(&device->ident_data); 223608f13879SWarner Losh } 223708f13879SWarner Losh 223808f13879SWarner Losh static void 223908f13879SWarner Losh ata_proto_denounce(struct cam_ed *device) 224008f13879SWarner Losh { 224108f13879SWarner Losh ata_print_ident_short(&device->ident_data); 224208f13879SWarner Losh } 224308f13879SWarner Losh 224408f13879SWarner Losh static void 22455d01277fSScott Long ata_proto_denounce_sbuf(struct cam_ed *device, struct sbuf *sb) 22465d01277fSScott Long { 22475d01277fSScott Long ata_print_ident_short_sbuf(&device->ident_data, sb); 22485d01277fSScott Long } 22495d01277fSScott Long 22505d01277fSScott Long static void 22515d01277fSScott Long semb_proto_announce_sbuf(struct cam_ed *device, struct sbuf *sb) 22525d01277fSScott Long { 22535d01277fSScott Long semb_print_ident_sbuf((struct sep_identify_data *)&device->ident_data, sb); 22545d01277fSScott Long } 22555d01277fSScott Long 22565d01277fSScott Long static void 225708f13879SWarner Losh semb_proto_announce(struct cam_ed *device) 225808f13879SWarner Losh { 225908f13879SWarner Losh semb_print_ident((struct sep_identify_data *)&device->ident_data); 226008f13879SWarner Losh } 226108f13879SWarner Losh 226208f13879SWarner Losh static void 226308f13879SWarner Losh semb_proto_denounce(struct cam_ed *device) 226408f13879SWarner Losh { 226508f13879SWarner Losh semb_print_ident_short((struct sep_identify_data *)&device->ident_data); 226608f13879SWarner Losh } 226708f13879SWarner Losh 226808f13879SWarner Losh static void 22695d01277fSScott Long semb_proto_denounce_sbuf(struct cam_ed *device, struct sbuf *sb) 22705d01277fSScott Long { 22715d01277fSScott Long semb_print_ident_short_sbuf((struct sep_identify_data *)&device->ident_data, sb); 22725d01277fSScott Long } 22735d01277fSScott Long 22745d01277fSScott Long static void 227508f13879SWarner Losh ata_proto_debug_out(union ccb *ccb) 227608f13879SWarner Losh { 227708f13879SWarner Losh char cdb_str[(sizeof(struct ata_cmd) * 3) + 1]; 227808f13879SWarner Losh 227908f13879SWarner Losh if (ccb->ccb_h.func_code != XPT_ATA_IO) 228008f13879SWarner Losh return; 228108f13879SWarner Losh 228208f13879SWarner Losh CAM_DEBUG(ccb->ccb_h.path, 228308f13879SWarner Losh CAM_DEBUG_CDB,("%s. ACB: %s\n", ata_op_string(&ccb->ataio.cmd), 228408f13879SWarner Losh ata_cmd_string(&ccb->ataio.cmd, cdb_str, sizeof(cdb_str)))); 228508f13879SWarner Losh } 2286