]> git.sesse.net Git - pistorm/blobdiff - emulator.c
Add code to autoconfigure A314
[pistorm] / emulator.c
index 35b6b9e7847ac6044ee8ad17daa87c3086d06326..a18513b3960218283474b7fca959a65764288634 100644 (file)
@@ -1,3 +1,7 @@
+/*
+Copyright 2020 Claude Schwartz
+*/
+
 #include <assert.h>
 #include <dirent.h>
 #include <endian.h>
@@ -13,7 +17,9 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
+
 #include "Gayle.h"
+#include "a314/a314.h"
 #include "ide.h"
 #include "m68k.h"
 #include "main.h"
       reset |= (1 << (no)); \
   } while (0)
 
-#define FASTBASE 0x07FFFFFF
-#define FASTSIZE 0xFFFFFFF
-#define GAYLEBASE 0xD80000  // D7FFFF
-#define GAYLESIZE 0x6FFFF
+int fast_base_configured;
+unsigned int fast_base;
+#define FAST_SIZE (8 * 1024 * 1024)
+
+#define GAYLEBASE 0xD80000
+#define GAYLESIZE (448 * 1024)
 
 #define KICKBASE 0xF80000
-#define KICKSIZE 0x7FFFF
+#define KICKSIZE (512 * 1024)
+
+#define AC_BASE 0xE80000
+#define AC_SIZE (64 * 1024)
+
+#define AC_PIC_COUNT 2
+int ac_current_pic = 0;
+int ac_done = 0;
 
 int mem_fd;
 int mem_fd_gpclk;
+int gayle_emulation_enabled = 1;
 void *gpio_map;
 void *gpclk_map;
 
@@ -125,8 +141,8 @@ volatile uint16_t srdata;
 volatile uint32_t srdata2;
 volatile uint32_t srdata2_old;
 
-unsigned char g_kick[524288];
-unsigned char g_ram[FASTSIZE + 1]; /* RAM */
+unsigned char g_kick[KICKSIZE];
+unsigned char fast_ram_array[FAST_SIZE]; /* RAM */
 unsigned char toggle;
 static volatile unsigned char ovl;
 static volatile unsigned char maprom;
@@ -137,17 +153,39 @@ void sigint_handler(int sig_num) {
 }
 
 void *iplThread(void *args) {
-  printf("thread!/n");
+  printf("IPL thread running/n");
 
   while (42) {
+    if (GET_GPIO(1) == 0) {
+      toggle = 1;
+      m68k_end_timeslice();
+      //printf("thread!/n");
+    } else {
+      toggle = 0;
+    };
     usleep(1);
   }
 }
 
-int main() {
+int main(int argc, char *argv[]) {
   int g;
   const struct sched_param priority = {99};
 
+  // Some command line switch stuffles
+  for (g = 1; g < argc; g++) {
+    if (strcmp(argv[g], "--disable-gayle") == 0) {
+      gayle_emulation_enabled = 0;
+    }
+  }
+
+#if A314_ENABLED
+  int err = a314_init();
+  if (err < 0) {
+    printf("Unable to initialize A314 emulation\n");
+    return -1;
+  }
+#endif
+
   sched_setscheduler(0, SCHED_FIFO, &priority);
   mlockall(MCL_CURRENT);  // lock in memory to keep us from paging out
 
@@ -259,7 +297,7 @@ int main() {
   usleep(1500);
 
   m68k_init();
-  m68k_set_cpu_type(M68K_CPU_TYPE_68030);
+  m68k_set_cpu_type(M68K_CPU_TYPE_68020);
   m68k_pulse_reset();
 
   if (maprom == 1) {
@@ -269,23 +307,41 @@ int main() {
   }
 
   /*
-           pthread_t id;
-           int err;
-          //err = pthread_create(&id, NULL, &iplThread, NULL);
+          pthread_t id;
+          int err;
+          err = pthread_create(&id, NULL, &iplThread, NULL);
           if (err != 0)
               printf("\ncan't create IPL thread :[%s]", strerror(err));
           else
               printf("\n IPL Thread created successfully\n");
-  */
+*/
 
   m68k_pulse_reset();
   while (42) {
-    m68k_execute(3000);
+    m68k_execute(300);
+    /*
+    if (toggle == 1){
+      srdata = read_reg();
+      m68k_set_irq((srdata >> 13) & 0xff);
+    } else {
+         m68k_set_irq(0);
+    };
+    usleep(1);
+*/
+
+#if A314_ENABLED
+    a314_process_events();
+#endif
+
     if (GET_GPIO(1) == 0) {
       srdata = read_reg();
       m68k_set_irq((srdata >> 13) & 0xff);
     } else {
-      m68k_set_irq(0);
+      if (CheckIrq() == 1) {
+        write16(0xdff09c, 0x8008);
+        m68k_set_irq(2);
+      } else
+        m68k_set_irq(0);
     };
   }
 
@@ -305,133 +361,280 @@ 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, 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
+    0x0, 0x7, 0xd, 0xb,                     // 10/12/14/16, mfg id
+    0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x2, 0x0  // 18/.../26, serial
+};
+
+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 = rom[address / 2];
+  val <<= 4;
+  if (address != 0 && address != 2 && address != 40 && address != 42)
+    val ^= 0xf0;
+  return (unsigned int)val;
+}
+
+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]
+    *base = (value & 0xf0) << (16 - 4);
+  } else if (address == 0x48) {  // base[23:20]
+    *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;
+  }
+
+  if (done) {
+    ac_current_pic++;
+    if (ac_current_pic == AC_PIC_COUNT)
+      ac_done = 1;
+  }
+}
+
 unsigned int m68k_read_memory_8(unsigned int address) {
-  if (address > FASTBASE && address < FASTBASE + FASTSIZE) {
-    return g_ram[address - FASTBASE];
+  if (fast_base_configured && address >= fast_base && address < fast_base + FAST_SIZE) {
+    return fast_ram_array[address - fast_base];
+  }
+
+  if (!ac_done && address >= AC_BASE && address < AC_BASE + AC_SIZE) {
+    return autoconfig_read_memory_8(address - AC_BASE);
   }
 
   if (maprom == 1) {
-    if (address > KICKBASE && address < KICKBASE + KICKSIZE) {
+    if (address >= KICKBASE && address < KICKBASE + KICKSIZE) {
       return g_kick[address - KICKBASE];
     }
   }
 
-  if (address > GAYLEBASE && address < GAYLEBASE + GAYLESIZE) {
-    return readGayleB(address);
+  if (gayle_emulation_enabled) {
+    if (address >= GAYLEBASE && address < GAYLEBASE + GAYLESIZE) {
+      return readGayleB(address);
+    }
   }
 
-  if (address < 0xffffff) {
-    return read8((uint32_t)address);
+#if A314_ENABLED
+  if (a314_base_configured && address >= a314_base && address < a314_base + A314_COM_AREA_SIZE) {
+    return a314_read_memory_8(address - a314_base);
   }
+#endif
 
-  return 0;
+  address &= 0xFFFFFF;
+  //  if (address < 0xffffff) {
+  return read8((uint32_t)address);
+  //  }
+
+  //  return 1;
 }
 
 unsigned int m68k_read_memory_16(unsigned int address) {
-  if (address > FASTBASE && address < FASTBASE + FASTSIZE) {
-    return be16toh(*(uint16_t *)&g_ram[address - FASTBASE]);
+  if (fast_base_configured && address >= fast_base && address < fast_base + FAST_SIZE) {
+    return be16toh(*(uint16_t *)&fast_ram_array[address - fast_base]);
   }
 
   if (maprom == 1) {
-    if (address > KICKBASE && address < KICKBASE + KICKSIZE) {
+    if (address >= KICKBASE && address < KICKBASE + KICKSIZE) {
       return be16toh(*(uint16_t *)&g_kick[address - KICKBASE]);
     }
   }
 
-  if (address > GAYLEBASE && address < GAYLEBASE + GAYLESIZE) {
-    return readGayle(address);
+  if (gayle_emulation_enabled) {
+    if (address >= GAYLEBASE && address < GAYLEBASE + GAYLESIZE) {
+      return readGayle(address);
+    }
   }
 
-  if (address < 0xffffff) {
-    return (unsigned int)read16((uint32_t)address);
+#if A314_ENABLED
+  if (a314_base_configured && address >= a314_base && address < a314_base + A314_COM_AREA_SIZE) {
+    return a314_read_memory_16(address - a314_base);
   }
+#endif
 
-  return 0;
+  //  if (address < 0xffffff) {
+  address &= 0xFFFFFF;
+  return (unsigned int)read16((uint32_t)address);
+  //  }
+
+  //  return 1;
 }
 
 unsigned int m68k_read_memory_32(unsigned int address) {
-  if (address > FASTBASE && address < FASTBASE + FASTSIZE) {
-    return be32toh(*(uint32_t *)&g_ram[address - FASTBASE]);
+  if (fast_base_configured && address >= fast_base && address < fast_base + FAST_SIZE) {
+    return be32toh(*(uint32_t *)&fast_ram_array[address - fast_base]);
   }
 
   if (maprom == 1) {
-    if (address > KICKBASE && address < KICKBASE + KICKSIZE) {
+    if (address >= KICKBASE && address < KICKBASE + KICKSIZE) {
       return be32toh(*(uint32_t *)&g_kick[address - KICKBASE]);
     }
   }
 
-  if (address > GAYLEBASE && address < GAYLEBASE + GAYLESIZE) {
-    return readGayleL(address);
+  if (gayle_emulation_enabled) {
+    if (address >= GAYLEBASE && address < GAYLEBASE + GAYLESIZE) {
+      return readGayleL(address);
+    }
   }
 
-  if (address < 0xffffff) {
-    uint16_t a = read16(address);
-    uint16_t b = read16(address + 2);
-    return (a << 16) | b;
+#if A314_ENABLED
+  if (a314_base_configured && address >= a314_base && address < a314_base + A314_COM_AREA_SIZE) {
+    return a314_read_memory_32(address - a314_base);
   }
+#endif
 
-  return 0;
+  //  if (address < 0xffffff) {
+  address &= 0xFFFFFF;
+  uint16_t a = read16(address);
+  uint16_t b = read16(address + 2);
+  return (a << 16) | b;
+  //  }
+
+  //  return 1;
 }
 
 void m68k_write_memory_8(unsigned int address, unsigned int value) {
-  if (address > FASTBASE && address < FASTBASE + FASTSIZE) {
-    g_ram[address - FASTBASE] = value;
+  if (fast_base_configured && address >= fast_base && address < fast_base + FAST_SIZE) {
+    fast_ram_array[address - fast_base] = value;
     return;
   }
 
-  if (address > GAYLEBASE && address < GAYLEBASE + GAYLESIZE) {
-    writeGayleB(address, value);
+  if (!ac_done && address >= AC_BASE && address < AC_BASE + AC_SIZE) {
+    autoconfig_write_memory_8(address - AC_BASE, value);
     return;
   }
 
-  if (address == 0xbfe001) {
-    ovl = (value & (1 << 0));
-    printf("OVL:%x\n", ovl);
+  if (gayle_emulation_enabled) {
+    if (address >= GAYLEBASE && address < GAYLEBASE + GAYLESIZE) {
+      writeGayleB(address, value);
+      return;
+    }
   }
 
-  if (address < 0xffffff) {
-    write8((uint32_t)address, value);
+#if A314_ENABLED
+  if (a314_base_configured && address >= a314_base && address < a314_base + A314_COM_AREA_SIZE) {
+    a314_write_memory_8(address - a314_base, value);
     return;
   }
+#endif
 
+  /*
+  if (address == 0xbfe001) {
+    ovl = (value & (1 << 0));
+    printf("OVL:%x\n", ovl);
+  }
+*/
+  //  if (address < 0xffffff) {
+  address &= 0xFFFFFF;
+  write8((uint32_t)address, value);
   return;
+  //  }
+
+  //  return;
 }
 
 void m68k_write_memory_16(unsigned int address, unsigned int value) {
-  if (address > FASTBASE && address < FASTBASE + FASTSIZE) {
-    *(uint16_t *)&g_ram[address - FASTBASE] = htobe16(value);
+  if (fast_base_configured && address >= fast_base && address < fast_base + FAST_SIZE) {
+    *(uint16_t *)&fast_ram_array[address - fast_base] = htobe16(value);
     return;
   }
 
-  if (address > GAYLEBASE && address < GAYLEBASE + GAYLESIZE) {
-    writeGayle(address, value);
-    return;
+  if (gayle_emulation_enabled) {
+    if (address >= GAYLEBASE && address < GAYLEBASE + GAYLESIZE) {
+      writeGayle(address, value);
+      return;
+    }
   }
 
-  if (address < 0xffffff) {
-    write16((uint32_t)address, value);
+#if A314_ENABLED
+  if (a314_base_configured && address >= a314_base && address < a314_base + A314_COM_AREA_SIZE) {
+    a314_write_memory_16(address - a314_base, value);
     return;
   }
+#endif
+
+  //  if (address < 0xffffff) {
+  address &= 0xFFFFFF;
+  write16((uint32_t)address, value);
   return;
+  //  }
+  //  return;
 }
 
 void m68k_write_memory_32(unsigned int address, unsigned int value) {
-  if (address > FASTBASE && address < FASTBASE + FASTSIZE) {
-    *(uint32_t *)&g_ram[address - FASTBASE] = htobe32(value);
+  if (fast_base_configured && address >= fast_base && address < fast_base + FAST_SIZE) {
+    *(uint32_t *)&fast_ram_array[address - fast_base] = htobe32(value);
     return;
   }
 
-  if (address > GAYLEBASE && address < GAYLEBASE + GAYLESIZE) {
-    writeGayleL(address, value);
+  if (gayle_emulation_enabled) {
+    if (address >= GAYLEBASE && address < GAYLEBASE + GAYLESIZE) {
+      writeGayleL(address, value);
+    }
   }
 
-  if (address < 0xffffff) {
-    write16(address, value >> 16);
-    write16(address + 2, value);
+#if A314_ENABLED
+  if (a314_base_configured && address >= a314_base && address < a314_base + A314_COM_AREA_SIZE) {
+    a314_write_memory_32(address - a314_base, value);
     return;
   }
+#endif
 
+  //  if (address < 0xffffff) {
+  address &= 0xFFFFFF;
+  write16(address, value >> 16);
+  write16(address + 2, value);
   return;
+  //  }
+
+  //  return;
 }
 
 void write16(uint32_t address, uint32_t data) {
@@ -443,7 +646,8 @@ void write16(uint32_t address, uint32_t data) {
   uint32_t data_r = (~data & 0x0000ffff) << 8;
 
   //      asm volatile ("dmb" ::: "memory");
-  W16 *(gpio) = gpfsel0_o;
+  W16
+      *(gpio) = gpfsel0_o;
   *(gpio + 1) = gpfsel1_o;
   *(gpio + 2) = gpfsel2_o;
 
@@ -484,7 +688,8 @@ void write8(uint32_t address, uint32_t data) {
   uint32_t data_r = (~data & 0x0000ffff) << 8;
 
   //   asm volatile ("dmb" ::: "memory");
-  W8 *(gpio) = gpfsel0_o;
+  W8
+      *(gpio) = gpfsel0_o;
   *(gpio + 1) = gpfsel1_o;
   *(gpio + 2) = gpfsel2_o;
 
@@ -521,7 +726,6 @@ uint32_t read16(uint32_t address) {
 
   //   asm volatile ("dmb" ::: "memory");
   R16
-
       *(gpio) = gpfsel0_o;
   *(gpio + 1) = gpfsel1_o;
   *(gpio + 2) = gpfsel2_o;
@@ -558,7 +762,8 @@ uint32_t read8(uint32_t address) {
   uint32_t addr_l_r = (~address >> 16) << 8;
 
   //    asm volatile ("dmb" ::: "memory");
-  R8 *(gpio) = gpfsel0_o;
+  R8
+      *(gpio) = gpfsel0_o;
   *(gpio + 1) = gpfsel1_o;
   *(gpio + 2) = gpfsel2_o;
 
@@ -587,10 +792,9 @@ uint32_t read8(uint32_t address) {
 
   val = (val >> 8) & 0xffff;
   if ((address & 1) == 0)
-    val = (val >> 8) & 0xff;  // EVEN, A0=0,UDS
+    return (val >> 8) & 0xff;  // EVEN, A0=0,UDS
   else
-    val = val & 0xff;  // ODD , A0=1,LDS
-  return val;
+    return val & 0xff;  // ODD , A0=1,LDS
 }
 
 /******************************************************/