2017-01-18 23:57:09 +00:00
|
|
|
#include <stdio.h>
|
2017-01-16 18:35:28 +00:00
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdlib.h>
|
2017-02-20 20:29:52 +00:00
|
|
|
#include <stdbool.h>
|
2017-01-18 23:57:09 +00:00
|
|
|
#include <unistd.h>
|
2017-01-16 18:35:28 +00:00
|
|
|
#include <assert.h>
|
2017-02-20 20:29:52 +00:00
|
|
|
#include <fcntl.h>
|
2017-01-18 23:57:09 +00:00
|
|
|
|
|
|
|
#include <sys/types.h>
|
2017-01-16 18:35:28 +00:00
|
|
|
|
2017-02-20 11:31:26 +00:00
|
|
|
#include <utlist.h>
|
|
|
|
|
2017-02-19 20:45:15 +00:00
|
|
|
#include "bus.h"
|
2017-01-16 18:35:28 +00:00
|
|
|
|
2017-02-20 11:31:26 +00:00
|
|
|
#include "device_ram.h"
|
|
|
|
|
2017-02-19 20:45:15 +00:00
|
|
|
#define RK65C02_BUS_SIZE 64*1024
|
2017-01-16 18:35:28 +00:00
|
|
|
|
2017-02-20 11:31:26 +00:00
|
|
|
void
|
|
|
|
bus_device_add(bus_t *b, device_t *d, uint16_t addr)
|
|
|
|
{
|
|
|
|
device_mapping_t *dm;
|
|
|
|
|
|
|
|
dm = (device_mapping_t *) malloc(sizeof(device_mapping_t));
|
|
|
|
|
|
|
|
dm->dev = d;
|
2017-02-20 20:29:52 +00:00
|
|
|
/* TODO: check if addr + size is not bigger than RK65C02_BUS_SIZE */
|
2017-02-20 11:31:26 +00:00
|
|
|
dm->addr = addr;
|
|
|
|
|
|
|
|
LL_APPEND((b->dm_head), dm);
|
|
|
|
}
|
|
|
|
|
2017-02-20 20:29:52 +00:00
|
|
|
void
|
|
|
|
bus_device_dump(bus_t *b)
|
|
|
|
{
|
|
|
|
device_mapping_t *dm;
|
|
|
|
device_t *d;
|
|
|
|
|
|
|
|
LL_FOREACH(b->dm_head, dm) {
|
|
|
|
d = dm->dev;
|
|
|
|
printf("@ %x size %x - %s\n", dm->addr, d->size, d->name);
|
|
|
|
/* TODO: device specific info */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-16 18:35:28 +00:00
|
|
|
uint8_t
|
|
|
|
bus_read_1(bus_t *t, uint16_t addr)
|
|
|
|
{
|
2017-01-25 09:09:38 +00:00
|
|
|
uint8_t val;
|
2017-02-20 11:31:26 +00:00
|
|
|
device_mapping_t *dm;
|
|
|
|
device_t *d;
|
|
|
|
|
|
|
|
LL_FOREACH(t->dm_head, dm) {
|
|
|
|
d = dm->dev;
|
|
|
|
|
|
|
|
if (dm->addr == 0)
|
|
|
|
val = d->read_1(d, addr);
|
|
|
|
/*
|
|
|
|
* else
|
|
|
|
* Check if address is inside of given device range, calculate
|
|
|
|
* offset.
|
|
|
|
*/
|
|
|
|
|
|
|
|
}
|
2017-02-20 20:29:52 +00:00
|
|
|
// printf("bus READ @ %x value %x\n", addr, val);
|
2017-01-25 09:09:38 +00:00
|
|
|
return val;
|
2017-01-16 18:35:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
bus_write_1(bus_t *t, uint16_t addr, uint8_t val)
|
|
|
|
{
|
2017-02-20 11:31:26 +00:00
|
|
|
device_mapping_t *dm;
|
|
|
|
device_t *d;
|
|
|
|
|
|
|
|
LL_FOREACH(t->dm_head, dm) {
|
|
|
|
d = dm->dev;
|
|
|
|
|
|
|
|
if (dm->addr == 0)
|
|
|
|
d->write_1(d, addr, val);
|
|
|
|
/*
|
|
|
|
* else
|
|
|
|
* Check if address is inside of given device range, calculate
|
|
|
|
* offset.
|
|
|
|
*/
|
|
|
|
|
|
|
|
}
|
2017-02-20 20:29:52 +00:00
|
|
|
// printf("bus WRITE @ %x value %x\n", addr, val);
|
2017-01-16 18:35:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bus_t
|
|
|
|
bus_init()
|
|
|
|
{
|
|
|
|
bus_t t;
|
|
|
|
|
2017-02-20 11:31:26 +00:00
|
|
|
t.dm_head = NULL;
|
|
|
|
|
|
|
|
return t;
|
|
|
|
}
|
|
|
|
|
|
|
|
bus_t
|
|
|
|
bus_init_with_default_devs()
|
|
|
|
{
|
|
|
|
bus_t t;
|
2017-01-16 18:35:28 +00:00
|
|
|
|
2017-02-20 11:31:26 +00:00
|
|
|
t = bus_init();
|
2017-01-16 18:35:28 +00:00
|
|
|
|
2017-02-20 11:31:26 +00:00
|
|
|
bus_device_add(&t, device_ram_init(), 0x0);
|
2017-01-16 18:35:28 +00:00
|
|
|
|
2017-02-20 11:31:26 +00:00
|
|
|
return t;
|
2017-01-16 18:35:28 +00:00
|
|
|
}
|
2017-02-20 11:31:26 +00:00
|
|
|
|
2017-02-02 11:06:41 +00:00
|
|
|
bool
|
|
|
|
bus_load_buf(bus_t *t, uint16_t addr, uint8_t *buf, uint16_t bufsize)
|
|
|
|
{
|
|
|
|
uint16_t i;
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
2017-02-19 20:45:15 +00:00
|
|
|
// XXX: add sanity checks
|
2017-02-02 11:06:41 +00:00
|
|
|
|
|
|
|
while (i < bufsize) {
|
2017-02-20 20:29:52 +00:00
|
|
|
bus_write_1(t, addr+i, buf[i]); // XXX: overflow addr
|
2017-02-02 11:06:41 +00:00
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2017-02-20 20:29:52 +00:00
|
|
|
|
|
|
|
/* TODO: should be moved to ram/rom specific devs */
|
2017-01-18 23:57:09 +00:00
|
|
|
bool
|
|
|
|
bus_load_file(bus_t *t, uint16_t addr, const char *filename)
|
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
uint8_t data;
|
|
|
|
|
|
|
|
fd = open(filename, O_RDONLY);
|
|
|
|
if (fd == -1) {
|
|
|
|
perror("Problem while trying to open file");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
while ((read(fd, &data, 1)) > 0) {
|
2017-02-20 20:29:52 +00:00
|
|
|
bus_write_1(t, addr++, data); // XXX: overflow addr
|
2017-01-18 23:57:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
close(fd);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2017-02-20 20:29:52 +00:00
|
|
|
|
2017-01-16 18:35:28 +00:00
|
|
|
void
|
|
|
|
bus_finish(bus_t *t)
|
|
|
|
{
|
2017-01-16 20:34:56 +00:00
|
|
|
assert(t != NULL);
|
|
|
|
|
2017-02-20 20:29:52 +00:00
|
|
|
/* TODO: foreach devices free 'em */
|
2017-01-16 18:35:28 +00:00
|
|
|
}
|
|
|
|
|