nvme_ns_cmd.c revision 253474
1/*-
2 * Copyright (C) 2012 Intel Corporation
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/dev/nvme/nvme_ns_cmd.c 253474 2013-07-19 21:33:24Z jimharris $");
29
30#include "nvme_private.h"
31
32int
33nvme_ns_cmd_read(struct nvme_namespace *ns, void *payload, uint64_t lba,
34    uint32_t lba_count, nvme_cb_fn_t cb_fn, void *cb_arg)
35{
36	struct nvme_request	*req;
37	struct nvme_command	*cmd;
38
39	req = nvme_allocate_request_vaddr(payload,
40	    lba_count*nvme_ns_get_sector_size(ns), cb_fn, cb_arg);
41
42	if (req == NULL)
43		return (ENOMEM);
44	cmd = &req->cmd;
45	cmd->opc = NVME_OPC_READ;
46	cmd->nsid = ns->id;
47
48	/* TODO: create a read command data structure */
49	*(uint64_t *)&cmd->cdw10 = lba;
50	cmd->cdw12 = lba_count-1;
51
52	nvme_ctrlr_submit_io_request(ns->ctrlr, req);
53
54	return (0);
55}
56
57int
58nvme_ns_cmd_read_bio(struct nvme_namespace *ns, struct bio *bp,
59    nvme_cb_fn_t cb_fn, void *cb_arg)
60{
61	struct nvme_request	*req;
62	struct nvme_command	*cmd;
63	uint64_t		lba;
64	uint64_t		lba_count;
65
66	req = nvme_allocate_request_bio(bp, cb_fn, cb_arg);
67
68	if (req == NULL)
69		return (ENOMEM);
70	cmd = &req->cmd;
71	cmd->opc = NVME_OPC_READ;
72	cmd->nsid = ns->id;
73
74	lba = bp->bio_offset / nvme_ns_get_sector_size(ns);
75	lba_count = bp->bio_bcount / nvme_ns_get_sector_size(ns);
76
77	/* TODO: create a read command data structure */
78	*(uint64_t *)&cmd->cdw10 = lba;
79	cmd->cdw12 = lba_count-1;
80
81	nvme_ctrlr_submit_io_request(ns->ctrlr, req);
82
83	return (0);
84}
85
86int
87nvme_ns_cmd_write(struct nvme_namespace *ns, void *payload, uint64_t lba,
88    uint32_t lba_count, nvme_cb_fn_t cb_fn, void *cb_arg)
89{
90	struct nvme_request	*req;
91	struct nvme_command	*cmd;
92
93	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