]> Git Repo - u-boot.git/blob - drivers/scsi/scsi.c
Restore patch series "arm: dts: am62-beagleplay: Fix Beagleplay Ethernet"
[u-boot.git] / 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 #define LOG_CATEGORY    UCLASS_SCSI
8
9 #include <blk.h>
10 #include <bootdev.h>
11 #include <bootstage.h>
12 #include <dm.h>
13 #include <env.h>
14 #include <libata.h>
15 #include <log.h>
16 #include <memalign.h>
17 #include <part.h>
18 #include <pci.h>
19 #include <scsi.h>
20 #include <dm/device-internal.h>
21 #include <dm/uclass-internal.h>
22
23 static struct scsi_cmd tempccb; /* temporary scsi command buffer */
24
25 DEFINE_CACHE_ALIGN_BUFFER(u8, tempbuff, 512);   /* temporary data buffer */
26
27 /* almost the maximum amount of the scsi_ext command.. */
28 #define SCSI_MAX_BLK 0xFFFF
29 #define SCSI_LBA48_READ 0xFFFFFFF
30
31 static void scsi_print_error(struct scsi_cmd *pccb)
32 {
33         /* Dummy function that could print an error for debugging */
34 }
35
36 #ifdef CONFIG_SYS_64BIT_LBA
37 void scsi_setup_read16(struct scsi_cmd *pccb, lbaint_t start,
38                        unsigned long blocks)
39 {
40         pccb->cmd[0] = SCSI_READ16;
41         pccb->cmd[1] = pccb->lun << 5;
42         pccb->cmd[2] = (unsigned char)(start >> 56) & 0xff;
43         pccb->cmd[3] = (unsigned char)(start >> 48) & 0xff;
44         pccb->cmd[4] = (unsigned char)(start >> 40) & 0xff;
45         pccb->cmd[5] = (unsigned char)(start >> 32) & 0xff;
46         pccb->cmd[6] = (unsigned char)(start >> 24) & 0xff;
47         pccb->cmd[7] = (unsigned char)(start >> 16) & 0xff;
48         pccb->cmd[8] = (unsigned char)(start >> 8) & 0xff;
49         pccb->cmd[9] = (unsigned char)start & 0xff;
50         pccb->cmd[10] = 0;
51         pccb->cmd[11] = (unsigned char)(blocks >> 24) & 0xff;
52         pccb->cmd[12] = (unsigned char)(blocks >> 16) & 0xff;
53         pccb->cmd[13] = (unsigned char)(blocks >> 8) & 0xff;
54         pccb->cmd[14] = (unsigned char)blocks & 0xff;
55         pccb->cmd[15] = 0;
56         pccb->cmdlen = 16;
57         pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
58         debug("scsi_setup_read16: cmd: %02X %02X startblk %02X%02X%02X%02X%02X%02X%02X%02X blccnt %02X%02X%02X%02X\n",
59               pccb->cmd[0], pccb->cmd[1],
60               pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5],
61               pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9],
62               pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]);
63 }
64 #endif
65
66 static void scsi_setup_inquiry(struct scsi_cmd *pccb)
67 {
68         pccb->cmd[0] = SCSI_INQUIRY;
69         pccb->cmd[1] = pccb->lun << 5;
70         pccb->cmd[2] = 0;
71         pccb->cmd[3] = 0;
72         if (pccb->datalen > 255)
73                 pccb->cmd[4] = 255;
74         else
75                 pccb->cmd[4] = (unsigned char)pccb->datalen;
76         pccb->cmd[5] = 0;
77         pccb->cmdlen = 6;
78         pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
79 }
80
81 static void scsi_setup_read_ext(struct scsi_cmd *pccb, lbaint_t start,
82                                 unsigned short blocks)
83 {
84         pccb->cmd[0] = SCSI_READ10;
85         pccb->cmd[1] = pccb->lun << 5;
86         pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff;
87         pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff;
88         pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff;
89         pccb->cmd[5] = (unsigned char)start & 0xff;
90         pccb->cmd[6] = 0;
91         pccb->cmd[7] = (unsigned char)(blocks >> 8) & 0xff;
92         pccb->cmd[8] = (unsigned char)blocks & 0xff;
93         pccb->cmd[6] = 0;
94         pccb->cmdlen = 10;
95         pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
96         debug("scsi_setup_read_ext: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n",
97               pccb->cmd[0], pccb->cmd[1],
98               pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5],
99               pccb->cmd[7], pccb->cmd[8]);
100 }
101
102 static void scsi_setup_write_ext(struct scsi_cmd *pccb, lbaint_t start,
103                                  unsigned short blocks)
104 {
105         pccb->cmd[0] = SCSI_WRITE10;
106         pccb->cmd[1] = pccb->lun << 5;
107         pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff;
108         pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff;
109         pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff;
110         pccb->cmd[5] = (unsigned char)start & 0xff;
111         pccb->cmd[6] = 0;
112         pccb->cmd[7] = ((unsigned char)(blocks >> 8)) & 0xff;
113         pccb->cmd[8] = (unsigned char)blocks & 0xff;
114         pccb->cmd[9] = 0;
115         pccb->cmdlen = 10;
116         pccb->msgout[0] = SCSI_IDENTIFY;  /* NOT USED */
117         debug("%s: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n",
118               __func__,
119               pccb->cmd[0], pccb->cmd[1],
120               pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5],
121               pccb->cmd[7], pccb->cmd[8]);
122 }
123
124 static ulong scsi_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
125                        void *buffer)
126 {
127         struct blk_desc *block_dev = dev_get_uclass_plat(dev);
128         struct udevice *bdev = dev->parent;
129         struct scsi_plat *uc_plat = dev_get_uclass_plat(bdev);
130         lbaint_t start, blks, max_blks;
131         uintptr_t buf_addr;
132         unsigned short smallblks = 0;
133         struct scsi_cmd *pccb = (struct scsi_cmd *)&tempccb;
134
135         /* Setup device */
136         pccb->target = block_dev->target;
137         pccb->lun = block_dev->lun;
138         buf_addr = (unsigned long)buffer;
139         start = blknr;
140         blks = blkcnt;
141         if (uc_plat->max_bytes_per_req)
142                 max_blks = uc_plat->max_bytes_per_req / block_dev->blksz;
143         else
144                 max_blks = SCSI_MAX_BLK;
145
146         debug("\nscsi_read: dev %d startblk " LBAF
147               ", blccnt " LBAF " buffer %lx\n",
148               block_dev->devnum, start, blks, (unsigned long)buffer);
149         do {
150                 pccb->pdata = (unsigned char *)buf_addr;
151                 pccb->dma_dir = DMA_FROM_DEVICE;
152 #ifdef CONFIG_SYS_64BIT_LBA
153                 if (start > SCSI_LBA48_READ) {
154                         unsigned long blocks;
155                         blocks = min_t(lbaint_t, blks, max_blks);
156                         pccb->datalen = block_dev->blksz * blocks;
157                         scsi_setup_read16(pccb, start, blocks);
158                         start += blocks;
159                         blks -= blocks;
160                 } else
161 #endif
162                 if (blks > max_blks) {
163                         pccb->datalen = block_dev->blksz * max_blks;
164                         smallblks = max_blks;
165                         scsi_setup_read_ext(pccb, start, smallblks);
166                         start += max_blks;
167                         blks -= max_blks;
168                 } else {
169                         pccb->datalen = block_dev->blksz * blks;
170                         smallblks = (unsigned short)blks;
171                         scsi_setup_read_ext(pccb, start, smallblks);
172                         start += blks;
173                         blks = 0;
174                 }
175                 debug("scsi_read_ext: startblk " LBAF
176                       ", blccnt %x buffer %lX\n",
177                       start, smallblks, buf_addr);
178                 if (scsi_exec(bdev, pccb)) {
179                         scsi_print_error(pccb);
180                         blkcnt -= blks;
181                         break;
182                 }
183                 buf_addr += pccb->datalen;
184         } while (blks != 0);
185         debug("scsi_read_ext: end startblk " LBAF
186               ", blccnt %x buffer %lX\n", start, smallblks, buf_addr);
187         return blkcnt;
188 }
189
190 /*******************************************************************************
191  * scsi_write
192  */
193
194 static ulong scsi_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
195                         const void *buffer)
196 {
197         struct blk_desc *block_dev = dev_get_uclass_plat(dev);
198         struct udevice *bdev = dev->parent;
199         struct scsi_plat *uc_plat = dev_get_uclass_plat(bdev);
200         lbaint_t start, blks, max_blks;
201         uintptr_t buf_addr;
202         unsigned short smallblks;
203         struct scsi_cmd *pccb = (struct scsi_cmd *)&tempccb;
204
205         /* Setup device */
206         pccb->target = block_dev->target;
207         pccb->lun = block_dev->lun;
208         buf_addr = (unsigned long)buffer;
209         start = blknr;
210         blks = blkcnt;
211         if (uc_plat->max_bytes_per_req)
212                 max_blks = uc_plat->max_bytes_per_req / block_dev->blksz;
213         else
214                 max_blks = SCSI_MAX_BLK;
215
216         debug("\n%s: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
217               __func__, block_dev->devnum, start, blks, (unsigned long)buffer);
218         do {
219                 pccb->pdata = (unsigned char *)buf_addr;
220                 pccb->dma_dir = DMA_TO_DEVICE;
221                 if (blks > max_blks) {
222                         pccb->datalen = block_dev->blksz * max_blks;
223                         smallblks = max_blks;
224                         scsi_setup_write_ext(pccb, start, smallblks);
225                         start += max_blks;
226                         blks -= max_blks;
227                 } else {
228                         pccb->datalen = block_dev->blksz * blks;
229                         smallblks = (unsigned short)blks;
230                         scsi_setup_write_ext(pccb, start, smallblks);
231                         start += blks;
232                         blks = 0;
233                 }
234                 debug("%s: startblk " LBAF ", blccnt %x buffer %lx\n",
235                       __func__, start, smallblks, buf_addr);
236                 if (scsi_exec(bdev, pccb)) {
237                         scsi_print_error(pccb);
238                         blkcnt -= blks;
239                         break;
240                 }
241                 buf_addr += pccb->datalen;
242         } while (blks != 0);
243         debug("%s: end startblk " LBAF ", blccnt %x buffer %lX\n",
244               __func__, start, smallblks, buf_addr);
245         return blkcnt;
246 }
247
248 #if IS_ENABLED(CONFIG_BOUNCE_BUFFER)
249 static int scsi_buffer_aligned(struct udevice *dev, struct bounce_buffer *state)
250 {
251         struct scsi_ops *ops = scsi_get_ops(dev->parent);
252
253         if (ops->buffer_aligned)
254                 return ops->buffer_aligned(dev->parent, state);
255
256         return 1;
257 }
258 #endif  /* CONFIG_BOUNCE_BUFFER */
259
260 /* copy src to dest, skipping leading and trailing blanks
261  * and null terminate the string
262  */
263 static void scsi_ident_cpy(unsigned char *dest, unsigned char *src,
264                            unsigned int len)
265 {
266         int start, end;
267
268         start = 0;
269         while (start < len) {
270                 if (src[start] != ' ')
271                         break;
272                 start++;
273         }
274         end = len-1;
275         while (end > start) {
276                 if (src[end] != ' ')
277                         break;
278                 end--;
279         }
280         for (; start <= end; start++)
281                 *dest ++= src[start];
282         *dest = '\0';
283 }
284
285 static int scsi_read_capacity(struct udevice *dev, struct scsi_cmd *pccb,
286                               lbaint_t *capacity, unsigned long *blksz)
287 {
288         *capacity = 0;
289
290         memset(pccb->cmd, '\0', sizeof(pccb->cmd));
291         pccb->cmd[0] = SCSI_RD_CAPAC10;
292         pccb->cmd[1] = pccb->lun << 5;
293         pccb->cmdlen = 10;
294         pccb->dma_dir = DMA_FROM_DEVICE;
295         pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
296
297         pccb->datalen = 8;
298         if (scsi_exec(dev, pccb))
299                 return 1;
300
301         *capacity = ((lbaint_t)pccb->pdata[0] << 24) |
302                     ((lbaint_t)pccb->pdata[1] << 16) |
303                     ((lbaint_t)pccb->pdata[2] << 8)  |
304                     ((lbaint_t)pccb->pdata[3]);
305
306         if (*capacity != 0xffffffff) {
307                 /* Read capacity (10) was sufficient for this drive. */
308                 *blksz = ((unsigned long)pccb->pdata[4] << 24) |
309                          ((unsigned long)pccb->pdata[5] << 16) |
310                          ((unsigned long)pccb->pdata[6] << 8)  |
311                          ((unsigned long)pccb->pdata[7]);
312                 return 0;
313         }
314
315         /* Read capacity (10) was insufficient. Use read capacity (16). */
316         memset(pccb->cmd, '\0', sizeof(pccb->cmd));
317         pccb->cmd[0] = SCSI_RD_CAPAC16;
318         pccb->cmd[1] = 0x10;
319         pccb->cmdlen = 16;
320         pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
321
322         pccb->datalen = 16;
323         pccb->dma_dir = DMA_FROM_DEVICE;
324         if (scsi_exec(dev, pccb))
325                 return 1;
326
327         *capacity = ((uint64_t)pccb->pdata[0] << 56) |
328                     ((uint64_t)pccb->pdata[1] << 48) |
329                     ((uint64_t)pccb->pdata[2] << 40) |
330                     ((uint64_t)pccb->pdata[3] << 32) |
331                     ((uint64_t)pccb->pdata[4] << 24) |
332                     ((uint64_t)pccb->pdata[5] << 16) |
333                     ((uint64_t)pccb->pdata[6] << 8)  |
334                     ((uint64_t)pccb->pdata[7]);
335
336         *blksz = ((uint64_t)pccb->pdata[8]  << 56) |
337                  ((uint64_t)pccb->pdata[9]  << 48) |
338                  ((uint64_t)pccb->pdata[10] << 40) |
339                  ((uint64_t)pccb->pdata[11] << 32) |
340                  ((uint64_t)pccb->pdata[12] << 24) |
341                  ((uint64_t)pccb->pdata[13] << 16) |
342                  ((uint64_t)pccb->pdata[14] << 8)  |
343                  ((uint64_t)pccb->pdata[15]);
344
345         return 0;
346 }
347
348
349 /*
350  * Some setup (fill-in) routines
351  */
352 static void scsi_setup_test_unit_ready(struct scsi_cmd *pccb)
353 {
354         pccb->cmd[0] = SCSI_TST_U_RDY;
355         pccb->cmd[1] = pccb->lun << 5;
356         pccb->cmd[2] = 0;
357         pccb->cmd[3] = 0;
358         pccb->cmd[4] = 0;
359         pccb->cmd[5] = 0;
360         pccb->cmdlen = 6;
361         pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
362 }
363
364 /**
365  * scsi_init_dev_desc_priv - initialize only SCSI specific blk_desc properties
366  *
367  * @dev_desc: Block device description pointer
368  */
369 static void scsi_init_dev_desc_priv(struct blk_desc *dev_desc)
370 {
371         memset(dev_desc, 0, sizeof(struct blk_desc));
372         dev_desc->target = 0xff;
373         dev_desc->lun = 0xff;
374         dev_desc->log2blksz =
375                 LOG2_INVALID(typeof(dev_desc->log2blksz));
376         dev_desc->type = DEV_TYPE_UNKNOWN;
377 #if IS_ENABLED(CONFIG_BOUNCE_BUFFER)
378         dev_desc->bb = true;
379 #endif  /* CONFIG_BOUNCE_BUFFER */
380 }
381
382 /**
383  * scsi_detect_dev - Detect scsi device
384  *
385  * @target: target id
386  * @lun: target lun
387  * @dev_desc: block device description
388  *
389  * The scsi_detect_dev detects and fills a dev_desc structure when the device is
390  * detected.
391  *
392  * Return: 0 on success, error value otherwise
393  */
394 static int scsi_detect_dev(struct udevice *dev, int target, int lun,
395                            struct blk_desc *dev_desc)
396 {
397         unsigned char perq, modi;
398         lbaint_t capacity;
399         unsigned long blksz;
400         struct scsi_cmd *pccb = (struct scsi_cmd *)&tempccb;
401         int count, err;
402
403         pccb->target = target;
404         pccb->lun = lun;
405         pccb->pdata = tempbuff;
406         pccb->datalen = 512;
407         pccb->dma_dir = DMA_FROM_DEVICE;
408         scsi_setup_inquiry(pccb);
409         if (scsi_exec(dev, pccb)) {
410                 if (pccb->contr_stat == SCSI_SEL_TIME_OUT) {
411                         /*
412                           * selection timeout => assuming no
413                           * device present
414                           */
415                         debug("Selection timeout ID %d\n",
416                               pccb->target);
417                         return -ETIMEDOUT;
418                 }
419                 scsi_print_error(pccb);
420                 return -ENODEV;
421         }
422         perq = tempbuff[0];
423         modi = tempbuff[1];
424         if ((perq & 0x1f) == 0x1f)
425                 return -ENODEV; /* skip unknown devices */
426         if ((modi & 0x80) == 0x80) /* drive is removable */
427                 dev_desc->removable = true;
428         /* get info for this device */
429         scsi_ident_cpy((unsigned char *)dev_desc->vendor,
430                        &tempbuff[8], 8);
431         scsi_ident_cpy((unsigned char *)dev_desc->product,
432                        &tempbuff[16], 16);
433         scsi_ident_cpy((unsigned char *)dev_desc->revision,
434                        &tempbuff[32], 4);
435         dev_desc->target = pccb->target;
436         dev_desc->lun = pccb->lun;
437
438         for (count = 0; count < 3; count++) {
439                 pccb->datalen = 0;
440                 pccb->dma_dir = DMA_NONE;
441                 scsi_setup_test_unit_ready(pccb);
442                 err = scsi_exec(dev, pccb);
443                 if (!err)
444                         break;
445         }
446         if (err) {
447                 if (dev_desc->removable) {
448                         dev_desc->type = perq;
449                         goto removable;
450                 }
451                 scsi_print_error(pccb);
452                 return -EINVAL;
453         }
454         if (scsi_read_capacity(dev, pccb, &capacity, &blksz)) {
455                 scsi_print_error(pccb);
456                 return -EINVAL;
457         }
458         dev_desc->lba = capacity;
459         dev_desc->blksz = blksz;
460         dev_desc->log2blksz = LOG2(dev_desc->blksz);
461         dev_desc->type = perq;
462 removable:
463         return 0;
464 }
465
466 /*
467  * (re)-scan the scsi bus and reports scsi device info
468  * to the user if mode = 1
469  */
470 static int do_scsi_scan_one(struct udevice *dev, int id, int lun, bool verbose)
471 {
472         int ret;
473         struct udevice *bdev;
474         struct blk_desc bd;
475         struct blk_desc *bdesc;
476         char str[10], *name;
477
478         /*
479          * detect the scsi driver to get information about its geometry (block
480          * size, number of blocks) and other parameters (ids, type, ...)
481          */
482         scsi_init_dev_desc_priv(&bd);
483         if (scsi_detect_dev(dev, id, lun, &bd))
484                 return -ENODEV;
485
486         /*
487         * Create only one block device and do detection
488         * to make sure that there won't be a lot of
489         * block devices created
490         */
491         snprintf(str, sizeof(str), "id%dlun%d", id, lun);
492         name = strdup(str);
493         if (!name)
494                 return log_msg_ret("nam", -ENOMEM);
495         ret = blk_create_devicef(dev, "scsi_blk", name, UCLASS_SCSI, -1,
496                                  bd.blksz, bd.lba, &bdev);
497         if (ret) {
498                 debug("Can't create device\n");
499                 return ret;
500         }
501         device_set_name_alloced(bdev);
502
503         bdesc = dev_get_uclass_plat(bdev);
504         bdesc->target = id;
505         bdesc->lun = lun;
506         bdesc->removable = bd.removable;
507         bdesc->type = bd.type;
508         bdesc->bb = bd.bb;
509         memcpy(&bdesc->vendor, &bd.vendor, sizeof(bd.vendor));
510         memcpy(&bdesc->product, &bd.product, sizeof(bd.product));
511         memcpy(&bdesc->revision, &bd.revision,  sizeof(bd.revision));
512         if (IS_ENABLED(CONFIG_SYS_BIG_ENDIAN)) {
513                 ata_swap_buf_le16((u16 *)&bdesc->vendor, sizeof(bd.vendor) / 2);
514                 ata_swap_buf_le16((u16 *)&bdesc->product, sizeof(bd.product) / 2);
515                 ata_swap_buf_le16((u16 *)&bdesc->revision, sizeof(bd.revision) / 2);
516         }
517
518         ret = blk_probe_or_unbind(bdev);
519         if (ret < 0)
520                 /* TODO: undo create */
521                 return log_msg_ret("pro", ret);
522
523         ret = bootdev_setup_for_sibling_blk(bdev, "scsi_bootdev");
524         if (ret)
525                 return log_msg_ret("bd", ret);
526
527         if (verbose) {
528                 printf("  Device %d: ", bdesc->devnum);
529                 dev_print(bdesc);
530         }
531         return 0;
532 }
533
534 int scsi_scan_dev(struct udevice *dev, bool verbose)
535 {
536         struct scsi_plat *uc_plat; /* scsi controller plat */
537         int ret;
538         int i;
539         int lun;
540
541         /* probe SCSI controller driver */
542         ret = device_probe(dev);
543         if (ret)
544                 return ret;
545
546         /* Get controller plat */
547         uc_plat = dev_get_uclass_plat(dev);
548
549         for (i = 0; i < uc_plat->max_id; i++)
550                 for (lun = 0; lun < uc_plat->max_lun; lun++)
551                         do_scsi_scan_one(dev, i, lun, verbose);
552
553         return 0;
554 }
555
556 int scsi_scan(bool verbose)
557 {
558         struct uclass *uc;
559         struct udevice *dev; /* SCSI controller */
560         int ret;
561
562         if (verbose)
563                 printf("scanning bus for devices...\n");
564
565         ret = uclass_get(UCLASS_SCSI, &uc);
566         if (ret)
567                 return ret;
568
569         /* remove all children of the SCSI devices */
570         uclass_foreach_dev(dev, uc) {
571                 log_debug("unbind %s\n", dev->name);
572                 ret = device_chld_remove(dev, NULL, DM_REMOVE_NORMAL);
573                 if (!ret)
574                         ret = device_chld_unbind(dev, NULL);
575                 if (ret) {
576                         if (verbose)
577                                 printf("unable to unbind devices (%dE)\n", ret);
578                         return log_msg_ret("unb", ret);
579                 }
580         }
581
582         uclass_foreach_dev(dev, uc) {
583                 ret = scsi_scan_dev(dev, verbose);
584                 if (ret)
585                         return ret;
586         }
587
588         return 0;
589 }
590
591 static const struct blk_ops scsi_blk_ops = {
592         .read   = scsi_read,
593         .write  = scsi_write,
594 #if IS_ENABLED(CONFIG_BOUNCE_BUFFER)
595         .buffer_aligned = scsi_buffer_aligned,
596 #endif  /* CONFIG_BOUNCE_BUFFER */
597 };
598
599 U_BOOT_DRIVER(scsi_blk) = {
600         .name           = "scsi_blk",
601         .id             = UCLASS_BLK,
602         .ops            = &scsi_blk_ops,
603 };
This page took 0.060717 seconds and 4 git commands to generate.