/*
 * 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);
}
