wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 1 | /* |
Wolfgang Denk | 2bc10cf | 2011-10-29 09:41:40 +0000 | [diff] [blame] | 2 | * (C) Copyright 2000-2011 |
wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 3 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. |
| 4 | * |
Wolfgang Denk | d79de1d | 2013-07-08 09:37:19 +0200 | [diff] [blame] | 5 | * SPDX-License-Identifier: GPL-2.0+ |
wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 6 | */ |
| 7 | |
| 8 | /* |
| 9 | * IDE support |
| 10 | */ |
Albert Aribaud | 4502755 | 2010-08-08 05:17:06 +0530 | [diff] [blame] | 11 | |
wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 12 | #include <common.h> |
Simon Glass | 2ee8ada | 2016-02-29 15:25:52 -0700 | [diff] [blame] | 13 | #include <blk.h> |
wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 14 | #include <config.h> |
| 15 | #include <watchdog.h> |
| 16 | #include <command.h> |
| 17 | #include <image.h> |
| 18 | #include <asm/byteorder.h> |
Heiko Schocher | 2559e0f | 2007-08-28 17:39:14 +0200 | [diff] [blame] | 19 | #include <asm/io.h> |
Grant Likely | ffc2dd7 | 2007-02-20 09:04:34 +0100 | [diff] [blame] | 20 | |
wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 21 | #if defined(CONFIG_IDE_8xx_DIRECT) || defined(CONFIG_IDE_PCMCIA) |
| 22 | # include <pcmcia.h> |
| 23 | #endif |
Grant Likely | ffc2dd7 | 2007-02-20 09:04:34 +0100 | [diff] [blame] | 24 | |
wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 25 | #include <ide.h> |
| 26 | #include <ata.h> |
Grant Likely | ffc2dd7 | 2007-02-20 09:04:34 +0100 | [diff] [blame] | 27 | |
Uri Mashiach | 4892d39 | 2017-01-19 10:51:45 +0200 | [diff] [blame] | 28 | #ifdef CONFIG_LED_STATUS |
wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 29 | # include <status_led.h> |
| 30 | #endif |
Grant Likely | ffc2dd7 | 2007-02-20 09:04:34 +0100 | [diff] [blame] | 31 | |
wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 32 | /* Current I/O Device */ |
| 33 | static int curr_device = -1; |
| 34 | |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 35 | int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) |
| 36 | { |
| 37 | int rcode = 0; |
| 38 | |
| 39 | switch (argc) { |
| 40 | case 0: |
| 41 | case 1: |
| 42 | return CMD_RET_USAGE; |
| 43 | case 2: |
| 44 | if (strncmp(argv[1], "res", 3) == 0) { |
| 45 | puts("\nReset IDE" |
| 46 | #ifdef CONFIG_IDE_8xx_DIRECT |
| 47 | " on PCMCIA " PCMCIA_SLOT_MSG |
| 48 | #endif |
| 49 | ": "); |
| 50 | |
| 51 | ide_init(); |
| 52 | return 0; |
| 53 | } else if (strncmp(argv[1], "inf", 3) == 0) { |
Simon Glass | e11f0ef | 2016-05-01 11:36:10 -0600 | [diff] [blame] | 54 | blk_list_devices(IF_TYPE_IDE); |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 55 | return 0; |
| 56 | |
| 57 | } else if (strncmp(argv[1], "dev", 3) == 0) { |
Simon Glass | e11f0ef | 2016-05-01 11:36:10 -0600 | [diff] [blame] | 58 | if (blk_print_device_num(IF_TYPE_IDE, curr_device)) { |
| 59 | printf("\nno IDE devices available\n"); |
| 60 | return CMD_RET_FAILURE; |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 61 | } |
Simon Glass | e11f0ef | 2016-05-01 11:36:10 -0600 | [diff] [blame] | 62 | |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 63 | return 0; |
| 64 | } else if (strncmp(argv[1], "part", 4) == 0) { |
Simon Glass | e11f0ef | 2016-05-01 11:36:10 -0600 | [diff] [blame] | 65 | if (blk_list_part(IF_TYPE_IDE)) |
| 66 | printf("\nno IDE devices available\n"); |
| 67 | return 1; |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 68 | } |
| 69 | return CMD_RET_USAGE; |
| 70 | case 3: |
| 71 | if (strncmp(argv[1], "dev", 3) == 0) { |
| 72 | int dev = (int)simple_strtoul(argv[2], NULL, 10); |
wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 73 | |
Simon Glass | e11f0ef | 2016-05-01 11:36:10 -0600 | [diff] [blame] | 74 | if (!blk_show_device(IF_TYPE_IDE, dev)) { |
| 75 | curr_device = dev; |
| 76 | printf("... is now current device\n"); |
| 77 | } else { |
| 78 | return CMD_RET_FAILURE; |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 79 | } |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 80 | return 0; |
| 81 | } else if (strncmp(argv[1], "part", 4) == 0) { |
| 82 | int dev = (int)simple_strtoul(argv[2], NULL, 10); |
wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 83 | |
Simon Glass | e11f0ef | 2016-05-01 11:36:10 -0600 | [diff] [blame] | 84 | if (blk_print_part_devnum(IF_TYPE_IDE, dev)) { |
| 85 | printf("\nIDE device %d not available\n", dev); |
| 86 | return CMD_RET_FAILURE; |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 87 | } |
Simon Glass | e11f0ef | 2016-05-01 11:36:10 -0600 | [diff] [blame] | 88 | return 1; |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 89 | } |
wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 90 | |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 91 | return CMD_RET_USAGE; |
| 92 | default: |
| 93 | /* at least 4 args */ |
wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 94 | |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 95 | if (strcmp(argv[1], "read") == 0) { |
| 96 | ulong addr = simple_strtoul(argv[2], NULL, 16); |
| 97 | ulong cnt = simple_strtoul(argv[4], NULL, 16); |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 98 | ulong n; |
wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 99 | |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 100 | #ifdef CONFIG_SYS_64BIT_LBA |
| 101 | lbaint_t blk = simple_strtoull(argv[3], NULL, 16); |
wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 102 | |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 103 | printf("\nIDE read: device %d block # %lld, count %ld...", |
| 104 | curr_device, blk, cnt); |
| 105 | #else |
| 106 | lbaint_t blk = simple_strtoul(argv[3], NULL, 16); |
wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 107 | |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 108 | printf("\nIDE read: device %d block # %ld, count %ld...", |
| 109 | curr_device, blk, cnt); |
| 110 | #endif |
wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 111 | |
Simon Glass | e11f0ef | 2016-05-01 11:36:10 -0600 | [diff] [blame] | 112 | n = blk_read_devnum(IF_TYPE_IDE, curr_device, blk, cnt, |
| 113 | (ulong *)addr); |
wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 114 | |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 115 | printf("%ld blocks read: %s\n", |
| 116 | n, (n == cnt) ? "OK" : "ERROR"); |
| 117 | if (n == cnt) |
| 118 | return 0; |
| 119 | else |
| 120 | return 1; |
| 121 | } else if (strcmp(argv[1], "write") == 0) { |
| 122 | ulong addr = simple_strtoul(argv[2], NULL, 16); |
| 123 | ulong cnt = simple_strtoul(argv[4], NULL, 16); |
| 124 | ulong n; |
wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 125 | |
Jean-Christophe PLAGNIOL-VILLARD | 0383694 | 2008-10-16 15:01:15 +0200 | [diff] [blame] | 126 | #ifdef CONFIG_SYS_64BIT_LBA |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 127 | lbaint_t blk = simple_strtoull(argv[3], NULL, 16); |
| 128 | |
| 129 | printf("\nIDE write: device %d block # %lld, count %ld...", |
| 130 | curr_device, blk, cnt); |
Guennadi Liakhovetski | b71f1ca | 2008-04-28 14:36:06 +0200 | [diff] [blame] | 131 | #else |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 132 | lbaint_t blk = simple_strtoul(argv[3], NULL, 16); |
| 133 | |
| 134 | printf("\nIDE write: device %d block # %ld, count %ld...", |
| 135 | curr_device, blk, cnt); |
Guennadi Liakhovetski | b71f1ca | 2008-04-28 14:36:06 +0200 | [diff] [blame] | 136 | #endif |
Simon Glass | e11f0ef | 2016-05-01 11:36:10 -0600 | [diff] [blame] | 137 | n = blk_write_devnum(IF_TYPE_IDE, curr_device, blk, cnt, |
| 138 | (ulong *)addr); |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 139 | |
| 140 | printf("%ld blocks written: %s\n", n, |
| 141 | n == cnt ? "OK" : "ERROR"); |
| 142 | if (n == cnt) |
| 143 | return 0; |
| 144 | else |
| 145 | return 1; |
| 146 | } else { |
| 147 | return CMD_RET_USAGE; |
wdenk | f602aa0 | 2004-03-13 23:29:43 +0000 | [diff] [blame] | 148 | } |
wdenk | f602aa0 | 2004-03-13 23:29:43 +0000 | [diff] [blame] | 149 | |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 150 | return rcode; |
| 151 | } |
| 152 | } |
wdenk | f602aa0 | 2004-03-13 23:29:43 +0000 | [diff] [blame] | 153 | |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 154 | int do_diskboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) |
| 155 | { |
| 156 | return common_diskboot(cmdtp, "ide", argc, argv); |
| 157 | } |
wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 158 | |
Wolfgang Denk | 2bc10cf | 2011-10-29 09:41:40 +0000 | [diff] [blame] | 159 | U_BOOT_CMD(ide, 5, 1, do_ide, |
| 160 | "IDE sub-system", |
| 161 | "reset - reset IDE controller\n" |
| 162 | "ide info - show available IDE devices\n" |
| 163 | "ide device [dev] - show or set current device\n" |
| 164 | "ide part [dev] - print partition table of one or all IDE devices\n" |
| 165 | "ide read addr blk# cnt\n" |
| 166 | "ide write addr blk# cnt - read/write `cnt'" |
| 167 | " blocks starting at block `blk#'\n" |
| 168 | " to/from memory address `addr'"); |
wdenk | 57b2d80 | 2003-06-27 21:31:46 +0000 | [diff] [blame] | 169 | |
Wolfgang Denk | 2bc10cf | 2011-10-29 09:41:40 +0000 | [diff] [blame] | 170 | U_BOOT_CMD(diskboot, 3, 1, do_diskboot, |
| 171 | "boot from IDE device", "loadAddr dev:part"); |