|
20 | 20 | #include "../../libk/core/mem.h" |
21 | 21 | #include "../../libk/spinlock.h" |
22 | 22 | #include "../../drv/rtc.h" |
| 23 | +#include "../../kernel/sched.h" |
| 24 | + |
| 25 | +#define FAT_IO_CHUNK 4096U |
23 | 26 |
|
24 | 27 | DWORD get_fattime(void) { |
25 | 28 | rtc_time_t t = rtc_get_time(); |
@@ -155,23 +158,49 @@ int fat_open(const char *path, int write) { return fat_open_vol(path, write, 0); |
155 | 158 |
|
156 | 159 | int fat_read(int fd, void *buf, uint32_t size, uint32_t *bytes_read) { |
157 | 160 | if (!initialized || fd < 0 || fd >= FAT_MAX_FDS || !fd_table[fd].used) return -1; |
158 | | - UINT br = 0; |
159 | | - fat_lock(); |
160 | | - FRESULT fr = f_read(&fd_table[fd].fil, buf, size, &br); |
161 | | - fat_unlock(); |
162 | | - if (bytes_read) *bytes_read = br; |
163 | | - return (fr == FR_OK) ? 0 : -1; |
| 161 | + uint8_t *out = (uint8_t *)buf; |
| 162 | + uint32_t total = 0; |
| 163 | + while (total < size) { |
| 164 | + UINT br = 0; |
| 165 | + UINT chunk = (UINT)(size - total); |
| 166 | + if (chunk > FAT_IO_CHUNK) |
| 167 | + chunk = FAT_IO_CHUNK; |
| 168 | + fat_lock(); |
| 169 | + FRESULT fr = f_read(&fd_table[fd].fil, out + total, chunk, &br); |
| 170 | + fat_unlock(); |
| 171 | + total += br; |
| 172 | + if (fr != FR_OK) { |
| 173 | + if (bytes_read) *bytes_read = total; |
| 174 | + return total ? 0 : -1; |
| 175 | + } |
| 176 | + if (br == 0 || br < chunk) |
| 177 | + break; |
| 178 | + if (total < size) |
| 179 | + sched_yield(); |
| 180 | + } |
| 181 | + if (bytes_read) *bytes_read = total; |
| 182 | + return 0; |
164 | 183 | } |
165 | 184 |
|
166 | 185 | int fat_write(int fd, const void *buf, uint32_t size) { |
167 | 186 | if (!initialized || fd < 0 || fd >= FAT_MAX_FDS || !fd_table[fd].used) return -1; |
168 | 187 | if (!fd_table[fd].writable) return -1; |
169 | | - UINT bw = 0; |
170 | | - fat_lock(); |
171 | | - FRESULT fr = f_write(&fd_table[fd].fil, buf, size, &bw); |
172 | | - fat_unlock(); |
173 | | - if (fr != FR_OK || bw != size) { log("Write fd=%d failed.", 2, 0, fd); return -1; } |
174 | | - fd_table[fd].total_written += bw; |
| 188 | + const uint8_t *in = (const uint8_t *)buf; |
| 189 | + uint32_t total = 0; |
| 190 | + while (total < size) { |
| 191 | + UINT bw = 0; |
| 192 | + UINT chunk = (UINT)(size - total); |
| 193 | + if (chunk > FAT_IO_CHUNK) |
| 194 | + chunk = FAT_IO_CHUNK; |
| 195 | + fat_lock(); |
| 196 | + FRESULT fr = f_write(&fd_table[fd].fil, in + total, chunk, &bw); |
| 197 | + fat_unlock(); |
| 198 | + fd_table[fd].total_written += bw; |
| 199 | + total += bw; |
| 200 | + if (fr != FR_OK || bw != chunk) { log("Write fd=%d failed.", 2, 0, fd); return -1; } |
| 201 | + if (total < size) |
| 202 | + sched_yield(); |
| 203 | + } |
175 | 204 | return 0; |
176 | 205 | } |
177 | 206 |
|
@@ -446,23 +475,50 @@ int fat_open_entry(const char *path, int write, fd_entry_t *out) { return fat_op |
446 | 475 |
|
447 | 476 | int fat_read_entry(fd_entry_t *e, void *buf, uint32_t size, uint32_t *bytes_read) { |
448 | 477 | if (!e || !e->used || e->type != FD_FILE || !e->file) return -1; |
449 | | - UINT br = 0; |
450 | | - fat_lock(); |
451 | | - FRESULT fr = f_read(&e->file->fil, buf, size, &br); |
452 | | - fat_unlock(); |
453 | | - if (bytes_read) *bytes_read = br; |
454 | | - return (fr == FR_OK) ? 0 : -1; |
| 478 | + uint8_t *out = (uint8_t *)buf; |
| 479 | + uint32_t total = 0; |
| 480 | + while (total < size) { |
| 481 | + UINT br = 0; |
| 482 | + UINT chunk = (UINT)(size - total); |
| 483 | + if (chunk > FAT_IO_CHUNK) |
| 484 | + chunk = FAT_IO_CHUNK; |
| 485 | + fat_lock(); |
| 486 | + FRESULT fr = f_read(&e->file->fil, out + total, chunk, &br); |
| 487 | + fat_unlock(); |
| 488 | + total += br; |
| 489 | + if (fr != FR_OK) { |
| 490 | + if (bytes_read) *bytes_read = total; |
| 491 | + return total ? 0 : -1; |
| 492 | + } |
| 493 | + if (br == 0 || br < chunk) |
| 494 | + break; |
| 495 | + if (total < size) |
| 496 | + sched_yield(); |
| 497 | + } |
| 498 | + if (bytes_read) *bytes_read = total; |
| 499 | + return 0; |
455 | 500 | } |
456 | 501 |
|
457 | 502 | int fat_write_entry(fd_entry_t *e, const void *buf, uint32_t size) { |
458 | 503 | if (!e || !e->used || e->type != FD_FILE || !e->file) return -1; |
459 | 504 | if (!e->file->writable) return -1; |
460 | | - UINT bw = 0; |
461 | | - fat_lock(); |
462 | | - FRESULT fr = f_write(&e->file->fil, buf, size, &bw); |
463 | | - fat_unlock(); |
464 | | - if (fr != FR_OK || bw != size) return -1; |
465 | | - e->file->total_written += bw; |
| 505 | + const uint8_t *in = (const uint8_t *)buf; |
| 506 | + uint32_t total = 0; |
| 507 | + while (total < size) { |
| 508 | + UINT bw = 0; |
| 509 | + UINT chunk = (UINT)(size - total); |
| 510 | + if (chunk > FAT_IO_CHUNK) |
| 511 | + chunk = FAT_IO_CHUNK; |
| 512 | + fat_lock(); |
| 513 | + FRESULT fr = f_write(&e->file->fil, in + total, chunk, &bw); |
| 514 | + fat_unlock(); |
| 515 | + e->file->total_written += bw; |
| 516 | + total += bw; |
| 517 | + if (fr != FR_OK || bw != chunk) |
| 518 | + return -1; |
| 519 | + if (total < size) |
| 520 | + sched_yield(); |
| 521 | + } |
466 | 522 | return 0; |
467 | 523 | } |
468 | 524 |
|
|
0 commit comments