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