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