mirror of
https://github.com/captain-amygdala/pistorm.git
synced 2026-02-21 14:47:42 +00:00
Add code to autoconfigure A314
This commit is contained in:
35
a314/a314.cc
35
a314/a314.cc
@@ -108,7 +108,9 @@ static int irq_fds[2];
|
||||
extern "C" unsigned char fast_ram_array[];
|
||||
extern "C" void write16(unsigned int address, unsigned int value);
|
||||
|
||||
// Register bank in 0xE90000 memory.
|
||||
unsigned int a314_base;
|
||||
int a314_base_configured;
|
||||
|
||||
struct ComArea
|
||||
{
|
||||
uint8_t a_events;
|
||||
@@ -116,6 +118,9 @@ struct ComArea
|
||||
uint8_t r_events;
|
||||
uint8_t r_enable; // Unused.
|
||||
|
||||
uint32_t mem_base;
|
||||
uint32_t mem_size;
|
||||
|
||||
uint8_t a2r_tail;
|
||||
uint8_t r2a_head;
|
||||
uint8_t r2a_tail;
|
||||
@@ -1295,10 +1300,6 @@ static void write_r_events(uint8_t events)
|
||||
logger_error("Write to interrupt socket pair did not return 1\n");
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int a314_init()
|
||||
{
|
||||
std::string conf_filename("/etc/opt/a314/a314d.conf");
|
||||
@@ -1322,6 +1323,12 @@ int a314_init()
|
||||
return 0;
|
||||
}
|
||||
|
||||
void a314_set_mem_base_size(unsigned int base, unsigned int size)
|
||||
{
|
||||
ca.mem_base = htobe32(base);
|
||||
ca.mem_size = htobe32(size);
|
||||
}
|
||||
|
||||
void a314_process_events()
|
||||
{
|
||||
if (ca.a_events & ca.a_enable)
|
||||
@@ -1355,14 +1362,20 @@ unsigned int a314_read_memory_8(unsigned int address)
|
||||
|
||||
unsigned int a314_read_memory_16(unsigned int address)
|
||||
{
|
||||
// Not implemented.
|
||||
return 0;
|
||||
if (address >= sizeof(ca))
|
||||
return 0;
|
||||
|
||||
uint16_t *p = (uint16_t *)&ca;
|
||||
return be16toh(p[address >> 1]);
|
||||
}
|
||||
|
||||
unsigned int a314_read_memory_32(unsigned int address)
|
||||
{
|
||||
// Not implemented.
|
||||
return 0;
|
||||
if (address >= sizeof(ca))
|
||||
return 0;
|
||||
|
||||
uint32_t *p = (uint32_t *)&ca;
|
||||
return be32toh(p[address >> 2]);
|
||||
}
|
||||
|
||||
void a314_write_memory_8(unsigned int address, unsigned int value)
|
||||
@@ -1399,7 +1412,3 @@ void a314_write_memory_32(unsigned int address, unsigned int value)
|
||||
{
|
||||
// Not implemented.
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -9,11 +9,13 @@ extern "C" {
|
||||
|
||||
#define A314_ENABLED 1
|
||||
|
||||
// TODO: Base address should be obtained dynamically through Auto-Config.
|
||||
#define A314_COM_AREA_BASE 0xE90000
|
||||
#define A314_COM_AREA_SIZE (64*1024)
|
||||
extern unsigned int a314_base;
|
||||
extern int a314_base_configured;
|
||||
|
||||
#define A314_COM_AREA_SIZE (64 * 1024)
|
||||
|
||||
int a314_init();
|
||||
void a314_set_mem_base_size(unsigned int base, unsigned int size);
|
||||
void a314_process_events();
|
||||
|
||||
unsigned int a314_read_memory_8(unsigned int address);
|
||||
|
||||
@@ -106,7 +106,6 @@ void mark_region_a314(ULONG address, ULONG size)
|
||||
Enqueue(memlist, (struct Node *)new_mh);
|
||||
}
|
||||
|
||||
mh->mh_Node.ln_Pri = -20;
|
||||
mh->mh_Attributes |= MEMF_A314;
|
||||
Enqueue(memlist, (struct Node *)mh);
|
||||
return;
|
||||
@@ -117,15 +116,15 @@ void mark_region_a314(ULONG address, ULONG size)
|
||||
BOOL fix_memory()
|
||||
{
|
||||
Forbid();
|
||||
mark_region_a314(PISTORM_BASE, PISTORM_SIZE);
|
||||
mark_region_a314(ca->mem_base, ca->mem_size);
|
||||
Permit();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ULONG translate_address_a314(__reg("a0") void *address)
|
||||
{
|
||||
ULONG offset = (ULONG)address - PISTORM_BASE;
|
||||
if (offset < PISTORM_SIZE)
|
||||
ULONG offset = (ULONG)address - ca->mem_base;
|
||||
if (offset < ca->mem_size)
|
||||
return offset;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
XDEF _IntServer
|
||||
CODE
|
||||
|
||||
COM_AREA equ $e90000
|
||||
|
||||
SIGB_INT equ 14
|
||||
SIGF_INT equ (1 << SIGB_INT)
|
||||
|
||||
; a1 points to driver task
|
||||
_IntServer: lea.l COM_AREA,a5
|
||||
; a1 points to interrupt_data
|
||||
_IntServer: move.l 4(a1),a5 ; interrupt_data.ca
|
||||
|
||||
move.b 0(a5),d0 ; A_EVENTS
|
||||
and.b 1(a5),d0 ; A_ENABLE
|
||||
@@ -17,7 +15,7 @@ _IntServer: lea.l COM_AREA,a5
|
||||
|
||||
move.l $4.w,a6
|
||||
move.l #SIGF_INT,d0
|
||||
; a1 = pointer to driver task
|
||||
move.l 0(a1),a1 ; interrupt_data.task
|
||||
jsr -324(a6) ; Signal()
|
||||
|
||||
should_not_signal:
|
||||
|
||||
@@ -19,11 +19,6 @@
|
||||
#define A_EVENT_R2A_TAIL 1
|
||||
#define A_EVENT_A2R_HEAD 2
|
||||
|
||||
#define COM_AREA_BASE 0xe90000
|
||||
|
||||
#define PISTORM_BASE 0xc00000
|
||||
#define PISTORM_SIZE (3*512*1024)
|
||||
|
||||
// The communication area, used to create the physical channel.
|
||||
struct ComArea
|
||||
{
|
||||
@@ -32,6 +27,9 @@ struct ComArea
|
||||
volatile UBYTE r_events;
|
||||
volatile UBYTE r_enable;
|
||||
|
||||
ULONG mem_base;
|
||||
ULONG mem_size;
|
||||
|
||||
volatile UBYTE a2r_tail;
|
||||
volatile UBYTE r2a_head;
|
||||
volatile UBYTE r2a_tail;
|
||||
|
||||
@@ -2,8 +2,11 @@
|
||||
#include <exec/memory.h>
|
||||
#include <exec/tasks.h>
|
||||
#include <hardware/intbits.h>
|
||||
#include <libraries/expansion.h>
|
||||
#include <libraries/expansionbase.h>
|
||||
|
||||
#include <proto/exec.h>
|
||||
#include <proto/expansion.h>
|
||||
|
||||
#include "a314.h"
|
||||
#include "device.h"
|
||||
@@ -12,13 +15,24 @@
|
||||
#include "fix_mem_region.h"
|
||||
#include "debug.h"
|
||||
|
||||
#define A314_MANUFACTURER 0x07db
|
||||
#define A314_PRODUCT 0xa3
|
||||
|
||||
#define TASK_PRIORITY 80
|
||||
#define TASK_STACK_SIZE 1024
|
||||
|
||||
struct ExpansionBase *ExpansionBase;
|
||||
struct MsgPort task_mp;
|
||||
struct Task *task;
|
||||
struct ComArea *ca;
|
||||
|
||||
struct InterruptData
|
||||
{
|
||||
struct Task *task;
|
||||
struct ComArea *ca;
|
||||
};
|
||||
|
||||
struct InterruptData interrupt_data;
|
||||
struct Interrupt ports_interrupt;
|
||||
|
||||
extern void task_main();
|
||||
@@ -69,10 +83,13 @@ static void init_message_port()
|
||||
|
||||
static void add_interrupt_handler()
|
||||
{
|
||||
interrupt_data.task = task;
|
||||
interrupt_data.ca = ca;
|
||||
|
||||
ports_interrupt.is_Node.ln_Type = NT_INTERRUPT;
|
||||
ports_interrupt.is_Node.ln_Pri = 0;
|
||||
ports_interrupt.is_Node.ln_Name = device_name;
|
||||
ports_interrupt.is_Data = (APTR)task;
|
||||
ports_interrupt.is_Data = (APTR)&interrupt_data;
|
||||
ports_interrupt.is_Code = IntServer;
|
||||
|
||||
AddIntServer(INTB_PORTS, &ports_interrupt);
|
||||
@@ -80,10 +97,21 @@ static void add_interrupt_handler()
|
||||
|
||||
BOOL task_start()
|
||||
{
|
||||
if (!fix_memory())
|
||||
ExpansionBase = (struct ExpansionBase *)OpenLibrary(EXPANSIONNAME, 0);
|
||||
if (!ExpansionBase)
|
||||
return FALSE;
|
||||
|
||||
ca = (struct ComArea *)COM_AREA_BASE;
|
||||
struct ConfigDev *cd = FindConfigDev(NULL, A314_MANUFACTURER, A314_PRODUCT);
|
||||
if (!cd)
|
||||
{
|
||||
CloseLibrary((struct Library *)ExpansionBase);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ca = (struct ComArea *)cd->cd_BoardAddr;
|
||||
|
||||
if (!fix_memory())
|
||||
return FALSE;
|
||||
|
||||
task = create_task(device_name, TASK_PRIORITY, (void *)task_main, TASK_STACK_SIZE);
|
||||
if (task == NULL)
|
||||
|
||||
97
emulator.c
97
emulator.c
@@ -85,7 +85,7 @@ unsigned int fast_base;
|
||||
#define AC_BASE 0xE80000
|
||||
#define AC_SIZE (64 * 1024)
|
||||
|
||||
#define AC_PIC_COUNT 1
|
||||
#define AC_PIC_COUNT 2
|
||||
int ac_current_pic = 0;
|
||||
int ac_done = 0;
|
||||
|
||||
@@ -361,8 +361,17 @@ int cpu_irq_ack(int level) {
|
||||
return level;
|
||||
}
|
||||
|
||||
#define AC_MEM_SIZE_8MB 0
|
||||
#define AC_MEM_SIZE_64KB 1
|
||||
#define AC_MEM_SIZE_128KB 2
|
||||
#define AC_MEM_SIZE_256KB 3
|
||||
#define AC_MEM_SIZE_512KB 4
|
||||
#define AC_MEM_SIZE_1MB 5
|
||||
#define AC_MEM_SIZE_2MB 6
|
||||
#define AC_MEM_SIZE_4MB 7
|
||||
|
||||
static unsigned char ac_fast_ram_rom[] = {
|
||||
0xe, 0x0, // 00/02, link into memory free list, 8 MB
|
||||
0xe, AC_MEM_SIZE_8MB, // 00/02, link into memory free list, 8 MB
|
||||
0x6, 0x9, // 04/06, product id
|
||||
0x8, 0x0, // 08/0a, preference to 8 MB space
|
||||
0x0, 0x0, // 0c/0e, reserved
|
||||
@@ -370,25 +379,56 @@ static unsigned char ac_fast_ram_rom[] = {
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x2, 0x0 // 18/.../26, serial
|
||||
};
|
||||
|
||||
static unsigned int ac_fast_ram_read_memory_8(unsigned int address) {
|
||||
static unsigned char ac_a314_rom[] = {
|
||||
0xc, AC_MEM_SIZE_64KB, // 00/02, 64 kB
|
||||
0xa, 0x3, // 04/06, product id
|
||||
0x0, 0x0, // 08/0a, any space okay
|
||||
0x0, 0x0, // 0c/0e, reserved
|
||||
0x0, 0x7, 0xd, 0xb, // 10/12/14/16, mfg id
|
||||
0xa, 0x3, 0x1, 0x4, 0x0, 0x0, 0x0, 0x0 // 18/.../26, serial
|
||||
};
|
||||
|
||||
static unsigned int autoconfig_read_memory_8(unsigned int address) {
|
||||
unsigned char *rom = NULL;
|
||||
|
||||
if (ac_current_pic == 0)
|
||||
rom = ac_fast_ram_rom;
|
||||
else if (ac_current_pic == 1)
|
||||
rom = ac_a314_rom;
|
||||
|
||||
unsigned char val = 0;
|
||||
if ((address & 1) == 0 && (address / 2) < sizeof(ac_fast_ram_rom))
|
||||
val = ac_fast_ram_rom[address / 2];
|
||||
val = rom[address / 2];
|
||||
val <<= 4;
|
||||
if (address != 0 && address != 2 && address != 40 && address != 42)
|
||||
val ^= 0xf0;
|
||||
return (unsigned int)val;
|
||||
}
|
||||
|
||||
static void ac_fast_ram_write_memory_8(unsigned int address, unsigned int value) {
|
||||
static void autoconfig_write_memory_8(unsigned int address, unsigned int value) {
|
||||
int done = 0;
|
||||
|
||||
unsigned int *base = NULL;
|
||||
int *base_configured = NULL;
|
||||
|
||||
if (ac_current_pic == 0) {
|
||||
base = &fast_base;
|
||||
base_configured = &fast_base_configured;
|
||||
} else if (ac_current_pic == 1) {
|
||||
base = &a314_base;
|
||||
base_configured = &a314_base_configured;
|
||||
}
|
||||
|
||||
if (address == 0x4a) { // base[19:16]
|
||||
fast_base = (value & 0xf0) << (16 - 4);
|
||||
*base = (value & 0xf0) << (16 - 4);
|
||||
} else if (address == 0x48) { // base[23:20]
|
||||
fast_base &= 0xff0fffff;
|
||||
fast_base |= (value & 0xf0) << (20 - 4);
|
||||
fast_base_configured = 1;
|
||||
*base &= 0xff0fffff;
|
||||
*base |= (value & 0xf0) << (20 - 4);
|
||||
*base_configured = 1;
|
||||
|
||||
if (ac_current_pic == 0) // fast ram
|
||||
a314_set_mem_base_size(*base, FAST_SIZE);
|
||||
|
||||
done = 1;
|
||||
} else if (address == 0x4c) { // shut up
|
||||
done = 1;
|
||||
@@ -401,18 +441,6 @@ static void ac_fast_ram_write_memory_8(unsigned int address, unsigned int value)
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int autoconfig_read_memory_8(unsigned int address) {
|
||||
if (ac_current_pic == 0) {
|
||||
return ac_fast_ram_read_memory_8(address);
|
||||
}
|
||||
}
|
||||
|
||||
static void autoconfig_write_memory_8(unsigned int address, unsigned int value) {
|
||||
if (ac_current_pic == 0) {
|
||||
return ac_fast_ram_write_memory_8(address, value);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int m68k_read_memory_8(unsigned int address) {
|
||||
if (fast_base_configured && address >= fast_base && address < fast_base + FAST_SIZE) {
|
||||
return fast_ram_array[address - fast_base];
|
||||
@@ -435,8 +463,8 @@ unsigned int m68k_read_memory_8(unsigned int address) {
|
||||
}
|
||||
|
||||
#if A314_ENABLED
|
||||
if (address >= A314_COM_AREA_BASE && address < A314_COM_AREA_BASE + A314_COM_AREA_SIZE) {
|
||||
return a314_read_memory_8(address - A314_COM_AREA_BASE);
|
||||
if (a314_base_configured && address >= a314_base && address < a314_base + A314_COM_AREA_SIZE) {
|
||||
return a314_read_memory_8(address - a314_base);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -466,8 +494,8 @@ unsigned int m68k_read_memory_16(unsigned int address) {
|
||||
}
|
||||
|
||||
#if A314_ENABLED
|
||||
if (address >= A314_COM_AREA_BASE && address < A314_COM_AREA_BASE + A314_COM_AREA_SIZE) {
|
||||
return a314_read_memory_16(address - A314_COM_AREA_BASE);
|
||||
if (a314_base_configured && address >= a314_base && address < a314_base + A314_COM_AREA_SIZE) {
|
||||
return a314_read_memory_16(address - a314_base);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -497,8 +525,8 @@ unsigned int m68k_read_memory_32(unsigned int address) {
|
||||
}
|
||||
|
||||
#if A314_ENABLED
|
||||
if (address >= A314_COM_AREA_BASE && address < A314_COM_AREA_BASE + A314_COM_AREA_SIZE) {
|
||||
return a314_read_memory_32(address - A314_COM_AREA_BASE);
|
||||
if (a314_base_configured && address >= a314_base && address < a314_base + A314_COM_AREA_SIZE) {
|
||||
return a314_read_memory_32(address - a314_base);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -519,7 +547,8 @@ void m68k_write_memory_8(unsigned int address, unsigned int value) {
|
||||
}
|
||||
|
||||
if (!ac_done && address >= AC_BASE && address < AC_BASE + AC_SIZE) {
|
||||
return autoconfig_write_memory_8(address - AC_BASE, value);
|
||||
autoconfig_write_memory_8(address - AC_BASE, value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gayle_emulation_enabled) {
|
||||
@@ -530,8 +559,8 @@ void m68k_write_memory_8(unsigned int address, unsigned int value) {
|
||||
}
|
||||
|
||||
#if A314_ENABLED
|
||||
if (address >= A314_COM_AREA_BASE && address < A314_COM_AREA_BASE + A314_COM_AREA_SIZE) {
|
||||
a314_write_memory_8(address - A314_COM_AREA_BASE, value);
|
||||
if (a314_base_configured && address >= a314_base && address < a314_base + A314_COM_AREA_SIZE) {
|
||||
a314_write_memory_8(address - a314_base, value);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -565,8 +594,8 @@ void m68k_write_memory_16(unsigned int address, unsigned int value) {
|
||||
}
|
||||
|
||||
#if A314_ENABLED
|
||||
if (address >= A314_COM_AREA_BASE && address < A314_COM_AREA_BASE + A314_COM_AREA_SIZE) {
|
||||
a314_write_memory_16(address - A314_COM_AREA_BASE, value);
|
||||
if (a314_base_configured && address >= a314_base && address < a314_base + A314_COM_AREA_SIZE) {
|
||||
a314_write_memory_16(address - a314_base, value);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -592,8 +621,8 @@ void m68k_write_memory_32(unsigned int address, unsigned int value) {
|
||||
}
|
||||
|
||||
#if A314_ENABLED
|
||||
if (address >= A314_COM_AREA_BASE && address < A314_COM_AREA_BASE + A314_COM_AREA_SIZE) {
|
||||
a314_write_memory_32(address - A314_COM_AREA_BASE, value);
|
||||
if (a314_base_configured && address >= a314_base && address < a314_base + A314_COM_AREA_SIZE) {
|
||||
a314_write_memory_32(address - a314_base, value);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user