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