]> cloudbase.mooo.com Git - z180-stamp.git/blame - avr/cmd_sd.c
Sd card commands: read sector, write sector
[z180-stamp.git] / avr / cmd_sd.c
CommitLineData
7f552300
L
1#include "common.h"
2#include <stdlib.h>
3
a882a089 4#include "command.h"
7f552300
L
5#include "diskio.h"
6#include "ff.h"
a882a089 7#include "z80-if.h"
7f552300
L
8#include "print-utils.h"
9
10
11static const FLASH char * const FLASH rc_names[] = {
12 FSTR("OK"),
13 FSTR("DISK_ERR"),
14 FSTR("INT_ERR"),
15 FSTR("NOT_READY"),
16 FSTR("NO_FILE"),
17 FSTR("NO_PATH"),
18 FSTR("INVALID_NAME"),
19 FSTR("DENIED"),
20 FSTR("EXIST"),
21 FSTR("INVALID_OBJECT"),
22 FSTR("WRITE_PROTECTED"),
23 FSTR("INVALID_DRIVE"),
24 FSTR("NOT_ENABLED"),
25 FSTR("NO_FILE_SYSTEM"),
26 FSTR("MKFS_ABORTED"),
27 FSTR("TIMEOUT"),
28 FSTR("LOCKED"),
29 FSTR("NOT_ENOUGH_CORE"),
30 FSTR("TOO_MANY_OPEN_FILES")
31 };
32
33static
34void put_rc (FRESULT rc)
35{
36#if 0
37 printf_P(PSTR("rc=%u FR_%S\n"), rc, rc_names[rc]);
38#else
39 printf_P(PSTR("rc=%u FR_"), rc);
40 my_puts_P(rc_names[rc]);
a882a089 41 my_puts_P(PSTR("\n"));
7f552300
L
42
43#endif
44
45}
46
7f552300
L
47
48/*
a882a089 49 * di <pd#> - Initialize disk
7f552300
L
50 *
51 */
a882a089
L
52static
53command_ret_t do_init(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
7f552300 54{
a882a089 55 DSTATUS res;
7f552300 56 BYTE dev;
7f552300
L
57
58 (void) cmdtp; (void) flag;
59
60 if (argc < 2)
61 return CMD_RET_USAGE;
62
63 dev = (BYTE) strtoul(argv[1], 0, 10);
a882a089
L
64 res = disk_status(dev);
65 printf_P(PSTR("disk_status=%.2x\n"), res);
7f552300 66
a882a089
L
67 if ((res & STA_NODISK) == 0) {
68 res = disk_initialize(dev);
69 }
70 printf_P(PSTR("rc=%.2x\n"), res);
7f552300 71 if (res) {
7f552300
L
72 return CMD_RET_FAILURE;
73 }
74
7f552300
L
75 return CMD_RET_SUCCESS;
76}
77
78/*
a882a089 79 * ds <pd#> - Show disk status
7f552300
L
80 *
81 */
a882a089
L
82static
83command_ret_t do_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
7f552300 84{
7f552300
L
85 BYTE dev;
86
a882a089
L
87 union {
88 unsigned char uca[64];
89 unsigned long ul;
90 unsigned char uc;
91 } dat;
92
7f552300
L
93 (void) cmdtp; (void) flag;
94
95 if (argc < 2)
96 return CMD_RET_USAGE;
97
98 dev = (BYTE) strtoul(argv[1], 0, 10);
7f552300 99
a882a089
L
100
101 if (disk_ioctl(dev, GET_SECTOR_COUNT, &dat.ul) == RES_OK)
102 printf_P(PSTR("Drive size: %lu sectors\n"), dat.ul);
103
104 if (disk_ioctl(dev, GET_BLOCK_SIZE, &dat.ul) == RES_OK)
105 printf_P(PSTR("Erase block: %lu sectors\n"), dat.ul);
106
107 if (disk_ioctl(dev, MMC_GET_TYPE, &dat.uc) == RES_OK)
108 printf_P(PSTR("Card type: %u\n"), dat.uc);
109
110 if (disk_ioctl(dev, MMC_GET_CSD, dat.uca) == RES_OK)
111 dump_ram((uint32_t) (size_t) dat.uca, 0, 16, "CSD:");
112
113 if (disk_ioctl(dev, MMC_GET_CID, dat.uca) == RES_OK)
114 dump_ram((uint32_t) (size_t) dat.uca, 0, 16, "CID:");
115
116 if (disk_ioctl(dev, MMC_GET_OCR, dat.uca) == RES_OK)
117 dump_ram((uint32_t) (size_t) dat.uca, 0, 4, "OCR:");
118
119 if (disk_ioctl(dev, MMC_GET_SDSTAT, dat.uca) == RES_OK)
120 dump_ram((uint32_t) (size_t) dat.uca, 0, 64, "SD Status:");
121
122 if (disk_ioctl(dev, ATA_GET_MODEL, dat.uca) == RES_OK) {
123 dat.uca[40] = '\0';
124 printf_P(PSTR("Model: %s\n"), dat.uca);
7f552300 125 }
a882a089
L
126 if (disk_ioctl(dev, ATA_GET_SN, dat.uca) == RES_OK) {
127 dat.uca[20] = '\0'; printf_P(PSTR("S/N: %s\n"), dat.uca);
7f552300
L
128 }
129
130 return CMD_RET_SUCCESS;
131}
132
a882a089 133
7f552300 134/*
a882a089 135 * dump <pd#> [<sector> [count]] - Dump sector
7f552300
L
136 *
137 */
a882a089
L
138static
139command_ret_t do_dump(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
7f552300 140{
a882a089
L
141 static BYTE dev_last;
142 static DWORD sec_last;
143 BYTE buffer[_MAX_SS];
144 char header[20];
7f552300 145
a882a089
L
146 DRESULT res;
147 BYTE dev;
148 DWORD sec;
149 UINT count;
7f552300
L
150
151 (void) cmdtp; (void) flag;
152
153 if (argc < 2)
154 return CMD_RET_USAGE;
155
a882a089
L
156 dev = (BYTE) strtoul(argv[1], NULL, 10);
157 if (dev != dev_last)
158 sec_last = 0;
159 sec = sec_last;
160 count = 1;
161
162 if ((flag & CMD_FLAG_REPEAT) == 0) {
163 /* If another parameter, it is the sector to dump. */
164 if (argc > 2)
165 sec = strtoul(argv[2], 0, 10);
166 if (argc > 3)
167 count = (UINT) strtoul(argv[3], 0, 10);
168 }
7f552300 169
a882a089
L
170 for ( ; count; count--, sec++) {
171 res = disk_read(dev, buffer, sec, 1);
7f552300 172
a882a089
L
173 if (res) {
174 printf_P(PSTR("rc=%.2x\n"), res);
175 return CMD_RET_FAILURE;
176 }
7f552300 177
a882a089
L
178 sprintf_P(header, PSTR("Sector: %lu"), sec);
179 dump_ram((uint32_t) (size_t) buffer, 0, _MAX_SS, header);
180 }
181 dev_last = dev;
182 sec_last = sec;
7f552300 183
a882a089
L
184 return CMD_RET_SUCCESS;
185}
7f552300 186
a882a089
L
187/*
188 * read drive sector count memaddr - Read disk into memory
189 *
190 */
191static
192command_ret_t do_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
193{
194 DRESULT res;
195 BYTE dev;
196 DWORD sec;
197 uint32_t addr;
198 int count, nr;
199 BYTE buffer[_MAX_SS];
7f552300 200
a882a089
L
201 static DWORD sec_last;
202 static uint32_t addr_last;
7f552300 203
a882a089 204 (void) cmdtp;
7f552300 205
a882a089
L
206 if (argc < 2)
207 return CMD_RET_USAGE;
7f552300 208
a882a089
L
209 dev = (BYTE) strtoul(argv[1], NULL, 10);
210 sec = sec_last;
211 count = 1;
212 addr = addr_last;
213
214 if ((flag & CMD_FLAG_REPEAT) == 0) {
215 /* If another parameter, it is the sector to dump. */
216 if (argc > 2)
217 sec = strtoul(argv[2], 0, 10);
218 if (argc > 3)
219 count = strtoul(argv[3], 0, 10);
220 if (argc > 4)
221 addr = strtoul(argv[4], 0, 16);
7f552300 222 }
a882a089
L
223
224 for (nr = 0; nr < count;) {
225 nr++;
226 if ((res = disk_read(dev, buffer, sec, 1)) == RES_OK) {
227 if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
228 my_puts_P(PSTR("Bus timeout\n"));
229 return CMD_RET_FAILURE;
230 }
231 z80_write_block(buffer, addr /*+ base*/, _MAX_SS);
232 z80_bus_cmd(Release);
233 sec++; addr += _MAX_SS;
234 } else
235 break;
7f552300
L
236 }
237
a882a089
L
238 printf_P(PSTR("Read %d sector(s), rc=%.2x.\n"), nr, res);
239 if (res)
240 printf_P(PSTR("Last sector not written!\n"));
241
242 sec_last = sec;
243 addr_last = addr;
7f552300 244
a882a089
L
245 return res ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
246}
7f552300
L
247
248
249/*
a882a089 250 * write <pd#> <sector> <memaddr> [<n>] - Write memory to disk
7f552300
L
251 *
252 */
a882a089
L
253static
254command_ret_t do_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
7f552300 255{
a882a089 256 DRESULT res;
7f552300 257 BYTE dev;
a882a089
L
258 DWORD sec;
259 uint32_t addr;
260 int count, nr;
261 BYTE buffer[_MAX_SS];
7f552300 262
a882a089
L
263 static DWORD sec_last;
264 static uint32_t addr_last;
265
266 (void) cmdtp;
7f552300
L
267
268 if (argc < 2)
269 return CMD_RET_USAGE;
270
a882a089
L
271 dev = (BYTE) strtoul(argv[1], NULL, 10);
272 sec = sec_last;
273 addr = addr_last;
274 count = 1;
275
276 if ((flag & CMD_FLAG_REPEAT) == 0) {
277 /* If another parameter, it is the sector to dump. */
278 if (argc > 2)
279 sec = strtoul(argv[2], 0, 10);
280 if (argc > 3)
281 count = strtoul(argv[3], 0, 10);
282 if (argc > 4)
283 addr = strtoul(argv[4], 0, 16);
284 }
7f552300 285
a882a089
L
286 for (nr = 0; nr < count;) {
287 nr++;
288 if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
289 my_puts_P(PSTR("Bus timeout\n"));
290 return CMD_RET_FAILURE;
291 }
292 z80_read_block(buffer, addr /*+ base*/, _MAX_SS);
293 z80_bus_cmd(Release);
294
295 res = disk_write(dev, buffer, sec, 1);
296 if (res != RES_OK)
297 break;
298 sec++; addr += _MAX_SS;
299 }
300
301 printf_P(PSTR("%d sector(s) written, rc=%.2x.\n"), nr, res);
302
303 sec_last = sec;
304 addr_last = addr;
305
306 return res ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
7f552300
L
307}
308
309
310
a882a089
L
311/*
312 * Disk ioctl
313 * dcs <pd#> - CTRL_SYNC
314 *
315 */
316static
317command_ret_t do_ioctl_sync(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
7f552300 318{
a882a089 319 BYTE dev;
7f552300 320
a882a089 321 (void) cmdtp; (void) flag;
7f552300 322
a882a089
L
323 if (argc < 2)
324 return CMD_RET_USAGE;
7f552300 325
a882a089
L
326 dev = (BYTE) strtoul(argv[1], 0, 10);
327 printf_P(PSTR("rc=%.2x\n"), disk_ioctl(dev, CTRL_SYNC, 0));
7f552300
L
328
329 return CMD_RET_SUCCESS;
330}
331
7f552300
L
332
333static
334command_ret_t do_help(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
335
336cmd_tbl_t cmd_sd_sub[] = {
337CMD_TBL_ITEM(
a882a089 338 init, 2, 1, do_init,
7f552300
L
339 "Initialize disk",
340 ""
341),
342CMD_TBL_ITEM(
a882a089 343 status, 2, 1, do_status,
7f552300
L
344 "Disk status",
345 ""
346),
347CMD_TBL_ITEM(
a882a089
L
348 dump, CONFIG_SYS_MAXARGS, 1, do_dump,
349 "Dump sector",
7f552300
L
350 ""
351),
352CMD_TBL_ITEM(
a882a089
L
353 read, 2, 1, do_read,
354 "read disk sector(s) into meomory",
355 "drive [sector [count [memaddr]]]"
356),
357CMD_TBL_ITEM(
358 write, 2, 1, do_write,
359 "write sector(s) from meomory to disk",
360 "drive [sector [count [memaddr]]]"
7f552300
L
361),
362CMD_TBL_ITEM(
a882a089
L
363 sync, 2, 1, do_ioctl_sync,
364 "Device control: SYNC",
365 ""
7f552300 366),
a882a089 367
7f552300
L
368CMD_TBL_ITEM(
369 help, CONFIG_SYS_MAXARGS, 1, do_help,
370 "print sub command description/usage",
371 "\n"
372 " - print brief description of all sub commands\n"
373 "sd help command ...\n"
374 " - print detailed usage of sub cmd 'command'"
375),
376
377/* This does not use the CMD_TBL_ITEM macro as ? can't be used in symbol names */
378 {FSTR("?"), CONFIG_SYS_MAXARGS, 1, do_help,
379 FSTR("alias for 'help'"),
380#ifdef CONFIG_SYS_LONGHELP
381 FSTR(""),
382#endif /* CONFIG_SYS_LONGHELP */
383#ifdef CONFIG_AUTO_COMPLETE
384 0,
385#endif
386},
387};
388
389static
390command_ret_t do_help(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
391{
392 return _do_help(cmd_sd_sub, ARRAY_SIZE(cmd_sd_sub), cmdtp, flag, argc, argv);
393}
394
395
396command_ret_t do_sd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
397{
398 cmd_tbl_t *cp;
399
400 if (argc < 2)
401 return CMD_RET_USAGE;
402
403 /* drop initial "sd" arg */
404 argc--;
405 argv++;
406
407 cp = find_cmd_tbl(argv[0], cmd_sd_sub, ARRAY_SIZE(cmd_sd_sub));
408
409 if (cp)
410 return cp->cmd(cmdtp, flag, argc, argv);
411
412 return CMD_RET_USAGE;
413}