Memory interface is now MMIO-capable
This commit is contained in:
+203
-2
@@ -4,8 +4,209 @@
|
||||
uint8_t* memory;
|
||||
pthread_mutex_t memory_mutex;
|
||||
|
||||
#define MMIO_INSIDE(io, addr) (addr >= io->address && addr < io->address + (io->reg_size * io->reg_count))
|
||||
struct MMIO_ENTRY
|
||||
{
|
||||
uint32_t address;
|
||||
uint32_t reg_size;
|
||||
uint32_t reg_count;
|
||||
void* fn_write;
|
||||
void* fn_read;
|
||||
struct MMIO_ENTRY* next;
|
||||
};
|
||||
struct MMIO_ENTRY* mmio = 0;
|
||||
|
||||
void mem_init()
|
||||
{
|
||||
memory = malloc(memory_size);
|
||||
pthread_mutex_init(&memory_mutex, 0);
|
||||
memory = malloc(memory_size);
|
||||
pthread_mutex_init(&memory_mutex, 0);
|
||||
}
|
||||
|
||||
void mem_register_mmio(uint32_t address, uint32_t reg_size, uint32_t reg_count, void* fn_write, void* fn_read)
|
||||
{
|
||||
struct MMIO_ENTRY** current = &mmio;
|
||||
while(*current)
|
||||
current = &(*current)->next;
|
||||
|
||||
*current = malloc(sizeof(struct MMIO_ENTRY));
|
||||
(*current)->address = address;
|
||||
(*current)->reg_count = reg_count;
|
||||
(*current)->reg_size = reg_size;
|
||||
(*current)->fn_write = fn_write;
|
||||
(*current)->fn_read = fn_read;
|
||||
(*current)->next = 0;
|
||||
}
|
||||
|
||||
void mem_write8(uint32_t address, uint8_t value)
|
||||
{
|
||||
// Look wether we are on an MMIO region
|
||||
struct MMIO_ENTRY* io = mmio;
|
||||
while(io)
|
||||
{
|
||||
if(MMIO_INSIDE(io, address))
|
||||
{
|
||||
if(io->reg_size == 1)
|
||||
{
|
||||
void (*fn_write)(uint32_t, uint8_t) = io->fn_write;
|
||||
fn_write(address, value);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "MEMORY: Invalid MMIO access of size 1 in a mapping of %u-sized registers\n", io->reg_size);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
io = io->next;
|
||||
}
|
||||
|
||||
// Proceed with memory write
|
||||
pthread_mutex_lock(&memory_mutex);
|
||||
memory[address] = value;
|
||||
pthread_mutex_unlock(&memory_mutex);
|
||||
}
|
||||
|
||||
void mem_write16(uint32_t address, uint16_t value)
|
||||
{
|
||||
// Look wether we are on an MMIO region
|
||||
struct MMIO_ENTRY* io = mmio;
|
||||
while(io)
|
||||
{
|
||||
if(MMIO_INSIDE(io, address))
|
||||
{
|
||||
if(io->reg_size == 2)
|
||||
{
|
||||
void (*fn_write)(uint32_t, uint16_t) = io->fn_write;
|
||||
fn_write(address, value);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "MEMORY: Invalid MMIO access of size 2 in a mapping of %u-sized registers\n", io->reg_size);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
io = io->next;
|
||||
}
|
||||
|
||||
// Proceed with memory write
|
||||
pthread_mutex_lock(&memory_mutex);
|
||||
*((uint16_t*) &memory[address]) = value;
|
||||
pthread_mutex_unlock(&memory_mutex);
|
||||
}
|
||||
|
||||
void mem_write32(uint32_t address, uint32_t value)
|
||||
{
|
||||
// Look wether we are on an MMIO region
|
||||
struct MMIO_ENTRY* io = mmio;
|
||||
while(io)
|
||||
{
|
||||
if(MMIO_INSIDE(io, address))
|
||||
{
|
||||
if(io->reg_size == 4)
|
||||
{
|
||||
void (*fn_write)(uint32_t, uint32_t) = io->fn_write;
|
||||
fn_write(address, value);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "MEMORY: Invalid MMIO access of size 4 in a mapping of %u-sized registers\n", io->reg_size);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
io = io->next;
|
||||
}
|
||||
|
||||
// Proceed with memory write
|
||||
pthread_mutex_lock(&memory_mutex);
|
||||
*((uint32_t*) &memory[address]) = value;
|
||||
pthread_mutex_unlock(&memory_mutex);
|
||||
}
|
||||
|
||||
uint8_t mem_read8(uint32_t address)
|
||||
{
|
||||
// Look wether we are on an MMIO region
|
||||
struct MMIO_ENTRY* io = mmio;
|
||||
while(io)
|
||||
{
|
||||
if(MMIO_INSIDE(io, address))
|
||||
{
|
||||
if(io->reg_size == 1)
|
||||
{
|
||||
uint8_t (*fn_read)(uint32_t) = io->fn_read;
|
||||
return fn_read(address);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "MEMORY: Invalid MMIO access of size 1 in a mapping of %u-sized registers\n", io->reg_size);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
io = io->next;
|
||||
}
|
||||
|
||||
// Proceed with memory read
|
||||
pthread_mutex_lock(&memory_mutex);
|
||||
uint8_t tr = memory[address];
|
||||
pthread_mutex_unlock(&memory_mutex);
|
||||
return tr;
|
||||
}
|
||||
|
||||
uint16_t mem_read16(uint32_t address)
|
||||
{
|
||||
// Look wether we are on an MMIO region
|
||||
struct MMIO_ENTRY* io = mmio;
|
||||
while(io)
|
||||
{
|
||||
if(MMIO_INSIDE(io, address))
|
||||
{
|
||||
if(io->reg_size == 2)
|
||||
{
|
||||
uint16_t (*fn_read)(uint32_t) = io->fn_read;
|
||||
return fn_read(address);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "MEMORY: Invalid MMIO access of size 2 in a mapping of %u-sized registers\n", io->reg_size);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
io = io->next;
|
||||
}
|
||||
|
||||
// Proceed with memory read
|
||||
pthread_mutex_lock(&memory_mutex);
|
||||
uint16_t tr = *((uint16_t*) &memory[address]);
|
||||
pthread_mutex_unlock(&memory_mutex);
|
||||
return tr;
|
||||
}
|
||||
|
||||
uint32_t mem_read32(uint32_t address)
|
||||
{
|
||||
// Look wether we are on an MMIO region
|
||||
struct MMIO_ENTRY* io = mmio;
|
||||
while(io)
|
||||
{
|
||||
if(MMIO_INSIDE(io, address))
|
||||
{
|
||||
if(io->reg_size == 4)
|
||||
{
|
||||
uint32_t (*fn_read)(uint32_t) = io->fn_read;
|
||||
return fn_read(address);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "MEMORY: Invalid MMIO access of size 4 in a mapping of %u-sized registers\n", io->reg_size);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
io = io->next;
|
||||
}
|
||||
|
||||
// Proceed with memory read
|
||||
pthread_mutex_lock(&memory_mutex);
|
||||
uint32_t tr = *((uint32_t*) &memory[address]);
|
||||
pthread_mutex_unlock(&memory_mutex);
|
||||
return tr;
|
||||
}
|
||||
|
||||
+7
-1
@@ -5,8 +5,14 @@
|
||||
#include <pthread.h>
|
||||
|
||||
extern uint8_t* memory;
|
||||
extern pthread_mutex_t memory_mutex;
|
||||
|
||||
void mem_init();
|
||||
void mem_register_mmio(uint32_t address, uint32_t size, uint32_t reg_size, void* fn_write, void* fn_read);
|
||||
void mem_write8(uint32_t address, uint8_t value);
|
||||
void mem_write16(uint32_t address, uint16_t value);
|
||||
void mem_write32(uint32_t address, uint32_t value);
|
||||
uint8_t mem_read8(uint32_t address);
|
||||
uint16_t mem_read16(uint32_t address);
|
||||
uint32_t mem_read32(uint32_t address);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
#ifndef MMU_H
|
||||
#define MMU_H
|
||||
|
||||
#define mmu_translate(vaddr) (vaddr)
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user