From 2ddbeb9f7214f6d3feef651eba83e6a9d120a743 Mon Sep 17 00:00:00 2001 From: Benji Dial Date: Thu, 13 Aug 2020 17:58:50 -0400 Subject: lots of progress, including readonly PATA driver and part of FAT16 driver --- src/kernel/fat.c | 70 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 28 deletions(-) (limited to 'src/kernel/fat.c') diff --git a/src/kernel/fat.c b/src/kernel/fat.c index 087d79e..807af00 100644 --- a/src/kernel/fat.c +++ b/src/kernel/fat.c @@ -1,9 +1,9 @@ -#include "fat.h" -#include "ata.h" -#include "panic.h" #include "drive.h" -#include "mem.h" +#include "panic.h" #include "util.h" +#include "ata.h" +#include "fat.h" +#include "mem.h" #define MAX_FAT_DRIVES 16 #define MAX_OPEN_FILES_PER_DRIVE 32 @@ -57,20 +57,19 @@ struct fat_info { uint8_t fs_type[8]; } __attribute__ ((packed)); -#define CTOS(c, fi) ((fi)->reserved_sectors + (fi)->sectors_per_fat * (fi)->fats + ((fi)->root_entries >> 4) + (c) - 2) +#define CTOS(c, fdi) ((fdi)->data_start + (c) - 2) struct fat_drive_info { - struct fat_info *fi; + const struct fat_info *fi; uint16_t *fat; + uint16_t root_start; + uint16_t data_start; struct directory_entry open_files[MAX_OPEN_FILES_PER_DRIVE]; }; struct fat_drive_info infos[MAX_FAT_DRIVES]; uint8_t next_id = 0; -#define FI(n) ((struct fat_info *)(infos[n].fi + 3)) -#define FN(n, f) (infos[n].open_files[f - 1]) - uint8_t fat_driver_buffer[512]; struct fat_info *next_fi; @@ -80,8 +79,9 @@ void alloc_next_fi() { panic("Out of memory in FAT driver."); } -struct drive *cur_drive; +const struct drive *cur_drive; fs_id_t cur_id; +const struct fat_drive_info *cur_fdi; struct directory_entry *cur_dir; //loads cluster `c` @@ -91,7 +91,7 @@ void load_cluster(uint16_t c, void *to) { return; } - uint32_t s = CTOS(c, FI(cur_id)); + uint32_t s = CTOS(c, cur_fdi); cur_drive->read_sectors(cur_drive, s, 1, to); } @@ -99,7 +99,7 @@ uint16_t next_cluster(uint16_t c) { panic("TODO: compute next sector (or 0 for none)"); } -static inline bool check_fat_names(uint8_t *a, uint8_t *b) { +static inline bool check_fat_names(const uint8_t *a, const uint8_t *b) { return (((uint32_t *)a)[0] == ((uint32_t *)b)[0]) && (((uint32_t *)a)[1] == ((uint32_t *)b)[1]) && (((uint16_t *)a)[8] == ((uint16_t *)b)[8]) && @@ -107,8 +107,8 @@ static inline bool check_fat_names(uint8_t *a, uint8_t *b) { } //after: cur_dir -> specified entry in root -bool try_locate_root_entry(uint8_t *fat_name) { - uint32_t cur_dir_sect = FI(cur_id)->reserved_sectors + FI(cur_id)->sectors_per_fat * FI(cur_id)->fats - 1; +bool try_locate_root_entry(const uint8_t *fat_name) { + uint32_t cur_dir_sect = cur_fdi->root_start - 1; cur_dir = (struct directory_entry *)(fat_driver_buffer + 512); while (true) { if (cur_dir == (struct directory_entry *)(fat_driver_buffer + 512)) { @@ -127,7 +127,7 @@ bool try_locate_root_entry(uint8_t *fat_name) { //before: cur_dir -> entry of dir to search //after: cur_dir -> specified entry in dir -bool try_locate_entry(uint8_t *fat_name) { +bool try_locate_entry(const uint8_t *fat_name) { uint16_t cur_dir_cluster = cur_dir->first_cluster; load_cluster(cur_dir_cluster, fat_driver_buffer); cur_dir = (struct directory_entry *)fat_driver_buffer; @@ -146,32 +146,41 @@ bool try_locate_entry(uint8_t *fat_name) { } } -drive_file_id_t fat_get_file(struct drive *d, char *path) { +drive_file_id_t fat_get_file(const struct drive *d, const char *path) { cur_drive = d; cur_id = d->drive_id; + cur_fdi = &infos[cur_id]; + const struct directory_entry *open_files = cur_fdi->open_files - 1; for (drive_file_id_t n = 1; n != MAX_OPEN_FILES_PER_DRIVE + 1; ++n) - if (!*(uint8_t *)(&FN(d->drive_id, n))) { - panic("TODO: open path at FN(id, n)"); + if (!*(uint8_t *)(&open_files[n])) { + panic("TODO: open path into open_files[n]"); return n; } panic("Maximum number of files open reached for FAT drive."); } -void fat_free_file(struct drive *d, drive_file_id_t fid) { - *(uint8_t *)(&FN(d->drive_id, fid)) = 0; +void fat_free_file(const struct drive *d, drive_file_id_t fid) { + *(uint8_t *)(&infos[d->drive_id].open_files[fid - 1]) = 0; } -void fat_load_sector(struct drive *d, drive_file_id_t fid, uint32_t sector, void *at) { +void fat_load_sector(const struct drive *d, drive_file_id_t fid, uint32_t sector, void *at) { cur_drive = d; cur_id = d->drive_id; - uint16_t c = FN(d->drive_id, fid).first_cluster; + cur_fdi = &infos[cur_id]; + uint16_t c = cur_fdi->open_files[fid - 1].first_cluster; for (uint32_t i = 0; i < sector; ++i) c = next_cluster(c); load_cluster(c, at); } -uint32_t fat_get_free_sectors(struct drive *d) { - panic("TODO: get free sectors of drive"); +__attribute__ ((pure)) uint32_t fat_get_free_sectors(const struct drive *d) { + uint16_t *start = infos[d->fs_id].fat + 2; + uint16_t *end = start + d->n_sectors - infos[d->fs_id].data_start; + uint32_t count = 0; + for (uint16_t *i = start; i < end; ++i) + if (!*i) + ++count; + return count; } void init_fat() { @@ -186,8 +195,8 @@ bool try_fat_init_drive(struct drive *d) { return false; memcpy(next_fi, fat_driver_buffer + 3, sizeof(struct fat_info)); uint32_t *fs_type_32 = (uint32_t *)next_fi->fs_type; - if ((fs_type_32[0] != ('F' + 'A' * 256 + 'T' + 65536 + '1' * 16777216)) || - (fs_type_32[1] != ('6' + ' ' * 256 + ' ' + 65536 + ' ' * 16777216))) + if ((fs_type_32[0] != ('F' + 'A' * 256 + 'T' * 65536 + '1' * 16777216)) || + (fs_type_32[1] != ('6' + ' ' * 256 + ' ' * 65536 + ' ' * 16777216))) return false; d->fs_type = "FAT16"; @@ -199,10 +208,15 @@ 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); - for (drive_file_id_t i = 0; i < MAX_OPEN_FILES_PER_DRIVE; ++i) - *(uint8_t *)&FN(next_id, i) = 0; + 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 + + ((next_fi->root_entries - 1) >> 4) + 1; d->read_sectors(d, next_fi->reserved_sectors, next_fi->sectors_per_fat, infos[next_id].fat); + struct directory_entry *open_files = infos[next_id].open_files - 1; + for (drive_file_id_t i = 0; i < MAX_OPEN_FILES_PER_DRIVE; ++i) + *(uint8_t *)&open_files[i] = 0; alloc_next_fi(); ++next_id; -- cgit v1.2.3