aboutsummaryrefslogtreecommitdiff
path: root/src/kernel/fs/marfs/sectorlevel.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/fs/marfs/sectorlevel.c')
-rw-r--r--src/kernel/fs/marfs/sectorlevel.c101
1 files changed, 101 insertions, 0 deletions
diff --git a/src/kernel/fs/marfs/sectorlevel.c b/src/kernel/fs/marfs/sectorlevel.c
new file mode 100644
index 0000000..7575f8c
--- /dev/null
+++ b/src/kernel/fs/marfs/sectorlevel.c
@@ -0,0 +1,101 @@
+#include <stdint.h>
+#include <kernel/lib/alloc.h>
+#include <kernel/fs/ata_pio.h>
+#include "marfs.h"
+
+uint8_t marfs_init(struct ATA_INTERFACE *_iface) {
+ iface = _iface;
+ uint16_t identifydata[256 * 2];
+ uint8_t ret = ATA_identify(iface, identifydata);
+ maxLBA = (identifydata[61] << 16) + identifydata[60];
+ return ret;
+}
+
+uint32_t marfs_get_max_lba(void) { return maxLBA; }
+
+uint8_t marfs_write_mbr(uint8_t *mbr) {
+ return ATA_write28(iface, 0, mbr);
+}
+
+struct marfs_SUPERBLOCK *marfs_read_superblock() {
+ struct marfs_SUPERBLOCK *p = (struct marfs_SUPERBLOCK *) ATA_read28(iface, 1);
+ sb_cache = *p;
+ return p;
+}
+
+uint8_t marfs_writeSB(struct marfs_SUPERBLOCK *sb) {
+ sb_cache = *sb;
+ return ATA_write28(iface, 1, (uint8_t *) sb);
+}
+
+uint32_t marfs_get_free_lba_block(void) {
+ uint32_t offset = 2 + sb_cache.s_first_chunk;
+ uint8_t *p = 0;
+ for (uint32_t i = 0; i < sb_cache.n_chunks; i++) {
+ p = ATA_read28(iface, offset);
+ if (!(*p & 0x80)) break;
+ kfree(p);
+ offset += 512;
+ }
+
+ offset++;
+ for (uint16_t i = 1; i < 512; i++) {
+ if (!p[i]) break;
+ offset++;
+ }
+ kfree(p);
+
+ ATA_clear28(iface, offset);
+
+ return offset;
+}
+
+static uint8_t marfs_mark_block(uint32_t lba_sector, uint8_t mode) {
+ lba_sector -= 2;
+ lba_sector -= sb_cache.s_first_chunk;
+ uint16_t block_in_chunk = lba_sector % 512;
+ lba_sector /= 512;
+ lba_sector = 2 + sb_cache.s_first_chunk + (512 * lba_sector);
+
+ uint8_t *p = ATA_read28(iface, lba_sector);
+ p[block_in_chunk] = mode;
+
+ if (mode == 0) {
+ p[0] = 0;
+ } else {
+ uint8_t full_chunk = 1;
+ for (uint16_t i = 1; i < 512; i++) {
+ if (!p[i]) {
+ full_chunk = 0;
+ break;
+ }
+ }
+ p[0] = full_chunk;
+ }
+
+ uint8_t ret = ATA_write28(iface, lba_sector, p);
+ kfree(p);
+ return ret;
+}
+
+uint8_t marfs_mark_block_as_free(uint32_t lba_sector) { return marfs_mark_block(lba_sector, 0); }
+
+uint8_t marfs_mark_block_as_used(uint32_t lba_sector) { return marfs_mark_block(lba_sector, 1); }
+
+uint32_t marfs_get_free_lba_inode(void) {
+ uint32_t offset;
+ for (offset = 2; offset < 2 + sb_cache.n_inodes; offset++) {
+ struct marfs_INODE *inode = (struct marfs_INODE *) ATA_read28(iface, offset);
+ uint8_t used = inode->isUsed;
+ kfree(inode);
+ if (!used) break;
+ }
+ return offset;
+}
+
+void marfs_mark_inode_as_free(uint32_t lba_sector) {
+ struct marfs_INODE *inode = (struct marfs_INODE *) ATA_read28(iface, lba_sector);
+ inode->isUsed = 0;
+ ATA_write28(iface, lba_sector, (uint8_t *) inode);
+ kfree(inode);
+} \ No newline at end of file