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_IDE, 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 const char *blk_get_if_type_name(enum if_type if_type) 61 { 62 return if_typename_str[if_type]; 63 } 64 65 struct blk_desc *blk_get_devnum_by_type(enum if_type if_type, int devnum) 66 { 67 struct blk_desc *desc; 68 struct udevice *dev; 69 int ret; 70 71 ret = blk_get_device(if_type, devnum, &dev); 72 if (ret) 73 return NULL; 74 desc = dev_get_uclass_platdata(dev); 75 76 return desc; 77 } 78 79 /* 80 * This function is complicated with driver model. We look up the interface 81 * name in a local table. This gives us an interface type which we can match 82 * against the uclass of the block device's parent. 83 */ 84 struct blk_desc *blk_get_devnum_by_typename(const char *if_typename, int devnum) 85 { 86 enum uclass_id uclass_id; 87 enum if_type if_type; 88 struct udevice *dev; 89 struct uclass *uc; 90 int ret; 91 92 if_type = if_typename_to_iftype(if_typename); 93 if (if_type == IF_TYPE_UNKNOWN) { 94 debug("%s: Unknown interface type '%s'\n", __func__, 95 if_typename); 96 return NULL; 97 } 98 uclass_id = if_type_to_uclass_id(if_type); 99 if (uclass_id == UCLASS_INVALID) { 100 debug("%s: Unknown uclass for interface type'\n", 101 if_typename_str[if_type]); 102 return NULL; 103 } 104 105 ret = uclass_get(UCLASS_BLK, &uc); 106 if (ret) 107 return NULL; 108 uclass_foreach_dev(dev, uc) { 109 struct blk_desc *desc = dev_get_uclass_platdata(dev); 110 111 debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__, 112 if_type, devnum, dev->name, desc->if_type, desc->devnum); 113 if (desc->devnum != devnum) 114 continue; 115 116 /* Find out the parent device uclass */ 117 if (device_get_uclass_id(dev->parent) != uclass_id) { 118 debug("%s: parent uclass %d, this dev %d\n", __func__, 119 device_get_uclass_id(dev->parent), uclass_id); 120 continue; 121 } 122 123 if (device_probe(dev)) 124 return NULL; 125 126 debug("%s: Device desc %p\n", __func__, desc); 127 return desc; 128 } 129 debug("%s: No device found\n", __func__); 130 131 return NULL; 132 } 133 134 /** 135 * get_desc() - Get the block device descriptor for the given device number 136 * 137 * @if_type: Interface type 138 * @devnum: Device number (0 = first) 139 * @descp: Returns block device descriptor on success 140 * @return 0 on success, -ENODEV if there is no such device and no device 141 * with a higher device number, -ENOENT if there is no such device but there 142 * is one with a higher number, or other -ve on other error. 143 */ 144 static int get_desc(enum if_type if_type, int devnum, struct blk_desc **descp) 145 { 146 bool found_more = false; 147 struct udevice *dev; 148 struct uclass *uc; 149 int ret; 150 151 *descp = NULL; 152 ret = uclass_get(UCLASS_BLK, &uc); 153 if (ret) 154 return ret; 155 uclass_foreach_dev(dev, uc) { 156 struct blk_desc *desc = dev_get_uclass_platdata(dev); 157 158 debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__, 159 if_type, devnum, dev->name, desc->if_type, desc->devnum); 160 if (desc->if_type == if_type) { 161 if (desc->devnum == devnum) { 162 ret = device_probe(dev); 163 if (ret) 164 return ret; 165 166 *descp = desc; 167 return 0; 168 } else if (desc->devnum > devnum) { 169 found_more = true; 170 } 171 } 172 } 173 174 return found_more ? -ENOENT : -ENODEV; 175 } 176 177 int blk_select_hwpart_devnum(enum if_type if_type, int devnum, int hwpart) 178 { 179 struct udevice *dev; 180 int ret; 181 182 ret = blk_get_device(if_type, devnum, &dev); 183 if (ret) 184 return ret; 185 186 return blk_select_hwpart(dev, hwpart); 187 } 188 189 int blk_list_part(enum if_type if_type) 190 { 191 struct blk_desc *desc; 192 int devnum, ok; 193 int ret; 194 195 for (ok = 0, devnum = 0;; ++devnum) { 196 ret = get_desc(if_type, devnum, &desc); 197 if (ret == -ENODEV) 198 break; 199 else if (ret) 200 continue; 201 if (desc->part_type != PART_TYPE_UNKNOWN) { 202 ++ok; 203 if (devnum) 204 putc('\n'); 205 part_print(desc); 206 } 207 } 208 if (!ok) 209 return -ENODEV; 210 211 return 0; 212 } 213 214 int blk_print_part_devnum(enum if_type if_type, int devnum) 215 { 216 struct blk_desc *desc; 217 int ret; 218 219 ret = get_desc(if_type, devnum, &desc); 220 if (ret) 221 return ret; 222 if (desc->type == DEV_TYPE_UNKNOWN) 223 return -ENOENT; 224 part_print(desc); 225 226 return 0; 227 } 228 229 void blk_list_devices(enum if_type if_type) 230 { 231 struct blk_desc *desc; 232 int ret; 233 int i; 234 235 for (i = 0;; ++i) { 236 ret = get_desc(if_type, i, &desc); 237 if (ret == -ENODEV) 238 break; 239 else if (ret) 240 continue; 241 if (desc->type == DEV_TYPE_UNKNOWN) 242 continue; /* list only known devices */ 243 printf("Device %d: ", i); 244 dev_print(desc); 245 } 246 } 247 248 int blk_print_device_num(enum if_type if_type, int devnum) 249 { 250 struct blk_desc *desc; 251 int ret; 252 253 ret = get_desc(if_type, devnum, &desc); 254 if (ret) 255 return ret; 256 printf("\nIDE device %d: ", devnum); 257 dev_print(desc); 258 259 return 0; 260 } 261 262 int blk_show_device(enum if_type if_type, int devnum) 263 { 264 struct blk_desc *desc; 265 int ret; 266 267 printf("\nDevice %d: ", devnum); 268 ret = get_desc(if_type, devnum, &desc); 269 if (ret == -ENODEV || ret == -ENOENT) { 270 printf("unknown device\n"); 271 return -ENODEV; 272 } 273 if (ret) 274 return ret; 275 dev_print(desc); 276 277 if (desc->type == DEV_TYPE_UNKNOWN) 278 return -ENOENT; 279 280 return 0; 281 } 282 283 ulong blk_read_devnum(enum if_type if_type, int devnum, lbaint_t start, 284 lbaint_t blkcnt, void *buffer) 285 { 286 struct blk_desc *desc; 287 ulong n; 288 int ret; 289 290 ret = get_desc(if_type, devnum, &desc); 291 if (ret) 292 return ret; 293 n = blk_dread(desc, start, blkcnt, buffer); 294 if (IS_ERR_VALUE(n)) 295 return n; 296 297 /* flush cache after read */ 298 flush_cache((ulong)buffer, blkcnt * desc->blksz); 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_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_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_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 size, 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 = size / blksz; 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 size, 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, size, 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