diff options
Diffstat (limited to 'emu/bus.c')
-rw-r--r-- | emu/bus.c | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/emu/bus.c b/emu/bus.c new file mode 100644 index 0000000..5bbbcb1 --- /dev/null +++ b/emu/bus.c @@ -0,0 +1,75 @@ +#include "bus.h" + +#include <stdio.h> +#include <stdlib.h> + +static device_vtable_t const bus_vtable = { + bus_read, + bus_write, + bus_deinit +}; + +void bus_init( bus_t *bus ) +{ + device_init( &bus->base, "bus" ); + ((device_t *)bus)->vtable = (device_vtable_t *)&bus_vtable; + + bus->nof_devices = 0; +} + +void bus_register( bus_t *bus, device_t *device, uint16_t from, uint16_t to ) +{ + if( bus->nof_devices < MAX_NOF_DEVICES ) { + registered_device_t *reg = &bus->devices[bus->nof_devices]; + reg->device = device; + reg->from = from; + reg->to = to; + bus->nof_devices++; + } else { + fprintf( stderr, "ERROR: too many devices on bus\n" ); + exit( EXIT_FAILURE ); + } +} + +uint8_t bus_read( void *obj, uint16_t addr ) +{ + bus_t *bus = (bus_t *)obj; + + for( int i = 0; i < bus->nof_devices; i++ ) { + registered_device_t *reg = &bus->devices[i]; + if( reg->from <= addr && addr <= reg->to ) { + return reg->device->vtable->read( reg->device, addr ); + } + } + + fprintf( stderr, "ERROR: illegal bus access reading from address %04X\n", addr ); + + return 0; +} + +void bus_write( void *obj, uint16_t addr, uint8_t data ) +{ + bus_t *bus = (bus_t *)obj; + + for( int i = 0; i < bus->nof_devices; i++ ) { + registered_device_t *reg = &bus->devices[i]; + if( reg->from <= addr && addr <= reg->to ) { + return reg->device->vtable->write( reg->device, addr, data ); + } + } + + fprintf( stderr, "ERROR: illegal bus access writing from address %04X\n", addr ); +} + +void bus_deinit( void *obj ) +{ + bus_t *bus = (bus_t *)obj; + + for( int i = bus->nof_devices - 1; i >= 0; i-- ) { + registered_device_t *reg = &bus->devices[i]; + reg->device->vtable->deinit( reg->device ); + } + bus->nof_devices = 0; + + device_deinit( &bus->base ); +} |