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 2739982b3eeSConrad Meyer aprobe_periph_init(void) 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 729ec5325dbSEdward Tomasz Napierala bzero(&cts, sizeof(cts)); 73083c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE); 73152c9ce25SScott Long cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 73252c9ce25SScott Long cts.type = CTS_TYPE_USER_SETTINGS; 73352c9ce25SScott Long xpt_action((union ccb *)&cts); 734b9c473b2SAlexander Motin if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 73552c9ce25SScott Long return; 736b9c473b2SAlexander Motin cts.xport_specific.valid = 0; 73752c9ce25SScott Long cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 73852c9ce25SScott Long cts.type = CTS_TYPE_CURRENT_SETTINGS; 73952c9ce25SScott Long xpt_action((union ccb *)&cts); 74052c9ce25SScott Long } 74152c9ce25SScott Long 74252c9ce25SScott Long static void 7430f280cbdSWarner Losh aprobedone(struct cam_periph *periph, union ccb *done_ccb) 74452c9ce25SScott Long { 745c8039fc6SAlexander Motin struct ccb_trans_settings cts; 74652c9ce25SScott Long struct ata_params *ident_buf; 7473089bb2eSAlexander Motin struct scsi_inquiry_data *inq_buf; 74852c9ce25SScott Long probe_softc *softc; 74952c9ce25SScott Long struct cam_path *path; 75026bdaeddSAlexander Motin cam_status status; 75152c9ce25SScott Long u_int32_t priority; 75276d843daSAlexander Motin u_int caps, oif; 75376d843daSAlexander Motin int changed, found = 1; 7543089bb2eSAlexander Motin static const uint8_t fake_device_id_hdr[8] = 7553089bb2eSAlexander Motin {0, SVPD_DEVICE_ID, 0, 12, 7563089bb2eSAlexander Motin SVPD_ID_CODESET_BINARY, SVPD_ID_TYPE_NAA, 0, 8}; 75752c9ce25SScott Long 7580f280cbdSWarner Losh CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("aprobedone\n")); 75952c9ce25SScott Long 76052c9ce25SScott Long softc = (probe_softc *)periph->softc; 76152c9ce25SScott Long path = done_ccb->ccb_h.path; 76252c9ce25SScott Long priority = done_ccb->ccb_h.pinfo.priority; 76352c9ce25SScott Long ident_buf = &path->device->ident_data; 7643089bb2eSAlexander Motin inq_buf = &path->device->inq_data; 76552c9ce25SScott Long 7661e637ba6SAlexander Motin if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 7670191d9b3SAlexander Motin if (cam_periph_error(done_ccb, 768553484aeSWarner Losh 0, softc->restart ? (SF_NO_RECOVERY | SF_NO_RETRY) : 0 769553484aeSWarner Losh ) == ERESTART) { 770cccf4220SAlexander Motin out: 771cccf4220SAlexander Motin /* Drop freeze taken due to CAM_DEV_QFREEZE flag set. */ 772cccf4220SAlexander Motin cam_release_devq(path, 0, 0, 0, FALSE); 7731e637ba6SAlexander Motin return; 774cccf4220SAlexander Motin } 77525a519a9SAlexander Motin if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 7761e637ba6SAlexander Motin /* Don't wedge the queue */ 777cccf4220SAlexander Motin xpt_release_devq(path, /*count*/1, /*run_queue*/TRUE); 7781e637ba6SAlexander Motin } 77926bdaeddSAlexander Motin status = done_ccb->ccb_h.status & CAM_STATUS_MASK; 78025a519a9SAlexander Motin if (softc->restart) { 78125a519a9SAlexander Motin softc->faults++; 78225a519a9SAlexander Motin if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == 78325a519a9SAlexander Motin CAM_CMD_TIMEOUT) 78425a519a9SAlexander Motin softc->faults += 4; 78525a519a9SAlexander Motin if (softc->faults < 10) 78625a519a9SAlexander Motin goto done; 78725a519a9SAlexander Motin else 78825a519a9SAlexander Motin softc->restart = 0; 78926bdaeddSAlexander Motin 7901e637ba6SAlexander Motin /* Old PIO2 devices may not support mode setting. */ 79126bdaeddSAlexander Motin } else if (softc->action == PROBE_SETMODE && 79226bdaeddSAlexander Motin status == CAM_ATA_STATUS_ERROR && 7931e637ba6SAlexander Motin ata_max_pmode(ident_buf) <= ATA_PIO2 && 79426bdaeddSAlexander Motin (ident_buf->capabilities1 & ATA_SUPPORT_IORDY) == 0) { 7951e637ba6SAlexander Motin goto noerror; 79626bdaeddSAlexander Motin 79726bdaeddSAlexander Motin /* 79826bdaeddSAlexander Motin * Some old WD SATA disks report supported and enabled 79926bdaeddSAlexander Motin * device-initiated interface power management, but return 80026bdaeddSAlexander Motin * ABORT on attempt to disable it. 80126bdaeddSAlexander Motin */ 80226bdaeddSAlexander Motin } else if (softc->action == PROBE_SETPM && 80326bdaeddSAlexander Motin status == CAM_ATA_STATUS_ERROR) { 80426bdaeddSAlexander Motin goto noerror; 805025e2c12SAlexander Motin 806025e2c12SAlexander Motin /* 807b5617df5SAndriy Gapon * Some old WD SATA disks have broken SPINUP handling. 808b5617df5SAndriy Gapon * If we really fail to spin up the disk, then there will be 809b5617df5SAndriy Gapon * some media access errors later on, but at least we will 810b5617df5SAndriy Gapon * have a device to interact with for recovery attempts. 811b5617df5SAndriy Gapon */ 812b5617df5SAndriy Gapon } else if (softc->action == PROBE_SPINUP && 813b5617df5SAndriy Gapon status == CAM_ATA_STATUS_ERROR) { 814b5617df5SAndriy Gapon goto noerror; 815b5617df5SAndriy Gapon 816b5617df5SAndriy Gapon /* 817025e2c12SAlexander Motin * Some HP SATA disks report supported DMA Auto-Activation, 818025e2c12SAlexander Motin * but return ABORT on attempt to enable it. 819025e2c12SAlexander Motin */ 820025e2c12SAlexander Motin } else if (softc->action == PROBE_SETDMAAA && 821025e2c12SAlexander Motin status == CAM_ATA_STATUS_ERROR) { 822025e2c12SAlexander Motin goto noerror; 8233089bb2eSAlexander Motin 8243089bb2eSAlexander Motin /* 8253089bb2eSAlexander Motin * SES and SAF-TE SEPs have different IDENTIFY commands, 8263089bb2eSAlexander Motin * but SATA specification doesn't tell how to identify them. 8273089bb2eSAlexander Motin * Until better way found, just try another if first fail. 8283089bb2eSAlexander Motin */ 8293089bb2eSAlexander Motin } else if (softc->action == PROBE_IDENTIFY_SES && 8303089bb2eSAlexander Motin status == CAM_ATA_STATUS_ERROR) { 8313089bb2eSAlexander Motin PROBE_SET_ACTION(softc, PROBE_IDENTIFY_SAFTE); 8323089bb2eSAlexander Motin xpt_release_ccb(done_ccb); 8333089bb2eSAlexander Motin xpt_schedule(periph, priority); 834cccf4220SAlexander Motin goto out; 83526bdaeddSAlexander Motin } 83626bdaeddSAlexander Motin 8371e637ba6SAlexander Motin /* 8381e637ba6SAlexander Motin * If we get to this point, we got an error status back 8391e637ba6SAlexander Motin * from the inquiry and the error status doesn't require 8401e637ba6SAlexander Motin * automatically retrying the command. Therefore, the 8411e637ba6SAlexander Motin * inquiry failed. If we had inquiry information before 8421e637ba6SAlexander Motin * for this device, but this latest inquiry command failed, 8431e637ba6SAlexander Motin * the device has probably gone away. If this device isn't 8441e637ba6SAlexander Motin * already marked unconfigured, notify the peripheral 8451e637ba6SAlexander Motin * drivers that this device is no more. 8461e637ba6SAlexander Motin */ 84725a519a9SAlexander Motin device_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0) 8481e637ba6SAlexander Motin xpt_async(AC_LOST_DEVICE, path, NULL); 849a4d953c4SAlexander Motin PROBE_SET_ACTION(softc, PROBE_INVALID); 8501e637ba6SAlexander Motin found = 0; 8511e637ba6SAlexander Motin goto done; 8521e637ba6SAlexander Motin } 8531e637ba6SAlexander Motin noerror: 854a9b8edb1SAlexander Motin if (softc->restart) 855a9b8edb1SAlexander Motin goto done; 85652c9ce25SScott Long switch (softc->action) { 85752c9ce25SScott Long case PROBE_RESET: 8581e637ba6SAlexander Motin { 85952c9ce25SScott Long int sign = (done_ccb->ataio.res.lba_high << 8) + 86052c9ce25SScott Long done_ccb->ataio.res.lba_mid; 861a4d953c4SAlexander Motin CAM_DEBUG(path, CAM_DEBUG_PROBE, 862a4d953c4SAlexander Motin ("SIGNATURE: %04x\n", sign)); 86352c9ce25SScott Long if (sign == 0x0000 && 86452c9ce25SScott Long done_ccb->ccb_h.target_id != 15) { 86552c9ce25SScott Long path->device->protocol = PROTO_ATA; 86652c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 86752c9ce25SScott Long } else if (sign == 0x9669 && 86852c9ce25SScott Long done_ccb->ccb_h.target_id == 15) { 86952c9ce25SScott Long /* Report SIM that PM is present. */ 87052c9ce25SScott Long bzero(&cts, sizeof(cts)); 87183c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 87252c9ce25SScott Long cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 87352c9ce25SScott Long cts.type = CTS_TYPE_CURRENT_SETTINGS; 87452c9ce25SScott Long cts.xport_specific.sata.pm_present = 1; 87552c9ce25SScott Long cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; 87652c9ce25SScott Long xpt_action((union ccb *)&cts); 87752c9ce25SScott Long path->device->protocol = PROTO_SATAPM; 87852c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_PM_PID); 8793089bb2eSAlexander Motin } else if (sign == 0xc33c && 8803089bb2eSAlexander Motin done_ccb->ccb_h.target_id != 15) { 8813089bb2eSAlexander Motin path->device->protocol = PROTO_SEMB; 8823089bb2eSAlexander Motin PROBE_SET_ACTION(softc, PROBE_IDENTIFY_SES); 88352c9ce25SScott Long } else if (sign == 0xeb14 && 88452c9ce25SScott Long done_ccb->ccb_h.target_id != 15) { 88552c9ce25SScott Long path->device->protocol = PROTO_SCSI; 88652c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 88752c9ce25SScott Long } else { 88852c9ce25SScott Long if (done_ccb->ccb_h.target_id != 15) { 88952c9ce25SScott Long xpt_print(path, 89052c9ce25SScott Long "Unexpected signature 0x%04x\n", sign); 89152c9ce25SScott Long } 89265d0fb03SAlexander Motin goto device_fail; 89352c9ce25SScott Long } 89452c9ce25SScott Long xpt_release_ccb(done_ccb); 89552c9ce25SScott Long xpt_schedule(periph, priority); 896cccf4220SAlexander Motin goto out; 89752c9ce25SScott Long } 89852c9ce25SScott Long case PROBE_IDENTIFY: 89952c9ce25SScott Long { 900699f853bSAlexander Motin struct ccb_pathinq cpi; 901a11463fdSSepherosa Ziehau int veto = 0; 90252c9ce25SScott Long 90376769dc1SWarner Losh /* 90476769dc1SWarner Losh * Convert to host byte order, and fix the strings. 90576769dc1SWarner Losh */ 906a9b8edb1SAlexander Motin ident_buf = &softc->ident_data; 907296218d4SWarner Losh ata_param_fixup(ident_buf); 90876769dc1SWarner Losh 90976769dc1SWarner Losh /* 91076769dc1SWarner Losh * Allow others to veto this ATA disk attachment. This 91176769dc1SWarner Losh * is mainly used by VMs, whose disk controllers may 91276769dc1SWarner Losh * share the disks with the simulated ATA controllers. 91376769dc1SWarner Losh */ 91476769dc1SWarner Losh EVENTHANDLER_INVOKE(ada_probe_veto, path, ident_buf, &veto); 91576769dc1SWarner Losh if (veto) { 91676769dc1SWarner Losh goto device_fail; 91776769dc1SWarner Losh } 91876769dc1SWarner Losh 9194ef08dc5SAlexander Motin /* Device may need spin-up before IDENTIFY become valid. */ 9201254b680SAlexander Motin if ((ident_buf->specconf == 0x37c8 || 9211254b680SAlexander Motin ident_buf->specconf == 0x738c) && 9221254b680SAlexander Motin ((ident_buf->config & ATA_RESP_INCOMPLETE) || 9234ef08dc5SAlexander Motin softc->spinup == 0)) { 9244ef08dc5SAlexander Motin PROBE_SET_ACTION(softc, PROBE_SPINUP); 9254ef08dc5SAlexander Motin xpt_release_ccb(done_ccb); 9264ef08dc5SAlexander Motin xpt_schedule(periph, priority); 927cccf4220SAlexander Motin goto out; 9284ef08dc5SAlexander Motin } 929a9b8edb1SAlexander Motin ident_buf = &path->device->ident_data; 93076d843daSAlexander Motin 93176d843daSAlexander Motin /* Check that it is the same device as we know. */ 93252c9ce25SScott Long if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) { 933a9b8edb1SAlexander Motin if (bcmp(softc->ident_data.model, ident_buf->model, 934a9b8edb1SAlexander Motin sizeof(ident_buf->model)) || 935a9b8edb1SAlexander Motin bcmp(softc->ident_data.serial, ident_buf->serial, 936a9b8edb1SAlexander Motin sizeof(ident_buf->serial))) { 93776d843daSAlexander Motin /* The device was replaced. */ 93876d843daSAlexander Motin changed = 2; 93952c9ce25SScott Long xpt_async(AC_LOST_DEVICE, path, NULL); 94076d843daSAlexander Motin } else if (bcmp(&softc->ident_data, ident_buf, 94176d843daSAlexander Motin sizeof(*ident_buf))) { 94276d843daSAlexander Motin /* The device is the same, but has changed. */ 94376d843daSAlexander Motin changed = 1; 9441e637ba6SAlexander Motin } else { 94576d843daSAlexander Motin /* Nothing has changed. */ 9462eb4a8dcSAlexander Motin changed = 0; 9472eb4a8dcSAlexander Motin } 94876d843daSAlexander Motin } else { 94976d843daSAlexander Motin /* This is a new device. */ 95076d843daSAlexander Motin changed = 2; 9512eb4a8dcSAlexander Motin } 95276d843daSAlexander Motin 95376d843daSAlexander Motin if (changed != 0) 9542eb4a8dcSAlexander Motin bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 95576d843daSAlexander Motin if (changed == 2) { 95652c9ce25SScott Long /* Clean up from previous instance of this device */ 95752c9ce25SScott Long if (path->device->serial_num != NULL) { 95852c9ce25SScott Long free(path->device->serial_num, M_CAMXPT); 95952c9ce25SScott Long path->device->serial_num = NULL; 96052c9ce25SScott Long path->device->serial_num_len = 0; 96152c9ce25SScott Long } 9623089bb2eSAlexander Motin if (path->device->device_id != NULL) { 9633089bb2eSAlexander Motin free(path->device->device_id, M_CAMXPT); 9643089bb2eSAlexander Motin path->device->device_id = NULL; 9653089bb2eSAlexander Motin path->device->device_id_len = 0; 9663089bb2eSAlexander Motin } 96752c9ce25SScott Long path->device->serial_num = 96852c9ce25SScott Long (u_int8_t *)malloc((sizeof(ident_buf->serial) + 1), 96952c9ce25SScott Long M_CAMXPT, M_NOWAIT); 97052c9ce25SScott Long if (path->device->serial_num != NULL) { 97152c9ce25SScott Long bcopy(ident_buf->serial, 97252c9ce25SScott Long path->device->serial_num, 97352c9ce25SScott Long sizeof(ident_buf->serial)); 97452c9ce25SScott Long path->device->serial_num[sizeof(ident_buf->serial)] 97552c9ce25SScott Long = '\0'; 97652c9ce25SScott Long path->device->serial_num_len = 97752c9ce25SScott Long strlen(path->device->serial_num); 97852c9ce25SScott Long } 9793089bb2eSAlexander Motin if (ident_buf->enabled.extension & 9803089bb2eSAlexander Motin ATA_SUPPORT_64BITWWN) { 9813089bb2eSAlexander Motin path->device->device_id = 9823089bb2eSAlexander Motin malloc(16, M_CAMXPT, M_NOWAIT); 9833089bb2eSAlexander Motin if (path->device->device_id != NULL) { 9843089bb2eSAlexander Motin path->device->device_id_len = 16; 9853089bb2eSAlexander Motin bcopy(&fake_device_id_hdr, 9863089bb2eSAlexander Motin path->device->device_id, 8); 9873d6dd54eSAlexander Motin bcopy(ident_buf->wwn, 9883d6dd54eSAlexander Motin path->device->device_id + 8, 8); 9893d6dd54eSAlexander Motin ata_bswap(path->device->device_id + 8, 8); 9903089bb2eSAlexander Motin } 9913089bb2eSAlexander Motin } 9924b997c49SAlexander Motin path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 9931e637ba6SAlexander Motin } 99476d843daSAlexander Motin if (changed == 1) 99576d843daSAlexander Motin xpt_async(AC_GETDEV_CHANGED, path, NULL); 99630a4094fSAlexander Motin if (ident_buf->satacapabilities & ATA_SUPPORT_NCQ) { 9977dc3213dSAlexander Motin path->device->mintags = 2; 9987dc3213dSAlexander Motin path->device->maxtags = 99930a4094fSAlexander Motin ATA_QUEUE_LEN(ident_buf->queue) + 1; 100030a4094fSAlexander Motin } 100130a4094fSAlexander Motin ata_find_quirk(path->device); 1002507e5811SAlexander Motin if (path->device->mintags != 0 && 1003507e5811SAlexander Motin path->bus->sim->max_tagged_dev_openings != 0) { 1004699f853bSAlexander Motin /* Check if the SIM does not want queued commands. */ 1005762a7f4fSWarner Losh xpt_path_inq(&cpi, path); 1006699f853bSAlexander Motin if (cpi.ccb_h.status == CAM_REQ_CMP && 1007699f853bSAlexander Motin (cpi.hba_inquiry & PI_TAG_ABLE)) { 1008c8039fc6SAlexander Motin /* Report SIM which tags are allowed. */ 1009c8039fc6SAlexander Motin bzero(&cts, sizeof(cts)); 101083c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1011c8039fc6SAlexander Motin cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1012c8039fc6SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 1013c8039fc6SAlexander Motin cts.xport_specific.sata.tags = path->device->maxtags; 1014c8039fc6SAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_TAGS; 1015c8039fc6SAlexander Motin xpt_action((union ccb *)&cts); 101630a4094fSAlexander Motin } 1017699f853bSAlexander Motin } 1018bc1bf6e8SAlexander Motin ata_device_transport(path); 101976d843daSAlexander Motin if (changed == 2) 10200f280cbdSWarner Losh aproberequestdefaultnegotiation(periph); 102152c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_SETMODE); 102252c9ce25SScott Long xpt_release_ccb(done_ccb); 102352c9ce25SScott Long xpt_schedule(periph, priority); 1024cccf4220SAlexander Motin goto out; 102552c9ce25SScott Long } 10264ef08dc5SAlexander Motin case PROBE_SPINUP: 10274ef08dc5SAlexander Motin if (bootverbose) 10284ef08dc5SAlexander Motin xpt_print(path, "Spin-up done\n"); 10294ef08dc5SAlexander Motin softc->spinup = 1; 10304ef08dc5SAlexander Motin PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 10314ef08dc5SAlexander Motin xpt_release_ccb(done_ccb); 10324ef08dc5SAlexander Motin xpt_schedule(periph, priority); 1033cccf4220SAlexander Motin goto out; 103452c9ce25SScott Long case PROBE_SETMODE: 1035da6808c1SAlexander Motin /* Set supported bits. */ 1036da6808c1SAlexander Motin bzero(&cts, sizeof(cts)); 1037da6808c1SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1038da6808c1SAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1039da6808c1SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 1040da6808c1SAlexander Motin xpt_action((union ccb *)&cts); 10412e1eb332SMarius Strobl if (path->device->transport == XPORT_SATA && 10422e1eb332SMarius Strobl cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1043da6808c1SAlexander Motin caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H; 10442e1eb332SMarius Strobl else if (path->device->transport == XPORT_ATA && 10452e1eb332SMarius Strobl cts.xport_specific.ata.valid & CTS_ATA_VALID_CAPS) 10462e1eb332SMarius Strobl caps = cts.xport_specific.ata.caps & CTS_ATA_CAPS_H; 1047da6808c1SAlexander Motin else 1048da6808c1SAlexander Motin caps = 0; 10492e1eb332SMarius Strobl if (path->device->transport == XPORT_SATA && 10502e1eb332SMarius Strobl ident_buf->satacapabilities != 0xffff) { 1051da6808c1SAlexander Motin if (ident_buf->satacapabilities & ATA_SUPPORT_IFPWRMNGTRCV) 1052da6808c1SAlexander Motin caps |= CTS_SATA_CAPS_D_PMREQ; 1053da6808c1SAlexander Motin if (ident_buf->satacapabilities & ATA_SUPPORT_HAPST) 1054da6808c1SAlexander Motin caps |= CTS_SATA_CAPS_D_APST; 1055da6808c1SAlexander Motin } 1056da6808c1SAlexander Motin /* Mask unwanted bits. */ 1057da6808c1SAlexander Motin bzero(&cts, sizeof(cts)); 1058da6808c1SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1059da6808c1SAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1060da6808c1SAlexander Motin cts.type = CTS_TYPE_USER_SETTINGS; 1061da6808c1SAlexander Motin xpt_action((union ccb *)&cts); 10622e1eb332SMarius Strobl if (path->device->transport == XPORT_SATA && 10632e1eb332SMarius Strobl cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1064da6808c1SAlexander Motin caps &= cts.xport_specific.sata.caps; 10652e1eb332SMarius Strobl else if (path->device->transport == XPORT_ATA && 10662e1eb332SMarius Strobl cts.xport_specific.ata.valid & CTS_ATA_VALID_CAPS) 10672e1eb332SMarius Strobl caps &= cts.xport_specific.ata.caps; 1068c2b82f3eSAlexander Motin else 1069c2b82f3eSAlexander Motin caps = 0; 10702e1eb332SMarius Strobl /* 10712e1eb332SMarius Strobl * Remember what transport thinks about 48-bit DMA. If 10722e1eb332SMarius Strobl * capability information is not provided or transport is 10732e1eb332SMarius Strobl * SATA, we take support for granted. 10742e1eb332SMarius Strobl */ 107576d843daSAlexander Motin oif = path->device->inq_flags; 10762e1eb332SMarius Strobl if (!(path->device->inq_flags & SID_DMA) || 10772e1eb332SMarius Strobl (path->device->transport == XPORT_ATA && 10782e1eb332SMarius Strobl (cts.xport_specific.ata.valid & CTS_ATA_VALID_CAPS) && 10792e1eb332SMarius Strobl !(caps & CTS_ATA_CAPS_H_DMA48))) 10802e1eb332SMarius Strobl path->device->inq_flags &= ~SID_DMA48; 10812e1eb332SMarius Strobl else 10822e1eb332SMarius Strobl path->device->inq_flags |= SID_DMA48; 108376d843daSAlexander Motin if (path->device->inq_flags != oif) 108476d843daSAlexander Motin xpt_async(AC_GETDEV_CHANGED, path, NULL); 1085da6808c1SAlexander Motin /* Store result to SIM. */ 1086da6808c1SAlexander Motin bzero(&cts, sizeof(cts)); 1087da6808c1SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1088da6808c1SAlexander Motin cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1089da6808c1SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 10902e1eb332SMarius Strobl if (path->device->transport == XPORT_SATA) { 1091da6808c1SAlexander Motin cts.xport_specific.sata.caps = caps; 1092da6808c1SAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS; 10932e1eb332SMarius Strobl } else { 10942e1eb332SMarius Strobl cts.xport_specific.ata.caps = caps; 10952e1eb332SMarius Strobl cts.xport_specific.ata.valid = CTS_ATA_VALID_CAPS; 10962e1eb332SMarius Strobl } 1097da6808c1SAlexander Motin xpt_action((union ccb *)&cts); 1098da6808c1SAlexander Motin softc->caps = caps; 10992e1eb332SMarius Strobl if (path->device->transport != XPORT_SATA) 11002e1eb332SMarius Strobl goto notsata; 1101958e4a69SAlexander Motin if ((ident_buf->satasupport & ATA_SUPPORT_IFPWRMNGT) && 1102958e4a69SAlexander Motin (!(softc->caps & CTS_SATA_CAPS_H_PMREQ)) != 1103958e4a69SAlexander Motin (!(ident_buf->sataenabled & ATA_SUPPORT_IFPWRMNGT))) { 1104da6808c1SAlexander Motin PROBE_SET_ACTION(softc, PROBE_SETPM); 1105da6808c1SAlexander Motin xpt_release_ccb(done_ccb); 1106da6808c1SAlexander Motin xpt_schedule(periph, priority); 1107cccf4220SAlexander Motin goto out; 1108da6808c1SAlexander Motin } 1109da6808c1SAlexander Motin /* FALLTHROUGH */ 1110da6808c1SAlexander Motin case PROBE_SETPM: 1111da6808c1SAlexander Motin if (ident_buf->satacapabilities != 0xffff && 1112958e4a69SAlexander Motin (ident_buf->satacapabilities & ATA_SUPPORT_DAPST) && 1113958e4a69SAlexander Motin (!(softc->caps & CTS_SATA_CAPS_H_APST)) != 1114958e4a69SAlexander Motin (!(ident_buf->sataenabled & ATA_ENABLED_DAPST))) { 1115da6808c1SAlexander Motin PROBE_SET_ACTION(softc, PROBE_SETAPST); 1116da6808c1SAlexander Motin xpt_release_ccb(done_ccb); 1117da6808c1SAlexander Motin xpt_schedule(periph, priority); 1118cccf4220SAlexander Motin goto out; 1119da6808c1SAlexander Motin } 1120da6808c1SAlexander Motin /* FALLTHROUGH */ 1121da6808c1SAlexander Motin case PROBE_SETAPST: 1122958e4a69SAlexander Motin if ((ident_buf->satasupport & ATA_SUPPORT_AUTOACTIVATE) && 1123958e4a69SAlexander Motin (!(softc->caps & CTS_SATA_CAPS_H_DMAAA)) != 1124958e4a69SAlexander Motin (!(ident_buf->sataenabled & ATA_SUPPORT_AUTOACTIVATE))) { 1125da6808c1SAlexander Motin PROBE_SET_ACTION(softc, PROBE_SETDMAAA); 1126da6808c1SAlexander Motin xpt_release_ccb(done_ccb); 1127da6808c1SAlexander Motin xpt_schedule(periph, priority); 1128cccf4220SAlexander Motin goto out; 1129da6808c1SAlexander Motin } 1130da6808c1SAlexander Motin /* FALLTHROUGH */ 1131da6808c1SAlexander Motin case PROBE_SETDMAAA: 1132e4bed0b4SWarner Losh if (path->device->protocol != PROTO_ATA && 1133e4bed0b4SWarner Losh (ident_buf->satasupport & ATA_SUPPORT_ASYNCNOTIF) && 11348d169381SAlexander Motin (!(softc->caps & CTS_SATA_CAPS_H_AN)) != 11358d169381SAlexander Motin (!(ident_buf->sataenabled & ATA_SUPPORT_ASYNCNOTIF))) { 11368d169381SAlexander Motin PROBE_SET_ACTION(softc, PROBE_SETAN); 11378d169381SAlexander Motin xpt_release_ccb(done_ccb); 11388d169381SAlexander Motin xpt_schedule(periph, priority); 1139cccf4220SAlexander Motin goto out; 11408d169381SAlexander Motin } 11418d169381SAlexander Motin /* FALLTHROUGH */ 11428d169381SAlexander Motin case PROBE_SETAN: 1143da6808c1SAlexander Motin notsata: 11441e637ba6SAlexander Motin if (path->device->protocol == PROTO_ATA) { 11451e637ba6SAlexander Motin PROBE_SET_ACTION(softc, PROBE_SET_MULTI); 11461e637ba6SAlexander Motin } else { 11471e637ba6SAlexander Motin PROBE_SET_ACTION(softc, PROBE_INQUIRY); 11481e637ba6SAlexander Motin } 11491e637ba6SAlexander Motin xpt_release_ccb(done_ccb); 11501e637ba6SAlexander Motin xpt_schedule(periph, priority); 1151cccf4220SAlexander Motin goto out; 11521e637ba6SAlexander Motin case PROBE_SET_MULTI: 11531e637ba6SAlexander Motin if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 115452c9ce25SScott Long path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1155f98d7a47SAlexander Motin xpt_acquire_device(path->device); 115652c9ce25SScott Long done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 115752c9ce25SScott Long xpt_action(done_ccb); 1158cccf4220SAlexander Motin xpt_async(AC_FOUND_DEVICE, path, done_ccb); 11591e637ba6SAlexander Motin } 1160a4d953c4SAlexander Motin PROBE_SET_ACTION(softc, PROBE_DONE); 116152c9ce25SScott Long break; 116252c9ce25SScott Long case PROBE_INQUIRY: 116352c9ce25SScott Long case PROBE_FULL_INQUIRY: 116452c9ce25SScott Long { 11651e637ba6SAlexander Motin u_int8_t periph_qual, len; 116652c9ce25SScott Long 116752c9ce25SScott Long path->device->flags |= CAM_DEV_INQUIRY_DATA_VALID; 116852c9ce25SScott Long 116952c9ce25SScott Long periph_qual = SID_QUAL(inq_buf); 117052c9ce25SScott Long 117192024858SAlexander Motin if (periph_qual != SID_QUAL_LU_CONNECTED && 117292024858SAlexander Motin periph_qual != SID_QUAL_LU_OFFLINE) 11731e637ba6SAlexander Motin break; 117452c9ce25SScott Long 117552c9ce25SScott Long /* 117652c9ce25SScott Long * We conservatively request only 117752c9ce25SScott Long * SHORT_INQUIRY_LEN bytes of inquiry 117852c9ce25SScott Long * information during our first try 117952c9ce25SScott Long * at sending an INQUIRY. If the device 118052c9ce25SScott Long * has more information to give, 118152c9ce25SScott Long * perform a second request specifying 118252c9ce25SScott Long * the amount of information the device 118352c9ce25SScott Long * is willing to give. 118452c9ce25SScott Long */ 118552c9ce25SScott Long len = inq_buf->additional_length 11861e637ba6SAlexander Motin + offsetof(struct scsi_inquiry_data, additional_length) + 1; 118752c9ce25SScott Long if (softc->action == PROBE_INQUIRY 118852c9ce25SScott Long && len > SHORT_INQUIRY_LENGTH) { 118952c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_FULL_INQUIRY); 119052c9ce25SScott Long xpt_release_ccb(done_ccb); 119152c9ce25SScott Long xpt_schedule(periph, priority); 1192cccf4220SAlexander Motin goto out; 119352c9ce25SScott Long } 119452c9ce25SScott Long 11954b997c49SAlexander Motin ata_device_transport(path); 11961e637ba6SAlexander Motin if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 119752c9ce25SScott Long path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1198f98d7a47SAlexander Motin xpt_acquire_device(path->device); 119952c9ce25SScott Long done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 120052c9ce25SScott Long xpt_action(done_ccb); 1201cccf4220SAlexander Motin xpt_async(AC_FOUND_DEVICE, path, done_ccb); 12021e637ba6SAlexander Motin } 1203a4d953c4SAlexander Motin PROBE_SET_ACTION(softc, PROBE_DONE); 120452c9ce25SScott Long break; 120552c9ce25SScott Long } 120652c9ce25SScott Long case PROBE_PM_PID: 12074b997c49SAlexander Motin if ((path->device->flags & CAM_DEV_IDENTIFY_DATA_VALID) == 0) 120852c9ce25SScott Long bzero(ident_buf, sizeof(*ident_buf)); 120952c9ce25SScott Long softc->pm_pid = (done_ccb->ataio.res.lba_high << 24) + 121052c9ce25SScott Long (done_ccb->ataio.res.lba_mid << 16) + 121152c9ce25SScott Long (done_ccb->ataio.res.lba_low << 8) + 121252c9ce25SScott Long done_ccb->ataio.res.sector_count; 121365d0fb03SAlexander Motin ((uint32_t *)ident_buf)[0] = softc->pm_pid; 121452c9ce25SScott Long snprintf(ident_buf->model, sizeof(ident_buf->model), 121552c9ce25SScott Long "Port Multiplier %08x", softc->pm_pid); 121652c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_PM_PRV); 121752c9ce25SScott Long xpt_release_ccb(done_ccb); 121852c9ce25SScott Long xpt_schedule(periph, priority); 1219cccf4220SAlexander Motin goto out; 122052c9ce25SScott Long case PROBE_PM_PRV: 122152c9ce25SScott Long softc->pm_prv = (done_ccb->ataio.res.lba_high << 24) + 122252c9ce25SScott Long (done_ccb->ataio.res.lba_mid << 16) + 122352c9ce25SScott Long (done_ccb->ataio.res.lba_low << 8) + 122452c9ce25SScott Long done_ccb->ataio.res.sector_count; 122565d0fb03SAlexander Motin ((uint32_t *)ident_buf)[1] = softc->pm_prv; 122652c9ce25SScott Long snprintf(ident_buf->revision, sizeof(ident_buf->revision), 122752c9ce25SScott Long "%04x", softc->pm_prv); 12284b997c49SAlexander Motin path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 1229bc1bf6e8SAlexander Motin ata_device_transport(path); 1230bc1bf6e8SAlexander Motin if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) 12310f280cbdSWarner Losh aproberequestdefaultnegotiation(periph); 1232da6808c1SAlexander Motin /* Set supported bits. */ 1233da6808c1SAlexander Motin bzero(&cts, sizeof(cts)); 1234da6808c1SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1235da6808c1SAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1236da6808c1SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 1237da6808c1SAlexander Motin xpt_action((union ccb *)&cts); 1238da6808c1SAlexander Motin if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1239da6808c1SAlexander Motin caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H; 1240da6808c1SAlexander Motin else 1241da6808c1SAlexander Motin caps = 0; 1242da6808c1SAlexander Motin /* All PMPs must support PM requests. */ 1243da6808c1SAlexander Motin caps |= CTS_SATA_CAPS_D_PMREQ; 1244da6808c1SAlexander Motin /* Mask unwanted bits. */ 1245da6808c1SAlexander Motin bzero(&cts, sizeof(cts)); 1246da6808c1SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1247da6808c1SAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1248da6808c1SAlexander Motin cts.type = CTS_TYPE_USER_SETTINGS; 1249da6808c1SAlexander Motin xpt_action((union ccb *)&cts); 1250da6808c1SAlexander Motin if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1251da6808c1SAlexander Motin caps &= cts.xport_specific.sata.caps; 1252c2b82f3eSAlexander Motin else 1253c2b82f3eSAlexander Motin caps = 0; 12542e1eb332SMarius Strobl /* Remember what transport thinks about AEN. */ 125576d843daSAlexander Motin oif = path->device->inq_flags; 1256e4bed0b4SWarner Losh if ((caps & CTS_SATA_CAPS_H_AN) && path->device->protocol != PROTO_ATA) 12572e1eb332SMarius Strobl path->device->inq_flags |= SID_AEN; 12582e1eb332SMarius Strobl else 12592e1eb332SMarius Strobl path->device->inq_flags &= ~SID_AEN; 1260da6808c1SAlexander Motin /* Store result to SIM. */ 1261da6808c1SAlexander Motin bzero(&cts, sizeof(cts)); 1262da6808c1SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1263da6808c1SAlexander Motin cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1264da6808c1SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 1265da6808c1SAlexander Motin cts.xport_specific.sata.caps = caps; 1266da6808c1SAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS; 1267da6808c1SAlexander Motin xpt_action((union ccb *)&cts); 1268da6808c1SAlexander Motin softc->caps = caps; 126965d0fb03SAlexander Motin if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 127052c9ce25SScott Long path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1271f98d7a47SAlexander Motin xpt_acquire_device(path->device); 127252c9ce25SScott Long done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 127352c9ce25SScott Long xpt_action(done_ccb); 1274cccf4220SAlexander Motin xpt_async(AC_FOUND_DEVICE, path, done_ccb); 127565d0fb03SAlexander Motin } else { 127676d843daSAlexander Motin if (path->device->inq_flags != oif) 127776d843daSAlexander Motin xpt_async(AC_GETDEV_CHANGED, path, NULL); 127865d0fb03SAlexander Motin done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 127965d0fb03SAlexander Motin xpt_action(done_ccb); 1280cccf4220SAlexander Motin xpt_async(AC_SCSI_AEN, path, done_ccb); 128152c9ce25SScott Long } 1282a4d953c4SAlexander Motin PROBE_SET_ACTION(softc, PROBE_DONE); 128352c9ce25SScott Long break; 12843089bb2eSAlexander Motin case PROBE_IDENTIFY_SES: 12853089bb2eSAlexander Motin case PROBE_IDENTIFY_SAFTE: 12863089bb2eSAlexander Motin if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) { 12873089bb2eSAlexander Motin /* Check that it is the same device. */ 12883089bb2eSAlexander Motin if (bcmp(&softc->ident_data, ident_buf, 53)) { 12893089bb2eSAlexander Motin /* Device changed. */ 129076d843daSAlexander Motin changed = 2; 12913089bb2eSAlexander Motin xpt_async(AC_LOST_DEVICE, path, NULL); 12923089bb2eSAlexander Motin } else { 12933089bb2eSAlexander Motin bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 12943089bb2eSAlexander Motin changed = 0; 12953089bb2eSAlexander Motin } 129676d843daSAlexander Motin } else 129776d843daSAlexander Motin changed = 2; 12983089bb2eSAlexander Motin if (changed) { 12993089bb2eSAlexander Motin bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 13003089bb2eSAlexander Motin /* Clean up from previous instance of this device */ 13013089bb2eSAlexander Motin if (path->device->device_id != NULL) { 13023089bb2eSAlexander Motin free(path->device->device_id, M_CAMXPT); 13033089bb2eSAlexander Motin path->device->device_id = NULL; 13043089bb2eSAlexander Motin path->device->device_id_len = 0; 13053089bb2eSAlexander Motin } 13063089bb2eSAlexander Motin path->device->device_id = 13073089bb2eSAlexander Motin malloc(16, M_CAMXPT, M_NOWAIT); 13083089bb2eSAlexander Motin if (path->device->device_id != NULL) { 13093089bb2eSAlexander Motin path->device->device_id_len = 16; 13103089bb2eSAlexander Motin bcopy(&fake_device_id_hdr, 13113089bb2eSAlexander Motin path->device->device_id, 8); 13123089bb2eSAlexander Motin bcopy(((uint8_t*)ident_buf) + 2, 13133089bb2eSAlexander Motin path->device->device_id + 8, 8); 13143089bb2eSAlexander Motin } 13153089bb2eSAlexander Motin 13163089bb2eSAlexander Motin path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 13173089bb2eSAlexander Motin } 1318bc1bf6e8SAlexander Motin ata_device_transport(path); 1319bc1bf6e8SAlexander Motin if (changed) 13200f280cbdSWarner Losh aproberequestdefaultnegotiation(periph); 13213089bb2eSAlexander Motin 13223089bb2eSAlexander Motin if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 13233089bb2eSAlexander Motin path->device->flags &= ~CAM_DEV_UNCONFIGURED; 13243089bb2eSAlexander Motin xpt_acquire_device(path->device); 13253089bb2eSAlexander Motin done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 13263089bb2eSAlexander Motin xpt_action(done_ccb); 1327cccf4220SAlexander Motin xpt_async(AC_FOUND_DEVICE, path, done_ccb); 13283089bb2eSAlexander Motin } 1329a4d953c4SAlexander Motin PROBE_SET_ACTION(softc, PROBE_DONE); 13303089bb2eSAlexander Motin break; 133152c9ce25SScott Long default: 13320f280cbdSWarner Losh panic("aprobedone: invalid action state 0x%x\n", softc->action); 133352c9ce25SScott Long } 13341e637ba6SAlexander Motin done: 133583c5d981SAlexander Motin if (softc->restart) { 133683c5d981SAlexander Motin softc->restart = 0; 13371e637ba6SAlexander Motin xpt_release_ccb(done_ccb); 13380f280cbdSWarner Losh aprobeschedule(periph); 1339cccf4220SAlexander Motin goto out; 134083c5d981SAlexander Motin } 134183c5d981SAlexander Motin xpt_release_ccb(done_ccb); 1342a4d953c4SAlexander Motin CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe completed\n")); 134383c5d981SAlexander Motin while ((done_ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs))) { 134483c5d981SAlexander Motin TAILQ_REMOVE(&softc->request_ccbs, 134583c5d981SAlexander Motin &done_ccb->ccb_h, periph_links.tqe); 134683c5d981SAlexander Motin done_ccb->ccb_h.status = found ? CAM_REQ_CMP : CAM_REQ_CMP_ERR; 134752c9ce25SScott Long xpt_done(done_ccb); 134883c5d981SAlexander Motin } 1349cccf4220SAlexander Motin /* Drop freeze taken due to CAM_DEV_QFREEZE flag set. */ 1350cccf4220SAlexander Motin cam_release_devq(path, 0, 0, 0, FALSE); 13512e3f592bSAlexander Motin cam_periph_invalidate(periph); 135252c9ce25SScott Long cam_periph_release_locked(periph); 135352c9ce25SScott Long } 135452c9ce25SScott Long 135552c9ce25SScott Long static void 13560f280cbdSWarner Losh aprobecleanup(struct cam_periph *periph) 135752c9ce25SScott Long { 135852c9ce25SScott Long free(periph->softc, M_CAMXPT); 135952c9ce25SScott Long } 136052c9ce25SScott Long 136152c9ce25SScott Long static void 136230a4094fSAlexander Motin ata_find_quirk(struct cam_ed *device) 136352c9ce25SScott Long { 136430a4094fSAlexander Motin struct ata_quirk_entry *quirk; 136552c9ce25SScott Long caddr_t match; 136652c9ce25SScott Long 136730a4094fSAlexander Motin match = cam_quirkmatch((caddr_t)&device->ident_data, 136830a4094fSAlexander Motin (caddr_t)ata_quirk_table, 13698dfea464SPedro F. Giffuni nitems(ata_quirk_table), 137030a4094fSAlexander Motin sizeof(*ata_quirk_table), ata_identify_match); 137152c9ce25SScott Long 137252c9ce25SScott Long if (match == NULL) 137352c9ce25SScott Long panic("xpt_find_quirk: device didn't match wildcard entry!!"); 137452c9ce25SScott Long 137530a4094fSAlexander Motin quirk = (struct ata_quirk_entry *)match; 137652c9ce25SScott Long device->quirk = quirk; 13777dc3213dSAlexander Motin if (quirk->quirks & CAM_QUIRK_MAXTAGS) { 13787dc3213dSAlexander Motin device->mintags = quirk->mintags; 13797dc3213dSAlexander Motin device->maxtags = quirk->maxtags; 13807dc3213dSAlexander Motin } 138152c9ce25SScott Long } 138252c9ce25SScott Long 138352c9ce25SScott Long typedef struct { 138452c9ce25SScott Long union ccb *request_ccb; 138552c9ce25SScott Long struct ccb_pathinq *cpi; 138652c9ce25SScott Long int counter; 138752c9ce25SScott Long } ata_scan_bus_info; 138852c9ce25SScott Long 138952c9ce25SScott Long /* 139052c9ce25SScott Long * To start a scan, request_ccb is an XPT_SCAN_BUS ccb. 139152c9ce25SScott Long * As the scan progresses, xpt_scan_bus is used as the 139252c9ce25SScott Long * callback on completion function. 139352c9ce25SScott Long */ 139452c9ce25SScott Long static void 139552c9ce25SScott Long ata_scan_bus(struct cam_periph *periph, union ccb *request_ccb) 139652c9ce25SScott Long { 139752c9ce25SScott Long struct cam_path *path; 139852c9ce25SScott Long ata_scan_bus_info *scan_info; 139983c5d981SAlexander Motin union ccb *work_ccb, *reset_ccb; 1400227d67aaSAlexander Motin struct mtx *mtx; 140152c9ce25SScott Long cam_status status; 140252c9ce25SScott Long 140352c9ce25SScott Long CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE, 140452c9ce25SScott Long ("xpt_scan_bus\n")); 140552c9ce25SScott Long switch (request_ccb->ccb_h.func_code) { 140652c9ce25SScott Long case XPT_SCAN_BUS: 14070e85f214SMatt Jacob case XPT_SCAN_TGT: 140852c9ce25SScott Long /* Find out the characteristics of the bus */ 140952c9ce25SScott Long work_ccb = xpt_alloc_ccb_nowait(); 141052c9ce25SScott Long if (work_ccb == NULL) { 141152c9ce25SScott Long request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 141252c9ce25SScott Long xpt_done(request_ccb); 141352c9ce25SScott Long return; 141452c9ce25SScott Long } 1415762a7f4fSWarner Losh xpt_path_inq(&work_ccb->cpi, request_ccb->ccb_h.path); 141652c9ce25SScott Long if (work_ccb->ccb_h.status != CAM_REQ_CMP) { 141752c9ce25SScott Long request_ccb->ccb_h.status = work_ccb->ccb_h.status; 141852c9ce25SScott Long xpt_free_ccb(work_ccb); 141952c9ce25SScott Long xpt_done(request_ccb); 142052c9ce25SScott Long return; 142152c9ce25SScott Long } 142252c9ce25SScott Long 142383c5d981SAlexander Motin /* We may need to reset bus first, if we haven't done it yet. */ 142483c5d981SAlexander Motin if ((work_ccb->cpi.hba_inquiry & 142583c5d981SAlexander Motin (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE)) && 142683c5d981SAlexander Motin !(work_ccb->cpi.hba_misc & PIM_NOBUSRESET) && 142783c5d981SAlexander Motin !timevalisset(&request_ccb->ccb_h.path->bus->last_reset)) { 142883c5d981SAlexander Motin reset_ccb = xpt_alloc_ccb_nowait(); 1429f1893540SAlexander Motin if (reset_ccb == NULL) { 1430f1893540SAlexander Motin request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1431f1893540SAlexander Motin xpt_free_ccb(work_ccb); 1432f1893540SAlexander Motin xpt_done(request_ccb); 1433f1893540SAlexander Motin return; 1434f1893540SAlexander Motin } 143583c5d981SAlexander Motin xpt_setup_ccb(&reset_ccb->ccb_h, request_ccb->ccb_h.path, 143683c5d981SAlexander Motin CAM_PRIORITY_NONE); 143783c5d981SAlexander Motin reset_ccb->ccb_h.func_code = XPT_RESET_BUS; 143883c5d981SAlexander Motin xpt_action(reset_ccb); 143983c5d981SAlexander Motin if (reset_ccb->ccb_h.status != CAM_REQ_CMP) { 144083c5d981SAlexander Motin request_ccb->ccb_h.status = reset_ccb->ccb_h.status; 144183c5d981SAlexander Motin xpt_free_ccb(reset_ccb); 144283c5d981SAlexander Motin xpt_free_ccb(work_ccb); 144383c5d981SAlexander Motin xpt_done(request_ccb); 144483c5d981SAlexander Motin return; 144583c5d981SAlexander Motin } 144683c5d981SAlexander Motin xpt_free_ccb(reset_ccb); 144783c5d981SAlexander Motin } 144883c5d981SAlexander Motin 144952c9ce25SScott Long /* Save some state for use while we probe for devices */ 145052c9ce25SScott Long scan_info = (ata_scan_bus_info *) 145152c9ce25SScott Long malloc(sizeof(ata_scan_bus_info), M_CAMXPT, M_NOWAIT); 145252c9ce25SScott Long if (scan_info == NULL) { 145352c9ce25SScott Long request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1454f1893540SAlexander Motin xpt_free_ccb(work_ccb); 145552c9ce25SScott Long xpt_done(request_ccb); 145652c9ce25SScott Long return; 145752c9ce25SScott Long } 145852c9ce25SScott Long scan_info->request_ccb = request_ccb; 145952c9ce25SScott Long scan_info->cpi = &work_ccb->cpi; 146052c9ce25SScott Long /* If PM supported, probe it first. */ 146152c9ce25SScott Long if (scan_info->cpi->hba_inquiry & PI_SATAPM) 14620025eb12SAlexander Motin scan_info->counter = scan_info->cpi->max_target; 14630025eb12SAlexander Motin else 14640025eb12SAlexander Motin scan_info->counter = 0; 146552c9ce25SScott Long 146652c9ce25SScott Long work_ccb = xpt_alloc_ccb_nowait(); 146752c9ce25SScott Long if (work_ccb == NULL) { 146852c9ce25SScott Long free(scan_info, M_CAMXPT); 146952c9ce25SScott Long request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 147052c9ce25SScott Long xpt_done(request_ccb); 147152c9ce25SScott Long break; 147252c9ce25SScott Long } 1473227d67aaSAlexander Motin mtx = xpt_path_mtx(scan_info->request_ccb->ccb_h.path); 147452c9ce25SScott Long goto scan_next; 147552c9ce25SScott Long case XPT_SCAN_LUN: 147652c9ce25SScott Long work_ccb = request_ccb; 147752c9ce25SScott Long /* Reuse the same CCB to query if a device was really found */ 147852c9ce25SScott Long scan_info = (ata_scan_bus_info *)work_ccb->ccb_h.ppriv_ptr0; 1479227d67aaSAlexander Motin mtx = xpt_path_mtx(scan_info->request_ccb->ccb_h.path); 1480227d67aaSAlexander Motin mtx_lock(mtx); 148165d0fb03SAlexander Motin /* If there is PMP... */ 14820025eb12SAlexander Motin if ((scan_info->cpi->hba_inquiry & PI_SATAPM) && 14830025eb12SAlexander Motin (scan_info->counter == scan_info->cpi->max_target)) { 148483c5d981SAlexander Motin if (work_ccb->ccb_h.status == CAM_REQ_CMP) { 148565d0fb03SAlexander Motin /* everything else will be probed by it */ 1486e2a75189SAlexander Motin /* Free the current request path- we're done with it. */ 1487e2a75189SAlexander Motin xpt_free_path(work_ccb->ccb_h.path); 14880025eb12SAlexander Motin goto done; 148952c9ce25SScott Long } else { 149052c9ce25SScott Long struct ccb_trans_settings cts; 149152c9ce25SScott Long 149252c9ce25SScott Long /* Report SIM that PM is absent. */ 149352c9ce25SScott Long bzero(&cts, sizeof(cts)); 149452c9ce25SScott Long xpt_setup_ccb(&cts.ccb_h, 1495e2a75189SAlexander Motin work_ccb->ccb_h.path, CAM_PRIORITY_NONE); 149652c9ce25SScott Long cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 149752c9ce25SScott Long cts.type = CTS_TYPE_CURRENT_SETTINGS; 14983ccda2f3SAlexander Motin cts.xport_specific.sata.pm_present = 0; 149952c9ce25SScott Long cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; 150052c9ce25SScott Long xpt_action((union ccb *)&cts); 150152c9ce25SScott Long } 150252c9ce25SScott Long } 1503e2a75189SAlexander Motin /* Free the current request path- we're done with it. */ 1504e2a75189SAlexander Motin xpt_free_path(work_ccb->ccb_h.path); 15050025eb12SAlexander Motin if (scan_info->counter == 15060025eb12SAlexander Motin ((scan_info->cpi->hba_inquiry & PI_SATAPM) ? 15070025eb12SAlexander Motin 0 : scan_info->cpi->max_target)) { 15080025eb12SAlexander Motin done: 1509227d67aaSAlexander Motin mtx_unlock(mtx); 151052c9ce25SScott Long xpt_free_ccb(work_ccb); 151152c9ce25SScott Long xpt_free_ccb((union ccb *)scan_info->cpi); 151252c9ce25SScott Long request_ccb = scan_info->request_ccb; 151352c9ce25SScott Long free(scan_info, M_CAMXPT); 151452c9ce25SScott Long request_ccb->ccb_h.status = CAM_REQ_CMP; 151552c9ce25SScott Long xpt_done(request_ccb); 151652c9ce25SScott Long break; 151752c9ce25SScott Long } 15180025eb12SAlexander Motin /* Take next device. Wrap from max (PMP) to 0. */ 15190025eb12SAlexander Motin scan_info->counter = (scan_info->counter + 1 ) % 15200025eb12SAlexander Motin (scan_info->cpi->max_target + 1); 152152c9ce25SScott Long scan_next: 1522e5dfa058SAlexander Motin status = xpt_create_path(&path, NULL, 152352c9ce25SScott Long scan_info->request_ccb->ccb_h.path_id, 152452c9ce25SScott Long scan_info->counter, 0); 152552c9ce25SScott Long if (status != CAM_REQ_CMP) { 1526227d67aaSAlexander Motin if (request_ccb->ccb_h.func_code == XPT_SCAN_LUN) 1527227d67aaSAlexander Motin mtx_unlock(mtx); 152852c9ce25SScott Long printf("xpt_scan_bus: xpt_create_path failed" 152952c9ce25SScott Long " with status %#x, bus scan halted\n", 153052c9ce25SScott Long status); 153152c9ce25SScott Long xpt_free_ccb(work_ccb); 153252c9ce25SScott Long xpt_free_ccb((union ccb *)scan_info->cpi); 153352c9ce25SScott Long request_ccb = scan_info->request_ccb; 153452c9ce25SScott Long free(scan_info, M_CAMXPT); 153552c9ce25SScott Long request_ccb->ccb_h.status = status; 153652c9ce25SScott Long xpt_done(request_ccb); 153752c9ce25SScott Long break; 153852c9ce25SScott Long } 153952c9ce25SScott Long xpt_setup_ccb(&work_ccb->ccb_h, path, 154052c9ce25SScott Long scan_info->request_ccb->ccb_h.pinfo.priority); 154152c9ce25SScott Long work_ccb->ccb_h.func_code = XPT_SCAN_LUN; 154252c9ce25SScott Long work_ccb->ccb_h.cbfcnp = ata_scan_bus; 1543227d67aaSAlexander Motin work_ccb->ccb_h.flags |= CAM_UNLOCKED; 154452c9ce25SScott Long work_ccb->ccb_h.ppriv_ptr0 = scan_info; 154552c9ce25SScott Long work_ccb->crcn.flags = scan_info->request_ccb->crcn.flags; 1546227d67aaSAlexander Motin mtx_unlock(mtx); 1547227d67aaSAlexander Motin if (request_ccb->ccb_h.func_code == XPT_SCAN_LUN) 1548227d67aaSAlexander Motin mtx = NULL; 154952c9ce25SScott Long xpt_action(work_ccb); 1550227d67aaSAlexander Motin if (mtx != NULL) 1551227d67aaSAlexander Motin mtx_lock(mtx); 155252c9ce25SScott Long break; 155352c9ce25SScott Long default: 155452c9ce25SScott Long break; 155552c9ce25SScott Long } 155652c9ce25SScott Long } 155752c9ce25SScott Long 155852c9ce25SScott Long static void 155952c9ce25SScott Long ata_scan_lun(struct cam_periph *periph, struct cam_path *path, 156052c9ce25SScott Long cam_flags flags, union ccb *request_ccb) 156152c9ce25SScott Long { 156252c9ce25SScott Long struct ccb_pathinq cpi; 156352c9ce25SScott Long cam_status status; 156452c9ce25SScott Long struct cam_path *new_path; 156552c9ce25SScott Long struct cam_periph *old_periph; 1566227d67aaSAlexander Motin int lock; 156752c9ce25SScott Long 156883c5d981SAlexander Motin CAM_DEBUG(path, CAM_DEBUG_TRACE, ("xpt_scan_lun\n")); 156952c9ce25SScott Long 1570762a7f4fSWarner Losh xpt_path_inq(&cpi, path); 157152c9ce25SScott Long if (cpi.ccb_h.status != CAM_REQ_CMP) { 157252c9ce25SScott Long if (request_ccb != NULL) { 157352c9ce25SScott Long request_ccb->ccb_h.status = cpi.ccb_h.status; 157452c9ce25SScott Long xpt_done(request_ccb); 157552c9ce25SScott Long } 157652c9ce25SScott Long return; 157752c9ce25SScott Long } 157852c9ce25SScott Long 157952c9ce25SScott Long if (request_ccb == NULL) { 158032aa80a6SAlexander Motin request_ccb = xpt_alloc_ccb_nowait(); 158152c9ce25SScott Long if (request_ccb == NULL) { 158252c9ce25SScott Long xpt_print(path, "xpt_scan_lun: can't allocate CCB, " 158352c9ce25SScott Long "can't continue\n"); 158452c9ce25SScott Long return; 158552c9ce25SScott Long } 1586e5dfa058SAlexander Motin status = xpt_create_path(&new_path, NULL, 158752c9ce25SScott Long path->bus->path_id, 158852c9ce25SScott Long path->target->target_id, 158952c9ce25SScott Long path->device->lun_id); 159052c9ce25SScott Long if (status != CAM_REQ_CMP) { 159132aa80a6SAlexander Motin xpt_print(path, "xpt_scan_lun: can't create path, " 159252c9ce25SScott Long "can't continue\n"); 159332aa80a6SAlexander Motin xpt_free_ccb(request_ccb); 159452c9ce25SScott Long return; 159552c9ce25SScott Long } 159683c5d981SAlexander Motin xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_XPT); 15970f280cbdSWarner Losh request_ccb->ccb_h.cbfcnp = axptscandone; 1598227d67aaSAlexander Motin request_ccb->ccb_h.flags |= CAM_UNLOCKED; 159952c9ce25SScott Long request_ccb->ccb_h.func_code = XPT_SCAN_LUN; 160052c9ce25SScott Long request_ccb->crcn.flags = flags; 160152c9ce25SScott Long } 160252c9ce25SScott Long 1603227d67aaSAlexander Motin lock = (xpt_path_owned(path) == 0); 1604227d67aaSAlexander Motin if (lock) 1605227d67aaSAlexander Motin xpt_path_lock(path); 1606f09f8e3eSAlexander Motin if ((old_periph = cam_periph_find(path, "aprobe")) != NULL) { 16072e3f592bSAlexander Motin if ((old_periph->flags & CAM_PERIPH_INVALID) == 0) { 160852c9ce25SScott Long probe_softc *softc; 160952c9ce25SScott Long 161052c9ce25SScott Long softc = (probe_softc *)old_periph->softc; 16112e3f592bSAlexander Motin TAILQ_INSERT_TAIL(&softc->request_ccbs, 16122e3f592bSAlexander Motin &request_ccb->ccb_h, periph_links.tqe); 161383c5d981SAlexander Motin softc->restart = 1; 161452c9ce25SScott Long } else { 16152e3f592bSAlexander Motin request_ccb->ccb_h.status = CAM_REQ_CMP_ERR; 16162e3f592bSAlexander Motin xpt_done(request_ccb); 16172e3f592bSAlexander Motin } 16182e3f592bSAlexander Motin } else { 16190f280cbdSWarner Losh status = cam_periph_alloc(aproberegister, NULL, aprobecleanup, 16200f280cbdSWarner Losh aprobestart, "aprobe", 162152c9ce25SScott Long CAM_PERIPH_BIO, 162252c9ce25SScott Long request_ccb->ccb_h.path, NULL, 0, 162352c9ce25SScott Long request_ccb); 162452c9ce25SScott Long 162552c9ce25SScott Long if (status != CAM_REQ_CMP) { 162652c9ce25SScott Long xpt_print(path, "xpt_scan_lun: cam_alloc_periph " 162752c9ce25SScott Long "returned an error, can't continue probe\n"); 162852c9ce25SScott Long request_ccb->ccb_h.status = status; 162952c9ce25SScott Long xpt_done(request_ccb); 163052c9ce25SScott Long } 163152c9ce25SScott Long } 1632227d67aaSAlexander Motin if (lock) 1633227d67aaSAlexander Motin xpt_path_unlock(path); 163452c9ce25SScott Long } 163552c9ce25SScott Long 163652c9ce25SScott Long static void 16370f280cbdSWarner Losh axptscandone(struct cam_periph *periph, union ccb *done_ccb) 163852c9ce25SScott Long { 163932aa80a6SAlexander Motin 164032aa80a6SAlexander Motin xpt_free_path(done_ccb->ccb_h.path); 164132aa80a6SAlexander Motin xpt_free_ccb(done_ccb); 164252c9ce25SScott Long } 164352c9ce25SScott Long 164452c9ce25SScott Long static struct cam_ed * 164552c9ce25SScott Long ata_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id) 164652c9ce25SScott Long { 164730a4094fSAlexander Motin struct ata_quirk_entry *quirk; 164852c9ce25SScott Long struct cam_ed *device; 164952c9ce25SScott Long 165052c9ce25SScott Long device = xpt_alloc_device(bus, target, lun_id); 165152c9ce25SScott Long if (device == NULL) 165252c9ce25SScott Long return (NULL); 165352c9ce25SScott Long 165452c9ce25SScott Long /* 165552c9ce25SScott Long * Take the default quirk entry until we have inquiry 165652c9ce25SScott Long * data and can determine a better quirk to use. 165752c9ce25SScott Long */ 16588dfea464SPedro F. Giffuni quirk = &ata_quirk_table[nitems(ata_quirk_table) - 1]; 165952c9ce25SScott Long device->quirk = (void *)quirk; 166030a4094fSAlexander Motin device->mintags = 0; 166130a4094fSAlexander Motin device->maxtags = 0; 166252c9ce25SScott Long bzero(&device->inq_data, sizeof(device->inq_data)); 166352c9ce25SScott Long device->inq_flags = 0; 166452c9ce25SScott Long device->queue_flags = 0; 166552c9ce25SScott Long device->serial_num = NULL; 166652c9ce25SScott Long device->serial_num_len = 0; 166752c9ce25SScott Long return (device); 166852c9ce25SScott Long } 166952c9ce25SScott Long 167052c9ce25SScott Long static void 167152c9ce25SScott Long ata_device_transport(struct cam_path *path) 167252c9ce25SScott Long { 167352c9ce25SScott Long struct ccb_pathinq cpi; 16744b997c49SAlexander Motin struct ccb_trans_settings cts; 16754b997c49SAlexander Motin struct scsi_inquiry_data *inq_buf = NULL; 16764b997c49SAlexander Motin struct ata_params *ident_buf = NULL; 167752c9ce25SScott Long 167852c9ce25SScott Long /* Get transport information from the SIM */ 1679762a7f4fSWarner Losh xpt_path_inq(&cpi, path); 168052c9ce25SScott Long 168152c9ce25SScott Long path->device->transport = cpi.transport; 16824b997c49SAlexander Motin if ((path->device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0) 16834b997c49SAlexander Motin inq_buf = &path->device->inq_data; 16844b997c49SAlexander Motin if ((path->device->flags & CAM_DEV_IDENTIFY_DATA_VALID) != 0) 16854b997c49SAlexander Motin ident_buf = &path->device->ident_data; 16864b997c49SAlexander Motin if (path->device->protocol == PROTO_ATA) { 16874b997c49SAlexander Motin path->device->protocol_version = ident_buf ? 16884b997c49SAlexander Motin ata_version(ident_buf->version_major) : cpi.protocol_version; 16894b997c49SAlexander Motin } else if (path->device->protocol == PROTO_SCSI) { 16904b997c49SAlexander Motin path->device->protocol_version = inq_buf ? 16914b997c49SAlexander Motin SID_ANSI_REV(inq_buf) : cpi.protocol_version; 169252c9ce25SScott Long } 16934b997c49SAlexander Motin path->device->transport_version = ident_buf ? 16944b997c49SAlexander Motin ata_version(ident_buf->version_major) : cpi.transport_version; 169552c9ce25SScott Long 169652c9ce25SScott Long /* Tell the controller what we think */ 1697ec5325dbSEdward Tomasz Napierala bzero(&cts, sizeof(cts)); 169883c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 169952c9ce25SScott Long cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 170052c9ce25SScott Long cts.type = CTS_TYPE_CURRENT_SETTINGS; 170152c9ce25SScott Long cts.transport = path->device->transport; 170252c9ce25SScott Long cts.transport_version = path->device->transport_version; 170352c9ce25SScott Long cts.protocol = path->device->protocol; 170452c9ce25SScott Long cts.protocol_version = path->device->protocol_version; 170552c9ce25SScott Long cts.proto_specific.valid = 0; 17064cca1530SAlexander Motin if (ident_buf) { 17074cca1530SAlexander Motin if (path->device->transport == XPORT_ATA) { 17084cca1530SAlexander Motin cts.xport_specific.ata.atapi = 17098e6cab54SAlexander Motin (ident_buf->config == ATA_PROTO_CFA) ? 0 : 17104cca1530SAlexander Motin ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_16) ? 16 : 17114cca1530SAlexander Motin ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) ? 12 : 0; 17124cca1530SAlexander Motin cts.xport_specific.ata.valid = CTS_ATA_VALID_ATAPI; 17134cca1530SAlexander Motin } else { 17144cca1530SAlexander Motin cts.xport_specific.sata.atapi = 17158e6cab54SAlexander Motin (ident_buf->config == ATA_PROTO_CFA) ? 0 : 17164cca1530SAlexander Motin ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_16) ? 16 : 17174cca1530SAlexander Motin ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) ? 12 : 0; 17184cca1530SAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_ATAPI; 17194cca1530SAlexander Motin } 17204cca1530SAlexander Motin } else 172152c9ce25SScott Long cts.xport_specific.valid = 0; 172252c9ce25SScott Long xpt_action((union ccb *)&cts); 172352c9ce25SScott Long } 172452c9ce25SScott Long 172552c9ce25SScott Long static void 172614f900e2SWill Andrews ata_dev_advinfo(union ccb *start_ccb) 172714f900e2SWill Andrews { 172814f900e2SWill Andrews struct cam_ed *device; 172914f900e2SWill Andrews struct ccb_dev_advinfo *cdai; 173014f900e2SWill Andrews off_t amt; 173114f900e2SWill Andrews 17326a216c0bSAlexander Motin xpt_path_assert(start_ccb->ccb_h.path, MA_OWNED); 173314f900e2SWill Andrews start_ccb->ccb_h.status = CAM_REQ_INVALID; 173414f900e2SWill Andrews device = start_ccb->ccb_h.path->device; 173514f900e2SWill Andrews cdai = &start_ccb->cdai; 173614f900e2SWill Andrews switch(cdai->buftype) { 17373089bb2eSAlexander Motin case CDAI_TYPE_SCSI_DEVID: 17383089bb2eSAlexander Motin if (cdai->flags & CDAI_FLAG_STORE) 17393089bb2eSAlexander Motin return; 17403089bb2eSAlexander Motin cdai->provsiz = device->device_id_len; 17413089bb2eSAlexander Motin if (device->device_id_len == 0) 17423089bb2eSAlexander Motin break; 17433089bb2eSAlexander Motin amt = device->device_id_len; 17443089bb2eSAlexander Motin if (cdai->provsiz > cdai->bufsiz) 17453089bb2eSAlexander Motin amt = cdai->bufsiz; 17463089bb2eSAlexander Motin memcpy(cdai->buf, device->device_id, amt); 17473089bb2eSAlexander Motin break; 174814f900e2SWill Andrews case CDAI_TYPE_SERIAL_NUM: 174914f900e2SWill Andrews if (cdai->flags & CDAI_FLAG_STORE) 17503089bb2eSAlexander Motin return; 175114f900e2SWill Andrews cdai->provsiz = device->serial_num_len; 175214f900e2SWill Andrews if (device->serial_num_len == 0) 175314f900e2SWill Andrews break; 175414f900e2SWill Andrews amt = device->serial_num_len; 175514f900e2SWill Andrews if (cdai->provsiz > cdai->bufsiz) 175614f900e2SWill Andrews amt = cdai->bufsiz; 175714f900e2SWill Andrews memcpy(cdai->buf, device->serial_num, amt); 175814f900e2SWill Andrews break; 17593089bb2eSAlexander Motin case CDAI_TYPE_PHYS_PATH: 17603089bb2eSAlexander Motin if (cdai->flags & CDAI_FLAG_STORE) { 17613089bb2eSAlexander Motin if (device->physpath != NULL) 17623089bb2eSAlexander Motin free(device->physpath, M_CAMXPT); 17633089bb2eSAlexander Motin device->physpath_len = cdai->bufsiz; 17643089bb2eSAlexander Motin /* Clear existing buffer if zero length */ 17653089bb2eSAlexander Motin if (cdai->bufsiz == 0) 176614f900e2SWill Andrews break; 17673089bb2eSAlexander Motin device->physpath = malloc(cdai->bufsiz, M_CAMXPT, M_NOWAIT); 17683089bb2eSAlexander Motin if (device->physpath == NULL) { 17693089bb2eSAlexander Motin start_ccb->ccb_h.status = CAM_REQ_ABORTED; 17703089bb2eSAlexander Motin return; 17713089bb2eSAlexander Motin } 17723089bb2eSAlexander Motin memcpy(device->physpath, cdai->buf, cdai->bufsiz); 17733089bb2eSAlexander Motin } else { 17743089bb2eSAlexander Motin cdai->provsiz = device->physpath_len; 17753089bb2eSAlexander Motin if (device->physpath_len == 0) 17763089bb2eSAlexander Motin break; 17773089bb2eSAlexander Motin amt = device->physpath_len; 17783089bb2eSAlexander Motin if (cdai->provsiz > cdai->bufsiz) 17793089bb2eSAlexander Motin amt = cdai->bufsiz; 17803089bb2eSAlexander Motin memcpy(cdai->buf, device->physpath, amt); 17813089bb2eSAlexander Motin } 17823089bb2eSAlexander Motin break; 17833089bb2eSAlexander Motin default: 17843089bb2eSAlexander Motin return; 17853089bb2eSAlexander Motin } 17863089bb2eSAlexander Motin start_ccb->ccb_h.status = CAM_REQ_CMP; 17873089bb2eSAlexander Motin 17883089bb2eSAlexander Motin if (cdai->flags & CDAI_FLAG_STORE) { 17893089bb2eSAlexander Motin xpt_async(AC_ADVINFO_CHANGED, start_ccb->ccb_h.path, 17903089bb2eSAlexander Motin (void *)(uintptr_t)cdai->buftype); 179114f900e2SWill Andrews } 179214f900e2SWill Andrews } 179314f900e2SWill Andrews 179414f900e2SWill Andrews static void 179552c9ce25SScott Long ata_action(union ccb *start_ccb) 179652c9ce25SScott Long { 179752c9ce25SScott Long 179852c9ce25SScott Long switch (start_ccb->ccb_h.func_code) { 179952c9ce25SScott Long case XPT_SET_TRAN_SETTINGS: 180052c9ce25SScott Long { 180130a4094fSAlexander Motin ata_set_transfer_settings(&start_ccb->cts, 1802227d67aaSAlexander Motin start_ccb->ccb_h.path, 180352c9ce25SScott Long /*async_update*/FALSE); 180452c9ce25SScott Long break; 180552c9ce25SScott Long } 180652c9ce25SScott Long case XPT_SCAN_BUS: 18070e85f214SMatt Jacob case XPT_SCAN_TGT: 180852c9ce25SScott Long ata_scan_bus(start_ccb->ccb_h.path->periph, start_ccb); 180952c9ce25SScott Long break; 181052c9ce25SScott Long case XPT_SCAN_LUN: 181152c9ce25SScott Long ata_scan_lun(start_ccb->ccb_h.path->periph, 181252c9ce25SScott Long start_ccb->ccb_h.path, start_ccb->crcn.flags, 181352c9ce25SScott Long start_ccb); 181452c9ce25SScott Long break; 181552c9ce25SScott Long case XPT_GET_TRAN_SETTINGS: 181652c9ce25SScott Long { 1817b9c473b2SAlexander Motin ata_get_transfer_settings(&start_ccb->cts); 181852c9ce25SScott Long break; 181952c9ce25SScott Long } 18204cca1530SAlexander Motin case XPT_SCSI_IO: 18214cca1530SAlexander Motin { 18224cca1530SAlexander Motin struct cam_ed *device; 18234cca1530SAlexander Motin u_int maxlen = 0; 18244cca1530SAlexander Motin 18254cca1530SAlexander Motin device = start_ccb->ccb_h.path->device; 18264cca1530SAlexander Motin if (device->protocol == PROTO_SCSI && 18274cca1530SAlexander Motin (device->flags & CAM_DEV_IDENTIFY_DATA_VALID)) { 18284cca1530SAlexander Motin uint16_t p = 18294cca1530SAlexander Motin device->ident_data.config & ATA_PROTO_MASK; 18304cca1530SAlexander Motin 18318e6cab54SAlexander Motin maxlen = 18328e6cab54SAlexander Motin (device->ident_data.config == ATA_PROTO_CFA) ? 0 : 18338e6cab54SAlexander Motin (p == ATA_PROTO_ATAPI_16) ? 16 : 18344cca1530SAlexander Motin (p == ATA_PROTO_ATAPI_12) ? 12 : 0; 18354cca1530SAlexander Motin } 18364cca1530SAlexander Motin if (start_ccb->csio.cdb_len > maxlen) { 18374cca1530SAlexander Motin start_ccb->ccb_h.status = CAM_REQ_INVALID; 18384cca1530SAlexander Motin xpt_done(start_ccb); 18394cca1530SAlexander Motin break; 18404cca1530SAlexander Motin } 1841ee2b236bSAlexander Motin xpt_action_default(start_ccb); 1842ee2b236bSAlexander Motin break; 18434cca1530SAlexander Motin } 184414f900e2SWill Andrews case XPT_DEV_ADVINFO: 184514f900e2SWill Andrews { 184614f900e2SWill Andrews ata_dev_advinfo(start_ccb); 184714f900e2SWill Andrews break; 184814f900e2SWill Andrews } 184952c9ce25SScott Long default: 185052c9ce25SScott Long xpt_action_default(start_ccb); 185152c9ce25SScott Long break; 185252c9ce25SScott Long } 185352c9ce25SScott Long } 185452c9ce25SScott Long 185552c9ce25SScott Long static void 1856b9c473b2SAlexander Motin ata_get_transfer_settings(struct ccb_trans_settings *cts) 1857b9c473b2SAlexander Motin { 1858b9c473b2SAlexander Motin struct ccb_trans_settings_ata *ata; 1859b9c473b2SAlexander Motin struct ccb_trans_settings_scsi *scsi; 1860b9c473b2SAlexander Motin struct cam_ed *device; 1861b9c473b2SAlexander Motin 1862b9c473b2SAlexander Motin device = cts->ccb_h.path->device; 1863227d67aaSAlexander Motin xpt_action_default((union ccb *)cts); 1864b9c473b2SAlexander Motin 1865bc1bf6e8SAlexander Motin if (cts->protocol == PROTO_UNKNOWN || 1866bc1bf6e8SAlexander Motin cts->protocol == PROTO_UNSPECIFIED) { 1867bc1bf6e8SAlexander Motin cts->protocol = device->protocol; 1868bc1bf6e8SAlexander Motin cts->protocol_version = device->protocol_version; 1869bc1bf6e8SAlexander Motin } 1870bc1bf6e8SAlexander Motin 1871b9c473b2SAlexander Motin if (cts->protocol == PROTO_ATA) { 1872b9c473b2SAlexander Motin ata = &cts->proto_specific.ata; 1873b9c473b2SAlexander Motin if ((ata->valid & CTS_ATA_VALID_TQ) == 0) { 1874b9c473b2SAlexander Motin ata->valid |= CTS_ATA_VALID_TQ; 1875b9c473b2SAlexander Motin if (cts->type == CTS_TYPE_USER_SETTINGS || 1876b9c473b2SAlexander Motin (device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 || 1877b9c473b2SAlexander Motin (device->inq_flags & SID_CmdQue) != 0) 1878b9c473b2SAlexander Motin ata->flags |= CTS_ATA_FLAGS_TAG_ENB; 1879b9c473b2SAlexander Motin } 1880b9c473b2SAlexander Motin } 1881b9c473b2SAlexander Motin if (cts->protocol == PROTO_SCSI) { 1882b9c473b2SAlexander Motin scsi = &cts->proto_specific.scsi; 1883b9c473b2SAlexander Motin if ((scsi->valid & CTS_SCSI_VALID_TQ) == 0) { 1884b9c473b2SAlexander Motin scsi->valid |= CTS_SCSI_VALID_TQ; 1885b9c473b2SAlexander Motin if (cts->type == CTS_TYPE_USER_SETTINGS || 1886b9c473b2SAlexander Motin (device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 || 1887b9c473b2SAlexander Motin (device->inq_flags & SID_CmdQue) != 0) 1888b9c473b2SAlexander Motin scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 1889b9c473b2SAlexander Motin } 1890b9c473b2SAlexander Motin } 1891bc1bf6e8SAlexander Motin 1892bc1bf6e8SAlexander Motin if (cts->transport == XPORT_UNKNOWN || 1893bc1bf6e8SAlexander Motin cts->transport == XPORT_UNSPECIFIED) { 1894bc1bf6e8SAlexander Motin cts->transport = device->transport; 1895bc1bf6e8SAlexander Motin cts->transport_version = device->transport_version; 1896bc1bf6e8SAlexander Motin } 1897b9c473b2SAlexander Motin } 1898b9c473b2SAlexander Motin 1899b9c473b2SAlexander Motin static void 1900227d67aaSAlexander Motin ata_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_path *path, 190152c9ce25SScott Long int async_update) 190252c9ce25SScott Long { 190352c9ce25SScott Long struct ccb_pathinq cpi; 1904b9c473b2SAlexander Motin struct ccb_trans_settings_ata *ata; 190552c9ce25SScott Long struct ccb_trans_settings_scsi *scsi; 1906b9c473b2SAlexander Motin struct ata_params *ident_data; 190752c9ce25SScott Long struct scsi_inquiry_data *inq_data; 1908227d67aaSAlexander Motin struct cam_ed *device; 190952c9ce25SScott Long 1910227d67aaSAlexander Motin if (path == NULL || (device = path->device) == NULL) { 191152c9ce25SScott Long cts->ccb_h.status = CAM_PATH_INVALID; 191252c9ce25SScott Long xpt_done((union ccb *)cts); 191352c9ce25SScott Long return; 191452c9ce25SScott Long } 191552c9ce25SScott Long 191652c9ce25SScott Long if (cts->protocol == PROTO_UNKNOWN 191752c9ce25SScott Long || cts->protocol == PROTO_UNSPECIFIED) { 191852c9ce25SScott Long cts->protocol = device->protocol; 191952c9ce25SScott Long cts->protocol_version = device->protocol_version; 192052c9ce25SScott Long } 192152c9ce25SScott Long 192252c9ce25SScott Long if (cts->protocol_version == PROTO_VERSION_UNKNOWN 192352c9ce25SScott Long || cts->protocol_version == PROTO_VERSION_UNSPECIFIED) 192452c9ce25SScott Long cts->protocol_version = device->protocol_version; 192552c9ce25SScott Long 192652c9ce25SScott Long if (cts->protocol != device->protocol) { 1927227d67aaSAlexander Motin xpt_print(path, "Uninitialized Protocol %x:%x?\n", 192852c9ce25SScott Long cts->protocol, device->protocol); 192952c9ce25SScott Long cts->protocol = device->protocol; 193052c9ce25SScott Long } 193152c9ce25SScott Long 193252c9ce25SScott Long if (cts->protocol_version > device->protocol_version) { 193352c9ce25SScott Long if (bootverbose) { 1934227d67aaSAlexander Motin xpt_print(path, "Down reving Protocol " 193552c9ce25SScott Long "Version from %d to %d?\n", cts->protocol_version, 193652c9ce25SScott Long device->protocol_version); 193752c9ce25SScott Long } 193852c9ce25SScott Long cts->protocol_version = device->protocol_version; 193952c9ce25SScott Long } 194052c9ce25SScott Long 194152c9ce25SScott Long if (cts->transport == XPORT_UNKNOWN 194252c9ce25SScott Long || cts->transport == XPORT_UNSPECIFIED) { 194352c9ce25SScott Long cts->transport = device->transport; 194452c9ce25SScott Long cts->transport_version = device->transport_version; 194552c9ce25SScott Long } 194652c9ce25SScott Long 194752c9ce25SScott Long if (cts->transport_version == XPORT_VERSION_UNKNOWN 194852c9ce25SScott Long || cts->transport_version == XPORT_VERSION_UNSPECIFIED) 194952c9ce25SScott Long cts->transport_version = device->transport_version; 195052c9ce25SScott Long 195152c9ce25SScott Long if (cts->transport != device->transport) { 1952227d67aaSAlexander Motin xpt_print(path, "Uninitialized Transport %x:%x?\n", 195352c9ce25SScott Long cts->transport, device->transport); 195452c9ce25SScott Long cts->transport = device->transport; 195552c9ce25SScott Long } 195652c9ce25SScott Long 195752c9ce25SScott Long if (cts->transport_version > device->transport_version) { 195852c9ce25SScott Long if (bootverbose) { 1959227d67aaSAlexander Motin xpt_print(path, "Down reving Transport " 196052c9ce25SScott Long "Version from %d to %d?\n", cts->transport_version, 196152c9ce25SScott Long device->transport_version); 196252c9ce25SScott Long } 196352c9ce25SScott Long cts->transport_version = device->transport_version; 196452c9ce25SScott Long } 196552c9ce25SScott Long 1966b9c473b2SAlexander Motin ident_data = &device->ident_data; 196752c9ce25SScott Long inq_data = &device->inq_data; 1968b9c473b2SAlexander Motin if (cts->protocol == PROTO_ATA) 1969b9c473b2SAlexander Motin ata = &cts->proto_specific.ata; 1970b9c473b2SAlexander Motin else 1971b9c473b2SAlexander Motin ata = NULL; 1972b9c473b2SAlexander Motin if (cts->protocol == PROTO_SCSI) 197352c9ce25SScott Long scsi = &cts->proto_specific.scsi; 1974b9c473b2SAlexander Motin else 1975b9c473b2SAlexander Motin scsi = NULL; 1976762a7f4fSWarner Losh xpt_path_inq(&cpi, path); 197752c9ce25SScott Long 1978b9c473b2SAlexander Motin /* Sanity checking */ 197952c9ce25SScott Long if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0 1980b9c473b2SAlexander Motin || (ata && (ident_data->satacapabilities & ATA_SUPPORT_NCQ) == 0) 1981b9c473b2SAlexander Motin || (scsi && (INQ_DATA_TQ_ENABLED(inq_data)) == 0) 198252c9ce25SScott Long || (device->queue_flags & SCP_QUEUE_DQUE) != 0 198352c9ce25SScott Long || (device->mintags == 0)) { 198452c9ce25SScott Long /* 198552c9ce25SScott Long * Can't tag on hardware that doesn't support tags, 198652c9ce25SScott Long * doesn't have it enabled, or has broken tag support. 198752c9ce25SScott Long */ 1988b9c473b2SAlexander Motin if (ata) 1989b9c473b2SAlexander Motin ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB; 1990b9c473b2SAlexander Motin if (scsi) 199152c9ce25SScott Long scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 199252c9ce25SScott Long } 199352c9ce25SScott Long 1994b9c473b2SAlexander Motin /* Start/stop tags use. */ 1995b9c473b2SAlexander Motin if (cts->type == CTS_TYPE_CURRENT_SETTINGS && 1996b9c473b2SAlexander Motin ((ata && (ata->valid & CTS_ATA_VALID_TQ) != 0) || 1997b9c473b2SAlexander Motin (scsi && (scsi->valid & CTS_SCSI_VALID_TQ) != 0))) { 1998b9c473b2SAlexander Motin int nowt, newt = 0; 199952c9ce25SScott Long 2000b9c473b2SAlexander Motin nowt = ((device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 || 2001b9c473b2SAlexander Motin (device->inq_flags & SID_CmdQue) != 0); 2002b9c473b2SAlexander Motin if (ata) 2003b9c473b2SAlexander Motin newt = (ata->flags & CTS_ATA_FLAGS_TAG_ENB) != 0; 2004b9c473b2SAlexander Motin if (scsi) 2005b9c473b2SAlexander Motin newt = (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0; 200652c9ce25SScott Long 2007b9c473b2SAlexander Motin if (newt && !nowt) { 200852c9ce25SScott Long /* 200952c9ce25SScott Long * Delay change to use tags until after a 201052c9ce25SScott Long * few commands have gone to this device so 201152c9ce25SScott Long * the controller has time to perform transfer 201252c9ce25SScott Long * negotiations without tagged messages getting 201352c9ce25SScott Long * in the way. 201452c9ce25SScott Long */ 201552c9ce25SScott Long device->tag_delay_count = CAM_TAG_DELAY_COUNT; 201652c9ce25SScott Long device->flags |= CAM_DEV_TAG_AFTER_COUNT; 2017b9c473b2SAlexander Motin } else if (nowt && !newt) 2018227d67aaSAlexander Motin xpt_stop_tags(path); 201952c9ce25SScott Long } 2020b9c473b2SAlexander Motin 202152c9ce25SScott Long if (async_update == FALSE) 2022227d67aaSAlexander Motin xpt_action_default((union ccb *)cts); 202352c9ce25SScott Long } 202452c9ce25SScott Long 202552c9ce25SScott Long /* 202652c9ce25SScott Long * Handle any per-device event notifications that require action by the XPT. 202752c9ce25SScott Long */ 202852c9ce25SScott Long static void 202952c9ce25SScott Long ata_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target, 203052c9ce25SScott Long struct cam_ed *device, void *async_arg) 203152c9ce25SScott Long { 203252c9ce25SScott Long cam_status status; 203352c9ce25SScott Long struct cam_path newpath; 203452c9ce25SScott Long 203552c9ce25SScott Long /* 203652c9ce25SScott Long * We only need to handle events for real devices. 203752c9ce25SScott Long */ 203852c9ce25SScott Long if (target->target_id == CAM_TARGET_WILDCARD 203952c9ce25SScott Long || device->lun_id == CAM_LUN_WILDCARD) 204052c9ce25SScott Long return; 204152c9ce25SScott Long 204252c9ce25SScott Long /* 204352c9ce25SScott Long * We need our own path with wildcards expanded to 204452c9ce25SScott Long * handle certain types of events. 204552c9ce25SScott Long */ 204652c9ce25SScott Long if ((async_code == AC_SENT_BDR) 204752c9ce25SScott Long || (async_code == AC_BUS_RESET) 204852c9ce25SScott Long || (async_code == AC_INQ_CHANGED)) 204952c9ce25SScott Long status = xpt_compile_path(&newpath, NULL, 205052c9ce25SScott Long bus->path_id, 205152c9ce25SScott Long target->target_id, 205252c9ce25SScott Long device->lun_id); 205352c9ce25SScott Long else 205452c9ce25SScott Long status = CAM_REQ_CMP_ERR; 205552c9ce25SScott Long 205652c9ce25SScott Long if (status == CAM_REQ_CMP) { 205752c9ce25SScott Long if (async_code == AC_INQ_CHANGED) { 205852c9ce25SScott Long /* 205952c9ce25SScott Long * We've sent a start unit command, or 206052c9ce25SScott Long * something similar to a device that 206152c9ce25SScott Long * may have caused its inquiry data to 206252c9ce25SScott Long * change. So we re-scan the device to 206352c9ce25SScott Long * refresh the inquiry data for it. 206452c9ce25SScott Long */ 206552c9ce25SScott Long ata_scan_lun(newpath.periph, &newpath, 206652c9ce25SScott Long CAM_EXPECT_INQ_CHANGE, NULL); 206783c5d981SAlexander Motin } else { 206883c5d981SAlexander Motin /* We need to reinitialize device after reset. */ 206983c5d981SAlexander Motin ata_scan_lun(newpath.periph, &newpath, 207083c5d981SAlexander Motin 0, NULL); 207152c9ce25SScott Long } 207252c9ce25SScott Long xpt_release_path(&newpath); 2073f98d7a47SAlexander Motin } else if (async_code == AC_LOST_DEVICE && 2074f98d7a47SAlexander Motin (device->flags & CAM_DEV_UNCONFIGURED) == 0) { 207552c9ce25SScott Long device->flags |= CAM_DEV_UNCONFIGURED; 2076f98d7a47SAlexander Motin xpt_release_device(device); 207752c9ce25SScott Long } else if (async_code == AC_TRANSFER_NEG) { 207852c9ce25SScott Long struct ccb_trans_settings *settings; 2079227d67aaSAlexander Motin struct cam_path path; 208052c9ce25SScott Long 208152c9ce25SScott Long settings = (struct ccb_trans_settings *)async_arg; 2082227d67aaSAlexander Motin xpt_compile_path(&path, NULL, bus->path_id, target->target_id, 2083227d67aaSAlexander Motin device->lun_id); 2084227d67aaSAlexander Motin ata_set_transfer_settings(settings, &path, 208552c9ce25SScott Long /*async_update*/TRUE); 2086227d67aaSAlexander Motin xpt_release_path(&path); 208752c9ce25SScott Long } 208852c9ce25SScott Long } 208952c9ce25SScott Long 209057079b17SAlexander Motin static void 20915d01277fSScott Long _ata_announce_periph(struct cam_periph *periph, struct ccb_trans_settings *cts, u_int *speed) 209257079b17SAlexander Motin { 209357079b17SAlexander Motin struct ccb_pathinq cpi; 209457079b17SAlexander Motin struct cam_path *path = periph->path; 209557079b17SAlexander Motin 2096227d67aaSAlexander Motin cam_periph_assert(periph, MA_OWNED); 209757079b17SAlexander Motin 20985d01277fSScott Long xpt_setup_ccb(&cts->ccb_h, path, CAM_PRIORITY_NORMAL); 20995d01277fSScott Long cts->ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 21005d01277fSScott Long cts->type = CTS_TYPE_CURRENT_SETTINGS; 21015d01277fSScott Long xpt_action((union ccb*)cts); 21025d01277fSScott Long if ((cts->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 210357079b17SAlexander Motin return; 210457079b17SAlexander Motin /* Ask the SIM for its base transfer speed */ 2105762a7f4fSWarner Losh xpt_path_inq(&cpi, path); 210657079b17SAlexander Motin /* Report connection speed */ 21075d01277fSScott Long *speed = cpi.base_transfer_speed; 21085d01277fSScott Long if (cts->transport == XPORT_ATA) { 2109b9c473b2SAlexander Motin struct ccb_trans_settings_pata *pata = 21105d01277fSScott Long &cts->xport_specific.ata; 211157079b17SAlexander Motin 2112b9c473b2SAlexander Motin if (pata->valid & CTS_ATA_VALID_MODE) 21135d01277fSScott Long *speed = ata_mode2speed(pata->mode); 211457079b17SAlexander Motin } 21155d01277fSScott Long if (cts->transport == XPORT_SATA) { 211657079b17SAlexander Motin struct ccb_trans_settings_sata *sata = 21175d01277fSScott Long &cts->xport_specific.sata; 211857079b17SAlexander Motin 211957079b17SAlexander Motin if (sata->valid & CTS_SATA_VALID_REVISION) 21205d01277fSScott Long *speed = ata_revision2speed(sata->revision); 212157079b17SAlexander Motin } 21225d01277fSScott Long } 21235d01277fSScott Long 21245d01277fSScott Long static void 21255d01277fSScott Long ata_announce_periph(struct cam_periph *periph) 21265d01277fSScott Long { 21275d01277fSScott Long struct ccb_trans_settings cts; 21285d01277fSScott Long u_int speed, mb; 21295d01277fSScott Long 2130ec5325dbSEdward Tomasz Napierala bzero(&cts, sizeof(cts)); 21315d01277fSScott Long _ata_announce_periph(periph, &cts, &speed); 21325d01277fSScott Long if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 21335d01277fSScott Long return; 21345d01277fSScott Long 213557079b17SAlexander Motin mb = speed / 1000; 213657079b17SAlexander Motin if (mb > 0) 213757079b17SAlexander Motin printf("%s%d: %d.%03dMB/s transfers", 213857079b17SAlexander Motin periph->periph_name, periph->unit_number, 213957079b17SAlexander Motin mb, speed % 1000); 214057079b17SAlexander Motin else 214157079b17SAlexander Motin printf("%s%d: %dKB/s transfers", periph->periph_name, 214257079b17SAlexander Motin periph->unit_number, speed); 214357079b17SAlexander Motin /* Report additional information about connection */ 21445d01277fSScott Long if (cts.transport == XPORT_ATA) { 2145b9c473b2SAlexander Motin struct ccb_trans_settings_pata *pata = 214657079b17SAlexander Motin &cts.xport_specific.ata; 214757079b17SAlexander Motin 214857079b17SAlexander Motin printf(" ("); 2149b9c473b2SAlexander Motin if (pata->valid & CTS_ATA_VALID_MODE) 2150b9c473b2SAlexander Motin printf("%s, ", ata_mode2string(pata->mode)); 2151b9c473b2SAlexander Motin if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0) 2152b9c473b2SAlexander Motin printf("ATAPI %dbytes, ", pata->atapi); 2153b9c473b2SAlexander Motin if (pata->valid & CTS_ATA_VALID_BYTECOUNT) 2154b9c473b2SAlexander Motin printf("PIO %dbytes", pata->bytecount); 215557079b17SAlexander Motin printf(")"); 215657079b17SAlexander Motin } 21575d01277fSScott Long if (cts.transport == XPORT_SATA) { 215857079b17SAlexander Motin struct ccb_trans_settings_sata *sata = 215957079b17SAlexander Motin &cts.xport_specific.sata; 216057079b17SAlexander Motin 216157079b17SAlexander Motin printf(" ("); 216257079b17SAlexander Motin if (sata->valid & CTS_SATA_VALID_REVISION) 216357079b17SAlexander Motin printf("SATA %d.x, ", sata->revision); 216457079b17SAlexander Motin else 216557079b17SAlexander Motin printf("SATA, "); 216657079b17SAlexander Motin if (sata->valid & CTS_SATA_VALID_MODE) 216757079b17SAlexander Motin printf("%s, ", ata_mode2string(sata->mode)); 216857079b17SAlexander Motin if ((sata->valid & CTS_ATA_VALID_ATAPI) && sata->atapi != 0) 216957079b17SAlexander Motin printf("ATAPI %dbytes, ", sata->atapi); 217057079b17SAlexander Motin if (sata->valid & CTS_SATA_VALID_BYTECOUNT) 217157079b17SAlexander Motin printf("PIO %dbytes", sata->bytecount); 217257079b17SAlexander Motin printf(")"); 217357079b17SAlexander Motin } 217457079b17SAlexander Motin printf("\n"); 217557079b17SAlexander Motin } 217608f13879SWarner Losh 217708f13879SWarner Losh static void 21785d01277fSScott Long ata_announce_periph_sbuf(struct cam_periph *periph, struct sbuf *sb) 21795d01277fSScott Long { 21805d01277fSScott Long struct ccb_trans_settings cts; 21815d01277fSScott Long u_int speed, mb; 21825d01277fSScott Long 21835d01277fSScott Long _ata_announce_periph(periph, &cts, &speed); 21845d01277fSScott Long if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 21855d01277fSScott Long return; 21865d01277fSScott Long 21875d01277fSScott Long mb = speed / 1000; 21885d01277fSScott Long if (mb > 0) 21895d01277fSScott Long sbuf_printf(sb, "%s%d: %d.%03dMB/s transfers", 21905d01277fSScott Long periph->periph_name, periph->unit_number, 21915d01277fSScott Long mb, speed % 1000); 21925d01277fSScott Long else 21935d01277fSScott Long sbuf_printf(sb, "%s%d: %dKB/s transfers", periph->periph_name, 21945d01277fSScott Long periph->unit_number, speed); 21955d01277fSScott Long /* Report additional information about connection */ 21965d01277fSScott Long if (cts.transport == XPORT_ATA) { 21975d01277fSScott Long struct ccb_trans_settings_pata *pata = 21985d01277fSScott Long &cts.xport_specific.ata; 21995d01277fSScott Long 22005d01277fSScott Long sbuf_printf(sb, " ("); 22015d01277fSScott Long if (pata->valid & CTS_ATA_VALID_MODE) 22025d01277fSScott Long sbuf_printf(sb, "%s, ", ata_mode2string(pata->mode)); 22035d01277fSScott Long if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0) 22045d01277fSScott Long sbuf_printf(sb, "ATAPI %dbytes, ", pata->atapi); 22055d01277fSScott Long if (pata->valid & CTS_ATA_VALID_BYTECOUNT) 22065d01277fSScott Long sbuf_printf(sb, "PIO %dbytes", pata->bytecount); 22075d01277fSScott Long sbuf_printf(sb, ")"); 22085d01277fSScott Long } 22095d01277fSScott Long if (cts.transport == XPORT_SATA) { 22105d01277fSScott Long struct ccb_trans_settings_sata *sata = 22115d01277fSScott Long &cts.xport_specific.sata; 22125d01277fSScott Long 22135d01277fSScott Long sbuf_printf(sb, " ("); 22145d01277fSScott Long if (sata->valid & CTS_SATA_VALID_REVISION) 22155d01277fSScott Long sbuf_printf(sb, "SATA %d.x, ", sata->revision); 22165d01277fSScott Long else 22175d01277fSScott Long sbuf_printf(sb, "SATA, "); 22185d01277fSScott Long if (sata->valid & CTS_SATA_VALID_MODE) 22195d01277fSScott Long sbuf_printf(sb, "%s, ", ata_mode2string(sata->mode)); 22205d01277fSScott Long if ((sata->valid & CTS_ATA_VALID_ATAPI) && sata->atapi != 0) 22215d01277fSScott Long sbuf_printf(sb, "ATAPI %dbytes, ", sata->atapi); 22225d01277fSScott Long if (sata->valid & CTS_SATA_VALID_BYTECOUNT) 22235d01277fSScott Long sbuf_printf(sb, "PIO %dbytes", sata->bytecount); 22245d01277fSScott Long sbuf_printf(sb, ")"); 22255d01277fSScott Long } 22265d01277fSScott Long sbuf_printf(sb, "\n"); 22275d01277fSScott Long } 22285d01277fSScott Long 22295d01277fSScott Long static void 22305d01277fSScott Long ata_proto_announce_sbuf(struct cam_ed *device, struct sbuf *sb) 22315d01277fSScott Long { 22325d01277fSScott Long ata_print_ident_sbuf(&device->ident_data, sb); 22335d01277fSScott Long } 22345d01277fSScott Long 22355d01277fSScott Long static void 223608f13879SWarner Losh ata_proto_announce(struct cam_ed *device) 223708f13879SWarner Losh { 223808f13879SWarner Losh ata_print_ident(&device->ident_data); 223908f13879SWarner Losh } 224008f13879SWarner Losh 224108f13879SWarner Losh static void 224208f13879SWarner Losh ata_proto_denounce(struct cam_ed *device) 224308f13879SWarner Losh { 224408f13879SWarner Losh ata_print_ident_short(&device->ident_data); 224508f13879SWarner Losh } 224608f13879SWarner Losh 224708f13879SWarner Losh static void 22485d01277fSScott Long ata_proto_denounce_sbuf(struct cam_ed *device, struct sbuf *sb) 22495d01277fSScott Long { 22505d01277fSScott Long ata_print_ident_short_sbuf(&device->ident_data, sb); 22515d01277fSScott Long } 22525d01277fSScott Long 22535d01277fSScott Long static void 22545d01277fSScott Long semb_proto_announce_sbuf(struct cam_ed *device, struct sbuf *sb) 22555d01277fSScott Long { 22565d01277fSScott Long semb_print_ident_sbuf((struct sep_identify_data *)&device->ident_data, sb); 22575d01277fSScott Long } 22585d01277fSScott Long 22595d01277fSScott Long static void 226008f13879SWarner Losh semb_proto_announce(struct cam_ed *device) 226108f13879SWarner Losh { 226208f13879SWarner Losh semb_print_ident((struct sep_identify_data *)&device->ident_data); 226308f13879SWarner Losh } 226408f13879SWarner Losh 226508f13879SWarner Losh static void 226608f13879SWarner Losh semb_proto_denounce(struct cam_ed *device) 226708f13879SWarner Losh { 226808f13879SWarner Losh semb_print_ident_short((struct sep_identify_data *)&device->ident_data); 226908f13879SWarner Losh } 227008f13879SWarner Losh 227108f13879SWarner Losh static void 22725d01277fSScott Long semb_proto_denounce_sbuf(struct cam_ed *device, struct sbuf *sb) 22735d01277fSScott Long { 22745d01277fSScott Long semb_print_ident_short_sbuf((struct sep_identify_data *)&device->ident_data, sb); 22755d01277fSScott Long } 22765d01277fSScott Long 22775d01277fSScott Long static void 227808f13879SWarner Losh ata_proto_debug_out(union ccb *ccb) 227908f13879SWarner Losh { 228008f13879SWarner Losh char cdb_str[(sizeof(struct ata_cmd) * 3) + 1]; 228108f13879SWarner Losh 228208f13879SWarner Losh if (ccb->ccb_h.func_code != XPT_ATA_IO) 228308f13879SWarner Losh return; 228408f13879SWarner Losh 228508f13879SWarner Losh CAM_DEBUG(ccb->ccb_h.path, 228608f13879SWarner Losh CAM_DEBUG_CDB,("%s. ACB: %s\n", ata_op_string(&ccb->ataio.cmd), 228708f13879SWarner Losh ata_cmd_string(&ccb->ataio.cmd, cdb_str, sizeof(cdb_str)))); 228808f13879SWarner Losh } 2289