]> git.sur5r.net Git - u-boot/blob - drivers/block/blk_legacy.c
dm: core: Add logging of some common errors
[u-boot] / drivers / block / blk_legacy.c
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 }