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