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 <scsi.h> 142e192b24SSimon Glass 152e192b24SSimon Glass static int scsi_curr_dev; /* current device */ 162e192b24SSimon Glass 172e192b24SSimon Glass /* 182e192b24SSimon Glass * scsi boot command intepreter. Derived from diskboot 192e192b24SSimon Glass */ 20861fe650SMichal Simek static int do_scsiboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 212e192b24SSimon Glass { 222e192b24SSimon Glass return common_diskboot(cmdtp, "scsi", argc, argv); 232e192b24SSimon Glass } 242e192b24SSimon Glass 2511f610edSSimon Glass /* 262e192b24SSimon Glass * scsi command intepreter 272e192b24SSimon Glass */ 28861fe650SMichal Simek static int do_scsi(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 292e192b24SSimon Glass { 30c002e39aSMichal Simek int ret; 31c002e39aSMichal Simek 322e192b24SSimon Glass switch (argc) { 332e192b24SSimon Glass case 0: 342e192b24SSimon Glass case 1: 352e192b24SSimon Glass return CMD_RET_USAGE; 362e192b24SSimon Glass case 2: 372e192b24SSimon Glass if (strncmp(argv[1], "res", 3) == 0) { 382e192b24SSimon Glass printf("\nReset SCSI\n"); 394682c8a1SSimon Glass scsi_bus_reset(NULL); 40*8eab1a58SSimon Glass ret = scsi_scan(true); 41c002e39aSMichal Simek if (ret) 42c002e39aSMichal Simek return CMD_RET_FAILURE; 43c002e39aSMichal Simek return ret; 442e192b24SSimon Glass } 452e192b24SSimon Glass if (strncmp(argv[1], "inf", 3) == 0) { 4611f610edSSimon Glass blk_list_devices(IF_TYPE_SCSI); 472e192b24SSimon Glass return 0; 482e192b24SSimon Glass } 492e192b24SSimon Glass if (strncmp(argv[1], "dev", 3) == 0) { 5011f610edSSimon Glass if (blk_print_device_num(IF_TYPE_SCSI, scsi_curr_dev)) { 512e192b24SSimon Glass printf("\nno SCSI devices available\n"); 5211f610edSSimon Glass return CMD_RET_FAILURE; 532e192b24SSimon Glass } 5411f610edSSimon Glass 552e192b24SSimon Glass return 0; 562e192b24SSimon Glass } 572e192b24SSimon Glass if (strncmp(argv[1], "scan", 4) == 0) { 58*8eab1a58SSimon Glass ret = scsi_scan(true); 59c002e39aSMichal Simek if (ret) 60c002e39aSMichal Simek return CMD_RET_FAILURE; 61c002e39aSMichal Simek return ret; 622e192b24SSimon Glass } 632e192b24SSimon Glass if (strncmp(argv[1], "part", 4) == 0) { 6411f610edSSimon Glass if (blk_list_part(IF_TYPE_SCSI)) 652e192b24SSimon Glass printf("\nno SCSI devices available\n"); 6611f610edSSimon Glass return 0; 672e192b24SSimon Glass } 682e192b24SSimon Glass return CMD_RET_USAGE; 692e192b24SSimon Glass case 3: 702e192b24SSimon Glass if (strncmp(argv[1], "dev", 3) == 0) { 712e192b24SSimon Glass int dev = (int)simple_strtoul(argv[2], NULL, 10); 7211f610edSSimon Glass 7311f610edSSimon Glass if (!blk_show_device(IF_TYPE_SCSI, dev)) { 742e192b24SSimon Glass scsi_curr_dev = dev; 752e192b24SSimon Glass printf("... is now current device\n"); 7611f610edSSimon Glass } else { 7711f610edSSimon Glass return CMD_RET_FAILURE; 7811f610edSSimon Glass } 792e192b24SSimon Glass return 0; 802e192b24SSimon Glass } 812e192b24SSimon Glass if (strncmp(argv[1], "part", 4) == 0) { 822e192b24SSimon Glass int dev = (int)simple_strtoul(argv[2], NULL, 10); 8311f610edSSimon Glass 8411f610edSSimon Glass if (blk_print_part_devnum(IF_TYPE_SCSI, dev)) { 8511f610edSSimon Glass printf("\nSCSI device %d not available\n", 8611f610edSSimon Glass dev); 8711f610edSSimon Glass return CMD_RET_FAILURE; 8811f610edSSimon Glass } 8911f610edSSimon Glass return 0; 902e192b24SSimon Glass } 912e192b24SSimon Glass return CMD_RET_USAGE; 922e192b24SSimon Glass default: 932e192b24SSimon Glass /* at least 4 args */ 942e192b24SSimon Glass if (strcmp(argv[1], "read") == 0) { 952e192b24SSimon Glass ulong addr = simple_strtoul(argv[2], NULL, 16); 962e192b24SSimon Glass ulong blk = simple_strtoul(argv[3], NULL, 16); 972e192b24SSimon Glass ulong cnt = simple_strtoul(argv[4], NULL, 16); 982e192b24SSimon Glass ulong n; 9911f610edSSimon Glass 1002e192b24SSimon Glass printf("\nSCSI read: device %d block # %ld, count %ld ... ", 1012e192b24SSimon Glass scsi_curr_dev, blk, cnt); 10211f610edSSimon Glass n = blk_read_devnum(IF_TYPE_SCSI, scsi_curr_dev, blk, 10311f610edSSimon Glass cnt, (ulong *)addr); 104f1d4d937SSimon Glass printf("%ld blocks read: %s\n", n, 105f1d4d937SSimon Glass n == cnt ? "OK" : "ERROR"); 1062e192b24SSimon Glass return 0; 1072e192b24SSimon Glass } else if (strcmp(argv[1], "write") == 0) { 1082e192b24SSimon Glass ulong addr = simple_strtoul(argv[2], NULL, 16); 1092e192b24SSimon Glass ulong blk = simple_strtoul(argv[3], NULL, 16); 1102e192b24SSimon Glass ulong cnt = simple_strtoul(argv[4], NULL, 16); 1112e192b24SSimon Glass ulong n; 11211f610edSSimon Glass 113f1d4d937SSimon Glass printf("\nSCSI write: device %d block # %ld, count %ld ... ", 1142e192b24SSimon Glass scsi_curr_dev, blk, cnt); 11511f610edSSimon Glass n = blk_write_devnum(IF_TYPE_SCSI, scsi_curr_dev, blk, 11611f610edSSimon Glass cnt, (ulong *)addr); 1172e192b24SSimon Glass printf("%ld blocks written: %s\n", n, 118f1d4d937SSimon Glass n == cnt ? "OK" : "ERROR"); 1192e192b24SSimon Glass return 0; 1202e192b24SSimon Glass } 1212e192b24SSimon Glass } /* switch */ 1222e192b24SSimon Glass return CMD_RET_USAGE; 1232e192b24SSimon Glass } 1242e192b24SSimon Glass 125ba524269STom Rini U_BOOT_CMD( 126ba524269STom Rini scsi, 5, 1, do_scsi, 127ba524269STom Rini "SCSI sub-system", 128ba524269STom Rini "reset - reset SCSI controller\n" 129ba524269STom Rini "scsi info - show available SCSI devices\n" 130ba524269STom Rini "scsi scan - (re-)scan SCSI bus\n" 131ba524269STom Rini "scsi device [dev] - show or set current device\n" 132ba524269STom Rini "scsi part [dev] - print partition table of one or all SCSI devices\n" 133ba524269STom Rini "scsi read addr blk# cnt - read `cnt' blocks starting at block `blk#'\n" 134ba524269STom Rini " to memory address `addr'\n" 135ba524269STom Rini "scsi write addr blk# cnt - write `cnt' blocks starting at block\n" 136ba524269STom Rini " `blk#' from memory address `addr'" 137ba524269STom Rini ); 138ba524269STom Rini 139ba524269STom Rini U_BOOT_CMD( 140ba524269STom Rini scsiboot, 3, 1, do_scsiboot, 141ba524269STom Rini "boot from SCSI device", 142ba524269STom Rini "loadAddr dev:part" 143ba524269STom Rini ); 144