]> git.sesse.net Git - pistorm/commitdiff
Add code to autoconfigure A314
authorNiklas Ekström <mail@niklasekstrom.nu>
Tue, 1 Dec 2020 22:39:13 +0000 (23:39 +0100)
committerNiklas Ekström <mail@niklasekstrom.nu>
Tue, 1 Dec 2020 22:39:13 +0000 (23:39 +0100)
a314/a314.cc
a314/a314.h
a314/a314device/fix_mem_region.c
a314/a314device/int_server.asm
a314/a314device/protocol.h
a314/a314device/startup.c
emulator.c

index 4d5dfe6942c511faca4eee6325af6ad480919f48..70b45d5f336d6eacd4db078da870425a8ea50ea9 100644 (file)
@@ -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
index 14fca5b1b875bdcc68dcd2548ad813a95a70dead..fa15430db5e9ac7fa5e12cc3ded34b3f21bf0289 100644 (file)
@@ -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);
index 9d9587c22e265243b9b46b3ccf3c0c476878609e..802dcae05822b83809df917b53ac256c445a2374 100644 (file)
@@ -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;
 }
index 2a7b866ef3b92e956c7fd92b82444e9c987f3c8a..e7d582f608ed4942b15de226a5d848f0085beae8 100644 (file)
@@ -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:
index 6ff50a229d2ff7d2adc5b9d8e9bef727877e3f35..28dc1681f2376c6d6f1d4ee82f4502ce32fcd733 100644 (file)
 #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;
index cce7a1374e34cc63acc0e2c645f44353588668ff..ccb3bb63762d58f5e8c6b5712863ef120df937ed 100644 (file)
@@ -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"
 #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;
+
+       struct ConfigDev *cd = FindConfigDev(NULL, A314_MANUFACTURER, A314_PRODUCT);
+       if (!cd)
+       {
+               CloseLibrary((struct Library *)ExpansionBase);
                return FALSE;
+       }
 
-       ca = (struct ComArea *)COM_AREA_BASE;
+       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)
index 9b2b49792276c52598a7553fc9c9b70e2972f413..a18513b3960218283474b7fca959a65764288634 100644 (file)
@@ -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