summaryrefslogtreecommitdiff
path: root/emu/bus.c
diff options
context:
space:
mode:
Diffstat (limited to 'emu/bus.c')
-rw-r--r--emu/bus.c75
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 );
+}