uboot/drivers/scsi/scsi.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2001
   4 * Denis Peter, MPL AG Switzerland
   5 */
   6
   7#include <common.h>
   8#include <blk.h>
   9#include <bootstage.h>
  10#include <dm.h>
  11#include <env.h>
  12#include <libata.h>
  13#include <log.h>
  14#include <part.h>
  15#include <pci.h>
  16#include <scsi.h>
  17#include <dm/device-internal.h>
  18#include <dm/uclass-internal.h>
  19
  20#if !defined(CONFIG_DM_SCSI)
  21# ifdef CONFIG_SCSI_DEV_LIST
  22#  define SCSI_DEV_LIST CONFIG_SCSI_DEV_LIST
  23# else
  24#  ifdef CONFIG_SATA_ULI5288
  25
  26#   define SCSI_VEND_ID 0x10b9
  27#   define SCSI_DEV_ID  0x5288
  28
  29#  elif !defined(CONFIG_SCSI_AHCI_PLAT)
  30#   error no scsi device defined
  31#  endif
  32# define SCSI_DEV_LIST {SCSI_VEND_ID, SCSI_DEV_ID}
  33# endif
  34#endif
  35
  36#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT) && \
  37        !defined(CONFIG_DM_SCSI)
  38const struct pci_device_id scsi_device_list[] = { SCSI_DEV_LIST };
  39#endif
  40static struct scsi_cmd tempccb; /* temporary scsi command buffer */
  41
  42static unsigned char tempbuff[512]; /* temporary data buffer */
  43
  44#if !defined(CONFIG_DM_SCSI)
  45static int scsi_max_devs; /* number of highest available scsi device */
  46
  47static int scsi_curr_dev; /* current device */
  48
  49static struct blk_desc scsi_dev_desc[SCSI_MAX_DEVICE];
  50#endif
  51
  52/* almost the maximum amount of the scsi_ext command.. */
  53#define SCSI_MAX_BLK 0xFFFF
  54#define SCSI_LBA48_READ 0xFFFFFFF
  55
  56static void scsi_print_error(struct scsi_cmd *pccb)
  57{
  58        /* Dummy function that could print an error for debugging */
  59}
  60
  61#ifdef CONFIG_SYS_64BIT_LBA
  62void scsi_setup_read16(struct scsi_cmd *pccb, lbaint_t start,
  63                       unsigned long blocks)
  64{
  65        pccb->cmd[0] = SCSI_READ16;
  66        pccb->cmd[1] = pccb->lun << 5;
  67        pccb->cmd[2] = (unsigned char)(start >> 56) & 0xff;
  68        pccb->cmd[3] = (unsigned char)(start >> 48) & 0xff;
  69        pccb->cmd[4] = (unsigned char)(start >> 40) & 0xff;
  70        pccb->cmd[5] = (unsigned char)(start >> 32) & 0xff;
  71        pccb->cmd[6] = (unsigned char)(start >> 24) & 0xff;
  72        pccb->cmd[7] = (unsigned char)(start >> 16) & 0xff;
  73        pccb->cmd[8] = (unsigned char)(start >> 8) & 0xff;
  74        pccb->cmd[9] = (unsigned char)start & 0xff;
  75        pccb->cmd[10] = 0;
  76        pccb->cmd[11] = (unsigned char)(blocks >> 24) & 0xff;
  77        pccb->cmd[12] = (unsigned char)(blocks >> 16) & 0xff;
  78        pccb->cmd[13] = (unsigned char)(blocks >> 8) & 0xff;
  79        pccb->cmd[14] = (unsigned char)blocks & 0xff;
  80        pccb->cmd[15] = 0;
  81        pccb->cmdlen = 16;
  82        pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
  83        debug("scsi_setup_read16: cmd: %02X %02X startblk %02X%02X%02X%02X%02X%02X%02X%02X blccnt %02X%02X%02X%02X\n",
  84              pccb->cmd[0], pccb->cmd[1],
  85              pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5],
  86              pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9],
  87              pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]);
  88}
  89#endif
  90
  91static void scsi_setup_inquiry(struct scsi_cmd *pccb)
  92{
  93        pccb->cmd[0] = SCSI_INQUIRY;
  94        pccb->cmd[1] = pccb->lun << 5;
  95        pccb->cmd[2] = 0;
  96        pccb->cmd[3] = 0;
  97        if (pccb->datalen > 255)
  98                pccb->cmd[4] = 255;
  99        else
 100                pccb->cmd[4] = (unsigned char)pccb->datalen;
 101        pccb->cmd[5] = 0;
 102        pccb->cmdlen = 6;
 103        pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
 104}
 105
 106#ifdef CONFIG_BLK
 107static void scsi_setup_read_ext(struct scsi_cmd *pccb, lbaint_t start,
 108                                unsigned short blocks)
 109{
 110        pccb->cmd[0] = SCSI_READ10;
 111        pccb->cmd[1] = pccb->lun << 5;
 112        pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff;
 113        pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff;
 114        pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff;
 115        pccb->cmd[5] = (unsigned char)start & 0xff;
 116        pccb->cmd[6] = 0;
 117        pccb->cmd[7] = (unsigned char)(blocks >> 8) & 0xff;
 118        pccb->cmd[8] = (unsigned char)blocks & 0xff;
 119        pccb->cmd[6] = 0;
 120        pccb->cmdlen = 10;
 121        pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
 122        debug("scsi_setup_read_ext: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n",
 123              pccb->cmd[0], pccb->cmd[1],
 124              pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5],
 125              pccb->cmd[7], pccb->cmd[8]);
 126}
 127
 128static void scsi_setup_write_ext(struct scsi_cmd *pccb, lbaint_t start,
 129                                 unsigned short blocks)
 130{
 131        pccb->cmd[0] = SCSI_WRITE10;
 132        pccb->cmd[1] = pccb->lun << 5;
 133        pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff;
 134        pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff;
 135        pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff;
 136        pccb->cmd[5] = (unsigned char)start & 0xff;
 137        pccb->cmd[6] = 0;
 138        pccb->cmd[7] = ((unsigned char)(blocks >> 8)) & 0xff;
 139        pccb->cmd[8] = (unsigned char)blocks & 0xff;
 140        pccb->cmd[9] = 0;
 141        pccb->cmdlen = 10;
 142        pccb->msgout[0] = SCSI_IDENTIFY;  /* NOT USED */
 143        debug("%s: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n",
 144              __func__,
 145              pccb->cmd[0], pccb->cmd[1],
 146              pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5],
 147              pccb->cmd[7], pccb->cmd[8]);
 148}
 149
 150static ulong scsi_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
 151                       void *buffer)
 152{
 153        struct blk_desc *block_dev = dev_get_uclass_plat(dev);
 154        struct udevice *bdev = dev->parent;
 155        struct scsi_plat *uc_plat = dev_get_uclass_plat(bdev);
 156        lbaint_t start, blks, max_blks;
 157        uintptr_t buf_addr;
 158        unsigned short smallblks = 0;
 159        struct scsi_cmd *pccb = (struct scsi_cmd *)&tempccb;
 160
 161        /* Setup device */
 162        pccb->target = block_dev->target;
 163        pccb->lun = block_dev->lun;
 164        buf_addr = (unsigned long)buffer;
 165        start = blknr;
 166        blks = blkcnt;
 167        if (uc_plat->max_bytes_per_req)
 168                max_blks = uc_plat->max_bytes_per_req / block_dev->blksz;
 169        else
 170                max_blks = SCSI_MAX_BLK;
 171
 172        debug("\nscsi_read: dev %d startblk " LBAF
 173              ", blccnt " LBAF " buffer %lx\n",
 174              block_dev->devnum, start, blks, (unsigned long)buffer);
 175        do {
 176                pccb->pdata = (unsigned char *)buf_addr;
 177                pccb->dma_dir = DMA_FROM_DEVICE;
 178#ifdef CONFIG_SYS_64BIT_LBA
 179                if (start > SCSI_LBA48_READ) {
 180                        unsigned long blocks;
 181                        blocks = min_t(lbaint_t, blks, max_blks);
 182                        pccb->datalen = block_dev->blksz * blocks;
 183                        scsi_setup_read16(pccb, start, blocks);
 184                        start += blocks;
 185                        blks -= blocks;
 186                } else
 187#endif
 188                if (blks > max_blks) {
 189                        pccb->datalen = block_dev->blksz * max_blks;
 190                        smallblks = max_blks;
 191                        scsi_setup_read_ext(pccb, start, smallblks);
 192                        start += max_blks;
 193                        blks -= max_blks;
 194                } else {
 195                        pccb->datalen = block_dev->blksz * blks;
 196                        smallblks = (unsigned short)blks;
 197                        scsi_setup_read_ext(pccb, start, smallblks);
 198                        start += blks;
 199                        blks = 0;
 200                }
 201                debug("scsi_read_ext: startblk " LBAF
 202                      ", blccnt %x buffer %lX\n",
 203                      start, smallblks, buf_addr);
 204                if (scsi_exec(bdev, pccb)) {
 205                        scsi_print_error(pccb);
 206                        blkcnt -= blks;
 207                        break;
 208                }
 209                buf_addr += pccb->datalen;
 210        } while (blks != 0);
 211        debug("scsi_read_ext: end startblk " LBAF
 212              ", blccnt %x buffer %lX\n", start, smallblks, buf_addr);
 213        return blkcnt;
 214}
 215
 216/*******************************************************************************
 217 * scsi_write
 218 */
 219
 220static ulong scsi_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
 221                        const void *buffer)
 222{
 223        struct blk_desc *block_dev = dev_get_uclass_plat(dev);
 224        struct udevice *bdev = dev->parent;
 225        struct scsi_plat *uc_plat = dev_get_uclass_plat(bdev);
 226        lbaint_t start, blks, max_blks;
 227        uintptr_t buf_addr;
 228        unsigned short smallblks;
 229        struct scsi_cmd *pccb = (struct scsi_cmd *)&tempccb;
 230
 231        /* Setup device */
 232        pccb->target = block_dev->target;
 233        pccb->lun = block_dev->lun;
 234        buf_addr = (unsigned long)buffer;
 235        start = blknr;
 236        blks = blkcnt;
 237        if (uc_plat->max_bytes_per_req)
 238                max_blks = uc_plat->max_bytes_per_req / block_dev->blksz;
 239        else
 240                max_blks = SCSI_MAX_BLK;
 241
 242        debug("\n%s: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
 243              __func__, block_dev->devnum, start, blks, (unsigned long)buffer);
 244        do {
 245                pccb->pdata = (unsigned char *)buf_addr;
 246                pccb->dma_dir = DMA_TO_DEVICE;
 247                if (blks > max_blks) {
 248                        pccb->datalen = block_dev->blksz * max_blks;
 249                        smallblks = max_blks;
 250                        scsi_setup_write_ext(pccb, start, smallblks);
 251                        start += max_blks;
 252                        blks -= max_blks;
 253                } else {
 254                        pccb->datalen = block_dev->blksz * blks;
 255                        smallblks = (unsigned short)blks;
 256                        scsi_setup_write_ext(pccb, start, smallblks);
 257                        start += blks;
 258                        blks = 0;
 259                }
 260                debug("%s: startblk " LBAF ", blccnt %x buffer %lx\n",
 261                      __func__, start, smallblks, buf_addr);
 262                if (scsi_exec(bdev, pccb)) {
 263                        scsi_print_error(pccb);
 264                        blkcnt -= blks;
 265                        break;
 266                }
 267                buf_addr += pccb->datalen;
 268        } while (blks != 0);
 269        debug("%s: end startblk " LBAF ", blccnt %x buffer %lX\n",
 270              __func__, start, smallblks, buf_addr);
 271        return blkcnt;
 272}
 273#endif
 274
 275#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT) && \
 276        !defined(CONFIG_DM_SCSI)
 277void scsi_init(void)
 278{
 279        int busdevfunc = -1;
 280        int i;
 281        /*
 282         * Find a device from the list, this driver will support a single
 283         * controller.
 284         */
 285        for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) {
 286                /* get PCI Device ID */
 287                struct udevice *dev;
 288                int ret;
 289
 290                ret = dm_pci_find_device(scsi_device_list[i].vendor,
 291                                         scsi_device_list[i].device, 0, &dev);
 292                if (!ret) {
 293                        busdevfunc = dm_pci_get_bdf(dev);
 294                        break;
 295                }
 296                if (busdevfunc != -1)
 297                        break;
 298        }
 299
 300        if (busdevfunc == -1) {
 301                printf("Error: SCSI Controller(s) ");
 302                for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) {
 303                        printf("%04X:%04X ",
 304                               scsi_device_list[i].vendor,
 305                               scsi_device_list[i].device);
 306                }
 307                printf("not found\n");
 308                return;
 309        }
 310#ifdef DEBUG
 311        else {
 312                printf("SCSI Controller (%04X,%04X) found (%d:%d:%d)\n",
 313                       scsi_device_list[i].vendor,
 314                       scsi_device_list[i].device,
 315                       (busdevfunc >> 16) & 0xFF,
 316                       (busdevfunc >> 11) & 0x1F,
 317                       (busdevfunc >> 8) & 0x7);
 318        }
 319#endif
 320        bootstage_start(BOOTSTAGE_ID_ACCUM_SCSI, "ahci");
 321        scsi_low_level_init(busdevfunc);
 322        scsi_scan(true);
 323        bootstage_accum(BOOTSTAGE_ID_ACCUM_SCSI);
 324}
 325#endif
 326
 327/* copy src to dest, skipping leading and trailing blanks
 328 * and null terminate the string
 329 */
 330static void scsi_ident_cpy(unsigned char *dest, unsigned char *src,
 331                           unsigned int len)
 332{
 333        int start, end;
 334
 335        start = 0;
 336        while (start < len) {
 337                if (src[start] != ' ')
 338                        break;
 339                start++;
 340        }
 341        end = len-1;
 342        while (end > start) {
 343                if (src[end] != ' ')
 344                        break;
 345                end--;
 346        }
 347        for (; start <= end; start++)
 348                *dest ++= src[start];
 349        *dest = '\0';
 350}
 351
 352static int scsi_read_capacity(struct udevice *dev, struct scsi_cmd *pccb,
 353                              lbaint_t *capacity, unsigned long *blksz)
 354{
 355        *capacity = 0;
 356
 357        memset(pccb->cmd, '\0', sizeof(pccb->cmd));
 358        pccb->cmd[0] = SCSI_RD_CAPAC10;
 359        pccb->cmd[1] = pccb->lun << 5;
 360        pccb->cmdlen = 10;
 361        pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
 362
 363        pccb->datalen = 8;
 364        if (scsi_exec(dev, pccb))
 365                return 1;
 366
 367        *capacity = ((lbaint_t)pccb->pdata[0] << 24) |
 368                    ((lbaint_t)pccb->pdata[1] << 16) |
 369                    ((lbaint_t)pccb->pdata[2] << 8)  |
 370                    ((lbaint_t)pccb->pdata[3]);
 371
 372        if (*capacity != 0xffffffff) {
 373                /* Read capacity (10) was sufficient for this drive. */
 374                *blksz = ((unsigned long)pccb->pdata[4] << 24) |
 375                         ((unsigned long)pccb->pdata[5] << 16) |
 376                         ((unsigned long)pccb->pdata[6] << 8)  |
 377                         ((unsigned long)pccb->pdata[7]);
 378                return 0;
 379        }
 380
 381        /* Read capacity (10) was insufficient. Use read capacity (16). */
 382        memset(pccb->cmd, '\0', sizeof(pccb->cmd));
 383        pccb->cmd[0] = SCSI_RD_CAPAC16;
 384        pccb->cmd[1] = 0x10;
 385        pccb->cmdlen = 16;
 386        pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
 387
 388        pccb->datalen = 16;
 389        pccb->dma_dir = DMA_FROM_DEVICE;
 390        if (scsi_exec(dev, pccb))
 391                return 1;
 392
 393        *capacity = ((uint64_t)pccb->pdata[0] << 56) |
 394                    ((uint64_t)pccb->pdata[1] << 48) |
 395                    ((uint64_t)pccb->pdata[2] << 40) |
 396                    ((uint64_t)pccb->pdata[3] << 32) |
 397                    ((uint64_t)pccb->pdata[4] << 24) |
 398                    ((uint64_t)pccb->pdata[5] << 16) |
 399                    ((uint64_t)pccb->pdata[6] << 8)  |
 400                    ((uint64_t)pccb->pdata[7]);
 401
 402        *blksz = ((uint64_t)pccb->pdata[8]  << 56) |
 403                 ((uint64_t)pccb->pdata[9]  << 48) |
 404                 ((uint64_t)pccb->pdata[10] << 40) |
 405                 ((uint64_t)pccb->pdata[11] << 32) |
 406                 ((uint64_t)pccb->pdata[12] << 24) |
 407                 ((uint64_t)pccb->pdata[13] << 16) |
 408                 ((uint64_t)pccb->pdata[14] << 8)  |
 409                 ((uint64_t)pccb->pdata[15]);
 410
 411        return 0;
 412}
 413
 414
 415/*
 416 * Some setup (fill-in) routines
 417 */
 418static void scsi_setup_test_unit_ready(struct scsi_cmd *pccb)
 419{
 420        pccb->cmd[0] = SCSI_TST_U_RDY;
 421        pccb->cmd[1] = pccb->lun << 5;
 422        pccb->cmd[2] = 0;
 423        pccb->cmd[3] = 0;
 424        pccb->cmd[4] = 0;
 425        pccb->cmd[5] = 0;
 426        pccb->cmdlen = 6;
 427        pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
 428}
 429
 430/**
 431 * scsi_init_dev_desc_priv - initialize only SCSI specific blk_desc properties
 432 *
 433 * @dev_desc: Block device description pointer
 434 */
 435static void scsi_init_dev_desc_priv(struct blk_desc *dev_desc)
 436{
 437        dev_desc->target = 0xff;
 438        dev_desc->lun = 0xff;
 439        dev_desc->log2blksz =
 440                LOG2_INVALID(typeof(dev_desc->log2blksz));
 441        dev_desc->type = DEV_TYPE_UNKNOWN;
 442        dev_desc->vendor[0] = 0;
 443        dev_desc->product[0] = 0;
 444        dev_desc->revision[0] = 0;
 445        dev_desc->removable = false;
 446}
 447
 448#if !defined(CONFIG_DM_SCSI)
 449/**
 450 * scsi_init_dev_desc - initialize all SCSI specific blk_desc properties
 451 *
 452 * @dev_desc: Block device description pointer
 453 * @devnum: Device number
 454 */
 455static void scsi_init_dev_desc(struct blk_desc *dev_desc, int devnum)
 456{
 457        dev_desc->lba = 0;
 458        dev_desc->blksz = 0;
 459        dev_desc->uclass_id = UCLASS_SCSI;
 460        dev_desc->devnum = devnum;
 461        dev_desc->part_type = PART_TYPE_UNKNOWN;
 462
 463        scsi_init_dev_desc_priv(dev_desc);
 464}
 465#endif
 466
 467/**
 468 * scsi_detect_dev - Detect scsi device
 469 *
 470 * @target: target id
 471 * @lun: target lun
 472 * @dev_desc: block device description
 473 *
 474 * The scsi_detect_dev detects and fills a dev_desc structure when the device is
 475 * detected.
 476 *
 477 * Return: 0 on success, error value otherwise
 478 */
 479static int scsi_detect_dev(struct udevice *dev, int target, int lun,
 480                           struct blk_desc *dev_desc)
 481{
 482        unsigned char perq, modi;
 483        lbaint_t capacity;
 484        unsigned long blksz;
 485        struct scsi_cmd *pccb = (struct scsi_cmd *)&tempccb;
 486        int count, err;
 487
 488        pccb->target = target;
 489        pccb->lun = lun;
 490        pccb->pdata = (unsigned char *)&tempbuff;
 491        pccb->datalen = 512;
 492        pccb->dma_dir = DMA_FROM_DEVICE;
 493        scsi_setup_inquiry(pccb);
 494        if (scsi_exec(dev, pccb)) {
 495                if (pccb->contr_stat == SCSI_SEL_TIME_OUT) {
 496                        /*
 497                          * selection timeout => assuming no
 498                          * device present
 499                          */
 500                        debug("Selection timeout ID %d\n",
 501                              pccb->target);
 502                        return -ETIMEDOUT;
 503                }
 504                scsi_print_error(pccb);
 505                return -ENODEV;
 506        }
 507        perq = tempbuff[0];
 508        modi = tempbuff[1];
 509        if ((perq & 0x1f) == 0x1f)
 510                return -ENODEV; /* skip unknown devices */
 511        if ((modi & 0x80) == 0x80) /* drive is removable */
 512                dev_desc->removable = true;
 513        /* get info for this device */
 514        scsi_ident_cpy((unsigned char *)dev_desc->vendor,
 515                       &tempbuff[8], 8);
 516        scsi_ident_cpy((unsigned char *)dev_desc->product,
 517                       &tempbuff[16], 16);
 518        scsi_ident_cpy((unsigned char *)dev_desc->revision,
 519                       &tempbuff[32], 4);
 520        dev_desc->target = pccb->target;
 521        dev_desc->lun = pccb->lun;
 522
 523        for (count = 0; count < 3; count++) {
 524                pccb->datalen = 0;
 525                scsi_setup_test_unit_ready(pccb);
 526                err = scsi_exec(dev, pccb);
 527                if (!err)
 528                        break;
 529        }
 530        if (err) {
 531                if (dev_desc->removable) {
 532                        dev_desc->type = perq;
 533                        goto removable;
 534                }
 535                scsi_print_error(pccb);
 536                return -EINVAL;
 537        }
 538        if (scsi_read_capacity(dev, pccb, &capacity, &blksz)) {
 539                scsi_print_error(pccb);
 540                return -EINVAL;
 541        }
 542        dev_desc->lba = capacity;
 543        dev_desc->blksz = blksz;
 544        dev_desc->log2blksz = LOG2(dev_desc->blksz);
 545        dev_desc->type = perq;
 546removable:
 547        return 0;
 548}
 549
 550/*
 551 * (re)-scan the scsi bus and reports scsi device info
 552 * to the user if mode = 1
 553 */
 554#if defined(CONFIG_DM_SCSI)
 555static int do_scsi_scan_one(struct udevice *dev, int id, int lun, bool verbose)
 556{
 557        int ret;
 558        struct udevice *bdev;
 559        struct blk_desc bd;
 560        struct blk_desc *bdesc;
 561        char str[10];
 562
 563        /*
 564         * detect the scsi driver to get information about its geometry (block
 565         * size, number of blocks) and other parameters (ids, type, ...)
 566         */
 567        scsi_init_dev_desc_priv(&bd);
 568        if (scsi_detect_dev(dev, id, lun, &bd))
 569                return -ENODEV;
 570
 571        /*
 572        * Create only one block device and do detection
 573        * to make sure that there won't be a lot of
 574        * block devices created
 575        */
 576        snprintf(str, sizeof(str), "id%dlun%d", id, lun);
 577        ret = blk_create_devicef(dev, "scsi_blk", str, UCLASS_SCSI, -1,
 578                                 bd.blksz, bd.lba, &bdev);
 579        if (ret) {
 580                debug("Can't create device\n");
 581                return ret;
 582        }
 583
 584        bdesc = dev_get_uclass_plat(bdev);
 585        bdesc->target = id;
 586        bdesc->lun = lun;
 587        bdesc->removable = bd.removable;
 588        bdesc->type = bd.type;
 589        memcpy(&bdesc->vendor, &bd.vendor, sizeof(bd.vendor));
 590        memcpy(&bdesc->product, &bd.product, sizeof(bd.product));
 591        memcpy(&bdesc->revision, &bd.revision,  sizeof(bd.revision));
 592        if (IS_ENABLED(CONFIG_SYS_BIG_ENDIAN)) {
 593                ata_swap_buf_le16((u16 *)&bdesc->vendor, sizeof(bd.vendor) / 2);
 594                ata_swap_buf_le16((u16 *)&bdesc->product, sizeof(bd.product) / 2);
 595                ata_swap_buf_le16((u16 *)&bdesc->revision, sizeof(bd.revision) / 2);
 596        }
 597
 598        ret = blk_probe_or_unbind(bdev);
 599        if (ret < 0)
 600                /* TODO: undo create */
 601                return ret;
 602
 603        if (verbose) {
 604                printf("  Device %d: ", bdesc->devnum);
 605                dev_print(bdesc);
 606        }
 607        return 0;
 608}
 609
 610int scsi_scan_dev(struct udevice *dev, bool verbose)
 611{
 612        struct scsi_plat *uc_plat; /* scsi controller plat */
 613        int ret;
 614        int i;
 615        int lun;
 616
 617        /* probe SCSI controller driver */
 618        ret = device_probe(dev);
 619        if (ret)
 620                return ret;
 621
 622        /* Get controller plat */
 623        uc_plat = dev_get_uclass_plat(dev);
 624
 625        for (i = 0; i < uc_plat->max_id; i++)
 626                for (lun = 0; lun < uc_plat->max_lun; lun++)
 627                        do_scsi_scan_one(dev, i, lun, verbose);
 628
 629        return 0;
 630}
 631
 632int scsi_scan(bool verbose)
 633{
 634        struct uclass *uc;
 635        struct udevice *dev; /* SCSI controller */
 636        int ret;
 637
 638        if (verbose)
 639                printf("scanning bus for devices...\n");
 640
 641        blk_unbind_all(UCLASS_SCSI);
 642
 643        ret = uclass_get(UCLASS_SCSI, &uc);
 644        if (ret)
 645                return ret;
 646
 647        uclass_foreach_dev(dev, uc) {
 648                ret = scsi_scan_dev(dev, verbose);
 649                if (ret)
 650                        return ret;
 651        }
 652
 653        return 0;
 654}
 655#else
 656int scsi_scan(bool verbose)
 657{
 658        unsigned char i, lun;
 659        int ret;
 660
 661        if (verbose)
 662                printf("scanning bus for devices...\n");
 663        for (i = 0; i < SCSI_MAX_DEVICE; i++)
 664                scsi_init_dev_desc(&scsi_dev_desc[i], i);
 665
 666        scsi_max_devs = 0;
 667        for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) {
 668                for (lun = 0; lun < CONFIG_SYS_SCSI_MAX_LUN; lun++) {
 669                        struct blk_desc *bdesc = &scsi_dev_desc[scsi_max_devs];
 670
 671                        ret = scsi_detect_dev(NULL, i, lun, bdesc);
 672                        if (ret)
 673                                continue;
 674                        part_init(bdesc);
 675
 676                        if (verbose) {
 677                                printf("  Device %d: ", bdesc->devnum);
 678                                dev_print(bdesc);
 679                        }
 680                        scsi_max_devs++;
 681                } /* next LUN */
 682        }
 683        if (scsi_max_devs > 0)
 684                scsi_curr_dev = 0;
 685        else
 686                scsi_curr_dev = -1;
 687
 688        printf("Found %d device(s).\n", scsi_max_devs);
 689#ifndef CONFIG_SPL_BUILD
 690        env_set_ulong("scsidevs", scsi_max_devs);
 691#endif
 692        return 0;
 693}
 694#endif
 695
 696#ifdef CONFIG_BLK
 697static const struct blk_ops scsi_blk_ops = {
 698        .read   = scsi_read,
 699        .write  = scsi_write,
 700};
 701
 702U_BOOT_DRIVER(scsi_blk) = {
 703        .name           = "scsi_blk",
 704        .id             = UCLASS_BLK,
 705        .ops            = &scsi_blk_ops,
 706};
 707#else
 708U_BOOT_LEGACY_BLK(scsi) = {
 709        .uclass_idname  = "scsi",
 710        .uclass_id      = UCLASS_SCSI,
 711        .max_devs       = SCSI_MAX_DEVICE,
 712        .desc           = scsi_dev_desc,
 713};
 714#endif
 715