xref: /freebsd/sys/cam/nvme/nvme_all.c (revision 60159a98a83747e539eb14c6a0eaaa1875e2cacc)
1baabaca3SWarner Losh /*-
2891c6986SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3f24882ecSPedro F. Giffuni  *
452467047SWarner Losh  * Copyright (c) 2015 Netflix, Inc.
5baabaca3SWarner Losh  *
6baabaca3SWarner Losh  * Redistribution and use in source and binary forms, with or without
7baabaca3SWarner Losh  * modification, are permitted provided that the following conditions
8baabaca3SWarner Losh  * are met:
9baabaca3SWarner Losh  * 1. Redistributions of source code must retain the above copyright
10891c6986SWarner Losh  *    notice, this list of conditions and the following disclaimer.
11baabaca3SWarner Losh  * 2. Redistributions in binary form must reproduce the above copyright
12baabaca3SWarner Losh  *    notice, this list of conditions and the following disclaimer in the
13baabaca3SWarner Losh  *    documentation and/or other materials provided with the distribution.
14baabaca3SWarner Losh  *
15891c6986SWarner Losh  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16891c6986SWarner Losh  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17891c6986SWarner Losh  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18891c6986SWarner Losh  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19891c6986SWarner Losh  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20891c6986SWarner Losh  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21891c6986SWarner Losh  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22891c6986SWarner Losh  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23891c6986SWarner Losh  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24891c6986SWarner Losh  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25891c6986SWarner Losh  * SUCH DAMAGE.
26baabaca3SWarner Losh  */
27baabaca3SWarner Losh 
28baabaca3SWarner Losh #include <sys/param.h>
29baabaca3SWarner Losh 
30baabaca3SWarner Losh #ifdef _KERNEL
31baabaca3SWarner Losh #include "opt_scsi.h"
32baabaca3SWarner Losh 
33baabaca3SWarner Losh #include <sys/systm.h>
34baabaca3SWarner Losh #include <sys/libkern.h>
35baabaca3SWarner Losh #include <sys/kernel.h>
369f8ed7e4SWarner Losh #include <sys/malloc.h>
37baabaca3SWarner Losh #include <sys/sysctl.h>
38baabaca3SWarner Losh #else
39baabaca3SWarner Losh #include <errno.h>
40baabaca3SWarner Losh #include <stdio.h>
41baabaca3SWarner Losh #include <stdlib.h>
42baabaca3SWarner Losh #include <string.h>
43baabaca3SWarner Losh #ifndef min
44baabaca3SWarner Losh #define min(a,b) (((a)<(b))?(a):(b))
45baabaca3SWarner Losh #endif
46baabaca3SWarner Losh #endif
47baabaca3SWarner Losh 
48baabaca3SWarner Losh #include <cam/cam.h>
49baabaca3SWarner Losh #include <cam/cam_ccb.h>
50baabaca3SWarner Losh #include <cam/cam_queue.h>
51baabaca3SWarner Losh #include <cam/cam_xpt.h>
52baabaca3SWarner Losh #include <cam/nvme/nvme_all.h>
53baabaca3SWarner Losh #include <sys/sbuf.h>
54baabaca3SWarner Losh #include <sys/endian.h>
55baabaca3SWarner Losh 
569f8ed7e4SWarner Losh #ifdef _KERNEL
579f8ed7e4SWarner Losh #include <cam/cam_periph.h>
589f8ed7e4SWarner Losh #include <cam/cam_xpt_sim.h>
599f8ed7e4SWarner Losh #include <cam/cam_xpt_periph.h>
609f8ed7e4SWarner Losh #include <cam/cam_xpt_internal.h>
619f8ed7e4SWarner Losh #endif
629f8ed7e4SWarner Losh 
63baabaca3SWarner Losh void
nvme_ns_cmd(struct ccb_nvmeio * nvmeio,uint8_t cmd,uint32_t nsid,uint32_t cdw10,uint32_t cdw11,uint32_t cdw12,uint32_t cdw13,uint32_t cdw14,uint32_t cdw15)64baabaca3SWarner Losh nvme_ns_cmd(struct ccb_nvmeio *nvmeio, uint8_t cmd, uint32_t nsid,
65baabaca3SWarner Losh     uint32_t cdw10, uint32_t cdw11, uint32_t cdw12, uint32_t cdw13,
66baabaca3SWarner Losh     uint32_t cdw14, uint32_t cdw15)
67baabaca3SWarner Losh {
68baabaca3SWarner Losh 	bzero(&nvmeio->cmd, sizeof(struct nvme_command));
699544e6dcSChuck Tuffli 	nvmeio->cmd.opc = cmd;
700d787e9bSWojciech Macek 	nvmeio->cmd.nsid = htole32(nsid);
710d787e9bSWojciech Macek 	nvmeio->cmd.cdw10 = htole32(cdw10);
720d787e9bSWojciech Macek 	nvmeio->cmd.cdw11 = htole32(cdw11);
730d787e9bSWojciech Macek 	nvmeio->cmd.cdw12 = htole32(cdw12);
740d787e9bSWojciech Macek 	nvmeio->cmd.cdw13 = htole32(cdw13);
750d787e9bSWojciech Macek 	nvmeio->cmd.cdw14 = htole32(cdw14);
760d787e9bSWojciech Macek 	nvmeio->cmd.cdw15 = htole32(cdw15);
77baabaca3SWarner Losh }
78baabaca3SWarner Losh 
79baabaca3SWarner Losh int
nvme_identify_match(caddr_t identbuffer,caddr_t table_entry)80baabaca3SWarner Losh nvme_identify_match(caddr_t identbuffer, caddr_t table_entry)
81baabaca3SWarner Losh {
82baabaca3SWarner Losh 	return 0;
83baabaca3SWarner Losh }
84baabaca3SWarner Losh 
85baabaca3SWarner Losh void
nvme_print_ident(const struct nvme_controller_data * cdata,const struct nvme_namespace_data * data,struct sbuf * sb)86baabaca3SWarner Losh nvme_print_ident(const struct nvme_controller_data *cdata,
875e8a39f6SWarner Losh     const struct nvme_namespace_data *data, struct sbuf *sb)
88baabaca3SWarner Losh {
890be27bdeSJohn Baldwin 	nvme_print_ident_short(cdata, data, sb);
90519b24f0SAlexander Motin 	sbuf_putc(sb, '\n');
910be27bdeSJohn Baldwin }
925e8a39f6SWarner Losh 
930be27bdeSJohn Baldwin void
nvme_print_ident_short(const struct nvme_controller_data * cdata,const struct nvme_namespace_data * data,struct sbuf * sb)940be27bdeSJohn Baldwin nvme_print_ident_short(const struct nvme_controller_data *cdata,
950be27bdeSJohn Baldwin     const struct nvme_namespace_data *data, struct sbuf *sb)
960be27bdeSJohn Baldwin {
97519b24f0SAlexander Motin 	sbuf_putc(sb, '<');
983090d504SKenneth D. Merry 	cam_strvis_sbuf(sb, cdata->mn, sizeof(cdata->mn),
993090d504SKenneth D. Merry 	    CAM_STRVIS_FLAG_NONASCII_SPC);
100519b24f0SAlexander Motin 	sbuf_putc(sb, ' ');
1013090d504SKenneth D. Merry 	cam_strvis_sbuf(sb, cdata->fr, sizeof(cdata->fr),
1023090d504SKenneth D. Merry 	    CAM_STRVIS_FLAG_NONASCII_SPC);
103519b24f0SAlexander Motin 	sbuf_putc(sb, ' ');
1043090d504SKenneth D. Merry 	cam_strvis_sbuf(sb, cdata->sn, sizeof(cdata->sn),
1053090d504SKenneth D. Merry 	    CAM_STRVIS_FLAG_NONASCII_SPC);
106519b24f0SAlexander Motin 	sbuf_putc(sb, '>');
107baabaca3SWarner Losh }
108baabaca3SWarner Losh 
109baabaca3SWarner Losh const char *
nvme_command_string(struct ccb_nvmeio * nvmeio,char * cmd_string,size_t len)110*5304a20fSJohn Baldwin nvme_command_string(struct ccb_nvmeio *nvmeio, char *cmd_string, size_t len)
111baabaca3SWarner Losh {
112e40d8dbbSAlexander Motin 	struct sbuf sb;
113e40d8dbbSAlexander Motin 	int error;
114e40d8dbbSAlexander Motin 
115e40d8dbbSAlexander Motin 	if (len == 0)
116e40d8dbbSAlexander Motin 		return ("");
117e40d8dbbSAlexander Motin 
118e40d8dbbSAlexander Motin 	sbuf_new(&sb, cmd_string, len, SBUF_FIXEDLEN);
119*5304a20fSJohn Baldwin 	nvme_command_sbuf(nvmeio, &sb);
120e40d8dbbSAlexander Motin 
121e40d8dbbSAlexander Motin 	error = sbuf_finish(&sb);
122cd500da9SAlexander Motin 	if (error != 0 &&
123cd500da9SAlexander Motin #ifdef _KERNEL
124cd500da9SAlexander Motin 	    error != ENOMEM)
125cd500da9SAlexander Motin #else
126cd500da9SAlexander Motin 	    errno != ENOMEM)
127cd500da9SAlexander Motin #endif
128e40d8dbbSAlexander Motin 		return ("");
129e40d8dbbSAlexander Motin 
130e40d8dbbSAlexander Motin 	return(sbuf_data(&sb));
131e40d8dbbSAlexander Motin }
132e40d8dbbSAlexander Motin 
133e40d8dbbSAlexander Motin void
nvme_cmd_sbuf(const struct nvme_command * cmd,struct sbuf * sb)134e40d8dbbSAlexander Motin nvme_cmd_sbuf(const struct nvme_command *cmd, struct sbuf *sb)
135e40d8dbbSAlexander Motin {
1360d787e9bSWojciech Macek 
137baabaca3SWarner Losh 	/*
138baabaca3SWarner Losh 	 * cid, rsvd areas and mptr not printed, since they are used
139baabaca3SWarner Losh 	 * only internally by the SIM.
140baabaca3SWarner Losh 	 */
141e40d8dbbSAlexander Motin 	sbuf_printf(sb,
142baabaca3SWarner Losh 	    "opc=%x fuse=%x nsid=%x prp1=%llx prp2=%llx cdw=%x %x %x %x %x %x",
1439544e6dcSChuck Tuffli 	    cmd->opc, cmd->fuse, cmd->nsid,
144baabaca3SWarner Losh 	    (unsigned long long)cmd->prp1, (unsigned long long)cmd->prp2,
1450d787e9bSWojciech Macek 	    cmd->cdw10, cmd->cdw11, cmd->cdw12,
1460d787e9bSWojciech Macek 	    cmd->cdw13, cmd->cdw14, cmd->cdw15);
147baabaca3SWarner Losh }
1489f8ed7e4SWarner Losh 
149e40d8dbbSAlexander Motin /*
150e40d8dbbSAlexander Motin  * nvme_command_sbuf() returns 0 for success and -1 for failure.
151e40d8dbbSAlexander Motin  */
152e40d8dbbSAlexander Motin int
nvme_command_sbuf(struct ccb_nvmeio * nvmeio,struct sbuf * sb)153e40d8dbbSAlexander Motin nvme_command_sbuf(struct ccb_nvmeio *nvmeio, struct sbuf *sb)
154e40d8dbbSAlexander Motin {
155e40d8dbbSAlexander Motin 
156f2a587b8SJohn Baldwin 	nvme_opcode_sbuf(nvmeio->ccb_h.func_code == XPT_NVME_ADMIN,
157f2a587b8SJohn Baldwin 	    nvmeio->cmd.opc, sb);
158f2a587b8SJohn Baldwin 	sbuf_cat(sb, ". NCB: ");
159e40d8dbbSAlexander Motin 	nvme_cmd_sbuf(&nvmeio->cmd, sb);
160e40d8dbbSAlexander Motin 	return(0);
161e40d8dbbSAlexander Motin }
162e40d8dbbSAlexander Motin 
163f2a587b8SJohn Baldwin /*
164f2a587b8SJohn Baldwin  * nvme_status_sbuf() returns 0 for success and -1 for failure.
165f2a587b8SJohn Baldwin  */
166f2a587b8SJohn Baldwin int
nvme_status_sbuf(struct ccb_nvmeio * nvmeio,struct sbuf * sb)167f2a587b8SJohn Baldwin nvme_status_sbuf(struct ccb_nvmeio *nvmeio, struct sbuf *sb)
168f2a587b8SJohn Baldwin {
169f2a587b8SJohn Baldwin 	nvme_cpl_sbuf(&nvmeio->cpl, sb);
170f2a587b8SJohn Baldwin 	return (0);
171f2a587b8SJohn Baldwin }
172f2a587b8SJohn Baldwin 
173e40d8dbbSAlexander Motin #ifdef _KERNEL
1749f8ed7e4SWarner Losh const void *
nvme_get_identify_cntrl(struct cam_periph * periph)1759f8ed7e4SWarner Losh nvme_get_identify_cntrl(struct cam_periph *periph)
1769f8ed7e4SWarner Losh {
1779f8ed7e4SWarner Losh 	struct cam_ed *device;
1789f8ed7e4SWarner Losh 
1799f8ed7e4SWarner Losh 	device = periph->path->device;
1809f8ed7e4SWarner Losh 
1819f8ed7e4SWarner Losh 	return device->nvme_cdata;
1829f8ed7e4SWarner Losh }
1839f8ed7e4SWarner Losh 
1849f8ed7e4SWarner Losh const void *
nvme_get_identify_ns(struct cam_periph * periph)1859f8ed7e4SWarner Losh nvme_get_identify_ns(struct cam_periph *periph)
1869f8ed7e4SWarner Losh {
1879f8ed7e4SWarner Losh 	struct cam_ed *device;
1889f8ed7e4SWarner Losh 
1899f8ed7e4SWarner Losh 	device = periph->path->device;
1909f8ed7e4SWarner Losh 
1919f8ed7e4SWarner Losh 	return device->nvme_data;
1929f8ed7e4SWarner Losh }
193e40d8dbbSAlexander Motin #endif
194