summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile3
-rw-r--r--include/kernel/fs.h15
-rw-r--r--include/kernel/hd.h6
-rw-r--r--kernel/boot.s2
-rw-r--r--kernel/fs/block.c9
-rw-r--r--kernel/fs/buffer.c82
-rw-r--r--kernel/fs/fs.c5
-rw-r--r--kernel/fs/mount.c6
-rw-r--r--kernel/hd.c41
9 files changed, 132 insertions, 37 deletions
diff --git a/Makefile b/Makefile
index 391597f..0d62a8f 100644
--- a/Makefile
+++ b/Makefile
@@ -21,7 +21,8 @@ clean:
rm -f $(TARGET)
run: $(TARGET)
- qemu-system-x86_64 -s -kernel $(TARGET) -drive file=hd.img,format=raw -serial stdio
+ #qemu-system-x86_64 -s -kernel $(TARGET) -drive file=hd.img,format=raw -serial stdio
+ qemu-system-x86_64 -s -kernel $(TARGET)
#qemu-system-x86_64 -s -S -kernel $(TARGET) -drive file=hd.img,format=raw
.FORCE:
diff --git a/include/kernel/fs.h b/include/kernel/fs.h
index a752ddf..4ec4de1 100644
--- a/include/kernel/fs.h
+++ b/include/kernel/fs.h
@@ -50,13 +50,24 @@ struct m_inode {
uint16_t i_zone[9];
} __attribute__((packed));
+struct buffer {
+ void *b_data;
+ uint16_t b_device;
+ uint16_t b_block;
+ struct buffer *b_next;
+ struct buffer *b_prev;
+} __attribute__((packed));
+
extern struct super_block sblocks[NRSUPER];
-size_t block_read(void*, size_t , size_t);
-size_t block_write(void*, size_t , size_t);
+int block_read(void*, size_t);
+int block_write(void*, size_t);
void mount_root(void);
void fs_init(void);
+/* various init functions called by fs_init() */
+void buffer_init(void);
+
#endif
diff --git a/include/kernel/hd.h b/include/kernel/hd.h
index 7244c92..d4cf2e4 100644
--- a/include/kernel/hd.h
+++ b/include/kernel/hd.h
@@ -3,9 +3,9 @@
#include <sys/types.h>
-void hd_init(void);
+int hd_init(void);
-size_t hd_read_block(void*, size_t , size_t);
-size_t hd_write_block(void*, size_t , size_t);
+int hd_read_block(void*, size_t);
+int hd_write_block(void*, size_t);
#endif
diff --git a/kernel/boot.s b/kernel/boot.s
index 5050705..4db2cf7 100644
--- a/kernel/boot.s
+++ b/kernel/boot.s
@@ -40,7 +40,7 @@ kboot:
call flush_idt
; initialize the console
call con_init
- ; add this point, we can display *some* output
+ ; at this point, we can display *some* output
push .msg
call printk
add esp, 4
diff --git a/kernel/fs/block.c b/kernel/fs/block.c
index b3f7386..caf97d2 100644
--- a/kernel/fs/block.c
+++ b/kernel/fs/block.c
@@ -1,10 +1,9 @@
-#include <kernel/hd.h>
#include <sys/types.h>
-size_t block_read(void *buf, size_t block, size_t len) {
- return hd_read_block(buf, block, len);
+int block_read(void *buf, size_t block) {
+ return -1;
}
-size_t block_write(void *buf, size_t block, size_t len) {
- return hd_write_block(buf, block, len);
+int block_write(void *buf, size_t block) {
+ return -1;
}
diff --git a/kernel/fs/buffer.c b/kernel/fs/buffer.c
new file mode 100644
index 0000000..7405738
--- /dev/null
+++ b/kernel/fs/buffer.c
@@ -0,0 +1,82 @@
+#include <kernel/con.h>
+#include <kernel/fs.h>
+#include <stdint.h>
+#include <string.h>
+
+/* memory dedicated to the block cache */
+#define BSTART 0x80000
+#define BEND 0xA0000
+
+static struct buffer *lru;
+static struct buffer *mru;
+
+struct buffer *buffer_get_block(uint16_t device, uint16_t block);
+
+void buffer_init(void) {
+ int c = 0;
+ struct buffer *last = NULL;
+ struct buffer *b = (struct buffer*) BSTART;
+ void *d = (void*) (BEND - BLOCK_SIZE);
+
+ while(d > (void*) b) {
+ memset(b, 0, sizeof(struct buffer));
+
+ b->b_data = d;
+ b->b_prev = last;
+
+ if(last)
+ last->b_next = b;
+
+ last = b;
+
+ b = (struct buffer*) ((void*) b + sizeof(struct buffer));
+ d = (void*) (d - (void*) BLOCK_SIZE);
+
+ c++;
+ }
+
+ lru = (struct buffer*) BSTART;
+ mru = last;
+
+ printk("[buf] Buffers initialized (0x%x buffers in pool)\n", c);
+}
+
+struct buffer *buffer_get_block(uint16_t device, uint16_t block) {
+ int ret;
+ struct buffer **p = &mru;
+ struct buffer *b;
+
+ /* check if the requested block is already in the cache */
+ while(*p) {
+ if((*p)->b_device == device && (*p)->b_block == block) {
+ /* put the buffer back at the MRU end of the list */
+ (*p)->b_next = NULL;
+ (*p)->b_prev = mru;
+ mru = *p;
+ return *p;
+ }
+ p = &(*p)->b_prev;
+ }
+
+ /* find a buffer at the end of the LRU list */
+ b = lru;
+ lru = lru->b_next;
+ lru->b_prev = NULL;
+ ret = block_read(b->b_data, block);
+ /* abort if we failed to read in the block */
+ if(ret < 0) {
+ /* release the allocated buffer to the pool */
+ lru->b_prev = b;
+ b->b_next = lru;
+ b->b_prev = NULL;
+ lru = b;
+ return NULL;
+ }
+ b->b_device = device;
+ b->b_block = block;
+ /* put the buffer back at the MRU end of the list */
+ b->b_next = NULL;
+ b->b_prev = mru;
+ mru = b;
+ return b;
+}
diff --git a/kernel/fs/fs.c b/kernel/fs/fs.c
index 792668e..e0d9205 100644
--- a/kernel/fs/fs.c
+++ b/kernel/fs/fs.c
@@ -1,6 +1,5 @@
#include <kernel/con.h>
#include <kernel/fs.h>
-#include <kernel/hd.h>
#include <kernel/kernel.h>
#include <kernel/sched.h>
#include <kernel/tty.h>
@@ -22,7 +21,9 @@ void fs_init(void) {
memset(&sblocks, 0, sizeof(sblocks));
memset(&ftable, 0, sizeof(ftable));
- hd_init();
+ buffer_init();
+
+ /* hd_init(); */
mount_root();
}
diff --git a/kernel/fs/mount.c b/kernel/fs/mount.c
index 47911fb..9cdf49b 100644
--- a/kernel/fs/mount.c
+++ b/kernel/fs/mount.c
@@ -6,12 +6,12 @@
struct super_block sblocks[NRSUPER];
void mount_root(void) {
- size_t ret;
+ int ret;
char buf[BLOCK_SIZE];
struct super_block *s = (void*) buf;
- ret = block_read(buf, 1, 1);
- if(ret < 1) {
+ ret = block_read(buf, 1);
+ if(ret < 0) {
printk("[fs] Failed to read super block\n");
return;
}
diff --git a/kernel/hd.c b/kernel/hd.c
index 3b2aa3c..2f680d1 100644
--- a/kernel/hd.c
+++ b/kernel/hd.c
@@ -102,53 +102,53 @@ static int write_sect(void *buf, uint32_t lba) {
return 0;
}
-size_t hd_read_block(void *buf, size_t block, size_t len) {
+int hd_read_block(void *buf, size_t block) {
int ret;
size_t i;
uint32_t s = SECTS(block);
- uint32_t e = SECTS(block + len);
+ uint32_t e = SECTS(block + 1);
- if(s > nblocks - 1)
- s = nblocks - 1;
- if(e > nblocks - 1)
- e = nblocks - 1;
+ if(nblocks <= s)
+ return -1;
+ if(nblocks <= e)
+ return -1;
for(i = 0; i < (e - s); i++) {
ret = read_sect(buf, i + s);
if(ret < 0)
- return BLOCKS(i);
+ return -1;
buf = ((char*) buf + 512);
}
- return len;
+ return 0;
}
-size_t hd_write_block(void *buf, size_t block, size_t len) {
+int hd_write_block(void *buf, size_t block) {
int ret;
size_t i;
uint32_t s = SECTS(block);
- uint32_t e = SECTS(block + len);
+ uint32_t e = SECTS(block + 1);
- if(s > nblocks - 1)
- s = nblocks - 1;
- if(e > nblocks - 1)
- e = nblocks - 1;
+ if(nblocks <= s)
+ return -1;
+ if(nblocks <= e)
+ return -1;
for(i = 0; i < (e - s); i++) {
ret = write_sect(buf, i + s);
if(ret < 0)
- return BLOCKS(i);
+ return -1;
buf = ((char*) buf + 512);
}
- return len;
+ return 0;
}
-void hd_init(void) {
+int hd_init(void) {
int i;
uint8_t s;
uint16_t *buf = (uint16_t*) sbuf;
@@ -162,13 +162,13 @@ void hd_init(void) {
s = inb(0x1F7);
if(!s) {
printk("[hd] Master drive not detected on primary bus!\n");
- return;
+ return -1;
}
if(s & ST_ERR) {
if(!inb(0x1F4) && !inb(0x1F5))
continue;
printk("[hd] IDENTIFY command error!\n");
- return;
+ return -1;
}
if(s & ST_DRQ && !(s & ST_ERR))
break;
@@ -180,8 +180,9 @@ void hd_init(void) {
nblocks = *((uint32_t*) &buf[60]);
if(!nblocks) {
printk("[hd] Drive does not support LBA28 addressing!\n");
- return;
+ return -1;
}
printk("[hd] Primary bus master drive initialized! (status: 0x%02x, nsects: 0x%01x)\n", s, nblocks);
+ return 0;
}