diff options
author | dzwdz | 2022-08-08 19:37:10 +0200 |
---|---|---|
committer | dzwdz | 2022-08-08 19:37:10 +0200 |
commit | 06415b58cdba12cd6a1a5b06f567d11d584364cc (patch) | |
tree | 13e6864247f81f44056afb053f0fef11af576317 /src/kernel/arch/amd64/driver/pata.c | |
parent | f2703089da21898e9c3127615e98c1717c7ceeb5 (diff) |
driver/ata: separate out from the fsroot driver
Diffstat (limited to 'src/kernel/arch/amd64/driver/pata.c')
-rw-r--r-- | src/kernel/arch/amd64/driver/pata.c | 76 |
1 files changed, 76 insertions, 0 deletions
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; + } +} |