zephyr/drivers/disk/nvme/nvme_controller_cmd.c

224 lines
5.6 KiB
C

/*
* Copyright (c) 2022 Intel Corporation
* SPDX-License-Identifier: Apache-2.0
*
* Derived from FreeBSD original driver made by Jim Harris
*/
#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(nvme, CONFIG_NVME_LOG_LEVEL);
#include <zephyr/kernel.h>
#include <zephyr/sys/byteorder.h>
#include <string.h>
#include "nvme.h"
#include "nvme_helpers.h"
int nvme_ctrlr_cmd_identify_controller(struct nvme_controller *ctrlr,
nvme_cb_fn_t cb_fn, void *cb_arg)
{
struct nvme_request *request;
request = nvme_allocate_request_vaddr(
&ctrlr->cdata, sizeof(struct nvme_controller_data),
cb_fn, cb_arg);
if (!request) {
return -ENOMEM;
}
memset(&request->cmd, 0, sizeof(request->cmd));
request->cmd.cdw0.opc = NVME_OPC_IDENTIFY;
request->cmd.cdw10 = sys_cpu_to_le32(1);
return nvme_cmd_qpair_submit_request(ctrlr->adminq, request);
}
int nvme_ctrlr_cmd_identify_namespace(struct nvme_controller *ctrlr,
uint32_t nsid, void *payload,
nvme_cb_fn_t cb_fn, void *cb_arg)
{
struct nvme_request *request;
request = nvme_allocate_request_vaddr(
payload, sizeof(struct nvme_namespace_data),
cb_fn, cb_arg);
if (!request) {
return -ENOMEM;
}
request->cmd.cdw0.opc = NVME_OPC_IDENTIFY;
/*
* TODO: create an identify command data structure
*/
request->cmd.nsid = sys_cpu_to_le32(nsid);
return nvme_cmd_qpair_submit_request(ctrlr->adminq, request);
}
int nvme_ctrlr_cmd_create_io_cq(struct nvme_controller *ctrlr,
struct nvme_cmd_qpair *io_queue,
nvme_cb_fn_t cb_fn, void *cb_arg)
{
struct nvme_request *request;
struct nvme_command *cmd;
request = nvme_allocate_request_null(cb_fn, cb_arg);
if (!request) {
return -ENOMEM;
}
cmd = &request->cmd;
cmd->cdw0.opc = NVME_OPC_CREATE_IO_CQ;
/*
* TODO: create a create io completion queue command data
* structure.
*/
cmd->cdw10 = sys_cpu_to_le32(((io_queue->num_entries-1) << 16) |
io_queue->id);
/* 0x3 = interrupts enabled | physically contiguous */
cmd->cdw11 = sys_cpu_to_le32((io_queue->vector << 16) | 0x3);
cmd->dptr.prp1 = sys_cpu_to_le64(io_queue->cpl_bus_addr);
return nvme_cmd_qpair_submit_request(ctrlr->adminq, request);
}
int nvme_ctrlr_cmd_create_io_sq(struct nvme_controller *ctrlr,
struct nvme_cmd_qpair *io_queue,
nvme_cb_fn_t cb_fn, void *cb_arg)
{
struct nvme_request *request;
struct nvme_command *cmd;
request = nvme_allocate_request_null(cb_fn, cb_arg);
if (!request) {
return -ENOMEM;
}
cmd = &request->cmd;
cmd->cdw0.opc = NVME_OPC_CREATE_IO_SQ;
/*
* TODO: create a create io submission queue command data
* structure.
*/
cmd->cdw10 = sys_cpu_to_le32(((io_queue->num_entries - 1) << 16) |
io_queue->id);
/* 0x1 = physically contiguous */
cmd->cdw11 = sys_cpu_to_le32((io_queue->id << 16) | 0x1);
cmd->dptr.prp1 = sys_cpu_to_le64(io_queue->cmd_bus_addr);
return nvme_cmd_qpair_submit_request(ctrlr->adminq, request);
}
int nvme_ctrlr_cmd_delete_io_cq(struct nvme_controller *ctrlr,
struct nvme_cmd_qpair *io_queue,
nvme_cb_fn_t cb_fn, void *cb_arg)
{
struct nvme_request *request;
struct nvme_command *cmd;
request = nvme_allocate_request_null(cb_fn, cb_arg);
if (!request) {
return -ENOMEM;
}
cmd = &request->cmd;
cmd->cdw0.opc = NVME_OPC_DELETE_IO_CQ;
/*
* TODO: create a delete io completion queue command data
* structure.
*/
cmd->cdw10 = sys_cpu_to_le32(io_queue->id);
return nvme_cmd_qpair_submit_request(ctrlr->adminq, request);
}
int nvme_ctrlr_cmd_delete_io_sq(struct nvme_controller *ctrlr,
struct nvme_cmd_qpair *io_queue,
nvme_cb_fn_t cb_fn, void *cb_arg)
{
struct nvme_request *request;
struct nvme_command *cmd;
request = nvme_allocate_request_null(cb_fn, cb_arg);
if (!request) {
return -ENOMEM;
}
cmd = &request->cmd;
cmd->cdw0.opc = NVME_OPC_DELETE_IO_SQ;
/*
* TODO: create a delete io submission queue command data
* structure.
*/
cmd->cdw10 = sys_cpu_to_le32(io_queue->id);
return nvme_cmd_qpair_submit_request(ctrlr->adminq, request);
}
int nvme_ctrlr_cmd_set_feature(struct nvme_controller *ctrlr,
uint8_t feature, uint32_t cdw11,
uint32_t cdw12, uint32_t cdw13,
uint32_t cdw14, uint32_t cdw15,
void *payload, uint32_t payload_size,
nvme_cb_fn_t cb_fn, void *cb_arg)
{
struct nvme_request *request;
struct nvme_command *cmd;
request = nvme_allocate_request_null(cb_fn, cb_arg);
if (!request) {
return -ENOMEM;
}
cmd = &request->cmd;
cmd->cdw0.opc = NVME_OPC_SET_FEATURES;
cmd->cdw10 = sys_cpu_to_le32(feature);
cmd->cdw11 = sys_cpu_to_le32(cdw11);
cmd->cdw12 = sys_cpu_to_le32(cdw12);
cmd->cdw13 = sys_cpu_to_le32(cdw13);
cmd->cdw14 = sys_cpu_to_le32(cdw14);
cmd->cdw15 = sys_cpu_to_le32(cdw15);
return nvme_cmd_qpair_submit_request(ctrlr->adminq, request);
}
int nvme_ctrlr_cmd_get_feature(struct nvme_controller *ctrlr,
uint8_t feature, uint32_t cdw11,
void *payload, uint32_t payload_size,
nvme_cb_fn_t cb_fn, void *cb_arg)
{
struct nvme_request *request;
struct nvme_command *cmd;
request = nvme_allocate_request_null(cb_fn, cb_arg);
if (!request) {
return -ENOMEM;
}
cmd = &request->cmd;
cmd->cdw0.opc = NVME_OPC_GET_FEATURES;
cmd->cdw10 = sys_cpu_to_le32(feature);
cmd->cdw11 = sys_cpu_to_le32(cdw11);
return nvme_cmd_qpair_submit_request(ctrlr->adminq, request);
}
int nvme_ctrlr_cmd_set_num_queues(struct nvme_controller *ctrlr,
uint32_t num_queues,
nvme_cb_fn_t cb_fn, void *cb_arg)
{
uint32_t cdw11;
cdw11 = ((num_queues - 1) << 16) | (num_queues - 1);
return nvme_ctrlr_cmd_set_feature(ctrlr, NVME_FEAT_NUMBER_OF_QUEUES,
cdw11, 0, 0, 0, 0, NULL, 0,
cb_fn, cb_arg);
}