diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/kernel/arch/amd64/ata.c | 3 | ||||
-rw-r--r-- | src/kernel/arch/amd64/boot.c | 4 | ||||
-rw-r--r-- | src/kernel/arch/amd64/driver/fsroot.c | 89 | ||||
-rw-r--r-- | src/kernel/arch/amd64/driver/pata.c | 76 | ||||
-rw-r--r-- | src/kernel/arch/amd64/driver/pata.h | 3 |
5 files changed, 98 insertions, 77 deletions
diff --git a/src/kernel/arch/amd64/ata.c b/src/kernel/arch/amd64/ata.c index 371730e..5c5fc57 100644 --- a/src/kernel/arch/amd64/ata.c +++ b/src/kernel/arch/amd64/ata.c @@ -125,7 +125,8 @@ bool ata_available(int drive) { } int ata_read(int drive, uint32_t lba, void *buf) { - assert(ata_drives[drive].type == DEV_PATA); + if (ata_drives[drive].type != DEV_PATA) + panic_unimplemented(); int iobase = ata_iobase(drive); ata_driveselect(drive, lba); diff --git a/src/kernel/arch/amd64/boot.c b/src/kernel/arch/amd64/boot.c index 2347df4..1041c7d 100644 --- a/src/kernel/arch/amd64/boot.c +++ b/src/kernel/arch/amd64/boot.c @@ -1,6 +1,6 @@ -#include <kernel/arch/amd64/ata.h> #include <kernel/arch/amd64/boot.h> #include <kernel/arch/amd64/driver/fsroot.h> +#include <kernel/arch/amd64/driver/pata.h> #include <kernel/arch/amd64/driver/ps2.h> #include <kernel/arch/amd64/driver/serial.h> #include <kernel/arch/amd64/driver/video.h> @@ -47,7 +47,7 @@ void kmain_early(struct multiboot_info *multiboot) { serial_init(); kprintf("ata...\n"); - ata_init(); + pata_init(); vid.b = (void*)multiboot->framebuffer_addr; vid.pitch = multiboot->framebuffer_pitch; diff --git a/src/kernel/arch/amd64/driver/fsroot.c b/src/kernel/arch/amd64/driver/fsroot.c index 882fe91..7856fba 100644 --- a/src/kernel/arch/amd64/driver/fsroot.c +++ b/src/kernel/arch/amd64/driver/fsroot.c @@ -1,95 +1,36 @@ #include <camellia/errno.h> #include <camellia/fsutil.h> -#include <kernel/arch/amd64/ata.h> #include <kernel/arch/amd64/driver/fsroot.h> #include <kernel/arch/amd64/driver/util.h> -#include <kernel/mem/virt.h> #include <kernel/panic.h> -#include <kernel/proc.h> #include <kernel/util.h> +#include <kernel/vfs/request.h> #include <shared/mem.h> -#include <stdbool.h> - -enum { - HANDLE_ROOT, - HANDLE_ATA_ROOT, - HANDLE_ATA, - _SKIP = HANDLE_ATA + 4, -}; - -static bool exacteq(struct vfs_request *req, const char *str) { - size_t len = strlen(str); - assert(req->input.kern); - return req->input.len == len && !memcmp(req->input.buf_kern, str, len); -} static int handle(struct vfs_request *req) { - assert(req->caller); - int id = (int)(long __force)req->id; + // TODO document directory read format + // TODO don't hardcode + const char dir[] = + "com1\0" + "ps2/\0" + "ata/\0" + "video/"; + if (!req->caller) return -1; switch (req->type) { case VFSOP_OPEN: - if (exacteq(req, "/")) return HANDLE_ROOT; - if (exacteq(req, "/ata/")) return HANDLE_ATA_ROOT; - if (exacteq(req, "/ata/0")) - return ata_available(0) ? HANDLE_ATA+0 : -1; - if (exacteq(req, "/ata/1")) - return ata_available(1) ? HANDLE_ATA+1 : -1; - if (exacteq(req, "/ata/2")) - return ata_available(2) ? HANDLE_ATA+2 : -1; - if (exacteq(req, "/ata/3")) - return ata_available(3) ? HANDLE_ATA+3 : -1; - - return -1; + return req->input.len == 1 ? 0 : -1; case VFSOP_READ: - switch (id) { - case HANDLE_ROOT: { - // TODO document directory read format - // TODO don't hardcode - const char src[] = - "com1\0" - "ps2/\0" - "ata/\0" - "video/"; - return req_readcopy(req, src, sizeof src); - } - case HANDLE_ATA_ROOT: { - char list[8] = {}; - size_t len = 0; - for (int i = 0; i < 4; i++) { - if (ata_available(i)) { - list[len] = '0' + i; - len += 2; - } - } - return req_readcopy(req, list, len); - } - case HANDLE_ATA: case HANDLE_ATA+1: - case HANDLE_ATA+2: case HANDLE_ATA+3: - if (req->offset < 0) return -1; - char buf[512]; - uint32_t sector = req->offset / 512; - size_t len = min(req->output.len, 512 - ((size_t)req->offset & 511)); - ata_read(id - HANDLE_ATA, sector, buf); - virt_cpy_to(req->caller->pages, req->output.buf, buf, len); - return len; - default: panic_invalid_state(); - } - - case VFSOP_CLOSE: return 0; - // TODO getsize for kernel provided directories - case VFSOP_GETSIZE: return -ENOSYS; + return req_readcopy(req, dir, sizeof dir); - default: panic_invalid_state(); + // TODO getsize for the other kernel provided directories + case VFSOP_GETSIZE: return sizeof dir; + default: return 0; } } static void accept(struct vfs_request *req) { - if (req->caller) { - vfsreq_finish_short(req, handle(req)); - } else { - vfsreq_finish_short(req, -1); - } + vfsreq_finish_short(req, handle(req)); } static struct vfs_backend backend = BACKEND_KERN(accept); diff --git a/src/kernel/arch/amd64/driver/pata.c b/src/kernel/arch/amd64/driver/pata.c new file mode 100644 index 0000000..a21fc2b --- /dev/null +++ b/src/kernel/arch/amd64/driver/pata.c @@ -0,0 +1,76 @@ +#include <camellia/errno.h> +#include <kernel/arch/amd64/ata.h> +#include <kernel/arch/amd64/driver/pata.h> +#include <kernel/arch/amd64/driver/util.h> +#include <kernel/mem/virt.h> +#include <kernel/panic.h> +#include <kernel/vfs/request.h> +#include <shared/mem.h> + +const int root_id = 100; + +static void accept(struct vfs_request *req); +static struct vfs_backend backend = BACKEND_KERN(accept); + +void pata_init(void) { + ata_init(); + vfs_mount_root_register("/ata", &backend); +} + + +static bool exacteq(struct vfs_request *req, const char *str) { + size_t len = strlen(str); + assert(req->input.kern); + return req->input.len == len && !memcmp(req->input.buf_kern, str, len); +} + +static void accept(struct vfs_request *req) { + int ret; + long id = (long __force)req->id; + switch (req->type) { + case VFSOP_OPEN: + if (!req->input.kern) panic_invalid_state(); + ret = -ENOENT; + if (exacteq(req, "/")) ret = root_id; + else if (exacteq(req, "/0")) ret = 0; + else if (exacteq(req, "/1")) ret = 1; + else if (exacteq(req, "/2")) ret = 2; + else if (exacteq(req, "/3")) ret = 3; + vfsreq_finish_short(req, ret); + break; + + case VFSOP_READ: + if (id == root_id) { + // TODO use dirbuild + char list[8] = {}; + size_t len = 0; + for (int i = 0; i < 4; i++) { + if (ata_available(i)) { + list[len] = '0' + i; + len += 2; + } + } + vfsreq_finish_short(req, req_readcopy(req, list, len)); + break; + } + // TODO ata size get + if (req->offset < 0) { + vfsreq_finish_short(req, -ENOSYS); + break; + } + char buf[512]; /* stupid */ + uint32_t sector = req->offset / 512; + size_t len = min(req->output.len, 512 - ((size_t)req->offset & 511)); + ata_read(id, sector, buf); + virt_cpy_to(req->caller->pages, req->output.buf, buf, len); + vfsreq_finish_short(req, len); + break; + + case VFSOP_WRITE: + panic_unimplemented(); + + default: + vfsreq_finish_short(req, -ENOSYS); + break; + } +} diff --git a/src/kernel/arch/amd64/driver/pata.h b/src/kernel/arch/amd64/driver/pata.h new file mode 100644 index 0000000..f74712b --- /dev/null +++ b/src/kernel/arch/amd64/driver/pata.h @@ -0,0 +1,3 @@ +#pragma once + +void pata_init(void); |