224 lines
5.6 KiB
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);
|
|
}
|