diff options
Diffstat (limited to 'src/components/bus/simple_bus.c')
| -rw-r--r-- | src/components/bus/simple_bus.c | 64 |
1 files changed, 49 insertions, 15 deletions
diff --git a/src/components/bus/simple_bus.c b/src/components/bus/simple_bus.c index 3629ecd..440ff8a 100644 --- a/src/components/bus/simple_bus.c +++ b/src/components/bus/simple_bus.c @@ -64,65 +64,94 @@ static stat add_mem_region(struct simple_bus *bus, struct mem_region *new) return OK; } -static stat simple_bus_write(struct simple_bus *bus, uintptr_t addr, - size_t size, char *buf) +static stat simple_bus_write(struct simple_bus *bus, struct packet *pkt) { /* 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); + struct mem_region *mem_region = find_mem_region(bus, packet_addr(pkt)); if (!mem_region) { warn("nothing to write on bus %s at %" PRIuPTR, - bus->component.name, addr); + bus->component.name, packet_addr(pkt)); return EBUS; } - stat ret = write(mem_region->component, addr, size, buf); + stat ret = write(mem_region->component, pkt); mtx_unlock(&bus->lock); return ret; } -static stat simple_bus_read(struct simple_bus *bus, uintptr_t addr, size_t size, - char *buf) +static stat simple_bus_read(struct simple_bus *bus, struct packet *pkt) { /* 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); + struct mem_region *mem_region = find_mem_region(bus, packet_addr(pkt)); if (!mem_region) { warn("nothing to read on bus %s at %" PRIuPTR, - bus->component.name, addr); + bus->component.name, packet_addr(pkt)); return EBUS; } - stat ret = read(mem_region->component, addr, size, buf); + stat ret = read(mem_region->component, pkt); 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) +static stat simple_bus_swap(struct simple_bus *bus, struct packet *pkt) { if (mtx_trylock(&bus->lock) != thrd_success) return EBUSY; - struct mem_region *mem_region = find_mem_region(bus, addr); + struct mem_region *mem_region = find_mem_region(bus, packet_addr(pkt)); if (!mem_region) { warn("nothing to swap on bus %s at %" PRIuPTR, - bus->component.name, addr); + bus->component.name, packet_addr(pkt)); return EBUS; } - stat ret = swap(mem_region->component, addr, wsize, wbuf, rsize, rbuf); + stat ret = swap(mem_region->component, pkt); mtx_unlock(&bus->lock); return ret; } +static stat simple_bus_snoop(struct simple_bus *bus, struct snoop *snoop) +{ + struct mem_region *cur = bus->mem_regions; + while (cur) { + if (cur->component->snoop) { + stat ret = cur->component->snoop(cur->component, snoop); + if (ret) + return ret; + + if (snoop_state(snoop) == SNOOP_ANSWERED) + return OK; + } + + cur = cur->next; + } + + return OK; +} + +static void simple_bus_destroy(struct simple_bus *bus) +{ + struct mem_region *cur = bus->mem_regions, *next = NULL; + if (cur) + do { + next = cur->next; + destroy(cur->component); + free(cur); + } while ((cur = next)); + + free(bus); +} + struct component *create_simple_bus() { struct simple_bus *bus = calloc(1, sizeof(struct simple_bus)); @@ -132,6 +161,11 @@ struct component *create_simple_bus() bus->component.write = (write_callback)simple_bus_write; bus->component.read = (read_callback)simple_bus_read; bus->component.swap = (swap_callback)simple_bus_swap; + bus->component.snoop = (snoop_callback)simple_bus_snoop; + // actually, still not sure about what API I want to use for controls + // bus->component.ctrl = (ctrl_callback)simple_bus_ctrl; + + bus->component.destroy = (destroy_callback)simple_bus_destroy; mtx_init(&bus->lock, mtx_plain); return (struct component *)bus; |
