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