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