1 /*
2  * Copyright (c) 2022 Intel Corporation
3  * SPDX-License-Identifier: Apache-2.0
4  *
5  * Derived from FreeBSD original driver made by Jim Harris
6  * with contributions from Alexander Motin and Wojciech Macek
7  */
8 
9 #ifndef ZEPHYR_DRIVERS_DISK_NVME_NVME_NAMESPACE_H_
10 #define ZEPHYR_DRIVERS_DISK_NVME_NVME_NAMESPACE_H_
11 
12 #include <zephyr/drivers/disk.h>
13 
14 struct nvme_namespace_data {
15 	/** namespace size */
16 	uint64_t		nsze;
17 
18 	/** namespace capacity */
19 	uint64_t		ncap;
20 
21 	/** namespace utilization */
22 	uint64_t		nuse;
23 
24 	/** namespace features */
25 	uint8_t			nsfeat;
26 
27 	/** number of lba formats */
28 	uint8_t			nlbaf;
29 
30 	/** formatted lba size */
31 	uint8_t			flbas;
32 
33 	/** metadata capabilities */
34 	uint8_t			mc;
35 
36 	/** end-to-end data protection capabilities */
37 	uint8_t			dpc;
38 
39 	/** end-to-end data protection type settings */
40 	uint8_t			dps;
41 
42 	/** Namespace Multi-path I/O and Namespace Sharing Capabilities */
43 	uint8_t			nmic;
44 
45 	/** Reservation Capabilities */
46 	uint8_t			rescap;
47 
48 	/** Format Progress Indicator */
49 	uint8_t			fpi;
50 
51 	/** Deallocate Logical Block Features */
52 	uint8_t			dlfeat;
53 
54 	/** Namespace Atomic Write Unit Normal  */
55 	uint16_t		nawun;
56 
57 	/** Namespace Atomic Write Unit Power Fail */
58 	uint16_t		nawupf;
59 
60 	/** Namespace Atomic Compare & Write Unit */
61 	uint16_t		nacwu;
62 
63 	/** Namespace Atomic Boundary Size Normal */
64 	uint16_t		nabsn;
65 
66 	/** Namespace Atomic Boundary Offset */
67 	uint16_t		nabo;
68 
69 	/** Namespace Atomic Boundary Size Power Fail */
70 	uint16_t		nabspf;
71 
72 	/** Namespace Optimal IO Boundary */
73 	uint16_t		noiob;
74 
75 	/** NVM Capacity */
76 	uint8_t			nvmcap[16];
77 
78 	/** Namespace Preferred Write Granularity  */
79 	uint16_t		npwg;
80 
81 	/** Namespace Preferred Write Alignment */
82 	uint16_t		npwa;
83 
84 	/** Namespace Preferred Deallocate Granularity */
85 	uint16_t		npdg;
86 
87 	/** Namespace Preferred Deallocate Alignment */
88 	uint16_t		npda;
89 
90 	/** Namespace Optimal Write Size */
91 	uint16_t		nows;
92 
93 	/* bytes 74-91: Reserved */
94 	uint8_t			reserved5[18];
95 
96 	/** ANA Group Identifier */
97 	uint32_t		anagrpid;
98 
99 	/* bytes 96-98: Reserved */
100 	uint8_t			reserved6[3];
101 
102 	/** Namespace Attributes */
103 	uint8_t			nsattr;
104 
105 	/** NVM Set Identifier */
106 	uint16_t		nvmsetid;
107 
108 	/** Endurance Group Identifier */
109 	uint16_t		endgid;
110 
111 	/** Namespace Globally Unique Identifier */
112 	uint8_t			nguid[16];
113 
114 	/** IEEE Extended Unique Identifier */
115 	uint8_t			eui64[8];
116 
117 	/** lba format support */
118 	uint32_t		lbaf[16];
119 
120 	uint8_t			reserved7[192];
121 
122 	uint8_t			vendor_specific[3712];
123 } __packed __aligned(4);
124 
125 static inline
nvme_namespace_data_swapbytes(struct nvme_namespace_data * s)126 void nvme_namespace_data_swapbytes(struct nvme_namespace_data *s)
127 {
128 #if _BYTE_ORDER != _LITTLE_ENDIAN
129 	int i;
130 
131 	s->nsze = sys_le64_to_cpu(s->nsze);
132 	s->ncap = sys_le64_to_cpu(s->ncap);
133 	s->nuse = sys_le64_to_cpu(s->nuse);
134 	s->nawun = sys_le16_to_cpu(s->nawun);
135 	s->nawupf = sys_le16_to_cpu(s->nawupf);
136 	s->nacwu = sys_le16_to_cpu(s->nacwu);
137 	s->nabsn = sys_le16_to_cpu(s->nabsn);
138 	s->nabo = sys_le16_to_cpu(s->nabo);
139 	s->nabspf = sys_le16_to_cpu(s->nabspf);
140 	s->noiob = sys_le16_to_cpu(s->noiob);
141 	s->npwg = sys_le16_to_cpu(s->npwg);
142 	s->npwa = sys_le16_to_cpu(s->npwa);
143 	s->npdg = sys_le16_to_cpu(s->npdg);
144 	s->npda = sys_le16_to_cpu(s->npda);
145 	s->nows = sys_le16_to_cpu(s->nows);
146 	s->anagrpid = sys_le32_to_cpu(s->anagrpid);
147 	s->nvmsetid = sys_le16_to_cpu(s->nvmsetid);
148 	s->endgid = sys_le16_to_cpu(s->endgid);
149 	for (i = 0; i < 16; i++) {
150 		s->lbaf[i] = sys_le32_to_cpu(s->lbaf[i]);
151 	}
152 #else
153 	ARG_UNUSED(s);
154 #endif
155 }
156 
157 /* Readable identifier: nvme%%n%%\0 */
158 #define NVME_NAMESPACE_NAME_MAX_LENGTH 10
159 
160 struct nvme_namespace {
161 	struct nvme_controller *ctrlr;
162 	struct nvme_namespace_data data;
163 	struct disk_info disk;
164 	uint32_t id;
165 	uint32_t flags;
166 	uint32_t boundary;
167 	char name[NVME_NAMESPACE_NAME_MAX_LENGTH];
168 };
169 
170 enum nvme_namespace_flags {
171 	NVME_NS_DEALLOCATE_SUPPORTED	= 0x1,
172 	NVME_NS_FLUSH_SUPPORTED		= 0x2,
173 };
174 
175 uint32_t nvme_namespace_get_sector_size(struct nvme_namespace *ns);
176 
177 uint64_t nvme_namespace_get_num_sectors(struct nvme_namespace *ns);
178 
179 uint64_t nvme_namespace_get_size(struct nvme_namespace *ns);
180 
181 uint32_t nvme_namespace_get_flags(struct nvme_namespace *ns);
182 
183 const char *nvme_namespace_get_serial_number(struct nvme_namespace *ns);
184 
185 const char *nvme_namespace_get_model_number(struct nvme_namespace *ns);
186 
187 const struct nvme_namespace_data *
188 nvme_namespace_get_data(struct nvme_namespace *ns);
189 
190 uint32_t nvme_namespace_get_stripesize(struct nvme_namespace *ns);
191 
192 int nvme_namespace_construct(struct nvme_namespace *ns,
193 			     uint32_t id,
194 			     struct nvme_controller *ctrlr);
195 
196 int nvme_namespace_disk_setup(struct nvme_namespace *ns,
197 			      struct disk_info *disk);
198 
199 #endif /* ZEPHYR_DRIVERS_DISK_NVME_NVME_NAMESPACE_H_ */
200