}
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);
- ide_reset_begin(ide0);
- printf("HDD Image %s attached\n", hdd_image_file[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) {
+ 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);
+ }
+ else {
+ printf("Attaching HDD image with header.\n");
+ ide_attach(ide0, i, fd);
+ }
+ printf("[HDD%d] HDD Image %s attached\n", i, hdd_image_file[i]);
+ }
+ }
}
+ ide_reset_begin(ide0);
}
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;
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_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 = 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:
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;
}
}
uint8_t readGayleB(unsigned int address) {
- uint8_t ide_action = 0;
+ uint8_t ide_action = 0, ide_val = 0;
if (address >= gayle_ide_base) {
switch ((address - gayle_ide_base) - gayle_ide_adj) {
}
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);
skip_ideread8:;
}
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
#include <errno.h>
#include <time.h>
#include <arpa/inet.h>
+#include "../../../config_file/config_file.h"
#include "ide.h"
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 */
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);
}
c->drive[1].taskfile.status = ST_DRDY;
c->drive[1].eightbit = 0;
}
+ if (c->selected != 0) {
+ }
c->selected = 0;
}
{
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 */
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;
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:
}
}
+ uint8_t ve;
+
switch(r) {
case ide_data:
ide_data_out(d, v, 1);
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;
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
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)
*/
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;