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 /* XXX need to do nvme admin opcodes too, but those aren't used yet by nda */ 110 static const char * 111 nvme_opc2str[] = { 112 "FLUSH", 113 "WRITE", 114 "READ", 115 "RSVD-3", 116 "WRITE_UNCORRECTABLE", 117 "COMPARE", 118 "RSVD-6", 119 "RSVD-7", 120 "WRITE_ZEROES", 121 "DATASET_MANAGEMENT", 122 "RSVD-a", 123 "RSVD-b", 124 "RSVD-c", 125 "RESERVATION_REGISTER", 126 "RESERVATION_REPORT", 127 "RSVD-f", 128 "RSVD-10", 129 "RESERVATION_ACQUIRE", 130 "RSVD-12", 131 "RSVD-13", 132 "RSVD-14", 133 "RESERVATION_RELEASE", 134 }; 135 136 const char * 137 nvme_op_string(const struct nvme_command *cmd, int admin) 138 { 139 140 if (admin) { 141 return "ADMIN"; 142 } else { 143 if (cmd->opc >= nitems(nvme_opc2str)) 144 return "UNKNOWN"; 145 return nvme_opc2str[cmd->opc]; 146 } 147 } 148 149 const char * 150 nvme_cmd_string(const struct nvme_command *cmd, char *cmd_string, size_t len) 151 { 152 struct sbuf sb; 153 int error; 154 155 if (len == 0) 156 return (""); 157 158 sbuf_new(&sb, cmd_string, len, SBUF_FIXEDLEN); 159 nvme_cmd_sbuf(cmd, &sb); 160 161 error = sbuf_finish(&sb); 162 if (error != 0 && 163 #ifdef _KERNEL 164 error != ENOMEM) 165 #else 166 errno != ENOMEM) 167 #endif 168 return (""); 169 170 return(sbuf_data(&sb)); 171 } 172 173 void 174 nvme_cmd_sbuf(const struct nvme_command *cmd, struct sbuf *sb) 175 { 176 177 /* 178 * cid, rsvd areas and mptr not printed, since they are used 179 * only internally by the SIM. 180 */ 181 sbuf_printf(sb, 182 "opc=%x fuse=%x nsid=%x prp1=%llx prp2=%llx cdw=%x %x %x %x %x %x", 183 cmd->opc, cmd->fuse, cmd->nsid, 184 (unsigned long long)cmd->prp1, (unsigned long long)cmd->prp2, 185 cmd->cdw10, cmd->cdw11, cmd->cdw12, 186 cmd->cdw13, cmd->cdw14, cmd->cdw15); 187 } 188 189 /* 190 * nvme_command_sbuf() returns 0 for success and -1 for failure. 191 */ 192 int 193 nvme_command_sbuf(struct ccb_nvmeio *nvmeio, struct sbuf *sb) 194 { 195 196 sbuf_printf(sb, "%s. NCB: ", nvme_op_string(&nvmeio->cmd, 197 nvmeio->ccb_h.func_code == XPT_NVME_ADMIN)); 198 nvme_cmd_sbuf(&nvmeio->cmd, sb); 199 return(0); 200 } 201 202 #ifdef _KERNEL 203 const void * 204 nvme_get_identify_cntrl(struct cam_periph *periph) 205 { 206 struct cam_ed *device; 207 208 device = periph->path->device; 209 210 return device->nvme_cdata; 211 } 212 213 const void * 214 nvme_get_identify_ns(struct cam_periph *periph) 215 { 216 struct cam_ed *device; 217 218 device = periph->path->device; 219 220 return device->nvme_data; 221 } 222 #endif 223