Commit 0fcd48fe00e8fb2d433c1bf5ebe586b19228f027
1 parent
f2105c6182
Exists in
smarc_8mq_lf_v2020.04
and in
17 other branches
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
common/Makefile
... | ... | @@ -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 |
drivers/Kconfig
drivers/Makefile
... | ... | @@ -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
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 | +}; |
drivers/scsi/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 |