Improve disk driver
diff --git a/src/drivers/disk.c b/src/drivers/disk.c
index df13b5a2..f94e1488 100644
--- a/src/drivers/disk.c
+++ b/src/drivers/disk.c
@@ -7,9 +7,15 @@
#include <lib/mbr.h>
#define SECTOR_SIZE 512
+#define BLOCK_SIZE_IN_SECTORS 16
+#define BLOCK_SIZE (SECTOR_SIZE * BLOCK_SIZE_IN_SECTORS)
+#define BUFFER_SEG 0x7000
+#define BUFFER_OFF 0
+#define BUFFER_ADDR ((uint8_t *)((BUFFER_SEG << 4) + BUFFER_OFF))
-static uint64_t cached_sector = -1;
-static uint8_t sector_buf[512];
+#define CACHE_INVALID (~((uint64_t)0))
+
+static uint64_t cached_block = CACHE_INVALID;
static struct {
uint16_t size;
@@ -17,14 +23,13 @@ static struct {
uint16_t offset;
uint16_t segment;
uint64_t lba;
-} dap = { 16, 1, 0, 0, 0 };
+} dap = { 16, BLOCK_SIZE_IN_SECTORS, BUFFER_OFF, BUFFER_SEG, 0 };
-static int cache_sector(int drive, uint64_t lba) {
- if (lba == cached_sector)
+static int cache_block(int drive, uint64_t block) {
+ if (block == cached_block)
return 0;
- dap.offset = (uint16_t)(size_t)sector_buf;
- dap.lba = lba;
+ dap.lba = block * BLOCK_SIZE_IN_SECTORS;
struct rm_regs r = {0};
r.eax = 0x4200;
@@ -35,25 +40,12 @@ static int cache_sector(int drive, uint64_t lba) {
if (r.eflags & EFLAGS_CF) {
int ah = (r.eax >> 8) & 0xff;
- print("Disk error %x. Drive %x, LBA %x.\n", ah, drive, lba);
+ print("Disk error %x. Drive %x, LBA %x.\n", ah, drive, dap.lba);
+ cached_block = CACHE_INVALID;
return ah;
}
- cached_sector = lba;
-
- return 0;
-}
-
-int read_sector(int drive, void *buffer, uint64_t lba, uint64_t count) {
- while (count--) {
- int ret;
- if ((ret = cache_sector(drive, lba++)))
- return ret;
-
- memcpy(buffer, sector_buf, SECTOR_SIZE);
-
- buffer += SECTOR_SIZE;
- }
+ cached_block = block;
return 0;
}
@@ -61,30 +53,24 @@ int read_sector(int drive, void *buffer, uint64_t lba, uint64_t count) {
int read(int drive, void *buffer, uint64_t loc, uint64_t count) {
uint64_t progress = 0;
while (progress < count) {
- uint64_t sect = (loc + progress) / SECTOR_SIZE;
+ uint64_t block = (loc + progress) / BLOCK_SIZE;
int ret;
- if ((ret = cache_sector(drive, sect)))
+ if ((ret = cache_block(drive, block)))
return ret;
uint64_t chunk = count - progress;
- uint64_t offset = (loc + progress) % SECTOR_SIZE;
- if (chunk > SECTOR_SIZE - offset)
- chunk = SECTOR_SIZE - offset;
+ uint64_t offset = (loc + progress) % BLOCK_SIZE;
+ if (chunk > BLOCK_SIZE - offset)
+ chunk = BLOCK_SIZE - offset;
- memcpy(buffer + progress, §or_buf[offset], chunk);
+ memcpy(buffer + progress, &BUFFER_ADDR[offset], chunk);
progress += chunk;
}
return 0;
}
-int read_partition(int drive, int partition, void *buffer, uint64_t loc, uint64_t count) {
- struct mbr_part part;
- int ret = mbr_get_part(&part, drive, partition);
- if (ret) {
- return ret;
- }
-
- return read(drive, buffer, loc + (part.first_sect * 512), count);
+int read_partition(int drive, struct mbr_part *part, void *buffer, uint64_t loc, uint64_t count) {
+ return read(drive, buffer, loc + (part->first_sect * 512), count);
}
diff --git a/src/drivers/disk.h b/src/drivers/disk.h
index 4bce1fb1..e6ed913a 100644
--- a/src/drivers/disk.h
+++ b/src/drivers/disk.h
@@ -1,11 +1,11 @@
-#ifndef __DISK_H__
-#define __DISK_H__
+#ifndef __DRIVERS__DISK_H__
+#define __DRIVERS__DISK_H__
#include <stddef.h>
#include <stdint.h>
+#include <lib/mbr.h>
-int read_sector(int drive, void *buffer, uint64_t lba, uint64_t count);
int read(int drive, void *buffer, uint64_t loc, uint64_t count);
-int read_partition(int drive, int partition, void *buffer, uint64_t loc, uint64_t count);
+int read_partition(int drive, struct mbr_part *part, void *buffer, uint64_t loc, uint64_t count);
#endif
diff --git a/src/fs/echfs.c b/src/fs/echfs.c
index 1bbf85f7..20c1491f 100644
--- a/src/fs/echfs.c
+++ b/src/fs/echfs.c
@@ -31,8 +31,11 @@ struct echfs_dir_entry {
#define FILE_TYPE 0
int load_echfs_file(int disk, int partition, void *buffer, const char *filename) {
+ struct mbr_part mbr_part;
+ mbr_get_part(&mbr_part, disk, partition);
+
struct echfs_identity_table id_table;
- read_partition(disk, partition, &id_table, 0, sizeof(struct echfs_identity_table));
+ read_partition(disk, &mbr_part, &id_table, 0, sizeof(struct echfs_identity_table));
if (strncmp(id_table.signature, "_ECH_FS_", 8)) {
print("echfs: signature invalid\n", filename);
@@ -49,7 +52,7 @@ int load_echfs_file(int disk, int partition, void *buffer, const char *filename)
// Find the file in the root dir.
struct echfs_dir_entry entry;
for (uint64_t i = 0; i < dir_length; i += sizeof(struct echfs_dir_entry)) {
- read_partition(disk, partition, &entry, i + dir_offset, sizeof(struct echfs_dir_entry));
+ read_partition(disk, &mbr_part, &entry, i + dir_offset, sizeof(struct echfs_dir_entry));
if (!entry.parent_id) {
break;
@@ -67,11 +70,11 @@ found:;
// Load the file.
for (uint64_t i = entry.payload; i != END_OF_CHAIN;) {
// Read block.
- read_partition(disk, partition, buffer, i * block_size, block_size);
+ read_partition(disk, &mbr_part, buffer, i * block_size, block_size);
buffer += block_size;
// Read the next block.
- read_partition(disk, partition, &i, alloc_table_offset + i * sizeof(uint64_t), sizeof(uint64_t));
+ read_partition(disk, &mbr_part, &i, alloc_table_offset + i * sizeof(uint64_t), sizeof(uint64_t));
}
return 0;
diff --git a/src/fs/echfs.h b/src/fs/echfs.h
index 1132ecd5..7323e470 100644
--- a/src/fs/echfs.h
+++ b/src/fs/echfs.h
@@ -1,5 +1,5 @@
-#ifndef __ECHFS_H__
-#define __ECHFS_H__
+#ifndef __FS__ECHFS_H__
+#define __FS__ECHFS_H__
int load_echfs_file(int disk, int partition, void *buffer, const char *filename);
