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