]> git.sesse.net Git - pistorm/blobdiff - platforms/amiga/Gayle.c
[WIP] PiSCSI custom file system experiments
[pistorm] / platforms / amiga / Gayle.c
index 520ca9bdfab867a737f3fb3888af314a8c57cd62..cf5729ad7406782c6db8a3ae6a1f1e4562a5fb80 100644 (file)
@@ -25,6 +25,9 @@
 #include "gayle-ide/ide.h"
 #include "amiga-registers.h"
 
+//#define DEBUG(...)
+#define DEBUG printf
+
 uint8_t gary_cfg[8];
 
 uint8_t ramsey_cfg = 0x08;
@@ -32,7 +35,7 @@ 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;
@@ -49,10 +52,12 @@ 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;
 }
 
@@ -74,16 +79,16 @@ 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");
-  }
-
-  ide0 = ide_allocate("cf");
+  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");
+      }
+
       if (fd == -1) {
         printf("[HDD%d] HDD Image %s failed open\n", i, hdd_image_file[i]);
       } else {
@@ -91,16 +96,25 @@ void InitGayle(void) {
         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]);
       }
     }
   }
-  ide_reset_begin(ide0);
+  if (ide0)
+    ide_reset_begin(ide0);
+  
+  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;
+  }
 }
 
 uint8_t CheckIrq(void) {
@@ -118,47 +132,49 @@ uint8_t CheckIrq(void) {
 static uint8_t ide_action = 0;
 
 void writeGayleB(unsigned int address, unsigned int value) {
-  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;
+  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;
+      ide_write8(ide0, ide_action, value);
+      return;
 skip_idewrite8:;
+    }
   }
 
   switch (address) {
@@ -206,14 +222,16 @@ skip_idewrite8:;
 }
 
 void writeGayle(unsigned int address, unsigned int value) {
-  if (address - gayle_ide_base == GDATA_OFFSET) {
-    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 == GIRQ_A4000) {
+      gayle_a4k_irq = value;
+      return;
+    }
   }
 
   if ((address & GAYLEMASK) == CLOCKBASE) {
@@ -254,100 +272,100 @@ void writeGayleL(unsigned int address, unsigned int value) {
 }
 
 uint8_t readGayleB(unsigned int address) {
-  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;
+  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);
-    //if (((address - gayle_ide_base) - gayle_ide_adj) == GDEVHEAD_OFFSET)
-      //printf("Read from GDEVHEAD: %.2X\n", ide_val);
-    return ide_read8(ide0, ide_action);
+      ide_val = ide_read8(ide0, ide_action);
+      return ide_val;
 skip_ideread8:;
-  }
+    }
 
-  switch (address) {
-    case GIDENT: {
-      uint8_t val;
-      if (counter == 0 || counter == 1 || counter == 3) {
-        val = 0x80;  // 80; to enable gayle
-      } else {
-        val = 0x00;
+    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;
       }
-      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;
+      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;
       }
-      counter++;
-      return val;
+      // 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;
     }
-    //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) {
@@ -367,16 +385,18 @@ skip_ideread8:;
 }
 
 uint16_t readGayle(unsigned int address) {
-  if (address - gayle_ide_base == GDATA_OFFSET) {
-    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 == GIRQ_A4000) {
+      gayle_a4k_irq = 0x8000;
+      return 0x8000;
+    }
   }
 
   if ((address & GAYLEMASK) == CLOCKBASE) {