diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/boot.s | 2 | ||||
| -rw-r--r-- | kernel/fs/block.c | 9 | ||||
| -rw-r--r-- | kernel/fs/buffer.c | 82 | ||||
| -rw-r--r-- | kernel/fs/fs.c | 5 | ||||
| -rw-r--r-- | kernel/fs/mount.c | 6 | ||||
| -rw-r--r-- | kernel/hd.c | 41 |
6 files changed, 114 insertions, 31 deletions
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; } |
