1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2015 Netflix, Inc. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/param.h> 29 30 #ifdef _KERNEL 31 #include "opt_scsi.h" 32 33 #include <sys/systm.h> 34 #include <sys/libkern.h> 35 #include <sys/kernel.h> 36 #include <sys/malloc.h> 37 #include <sys/sysctl.h> 38 #else 39 #include <errno.h> 40 #include <stdio.h> 41 #include <stdlib.h> 42 #include <string.h> 43 #ifndef min 44 #define min(a,b) (((a)<(b))?(a):(b)) 45 #endif 46 #endif 47 48 #include <cam/cam.h> 49 #include <cam/cam_ccb.h> 50 #include <cam/cam_queue.h> 51 #include <cam/cam_xpt.h> 52 #include <cam/nvme/nvme_all.h> 53 #include <sys/sbuf.h> 54 #include <sys/endian.h> 55 56 #ifdef _KERNEL 57 #include <cam/cam_periph.h> 58 #include <cam/cam_xpt_sim.h> 59 #include <cam/cam_xpt_periph.h> 60 #include <cam/cam_xpt_internal.h> 61 #endif 62 63 void 64 nvme_ns_cmd(struct ccb_nvmeio *nvmeio, uint8_t cmd, uint32_t nsid, 65 uint32_t cdw10, uint32_t cdw11, uint32_t cdw12, uint32_t cdw13, 66 uint32_t cdw14, uint32_t cdw15) 67 { 68 bzero(&nvmeio->cmd, sizeof(struct nvme_command)); 69 nvmeio->cmd.opc = cmd; 70 nvmeio->cmd.nsid = htole32(nsid); 71 nvmeio->cmd.cdw10 = htole32(cdw10); 72 nvmeio->cmd.cdw11 = htole32(cdw11); 73 nvmeio->cmd.cdw12 = htole32(cdw12); 74 nvmeio->cmd.cdw13 = htole32(cdw13); 75 nvmeio->cmd.cdw14 = htole32(cdw14); 76 nvmeio->cmd.cdw15 = htole32(cdw15); 77 } 78 79 int 80 nvme_identify_match(caddr_t identbuffer, caddr_t table_entry) 81 { 82 return 0; 83 } 84 85 void 86 nvme_print_ident(const struct nvme_controller_data *cdata, 87 const struct nvme_namespace_data *data, struct sbuf *sb) 88 { 89 nvme_print_ident_short(cdata, data, sb); 90 sbuf_putc(sb, '\n'); 91 } 92 93 void 94 nvme_print_ident_short(const struct nvme_controller_data *cdata, 95 const struct nvme_namespace_data *data, struct sbuf *sb) 96 { 97 sbuf_putc(sb, '<'); 98 cam_strvis_sbuf(sb, cdata->mn, sizeof(cdata->mn), 99 CAM_STRVIS_FLAG_NONASCII_SPC); 100 sbuf_putc(sb, ' '); 101 cam_strvis_sbuf(sb, cdata->fr, sizeof(cdata->fr), 102 CAM_STRVIS_FLAG_NONASCII_SPC); 103 sbuf_putc(sb, ' '); 104 cam_strvis_sbuf(sb, cdata->sn, sizeof(cdata->sn), 105 CAM_STRVIS_FLAG_NONASCII_SPC); 106 sbuf_putc(sb, '>'); 107 } 108 109 const char * 110 nvme_command_string(struct ccb_nvmeio *nvmeio, char *cmd_string, size_t len) 111 { 112 struct sbuf sb; 113 int error; 114 115 if (len == 0) 116 return (""); 117 118 sbuf_new(&sb, cmd_string, len, SBUF_FIXEDLEN); 119 nvme_command_sbuf(nvmeio, &sb); 120 121 error = sbuf_finish(&sb); 122 if (error != 0 && 123 #ifdef _KERNEL 124 error != ENOMEM) 125 #else 126 errno != ENOMEM) 127 #endif 128 return (""); 129 130 return(sbuf_data(&sb)); 131 } 132 133 void 134 nvme_cmd_sbuf(const struct nvme_command *cmd, struct sbuf *sb) 135 { 136 137 /* 138 * cid, rsvd areas and mptr not printed, since they are used 139 * only internally by the SIM. 140 */ 141 sbuf_printf(sb, 142 "opc=%x fuse=%x nsid=%x prp1=%llx prp2=%llx cdw=%x %x %x %x %x %x", 143 cmd->opc, cmd->fuse, cmd->nsid, 144 (unsigned long long)cmd->prp1, (unsigned long long)cmd->prp2, 145 cmd->cdw10, cmd->cdw11, cmd->cdw12, 146 cmd->cdw13, cmd->cdw14, cmd->cdw15); 147 } 148 149 /* 150 * nvme_command_sbuf() returns 0 for success and -1 for failure. 151 */ 152 int 153 nvme_command_sbuf(struct ccb_nvmeio *nvmeio, struct sbuf *sb) 154 { 155 156 nvme_opcode_sbuf(nvmeio->ccb_h.func_code == XPT_NVME_ADMIN, 157 nvmeio->cmd.opc, sb); 158 sbuf_cat(sb, ". NCB: "); 159 nvme_cmd_sbuf(&nvmeio->cmd, sb); 160 return(0); 161 } 162 163 /* 164 * nvme_status_sbuf() returns 0 for success and -1 for failure. 165 */ 166 int 167 nvme_status_sbuf(struct ccb_nvmeio *nvmeio, struct sbuf *sb) 168 { 169 nvme_cpl_sbuf(&nvmeio->cpl, sb); 170 return (0); 171 } 172 173 #ifdef _KERNEL 174 const void * 175 nvme_get_identify_cntrl(struct cam_periph *periph) 176 { 177 struct cam_ed *device; 178 179 device = periph->path->device; 180 181 return device->nvme_cdata; 182 } 183 184 const void * 185 nvme_get_identify_ns(struct cam_periph *periph) 186 { 187 struct cam_ed *device; 188 189 device = periph->path->device; 190 191 return device->nvme_data; 192 } 193 #endif 194