Blame view
api/api_storage.c
7.58 KB
500856eb1 API for external ... |
1 |
/* |
f2302d443 Fix merge problems |
2 |
* (C) Copyright 2007-2008 Semihalf |
500856eb1 API for external ... |
3 4 5 |
* * Written by: Rafal Jaworowski <raj@semihalf.com> * |
1a4596601 Add GPL-2.0+ SPDX... |
6 |
* SPDX-License-Identifier: GPL-2.0+ |
500856eb1 API for external ... |
7 8 9 |
*/ #include <config.h> |
500856eb1 API for external ... |
10 11 |
#include <common.h> #include <api_public.h> |
3d0ea3110 api: Fix building... |
12 13 14 |
#if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE) #include <usb.h> #endif |
500856eb1 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 Fix merge problems |
31 32 |
#define ENUM_SATA 4 #define ENUM_MAX 5 |
500856eb1 API for external ... |
33 34 35 36 37 |
struct stor_spec { int max_dev; int enum_started; int enum_ended; |
e3d7675ac Cosmetic api: api... |
38 |
int type; /* "external" type: DT_STOR_{IDE,USB,etc} */ |
f2302d443 Fix merge problems |
39 |
char *name; |
500856eb1 API for external ... |
40 |
}; |
5d81c6df3 api: storage: Avo... |
41 |
static struct stor_spec specs[ENUM_MAX] = { { 0, 0, 0, 0, NULL }, }; |
500856eb1 API for external ... |
42 |
|
6d7a57076 api: Define a def... |
43 44 45 |
#ifndef CONFIG_SYS_MMC_MAX_DEVICE #define CONFIG_SYS_MMC_MAX_DEVICE 1 #endif |
500856eb1 API for external ... |
46 47 48 |
void dev_stor_init(void) { |
fc843a02a Kconfig: Add a CO... |
49 |
#if defined(CONFIG_IDE) |
6d0f6bcf3 rename CFG_ macro... |
50 |
specs[ENUM_IDE].max_dev = CONFIG_SYS_IDE_MAXDEVICE; |
500856eb1 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 Fix merge problems |
56 |
#if defined(CONFIG_CMD_MMC) |
6d0f6bcf3 rename CFG_ macro... |
57 |
specs[ENUM_MMC].max_dev = CONFIG_SYS_MMC_MAX_DEVICE; |
f2302d443 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 Kconfig: Add CONF... |
63 |
#if defined(CONFIG_SATA) |
6d0f6bcf3 rename CFG_ macro... |
64 |
specs[ENUM_SATA].max_dev = CONFIG_SYS_SATA_MAX_DEVICE; |
f2302d443 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 API for external ... |
69 |
#endif |
c649e3c91 dm: scsi: Rename ... |
70 |
#if defined(CONFIG_SCSI) |
6d0f6bcf3 rename CFG_ macro... |
71 |
specs[ENUM_SCSI].max_dev = CONFIG_SYS_SCSI_MAX_DEVICE; |
500856eb1 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 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 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 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 api: storage: Tes... |
96 |
static int dev_stor_get(int type, int *more, struct device_info *di) |
500856eb1 API for external ... |
97 |
{ |
4101f6879 dm: Drop the bloc... |
98 |
struct blk_desc *dd; |
d3e8f6302 api: storage: Tes... |
99 100 |
int found = 0; int i = 0; |
500856eb1 API for external ... |
101 |
|
5d81c6df3 api: storage: Avo... |
102 103 104 |
/* Wasn't configured for this type, return 0 directly */ if (specs[type].name == NULL) return 0; |
d3e8f6302 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 dm: blk: Rename g... |
108 109 |
if (di->cookie == (void *)blk_get_dev(specs[type].name, i)) { |
d3e8f6302 api: storage: Tes... |
110 |
i += 1; |
500856eb1 API for external ... |
111 112 |
break; } |
d3e8f6302 api: storage: Tes... |
113 |
} |
500856eb1 API for external ... |
114 |
} |
d3e8f6302 api: storage: Tes... |
115 116 |
for (; i < specs[type].max_dev; i++) { di->cookie = (void *)blk_get_dev(specs[type].name, i); |
500856eb1 API for external ... |
117 118 |
if (di->cookie != NULL) { |
d3e8f6302 api: storage: Tes... |
119 120 |
found = 1; break; |
500856eb1 API for external ... |
121 |
} |
d3e8f6302 api: storage: Tes... |
122 123 124 125 126 127 |
} if (i == specs[type].max_dev) *more = 0; else *more = 1; |
500856eb1 API for external ... |
128 |
|
d3e8f6302 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 API for external ... |
141 |
di->cookie = NULL; |
d3e8f6302 api: storage: Tes... |
142 |
} |
500856eb1 API for external ... |
143 144 145 |
return found; } |
c9db75a06 Cosmetic api: api... |
146 |
/* returns: ENUM_IDE, ENUM_USB etc. based on struct blk_desc */ |
4101f6879 dm: Drop the bloc... |
147 |
static int dev_stor_type(struct blk_desc *dd) |
500856eb1 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 dm: blk: Rename g... |
153 |
if (dd == blk_get_dev(specs[i].name, j)) |
500856eb1 API for external ... |
154 155 156 157 |
return i; return ENUM_MAX; } |
c9db75a06 Cosmetic api: api... |
158 |
/* returns: 0/1 whether cookie points to some device in this group */ |
500856eb1 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 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 api: storage: Tes... |
197 |
found = dev_stor_get(type, &more, di); |
500856eb1 API for external ... |
198 199 200 |
specs[type].enum_started = 1; } else if (dev_is_stor(type, di)) { |
500856eb1 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 api: storage: Tes... |
211 |
found = dev_stor_get(type, &more, di); |
500856eb1 API for external ... |
212 213 |
} else { |
500856eb1 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 Cosmetic api: api... |
227 |
* device from some other group (another storage |
500856eb1 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 api: storage: Tes... |
237 |
found = dev_stor_get(type, &more, di); |
500856eb1 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 Cosmetic api: api... |
256 |
(u_int32_t)di->cookie); |
500856eb1 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 Cosmetic api: api... |
277 |
/* check: ide, usb, scsi, mmc */ |
500856eb1 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 dm: Drop the bloc... |
285 |
static int dev_stor_is_valid(int type, struct blk_desc *dd) |
500856eb1 API for external ... |
286 287 288 289 |
{ int i; for (i = 0; i < specs[type].max_dev; i++) |
db1d9e78e dm: blk: Rename g... |
290 |
if (dd == blk_get_dev(specs[type].name, i)) |
500856eb1 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 dm: Drop the bloc... |
304 |
if (dev_stor_is_valid(type, (struct blk_desc *)cookie)) |
500856eb1 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 API for external ... |
319 320 321 |
lbasize_t dev_read_stor(void *cookie, void *buf, lbasize_t len, lbastart_t start) { int type; |
4101f6879 dm: Drop the bloc... |
322 |
struct blk_desc *dd = (struct blk_desc *)cookie; |
500856eb1 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 Apparent conflict... |
329 330 331 |
#ifdef CONFIG_BLK return blk_dread(dd, start, len, buf); #else |
500856eb1 API for external ... |
332 |
if ((dd->block_read) == NULL) { |
f2302d443 Fix merge problems |
333 334 |
debugf("no block_read() for device 0x%08x ", cookie); |
500856eb1 API for external ... |
335 336 |
return 0; } |
7c4213f6a block: pass block... |
337 |
return dd->block_read(dd, start, len, buf); |
f2288c5a5 Apparent conflict... |
338 |
#endif /* defined(CONFIG_BLK) */ |
500856eb1 API for external ... |
339 |
} |