#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;
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;
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);
}