Blame view

api/api_storage.c 8.14 KB
83d290c56   Tom Rini   SPDX: Convert all...
1
  // SPDX-License-Identifier: GPL-2.0+
500856eb1   Rafal Jaworowski   API for external ...
2
  /*
f2302d443   Stefan Roese   Fix merge problems
3
   * (C) Copyright 2007-2008 Semihalf
500856eb1   Rafal Jaworowski   API for external ...
4
5
   *
   * Written by: Rafal Jaworowski <raj@semihalf.com>
500856eb1   Rafal Jaworowski   API for external ...
6
7
8
   */
  
  #include <config.h>
500856eb1   Rafal Jaworowski   API for external ...
9
10
  #include <common.h>
  #include <api_public.h>
3d0ea3110   Matthias Fuchs   api: Fix building...
11
12
13
  #if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE)
  #include <usb.h>
  #endif
500856eb1   Rafal Jaworowski   API for external ...
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  #define DEBUG
  #undef DEBUG
  
  #ifdef DEBUG
  #define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt, ##args); } while (0)
  #else
  #define debugf(fmt, args...)
  #endif
  
  #define errf(fmt, args...) do { printf("ERROR @ %s(): ", __func__); printf(fmt, ##args); } while (0)
  
  
  #define ENUM_IDE	0
  #define ENUM_USB	1
  #define ENUM_SCSI	2
  #define ENUM_MMC	3
f2302d443   Stefan Roese   Fix merge problems
30
31
  #define ENUM_SATA	4
  #define ENUM_MAX	5
500856eb1   Rafal Jaworowski   API for external ...
32
33
34
35
36
  
  struct stor_spec {
  	int		max_dev;
  	int		enum_started;
  	int		enum_ended;
e3d7675ac   Walt Feasel   Cosmetic api: api...
37
  	int		type;	/* "external" type: DT_STOR_{IDE,USB,etc} */
f2302d443   Stefan Roese   Fix merge problems
38
  	char		*name;
500856eb1   Rafal Jaworowski   API for external ...
39
  };
5d81c6df3   Emmanuel Vadot   api: storage: Avo...
40
  static struct stor_spec specs[ENUM_MAX] = { { 0, 0, 0, 0, NULL }, };
500856eb1   Rafal Jaworowski   API for external ...
41

6d7a57076   Emmanuel Vadot   api: Define a def...
42
43
44
  #ifndef CONFIG_SYS_MMC_MAX_DEVICE
  #define CONFIG_SYS_MMC_MAX_DEVICE	1
  #endif
500856eb1   Rafal Jaworowski   API for external ...
45
46
47
  
  void dev_stor_init(void)
  {
fc843a02a   Simon Glass   Kconfig: Add a CO...
48
  #if defined(CONFIG_IDE)
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
49
  	specs[ENUM_IDE].max_dev = CONFIG_SYS_IDE_MAXDEVICE;
500856eb1   Rafal Jaworowski   API for external ...
50
51
52
53
54
  	specs[ENUM_IDE].enum_started = 0;
  	specs[ENUM_IDE].enum_ended = 0;
  	specs[ENUM_IDE].type = DEV_TYP_STOR | DT_STOR_IDE;
  	specs[ENUM_IDE].name = "ide";
  #endif
f2302d443   Stefan Roese   Fix merge problems
55
  #if defined(CONFIG_CMD_MMC)
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
56
  	specs[ENUM_MMC].max_dev = CONFIG_SYS_MMC_MAX_DEVICE;
f2302d443   Stefan Roese   Fix merge problems
57
58
59
60
61
  	specs[ENUM_MMC].enum_started = 0;
  	specs[ENUM_MMC].enum_ended = 0;
  	specs[ENUM_MMC].type = DEV_TYP_STOR | DT_STOR_MMC;
  	specs[ENUM_MMC].name = "mmc";
  #endif
10e40d54b   Simon Glass   Kconfig: Add CONF...
62
  #if defined(CONFIG_SATA)
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
63
  	specs[ENUM_SATA].max_dev = CONFIG_SYS_SATA_MAX_DEVICE;
f2302d443   Stefan Roese   Fix merge problems
64
65
66
67
  	specs[ENUM_SATA].enum_started = 0;
  	specs[ENUM_SATA].enum_ended = 0;
  	specs[ENUM_SATA].type = DEV_TYP_STOR | DT_STOR_SATA;
  	specs[ENUM_SATA].name = "sata";
500856eb1   Rafal Jaworowski   API for external ...
68
  #endif
c649e3c91   Simon Glass   dm: scsi: Rename ...
69
  #if defined(CONFIG_SCSI)
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
70
  	specs[ENUM_SCSI].max_dev = CONFIG_SYS_SCSI_MAX_DEVICE;
500856eb1   Rafal Jaworowski   API for external ...
71
72
73
74
75
  	specs[ENUM_SCSI].enum_started = 0;
  	specs[ENUM_SCSI].enum_ended = 0;
  	specs[ENUM_SCSI].type = DEV_TYP_STOR | DT_STOR_SCSI;
  	specs[ENUM_SCSI].name = "scsi";
  #endif
f2302d443   Stefan Roese   Fix merge problems
76
77
78
79
80
81
82
  #if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE)
  	specs[ENUM_USB].max_dev = USB_MAX_STOR_DEV;
  	specs[ENUM_USB].enum_started = 0;
  	specs[ENUM_USB].enum_ended = 0;
  	specs[ENUM_USB].type = DEV_TYP_STOR | DT_STOR_USB;
  	specs[ENUM_USB].name = "usb";
  #endif
500856eb1   Rafal Jaworowski   API for external ...
83
84
85
86
87
88
89
  }
  
  /*
   * Finds next available device in the storage group
   *
   * type:	storage group type - ENUM_IDE, ENUM_SCSI etc.
   *
500856eb1   Rafal Jaworowski   API for external ...
90
91
92
93
94
   * more:	returns 0/1 depending if there are more devices in this group
   *		available (for future iterations)
   *
   * returns:	0/1 depending if device found in this iteration
   */
d3e8f6302   Emmanuel Vadot   api: storage: Tes...
95
  static int dev_stor_get(int type, int *more, struct device_info *di)
500856eb1   Rafal Jaworowski   API for external ...
96
  {
4101f6879   Simon Glass   dm: Drop the bloc...
97
  	struct blk_desc *dd;
d3e8f6302   Emmanuel Vadot   api: storage: Tes...
98
  	int found = 0;
8efae021d   Cristian Ciocaltea   api: storage: Fix...
99
  	int found_last = 0;
d3e8f6302   Emmanuel Vadot   api: storage: Tes...
100
  	int i = 0;
500856eb1   Rafal Jaworowski   API for external ...
101

5d81c6df3   Emmanuel Vadot   api: storage: Avo...
102
103
104
  	/* Wasn't configured for this type, return 0 directly */
  	if (specs[type].name == NULL)
  		return 0;
d3e8f6302   Emmanuel Vadot   api: storage: Tes...
105
106
107
  	if (di->cookie != NULL) {
  		/* Find the last device we've returned  */
  		for (i = 0; i < specs[type].max_dev; i++) {
db1d9e78e   Simon Glass   dm: blk: Rename g...
108
109
  			if (di->cookie ==
  			    (void *)blk_get_dev(specs[type].name, i)) {
d3e8f6302   Emmanuel Vadot   api: storage: Tes...
110
  				i += 1;
8efae021d   Cristian Ciocaltea   api: storage: Fix...
111
  				found_last = 1;
500856eb1   Rafal Jaworowski   API for external ...
112
113
  				break;
  			}
d3e8f6302   Emmanuel Vadot   api: storage: Tes...
114
  		}
8efae021d   Cristian Ciocaltea   api: storage: Fix...
115
116
117
  
  		if (!found_last)
  			i = 0;
500856eb1   Rafal Jaworowski   API for external ...
118
  	}
d3e8f6302   Emmanuel Vadot   api: storage: Tes...
119
120
  	for (; i < specs[type].max_dev; i++) {
  		di->cookie = (void *)blk_get_dev(specs[type].name, i);
500856eb1   Rafal Jaworowski   API for external ...
121
122
  
  		if (di->cookie != NULL) {
d3e8f6302   Emmanuel Vadot   api: storage: Tes...
123
124
  			found = 1;
  			break;
500856eb1   Rafal Jaworowski   API for external ...
125
  		}
d3e8f6302   Emmanuel Vadot   api: storage: Tes...
126
127
128
129
130
131
  	}
  
  	if (i == specs[type].max_dev)
  		*more = 0;
  	else
  		*more = 1;
500856eb1   Rafal Jaworowski   API for external ...
132

d3e8f6302   Emmanuel Vadot   api: storage: Tes...
133
134
135
136
137
138
139
140
141
142
143
144
  	if (found) {
  		di->type = specs[type].type;
  
  		dd = (struct blk_desc *)di->cookie;
  		if (dd->type == DEV_TYPE_UNKNOWN) {
  			debugf("device instance exists, but is not active..");
  			found = 0;
  		} else {
  			di->di_stor.block_count = dd->lba;
  			di->di_stor.block_size = dd->blksz;
  		}
  	} else {
500856eb1   Rafal Jaworowski   API for external ...
145
  		di->cookie = NULL;
d3e8f6302   Emmanuel Vadot   api: storage: Tes...
146
  	}
500856eb1   Rafal Jaworowski   API for external ...
147
148
149
  
  	return found;
  }
c9db75a06   Walt Feasel   Cosmetic api: api...
150
  /* returns: ENUM_IDE, ENUM_USB etc. based on struct blk_desc */
4101f6879   Simon Glass   dm: Drop the bloc...
151
  static int dev_stor_type(struct blk_desc *dd)
500856eb1   Rafal Jaworowski   API for external ...
152
153
154
155
156
  {
  	int i, j;
  
  	for (i = ENUM_IDE; i < ENUM_MAX; i++)
  		for (j = 0; j < specs[i].max_dev; j++)
db1d9e78e   Simon Glass   dm: blk: Rename g...
157
  			if (dd == blk_get_dev(specs[i].name, j))
500856eb1   Rafal Jaworowski   API for external ...
158
159
160
161
  				return i;
  
  	return ENUM_MAX;
  }
c9db75a06   Walt Feasel   Cosmetic api: api...
162
  /* returns: 0/1 whether cookie points to some device in this group */
500856eb1   Rafal Jaworowski   API for external ...
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
  static int dev_is_stor(int type, struct device_info *di)
  {
  	return (dev_stor_type(di->cookie) == type) ? 1 : 0;
  }
  
  
  static int dev_enum_stor(int type, struct device_info *di)
  {
  	int found = 0, more = 0;
  
  	debugf("called, type %d
  ", type);
  
  	/*
  	 * Formulae for enumerating storage devices:
  	 * 1. if cookie (hint from previous enum call) is NULL we start again
  	 *    with enumeration, so return the first available device, done.
  	 *
  	 * 2. if cookie is not NULL, check if it identifies some device in
  	 *    this group:
  	 *
  	 * 2a. if cookie is a storage device from our group (IDE, USB etc.),
  	 *     return next available (if exists) in this group
  	 *
  	 * 2b. if it isn't device from our group, check if such devices were
  	 *     ever enumerated before:
  	 *     - if not, return the first available device from this group
  	 *     - else return 0
  	 */
  
  	if (di->cookie == NULL) {
500856eb1   Rafal Jaworowski   API for external ...
194
195
196
197
198
199
200
  		debugf("group%d - enum restart
  ", type);
  
  		/*
  		 * 1. Enumeration (re-)started: take the first available
  		 * device, if exists
  		 */
d3e8f6302   Emmanuel Vadot   api: storage: Tes...
201
  		found = dev_stor_get(type, &more, di);
500856eb1   Rafal Jaworowski   API for external ...
202
203
204
  		specs[type].enum_started = 1;
  
  	} else if (dev_is_stor(type, di)) {
500856eb1   Rafal Jaworowski   API for external ...
205
206
207
208
209
210
211
212
213
214
  		debugf("group%d - enum continued for the next device
  ", type);
  
  		if (specs[type].enum_ended) {
  			debugf("group%d - nothing more to enum!
  ", type);
  			return 0;
  		}
  
  		/* 2a. Attempt to take a next available device in the group */
d3e8f6302   Emmanuel Vadot   api: storage: Tes...
215
  		found = dev_stor_get(type, &more, di);
500856eb1   Rafal Jaworowski   API for external ...
216
217
  
  	} else {
500856eb1   Rafal Jaworowski   API for external ...
218
219
220
221
222
223
224
225
226
227
228
229
230
  		if (specs[type].enum_ended) {
  			debugf("group %d - already enumerated, skipping
  ", type);
  			return 0;
  		}
  
  		debugf("group%d - first time enum
  ", type);
  
  		if (specs[type].enum_started == 0) {
  			/*
  			 * 2b.  If enumerating devices in this group did not
  			 * happen before, it means the cookie pointed to a
83f9ecbe2   Walt Feasel   Cosmetic api: api...
231
  			 * device from some other group (another storage
500856eb1   Rafal Jaworowski   API for external ...
232
233
234
235
236
237
238
239
240
  			 * group, or network); in this case try to take the
  			 * first available device from our group
  			 */
  			specs[type].enum_started = 1;
  
  			/*
  			 * Attempt to take the first device in this group:
  			 *'first element' flag is set
  			 */
d3e8f6302   Emmanuel Vadot   api: storage: Tes...
241
  			found = dev_stor_get(type, &more, di);
500856eb1   Rafal Jaworowski   API for external ...
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
  
  		} else {
  			errf("group%d - out of order iteration
  ", type);
  			found = 0;
  			more = 0;
  		}
  	}
  
  	/*
  	 * If there are no more devices in this group, consider its
  	 * enumeration finished
  	 */
  	specs[type].enum_ended = (!more) ? 1 : 0;
  
  	if (found)
  		debugf("device found, returning cookie 0x%08x
  ",
e5fbf2a73   Walt Feasel   Cosmetic api: api...
260
  		       (u_int32_t)di->cookie);
500856eb1   Rafal Jaworowski   API for external ...
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
  	else
  		debugf("no device found
  ");
  
  	return found;
  }
  
  void dev_enum_reset(void)
  {
  	int i;
  
  	for (i = 0; i < ENUM_MAX; i ++) {
  		specs[i].enum_started = 0;
  		specs[i].enum_ended = 0;
  	}
  }
  
  int dev_enum_storage(struct device_info *di)
  {
  	int i;
c9db75a06   Walt Feasel   Cosmetic api: api...
281
  	/* check: ide, usb, scsi, mmc */
500856eb1   Rafal Jaworowski   API for external ...
282
283
284
285
286
287
288
  	for (i = ENUM_IDE; i < ENUM_MAX; i ++) {
  		if (dev_enum_stor(i, di))
  			return 1;
  	}
  
  	return 0;
  }
4101f6879   Simon Glass   dm: Drop the bloc...
289
  static int dev_stor_is_valid(int type, struct blk_desc *dd)
500856eb1   Rafal Jaworowski   API for external ...
290
291
292
293
  {
  	int i;
  
  	for (i = 0; i < specs[type].max_dev; i++)
db1d9e78e   Simon Glass   dm: blk: Rename g...
294
  		if (dd == blk_get_dev(specs[type].name, i))
500856eb1   Rafal Jaworowski   API for external ...
295
296
297
298
299
300
301
302
303
304
305
306
307
  			if (dd->type != DEV_TYPE_UNKNOWN)
  				return 1;
  
  	return 0;
  }
  
  
  int dev_open_stor(void *cookie)
  {
  	int type = dev_stor_type(cookie);
  
  	if (type == ENUM_MAX)
  		return API_ENODEV;
4101f6879   Simon Glass   dm: Drop the bloc...
308
  	if (dev_stor_is_valid(type, (struct blk_desc *)cookie))
500856eb1   Rafal Jaworowski   API for external ...
309
310
311
312
313
314
315
316
317
318
319
320
321
322
  		return 0;
  
  	return API_ENODEV;
  }
  
  
  int dev_close_stor(void *cookie)
  {
  	/*
  	 * Not much to do as we actually do not alter storage devices upon
  	 * close
  	 */
  	return 0;
  }
500856eb1   Rafal Jaworowski   API for external ...
323
324
325
  lbasize_t dev_read_stor(void *cookie, void *buf, lbasize_t len, lbastart_t start)
  {
  	int type;
4101f6879   Simon Glass   dm: Drop the bloc...
326
  	struct blk_desc *dd = (struct blk_desc *)cookie;
500856eb1   Rafal Jaworowski   API for external ...
327
328
329
330
331
332
  
  	if ((type = dev_stor_type(dd)) == ENUM_MAX)
  		return 0;
  
  	if (!dev_stor_is_valid(type, dd))
  		return 0;
f2288c5a5   fuz@fuz.su   Apparent conflict...
333
334
335
  #ifdef CONFIG_BLK
  	return blk_dread(dd, start, len, buf);
  #else
500856eb1   Rafal Jaworowski   API for external ...
336
  	if ((dd->block_read) == NULL) {
f2302d443   Stefan Roese   Fix merge problems
337
338
  		debugf("no block_read() for device 0x%08x
  ", cookie);
500856eb1   Rafal Jaworowski   API for external ...
339
340
  		return 0;
  	}
7c4213f6a   Stephen Warren   block: pass block...
341
  	return dd->block_read(dd, start, len, buf);
f2288c5a5   fuz@fuz.su   Apparent conflict...
342
  #endif	/* defined(CONFIG_BLK) */
500856eb1   Rafal Jaworowski   API for external ...
343
  }
036218a67   Cristian Ciocaltea   api: storage: Add...
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
  
  
  lbasize_t dev_write_stor(void *cookie, void *buf, lbasize_t len, lbastart_t start)
  {
  	struct blk_desc *dd = (struct blk_desc *)cookie;
  	int type = dev_stor_type(dd);
  
  	if (type == ENUM_MAX)
  		return 0;
  
  	if (!dev_stor_is_valid(type, dd))
  		return 0;
  
  #ifdef CONFIG_BLK
  	return blk_dwrite(dd, start, len, buf);
  #else
  	if (dd->block_write == NULL) {
  		debugf("no block_write() for device 0x%08x
  ", cookie);
  		return 0;
  	}
  
  	return dd->block_write(dd, start, len, buf);
  #endif	/* defined(CONFIG_BLK) */
  }