scsi: Simplify scsi_read/scsi_write()
[oweals/u-boot.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         lbaint_t start, blks;
165         uintptr_t buf_addr;
166         unsigned short smallblks = 0;
167         ccb *pccb = (ccb *)&tempccb;
168
169         /* Setup device */
170         pccb->target = block_dev->target;
171         pccb->lun = block_dev->lun;
172         buf_addr = (unsigned long)buffer;
173         start = blknr;
174         blks = blkcnt;
175         debug("\nscsi_read: dev %d startblk " LBAF
176               ", blccnt " LBAF " buffer %lx\n",
177               block_dev->devnum, start, blks, (unsigned long)buffer);
178         do {
179                 pccb->pdata = (unsigned char *)buf_addr;
180 #ifdef CONFIG_SYS_64BIT_LBA
181                 if (start > SCSI_LBA48_READ) {
182                         unsigned long blocks;
183                         blocks = min_t(lbaint_t, blks, SCSI_MAX_READ_BLK);
184                         pccb->datalen = block_dev->blksz * blocks;
185                         scsi_setup_read16(pccb, start, blocks);
186                         start += blocks;
187                         blks -= blocks;
188                 } else
189 #endif
190                 if (blks > SCSI_MAX_READ_BLK) {
191                         pccb->datalen = block_dev->blksz *
192                                 SCSI_MAX_READ_BLK;
193                         smallblks = SCSI_MAX_READ_BLK;
194                         scsi_setup_read_ext(pccb, start, smallblks);
195                         start += SCSI_MAX_READ_BLK;
196                         blks -= SCSI_MAX_READ_BLK;
197                 } else {
198                         pccb->datalen = block_dev->blksz * blks;
199                         smallblks = (unsigned short)blks;
200                         scsi_setup_read_ext(pccb, start, smallblks);
201                         start += blks;
202                         blks = 0;
203                 }
204                 debug("scsi_read_ext: startblk " LBAF
205                       ", blccnt %x buffer %" PRIXPTR "\n",
206                       start, smallblks, buf_addr);
207                 if (scsi_exec(pccb) != true) {
208                         scsi_print_error(pccb);
209                         blkcnt -= blks;
210                         break;
211                 }
212                 buf_addr += pccb->datalen;
213         } while (blks != 0);
214         debug("scsi_read_ext: end startblk " LBAF
215               ", blccnt %x buffer %" PRIXPTR "\n", start, smallblks, buf_addr);
216         return blkcnt;
217 }
218
219 /*******************************************************************************
220  * scsi_write
221  */
222
223 /* Almost the maximum amount of the scsi_ext command.. */
224 #define SCSI_MAX_WRITE_BLK 0xFFFF
225
226 #ifdef CONFIG_BLK
227 static ulong scsi_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
228                         const void *buffer)
229 #else
230 static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr,
231                         lbaint_t blkcnt, const void *buffer)
232 #endif
233 {
234 #ifdef CONFIG_BLK
235         struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
236 #endif
237         lbaint_t start, blks;
238         uintptr_t buf_addr;
239         unsigned short smallblks;
240         ccb *pccb = (ccb *)&tempccb;
241
242         /* Setup device */
243         pccb->target = block_dev->target;
244         pccb->lun = block_dev->lun;
245         buf_addr = (unsigned long)buffer;
246         start = blknr;
247         blks = blkcnt;
248         debug("\n%s: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
249               __func__, block_dev->devnum, start, blks, (unsigned long)buffer);
250         do {
251                 pccb->pdata = (unsigned char *)buf_addr;
252                 if (blks > SCSI_MAX_WRITE_BLK) {
253                         pccb->datalen = (block_dev->blksz *
254                                          SCSI_MAX_WRITE_BLK);
255                         smallblks = SCSI_MAX_WRITE_BLK;
256                         scsi_setup_write_ext(pccb, start, smallblks);
257                         start += SCSI_MAX_WRITE_BLK;
258                         blks -= SCSI_MAX_WRITE_BLK;
259                 } else {
260                         pccb->datalen = block_dev->blksz * blks;
261                         smallblks = (unsigned short)blks;
262                         scsi_setup_write_ext(pccb, start, smallblks);
263                         start += blks;
264                         blks = 0;
265                 }
266                 debug("%s: startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n",
267                       __func__, start, smallblks, buf_addr);
268                 if (scsi_exec(pccb) != true) {
269                         scsi_print_error(pccb);
270                         blkcnt -= blks;
271                         break;
272                 }
273                 buf_addr += pccb->datalen;
274         } while (blks != 0);
275         debug("%s: end startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n",
276               __func__, start, smallblks, buf_addr);
277         return blkcnt;
278 }
279
280 int scsi_get_disk_count(void)
281 {
282         return scsi_max_devs;
283 }
284
285 #if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT)
286 void scsi_init(void)
287 {
288         int busdevfunc = -1;
289         int i;
290         /*
291          * Find a device from the list, this driver will support a single
292          * controller.
293          */
294         for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) {
295                 /* get PCI Device ID */
296 #ifdef CONFIG_DM_PCI
297                 struct udevice *dev;
298                 int ret;
299
300                 ret = dm_pci_find_device(scsi_device_list[i].vendor,
301                                          scsi_device_list[i].device, 0, &dev);
302                 if (!ret) {
303                         busdevfunc = dm_pci_get_bdf(dev);
304                         break;
305                 }
306 #else
307                 busdevfunc = pci_find_device(scsi_device_list[i].vendor,
308                                              scsi_device_list[i].device,
309                                              0);
310 #endif
311                 if (busdevfunc != -1)
312                         break;
313         }
314
315         if (busdevfunc == -1) {
316                 printf("Error: SCSI Controller(s) ");
317                 for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) {
318                         printf("%04X:%04X ",
319                                scsi_device_list[i].vendor,
320                                scsi_device_list[i].device);
321                 }
322                 printf("not found\n");
323                 return;
324         }
325 #ifdef DEBUG
326         else {
327                 printf("SCSI Controller (%04X,%04X) found (%d:%d:%d)\n",
328                        scsi_device_list[i].vendor,
329                        scsi_device_list[i].device,
330                        (busdevfunc >> 16) & 0xFF,
331                        (busdevfunc >> 11) & 0x1F,
332                        (busdevfunc >> 8) & 0x7);
333         }
334 #endif
335         bootstage_start(BOOTSTAGE_ID_ACCUM_SCSI, "ahci");
336         scsi_low_level_init(busdevfunc);
337         scsi_scan(1);
338         bootstage_accum(BOOTSTAGE_ID_ACCUM_SCSI);
339 }
340 #endif
341
342 /* copy src to dest, skipping leading and trailing blanks
343  * and null terminate the string
344  */
345 void scsi_ident_cpy(unsigned char *dest, unsigned char *src, unsigned int len)
346 {
347         int start, end;
348
349         start = 0;
350         while (start < len) {
351                 if (src[start] != ' ')
352                         break;
353                 start++;
354         }
355         end = len-1;
356         while (end > start) {
357                 if (src[end] != ' ')
358                         break;
359                 end--;
360         }
361         for (; start <= end; start++)
362                 *dest ++= src[start];
363         *dest = '\0';
364 }
365
366
367 /* Trim trailing blanks, and NUL-terminate string
368  */
369 void scsi_trim_trail(unsigned char *str, unsigned int len)
370 {
371         unsigned char *p = str + len - 1;
372
373         while (len-- > 0) {
374                 *p-- = '\0';
375                 if (*p != ' ')
376                         return;
377         }
378 }
379
380 int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, unsigned long *blksz)
381 {
382         *capacity = 0;
383
384         memset(pccb->cmd, '\0', sizeof(pccb->cmd));
385         pccb->cmd[0] = SCSI_RD_CAPAC10;
386         pccb->cmd[1] = pccb->lun << 5;
387         pccb->cmdlen = 10;
388         pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
389
390         pccb->datalen = 8;
391         if (scsi_exec(pccb) != true)
392                 return 1;
393
394         *capacity = ((lbaint_t)pccb->pdata[0] << 24) |
395                     ((lbaint_t)pccb->pdata[1] << 16) |
396                     ((lbaint_t)pccb->pdata[2] << 8)  |
397                     ((lbaint_t)pccb->pdata[3]);
398
399         if (*capacity != 0xffffffff) {
400                 /* Read capacity (10) was sufficient for this drive. */
401                 *blksz = ((unsigned long)pccb->pdata[4] << 24) |
402                          ((unsigned long)pccb->pdata[5] << 16) |
403                          ((unsigned long)pccb->pdata[6] << 8)  |
404                          ((unsigned long)pccb->pdata[7]);
405                 return 0;
406         }
407
408         /* Read capacity (10) was insufficient. Use read capacity (16). */
409         memset(pccb->cmd, '\0', sizeof(pccb->cmd));
410         pccb->cmd[0] = SCSI_RD_CAPAC16;
411         pccb->cmd[1] = 0x10;
412         pccb->cmdlen = 16;
413         pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
414
415         pccb->datalen = 16;
416         if (scsi_exec(pccb) != true)
417                 return 1;
418
419         *capacity = ((uint64_t)pccb->pdata[0] << 56) |
420                     ((uint64_t)pccb->pdata[1] << 48) |
421                     ((uint64_t)pccb->pdata[2] << 40) |
422                     ((uint64_t)pccb->pdata[3] << 32) |
423                     ((uint64_t)pccb->pdata[4] << 24) |
424                     ((uint64_t)pccb->pdata[5] << 16) |
425                     ((uint64_t)pccb->pdata[6] << 8)  |
426                     ((uint64_t)pccb->pdata[7]);
427
428         *blksz = ((uint64_t)pccb->pdata[8]  << 56) |
429                  ((uint64_t)pccb->pdata[9]  << 48) |
430                  ((uint64_t)pccb->pdata[10] << 40) |
431                  ((uint64_t)pccb->pdata[11] << 32) |
432                  ((uint64_t)pccb->pdata[12] << 24) |
433                  ((uint64_t)pccb->pdata[13] << 16) |
434                  ((uint64_t)pccb->pdata[14] << 8)  |
435                  ((uint64_t)pccb->pdata[15]);
436
437         return 0;
438 }
439
440
441 /*
442  * Some setup (fill-in) routines
443  */
444 void scsi_setup_test_unit_ready(ccb *pccb)
445 {
446         pccb->cmd[0] = SCSI_TST_U_RDY;
447         pccb->cmd[1] = pccb->lun << 5;
448         pccb->cmd[2] = 0;
449         pccb->cmd[3] = 0;
450         pccb->cmd[4] = 0;
451         pccb->cmd[5] = 0;
452         pccb->cmdlen = 6;
453         pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
454 }
455
456 static void scsi_init_dev_desc(struct blk_desc *dev_desc, int devnum)
457 {
458         dev_desc->target = 0xff;
459         dev_desc->lun = 0xff;
460         dev_desc->lba = 0;
461         dev_desc->blksz = 0;
462         dev_desc->log2blksz =
463                 LOG2_INVALID(typeof(dev_desc->log2blksz));
464         dev_desc->type = DEV_TYPE_UNKNOWN;
465         dev_desc->vendor[0] = 0;
466         dev_desc->product[0] = 0;
467         dev_desc->revision[0] = 0;
468         dev_desc->removable = false;
469         dev_desc->if_type = IF_TYPE_SCSI;
470         dev_desc->devnum = devnum;
471         dev_desc->part_type = PART_TYPE_UNKNOWN;
472 #ifndef CONFIG_BLK
473         dev_desc->block_read = scsi_read;
474         dev_desc->block_write = scsi_write;
475 #endif
476 }
477
478
479 /**
480  * scsi_detect_dev - Detect scsi device
481  *
482  * @target: target id
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. The LUN number is taken from the struct blk_desc *dev_desc.
487  *
488  * Return: 0 on success, error value otherwise
489  */
490 static int scsi_detect_dev(int target, struct blk_desc *dev_desc)
491 {
492         unsigned char perq, modi;
493         lbaint_t capacity;
494         unsigned long blksz;
495         ccb *pccb = (ccb *)&tempccb;
496
497         pccb->target = target;
498         pccb->lun = dev_desc->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                         return -ETIMEDOUT;
511                 }
512                 scsi_print_error(pccb);
513                 return -ENODEV;
514         }
515         perq = tempbuff[0];
516         modi = tempbuff[1];
517         if ((perq & 0x1f) == 0x1f)
518                 return -ENODEV; /* skip unknown devices */
519         if ((modi & 0x80) == 0x80) /* drive is removable */
520                 dev_desc->removable = true;
521         /* get info for this device */
522         scsi_ident_cpy((unsigned char *)dev_desc->vendor,
523                        &tempbuff[8], 8);
524         scsi_ident_cpy((unsigned char *)dev_desc->product,
525                        &tempbuff[16], 16);
526         scsi_ident_cpy((unsigned char *)dev_desc->revision,
527                        &tempbuff[32], 4);
528         dev_desc->target = pccb->target;
529         dev_desc->lun = pccb->lun;
530
531         pccb->datalen = 0;
532         scsi_setup_test_unit_ready(pccb);
533         if (scsi_exec(pccb) != true) {
534                 if (dev_desc->removable) {
535                         dev_desc->type = perq;
536                         goto removable;
537                 }
538                 scsi_print_error(pccb);
539                 return -EINVAL;
540         }
541         if (scsi_read_capacity(pccb, &capacity, &blksz)) {
542                 scsi_print_error(pccb);
543                 return -EINVAL;
544         }
545         dev_desc->lba = capacity;
546         dev_desc->blksz = blksz;
547         dev_desc->log2blksz = LOG2(dev_desc->blksz);
548         dev_desc->type = perq;
549         part_init(&dev_desc[0]);
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 void scsi_scan(int mode)
559 {
560         unsigned char i, lun;
561         int ret;
562
563         if (mode == 1)
564                 printf("scanning bus for devices...\n");
565         for (i = 0; i < CONFIG_SYS_SCSI_MAX_DEVICE; i++)
566                 scsi_init_dev_desc(&scsi_dev_desc[i], i);
567
568         scsi_max_devs = 0;
569         for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) {
570                 for (lun = 0; lun < CONFIG_SYS_SCSI_MAX_LUN; lun++) {
571                         scsi_dev_desc[scsi_max_devs].lun = lun;
572                         ret = scsi_detect_dev(i, &scsi_dev_desc[scsi_max_devs]);
573                         if (ret)
574                                 continue;
575
576                         if (mode == 1) {
577                                 printf("  Device %d: ", 0);
578                                 dev_print(&scsi_dev_desc[scsi_max_devs]);
579                         } /* if mode */
580                         scsi_max_devs++;
581                 } /* next LUN */
582         }
583         if (scsi_max_devs > 0)
584                 scsi_curr_dev = 0;
585         else
586                 scsi_curr_dev = -1;
587
588         printf("Found %d device(s).\n", scsi_max_devs);
589 #ifndef CONFIG_SPL_BUILD
590         setenv_ulong("scsidevs", scsi_max_devs);
591 #endif
592 }
593
594 #ifdef CONFIG_BLK
595 static const struct blk_ops scsi_blk_ops = {
596         .read   = scsi_read,
597         .write  = scsi_write,
598 };
599
600 U_BOOT_DRIVER(scsi_blk) = {
601         .name           = "scsi_blk",
602         .id             = UCLASS_BLK,
603         .ops            = &scsi_blk_ops,
604 };
605 #else
606 U_BOOT_LEGACY_BLK(scsi) = {
607         .if_typename    = "scsi",
608         .if_type        = IF_TYPE_SCSI,
609         .max_devs       = CONFIG_SYS_SCSI_MAX_DEVICE,
610         .desc           = scsi_dev_desc,
611 };
612 #endif