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 | |
Heiko Schocher | 65d94db | 2017-06-07 17:33:09 +0200 | [diff] [blame] | 21 | #if defined(CONFIG_IDE_PCMCIA) |
wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 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) { |
Heiko Schocher | 65d94db | 2017-06-07 17:33:09 +0200 | [diff] [blame] | 45 | puts("\nReset IDE: "); |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 46 | ide_init(); |
| 47 | return 0; |
| 48 | } else if (strncmp(argv[1], "inf", 3) == 0) { |
Simon Glass | e11f0ef | 2016-05-01 11:36:10 -0600 | [diff] [blame] | 49 | blk_list_devices(IF_TYPE_IDE); |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 50 | return 0; |
| 51 | |
| 52 | } else if (strncmp(argv[1], "dev", 3) == 0) { |
Simon Glass | e11f0ef | 2016-05-01 11:36:10 -0600 | [diff] [blame] | 53 | if (blk_print_device_num(IF_TYPE_IDE, curr_device)) { |
| 54 | printf("\nno IDE devices available\n"); |
| 55 | return CMD_RET_FAILURE; |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 56 | } |
Simon Glass | e11f0ef | 2016-05-01 11:36:10 -0600 | [diff] [blame] | 57 | |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 58 | return 0; |
| 59 | } else if (strncmp(argv[1], "part", 4) == 0) { |
Simon Glass | e11f0ef | 2016-05-01 11:36:10 -0600 | [diff] [blame] | 60 | if (blk_list_part(IF_TYPE_IDE)) |
| 61 | printf("\nno IDE devices available\n"); |
| 62 | return 1; |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 63 | } |
| 64 | return CMD_RET_USAGE; |
| 65 | case 3: |
| 66 | if (strncmp(argv[1], "dev", 3) == 0) { |
| 67 | int dev = (int)simple_strtoul(argv[2], NULL, 10); |
wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 68 | |
Simon Glass | e11f0ef | 2016-05-01 11:36:10 -0600 | [diff] [blame] | 69 | if (!blk_show_device(IF_TYPE_IDE, dev)) { |
| 70 | curr_device = dev; |
| 71 | printf("... is now current device\n"); |
| 72 | } else { |
| 73 | return CMD_RET_FAILURE; |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 74 | } |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 75 | return 0; |
| 76 | } else if (strncmp(argv[1], "part", 4) == 0) { |
| 77 | int dev = (int)simple_strtoul(argv[2], NULL, 10); |
wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 78 | |
Simon Glass | e11f0ef | 2016-05-01 11:36:10 -0600 | [diff] [blame] | 79 | if (blk_print_part_devnum(IF_TYPE_IDE, dev)) { |
| 80 | printf("\nIDE device %d not available\n", dev); |
| 81 | return CMD_RET_FAILURE; |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 82 | } |
Simon Glass | e11f0ef | 2016-05-01 11:36:10 -0600 | [diff] [blame] | 83 | return 1; |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 84 | } |
wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 85 | |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 86 | return CMD_RET_USAGE; |
| 87 | default: |
| 88 | /* at least 4 args */ |
wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 89 | |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 90 | if (strcmp(argv[1], "read") == 0) { |
| 91 | ulong addr = simple_strtoul(argv[2], NULL, 16); |
| 92 | ulong cnt = simple_strtoul(argv[4], NULL, 16); |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 93 | ulong n; |
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 | #ifdef CONFIG_SYS_64BIT_LBA |
| 96 | lbaint_t blk = simple_strtoull(argv[3], NULL, 16); |
wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 97 | |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 98 | printf("\nIDE read: device %d block # %lld, count %ld...", |
| 99 | curr_device, blk, cnt); |
| 100 | #else |
| 101 | lbaint_t blk = simple_strtoul(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 # %ld, count %ld...", |
| 104 | curr_device, blk, cnt); |
| 105 | #endif |
wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 106 | |
Simon Glass | e11f0ef | 2016-05-01 11:36:10 -0600 | [diff] [blame] | 107 | n = blk_read_devnum(IF_TYPE_IDE, curr_device, blk, cnt, |
| 108 | (ulong *)addr); |
wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 109 | |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 110 | printf("%ld blocks read: %s\n", |
| 111 | n, (n == cnt) ? "OK" : "ERROR"); |
| 112 | if (n == cnt) |
| 113 | return 0; |
| 114 | else |
| 115 | return 1; |
| 116 | } else if (strcmp(argv[1], "write") == 0) { |
| 117 | ulong addr = simple_strtoul(argv[2], NULL, 16); |
| 118 | ulong cnt = simple_strtoul(argv[4], NULL, 16); |
| 119 | ulong n; |
wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 120 | |
Jean-Christophe PLAGNIOL-VILLARD | 0383694 | 2008-10-16 15:01:15 +0200 | [diff] [blame] | 121 | #ifdef CONFIG_SYS_64BIT_LBA |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 122 | lbaint_t blk = simple_strtoull(argv[3], NULL, 16); |
| 123 | |
| 124 | printf("\nIDE write: device %d block # %lld, count %ld...", |
| 125 | curr_device, blk, cnt); |
Guennadi Liakhovetski | b71f1ca | 2008-04-28 14:36:06 +0200 | [diff] [blame] | 126 | #else |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 127 | lbaint_t blk = simple_strtoul(argv[3], NULL, 16); |
| 128 | |
| 129 | printf("\nIDE write: device %d block # %ld, count %ld...", |
| 130 | curr_device, blk, cnt); |
Guennadi Liakhovetski | b71f1ca | 2008-04-28 14:36:06 +0200 | [diff] [blame] | 131 | #endif |
Simon Glass | e11f0ef | 2016-05-01 11:36:10 -0600 | [diff] [blame] | 132 | n = blk_write_devnum(IF_TYPE_IDE, curr_device, blk, cnt, |
| 133 | (ulong *)addr); |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 134 | |
| 135 | printf("%ld blocks written: %s\n", n, |
| 136 | n == cnt ? "OK" : "ERROR"); |
| 137 | if (n == cnt) |
| 138 | return 0; |
| 139 | else |
| 140 | return 1; |
| 141 | } else { |
| 142 | return CMD_RET_USAGE; |
wdenk | f602aa0 | 2004-03-13 23:29:43 +0000 | [diff] [blame] | 143 | } |
wdenk | f602aa0 | 2004-03-13 23:29:43 +0000 | [diff] [blame] | 144 | |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 145 | return rcode; |
| 146 | } |
| 147 | } |
wdenk | f602aa0 | 2004-03-13 23:29:43 +0000 | [diff] [blame] | 148 | |
Simon Glass | 43a464a | 2016-05-01 11:36:00 -0600 | [diff] [blame] | 149 | int do_diskboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) |
| 150 | { |
| 151 | return common_diskboot(cmdtp, "ide", argc, argv); |
| 152 | } |
wdenk | c609719 | 2002-11-03 00:24:07 +0000 | [diff] [blame] | 153 | |
Wolfgang Denk | 2bc10cf | 2011-10-29 09:41:40 +0000 | [diff] [blame] | 154 | U_BOOT_CMD(ide, 5, 1, do_ide, |
| 155 | "IDE sub-system", |
| 156 | "reset - reset IDE controller\n" |
| 157 | "ide info - show available IDE devices\n" |
| 158 | "ide device [dev] - show or set current device\n" |
| 159 | "ide part [dev] - print partition table of one or all IDE devices\n" |
| 160 | "ide read addr blk# cnt\n" |
| 161 | "ide write addr blk# cnt - read/write `cnt'" |
| 162 | " blocks starting at block `blk#'\n" |
| 163 | " to/from memory address `addr'"); |
wdenk | 57b2d80 | 2003-06-27 21:31:46 +0000 | [diff] [blame] | 164 | |
Wolfgang Denk | 2bc10cf | 2011-10-29 09:41:40 +0000 | [diff] [blame] | 165 | U_BOOT_CMD(diskboot, 3, 1, do_diskboot, |
| 166 | "boot from IDE device", "loadAddr dev:part"); |