12e192b24SSimon Glass /* 22e192b24SSimon Glass * (C) Copyright 2001 32e192b24SSimon Glass * Denis Peter, MPL AG Switzerland 42e192b24SSimon Glass * 52e192b24SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 62e192b24SSimon Glass */ 72e192b24SSimon Glass 82e192b24SSimon Glass /* 92e192b24SSimon Glass * SCSI support. 102e192b24SSimon Glass */ 112e192b24SSimon Glass #include <common.h> 122e192b24SSimon Glass #include <command.h> 132e192b24SSimon Glass #include <inttypes.h> 142e192b24SSimon Glass #include <asm/processor.h> 152e192b24SSimon Glass #include <scsi.h> 162e192b24SSimon Glass #include <image.h> 172e192b24SSimon Glass #include <pci.h> 182e192b24SSimon Glass 192e192b24SSimon Glass #ifdef CONFIG_SCSI_DEV_LIST 202e192b24SSimon Glass #define SCSI_DEV_LIST CONFIG_SCSI_DEV_LIST 212e192b24SSimon Glass #else 222e192b24SSimon Glass #ifdef CONFIG_SCSI_SYM53C8XX 232e192b24SSimon Glass #define SCSI_VEND_ID 0x1000 242e192b24SSimon Glass #ifndef CONFIG_SCSI_DEV_ID 252e192b24SSimon Glass #define SCSI_DEV_ID 0x0001 262e192b24SSimon Glass #else 272e192b24SSimon Glass #define SCSI_DEV_ID CONFIG_SCSI_DEV_ID 282e192b24SSimon Glass #endif 292e192b24SSimon Glass #elif defined CONFIG_SATA_ULI5288 302e192b24SSimon Glass 312e192b24SSimon Glass #define SCSI_VEND_ID 0x10b9 322e192b24SSimon Glass #define SCSI_DEV_ID 0x5288 332e192b24SSimon Glass 342e192b24SSimon Glass #elif !defined(CONFIG_SCSI_AHCI_PLAT) 352e192b24SSimon Glass #error no scsi device defined 362e192b24SSimon Glass #endif 372e192b24SSimon Glass #define SCSI_DEV_LIST {SCSI_VEND_ID, SCSI_DEV_ID} 382e192b24SSimon Glass #endif 392e192b24SSimon Glass 402e192b24SSimon Glass #if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT) 412e192b24SSimon Glass const struct pci_device_id scsi_device_list[] = { SCSI_DEV_LIST }; 422e192b24SSimon Glass #endif 432e192b24SSimon Glass static ccb tempccb; /* temporary scsi command buffer */ 442e192b24SSimon Glass 452e192b24SSimon Glass static unsigned char tempbuff[512]; /* temporary data buffer */ 462e192b24SSimon Glass 472e192b24SSimon Glass static int scsi_max_devs; /* number of highest available scsi device */ 482e192b24SSimon Glass 492e192b24SSimon Glass static int scsi_curr_dev; /* current device */ 502e192b24SSimon Glass 514101f687SSimon Glass static struct blk_desc scsi_dev_desc[CONFIG_SYS_SCSI_MAX_DEVICE]; 522e192b24SSimon Glass 532e192b24SSimon Glass /******************************************************************************** 542e192b24SSimon Glass * forward declerations of some Setup Routines 552e192b24SSimon Glass */ 562e192b24SSimon Glass void scsi_setup_test_unit_ready(ccb * pccb); 572e192b24SSimon Glass void scsi_setup_read6(ccb * pccb, lbaint_t start, unsigned short blocks); 582e192b24SSimon Glass void scsi_setup_read_ext(ccb * pccb, lbaint_t start, unsigned short blocks); 592e192b24SSimon Glass void scsi_setup_read16(ccb * pccb, lbaint_t start, unsigned long blocks); 602e192b24SSimon Glass 612e192b24SSimon Glass static void scsi_setup_write_ext(ccb *pccb, lbaint_t start, 622e192b24SSimon Glass unsigned short blocks); 632e192b24SSimon Glass void scsi_setup_inquiry(ccb * pccb); 642e192b24SSimon Glass void scsi_ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len); 652e192b24SSimon Glass 662e192b24SSimon Glass 672e192b24SSimon Glass static int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, 682e192b24SSimon Glass unsigned long *blksz); 694101f687SSimon Glass static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, 702e192b24SSimon Glass lbaint_t blkcnt, void *buffer); 714101f687SSimon Glass static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr, 722e192b24SSimon Glass lbaint_t blkcnt, const void *buffer); 732e192b24SSimon Glass 742e192b24SSimon Glass 752e192b24SSimon Glass /********************************************************************************* 762e192b24SSimon Glass * (re)-scan the scsi bus and reports scsi device info 772e192b24SSimon Glass * to the user if mode = 1 782e192b24SSimon Glass */ 792e192b24SSimon Glass void scsi_scan(int mode) 802e192b24SSimon Glass { 812e192b24SSimon Glass unsigned char i,perq,modi,lun; 822e192b24SSimon Glass lbaint_t capacity; 832e192b24SSimon Glass unsigned long blksz; 842e192b24SSimon Glass ccb* pccb=(ccb *)&tempccb; 852e192b24SSimon Glass 862e192b24SSimon Glass if(mode==1) { 872e192b24SSimon Glass printf("scanning bus for devices...\n"); 882e192b24SSimon Glass } 892e192b24SSimon Glass for(i=0;i<CONFIG_SYS_SCSI_MAX_DEVICE;i++) { 902e192b24SSimon Glass scsi_dev_desc[i].target=0xff; 912e192b24SSimon Glass scsi_dev_desc[i].lun=0xff; 922e192b24SSimon Glass scsi_dev_desc[i].lba=0; 932e192b24SSimon Glass scsi_dev_desc[i].blksz=0; 942e192b24SSimon Glass scsi_dev_desc[i].log2blksz = 952e192b24SSimon Glass LOG2_INVALID(typeof(scsi_dev_desc[i].log2blksz)); 962e192b24SSimon Glass scsi_dev_desc[i].type=DEV_TYPE_UNKNOWN; 972e192b24SSimon Glass scsi_dev_desc[i].vendor[0]=0; 982e192b24SSimon Glass scsi_dev_desc[i].product[0]=0; 992e192b24SSimon Glass scsi_dev_desc[i].revision[0]=0; 1002e192b24SSimon Glass scsi_dev_desc[i].removable = false; 1012e192b24SSimon Glass scsi_dev_desc[i].if_type=IF_TYPE_SCSI; 102bcce53d0SSimon Glass scsi_dev_desc[i].devnum = i; 1032e192b24SSimon Glass scsi_dev_desc[i].part_type=PART_TYPE_UNKNOWN; 1042e192b24SSimon Glass scsi_dev_desc[i].block_read=scsi_read; 1052e192b24SSimon Glass scsi_dev_desc[i].block_write = scsi_write; 1062e192b24SSimon Glass } 1072e192b24SSimon Glass scsi_max_devs=0; 1082e192b24SSimon Glass for(i=0;i<CONFIG_SYS_SCSI_MAX_SCSI_ID;i++) { 1092e192b24SSimon Glass pccb->target=i; 1102e192b24SSimon Glass for(lun=0;lun<CONFIG_SYS_SCSI_MAX_LUN;lun++) { 1112e192b24SSimon Glass pccb->lun=lun; 1122e192b24SSimon Glass pccb->pdata=(unsigned char *)&tempbuff; 1132e192b24SSimon Glass pccb->datalen=512; 1142e192b24SSimon Glass scsi_setup_inquiry(pccb); 1152e192b24SSimon Glass if (scsi_exec(pccb) != true) { 1162e192b24SSimon Glass if(pccb->contr_stat==SCSI_SEL_TIME_OUT) { 1172e192b24SSimon Glass debug ("Selection timeout ID %d\n",pccb->target); 1182e192b24SSimon Glass continue; /* selection timeout => assuming no device present */ 1192e192b24SSimon Glass } 1202e192b24SSimon Glass scsi_print_error(pccb); 1212e192b24SSimon Glass continue; 1222e192b24SSimon Glass } 1232e192b24SSimon Glass perq=tempbuff[0]; 1242e192b24SSimon Glass modi=tempbuff[1]; 1252e192b24SSimon Glass if((perq & 0x1f)==0x1f) { 1262e192b24SSimon Glass continue; /* skip unknown devices */ 1272e192b24SSimon Glass } 1282e192b24SSimon Glass if((modi&0x80)==0x80) /* drive is removable */ 1292e192b24SSimon Glass scsi_dev_desc[scsi_max_devs].removable=true; 1302e192b24SSimon Glass /* get info for this device */ 1312e192b24SSimon Glass scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].vendor[0], 1322e192b24SSimon Glass &tempbuff[8], 8); 1332e192b24SSimon Glass scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].product[0], 1342e192b24SSimon Glass &tempbuff[16], 16); 1352e192b24SSimon Glass scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].revision[0], 1362e192b24SSimon Glass &tempbuff[32], 4); 1372e192b24SSimon Glass scsi_dev_desc[scsi_max_devs].target=pccb->target; 1382e192b24SSimon Glass scsi_dev_desc[scsi_max_devs].lun=pccb->lun; 1392e192b24SSimon Glass 1402e192b24SSimon Glass pccb->datalen=0; 1412e192b24SSimon Glass scsi_setup_test_unit_ready(pccb); 1422e192b24SSimon Glass if (scsi_exec(pccb) != true) { 1432e192b24SSimon Glass if (scsi_dev_desc[scsi_max_devs].removable == true) { 1442e192b24SSimon Glass scsi_dev_desc[scsi_max_devs].type=perq; 1452e192b24SSimon Glass goto removable; 1462e192b24SSimon Glass } 1472e192b24SSimon Glass scsi_print_error(pccb); 1482e192b24SSimon Glass continue; 1492e192b24SSimon Glass } 1502e192b24SSimon Glass if (scsi_read_capacity(pccb, &capacity, &blksz)) { 1512e192b24SSimon Glass scsi_print_error(pccb); 1522e192b24SSimon Glass continue; 1532e192b24SSimon Glass } 1542e192b24SSimon Glass scsi_dev_desc[scsi_max_devs].lba=capacity; 1552e192b24SSimon Glass scsi_dev_desc[scsi_max_devs].blksz=blksz; 1562e192b24SSimon Glass scsi_dev_desc[scsi_max_devs].log2blksz = 1572e192b24SSimon Glass LOG2(scsi_dev_desc[scsi_max_devs].blksz); 1582e192b24SSimon Glass scsi_dev_desc[scsi_max_devs].type=perq; 1593e8bd469SSimon Glass part_init(&scsi_dev_desc[scsi_max_devs]); 1602e192b24SSimon Glass removable: 1612e192b24SSimon Glass if(mode==1) { 1622e192b24SSimon Glass printf (" Device %d: ", scsi_max_devs); 1632e192b24SSimon Glass dev_print(&scsi_dev_desc[scsi_max_devs]); 1642e192b24SSimon Glass } /* if mode */ 1652e192b24SSimon Glass scsi_max_devs++; 1662e192b24SSimon Glass } /* next LUN */ 1672e192b24SSimon Glass } 1682e192b24SSimon Glass if(scsi_max_devs>0) 1692e192b24SSimon Glass scsi_curr_dev=0; 1702e192b24SSimon Glass else 1712e192b24SSimon Glass scsi_curr_dev = -1; 1722e192b24SSimon Glass 1732e192b24SSimon Glass printf("Found %d device(s).\n", scsi_max_devs); 1742e192b24SSimon Glass #ifndef CONFIG_SPL_BUILD 1752e192b24SSimon Glass setenv_ulong("scsidevs", scsi_max_devs); 1762e192b24SSimon Glass #endif 1772e192b24SSimon Glass } 1782e192b24SSimon Glass 1792e192b24SSimon Glass int scsi_get_disk_count(void) 1802e192b24SSimon Glass { 1812e192b24SSimon Glass return scsi_max_devs; 1822e192b24SSimon Glass } 1832e192b24SSimon Glass 1842e192b24SSimon Glass #if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT) 1852e192b24SSimon Glass void scsi_init(void) 1862e192b24SSimon Glass { 1872e192b24SSimon Glass int busdevfunc = -1; 1882e192b24SSimon Glass int i; 1892e192b24SSimon Glass /* 1902e192b24SSimon Glass * Find a device from the list, this driver will support a single 1912e192b24SSimon Glass * controller. 1922e192b24SSimon Glass */ 1932e192b24SSimon Glass for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) { 1942e192b24SSimon Glass /* get PCI Device ID */ 1952e192b24SSimon Glass #ifdef CONFIG_DM_PCI 1962e192b24SSimon Glass struct udevice *dev; 1972e192b24SSimon Glass int ret; 1982e192b24SSimon Glass 1992e192b24SSimon Glass ret = dm_pci_find_device(scsi_device_list[i].vendor, 2002e192b24SSimon Glass scsi_device_list[i].device, 0, &dev); 2012e192b24SSimon Glass if (!ret) { 2022e192b24SSimon Glass busdevfunc = dm_pci_get_bdf(dev); 2032e192b24SSimon Glass break; 2042e192b24SSimon Glass } 2052e192b24SSimon Glass #else 2062e192b24SSimon Glass busdevfunc = pci_find_device(scsi_device_list[i].vendor, 2072e192b24SSimon Glass scsi_device_list[i].device, 2082e192b24SSimon Glass 0); 2092e192b24SSimon Glass #endif 2102e192b24SSimon Glass if (busdevfunc != -1) 2112e192b24SSimon Glass break; 2122e192b24SSimon Glass } 2132e192b24SSimon Glass 2142e192b24SSimon Glass if (busdevfunc == -1) { 2152e192b24SSimon Glass printf("Error: SCSI Controller(s) "); 2162e192b24SSimon Glass for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) { 2172e192b24SSimon Glass printf("%04X:%04X ", 2182e192b24SSimon Glass scsi_device_list[i].vendor, 2192e192b24SSimon Glass scsi_device_list[i].device); 2202e192b24SSimon Glass } 2212e192b24SSimon Glass printf("not found\n"); 2222e192b24SSimon Glass return; 2232e192b24SSimon Glass } 2242e192b24SSimon Glass #ifdef DEBUG 2252e192b24SSimon Glass else { 2262e192b24SSimon Glass printf("SCSI Controller (%04X,%04X) found (%d:%d:%d)\n", 2272e192b24SSimon Glass scsi_device_list[i].vendor, 2282e192b24SSimon Glass scsi_device_list[i].device, 2292e192b24SSimon Glass (busdevfunc >> 16) & 0xFF, 2302e192b24SSimon Glass (busdevfunc >> 11) & 0x1F, 2312e192b24SSimon Glass (busdevfunc >> 8) & 0x7); 2322e192b24SSimon Glass } 2332e192b24SSimon Glass #endif 2342e192b24SSimon Glass bootstage_start(BOOTSTAGE_ID_ACCUM_SCSI, "ahci"); 2352e192b24SSimon Glass scsi_low_level_init(busdevfunc); 2362e192b24SSimon Glass scsi_scan(1); 2372e192b24SSimon Glass bootstage_accum(BOOTSTAGE_ID_ACCUM_SCSI); 2382e192b24SSimon Glass } 2392e192b24SSimon Glass #endif 2402e192b24SSimon Glass 2412e192b24SSimon Glass #ifdef CONFIG_PARTITIONS 2424101f687SSimon Glass struct blk_desc *scsi_get_dev(int dev) 2432e192b24SSimon Glass { 2442e192b24SSimon Glass return (dev < CONFIG_SYS_SCSI_MAX_DEVICE) ? &scsi_dev_desc[dev] : NULL; 2452e192b24SSimon Glass } 2462e192b24SSimon Glass #endif 2472e192b24SSimon Glass 248*ba524269STom Rini #ifndef CONFIG_SPL_BUILD 2492e192b24SSimon Glass /****************************************************************************** 2502e192b24SSimon Glass * scsi boot command intepreter. Derived from diskboot 2512e192b24SSimon Glass */ 2522e192b24SSimon Glass int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 2532e192b24SSimon Glass { 2542e192b24SSimon Glass return common_diskboot(cmdtp, "scsi", argc, argv); 2552e192b24SSimon Glass } 2562e192b24SSimon Glass 2572e192b24SSimon Glass /********************************************************************************* 2582e192b24SSimon Glass * scsi command intepreter 2592e192b24SSimon Glass */ 2602e192b24SSimon Glass int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 2612e192b24SSimon Glass { 2622e192b24SSimon Glass switch (argc) { 2632e192b24SSimon Glass case 0: 2642e192b24SSimon Glass case 1: 2652e192b24SSimon Glass return CMD_RET_USAGE; 2662e192b24SSimon Glass 2672e192b24SSimon Glass case 2: 2682e192b24SSimon Glass if (strncmp(argv[1],"res",3) == 0) { 2692e192b24SSimon Glass printf("\nReset SCSI\n"); 2702e192b24SSimon Glass scsi_bus_reset(); 2712e192b24SSimon Glass scsi_scan(1); 2722e192b24SSimon Glass return 0; 2732e192b24SSimon Glass } 2742e192b24SSimon Glass if (strncmp(argv[1],"inf",3) == 0) { 2752e192b24SSimon Glass int i; 2762e192b24SSimon Glass for (i=0; i<CONFIG_SYS_SCSI_MAX_DEVICE; ++i) { 2772e192b24SSimon Glass if(scsi_dev_desc[i].type==DEV_TYPE_UNKNOWN) 2782e192b24SSimon Glass continue; /* list only known devices */ 2792e192b24SSimon Glass printf ("SCSI dev. %d: ", i); 2802e192b24SSimon Glass dev_print(&scsi_dev_desc[i]); 2812e192b24SSimon Glass } 2822e192b24SSimon Glass return 0; 2832e192b24SSimon Glass } 2842e192b24SSimon Glass if (strncmp(argv[1],"dev",3) == 0) { 2852e192b24SSimon Glass if ((scsi_curr_dev < 0) || (scsi_curr_dev >= CONFIG_SYS_SCSI_MAX_DEVICE)) { 2862e192b24SSimon Glass printf("\nno SCSI devices available\n"); 2872e192b24SSimon Glass return 1; 2882e192b24SSimon Glass } 2892e192b24SSimon Glass printf ("\n Device %d: ", scsi_curr_dev); 2902e192b24SSimon Glass dev_print(&scsi_dev_desc[scsi_curr_dev]); 2912e192b24SSimon Glass return 0; 2922e192b24SSimon Glass } 2932e192b24SSimon Glass if (strncmp(argv[1],"scan",4) == 0) { 2942e192b24SSimon Glass scsi_scan(1); 2952e192b24SSimon Glass return 0; 2962e192b24SSimon Glass } 2972e192b24SSimon Glass if (strncmp(argv[1],"part",4) == 0) { 2982e192b24SSimon Glass int dev, ok; 2992e192b24SSimon Glass for (ok=0, dev=0; dev<CONFIG_SYS_SCSI_MAX_DEVICE; ++dev) { 3002e192b24SSimon Glass if (scsi_dev_desc[dev].type!=DEV_TYPE_UNKNOWN) { 3012e192b24SSimon Glass ok++; 3022e192b24SSimon Glass if (dev) 3032e192b24SSimon Glass printf("\n"); 3042e192b24SSimon Glass debug ("print_part of %x\n",dev); 3053e8bd469SSimon Glass part_print(&scsi_dev_desc[dev]); 3062e192b24SSimon Glass } 3072e192b24SSimon Glass } 3082e192b24SSimon Glass if (!ok) 3092e192b24SSimon Glass printf("\nno SCSI devices available\n"); 3102e192b24SSimon Glass return 1; 3112e192b24SSimon Glass } 3122e192b24SSimon Glass return CMD_RET_USAGE; 3132e192b24SSimon Glass case 3: 3142e192b24SSimon Glass if (strncmp(argv[1],"dev",3) == 0) { 3152e192b24SSimon Glass int dev = (int)simple_strtoul(argv[2], NULL, 10); 3162e192b24SSimon Glass printf ("\nSCSI device %d: ", dev); 3172e192b24SSimon Glass if (dev >= CONFIG_SYS_SCSI_MAX_DEVICE) { 3182e192b24SSimon Glass printf("unknown device\n"); 3192e192b24SSimon Glass return 1; 3202e192b24SSimon Glass } 3212e192b24SSimon Glass printf ("\n Device %d: ", dev); 3222e192b24SSimon Glass dev_print(&scsi_dev_desc[dev]); 3232e192b24SSimon Glass if(scsi_dev_desc[dev].type == DEV_TYPE_UNKNOWN) { 3242e192b24SSimon Glass return 1; 3252e192b24SSimon Glass } 3262e192b24SSimon Glass scsi_curr_dev = dev; 3272e192b24SSimon Glass printf("... is now current device\n"); 3282e192b24SSimon Glass return 0; 3292e192b24SSimon Glass } 3302e192b24SSimon Glass if (strncmp(argv[1],"part",4) == 0) { 3312e192b24SSimon Glass int dev = (int)simple_strtoul(argv[2], NULL, 10); 3322e192b24SSimon Glass if(scsi_dev_desc[dev].type != DEV_TYPE_UNKNOWN) { 3333e8bd469SSimon Glass part_print(&scsi_dev_desc[dev]); 3342e192b24SSimon Glass } 3352e192b24SSimon Glass else { 3362e192b24SSimon Glass printf ("\nSCSI device %d not available\n", dev); 3372e192b24SSimon Glass } 3382e192b24SSimon Glass return 1; 3392e192b24SSimon Glass } 3402e192b24SSimon Glass return CMD_RET_USAGE; 3412e192b24SSimon Glass default: 3422e192b24SSimon Glass /* at least 4 args */ 3432e192b24SSimon Glass if (strcmp(argv[1],"read") == 0) { 3442e192b24SSimon Glass ulong addr = simple_strtoul(argv[2], NULL, 16); 3452e192b24SSimon Glass ulong blk = simple_strtoul(argv[3], NULL, 16); 3462e192b24SSimon Glass ulong cnt = simple_strtoul(argv[4], NULL, 16); 3472e192b24SSimon Glass ulong n; 3482e192b24SSimon Glass printf ("\nSCSI read: device %d block # %ld, count %ld ... ", 3492e192b24SSimon Glass scsi_curr_dev, blk, cnt); 3502e192b24SSimon Glass n = scsi_read(&scsi_dev_desc[scsi_curr_dev], 3512e192b24SSimon Glass blk, cnt, (ulong *)addr); 3522e192b24SSimon Glass printf ("%ld blocks read: %s\n",n,(n==cnt) ? "OK" : "ERROR"); 3532e192b24SSimon Glass return 0; 3542e192b24SSimon Glass } else if (strcmp(argv[1], "write") == 0) { 3552e192b24SSimon Glass ulong addr = simple_strtoul(argv[2], NULL, 16); 3562e192b24SSimon Glass ulong blk = simple_strtoul(argv[3], NULL, 16); 3572e192b24SSimon Glass ulong cnt = simple_strtoul(argv[4], NULL, 16); 3582e192b24SSimon Glass ulong n; 3592e192b24SSimon Glass printf("\nSCSI write: device %d block # %ld, " 3602e192b24SSimon Glass "count %ld ... ", 3612e192b24SSimon Glass scsi_curr_dev, blk, cnt); 3622e192b24SSimon Glass n = scsi_write(&scsi_dev_desc[scsi_curr_dev], 3632e192b24SSimon Glass blk, cnt, (ulong *)addr); 3642e192b24SSimon Glass printf("%ld blocks written: %s\n", n, 3652e192b24SSimon Glass (n == cnt) ? "OK" : "ERROR"); 3662e192b24SSimon Glass return 0; 3672e192b24SSimon Glass } 3682e192b24SSimon Glass } /* switch */ 3692e192b24SSimon Glass return CMD_RET_USAGE; 3702e192b24SSimon Glass } 3712e192b24SSimon Glass 372*ba524269STom Rini U_BOOT_CMD( 373*ba524269STom Rini scsi, 5, 1, do_scsi, 374*ba524269STom Rini "SCSI sub-system", 375*ba524269STom Rini "reset - reset SCSI controller\n" 376*ba524269STom Rini "scsi info - show available SCSI devices\n" 377*ba524269STom Rini "scsi scan - (re-)scan SCSI bus\n" 378*ba524269STom Rini "scsi device [dev] - show or set current device\n" 379*ba524269STom Rini "scsi part [dev] - print partition table of one or all SCSI devices\n" 380*ba524269STom Rini "scsi read addr blk# cnt - read `cnt' blocks starting at block `blk#'\n" 381*ba524269STom Rini " to memory address `addr'\n" 382*ba524269STom Rini "scsi write addr blk# cnt - write `cnt' blocks starting at block\n" 383*ba524269STom Rini " `blk#' from memory address `addr'" 384*ba524269STom Rini ); 385*ba524269STom Rini 386*ba524269STom Rini U_BOOT_CMD( 387*ba524269STom Rini scsiboot, 3, 1, do_scsiboot, 388*ba524269STom Rini "boot from SCSI device", 389*ba524269STom Rini "loadAddr dev:part" 390*ba524269STom Rini ); 391*ba524269STom Rini #endif 392*ba524269STom Rini 3932e192b24SSimon Glass /**************************************************************************************** 3942e192b24SSimon Glass * scsi_read 3952e192b24SSimon Glass */ 3962e192b24SSimon Glass 3972e192b24SSimon Glass /* almost the maximum amount of the scsi_ext command.. */ 3982e192b24SSimon Glass #define SCSI_MAX_READ_BLK 0xFFFF 3992e192b24SSimon Glass #define SCSI_LBA48_READ 0xFFFFFFF 4002e192b24SSimon Glass 4014101f687SSimon Glass static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, 4022e192b24SSimon Glass lbaint_t blkcnt, void *buffer) 4032e192b24SSimon Glass { 404bcce53d0SSimon Glass int device = block_dev->devnum; 4052e192b24SSimon Glass lbaint_t start, blks; 4062e192b24SSimon Glass uintptr_t buf_addr; 4072e192b24SSimon Glass unsigned short smallblks = 0; 4082e192b24SSimon Glass ccb* pccb=(ccb *)&tempccb; 4092e192b24SSimon Glass device&=0xff; 4102e192b24SSimon Glass /* Setup device 4112e192b24SSimon Glass */ 4122e192b24SSimon Glass pccb->target=scsi_dev_desc[device].target; 4132e192b24SSimon Glass pccb->lun=scsi_dev_desc[device].lun; 4142e192b24SSimon Glass buf_addr=(unsigned long)buffer; 4152e192b24SSimon Glass start=blknr; 4162e192b24SSimon Glass blks=blkcnt; 4172e192b24SSimon Glass debug("\nscsi_read: dev %d startblk " LBAF 4182e192b24SSimon Glass ", blccnt " LBAF " buffer %lx\n", 4192e192b24SSimon Glass device, start, blks, (unsigned long)buffer); 4202e192b24SSimon Glass do { 4212e192b24SSimon Glass pccb->pdata=(unsigned char *)buf_addr; 4222e192b24SSimon Glass #ifdef CONFIG_SYS_64BIT_LBA 4232e192b24SSimon Glass if (start > SCSI_LBA48_READ) { 4242e192b24SSimon Glass unsigned long blocks; 4252e192b24SSimon Glass blocks = min_t(lbaint_t, blks, SCSI_MAX_READ_BLK); 4262e192b24SSimon Glass pccb->datalen = scsi_dev_desc[device].blksz * blocks; 4272e192b24SSimon Glass scsi_setup_read16(pccb, start, blocks); 4282e192b24SSimon Glass start += blocks; 4292e192b24SSimon Glass blks -= blocks; 4302e192b24SSimon Glass } else 4312e192b24SSimon Glass #endif 4322e192b24SSimon Glass if (blks > SCSI_MAX_READ_BLK) { 4332e192b24SSimon Glass pccb->datalen=scsi_dev_desc[device].blksz * SCSI_MAX_READ_BLK; 4342e192b24SSimon Glass smallblks=SCSI_MAX_READ_BLK; 4352e192b24SSimon Glass scsi_setup_read_ext(pccb,start,smallblks); 4362e192b24SSimon Glass start+=SCSI_MAX_READ_BLK; 4372e192b24SSimon Glass blks-=SCSI_MAX_READ_BLK; 4382e192b24SSimon Glass } 4392e192b24SSimon Glass else { 4402e192b24SSimon Glass pccb->datalen=scsi_dev_desc[device].blksz * blks; 4412e192b24SSimon Glass smallblks=(unsigned short) blks; 4422e192b24SSimon Glass scsi_setup_read_ext(pccb,start,smallblks); 4432e192b24SSimon Glass start+=blks; 4442e192b24SSimon Glass blks=0; 4452e192b24SSimon Glass } 4462e192b24SSimon Glass debug("scsi_read_ext: startblk " LBAF 4472e192b24SSimon Glass ", blccnt %x buffer %" PRIXPTR "\n", 4482e192b24SSimon Glass start, smallblks, buf_addr); 4492e192b24SSimon Glass if (scsi_exec(pccb) != true) { 4502e192b24SSimon Glass scsi_print_error(pccb); 4512e192b24SSimon Glass blkcnt-=blks; 4522e192b24SSimon Glass break; 4532e192b24SSimon Glass } 4542e192b24SSimon Glass buf_addr+=pccb->datalen; 4552e192b24SSimon Glass } while(blks!=0); 4562e192b24SSimon Glass debug("scsi_read_ext: end startblk " LBAF 4572e192b24SSimon Glass ", blccnt %x buffer %" PRIXPTR "\n", start, smallblks, buf_addr); 4582e192b24SSimon Glass return(blkcnt); 4592e192b24SSimon Glass } 4602e192b24SSimon Glass 4612e192b24SSimon Glass /******************************************************************************* 4622e192b24SSimon Glass * scsi_write 4632e192b24SSimon Glass */ 4642e192b24SSimon Glass 4652e192b24SSimon Glass /* Almost the maximum amount of the scsi_ext command.. */ 4662e192b24SSimon Glass #define SCSI_MAX_WRITE_BLK 0xFFFF 4672e192b24SSimon Glass 4684101f687SSimon Glass static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr, 4692e192b24SSimon Glass lbaint_t blkcnt, const void *buffer) 4702e192b24SSimon Glass { 471bcce53d0SSimon Glass int device = block_dev->devnum; 4722e192b24SSimon Glass lbaint_t start, blks; 4732e192b24SSimon Glass uintptr_t buf_addr; 4742e192b24SSimon Glass unsigned short smallblks; 4752e192b24SSimon Glass ccb* pccb = (ccb *)&tempccb; 4762e192b24SSimon Glass device &= 0xff; 4772e192b24SSimon Glass /* Setup device 4782e192b24SSimon Glass */ 4792e192b24SSimon Glass pccb->target = scsi_dev_desc[device].target; 4802e192b24SSimon Glass pccb->lun = scsi_dev_desc[device].lun; 4812e192b24SSimon Glass buf_addr = (unsigned long)buffer; 4822e192b24SSimon Glass start = blknr; 4832e192b24SSimon Glass blks = blkcnt; 4842e192b24SSimon Glass debug("\n%s: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n", 4852e192b24SSimon Glass __func__, device, start, blks, (unsigned long)buffer); 4862e192b24SSimon Glass do { 4872e192b24SSimon Glass pccb->pdata = (unsigned char *)buf_addr; 4882e192b24SSimon Glass if (blks > SCSI_MAX_WRITE_BLK) { 4892e192b24SSimon Glass pccb->datalen = (scsi_dev_desc[device].blksz * 4902e192b24SSimon Glass SCSI_MAX_WRITE_BLK); 4912e192b24SSimon Glass smallblks = SCSI_MAX_WRITE_BLK; 4922e192b24SSimon Glass scsi_setup_write_ext(pccb, start, smallblks); 4932e192b24SSimon Glass start += SCSI_MAX_WRITE_BLK; 4942e192b24SSimon Glass blks -= SCSI_MAX_WRITE_BLK; 4952e192b24SSimon Glass } else { 4962e192b24SSimon Glass pccb->datalen = scsi_dev_desc[device].blksz * blks; 4972e192b24SSimon Glass smallblks = (unsigned short)blks; 4982e192b24SSimon Glass scsi_setup_write_ext(pccb, start, smallblks); 4992e192b24SSimon Glass start += blks; 5002e192b24SSimon Glass blks = 0; 5012e192b24SSimon Glass } 5022e192b24SSimon Glass debug("%s: startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", 5032e192b24SSimon Glass __func__, start, smallblks, buf_addr); 5042e192b24SSimon Glass if (scsi_exec(pccb) != true) { 5052e192b24SSimon Glass scsi_print_error(pccb); 5062e192b24SSimon Glass blkcnt -= blks; 5072e192b24SSimon Glass break; 5082e192b24SSimon Glass } 5092e192b24SSimon Glass buf_addr += pccb->datalen; 5102e192b24SSimon Glass } while (blks != 0); 5112e192b24SSimon Glass debug("%s: end startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", 5122e192b24SSimon Glass __func__, start, smallblks, buf_addr); 5132e192b24SSimon Glass return blkcnt; 5142e192b24SSimon Glass } 5152e192b24SSimon Glass 5162e192b24SSimon Glass /* copy src to dest, skipping leading and trailing blanks 5172e192b24SSimon Glass * and null terminate the string 5182e192b24SSimon Glass */ 5192e192b24SSimon Glass void scsi_ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len) 5202e192b24SSimon Glass { 5212e192b24SSimon Glass int start,end; 5222e192b24SSimon Glass 5232e192b24SSimon Glass start=0; 5242e192b24SSimon Glass while(start<len) { 5252e192b24SSimon Glass if(src[start]!=' ') 5262e192b24SSimon Glass break; 5272e192b24SSimon Glass start++; 5282e192b24SSimon Glass } 5292e192b24SSimon Glass end=len-1; 5302e192b24SSimon Glass while(end>start) { 5312e192b24SSimon Glass if(src[end]!=' ') 5322e192b24SSimon Glass break; 5332e192b24SSimon Glass end--; 5342e192b24SSimon Glass } 5352e192b24SSimon Glass for( ; start<=end; start++) { 5362e192b24SSimon Glass *dest++=src[start]; 5372e192b24SSimon Glass } 5382e192b24SSimon Glass *dest='\0'; 5392e192b24SSimon Glass } 5402e192b24SSimon Glass 5412e192b24SSimon Glass 5422e192b24SSimon Glass /* Trim trailing blanks, and NUL-terminate string 5432e192b24SSimon Glass */ 5442e192b24SSimon Glass void scsi_trim_trail (unsigned char *str, unsigned int len) 5452e192b24SSimon Glass { 5462e192b24SSimon Glass unsigned char *p = str + len - 1; 5472e192b24SSimon Glass 5482e192b24SSimon Glass while (len-- > 0) { 5492e192b24SSimon Glass *p-- = '\0'; 5502e192b24SSimon Glass if (*p != ' ') { 5512e192b24SSimon Glass return; 5522e192b24SSimon Glass } 5532e192b24SSimon Glass } 5542e192b24SSimon Glass } 5552e192b24SSimon Glass 5562e192b24SSimon Glass int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, unsigned long *blksz) 5572e192b24SSimon Glass { 5582e192b24SSimon Glass *capacity = 0; 5592e192b24SSimon Glass 5602e192b24SSimon Glass memset(pccb->cmd, 0, sizeof(pccb->cmd)); 5612e192b24SSimon Glass pccb->cmd[0] = SCSI_RD_CAPAC10; 5622e192b24SSimon Glass pccb->cmd[1] = pccb->lun << 5; 5632e192b24SSimon Glass pccb->cmdlen = 10; 5642e192b24SSimon Glass pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ 5652e192b24SSimon Glass 5662e192b24SSimon Glass pccb->datalen = 8; 5672e192b24SSimon Glass if (scsi_exec(pccb) != true) 5682e192b24SSimon Glass return 1; 5692e192b24SSimon Glass 5702e192b24SSimon Glass *capacity = ((lbaint_t)pccb->pdata[0] << 24) | 5712e192b24SSimon Glass ((lbaint_t)pccb->pdata[1] << 16) | 5722e192b24SSimon Glass ((lbaint_t)pccb->pdata[2] << 8) | 5732e192b24SSimon Glass ((lbaint_t)pccb->pdata[3]); 5742e192b24SSimon Glass 5752e192b24SSimon Glass if (*capacity != 0xffffffff) { 5762e192b24SSimon Glass /* Read capacity (10) was sufficient for this drive. */ 5772e192b24SSimon Glass *blksz = ((unsigned long)pccb->pdata[4] << 24) | 5782e192b24SSimon Glass ((unsigned long)pccb->pdata[5] << 16) | 5792e192b24SSimon Glass ((unsigned long)pccb->pdata[6] << 8) | 5802e192b24SSimon Glass ((unsigned long)pccb->pdata[7]); 5812e192b24SSimon Glass return 0; 5822e192b24SSimon Glass } 5832e192b24SSimon Glass 5842e192b24SSimon Glass /* Read capacity (10) was insufficient. Use read capacity (16). */ 5852e192b24SSimon Glass 5862e192b24SSimon Glass memset(pccb->cmd, 0, sizeof(pccb->cmd)); 5872e192b24SSimon Glass pccb->cmd[0] = SCSI_RD_CAPAC16; 5882e192b24SSimon Glass pccb->cmd[1] = 0x10; 5892e192b24SSimon Glass pccb->cmdlen = 16; 5902e192b24SSimon Glass pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ 5912e192b24SSimon Glass 5922e192b24SSimon Glass pccb->datalen = 16; 5932e192b24SSimon Glass if (scsi_exec(pccb) != true) 5942e192b24SSimon Glass return 1; 5952e192b24SSimon Glass 5962e192b24SSimon Glass *capacity = ((uint64_t)pccb->pdata[0] << 56) | 5972e192b24SSimon Glass ((uint64_t)pccb->pdata[1] << 48) | 5982e192b24SSimon Glass ((uint64_t)pccb->pdata[2] << 40) | 5992e192b24SSimon Glass ((uint64_t)pccb->pdata[3] << 32) | 6002e192b24SSimon Glass ((uint64_t)pccb->pdata[4] << 24) | 6012e192b24SSimon Glass ((uint64_t)pccb->pdata[5] << 16) | 6022e192b24SSimon Glass ((uint64_t)pccb->pdata[6] << 8) | 6032e192b24SSimon Glass ((uint64_t)pccb->pdata[7]); 6042e192b24SSimon Glass 6052e192b24SSimon Glass *blksz = ((uint64_t)pccb->pdata[8] << 56) | 6062e192b24SSimon Glass ((uint64_t)pccb->pdata[9] << 48) | 6072e192b24SSimon Glass ((uint64_t)pccb->pdata[10] << 40) | 6082e192b24SSimon Glass ((uint64_t)pccb->pdata[11] << 32) | 6092e192b24SSimon Glass ((uint64_t)pccb->pdata[12] << 24) | 6102e192b24SSimon Glass ((uint64_t)pccb->pdata[13] << 16) | 6112e192b24SSimon Glass ((uint64_t)pccb->pdata[14] << 8) | 6122e192b24SSimon Glass ((uint64_t)pccb->pdata[15]); 6132e192b24SSimon Glass 6142e192b24SSimon Glass return 0; 6152e192b24SSimon Glass } 6162e192b24SSimon Glass 6172e192b24SSimon Glass 6182e192b24SSimon Glass /************************************************************************************ 6192e192b24SSimon Glass * Some setup (fill-in) routines 6202e192b24SSimon Glass */ 6212e192b24SSimon Glass void scsi_setup_test_unit_ready(ccb * pccb) 6222e192b24SSimon Glass { 6232e192b24SSimon Glass pccb->cmd[0]=SCSI_TST_U_RDY; 6242e192b24SSimon Glass pccb->cmd[1]=pccb->lun<<5; 6252e192b24SSimon Glass pccb->cmd[2]=0; 6262e192b24SSimon Glass pccb->cmd[3]=0; 6272e192b24SSimon Glass pccb->cmd[4]=0; 6282e192b24SSimon Glass pccb->cmd[5]=0; 6292e192b24SSimon Glass pccb->cmdlen=6; 6302e192b24SSimon Glass pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ 6312e192b24SSimon Glass } 6322e192b24SSimon Glass 6332e192b24SSimon Glass #ifdef CONFIG_SYS_64BIT_LBA 6342e192b24SSimon Glass void scsi_setup_read16(ccb * pccb, lbaint_t start, unsigned long blocks) 6352e192b24SSimon Glass { 6362e192b24SSimon Glass pccb->cmd[0] = SCSI_READ16; 6372e192b24SSimon Glass pccb->cmd[1] = pccb->lun<<5; 6382e192b24SSimon Glass pccb->cmd[2] = ((unsigned char) (start >> 56)) & 0xff; 6392e192b24SSimon Glass pccb->cmd[3] = ((unsigned char) (start >> 48)) & 0xff; 6402e192b24SSimon Glass pccb->cmd[4] = ((unsigned char) (start >> 40)) & 0xff; 6412e192b24SSimon Glass pccb->cmd[5] = ((unsigned char) (start >> 32)) & 0xff; 6422e192b24SSimon Glass pccb->cmd[6] = ((unsigned char) (start >> 24)) & 0xff; 6432e192b24SSimon Glass pccb->cmd[7] = ((unsigned char) (start >> 16)) & 0xff; 6442e192b24SSimon Glass pccb->cmd[8] = ((unsigned char) (start >> 8)) & 0xff; 6452e192b24SSimon Glass pccb->cmd[9] = ((unsigned char) (start)) & 0xff; 6462e192b24SSimon Glass pccb->cmd[10] = 0; 6472e192b24SSimon Glass pccb->cmd[11] = ((unsigned char) (blocks >> 24)) & 0xff; 6482e192b24SSimon Glass pccb->cmd[12] = ((unsigned char) (blocks >> 16)) & 0xff; 6492e192b24SSimon Glass pccb->cmd[13] = ((unsigned char) (blocks >> 8)) & 0xff; 6502e192b24SSimon Glass pccb->cmd[14] = (unsigned char) blocks & 0xff; 6512e192b24SSimon Glass pccb->cmd[15] = 0; 6522e192b24SSimon Glass pccb->cmdlen = 16; 6532e192b24SSimon Glass pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ 6542e192b24SSimon Glass debug ("scsi_setup_read16: cmd: %02X %02X " 6552e192b24SSimon Glass "startblk %02X%02X%02X%02X%02X%02X%02X%02X " 6562e192b24SSimon Glass "blccnt %02X%02X%02X%02X\n", 6572e192b24SSimon Glass pccb->cmd[0], pccb->cmd[1], 6582e192b24SSimon Glass pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], 6592e192b24SSimon Glass pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9], 6602e192b24SSimon Glass pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]); 6612e192b24SSimon Glass } 6622e192b24SSimon Glass #endif 6632e192b24SSimon Glass 6642e192b24SSimon Glass void scsi_setup_read_ext(ccb * pccb, lbaint_t start, unsigned short blocks) 6652e192b24SSimon Glass { 6662e192b24SSimon Glass pccb->cmd[0]=SCSI_READ10; 6672e192b24SSimon Glass pccb->cmd[1]=pccb->lun<<5; 6682e192b24SSimon Glass pccb->cmd[2]=((unsigned char) (start>>24))&0xff; 6692e192b24SSimon Glass pccb->cmd[3]=((unsigned char) (start>>16))&0xff; 6702e192b24SSimon Glass pccb->cmd[4]=((unsigned char) (start>>8))&0xff; 6712e192b24SSimon Glass pccb->cmd[5]=((unsigned char) (start))&0xff; 6722e192b24SSimon Glass pccb->cmd[6]=0; 6732e192b24SSimon Glass pccb->cmd[7]=((unsigned char) (blocks>>8))&0xff; 6742e192b24SSimon Glass pccb->cmd[8]=(unsigned char) blocks & 0xff; 6752e192b24SSimon Glass pccb->cmd[6]=0; 6762e192b24SSimon Glass pccb->cmdlen=10; 6772e192b24SSimon Glass pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ 6782e192b24SSimon Glass debug ("scsi_setup_read_ext: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n", 6792e192b24SSimon Glass pccb->cmd[0],pccb->cmd[1], 6802e192b24SSimon Glass pccb->cmd[2],pccb->cmd[3],pccb->cmd[4],pccb->cmd[5], 6812e192b24SSimon Glass pccb->cmd[7],pccb->cmd[8]); 6822e192b24SSimon Glass } 6832e192b24SSimon Glass 6842e192b24SSimon Glass void scsi_setup_write_ext(ccb *pccb, lbaint_t start, unsigned short blocks) 6852e192b24SSimon Glass { 6862e192b24SSimon Glass pccb->cmd[0] = SCSI_WRITE10; 6872e192b24SSimon Glass pccb->cmd[1] = pccb->lun << 5; 6882e192b24SSimon Glass pccb->cmd[2] = ((unsigned char) (start>>24)) & 0xff; 6892e192b24SSimon Glass pccb->cmd[3] = ((unsigned char) (start>>16)) & 0xff; 6902e192b24SSimon Glass pccb->cmd[4] = ((unsigned char) (start>>8)) & 0xff; 6912e192b24SSimon Glass pccb->cmd[5] = ((unsigned char) (start)) & 0xff; 6922e192b24SSimon Glass pccb->cmd[6] = 0; 6932e192b24SSimon Glass pccb->cmd[7] = ((unsigned char) (blocks>>8)) & 0xff; 6942e192b24SSimon Glass pccb->cmd[8] = (unsigned char)blocks & 0xff; 6952e192b24SSimon Glass pccb->cmd[9] = 0; 6962e192b24SSimon Glass pccb->cmdlen = 10; 6972e192b24SSimon Glass pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ 6982e192b24SSimon Glass debug("%s: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n", 6992e192b24SSimon Glass __func__, 7002e192b24SSimon Glass pccb->cmd[0], pccb->cmd[1], 7012e192b24SSimon Glass pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], 7022e192b24SSimon Glass pccb->cmd[7], pccb->cmd[8]); 7032e192b24SSimon Glass } 7042e192b24SSimon Glass 7052e192b24SSimon Glass void scsi_setup_read6(ccb * pccb, lbaint_t start, unsigned short blocks) 7062e192b24SSimon Glass { 7072e192b24SSimon Glass pccb->cmd[0]=SCSI_READ6; 7082e192b24SSimon Glass pccb->cmd[1]=pccb->lun<<5 | (((unsigned char)(start>>16))&0x1f); 7092e192b24SSimon Glass pccb->cmd[2]=((unsigned char) (start>>8))&0xff; 7102e192b24SSimon Glass pccb->cmd[3]=((unsigned char) (start))&0xff; 7112e192b24SSimon Glass pccb->cmd[4]=(unsigned char) blocks & 0xff; 7122e192b24SSimon Glass pccb->cmd[5]=0; 7132e192b24SSimon Glass pccb->cmdlen=6; 7142e192b24SSimon Glass pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ 7152e192b24SSimon Glass debug ("scsi_setup_read6: cmd: %02X %02X startblk %02X%02X blccnt %02X\n", 7162e192b24SSimon Glass pccb->cmd[0],pccb->cmd[1], 7172e192b24SSimon Glass pccb->cmd[2],pccb->cmd[3],pccb->cmd[4]); 7182e192b24SSimon Glass } 7192e192b24SSimon Glass 7202e192b24SSimon Glass 7212e192b24SSimon Glass void scsi_setup_inquiry(ccb * pccb) 7222e192b24SSimon Glass { 7232e192b24SSimon Glass pccb->cmd[0]=SCSI_INQUIRY; 7242e192b24SSimon Glass pccb->cmd[1]=pccb->lun<<5; 7252e192b24SSimon Glass pccb->cmd[2]=0; 7262e192b24SSimon Glass pccb->cmd[3]=0; 7272e192b24SSimon Glass if(pccb->datalen>255) 7282e192b24SSimon Glass pccb->cmd[4]=255; 7292e192b24SSimon Glass else 7302e192b24SSimon Glass pccb->cmd[4]=(unsigned char)pccb->datalen; 7312e192b24SSimon Glass pccb->cmd[5]=0; 7322e192b24SSimon Glass pccb->cmdlen=6; 7332e192b24SSimon Glass pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ 7342e192b24SSimon Glass } 735