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