From 164f56ca57439229cda9c5cd94066faa79a2a4b4 Mon Sep 17 00:00:00 2001 From: uosfz Date: Wed, 3 Jun 2026 22:17:23 +0200 Subject: [PATCH] move most of virtio-blk example outside main --- Makefile | 1 + src/kernel.c | 105 ++++------------------------------ src/virtio-block-example.c | 113 +++++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+), 94 deletions(-) create mode 100644 src/virtio-block-example.c diff --git a/Makefile b/Makefile index 0dbd90a..7813b23 100644 --- a/Makefile +++ b/Makefile @@ -65,6 +65,7 @@ KERNEL_SOURCES := \ src/tlsf.c \ src/virtio-common.c \ src/virtio-block.c \ + src/virtio-block-example.c \ $(KERNEL_SOURCES_$(ARCH)) \ # end of kernel sources list diff --git a/src/kernel.c b/src/kernel.c index 7469228..c837f1b 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -65,72 +65,6 @@ void _start() { } } -void mycb(struct blk_req req, void* userdata) { - char *type = NULL; - switch (req.type) { - case BLK_REQ_READ: type = "READ"; break; - case BLK_REQ_WRITE: type = "WRITE"; break; - case BLK_REQ_FLUSH: type = "FLUSH"; break; - } - if (req.type == BLK_REQ_FLUSH) { - printlinef("%s done.", type); - } else { - uint8_t *p = pa_to_pointer(req.data); - printlinef("%s done: %u sectors starting at %u", type, req.num_sectors, req.sector); - for (int i = 0; i < req.num_sectors; i++) { - printlinef("sector %u: %X8 %X8 %X8 %X8 ...", req.sector + i, - p[512*i], p[512*i + 1], p[512*i + 2], p[512*i + 3] - ); - } - } - slab_cache_free(pa_to_pointer(req.data)); -} - -struct slab_cache sector_cache; -struct cache_entry { - bool used; - bool done; - uint64_t bno; - struct pa data; -} re1, re2; - -void get_block_done(struct blk_req req, void* userdata) { - struct cache_entry *entry = userdata; - entry->done = true; -} -uint8_t *get_block(uint64_t bno,void *cbdata) { - struct virtio_blk_context *ctx = cbdata; - struct pa data = pa_from_pointer(slab_cache_alloc(§or_cache)); - volatile struct cache_entry *entry; - if (!re1.used) { - entry = &re1; - } else { - ASSERT(!re2.used); - entry = &re2; - } - entry->used = true; - entry->done = false; - entry->bno = bno; - entry->data = data; - virtio_blk_queue_req(ctx, BLK_READ(bno, 1, data), get_block_done, entry); - - while (!entry->done) { - virtio_blk_on_used_notif(ctx); - } - return pa_to_pointer(entry->data); -} -void put_block(uint64_t bno, void *cbdata) { - struct cache_entry *entry; - if (re1.used && re1.bno == bno) { - entry = &re1; - } else { - ASSERT(re2.used && re2.bno == bno); - entry = &re2; - } - slab_cache_free(pa_to_pointer(entry->data)); - entry->used = false; -} - void main(void) { __asm__("sti"); @@ -143,36 +77,19 @@ void main(void) { app_init_global(); printline("KarlOS initialized"); - // extern struct app_template cursor_template; - // app_push(&cursor_template, &tex, &RECT_XYWH(10, 10, 500, 500)); - // extern struct app_template snake_template; - // app_push(&snake_template, NULL, &RECT_XYWH(10, 10, 500, 500)); - __asm__ ("sti"); - struct virtio_dev_iter iter; - virtio_dev_iter_init(&iter, VIRTIO_DEV_KIND_BLOCK); - struct bdf bdf; - if (virtio_dev_iter_next(&iter, &bdf)) { - printlinef("found virtio block device with bdf %X8", bdf); - struct bdf second_bdf; - if (virtio_dev_iter_next(&iter, &second_bdf)) { - printline("WARNING: more than one virtio block device, ignoring all but first"); - } - struct virtio_blk_context ctx; - virtio_blk_device_init(bdf, &ctx); - slab_cache_init_with_align(§or_cache, 512, 512, NULL, NULL); - - uint64_t size; - uint64_t bno; - ASSERT(tar_get_file_info_custom("b.txt", ctx.num_sectors, get_block, put_block, &ctx, - &size, &bno)); - ASSERT(!re1.used && !re2.used); - printlinef("found file: size %lu bno %lu", size, bno); - - slab_cache_destroy(§or_cache); - } else { - printline("WARNING: did not find virtio device."); + bool vbe_initialize(); + bool vbe_read_file_info_from_disk(const char *name, uint64_t *size, uint64_t *bno); + bool success = vbe_initialize(); + if (success) { + uint64_t size, bno; + const char *name = "a.txt"; + ASSERT(vbe_read_file_info_from_disk(name, &size, &bno)); + printlinef("file %s: size %u bno %u", name, size, bno); + name = "b.txt"; + ASSERT(vbe_read_file_info_from_disk(name, &size, &bno)); + printlinef("file %s: size %u bno %u", name, size, bno); } while (1) { diff --git a/src/virtio-block-example.c b/src/virtio-block-example.c new file mode 100644 index 0000000..44b169d --- /dev/null +++ b/src/virtio-block-example.c @@ -0,0 +1,113 @@ +#include "virtio-block.h" +#include "std.h" +#include "slab.h" +#include "tar.h" + +void mycb(struct blk_req req, void* userdata) { + char *type = NULL; + switch (req.type) { + case BLK_REQ_READ: type = "READ"; break; + case BLK_REQ_WRITE: type = "WRITE"; break; + case BLK_REQ_FLUSH: type = "FLUSH"; break; + } + if (req.type == BLK_REQ_FLUSH) { + printlinef("%s done.", type); + } else { + uint8_t *p = pa_to_pointer(req.data); + printlinef("%s done: %u sectors starting at %u", type, req.num_sectors, req.sector); + for (int i = 0; i < req.num_sectors; i++) { + printlinef("sector %u: %X8 %X8 %X8 %X8 ...", req.sector + i, + p[512*i], p[512*i + 1], p[512*i + 2], p[512*i + 3] + ); + } + } + slab_cache_free(pa_to_pointer(req.data)); +} + +struct slab_cache sector_cache; +struct cache_entry { + bool used; + bool done; + uint64_t bno; + struct pa data; +} re1, re2; + +void get_block_done(struct blk_req req, void* userdata) { + struct cache_entry *entry = userdata; + entry->done = true; +} +uint8_t *get_block(uint64_t bno,void *cbdata) { + struct virtio_blk_context *ctx = cbdata; + struct pa data = pa_from_pointer(slab_cache_alloc(§or_cache)); + volatile struct cache_entry *entry; + if (!re1.used) { + entry = &re1; + } else { + ASSERT(!re2.used); + entry = &re2; + } + entry->used = true; + entry->done = false; + entry->bno = bno; + entry->data = data; + virtio_blk_queue_req(ctx, BLK_READ(bno, 1, data), get_block_done, entry); + + while (!entry->done) { + virtio_blk_on_used_notif(ctx); + } + return pa_to_pointer(entry->data); +} +void put_block(uint64_t bno, void *cbdata) { + struct cache_entry *entry; + if (re1.used && re1.bno == bno) { + entry = &re1; + } else { + ASSERT(re2.used && re2.bno == bno); + entry = &re2; + } + slab_cache_free(pa_to_pointer(entry->data)); + entry->used = false; +} + +bool vbe_initialized = false; +bool vbe_initialized_successful = false; +struct virtio_blk_context vbe_ctx; + +bool vbe_initialize() { + slab_cache_init_with_align(§or_cache, 512, 512, NULL, NULL); + struct virtio_dev_iter iter; + virtio_dev_iter_init(&iter, VIRTIO_DEV_KIND_BLOCK); + struct bdf bdf; + if (virtio_dev_iter_next(&iter, &bdf)) { + printlinef("found virtio block device with bdf %X8", bdf); + struct bdf second_bdf; + if (virtio_dev_iter_next(&iter, &second_bdf)) { + printline("WARNING: more than one virtio block device, ignoring all but first"); + } + virtio_blk_device_init(bdf, &vbe_ctx); + vbe_initialized = true; + vbe_initialized_successful = true; + return true; + } else { + printline("WARNING: did not find virtio device."); + vbe_initialized = true; + vbe_initialized_successful = false; + return false; + } +} + +bool vbe_read_file_info_from_disk(const char *name, uint64_t *size, uint64_t *bno) { + ASSERT(vbe_initialized && vbe_initialized_successful); + if (!vbe_initialized) { + bool success = vbe_initialize(); + vbe_initialized = true; + vbe_initialized_successful = success; + } + if (!vbe_initialized_successful) { + return false; + } + ASSERT(tar_get_file_info_custom(name, vbe_ctx.num_sectors, get_block, put_block, &vbe_ctx, + size, bno)); + ASSERT(!re1.used && !re2.used); + return true; +}