diff options
Diffstat (limited to 'src/kernel/fat.c')
-rw-r--r-- | src/kernel/fat.c | 53 |
1 files changed, 36 insertions, 17 deletions
diff --git a/src/kernel/fat.c b/src/kernel/fat.c index ff01d7d..1b6c52d 100644 --- a/src/kernel/fat.c +++ b/src/kernel/fat.c @@ -3,7 +3,7 @@ #include "util.h" #include "ata.h" #include "fat.h" -#include "mem.h" +#include "pmap.h" #define MAX_FAT_DRIVES 16 #define MAX_OPEN_FILES_PER_DRIVE 32 @@ -81,14 +81,14 @@ struct fat_drive_info { }; static struct fat_drive_info infos[MAX_FAT_DRIVES]; -static uint8_t next_id = 0; +static uint8_t next_id; static uint8_t fat_driver_buffer[512]; static struct fat_info *next_fi; static void alloc_next_fi() { if (!((uint32_t)(next_fi = (struct fat_info *)((uint32_t)next_fi + 64)) & 0xfff)) - if (!(next_fi = allocate_pages(1))) + if (!(next_fi = allocate_kernel_pages(1))) panic("Out of memory in FAT driver."); } @@ -109,8 +109,10 @@ static void load_cluster(uint16_t c, void *to) { cur_drive->read_sectors(cur_drive, s, 1, to); } +__attribute__ ((pure)) static uint16_t next_cluster(uint16_t c) { - panic("TODO: compute next sector (or 0 for none)"); + uint16_t found = infos[cur_id].fat[c]; + return (found < 2) || (found >= 0xfff0) ? 0 : found; } static const uint8_t this_dir[] = {'.', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '}; @@ -182,7 +184,7 @@ static const char *split_path(const char *path, uint8_t *fat_name_buffer) { } else panic("Bad path in FAT16 driver"); - else if ((fi == 8) || (fi == 11)) + else if (((fi == 8) && (path[pi - 1] != EXT_SEP_CHAR)) || (fi == 11)) panic("Bad path in FAT16 driver"); else { fat_name_buffer[fi++] = (uint8_t)path[pi++]; @@ -209,13 +211,17 @@ static bool try_load_from_path(const struct drive *d, const char *path) { return true; } -static drive_file_id_t fat_get_file(const struct drive *d, const char *path) { +static file_id_t fat_get_file(const struct drive *d, const char *path) { + d->ready(d); struct open_file_info *open_files = infos[d->drive_id].open_files - 1; - for (drive_file_id_t n = 1; n != MAX_OPEN_FILES_PER_DRIVE + 1; ++n) + for (file_id_t n = 1; n != MAX_OPEN_FILES_PER_DRIVE + 1; ++n) if (!open_files[n].di_sector) { - if (!try_load_from_path(d, path)) + if (!try_load_from_path(d, path)) { + d->done(d); return 0; + } + d->done(d); open_files[n].di_sector = cur_sect; open_files[n].di_number = cur_dir - (struct directory_entry *)fat_driver_buffer; open_files[n].start_cluster = cur_dir->first_cluster; @@ -226,22 +232,26 @@ static drive_file_id_t fat_get_file(const struct drive *d, const char *path) { panic("Maximum number of files open reached for FAT drive."); } -static void fat_free_file(const struct drive *d, drive_file_id_t fid) { +static void fat_free_file(const struct drive *d, file_id_t fid) { infos[d->drive_id].open_files[fid - 1].di_sector = 0; } -static void fat_load_sector(const struct drive *d, drive_file_id_t fid, uint32_t sector, void *at) { +static void fat_load_sector(const struct drive *d, file_id_t fid, uint32_t sector, void *at) { cur_drive = d; cur_id = d->drive_id; cur_fdi = &infos[cur_id]; + uint16_t c = cur_fdi->open_files[fid - 1].start_cluster; for (uint32_t i = 0; i < sector; ++i) c = next_cluster(c); + + d->ready(d); load_cluster(c, at); + d->done(d); } __attribute__ ((pure)) -static uint32_t fat_get_file_length(const struct drive *d, drive_file_id_t fid) { +static uint32_t fat_get_file_length(const struct drive *d, file_id_t fid) { return infos[d->drive_id].open_files[fid - 1].length; } @@ -288,8 +298,10 @@ static uint32_t enumerate_root(const struct drive *d, struct directory_content_i d->read_sectors(d, sect, 1, entry); } - if (!*(uint8_t *)entry || (info == fill + max)) + if (!*(uint8_t *)entry || (info == fill + max)) { + d->done(d); return fill - info; + } if (entry-> attrib & FA_LABEL) { ++entry; @@ -306,11 +318,15 @@ static uint32_t enumerate_root(const struct drive *d, struct directory_content_i } static uint32_t fat_enumerate_dir(const struct drive *d, const char *path, struct directory_content_info *info, uint32_t max) { + d->ready(d); + if (!*path) return enumerate_root(d, info, max); - if (!try_load_from_path(d, path)) + if (!try_load_from_path(d, path)) { + d->done(d); return 0; + } uint16_t cluster = cur_dir->first_cluster; load_cluster(cluster, fat_driver_buffer); @@ -323,8 +339,10 @@ static uint32_t fat_enumerate_dir(const struct drive *d, const char *path, struc load_cluster(cluster = next_cluster(cluster), fat_driver_buffer); } - if (!*(uint8_t *)entry || (fill == info + max)) + if (!*(uint8_t *)entry || (fill == info + max)) { + d->done(d); return fill - info; + } if (check_fat_names(entry->name, this_dir) || check_fat_names(entry->name, parent_dir)) { ++entry; @@ -341,7 +359,8 @@ static uint32_t fat_enumerate_dir(const struct drive *d, const char *path, struc } void init_fat() { - next_fi = allocate_pages(1); + next_fi = allocate_kernel_pages(1); + next_id = 0; } bool try_fat_init_drive(struct drive *d) { @@ -366,7 +385,7 @@ bool try_fat_init_drive(struct drive *d) { d->fs_id = next_id; infos[next_id].fi = next_fi; - infos[next_id].fat = allocate_pages(((next_fi->sectors_per_fat - 1) >> 3) + 1); + infos[next_id].fat = allocate_kernel_pages(((next_fi->sectors_per_fat - 1) >> 3) + 1); infos[next_id].root_start = next_fi->reserved_sectors + next_fi->sectors_per_fat * next_fi->fats; infos[next_id].data_start = infos[next_id].root_start + @@ -374,7 +393,7 @@ bool try_fat_init_drive(struct drive *d) { d->read_sectors(d, next_fi->reserved_sectors, next_fi->sectors_per_fat, infos[next_id].fat); struct open_file_info *open_files = infos[next_id].open_files - 1; - for (drive_file_id_t i = 0; i < MAX_OPEN_FILES_PER_DRIVE; ++i) + for (file_id_t i = 0; i < MAX_OPEN_FILES_PER_DRIVE; ++i) open_files[i].di_sector = 0; alloc_next_fi(); |