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 return n; 298 } 299 300 ulong blk_write_devnum(enum if_type if_type, int devnum, lbaint_t start, 301 lbaint_t blkcnt, const void *buffer) 302 { 303 struct blk_desc *desc; 304 int ret; 305 306 ret = get_desc(if_type, devnum, &desc); 307 if (ret) 308 return ret; 309 return blk_dwrite(desc, start, blkcnt, buffer); 310 } 311 312 int blk_select_hwpart(struct udevice *dev, int hwpart) 313 { 314 const struct blk_ops *ops = blk_get_ops(dev); 315 316 if (!ops) 317 return -ENOSYS; 318 if (!ops->select_hwpart) 319 return 0; 320 321 return ops->select_hwpart(dev, hwpart); 322 } 323 324 int blk_dselect_hwpart(struct blk_desc *desc, int hwpart) 325 { 326 return blk_select_hwpart(desc->bdev, hwpart); 327 } 328 329 int blk_first_device(int if_type, struct udevice **devp) 330 { 331 struct blk_desc *desc; 332 int ret; 333 334 ret = uclass_first_device(UCLASS_BLK, devp); 335 if (ret) 336 return ret; 337 if (!*devp) 338 return -ENODEV; 339 do { 340 desc = dev_get_uclass_platdata(*devp); 341 if (desc->if_type == if_type) 342 return 0; 343 ret = uclass_next_device(devp); 344 if (ret) 345 return ret; 346 } while (*devp); 347 348 return -ENODEV; 349 } 350 351 int blk_next_device(struct udevice **devp) 352 { 353 struct blk_desc *desc; 354 int ret, if_type; 355 356 desc = dev_get_uclass_platdata(*devp); 357 if_type = desc->if_type; 358 do { 359 ret = uclass_next_device(devp); 360 if (ret) 361 return ret; 362 if (!*devp) 363 return -ENODEV; 364 desc = dev_get_uclass_platdata(*devp); 365 if (desc->if_type == if_type) 366 return 0; 367 } while (1); 368 } 369 370 int blk_find_device(int if_type, int devnum, struct udevice **devp) 371 { 372 struct uclass *uc; 373 struct udevice *dev; 374 int ret; 375 376 ret = uclass_get(UCLASS_BLK, &uc); 377 if (ret) 378 return ret; 379 uclass_foreach_dev(dev, uc) { 380 struct blk_desc *desc = dev_get_uclass_platdata(dev); 381 382 debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__, 383 if_type, devnum, dev->name, desc->if_type, desc->devnum); 384 if (desc->if_type == if_type && desc->devnum == devnum) { 385 *devp = dev; 386 return 0; 387 } 388 } 389 390 return -ENODEV; 391 } 392 393 int blk_get_device(int if_type, int devnum, struct udevice **devp) 394 { 395 int ret; 396 397 ret = blk_find_device(if_type, devnum, devp); 398 if (ret) 399 return ret; 400 401 return device_probe(*devp); 402 } 403 404 unsigned long blk_dread(struct blk_desc *block_dev, lbaint_t start, 405 lbaint_t blkcnt, void *buffer) 406 { 407 struct udevice *dev = block_dev->bdev; 408 const struct blk_ops *ops = blk_get_ops(dev); 409 ulong blks_read; 410 411 if (!ops->read) 412 return -ENOSYS; 413 414 if (blkcache_read(block_dev->if_type, block_dev->devnum, 415 start, blkcnt, block_dev->blksz, buffer)) 416 return blkcnt; 417 blks_read = ops->read(dev, start, blkcnt, buffer); 418 if (blks_read == blkcnt) 419 blkcache_fill(block_dev->if_type, block_dev->devnum, 420 start, blkcnt, block_dev->blksz, buffer); 421 422 return blks_read; 423 } 424 425 unsigned long blk_dwrite(struct blk_desc *block_dev, lbaint_t start, 426 lbaint_t blkcnt, const void *buffer) 427 { 428 struct udevice *dev = block_dev->bdev; 429 const struct blk_ops *ops = blk_get_ops(dev); 430 431 if (!ops->write) 432 return -ENOSYS; 433 434 blkcache_invalidate(block_dev->if_type, block_dev->devnum); 435 return ops->write(dev, start, blkcnt, buffer); 436 } 437 438 unsigned long blk_derase(struct blk_desc *block_dev, lbaint_t start, 439 lbaint_t blkcnt) 440 { 441 struct udevice *dev = block_dev->bdev; 442 const struct blk_ops *ops = blk_get_ops(dev); 443 444 if (!ops->erase) 445 return -ENOSYS; 446 447 blkcache_invalidate(block_dev->if_type, block_dev->devnum); 448 return ops->erase(dev, start, blkcnt); 449 } 450 451 int blk_prepare_device(struct udevice *dev) 452 { 453 struct blk_desc *desc = dev_get_uclass_platdata(dev); 454 455 part_init(desc); 456 457 return 0; 458 } 459 460 int blk_get_from_parent(struct udevice *parent, struct udevice **devp) 461 { 462 struct udevice *dev; 463 enum uclass_id id; 464 int ret; 465 466 device_find_first_child(parent, &dev); 467 if (!dev) { 468 debug("%s: No block device found for parent '%s'\n", __func__, 469 parent->name); 470 return -ENODEV; 471 } 472 id = device_get_uclass_id(dev); 473 if (id != UCLASS_BLK) { 474 debug("%s: Incorrect uclass %s for block device '%s'\n", 475 __func__, uclass_get_name(id), dev->name); 476 return -ENOTBLK; 477 } 478 ret = device_probe(dev); 479 if (ret) 480 return ret; 481 *devp = dev; 482 483 return 0; 484 } 485 486 int blk_find_max_devnum(enum if_type if_type) 487 { 488 struct udevice *dev; 489 int max_devnum = -ENODEV; 490 struct uclass *uc; 491 int ret; 492 493 ret = uclass_get(UCLASS_BLK, &uc); 494 if (ret) 495 return ret; 496 uclass_foreach_dev(dev, uc) { 497 struct blk_desc *desc = dev_get_uclass_platdata(dev); 498 499 if (desc->if_type == if_type && desc->devnum > max_devnum) 500 max_devnum = desc->devnum; 501 } 502 503 return max_devnum; 504 } 505 506 static int blk_next_free_devnum(enum if_type if_type) 507 { 508 int ret; 509 510 ret = blk_find_max_devnum(if_type); 511 if (ret == -ENODEV) 512 return 0; 513 if (ret < 0) 514 return ret; 515 516 return ret + 1; 517 } 518 519 static int blk_claim_devnum(enum if_type if_type, int devnum) 520 { 521 struct udevice *dev; 522 struct uclass *uc; 523 int ret; 524 525 ret = uclass_get(UCLASS_BLK, &uc); 526 if (ret) 527 return ret; 528 uclass_foreach_dev(dev, uc) { 529 struct blk_desc *desc = dev_get_uclass_platdata(dev); 530 531 if (desc->if_type == if_type && desc->devnum == devnum) { 532 int next = blk_next_free_devnum(if_type); 533 534 if (next < 0) 535 return next; 536 desc->devnum = next; 537 return 0; 538 } 539 } 540 541 return -ENOENT; 542 } 543 544 int blk_create_device(struct udevice *parent, const char *drv_name, 545 const char *name, int if_type, int devnum, int blksz, 546 lbaint_t lba, struct udevice **devp) 547 { 548 struct blk_desc *desc; 549 struct udevice *dev; 550 int ret; 551 552 if (devnum == -1) { 553 devnum = blk_next_free_devnum(if_type); 554 } else { 555 ret = blk_claim_devnum(if_type, devnum); 556 if (ret < 0 && ret != -ENOENT) 557 return ret; 558 } 559 if (devnum < 0) 560 return devnum; 561 ret = device_bind_driver(parent, drv_name, name, &dev); 562 if (ret) 563 return ret; 564 desc = dev_get_uclass_platdata(dev); 565 desc->if_type = if_type; 566 desc->blksz = blksz; 567 desc->lba = lba; 568 desc->part_type = PART_TYPE_UNKNOWN; 569 desc->bdev = dev; 570 desc->devnum = devnum; 571 *devp = dev; 572 573 return 0; 574 } 575 576 int blk_create_devicef(struct udevice *parent, const char *drv_name, 577 const char *name, int if_type, int devnum, int blksz, 578 lbaint_t lba, struct udevice **devp) 579 { 580 char dev_name[30], *str; 581 int ret; 582 583 snprintf(dev_name, sizeof(dev_name), "%s.%s", parent->name, name); 584 str = strdup(dev_name); 585 if (!str) 586 return -ENOMEM; 587 588 ret = blk_create_device(parent, drv_name, str, if_type, devnum, 589 blksz, lba, devp); 590 if (ret) { 591 free(str); 592 return ret; 593 } 594 device_set_name_alloced(*devp); 595 596 return 0; 597 } 598 599 int blk_unbind_all(int if_type) 600 { 601 struct uclass *uc; 602 struct udevice *dev, *next; 603 int ret; 604 605 ret = uclass_get(UCLASS_BLK, &uc); 606 if (ret) 607 return ret; 608 uclass_foreach_dev_safe(dev, next, uc) { 609 struct blk_desc *desc = dev_get_uclass_platdata(dev); 610 611 if (desc->if_type == if_type) { 612 ret = device_remove(dev, DM_REMOVE_NORMAL); 613 if (ret) 614 return ret; 615 ret = device_unbind(dev); 616 if (ret) 617 return ret; 618 } 619 } 620 621 return 0; 622 } 623 624 UCLASS_DRIVER(blk) = { 625 .id = UCLASS_BLK, 626 .name = "blk", 627 .per_device_platdata_auto_alloc_size = sizeof(struct blk_desc), 628 }; 629