Commit 0fcd48fe00e8fb2d433c1bf5ebe586b19228f027

Authored by Simon Glass
1 parent f2105c6182

scsi: Move drivers into new drivers/scsi directory

At present we have the SCSI drivers in the drivers/block and common/
directories. It is better to split them out into their own place. Use
drivers/scsi which is what Linux does.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

Showing 13 changed files with 782 additions and 764 deletions Side-by-side Diff

... ... @@ -79,7 +79,6 @@
79 79 obj-$(CONFIG_LCD_DT_SIMPLEFB) += lcd_simplefb.o
80 80 obj-$(CONFIG_LYNXKDI) += lynxkdi.o
81 81 obj-$(CONFIG_MENU) += menu.o
82   -obj-$(CONFIG_SCSI) += scsi.o
83 82 obj-$(CONFIG_UPDATE_TFTP) += update.o
84 83 obj-$(CONFIG_DFU_TFTP) += update.o
85 84 obj-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
... ... @@ -120,9 +119,6 @@
120 119 obj-$(CONFIG_ENV_IS_IN_NAND) += env_nand.o
121 120 obj-$(CONFIG_ENV_IS_IN_SPI_FLASH) += env_sf.o
122 121 obj-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o
123   -endif
124   -ifdef CONFIG_SPL_SATA_SUPPORT
125   -obj-$(CONFIG_SCSI) += scsi.o
126 122 endif
127 123 endif
128 124 #environment
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   -#include <dm/device-internal.h>
14   -#include <dm/uclass-internal.h>
15   -
16   -#if !defined(CONFIG_DM_SCSI)
17   -#ifdef CONFIG_SCSI_DEV_LIST
18   -#define SCSI_DEV_LIST CONFIG_SCSI_DEV_LIST
19   -#else
20   -#ifdef CONFIG_SATA_ULI5288
21   -
22   -#define SCSI_VEND_ID 0x10b9
23   -#define SCSI_DEV_ID 0x5288
24   -
25   -#elif !defined(CONFIG_SCSI_AHCI_PLAT)
26   -#error no scsi device defined
27   -#endif
28   -#define SCSI_DEV_LIST {SCSI_VEND_ID, SCSI_DEV_ID}
29   -#endif
30   -#endif
31   -
32   -#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT)
33   -const struct pci_device_id scsi_device_list[] = { SCSI_DEV_LIST };
34   -#endif
35   -static ccb tempccb; /* temporary scsi command buffer */
36   -
37   -static unsigned char tempbuff[512]; /* temporary data buffer */
38   -
39   -#if !defined(CONFIG_DM_SCSI)
40   -static int scsi_max_devs; /* number of highest available scsi device */
41   -
42   -static int scsi_curr_dev; /* current device */
43   -
44   -static struct blk_desc scsi_dev_desc[CONFIG_SYS_SCSI_MAX_DEVICE];
45   -#endif
46   -
47   -/* almost the maximum amount of the scsi_ext command.. */
48   -#define SCSI_MAX_READ_BLK 0xFFFF
49   -#define SCSI_LBA48_READ 0xFFFFFFF
50   -
51   -static void scsi_print_error(ccb *pccb)
52   -{
53   - /* Dummy function that could print an error for debugging */
54   -}
55   -
56   -#ifdef CONFIG_SYS_64BIT_LBA
57   -void scsi_setup_read16(ccb *pccb, lbaint_t start, unsigned long blocks)
58   -{
59   - pccb->cmd[0] = SCSI_READ16;
60   - pccb->cmd[1] = pccb->lun << 5;
61   - pccb->cmd[2] = (unsigned char)(start >> 56) & 0xff;
62   - pccb->cmd[3] = (unsigned char)(start >> 48) & 0xff;
63   - pccb->cmd[4] = (unsigned char)(start >> 40) & 0xff;
64   - pccb->cmd[5] = (unsigned char)(start >> 32) & 0xff;
65   - pccb->cmd[6] = (unsigned char)(start >> 24) & 0xff;
66   - pccb->cmd[7] = (unsigned char)(start >> 16) & 0xff;
67   - pccb->cmd[8] = (unsigned char)(start >> 8) & 0xff;
68   - pccb->cmd[9] = (unsigned char)start & 0xff;
69   - pccb->cmd[10] = 0;
70   - pccb->cmd[11] = (unsigned char)(blocks >> 24) & 0xff;
71   - pccb->cmd[12] = (unsigned char)(blocks >> 16) & 0xff;
72   - pccb->cmd[13] = (unsigned char)(blocks >> 8) & 0xff;
73   - pccb->cmd[14] = (unsigned char)blocks & 0xff;
74   - pccb->cmd[15] = 0;
75   - pccb->cmdlen = 16;
76   - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
77   - debug("scsi_setup_read16: cmd: %02X %02X startblk %02X%02X%02X%02X%02X%02X%02X%02X blccnt %02X%02X%02X%02X\n",
78   - pccb->cmd[0], pccb->cmd[1],
79   - pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5],
80   - pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9],
81   - pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]);
82   -}
83   -#endif
84   -
85   -static void scsi_setup_read_ext(ccb *pccb, lbaint_t start,
86   - unsigned short blocks)
87   -{
88   - pccb->cmd[0] = SCSI_READ10;
89   - pccb->cmd[1] = pccb->lun << 5;
90   - pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff;
91   - pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff;
92   - pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff;
93   - pccb->cmd[5] = (unsigned char)start & 0xff;
94   - pccb->cmd[6] = 0;
95   - pccb->cmd[7] = (unsigned char)(blocks >> 8) & 0xff;
96   - pccb->cmd[8] = (unsigned char)blocks & 0xff;
97   - pccb->cmd[6] = 0;
98   - pccb->cmdlen = 10;
99   - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
100   - debug("scsi_setup_read_ext: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n",
101   - pccb->cmd[0], pccb->cmd[1],
102   - pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5],
103   - pccb->cmd[7], pccb->cmd[8]);
104   -}
105   -
106   -static void scsi_setup_write_ext(ccb *pccb, lbaint_t start,
107   - unsigned short blocks)
108   -{
109   - pccb->cmd[0] = SCSI_WRITE10;
110   - pccb->cmd[1] = pccb->lun << 5;
111   - pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff;
112   - pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff;
113   - pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff;
114   - pccb->cmd[5] = (unsigned char)start & 0xff;
115   - pccb->cmd[6] = 0;
116   - pccb->cmd[7] = ((unsigned char)(blocks >> 8)) & 0xff;
117   - pccb->cmd[8] = (unsigned char)blocks & 0xff;
118   - pccb->cmd[9] = 0;
119   - pccb->cmdlen = 10;
120   - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
121   - debug("%s: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n",
122   - __func__,
123   - pccb->cmd[0], pccb->cmd[1],
124   - pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5],
125   - pccb->cmd[7], pccb->cmd[8]);
126   -}
127   -
128   -static void scsi_setup_inquiry(ccb *pccb)
129   -{
130   - pccb->cmd[0] = SCSI_INQUIRY;
131   - pccb->cmd[1] = pccb->lun << 5;
132   - pccb->cmd[2] = 0;
133   - pccb->cmd[3] = 0;
134   - if (pccb->datalen > 255)
135   - pccb->cmd[4] = 255;
136   - else
137   - pccb->cmd[4] = (unsigned char)pccb->datalen;
138   - pccb->cmd[5] = 0;
139   - pccb->cmdlen = 6;
140   - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
141   -}
142   -
143   -#ifdef CONFIG_BLK
144   -static ulong scsi_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
145   - void *buffer)
146   -#else
147   -static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr,
148   - lbaint_t blkcnt, void *buffer)
149   -#endif
150   -{
151   -#ifdef CONFIG_BLK
152   - struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
153   -#endif
154   - lbaint_t start, blks;
155   - uintptr_t buf_addr;
156   - unsigned short smallblks = 0;
157   - ccb *pccb = (ccb *)&tempccb;
158   -
159   - /* Setup device */
160   - pccb->target = block_dev->target;
161   - pccb->lun = block_dev->lun;
162   - buf_addr = (unsigned long)buffer;
163   - start = blknr;
164   - blks = blkcnt;
165   - debug("\nscsi_read: dev %d startblk " LBAF
166   - ", blccnt " LBAF " buffer %lx\n",
167   - block_dev->devnum, start, blks, (unsigned long)buffer);
168   - do {
169   - pccb->pdata = (unsigned char *)buf_addr;
170   -#ifdef CONFIG_SYS_64BIT_LBA
171   - if (start > SCSI_LBA48_READ) {
172   - unsigned long blocks;
173   - blocks = min_t(lbaint_t, blks, SCSI_MAX_READ_BLK);
174   - pccb->datalen = block_dev->blksz * blocks;
175   - scsi_setup_read16(pccb, start, blocks);
176   - start += blocks;
177   - blks -= blocks;
178   - } else
179   -#endif
180   - if (blks > SCSI_MAX_READ_BLK) {
181   - pccb->datalen = block_dev->blksz *
182   - SCSI_MAX_READ_BLK;
183   - smallblks = SCSI_MAX_READ_BLK;
184   - scsi_setup_read_ext(pccb, start, smallblks);
185   - start += SCSI_MAX_READ_BLK;
186   - blks -= SCSI_MAX_READ_BLK;
187   - } else {
188   - pccb->datalen = block_dev->blksz * blks;
189   - smallblks = (unsigned short)blks;
190   - scsi_setup_read_ext(pccb, start, smallblks);
191   - start += blks;
192   - blks = 0;
193   - }
194   - debug("scsi_read_ext: startblk " LBAF
195   - ", blccnt %x buffer %" PRIXPTR "\n",
196   - start, smallblks, buf_addr);
197   - if (scsi_exec(pccb) != true) {
198   - scsi_print_error(pccb);
199   - blkcnt -= blks;
200   - break;
201   - }
202   - buf_addr += pccb->datalen;
203   - } while (blks != 0);
204   - debug("scsi_read_ext: end startblk " LBAF
205   - ", blccnt %x buffer %" PRIXPTR "\n", start, smallblks, buf_addr);
206   - return blkcnt;
207   -}
208   -
209   -/*******************************************************************************
210   - * scsi_write
211   - */
212   -
213   -/* Almost the maximum amount of the scsi_ext command.. */
214   -#define SCSI_MAX_WRITE_BLK 0xFFFF
215   -
216   -#ifdef CONFIG_BLK
217   -static ulong scsi_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
218   - const void *buffer)
219   -#else
220   -static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr,
221   - lbaint_t blkcnt, const void *buffer)
222   -#endif
223   -{
224   -#ifdef CONFIG_BLK
225   - struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
226   -#endif
227   - lbaint_t start, blks;
228   - uintptr_t buf_addr;
229   - unsigned short smallblks;
230   - ccb *pccb = (ccb *)&tempccb;
231   -
232   - /* Setup device */
233   - pccb->target = block_dev->target;
234   - pccb->lun = block_dev->lun;
235   - buf_addr = (unsigned long)buffer;
236   - start = blknr;
237   - blks = blkcnt;
238   - debug("\n%s: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
239   - __func__, block_dev->devnum, start, blks, (unsigned long)buffer);
240   - do {
241   - pccb->pdata = (unsigned char *)buf_addr;
242   - if (blks > SCSI_MAX_WRITE_BLK) {
243   - pccb->datalen = (block_dev->blksz *
244   - SCSI_MAX_WRITE_BLK);
245   - smallblks = SCSI_MAX_WRITE_BLK;
246   - scsi_setup_write_ext(pccb, start, smallblks);
247   - start += SCSI_MAX_WRITE_BLK;
248   - blks -= SCSI_MAX_WRITE_BLK;
249   - } else {
250   - pccb->datalen = block_dev->blksz * blks;
251   - smallblks = (unsigned short)blks;
252   - scsi_setup_write_ext(pccb, start, smallblks);
253   - start += blks;
254   - blks = 0;
255   - }
256   - debug("%s: startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n",
257   - __func__, start, smallblks, buf_addr);
258   - if (scsi_exec(pccb) != true) {
259   - scsi_print_error(pccb);
260   - blkcnt -= blks;
261   - break;
262   - }
263   - buf_addr += pccb->datalen;
264   - } while (blks != 0);
265   - debug("%s: end startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n",
266   - __func__, start, smallblks, buf_addr);
267   - return blkcnt;
268   -}
269   -
270   -#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT)
271   -void scsi_init(void)
272   -{
273   - int busdevfunc = -1;
274   - int i;
275   - /*
276   - * Find a device from the list, this driver will support a single
277   - * controller.
278   - */
279   - for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) {
280   - /* get PCI Device ID */
281   -#ifdef CONFIG_DM_PCI
282   - struct udevice *dev;
283   - int ret;
284   -
285   - ret = dm_pci_find_device(scsi_device_list[i].vendor,
286   - scsi_device_list[i].device, 0, &dev);
287   - if (!ret) {
288   - busdevfunc = dm_pci_get_bdf(dev);
289   - break;
290   - }
291   -#else
292   - busdevfunc = pci_find_device(scsi_device_list[i].vendor,
293   - scsi_device_list[i].device,
294   - 0);
295   -#endif
296   - if (busdevfunc != -1)
297   - break;
298   - }
299   -
300   - if (busdevfunc == -1) {
301   - printf("Error: SCSI Controller(s) ");
302   - for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) {
303   - printf("%04X:%04X ",
304   - scsi_device_list[i].vendor,
305   - scsi_device_list[i].device);
306   - }
307   - printf("not found\n");
308   - return;
309   - }
310   -#ifdef DEBUG
311   - else {
312   - printf("SCSI Controller (%04X,%04X) found (%d:%d:%d)\n",
313   - scsi_device_list[i].vendor,
314   - scsi_device_list[i].device,
315   - (busdevfunc >> 16) & 0xFF,
316   - (busdevfunc >> 11) & 0x1F,
317   - (busdevfunc >> 8) & 0x7);
318   - }
319   -#endif
320   - bootstage_start(BOOTSTAGE_ID_ACCUM_SCSI, "ahci");
321   - scsi_low_level_init(busdevfunc);
322   - scsi_scan(1);
323   - bootstage_accum(BOOTSTAGE_ID_ACCUM_SCSI);
324   -}
325   -#endif
326   -
327   -/* copy src to dest, skipping leading and trailing blanks
328   - * and null terminate the string
329   - */
330   -static void scsi_ident_cpy(unsigned char *dest, unsigned char *src,
331   - unsigned int len)
332   -{
333   - int start, end;
334   -
335   - start = 0;
336   - while (start < len) {
337   - if (src[start] != ' ')
338   - break;
339   - start++;
340   - }
341   - end = len-1;
342   - while (end > start) {
343   - if (src[end] != ' ')
344   - break;
345   - end--;
346   - }
347   - for (; start <= end; start++)
348   - *dest ++= src[start];
349   - *dest = '\0';
350   -}
351   -
352   -static int scsi_read_capacity(ccb *pccb, lbaint_t *capacity,
353   - unsigned long *blksz)
354   -{
355   - *capacity = 0;
356   -
357   - memset(pccb->cmd, '\0', sizeof(pccb->cmd));
358   - pccb->cmd[0] = SCSI_RD_CAPAC10;
359   - pccb->cmd[1] = pccb->lun << 5;
360   - pccb->cmdlen = 10;
361   - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
362   -
363   - pccb->datalen = 8;
364   - if (scsi_exec(pccb) != true)
365   - return 1;
366   -
367   - *capacity = ((lbaint_t)pccb->pdata[0] << 24) |
368   - ((lbaint_t)pccb->pdata[1] << 16) |
369   - ((lbaint_t)pccb->pdata[2] << 8) |
370   - ((lbaint_t)pccb->pdata[3]);
371   -
372   - if (*capacity != 0xffffffff) {
373   - /* Read capacity (10) was sufficient for this drive. */
374   - *blksz = ((unsigned long)pccb->pdata[4] << 24) |
375   - ((unsigned long)pccb->pdata[5] << 16) |
376   - ((unsigned long)pccb->pdata[6] << 8) |
377   - ((unsigned long)pccb->pdata[7]);
378   - return 0;
379   - }
380   -
381   - /* Read capacity (10) was insufficient. Use read capacity (16). */
382   - memset(pccb->cmd, '\0', sizeof(pccb->cmd));
383   - pccb->cmd[0] = SCSI_RD_CAPAC16;
384   - pccb->cmd[1] = 0x10;
385   - pccb->cmdlen = 16;
386   - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
387   -
388   - pccb->datalen = 16;
389   - if (scsi_exec(pccb) != true)
390   - return 1;
391   -
392   - *capacity = ((uint64_t)pccb->pdata[0] << 56) |
393   - ((uint64_t)pccb->pdata[1] << 48) |
394   - ((uint64_t)pccb->pdata[2] << 40) |
395   - ((uint64_t)pccb->pdata[3] << 32) |
396   - ((uint64_t)pccb->pdata[4] << 24) |
397   - ((uint64_t)pccb->pdata[5] << 16) |
398   - ((uint64_t)pccb->pdata[6] << 8) |
399   - ((uint64_t)pccb->pdata[7]);
400   -
401   - *blksz = ((uint64_t)pccb->pdata[8] << 56) |
402   - ((uint64_t)pccb->pdata[9] << 48) |
403   - ((uint64_t)pccb->pdata[10] << 40) |
404   - ((uint64_t)pccb->pdata[11] << 32) |
405   - ((uint64_t)pccb->pdata[12] << 24) |
406   - ((uint64_t)pccb->pdata[13] << 16) |
407   - ((uint64_t)pccb->pdata[14] << 8) |
408   - ((uint64_t)pccb->pdata[15]);
409   -
410   - return 0;
411   -}
412   -
413   -
414   -/*
415   - * Some setup (fill-in) routines
416   - */
417   -static void scsi_setup_test_unit_ready(ccb *pccb)
418   -{
419   - pccb->cmd[0] = SCSI_TST_U_RDY;
420   - pccb->cmd[1] = pccb->lun << 5;
421   - pccb->cmd[2] = 0;
422   - pccb->cmd[3] = 0;
423   - pccb->cmd[4] = 0;
424   - pccb->cmd[5] = 0;
425   - pccb->cmdlen = 6;
426   - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
427   -}
428   -
429   -/**
430   - * scsi_init_dev_desc_priv - initialize only SCSI specific blk_desc properties
431   - *
432   - * @dev_desc: Block device description pointer
433   - */
434   -static void scsi_init_dev_desc_priv(struct blk_desc *dev_desc)
435   -{
436   - dev_desc->target = 0xff;
437   - dev_desc->lun = 0xff;
438   - dev_desc->log2blksz =
439   - LOG2_INVALID(typeof(dev_desc->log2blksz));
440   - dev_desc->type = DEV_TYPE_UNKNOWN;
441   - dev_desc->vendor[0] = 0;
442   - dev_desc->product[0] = 0;
443   - dev_desc->revision[0] = 0;
444   - dev_desc->removable = false;
445   -#ifndef CONFIG_BLK
446   - dev_desc->block_read = scsi_read;
447   - dev_desc->block_write = scsi_write;
448   -#endif
449   -}
450   -
451   -#if !defined(CONFIG_DM_SCSI)
452   -/**
453   - * scsi_init_dev_desc - initialize all SCSI specific blk_desc properties
454   - *
455   - * @dev_desc: Block device description pointer
456   - * @devnum: Device number
457   - */
458   -static void scsi_init_dev_desc(struct blk_desc *dev_desc, int devnum)
459   -{
460   - dev_desc->lba = 0;
461   - dev_desc->blksz = 0;
462   - dev_desc->if_type = IF_TYPE_SCSI;
463   - dev_desc->devnum = devnum;
464   - dev_desc->part_type = PART_TYPE_UNKNOWN;
465   -
466   - scsi_init_dev_desc_priv(dev_desc);
467   -}
468   -#endif
469   -
470   -/**
471   - * scsi_detect_dev - Detect scsi device
472   - *
473   - * @target: target id
474   - * @lun: target lun
475   - * @dev_desc: block device description
476   - *
477   - * The scsi_detect_dev detects and fills a dev_desc structure when the device is
478   - * detected.
479   - *
480   - * Return: 0 on success, error value otherwise
481   - */
482   -static int scsi_detect_dev(int target, int lun, struct blk_desc *dev_desc)
483   -{
484   - unsigned char perq, modi;
485   - lbaint_t capacity;
486   - unsigned long blksz;
487   - ccb *pccb = (ccb *)&tempccb;
488   -
489   - pccb->target = target;
490   - pccb->lun = lun;
491   - pccb->pdata = (unsigned char *)&tempbuff;
492   - pccb->datalen = 512;
493   - scsi_setup_inquiry(pccb);
494   - if (scsi_exec(pccb) != true) {
495   - if (pccb->contr_stat == SCSI_SEL_TIME_OUT) {
496   - /*
497   - * selection timeout => assuming no
498   - * device present
499   - */
500   - debug("Selection timeout ID %d\n",
501   - pccb->target);
502   - return -ETIMEDOUT;
503   - }
504   - scsi_print_error(pccb);
505   - return -ENODEV;
506   - }
507   - perq = tempbuff[0];
508   - modi = tempbuff[1];
509   - if ((perq & 0x1f) == 0x1f)
510   - return -ENODEV; /* skip unknown devices */
511   - if ((modi & 0x80) == 0x80) /* drive is removable */
512   - dev_desc->removable = true;
513   - /* get info for this device */
514   - scsi_ident_cpy((unsigned char *)dev_desc->vendor,
515   - &tempbuff[8], 8);
516   - scsi_ident_cpy((unsigned char *)dev_desc->product,
517   - &tempbuff[16], 16);
518   - scsi_ident_cpy((unsigned char *)dev_desc->revision,
519   - &tempbuff[32], 4);
520   - dev_desc->target = pccb->target;
521   - dev_desc->lun = pccb->lun;
522   -
523   - pccb->datalen = 0;
524   - scsi_setup_test_unit_ready(pccb);
525   - if (scsi_exec(pccb) != true) {
526   - if (dev_desc->removable) {
527   - dev_desc->type = perq;
528   - goto removable;
529   - }
530   - scsi_print_error(pccb);
531   - return -EINVAL;
532   - }
533   - if (scsi_read_capacity(pccb, &capacity, &blksz)) {
534   - scsi_print_error(pccb);
535   - return -EINVAL;
536   - }
537   - dev_desc->lba = capacity;
538   - dev_desc->blksz = blksz;
539   - dev_desc->log2blksz = LOG2(dev_desc->blksz);
540   - dev_desc->type = perq;
541   -removable:
542   - return 0;
543   -}
544   -
545   -/*
546   - * (re)-scan the scsi bus and reports scsi device info
547   - * to the user if mode = 1
548   - */
549   -#if defined(CONFIG_DM_SCSI)
550   -static int do_scsi_scan_one(struct udevice *dev, int id, int lun, int mode)
551   -{
552   - int ret;
553   - struct udevice *bdev;
554   - struct blk_desc bd;
555   - struct blk_desc *bdesc;
556   - char str[10];
557   -
558   - /*
559   - * detect the scsi driver to get information about its geometry (block
560   - * size, number of blocks) and other parameters (ids, type, ...)
561   - */
562   - scsi_init_dev_desc_priv(&bd);
563   - if (scsi_detect_dev(id, lun, &bd))
564   - return -ENODEV;
565   -
566   - /*
567   - * Create only one block device and do detection
568   - * to make sure that there won't be a lot of
569   - * block devices created
570   - */
571   - snprintf(str, sizeof(str), "id%dlun%d", id, lun);
572   - ret = blk_create_devicef(dev, "scsi_blk", str, IF_TYPE_SCSI, -1,
573   - bd.blksz, bd.blksz * bd.lba, &bdev);
574   - if (ret) {
575   - debug("Can't create device\n");
576   - return ret;
577   - }
578   -
579   - bdesc = dev_get_uclass_platdata(bdev);
580   - bdesc->target = id;
581   - bdesc->lun = lun;
582   - bdesc->removable = bd.removable;
583   - bdesc->type = bd.type;
584   - memcpy(&bdesc->vendor, &bd.vendor, sizeof(bd.vendor));
585   - memcpy(&bdesc->product, &bd.product, sizeof(bd.product));
586   - memcpy(&bdesc->revision, &bd.revision, sizeof(bd.revision));
587   - part_init(bdesc);
588   -
589   - if (mode == 1) {
590   - printf(" Device %d: ", 0);
591   - dev_print(bdesc);
592   - }
593   - return 0;
594   -}
595   -
596   -int scsi_scan(int mode)
597   -{
598   - unsigned char i, lun;
599   - struct uclass *uc;
600   - struct udevice *dev; /* SCSI controller */
601   - int ret;
602   -
603   - if (mode == 1)
604   - printf("scanning bus for devices...\n");
605   -
606   - blk_unbind_all(IF_TYPE_SCSI);
607   -
608   - ret = uclass_get(UCLASS_SCSI, &uc);
609   - if (ret)
610   - return ret;
611   -
612   - uclass_foreach_dev(dev, uc) {
613   - struct scsi_platdata *plat; /* scsi controller platdata */
614   -
615   - /* probe SCSI controller driver */
616   - ret = device_probe(dev);
617   - if (ret)
618   - return ret;
619   -
620   - /* Get controller platdata */
621   - plat = dev_get_platdata(dev);
622   -
623   - for (i = 0; i < plat->max_id; i++)
624   - for (lun = 0; lun < plat->max_lun; lun++)
625   - do_scsi_scan_one(dev, i, lun, mode);
626   - }
627   -
628   - return 0;
629   -}
630   -#else
631   -int scsi_scan(int mode)
632   -{
633   - unsigned char i, lun;
634   - int ret;
635   -
636   - if (mode == 1)
637   - printf("scanning bus for devices...\n");
638   - for (i = 0; i < CONFIG_SYS_SCSI_MAX_DEVICE; i++)
639   - scsi_init_dev_desc(&scsi_dev_desc[i], i);
640   -
641   - scsi_max_devs = 0;
642   - for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) {
643   - for (lun = 0; lun < CONFIG_SYS_SCSI_MAX_LUN; lun++) {
644   - ret = scsi_detect_dev(i, lun,
645   - &scsi_dev_desc[scsi_max_devs]);
646   - if (ret)
647   - continue;
648   - part_init(&scsi_dev_desc[scsi_max_devs]);
649   -
650   - if (mode == 1) {
651   - printf(" Device %d: ", 0);
652   - dev_print(&scsi_dev_desc[scsi_max_devs]);
653   - } /* if mode */
654   - scsi_max_devs++;
655   - } /* next LUN */
656   - }
657   - if (scsi_max_devs > 0)
658   - scsi_curr_dev = 0;
659   - else
660   - scsi_curr_dev = -1;
661   -
662   - printf("Found %d device(s).\n", scsi_max_devs);
663   -#ifndef CONFIG_SPL_BUILD
664   - setenv_ulong("scsidevs", scsi_max_devs);
665   -#endif
666   - return 0;
667   -}
668   -#endif
669   -
670   -#ifdef CONFIG_BLK
671   -static const struct blk_ops scsi_blk_ops = {
672   - .read = scsi_read,
673   - .write = scsi_write,
674   -};
675   -
676   -U_BOOT_DRIVER(scsi_blk) = {
677   - .name = "scsi_blk",
678   - .id = UCLASS_BLK,
679   - .ops = &scsi_blk_ops,
680   -};
681   -#else
682   -U_BOOT_LEGACY_BLK(scsi) = {
683   - .if_typename = "scsi",
684   - .if_type = IF_TYPE_SCSI,
685   - .max_devs = CONFIG_SYS_SCSI_MAX_DEVICE,
686   - .desc = scsi_dev_desc,
687   -};
688   -#endif
... ... @@ -72,6 +72,8 @@
72 72  
73 73 source "drivers/rtc/Kconfig"
74 74  
  75 +source "drivers/scsi/Kconfig"
  76 +
75 77 source "drivers/serial/Kconfig"
76 78  
77 79 source "drivers/sound/Kconfig"
... ... @@ -45,7 +45,7 @@
45 45 obj-$(CONFIG_SPL_WATCHDOG_SUPPORT) += watchdog/
46 46 obj-$(CONFIG_SPL_USB_HOST_SUPPORT) += usb/host/
47 47 obj-$(CONFIG_OMAP_USB_PHY) += usb/phy/
48   -obj-$(CONFIG_SPL_SATA_SUPPORT) += ata/
  48 +obj-$(CONFIG_SPL_SATA_SUPPORT) += ata/ scsi/
49 49 obj-$(CONFIG_SPL_USB_HOST_SUPPORT) += block/
50 50 obj-$(CONFIG_SPL_MMC_SUPPORT) += block/
51 51 endif
... ... @@ -82,6 +82,7 @@
82 82 obj-$(CONFIG_X86) += pch/
83 83 obj-y += phy/marvell/
84 84 obj-y += rtc/
  85 +obj-y += scsi/
85 86 obj-y += sound/
86 87 obj-y += spmi/
87 88 obj-y += sysreset/
drivers/block/Kconfig
... ... @@ -10,24 +10,6 @@
10 10 be partitioned into several areas, called 'partitions' in U-Boot.
11 11 A filesystem can be placed in each partition.
12 12  
13   -config SCSI
14   - bool "Support SCSI controllers"
15   - help
16   - This enables support for SCSI (Small Computer System Interface),
17   - a parallel interface widely used with storage peripherals such as
18   - hard drives and optical drives. The SCSI standards define physical
19   - interfaces as well as protocols for controlling devices and
20   - tranferring data.
21   -
22   -config DM_SCSI
23   - bool "Support SCSI controllers with driver model"
24   - depends on BLK
25   - help
26   - This option enables the SCSI (Small Computer System Interface) uclass
27   - which supports SCSI and SATA HDDs. For every device configuration
28   - (IDs/LUNs) a block device is created with RAW read/write and
29   - filesystem support.
30   -
31 13 config BLOCK_CACHE
32 14 bool "Use block device cache"
33 15 default n
drivers/block/Makefile
... ... @@ -13,7 +13,7 @@
13 13  
14 14 obj-$(CONFIG_IDE) += ide.o
15 15 obj-$(CONFIG_IDE_FTIDE020) += ftide020.o
16   -obj-$(CONFIG_SANDBOX) += sandbox.o sandbox_scsi.o
  16 +obj-$(CONFIG_SANDBOX) += sandbox.o
17 17 obj-$(CONFIG_SYSTEMACE) += systemace.o
18 18 obj-$(CONFIG_BLOCK_CACHE) += blkcache.o
drivers/block/sandbox_scsi.c
1   -/*
2   - * Copyright (C) 2015 Google, Inc
3   - * Written by Simon Glass <sjg@chromium.org>
4   - *
5   - * SPDX-License-Identifier: GPL-2.0+
6   - *
7   - * This file contains dummy implementations of SCSI functions requried so
8   - * that CONFIG_SCSI can be enabled for sandbox.
9   - */
10   -
11   -#include <common.h>
12   -#include <scsi.h>
13   -
14   -void scsi_bus_reset(void)
15   -{
16   -}
17   -
18   -void scsi_init(void)
19   -{
20   -}
21   -
22   -int scsi_exec(ccb *pccb)
23   -{
24   - return 0;
25   -}
drivers/block/scsi-uclass.c
1   -/*
2   - * Copyright (c) 2015 Google, Inc
3   - * Written by Simon Glass <sjg@chromium.org>
4   - * Copyright (c) 2016 Xilinx, Inc
5   - * Written by Michal Simek
6   - *
7   - * Based on ahci-uclass.c
8   - *
9   - * SPDX-License-Identifier: GPL-2.0+
10   - */
11   -
12   -#include <common.h>
13   -#include <dm.h>
14   -#include <scsi.h>
15   -
16   -static int scsi_post_probe(struct udevice *dev)
17   -{
18   - debug("%s: device %p\n", __func__, dev);
19   - scsi_low_level_init(0, dev);
20   - return 0;
21   -}
22   -
23   -UCLASS_DRIVER(scsi) = {
24   - .id = UCLASS_SCSI,
25   - .name = "scsi",
26   - .post_probe = scsi_post_probe,
27   -};
drivers/scsi/Kconfig
  1 +config SCSI
  2 + bool "Support SCSI controllers"
  3 + help
  4 + This enables support for SCSI (Small Computer System Interface),
  5 + a parallel interface widely used with storage peripherals such as
  6 + hard drives and optical drives. The SCSI standards define physical
  7 + interfaces as well as protocols for controlling devices and
  8 + tranferring data.
  9 +
  10 +config DM_SCSI
  11 + bool "Support SCSI controllers with driver model"
  12 + depends on BLK
  13 + help
  14 + This option enables the SCSI (Small Computer System Interface) uclass
  15 + which supports SCSI and SATA HDDs. For every device configuration
  16 + (IDs/LUNs) a block device is created with RAW read/write and
  17 + filesystem support.
drivers/scsi/Makefile
  1 +#
  2 +# (C) Copyright 2000-2007
  3 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  4 +#
  5 +# SPDX-License-Identifier: GPL-2.0+
  6 +#
  7 +
  8 +ifndef CONFIG_SPL_BUILD
  9 +obj-$(CONFIG_DM_SCSI) += scsi-uclass.o
  10 +obj-$(CONFIG_SCSI) += scsi.o
  11 +endif
  12 +
  13 +ifdef CONFIG_SPL_BUILD
  14 +ifdef CONFIG_SPL_SATA_SUPPORT
  15 +obj-$(CONFIG_DM_SCSI) += scsi-uclass.o
  16 +obj-$(CONFIG_SCSI) += scsi.o
  17 +endif
  18 +endif
  19 +
  20 +obj-$(CONFIG_SANDBOX) += sandbox_scsi.o
drivers/scsi/sandbox_scsi.c
  1 +/*
  2 + * Copyright (C) 2015 Google, Inc
  3 + * Written by Simon Glass <sjg@chromium.org>
  4 + *
  5 + * SPDX-License-Identifier: GPL-2.0+
  6 + *
  7 + * This file contains dummy implementations of SCSI functions requried so
  8 + * that CONFIG_SCSI can be enabled for sandbox.
  9 + */
  10 +
  11 +#include <common.h>
  12 +#include <scsi.h>
  13 +
  14 +void scsi_bus_reset(void)
  15 +{
  16 +}
  17 +
  18 +void scsi_init(void)
  19 +{
  20 +}
  21 +
  22 +int scsi_exec(ccb *pccb)
  23 +{
  24 + return 0;
  25 +}
drivers/scsi/scsi-uclass.c
  1 +/*
  2 + * Copyright (c) 2015 Google, Inc
  3 + * Written by Simon Glass <sjg@chromium.org>
  4 + * Copyright (c) 2016 Xilinx, Inc
  5 + * Written by Michal Simek
  6 + *
  7 + * Based on ahci-uclass.c
  8 + *
  9 + * SPDX-License-Identifier: GPL-2.0+
  10 + */
  11 +
  12 +#include <common.h>
  13 +#include <dm.h>
  14 +#include <scsi.h>
  15 +
  16 +static int scsi_post_probe(struct udevice *dev)
  17 +{
  18 + debug("%s: device %p\n", __func__, dev);
  19 + scsi_low_level_init(0, dev);
  20 + return 0;
  21 +}
  22 +
  23 +UCLASS_DRIVER(scsi) = {
  24 + .id = UCLASS_SCSI,
  25 + .name = "scsi",
  26 + .post_probe = scsi_post_probe,
  27 +};
  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 +#include <dm/device-internal.h>
  14 +#include <dm/uclass-internal.h>
  15 +
  16 +#if !defined(CONFIG_DM_SCSI)
  17 +#ifdef CONFIG_SCSI_DEV_LIST
  18 +#define SCSI_DEV_LIST CONFIG_SCSI_DEV_LIST
  19 +#else
  20 +#ifdef CONFIG_SATA_ULI5288
  21 +
  22 +#define SCSI_VEND_ID 0x10b9
  23 +#define SCSI_DEV_ID 0x5288
  24 +
  25 +#elif !defined(CONFIG_SCSI_AHCI_PLAT)
  26 +#error no scsi device defined
  27 +#endif
  28 +#define SCSI_DEV_LIST {SCSI_VEND_ID, SCSI_DEV_ID}
  29 +#endif
  30 +#endif
  31 +
  32 +#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT)
  33 +const struct pci_device_id scsi_device_list[] = { SCSI_DEV_LIST };
  34 +#endif
  35 +static ccb tempccb; /* temporary scsi command buffer */
  36 +
  37 +static unsigned char tempbuff[512]; /* temporary data buffer */
  38 +
  39 +#if !defined(CONFIG_DM_SCSI)
  40 +static int scsi_max_devs; /* number of highest available scsi device */
  41 +
  42 +static int scsi_curr_dev; /* current device */
  43 +
  44 +static struct blk_desc scsi_dev_desc[CONFIG_SYS_SCSI_MAX_DEVICE];
  45 +#endif
  46 +
  47 +/* almost the maximum amount of the scsi_ext command.. */
  48 +#define SCSI_MAX_READ_BLK 0xFFFF
  49 +#define SCSI_LBA48_READ 0xFFFFFFF
  50 +
  51 +static void scsi_print_error(ccb *pccb)
  52 +{
  53 + /* Dummy function that could print an error for debugging */
  54 +}
  55 +
  56 +#ifdef CONFIG_SYS_64BIT_LBA
  57 +void scsi_setup_read16(ccb *pccb, lbaint_t start, unsigned long blocks)
  58 +{
  59 + pccb->cmd[0] = SCSI_READ16;
  60 + pccb->cmd[1] = pccb->lun << 5;
  61 + pccb->cmd[2] = (unsigned char)(start >> 56) & 0xff;
  62 + pccb->cmd[3] = (unsigned char)(start >> 48) & 0xff;
  63 + pccb->cmd[4] = (unsigned char)(start >> 40) & 0xff;
  64 + pccb->cmd[5] = (unsigned char)(start >> 32) & 0xff;
  65 + pccb->cmd[6] = (unsigned char)(start >> 24) & 0xff;
  66 + pccb->cmd[7] = (unsigned char)(start >> 16) & 0xff;
  67 + pccb->cmd[8] = (unsigned char)(start >> 8) & 0xff;
  68 + pccb->cmd[9] = (unsigned char)start & 0xff;
  69 + pccb->cmd[10] = 0;
  70 + pccb->cmd[11] = (unsigned char)(blocks >> 24) & 0xff;
  71 + pccb->cmd[12] = (unsigned char)(blocks >> 16) & 0xff;
  72 + pccb->cmd[13] = (unsigned char)(blocks >> 8) & 0xff;
  73 + pccb->cmd[14] = (unsigned char)blocks & 0xff;
  74 + pccb->cmd[15] = 0;
  75 + pccb->cmdlen = 16;
  76 + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
  77 + debug("scsi_setup_read16: cmd: %02X %02X startblk %02X%02X%02X%02X%02X%02X%02X%02X blccnt %02X%02X%02X%02X\n",
  78 + pccb->cmd[0], pccb->cmd[1],
  79 + pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5],
  80 + pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9],
  81 + pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]);
  82 +}
  83 +#endif
  84 +
  85 +static void scsi_setup_read_ext(ccb *pccb, lbaint_t start,
  86 + unsigned short blocks)
  87 +{
  88 + pccb->cmd[0] = SCSI_READ10;
  89 + pccb->cmd[1] = pccb->lun << 5;
  90 + pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff;
  91 + pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff;
  92 + pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff;
  93 + pccb->cmd[5] = (unsigned char)start & 0xff;
  94 + pccb->cmd[6] = 0;
  95 + pccb->cmd[7] = (unsigned char)(blocks >> 8) & 0xff;
  96 + pccb->cmd[8] = (unsigned char)blocks & 0xff;
  97 + pccb->cmd[6] = 0;
  98 + pccb->cmdlen = 10;
  99 + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
  100 + debug("scsi_setup_read_ext: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n",
  101 + pccb->cmd[0], pccb->cmd[1],
  102 + pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5],
  103 + pccb->cmd[7], pccb->cmd[8]);
  104 +}
  105 +
  106 +static void scsi_setup_write_ext(ccb *pccb, lbaint_t start,
  107 + unsigned short blocks)
  108 +{
  109 + pccb->cmd[0] = SCSI_WRITE10;
  110 + pccb->cmd[1] = pccb->lun << 5;
  111 + pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff;
  112 + pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff;
  113 + pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff;
  114 + pccb->cmd[5] = (unsigned char)start & 0xff;
  115 + pccb->cmd[6] = 0;
  116 + pccb->cmd[7] = ((unsigned char)(blocks >> 8)) & 0xff;
  117 + pccb->cmd[8] = (unsigned char)blocks & 0xff;
  118 + pccb->cmd[9] = 0;
  119 + pccb->cmdlen = 10;
  120 + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
  121 + debug("%s: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n",
  122 + __func__,
  123 + pccb->cmd[0], pccb->cmd[1],
  124 + pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5],
  125 + pccb->cmd[7], pccb->cmd[8]);
  126 +}
  127 +
  128 +static void scsi_setup_inquiry(ccb *pccb)
  129 +{
  130 + pccb->cmd[0] = SCSI_INQUIRY;
  131 + pccb->cmd[1] = pccb->lun << 5;
  132 + pccb->cmd[2] = 0;
  133 + pccb->cmd[3] = 0;
  134 + if (pccb->datalen > 255)
  135 + pccb->cmd[4] = 255;
  136 + else
  137 + pccb->cmd[4] = (unsigned char)pccb->datalen;
  138 + pccb->cmd[5] = 0;
  139 + pccb->cmdlen = 6;
  140 + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
  141 +}
  142 +
  143 +#ifdef CONFIG_BLK
  144 +static ulong scsi_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
  145 + void *buffer)
  146 +#else
  147 +static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr,
  148 + lbaint_t blkcnt, void *buffer)
  149 +#endif
  150 +{
  151 +#ifdef CONFIG_BLK
  152 + struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
  153 +#endif
  154 + lbaint_t start, blks;
  155 + uintptr_t buf_addr;
  156 + unsigned short smallblks = 0;
  157 + ccb *pccb = (ccb *)&tempccb;
  158 +
  159 + /* Setup device */
  160 + pccb->target = block_dev->target;
  161 + pccb->lun = block_dev->lun;
  162 + buf_addr = (unsigned long)buffer;
  163 + start = blknr;
  164 + blks = blkcnt;
  165 + debug("\nscsi_read: dev %d startblk " LBAF
  166 + ", blccnt " LBAF " buffer %lx\n",
  167 + block_dev->devnum, start, blks, (unsigned long)buffer);
  168 + do {
  169 + pccb->pdata = (unsigned char *)buf_addr;
  170 +#ifdef CONFIG_SYS_64BIT_LBA
  171 + if (start > SCSI_LBA48_READ) {
  172 + unsigned long blocks;
  173 + blocks = min_t(lbaint_t, blks, SCSI_MAX_READ_BLK);
  174 + pccb->datalen = block_dev->blksz * blocks;
  175 + scsi_setup_read16(pccb, start, blocks);
  176 + start += blocks;
  177 + blks -= blocks;
  178 + } else
  179 +#endif
  180 + if (blks > SCSI_MAX_READ_BLK) {
  181 + pccb->datalen = block_dev->blksz *
  182 + SCSI_MAX_READ_BLK;
  183 + smallblks = SCSI_MAX_READ_BLK;
  184 + scsi_setup_read_ext(pccb, start, smallblks);
  185 + start += SCSI_MAX_READ_BLK;
  186 + blks -= SCSI_MAX_READ_BLK;
  187 + } else {
  188 + pccb->datalen = block_dev->blksz * blks;
  189 + smallblks = (unsigned short)blks;
  190 + scsi_setup_read_ext(pccb, start, smallblks);
  191 + start += blks;
  192 + blks = 0;
  193 + }
  194 + debug("scsi_read_ext: startblk " LBAF
  195 + ", blccnt %x buffer %" PRIXPTR "\n",
  196 + start, smallblks, buf_addr);
  197 + if (scsi_exec(pccb) != true) {
  198 + scsi_print_error(pccb);
  199 + blkcnt -= blks;
  200 + break;
  201 + }
  202 + buf_addr += pccb->datalen;
  203 + } while (blks != 0);
  204 + debug("scsi_read_ext: end startblk " LBAF
  205 + ", blccnt %x buffer %" PRIXPTR "\n", start, smallblks, buf_addr);
  206 + return blkcnt;
  207 +}
  208 +
  209 +/*******************************************************************************
  210 + * scsi_write
  211 + */
  212 +
  213 +/* Almost the maximum amount of the scsi_ext command.. */
  214 +#define SCSI_MAX_WRITE_BLK 0xFFFF
  215 +
  216 +#ifdef CONFIG_BLK
  217 +static ulong scsi_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
  218 + const void *buffer)
  219 +#else
  220 +static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr,
  221 + lbaint_t blkcnt, const void *buffer)
  222 +#endif
  223 +{
  224 +#ifdef CONFIG_BLK
  225 + struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
  226 +#endif
  227 + lbaint_t start, blks;
  228 + uintptr_t buf_addr;
  229 + unsigned short smallblks;
  230 + ccb *pccb = (ccb *)&tempccb;
  231 +
  232 + /* Setup device */
  233 + pccb->target = block_dev->target;
  234 + pccb->lun = block_dev->lun;
  235 + buf_addr = (unsigned long)buffer;
  236 + start = blknr;
  237 + blks = blkcnt;
  238 + debug("\n%s: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
  239 + __func__, block_dev->devnum, start, blks, (unsigned long)buffer);
  240 + do {
  241 + pccb->pdata = (unsigned char *)buf_addr;
  242 + if (blks > SCSI_MAX_WRITE_BLK) {
  243 + pccb->datalen = (block_dev->blksz *
  244 + SCSI_MAX_WRITE_BLK);
  245 + smallblks = SCSI_MAX_WRITE_BLK;
  246 + scsi_setup_write_ext(pccb, start, smallblks);
  247 + start += SCSI_MAX_WRITE_BLK;
  248 + blks -= SCSI_MAX_WRITE_BLK;
  249 + } else {
  250 + pccb->datalen = block_dev->blksz * blks;
  251 + smallblks = (unsigned short)blks;
  252 + scsi_setup_write_ext(pccb, start, smallblks);
  253 + start += blks;
  254 + blks = 0;
  255 + }
  256 + debug("%s: startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n",
  257 + __func__, start, smallblks, buf_addr);
  258 + if (scsi_exec(pccb) != true) {
  259 + scsi_print_error(pccb);
  260 + blkcnt -= blks;
  261 + break;
  262 + }
  263 + buf_addr += pccb->datalen;
  264 + } while (blks != 0);
  265 + debug("%s: end startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n",
  266 + __func__, start, smallblks, buf_addr);
  267 + return blkcnt;
  268 +}
  269 +
  270 +#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT)
  271 +void scsi_init(void)
  272 +{
  273 + int busdevfunc = -1;
  274 + int i;
  275 + /*
  276 + * Find a device from the list, this driver will support a single
  277 + * controller.
  278 + */
  279 + for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) {
  280 + /* get PCI Device ID */
  281 +#ifdef CONFIG_DM_PCI
  282 + struct udevice *dev;
  283 + int ret;
  284 +
  285 + ret = dm_pci_find_device(scsi_device_list[i].vendor,
  286 + scsi_device_list[i].device, 0, &dev);
  287 + if (!ret) {
  288 + busdevfunc = dm_pci_get_bdf(dev);
  289 + break;
  290 + }
  291 +#else
  292 + busdevfunc = pci_find_device(scsi_device_list[i].vendor,
  293 + scsi_device_list[i].device,
  294 + 0);
  295 +#endif
  296 + if (busdevfunc != -1)
  297 + break;
  298 + }
  299 +
  300 + if (busdevfunc == -1) {
  301 + printf("Error: SCSI Controller(s) ");
  302 + for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) {
  303 + printf("%04X:%04X ",
  304 + scsi_device_list[i].vendor,
  305 + scsi_device_list[i].device);
  306 + }
  307 + printf("not found\n");
  308 + return;
  309 + }
  310 +#ifdef DEBUG
  311 + else {
  312 + printf("SCSI Controller (%04X,%04X) found (%d:%d:%d)\n",
  313 + scsi_device_list[i].vendor,
  314 + scsi_device_list[i].device,
  315 + (busdevfunc >> 16) & 0xFF,
  316 + (busdevfunc >> 11) & 0x1F,
  317 + (busdevfunc >> 8) & 0x7);
  318 + }
  319 +#endif
  320 + bootstage_start(BOOTSTAGE_ID_ACCUM_SCSI, "ahci");
  321 + scsi_low_level_init(busdevfunc);
  322 + scsi_scan(1);
  323 + bootstage_accum(BOOTSTAGE_ID_ACCUM_SCSI);
  324 +}
  325 +#endif
  326 +
  327 +/* copy src to dest, skipping leading and trailing blanks
  328 + * and null terminate the string
  329 + */
  330 +static void scsi_ident_cpy(unsigned char *dest, unsigned char *src,
  331 + unsigned int len)
  332 +{
  333 + int start, end;
  334 +
  335 + start = 0;
  336 + while (start < len) {
  337 + if (src[start] != ' ')
  338 + break;
  339 + start++;
  340 + }
  341 + end = len-1;
  342 + while (end > start) {
  343 + if (src[end] != ' ')
  344 + break;
  345 + end--;
  346 + }
  347 + for (; start <= end; start++)
  348 + *dest ++= src[start];
  349 + *dest = '\0';
  350 +}
  351 +
  352 +static int scsi_read_capacity(ccb *pccb, lbaint_t *capacity,
  353 + unsigned long *blksz)
  354 +{
  355 + *capacity = 0;
  356 +
  357 + memset(pccb->cmd, '\0', sizeof(pccb->cmd));
  358 + pccb->cmd[0] = SCSI_RD_CAPAC10;
  359 + pccb->cmd[1] = pccb->lun << 5;
  360 + pccb->cmdlen = 10;
  361 + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
  362 +
  363 + pccb->datalen = 8;
  364 + if (scsi_exec(pccb) != true)
  365 + return 1;
  366 +
  367 + *capacity = ((lbaint_t)pccb->pdata[0] << 24) |
  368 + ((lbaint_t)pccb->pdata[1] << 16) |
  369 + ((lbaint_t)pccb->pdata[2] << 8) |
  370 + ((lbaint_t)pccb->pdata[3]);
  371 +
  372 + if (*capacity != 0xffffffff) {
  373 + /* Read capacity (10) was sufficient for this drive. */
  374 + *blksz = ((unsigned long)pccb->pdata[4] << 24) |
  375 + ((unsigned long)pccb->pdata[5] << 16) |
  376 + ((unsigned long)pccb->pdata[6] << 8) |
  377 + ((unsigned long)pccb->pdata[7]);
  378 + return 0;
  379 + }
  380 +
  381 + /* Read capacity (10) was insufficient. Use read capacity (16). */
  382 + memset(pccb->cmd, '\0', sizeof(pccb->cmd));
  383 + pccb->cmd[0] = SCSI_RD_CAPAC16;
  384 + pccb->cmd[1] = 0x10;
  385 + pccb->cmdlen = 16;
  386 + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
  387 +
  388 + pccb->datalen = 16;
  389 + if (scsi_exec(pccb) != true)
  390 + return 1;
  391 +
  392 + *capacity = ((uint64_t)pccb->pdata[0] << 56) |
  393 + ((uint64_t)pccb->pdata[1] << 48) |
  394 + ((uint64_t)pccb->pdata[2] << 40) |
  395 + ((uint64_t)pccb->pdata[3] << 32) |
  396 + ((uint64_t)pccb->pdata[4] << 24) |
  397 + ((uint64_t)pccb->pdata[5] << 16) |
  398 + ((uint64_t)pccb->pdata[6] << 8) |
  399 + ((uint64_t)pccb->pdata[7]);
  400 +
  401 + *blksz = ((uint64_t)pccb->pdata[8] << 56) |
  402 + ((uint64_t)pccb->pdata[9] << 48) |
  403 + ((uint64_t)pccb->pdata[10] << 40) |
  404 + ((uint64_t)pccb->pdata[11] << 32) |
  405 + ((uint64_t)pccb->pdata[12] << 24) |
  406 + ((uint64_t)pccb->pdata[13] << 16) |
  407 + ((uint64_t)pccb->pdata[14] << 8) |
  408 + ((uint64_t)pccb->pdata[15]);
  409 +
  410 + return 0;
  411 +}
  412 +
  413 +
  414 +/*
  415 + * Some setup (fill-in) routines
  416 + */
  417 +static void scsi_setup_test_unit_ready(ccb *pccb)
  418 +{
  419 + pccb->cmd[0] = SCSI_TST_U_RDY;
  420 + pccb->cmd[1] = pccb->lun << 5;
  421 + pccb->cmd[2] = 0;
  422 + pccb->cmd[3] = 0;
  423 + pccb->cmd[4] = 0;
  424 + pccb->cmd[5] = 0;
  425 + pccb->cmdlen = 6;
  426 + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
  427 +}
  428 +
  429 +/**
  430 + * scsi_init_dev_desc_priv - initialize only SCSI specific blk_desc properties
  431 + *
  432 + * @dev_desc: Block device description pointer
  433 + */
  434 +static void scsi_init_dev_desc_priv(struct blk_desc *dev_desc)
  435 +{
  436 + dev_desc->target = 0xff;
  437 + dev_desc->lun = 0xff;
  438 + dev_desc->log2blksz =
  439 + LOG2_INVALID(typeof(dev_desc->log2blksz));
  440 + dev_desc->type = DEV_TYPE_UNKNOWN;
  441 + dev_desc->vendor[0] = 0;
  442 + dev_desc->product[0] = 0;
  443 + dev_desc->revision[0] = 0;
  444 + dev_desc->removable = false;
  445 +#ifndef CONFIG_BLK
  446 + dev_desc->block_read = scsi_read;
  447 + dev_desc->block_write = scsi_write;
  448 +#endif
  449 +}
  450 +
  451 +#if !defined(CONFIG_DM_SCSI)
  452 +/**
  453 + * scsi_init_dev_desc - initialize all SCSI specific blk_desc properties
  454 + *
  455 + * @dev_desc: Block device description pointer
  456 + * @devnum: Device number
  457 + */
  458 +static void scsi_init_dev_desc(struct blk_desc *dev_desc, int devnum)
  459 +{
  460 + dev_desc->lba = 0;
  461 + dev_desc->blksz = 0;
  462 + dev_desc->if_type = IF_TYPE_SCSI;
  463 + dev_desc->devnum = devnum;
  464 + dev_desc->part_type = PART_TYPE_UNKNOWN;
  465 +
  466 + scsi_init_dev_desc_priv(dev_desc);
  467 +}
  468 +#endif
  469 +
  470 +/**
  471 + * scsi_detect_dev - Detect scsi device
  472 + *
  473 + * @target: target id
  474 + * @lun: target lun
  475 + * @dev_desc: block device description
  476 + *
  477 + * The scsi_detect_dev detects and fills a dev_desc structure when the device is
  478 + * detected.
  479 + *
  480 + * Return: 0 on success, error value otherwise
  481 + */
  482 +static int scsi_detect_dev(int target, int lun, struct blk_desc *dev_desc)
  483 +{
  484 + unsigned char perq, modi;
  485 + lbaint_t capacity;
  486 + unsigned long blksz;
  487 + ccb *pccb = (ccb *)&tempccb;
  488 +
  489 + pccb->target = target;
  490 + pccb->lun = lun;
  491 + pccb->pdata = (unsigned char *)&tempbuff;
  492 + pccb->datalen = 512;
  493 + scsi_setup_inquiry(pccb);
  494 + if (scsi_exec(pccb) != true) {
  495 + if (pccb->contr_stat == SCSI_SEL_TIME_OUT) {
  496 + /*
  497 + * selection timeout => assuming no
  498 + * device present
  499 + */
  500 + debug("Selection timeout ID %d\n",
  501 + pccb->target);
  502 + return -ETIMEDOUT;
  503 + }
  504 + scsi_print_error(pccb);
  505 + return -ENODEV;
  506 + }
  507 + perq = tempbuff[0];
  508 + modi = tempbuff[1];
  509 + if ((perq & 0x1f) == 0x1f)
  510 + return -ENODEV; /* skip unknown devices */
  511 + if ((modi & 0x80) == 0x80) /* drive is removable */
  512 + dev_desc->removable = true;
  513 + /* get info for this device */
  514 + scsi_ident_cpy((unsigned char *)dev_desc->vendor,
  515 + &tempbuff[8], 8);
  516 + scsi_ident_cpy((unsigned char *)dev_desc->product,
  517 + &tempbuff[16], 16);
  518 + scsi_ident_cpy((unsigned char *)dev_desc->revision,
  519 + &tempbuff[32], 4);
  520 + dev_desc->target = pccb->target;
  521 + dev_desc->lun = pccb->lun;
  522 +
  523 + pccb->datalen = 0;
  524 + scsi_setup_test_unit_ready(pccb);
  525 + if (scsi_exec(pccb) != true) {
  526 + if (dev_desc->removable) {
  527 + dev_desc->type = perq;
  528 + goto removable;
  529 + }
  530 + scsi_print_error(pccb);
  531 + return -EINVAL;
  532 + }
  533 + if (scsi_read_capacity(pccb, &capacity, &blksz)) {
  534 + scsi_print_error(pccb);
  535 + return -EINVAL;
  536 + }
  537 + dev_desc->lba = capacity;
  538 + dev_desc->blksz = blksz;
  539 + dev_desc->log2blksz = LOG2(dev_desc->blksz);
  540 + dev_desc->type = perq;
  541 +removable:
  542 + return 0;
  543 +}
  544 +
  545 +/*
  546 + * (re)-scan the scsi bus and reports scsi device info
  547 + * to the user if mode = 1
  548 + */
  549 +#if defined(CONFIG_DM_SCSI)
  550 +static int do_scsi_scan_one(struct udevice *dev, int id, int lun, int mode)
  551 +{
  552 + int ret;
  553 + struct udevice *bdev;
  554 + struct blk_desc bd;
  555 + struct blk_desc *bdesc;
  556 + char str[10];
  557 +
  558 + /*
  559 + * detect the scsi driver to get information about its geometry (block
  560 + * size, number of blocks) and other parameters (ids, type, ...)
  561 + */
  562 + scsi_init_dev_desc_priv(&bd);
  563 + if (scsi_detect_dev(id, lun, &bd))
  564 + return -ENODEV;
  565 +
  566 + /*
  567 + * Create only one block device and do detection
  568 + * to make sure that there won't be a lot of
  569 + * block devices created
  570 + */
  571 + snprintf(str, sizeof(str), "id%dlun%d", id, lun);
  572 + ret = blk_create_devicef(dev, "scsi_blk", str, IF_TYPE_SCSI, -1,
  573 + bd.blksz, bd.blksz * bd.lba, &bdev);
  574 + if (ret) {
  575 + debug("Can't create device\n");
  576 + return ret;
  577 + }
  578 +
  579 + bdesc = dev_get_uclass_platdata(bdev);
  580 + bdesc->target = id;
  581 + bdesc->lun = lun;
  582 + bdesc->removable = bd.removable;
  583 + bdesc->type = bd.type;
  584 + memcpy(&bdesc->vendor, &bd.vendor, sizeof(bd.vendor));
  585 + memcpy(&bdesc->product, &bd.product, sizeof(bd.product));
  586 + memcpy(&bdesc->revision, &bd.revision, sizeof(bd.revision));
  587 + part_init(bdesc);
  588 +
  589 + if (mode == 1) {
  590 + printf(" Device %d: ", 0);
  591 + dev_print(bdesc);
  592 + }
  593 + return 0;
  594 +}
  595 +
  596 +int scsi_scan(int mode)
  597 +{
  598 + unsigned char i, lun;
  599 + struct uclass *uc;
  600 + struct udevice *dev; /* SCSI controller */
  601 + int ret;
  602 +
  603 + if (mode == 1)
  604 + printf("scanning bus for devices...\n");
  605 +
  606 + blk_unbind_all(IF_TYPE_SCSI);
  607 +
  608 + ret = uclass_get(UCLASS_SCSI, &uc);
  609 + if (ret)
  610 + return ret;
  611 +
  612 + uclass_foreach_dev(dev, uc) {
  613 + struct scsi_platdata *plat; /* scsi controller platdata */
  614 +
  615 + /* probe SCSI controller driver */
  616 + ret = device_probe(dev);
  617 + if (ret)
  618 + return ret;
  619 +
  620 + /* Get controller platdata */
  621 + plat = dev_get_platdata(dev);
  622 +
  623 + for (i = 0; i < plat->max_id; i++)
  624 + for (lun = 0; lun < plat->max_lun; lun++)
  625 + do_scsi_scan_one(dev, i, lun, mode);
  626 + }
  627 +
  628 + return 0;
  629 +}
  630 +#else
  631 +int scsi_scan(int mode)
  632 +{
  633 + unsigned char i, lun;
  634 + int ret;
  635 +
  636 + if (mode == 1)
  637 + printf("scanning bus for devices...\n");
  638 + for (i = 0; i < CONFIG_SYS_SCSI_MAX_DEVICE; i++)
  639 + scsi_init_dev_desc(&scsi_dev_desc[i], i);
  640 +
  641 + scsi_max_devs = 0;
  642 + for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) {
  643 + for (lun = 0; lun < CONFIG_SYS_SCSI_MAX_LUN; lun++) {
  644 + ret = scsi_detect_dev(i, lun,
  645 + &scsi_dev_desc[scsi_max_devs]);
  646 + if (ret)
  647 + continue;
  648 + part_init(&scsi_dev_desc[scsi_max_devs]);
  649 +
  650 + if (mode == 1) {
  651 + printf(" Device %d: ", 0);
  652 + dev_print(&scsi_dev_desc[scsi_max_devs]);
  653 + } /* if mode */
  654 + scsi_max_devs++;
  655 + } /* next LUN */
  656 + }
  657 + if (scsi_max_devs > 0)
  658 + scsi_curr_dev = 0;
  659 + else
  660 + scsi_curr_dev = -1;
  661 +
  662 + printf("Found %d device(s).\n", scsi_max_devs);
  663 +#ifndef CONFIG_SPL_BUILD
  664 + setenv_ulong("scsidevs", scsi_max_devs);
  665 +#endif
  666 + return 0;
  667 +}
  668 +#endif
  669 +
  670 +#ifdef CONFIG_BLK
  671 +static const struct blk_ops scsi_blk_ops = {
  672 + .read = scsi_read,
  673 + .write = scsi_write,
  674 +};
  675 +
  676 +U_BOOT_DRIVER(scsi_blk) = {
  677 + .name = "scsi_blk",
  678 + .id = UCLASS_BLK,
  679 + .ops = &scsi_blk_ops,
  680 +};
  681 +#else
  682 +U_BOOT_LEGACY_BLK(scsi) = {
  683 + .if_typename = "scsi",
  684 + .if_type = IF_TYPE_SCSI,
  685 + .max_devs = CONFIG_SYS_SCSI_MAX_DEVICE,
  686 + .desc = scsi_dev_desc,
  687 +};
  688 +#endif