1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
|
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2023-2024 Chelsio Communications, Inc.
* Written by: John Baldwin <jhb@FreeBSD.org>
*/
#include <sys/types.h>
#include <sys/memdesc.h>
#include <sys/systm.h>
#include <dev/nvme/nvme.h>
#include <dev/nvmf/nvmf.h>
#include <dev/nvmf/nvmf_proto.h>
#include <dev/nvmf/host/nvmf_var.h>
bool
nvmf_cmd_get_property(struct nvmf_softc *sc, uint32_t offset, uint8_t size,
nvmf_request_complete_t *cb, void *cb_arg, int how)
{
struct nvmf_fabric_prop_get_cmd cmd;
struct nvmf_request *req;
memset(&cmd, 0, sizeof(cmd));
cmd.opcode = NVME_OPC_FABRICS_COMMANDS;
cmd.fctype = NVMF_FABRIC_COMMAND_PROPERTY_GET;
switch (size) {
case 4:
cmd.attrib.size = NVMF_PROP_SIZE_4;
break;
case 8:
cmd.attrib.size = NVMF_PROP_SIZE_8;
break;
default:
panic("Invalid property size");
}
cmd.ofst = htole32(offset);
req = nvmf_allocate_request(sc->admin, &cmd, cb, cb_arg, how);
if (req != NULL)
nvmf_submit_request(req);
return (req != NULL);
}
bool
nvmf_cmd_set_property(struct nvmf_softc *sc, uint32_t offset, uint8_t size,
uint64_t value, nvmf_request_complete_t *cb, void *cb_arg, int how)
{
struct nvmf_fabric_prop_set_cmd cmd;
struct nvmf_request *req;
memset(&cmd, 0, sizeof(cmd));
cmd.opcode = NVME_OPC_FABRICS_COMMANDS;
cmd.fctype = NVMF_FABRIC_COMMAND_PROPERTY_SET;
switch (size) {
case 4:
cmd.attrib.size = NVMF_PROP_SIZE_4;
cmd.value.u32.low = htole32(value);
break;
case 8:
cmd.attrib.size = NVMF_PROP_SIZE_8;
cmd.value.u64 = htole64(value);
break;
default:
panic("Invalid property size");
}
cmd.ofst = htole32(offset);
req = nvmf_allocate_request(sc->admin, &cmd, cb, cb_arg, how);
if (req != NULL)
nvmf_submit_request(req);
return (req != NULL);
}
bool
nvmf_cmd_keep_alive(struct nvmf_softc *sc, nvmf_request_complete_t *cb,
void *cb_arg, int how)
{
struct nvme_command cmd;
struct nvmf_request *req;
memset(&cmd, 0, sizeof(cmd));
cmd.opc = NVME_OPC_KEEP_ALIVE;
req = nvmf_allocate_request(sc->admin, &cmd, cb, cb_arg, how);
if (req != NULL)
nvmf_submit_request(req);
return (req != NULL);
}
bool
nvmf_cmd_identify_active_namespaces(struct nvmf_softc *sc, uint32_t id,
struct nvme_ns_list *nslist, nvmf_request_complete_t *req_cb,
void *req_cb_arg, nvmf_io_complete_t *io_cb, void *io_cb_arg, int how)
{
struct nvme_command cmd;
struct memdesc mem;
struct nvmf_request *req;
memset(&cmd, 0, sizeof(cmd));
cmd.opc = NVME_OPC_IDENTIFY;
/* 5.15.1 Use CNS of 0x02 for namespace data. */
cmd.cdw10 = htole32(2);
cmd.nsid = htole32(id);
req = nvmf_allocate_request(sc->admin, &cmd, req_cb, req_cb_arg, how);
if (req == NULL)
return (false);
mem = memdesc_vaddr(nslist, sizeof(*nslist));
nvmf_capsule_append_data(req->nc, &mem, sizeof(*nslist), false,
io_cb, io_cb_arg);
nvmf_submit_request(req);
return (true);
}
bool
nvmf_cmd_identify_namespace(struct nvmf_softc *sc, uint32_t id,
struct nvme_namespace_data *nsdata, nvmf_request_complete_t *req_cb,
void *req_cb_arg, nvmf_io_complete_t *io_cb, void *io_cb_arg, int how)
{
struct nvme_command cmd;
struct memdesc mem;
struct nvmf_request *req;
memset(&cmd, 0, sizeof(cmd));
cmd.opc = NVME_OPC_IDENTIFY;
/* 5.15.1 Use CNS of 0x00 for namespace data. */
cmd.cdw10 = htole32(0);
cmd.nsid = htole32(id);
req = nvmf_allocate_request(sc->admin, &cmd, req_cb, req_cb_arg, how);
if (req == NULL)
return (false);
mem = memdesc_vaddr(nsdata, sizeof(*nsdata));
nvmf_capsule_append_data(req->nc, &mem, sizeof(*nsdata), false,
io_cb, io_cb_arg);
nvmf_submit_request(req);
return (true);
}
bool
nvmf_cmd_get_log_page(struct nvmf_softc *sc, uint32_t nsid, uint8_t lid,
uint64_t offset, void *buf, size_t len, nvmf_request_complete_t *req_cb,
void *req_cb_arg, nvmf_io_complete_t *io_cb, void *io_cb_arg, int how)
{
struct nvme_command cmd;
struct memdesc mem;
struct nvmf_request *req;
size_t numd;
MPASS(len != 0 && len % 4 == 0);
MPASS(offset % 4 == 0);
numd = (len / 4) - 1;
memset(&cmd, 0, sizeof(cmd));
cmd.opc = NVME_OPC_GET_LOG_PAGE;
cmd.nsid = htole32(nsid);
cmd.cdw10 = htole32(numd << 16 | lid);
cmd.cdw11 = htole32(numd >> 16);
cmd.cdw12 = htole32(offset);
cmd.cdw13 = htole32(offset >> 32);
req = nvmf_allocate_request(sc->admin, &cmd, req_cb, req_cb_arg, how);
if (req == NULL)
return (false);
mem = memdesc_vaddr(buf, len);
nvmf_capsule_append_data(req->nc, &mem, len, false, io_cb, io_cb_arg);
nvmf_submit_request(req);
return (true);
}
|