1 /* 2 * Copyright (C) 2016 Google, Inc 3 * Written by Simon Glass <sjg@chromium.org> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <blk.h> 10 #include <dm.h> 11 #include <dm/device-internal.h> 12 #include <dm/lists.h> 13 14 static const char *if_typename_str[IF_TYPE_COUNT] = { 15 [IF_TYPE_IDE] = "ide", 16 [IF_TYPE_SCSI] = "scsi", 17 [IF_TYPE_ATAPI] = "atapi", 18 [IF_TYPE_USB] = "usb", 19 [IF_TYPE_DOC] = "doc", 20 [IF_TYPE_MMC] = "mmc", 21 [IF_TYPE_SD] = "sd", 22 [IF_TYPE_SATA] = "sata", 23 [IF_TYPE_HOST] = "host", 24 [IF_TYPE_SYSTEMACE] = "ace", 25 }; 26 27 static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = { 28 [IF_TYPE_IDE] = UCLASS_INVALID, 29 [IF_TYPE_SCSI] = UCLASS_SCSI, 30 [IF_TYPE_ATAPI] = UCLASS_INVALID, 31 [IF_TYPE_USB] = UCLASS_MASS_STORAGE, 32 [IF_TYPE_DOC] = UCLASS_INVALID, 33 [IF_TYPE_MMC] = UCLASS_MMC, 34 [IF_TYPE_SD] = UCLASS_INVALID, 35 [IF_TYPE_SATA] = UCLASS_AHCI, 36 [IF_TYPE_HOST] = UCLASS_ROOT, 37 [IF_TYPE_SYSTEMACE] = UCLASS_INVALID, 38 }; 39 40 static enum if_type if_typename_to_iftype(const char *if_typename) 41 { 42 int i; 43 44 for (i = 0; i < IF_TYPE_COUNT; i++) { 45 if (if_typename_str[i] && 46 !strcmp(if_typename, if_typename_str[i])) 47 return i; 48 } 49 50 return IF_TYPE_UNKNOWN; 51 } 52 53 static enum uclass_id if_type_to_uclass_id(enum if_type if_type) 54 { 55 return if_type_uclass_id[if_type]; 56 } 57 58 struct blk_desc *blk_get_devnum_by_type(enum if_type if_type, int devnum) 59 { 60 struct blk_desc *desc; 61 struct udevice *dev; 62 int ret; 63 64 ret = blk_get_device(if_type, devnum, &dev); 65 if (ret) 66 return NULL; 67 desc = dev_get_uclass_platdata(dev); 68 69 return desc; 70 } 71 72 /* 73 * This function is complicated with driver model. We look up the interface 74 * name in a local table. This gives us an interface type which we can match 75 * against the uclass of the block device's parent. 76 */ 77 struct blk_desc *blk_get_devnum_by_typename(const char *if_typename, int devnum) 78 { 79 enum uclass_id uclass_id; 80 enum if_type if_type; 81 struct udevice *dev; 82 struct uclass *uc; 83 int ret; 84 85 if_type = if_typename_to_iftype(if_typename); 86 if (if_type == IF_TYPE_UNKNOWN) { 87 debug("%s: Unknown interface type '%s'\n", __func__, 88 if_typename); 89 return NULL; 90 } 91 uclass_id = if_type_to_uclass_id(if_type); 92 if (uclass_id == UCLASS_INVALID) { 93 debug("%s: Unknown uclass for interface type'\n", 94 if_typename_str[if_type]); 95 return NULL; 96 } 97 98 ret = uclass_get(UCLASS_BLK, &uc); 99 if (ret) 100 return NULL; 101 uclass_foreach_dev(dev, uc) { 102 struct blk_desc *desc = dev_get_uclass_platdata(dev); 103 104 debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__, 105 if_type, devnum, dev->name, desc->if_type, desc->devnum); 106 if (desc->devnum != devnum) 107 continue; 108 109 /* Find out the parent device uclass */ 110 if (device_get_uclass_id(dev->parent) != uclass_id) { 111 debug("%s: parent uclass %d, this dev %d\n", __func__, 112 device_get_uclass_id(dev->parent), uclass_id); 113 continue; 114 } 115 116 if (device_probe(dev)) 117 return NULL; 118 119 debug("%s: Device desc %p\n", __func__, desc); 120 return desc; 121 } 122 debug("%s: No device found\n", __func__); 123 124 return NULL; 125 } 126 127 /** 128 * get_desc() - Get the block device descriptor for the given device number 129 * 130 * @if_type: Interface type 131 * @devnum: Device number (0 = first) 132 * @descp: Returns block device descriptor on success 133 * @return 0 on success, -ENODEV if there is no such device and no device 134 * with a higher device number, -ENOENT if there is no such device but there 135 * is one with a higher number, or other -ve on other error. 136 */ 137 static int get_desc(enum if_type if_type, int devnum, struct blk_desc **descp) 138 { 139 bool found_more = false; 140 struct udevice *dev; 141 struct uclass *uc; 142 int ret; 143 144 *descp = NULL; 145 ret = uclass_get(UCLASS_BLK, &uc); 146 if (ret) 147 return ret; 148 uclass_foreach_dev(dev, uc) { 149 struct blk_desc *desc = dev_get_uclass_platdata(dev); 150 151 debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__, 152 if_type, devnum, dev->name, desc->if_type, desc->devnum); 153 if (desc->if_type == if_type) { 154 if (desc->devnum == devnum) { 155 ret = device_probe(dev); 156 if (ret) 157 return ret; 158 159 *descp = desc; 160 return 0; 161 } else if (desc->devnum > devnum) { 162 found_more = true; 163 } 164 } 165 } 166 167 return found_more ? -ENOENT : -ENODEV; 168 } 169 170 int blk_select_hwpart_devnum(enum if_type if_type, int devnum, int hwpart) 171 { 172 struct udevice *dev; 173 int ret; 174 175 ret = blk_get_device(if_type, devnum, &dev); 176 if (ret) 177 return ret; 178 179 return blk_select_hwpart(dev, hwpart); 180 } 181 182 int blk_list_part(enum if_type if_type) 183 { 184 struct blk_desc *desc; 185 int devnum, ok; 186 int ret; 187 188 for (ok = 0, devnum = 0;; ++devnum) { 189 ret = get_desc(if_type, devnum, &desc); 190 if (ret == -ENODEV) 191 break; 192 else if (ret) 193 continue; 194 if (desc->part_type != PART_TYPE_UNKNOWN) { 195 ++ok; 196 if (devnum) 197 putc('\n'); 198 part_print(desc); 199 } 200 } 201 if (!ok) 202 return -ENODEV; 203 204 return 0; 205 } 206 207 int blk_print_part_devnum(enum if_type if_type, int devnum) 208 { 209 struct blk_desc *desc; 210 int ret; 211 212 ret = get_desc(if_type, devnum, &desc); 213 if (ret) 214 return ret; 215 if (desc->type == DEV_TYPE_UNKNOWN) 216 return -ENOENT; 217 part_print(desc); 218 219 return 0; 220 } 221 222 void blk_list_devices(enum if_type if_type) 223 { 224 struct blk_desc *desc; 225 int ret; 226 int i; 227 228 for (i = 0;; ++i) { 229 ret = get_desc(if_type, i, &desc); 230 if (ret == -ENODEV) 231 break; 232 else if (ret) 233 continue; 234 if (desc->type == DEV_TYPE_UNKNOWN) 235 continue; /* list only known devices */ 236 printf("Device %d: ", i); 237 dev_print(desc); 238 } 239 } 240 241 int blk_print_device_num(enum if_type if_type, int devnum) 242 { 243 struct blk_desc *desc; 244 int ret; 245 246 ret = get_desc(if_type, devnum, &desc); 247 if (ret) 248 return ret; 249 printf("\nIDE device %d: ", devnum); 250 dev_print(desc); 251 252 return 0; 253 } 254 255 int blk_show_device(enum if_type if_type, int devnum) 256 { 257 struct blk_desc *desc; 258 int ret; 259 260 printf("\nDevice %d: ", devnum); 261 ret = get_desc(if_type, devnum, &desc); 262 if (ret == -ENODEV || ret == -ENOENT) { 263 printf("unknown device\n"); 264 return -ENODEV; 265 } 266 if (ret) 267 return ret; 268 dev_print(desc); 269 270 if (desc->type == DEV_TYPE_UNKNOWN) 271 return -ENOENT; 272 273 return 0; 274 } 275 276 ulong blk_read_devnum(enum if_type if_type, int devnum, lbaint_t start, 277 lbaint_t blkcnt, void *buffer) 278 { 279 struct blk_desc *desc; 280 ulong n; 281 int ret; 282 283 ret = get_desc(if_type, devnum, &desc); 284 if (ret) 285 return ret; 286 n = blk_dread(desc, start, blkcnt, buffer); 287 if (IS_ERR_VALUE(n)) 288 return n; 289 290 /* flush cache after read */ 291 flush_cache((ulong)buffer, blkcnt * desc->blksz); 292 293 return n; 294 } 295 296 ulong blk_write_devnum(enum if_type if_type, int devnum, lbaint_t start, 297 lbaint_t blkcnt, const void *buffer) 298 { 299 struct blk_desc *desc; 300 int ret; 301 302 ret = get_desc(if_type, devnum, &desc); 303 if (ret) 304 return ret; 305 return blk_dwrite(desc, start, blkcnt, buffer); 306 } 307 308 int blk_select_hwpart(struct udevice *dev, int hwpart) 309 { 310 const struct blk_ops *ops = blk_get_ops(dev); 311 312 if (!ops) 313 return -ENOSYS; 314 if (!ops->select_hwpart) 315 return 0; 316 317 return ops->select_hwpart(dev, hwpart); 318 } 319 320 int blk_dselect_hwpart(struct blk_desc *desc, int hwpart) 321 { 322 return blk_select_hwpart(desc->bdev, hwpart); 323 } 324 325 int blk_first_device(int if_type, struct udevice **devp) 326 { 327 struct blk_desc *desc; 328 int ret; 329 330 ret = uclass_first_device(UCLASS_BLK, devp); 331 if (ret) 332 return ret; 333 if (!*devp) 334 return -ENODEV; 335 do { 336 desc = dev_get_uclass_platdata(*devp); 337 if (desc->if_type == if_type) 338 return 0; 339 ret = uclass_next_device(devp); 340 if (ret) 341 return ret; 342 } while (*devp); 343 344 return -ENODEV; 345 } 346 347 int blk_next_device(struct udevice **devp) 348 { 349 struct blk_desc *desc; 350 int ret, if_type; 351 352 desc = dev_get_uclass_platdata(*devp); 353 if_type = desc->if_type; 354 do { 355 ret = uclass_next_device(devp); 356 if (ret) 357 return ret; 358 if (!*devp) 359 return -ENODEV; 360 desc = dev_get_uclass_platdata(*devp); 361 if (desc->if_type == if_type) 362 return 0; 363 } while (1); 364 } 365 366 int blk_find_device(int if_type, int devnum, struct udevice **devp) 367 { 368 struct uclass *uc; 369 struct udevice *dev; 370 int ret; 371 372 ret = uclass_get(UCLASS_BLK, &uc); 373 if (ret) 374 return ret; 375 uclass_foreach_dev(dev, uc) { 376 struct blk_desc *desc = dev_get_uclass_platdata(dev); 377 378 debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__, 379 if_type, devnum, dev->name, desc->if_type, desc->devnum); 380 if (desc->if_type == if_type && desc->devnum == devnum) { 381 *devp = dev; 382 return 0; 383 } 384 } 385 386 return -ENODEV; 387 } 388 389 int blk_get_device(int if_type, int devnum, struct udevice **devp) 390 { 391 int ret; 392 393 ret = blk_find_device(if_type, devnum, devp); 394 if (ret) 395 return ret; 396 397 return device_probe(*devp); 398 } 399 400 unsigned long blk_dread(struct blk_desc *block_dev, lbaint_t start, 401 lbaint_t blkcnt, void *buffer) 402 { 403 struct udevice *dev = block_dev->bdev; 404 const struct blk_ops *ops = blk_get_ops(dev); 405 ulong blks_read; 406 407 if (!ops->read) 408 return -ENOSYS; 409 410 if (blkcache_read(block_dev->if_type, block_dev->devnum, 411 start, blkcnt, block_dev->blksz, buffer)) 412 return blkcnt; 413 blks_read = ops->read(dev, start, blkcnt, buffer); 414 if (blks_read == blkcnt) 415 blkcache_fill(block_dev->if_type, block_dev->devnum, 416 start, blkcnt, block_dev->blksz, buffer); 417 418 return blks_read; 419 } 420 421 unsigned long blk_dwrite(struct blk_desc *block_dev, lbaint_t start, 422 lbaint_t blkcnt, const void *buffer) 423 { 424 struct udevice *dev = block_dev->bdev; 425 const struct blk_ops *ops = blk_get_ops(dev); 426 427 if (!ops->write) 428 return -ENOSYS; 429 430 blkcache_invalidate(block_dev->if_type, block_dev->devnum); 431 return ops->write(dev, start, blkcnt, buffer); 432 } 433 434 unsigned long blk_derase(struct blk_desc *block_dev, lbaint_t start, 435 lbaint_t blkcnt) 436 { 437 struct udevice *dev = block_dev->bdev; 438 const struct blk_ops *ops = blk_get_ops(dev); 439 440 if (!ops->erase) 441 return -ENOSYS; 442 443 blkcache_invalidate(block_dev->if_type, block_dev->devnum); 444 return ops->erase(dev, start, blkcnt); 445 } 446 447 int blk_prepare_device(struct udevice *dev) 448 { 449 struct blk_desc *desc = dev_get_uclass_platdata(dev); 450 451 part_init(desc); 452 453 return 0; 454 } 455 456 int blk_get_from_parent(struct udevice *parent, struct udevice **devp) 457 { 458 struct udevice *dev; 459 enum uclass_id id; 460 int ret; 461 462 device_find_first_child(parent, &dev); 463 if (!dev) { 464 debug("%s: No block device found for parent '%s'\n", __func__, 465 parent->name); 466 return -ENODEV; 467 } 468 id = device_get_uclass_id(dev); 469 if (id != UCLASS_BLK) { 470 debug("%s: Incorrect uclass %s for block device '%s'\n", 471 __func__, uclass_get_name(id), dev->name); 472 return -ENOTBLK; 473 } 474 ret = device_probe(dev); 475 if (ret) 476 return ret; 477 *devp = dev; 478 479 return 0; 480 } 481 482 int blk_find_max_devnum(enum if_type if_type) 483 { 484 struct udevice *dev; 485 int max_devnum = -ENODEV; 486 struct uclass *uc; 487 int ret; 488 489 ret = uclass_get(UCLASS_BLK, &uc); 490 if (ret) 491 return ret; 492 uclass_foreach_dev(dev, uc) { 493 struct blk_desc *desc = dev_get_uclass_platdata(dev); 494 495 if (desc->if_type == if_type && desc->devnum > max_devnum) 496 max_devnum = desc->devnum; 497 } 498 499 return max_devnum; 500 } 501 502 static int blk_next_free_devnum(enum if_type if_type) 503 { 504 int ret; 505 506 ret = blk_find_max_devnum(if_type); 507 if (ret == -ENODEV) 508 return 0; 509 if (ret < 0) 510 return ret; 511 512 return ret + 1; 513 } 514 515 static int blk_claim_devnum(enum if_type if_type, int devnum) 516 { 517 struct udevice *dev; 518 struct uclass *uc; 519 int ret; 520 521 ret = uclass_get(UCLASS_BLK, &uc); 522 if (ret) 523 return ret; 524 uclass_foreach_dev(dev, uc) { 525 struct blk_desc *desc = dev_get_uclass_platdata(dev); 526 527 if (desc->if_type == if_type && desc->devnum == devnum) { 528 int next = blk_next_free_devnum(if_type); 529 530 if (next < 0) 531 return next; 532 desc->devnum = next; 533 return 0; 534 } 535 } 536 537 return -ENOENT; 538 } 539 540 int blk_create_device(struct udevice *parent, const char *drv_name, 541 const char *name, int if_type, int devnum, int blksz, 542 lbaint_t size, struct udevice **devp) 543 { 544 struct blk_desc *desc; 545 struct udevice *dev; 546 int ret; 547 548 if (devnum == -1) { 549 devnum = blk_next_free_devnum(if_type); 550 } else { 551 ret = blk_claim_devnum(if_type, devnum); 552 if (ret < 0 && ret != -ENOENT) 553 return ret; 554 } 555 if (devnum < 0) 556 return devnum; 557 ret = device_bind_driver(parent, drv_name, name, &dev); 558 if (ret) 559 return ret; 560 desc = dev_get_uclass_platdata(dev); 561 desc->if_type = if_type; 562 desc->blksz = blksz; 563 desc->lba = size / blksz; 564 desc->part_type = PART_TYPE_UNKNOWN; 565 desc->bdev = dev; 566 desc->devnum = devnum; 567 *devp = dev; 568 569 return 0; 570 } 571 572 int blk_create_devicef(struct udevice *parent, const char *drv_name, 573 const char *name, int if_type, int devnum, int blksz, 574 lbaint_t size, struct udevice **devp) 575 { 576 char dev_name[30], *str; 577 int ret; 578 579 snprintf(dev_name, sizeof(dev_name), "%s.%s", parent->name, name); 580 str = strdup(dev_name); 581 if (!str) 582 return -ENOMEM; 583 584 ret = blk_create_device(parent, drv_name, str, if_type, devnum, 585 blksz, size, devp); 586 if (ret) { 587 free(str); 588 return ret; 589 } 590 device_set_name_alloced(*devp); 591 592 return ret; 593 } 594 595 int blk_unbind_all(int if_type) 596 { 597 struct uclass *uc; 598 struct udevice *dev, *next; 599 int ret; 600 601 ret = uclass_get(UCLASS_BLK, &uc); 602 if (ret) 603 return ret; 604 uclass_foreach_dev_safe(dev, next, uc) { 605 struct blk_desc *desc = dev_get_uclass_platdata(dev); 606 607 if (desc->if_type == if_type) { 608 ret = device_remove(dev, DM_REMOVE_NORMAL); 609 if (ret) 610 return ret; 611 ret = device_unbind(dev); 612 if (ret) 613 return ret; 614 } 615 } 616 617 return 0; 618 } 619 620 UCLASS_DRIVER(blk) = { 621 .id = UCLASS_BLK, 622 .name = "blk", 623 .per_device_platdata_auto_alloc_size = sizeof(struct blk_desc), 624 }; 625