]> cloudbase.mooo.com Git - z180-stamp.git/blob - avr/cmd_fat.c
9222c1bf91d4ae61086288c315a5aea9a0874fae
[z180-stamp.git] / avr / cmd_fat.c
1 #include "common.h"
2 #include <stdlib.h>
3 #include <string.h>
4 #include <stdbool.h>
5
6 #include "command.h"
7 #include "ff.h"
8 #include "z80-if.h"
9 #include "print-utils.h"
10 #include "timer.h"
11
12
13 DWORD get_fattime (void)
14 {
15 return 0;
16 }
17
18
19 static const FLASH char * const FLASH rc_names[] = {
20 FSTR("OK"),
21 FSTR("DISK_ERR"),
22 FSTR("INT_ERR"),
23 FSTR("NOT_READY"),
24 FSTR("NO_FILE"),
25 FSTR("NO_PATH"),
26 FSTR("INVALID_NAME"),
27 FSTR("DENIED"),
28 FSTR("EXIST"),
29 FSTR("INVALID_OBJECT"),
30 FSTR("WRITE_PROTECTED"),
31 FSTR("INVALID_DRIVE"),
32 FSTR("NOT_ENABLED"),
33 FSTR("NO_FILE_SYSTEM"),
34 FSTR("MKFS_ABORTED"),
35 FSTR("TIMEOUT"),
36 FSTR("LOCKED"),
37 FSTR("NOT_ENOUGH_CORE"),
38 FSTR("TOO_MANY_OPEN_FILES")
39 };
40
41 static
42 void put_rc (FRESULT rc)
43 {
44 #if GCC_BUG_61443
45 printf_P(PSTR("rc=%u FR_"), rc);
46 my_puts_P(rc_names[rc]);
47 my_puts_P(PSTR("\n"));
48 #else
49 printf_P(PSTR("rc=%u FR_%S\n"), rc, rc_names[rc]);
50 #endif
51 }
52
53 /* Work register for fs command */
54 static DWORD AccSize;
55 static WORD AccFiles, AccDirs;
56 FILINFO Finfo;
57
58 static
59 FRESULT scan_files (
60 char* path /* Pointer to the working buffer with start path */
61 )
62 {
63 DIR dirs;
64 FRESULT res;
65 int i;
66 char *fn;
67
68 res = f_opendir(&dirs, path);
69 if (res == FR_OK) {
70 i = strlen(path);
71 while (((res = f_readdir(&dirs, &Finfo)) == FR_OK) && Finfo.fname[0]) {
72 if (_FS_RPATH && Finfo.fname[0] == '.') continue;
73 #if _USE_LFN
74 fn = *Finfo.lfname ? Finfo.lfname : Finfo.fname;
75 #else
76 fn = Finfo.fname;
77 #endif
78 if (Finfo.fattrib & AM_DIR) {
79 AccDirs++;
80 path[i] = '/'; strcpy(path+i+1, fn);
81 res = scan_files(path);
82 path[i] = '\0';
83 if (res != FR_OK) break;
84 } else {
85 // printf_P(PSTR("%s/%s\n"), path, fn);
86 AccFiles++;
87 AccSize += Finfo.fsize;
88 }
89 }
90 }
91
92 return res;
93 }
94
95
96 /*
97 * fatstat path - Show logical drive status
98 *
99 */
100 command_ret_t do_fat_stat(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
101 {
102 FATFS FatFs, *fs;
103 DWORD p1, p2;
104 FRESULT res;
105 char buffer[512];
106
107 (void) cmdtp; (void) flag; (void) argc;
108
109 res = f_mount(&FatFs, argv[1], 0);
110 if (!res)
111 res = f_getfree(argv[1], &p2, &fs);
112 if (res) {
113 put_rc(res);
114 return CMD_RET_FAILURE;
115 }
116
117 printf_P(PSTR(
118 "FAT type: %u\n"
119 "Bytes/Cluster: %lu\n"
120 "Number of FATs: %u\n"
121 "Root DIR entries: %u\n"
122 "Sectors/FAT: %lu\n"
123 "Number of clusters: %lu\n"
124 "FAT start (lba): %lu\n"
125 "DIR start (lba,cluster): %lu\n"
126 "Data start (lba): %lu\n"),
127 fs->fs_type, (DWORD)fs->csize * 512, fs->n_fats,
128 fs->n_rootdir, fs->fsize, fs->n_fatent - 2,
129 fs->fatbase, fs->dirbase, fs->database);
130
131 #if _USE_LABEL
132 TCHAR label[12];
133 res = f_getlabel(argv[1], label, &p1);
134 if (res) {
135 put_rc(res);
136 return CMD_RET_FAILURE;
137 }
138 printf_P(PSTR(
139 "Volume name: %s\n"
140 "Volume S/N: %04X-%04X\n"),
141 label, (WORD)((DWORD)p1 >> 16), (WORD)(p1 & 0xFFFF));
142 #endif
143 my_puts_P(PSTR("\n..."));
144 AccSize = AccFiles = AccDirs = 0;
145
146 strcpy(buffer, argv[1]);
147
148 res = scan_files(buffer);
149 if (res) {
150 put_rc(res);
151 return CMD_RET_FAILURE;
152 }
153 printf_P(PSTR("\r%u files, %lu bytes.\n%u folders.\n"
154 "%lu KB total disk space.\n%lu KB available.\n"),
155 AccFiles, AccSize, AccDirs,
156 (fs->n_fatent - 2) * (fs->csize / 2), p2 * (fs->csize / 2)
157 );
158
159 res = f_mount(NULL, argv[1], 0);
160 if (res) {
161 put_rc(res);
162 return CMD_RET_FAILURE;
163 }
164 return CMD_RET_SUCCESS;
165 }
166
167
168 /*
169 * fatls path - Directory listing
170 *
171 */
172 command_ret_t do_fat_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
173 {
174 FATFS FatFs, *fs;
175 DIR Dir; /* Directory object */
176 FILINFO Finfo;
177 unsigned long p1;
178 unsigned int s1, s2;
179 FRESULT res;
180 #if _USE_LFN
181 char Lfname[_MAX_LFN+1];
182 Finfo.lfname = Lfname;
183 Finfo.lfsize = sizeof Lfname;
184 #endif
185
186 (void) cmdtp; (void) flag; (void) argc;
187
188 res = f_mount(&FatFs, argv[1], 0);
189 if (!res)
190 res = f_opendir(&Dir, argv[1]);
191 if (res) {
192 put_rc(res);
193 return CMD_RET_FAILURE;
194 }
195
196 p1 = s1 = s2 = 0;
197 for(;;) {
198 res = f_readdir(&Dir, &Finfo);
199 if ((res != FR_OK) || !Finfo.fname[0])
200 break;
201 if (Finfo.fattrib & AM_DIR) {
202 s2++;
203 } else {
204 s1++; p1 += Finfo.fsize;
205 }
206 printf_P(PSTR("%c%c%c%c%c %u/%02u/%02u %02u:%02u %9lu %s"),
207 (Finfo.fattrib & AM_DIR) ? 'D' : '-',
208 (Finfo.fattrib & AM_RDO) ? 'R' : '-',
209 (Finfo.fattrib & AM_HID) ? 'H' : '-',
210 (Finfo.fattrib & AM_SYS) ? 'S' : '-',
211 (Finfo.fattrib & AM_ARC) ? 'A' : '-',
212 (Finfo.fdate >> 9) + 1980, (Finfo.fdate >> 5) & 15, Finfo.fdate & 31,
213 (Finfo.ftime >> 11), (Finfo.ftime >> 5) & 63,
214 Finfo.fsize, &(Finfo.fname[0]));
215 #if _USE_LFN
216 for (int i = strlen(Finfo.fname); i < 14; i++)
217 putchar(' ');
218 printf_P(PSTR("%s\n"), Lfname);
219 #else
220 putchar('\n');
221 #endif
222 }
223
224 if (res == FR_OK) {
225 printf_P(PSTR("%4u File(s),%10lu bytes total\n%4u Dir(s)"), s1, p1, s2);
226 if (f_getfree(argv[1], (DWORD*)&p1, &fs) == FR_OK)
227 printf_P(PSTR(", %10luK bytes free\n"), p1 * fs->csize / 2);
228 }
229
230 if (res) {
231 put_rc(res);
232 return CMD_RET_FAILURE;
233 }
234
235 return CMD_RET_SUCCESS;
236 }
237
238
239 /*
240 * fatread - load binary file from a dos filesystem
241 * <d:/path/filename> <addr> [bytes [pos]]
242 */
243 command_ret_t do_fat_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
244 {
245 FATFS FatFs;
246 FIL File;
247 unsigned long bytes = 0x80000;
248 unsigned long pos= 0;
249 unsigned long bytes_read;
250 uint32_t addr;
251 FRESULT res;
252 bool buserr = 0;
253 uint32_t timer;
254 uint8_t buffer[512];
255
256 (void) cmdtp; (void) flag;
257
258 if (argc < 3)
259 return CMD_RET_USAGE;
260
261 addr = strtoul(argv[2], 0, 16);
262 if (argc > 3)
263 bytes = strtoul(argv[3], 0, 16);
264 if (argc > 4)
265 pos = strtoul(argv[4], 0, 16);
266
267 res = f_mount(&FatFs, argv[1], 0);
268 if (!res) {
269 res = f_open(&File, argv[1], FA_READ);
270
271 if (!res) {
272 res = f_lseek(&File, pos);
273 if (!res) {
274 bytes_read = 0;
275 timer = get_timer(0);
276 while (bytes) {
277 unsigned int cnt, br;
278
279 if (bytes >= sizeof buffer) {
280 cnt = sizeof buffer;
281 bytes -= sizeof buffer;
282 } else {
283 cnt = bytes; bytes = 0;
284 }
285 res = f_read(&File, buffer, cnt, &br);
286 if (res != FR_OK)
287 break;
288 if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
289 buserr = 1;
290 break;
291 }
292 z80_write_block(buffer, addr, br);
293 z80_bus_cmd(Release);
294 addr += br;
295
296 bytes_read += br;
297 if (cnt != br)
298 break;
299 }
300 timer = get_timer(timer);
301 printf_P(PSTR("%lu bytes read with %lu bytes/sec.\n"),
302 bytes_read, timer ? (bytes_read * 1000 / timer) : 0);
303 }
304 }
305 f_mount(NULL, argv[1], 0);
306 }
307
308 if (buserr)
309 my_puts_P(PSTR("Bus timeout\n"));
310 if (res)
311 put_rc(res);
312 if (buserr || res)
313 return CMD_RET_FAILURE;
314
315 return CMD_RET_SUCCESS;
316 }
317
318 /*
319 * fatwrite - write file into a dos filesystem
320 * <d:/path/filename> <addr> <bytes>
321 */
322 command_ret_t do_fat_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
323 {
324 FATFS FatFs;
325 FIL File;
326 unsigned long bytes;
327 unsigned long bytes_written;
328 uint32_t addr;
329 FRESULT res;
330 bool buserr = 0;
331 uint32_t timer;
332 uint8_t buffer[512];
333
334 (void) cmdtp; (void) flag;
335
336 if (argc < 4)
337 return CMD_RET_USAGE;
338
339 addr = strtoul(argv[2], 0, 16);
340 bytes = strtoul(argv[3], 0, 16);
341
342 res = f_mount(&FatFs, argv[1], 0);
343 if (!res) {
344 res = f_open(&File, argv[1], FA_CREATE_ALWAYS | FA_WRITE);
345 if (!res) {
346 bytes_written = 0;
347 timer = get_timer(0);
348 while (bytes) {
349 unsigned int cnt, br;
350
351 if (bytes >= sizeof buffer) {
352 cnt = sizeof buffer;
353 bytes -= sizeof buffer;
354 } else {
355 cnt = bytes; bytes = 0;
356 }
357 if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
358 buserr = 1;
359 break;
360 }
361 z80_read_block(buffer, addr, cnt);
362 z80_bus_cmd(Release);
363 res = f_write(&File, buffer, cnt, &br);
364 if (res != FR_OK)
365 break;
366 addr += br;
367 bytes_written += br;
368 if (cnt != br)
369 break;
370 }
371 res = f_close(&File);
372 timer = get_timer(timer);
373 printf_P(PSTR("%lu bytes written with %lu bytes/sec.\n"),
374 bytes_written, timer ? (bytes_written * 1000 / timer) : 0);
375 }
376 f_mount(NULL, argv[1], 0);
377 }
378
379 if (buserr)
380 my_puts_P(PSTR("Bus timeout\n"));
381 if (res)
382 put_rc(res);
383 if (buserr || res)
384 return CMD_RET_FAILURE;
385
386 return CMD_RET_SUCCESS;
387 }