ide: Avoid preprocessor for CONFIG_LBA48
[platform/kernel/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 uclass_id)
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 (uclass_id == entry->uclass_id)
20                         return entry;
21         }
22
23         /* Not found */
24         return NULL;
25 }
26
27 static struct blk_driver *blk_driver_lookup_typename(const char *uclass_idname)
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(uclass_idname, entry->uclass_idname))
35                         return entry;
36         }
37
38         /* Not found */
39         return NULL;
40 }
41
42 const char *blk_get_uclass_name(enum uclass_id uclass_id)
43 {
44         struct blk_driver *drv = blk_driver_lookup_type(uclass_id);
45
46         return drv ? drv->uclass_idname : 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 int blk_list_part(enum uclass_id uclass_id)
74 {
75         struct blk_driver *drv;
76         struct blk_desc *desc;
77         int devnum, ok;
78         bool first = true;
79
80         drv = blk_driver_lookup_type(uclass_id);
81         if (!drv)
82                 return -ENOSYS;
83         for (ok = 0, devnum = 0; devnum < drv->max_devs; ++devnum) {
84                 if (get_desc(drv, devnum, &desc))
85                         continue;
86                 if (desc->part_type != PART_TYPE_UNKNOWN) {
87                         ++ok;
88                         if (!first)
89                                 putc('\n');
90                         part_print(desc);
91                         first = false;
92                 }
93         }
94         if (!ok)
95                 return -ENODEV;
96
97         return 0;
98 }
99
100 int blk_print_part_devnum(enum uclass_id uclass_id, int devnum)
101 {
102         struct blk_driver *drv = blk_driver_lookup_type(uclass_id);
103         struct blk_desc *desc;
104         int ret;
105
106         if (!drv)
107                 return -ENOSYS;
108         ret = get_desc(drv, devnum, &desc);
109         if (ret)
110                 return ret;
111         if (desc->type == DEV_TYPE_UNKNOWN)
112                 return -ENOENT;
113         part_print(desc);
114
115         return 0;
116 }
117
118 void blk_list_devices(enum uclass_id uclass_id)
119 {
120         struct blk_driver *drv = blk_driver_lookup_type(uclass_id);
121         struct blk_desc *desc;
122         int i;
123
124         if (!drv)
125                 return;
126         for (i = 0; i < drv->max_devs; ++i) {
127                 if (get_desc(drv, i, &desc))
128                         continue;
129                 if (desc->type == DEV_TYPE_UNKNOWN)
130                         continue;  /* list only known devices */
131                 printf("Device %d: ", i);
132                 dev_print(desc);
133         }
134 }
135
136 int blk_print_device_num(enum uclass_id uclass_id, int devnum)
137 {
138         struct blk_driver *drv = blk_driver_lookup_type(uclass_id);
139         struct blk_desc *desc;
140         int ret;
141
142         if (!drv)
143                 return -ENOSYS;
144         ret = get_desc(drv, devnum, &desc);
145         if (ret)
146                 return ret;
147         printf("\n%s device %d: ", drv->uclass_idname, devnum);
148         dev_print(desc);
149
150         return 0;
151 }
152
153 int blk_show_device(enum uclass_id uclass_id, int devnum)
154 {
155         struct blk_driver *drv = blk_driver_lookup_type(uclass_id);
156         struct blk_desc *desc;
157         int ret;
158
159         if (!drv)
160                 return -ENOSYS;
161         printf("\nDevice %d: ", devnum);
162         if (devnum >= drv->max_devs) {
163                 puts("unknown device\n");
164                 return -ENODEV;
165         }
166         ret = get_desc(drv, devnum, &desc);
167         if (ret)
168                 return ret;
169         dev_print(desc);
170
171         if (desc->type == DEV_TYPE_UNKNOWN)
172                 return -ENOENT;
173
174         return 0;
175 }
176
177 struct blk_desc *blk_get_devnum_by_uclass_id(enum uclass_id uclass_id, int devnum)
178 {
179         struct blk_driver *drv = blk_driver_lookup_type(uclass_id);
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->uclass_id);
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_uclass_idname(const char *uclass_idname, int devnum)
204 {
205         struct blk_driver *drv = blk_driver_lookup_typename(uclass_idname);
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 uclass_id uclass_id, int devnum, lbaint_t start,
218                       lbaint_t blkcnt, void *buffer)
219 {
220         struct blk_driver *drv = blk_driver_lookup_type(uclass_id);
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 uclass_id uclass_id, int devnum, lbaint_t start,
238                        lbaint_t blkcnt, const void *buffer)
239 {
240         struct blk_driver *drv = blk_driver_lookup_type(uclass_id);
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 uclass_id uclass_id, int devnum, int hwpart)
253 {
254         struct blk_driver *drv = blk_driver_lookup_type(uclass_id);
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 }