]> git.sesse.net Git - pistorm/blobdiff - platforms/amiga/gayle-ide/ide.c
IDE updates, fix mouse hook hotkey
[pistorm] / platforms / amiga / gayle-ide / ide.c
index f82dfb53a1da6b29154bb2de791b5bf047acc55c..765bb139ff0cecc9aa9cd1ed54ba9553a7b62376 100644 (file)
@@ -25,6 +25,7 @@
 #include <errno.h>
 #include <time.h>
 #include <arpa/inet.h>
+#include "../../../config_file/config_file.h"
 
 #include "ide.h"
 
@@ -139,29 +140,34 @@ static off_t xlate_block(struct ide_taskfile *t)
   struct ide_drive *d = t->drive;
   uint16_t cyl;
 
-  if (t->lba4 & DEVH_LBA) {
+  if (d->controller->lba4 & DEVH_LBA) {
 /*    fprintf(stderr, "XLATE LBA %02X:%02X:%02X:%02X\n", 
       t->lba4, t->lba3, t->lba2, t->lba1);*/
     if (d->lba)
-      return 2 + (((t->lba4 & DEVH_HEAD) << 24) | (t->lba3 << 16) | (t->lba2 << 8) | t->lba1);
+      return ((d->header_present) ? 2 : 0) + (((t->drive->controller->lba4 & DEVH_HEAD) << 24) | (t->drive->controller->lba3 << 16) | (t->drive->controller->lba2 << 8) | t->drive->controller->lba1);
     ide_fault(d, "LBA on non LBA drive");
   }
 
   /* Some well known software asks for 0/0/0 when it means 0/0/1. Drives appear
      to interpret sector 0 as sector 1 */
-  if (t->lba1 == 0) {
+  if (t->drive->controller->lba1 == 0) {
     fprintf(stderr, "[Bug: request for sector offset 0].\n");
-    t->lba1 = 1;
+    t->drive->controller->lba1 = 1;
   }
-  cyl = (t->lba3 << 8) | t->lba2;
+  cyl = (t->drive->controller->lba3 << 8) | t->drive->controller->lba2;
   /* fprintf(stderr, "(H %d C %d S %d)\n", t->lba4 & DEVH_HEAD, cyl, t->lba1); */
-  if (t->lba1 == 0 || t->lba1 > d->sectors || t->lba4 >= d->heads || cyl >= d->cylinders) {
+  if (t->drive->controller->lba1 == 0 || t->drive->controller->lba1 > d->sectors || t->drive->controller->lba4 >= d->heads || cyl >= d->cylinders) {
     return -1;
   }
   /* Sector 1 is first */
   /* Images generally go cylinder/head/sector. This also matters if we ever
      implement more advanced geometry setting */
-  return 1 + ((cyl * d->heads) + (t->lba4 & DEVH_HEAD)) * d->sectors + t->lba1;
+  //off_t ret = ((d->header_present) ? 1 : -1) + ((cyl * d->heads) + (t->drive->controller->lba4 & DEVH_HEAD)) * d->sectors + t->drive->controller->lba1;
+  //printf("Non-LBA xlate block %lX.\n", ret);
+  //printf("Cyl: %d Heads: %d Sectors: %d\n", cyl, d->heads, d->sectors);
+  //printf("LBA1: %.2X LBA2: %.2X LBA3: %.2X LBA4: %.2X\n", t->drive->controller->lba1, t->drive->controller->lba2, t->drive->controller->lba3, t->drive->controller->lba4);
+
+  return ((d->header_present) ? 1 : -1) + ((cyl * d->heads) + (t->drive->controller->lba4 & DEVH_HEAD)) * d->sectors + t->drive->controller->lba1;
 }
 
 /* Indicate the drive is ready */
@@ -211,10 +217,10 @@ static void data_out_state(struct ide_taskfile *tf)
 static void edd_setup(struct ide_taskfile *tf)
 {
   tf->error = 0x01;            /* All good */
-  tf->lba1 = 0x01;             /* EDD always updates drive 0 */
-  tf->lba2 = 0x00;
-  tf->lba3 = 0x00;
-  tf->lba4 = 0x00;
+  tf->drive->controller->lba1 = 0x01;          /* EDD always updates drive 0 */
+  tf->drive->controller->lba2 = 0x00;
+  tf->drive->controller->lba3 = 0x00;
+  tf->drive->controller->lba4 = 0x00;
   tf->count = 0x01;
   ready(tf);
 }
@@ -233,6 +239,8 @@ void ide_reset(struct ide_controller *c)
     c->drive[1].taskfile.status = ST_DRDY;
     c->drive[1].eightbit = 0;
   }
+  if (c->selected != 0) {
+  }
   c->selected = 0;
 }
 
@@ -286,7 +294,7 @@ static void cmd_initparam_complete(struct ide_taskfile *tf)
 {
   struct ide_drive *d = tf->drive;
   /* We only support the current mapping */
-  if (tf->count != d->sectors || (tf->lba4 & DEVH_HEAD) + 1 != d->heads) {
+  if (tf->count != d->sectors || (tf->drive->controller->lba4 & DEVH_HEAD) + 1 != d->heads) {
     tf->status |= ST_ERR;
     tf->error |= ERR_ABRT;
     tf->drive->failed = 1;             /* Report ID NF until fixed */
@@ -426,20 +434,20 @@ static void cmd_writesectors_complete(struct ide_taskfile *tf)
 
 static void ide_set_error(struct ide_drive *d)
 {
-  d->taskfile.lba4 &= ~DEVH_HEAD;
+  d->controller->lba4 &= ~DEVH_HEAD;
 
-  if (d->taskfile.lba4 & DEVH_LBA) {
-    d->taskfile.lba1 = d->offset & 0xFF;
-    d->taskfile.lba2 = (d->offset >> 8) & 0xFF;
-    d->taskfile.lba3 = (d->offset >> 16) & 0xFF;
-    d->taskfile.lba4 |= (d->offset >> 24) & DEVH_HEAD;
+  if (d->controller->lba4 & DEVH_LBA) {
+    d->controller->lba1 = d->offset & 0xFF;
+    d->controller->lba2 = (d->offset >> 8) & 0xFF;
+    d->controller->lba3 = (d->offset >> 16) & 0xFF;
+    d->controller->lba4 |= (d->offset >> 24) & DEVH_HEAD;
   } else {
-    d->taskfile.lba1 = d->offset % d->sectors + 1;
+    d->controller->lba1 = d->offset % d->sectors + 1;
     d->offset /= d->sectors;
-    d->taskfile.lba4 |= d->offset / (d->cylinders * d->sectors);
+    d->controller->lba4 |= d->offset / (d->cylinders * d->sectors);
     d->offset %= (d->cylinders * d->sectors);
-    d->taskfile.lba2 = d->offset & 0xFF;
-    d->taskfile.lba3 = (d->offset >> 8) & 0xFF;
+    d->controller->lba2 = d->offset & 0xFF;
+    d->controller->lba3 = (d->offset >> 8) & 0xFF;
   }
   d->taskfile.count = d->length;
   d->taskfile.status |= ST_ERR;
@@ -607,13 +615,13 @@ uint8_t ide_read8(struct ide_controller *c, uint8_t r)
     case ide_sec_count:
       return t->count;
     case ide_lba_low:
-      return t->lba1;
+      return c->lba1;
     case ide_lba_mid:
-      return t->lba2;
+      return c->lba2;
     case ide_lba_hi:
-      return t->lba3;
+      return c->lba3;
     case ide_lba_top:
-      return t->lba4;
+      return c->lba4 | ((c->selected) ? 0x10 : 0x00);
     case ide_status_r:
       d->intrq = 0;            /* Acked */
     case ide_altst_r:
@@ -641,6 +649,8 @@ void ide_write8(struct ide_controller *c, uint8_t r, uint8_t v)
     }
   }
 
+  uint8_t ve;
+
   switch(r) {
     case ide_data:
       ide_data_out(d, v, 1);
@@ -652,17 +662,17 @@ void ide_write8(struct ide_controller *c, uint8_t r, uint8_t v)
       t->count = v;
       break;
     case ide_lba_low:
-      t->lba1 = v;
+      c->lba1 = v;
       break;
     case ide_lba_mid:
-      t->lba2 = v;
+      c->lba2 = v;
       break;
     case ide_lba_hi:
-      t->lba3 = v;
+      c->lba3 = v;
       break;
     case ide_lba_top:
       c->selected = (v & DEVH_DEV) ? 1 : 0;
-      c->drive[c->selected].taskfile.lba4 = v & (DEVH_HEAD|DEVH_DEV|DEVH_LBA);
+      c->lba4 = v & (DEVH_HEAD|/*DEVH_DEV|*/DEVH_LBA);
       break;
     case ide_command_w:
       t->command = v; 
@@ -755,6 +765,7 @@ int ide_attach(struct ide_controller *c, int drive, int fd)
   d->heads = d->identify[3];
   d->sectors = d->identify[6];
   d->cylinders = le16(d->identify[1]);
+  d->header_present = 1;
   if (d->identify[49] & le16(1 << 9))
     d->lba = 1;
   else
@@ -762,6 +773,52 @@ int ide_attach(struct ide_controller *c, int drive, int fd)
   return 0;
 }
 
+// Attach a headerless HDD image to the controller
+int ide_attach_hdf(struct ide_controller *c, int drive, int fd)
+{
+  struct ide_drive *d = &c->drive[drive];
+  if (d->present) {
+    printf("[IDE/HDL] Drive already attached.\n");
+    return -1;
+  }
+
+  d->fd = fd;
+  d->present = 1;
+  d->lba = 0;
+
+  d->heads = 255;
+  d->sectors = 63;
+  d->header_present = 0;
+
+  uint64_t file_size = lseek(fd, 0, SEEK_END);
+  lseek(fd, 1024, SEEK_SET);
+
+  if (file_size < 500 * SIZE_MEGA) {
+    d->heads = 16;
+  }
+  else if (file_size < 1000 * SIZE_MEGA) {
+    d->heads = 32;
+  }
+  else if (file_size < 2000 * SIZE_MEGA) {
+    d->heads = 64;
+  }
+  else if (file_size < (uint64_t)4000 * SIZE_MEGA) {
+    d->heads = 128;
+  }
+
+  d->cylinders = (file_size / 512) / (d->sectors * d->heads);
+
+  printf("[IDE/HDL] Cylinders: %d Heads: %d Sectors: %d\n", d->cylinders, d->heads, d->sectors);
+
+  if (file_size >= 4 * 1000 * 1000) {
+    d->lba = 1;
+  }
+
+  ide_make_ident(d->cylinders, d->heads, d->sectors, "PISTORM HDD IMAGE v0.1", d->identify);
+
+  return 0;
+}
+
 /*
  *     Detach an IDE device from the interface (not hot pluggable)
  */
@@ -837,6 +894,40 @@ static void make_serial(uint16_t *p)
   make_ascii(p, buf, 20);
 }
 
+int ide_make_ident(uint16_t c, uint8_t h, uint8_t s, char *name, uint16_t *target)
+{
+  uint16_t *ident = target;
+  uint32_t sectors;
+
+  memset(ident, 0, 512);
+  memcpy(ident, ide_magic, 8);
+
+  memset(ident, 0, 8);
+  ident[0] = le16((1 << 15) | (1 << 6));       /* Non removable */
+  make_serial(ident + 10);
+  ident[47] = 0; /* no read multi for now */
+  ident[51] = le16(240 /* PIO2 */ << 8);       /* PIO cycle time */
+  ident[53] = le16(1);         /* Geometry words are valid */
+
+  make_ascii(ident + 23, "A001.001", 8);
+  make_ascii(ident + 27, name, 40);
+  ident[49] = le16(1 << 9); /* LBA */
+
+  ident[1] = le16(c);
+  ident[3] = le16(h);
+  ident[6] = le16(s);
+  ident[54] = ident[1];
+  ident[55] = ident[3];
+  ident[56] = ident[6];
+  sectors = c * h * s;
+  ident[57] = le16(sectors & 0xFFFF);
+  ident[58] = le16(sectors >> 16);
+  ident[60] = ident[57];
+  ident[61] = ident[58];
+
+  return 0;
+}
+
 int ide_make_drive(uint8_t type, int fd)
 {
   uint8_t s, h;