move most of virtio-blk example outside main

This commit is contained in:
uosfz 2026-06-03 22:17:23 +02:00
parent a798d37ebe
commit 164f56ca57
Signed by: uosfz
SSH key fingerprint: SHA256:FlktuluyhTQg3jHZNLKwxOOC5hbfrUXM0tz3IA3lGJo
3 changed files with 125 additions and 94 deletions

View file

@ -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

View file

@ -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(&sector_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(&sector_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(&sector_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) {

113
src/virtio-block-example.c Normal file
View file

@ -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(&sector_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(&sector_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;
}