1301771Simp/*- 2301771Simp * Copyright (c) 2015 Netflix, Inc. 3301771Simp * All rights reserved. 4301771Simp * 5301771Simp * Redistribution and use in source and binary forms, with or without 6301771Simp * modification, are permitted provided that the following conditions 7301771Simp * are met: 8301771Simp * 1. Redistributions of source code must retain the above copyright 9301771Simp * notice, this list of conditions and the following disclaimer, 10301771Simp * without modification, immediately at the beginning of the file. 11301771Simp * 2. Redistributions in binary form must reproduce the above copyright 12301771Simp * notice, this list of conditions and the following disclaimer in the 13301771Simp * documentation and/or other materials provided with the distribution. 14301771Simp * 15301771Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16301771Simp * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17301771Simp * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18301771Simp * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19301771Simp * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20301771Simp * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21301771Simp * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22301771Simp * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23301771Simp * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24301771Simp * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25301771Simp * 26301771Simp * derived from ata_xpt.c: Copyright (c) 2009 Alexander Motin <mav@FreeBSD.org> 27301771Simp */ 28301771Simp 29301771Simp#include <sys/cdefs.h> 30301771Simp__FBSDID("$FreeBSD: stable/11/sys/cam/nvme/nvme_xpt.c 351754 2019-09-03 16:24:44Z mav $"); 31301771Simp 32301771Simp#include <sys/param.h> 33301771Simp#include <sys/bus.h> 34301771Simp#include <sys/endian.h> 35301771Simp#include <sys/systm.h> 36301771Simp#include <sys/types.h> 37301771Simp#include <sys/malloc.h> 38301771Simp#include <sys/kernel.h> 39301771Simp#include <sys/time.h> 40301771Simp#include <sys/conf.h> 41301771Simp#include <sys/fcntl.h> 42301771Simp#include <sys/sbuf.h> 43301771Simp 44301771Simp#include <sys/lock.h> 45301771Simp#include <sys/mutex.h> 46301771Simp#include <sys/sysctl.h> 47301771Simp 48301771Simp#include <cam/cam.h> 49301771Simp#include <cam/cam_ccb.h> 50301771Simp#include <cam/cam_queue.h> 51301771Simp#include <cam/cam_periph.h> 52301771Simp#include <cam/cam_sim.h> 53301771Simp#include <cam/cam_xpt.h> 54301771Simp#include <cam/cam_xpt_sim.h> 55301771Simp#include <cam/cam_xpt_periph.h> 56301771Simp#include <cam/cam_xpt_internal.h> 57301771Simp#include <cam/cam_debug.h> 58301771Simp 59301771Simp#include <cam/scsi/scsi_all.h> 60301771Simp#include <cam/scsi/scsi_message.h> 61301771Simp#include <cam/nvme/nvme_all.h> 62301771Simp#include <machine/stdarg.h> /* for xpt_print below */ 63301771Simp#include "opt_cam.h" 64301771Simp 65301771Simpstruct nvme_quirk_entry { 66301771Simp u_int quirks; 67301771Simp#define CAM_QUIRK_MAXTAGS 1 68301771Simp u_int mintags; 69301771Simp u_int maxtags; 70301771Simp}; 71301771Simp 72301771Simp/* Not even sure why we need this */ 73301771Simpstatic periph_init_t nvme_probe_periph_init; 74301771Simp 75301771Simpstatic struct periph_driver nvme_probe_driver = 76301771Simp{ 77301771Simp nvme_probe_periph_init, "nvme_probe", 78301771Simp TAILQ_HEAD_INITIALIZER(nvme_probe_driver.units), /* generation */ 0, 79301771Simp CAM_PERIPH_DRV_EARLY 80301771Simp}; 81301771Simp 82301771SimpPERIPHDRIVER_DECLARE(nvme_probe, nvme_probe_driver); 83301771Simp 84301771Simptypedef enum { 85301771Simp NVME_PROBE_IDENTIFY, 86301771Simp NVME_PROBE_DONE, 87301771Simp NVME_PROBE_INVALID, 88301771Simp NVME_PROBE_RESET 89301771Simp} nvme_probe_action; 90301771Simp 91301771Simpstatic char *nvme_probe_action_text[] = { 92301771Simp "NVME_PROBE_IDENTIFY", 93301771Simp "NVME_PROBE_DONE", 94301771Simp "NVME_PROBE_INVALID", 95301771Simp "NVME_PROBE_RESET", 96301771Simp}; 97301771Simp 98301771Simp#define NVME_PROBE_SET_ACTION(softc, newaction) \ 99301771Simpdo { \ 100301771Simp char **text; \ 101301771Simp text = nvme_probe_action_text; \ 102301771Simp CAM_DEBUG((softc)->periph->path, CAM_DEBUG_PROBE, \ 103301771Simp ("Probe %s to %s\n", text[(softc)->action], \ 104301771Simp text[(newaction)])); \ 105301771Simp (softc)->action = (newaction); \ 106301771Simp} while(0) 107301771Simp 108301771Simptypedef enum { 109301771Simp NVME_PROBE_NO_ANNOUNCE = 0x04 110301771Simp} nvme_probe_flags; 111301771Simp 112301771Simptypedef struct { 113301771Simp TAILQ_HEAD(, ccb_hdr) request_ccbs; 114301771Simp nvme_probe_action action; 115301771Simp nvme_probe_flags flags; 116301771Simp int restart; 117301771Simp struct cam_periph *periph; 118301771Simp} nvme_probe_softc; 119301771Simp 120301771Simpstatic struct nvme_quirk_entry nvme_quirk_table[] = 121301771Simp{ 122301771Simp { 123301771Simp// { 124301771Simp// T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED, 125301771Simp// /*vendor*/"*", /*product*/"*", /*revision*/"*" 126301771Simp// }, 127301771Simp .quirks = 0, .mintags = 0, .maxtags = 0 128301771Simp }, 129301771Simp}; 130301771Simp 131301771Simpstatic const int nvme_quirk_table_size = 132301771Simp sizeof(nvme_quirk_table) / sizeof(*nvme_quirk_table); 133301771Simp 134301771Simpstatic cam_status nvme_probe_register(struct cam_periph *periph, 135301771Simp void *arg); 136301771Simpstatic void nvme_probe_schedule(struct cam_periph *nvme_probe_periph); 137301771Simpstatic void nvme_probe_start(struct cam_periph *periph, union ccb *start_ccb); 138301771Simpstatic void nvme_probe_cleanup(struct cam_periph *periph); 139301778Simp//static void nvme_find_quirk(struct cam_ed *device); 140301771Simpstatic void nvme_scan_lun(struct cam_periph *periph, 141301771Simp struct cam_path *path, cam_flags flags, 142301771Simp union ccb *ccb); 143301771Simpstatic struct cam_ed * 144301771Simp nvme_alloc_device(struct cam_eb *bus, struct cam_et *target, 145301771Simp lun_id_t lun_id); 146301771Simpstatic void nvme_device_transport(struct cam_path *path); 147301771Simpstatic void nvme_dev_async(u_int32_t async_code, 148301771Simp struct cam_eb *bus, 149301771Simp struct cam_et *target, 150301771Simp struct cam_ed *device, 151301771Simp void *async_arg); 152301771Simpstatic void nvme_action(union ccb *start_ccb); 153301771Simpstatic void nvme_announce_periph(struct cam_periph *periph); 154328820Smavstatic void nvme_proto_announce(struct cam_ed *device); 155328820Smavstatic void nvme_proto_denounce(struct cam_ed *device); 156328820Smavstatic void nvme_proto_debug_out(union ccb *ccb); 157301771Simp 158328819Smavstatic struct xpt_xport_ops nvme_xport_ops = { 159301771Simp .alloc_device = nvme_alloc_device, 160301771Simp .action = nvme_action, 161301771Simp .async = nvme_dev_async, 162301771Simp .announce = nvme_announce_periph, 163301771Simp}; 164328819Smav#define NVME_XPT_XPORT(x, X) \ 165328819Smavstatic struct xpt_xport nvme_xport_ ## x = { \ 166328819Smav .xport = XPORT_ ## X, \ 167328819Smav .name = #x, \ 168328819Smav .ops = &nvme_xport_ops, \ 169328819Smav}; \ 170328819SmavCAM_XPT_XPORT(nvme_xport_ ## x); 171301771Simp 172328819SmavNVME_XPT_XPORT(nvme, NVME); 173328705Smav 174328819Smav#undef NVME_XPT_XPORT 175301771Simp 176328820Smavstatic struct xpt_proto_ops nvme_proto_ops = { 177328820Smav .announce = nvme_proto_announce, 178328820Smav .denounce = nvme_proto_denounce, 179328820Smav .debug_out = nvme_proto_debug_out, 180328820Smav}; 181328820Smavstatic struct xpt_proto nvme_proto = { 182328820Smav .proto = PROTO_NVME, 183328820Smav .name = "nvme", 184328820Smav .ops = &nvme_proto_ops, 185328820Smav}; 186328820SmavCAM_XPT_PROTO(nvme_proto); 187328820Smav 188301771Simpstatic void 189301771Simpnvme_probe_periph_init() 190301771Simp{ 191328705Smav 192301771Simp} 193301771Simp 194301771Simpstatic cam_status 195301771Simpnvme_probe_register(struct cam_periph *periph, void *arg) 196301771Simp{ 197301771Simp union ccb *request_ccb; /* CCB representing the probe request */ 198301771Simp cam_status status; 199301771Simp nvme_probe_softc *softc; 200301771Simp 201301771Simp request_ccb = (union ccb *)arg; 202301771Simp if (request_ccb == NULL) { 203301771Simp printf("nvme_probe_register: no probe CCB, " 204301771Simp "can't register device\n"); 205301771Simp return(CAM_REQ_CMP_ERR); 206301771Simp } 207301771Simp 208301771Simp softc = (nvme_probe_softc *)malloc(sizeof(*softc), M_CAMXPT, M_ZERO | M_NOWAIT); 209301771Simp 210301771Simp if (softc == NULL) { 211301771Simp printf("nvme_probe_register: Unable to probe new device. " 212301771Simp "Unable to allocate softc\n"); 213301771Simp return(CAM_REQ_CMP_ERR); 214301771Simp } 215301771Simp TAILQ_INIT(&softc->request_ccbs); 216301771Simp TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h, 217301771Simp periph_links.tqe); 218301771Simp softc->flags = 0; 219301771Simp periph->softc = softc; 220301771Simp softc->periph = periph; 221301771Simp softc->action = NVME_PROBE_INVALID; 222301771Simp status = cam_periph_acquire(periph); 223301771Simp if (status != CAM_REQ_CMP) { 224301771Simp return (status); 225301771Simp } 226301771Simp CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe started\n")); 227301771Simp 228301771Simp// nvme_device_transport(periph->path); 229301771Simp nvme_probe_schedule(periph); 230301771Simp 231301771Simp return(CAM_REQ_CMP); 232301771Simp} 233301771Simp 234301771Simpstatic void 235301771Simpnvme_probe_schedule(struct cam_periph *periph) 236301771Simp{ 237301771Simp union ccb *ccb; 238301771Simp nvme_probe_softc *softc; 239301771Simp 240301771Simp softc = (nvme_probe_softc *)periph->softc; 241301771Simp ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs); 242301771Simp 243301771Simp NVME_PROBE_SET_ACTION(softc, NVME_PROBE_IDENTIFY); 244301771Simp 245301771Simp if (ccb->crcn.flags & CAM_EXPECT_INQ_CHANGE) 246301771Simp softc->flags |= NVME_PROBE_NO_ANNOUNCE; 247301771Simp else 248301771Simp softc->flags &= ~NVME_PROBE_NO_ANNOUNCE; 249301771Simp 250301771Simp xpt_schedule(periph, CAM_PRIORITY_XPT); 251301771Simp} 252301771Simp 253301771Simpstatic void 254301771Simpnvme_probe_start(struct cam_periph *periph, union ccb *start_ccb) 255301771Simp{ 256301771Simp struct ccb_nvmeio *nvmeio; 257301771Simp struct ccb_scsiio *csio; 258301771Simp nvme_probe_softc *softc; 259301771Simp struct cam_path *path; 260301771Simp const struct nvme_namespace_data *nvme_data; 261301771Simp lun_id_t lun; 262301771Simp 263301771Simp CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("nvme_probe_start\n")); 264301771Simp 265301771Simp softc = (nvme_probe_softc *)periph->softc; 266301771Simp path = start_ccb->ccb_h.path; 267301771Simp nvmeio = &start_ccb->nvmeio; 268301771Simp csio = &start_ccb->csio; 269301771Simp nvme_data = periph->path->device->nvme_data; 270301771Simp 271301771Simp if (softc->restart) { 272301771Simp softc->restart = 0; 273301771Simp if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) 274301771Simp NVME_PROBE_SET_ACTION(softc, NVME_PROBE_RESET); 275301771Simp else 276301771Simp NVME_PROBE_SET_ACTION(softc, NVME_PROBE_IDENTIFY); 277301771Simp } 278301771Simp 279301771Simp /* 280301771Simp * Other transports have to ask their SIM to do a lot of action. 281301771Simp * NVMe doesn't, so don't do the dance. Just do things 282301771Simp * directly. 283301771Simp */ 284301771Simp switch (softc->action) { 285301771Simp case NVME_PROBE_RESET: 286301771Simp /* FALLTHROUGH */ 287301771Simp case NVME_PROBE_IDENTIFY: 288301771Simp nvme_device_transport(path); 289301771Simp /* 290301771Simp * Test for lun == CAM_LUN_WILDCARD is lame, but 291301771Simp * appears to be necessary here. XXX 292301771Simp */ 293301771Simp lun = xpt_path_lun_id(periph->path); 294301771Simp if (lun == CAM_LUN_WILDCARD || 295301771Simp periph->path->device->flags & CAM_DEV_UNCONFIGURED) { 296301771Simp path->device->flags &= ~CAM_DEV_UNCONFIGURED; 297301771Simp xpt_acquire_device(path->device); 298301771Simp start_ccb->ccb_h.func_code = XPT_GDEV_TYPE; 299301771Simp xpt_action(start_ccb); 300301771Simp xpt_async(AC_FOUND_DEVICE, path, start_ccb); 301301771Simp } 302301771Simp NVME_PROBE_SET_ACTION(softc, NVME_PROBE_DONE); 303301771Simp break; 304301771Simp default: 305301771Simp panic("nvme_probe_start: invalid action state 0x%x\n", softc->action); 306301771Simp } 307301771Simp /* 308301771Simp * Probing is now done. We need to complete any lingering items 309301771Simp * in the queue, though there shouldn't be any. 310301771Simp */ 311301771Simp xpt_release_ccb(start_ccb); 312301771Simp CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe completed\n")); 313301771Simp while ((start_ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs))) { 314301771Simp TAILQ_REMOVE(&softc->request_ccbs, 315301771Simp &start_ccb->ccb_h, periph_links.tqe); 316301771Simp start_ccb->ccb_h.status = CAM_REQ_CMP; 317301771Simp xpt_done(start_ccb); 318301771Simp } 319301771Simp cam_periph_invalidate(periph); 320328705Smav /* Can't release periph since we hit a (possibly bogus) assertion */ 321328705Smav// cam_periph_release_locked(periph); 322301771Simp} 323301771Simp 324301771Simpstatic void 325301771Simpnvme_probe_cleanup(struct cam_periph *periph) 326301771Simp{ 327328705Smav 328301771Simp free(periph->softc, M_CAMXPT); 329301771Simp} 330301771Simp 331301778Simp#if 0 332301771Simp/* XXX should be used, don't delete */ 333301771Simpstatic void 334301771Simpnvme_find_quirk(struct cam_ed *device) 335301771Simp{ 336301771Simp struct nvme_quirk_entry *quirk; 337301771Simp caddr_t match; 338301771Simp 339301771Simp match = cam_quirkmatch((caddr_t)&device->nvme_data, 340301771Simp (caddr_t)nvme_quirk_table, 341301771Simp nvme_quirk_table_size, 342301771Simp sizeof(*nvme_quirk_table), nvme_identify_match); 343301771Simp 344301771Simp if (match == NULL) 345301771Simp panic("xpt_find_quirk: device didn't match wildcard entry!!"); 346301771Simp 347301771Simp quirk = (struct nvme_quirk_entry *)match; 348301771Simp device->quirk = quirk; 349301771Simp if (quirk->quirks & CAM_QUIRK_MAXTAGS) { 350301771Simp device->mintags = quirk->mintags; 351301771Simp device->maxtags = quirk->maxtags; 352301771Simp } 353301771Simp} 354301778Simp#endif 355301771Simp 356301771Simpstatic void 357301771Simpnvme_scan_lun(struct cam_periph *periph, struct cam_path *path, 358301771Simp cam_flags flags, union ccb *request_ccb) 359301771Simp{ 360301771Simp struct ccb_pathinq cpi; 361301771Simp cam_status status; 362301771Simp struct cam_periph *old_periph; 363301771Simp int lock; 364301771Simp 365301771Simp CAM_DEBUG(path, CAM_DEBUG_TRACE, ("nvme_scan_lun\n")); 366301771Simp 367350804Smav xpt_path_inq(&cpi, path); 368301771Simp 369301771Simp if (cpi.ccb_h.status != CAM_REQ_CMP) { 370301771Simp if (request_ccb != NULL) { 371301771Simp request_ccb->ccb_h.status = cpi.ccb_h.status; 372301771Simp xpt_done(request_ccb); 373301771Simp } 374301771Simp return; 375301771Simp } 376301771Simp 377301771Simp if (xpt_path_lun_id(path) == CAM_LUN_WILDCARD) { 378301771Simp CAM_DEBUG(path, CAM_DEBUG_TRACE, ("nvme_scan_lun ignoring bus\n")); 379301771Simp request_ccb->ccb_h.status = CAM_REQ_CMP; /* XXX signal error ? */ 380301771Simp xpt_done(request_ccb); 381301771Simp return; 382301771Simp } 383301771Simp 384301771Simp lock = (xpt_path_owned(path) == 0); 385301771Simp if (lock) 386301771Simp xpt_path_lock(path); 387301771Simp if ((old_periph = cam_periph_find(path, "nvme_probe")) != NULL) { 388301771Simp if ((old_periph->flags & CAM_PERIPH_INVALID) == 0) { 389301771Simp nvme_probe_softc *softc; 390301771Simp 391301771Simp softc = (nvme_probe_softc *)old_periph->softc; 392301771Simp TAILQ_INSERT_TAIL(&softc->request_ccbs, 393301771Simp &request_ccb->ccb_h, periph_links.tqe); 394301771Simp softc->restart = 1; 395301771Simp CAM_DEBUG(path, CAM_DEBUG_TRACE, 396301771Simp ("restarting nvme_probe device\n")); 397301771Simp } else { 398301771Simp request_ccb->ccb_h.status = CAM_REQ_CMP_ERR; 399301771Simp CAM_DEBUG(path, CAM_DEBUG_TRACE, 400301771Simp ("Failing to restart nvme_probe device\n")); 401301771Simp xpt_done(request_ccb); 402301771Simp } 403301771Simp } else { 404301771Simp CAM_DEBUG(path, CAM_DEBUG_TRACE, 405301771Simp ("Adding nvme_probe device\n")); 406301771Simp status = cam_periph_alloc(nvme_probe_register, NULL, nvme_probe_cleanup, 407301771Simp nvme_probe_start, "nvme_probe", 408301771Simp CAM_PERIPH_BIO, 409301771Simp request_ccb->ccb_h.path, NULL, 0, 410301771Simp request_ccb); 411301771Simp 412301771Simp if (status != CAM_REQ_CMP) { 413301771Simp xpt_print(path, "xpt_scan_lun: cam_alloc_periph " 414301771Simp "returned an error, can't continue probe\n"); 415301771Simp request_ccb->ccb_h.status = status; 416301771Simp xpt_done(request_ccb); 417301771Simp } 418301771Simp } 419301771Simp if (lock) 420301771Simp xpt_path_unlock(path); 421301771Simp} 422301771Simp 423301771Simpstatic struct cam_ed * 424301771Simpnvme_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id) 425301771Simp{ 426301771Simp struct nvme_quirk_entry *quirk; 427301771Simp struct cam_ed *device; 428301771Simp 429301771Simp device = xpt_alloc_device(bus, target, lun_id); 430301771Simp if (device == NULL) 431301771Simp return (NULL); 432301771Simp 433301771Simp /* 434301771Simp * Take the default quirk entry until we have inquiry 435301771Simp * data from nvme and can determine a better quirk to use. 436301771Simp */ 437301771Simp quirk = &nvme_quirk_table[nvme_quirk_table_size - 1]; 438301771Simp device->quirk = (void *)quirk; 439301771Simp device->mintags = 0; 440301771Simp device->maxtags = 0; 441301771Simp device->inq_flags = 0; 442301771Simp device->queue_flags = 0; 443301771Simp device->device_id = NULL; /* XXX Need to set this somewhere */ 444301771Simp device->device_id_len = 0; 445301771Simp device->serial_num = NULL; /* XXX Need to set this somewhere */ 446301771Simp device->serial_num_len = 0; 447301771Simp return (device); 448301771Simp} 449301771Simp 450301771Simpstatic void 451301771Simpnvme_device_transport(struct cam_path *path) 452301771Simp{ 453301771Simp struct ccb_pathinq cpi; 454301771Simp struct ccb_trans_settings cts; 455301771Simp /* XXX get data from nvme namespace and other info ??? */ 456301771Simp 457301771Simp /* Get transport information from the SIM */ 458350804Smav xpt_path_inq(&cpi, path); 459301771Simp 460301771Simp path->device->transport = cpi.transport; 461301771Simp path->device->transport_version = cpi.transport_version; 462301771Simp 463301771Simp path->device->protocol = cpi.protocol; 464301771Simp path->device->protocol_version = cpi.protocol_version; 465301771Simp 466301771Simp /* Tell the controller what we think */ 467301771Simp xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); 468301771Simp cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 469301771Simp cts.type = CTS_TYPE_CURRENT_SETTINGS; 470301771Simp cts.transport = path->device->transport; 471301771Simp cts.transport_version = path->device->transport_version; 472301771Simp cts.protocol = path->device->protocol; 473301771Simp cts.protocol_version = path->device->protocol_version; 474301771Simp cts.proto_specific.valid = 0; 475301771Simp cts.xport_specific.valid = 0; 476301771Simp xpt_action((union ccb *)&cts); 477301771Simp} 478301771Simp 479301771Simpstatic void 480301771Simpnvme_dev_advinfo(union ccb *start_ccb) 481301771Simp{ 482301771Simp struct cam_ed *device; 483301771Simp struct ccb_dev_advinfo *cdai; 484351754Smav off_t amt; 485301771Simp 486351754Smav xpt_path_assert(start_ccb->ccb_h.path, MA_OWNED); 487301771Simp start_ccb->ccb_h.status = CAM_REQ_INVALID; 488301771Simp device = start_ccb->ccb_h.path->device; 489301771Simp cdai = &start_ccb->cdai; 490301771Simp switch(cdai->buftype) { 491301771Simp case CDAI_TYPE_SCSI_DEVID: 492301771Simp if (cdai->flags & CDAI_FLAG_STORE) 493301771Simp return; 494301771Simp cdai->provsiz = device->device_id_len; 495301771Simp if (device->device_id_len == 0) 496301771Simp break; 497301771Simp amt = device->device_id_len; 498301771Simp if (cdai->provsiz > cdai->bufsiz) 499301771Simp amt = cdai->bufsiz; 500301771Simp memcpy(cdai->buf, device->device_id, amt); 501301771Simp break; 502301771Simp case CDAI_TYPE_SERIAL_NUM: 503301771Simp if (cdai->flags & CDAI_FLAG_STORE) 504301771Simp return; 505301771Simp cdai->provsiz = device->serial_num_len; 506301771Simp if (device->serial_num_len == 0) 507301771Simp break; 508301771Simp amt = device->serial_num_len; 509301771Simp if (cdai->provsiz > cdai->bufsiz) 510301771Simp amt = cdai->bufsiz; 511301771Simp memcpy(cdai->buf, device->serial_num, amt); 512301771Simp break; 513301771Simp case CDAI_TYPE_PHYS_PATH: 514301771Simp if (cdai->flags & CDAI_FLAG_STORE) { 515301771Simp if (device->physpath != NULL) 516301771Simp free(device->physpath, M_CAMXPT); 517301771Simp device->physpath_len = cdai->bufsiz; 518301771Simp /* Clear existing buffer if zero length */ 519301771Simp if (cdai->bufsiz == 0) 520301771Simp break; 521301771Simp device->physpath = malloc(cdai->bufsiz, M_CAMXPT, M_NOWAIT); 522301771Simp if (device->physpath == NULL) { 523301771Simp start_ccb->ccb_h.status = CAM_REQ_ABORTED; 524301771Simp return; 525301771Simp } 526301771Simp memcpy(device->physpath, cdai->buf, cdai->bufsiz); 527301771Simp } else { 528301771Simp cdai->provsiz = device->physpath_len; 529301771Simp if (device->physpath_len == 0) 530301771Simp break; 531301771Simp amt = device->physpath_len; 532301771Simp if (cdai->provsiz > cdai->bufsiz) 533301771Simp amt = cdai->bufsiz; 534301771Simp memcpy(cdai->buf, device->physpath, amt); 535301771Simp } 536301771Simp break; 537328735Smav case CDAI_TYPE_NVME_CNTRL: 538328735Smav if (cdai->flags & CDAI_FLAG_STORE) 539328735Smav return; 540328735Smav amt = sizeof(struct nvme_controller_data); 541328735Smav cdai->provsiz = amt; 542328735Smav if (amt > cdai->bufsiz) 543328735Smav amt = cdai->bufsiz; 544328735Smav memcpy(cdai->buf, device->nvme_cdata, amt); 545328735Smav break; 546328735Smav case CDAI_TYPE_NVME_NS: 547328735Smav if (cdai->flags & CDAI_FLAG_STORE) 548328735Smav return; 549328735Smav amt = sizeof(struct nvme_namespace_data); 550328735Smav cdai->provsiz = amt; 551328735Smav if (amt > cdai->bufsiz) 552328735Smav amt = cdai->bufsiz; 553328735Smav memcpy(cdai->buf, device->nvme_data, amt); 554328735Smav break; 555301771Simp default: 556301771Simp return; 557301771Simp } 558301771Simp start_ccb->ccb_h.status = CAM_REQ_CMP; 559301771Simp 560301771Simp if (cdai->flags & CDAI_FLAG_STORE) { 561301771Simp xpt_async(AC_ADVINFO_CHANGED, start_ccb->ccb_h.path, 562301771Simp (void *)(uintptr_t)cdai->buftype); 563301771Simp } 564301771Simp} 565301771Simp 566301771Simpstatic void 567301771Simpnvme_action(union ccb *start_ccb) 568301771Simp{ 569301771Simp CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, 570301771Simp ("nvme_action: func= %#x\n", start_ccb->ccb_h.func_code)); 571301771Simp 572301771Simp switch (start_ccb->ccb_h.func_code) { 573301771Simp case XPT_SCAN_BUS: 574301771Simp case XPT_SCAN_TGT: 575301771Simp case XPT_SCAN_LUN: 576301771Simp nvme_scan_lun(start_ccb->ccb_h.path->periph, 577301771Simp start_ccb->ccb_h.path, start_ccb->crcn.flags, 578301771Simp start_ccb); 579301771Simp break; 580301771Simp case XPT_DEV_ADVINFO: 581301771Simp nvme_dev_advinfo(start_ccb); 582301771Simp break; 583301771Simp 584301771Simp default: 585301771Simp xpt_action_default(start_ccb); 586301771Simp break; 587301771Simp } 588301771Simp} 589301771Simp 590301771Simp/* 591301771Simp * Handle any per-device event notifications that require action by the XPT. 592301771Simp */ 593301771Simpstatic void 594301771Simpnvme_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target, 595301771Simp struct cam_ed *device, void *async_arg) 596301771Simp{ 597301771Simp 598301771Simp /* 599301771Simp * We only need to handle events for real devices. 600301771Simp */ 601301771Simp if (target->target_id == CAM_TARGET_WILDCARD 602301771Simp || device->lun_id == CAM_LUN_WILDCARD) 603301771Simp return; 604301771Simp 605301771Simp if (async_code == AC_LOST_DEVICE && 606301771Simp (device->flags & CAM_DEV_UNCONFIGURED) == 0) { 607301771Simp device->flags |= CAM_DEV_UNCONFIGURED; 608301771Simp xpt_release_device(device); 609301771Simp } 610301771Simp} 611301771Simp 612301771Simpstatic void 613301771Simpnvme_announce_periph(struct cam_periph *periph) 614301771Simp{ 615301771Simp struct ccb_pathinq cpi; 616301771Simp struct ccb_trans_settings cts; 617301771Simp struct cam_path *path = periph->path; 618301771Simp 619301771Simp cam_periph_assert(periph, MA_OWNED); 620301771Simp 621301771Simp xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); 622301771Simp cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 623301771Simp cts.type = CTS_TYPE_CURRENT_SETTINGS; 624301771Simp xpt_action((union ccb*)&cts); 625301771Simp if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 626301771Simp return; 627301771Simp /* Ask the SIM for its base transfer speed */ 628350804Smav xpt_path_inq(&cpi, periph->path); 629301771Simp /* XXX NVME STUFF HERE */ 630301771Simp printf("\n"); 631301771Simp} 632328820Smav 633328820Smavstatic void 634328820Smavnvme_proto_announce(struct cam_ed *device) 635328820Smav{ 636335166Smav 637328820Smav nvme_print_ident(device->nvme_cdata, device->nvme_data); 638328820Smav} 639328820Smav 640328820Smavstatic void 641328820Smavnvme_proto_denounce(struct cam_ed *device) 642328820Smav{ 643335166Smav 644328820Smav nvme_print_ident(device->nvme_cdata, device->nvme_data); 645328820Smav} 646328820Smav 647328820Smavstatic void 648328820Smavnvme_proto_debug_out(union ccb *ccb) 649328820Smav{ 650328820Smav char cdb_str[(sizeof(struct nvme_command) * 3) + 1]; 651328820Smav 652328820Smav if (ccb->ccb_h.func_code != XPT_NVME_IO) 653328820Smav return; 654328820Smav 655328820Smav CAM_DEBUG(ccb->ccb_h.path, 656328820Smav CAM_DEBUG_CDB,("%s. NCB: %s\n", nvme_op_string(&ccb->nvmeio.cmd), 657328820Smav nvme_cmd_string(&ccb->nvmeio.cmd, cdb_str, sizeof(cdb_str)))); 658328820Smav} 659328820Smav 660