Coverage Report

Created: 2026-03-11 06:21

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