Blame view

api/api_storage.c 7.58 KB
500856eb1   Rafal Jaworowski   API for external ...
1
  /*
f2302d443   Stefan Roese   Fix merge problems
2
   * (C) Copyright 2007-2008 Semihalf
500856eb1   Rafal Jaworowski   API for external ...
3
4
5
   *
   * Written by: Rafal Jaworowski <raj@semihalf.com>
   *
1a4596601   Wolfgang Denk   Add GPL-2.0+ SPDX...
6
   * SPDX-License-Identifier:	GPL-2.0+
500856eb1   Rafal Jaworowski   API for external ...
7
8
9
   */
  
  #include <config.h>
500856eb1   Rafal Jaworowski   API for external ...
10
11
  #include <common.h>
  #include <api_public.h>
3d0ea3110   Matthias Fuchs   api: Fix building...
12
13
14
  #if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE)
  #include <usb.h>
  #endif
500856eb1   Rafal Jaworowski   API for external ...
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
  #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
31
32
  #define ENUM_SATA	4
  #define ENUM_MAX	5
500856eb1   Rafal Jaworowski   API for external ...
33
34
35
36
37
  
  struct stor_spec {
  	int		max_dev;
  	int		enum_started;
  	int		enum_ended;
e3d7675ac   Walt Feasel   Cosmetic api: api...
38
  	int		type;	/* "external" type: DT_STOR_{IDE,USB,etc} */
f2302d443   Stefan Roese   Fix merge problems
39
  	char		*name;
500856eb1   Rafal Jaworowski   API for external ...
40
  };
5d81c6df3   Emmanuel Vadot   api: storage: Avo...
41
  static struct stor_spec specs[ENUM_MAX] = { { 0, 0, 0, 0, NULL }, };
500856eb1   Rafal Jaworowski   API for external ...
42

6d7a57076   Emmanuel Vadot   api: Define a def...
43
44
45
  #ifndef CONFIG_SYS_MMC_MAX_DEVICE
  #define CONFIG_SYS_MMC_MAX_DEVICE	1
  #endif
500856eb1   Rafal Jaworowski   API for external ...
46
47
48
  
  void dev_stor_init(void)
  {
fc843a02a   Simon Glass   Kconfig: Add a CO...
49
  #if defined(CONFIG_IDE)
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
50
  	specs[ENUM_IDE].max_dev = CONFIG_SYS_IDE_MAXDEVICE;
500856eb1   Rafal Jaworowski   API for external ...
51
52
53
54
55
  	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
56
  #if defined(CONFIG_CMD_MMC)
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
57
  	specs[ENUM_MMC].max_dev = CONFIG_SYS_MMC_MAX_DEVICE;
f2302d443   Stefan Roese   Fix merge problems
58
59
60
61
62
  	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...
63
  #if defined(CONFIG_SATA)
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
64
  	specs[ENUM_SATA].max_dev = CONFIG_SYS_SATA_MAX_DEVICE;
f2302d443   Stefan Roese   Fix merge problems
65
66
67
68
  	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 ...
69
  #endif
c649e3c91   Simon Glass   dm: scsi: Rename ...
70
  #if defined(CONFIG_SCSI)
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
71
  	specs[ENUM_SCSI].max_dev = CONFIG_SYS_SCSI_MAX_DEVICE;
500856eb1   Rafal Jaworowski   API for external ...
72
73
74
75
76
  	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
77
78
79
80
81
82
83
  #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 ...
84
85
86
87
88
89
90
  }
  
  /*
   * Finds next available device in the storage group
   *
   * type:	storage group type - ENUM_IDE, ENUM_SCSI etc.
   *
500856eb1   Rafal Jaworowski   API for external ...
91
92
93
94
95
   * 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...
96
  static int dev_stor_get(int type, int *more, struct device_info *di)
500856eb1   Rafal Jaworowski   API for external ...
97
  {
4101f6879   Simon Glass   dm: Drop the bloc...
98
  	struct blk_desc *dd;
d3e8f6302   Emmanuel Vadot   api: storage: Tes...
99
100
  	int found = 0;
  	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;
500856eb1   Rafal Jaworowski   API for external ...
111
112
  				break;
  			}
d3e8f6302   Emmanuel Vadot   api: storage: Tes...
113
  		}
500856eb1   Rafal Jaworowski   API for external ...
114
  	}
d3e8f6302   Emmanuel Vadot   api: storage: Tes...
115
116
  	for (; i < specs[type].max_dev; i++) {
  		di->cookie = (void *)blk_get_dev(specs[type].name, i);
500856eb1   Rafal Jaworowski   API for external ...
117
118
  
  		if (di->cookie != NULL) {
d3e8f6302   Emmanuel Vadot   api: storage: Tes...
119
120
  			found = 1;
  			break;
500856eb1   Rafal Jaworowski   API for external ...
121
  		}
d3e8f6302   Emmanuel Vadot   api: storage: Tes...
122
123
124
125
126
127
  	}
  
  	if (i == specs[type].max_dev)
  		*more = 0;
  	else
  		*more = 1;
500856eb1   Rafal Jaworowski   API for external ...
128

d3e8f6302   Emmanuel Vadot   api: storage: Tes...
129
130
131
132
133
134
135
136
137
138
139
140
  	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 ...
141
  		di->cookie = NULL;
d3e8f6302   Emmanuel Vadot   api: storage: Tes...
142
  	}
500856eb1   Rafal Jaworowski   API for external ...
143
144
145
  
  	return found;
  }
c9db75a06   Walt Feasel   Cosmetic api: api...
146
  /* returns: ENUM_IDE, ENUM_USB etc. based on struct blk_desc */
4101f6879   Simon Glass   dm: Drop the bloc...
147
  static int dev_stor_type(struct blk_desc *dd)
500856eb1   Rafal Jaworowski   API for external ...
148
149
150
151
152
  {
  	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...
153
  			if (dd == blk_get_dev(specs[i].name, j))
500856eb1   Rafal Jaworowski   API for external ...
154
155
156
157
  				return i;
  
  	return ENUM_MAX;
  }
c9db75a06   Walt Feasel   Cosmetic api: api...
158
  /* returns: 0/1 whether cookie points to some device in this group */
500856eb1   Rafal Jaworowski   API for external ...
159
160
161
162
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
  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 ...
190
191
192
193
194
195
196
  		debugf("group%d - enum restart
  ", type);
  
  		/*
  		 * 1. Enumeration (re-)started: take the first available
  		 * device, if exists
  		 */
d3e8f6302   Emmanuel Vadot   api: storage: Tes...
197
  		found = dev_stor_get(type, &more, di);
500856eb1   Rafal Jaworowski   API for external ...
198
199
200
  		specs[type].enum_started = 1;
  
  	} else if (dev_is_stor(type, di)) {
500856eb1   Rafal Jaworowski   API for external ...
201
202
203
204
205
206
207
208
209
210
  		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...
211
  		found = dev_stor_get(type, &more, di);
500856eb1   Rafal Jaworowski   API for external ...
212
213
  
  	} else {
500856eb1   Rafal Jaworowski   API for external ...
214
215
216
217
218
219
220
221
222
223
224
225
226
  		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...
227
  			 * device from some other group (another storage
500856eb1   Rafal Jaworowski   API for external ...
228
229
230
231
232
233
234
235
236
  			 * 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...
237
  			found = dev_stor_get(type, &more, di);
500856eb1   Rafal Jaworowski   API for external ...
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
  
  		} 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...
256
  		       (u_int32_t)di->cookie);
500856eb1   Rafal Jaworowski   API for external ...
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
  	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...
277
  	/* check: ide, usb, scsi, mmc */
500856eb1   Rafal Jaworowski   API for external ...
278
279
280
281
282
283
284
  	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...
285
  static int dev_stor_is_valid(int type, struct blk_desc *dd)
500856eb1   Rafal Jaworowski   API for external ...
286
287
288
289
  {
  	int i;
  
  	for (i = 0; i < specs[type].max_dev; i++)
db1d9e78e   Simon Glass   dm: blk: Rename g...
290
  		if (dd == blk_get_dev(specs[type].name, i))
500856eb1   Rafal Jaworowski   API for external ...
291
292
293
294
295
296
297
298
299
300
301
302
303
  			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...
304
  	if (dev_stor_is_valid(type, (struct blk_desc *)cookie))
500856eb1   Rafal Jaworowski   API for external ...
305
306
307
308
309
310
311
312
313
314
315
316
317
318
  		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 ...
319
320
321
  lbasize_t dev_read_stor(void *cookie, void *buf, lbasize_t len, lbastart_t start)
  {
  	int type;
4101f6879   Simon Glass   dm: Drop the bloc...
322
  	struct blk_desc *dd = (struct blk_desc *)cookie;
500856eb1   Rafal Jaworowski   API for external ...
323
324
325
326
327
328
  
  	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...
329
330
331
  #ifdef CONFIG_BLK
  	return blk_dread(dd, start, len, buf);
  #else
500856eb1   Rafal Jaworowski   API for external ...
332
  	if ((dd->block_read) == NULL) {
f2302d443   Stefan Roese   Fix merge problems
333
334
  		debugf("no block_read() for device 0x%08x
  ", cookie);
500856eb1   Rafal Jaworowski   API for external ...
335
336
  		return 0;
  	}
7c4213f6a   Stephen Warren   block: pass block...
337
  	return dd->block_read(dd, start, len, buf);
f2288c5a5   fuz@fuz.su   Apparent conflict...
338
  #endif	/* defined(CONFIG_BLK) */
500856eb1   Rafal Jaworowski   API for external ...
339
  }