xref: /openbmc/u-boot/drivers/block/blk_legacy.c (revision 3ebd892f)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2016 Google, Inc
4  * Written by Simon Glass <sjg@chromium.org>
5  */
6 
7 #include <common.h>
8 #include <linux/err.h>
9 
10 struct blk_driver *blk_driver_lookup_type(int if_type)
11 {
12 	struct blk_driver *drv = ll_entry_start(struct blk_driver, blk_driver);
13 	const int n_ents = ll_entry_count(struct blk_driver, blk_driver);
14 	struct blk_driver *entry;
15 
16 	for (entry = drv; entry != drv + n_ents; entry++) {
17 		if (if_type == entry->if_type)
18 			return entry;
19 	}
20 
21 	/* Not found */
22 	return NULL;
23 }
24 
25 static struct blk_driver *blk_driver_lookup_typename(const char *if_typename)
26 {
27 	struct blk_driver *drv = ll_entry_start(struct blk_driver, blk_driver);
28 	const int n_ents = ll_entry_count(struct blk_driver, blk_driver);
29 	struct blk_driver *entry;
30 
31 	for (entry = drv; entry != drv + n_ents; entry++) {
32 		if (!strcmp(if_typename, entry->if_typename))
33 			return entry;
34 	}
35 
36 	/* Not found */
37 	return NULL;
38 }
39 
40 const char *blk_get_if_type_name(enum if_type if_type)
41 {
42 	struct blk_driver *drv = blk_driver_lookup_type(if_type);
43 
44 	return drv ? drv->if_typename : NULL;
45 }
46 
47 /**
48  * get_desc() - Get the block device descriptor for the given device number
49  *
50  * @drv:	Legacy block driver
51  * @devnum:	Device number (0 = first)
52  * @descp:	Returns block device descriptor on success
53  * @return 0 on success, -ENODEV if there is no such device, -ENOSYS if the
54  * driver does not provide a way to find a device, or other -ve on other
55  * error.
56  */
57 static int get_desc(struct blk_driver *drv, int devnum, struct blk_desc **descp)
58 {
59 	if (drv->desc) {
60 		if (devnum < 0 || devnum >= drv->max_devs)
61 			return -ENODEV;
62 		*descp = &drv->desc[devnum];
63 		return 0;
64 	}
65 	if (!drv->get_dev)
66 		return -ENOSYS;
67 
68 	return drv->get_dev(devnum, descp);
69 }
70 
71 #ifdef CONFIG_HAVE_BLOCK_DEVICE
72 int blk_list_part(enum if_type if_type)
73 {
74 	struct blk_driver *drv;
75 	struct blk_desc *desc;
76 	int devnum, ok;
77 	bool first = true;
78 
79 	drv = blk_driver_lookup_type(if_type);
80 	if (!drv)
81 		return -ENOSYS;
82 	for (ok = 0, devnum = 0; devnum < drv->max_devs; ++devnum) {
83 		if (get_desc(drv, devnum, &desc))
84 			continue;
85 		if (desc->part_type != PART_TYPE_UNKNOWN) {
86 			++ok;
87 			if (!first)
88 				putc('\n');
89 			part_print(desc);
90 			first = false;
91 		}
92 	}
93 	if (!ok)
94 		return -ENODEV;
95 
96 	return 0;
97 }
98 
99 int blk_print_part_devnum(enum if_type if_type, int devnum)
100 {
101 	struct blk_driver *drv = blk_driver_lookup_type(if_type);
102 	struct blk_desc *desc;
103 	int ret;
104 
105 	if (!drv)
106 		return -ENOSYS;
107 	ret = get_desc(drv, devnum, &desc);
108 	if (ret)
109 		return ret;
110 	if (desc->type == DEV_TYPE_UNKNOWN)
111 		return -ENOENT;
112 	part_print(desc);
113 
114 	return 0;
115 }
116 
117 void blk_list_devices(enum if_type if_type)
118 {
119 	struct blk_driver *drv = blk_driver_lookup_type(if_type);
120 	struct blk_desc *desc;
121 	int i;
122 
123 	if (!drv)
124 		return;
125 	for (i = 0; i < drv->max_devs; ++i) {
126 		if (get_desc(drv, i, &desc))
127 			continue;
128 		if (desc->type == DEV_TYPE_UNKNOWN)
129 			continue;  /* list only known devices */
130 		printf("Device %d: ", i);
131 		dev_print(desc);
132 	}
133 }
134 
135 int blk_print_device_num(enum if_type if_type, int devnum)
136 {
137 	struct blk_driver *drv = blk_driver_lookup_type(if_type);
138 	struct blk_desc *desc;
139 	int ret;
140 
141 	if (!drv)
142 		return -ENOSYS;
143 	ret = get_desc(drv, devnum, &desc);
144 	if (ret)
145 		return ret;
146 	printf("\n%s device %d: ", drv->if_typename, devnum);
147 	dev_print(desc);
148 
149 	return 0;
150 }
151 
152 int blk_show_device(enum if_type if_type, int devnum)
153 {
154 	struct blk_driver *drv = blk_driver_lookup_type(if_type);
155 	struct blk_desc *desc;
156 	int ret;
157 
158 	if (!drv)
159 		return -ENOSYS;
160 	printf("\nDevice %d: ", devnum);
161 	if (devnum >= drv->max_devs) {
162 		puts("unknown device\n");
163 		return -ENODEV;
164 	}
165 	ret = get_desc(drv, devnum, &desc);
166 	if (ret)
167 		return ret;
168 	dev_print(desc);
169 
170 	if (desc->type == DEV_TYPE_UNKNOWN)
171 		return -ENOENT;
172 
173 	return 0;
174 }
175 #endif /* CONFIG_HAVE_BLOCK_DEVICE */
176 
177 struct blk_desc *blk_get_devnum_by_type(enum if_type if_type, int devnum)
178 {
179 	struct blk_driver *drv = blk_driver_lookup_type(if_type);
180 	struct blk_desc *desc;
181 
182 	if (!drv)
183 		return NULL;
184 
185 	if (get_desc(drv, devnum, &desc))
186 		return NULL;
187 
188 	return desc;
189 }
190 
191 int blk_dselect_hwpart(struct blk_desc *desc, int hwpart)
192 {
193 	struct blk_driver *drv = blk_driver_lookup_type(desc->if_type);
194 
195 	if (!drv)
196 		return -ENOSYS;
197 	if (drv->select_hwpart)
198 		return drv->select_hwpart(desc, hwpart);
199 
200 	return 0;
201 }
202 
203 struct blk_desc *blk_get_devnum_by_typename(const char *if_typename, int devnum)
204 {
205 	struct blk_driver *drv = blk_driver_lookup_typename(if_typename);
206 	struct blk_desc *desc;
207 
208 	if (!drv)
209 		return NULL;
210 
211 	if (get_desc(drv, devnum, &desc))
212 		return NULL;
213 
214 	return desc;
215 }
216 
217 ulong blk_read_devnum(enum if_type if_type, int devnum, lbaint_t start,
218 		      lbaint_t blkcnt, void *buffer)
219 {
220 	struct blk_driver *drv = blk_driver_lookup_type(if_type);
221 	struct blk_desc *desc;
222 	ulong n;
223 	int ret;
224 
225 	if (!drv)
226 		return -ENOSYS;
227 	ret = get_desc(drv, devnum, &desc);
228 	if (ret)
229 		return ret;
230 	n = desc->block_read(desc, start, blkcnt, buffer);
231 	if (IS_ERR_VALUE(n))
232 		return n;
233 
234 	return n;
235 }
236 
237 ulong blk_write_devnum(enum if_type if_type, int devnum, lbaint_t start,
238 		       lbaint_t blkcnt, const void *buffer)
239 {
240 	struct blk_driver *drv = blk_driver_lookup_type(if_type);
241 	struct blk_desc *desc;
242 	int ret;
243 
244 	if (!drv)
245 		return -ENOSYS;
246 	ret = get_desc(drv, devnum, &desc);
247 	if (ret)
248 		return ret;
249 	return desc->block_write(desc, start, blkcnt, buffer);
250 }
251 
252 int blk_select_hwpart_devnum(enum if_type if_type, int devnum, int hwpart)
253 {
254 	struct blk_driver *drv = blk_driver_lookup_type(if_type);
255 	struct blk_desc *desc;
256 	int ret;
257 
258 	if (!drv)
259 		return -ENOSYS;
260 	ret = get_desc(drv, devnum, &desc);
261 	if (ret)
262 		return ret;
263 	return drv->select_hwpart(desc, hwpart);
264 }
265