summaryrefslogtreecommitdiff
path: root/src/kernel/fat.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/fat.c')
-rw-r--r--src/kernel/fat.c53
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();