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