10SN/A/*- 2157SN/A * Copyright (C) 2012 Intel Corporation 30SN/A * All rights reserved. 40SN/A * 50SN/A * Redistribution and use in source and binary forms, with or without 60SN/A * modification, are permitted provided that the following conditions 7157SN/A * are met: 80SN/A * 1. Redistributions of source code must retain the above copyright 9157SN/A * notice, this list of conditions and the following disclaimer. 100SN/A * 2. Redistributions in binary form must reproduce the above copyright 110SN/A * notice, this list of conditions and the following disclaimer in the 120SN/A * documentation and/or other materials provided with the distribution. 130SN/A * 140SN/A * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 150SN/A * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 160SN/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 170SN/A * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 180SN/A * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 190SN/A * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 200SN/A * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21157SN/A * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22157SN/A * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23157SN/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 240SN/A * SUCH DAMAGE. 250SN/A */ 260SN/A 270SN/A#include <sys/cdefs.h> 280SN/A__FBSDID("$FreeBSD$"); 290SN/A 300SN/A#include "nvme_private.h" 310SN/A 320SN/Aint 330SN/Anvme_ns_cmd_read(struct nvme_namespace *ns, void *payload, uint64_t lba, 34704Savstepan uint32_t lba_count, nvme_cb_fn_t cb_fn, void *cb_arg) 350SN/A{ 360SN/A struct nvme_request *req; 37704Savstepan struct nvme_command *cmd; 380SN/A 39704Savstepan req = nvme_allocate_request_vaddr(payload, 400SN/A lba_count*nvme_ns_get_sector_size(ns), cb_fn, cb_arg); 41704Savstepan 420SN/A if (req == NULL) 430SN/A return (ENOMEM); 440SN/A cmd = &req->cmd; 450SN/A cmd->opc = NVME_OPC_READ; 460SN/A cmd->nsid = ns->id; 47704Savstepan 48704Savstepan /* TODO: create a read command data structure */ 49704Savstepan *(uint64_t *)&cmd->cdw10 = lba; 500SN/A cmd->cdw12 = lba_count-1; 510SN/A 520SN/A nvme_ctrlr_submit_io_request(ns->ctrlr, req); 530SN/A 540SN/A return (0); 550SN/A} 560SN/A 57704Savstepanint 580SN/Anvme_ns_cmd_read_bio(struct nvme_namespace *ns, struct bio *bp, 590SN/A nvme_cb_fn_t cb_fn, void *cb_arg) 600SN/A{ 610SN/A struct nvme_request *req; 620SN/A struct nvme_command *cmd; 63704Savstepan uint64_t lba; 64704Savstepan uint64_t lba_count; 650SN/A 660SN/A req = nvme_allocate_request_bio(bp, cb_fn, cb_arg); 670SN/A 680SN/A if (req == NULL) 690SN/A return (ENOMEM); 70704Savstepan cmd = &req->cmd; 71704Savstepan cmd->opc = NVME_OPC_READ; 72704Savstepan cmd->nsid = ns->id; 73704Savstepan 74704Savstepan lba = bp->bio_offset / nvme_ns_get_sector_size(ns); 75704Savstepan lba_count = bp->bio_bcount / nvme_ns_get_sector_size(ns); 760SN/A 770SN/A /* TODO: create a read command data structure */ 780SN/A *(uint64_t *)&cmd->cdw10 = lba; 790SN/A cmd->cdw12 = lba_count-1; 800SN/A 810SN/A nvme_ctrlr_submit_io_request(ns->ctrlr, req); 820SN/A 830SN/A return (0); 840SN/A} 850SN/A 860SN/Aint 870SN/Anvme_ns_cmd_write(struct nvme_namespace *ns, void *payload, uint64_t lba, 880SN/A uint32_t lba_count, nvme_cb_fn_t cb_fn, void *cb_arg) 890SN/A{ 900SN/A struct nvme_request *req; 910SN/A struct nvme_command *cmd; 920SN/A 930SN/A req = nvme_allocate_request_vaddr(payload, 94 lba_count*nvme_ns_get_sector_size(ns), cb_fn, cb_arg); 95 96 if (req == NULL) 97 return (ENOMEM); 98 99 cmd = &req->cmd; 100 cmd->opc = NVME_OPC_WRITE; 101 cmd->nsid = ns->id; 102 103 /* TODO: create a write command data structure */ 104 *(uint64_t *)&cmd->cdw10 = lba; 105 cmd->cdw12 = lba_count-1; 106 107 nvme_ctrlr_submit_io_request(ns->ctrlr, req); 108 109 return (0); 110} 111 112int 113nvme_ns_cmd_write_bio(struct nvme_namespace *ns, struct bio *bp, 114 nvme_cb_fn_t cb_fn, void *cb_arg) 115{ 116 struct nvme_request *req; 117 struct nvme_command *cmd; 118 uint64_t lba; 119 uint64_t lba_count; 120 121 req = nvme_allocate_request_bio(bp, cb_fn, cb_arg); 122 123 if (req == NULL) 124 return (ENOMEM); 125 cmd = &req->cmd; 126 cmd->opc = NVME_OPC_WRITE; 127 cmd->nsid = ns->id; 128 129 lba = bp->bio_offset / nvme_ns_get_sector_size(ns); 130 lba_count = bp->bio_bcount / nvme_ns_get_sector_size(ns); 131 132 /* TODO: create a write command data structure */ 133 *(uint64_t *)&cmd->cdw10 = lba; 134 cmd->cdw12 = lba_count-1; 135 136 nvme_ctrlr_submit_io_request(ns->ctrlr, req); 137 138 return (0); 139} 140 141int 142nvme_ns_cmd_deallocate(struct nvme_namespace *ns, void *payload, 143 uint8_t num_ranges, nvme_cb_fn_t cb_fn, void *cb_arg) 144{ 145 struct nvme_request *req; 146 struct nvme_command *cmd; 147 148 req = nvme_allocate_request_vaddr(payload, 149 num_ranges * sizeof(struct nvme_dsm_range), cb_fn, cb_arg); 150 151 if (req == NULL) 152 return (ENOMEM); 153 154 cmd = &req->cmd; 155 cmd->opc = NVME_OPC_DATASET_MANAGEMENT; 156 cmd->nsid = ns->id; 157 158 /* TODO: create a delete command data structure */ 159 cmd->cdw10 = num_ranges - 1; 160 cmd->cdw11 = NVME_DSM_ATTR_DEALLOCATE; 161 162 nvme_ctrlr_submit_io_request(ns->ctrlr, req); 163 164 return (0); 165} 166 167int 168nvme_ns_cmd_flush(struct nvme_namespace *ns, nvme_cb_fn_t cb_fn, void *cb_arg) 169{ 170 struct nvme_request *req; 171 struct nvme_command *cmd; 172 173 req = nvme_allocate_request_null(cb_fn, cb_arg); 174 175 if (req == NULL) 176 return (ENOMEM); 177 178 cmd = &req->cmd; 179 cmd->opc = NVME_OPC_FLUSH; 180 cmd->nsid = ns->id; 181 182 nvme_ctrlr_submit_io_request(ns->ctrlr, req); 183 184 return (0); 185} 186