+
+struct ao_file {
+ struct ao_fat_dirent *dirent;
+ offset_t offset;
+ offset_t cluster_offset;
+ cluster_t cluster;
+ uint8_t busy;
+};
+
+#define AO_FAT_NFILE 8
+
+static struct ao_fat_dirent ao_file_dirent[AO_FAT_NFILE];
+
+static struct ao_fat_dirent *
+_ao_fat_file_dirent_alloc(struct ao_fat_dirent *want)
+{
+ int8_t d;
+ struct ao_fat_dirent *free = NULL, *dirent;
+
+ for (d = 0; d < AO_FAT_NFILE; d++) {
+
+ dirent = &ao_file_dirent[d];
+ /* See if there's another user of this file already */
+ if (want && dirent->name[0] != 0) {
+ if (dirent->entry == want->entry)
+ return dirent;
+ } else {
+ if (!free) {
+ free = dirent;
+ if (!want)
+ break;
+ }
+ }
+ }
+ if (free && want)
+ *free = *want;
+ return free;
+}
+
+static struct ao_file ao_file_table[AO_FAT_NFILE];
+
+static int8_t
+_ao_fat_fd_alloc(struct ao_fat_dirent *dirent)
+{
+ int8_t fd;
+
+ for (fd = 0; fd < AO_FAT_NFILE; fd++)
+ if (!ao_file_table[fd].busy) {
+ ao_file_table[fd].dirent = _ao_fat_file_dirent_alloc(dirent);
+ ao_file_table[fd].busy = 1;
+ ao_file_table[fd].offset = 0;
+ ao_file_table[fd].cluster_offset = 0;
+ ao_file_table[fd].cluster = ao_file_table[fd].dirent->cluster;
+
+ return fd;
+ }
+ return -AO_FAT_EMFILE;
+}
+
+static void
+_ao_fat_fd_free(int8_t fd)
+{
+ struct ao_file *file = &ao_file_table[fd];
+ struct ao_fat_dirent *dirent = file->dirent;
+ memset(&ao_file_table[fd], '\0', sizeof (struct ao_file));
+
+ /* Check and see if another ao_file references the same dirent */
+ for (fd = 0; fd < AO_FAT_NFILE; fd++)
+ if (ao_file_table[fd].dirent == dirent)
+ return;
+ memset(dirent, '\0', sizeof (struct ao_fat_dirent));
+}
+
+static struct ao_file *
+_ao_fat_fd_to_file(int8_t fd)
+{
+ struct ao_file *file;
+ if (fd < 0 || AO_FAT_NFILE <= fd)
+ return NULL;
+
+ file = &ao_file_table[fd];
+ if (!file->busy)
+ return NULL;
+ return file;
+}
+
+static uint8_t ao_filesystem_setup;
+static uint8_t ao_filesystem_status;