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"); 39*db13a768SBin Meng #ifndef CONFIG_DM_SCSI 404682c8a1SSimon Glass scsi_bus_reset(NULL); 41*db13a768SBin Meng #endif 428eab1a58SSimon Glass ret = scsi_scan(true); 43c002e39aSMichal Simek if (ret) 44c002e39aSMichal Simek return CMD_RET_FAILURE; 45c002e39aSMichal Simek return ret; 462e192b24SSimon Glass } 472e192b24SSimon Glass if (strncmp(argv[1], "inf", 3) == 0) { 4811f610edSSimon Glass blk_list_devices(IF_TYPE_SCSI); 492e192b24SSimon Glass return 0; 502e192b24SSimon Glass } 512e192b24SSimon Glass if (strncmp(argv[1], "dev", 3) == 0) { 5211f610edSSimon Glass if (blk_print_device_num(IF_TYPE_SCSI, scsi_curr_dev)) { 532e192b24SSimon Glass printf("\nno SCSI devices available\n"); 5411f610edSSimon Glass return CMD_RET_FAILURE; 552e192b24SSimon Glass } 5611f610edSSimon Glass 572e192b24SSimon Glass return 0; 582e192b24SSimon Glass } 592e192b24SSimon Glass if (strncmp(argv[1], "scan", 4) == 0) { 608eab1a58SSimon Glass ret = scsi_scan(true); 61c002e39aSMichal Simek if (ret) 62c002e39aSMichal Simek return CMD_RET_FAILURE; 63c002e39aSMichal Simek return ret; 642e192b24SSimon Glass } 652e192b24SSimon Glass if (strncmp(argv[1], "part", 4) == 0) { 6611f610edSSimon Glass if (blk_list_part(IF_TYPE_SCSI)) 672e192b24SSimon Glass printf("\nno SCSI devices available\n"); 6811f610edSSimon Glass return 0; 692e192b24SSimon Glass } 702e192b24SSimon Glass return CMD_RET_USAGE; 712e192b24SSimon Glass case 3: 722e192b24SSimon Glass if (strncmp(argv[1], "dev", 3) == 0) { 732e192b24SSimon Glass int dev = (int)simple_strtoul(argv[2], NULL, 10); 7411f610edSSimon Glass 7511f610edSSimon Glass if (!blk_show_device(IF_TYPE_SCSI, dev)) { 762e192b24SSimon Glass scsi_curr_dev = dev; 772e192b24SSimon Glass printf("... is now current device\n"); 7811f610edSSimon Glass } else { 7911f610edSSimon Glass return CMD_RET_FAILURE; 8011f610edSSimon Glass } 812e192b24SSimon Glass return 0; 822e192b24SSimon Glass } 832e192b24SSimon Glass if (strncmp(argv[1], "part", 4) == 0) { 842e192b24SSimon Glass int dev = (int)simple_strtoul(argv[2], NULL, 10); 8511f610edSSimon Glass 8611f610edSSimon Glass if (blk_print_part_devnum(IF_TYPE_SCSI, dev)) { 8711f610edSSimon Glass printf("\nSCSI device %d not available\n", 8811f610edSSimon Glass dev); 8911f610edSSimon Glass return CMD_RET_FAILURE; 9011f610edSSimon Glass } 9111f610edSSimon Glass return 0; 922e192b24SSimon Glass } 932e192b24SSimon Glass return CMD_RET_USAGE; 942e192b24SSimon Glass default: 952e192b24SSimon Glass /* at least 4 args */ 962e192b24SSimon Glass if (strcmp(argv[1], "read") == 0) { 972e192b24SSimon Glass ulong addr = simple_strtoul(argv[2], NULL, 16); 982e192b24SSimon Glass ulong blk = simple_strtoul(argv[3], NULL, 16); 992e192b24SSimon Glass ulong cnt = simple_strtoul(argv[4], NULL, 16); 1002e192b24SSimon Glass ulong n; 10111f610edSSimon Glass 1022e192b24SSimon Glass printf("\nSCSI read: device %d block # %ld, count %ld ... ", 1032e192b24SSimon Glass scsi_curr_dev, blk, cnt); 10411f610edSSimon Glass n = blk_read_devnum(IF_TYPE_SCSI, scsi_curr_dev, blk, 10511f610edSSimon Glass cnt, (ulong *)addr); 106f1d4d937SSimon Glass printf("%ld blocks read: %s\n", n, 107f1d4d937SSimon Glass n == cnt ? "OK" : "ERROR"); 1082e192b24SSimon Glass return 0; 1092e192b24SSimon Glass } else if (strcmp(argv[1], "write") == 0) { 1102e192b24SSimon Glass ulong addr = simple_strtoul(argv[2], NULL, 16); 1112e192b24SSimon Glass ulong blk = simple_strtoul(argv[3], NULL, 16); 1122e192b24SSimon Glass ulong cnt = simple_strtoul(argv[4], NULL, 16); 1132e192b24SSimon Glass ulong n; 11411f610edSSimon Glass 115f1d4d937SSimon Glass printf("\nSCSI write: device %d block # %ld, count %ld ... ", 1162e192b24SSimon Glass scsi_curr_dev, blk, cnt); 11711f610edSSimon Glass n = blk_write_devnum(IF_TYPE_SCSI, scsi_curr_dev, blk, 11811f610edSSimon Glass cnt, (ulong *)addr); 1192e192b24SSimon Glass printf("%ld blocks written: %s\n", n, 120f1d4d937SSimon Glass n == cnt ? "OK" : "ERROR"); 1212e192b24SSimon Glass return 0; 1222e192b24SSimon Glass } 1232e192b24SSimon Glass } /* switch */ 1242e192b24SSimon Glass return CMD_RET_USAGE; 1252e192b24SSimon Glass } 1262e192b24SSimon Glass 127ba524269STom Rini U_BOOT_CMD( 128ba524269STom Rini scsi, 5, 1, do_scsi, 129ba524269STom Rini "SCSI sub-system", 130ba524269STom Rini "reset - reset SCSI controller\n" 131ba524269STom Rini "scsi info - show available SCSI devices\n" 132ba524269STom Rini "scsi scan - (re-)scan SCSI bus\n" 133ba524269STom Rini "scsi device [dev] - show or set current device\n" 134ba524269STom Rini "scsi part [dev] - print partition table of one or all SCSI devices\n" 135ba524269STom Rini "scsi read addr blk# cnt - read `cnt' blocks starting at block `blk#'\n" 136ba524269STom Rini " to memory address `addr'\n" 137ba524269STom Rini "scsi write addr blk# cnt - write `cnt' blocks starting at block\n" 138ba524269STom Rini " `blk#' from memory address `addr'" 139ba524269STom Rini ); 140ba524269STom Rini 141ba524269STom Rini U_BOOT_CMD( 142ba524269STom Rini scsiboot, 3, 1, do_scsiboot, 143ba524269STom Rini "boot from SCSI device", 144ba524269STom Rini "loadAddr dev:part" 145ba524269STom Rini ); 146