]> git.sesse.net Git - pistorm/blobdiff - platforms/amiga/Gayle.c
tidy up headers, remove extraneous duplicate decls
[pistorm] / platforms / amiga / Gayle.c
index 1bbba361bb929f6af15b3290170f067d405f4cde..55da51ad6407b1297fd8692edbdfe5639fad57e2 100644 (file)
 #include <time.h>
 #include <endian.h>
 
-#include "../shared/rtc.h"
-#include "../../config_file/config_file.h"
+#include "platforms/shared/rtc.h"
+#include "config_file/config_file.h"
 
 #include "gayle-ide/ide.h"
 #include "amiga-registers.h"
 
-//#define GSTATUS 0xda201c
-//#define GCLOW   0xda2010
-//#define GDH  0xda2018
-
-// Gayle Addresses
-
-// Gayle IDE Reads
-#define GERROR 0xda2004   // Error
-#define GSTATUS 0xda201c  // Status
-// Gayle IDE Writes
-#define GFEAT 0xda2004  // Write : Feature
-#define GCMD 0xda201c   // Write : Command
-// Gayle IDE RW
-#define GDATA 0xda2000     // Data
-#define GSECTCNT 0xda2008  // SectorCount
-#define GSECTNUM 0xda200c  // SectorNumber
-#define GCYLLOW 0xda2010   // CylinderLow
-#define GCYLHIGH 0xda2014  // CylinderHigh
-#define GDEVHEAD 0xda2018  // Device/Head
-#define GCTRL 0xda3018     // Control
-// Gayle Ident
-#define GIDENT 0xDE1000
-
-// Gayle IRQ/CC
-#define GCS 0xDA8000   // Card Control
-#define GIRQ 0xDA9000  // IRQ
-#define GINT 0xDAA000  // Int enable
-#define GCONF 0xDAB000  // Gayle Config
-
-/* DA8000 */
-#define GAYLE_CS_IDE 0x80   /* IDE int status */
-#define GAYLE_CS_CCDET 0x40 /* credit card detect */
-#define GAYLE_CS_BVD1 0x20  /* battery voltage detect 1 */
-#define GAYLE_CS_SC 0x20    /* credit card status change */
-#define GAYLE_CS_BVD2 0x10  /* battery voltage detect 2 */
-#define GAYLE_CS_DA 0x10    /* digital audio */
-#define GAYLE_CS_WR 0x08    /* write enable (1 == enabled) */
-#define GAYLE_CS_BSY 0x04   /* credit card busy */
-#define GAYLE_CS_IRQ 0x04   /* interrupt request */
-#define GAYLE_CS_DAEN 0x02  /* enable digital audio */
-#define GAYLE_CS_DIS 0x01   /* disable PCMCIA slot */
-
-/* DA9000 */
-#define GAYLE_IRQ_IDE 0x80
-#define GAYLE_IRQ_CCDET 0x40 /* credit card detect */
-#define GAYLE_IRQ_BVD1 0x20  /* battery voltage detect 1 */
-#define GAYLE_IRQ_SC 0x20    /* credit card status change */
-#define GAYLE_IRQ_BVD2 0x10  /* battery voltage detect 2 */
-#define GAYLE_IRQ_DA 0x10    /* digital audio */
-#define GAYLE_IRQ_WR 0x08    /* write enable (1 == enabled) */
-#define GAYLE_IRQ_BSY 0x04   /* credit card busy */
-#define GAYLE_IRQ_IRQ 0x04   /* interrupt request */
-#define GAYLE_IRQ_RESET 0x02 /* reset machine after CCDET change */
-#define GAYLE_IRQ_BERR 0x01  /* generate bus error after CCDET change */
-
-/* DAA000 */
-#define GAYLE_INT_IDE 0x80     /* IDE interrupt enable */
-#define GAYLE_INT_CCDET 0x40   /* credit card detect change enable */
-#define GAYLE_INT_BVD1 0x20    /* battery voltage detect 1 change enable */
-#define GAYLE_INT_SC 0x20      /* credit card status change enable */
-#define GAYLE_INT_BVD2 0x10    /* battery voltage detect 2 change enable */
-#define GAYLE_INT_DA 0x10      /* digital audio change enable */
-#define GAYLE_INT_WR 0x08      /* write enable change enabled */
-#define GAYLE_INT_BSY 0x04     /* credit card busy */
-#define GAYLE_INT_IRQ 0x04     /* credit card interrupt request */
-#define GAYLE_INT_BVD_LEV 0x02 /* BVD int level, 0=lev2,1=lev6 */
-#define GAYLE_INT_BSY_LEV 0x01 /* BSY int level, 0=lev2,1=lev6 */
+#define DEBUG(...)
+//#define DEBUG printf
+
+uint8_t gary_cfg[8];
+
+uint8_t ramsey_cfg = 0x08;
+static uint8_t ramsey_id = RAMSEY_REV7;
 
 int counter;
 static uint8_t gayle_irq, gayle_cs, gayle_cs_mask, gayle_cfg;
-static struct ide_controller *ide0;
+static struct ide_controller *ide0 = NULL;
 int fd;
 
 uint8_t rtc_type = RTC_TYPE_RICOH;
@@ -105,13 +45,32 @@ char *hdd_image_file[GAYLE_MAX_HARDFILES];
 uint8_t cdtv_mode = 0;
 unsigned char cdtv_sram[32 * SIZE_KILO];
 
-uint8_t gayle_int;
+uint8_t gayle_a4k = 0xA0;
+uint16_t gayle_a4k_irq = 0;
+uint8_t gayle_a4k_int = 0;
+uint8_t gayle_int = 0;
+
+uint32_t gayle_ide_mask = ~GDATA;
+uint32_t gayle_ide_base = GDATA;
+uint8_t gayle_ide_enabled = 1;
+uint8_t gayle_emulation_enabled = 1;
+uint8_t gayle_ide_adj = 0;
 
 struct ide_controller *get_ide(int index) {
-  //if (index) {}
+  if (index) {}
   return ide0;
 }
 
+void adjust_gayle_4000() {
+  gayle_ide_base = GAYLE_IDE_BASE_A4000;
+  gayle_ide_adj = 2;
+  gayle_a4k_int = 1;
+}
+
+void adjust_gayle_1200() {
+
+}
+
 void set_hard_drive_image_file_amiga(uint8_t index, char *filename) {
   if (hdd_image_file[index] != NULL)
     free(hdd_image_file[index]);
@@ -120,19 +79,41 @@ void set_hard_drive_image_file_amiga(uint8_t index, char *filename) {
 }
 
 void InitGayle(void) {
-  if (!hdd_image_file[0]) {
-    hdd_image_file[0] = calloc(1, 64);
-    sprintf(hdd_image_file[0], "hd0.img");
-  }
+  uint8_t num_ide_drives = 0;
+
+  for (int i = 0; i < GAYLE_MAX_HARDFILES; i++) {
+    if (hdd_image_file[i]) {
+      fd = open(hdd_image_file[i], O_RDWR);
+      if (fd != -1) {
+        if (!ide0)
+            ide0 = ide_allocate("cf");
+      }
 
-  ide0 = ide_allocate("cf");
-  fd = open(hdd_image_file[0], O_RDWR);
-  if (fd == -1) {
-    printf("HDD Image %s failed open\n", hdd_image_file[0]);
-  } else {
-    ide_attach(ide0, 0, fd);
+      if (fd == -1) {
+        printf("[HDD%d] HDD Image %s failed open\n", i, hdd_image_file[i]);
+      } else {
+        printf("[HDD%d] Attaching HDD image %s.\n", i, hdd_image_file[i]);
+        if (strcmp(hdd_image_file[i] + (strlen(hdd_image_file[i]) - 3), "img") != 0) {
+          printf("No header present on HDD image %s.\n", hdd_image_file[i]);
+          ide_attach_hdf(ide0, i, fd);
+          num_ide_drives++;
+        }
+        else {
+          printf("Attaching HDD image with header.\n");
+          ide_attach(ide0, i, fd);
+          num_ide_drives++;
+        }
+        printf("[HDD%d] HDD Image %s attached\n", i, hdd_image_file[i]);
+      }
+    }
+  }
+  if (ide0)
     ide_reset_begin(ide0);
-    printf("HDD Image %s attached\n", hdd_image_file[0]);
+
+  if (num_ide_drives == 0) {
+    // No IDE drives mounted, disable IDE component of Gayle
+    printf("No IDE drives mounted, disabling Gayle IDE component.\n");
+    gayle_ide_enabled = 0;
   }
 }
 
@@ -140,7 +121,7 @@ uint8_t CheckIrq(void) {
   uint8_t irq;
 
   if (gayle_int & (1 << 7)) {
-    irq = ide0->drive->intrq;
+    irq = ide0->drive[0].intrq || ide0->drive[1].intrq;
     // if (irq==0)
     // printf("IDE IRQ: %x\n",irq);
     return irq;
@@ -148,71 +129,80 @@ uint8_t CheckIrq(void) {
   return 0;
 }
 
-void writeGayleB(unsigned int address, unsigned int value) {
-  if (address == GFEAT) {
-    ide_write8(ide0, ide_feature_w, value);
-    return;
-  }
-  if (address == GCMD) {
-    ide_write8(ide0, ide_command_w, value);
-    return;
-  }
-  if (address == GSECTCNT) {
-    ide_write8(ide0, ide_sec_count, value);
-    return;
-  }
-  if (address == GSECTNUM) {
-    ide_write8(ide0, ide_sec_num, value);
-    return;
-  }
-  if (address == GCYLLOW) {
-    ide_write8(ide0, ide_cyl_low, value);
-    return;
-  }
-  if (address == GCYLHIGH) {
-    ide_write8(ide0, ide_cyl_hi, value);
-    return;
-  }
-  if (address == GDEVHEAD) {
-    ide_write8(ide0, ide_dev_head, value);
-    return;
-  }
-  if (address == GCTRL) {
-    ide_write8(ide0, ide_devctrl_w, value);
-    return;
-  }
-
-  if (address == GIDENT) {
-    counter = 0;
-    // printf("Write Byte to Gayle Ident 0x%06x (0x%06x)\n",address,value);
-    return;
-  }
-
-  if (address == GIRQ) {
-    //  printf("Write Byte to Gayle GIRQ 0x%06x (0x%06x)\n",address,value);
-    gayle_irq = (gayle_irq & value) | (value & (GAYLE_IRQ_RESET | GAYLE_IRQ_BERR));
+static uint8_t ide_action = 0;
 
-    return;
-  }
-
-  if (address == GCS) {
-    printf("Write Byte to Gayle GCS 0x%06x (0x%06x)\n", address, value);
-    gayle_cs_mask = value & ~3;
-    gayle_cs &= ~3;
-    gayle_cs |= value & 3;
-    return;
-  }
-
-  if (address == GINT) {
-    printf("Write Byte to Gayle GINT 0x%06x (0x%06x)\n", address, value);
-    gayle_int = value;
-    return;
+void writeGayleB(unsigned int address, unsigned int value) {
+  if (ide0) {
+    if (address >= gayle_ide_base) {
+      switch ((address - gayle_ide_base) - gayle_ide_adj) {
+        case GFEAT_OFFSET:
+          //printf("Write to GFEAT: %.2X.\n", value);
+          ide_action = ide_feature_w;
+          goto idewrite8;
+        case GCMD_OFFSET:
+          //printf("Write to GCMD: %.2X.\n", value);
+          ide_action = ide_command_w;
+          goto idewrite8;
+        case GSECTCOUNT_OFFSET:
+          ide_action = ide_sec_count;
+          goto idewrite8;
+        case GSECTNUM_OFFSET:
+          ide_action = ide_sec_num;
+          goto idewrite8;
+        case GCYLLOW_OFFSET:
+          ide_action = ide_cyl_low;
+          goto idewrite8;
+        case GCYLHIGH_OFFSET:
+          ide_action = ide_cyl_hi;
+          goto idewrite8;
+        case GDEVHEAD_OFFSET:
+          //printf("Write to GDEVHEAD: %.2X.\n", value);
+          ide_action = ide_dev_head;
+          goto idewrite8;
+        case GCTRL_OFFSET:
+          //printf("Write to GCTRL: %.2X.\n", value);
+          ide_action = ide_devctrl_w;
+          goto idewrite8;
+        case GIRQ_4000_OFFSET:
+          gayle_a4k_irq = value;
+        case GIRQ_OFFSET:
+          gayle_irq = (gayle_irq & value) | (value & (GAYLE_IRQ_RESET | GAYLE_IRQ_BERR));
+          return;
+      }
+      goto skip_idewrite8;
+idewrite8:;
+      ide_write8(ide0, ide_action, value);
+      return;
+skip_idewrite8:;
+    }
   }
 
-  if (address == GCONF) {
-    printf("Write Byte to Gayle GCONF 0x%06x (0x%06x)\n", address, value);
-    gayle_cfg = value;
-    return;
+  switch (address) {
+    /*case 0xDD203A:
+      printf("Write bye to A4000 Gayle: %.2X\n", value);
+      gayle_a4k = value;
+      return;*/
+    case GIDENT:
+      //printf("Write to GIDENT: %d\n", value);
+      counter = 0;
+      return;
+    case GCONF:
+      //printf("Write to GCONF: %d\n", gayle_cfg);
+      gayle_cfg = value;
+      return;
+    case RAMSEY_REG:
+      ramsey_cfg = value & 0x0F;
+      return;
+    case GINT:
+      gayle_int = value;
+      return;
+    case GCS:
+      gayle_cs_mask = value & ~3;
+      gayle_cs &= ~3;
+      gayle_cs |= value & 3;
+      printf("Write to GCS: %d\n", gayle_cs);
+      //ide0->selected = gayle_cs;
+      return;
   }
 
   if ((address & GAYLEMASK) == CLOCKBASE) {
@@ -228,13 +218,20 @@ void writeGayleB(unsigned int address, unsigned int value) {
     return;
   }
 
-  printf("Write Byte to Gayle Space 0x%06x (0x%06x)\n", address, value);
+  DEBUG("Write Byte to Gayle Space 0x%06x (0x%06x)\n", address, value);
 }
 
 void writeGayle(unsigned int address, unsigned int value) {
-  if (address == GDATA) {
-    ide_write16(ide0, ide_data, value);
-    return;
+  if (ide0) {
+    if (address - gayle_ide_base == GDATA_OFFSET) {
+      ide_write16(ide0, ide_data, value);
+      return;
+    }
+
+    if (address == GIRQ_A4000) {
+      gayle_a4k_irq = value;
+      return;
+    }
   }
 
   if ((address & GAYLEMASK) == CLOCKBASE) {
@@ -251,7 +248,7 @@ void writeGayle(unsigned int address, unsigned int value) {
     return;
   }
 
-  printf("Write Word to Gayle Space 0x%06x (0x%06x)\n", address, value);
+  DEBUG("Write Word to Gayle Space 0x%06x (0x%06x)\n", address, value);
 }
 
 void writeGayleL(unsigned int address, unsigned int value) {
@@ -271,39 +268,104 @@ void writeGayleL(unsigned int address, unsigned int value) {
     return;
   }
 
-  printf("Write Long to Gayle Space 0x%06x (0x%06x)\n", address, value);
+  DEBUG("Write Long to Gayle Space 0x%06x (0x%06x)\n", address, value);
 }
 
 uint8_t readGayleB(unsigned int address) {
-  if (address == GERROR) {
-    return ide_read8(ide0, ide_error_r);
-  }
-  if (address == GSTATUS) {
-    return ide_read8(ide0, ide_status_r);
-  }
-
-  if (address == GSECTCNT) {
-    return ide_read8(ide0, ide_sec_count);
-  }
-
-  if (address == GSECTNUM) {
-    return ide_read8(ide0, ide_sec_num);
-  }
-
-  if (address == GCYLLOW) {
-    return ide_read8(ide0, ide_cyl_low);
-  }
-
-  if (address == GCYLHIGH) {
-    return ide_read8(ide0, ide_cyl_hi);
-  }
-
-  if (address == GDEVHEAD) {
-    return ide_read8(ide0, ide_dev_head);
-  }
+  if (ide0) {
+    uint8_t ide_action = 0, ide_val = 0;
+
+    if (address >= gayle_ide_base) {
+      switch ((address - gayle_ide_base) - gayle_ide_adj) {
+        case GERROR_OFFSET:
+          ide_action = ide_error_r;
+          goto ideread8;
+        case GSTATUS_OFFSET:
+          ide_action = ide_status_r;
+          goto ideread8;
+        case GSECTCOUNT_OFFSET:
+          ide_action = ide_sec_count;
+          goto ideread8;
+        case GSECTNUM_OFFSET:
+          ide_action = ide_sec_num;
+          goto ideread8;
+        case GCYLLOW_OFFSET:
+          ide_action = ide_cyl_low;
+          goto ideread8;
+        case GCYLHIGH_OFFSET:
+          ide_action = ide_cyl_hi;
+          goto ideread8;
+        case GDEVHEAD_OFFSET:
+          ide_action = ide_dev_head;
+          goto ideread8;
+        case GCTRL_OFFSET:
+          ide_action = ide_altst_r;
+          goto ideread8;
+        case GIRQ_4000_OFFSET:
+        case GIRQ_OFFSET:
+          return 0x80;
+          //gayle_irq = (gayle_irq & value) | (value & (GAYLE_IRQ_RESET | GAYLE_IRQ_BERR));
+      }
+      goto skip_ideread8;
+ideread8:;
+      ide_val = ide_read8(ide0, ide_action);
+      return ide_val;
+skip_ideread8:;
+    }
 
-  if (address == GCTRL) {
-    return ide_read8(ide0, ide_altst_r);
+    switch (address) {
+      case GIDENT: {
+        uint8_t val;
+        if (counter == 0 || counter == 1 || counter == 3) {
+          val = 0x80;  // 80; to enable gayle
+        } else {
+          val = 0x00;
+        }
+        counter++;
+        //printf("Read from GIDENT: %.2X.\n", val);
+        return val;
+      }
+      case GINT:
+        return gayle_int;
+      case GCONF:
+        //printf("Read from GCONF: %d\n", gayle_cfg & 0x0F);
+        return gayle_cfg & 0x0f;
+      case GCS: {
+        uint8_t v;
+        v = gayle_cs_mask | gayle_cs;
+        printf("Read from GCS: %d\n", v);
+        return v;
+      }
+      // This seems incorrect, GARY_REG3 is the same as GIDENT, and the A4000
+      // service manual says that Gary is accessible in the address range $DFC000 to $DFFFFF.
+      case GARY_REG0:
+      case GARY_REG1:
+      case GARY_REG2:
+        return gary_cfg[address - GARY_REG0];
+        break;
+      //case GARY_REG3:
+      case GARY_REG4:
+      //case GARY_REG5:
+        return gary_cfg[address - GARY_REG4];
+      case RAMSEY_ID:
+        return ramsey_id;
+      case RAMSEY_REG:
+        return ramsey_cfg;
+      case GARY_REG5: { // This makes no sense.
+        uint8_t val;
+        if (counter == 0 || counter == 1 || counter == 3) {
+          val = 0x80;  // 80; to enable GARY
+        } else {
+          val = 0x00;
+        }
+        counter++;
+        return val;
+      }
+      //case 0xDD203A:
+        // This can't be correct, as this is the same address as GDEVHEAD on the A4000 Gayle.
+        //printf("Read Byte from Gayle A4k: %.2X\n", gayle_a4k);
+        //return gayle_a4k;
+    }
   }
 
   if ((address & GAYLEMASK) == CLOCKBASE) {
@@ -318,62 +380,23 @@ uint8_t readGayleB(unsigned int address) {
     return get_rtc_byte(address, rtc_type);
   }
 
-  if (address == GIDENT) {
-    uint8_t val;
-    // printf("Read Byte from Gayle Ident 0x%06x (0x%06x)\n",address,counter);
-    if (counter == 0 || counter == 1 || counter == 3) {
-      val = 0x80;  // 80; to enable gayle
-    } else {
-      val = 0x00;
-    }
-    counter++;
-    return val;
-  }
-
-  if (address == GIRQ) {
-    // printf("Read Byte From GIRQ Space 0x%06x\n",gayle_irq);
-
-    return 0x80;//gayle_irq;
-/*
-    uint8_t irq;
-    irq = ide0->drive->intrq;
-
-    if (irq == 1) {
-      // printf("IDE IRQ: %x\n",irq);
-      return 0x80;  // gayle_irq;
-    }
-
-    return 0;
-*/ 
- }
-
-  if (address == GCS) {
-    printf("Read Byte From GCS Space 0x%06x\n", 0x1234);
-    uint8_t v;
-    v = gayle_cs_mask | gayle_cs;
-    return v;
-  }
-
-  if (address == GINT) {
-    // printf("Read Byte From GINT Space 0x%06x\n",gayle_int);
-    return gayle_int;
-  }
-
-  if (address == GCONF) {
-    printf("Read Byte From GCONF Space 0x%06x\n", gayle_cfg & 0x0f);
-    return gayle_cfg & 0x0f;
-  }
-
-  printf("Read Byte From Gayle Space 0x%06x\n", address);
+  DEBUG("Read Byte From Gayle Space 0x%06x\n", address);
   return 0xFF;
 }
 
 uint16_t readGayle(unsigned int address) {
-  if (address == GDATA) {
-    uint16_t value;
-    value = ide_read16(ide0, ide_data);
-    // value = (value << 8) | (value >> 8);
-    return value;
+  if (ide0) {
+    if (address - gayle_ide_base == GDATA_OFFSET) {
+      uint16_t value;
+      value = ide_read16(ide0, ide_data);
+      //       value = (value << 8) | (value >> 8);
+      return value;
+    }
+
+    if (address == GIRQ_A4000) {
+      gayle_a4k_irq = 0x8000;
+      return 0x8000;
+    }
   }
 
   if ((address & GAYLEMASK) == CLOCKBASE) {
@@ -388,7 +411,7 @@ uint16_t readGayle(unsigned int address) {
     return ((get_rtc_byte(address, rtc_type) << 8) | (get_rtc_byte(address + 1, rtc_type)));
   }
 
-  printf("Read Word From Gayle Space 0x%06x\n", address);
+  DEBUG("Read Word From Gayle Space 0x%06x\n", address);
   return 0x8000;
 }
 
@@ -405,6 +428,6 @@ uint32_t readGayleL(unsigned int address) {
     return ((get_rtc_byte(address, rtc_type) << 24) | (get_rtc_byte(address + 1, rtc_type) << 16) | (get_rtc_byte(address + 2, rtc_type) << 8) | (get_rtc_byte(address + 3, rtc_type)));
   }
 
-  printf("Read Long From Gayle Space 0x%06x\n", address);
+  DEBUG("Read Long From Gayle Space 0x%06x\n", address);
   return 0x8000;
 }