152c9ce25SScott Long /*- 2bec9534dSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3bec9534dSPedro F. Giffuni * 452c9ce25SScott Long * Copyright (c) 2009 Alexander Motin <mav@FreeBSD.org> 552c9ce25SScott Long * All rights reserved. 652c9ce25SScott Long * 752c9ce25SScott Long * Redistribution and use in source and binary forms, with or without 852c9ce25SScott Long * modification, are permitted provided that the following conditions 952c9ce25SScott Long * are met: 1052c9ce25SScott Long * 1. Redistributions of source code must retain the above copyright 1152c9ce25SScott Long * notice, this list of conditions and the following disclaimer, 1252c9ce25SScott Long * without modification, immediately at the beginning of the file. 1352c9ce25SScott Long * 2. Redistributions in binary form must reproduce the above copyright 1452c9ce25SScott Long * notice, this list of conditions and the following disclaimer in the 1552c9ce25SScott Long * documentation and/or other materials provided with the distribution. 1652c9ce25SScott Long * 1752c9ce25SScott Long * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1852c9ce25SScott Long * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1952c9ce25SScott Long * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2052c9ce25SScott Long * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2152c9ce25SScott Long * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2252c9ce25SScott Long * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2352c9ce25SScott Long * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2452c9ce25SScott Long * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2552c9ce25SScott Long * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2652c9ce25SScott Long * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2752c9ce25SScott Long */ 2852c9ce25SScott Long 2952c9ce25SScott Long #include <sys/cdefs.h> 3052c9ce25SScott Long __FBSDID("$FreeBSD$"); 3152c9ce25SScott Long 3252c9ce25SScott Long #include <sys/param.h> 3352c9ce25SScott Long #include <sys/bus.h> 3452c9ce25SScott Long #include <sys/endian.h> 3552c9ce25SScott Long #include <sys/systm.h> 3652c9ce25SScott Long #include <sys/types.h> 3752c9ce25SScott Long #include <sys/malloc.h> 3852c9ce25SScott Long #include <sys/kernel.h> 3952c9ce25SScott Long #include <sys/time.h> 4052c9ce25SScott Long #include <sys/conf.h> 4152c9ce25SScott Long #include <sys/fcntl.h> 4252c9ce25SScott Long #include <sys/interrupt.h> 4352c9ce25SScott Long #include <sys/sbuf.h> 4452c9ce25SScott Long 45a11463fdSSepherosa Ziehau #include <sys/eventhandler.h> 4652c9ce25SScott Long #include <sys/lock.h> 4752c9ce25SScott Long #include <sys/mutex.h> 4852c9ce25SScott Long #include <sys/sysctl.h> 4952c9ce25SScott Long 5052c9ce25SScott Long #include <cam/cam.h> 5152c9ce25SScott Long #include <cam/cam_ccb.h> 5252c9ce25SScott Long #include <cam/cam_queue.h> 5352c9ce25SScott Long #include <cam/cam_periph.h> 5452c9ce25SScott Long #include <cam/cam_sim.h> 5552c9ce25SScott Long #include <cam/cam_xpt.h> 5652c9ce25SScott Long #include <cam/cam_xpt_sim.h> 5752c9ce25SScott Long #include <cam/cam_xpt_periph.h> 5852c9ce25SScott Long #include <cam/cam_xpt_internal.h> 5952c9ce25SScott Long #include <cam/cam_debug.h> 6052c9ce25SScott Long 6152c9ce25SScott Long #include <cam/scsi/scsi_all.h> 6252c9ce25SScott Long #include <cam/scsi/scsi_message.h> 6352c9ce25SScott Long #include <cam/ata/ata_all.h> 6452c9ce25SScott Long #include <machine/stdarg.h> /* for xpt_print below */ 6552c9ce25SScott Long #include "opt_cam.h" 6652c9ce25SScott Long 6730a4094fSAlexander Motin struct ata_quirk_entry { 6852c9ce25SScott Long struct scsi_inquiry_pattern inq_pat; 6952c9ce25SScott Long u_int8_t quirks; 7030a4094fSAlexander Motin #define CAM_QUIRK_MAXTAGS 0x01 717dc3213dSAlexander Motin u_int mintags; 7252c9ce25SScott Long u_int maxtags; 7352c9ce25SScott Long }; 7452c9ce25SScott Long 7552c9ce25SScott Long static periph_init_t probe_periph_init; 7652c9ce25SScott Long 7752c9ce25SScott Long static struct periph_driver probe_driver = 7852c9ce25SScott Long { 79f09f8e3eSAlexander Motin probe_periph_init, "aprobe", 801e637ba6SAlexander Motin TAILQ_HEAD_INITIALIZER(probe_driver.units), /* generation */ 0, 811e637ba6SAlexander Motin CAM_PERIPH_DRV_EARLY 8252c9ce25SScott Long }; 8352c9ce25SScott Long 84f09f8e3eSAlexander Motin PERIPHDRIVER_DECLARE(aprobe, probe_driver); 8552c9ce25SScott Long 8652c9ce25SScott Long typedef enum { 8752c9ce25SScott Long PROBE_RESET, 8852c9ce25SScott Long PROBE_IDENTIFY, 894ef08dc5SAlexander Motin PROBE_SPINUP, 9052c9ce25SScott Long PROBE_SETMODE, 91da6808c1SAlexander Motin PROBE_SETPM, 92da6808c1SAlexander Motin PROBE_SETAPST, 93da6808c1SAlexander Motin PROBE_SETDMAAA, 948d169381SAlexander Motin PROBE_SETAN, 951e637ba6SAlexander Motin PROBE_SET_MULTI, 9652c9ce25SScott Long PROBE_INQUIRY, 9752c9ce25SScott Long PROBE_FULL_INQUIRY, 9852c9ce25SScott Long PROBE_PM_PID, 9952c9ce25SScott Long PROBE_PM_PRV, 1003089bb2eSAlexander Motin PROBE_IDENTIFY_SES, 1013089bb2eSAlexander Motin PROBE_IDENTIFY_SAFTE, 102a4d953c4SAlexander Motin PROBE_DONE, 10352c9ce25SScott Long PROBE_INVALID 10452c9ce25SScott Long } probe_action; 10552c9ce25SScott Long 10652c9ce25SScott Long static char *probe_action_text[] = { 10752c9ce25SScott Long "PROBE_RESET", 10852c9ce25SScott Long "PROBE_IDENTIFY", 1094ef08dc5SAlexander Motin "PROBE_SPINUP", 11052c9ce25SScott Long "PROBE_SETMODE", 111da6808c1SAlexander Motin "PROBE_SETPM", 112da6808c1SAlexander Motin "PROBE_SETAPST", 113da6808c1SAlexander Motin "PROBE_SETDMAAA", 1148d169381SAlexander Motin "PROBE_SETAN", 1151e637ba6SAlexander Motin "PROBE_SET_MULTI", 11652c9ce25SScott Long "PROBE_INQUIRY", 11752c9ce25SScott Long "PROBE_FULL_INQUIRY", 11852c9ce25SScott Long "PROBE_PM_PID", 11952c9ce25SScott Long "PROBE_PM_PRV", 1203089bb2eSAlexander Motin "PROBE_IDENTIFY_SES", 1213089bb2eSAlexander Motin "PROBE_IDENTIFY_SAFTE", 122a4d953c4SAlexander Motin "PROBE_DONE", 12352c9ce25SScott Long "PROBE_INVALID" 12452c9ce25SScott Long }; 12552c9ce25SScott Long 12652c9ce25SScott Long #define PROBE_SET_ACTION(softc, newaction) \ 12752c9ce25SScott Long do { \ 12852c9ce25SScott Long char **text; \ 12952c9ce25SScott Long text = probe_action_text; \ 130a4d953c4SAlexander Motin CAM_DEBUG((softc)->periph->path, CAM_DEBUG_PROBE, \ 13152c9ce25SScott Long ("Probe %s to %s\n", text[(softc)->action], \ 13252c9ce25SScott Long text[(newaction)])); \ 13352c9ce25SScott Long (softc)->action = (newaction); \ 13452c9ce25SScott Long } while(0) 13552c9ce25SScott Long 13652c9ce25SScott Long typedef enum { 13752c9ce25SScott Long PROBE_NO_ANNOUNCE = 0x04 13852c9ce25SScott Long } probe_flags; 13952c9ce25SScott Long 14052c9ce25SScott Long typedef struct { 14152c9ce25SScott Long TAILQ_HEAD(, ccb_hdr) request_ccbs; 142a9b8edb1SAlexander Motin struct ata_params ident_data; 14352c9ce25SScott Long probe_action action; 14452c9ce25SScott Long probe_flags flags; 14552c9ce25SScott Long uint32_t pm_pid; 14652c9ce25SScott Long uint32_t pm_prv; 14783c5d981SAlexander Motin int restart; 1484ef08dc5SAlexander Motin int spinup; 14925a519a9SAlexander Motin int faults; 150da6808c1SAlexander Motin u_int caps; 15152c9ce25SScott Long struct cam_periph *periph; 15252c9ce25SScott Long } probe_softc; 15352c9ce25SScott Long 15430a4094fSAlexander Motin static struct ata_quirk_entry ata_quirk_table[] = 15552c9ce25SScott Long { 15652c9ce25SScott Long { 15752c9ce25SScott Long /* Default tagged queuing parameters for all devices */ 15852c9ce25SScott Long { 15952c9ce25SScott Long T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED, 16052c9ce25SScott Long /*vendor*/"*", /*product*/"*", /*revision*/"*" 16152c9ce25SScott Long }, 1627dc3213dSAlexander Motin /*quirks*/0, /*mintags*/0, /*maxtags*/0 16352c9ce25SScott Long }, 16452c9ce25SScott Long }; 16552c9ce25SScott Long 16652c9ce25SScott Long static cam_status proberegister(struct cam_periph *periph, 16752c9ce25SScott Long void *arg); 16852c9ce25SScott Long static void probeschedule(struct cam_periph *probe_periph); 16952c9ce25SScott Long static void probestart(struct cam_periph *periph, union ccb *start_ccb); 170b9c473b2SAlexander Motin static void proberequestdefaultnegotiation(struct cam_periph *periph); 17152c9ce25SScott Long static void probedone(struct cam_periph *periph, union ccb *done_ccb); 17252c9ce25SScott Long static void probecleanup(struct cam_periph *periph); 17330a4094fSAlexander Motin static void ata_find_quirk(struct cam_ed *device); 17452c9ce25SScott Long static void ata_scan_bus(struct cam_periph *periph, union ccb *ccb); 17552c9ce25SScott Long static void ata_scan_lun(struct cam_periph *periph, 17652c9ce25SScott Long struct cam_path *path, cam_flags flags, 17752c9ce25SScott Long union ccb *ccb); 17852c9ce25SScott Long static void xptscandone(struct cam_periph *periph, union ccb *done_ccb); 17952c9ce25SScott Long static struct cam_ed * 18052c9ce25SScott Long ata_alloc_device(struct cam_eb *bus, struct cam_et *target, 18152c9ce25SScott Long lun_id_t lun_id); 18252c9ce25SScott Long static void ata_device_transport(struct cam_path *path); 183b9c473b2SAlexander Motin static void ata_get_transfer_settings(struct ccb_trans_settings *cts); 18430a4094fSAlexander Motin static void ata_set_transfer_settings(struct ccb_trans_settings *cts, 185227d67aaSAlexander Motin struct cam_path *path, 18652c9ce25SScott Long int async_update); 18752c9ce25SScott Long static void ata_dev_async(u_int32_t async_code, 18852c9ce25SScott Long struct cam_eb *bus, 18952c9ce25SScott Long struct cam_et *target, 19052c9ce25SScott Long struct cam_ed *device, 19152c9ce25SScott Long void *async_arg); 19252c9ce25SScott Long static void ata_action(union ccb *start_ccb); 19357079b17SAlexander Motin static void ata_announce_periph(struct cam_periph *periph); 1945d01277fSScott Long static void ata_announce_periph_sbuf(struct cam_periph *periph, struct sbuf *sb); 19508f13879SWarner Losh static void ata_proto_announce(struct cam_ed *device); 1965d01277fSScott Long static void ata_proto_announce_sbuf(struct cam_ed *device, struct sbuf *sb); 19708f13879SWarner Losh static void ata_proto_denounce(struct cam_ed *device); 1985d01277fSScott Long static void ata_proto_denounce_sbuf(struct cam_ed *device, struct sbuf *sb); 19908f13879SWarner Losh static void ata_proto_debug_out(union ccb *ccb); 20008f13879SWarner Losh static void semb_proto_announce(struct cam_ed *device); 2015d01277fSScott Long static void semb_proto_announce_sbuf(struct cam_ed *device, struct sbuf *sb); 20208f13879SWarner Losh static void semb_proto_denounce(struct cam_ed *device); 2035d01277fSScott Long static void semb_proto_denounce_sbuf(struct cam_ed *device, struct sbuf *sb); 20452c9ce25SScott Long 2052121d8a5SAlexander Motin static int ata_dma = 1; 2062121d8a5SAlexander Motin static int atapi_dma = 1; 2072121d8a5SAlexander Motin 2082121d8a5SAlexander Motin TUNABLE_INT("hw.ata.ata_dma", &ata_dma); 2092121d8a5SAlexander Motin TUNABLE_INT("hw.ata.atapi_dma", &atapi_dma); 2102121d8a5SAlexander Motin 211ded2b706SWarner Losh static struct xpt_xport_ops ata_xport_ops = { 21252c9ce25SScott Long .alloc_device = ata_alloc_device, 21352c9ce25SScott Long .action = ata_action, 21452c9ce25SScott Long .async = ata_dev_async, 21557079b17SAlexander Motin .announce = ata_announce_periph, 2165d01277fSScott Long .announce_sbuf = ata_announce_periph_sbuf, 21752c9ce25SScott Long }; 218ded2b706SWarner Losh #define ATA_XPT_XPORT(x, X) \ 219ded2b706SWarner Losh static struct xpt_xport ata_xport_ ## x = { \ 220ded2b706SWarner Losh .xport = XPORT_ ## X, \ 221ded2b706SWarner Losh .name = #x, \ 222ded2b706SWarner Losh .ops = &ata_xport_ops, \ 223ded2b706SWarner Losh }; \ 224ded2b706SWarner Losh CAM_XPT_XPORT(ata_xport_ ## x); 22552c9ce25SScott Long 226ded2b706SWarner Losh ATA_XPT_XPORT(ata, ATA); 227ded2b706SWarner Losh ATA_XPT_XPORT(sata, SATA); 228ded2b706SWarner Losh 229ded2b706SWarner Losh #undef ATA_XPORT_XPORT 23052c9ce25SScott Long 23108f13879SWarner Losh static struct xpt_proto_ops ata_proto_ops_ata = { 23208f13879SWarner Losh .announce = ata_proto_announce, 2335d01277fSScott Long .announce_sbuf = ata_proto_announce_sbuf, 23408f13879SWarner Losh .denounce = ata_proto_denounce, 2355d01277fSScott Long .denounce_sbuf = ata_proto_denounce_sbuf, 23608f13879SWarner Losh .debug_out = ata_proto_debug_out, 23708f13879SWarner Losh }; 23808f13879SWarner Losh static struct xpt_proto ata_proto_ata = { 23908f13879SWarner Losh .proto = PROTO_ATA, 24008f13879SWarner Losh .name = "ata", 24108f13879SWarner Losh .ops = &ata_proto_ops_ata, 24208f13879SWarner Losh }; 24308f13879SWarner Losh 24408f13879SWarner Losh static struct xpt_proto_ops ata_proto_ops_satapm = { 24508f13879SWarner Losh .announce = ata_proto_announce, 2465d01277fSScott Long .announce_sbuf = ata_proto_announce_sbuf, 24708f13879SWarner Losh .denounce = ata_proto_denounce, 2485d01277fSScott Long .denounce_sbuf = ata_proto_denounce_sbuf, 24908f13879SWarner Losh .debug_out = ata_proto_debug_out, 25008f13879SWarner Losh }; 25108f13879SWarner Losh static struct xpt_proto ata_proto_satapm = { 25208f13879SWarner Losh .proto = PROTO_SATAPM, 25308f13879SWarner Losh .name = "satapm", 25408f13879SWarner Losh .ops = &ata_proto_ops_satapm, 25508f13879SWarner Losh }; 25608f13879SWarner Losh 25708f13879SWarner Losh static struct xpt_proto_ops ata_proto_ops_semb = { 25808f13879SWarner Losh .announce = semb_proto_announce, 2595d01277fSScott Long .announce_sbuf = semb_proto_announce_sbuf, 26008f13879SWarner Losh .denounce = semb_proto_denounce, 2615d01277fSScott Long .denounce_sbuf = semb_proto_denounce_sbuf, 26208f13879SWarner Losh .debug_out = ata_proto_debug_out, 26308f13879SWarner Losh }; 26408f13879SWarner Losh static struct xpt_proto ata_proto_semb = { 26508f13879SWarner Losh .proto = PROTO_SEMB, 26608f13879SWarner Losh .name = "semb", 26708f13879SWarner Losh .ops = &ata_proto_ops_semb, 26808f13879SWarner Losh }; 26908f13879SWarner Losh 27008f13879SWarner Losh CAM_XPT_PROTO(ata_proto_ata); 27108f13879SWarner Losh CAM_XPT_PROTO(ata_proto_satapm); 27208f13879SWarner Losh CAM_XPT_PROTO(ata_proto_semb); 27308f13879SWarner Losh 27452c9ce25SScott Long static void 27552c9ce25SScott Long probe_periph_init() 27652c9ce25SScott Long { 27752c9ce25SScott Long } 27852c9ce25SScott Long 27952c9ce25SScott Long static cam_status 28052c9ce25SScott Long proberegister(struct cam_periph *periph, void *arg) 28152c9ce25SScott Long { 28252c9ce25SScott Long union ccb *request_ccb; /* CCB representing the probe request */ 28352c9ce25SScott Long cam_status status; 28452c9ce25SScott Long probe_softc *softc; 28552c9ce25SScott Long 28652c9ce25SScott Long request_ccb = (union ccb *)arg; 28752c9ce25SScott Long if (request_ccb == NULL) { 28852c9ce25SScott Long printf("proberegister: no probe CCB, " 28952c9ce25SScott Long "can't register device\n"); 29052c9ce25SScott Long return(CAM_REQ_CMP_ERR); 29152c9ce25SScott Long } 29252c9ce25SScott Long 2934ef08dc5SAlexander Motin softc = (probe_softc *)malloc(sizeof(*softc), M_CAMXPT, M_ZERO | M_NOWAIT); 29452c9ce25SScott Long 29552c9ce25SScott Long if (softc == NULL) { 29652c9ce25SScott Long printf("proberegister: Unable to probe new device. " 29752c9ce25SScott Long "Unable to allocate softc\n"); 29852c9ce25SScott Long return(CAM_REQ_CMP_ERR); 29952c9ce25SScott Long } 30052c9ce25SScott Long TAILQ_INIT(&softc->request_ccbs); 30152c9ce25SScott Long TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h, 30252c9ce25SScott Long periph_links.tqe); 30352c9ce25SScott Long softc->flags = 0; 30452c9ce25SScott Long periph->softc = softc; 30552c9ce25SScott Long softc->periph = periph; 30652c9ce25SScott Long softc->action = PROBE_INVALID; 30752c9ce25SScott Long status = cam_periph_acquire(periph); 30852c9ce25SScott Long if (status != CAM_REQ_CMP) { 30952c9ce25SScott Long return (status); 31052c9ce25SScott Long } 311a4d953c4SAlexander Motin CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe started\n")); 312227d67aaSAlexander Motin ata_device_transport(periph->path); 31352c9ce25SScott Long probeschedule(periph); 31452c9ce25SScott Long return(CAM_REQ_CMP); 31552c9ce25SScott Long } 31652c9ce25SScott Long 31752c9ce25SScott Long static void 31852c9ce25SScott Long probeschedule(struct cam_periph *periph) 31952c9ce25SScott Long { 32052c9ce25SScott Long union ccb *ccb; 32152c9ce25SScott Long probe_softc *softc; 32252c9ce25SScott Long 32352c9ce25SScott Long softc = (probe_softc *)periph->softc; 32452c9ce25SScott Long ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs); 32552c9ce25SScott Long 32665d0fb03SAlexander Motin if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) || 3273089bb2eSAlexander Motin periph->path->device->protocol == PROTO_SATAPM || 3283089bb2eSAlexander Motin periph->path->device->protocol == PROTO_SEMB) 32952c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_RESET); 33052c9ce25SScott Long else 33152c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 33252c9ce25SScott Long 33352c9ce25SScott Long if (ccb->crcn.flags & CAM_EXPECT_INQ_CHANGE) 33452c9ce25SScott Long softc->flags |= PROBE_NO_ANNOUNCE; 33552c9ce25SScott Long else 33652c9ce25SScott Long softc->flags &= ~PROBE_NO_ANNOUNCE; 33752c9ce25SScott Long 33883c5d981SAlexander Motin xpt_schedule(periph, CAM_PRIORITY_XPT); 33952c9ce25SScott Long } 34052c9ce25SScott Long 34152c9ce25SScott Long static void 34252c9ce25SScott Long probestart(struct cam_periph *periph, union ccb *start_ccb) 34352c9ce25SScott Long { 344c8039fc6SAlexander Motin struct ccb_trans_settings cts; 34552c9ce25SScott Long struct ccb_ataio *ataio; 34652c9ce25SScott Long struct ccb_scsiio *csio; 34752c9ce25SScott Long probe_softc *softc; 3481e637ba6SAlexander Motin struct cam_path *path; 3491e637ba6SAlexander Motin struct ata_params *ident_buf; 35052c9ce25SScott Long 35152c9ce25SScott Long CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probestart\n")); 35252c9ce25SScott Long 35352c9ce25SScott Long softc = (probe_softc *)periph->softc; 3541e637ba6SAlexander Motin path = start_ccb->ccb_h.path; 35552c9ce25SScott Long ataio = &start_ccb->ataio; 35652c9ce25SScott Long csio = &start_ccb->csio; 3571e637ba6SAlexander Motin ident_buf = &periph->path->device->ident_data; 35852c9ce25SScott Long 35983c5d981SAlexander Motin if (softc->restart) { 36083c5d981SAlexander Motin softc->restart = 0; 36183c5d981SAlexander Motin if ((path->device->flags & CAM_DEV_UNCONFIGURED) || 3623089bb2eSAlexander Motin path->device->protocol == PROTO_SATAPM || 3633089bb2eSAlexander Motin path->device->protocol == PROTO_SEMB) 36483c5d981SAlexander Motin softc->action = PROBE_RESET; 36583c5d981SAlexander Motin else 36683c5d981SAlexander Motin softc->action = PROBE_IDENTIFY; 36783c5d981SAlexander Motin } 36852c9ce25SScott Long switch (softc->action) { 36952c9ce25SScott Long case PROBE_RESET: 37052c9ce25SScott Long cam_fill_ataio(ataio, 37152c9ce25SScott Long 0, 37252c9ce25SScott Long probedone, 37352c9ce25SScott Long /*flags*/CAM_DIR_NONE, 37465d0fb03SAlexander Motin 0, 37552c9ce25SScott Long /*data_ptr*/NULL, 37652c9ce25SScott Long /*dxfer_len*/0, 37783c5d981SAlexander Motin 15 * 1000); 37852c9ce25SScott Long ata_reset_cmd(ataio); 37952c9ce25SScott Long break; 38052c9ce25SScott Long case PROBE_IDENTIFY: 38152c9ce25SScott Long cam_fill_ataio(ataio, 38252c9ce25SScott Long 1, 38352c9ce25SScott Long probedone, 38452c9ce25SScott Long /*flags*/CAM_DIR_IN, 38565d0fb03SAlexander Motin 0, 386a9b8edb1SAlexander Motin /*data_ptr*/(u_int8_t *)&softc->ident_data, 387a9b8edb1SAlexander Motin /*dxfer_len*/sizeof(softc->ident_data), 38852c9ce25SScott Long 30 * 1000); 38952c9ce25SScott Long if (periph->path->device->protocol == PROTO_ATA) 3907606b445SAlexander Motin ata_28bit_cmd(ataio, ATA_ATA_IDENTIFY, 0, 0, 0); 39152c9ce25SScott Long else 3927606b445SAlexander Motin ata_28bit_cmd(ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0); 39352c9ce25SScott Long break; 3944ef08dc5SAlexander Motin case PROBE_SPINUP: 3954ef08dc5SAlexander Motin if (bootverbose) 3964ef08dc5SAlexander Motin xpt_print(path, "Spinning up device\n"); 3974ef08dc5SAlexander Motin cam_fill_ataio(ataio, 3984ef08dc5SAlexander Motin 1, 3994ef08dc5SAlexander Motin probedone, 4004ef08dc5SAlexander Motin /*flags*/CAM_DIR_NONE | CAM_HIGH_POWER, 4014ef08dc5SAlexander Motin 0, 4024ef08dc5SAlexander Motin /*data_ptr*/NULL, 4034ef08dc5SAlexander Motin /*dxfer_len*/0, 4044ef08dc5SAlexander Motin 30 * 1000); 4054ef08dc5SAlexander Motin ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_PUIS_SPINUP, 0, 0); 4064ef08dc5SAlexander Motin break; 40752c9ce25SScott Long case PROBE_SETMODE: 408c8039fc6SAlexander Motin { 409c8039fc6SAlexander Motin int mode, wantmode; 410c8039fc6SAlexander Motin 411c8039fc6SAlexander Motin mode = 0; 412c8039fc6SAlexander Motin /* Fetch user modes from SIM. */ 413c8039fc6SAlexander Motin bzero(&cts, sizeof(cts)); 41483c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 415c8039fc6SAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 416c8039fc6SAlexander Motin cts.type = CTS_TYPE_USER_SETTINGS; 417c8039fc6SAlexander Motin xpt_action((union ccb *)&cts); 418c8039fc6SAlexander Motin if (path->device->transport == XPORT_ATA) { 419c8039fc6SAlexander Motin if (cts.xport_specific.ata.valid & CTS_ATA_VALID_MODE) 420c8039fc6SAlexander Motin mode = cts.xport_specific.ata.mode; 421c8039fc6SAlexander Motin } else { 4221a6f09b8SAlexander Motin if (cts.xport_specific.sata.valid & CTS_SATA_VALID_MODE) 423c8039fc6SAlexander Motin mode = cts.xport_specific.sata.mode; 424c8039fc6SAlexander Motin } 4252121d8a5SAlexander Motin if (periph->path->device->protocol == PROTO_ATA) { 4262121d8a5SAlexander Motin if (ata_dma == 0 && (mode == 0 || mode > ATA_PIO_MAX)) 4272121d8a5SAlexander Motin mode = ATA_PIO_MAX; 4282121d8a5SAlexander Motin } else { 4292121d8a5SAlexander Motin if (atapi_dma == 0 && (mode == 0 || mode > ATA_PIO_MAX)) 4302121d8a5SAlexander Motin mode = ATA_PIO_MAX; 4312121d8a5SAlexander Motin } 432c8039fc6SAlexander Motin negotiate: 433c8039fc6SAlexander Motin /* Honor device capabilities. */ 434c8039fc6SAlexander Motin wantmode = mode = ata_max_mode(ident_buf, mode); 435c8039fc6SAlexander Motin /* Report modes to SIM. */ 436c8039fc6SAlexander Motin bzero(&cts, sizeof(cts)); 43783c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 438c8039fc6SAlexander Motin cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 439c8039fc6SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 440c8039fc6SAlexander Motin if (path->device->transport == XPORT_ATA) { 441c8039fc6SAlexander Motin cts.xport_specific.ata.mode = mode; 442c8039fc6SAlexander Motin cts.xport_specific.ata.valid = CTS_ATA_VALID_MODE; 443c8039fc6SAlexander Motin } else { 444c8039fc6SAlexander Motin cts.xport_specific.sata.mode = mode; 445c8039fc6SAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_MODE; 446c8039fc6SAlexander Motin } 447c8039fc6SAlexander Motin xpt_action((union ccb *)&cts); 448066f913aSAlexander Motin /* Fetch current modes from SIM. */ 449c8039fc6SAlexander Motin bzero(&cts, sizeof(cts)); 45083c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 451c8039fc6SAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 452c8039fc6SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 453c8039fc6SAlexander Motin xpt_action((union ccb *)&cts); 454c8039fc6SAlexander Motin if (path->device->transport == XPORT_ATA) { 455c8039fc6SAlexander Motin if (cts.xport_specific.ata.valid & CTS_ATA_VALID_MODE) 456c8039fc6SAlexander Motin mode = cts.xport_specific.ata.mode; 457c8039fc6SAlexander Motin } else { 458c8039fc6SAlexander Motin if (cts.xport_specific.ata.valid & CTS_SATA_VALID_MODE) 459c8039fc6SAlexander Motin mode = cts.xport_specific.sata.mode; 460c8039fc6SAlexander Motin } 461c8039fc6SAlexander Motin /* If SIM disagree - renegotiate. */ 462c8039fc6SAlexander Motin if (mode != wantmode) 463c8039fc6SAlexander Motin goto negotiate; 464cf2b9a5fSAlexander Motin /* Remember what transport thinks about DMA. */ 465cf2b9a5fSAlexander Motin if (mode < ATA_DMA) 466cf2b9a5fSAlexander Motin path->device->inq_flags &= ~SID_DMA; 467cf2b9a5fSAlexander Motin else 468cf2b9a5fSAlexander Motin path->device->inq_flags |= SID_DMA; 469581b2e78SAlexander Motin xpt_async(AC_GETDEV_CHANGED, path, NULL); 47052c9ce25SScott Long cam_fill_ataio(ataio, 47152c9ce25SScott Long 1, 47252c9ce25SScott Long probedone, 4735daa555dSAlexander Motin /*flags*/CAM_DIR_NONE, 4745daa555dSAlexander Motin 0, 4755daa555dSAlexander Motin /*data_ptr*/NULL, 4765daa555dSAlexander Motin /*dxfer_len*/0, 47752c9ce25SScott Long 30 * 1000); 478c8039fc6SAlexander Motin ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); 47952c9ce25SScott Long break; 480c8039fc6SAlexander Motin } 481da6808c1SAlexander Motin case PROBE_SETPM: 482da6808c1SAlexander Motin cam_fill_ataio(ataio, 483da6808c1SAlexander Motin 1, 484da6808c1SAlexander Motin probedone, 485da6808c1SAlexander Motin CAM_DIR_NONE, 486da6808c1SAlexander Motin 0, 487da6808c1SAlexander Motin NULL, 488da6808c1SAlexander Motin 0, 489da6808c1SAlexander Motin 30*1000); 490da6808c1SAlexander Motin ata_28bit_cmd(ataio, ATA_SETFEATURES, 491da6808c1SAlexander Motin (softc->caps & CTS_SATA_CAPS_H_PMREQ) ? 0x10 : 0x90, 492da6808c1SAlexander Motin 0, 0x03); 493da6808c1SAlexander Motin break; 494da6808c1SAlexander Motin case PROBE_SETAPST: 495da6808c1SAlexander Motin cam_fill_ataio(ataio, 496da6808c1SAlexander Motin 1, 497da6808c1SAlexander Motin probedone, 498da6808c1SAlexander Motin CAM_DIR_NONE, 499da6808c1SAlexander Motin 0, 500da6808c1SAlexander Motin NULL, 501da6808c1SAlexander Motin 0, 502da6808c1SAlexander Motin 30*1000); 503da6808c1SAlexander Motin ata_28bit_cmd(ataio, ATA_SETFEATURES, 504da6808c1SAlexander Motin (softc->caps & CTS_SATA_CAPS_H_APST) ? 0x10 : 0x90, 505da6808c1SAlexander Motin 0, 0x07); 506da6808c1SAlexander Motin break; 507da6808c1SAlexander Motin case PROBE_SETDMAAA: 508da6808c1SAlexander Motin cam_fill_ataio(ataio, 509da6808c1SAlexander Motin 1, 510da6808c1SAlexander Motin probedone, 511da6808c1SAlexander Motin CAM_DIR_NONE, 512da6808c1SAlexander Motin 0, 513da6808c1SAlexander Motin NULL, 514da6808c1SAlexander Motin 0, 515da6808c1SAlexander Motin 30*1000); 516da6808c1SAlexander Motin ata_28bit_cmd(ataio, ATA_SETFEATURES, 517da6808c1SAlexander Motin (softc->caps & CTS_SATA_CAPS_H_DMAAA) ? 0x10 : 0x90, 518da6808c1SAlexander Motin 0, 0x02); 519da6808c1SAlexander Motin break; 5208d169381SAlexander Motin case PROBE_SETAN: 521e4bed0b4SWarner Losh /* Remember what transport thinks about AEN. */ 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; 5263631c638SAlexander Motin xpt_async(AC_GETDEV_CHANGED, path, NULL); 5278d169381SAlexander Motin cam_fill_ataio(ataio, 5288d169381SAlexander Motin 1, 5298d169381SAlexander Motin probedone, 5308d169381SAlexander Motin CAM_DIR_NONE, 5318d169381SAlexander Motin 0, 5328d169381SAlexander Motin NULL, 5338d169381SAlexander Motin 0, 5348d169381SAlexander Motin 30*1000); 5358d169381SAlexander Motin ata_28bit_cmd(ataio, ATA_SETFEATURES, 5368d169381SAlexander Motin (softc->caps & CTS_SATA_CAPS_H_AN) ? 0x10 : 0x90, 5378d169381SAlexander Motin 0, 0x05); 5388d169381SAlexander Motin break; 5391e637ba6SAlexander Motin case PROBE_SET_MULTI: 5401e637ba6SAlexander Motin { 541066f913aSAlexander Motin u_int sectors, bytecount; 5421e637ba6SAlexander Motin 543066f913aSAlexander Motin bytecount = 8192; /* SATA maximum */ 544066f913aSAlexander Motin /* Fetch user bytecount from SIM. */ 545066f913aSAlexander Motin bzero(&cts, sizeof(cts)); 54683c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 547066f913aSAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 548066f913aSAlexander Motin cts.type = CTS_TYPE_USER_SETTINGS; 549066f913aSAlexander Motin xpt_action((union ccb *)&cts); 550066f913aSAlexander Motin if (path->device->transport == XPORT_ATA) { 551066f913aSAlexander Motin if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 552066f913aSAlexander Motin bytecount = cts.xport_specific.ata.bytecount; 553066f913aSAlexander Motin } else { 554066f913aSAlexander Motin if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 555066f913aSAlexander Motin bytecount = cts.xport_specific.sata.bytecount; 556066f913aSAlexander Motin } 557066f913aSAlexander Motin /* Honor device capabilities. */ 558066f913aSAlexander Motin sectors = max(1, min(ident_buf->sectors_intr & 0xff, 559066f913aSAlexander Motin bytecount / ata_logical_sector_size(ident_buf))); 5601e637ba6SAlexander Motin /* Report bytecount to SIM. */ 5611e637ba6SAlexander Motin bzero(&cts, sizeof(cts)); 56283c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 5631e637ba6SAlexander Motin cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 5641e637ba6SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 5651e637ba6SAlexander Motin if (path->device->transport == XPORT_ATA) { 566c1bd46c2SAlexander Motin cts.xport_specific.ata.bytecount = sectors * 567c1bd46c2SAlexander Motin ata_logical_sector_size(ident_buf); 5681e637ba6SAlexander Motin cts.xport_specific.ata.valid = CTS_ATA_VALID_BYTECOUNT; 5691e637ba6SAlexander Motin } else { 570c1bd46c2SAlexander Motin cts.xport_specific.sata.bytecount = sectors * 571c1bd46c2SAlexander Motin ata_logical_sector_size(ident_buf); 5721e637ba6SAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_BYTECOUNT; 5731e637ba6SAlexander Motin } 5741e637ba6SAlexander Motin xpt_action((union ccb *)&cts); 575066f913aSAlexander Motin /* Fetch current bytecount from SIM. */ 576066f913aSAlexander Motin bzero(&cts, sizeof(cts)); 57783c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 578066f913aSAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 579066f913aSAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 580066f913aSAlexander Motin xpt_action((union ccb *)&cts); 581066f913aSAlexander Motin if (path->device->transport == XPORT_ATA) { 582066f913aSAlexander Motin if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 583066f913aSAlexander Motin bytecount = cts.xport_specific.ata.bytecount; 584066f913aSAlexander Motin } else { 585066f913aSAlexander Motin if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 586066f913aSAlexander Motin bytecount = cts.xport_specific.sata.bytecount; 587066f913aSAlexander Motin } 588066f913aSAlexander Motin sectors = bytecount / ata_logical_sector_size(ident_buf); 5891e637ba6SAlexander Motin 5901e637ba6SAlexander Motin cam_fill_ataio(ataio, 5911e637ba6SAlexander Motin 1, 5921e637ba6SAlexander Motin probedone, 5931e637ba6SAlexander Motin CAM_DIR_NONE, 5941e637ba6SAlexander Motin 0, 5951e637ba6SAlexander Motin NULL, 5961e637ba6SAlexander Motin 0, 5971e637ba6SAlexander Motin 30*1000); 5981e637ba6SAlexander Motin ata_28bit_cmd(ataio, ATA_SET_MULTI, 0, 0, sectors); 5991e637ba6SAlexander Motin break; 60052c9ce25SScott Long } 60152c9ce25SScott Long case PROBE_INQUIRY: 602066f913aSAlexander Motin { 603066f913aSAlexander Motin u_int bytecount; 604066f913aSAlexander Motin 605066f913aSAlexander Motin bytecount = 8192; /* SATA maximum */ 606066f913aSAlexander Motin /* Fetch user bytecount from SIM. */ 607066f913aSAlexander Motin bzero(&cts, sizeof(cts)); 60883c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 609066f913aSAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 610066f913aSAlexander Motin cts.type = CTS_TYPE_USER_SETTINGS; 611066f913aSAlexander Motin xpt_action((union ccb *)&cts); 612066f913aSAlexander Motin if (path->device->transport == XPORT_ATA) { 613066f913aSAlexander Motin if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) 614066f913aSAlexander Motin bytecount = cts.xport_specific.ata.bytecount; 615066f913aSAlexander Motin } else { 616066f913aSAlexander Motin if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) 617066f913aSAlexander Motin bytecount = cts.xport_specific.sata.bytecount; 618066f913aSAlexander Motin } 619066f913aSAlexander Motin /* Honor device capabilities. */ 620066f913aSAlexander Motin bytecount &= ~1; 621066f913aSAlexander Motin bytecount = max(2, min(65534, bytecount)); 622066f913aSAlexander Motin if (ident_buf->satacapabilities != 0x0000 && 623066f913aSAlexander Motin ident_buf->satacapabilities != 0xffff) { 624066f913aSAlexander Motin bytecount = min(8192, bytecount); 625066f913aSAlexander Motin } 626066f913aSAlexander Motin /* Report bytecount to SIM. */ 627066f913aSAlexander Motin bzero(&cts, sizeof(cts)); 62883c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 629066f913aSAlexander Motin cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 630066f913aSAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 631066f913aSAlexander Motin if (path->device->transport == XPORT_ATA) { 632066f913aSAlexander Motin cts.xport_specific.ata.bytecount = bytecount; 633066f913aSAlexander Motin cts.xport_specific.ata.valid = CTS_ATA_VALID_BYTECOUNT; 634066f913aSAlexander Motin } else { 635066f913aSAlexander Motin cts.xport_specific.sata.bytecount = bytecount; 636066f913aSAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_BYTECOUNT; 637066f913aSAlexander Motin } 638066f913aSAlexander Motin xpt_action((union ccb *)&cts); 639066f913aSAlexander Motin /* FALLTHROUGH */ 640066f913aSAlexander Motin } 64152c9ce25SScott Long case PROBE_FULL_INQUIRY: 64252c9ce25SScott Long { 64352c9ce25SScott Long u_int inquiry_len; 64452c9ce25SScott Long struct scsi_inquiry_data *inq_buf = 64552c9ce25SScott Long &periph->path->device->inq_data; 64652c9ce25SScott Long 64752c9ce25SScott Long if (softc->action == PROBE_INQUIRY) 64852c9ce25SScott Long inquiry_len = SHORT_INQUIRY_LENGTH; 64952c9ce25SScott Long else 65052c9ce25SScott Long inquiry_len = SID_ADDITIONAL_LENGTH(inq_buf); 65152c9ce25SScott Long /* 65252c9ce25SScott Long * Some parallel SCSI devices fail to send an 65352c9ce25SScott Long * ignore wide residue message when dealing with 65452c9ce25SScott Long * odd length inquiry requests. Round up to be 65552c9ce25SScott Long * safe. 65652c9ce25SScott Long */ 65752c9ce25SScott Long inquiry_len = roundup2(inquiry_len, 2); 65852c9ce25SScott Long scsi_inquiry(csio, 65952c9ce25SScott Long /*retries*/1, 66052c9ce25SScott Long probedone, 66152c9ce25SScott Long MSG_SIMPLE_Q_TAG, 66252c9ce25SScott Long (u_int8_t *)inq_buf, 66352c9ce25SScott Long inquiry_len, 66452c9ce25SScott Long /*evpd*/FALSE, 66552c9ce25SScott Long /*page_code*/0, 66652c9ce25SScott Long SSD_MIN_SIZE, 66752c9ce25SScott Long /*timeout*/60 * 1000); 66852c9ce25SScott Long break; 66952c9ce25SScott Long } 67052c9ce25SScott Long case PROBE_PM_PID: 67152c9ce25SScott Long cam_fill_ataio(ataio, 67252c9ce25SScott Long 1, 67352c9ce25SScott Long probedone, 67452c9ce25SScott Long /*flags*/CAM_DIR_NONE, 67565d0fb03SAlexander Motin 0, 67652c9ce25SScott Long /*data_ptr*/NULL, 67752c9ce25SScott Long /*dxfer_len*/0, 67852c9ce25SScott Long 10 * 1000); 67952c9ce25SScott Long ata_pm_read_cmd(ataio, 0, 15); 68052c9ce25SScott Long break; 68152c9ce25SScott Long case PROBE_PM_PRV: 68252c9ce25SScott Long cam_fill_ataio(ataio, 68352c9ce25SScott Long 1, 68452c9ce25SScott Long probedone, 68552c9ce25SScott Long /*flags*/CAM_DIR_NONE, 68665d0fb03SAlexander Motin 0, 68752c9ce25SScott Long /*data_ptr*/NULL, 68852c9ce25SScott Long /*dxfer_len*/0, 68952c9ce25SScott Long 10 * 1000); 69052c9ce25SScott Long ata_pm_read_cmd(ataio, 1, 15); 69152c9ce25SScott Long break; 6923089bb2eSAlexander Motin case PROBE_IDENTIFY_SES: 6933089bb2eSAlexander Motin cam_fill_ataio(ataio, 6943089bb2eSAlexander Motin 1, 6953089bb2eSAlexander Motin probedone, 6963089bb2eSAlexander Motin /*flags*/CAM_DIR_IN, 6973089bb2eSAlexander Motin 0, 6983089bb2eSAlexander Motin /*data_ptr*/(u_int8_t *)&softc->ident_data, 6993089bb2eSAlexander Motin /*dxfer_len*/sizeof(softc->ident_data), 7003089bb2eSAlexander Motin 30 * 1000); 7013089bb2eSAlexander Motin ata_28bit_cmd(ataio, ATA_SEP_ATTN, 0xEC, 0x02, 7023089bb2eSAlexander Motin sizeof(softc->ident_data) / 4); 7033089bb2eSAlexander Motin break; 7043089bb2eSAlexander Motin case PROBE_IDENTIFY_SAFTE: 7053089bb2eSAlexander Motin cam_fill_ataio(ataio, 7063089bb2eSAlexander Motin 1, 7073089bb2eSAlexander Motin probedone, 7083089bb2eSAlexander Motin /*flags*/CAM_DIR_IN, 7093089bb2eSAlexander Motin 0, 7103089bb2eSAlexander Motin /*data_ptr*/(u_int8_t *)&softc->ident_data, 7113089bb2eSAlexander Motin /*dxfer_len*/sizeof(softc->ident_data), 7123089bb2eSAlexander Motin 30 * 1000); 7133089bb2eSAlexander Motin ata_28bit_cmd(ataio, ATA_SEP_ATTN, 0xEC, 0x00, 7143089bb2eSAlexander Motin sizeof(softc->ident_data) / 4); 7153089bb2eSAlexander Motin break; 71652c9ce25SScott Long default: 717a4d953c4SAlexander Motin panic("probestart: invalid action state 0x%x\n", softc->action); 71852c9ce25SScott Long } 719cccf4220SAlexander Motin start_ccb->ccb_h.flags |= CAM_DEV_QFREEZE; 72052c9ce25SScott Long xpt_action(start_ccb); 72152c9ce25SScott Long } 722b9c473b2SAlexander Motin 72352c9ce25SScott Long static void 72452c9ce25SScott Long proberequestdefaultnegotiation(struct cam_periph *periph) 72552c9ce25SScott Long { 72652c9ce25SScott Long struct ccb_trans_settings cts; 72752c9ce25SScott Long 72883c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE); 72952c9ce25SScott Long cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 73052c9ce25SScott Long cts.type = CTS_TYPE_USER_SETTINGS; 73152c9ce25SScott Long xpt_action((union ccb *)&cts); 732b9c473b2SAlexander Motin if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 73352c9ce25SScott Long return; 734b9c473b2SAlexander Motin cts.xport_specific.valid = 0; 73552c9ce25SScott Long cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 73652c9ce25SScott Long cts.type = CTS_TYPE_CURRENT_SETTINGS; 73752c9ce25SScott Long xpt_action((union ccb *)&cts); 73852c9ce25SScott Long } 73952c9ce25SScott Long 74052c9ce25SScott Long static void 74152c9ce25SScott Long probedone(struct cam_periph *periph, union ccb *done_ccb) 74252c9ce25SScott Long { 743c8039fc6SAlexander Motin struct ccb_trans_settings cts; 74452c9ce25SScott Long struct ata_params *ident_buf; 7453089bb2eSAlexander Motin struct scsi_inquiry_data *inq_buf; 74652c9ce25SScott Long probe_softc *softc; 74752c9ce25SScott Long struct cam_path *path; 74826bdaeddSAlexander Motin cam_status status; 74952c9ce25SScott Long u_int32_t priority; 750da6808c1SAlexander Motin u_int caps; 7513089bb2eSAlexander Motin int changed = 1, found = 1; 7523089bb2eSAlexander Motin static const uint8_t fake_device_id_hdr[8] = 7533089bb2eSAlexander Motin {0, SVPD_DEVICE_ID, 0, 12, 7543089bb2eSAlexander Motin SVPD_ID_CODESET_BINARY, SVPD_ID_TYPE_NAA, 0, 8}; 75552c9ce25SScott Long 75652c9ce25SScott Long CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probedone\n")); 75752c9ce25SScott Long 75852c9ce25SScott Long softc = (probe_softc *)periph->softc; 75952c9ce25SScott Long path = done_ccb->ccb_h.path; 76052c9ce25SScott Long priority = done_ccb->ccb_h.pinfo.priority; 76152c9ce25SScott Long ident_buf = &path->device->ident_data; 7623089bb2eSAlexander Motin inq_buf = &path->device->inq_data; 76352c9ce25SScott Long 7641e637ba6SAlexander Motin if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 7650191d9b3SAlexander Motin if (cam_periph_error(done_ccb, 7660191d9b3SAlexander Motin 0, softc->restart ? (SF_NO_RECOVERY | SF_NO_RETRY) : 0, 767cccf4220SAlexander Motin NULL) == ERESTART) { 768cccf4220SAlexander Motin out: 769cccf4220SAlexander Motin /* Drop freeze taken due to CAM_DEV_QFREEZE flag set. */ 770cccf4220SAlexander Motin cam_release_devq(path, 0, 0, 0, FALSE); 7711e637ba6SAlexander Motin return; 772cccf4220SAlexander Motin } 77325a519a9SAlexander Motin if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 7741e637ba6SAlexander Motin /* Don't wedge the queue */ 775cccf4220SAlexander Motin xpt_release_devq(path, /*count*/1, /*run_queue*/TRUE); 7761e637ba6SAlexander Motin } 77726bdaeddSAlexander Motin status = done_ccb->ccb_h.status & CAM_STATUS_MASK; 77825a519a9SAlexander Motin if (softc->restart) { 77925a519a9SAlexander Motin softc->faults++; 78025a519a9SAlexander Motin if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == 78125a519a9SAlexander Motin CAM_CMD_TIMEOUT) 78225a519a9SAlexander Motin softc->faults += 4; 78325a519a9SAlexander Motin if (softc->faults < 10) 78425a519a9SAlexander Motin goto done; 78525a519a9SAlexander Motin else 78625a519a9SAlexander Motin softc->restart = 0; 78726bdaeddSAlexander Motin 7881e637ba6SAlexander Motin /* Old PIO2 devices may not support mode setting. */ 78926bdaeddSAlexander Motin } else if (softc->action == PROBE_SETMODE && 79026bdaeddSAlexander Motin status == CAM_ATA_STATUS_ERROR && 7911e637ba6SAlexander Motin ata_max_pmode(ident_buf) <= ATA_PIO2 && 79226bdaeddSAlexander Motin (ident_buf->capabilities1 & ATA_SUPPORT_IORDY) == 0) { 7931e637ba6SAlexander Motin goto noerror; 79426bdaeddSAlexander Motin 79526bdaeddSAlexander Motin /* 79626bdaeddSAlexander Motin * Some old WD SATA disks report supported and enabled 79726bdaeddSAlexander Motin * device-initiated interface power management, but return 79826bdaeddSAlexander Motin * ABORT on attempt to disable it. 79926bdaeddSAlexander Motin */ 80026bdaeddSAlexander Motin } else if (softc->action == PROBE_SETPM && 80126bdaeddSAlexander Motin status == CAM_ATA_STATUS_ERROR) { 80226bdaeddSAlexander Motin goto noerror; 803025e2c12SAlexander Motin 804025e2c12SAlexander Motin /* 805b5617df5SAndriy Gapon * Some old WD SATA disks have broken SPINUP handling. 806b5617df5SAndriy Gapon * If we really fail to spin up the disk, then there will be 807b5617df5SAndriy Gapon * some media access errors later on, but at least we will 808b5617df5SAndriy Gapon * have a device to interact with for recovery attempts. 809b5617df5SAndriy Gapon */ 810b5617df5SAndriy Gapon } else if (softc->action == PROBE_SPINUP && 811b5617df5SAndriy Gapon status == CAM_ATA_STATUS_ERROR) { 812b5617df5SAndriy Gapon goto noerror; 813b5617df5SAndriy Gapon 814b5617df5SAndriy Gapon /* 815025e2c12SAlexander Motin * Some HP SATA disks report supported DMA Auto-Activation, 816025e2c12SAlexander Motin * but return ABORT on attempt to enable it. 817025e2c12SAlexander Motin */ 818025e2c12SAlexander Motin } else if (softc->action == PROBE_SETDMAAA && 819025e2c12SAlexander Motin status == CAM_ATA_STATUS_ERROR) { 820025e2c12SAlexander Motin goto noerror; 8213089bb2eSAlexander Motin 8223089bb2eSAlexander Motin /* 8233089bb2eSAlexander Motin * SES and SAF-TE SEPs have different IDENTIFY commands, 8243089bb2eSAlexander Motin * but SATA specification doesn't tell how to identify them. 8253089bb2eSAlexander Motin * Until better way found, just try another if first fail. 8263089bb2eSAlexander Motin */ 8273089bb2eSAlexander Motin } else if (softc->action == PROBE_IDENTIFY_SES && 8283089bb2eSAlexander Motin status == CAM_ATA_STATUS_ERROR) { 8293089bb2eSAlexander Motin PROBE_SET_ACTION(softc, PROBE_IDENTIFY_SAFTE); 8303089bb2eSAlexander Motin xpt_release_ccb(done_ccb); 8313089bb2eSAlexander Motin xpt_schedule(periph, priority); 832cccf4220SAlexander Motin goto out; 83326bdaeddSAlexander Motin } 83426bdaeddSAlexander Motin 8351e637ba6SAlexander Motin /* 8361e637ba6SAlexander Motin * If we get to this point, we got an error status back 8371e637ba6SAlexander Motin * from the inquiry and the error status doesn't require 8381e637ba6SAlexander Motin * automatically retrying the command. Therefore, the 8391e637ba6SAlexander Motin * inquiry failed. If we had inquiry information before 8401e637ba6SAlexander Motin * for this device, but this latest inquiry command failed, 8411e637ba6SAlexander Motin * the device has probably gone away. If this device isn't 8421e637ba6SAlexander Motin * already marked unconfigured, notify the peripheral 8431e637ba6SAlexander Motin * drivers that this device is no more. 8441e637ba6SAlexander Motin */ 84525a519a9SAlexander Motin device_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0) 8461e637ba6SAlexander Motin xpt_async(AC_LOST_DEVICE, path, NULL); 847a4d953c4SAlexander Motin PROBE_SET_ACTION(softc, PROBE_INVALID); 8481e637ba6SAlexander Motin found = 0; 8491e637ba6SAlexander Motin goto done; 8501e637ba6SAlexander Motin } 8511e637ba6SAlexander Motin noerror: 852a9b8edb1SAlexander Motin if (softc->restart) 853a9b8edb1SAlexander Motin goto done; 85452c9ce25SScott Long switch (softc->action) { 85552c9ce25SScott Long case PROBE_RESET: 8561e637ba6SAlexander Motin { 85752c9ce25SScott Long int sign = (done_ccb->ataio.res.lba_high << 8) + 85852c9ce25SScott Long done_ccb->ataio.res.lba_mid; 859a4d953c4SAlexander Motin CAM_DEBUG(path, CAM_DEBUG_PROBE, 860a4d953c4SAlexander Motin ("SIGNATURE: %04x\n", sign)); 86152c9ce25SScott Long if (sign == 0x0000 && 86252c9ce25SScott Long done_ccb->ccb_h.target_id != 15) { 86352c9ce25SScott Long path->device->protocol = PROTO_ATA; 86452c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 86552c9ce25SScott Long } else if (sign == 0x9669 && 86652c9ce25SScott Long done_ccb->ccb_h.target_id == 15) { 86752c9ce25SScott Long /* Report SIM that PM is present. */ 86852c9ce25SScott Long bzero(&cts, sizeof(cts)); 86983c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 87052c9ce25SScott Long cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 87152c9ce25SScott Long cts.type = CTS_TYPE_CURRENT_SETTINGS; 87252c9ce25SScott Long cts.xport_specific.sata.pm_present = 1; 87352c9ce25SScott Long cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; 87452c9ce25SScott Long xpt_action((union ccb *)&cts); 87552c9ce25SScott Long path->device->protocol = PROTO_SATAPM; 87652c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_PM_PID); 8773089bb2eSAlexander Motin } else if (sign == 0xc33c && 8783089bb2eSAlexander Motin done_ccb->ccb_h.target_id != 15) { 8793089bb2eSAlexander Motin path->device->protocol = PROTO_SEMB; 8803089bb2eSAlexander Motin PROBE_SET_ACTION(softc, PROBE_IDENTIFY_SES); 88152c9ce25SScott Long } else if (sign == 0xeb14 && 88252c9ce25SScott Long done_ccb->ccb_h.target_id != 15) { 88352c9ce25SScott Long path->device->protocol = PROTO_SCSI; 88452c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 88552c9ce25SScott Long } else { 88652c9ce25SScott Long if (done_ccb->ccb_h.target_id != 15) { 88752c9ce25SScott Long xpt_print(path, 88852c9ce25SScott Long "Unexpected signature 0x%04x\n", sign); 88952c9ce25SScott Long } 89065d0fb03SAlexander Motin goto device_fail; 89152c9ce25SScott Long } 89252c9ce25SScott Long xpt_release_ccb(done_ccb); 89352c9ce25SScott Long xpt_schedule(periph, priority); 894cccf4220SAlexander Motin goto out; 89552c9ce25SScott Long } 89652c9ce25SScott Long case PROBE_IDENTIFY: 89752c9ce25SScott Long { 898699f853bSAlexander Motin struct ccb_pathinq cpi; 89952c9ce25SScott Long int16_t *ptr; 900a11463fdSSepherosa Ziehau int veto = 0; 90152c9ce25SScott Long 902a9b8edb1SAlexander Motin ident_buf = &softc->ident_data; 90352c9ce25SScott Long for (ptr = (int16_t *)ident_buf; 90452c9ce25SScott Long ptr < (int16_t *)ident_buf + sizeof(struct ata_params)/2; ptr++) { 90552c9ce25SScott Long *ptr = le16toh(*ptr); 90652c9ce25SScott Long } 907a11463fdSSepherosa Ziehau 908a11463fdSSepherosa Ziehau /* 909a11463fdSSepherosa Ziehau * Allow others to veto this ATA disk attachment. This 910a11463fdSSepherosa Ziehau * is mainly used by VMs, whose disk controllers may 911a11463fdSSepherosa Ziehau * share the disks with the simulated ATA controllers. 912a11463fdSSepherosa Ziehau */ 913a11463fdSSepherosa Ziehau EVENTHANDLER_INVOKE(ada_probe_veto, path, ident_buf, &veto); 914a11463fdSSepherosa Ziehau if (veto) { 915a11463fdSSepherosa Ziehau goto device_fail; 916a11463fdSSepherosa Ziehau } 917a11463fdSSepherosa Ziehau 91852c9ce25SScott Long if (strncmp(ident_buf->model, "FX", 2) && 91952c9ce25SScott Long strncmp(ident_buf->model, "NEC", 3) && 92052c9ce25SScott Long strncmp(ident_buf->model, "Pioneer", 7) && 92152c9ce25SScott Long strncmp(ident_buf->model, "SHARP", 5)) { 92252c9ce25SScott Long ata_bswap(ident_buf->model, sizeof(ident_buf->model)); 92352c9ce25SScott Long ata_bswap(ident_buf->revision, sizeof(ident_buf->revision)); 92452c9ce25SScott Long ata_bswap(ident_buf->serial, sizeof(ident_buf->serial)); 92552c9ce25SScott Long } 92652c9ce25SScott Long ata_btrim(ident_buf->model, sizeof(ident_buf->model)); 92752c9ce25SScott Long ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model)); 92852c9ce25SScott Long ata_btrim(ident_buf->revision, sizeof(ident_buf->revision)); 92952c9ce25SScott Long ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision)); 93052c9ce25SScott Long ata_btrim(ident_buf->serial, sizeof(ident_buf->serial)); 93152c9ce25SScott Long ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial)); 9324ef08dc5SAlexander Motin /* Device may need spin-up before IDENTIFY become valid. */ 9331254b680SAlexander Motin if ((ident_buf->specconf == 0x37c8 || 9341254b680SAlexander Motin ident_buf->specconf == 0x738c) && 9351254b680SAlexander Motin ((ident_buf->config & ATA_RESP_INCOMPLETE) || 9364ef08dc5SAlexander Motin softc->spinup == 0)) { 9374ef08dc5SAlexander Motin PROBE_SET_ACTION(softc, PROBE_SPINUP); 9384ef08dc5SAlexander Motin xpt_release_ccb(done_ccb); 9394ef08dc5SAlexander Motin xpt_schedule(periph, priority); 940cccf4220SAlexander Motin goto out; 9414ef08dc5SAlexander Motin } 942a9b8edb1SAlexander Motin ident_buf = &path->device->ident_data; 94352c9ce25SScott Long if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) { 94452c9ce25SScott Long /* Check that it is the same device. */ 945a9b8edb1SAlexander Motin if (bcmp(softc->ident_data.model, ident_buf->model, 946a9b8edb1SAlexander Motin sizeof(ident_buf->model)) || 947a9b8edb1SAlexander Motin bcmp(softc->ident_data.revision, ident_buf->revision, 948a9b8edb1SAlexander Motin sizeof(ident_buf->revision)) || 949a9b8edb1SAlexander Motin bcmp(softc->ident_data.serial, ident_buf->serial, 950a9b8edb1SAlexander Motin sizeof(ident_buf->serial))) { 95152c9ce25SScott Long /* Device changed. */ 95252c9ce25SScott Long xpt_async(AC_LOST_DEVICE, path, NULL); 9531e637ba6SAlexander Motin } else { 954a9b8edb1SAlexander Motin bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 9552eb4a8dcSAlexander Motin changed = 0; 9562eb4a8dcSAlexander Motin } 9572eb4a8dcSAlexander Motin } 9582eb4a8dcSAlexander Motin if (changed) { 9592eb4a8dcSAlexander Motin bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 96052c9ce25SScott Long /* Clean up from previous instance of this device */ 96152c9ce25SScott Long if (path->device->serial_num != NULL) { 96252c9ce25SScott Long free(path->device->serial_num, M_CAMXPT); 96352c9ce25SScott Long path->device->serial_num = NULL; 96452c9ce25SScott Long path->device->serial_num_len = 0; 96552c9ce25SScott Long } 9663089bb2eSAlexander Motin if (path->device->device_id != NULL) { 9673089bb2eSAlexander Motin free(path->device->device_id, M_CAMXPT); 9683089bb2eSAlexander Motin path->device->device_id = NULL; 9693089bb2eSAlexander Motin path->device->device_id_len = 0; 9703089bb2eSAlexander Motin } 97152c9ce25SScott Long path->device->serial_num = 97252c9ce25SScott Long (u_int8_t *)malloc((sizeof(ident_buf->serial) + 1), 97352c9ce25SScott Long M_CAMXPT, M_NOWAIT); 97452c9ce25SScott Long if (path->device->serial_num != NULL) { 97552c9ce25SScott Long bcopy(ident_buf->serial, 97652c9ce25SScott Long path->device->serial_num, 97752c9ce25SScott Long sizeof(ident_buf->serial)); 97852c9ce25SScott Long path->device->serial_num[sizeof(ident_buf->serial)] 97952c9ce25SScott Long = '\0'; 98052c9ce25SScott Long path->device->serial_num_len = 98152c9ce25SScott Long strlen(path->device->serial_num); 98252c9ce25SScott Long } 9833089bb2eSAlexander Motin if (ident_buf->enabled.extension & 9843089bb2eSAlexander Motin ATA_SUPPORT_64BITWWN) { 9853089bb2eSAlexander Motin path->device->device_id = 9863089bb2eSAlexander Motin malloc(16, M_CAMXPT, M_NOWAIT); 9873089bb2eSAlexander Motin if (path->device->device_id != NULL) { 9883089bb2eSAlexander Motin path->device->device_id_len = 16; 9893089bb2eSAlexander Motin bcopy(&fake_device_id_hdr, 9903089bb2eSAlexander Motin path->device->device_id, 8); 9913d6dd54eSAlexander Motin bcopy(ident_buf->wwn, 9923d6dd54eSAlexander Motin path->device->device_id + 8, 8); 9933d6dd54eSAlexander Motin ata_bswap(path->device->device_id + 8, 8); 9943089bb2eSAlexander Motin } 9953089bb2eSAlexander Motin } 99652c9ce25SScott Long 9974b997c49SAlexander Motin path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 998581b2e78SAlexander Motin xpt_async(AC_GETDEV_CHANGED, path, NULL); 9991e637ba6SAlexander Motin } 100030a4094fSAlexander Motin if (ident_buf->satacapabilities & ATA_SUPPORT_NCQ) { 10017dc3213dSAlexander Motin path->device->mintags = 2; 10027dc3213dSAlexander Motin path->device->maxtags = 100330a4094fSAlexander Motin ATA_QUEUE_LEN(ident_buf->queue) + 1; 100430a4094fSAlexander Motin } 100530a4094fSAlexander Motin ata_find_quirk(path->device); 1006507e5811SAlexander Motin if (path->device->mintags != 0 && 1007507e5811SAlexander Motin path->bus->sim->max_tagged_dev_openings != 0) { 1008699f853bSAlexander Motin /* Check if the SIM does not want queued commands. */ 1009699f853bSAlexander Motin bzero(&cpi, sizeof(cpi)); 1010699f853bSAlexander Motin xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 1011699f853bSAlexander Motin cpi.ccb_h.func_code = XPT_PATH_INQ; 1012699f853bSAlexander Motin xpt_action((union ccb *)&cpi); 1013699f853bSAlexander Motin if (cpi.ccb_h.status == CAM_REQ_CMP && 1014699f853bSAlexander Motin (cpi.hba_inquiry & PI_TAG_ABLE)) { 1015c8039fc6SAlexander Motin /* Report SIM which tags are allowed. */ 1016c8039fc6SAlexander Motin bzero(&cts, sizeof(cts)); 101783c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1018c8039fc6SAlexander Motin cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1019c8039fc6SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 1020c8039fc6SAlexander Motin cts.xport_specific.sata.tags = path->device->maxtags; 1021c8039fc6SAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_TAGS; 1022c8039fc6SAlexander Motin xpt_action((union ccb *)&cts); 102330a4094fSAlexander Motin } 1024699f853bSAlexander Motin } 1025bc1bf6e8SAlexander Motin ata_device_transport(path); 1026b9c473b2SAlexander Motin if (changed) 1027b9c473b2SAlexander Motin proberequestdefaultnegotiation(periph); 102852c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_SETMODE); 102952c9ce25SScott Long xpt_release_ccb(done_ccb); 103052c9ce25SScott Long xpt_schedule(periph, priority); 1031cccf4220SAlexander Motin goto out; 103252c9ce25SScott Long } 10334ef08dc5SAlexander Motin case PROBE_SPINUP: 10344ef08dc5SAlexander Motin if (bootverbose) 10354ef08dc5SAlexander Motin xpt_print(path, "Spin-up done\n"); 10364ef08dc5SAlexander Motin softc->spinup = 1; 10374ef08dc5SAlexander Motin PROBE_SET_ACTION(softc, PROBE_IDENTIFY); 10384ef08dc5SAlexander Motin xpt_release_ccb(done_ccb); 10394ef08dc5SAlexander Motin xpt_schedule(periph, priority); 1040cccf4220SAlexander Motin goto out; 104152c9ce25SScott Long case PROBE_SETMODE: 1042da6808c1SAlexander Motin /* Set supported bits. */ 1043da6808c1SAlexander Motin bzero(&cts, sizeof(cts)); 1044da6808c1SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1045da6808c1SAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1046da6808c1SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 1047da6808c1SAlexander Motin xpt_action((union ccb *)&cts); 10482e1eb332SMarius Strobl if (path->device->transport == XPORT_SATA && 10492e1eb332SMarius Strobl cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1050da6808c1SAlexander Motin caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H; 10512e1eb332SMarius Strobl else if (path->device->transport == XPORT_ATA && 10522e1eb332SMarius Strobl cts.xport_specific.ata.valid & CTS_ATA_VALID_CAPS) 10532e1eb332SMarius Strobl caps = cts.xport_specific.ata.caps & CTS_ATA_CAPS_H; 1054da6808c1SAlexander Motin else 1055da6808c1SAlexander Motin caps = 0; 10562e1eb332SMarius Strobl if (path->device->transport == XPORT_SATA && 10572e1eb332SMarius Strobl ident_buf->satacapabilities != 0xffff) { 1058da6808c1SAlexander Motin if (ident_buf->satacapabilities & ATA_SUPPORT_IFPWRMNGTRCV) 1059da6808c1SAlexander Motin caps |= CTS_SATA_CAPS_D_PMREQ; 1060da6808c1SAlexander Motin if (ident_buf->satacapabilities & ATA_SUPPORT_HAPST) 1061da6808c1SAlexander Motin caps |= CTS_SATA_CAPS_D_APST; 1062da6808c1SAlexander Motin } 1063da6808c1SAlexander Motin /* Mask unwanted bits. */ 1064da6808c1SAlexander Motin bzero(&cts, sizeof(cts)); 1065da6808c1SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1066da6808c1SAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1067da6808c1SAlexander Motin cts.type = CTS_TYPE_USER_SETTINGS; 1068da6808c1SAlexander Motin xpt_action((union ccb *)&cts); 10692e1eb332SMarius Strobl if (path->device->transport == XPORT_SATA && 10702e1eb332SMarius Strobl cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1071da6808c1SAlexander Motin caps &= cts.xport_specific.sata.caps; 10722e1eb332SMarius Strobl else if (path->device->transport == XPORT_ATA && 10732e1eb332SMarius Strobl cts.xport_specific.ata.valid & CTS_ATA_VALID_CAPS) 10742e1eb332SMarius Strobl caps &= cts.xport_specific.ata.caps; 1075c2b82f3eSAlexander Motin else 1076c2b82f3eSAlexander Motin caps = 0; 10772e1eb332SMarius Strobl /* 10782e1eb332SMarius Strobl * Remember what transport thinks about 48-bit DMA. If 10792e1eb332SMarius Strobl * capability information is not provided or transport is 10802e1eb332SMarius Strobl * SATA, we take support for granted. 10812e1eb332SMarius Strobl */ 10822e1eb332SMarius Strobl if (!(path->device->inq_flags & SID_DMA) || 10832e1eb332SMarius Strobl (path->device->transport == XPORT_ATA && 10842e1eb332SMarius Strobl (cts.xport_specific.ata.valid & CTS_ATA_VALID_CAPS) && 10852e1eb332SMarius Strobl !(caps & CTS_ATA_CAPS_H_DMA48))) 10862e1eb332SMarius Strobl path->device->inq_flags &= ~SID_DMA48; 10872e1eb332SMarius Strobl else 10882e1eb332SMarius Strobl path->device->inq_flags |= SID_DMA48; 1089da6808c1SAlexander Motin /* Store result to SIM. */ 1090da6808c1SAlexander Motin bzero(&cts, sizeof(cts)); 1091da6808c1SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1092da6808c1SAlexander Motin cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1093da6808c1SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 10942e1eb332SMarius Strobl if (path->device->transport == XPORT_SATA) { 1095da6808c1SAlexander Motin cts.xport_specific.sata.caps = caps; 1096da6808c1SAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS; 10972e1eb332SMarius Strobl } else { 10982e1eb332SMarius Strobl cts.xport_specific.ata.caps = caps; 10992e1eb332SMarius Strobl cts.xport_specific.ata.valid = CTS_ATA_VALID_CAPS; 11002e1eb332SMarius Strobl } 1101da6808c1SAlexander Motin xpt_action((union ccb *)&cts); 1102da6808c1SAlexander Motin softc->caps = caps; 11032e1eb332SMarius Strobl if (path->device->transport != XPORT_SATA) 11042e1eb332SMarius Strobl goto notsata; 1105958e4a69SAlexander Motin if ((ident_buf->satasupport & ATA_SUPPORT_IFPWRMNGT) && 1106958e4a69SAlexander Motin (!(softc->caps & CTS_SATA_CAPS_H_PMREQ)) != 1107958e4a69SAlexander Motin (!(ident_buf->sataenabled & ATA_SUPPORT_IFPWRMNGT))) { 1108da6808c1SAlexander Motin PROBE_SET_ACTION(softc, PROBE_SETPM); 1109da6808c1SAlexander Motin xpt_release_ccb(done_ccb); 1110da6808c1SAlexander Motin xpt_schedule(periph, priority); 1111cccf4220SAlexander Motin goto out; 1112da6808c1SAlexander Motin } 1113da6808c1SAlexander Motin /* FALLTHROUGH */ 1114da6808c1SAlexander Motin case PROBE_SETPM: 1115da6808c1SAlexander Motin if (ident_buf->satacapabilities != 0xffff && 1116958e4a69SAlexander Motin (ident_buf->satacapabilities & ATA_SUPPORT_DAPST) && 1117958e4a69SAlexander Motin (!(softc->caps & CTS_SATA_CAPS_H_APST)) != 1118958e4a69SAlexander Motin (!(ident_buf->sataenabled & ATA_ENABLED_DAPST))) { 1119da6808c1SAlexander Motin PROBE_SET_ACTION(softc, PROBE_SETAPST); 1120da6808c1SAlexander Motin xpt_release_ccb(done_ccb); 1121da6808c1SAlexander Motin xpt_schedule(periph, priority); 1122cccf4220SAlexander Motin goto out; 1123da6808c1SAlexander Motin } 1124da6808c1SAlexander Motin /* FALLTHROUGH */ 1125da6808c1SAlexander Motin case PROBE_SETAPST: 1126958e4a69SAlexander Motin if ((ident_buf->satasupport & ATA_SUPPORT_AUTOACTIVATE) && 1127958e4a69SAlexander Motin (!(softc->caps & CTS_SATA_CAPS_H_DMAAA)) != 1128958e4a69SAlexander Motin (!(ident_buf->sataenabled & ATA_SUPPORT_AUTOACTIVATE))) { 1129da6808c1SAlexander Motin PROBE_SET_ACTION(softc, PROBE_SETDMAAA); 1130da6808c1SAlexander Motin xpt_release_ccb(done_ccb); 1131da6808c1SAlexander Motin xpt_schedule(periph, priority); 1132cccf4220SAlexander Motin goto out; 1133da6808c1SAlexander Motin } 1134da6808c1SAlexander Motin /* FALLTHROUGH */ 1135da6808c1SAlexander Motin case PROBE_SETDMAAA: 1136e4bed0b4SWarner Losh if (path->device->protocol != PROTO_ATA && 1137e4bed0b4SWarner Losh (ident_buf->satasupport & ATA_SUPPORT_ASYNCNOTIF) && 11388d169381SAlexander Motin (!(softc->caps & CTS_SATA_CAPS_H_AN)) != 11398d169381SAlexander Motin (!(ident_buf->sataenabled & ATA_SUPPORT_ASYNCNOTIF))) { 11408d169381SAlexander Motin PROBE_SET_ACTION(softc, PROBE_SETAN); 11418d169381SAlexander Motin xpt_release_ccb(done_ccb); 11428d169381SAlexander Motin xpt_schedule(periph, priority); 1143cccf4220SAlexander Motin goto out; 11448d169381SAlexander Motin } 11458d169381SAlexander Motin /* FALLTHROUGH */ 11468d169381SAlexander Motin case PROBE_SETAN: 1147da6808c1SAlexander Motin notsata: 11481e637ba6SAlexander Motin if (path->device->protocol == PROTO_ATA) { 11491e637ba6SAlexander Motin PROBE_SET_ACTION(softc, PROBE_SET_MULTI); 11501e637ba6SAlexander Motin } else { 11511e637ba6SAlexander Motin PROBE_SET_ACTION(softc, PROBE_INQUIRY); 11521e637ba6SAlexander Motin } 11531e637ba6SAlexander Motin xpt_release_ccb(done_ccb); 11541e637ba6SAlexander Motin xpt_schedule(periph, priority); 1155cccf4220SAlexander Motin goto out; 11561e637ba6SAlexander Motin case PROBE_SET_MULTI: 11571e637ba6SAlexander Motin if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 115852c9ce25SScott Long path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1159f98d7a47SAlexander Motin xpt_acquire_device(path->device); 116052c9ce25SScott Long done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 116152c9ce25SScott Long xpt_action(done_ccb); 1162cccf4220SAlexander Motin xpt_async(AC_FOUND_DEVICE, path, done_ccb); 11631e637ba6SAlexander Motin } 1164a4d953c4SAlexander Motin PROBE_SET_ACTION(softc, PROBE_DONE); 116552c9ce25SScott Long break; 116652c9ce25SScott Long case PROBE_INQUIRY: 116752c9ce25SScott Long case PROBE_FULL_INQUIRY: 116852c9ce25SScott Long { 11691e637ba6SAlexander Motin u_int8_t periph_qual, len; 117052c9ce25SScott Long 117152c9ce25SScott Long path->device->flags |= CAM_DEV_INQUIRY_DATA_VALID; 117252c9ce25SScott Long 117352c9ce25SScott Long periph_qual = SID_QUAL(inq_buf); 117452c9ce25SScott Long 117592024858SAlexander Motin if (periph_qual != SID_QUAL_LU_CONNECTED && 117692024858SAlexander Motin periph_qual != SID_QUAL_LU_OFFLINE) 11771e637ba6SAlexander Motin break; 117852c9ce25SScott Long 117952c9ce25SScott Long /* 118052c9ce25SScott Long * We conservatively request only 118152c9ce25SScott Long * SHORT_INQUIRY_LEN bytes of inquiry 118252c9ce25SScott Long * information during our first try 118352c9ce25SScott Long * at sending an INQUIRY. If the device 118452c9ce25SScott Long * has more information to give, 118552c9ce25SScott Long * perform a second request specifying 118652c9ce25SScott Long * the amount of information the device 118752c9ce25SScott Long * is willing to give. 118852c9ce25SScott Long */ 118952c9ce25SScott Long len = inq_buf->additional_length 11901e637ba6SAlexander Motin + offsetof(struct scsi_inquiry_data, additional_length) + 1; 119152c9ce25SScott Long if (softc->action == PROBE_INQUIRY 119252c9ce25SScott Long && len > SHORT_INQUIRY_LENGTH) { 119352c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_FULL_INQUIRY); 119452c9ce25SScott Long xpt_release_ccb(done_ccb); 119552c9ce25SScott Long xpt_schedule(periph, priority); 1196cccf4220SAlexander Motin goto out; 119752c9ce25SScott Long } 119852c9ce25SScott Long 11994b997c49SAlexander Motin ata_device_transport(path); 12001e637ba6SAlexander Motin if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 120152c9ce25SScott Long path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1202f98d7a47SAlexander Motin xpt_acquire_device(path->device); 120352c9ce25SScott Long done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 120452c9ce25SScott Long xpt_action(done_ccb); 1205cccf4220SAlexander Motin xpt_async(AC_FOUND_DEVICE, path, done_ccb); 12061e637ba6SAlexander Motin } 1207a4d953c4SAlexander Motin PROBE_SET_ACTION(softc, PROBE_DONE); 120852c9ce25SScott Long break; 120952c9ce25SScott Long } 121052c9ce25SScott Long case PROBE_PM_PID: 12114b997c49SAlexander Motin if ((path->device->flags & CAM_DEV_IDENTIFY_DATA_VALID) == 0) 121252c9ce25SScott Long bzero(ident_buf, sizeof(*ident_buf)); 121352c9ce25SScott Long softc->pm_pid = (done_ccb->ataio.res.lba_high << 24) + 121452c9ce25SScott Long (done_ccb->ataio.res.lba_mid << 16) + 121552c9ce25SScott Long (done_ccb->ataio.res.lba_low << 8) + 121652c9ce25SScott Long done_ccb->ataio.res.sector_count; 121765d0fb03SAlexander Motin ((uint32_t *)ident_buf)[0] = softc->pm_pid; 121852c9ce25SScott Long snprintf(ident_buf->model, sizeof(ident_buf->model), 121952c9ce25SScott Long "Port Multiplier %08x", softc->pm_pid); 122052c9ce25SScott Long PROBE_SET_ACTION(softc, PROBE_PM_PRV); 122152c9ce25SScott Long xpt_release_ccb(done_ccb); 122252c9ce25SScott Long xpt_schedule(periph, priority); 1223cccf4220SAlexander Motin goto out; 122452c9ce25SScott Long case PROBE_PM_PRV: 122552c9ce25SScott Long softc->pm_prv = (done_ccb->ataio.res.lba_high << 24) + 122652c9ce25SScott Long (done_ccb->ataio.res.lba_mid << 16) + 122752c9ce25SScott Long (done_ccb->ataio.res.lba_low << 8) + 122852c9ce25SScott Long done_ccb->ataio.res.sector_count; 122965d0fb03SAlexander Motin ((uint32_t *)ident_buf)[1] = softc->pm_prv; 123052c9ce25SScott Long snprintf(ident_buf->revision, sizeof(ident_buf->revision), 123152c9ce25SScott Long "%04x", softc->pm_prv); 12324b997c49SAlexander Motin path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; 1233bc1bf6e8SAlexander Motin ata_device_transport(path); 1234bc1bf6e8SAlexander Motin if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) 1235bc1bf6e8SAlexander Motin proberequestdefaultnegotiation(periph); 1236da6808c1SAlexander Motin /* Set supported bits. */ 1237da6808c1SAlexander Motin bzero(&cts, sizeof(cts)); 1238da6808c1SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1239da6808c1SAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1240da6808c1SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 1241da6808c1SAlexander Motin xpt_action((union ccb *)&cts); 1242da6808c1SAlexander Motin if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1243da6808c1SAlexander Motin caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H; 1244da6808c1SAlexander Motin else 1245da6808c1SAlexander Motin caps = 0; 1246da6808c1SAlexander Motin /* All PMPs must support PM requests. */ 1247da6808c1SAlexander Motin caps |= CTS_SATA_CAPS_D_PMREQ; 1248da6808c1SAlexander Motin /* Mask unwanted bits. */ 1249da6808c1SAlexander Motin bzero(&cts, sizeof(cts)); 1250da6808c1SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1251da6808c1SAlexander Motin cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1252da6808c1SAlexander Motin cts.type = CTS_TYPE_USER_SETTINGS; 1253da6808c1SAlexander Motin xpt_action((union ccb *)&cts); 1254da6808c1SAlexander Motin if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 1255da6808c1SAlexander Motin caps &= cts.xport_specific.sata.caps; 1256c2b82f3eSAlexander Motin else 1257c2b82f3eSAlexander Motin caps = 0; 12582e1eb332SMarius Strobl /* Remember what transport thinks about AEN. */ 1259e4bed0b4SWarner Losh if ((caps & CTS_SATA_CAPS_H_AN) && path->device->protocol != PROTO_ATA) 12602e1eb332SMarius Strobl path->device->inq_flags |= SID_AEN; 12612e1eb332SMarius Strobl else 12622e1eb332SMarius Strobl path->device->inq_flags &= ~SID_AEN; 1263da6808c1SAlexander Motin /* Store result to SIM. */ 1264da6808c1SAlexander Motin bzero(&cts, sizeof(cts)); 1265da6808c1SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 1266da6808c1SAlexander Motin cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 1267da6808c1SAlexander Motin cts.type = CTS_TYPE_CURRENT_SETTINGS; 1268da6808c1SAlexander Motin cts.xport_specific.sata.caps = caps; 1269da6808c1SAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS; 1270da6808c1SAlexander Motin xpt_action((union ccb *)&cts); 1271da6808c1SAlexander Motin softc->caps = caps; 12723631c638SAlexander Motin xpt_async(AC_GETDEV_CHANGED, path, NULL); 127365d0fb03SAlexander Motin if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 127452c9ce25SScott Long path->device->flags &= ~CAM_DEV_UNCONFIGURED; 1275f98d7a47SAlexander Motin xpt_acquire_device(path->device); 127652c9ce25SScott Long done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 127752c9ce25SScott Long xpt_action(done_ccb); 1278cccf4220SAlexander Motin xpt_async(AC_FOUND_DEVICE, path, done_ccb); 127965d0fb03SAlexander Motin } else { 128065d0fb03SAlexander Motin done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 128165d0fb03SAlexander Motin xpt_action(done_ccb); 1282cccf4220SAlexander Motin xpt_async(AC_SCSI_AEN, path, done_ccb); 128352c9ce25SScott Long } 1284a4d953c4SAlexander Motin PROBE_SET_ACTION(softc, PROBE_DONE); 128552c9ce25SScott Long break; 12863089bb2eSAlexander Motin case PROBE_IDENTIFY_SES: 12873089bb2eSAlexander Motin case PROBE_IDENTIFY_SAFTE: 12883089bb2eSAlexander Motin if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) { 12893089bb2eSAlexander Motin /* Check that it is the same device. */ 12903089bb2eSAlexander Motin if (bcmp(&softc->ident_data, ident_buf, 53)) { 12913089bb2eSAlexander Motin /* Device changed. */ 12923089bb2eSAlexander Motin xpt_async(AC_LOST_DEVICE, path, NULL); 12933089bb2eSAlexander Motin } else { 12943089bb2eSAlexander Motin bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); 12953089bb2eSAlexander Motin changed = 0; 12963089bb2eSAlexander Motin } 12973089bb2eSAlexander Motin } 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) 1320bc1bf6e8SAlexander Motin proberequestdefaultnegotiation(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: 1332a4d953c4SAlexander Motin panic("probedone: 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); 133883c5d981SAlexander Motin probeschedule(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 135652c9ce25SScott Long probecleanup(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 } 141552c9ce25SScott Long xpt_setup_ccb(&work_ccb->ccb_h, request_ccb->ccb_h.path, 141652c9ce25SScott Long request_ccb->ccb_h.pinfo.priority); 141752c9ce25SScott Long work_ccb->ccb_h.func_code = XPT_PATH_INQ; 141852c9ce25SScott Long xpt_action(work_ccb); 141952c9ce25SScott Long if (work_ccb->ccb_h.status != CAM_REQ_CMP) { 142052c9ce25SScott Long request_ccb->ccb_h.status = work_ccb->ccb_h.status; 142152c9ce25SScott Long xpt_free_ccb(work_ccb); 142252c9ce25SScott Long xpt_done(request_ccb); 142352c9ce25SScott Long return; 142452c9ce25SScott Long } 142552c9ce25SScott Long 142683c5d981SAlexander Motin /* We may need to reset bus first, if we haven't done it yet. */ 142783c5d981SAlexander Motin if ((work_ccb->cpi.hba_inquiry & 142883c5d981SAlexander Motin (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE)) && 142983c5d981SAlexander Motin !(work_ccb->cpi.hba_misc & PIM_NOBUSRESET) && 143083c5d981SAlexander Motin !timevalisset(&request_ccb->ccb_h.path->bus->last_reset)) { 143183c5d981SAlexander Motin reset_ccb = xpt_alloc_ccb_nowait(); 1432f1893540SAlexander Motin if (reset_ccb == NULL) { 1433f1893540SAlexander Motin request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1434f1893540SAlexander Motin xpt_free_ccb(work_ccb); 1435f1893540SAlexander Motin xpt_done(request_ccb); 1436f1893540SAlexander Motin return; 1437f1893540SAlexander Motin } 143883c5d981SAlexander Motin xpt_setup_ccb(&reset_ccb->ccb_h, request_ccb->ccb_h.path, 143983c5d981SAlexander Motin CAM_PRIORITY_NONE); 144083c5d981SAlexander Motin reset_ccb->ccb_h.func_code = XPT_RESET_BUS; 144183c5d981SAlexander Motin xpt_action(reset_ccb); 144283c5d981SAlexander Motin if (reset_ccb->ccb_h.status != CAM_REQ_CMP) { 144383c5d981SAlexander Motin request_ccb->ccb_h.status = reset_ccb->ccb_h.status; 144483c5d981SAlexander Motin xpt_free_ccb(reset_ccb); 144583c5d981SAlexander Motin xpt_free_ccb(work_ccb); 144683c5d981SAlexander Motin xpt_done(request_ccb); 144783c5d981SAlexander Motin return; 144883c5d981SAlexander Motin } 144983c5d981SAlexander Motin xpt_free_ccb(reset_ccb); 145083c5d981SAlexander Motin } 145183c5d981SAlexander Motin 145252c9ce25SScott Long /* Save some state for use while we probe for devices */ 145352c9ce25SScott Long scan_info = (ata_scan_bus_info *) 145452c9ce25SScott Long malloc(sizeof(ata_scan_bus_info), M_CAMXPT, M_NOWAIT); 145552c9ce25SScott Long if (scan_info == NULL) { 145652c9ce25SScott Long request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 1457f1893540SAlexander Motin xpt_free_ccb(work_ccb); 145852c9ce25SScott Long xpt_done(request_ccb); 145952c9ce25SScott Long return; 146052c9ce25SScott Long } 146152c9ce25SScott Long scan_info->request_ccb = request_ccb; 146252c9ce25SScott Long scan_info->cpi = &work_ccb->cpi; 146352c9ce25SScott Long /* If PM supported, probe it first. */ 146452c9ce25SScott Long if (scan_info->cpi->hba_inquiry & PI_SATAPM) 14650025eb12SAlexander Motin scan_info->counter = scan_info->cpi->max_target; 14660025eb12SAlexander Motin else 14670025eb12SAlexander Motin scan_info->counter = 0; 146852c9ce25SScott Long 146952c9ce25SScott Long work_ccb = xpt_alloc_ccb_nowait(); 147052c9ce25SScott Long if (work_ccb == NULL) { 147152c9ce25SScott Long free(scan_info, M_CAMXPT); 147252c9ce25SScott Long request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 147352c9ce25SScott Long xpt_done(request_ccb); 147452c9ce25SScott Long break; 147552c9ce25SScott Long } 1476227d67aaSAlexander Motin mtx = xpt_path_mtx(scan_info->request_ccb->ccb_h.path); 147752c9ce25SScott Long goto scan_next; 147852c9ce25SScott Long case XPT_SCAN_LUN: 147952c9ce25SScott Long work_ccb = request_ccb; 148052c9ce25SScott Long /* Reuse the same CCB to query if a device was really found */ 148152c9ce25SScott Long scan_info = (ata_scan_bus_info *)work_ccb->ccb_h.ppriv_ptr0; 1482227d67aaSAlexander Motin mtx = xpt_path_mtx(scan_info->request_ccb->ccb_h.path); 1483227d67aaSAlexander Motin mtx_lock(mtx); 148465d0fb03SAlexander Motin /* If there is PMP... */ 14850025eb12SAlexander Motin if ((scan_info->cpi->hba_inquiry & PI_SATAPM) && 14860025eb12SAlexander Motin (scan_info->counter == scan_info->cpi->max_target)) { 148783c5d981SAlexander Motin if (work_ccb->ccb_h.status == CAM_REQ_CMP) { 148865d0fb03SAlexander Motin /* everything else will be probed by it */ 1489e2a75189SAlexander Motin /* Free the current request path- we're done with it. */ 1490e2a75189SAlexander Motin xpt_free_path(work_ccb->ccb_h.path); 14910025eb12SAlexander Motin goto done; 149252c9ce25SScott Long } else { 149352c9ce25SScott Long struct ccb_trans_settings cts; 149452c9ce25SScott Long 149552c9ce25SScott Long /* Report SIM that PM is absent. */ 149652c9ce25SScott Long bzero(&cts, sizeof(cts)); 149752c9ce25SScott Long xpt_setup_ccb(&cts.ccb_h, 1498e2a75189SAlexander Motin work_ccb->ccb_h.path, CAM_PRIORITY_NONE); 149952c9ce25SScott Long cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 150052c9ce25SScott Long cts.type = CTS_TYPE_CURRENT_SETTINGS; 15013ccda2f3SAlexander Motin cts.xport_specific.sata.pm_present = 0; 150252c9ce25SScott Long cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; 150352c9ce25SScott Long xpt_action((union ccb *)&cts); 150452c9ce25SScott Long } 150552c9ce25SScott Long } 1506e2a75189SAlexander Motin /* Free the current request path- we're done with it. */ 1507e2a75189SAlexander Motin xpt_free_path(work_ccb->ccb_h.path); 15080025eb12SAlexander Motin if (scan_info->counter == 15090025eb12SAlexander Motin ((scan_info->cpi->hba_inquiry & PI_SATAPM) ? 15100025eb12SAlexander Motin 0 : scan_info->cpi->max_target)) { 15110025eb12SAlexander Motin done: 1512227d67aaSAlexander Motin mtx_unlock(mtx); 151352c9ce25SScott Long xpt_free_ccb(work_ccb); 151452c9ce25SScott Long xpt_free_ccb((union ccb *)scan_info->cpi); 151552c9ce25SScott Long request_ccb = scan_info->request_ccb; 151652c9ce25SScott Long free(scan_info, M_CAMXPT); 151752c9ce25SScott Long request_ccb->ccb_h.status = CAM_REQ_CMP; 151852c9ce25SScott Long xpt_done(request_ccb); 151952c9ce25SScott Long break; 152052c9ce25SScott Long } 15210025eb12SAlexander Motin /* Take next device. Wrap from max (PMP) to 0. */ 15220025eb12SAlexander Motin scan_info->counter = (scan_info->counter + 1 ) % 15230025eb12SAlexander Motin (scan_info->cpi->max_target + 1); 152452c9ce25SScott Long scan_next: 1525e5dfa058SAlexander Motin status = xpt_create_path(&path, NULL, 152652c9ce25SScott Long scan_info->request_ccb->ccb_h.path_id, 152752c9ce25SScott Long scan_info->counter, 0); 152852c9ce25SScott Long if (status != CAM_REQ_CMP) { 1529227d67aaSAlexander Motin if (request_ccb->ccb_h.func_code == XPT_SCAN_LUN) 1530227d67aaSAlexander Motin mtx_unlock(mtx); 153152c9ce25SScott Long printf("xpt_scan_bus: xpt_create_path failed" 153252c9ce25SScott Long " with status %#x, bus scan halted\n", 153352c9ce25SScott Long status); 153452c9ce25SScott Long xpt_free_ccb(work_ccb); 153552c9ce25SScott Long xpt_free_ccb((union ccb *)scan_info->cpi); 153652c9ce25SScott Long request_ccb = scan_info->request_ccb; 153752c9ce25SScott Long free(scan_info, M_CAMXPT); 153852c9ce25SScott Long request_ccb->ccb_h.status = status; 153952c9ce25SScott Long xpt_done(request_ccb); 154052c9ce25SScott Long break; 154152c9ce25SScott Long } 154252c9ce25SScott Long xpt_setup_ccb(&work_ccb->ccb_h, path, 154352c9ce25SScott Long scan_info->request_ccb->ccb_h.pinfo.priority); 154452c9ce25SScott Long work_ccb->ccb_h.func_code = XPT_SCAN_LUN; 154552c9ce25SScott Long work_ccb->ccb_h.cbfcnp = ata_scan_bus; 1546227d67aaSAlexander Motin work_ccb->ccb_h.flags |= CAM_UNLOCKED; 154752c9ce25SScott Long work_ccb->ccb_h.ppriv_ptr0 = scan_info; 154852c9ce25SScott Long work_ccb->crcn.flags = scan_info->request_ccb->crcn.flags; 1549227d67aaSAlexander Motin mtx_unlock(mtx); 1550227d67aaSAlexander Motin if (request_ccb->ccb_h.func_code == XPT_SCAN_LUN) 1551227d67aaSAlexander Motin mtx = NULL; 155252c9ce25SScott Long xpt_action(work_ccb); 1553227d67aaSAlexander Motin if (mtx != NULL) 1554227d67aaSAlexander Motin mtx_lock(mtx); 155552c9ce25SScott Long break; 155652c9ce25SScott Long default: 155752c9ce25SScott Long break; 155852c9ce25SScott Long } 155952c9ce25SScott Long } 156052c9ce25SScott Long 156152c9ce25SScott Long static void 156252c9ce25SScott Long ata_scan_lun(struct cam_periph *periph, struct cam_path *path, 156352c9ce25SScott Long cam_flags flags, union ccb *request_ccb) 156452c9ce25SScott Long { 156552c9ce25SScott Long struct ccb_pathinq cpi; 156652c9ce25SScott Long cam_status status; 156752c9ce25SScott Long struct cam_path *new_path; 156852c9ce25SScott Long struct cam_periph *old_periph; 1569227d67aaSAlexander Motin int lock; 157052c9ce25SScott Long 157183c5d981SAlexander Motin CAM_DEBUG(path, CAM_DEBUG_TRACE, ("xpt_scan_lun\n")); 157252c9ce25SScott Long 157383c5d981SAlexander Motin xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 157452c9ce25SScott Long cpi.ccb_h.func_code = XPT_PATH_INQ; 157552c9ce25SScott Long xpt_action((union ccb *)&cpi); 157652c9ce25SScott Long 157752c9ce25SScott Long if (cpi.ccb_h.status != CAM_REQ_CMP) { 157852c9ce25SScott Long if (request_ccb != NULL) { 157952c9ce25SScott Long request_ccb->ccb_h.status = cpi.ccb_h.status; 158052c9ce25SScott Long xpt_done(request_ccb); 158152c9ce25SScott Long } 158252c9ce25SScott Long return; 158352c9ce25SScott Long } 158452c9ce25SScott Long 158552c9ce25SScott Long if (request_ccb == NULL) { 158632aa80a6SAlexander Motin request_ccb = xpt_alloc_ccb_nowait(); 158752c9ce25SScott Long if (request_ccb == NULL) { 158852c9ce25SScott Long xpt_print(path, "xpt_scan_lun: can't allocate CCB, " 158952c9ce25SScott Long "can't continue\n"); 159052c9ce25SScott Long return; 159152c9ce25SScott Long } 1592e5dfa058SAlexander Motin status = xpt_create_path(&new_path, NULL, 159352c9ce25SScott Long path->bus->path_id, 159452c9ce25SScott Long path->target->target_id, 159552c9ce25SScott Long path->device->lun_id); 159652c9ce25SScott Long if (status != CAM_REQ_CMP) { 159732aa80a6SAlexander Motin xpt_print(path, "xpt_scan_lun: can't create path, " 159852c9ce25SScott Long "can't continue\n"); 159932aa80a6SAlexander Motin xpt_free_ccb(request_ccb); 160052c9ce25SScott Long return; 160152c9ce25SScott Long } 160283c5d981SAlexander Motin xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_XPT); 160352c9ce25SScott Long request_ccb->ccb_h.cbfcnp = xptscandone; 1604227d67aaSAlexander Motin request_ccb->ccb_h.flags |= CAM_UNLOCKED; 160552c9ce25SScott Long request_ccb->ccb_h.func_code = XPT_SCAN_LUN; 160652c9ce25SScott Long request_ccb->crcn.flags = flags; 160752c9ce25SScott Long } 160852c9ce25SScott Long 1609227d67aaSAlexander Motin lock = (xpt_path_owned(path) == 0); 1610227d67aaSAlexander Motin if (lock) 1611227d67aaSAlexander Motin xpt_path_lock(path); 1612f09f8e3eSAlexander Motin if ((old_periph = cam_periph_find(path, "aprobe")) != NULL) { 16132e3f592bSAlexander Motin if ((old_periph->flags & CAM_PERIPH_INVALID) == 0) { 161452c9ce25SScott Long probe_softc *softc; 161552c9ce25SScott Long 161652c9ce25SScott Long softc = (probe_softc *)old_periph->softc; 16172e3f592bSAlexander Motin TAILQ_INSERT_TAIL(&softc->request_ccbs, 16182e3f592bSAlexander Motin &request_ccb->ccb_h, periph_links.tqe); 161983c5d981SAlexander Motin softc->restart = 1; 162052c9ce25SScott Long } else { 16212e3f592bSAlexander Motin request_ccb->ccb_h.status = CAM_REQ_CMP_ERR; 16222e3f592bSAlexander Motin xpt_done(request_ccb); 16232e3f592bSAlexander Motin } 16242e3f592bSAlexander Motin } else { 162552c9ce25SScott Long status = cam_periph_alloc(proberegister, NULL, probecleanup, 1626f09f8e3eSAlexander Motin probestart, "aprobe", 162752c9ce25SScott Long CAM_PERIPH_BIO, 162852c9ce25SScott Long request_ccb->ccb_h.path, NULL, 0, 162952c9ce25SScott Long request_ccb); 163052c9ce25SScott Long 163152c9ce25SScott Long if (status != CAM_REQ_CMP) { 163252c9ce25SScott Long xpt_print(path, "xpt_scan_lun: cam_alloc_periph " 163352c9ce25SScott Long "returned an error, can't continue probe\n"); 163452c9ce25SScott Long request_ccb->ccb_h.status = status; 163552c9ce25SScott Long xpt_done(request_ccb); 163652c9ce25SScott Long } 163752c9ce25SScott Long } 1638227d67aaSAlexander Motin if (lock) 1639227d67aaSAlexander Motin xpt_path_unlock(path); 164052c9ce25SScott Long } 164152c9ce25SScott Long 164252c9ce25SScott Long static void 164352c9ce25SScott Long xptscandone(struct cam_periph *periph, union ccb *done_ccb) 164452c9ce25SScott Long { 164532aa80a6SAlexander Motin 164632aa80a6SAlexander Motin xpt_free_path(done_ccb->ccb_h.path); 164732aa80a6SAlexander Motin xpt_free_ccb(done_ccb); 164852c9ce25SScott Long } 164952c9ce25SScott Long 165052c9ce25SScott Long static struct cam_ed * 165152c9ce25SScott Long ata_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id) 165252c9ce25SScott Long { 165330a4094fSAlexander Motin struct ata_quirk_entry *quirk; 165452c9ce25SScott Long struct cam_ed *device; 165552c9ce25SScott Long 165652c9ce25SScott Long device = xpt_alloc_device(bus, target, lun_id); 165752c9ce25SScott Long if (device == NULL) 165852c9ce25SScott Long return (NULL); 165952c9ce25SScott Long 166052c9ce25SScott Long /* 166152c9ce25SScott Long * Take the default quirk entry until we have inquiry 166252c9ce25SScott Long * data and can determine a better quirk to use. 166352c9ce25SScott Long */ 16648dfea464SPedro F. Giffuni quirk = &ata_quirk_table[nitems(ata_quirk_table) - 1]; 166552c9ce25SScott Long device->quirk = (void *)quirk; 166630a4094fSAlexander Motin device->mintags = 0; 166730a4094fSAlexander Motin device->maxtags = 0; 166852c9ce25SScott Long bzero(&device->inq_data, sizeof(device->inq_data)); 166952c9ce25SScott Long device->inq_flags = 0; 167052c9ce25SScott Long device->queue_flags = 0; 167152c9ce25SScott Long device->serial_num = NULL; 167252c9ce25SScott Long device->serial_num_len = 0; 167352c9ce25SScott Long return (device); 167452c9ce25SScott Long } 167552c9ce25SScott Long 167652c9ce25SScott Long static void 167752c9ce25SScott Long ata_device_transport(struct cam_path *path) 167852c9ce25SScott Long { 167952c9ce25SScott Long struct ccb_pathinq cpi; 16804b997c49SAlexander Motin struct ccb_trans_settings cts; 16814b997c49SAlexander Motin struct scsi_inquiry_data *inq_buf = NULL; 16824b997c49SAlexander Motin struct ata_params *ident_buf = NULL; 168352c9ce25SScott Long 168452c9ce25SScott Long /* Get transport information from the SIM */ 168583c5d981SAlexander Motin xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 168652c9ce25SScott Long cpi.ccb_h.func_code = XPT_PATH_INQ; 168752c9ce25SScott Long xpt_action((union ccb *)&cpi); 168852c9ce25SScott Long 168952c9ce25SScott Long path->device->transport = cpi.transport; 16904b997c49SAlexander Motin if ((path->device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0) 16914b997c49SAlexander Motin inq_buf = &path->device->inq_data; 16924b997c49SAlexander Motin if ((path->device->flags & CAM_DEV_IDENTIFY_DATA_VALID) != 0) 16934b997c49SAlexander Motin ident_buf = &path->device->ident_data; 16944b997c49SAlexander Motin if (path->device->protocol == PROTO_ATA) { 16954b997c49SAlexander Motin path->device->protocol_version = ident_buf ? 16964b997c49SAlexander Motin ata_version(ident_buf->version_major) : cpi.protocol_version; 16974b997c49SAlexander Motin } else if (path->device->protocol == PROTO_SCSI) { 16984b997c49SAlexander Motin path->device->protocol_version = inq_buf ? 16994b997c49SAlexander Motin SID_ANSI_REV(inq_buf) : cpi.protocol_version; 170052c9ce25SScott Long } 17014b997c49SAlexander Motin path->device->transport_version = ident_buf ? 17024b997c49SAlexander Motin ata_version(ident_buf->version_major) : cpi.transport_version; 170352c9ce25SScott Long 170452c9ce25SScott Long /* Tell the controller what we think */ 170583c5d981SAlexander Motin xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 170652c9ce25SScott Long cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 170752c9ce25SScott Long cts.type = CTS_TYPE_CURRENT_SETTINGS; 170852c9ce25SScott Long cts.transport = path->device->transport; 170952c9ce25SScott Long cts.transport_version = path->device->transport_version; 171052c9ce25SScott Long cts.protocol = path->device->protocol; 171152c9ce25SScott Long cts.protocol_version = path->device->protocol_version; 171252c9ce25SScott Long cts.proto_specific.valid = 0; 17134cca1530SAlexander Motin if (ident_buf) { 17144cca1530SAlexander Motin if (path->device->transport == XPORT_ATA) { 17154cca1530SAlexander Motin cts.xport_specific.ata.atapi = 17168e6cab54SAlexander Motin (ident_buf->config == ATA_PROTO_CFA) ? 0 : 17174cca1530SAlexander Motin ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_16) ? 16 : 17184cca1530SAlexander Motin ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) ? 12 : 0; 17194cca1530SAlexander Motin cts.xport_specific.ata.valid = CTS_ATA_VALID_ATAPI; 17204cca1530SAlexander Motin } else { 17214cca1530SAlexander Motin cts.xport_specific.sata.atapi = 17228e6cab54SAlexander Motin (ident_buf->config == ATA_PROTO_CFA) ? 0 : 17234cca1530SAlexander Motin ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_16) ? 16 : 17244cca1530SAlexander Motin ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) ? 12 : 0; 17254cca1530SAlexander Motin cts.xport_specific.sata.valid = CTS_SATA_VALID_ATAPI; 17264cca1530SAlexander Motin } 17274cca1530SAlexander Motin } else 172852c9ce25SScott Long cts.xport_specific.valid = 0; 172952c9ce25SScott Long xpt_action((union ccb *)&cts); 173052c9ce25SScott Long } 173152c9ce25SScott Long 173252c9ce25SScott Long static void 173314f900e2SWill Andrews ata_dev_advinfo(union ccb *start_ccb) 173414f900e2SWill Andrews { 173514f900e2SWill Andrews struct cam_ed *device; 173614f900e2SWill Andrews struct ccb_dev_advinfo *cdai; 173714f900e2SWill Andrews off_t amt; 173814f900e2SWill Andrews 173914f900e2SWill Andrews start_ccb->ccb_h.status = CAM_REQ_INVALID; 174014f900e2SWill Andrews device = start_ccb->ccb_h.path->device; 174114f900e2SWill Andrews cdai = &start_ccb->cdai; 174214f900e2SWill Andrews switch(cdai->buftype) { 17433089bb2eSAlexander Motin case CDAI_TYPE_SCSI_DEVID: 17443089bb2eSAlexander Motin if (cdai->flags & CDAI_FLAG_STORE) 17453089bb2eSAlexander Motin return; 17463089bb2eSAlexander Motin cdai->provsiz = device->device_id_len; 17473089bb2eSAlexander Motin if (device->device_id_len == 0) 17483089bb2eSAlexander Motin break; 17493089bb2eSAlexander Motin amt = device->device_id_len; 17503089bb2eSAlexander Motin if (cdai->provsiz > cdai->bufsiz) 17513089bb2eSAlexander Motin amt = cdai->bufsiz; 17523089bb2eSAlexander Motin memcpy(cdai->buf, device->device_id, amt); 17533089bb2eSAlexander Motin break; 175414f900e2SWill Andrews case CDAI_TYPE_SERIAL_NUM: 175514f900e2SWill Andrews if (cdai->flags & CDAI_FLAG_STORE) 17563089bb2eSAlexander Motin return; 175714f900e2SWill Andrews cdai->provsiz = device->serial_num_len; 175814f900e2SWill Andrews if (device->serial_num_len == 0) 175914f900e2SWill Andrews break; 176014f900e2SWill Andrews amt = device->serial_num_len; 176114f900e2SWill Andrews if (cdai->provsiz > cdai->bufsiz) 176214f900e2SWill Andrews amt = cdai->bufsiz; 176314f900e2SWill Andrews memcpy(cdai->buf, device->serial_num, amt); 176414f900e2SWill Andrews break; 17653089bb2eSAlexander Motin case CDAI_TYPE_PHYS_PATH: 17663089bb2eSAlexander Motin if (cdai->flags & CDAI_FLAG_STORE) { 17673089bb2eSAlexander Motin if (device->physpath != NULL) 17683089bb2eSAlexander Motin free(device->physpath, M_CAMXPT); 17693089bb2eSAlexander Motin device->physpath_len = cdai->bufsiz; 17703089bb2eSAlexander Motin /* Clear existing buffer if zero length */ 17713089bb2eSAlexander Motin if (cdai->bufsiz == 0) 177214f900e2SWill Andrews break; 17733089bb2eSAlexander Motin device->physpath = malloc(cdai->bufsiz, M_CAMXPT, M_NOWAIT); 17743089bb2eSAlexander Motin if (device->physpath == NULL) { 17753089bb2eSAlexander Motin start_ccb->ccb_h.status = CAM_REQ_ABORTED; 17763089bb2eSAlexander Motin return; 17773089bb2eSAlexander Motin } 17783089bb2eSAlexander Motin memcpy(device->physpath, cdai->buf, cdai->bufsiz); 17793089bb2eSAlexander Motin } else { 17803089bb2eSAlexander Motin cdai->provsiz = device->physpath_len; 17813089bb2eSAlexander Motin if (device->physpath_len == 0) 17823089bb2eSAlexander Motin break; 17833089bb2eSAlexander Motin amt = device->physpath_len; 17843089bb2eSAlexander Motin if (cdai->provsiz > cdai->bufsiz) 17853089bb2eSAlexander Motin amt = cdai->bufsiz; 17863089bb2eSAlexander Motin memcpy(cdai->buf, device->physpath, amt); 17873089bb2eSAlexander Motin } 17883089bb2eSAlexander Motin break; 17893089bb2eSAlexander Motin default: 17903089bb2eSAlexander Motin return; 17913089bb2eSAlexander Motin } 17923089bb2eSAlexander Motin start_ccb->ccb_h.status = CAM_REQ_CMP; 17933089bb2eSAlexander Motin 17943089bb2eSAlexander Motin if (cdai->flags & CDAI_FLAG_STORE) { 17953089bb2eSAlexander Motin xpt_async(AC_ADVINFO_CHANGED, start_ccb->ccb_h.path, 17963089bb2eSAlexander Motin (void *)(uintptr_t)cdai->buftype); 179714f900e2SWill Andrews } 179814f900e2SWill Andrews } 179914f900e2SWill Andrews 180014f900e2SWill Andrews static void 180152c9ce25SScott Long ata_action(union ccb *start_ccb) 180252c9ce25SScott Long { 180352c9ce25SScott Long 180452c9ce25SScott Long switch (start_ccb->ccb_h.func_code) { 180552c9ce25SScott Long case XPT_SET_TRAN_SETTINGS: 180652c9ce25SScott Long { 180730a4094fSAlexander Motin ata_set_transfer_settings(&start_ccb->cts, 1808227d67aaSAlexander Motin start_ccb->ccb_h.path, 180952c9ce25SScott Long /*async_update*/FALSE); 181052c9ce25SScott Long break; 181152c9ce25SScott Long } 181252c9ce25SScott Long case XPT_SCAN_BUS: 18130e85f214SMatt Jacob case XPT_SCAN_TGT: 181452c9ce25SScott Long ata_scan_bus(start_ccb->ccb_h.path->periph, start_ccb); 181552c9ce25SScott Long break; 181652c9ce25SScott Long case XPT_SCAN_LUN: 181752c9ce25SScott Long ata_scan_lun(start_ccb->ccb_h.path->periph, 181852c9ce25SScott Long start_ccb->ccb_h.path, start_ccb->crcn.flags, 181952c9ce25SScott Long start_ccb); 182052c9ce25SScott Long break; 182152c9ce25SScott Long case XPT_GET_TRAN_SETTINGS: 182252c9ce25SScott Long { 1823b9c473b2SAlexander Motin ata_get_transfer_settings(&start_ccb->cts); 182452c9ce25SScott Long break; 182552c9ce25SScott Long } 18264cca1530SAlexander Motin case XPT_SCSI_IO: 18274cca1530SAlexander Motin { 18284cca1530SAlexander Motin struct cam_ed *device; 18294cca1530SAlexander Motin u_int maxlen = 0; 18304cca1530SAlexander Motin 18314cca1530SAlexander Motin device = start_ccb->ccb_h.path->device; 18324cca1530SAlexander Motin if (device->protocol == PROTO_SCSI && 18334cca1530SAlexander Motin (device->flags & CAM_DEV_IDENTIFY_DATA_VALID)) { 18344cca1530SAlexander Motin uint16_t p = 18354cca1530SAlexander Motin device->ident_data.config & ATA_PROTO_MASK; 18364cca1530SAlexander Motin 18378e6cab54SAlexander Motin maxlen = 18388e6cab54SAlexander Motin (device->ident_data.config == ATA_PROTO_CFA) ? 0 : 18398e6cab54SAlexander Motin (p == ATA_PROTO_ATAPI_16) ? 16 : 18404cca1530SAlexander Motin (p == ATA_PROTO_ATAPI_12) ? 12 : 0; 18414cca1530SAlexander Motin } 18424cca1530SAlexander Motin if (start_ccb->csio.cdb_len > maxlen) { 18434cca1530SAlexander Motin start_ccb->ccb_h.status = CAM_REQ_INVALID; 18444cca1530SAlexander Motin xpt_done(start_ccb); 18454cca1530SAlexander Motin break; 18464cca1530SAlexander Motin } 1847ee2b236bSAlexander Motin xpt_action_default(start_ccb); 1848ee2b236bSAlexander Motin break; 18494cca1530SAlexander Motin } 185014f900e2SWill Andrews case XPT_DEV_ADVINFO: 185114f900e2SWill Andrews { 185214f900e2SWill Andrews ata_dev_advinfo(start_ccb); 185314f900e2SWill Andrews break; 185414f900e2SWill Andrews } 185552c9ce25SScott Long default: 185652c9ce25SScott Long xpt_action_default(start_ccb); 185752c9ce25SScott Long break; 185852c9ce25SScott Long } 185952c9ce25SScott Long } 186052c9ce25SScott Long 186152c9ce25SScott Long static void 1862b9c473b2SAlexander Motin ata_get_transfer_settings(struct ccb_trans_settings *cts) 1863b9c473b2SAlexander Motin { 1864b9c473b2SAlexander Motin struct ccb_trans_settings_ata *ata; 1865b9c473b2SAlexander Motin struct ccb_trans_settings_scsi *scsi; 1866b9c473b2SAlexander Motin struct cam_ed *device; 1867b9c473b2SAlexander Motin 1868b9c473b2SAlexander Motin device = cts->ccb_h.path->device; 1869227d67aaSAlexander Motin xpt_action_default((union ccb *)cts); 1870b9c473b2SAlexander Motin 1871bc1bf6e8SAlexander Motin if (cts->protocol == PROTO_UNKNOWN || 1872bc1bf6e8SAlexander Motin cts->protocol == PROTO_UNSPECIFIED) { 1873bc1bf6e8SAlexander Motin cts->protocol = device->protocol; 1874bc1bf6e8SAlexander Motin cts->protocol_version = device->protocol_version; 1875bc1bf6e8SAlexander Motin } 1876bc1bf6e8SAlexander Motin 1877b9c473b2SAlexander Motin if (cts->protocol == PROTO_ATA) { 1878b9c473b2SAlexander Motin ata = &cts->proto_specific.ata; 1879b9c473b2SAlexander Motin if ((ata->valid & CTS_ATA_VALID_TQ) == 0) { 1880b9c473b2SAlexander Motin ata->valid |= CTS_ATA_VALID_TQ; 1881b9c473b2SAlexander Motin if (cts->type == CTS_TYPE_USER_SETTINGS || 1882b9c473b2SAlexander Motin (device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 || 1883b9c473b2SAlexander Motin (device->inq_flags & SID_CmdQue) != 0) 1884b9c473b2SAlexander Motin ata->flags |= CTS_ATA_FLAGS_TAG_ENB; 1885b9c473b2SAlexander Motin } 1886b9c473b2SAlexander Motin } 1887b9c473b2SAlexander Motin if (cts->protocol == PROTO_SCSI) { 1888b9c473b2SAlexander Motin scsi = &cts->proto_specific.scsi; 1889b9c473b2SAlexander Motin if ((scsi->valid & CTS_SCSI_VALID_TQ) == 0) { 1890b9c473b2SAlexander Motin scsi->valid |= CTS_SCSI_VALID_TQ; 1891b9c473b2SAlexander Motin if (cts->type == CTS_TYPE_USER_SETTINGS || 1892b9c473b2SAlexander Motin (device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 || 1893b9c473b2SAlexander Motin (device->inq_flags & SID_CmdQue) != 0) 1894b9c473b2SAlexander Motin scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 1895b9c473b2SAlexander Motin } 1896b9c473b2SAlexander Motin } 1897bc1bf6e8SAlexander Motin 1898bc1bf6e8SAlexander Motin if (cts->transport == XPORT_UNKNOWN || 1899bc1bf6e8SAlexander Motin cts->transport == XPORT_UNSPECIFIED) { 1900bc1bf6e8SAlexander Motin cts->transport = device->transport; 1901bc1bf6e8SAlexander Motin cts->transport_version = device->transport_version; 1902bc1bf6e8SAlexander Motin } 1903b9c473b2SAlexander Motin } 1904b9c473b2SAlexander Motin 1905b9c473b2SAlexander Motin static void 1906227d67aaSAlexander Motin ata_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_path *path, 190752c9ce25SScott Long int async_update) 190852c9ce25SScott Long { 190952c9ce25SScott Long struct ccb_pathinq cpi; 1910b9c473b2SAlexander Motin struct ccb_trans_settings_ata *ata; 191152c9ce25SScott Long struct ccb_trans_settings_scsi *scsi; 1912b9c473b2SAlexander Motin struct ata_params *ident_data; 191352c9ce25SScott Long struct scsi_inquiry_data *inq_data; 1914227d67aaSAlexander Motin struct cam_ed *device; 191552c9ce25SScott Long 1916227d67aaSAlexander Motin if (path == NULL || (device = path->device) == NULL) { 191752c9ce25SScott Long cts->ccb_h.status = CAM_PATH_INVALID; 191852c9ce25SScott Long xpt_done((union ccb *)cts); 191952c9ce25SScott Long return; 192052c9ce25SScott Long } 192152c9ce25SScott Long 192252c9ce25SScott Long if (cts->protocol == PROTO_UNKNOWN 192352c9ce25SScott Long || cts->protocol == PROTO_UNSPECIFIED) { 192452c9ce25SScott Long cts->protocol = device->protocol; 192552c9ce25SScott Long cts->protocol_version = device->protocol_version; 192652c9ce25SScott Long } 192752c9ce25SScott Long 192852c9ce25SScott Long if (cts->protocol_version == PROTO_VERSION_UNKNOWN 192952c9ce25SScott Long || cts->protocol_version == PROTO_VERSION_UNSPECIFIED) 193052c9ce25SScott Long cts->protocol_version = device->protocol_version; 193152c9ce25SScott Long 193252c9ce25SScott Long if (cts->protocol != device->protocol) { 1933227d67aaSAlexander Motin xpt_print(path, "Uninitialized Protocol %x:%x?\n", 193452c9ce25SScott Long cts->protocol, device->protocol); 193552c9ce25SScott Long cts->protocol = device->protocol; 193652c9ce25SScott Long } 193752c9ce25SScott Long 193852c9ce25SScott Long if (cts->protocol_version > device->protocol_version) { 193952c9ce25SScott Long if (bootverbose) { 1940227d67aaSAlexander Motin xpt_print(path, "Down reving Protocol " 194152c9ce25SScott Long "Version from %d to %d?\n", cts->protocol_version, 194252c9ce25SScott Long device->protocol_version); 194352c9ce25SScott Long } 194452c9ce25SScott Long cts->protocol_version = device->protocol_version; 194552c9ce25SScott Long } 194652c9ce25SScott Long 194752c9ce25SScott Long if (cts->transport == XPORT_UNKNOWN 194852c9ce25SScott Long || cts->transport == XPORT_UNSPECIFIED) { 194952c9ce25SScott Long cts->transport = device->transport; 195052c9ce25SScott Long cts->transport_version = device->transport_version; 195152c9ce25SScott Long } 195252c9ce25SScott Long 195352c9ce25SScott Long if (cts->transport_version == XPORT_VERSION_UNKNOWN 195452c9ce25SScott Long || cts->transport_version == XPORT_VERSION_UNSPECIFIED) 195552c9ce25SScott Long cts->transport_version = device->transport_version; 195652c9ce25SScott Long 195752c9ce25SScott Long if (cts->transport != device->transport) { 1958227d67aaSAlexander Motin xpt_print(path, "Uninitialized Transport %x:%x?\n", 195952c9ce25SScott Long cts->transport, device->transport); 196052c9ce25SScott Long cts->transport = device->transport; 196152c9ce25SScott Long } 196252c9ce25SScott Long 196352c9ce25SScott Long if (cts->transport_version > device->transport_version) { 196452c9ce25SScott Long if (bootverbose) { 1965227d67aaSAlexander Motin xpt_print(path, "Down reving Transport " 196652c9ce25SScott Long "Version from %d to %d?\n", cts->transport_version, 196752c9ce25SScott Long device->transport_version); 196852c9ce25SScott Long } 196952c9ce25SScott Long cts->transport_version = device->transport_version; 197052c9ce25SScott Long } 197152c9ce25SScott Long 1972b9c473b2SAlexander Motin ident_data = &device->ident_data; 197352c9ce25SScott Long inq_data = &device->inq_data; 1974b9c473b2SAlexander Motin if (cts->protocol == PROTO_ATA) 1975b9c473b2SAlexander Motin ata = &cts->proto_specific.ata; 1976b9c473b2SAlexander Motin else 1977b9c473b2SAlexander Motin ata = NULL; 1978b9c473b2SAlexander Motin if (cts->protocol == PROTO_SCSI) 197952c9ce25SScott Long scsi = &cts->proto_specific.scsi; 1980b9c473b2SAlexander Motin else 1981b9c473b2SAlexander Motin scsi = NULL; 1982227d67aaSAlexander Motin xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); 198352c9ce25SScott Long cpi.ccb_h.func_code = XPT_PATH_INQ; 198452c9ce25SScott Long xpt_action((union ccb *)&cpi); 198552c9ce25SScott Long 1986b9c473b2SAlexander Motin /* Sanity checking */ 198752c9ce25SScott Long if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0 1988b9c473b2SAlexander Motin || (ata && (ident_data->satacapabilities & ATA_SUPPORT_NCQ) == 0) 1989b9c473b2SAlexander Motin || (scsi && (INQ_DATA_TQ_ENABLED(inq_data)) == 0) 199052c9ce25SScott Long || (device->queue_flags & SCP_QUEUE_DQUE) != 0 199152c9ce25SScott Long || (device->mintags == 0)) { 199252c9ce25SScott Long /* 199352c9ce25SScott Long * Can't tag on hardware that doesn't support tags, 199452c9ce25SScott Long * doesn't have it enabled, or has broken tag support. 199552c9ce25SScott Long */ 1996b9c473b2SAlexander Motin if (ata) 1997b9c473b2SAlexander Motin ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB; 1998b9c473b2SAlexander Motin if (scsi) 199952c9ce25SScott Long scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 200052c9ce25SScott Long } 200152c9ce25SScott Long 2002b9c473b2SAlexander Motin /* Start/stop tags use. */ 2003b9c473b2SAlexander Motin if (cts->type == CTS_TYPE_CURRENT_SETTINGS && 2004b9c473b2SAlexander Motin ((ata && (ata->valid & CTS_ATA_VALID_TQ) != 0) || 2005b9c473b2SAlexander Motin (scsi && (scsi->valid & CTS_SCSI_VALID_TQ) != 0))) { 2006b9c473b2SAlexander Motin int nowt, newt = 0; 200752c9ce25SScott Long 2008b9c473b2SAlexander Motin nowt = ((device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 || 2009b9c473b2SAlexander Motin (device->inq_flags & SID_CmdQue) != 0); 2010b9c473b2SAlexander Motin if (ata) 2011b9c473b2SAlexander Motin newt = (ata->flags & CTS_ATA_FLAGS_TAG_ENB) != 0; 2012b9c473b2SAlexander Motin if (scsi) 2013b9c473b2SAlexander Motin newt = (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0; 201452c9ce25SScott Long 2015b9c473b2SAlexander Motin if (newt && !nowt) { 201652c9ce25SScott Long /* 201752c9ce25SScott Long * Delay change to use tags until after a 201852c9ce25SScott Long * few commands have gone to this device so 201952c9ce25SScott Long * the controller has time to perform transfer 202052c9ce25SScott Long * negotiations without tagged messages getting 202152c9ce25SScott Long * in the way. 202252c9ce25SScott Long */ 202352c9ce25SScott Long device->tag_delay_count = CAM_TAG_DELAY_COUNT; 202452c9ce25SScott Long device->flags |= CAM_DEV_TAG_AFTER_COUNT; 2025b9c473b2SAlexander Motin } else if (nowt && !newt) 2026227d67aaSAlexander Motin xpt_stop_tags(path); 202752c9ce25SScott Long } 2028b9c473b2SAlexander Motin 202952c9ce25SScott Long if (async_update == FALSE) 2030227d67aaSAlexander Motin xpt_action_default((union ccb *)cts); 203152c9ce25SScott Long } 203252c9ce25SScott Long 203352c9ce25SScott Long /* 203452c9ce25SScott Long * Handle any per-device event notifications that require action by the XPT. 203552c9ce25SScott Long */ 203652c9ce25SScott Long static void 203752c9ce25SScott Long ata_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target, 203852c9ce25SScott Long struct cam_ed *device, void *async_arg) 203952c9ce25SScott Long { 204052c9ce25SScott Long cam_status status; 204152c9ce25SScott Long struct cam_path newpath; 204252c9ce25SScott Long 204352c9ce25SScott Long /* 204452c9ce25SScott Long * We only need to handle events for real devices. 204552c9ce25SScott Long */ 204652c9ce25SScott Long if (target->target_id == CAM_TARGET_WILDCARD 204752c9ce25SScott Long || device->lun_id == CAM_LUN_WILDCARD) 204852c9ce25SScott Long return; 204952c9ce25SScott Long 205052c9ce25SScott Long /* 205152c9ce25SScott Long * We need our own path with wildcards expanded to 205252c9ce25SScott Long * handle certain types of events. 205352c9ce25SScott Long */ 205452c9ce25SScott Long if ((async_code == AC_SENT_BDR) 205552c9ce25SScott Long || (async_code == AC_BUS_RESET) 205652c9ce25SScott Long || (async_code == AC_INQ_CHANGED)) 205752c9ce25SScott Long status = xpt_compile_path(&newpath, NULL, 205852c9ce25SScott Long bus->path_id, 205952c9ce25SScott Long target->target_id, 206052c9ce25SScott Long device->lun_id); 206152c9ce25SScott Long else 206252c9ce25SScott Long status = CAM_REQ_CMP_ERR; 206352c9ce25SScott Long 206452c9ce25SScott Long if (status == CAM_REQ_CMP) { 206552c9ce25SScott Long if (async_code == AC_INQ_CHANGED) { 206652c9ce25SScott Long /* 206752c9ce25SScott Long * We've sent a start unit command, or 206852c9ce25SScott Long * something similar to a device that 206952c9ce25SScott Long * may have caused its inquiry data to 207052c9ce25SScott Long * change. So we re-scan the device to 207152c9ce25SScott Long * refresh the inquiry data for it. 207252c9ce25SScott Long */ 207352c9ce25SScott Long ata_scan_lun(newpath.periph, &newpath, 207452c9ce25SScott Long CAM_EXPECT_INQ_CHANGE, NULL); 207583c5d981SAlexander Motin } else { 207683c5d981SAlexander Motin /* We need to reinitialize device after reset. */ 207783c5d981SAlexander Motin ata_scan_lun(newpath.periph, &newpath, 207883c5d981SAlexander Motin 0, NULL); 207952c9ce25SScott Long } 208052c9ce25SScott Long xpt_release_path(&newpath); 2081f98d7a47SAlexander Motin } else if (async_code == AC_LOST_DEVICE && 2082f98d7a47SAlexander Motin (device->flags & CAM_DEV_UNCONFIGURED) == 0) { 208352c9ce25SScott Long device->flags |= CAM_DEV_UNCONFIGURED; 2084f98d7a47SAlexander Motin xpt_release_device(device); 208552c9ce25SScott Long } else if (async_code == AC_TRANSFER_NEG) { 208652c9ce25SScott Long struct ccb_trans_settings *settings; 2087227d67aaSAlexander Motin struct cam_path path; 208852c9ce25SScott Long 208952c9ce25SScott Long settings = (struct ccb_trans_settings *)async_arg; 2090227d67aaSAlexander Motin xpt_compile_path(&path, NULL, bus->path_id, target->target_id, 2091227d67aaSAlexander Motin device->lun_id); 2092227d67aaSAlexander Motin ata_set_transfer_settings(settings, &path, 209352c9ce25SScott Long /*async_update*/TRUE); 2094227d67aaSAlexander Motin xpt_release_path(&path); 209552c9ce25SScott Long } 209652c9ce25SScott Long } 209752c9ce25SScott Long 209857079b17SAlexander Motin static void 20995d01277fSScott Long _ata_announce_periph(struct cam_periph *periph, struct ccb_trans_settings *cts, u_int *speed) 210057079b17SAlexander Motin { 210157079b17SAlexander Motin struct ccb_pathinq cpi; 210257079b17SAlexander Motin struct cam_path *path = periph->path; 210357079b17SAlexander Motin 2104227d67aaSAlexander Motin cam_periph_assert(periph, MA_OWNED); 210557079b17SAlexander Motin 21065d01277fSScott Long xpt_setup_ccb(&cts->ccb_h, path, CAM_PRIORITY_NORMAL); 21075d01277fSScott Long cts->ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 21085d01277fSScott Long cts->type = CTS_TYPE_CURRENT_SETTINGS; 21095d01277fSScott Long xpt_action((union ccb*)cts); 21105d01277fSScott Long if ((cts->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 211157079b17SAlexander Motin return; 211257079b17SAlexander Motin /* Ask the SIM for its base transfer speed */ 211357079b17SAlexander Motin xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL); 211457079b17SAlexander Motin cpi.ccb_h.func_code = XPT_PATH_INQ; 211557079b17SAlexander Motin xpt_action((union ccb *)&cpi); 211657079b17SAlexander Motin /* Report connection speed */ 21175d01277fSScott Long *speed = cpi.base_transfer_speed; 21185d01277fSScott Long if (cts->transport == XPORT_ATA) { 2119b9c473b2SAlexander Motin struct ccb_trans_settings_pata *pata = 21205d01277fSScott Long &cts->xport_specific.ata; 212157079b17SAlexander Motin 2122b9c473b2SAlexander Motin if (pata->valid & CTS_ATA_VALID_MODE) 21235d01277fSScott Long *speed = ata_mode2speed(pata->mode); 212457079b17SAlexander Motin } 21255d01277fSScott Long if (cts->transport == XPORT_SATA) { 212657079b17SAlexander Motin struct ccb_trans_settings_sata *sata = 21275d01277fSScott Long &cts->xport_specific.sata; 212857079b17SAlexander Motin 212957079b17SAlexander Motin if (sata->valid & CTS_SATA_VALID_REVISION) 21305d01277fSScott Long *speed = ata_revision2speed(sata->revision); 213157079b17SAlexander Motin } 21325d01277fSScott Long } 21335d01277fSScott Long 21345d01277fSScott Long static void 21355d01277fSScott Long ata_announce_periph(struct cam_periph *periph) 21365d01277fSScott Long { 21375d01277fSScott Long struct ccb_trans_settings cts; 21385d01277fSScott Long u_int speed, mb; 21395d01277fSScott Long 21405d01277fSScott Long _ata_announce_periph(periph, &cts, &speed); 21415d01277fSScott Long if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 21425d01277fSScott Long return; 21435d01277fSScott Long 214457079b17SAlexander Motin mb = speed / 1000; 214557079b17SAlexander Motin if (mb > 0) 214657079b17SAlexander Motin printf("%s%d: %d.%03dMB/s transfers", 214757079b17SAlexander Motin periph->periph_name, periph->unit_number, 214857079b17SAlexander Motin mb, speed % 1000); 214957079b17SAlexander Motin else 215057079b17SAlexander Motin printf("%s%d: %dKB/s transfers", periph->periph_name, 215157079b17SAlexander Motin periph->unit_number, speed); 215257079b17SAlexander Motin /* Report additional information about connection */ 21535d01277fSScott Long if (cts.transport == XPORT_ATA) { 2154b9c473b2SAlexander Motin struct ccb_trans_settings_pata *pata = 215557079b17SAlexander Motin &cts.xport_specific.ata; 215657079b17SAlexander Motin 215757079b17SAlexander Motin printf(" ("); 2158b9c473b2SAlexander Motin if (pata->valid & CTS_ATA_VALID_MODE) 2159b9c473b2SAlexander Motin printf("%s, ", ata_mode2string(pata->mode)); 2160b9c473b2SAlexander Motin if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0) 2161b9c473b2SAlexander Motin printf("ATAPI %dbytes, ", pata->atapi); 2162b9c473b2SAlexander Motin if (pata->valid & CTS_ATA_VALID_BYTECOUNT) 2163b9c473b2SAlexander Motin printf("PIO %dbytes", pata->bytecount); 216457079b17SAlexander Motin printf(")"); 216557079b17SAlexander Motin } 21665d01277fSScott Long if (cts.transport == XPORT_SATA) { 216757079b17SAlexander Motin struct ccb_trans_settings_sata *sata = 216857079b17SAlexander Motin &cts.xport_specific.sata; 216957079b17SAlexander Motin 217057079b17SAlexander Motin printf(" ("); 217157079b17SAlexander Motin if (sata->valid & CTS_SATA_VALID_REVISION) 217257079b17SAlexander Motin printf("SATA %d.x, ", sata->revision); 217357079b17SAlexander Motin else 217457079b17SAlexander Motin printf("SATA, "); 217557079b17SAlexander Motin if (sata->valid & CTS_SATA_VALID_MODE) 217657079b17SAlexander Motin printf("%s, ", ata_mode2string(sata->mode)); 217757079b17SAlexander Motin if ((sata->valid & CTS_ATA_VALID_ATAPI) && sata->atapi != 0) 217857079b17SAlexander Motin printf("ATAPI %dbytes, ", sata->atapi); 217957079b17SAlexander Motin if (sata->valid & CTS_SATA_VALID_BYTECOUNT) 218057079b17SAlexander Motin printf("PIO %dbytes", sata->bytecount); 218157079b17SAlexander Motin printf(")"); 218257079b17SAlexander Motin } 218357079b17SAlexander Motin printf("\n"); 218457079b17SAlexander Motin } 218508f13879SWarner Losh 218608f13879SWarner Losh static void 21875d01277fSScott Long ata_announce_periph_sbuf(struct cam_periph *periph, struct sbuf *sb) 21885d01277fSScott Long { 21895d01277fSScott Long struct ccb_trans_settings cts; 21905d01277fSScott Long u_int speed, mb; 21915d01277fSScott Long 21925d01277fSScott Long _ata_announce_periph(periph, &cts, &speed); 21935d01277fSScott Long if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 21945d01277fSScott Long return; 21955d01277fSScott Long 21965d01277fSScott Long mb = speed / 1000; 21975d01277fSScott Long if (mb > 0) 21985d01277fSScott Long sbuf_printf(sb, "%s%d: %d.%03dMB/s transfers", 21995d01277fSScott Long periph->periph_name, periph->unit_number, 22005d01277fSScott Long mb, speed % 1000); 22015d01277fSScott Long else 22025d01277fSScott Long sbuf_printf(sb, "%s%d: %dKB/s transfers", periph->periph_name, 22035d01277fSScott Long periph->unit_number, speed); 22045d01277fSScott Long /* Report additional information about connection */ 22055d01277fSScott Long if (cts.transport == XPORT_ATA) { 22065d01277fSScott Long struct ccb_trans_settings_pata *pata = 22075d01277fSScott Long &cts.xport_specific.ata; 22085d01277fSScott Long 22095d01277fSScott Long sbuf_printf(sb, " ("); 22105d01277fSScott Long if (pata->valid & CTS_ATA_VALID_MODE) 22115d01277fSScott Long sbuf_printf(sb, "%s, ", ata_mode2string(pata->mode)); 22125d01277fSScott Long if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0) 22135d01277fSScott Long sbuf_printf(sb, "ATAPI %dbytes, ", pata->atapi); 22145d01277fSScott Long if (pata->valid & CTS_ATA_VALID_BYTECOUNT) 22155d01277fSScott Long sbuf_printf(sb, "PIO %dbytes", pata->bytecount); 22165d01277fSScott Long sbuf_printf(sb, ")"); 22175d01277fSScott Long } 22185d01277fSScott Long if (cts.transport == XPORT_SATA) { 22195d01277fSScott Long struct ccb_trans_settings_sata *sata = 22205d01277fSScott Long &cts.xport_specific.sata; 22215d01277fSScott Long 22225d01277fSScott Long sbuf_printf(sb, " ("); 22235d01277fSScott Long if (sata->valid & CTS_SATA_VALID_REVISION) 22245d01277fSScott Long sbuf_printf(sb, "SATA %d.x, ", sata->revision); 22255d01277fSScott Long else 22265d01277fSScott Long sbuf_printf(sb, "SATA, "); 22275d01277fSScott Long if (sata->valid & CTS_SATA_VALID_MODE) 22285d01277fSScott Long sbuf_printf(sb, "%s, ", ata_mode2string(sata->mode)); 22295d01277fSScott Long if ((sata->valid & CTS_ATA_VALID_ATAPI) && sata->atapi != 0) 22305d01277fSScott Long sbuf_printf(sb, "ATAPI %dbytes, ", sata->atapi); 22315d01277fSScott Long if (sata->valid & CTS_SATA_VALID_BYTECOUNT) 22325d01277fSScott Long sbuf_printf(sb, "PIO %dbytes", sata->bytecount); 22335d01277fSScott Long sbuf_printf(sb, ")"); 22345d01277fSScott Long } 22355d01277fSScott Long sbuf_printf(sb, "\n"); 22365d01277fSScott Long } 22375d01277fSScott Long 22385d01277fSScott Long static void 22395d01277fSScott Long ata_proto_announce_sbuf(struct cam_ed *device, struct sbuf *sb) 22405d01277fSScott Long { 22415d01277fSScott Long ata_print_ident_sbuf(&device->ident_data, sb); 22425d01277fSScott Long } 22435d01277fSScott Long 22445d01277fSScott Long static void 224508f13879SWarner Losh ata_proto_announce(struct cam_ed *device) 224608f13879SWarner Losh { 224708f13879SWarner Losh ata_print_ident(&device->ident_data); 224808f13879SWarner Losh } 224908f13879SWarner Losh 225008f13879SWarner Losh static void 225108f13879SWarner Losh ata_proto_denounce(struct cam_ed *device) 225208f13879SWarner Losh { 225308f13879SWarner Losh ata_print_ident_short(&device->ident_data); 225408f13879SWarner Losh } 225508f13879SWarner Losh 225608f13879SWarner Losh static void 22575d01277fSScott Long ata_proto_denounce_sbuf(struct cam_ed *device, struct sbuf *sb) 22585d01277fSScott Long { 22595d01277fSScott Long ata_print_ident_short_sbuf(&device->ident_data, sb); 22605d01277fSScott Long } 22615d01277fSScott Long 22625d01277fSScott Long static void 22635d01277fSScott Long semb_proto_announce_sbuf(struct cam_ed *device, struct sbuf *sb) 22645d01277fSScott Long { 22655d01277fSScott Long semb_print_ident_sbuf((struct sep_identify_data *)&device->ident_data, sb); 22665d01277fSScott Long } 22675d01277fSScott Long 22685d01277fSScott Long static void 226908f13879SWarner Losh semb_proto_announce(struct cam_ed *device) 227008f13879SWarner Losh { 227108f13879SWarner Losh semb_print_ident((struct sep_identify_data *)&device->ident_data); 227208f13879SWarner Losh } 227308f13879SWarner Losh 227408f13879SWarner Losh static void 227508f13879SWarner Losh semb_proto_denounce(struct cam_ed *device) 227608f13879SWarner Losh { 227708f13879SWarner Losh semb_print_ident_short((struct sep_identify_data *)&device->ident_data); 227808f13879SWarner Losh } 227908f13879SWarner Losh 228008f13879SWarner Losh static void 22815d01277fSScott Long semb_proto_denounce_sbuf(struct cam_ed *device, struct sbuf *sb) 22825d01277fSScott Long { 22835d01277fSScott Long semb_print_ident_short_sbuf((struct sep_identify_data *)&device->ident_data, sb); 22845d01277fSScott Long } 22855d01277fSScott Long 22865d01277fSScott Long static void 228708f13879SWarner Losh ata_proto_debug_out(union ccb *ccb) 228808f13879SWarner Losh { 228908f13879SWarner Losh char cdb_str[(sizeof(struct ata_cmd) * 3) + 1]; 229008f13879SWarner Losh 229108f13879SWarner Losh if (ccb->ccb_h.func_code != XPT_ATA_IO) 229208f13879SWarner Losh return; 229308f13879SWarner Losh 229408f13879SWarner Losh CAM_DEBUG(ccb->ccb_h.path, 229508f13879SWarner Losh CAM_DEBUG_CDB,("%s. ACB: %s\n", ata_op_string(&ccb->ataio.cmd), 229608f13879SWarner Losh ata_cmd_string(&ccb->ataio.cmd, cdb_str, sizeof(cdb_str)))); 229708f13879SWarner Losh } 2298