diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2023-04-30 16:03:55 +0300 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2023-04-30 16:03:55 +0300 |
| commit | 191eaea25cf569ad9c5fb12b8755ae6400750e58 (patch) | |
| tree | a0cd14f4a772da01b445355eb35eec54616d01ec /src/components | |
| download | gran-191eaea25cf569ad9c5fb12b8755ae6400750e58.tar.gz gran-191eaea25cf569ad9c5fb12b8755ae6400750e58.zip | |
initial
Diffstat (limited to 'src/components')
| -rw-r--r-- | src/components/bus/simple_bus.c | 154 | ||||
| -rw-r--r-- | src/components/bus/source.mk | 1 | ||||
| -rw-r--r-- | src/components/mem/simple_mem.c | 48 | ||||
| -rw-r--r-- | src/components/mem/source.mk | 1 | ||||
| -rw-r--r-- | src/components/source.mk | 1 |
5 files changed, 205 insertions, 0 deletions
diff --git a/src/components/bus/simple_bus.c b/src/components/bus/simple_bus.c new file mode 100644 index 0000000..23a6bc2 --- /dev/null +++ b/src/components/bus/simple_bus.c @@ -0,0 +1,154 @@ +#include <threads.h> +#include <inttypes.h> +#include <stdlib.h> + +#include <gran/common.h> +#include <gran/component.h> + +#include <gran/components/bus/simple_bus.h> + +struct mem_region { + uintptr_t addr; + size_t size; + struct component *component; + struct mem_region *next; +}; + +struct simple_bus { + struct component component; + mtx_t lock; + + struct mem_region *mem_regions; +}; + +static struct mem_region *find_mem_region(struct simple_bus *bus, + uintptr_t addr) +{ + if (!bus->mem_regions) + return NULL; + + struct mem_region *cur = bus->mem_regions; + while (cur) { + /* address is within memory region */ + if (addr >= cur->addr && addr < cur->addr + cur->size) + return cur; + + cur = cur->next; + } + + return NULL; +} + +static stat add_mem_region(struct simple_bus *bus, struct mem_region *new) +{ + if (!bus->mem_regions) { + bus->mem_regions = new; + return OK; + } + + struct mem_region *found = NULL; + if ((found = find_mem_region(bus, new->addr))) { + error("%s overlaps with %s at %" PRIuPTR, + new->component->name, + found->component->name, + new->addr + ); + return EEXISTS; + } + + new->next = bus->mem_regions; + bus->mem_regions = new; + return OK; +} + +static stat simple_bus_write(struct simple_bus *bus, uintptr_t addr, + size_t size, char *buf) +{ + /* only one device can drive the bus at one time */ + if (mtx_trylock(&bus->lock) != thrd_success) + return EBUSY; + + struct mem_region *mem_region = find_mem_region(bus, addr); + if (!mem_region) { + warn("nothing to write on bus %s at %" PRIuPTR, + bus->component.name, addr); + return EBUS; + } + + stat ret = write(mem_region->component, addr, size, buf); + + mtx_unlock(&bus->lock); + return ret; +} + +static stat simple_bus_read(struct simple_bus *bus, uintptr_t addr, size_t size, + char *buf) +{ + /* only one device can drive the bus at one time */ + if (mtx_trylock(&bus->lock) != thrd_success) + return EBUSY; + + struct mem_region *mem_region = find_mem_region(bus, addr); + if (!mem_region) { + warn("nothing to read on bus %s at %" PRIuPTR, + bus->component.name, addr); + return EBUS; + } + + stat ret = read(mem_region->component, addr, size, buf); + + mtx_unlock(&bus->lock); + return ret; +} + +static stat simple_bus_swap(struct simple_bus *bus, uintptr_t addr, + size_t wsize, char *wbuf, size_t rsize, char *rbuf) +{ + if (mtx_trylock(&bus->lock) != thrd_success) + return EBUSY; + + struct mem_region *mem_region = find_mem_region(bus, addr); + if (!mem_region) { + warn("nothing to swap on bus %s at %" PRIuPTR, + bus->component.name, addr); + return EBUS; + } + + stat ret = swap(mem_region->component, addr, wsize, wbuf, rsize, rbuf); + + mtx_unlock(&bus->lock); + return ret; +} + +struct component *create_simple_bus() +{ + struct simple_bus *bus = calloc(1, sizeof(struct simple_bus)); + if (!bus) + return NULL; + + bus->component.write = (write_callback)simple_bus_write; + bus->component.read = (read_callback)simple_bus_read; + bus->component.swap = (swap_callback)simple_bus_swap; + + mtx_init(&bus->lock, mtx_plain); + return (struct component *)bus; +} + +stat simple_bus_add(struct component *bus, struct component *component, + uintptr_t addr, size_t size) +{ + struct mem_region *new = calloc(1, sizeof(struct mem_region)); + if (!new) + return ENOMEM; + + new->addr = addr; + new->size = size; + new->component = component; + + if (add_mem_region((struct simple_bus *)bus, new)) { + free(new); + return EEXISTS; + } + + return OK; +} diff --git a/src/components/bus/source.mk b/src/components/bus/source.mk new file mode 100644 index 0000000..98a10b6 --- /dev/null +++ b/src/components/bus/source.mk @@ -0,0 +1 @@ +SOURCES += src/components/bus/simple_bus.c diff --git a/src/components/mem/simple_mem.c b/src/components/mem/simple_mem.c new file mode 100644 index 0000000..bea68ed --- /dev/null +++ b/src/components/mem/simple_mem.c @@ -0,0 +1,48 @@ +#include <string.h> +#include <stdlib.h> + +#include <gran/components/mem/simple_mem.h> + +struct simple_mem { + struct component component; + size_t size; + char buf[]; +}; + +static stat simple_mem_write(struct simple_mem *mem, uintptr_t addr, + size_t size, char *buf) +{ + uintptr_t offset = addr % mem->size; + if (offset + size > mem->size) { + error("write outside memory"); + return ESIZE; + } + + memcpy(mem->buf + offset, buf, size); + return OK; +} + +static stat simple_mem_read(struct simple_mem *mem, uintptr_t addr, size_t size, + char *buf) +{ + uintptr_t offset = addr % mem->size; + if (offset + size > mem->size) { + error("read outside memory"); + return ESIZE; + } + + memcpy(buf, mem->buf + offset, size); + return OK; +} + +struct component *create_simple_mem(size_t size) +{ + struct simple_mem *new = calloc(1, sizeof(struct simple_mem) + size); + if (!new) + return NULL; + + new->size = size; + new->component.write = (write_callback)simple_mem_write; + new->component.read = (read_callback)simple_mem_read; + return (struct component *)new; +} diff --git a/src/components/mem/source.mk b/src/components/mem/source.mk new file mode 100644 index 0000000..9c339ba --- /dev/null +++ b/src/components/mem/source.mk @@ -0,0 +1 @@ +SOURCES += src/components/mem/simple_mem.c diff --git a/src/components/source.mk b/src/components/source.mk new file mode 100644 index 0000000..c45f391 --- /dev/null +++ b/src/components/source.mk @@ -0,0 +1 @@ +include src/components/*/source.mk |
