uboot/common/scsi.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2001
   3 * Denis Peter, MPL AG Switzerland
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8#include <common.h>
   9#include <dm.h>
  10#include <inttypes.h>
  11#include <pci.h>
  12#include <scsi.h>
  13
  14#ifdef CONFIG_SCSI_DEV_LIST
  15#define SCSI_DEV_LIST CONFIG_SCSI_DEV_LIST
  16#else
  17#ifdef CONFIG_SCSI_SYM53C8XX
  18#define SCSI_VEND_ID    0x1000
  19#ifndef CONFIG_SCSI_DEV_ID
  20#define SCSI_DEV_ID             0x0001
  21#else
  22#define SCSI_DEV_ID             CONFIG_SCSI_DEV_ID
  23#endif
  24#elif defined 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
  35#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT)
  36const struct pci_device_id scsi_device_list[] = { SCSI_DEV_LIST };
  37#endif
  38static ccb tempccb;     /* temporary scsi command buffer */
  39
  40static unsigned char tempbuff[512]; /* temporary data buffer */
  41
  42static int scsi_max_devs; /* number of highest available scsi device */
  43
  44static int scsi_curr_dev; /* current device */
  45
  46static struct blk_desc scsi_dev_desc[CONFIG_SYS_SCSI_MAX_DEVICE];
  47
  48/* almost the maximum amount of the scsi_ext command.. */
  49#define SCSI_MAX_READ_BLK 0xFFFF
  50#define SCSI_LBA48_READ 0xFFFFFFF
  51
  52#ifdef CONFIG_SYS_64BIT_LBA
  53void scsi_setup_read16(ccb *pccb, lbaint_t start, unsigned long blocks)
  54{
  55        pccb->cmd[0] = SCSI_READ16;
  56        pccb->cmd[1] = pccb->lun << 5;
  57        pccb->cmd[2] = (unsigned char)(start >> 56) & 0xff;
  58        pccb->cmd[3] = (unsigned char)(start >> 48) & 0xff;
  59        pccb->cmd[4] = (unsigned char)(start >> 40) & 0xff;
  60        pccb->cmd[5] = (unsigned char)(start >> 32) & 0xff;
  61        pccb->cmd[6] = (unsigned char)(start >> 24) & 0xff;
  62        pccb->cmd[7] = (unsigned char)(start >> 16) & 0xff;
  63        pccb->cmd[8] = (unsigned char)(start >> 8) & 0xff;
  64        pccb->cmd[9] = (unsigned char)start & 0xff;
  65        pccb->cmd[10] = 0;
  66        pccb->cmd[11] = (unsigned char)(blocks >> 24) & 0xff;
  67        pccb->cmd[12] = (unsigned char)(blocks >> 16) & 0xff;
  68        pccb->cmd[13] = (unsigned char)(blocks >> 8) & 0xff;
  69        pccb->cmd[14] = (unsigned char)blocks & 0xff;
  70        pccb->cmd[15] = 0;
  71        pccb->cmdlen = 16;
  72        pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
  73        debug("scsi_setup_read16: cmd: %02X %02X startblk %02X%02X%02X%02X%02X%02X%02X%02X blccnt %02X%02X%02X%02X\n",
  74              pccb->cmd[0], pccb->cmd[1],
  75              pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5],
  76              pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9],
  77              pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]);
  78}
  79#endif
  80
  81void scsi_setup_read_ext(ccb *pccb, lbaint_t start, unsigned short blocks)
  82{
  83        pccb->cmd[0] = SCSI_READ10;
  84        pccb->cmd[1] = pccb->lun << 5;
  85        pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff;
  86        pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff;
  87        pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff;
  88        pccb->cmd[5] = (unsigned char)start & 0xff;
  89        pccb->cmd[6] = 0;
  90        pccb->cmd[7] = (unsigned char)(blocks >> 8) & 0xff;
  91        pccb->cmd[8] = (unsigned char)blocks & 0xff;
  92        pccb->cmd[6] = 0;
  93        pccb->cmdlen = 10;
  94        pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
  95        debug("scsi_setup_read_ext: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n",
  96              pccb->cmd[0], pccb->cmd[1],
  97              pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5],
  98              pccb->cmd[7], pccb->cmd[8]);
  99}
 100
 101void scsi_setup_write_ext(ccb *pccb, lbaint_t start, unsigned short blocks)
 102{
 103        pccb->cmd[0] = SCSI_WRITE10;
 104        pccb->cmd[1] = pccb->lun << 5;
 105        pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff;
 106        pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff;
 107        pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff;
 108        pccb->cmd[5] = (unsigned char)start & 0xff;
 109        pccb->cmd[6] = 0;
 110        pccb->cmd[7] = ((unsigned char)(blocks >> 8)) & 0xff;
 111        pccb->cmd[8] = (unsigned char)blocks & 0xff;
 112        pccb->cmd[9] = 0;
 113        pccb->cmdlen = 10;
 114        pccb->msgout[0] = SCSI_IDENTIFY;  /* NOT USED */
 115        debug("%s: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n",
 116              __func__,
 117              pccb->cmd[0], pccb->cmd[1],
 118              pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5],
 119              pccb->cmd[7], pccb->cmd[8]);
 120}
 121
 122void scsi_setup_read6(ccb *pccb, lbaint_t start, unsigned short blocks)
 123{
 124        pccb->cmd[0] = SCSI_READ6;
 125        pccb->cmd[1] = pccb->lun << 5 | ((unsigned char)(start >> 16) & 0x1f);
 126        pccb->cmd[2] = (unsigned char)(start >> 8) & 0xff;
 127        pccb->cmd[3] = (unsigned char)start & 0xff;
 128        pccb->cmd[4] = (unsigned char)blocks & 0xff;
 129        pccb->cmd[5] = 0;
 130        pccb->cmdlen = 6;
 131        pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
 132        debug("scsi_setup_read6: cmd: %02X %02X startblk %02X%02X blccnt %02X\n",
 133              pccb->cmd[0], pccb->cmd[1],
 134              pccb->cmd[2], pccb->cmd[3], pccb->cmd[4]);
 135}
 136
 137
 138void scsi_setup_inquiry(ccb *pccb)
 139{
 140        pccb->cmd[0] = SCSI_INQUIRY;
 141        pccb->cmd[1] = pccb->lun << 5;
 142        pccb->cmd[2] = 0;
 143        pccb->cmd[3] = 0;
 144        if (pccb->datalen > 255)
 145                pccb->cmd[4] = 255;
 146        else
 147                pccb->cmd[4] = (unsigned char)pccb->datalen;
 148        pccb->cmd[5] = 0;
 149        pccb->cmdlen = 6;
 150        pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
 151}
 152
 153#ifdef CONFIG_BLK
 154static ulong scsi_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
 155                       void *buffer)
 156#else
 157static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr,
 158                       lbaint_t blkcnt, void *buffer)
 159#endif
 160{
 161#ifdef CONFIG_BLK
 162        struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
 163#endif
 164        int device = block_dev->devnum;
 165        lbaint_t start, blks;
 166        uintptr_t buf_addr;
 167        unsigned short smallblks = 0;
 168        ccb *pccb = (ccb *)&tempccb;
 169        device &= 0xff;
 170
 171        /* Setup device */
 172        pccb->target = scsi_dev_desc[device].target;
 173        pccb->lun = scsi_dev_desc[device].lun;
 174        buf_addr = (unsigned long)buffer;
 175        start = blknr;
 176        blks = blkcnt;
 177        debug("\nscsi_read: dev %d startblk " LBAF
 178              ", blccnt " LBAF " buffer %lx\n",
 179              device, start, blks, (unsigned long)buffer);
 180        do {
 181                pccb->pdata = (unsigned char *)buf_addr;
 182#ifdef CONFIG_SYS_64BIT_LBA
 183                if (start > SCSI_LBA48_READ) {
 184                        unsigned long blocks;
 185                        blocks = min_t(lbaint_t, blks, SCSI_MAX_READ_BLK);
 186                        pccb->datalen = scsi_dev_desc[device].blksz * blocks;
 187                        scsi_setup_read16(pccb, start, blocks);
 188                        start += blocks;
 189                        blks -= blocks;
 190                } else
 191#endif
 192                if (blks > SCSI_MAX_READ_BLK) {
 193                        pccb->datalen = scsi_dev_desc[device].blksz *
 194                                SCSI_MAX_READ_BLK;
 195                        smallblks = SCSI_MAX_READ_BLK;
 196                        scsi_setup_read_ext(pccb, start, smallblks);
 197                        start += SCSI_MAX_READ_BLK;
 198                        blks -= SCSI_MAX_READ_BLK;
 199                } else {
 200                        pccb->datalen = scsi_dev_desc[device].blksz * blks;
 201                        smallblks = (unsigned short)blks;
 202                        scsi_setup_read_ext(pccb, start, smallblks);
 203                        start += blks;
 204                        blks = 0;
 205                }
 206                debug("scsi_read_ext: startblk " LBAF
 207                      ", blccnt %x buffer %" PRIXPTR "\n",
 208                      start, smallblks, buf_addr);
 209                if (scsi_exec(pccb) != true) {
 210                        scsi_print_error(pccb);
 211                        blkcnt -= blks;
 212                        break;
 213                }
 214                buf_addr += pccb->datalen;
 215        } while (blks != 0);
 216        debug("scsi_read_ext: end startblk " LBAF
 217              ", blccnt %x buffer %" PRIXPTR "\n", start, smallblks, buf_addr);
 218        return blkcnt;
 219}
 220
 221/*******************************************************************************
 222 * scsi_write
 223 */
 224
 225/* Almost the maximum amount of the scsi_ext command.. */
 226#define SCSI_MAX_WRITE_BLK 0xFFFF
 227
 228#ifdef CONFIG_BLK
 229static ulong scsi_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
 230                        const void *buffer)
 231#else
 232static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr,
 233                        lbaint_t blkcnt, const void *buffer)
 234#endif
 235{
 236#ifdef CONFIG_BLK
 237        struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
 238#endif
 239        int device = block_dev->devnum;
 240        lbaint_t start, blks;
 241        uintptr_t buf_addr;
 242        unsigned short smallblks;
 243        ccb *pccb = (ccb *)&tempccb;
 244
 245        device &= 0xff;
 246
 247        /* Setup device */
 248        pccb->target = scsi_dev_desc[device].target;
 249        pccb->lun = scsi_dev_desc[device].lun;
 250        buf_addr = (unsigned long)buffer;
 251        start = blknr;
 252        blks = blkcnt;
 253        debug("\n%s: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
 254              __func__, device, start, blks, (unsigned long)buffer);
 255        do {
 256                pccb->pdata = (unsigned char *)buf_addr;
 257                if (blks > SCSI_MAX_WRITE_BLK) {
 258                        pccb->datalen = (scsi_dev_desc[device].blksz *
 259                                         SCSI_MAX_WRITE_BLK);
 260                        smallblks = SCSI_MAX_WRITE_BLK;
 261                        scsi_setup_write_ext(pccb, start, smallblks);
 262                        start += SCSI_MAX_WRITE_BLK;
 263                        blks -= SCSI_MAX_WRITE_BLK;
 264                } else {
 265                        pccb->datalen = scsi_dev_desc[device].blksz * blks;
 266                        smallblks = (unsigned short)blks;
 267                        scsi_setup_write_ext(pccb, start, smallblks);
 268                        start += blks;
 269                        blks = 0;
 270                }
 271                debug("%s: startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n",
 272                      __func__, start, smallblks, buf_addr);
 273                if (scsi_exec(pccb) != true) {
 274                        scsi_print_error(pccb);
 275                        blkcnt -= blks;
 276                        break;
 277                }
 278                buf_addr += pccb->datalen;
 279        } while (blks != 0);
 280        debug("%s: end startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n",
 281              __func__, start, smallblks, buf_addr);
 282        return blkcnt;
 283}
 284
 285int scsi_get_disk_count(void)
 286{
 287        return scsi_max_devs;
 288}
 289
 290#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT)
 291void scsi_init(void)
 292{
 293        int busdevfunc = -1;
 294        int i;
 295        /*
 296         * Find a device from the list, this driver will support a single
 297         * controller.
 298         */
 299        for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) {
 300                /* get PCI Device ID */
 301#ifdef CONFIG_DM_PCI
 302                struct udevice *dev;
 303                int ret;
 304
 305                ret = dm_pci_find_device(scsi_device_list[i].vendor,
 306                                         scsi_device_list[i].device, 0, &dev);
 307                if (!ret) {
 308                        busdevfunc = dm_pci_get_bdf(dev);
 309                        break;
 310                }
 311#else
 312                busdevfunc = pci_find_device(scsi_device_list[i].vendor,
 313                                             scsi_device_list[i].device,
 314                                             0);
 315#endif
 316                if (busdevfunc != -1)
 317                        break;
 318        }
 319
 320        if (busdevfunc == -1) {
 321                printf("Error: SCSI Controller(s) ");
 322                for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) {
 323                        printf("%04X:%04X ",
 324                               scsi_device_list[i].vendor,
 325                               scsi_device_list[i].device);
 326                }
 327                printf("not found\n");
 328                return;
 329        }
 330#ifdef DEBUG
 331        else {
 332                printf("SCSI Controller (%04X,%04X) found (%d:%d:%d)\n",
 333                       scsi_device_list[i].vendor,
 334                       scsi_device_list[i].device,
 335                       (busdevfunc >> 16) & 0xFF,
 336                       (busdevfunc >> 11) & 0x1F,
 337                       (busdevfunc >> 8) & 0x7);
 338        }
 339#endif
 340        bootstage_start(BOOTSTAGE_ID_ACCUM_SCSI, "ahci");
 341        scsi_low_level_init(busdevfunc);
 342        scsi_scan(1);
 343        bootstage_accum(BOOTSTAGE_ID_ACCUM_SCSI);
 344}
 345#endif
 346
 347/* copy src to dest, skipping leading and trailing blanks
 348 * and null terminate the string
 349 */
 350void scsi_ident_cpy(unsigned char *dest, unsigned char *src, unsigned int len)
 351{
 352        int start, end;
 353
 354        start = 0;
 355        while (start < len) {
 356                if (src[start] != ' ')
 357                        break;
 358                start++;
 359        }
 360        end = len-1;
 361        while (end > start) {
 362                if (src[end] != ' ')
 363                        break;
 364                end--;
 365        }
 366        for (; start <= end; start++)
 367                *dest ++= src[start];
 368        *dest = '\0';
 369}
 370
 371
 372/* Trim trailing blanks, and NUL-terminate string
 373 */
 374void scsi_trim_trail(unsigned char *str, unsigned int len)
 375{
 376        unsigned char *p = str + len - 1;
 377
 378        while (len-- > 0) {
 379                *p-- = '\0';
 380                if (*p != ' ')
 381                        return;
 382        }
 383}
 384
 385int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, unsigned long *blksz)
 386{
 387        *capacity = 0;
 388
 389        memset(pccb->cmd, '\0', sizeof(pccb->cmd));
 390        pccb->cmd[0] = SCSI_RD_CAPAC10;
 391        pccb->cmd[1] = pccb->lun << 5;
 392        pccb->cmdlen = 10;
 393        pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
 394
 395        pccb->datalen = 8;
 396        if (scsi_exec(pccb) != true)
 397                return 1;
 398
 399        *capacity = ((lbaint_t)pccb->pdata[0] << 24) |
 400                    ((lbaint_t)pccb->pdata[1] << 16) |
 401                    ((lbaint_t)pccb->pdata[2] << 8)  |
 402                    ((lbaint_t)pccb->pdata[3]);
 403
 404        if (*capacity != 0xffffffff) {
 405                /* Read capacity (10) was sufficient for this drive. */
 406                *blksz = ((unsigned long)pccb->pdata[4] << 24) |
 407                         ((unsigned long)pccb->pdata[5] << 16) |
 408                         ((unsigned long)pccb->pdata[6] << 8)  |
 409                         ((unsigned long)pccb->pdata[7]);
 410                return 0;
 411        }
 412
 413        /* Read capacity (10) was insufficient. Use read capacity (16). */
 414        memset(pccb->cmd, '\0', sizeof(pccb->cmd));
 415        pccb->cmd[0] = SCSI_RD_CAPAC16;
 416        pccb->cmd[1] = 0x10;
 417        pccb->cmdlen = 16;
 418        pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
 419
 420        pccb->datalen = 16;
 421        if (scsi_exec(pccb) != true)
 422                return 1;
 423
 424        *capacity = ((uint64_t)pccb->pdata[0] << 56) |
 425                    ((uint64_t)pccb->pdata[1] << 48) |
 426                    ((uint64_t)pccb->pdata[2] << 40) |
 427                    ((uint64_t)pccb->pdata[3] << 32) |
 428                    ((uint64_t)pccb->pdata[4] << 24) |
 429                    ((uint64_t)pccb->pdata[5] << 16) |
 430                    ((uint64_t)pccb->pdata[6] << 8)  |
 431                    ((uint64_t)pccb->pdata[7]);
 432
 433        *blksz = ((uint64_t)pccb->pdata[8]  << 56) |
 434                 ((uint64_t)pccb->pdata[9]  << 48) |
 435                 ((uint64_t)pccb->pdata[10] << 40) |
 436                 ((uint64_t)pccb->pdata[11] << 32) |
 437                 ((uint64_t)pccb->pdata[12] << 24) |
 438                 ((uint64_t)pccb->pdata[13] << 16) |
 439                 ((uint64_t)pccb->pdata[14] << 8)  |
 440                 ((uint64_t)pccb->pdata[15]);
 441
 442        return 0;
 443}
 444
 445
 446/*
 447 * Some setup (fill-in) routines
 448 */
 449void scsi_setup_test_unit_ready(ccb *pccb)
 450{
 451        pccb->cmd[0] = SCSI_TST_U_RDY;
 452        pccb->cmd[1] = pccb->lun << 5;
 453        pccb->cmd[2] = 0;
 454        pccb->cmd[3] = 0;
 455        pccb->cmd[4] = 0;
 456        pccb->cmd[5] = 0;
 457        pccb->cmdlen = 6;
 458        pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
 459}
 460
 461/*
 462 * (re)-scan the scsi bus and reports scsi device info
 463 * to the user if mode = 1
 464 */
 465void scsi_scan(int mode)
 466{
 467        unsigned char i, perq, modi, lun;
 468        lbaint_t capacity;
 469        unsigned long blksz;
 470        ccb *pccb = (ccb *)&tempccb;
 471
 472        if (mode == 1)
 473                printf("scanning bus for devices...\n");
 474        for (i = 0; i < CONFIG_SYS_SCSI_MAX_DEVICE; i++) {
 475                scsi_dev_desc[i].target = 0xff;
 476                scsi_dev_desc[i].lun = 0xff;
 477                scsi_dev_desc[i].lba = 0;
 478                scsi_dev_desc[i].blksz = 0;
 479                scsi_dev_desc[i].log2blksz =
 480                        LOG2_INVALID(typeof(scsi_dev_desc[i].log2blksz));
 481                scsi_dev_desc[i].type = DEV_TYPE_UNKNOWN;
 482                scsi_dev_desc[i].vendor[0] = 0;
 483                scsi_dev_desc[i].product[0] = 0;
 484                scsi_dev_desc[i].revision[0] = 0;
 485                scsi_dev_desc[i].removable = false;
 486                scsi_dev_desc[i].if_type = IF_TYPE_SCSI;
 487                scsi_dev_desc[i].devnum = i;
 488                scsi_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
 489#ifndef CONFIG_BLK
 490                scsi_dev_desc[i].block_read = scsi_read;
 491                scsi_dev_desc[i].block_write = scsi_write;
 492#endif
 493        }
 494        scsi_max_devs = 0;
 495        for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) {
 496                pccb->target = i;
 497                for (lun = 0; lun < CONFIG_SYS_SCSI_MAX_LUN; lun++) {
 498                        pccb->lun = lun;
 499                        pccb->pdata = (unsigned char *)&tempbuff;
 500                        pccb->datalen = 512;
 501                        scsi_setup_inquiry(pccb);
 502                        if (scsi_exec(pccb) != true) {
 503                                if (pccb->contr_stat == SCSI_SEL_TIME_OUT) {
 504                                        /*
 505                                         * selection timeout => assuming no
 506                                         * device present
 507                                         */
 508                                        debug("Selection timeout ID %d\n",
 509                                              pccb->target);
 510                                        continue;
 511                                }
 512                                scsi_print_error(pccb);
 513                                continue;
 514                        }
 515                        perq = tempbuff[0];
 516                        modi = tempbuff[1];
 517                        if ((perq & 0x1f) == 0x1f)
 518                                continue; /* skip unknown devices */
 519                        if ((modi & 0x80) == 0x80) /* drive is removable */
 520                                scsi_dev_desc[scsi_max_devs].removable = true;
 521                        /* get info for this device */
 522                        scsi_ident_cpy((unsigned char *)&scsi_dev_desc
 523                                                [scsi_max_devs].vendor[0],
 524                                       &tempbuff[8], 8);
 525                        scsi_ident_cpy((unsigned char *)&scsi_dev_desc
 526                                                [scsi_max_devs].product[0],
 527                                       &tempbuff[16], 16);
 528                        scsi_ident_cpy((unsigned char *)&scsi_dev_desc
 529                                                [scsi_max_devs].revision[0],
 530                                       &tempbuff[32], 4);
 531                        scsi_dev_desc[scsi_max_devs].target = pccb->target;
 532                        scsi_dev_desc[scsi_max_devs].lun = pccb->lun;
 533
 534                        pccb->datalen = 0;
 535                        scsi_setup_test_unit_ready(pccb);
 536                        if (scsi_exec(pccb) != true) {
 537                                if (scsi_dev_desc[scsi_max_devs].removable) {
 538                                        scsi_dev_desc[scsi_max_devs].type =
 539                                                        perq;
 540                                        goto removable;
 541                                }
 542                                scsi_print_error(pccb);
 543                                continue;
 544                        }
 545                        if (scsi_read_capacity(pccb, &capacity, &blksz)) {
 546                                scsi_print_error(pccb);
 547                                continue;
 548                        }
 549                        scsi_dev_desc[scsi_max_devs].lba = capacity;
 550                        scsi_dev_desc[scsi_max_devs].blksz = blksz;
 551                        scsi_dev_desc[scsi_max_devs].log2blksz =
 552                                LOG2(scsi_dev_desc[scsi_max_devs].blksz);
 553                        scsi_dev_desc[scsi_max_devs].type = perq;
 554                        part_init(&scsi_dev_desc[scsi_max_devs]);
 555removable:
 556                        if (mode == 1) {
 557                                printf("  Device %d: ", scsi_max_devs);
 558                                dev_print(&scsi_dev_desc[scsi_max_devs]);
 559                        } /* if mode */
 560                        scsi_max_devs++;
 561                } /* next LUN */
 562        }
 563        if (scsi_max_devs > 0)
 564                scsi_curr_dev = 0;
 565        else
 566                scsi_curr_dev = -1;
 567
 568        printf("Found %d device(s).\n", scsi_max_devs);
 569#ifndef CONFIG_SPL_BUILD
 570        setenv_ulong("scsidevs", scsi_max_devs);
 571#endif
 572}
 573
 574#ifdef CONFIG_BLK
 575static const struct blk_ops scsi_blk_ops = {
 576        .read   = scsi_read,
 577        .write  = scsi_write,
 578};
 579
 580U_BOOT_DRIVER(scsi_blk) = {
 581        .name           = "scsi_blk",
 582        .id             = UCLASS_BLK,
 583        .ops            = &scsi_blk_ops,
 584};
 585#else
 586U_BOOT_LEGACY_BLK(scsi) = {
 587        .if_typename    = "scsi",
 588        .if_type        = IF_TYPE_SCSI,
 589        .max_devs       = CONFIG_SYS_SCSI_MAX_DEVICE,
 590        .desc           = scsi_dev_desc,
 591};
 592#endif
 593