]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - common/scsi.c
armv8: Move secure_ram variable out of generic global data
[karo-tx-uboot.git] / common / scsi.c
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)
36 const struct pci_device_id scsi_device_list[] = { SCSI_DEV_LIST };
37 #endif
38 static ccb tempccb;     /* temporary scsi command buffer */
39
40 static unsigned char tempbuff[512]; /* temporary data buffer */
41
42 static int scsi_max_devs; /* number of highest available scsi device */
43
44 static int scsi_curr_dev; /* current device */
45
46 static 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
53 void 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
81 void 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
101 void 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
122 void 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
138 void 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
154 static ulong scsi_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
155                        void *buffer)
156 #else
157 static 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
229 static ulong scsi_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
230                         const void *buffer)
231 #else
232 static 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
285 int scsi_get_disk_count(void)
286 {
287         return scsi_max_devs;
288 }
289
290 #if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT)
291 void 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  */
350 void 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  */
374 void 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
385 int 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  */
449 void 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  */
465 void 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]);
555 removable:
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
575 static const struct blk_ops scsi_blk_ops = {
576         .read   = scsi_read,
577         .write  = scsi_write,
578 };
579
580 U_BOOT_DRIVER(scsi_blk) = {
581         .name           = "scsi_blk",
582         .id             = UCLASS_BLK,
583         .ops            = &scsi_blk_ops,
584 };
585 #else
586 U_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