From 975ce97643fd0d74fa1befc8e51d6d7872c735e2 Mon Sep 17 00:00:00 2001 From: beeanyew Date: Wed, 14 Apr 2021 19:46:37 +0200 Subject: [PATCH] Remove IDE emulation, update default.cfg with a note about it --- Makefile | 1 - default.cfg | 8 +- emulator.c | 1 - ide/ide.c | 934 ---------------------------- ide/ide.h | 82 --- ide/makedisk | Bin 23612 -> 0 bytes ide/makedisk.c | 29 - platforms/amiga/Gayle.c | 69 ++- platforms/amiga/Gayle.h | 3 - platforms/amiga/gayle-ide/ide.c | 1032 ------------------------------- platforms/amiga/gayle-ide/ide.h | 86 --- 11 files changed, 44 insertions(+), 2201 deletions(-) delete mode 100644 ide/ide.c delete mode 100644 ide/ide.h delete mode 100755 ide/makedisk delete mode 100644 ide/makedisk.c delete mode 100644 platforms/amiga/gayle-ide/ide.c delete mode 100644 platforms/amiga/gayle-ide/ide.h diff --git a/Makefile b/Makefile index c3483e0..3396440 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,6 @@ MAINFILES = emulator.c \ platforms/dummy/dummy-registers.c \ platforms/amiga/Gayle.c \ platforms/amiga/hunk-reloc.c \ - platforms/amiga/gayle-ide/ide.c \ platforms/amiga/cdtv-dmac.c \ platforms/amiga/rtg/rtg.c \ platforms/amiga/rtg/rtg-output.c \ diff --git a/default.cfg b/default.cfg index 73b0363..0d66add 100644 --- a/default.cfg +++ b/default.cfg @@ -20,16 +20,16 @@ map type=ram address=0x10000000 size=128M id=z3_autoconf_fast #map type=ram address=0x0 size=2M # Map Gayle as a register range. -map type=register address=0xD80000 size=0x70000 +# NOTE: Gayle emulation is currently non-functional. Do not enable this. +#map type=register address=0xD80000 size=0x40000 +# Map RTC as a register range. +map type=register address=0xDC0000 size=0x30000 # Number of instructions to run every main loop. loopcycles 300 # Set the platform to Amiga to enable all the registers and stuff. platform amiga # Uncomment to let reads/writes through from/to the RTC memory range #setvar enable_rtc_emulation 0 -# Uncomment to set a HD image file for ide0 drive 0/1 -#setvar hdd0 snakes.img -#setvar hdd1 snakes2.img # Uncomment to enable RTG #setvar rtg # Uncomment to enable CDTV mode (not working, requires Kickstart 1.3+CDTV extended ROM) diff --git a/emulator.c b/emulator.c index 8129e29..157cb64 100644 --- a/emulator.c +++ b/emulator.c @@ -4,7 +4,6 @@ #include "input/input.h" #include "platforms/amiga/Gayle.h" -#include "platforms/amiga/gayle-ide/ide.h" #include "platforms/amiga/amiga-registers.h" #include "platforms/amiga/rtg/rtg.h" #include "platforms/amiga/hunk-reloc.h" diff --git a/ide/ide.c b/ide/ide.c deleted file mode 100644 index 148eb04..0000000 --- a/ide/ide.c +++ /dev/null @@ -1,934 +0,0 @@ -/* - * IDE Emulation Layer for retro-style PIO interfaces - * - * (c) Copyright Alan Cox, 2015-2019 - * - * IDE-emu is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * IDE-emu is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with IDE-emu. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ide.h" - -#define IDE_IDLE 0 -#define IDE_CMD 1 -#define IDE_DATA_IN 2 -#define IDE_DATA_OUT 3 - -#define DCR_NIEN 2 -#define DCR_SRST 4 - -#define DEVH_HEAD 15 -#define DEVH_DEV 16 -#define DEVH_LBA 64 - -#define ERR_AMNF 1 -#define ERR_TKNONF 2 -#define ERR_ABRT 4 -#define ERR_MCR 8 -#define ERR_IDNF 16 -#define ERR_MC 32 -#define ERR_UNC 64 - -#define ST_ERR 1 -#define ST_IDX 2 -#define ST_CORR 4 -#define ST_DRQ 8 -#define ST_DSC 16 -#define ST_DF 32 -#define ST_DRDY 64 -#define ST_BSY 128 - -#define DCL_SRST 4 -#define DCL_NIEN 2 - -#define IDE_CMD_CALIB 0x10 -#define IDE_CMD_READ 0x20 -#define IDE_CMD_READ_NR 0x21 -#define IDE_CMD_WRITE 0x30 -#define IDE_CMD_WRITE_NR 0x31 -#define IDE_CMD_VERIFY 0x40 -#define IDE_CMD_VERIFY_NR 0x41 -#define IDE_CMD_SEEK 0x70 -#define IDE_CMD_EDD 0x90 -#define IDE_CMD_INTPARAMS 0x91 -#define IDE_CMD_IDENTIFY 0xEC -#define IDE_CMD_SETFEATURES 0xEF - -const uint8_t ide_magic[8] = { - '1','D','E','D','1','5','C','0' -}; - -static char *charmap(uint8_t v) -{ - static char cbuf[3]; - if (v < 32) - sprintf(cbuf, "^%c", '@'+v); - else if (v < 127) - sprintf(cbuf, " %c", v); - else if (v == 127) - sprintf(cbuf, "DL"); - else if (v < 160) - sprintf(cbuf, ":%c", '@' + v - 128); - else if (v < 255) - sprintf(cbuf, "~%c", v - 128); - else - sprintf(cbuf, "!D"); - return cbuf; -} - -static void hexdump(uint8_t *bp) -{ - int i,j; - for (i = 0; i < 512; i+= 16) { - for(j = 0; j < 16; j++) - fprintf(stderr, "%02X ", bp[i+j]); - fprintf(stderr, "|"); - for(j = 0; j < 16; j++) - fprintf(stderr, "%2s", charmap(bp[i+j])); - fprintf(stderr, "\n"); - } -} - -/* FIXME: use proper endian convertors! */ -static uint16_t le16(uint16_t v) -{ - uint8_t *p = (uint8_t *)&v; - return p[0] | (p[1] << 8); -} - -static void ide_xlate_errno(struct ide_taskfile *t, int len) -{ - t->status |= ST_ERR; - if (len == -1) { - if (errno == EIO) - t->error = ERR_UNC; - else - t->error = ERR_AMNF; - } else - t->error = ERR_AMNF; -} - -static void ide_fault(struct ide_drive *d, const char *p) -{ - fprintf(stderr, "ide: %s: %d: %s\n", d->controller->name, - (int)(d - d->controller->drive), p); -} - -/* Disk translation */ -static off_t xlate_block(struct ide_taskfile *t) -{ - struct ide_drive *d = t->drive; - uint16_t cyl; - - if (t->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); - 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) { - fprintf(stderr, "[Bug: request for sector offset 0].\n"); - t->lba1 = 1; - } - cyl = (t->lba3 << 8) | t->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) { - 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; -} - -/* Indicate the drive is ready */ -static void ready(struct ide_taskfile *tf) -{ - tf->status &= ~(ST_BSY|ST_DRQ); - tf->status |= ST_DRDY; - tf->drive->state = IDE_IDLE; -} - -/* Return to idle state, completing a command */ -static void completed(struct ide_taskfile *tf) -{ - ready(tf); - tf->drive->intrq = 1; -} - -static void drive_failed(struct ide_taskfile *tf) -{ - tf->status |= ST_ERR; - tf->error = ERR_IDNF; - ready(tf); -} - -static void data_in_state(struct ide_taskfile *tf) -{ - struct ide_drive *d = tf->drive; - d->state = IDE_DATA_IN; - d->dptr = d->data + 512; - /* We don't clear DRDY here, drives may well accept a command at this - point and at least one firmware for RC2014 assumes this */ - tf->status &= ~ST_BSY; - tf->status |= ST_DRQ; - d->intrq = 1; /* Double check */ -} - -static void data_out_state(struct ide_taskfile *tf) -{ - struct ide_drive *d = tf->drive; - d->state = IDE_DATA_OUT; - d->dptr = d->data; - tf->status &= ~ (ST_BSY|ST_DRDY); - tf->status |= ST_DRQ; - d->intrq = 1; /* Double check */ -} - -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->count = 0x01; - ready(tf); -} - -void ide_reset(struct ide_controller *c) -{ - if (c->drive[0].present) { - edd_setup(&c->drive[0].taskfile); - /* A drive could clear busy then set DRDY up to 2 minutes later if its - mindnumbingly slow to start up ! We don't emulate any of that */ - c->drive[0].taskfile.status = ST_DRDY; - c->drive[0].eightbit = 0; - } - if (c->drive[1].present) { - edd_setup(&c->drive[1].taskfile); - c->drive[1].taskfile.status = ST_DRDY; - c->drive[1].eightbit = 0; - } - c->selected = 0; -} - -void ide_reset_begin(struct ide_controller *c) -{ - if (c->drive[0].present) - c->drive[0].taskfile.status |= ST_BSY; - if (c->drive[1].present) - c->drive[1].taskfile.status |= ST_BSY; - /* Ought to be a time delay relative to reset or power on */ - ide_reset(c); -} - -static void ide_srst_begin(struct ide_controller *c) -{ - ide_reset(c); - if (c->drive[0].present) - c->drive[0].taskfile.status |= ST_BSY; - if (c->drive[1].present) - c->drive[1].taskfile.status |= ST_BSY; -} - -static void ide_srst_end(struct ide_controller *c) -{ - /* Could be time delays here */ - ready(&c->drive[0].taskfile); - ready(&c->drive[1].taskfile); -} - -static void cmd_edd_complete(struct ide_taskfile *tf) -{ - struct ide_controller *c = tf->drive->controller; - if (c->drive[0].present) - edd_setup(&c->drive[0].taskfile); - if (c->drive[1].present) - edd_setup(&c->drive[1].taskfile); - c->selected = 0; -} - -static void cmd_identify_complete(struct ide_taskfile *tf) -{ - struct ide_drive *d = tf->drive; - memcpy(d->data, d->identify, 512); - data_in_state(tf); - /* Arrange to copy just the identify buffer */ - d->dptr = d->data; - d->length = 1; -} - -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) { - tf->status |= ST_ERR; - tf->error |= ERR_ABRT; - tf->drive->failed = 1; /* Report ID NF until fixed */ -/* fprintf(stderr, "geo is %d %d, asked for %d %d\n", - d->sectors, d->heads, tf->count, (tf->lba4 & DEVH_HEAD) + 1); */ - ide_fault(d, "invalid geometry"); - } else if (tf->drive->failed == 1) - tf->drive->failed = 0; /* Valid translation */ - completed(tf); -} - -static void cmd_readsectors_complete(struct ide_taskfile *tf) -{ - struct ide_drive *d = tf->drive; - /* Move to data xfer */ - if (d->failed) { - drive_failed(tf); - return; - } - d->offset = xlate_block(tf); - /* DRDY is not guaranteed here but at least one buggy RC2014 firmware - expects it */ - tf->status |= ST_DRQ | ST_DSC | ST_DRDY; - tf->status &= ~ST_BSY; - /* 0 = 256 sectors */ - d->length = tf->count ? tf->count : 256; - /* fprintf(stderr, "READ %d SECTORS @ %ld\n", d->length, d->offset); */ - if (d->offset == -1 || lseek(d->fd, 512 * d->offset, SEEK_SET) == -1) { - tf->status |= ST_ERR; - tf->status &= ~ST_DSC; - tf->error |= ERR_IDNF; - /* return null data */ - completed(tf); - return; - } - /* do the xfer */ - data_in_state(tf); -} - -static void cmd_verifysectors_complete(struct ide_taskfile *tf) -{ - struct ide_drive *d = tf->drive; - /* Move to data xfer */ - if (d->failed) { - drive_failed(tf); - return; - } - d->offset = xlate_block(tf); - /* 0 = 256 sectors */ - d->length = tf->count ? tf->count : 256; - if (d->offset == -1 || lseek(d->fd, 512 * (d->offset + d->length - 1), SEEK_SET) == -1) { - tf->status &= ~ST_DSC; - tf->status |= ST_ERR; - tf->error |= ERR_IDNF; - } - tf->status |= ST_DSC; - completed(tf); -} - -static void cmd_recalibrate_complete(struct ide_taskfile *tf) -{ - struct ide_drive *d = tf->drive; - if (d->failed) - drive_failed(tf); - if (d->offset == -1 || xlate_block(tf) != 0L) { - tf->status &= ~ST_DSC; - tf->status |= ST_ERR; - tf->error |= ERR_ABRT; - } - tf->status |= ST_DSC; - completed(tf); -} - -static void cmd_seek_complete(struct ide_taskfile *tf) -{ - struct ide_drive *d = tf->drive; - if (d->failed) - drive_failed(tf); - d->offset = xlate_block(tf); - if (d->offset == -1 || lseek(d->fd, 512 * d->offset, SEEK_SET) == -1) { - tf->status &= ~ST_DSC; - tf->status |= ST_ERR; - tf->error |= ERR_IDNF; - } - tf->status |= ST_DSC; - completed(tf); -} - -static void cmd_setfeatures_complete(struct ide_taskfile *tf) -{ - struct ide_drive *d = tf->drive; - switch(tf->feature) { - case 0x01: - d->eightbit = 1; - break; - case 0x03: - if ((tf->count & 0xF0) >= 0x20) { - tf->status |= ST_ERR; - tf->error |= ERR_ABRT; - } - /* Silently accept PIO mode settings */ - break; - case 0x81: - d->eightbit = 0; - break; - default: - tf->status |= ST_ERR; - tf->error |= ERR_ABRT; - } - completed(tf); -} - -static void cmd_writesectors_complete(struct ide_taskfile *tf) -{ - struct ide_drive *d = tf->drive; - /* Move to data xfer */ - if (d->failed) { - drive_failed(tf); - return; - } - d->offset = xlate_block(tf); - tf->status |= ST_DRQ; - /* 0 = 256 sectors */ - d->length = tf->count ? tf->count : 256; -/* fprintf(stderr, "WRITE %d SECTORS @ %ld\n", d->length, d->offset); */ - if (d->offset == -1 || lseek(d->fd, 512 * d->offset, SEEK_SET) == -1) { - tf->status |= ST_ERR; - tf->error |= ERR_IDNF; - tf->status &= ~ST_DSC; - /* return null data */ - completed(tf); - return; - } - /* do the xfer */ - data_out_state(tf); -} - -static void ide_set_error(struct ide_drive *d) -{ - d->taskfile.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; - } else { - d->taskfile.lba1 = d->offset % d->sectors + 1; - d->offset /= d->sectors; - d->taskfile.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->taskfile.count = d->length; - d->taskfile.status |= ST_ERR; - d->state = IDE_IDLE; - completed(&d->taskfile); -} - -static int ide_read_sector(struct ide_drive *d) -{ - int len; - - d->dptr = d->data; - if ((len = read(d->fd, d->data, 512)) != 512) { - perror("ide_read_sector"); - d->taskfile.status |= ST_ERR; - d->taskfile.status &= ~ST_DSC; - ide_xlate_errno(&d->taskfile, len); - return -1; - } -// hexdump(d->data); - d->offset += 512; - return 0; -} - -static int ide_write_sector(struct ide_drive *d) -{ - int len; - - d->dptr = d->data; - if ((len = write(d->fd, d->data, 512)) != 512) { - d->taskfile.status |= ST_ERR; - d->taskfile.status &= ~ST_DSC; - ide_xlate_errno(&d->taskfile, len); - return -1; - } -// hexdump(d->data); - d->offset += 512; - return 0; -} - -static uint16_t ide_data_in(struct ide_drive *d, int len) -{ - uint16_t v; - if (d->state == IDE_DATA_IN) { - if (d->dptr == d->data + 512) { - if (ide_read_sector(d) < 0) { - ide_set_error(d); /* Set the LBA or CHS etc */ - return 0xFFFF; /* and error bits set by read_sector */ - } - } - v = *d->dptr; - if (!d->eightbit) { - if (len == 2) - v |= (d->dptr[1] << 8); - d->dptr+=2; - } else - d->dptr++; - d->taskfile.data = v; - if (d->dptr == d->data + 512) { - d->length--; - d->intrq = 1; /* we don't yet emulate multimode */ - if (d->length == 0) { - d->state = IDE_IDLE; - completed(&d->taskfile); - } - } - } else - ide_fault(d, "bad data read"); - - if (len == 1) - return d->taskfile.data & 0xFF; - return d->taskfile.data; -} - -static void ide_data_out(struct ide_drive *d, uint16_t v, int len) -{ - if (d->state != IDE_DATA_OUT) { - ide_fault(d, "bad data write"); - d->taskfile.data = v; - } else { - if (d->eightbit) - v &= 0xFF; - *d->dptr++ = v; - d->taskfile.data = v; - if (!d->eightbit) { - *d->dptr++ = v >> 8; - d->taskfile.data = v >> 8; - } - if (d->dptr == d->data + 512) { - if (ide_write_sector(d) < 0) { - ide_set_error(d); - return; - } - d->length--; - d->intrq = 1; - if (d->length == 0) { - d->state = IDE_IDLE; - d->taskfile.status |= ST_DSC; - completed(&d->taskfile); - } - } - } -} - -static void ide_issue_command(struct ide_taskfile *t) -{ - t->status &= ~(ST_ERR|ST_DRDY); - t->status |= ST_BSY; - t->error = 0; - t->drive->state = IDE_CMD; - - /* We could complete with delays but don't do so yet */ - switch(t->command) { - case IDE_CMD_EDD: /* 0x90 */ - cmd_edd_complete(t); - break; - case IDE_CMD_IDENTIFY: /* 0xEC */ - cmd_identify_complete(t); - break; - case IDE_CMD_INTPARAMS: /* 0x91 */ - cmd_initparam_complete(t); - break; - case IDE_CMD_READ: /* 0x20 */ - case IDE_CMD_READ_NR: /* 0x21 */ - cmd_readsectors_complete(t); - break; - case IDE_CMD_SETFEATURES: /* 0xEF */ - cmd_setfeatures_complete(t); - break; - case IDE_CMD_VERIFY: /* 0x40 */ - case IDE_CMD_VERIFY_NR: /* 0x41 */ - cmd_verifysectors_complete(t); - break; - case IDE_CMD_WRITE: /* 0x30 */ - case IDE_CMD_WRITE_NR: /* 0x31 */ - cmd_writesectors_complete(t); - break; - default: - if ((t->command & 0xF0) == IDE_CMD_CALIB) /* 1x */ - cmd_recalibrate_complete(t); - else if ((t->command & 0xF0) == IDE_CMD_SEEK) /* 7x */ - cmd_seek_complete(t); - else { - /* Unknown */ - t->status |= ST_ERR; - t->error |= ERR_ABRT; - completed(t); - } - } -} - -/* - * 8bit IDE controller emulation - */ - -uint8_t ide_read8(struct ide_controller *c, uint8_t r) -{ - struct ide_drive *d = &c->drive[c->selected]; - struct ide_taskfile *t = &d->taskfile; - switch(r) { - case ide_data: - return ide_data_in(d, 1); - case ide_error_r: - return t->error; - case ide_sec_count: - return t->count; - case ide_lba_low: - return t->lba1; - case ide_lba_mid: - return t->lba2; - case ide_lba_hi: - return t->lba3; - case ide_lba_top: - return t->lba4; - case ide_status_r: - d->intrq = 0; /* Acked */ - case ide_altst_r: - return t->status; - default: - ide_fault(d, "bogus register"); - return 0xFF; - } -} - -void ide_write8(struct ide_controller *c, uint8_t r, uint8_t v) -{ - struct ide_drive *d = &c->drive[c->selected]; - struct ide_taskfile *t = &d->taskfile; - - if (r != ide_devctrl_w) { - if (t->status & ST_BSY) { - ide_fault(d, "command written while busy"); - return; - } - /* Not clear this is the right emulation */ - if (d->present == 0 && r != ide_lba_top) { - ide_fault(d, "not present"); - return; - } - } - - switch(r) { - case ide_data: - ide_data_out(d, v, 1); - break; - case ide_feature_w: - t->feature = v; - break; - case ide_sec_count: - t->count = v; - break; - case ide_lba_low: - t->lba1 = v; - break; - case ide_lba_mid: - t->lba2 = v; - break; - case ide_lba_hi: - t->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); - break; - case ide_command_w: - t->command = v; - ide_issue_command(t); - break; - case ide_devctrl_w: - /* ATA: "When the Device Control register is written, both devices - respond to the write regardless of which device is selected" */ - if ((v ^ t->devctrl) & DCL_SRST) { - if (v & DCL_SRST) - ide_srst_begin(c); - else - ide_srst_end(c); - } - c->drive[0].taskfile.devctrl = v; /* Check versus real h/w does this end up cleared */ - c->drive[1].taskfile.devctrl = v; - break; - } -} - -/* - * 16bit IDE controller emulation - */ - -uint16_t ide_read16(struct ide_controller *c, uint8_t r) -{ - struct ide_drive *d = &c->drive[c->selected]; - if (r == ide_data) - return htons(ide_data_in(d,2)); - return ide_read8(c, r); -} - -void ide_write16(struct ide_controller *c, uint8_t r, uint16_t v) -{ - struct ide_drive *d = &c->drive[c->selected]; - struct ide_taskfile *t = &d->taskfile; - - if (r != ide_devctrl_w && (t->status & ST_BSY)) { - ide_fault(d, "command written while busy"); - return; - } - if (r == ide_data) - ide_data_out(d, ntohs(v), 2); - else - ide_write8(c, r, v); -} - -/* - * Allocate a new IDE controller emulation - */ -struct ide_controller *ide_allocate(const char *name) -{ - struct ide_controller *c = calloc(1, sizeof(*c)); - if (c == NULL) - return NULL; - c->name = strdup(name); - if (c->name == NULL) { - free(c); - return NULL; - } - c->drive[0].controller = c; - c->drive[1].controller = c; - c->drive[0].taskfile.drive = &c->drive[0]; - c->drive[1].taskfile.drive = &c->drive[1]; - return c; -} - -/* - * Attach a file to a device on the controller - */ -int ide_attach(struct ide_controller *c, int drive, int fd) -{ - struct ide_drive *d = &c->drive[drive]; - if (d->present) { - ide_fault(d, "double attach"); - return -1; - } - d->fd = fd; - if (read(d->fd, d->data, 512) != 512 || - read(d->fd, d->identify, 512) != 512) { - ide_fault(d, "i/o error on attach"); - return -1; - } - if (memcmp(d->data, ide_magic, 8)) { - ide_fault(d, "bad magic"); - return -1; - } - d->fd = fd; - d->present = 1; - d->heads = d->identify[3]; - d->sectors = d->identify[6]; - d->cylinders = le16(d->identify[1]); - if (d->identify[49] & le16(1 << 9)) - d->lba = 1; - else - d->lba = 0; - return 0; -} - -/* - * Detach an IDE device from the interface (not hot pluggable) - */ -void ide_detach(struct ide_drive *d) -{ - close(d->fd); - d->fd = -1; - d->present = 0; -} - -/* - * Free up and release and IDE controller - */ -void ide_free(struct ide_controller *c) -{ - if (c->drive[0].present) - ide_detach(&c->drive[0]); - if (c->drive[1].present) - ide_detach(&c->drive[1]); - free((void *)c->name); - free(c); -} - -/* - * Emulation interface for an 8bit controller using latches on the - * data register - */ -uint8_t ide_read_latched(struct ide_controller *c, uint8_t reg) -{ - uint16_t v; - if (reg == ide_data_latch) - return c->data_latch; - v = ide_read16(c, reg); - if (reg == ide_data) { - c->data_latch = v >> 8; - v &= 0xFF; - } - return v; -} - -void ide_write_latched(struct ide_controller *c, uint8_t reg, uint8_t v) -{ - uint16_t d = v; - - if (reg == ide_data_latch) { - c->data_latch = v; - return; - } - if (reg == ide_data) - d |= (c->data_latch << 8); - ide_write16(c, reg, d); -} - -static void make_ascii(uint16_t *p, const char *t, int len) -{ - int i; - char *d = (char *)p; - strncpy(d, t, len); - - for (i = 0; i < len; i += 2) { - char c = *d; - *d = d[1]; - d[1] = c; - d += 2; - } -} - -static void make_serial(uint16_t *p) -{ - char buf[21]; - srand(getpid()^time(NULL)); - snprintf(buf, 21, "%08d%08d%04d", rand(), rand(), rand()); - make_ascii(p, buf, 20); -} - -int ide_make_drive(uint8_t type, int fd) -{ - uint8_t s, h; - uint16_t c; - uint32_t sectors; - uint16_t ident[256]; - - if (type < 1 || type > MAX_DRIVE_TYPE) - return -2; - - memset(ident, 0, 512); - memcpy(ident, ide_magic, 8); - if (write(fd, ident, 512) != 512) - return -1; - - 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 */ - - switch(type) { - case ACME_ROADRUNNER: - /* 504MB drive with LBA support */ - c = 1024; - h = 16; - s = 63; - make_ascii(ident + 23, "A001.001", 8); - make_ascii(ident + 27, "ACME ROADRUNNER v0.1", 40); - ident[49] = le16(1 << 9); /* LBA */ - break; - case ACME_ULTRASONICUS: - /* 40MB drive with LBA support */ - c = 977; - h = 5; - s = 16; - ident[49] = le16(1 << 9); /* LBA */ - make_ascii(ident + 23, "A001.001", 8); - make_ascii(ident + 27, "ACME ULTRASONICUS AD INFINITUM v0.1", 40); - break; - case ACME_NEMESIS: - /* 20MB drive with LBA support */ - c = 615; - h = 4; - s = 16; - ident[49] = le16(1 << 9); /* LBA */ - make_ascii(ident + 23, "A001.001", 8); - make_ascii(ident + 27, "ACME NEMESIS RIDICULII v0.1", 40); - break; - case ACME_COYOTE: - /* 20MB drive without LBA support */ - c = 615; - h = 4; - s = 16; - make_ascii(ident + 23, "A001.001", 8); - make_ascii(ident + 27, "ACME COYOTE v0.1", 40); - break; - case ACME_ACCELLERATTI: - c = 1024; - h = 16; - s = 16; - ident[49] = le16(1 << 9); /* LBA */ - make_ascii(ident + 23, "A001.001", 8); - make_ascii(ident + 27, "ACME ACCELLERATTI INCREDIBILUS v0.1", 40); - break; - case ACME_ZIPPIBUS: - c = 1024; - h = 16; - s = 32; - ident[49] = le16(1 << 9); /* LBA */ - make_ascii(ident + 23, "A001.001", 8); - make_ascii(ident + 27, "ACME ZIPPIBUS v0.1", 40); - break; - } - 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]; - if (write(fd, ident, 512) != 512) - return -1; - - memset(ident, 0xE5, 512); - while(sectors--) - if (write(fd, ident, 512) != 512) - return -1; - return 0; -} diff --git a/ide/ide.h b/ide/ide.h deleted file mode 100644 index 7c8e32d..0000000 --- a/ide/ide.h +++ /dev/null @@ -1,82 +0,0 @@ -#include - -#define ACME_ROADRUNNER 1 /* 504MB classic IDE drive */ -#define ACME_COYOTE 2 /* 20MB early IDE drive */ -#define ACME_NEMESIS 3 /* 20MB LBA capable drive */ -#define ACME_ULTRASONICUS 4 /* 40MB LBA capable drive */ -#define ACME_ACCELLERATTI 5 /* 128MB LBA capable drive */ -#define ACME_ZIPPIBUS 6 /* 256MB LBA capable drive */ - -#define MAX_DRIVE_TYPE 6 - -#define ide_data 0 -#define ide_error_r 1 -#define ide_feature_w 1 -#define ide_sec_count 2 -#define ide_sec_num 3 -#define ide_lba_low 3 -#define ide_cyl_low 4 -#define ide_lba_mid 4 -#define ide_cyl_hi 5 -#define ide_lba_hi 5 -#define ide_dev_head 6 -#define ide_lba_top 6 -#define ide_status_r 7 -#define ide_command_w 7 -#define ide_altst_r 8 -#define ide_devctrl_w 8 -#define ide_data_latch 9 - -struct ide_taskfile { - uint16_t data; - uint8_t error; - uint8_t feature; - uint8_t count; - uint8_t lba1; - uint8_t lba2; - uint8_t lba3; - uint8_t lba4; - uint8_t status; - uint8_t command; - uint8_t devctrl; - struct ide_drive *drive; -}; - -struct ide_drive { - struct ide_controller *controller; - struct ide_taskfile taskfile; - unsigned int present:1, intrq:1, failed:1, lba:1, eightbit:1; - uint16_t cylinders; - uint8_t heads, sectors; - uint8_t data[512]; - uint16_t identify[256]; - uint8_t *dptr; - int state; - int fd; - off_t offset; - int length; -}; - -struct ide_controller { - struct ide_drive drive[2]; - int selected; - const char *name; - uint16_t data_latch; -}; - -extern const uint8_t ide_magic[8]; - -void ide_reset_begin(struct ide_controller *c); -uint8_t ide_read8(struct ide_controller *c, uint8_t r); -void ide_write8(struct ide_controller *c, uint8_t r, uint8_t v); -uint16_t ide_read16(struct ide_controller *c, uint8_t r); -void ide_write16(struct ide_controller *c, uint8_t r, uint16_t v); -uint8_t ide_read_latched(struct ide_controller *c, uint8_t r); -void ide_write_latched(struct ide_controller *c, uint8_t r, uint8_t v); - -struct ide_controller *ide_allocate(const char *name); -int ide_attach(struct ide_controller *c, int drive, int fd); -void ide_detach(struct ide_drive *d); -void ide_free(struct ide_controller *c); - -int ide_make_drive(uint8_t type, int fd); diff --git a/ide/makedisk b/ide/makedisk deleted file mode 100755 index a3d920f981250b3b96e936d2ae4345bc173ef44d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23612 zcmeHveRx#Ib@$v|A%u{u1r%Era(rzIo5mm(kZlEHBOwW+#{y))4h>0GEA0wxkhIF~ zijO|jK|pNk;+oo|!3mBw3C%;dQY?iu=CQbz3)XQ#WzjUCB#ig~X)sXX{4& z{pLd&T?=d{e%gO>?P2E3oH=vmoHJ*>R`c1$<`s_P2=n>GTtVnafg`FBANv^o$rDqm zg)63^>8G}!TJ;*qKz;;>NhkwgZUWRgpVZaP5H$3zLzZY#YG$5bBl--d_ zMF76zWBmZaT9n)EpGO`8>yx(yU9q+WU6J`+v7Wwd^TUbm&W@^NylOFuBo1j1@3z%< zGD}b%en{(Rd zeyvEjp9}8vEp~RIIIk8+r7ORRf5+%khOEbLI>IFgGZAJXuw8y1Lbwc}9AP%Xl?Yq@ z=}S9;Cw3Kow6^H6d(QvSj+Q?=68PPp&M5i%mmaFP_3l5~kz9IU$AN8M-chysme-fP zHF~nLZ&z{6zyE%PxaO_He>iPw;Gw)_&!Px#JSkc;#;ESP;+=Yg;H z!2jfd4|?Dl58UX1DL3=6y)PR8F=44_ok#e%PBS9>Z4cb*f%gMGSnHFvFaw(SxTpM# z2mW0T-0Xq>)&tZ2%twB1H2`A5yFKuSJ@D5&aHR*{?15=N<|F;B20%>sQV)Ee2mXQw z78qac98oul=(bo&bf)4xNs;VL#ClR4BAE#HL_}{ik%%WmGL`6Q@7*p^vF@k{x5X1F zu_>DBjYU`z>FX8k;jXTDyXcN~C!;A53ZYt0JcO)pDi-e%iD)>&!uIZ7(b3zNY8PF} zXmqp80@*}3mW+Z_1l2^x)0&TCfM2I59m%=dw7(m_7)HH=aiI`98BY~r4`WP31-0{E{)`YmDcJesa9(D9 zE-y2XyCm~Krr`Wjx#w!Y=>L0QaMm;X2A_NLWX`0|Sm{$%`h=A}YNd}@>9mzTXr=dC z>AhBZrA6thBJwZ@w`u z!}C^p*h*)ZKAIj9nea6$J-!e?B_;lb<5& zgPsmmJ7ON2fsD_6=*O7Bhdw;I!1>eB(UGE?9I+SnUxxZ+z{Bj3Wm!O_ zCEl#j1=$0z4F-Odz^x1bH&BJbeSSt`%a0Wp@J)Lsa4s=OA$Q11Aj}3;~JrS>RyUlp$7r|J$L({*!$%0 zVdy7~J|98+O@yNe#}G~+1R#R~$e!E>2)UhvoSsI=J31d@M9GS6KNY+^dr9#2!2;ATKz+&}>3;Vt)9kyH zNp(7#41V`4I zXp7_!Y@_^Vzf>}yJf~fc8)iR^jTjyRumi)x4$2HVXC1Z? zIWwN7+?nqS)@SOkPG^18#X`orGyX-4>odD&rnBHbv)klfMSU&L?7D&Rt_=Gkg7?R|>-ecCwtHnWAZHl||9`xKXb znw`6xJc_khOs)43uR!OQ>3mGlA0giHh0kZ7a5rX&3n?xU!ORfH^Ao|1*#h*f41Igh z@5@LUs9OSgacr~fa#`lj(3UMZWNhE^B6LF?y=sk*B5gx#pEkUeIcBvtiO#-%M=+By9X+cq}OH1(RV^O>G%r3)+V5A=V^=1EtQH+L-qHe*V97{ z)qf%T%09KuRd#zZ+w<}aKP}rUMqhR>&1AoZV8)B&c@iE?om;@Ww~piw@_YQ<Td75Tc5kIq9sILFh5h)0-fAZ%4eoO$UX@~)3kbG)>sUNIi$MWfS+2_URKcpx7--7ge zv7d{{b3SM+)%3nJi9CN5`CuI)$Jv;CDwUk(L4I6=IN0mh@|teR3r7uO@|sL87n0+o z@`7%Ze8=S|?E!MkqOZTI>>z(>i~kB5M*q~c90Q=;L^(qLv@7&yY#hGd{!BJLFVvrJ zu}#d2ziywt0Xnp^GSaigmfg>Hv;Qyr=eYg%+GPI*7k+{h;c+#=pe=s zUHSN0LixZ-jt|t~SU3-#$8!W6f&Ea9SLB)Xrg!{$^#@sujMG;B5l3>8_QmYlONYLR zx~85MypMig%nw`-IyaLS(0rKV(bB!?r*|!DWb#4# LEyqo{L__+7@RrGBLeKY>^ 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 -#include -#include -#include -#include "ide.h" - -int main(int argc, const char *argv[]) -{ - int t, fd; - if (argc != 3) { - fprintf(stderr, "%s [type] [path]\n", argv[0]); - exit(1); - } - t = atoi(argv[1]); - if (t < 1 || t > MAX_DRIVE_TYPE) { - fprintf(stderr, "%s: unknown drive type.\n", argv[0]); - exit(1); - } - fd = open(argv[2], O_WRONLY|O_TRUNC|O_CREAT|O_EXCL, 0666); - if (fd == -1) { - perror(argv[2]); - exit(1); - } - if (ide_make_drive(t, fd) < 0) { - perror(argv[2]); - exit(1); - } - return 0; -} diff --git a/platforms/amiga/Gayle.c b/platforms/amiga/Gayle.c index b7c3011..43f5205 100644 --- a/platforms/amiga/Gayle.c +++ b/platforms/amiga/Gayle.c @@ -1,15 +1,10 @@ // // Gayle.c -// Omega -// -// Created by Matt Parsons on 06/03/2019. +// Originally based on Omega's Gayle emulation, +// created by Matt Parsons on 06/03/2019. // Copyright © 2019 Matt Parsons. All rights reserved. // -// Write Byte to Gayle Space 0xda9000 (0x0000c3) -// Read Byte From Gayle Space 0xda9000 -// Read Byte From Gayle Space 0xdaa000 - #include "Gayle.h" #include #include @@ -22,11 +17,46 @@ #include "platforms/shared/rtc.h" #include "config_file/config_file.h" -#include "gayle-ide/ide.h" #include "amiga-registers.h" +//#define DEBUG_GAYLE +#ifdef DEBUG_GAYLE +#define DEBUG printf +#else #define DEBUG(...) -//#define DEBUG printf +#endif + +#define IDE_DUMMY + +#ifdef IDE_DUMMY +uint8_t *ide0 = NULL; + +uint8_t ide_feature_w = 0, ide_command_w = 0, ide_sec_count = 0, ide_sec_num = 0, idewrite8 = 0, ide_cyl_hi = 0, ide_dev_head = 0; +uint8_t ide_devctrl_w = 0, ide_cyl_low = 0, ide_error_r = 0, ide_status_r = 0, ide_altst_r = 0, ide_data = 0; + +uint8_t ide_read8(uint8_t *dummy, uint8_t ide_action) { if (dummy || ide_action) {}; return 0; } +uint16_t ide_read16(uint8_t *dummy, uint8_t ide_action) { if (dummy || ide_action) {}; return 0; } + +void ide_write8(uint8_t *dummy, uint8_t ide_action, uint8_t value) { if (dummy || ide_action || value) {}; } +void ide_write16(uint8_t *dummy, uint8_t ide_action, uint16_t value) { if (dummy || ide_action || value) {}; } +void ide_reset_begin(uint8_t *dummy) { if (dummy) {}; } + +uint8_t *ide_allocate(const char *name) { if (name) {}; return NULL; } + +void ide_attach_hdf(uint8_t *dummy, uint32_t idx, uint32_t fd) { + if (dummy || idx || fd) {}; + printf("[!!!IDE] No IDE emulation layer available, HDF image not attached.\n"); + return; +} + +void ide_attach(uint8_t *dummy, uint32_t idx, uint32_t fd) { + if (dummy || idx || fd) {}; + printf("[!!!IDE] No IDE emulation layer available, image not mounted.\n"); + return; +} +#else +static struct ide_controller *ide0 = NULL; +#endif uint8_t gary_cfg[8]; @@ -35,7 +65,6 @@ 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 = NULL; int fd; uint8_t rtc_type = RTC_TYPE_RICOH; @@ -56,11 +85,6 @@ 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) {} - return ide0; -} - void adjust_gayle_4000() { gayle_ide_base = GAYLE_IDE_BASE_A4000; gayle_ide_adj = 2; @@ -68,7 +92,6 @@ void adjust_gayle_4000() { } void adjust_gayle_1200() { - } void set_hard_drive_image_file_amiga(uint8_t index, char *filename) { @@ -117,18 +140,6 @@ void InitGayle(void) { } } -uint8_t CheckIrq(void) { - uint8_t irq; - - if (gayle_int & (1 << 7)) { - irq = ide0->drive[0].intrq || ide0->drive[1].intrq; - // if (irq==0) - // printf("IDE IRQ: %x\n",irq); - return irq; - }; - return 0; -} - static uint8_t ide_action = 0; void writeGayleB(unsigned int address, unsigned int value) { @@ -165,7 +176,7 @@ void writeGayleB(unsigned int address, unsigned int value) { goto idewrite8; case GIRQ_4000_OFFSET: gayle_a4k_irq = value; - /* Fallthrough */ + // Fallthrough case GIRQ_OFFSET: gayle_irq = (gayle_irq & value) | (value & (GAYLE_IRQ_RESET | GAYLE_IRQ_BERR)); return; diff --git a/platforms/amiga/Gayle.h b/platforms/amiga/Gayle.h index b457556..27151da 100644 --- a/platforms/amiga/Gayle.h +++ b/platforms/amiga/Gayle.h @@ -14,7 +14,6 @@ #include #include -uint8_t CheckIrq(void); void InitGayle(void); void writeGayleB(unsigned int address, unsigned value); void writeGayle(unsigned int address, unsigned value); @@ -23,8 +22,6 @@ uint8_t readGayleB(unsigned int address); uint16_t readGayle(unsigned int address); uint32_t readGayleL(unsigned int address); -struct ide_controller *get_ide(int index); - // Gayle Addresses #define GAYLE_IDE_BASE_A1200 0xDA2000 //16bit base #define GAYLE_IDE_BASE_A4000 0xDD2020 diff --git a/platforms/amiga/gayle-ide/ide.c b/platforms/amiga/gayle-ide/ide.c deleted file mode 100644 index 8a70931..0000000 --- a/platforms/amiga/gayle-ide/ide.c +++ /dev/null @@ -1,1032 +0,0 @@ -/* - * IDE Emulation Layer for retro-style PIO interfaces - * - * (c) Copyright Alan Cox, 2015-2019 - * - * IDE-emu is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * IDE-emu is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with IDE-emu. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "config_file/config_file.h" -#include "ide.h" - -#define IDE_IDLE 0 -#define IDE_CMD 1 -#define IDE_DATA_IN 2 -#define IDE_DATA_OUT 3 - -#define DCR_NIEN 2 -#define DCR_SRST 4 - -#define DEVH_HEAD 15 -#define DEVH_DEV 16 -#define DEVH_LBA 64 - -#define ERR_AMNF 1 -#define ERR_TKNONF 2 -#define ERR_ABRT 4 -#define ERR_MCR 8 -#define ERR_IDNF 16 -#define ERR_MC 32 -#define ERR_UNC 64 - -#define ST_ERR 1 -#define ST_IDX 2 -#define ST_CORR 4 -#define ST_DRQ 8 -#define ST_DSC 16 -#define ST_DF 32 -#define ST_DRDY 64 -#define ST_BSY 128 - -#define DCL_SRST 4 -#define DCL_NIEN 2 - -#define IDE_CMD_CALIB 0x10 -#define IDE_CMD_READ 0x20 -#define IDE_CMD_READ_NR 0x21 -#define IDE_CMD_WRITE 0x30 -#define IDE_CMD_WRITE_NR 0x31 -#define IDE_CMD_VERIFY 0x40 -#define IDE_CMD_VERIFY_NR 0x41 -#define IDE_CMD_SEEK 0x70 -#define IDE_CMD_EDD 0x90 -#define IDE_CMD_INTPARAMS 0x91 -#define IDE_CMD_IDENTIFY 0xEC -#define IDE_CMD_SETFEATURES 0xEF - -const uint8_t ide_magic[9] = { - '1','D','E','D','1','5','C','0',0x00 -}; -/* -static char *charmap(uint8_t v) -{ - static char cbuf[3]; - if (v < 32) - sprintf(cbuf, "^%c", '@'+v); - else if (v < 127) - sprintf(cbuf, " %c", v); - else if (v == 127) - sprintf(cbuf, "DL"); - else if (v < 160) - sprintf(cbuf, ":%c", '@' + v - 128); - else if (v < 255) - sprintf(cbuf, "~%c", v - 128); - else - sprintf(cbuf, "!D"); - return cbuf; -} - -static void hexdump(uint8_t *bp) -{ - int i,j; - for (i = 0; i < 512; i+= 16) { - for(j = 0; j < 16; j++) - fprintf(stderr, "%02X ", bp[i+j]); - fprintf(stderr, "|"); - for(j = 0; j < 16; j++) - fprintf(stderr, "%2s", charmap(bp[i+j])); - fprintf(stderr, "\n"); - } -} -*/ -/* FIXME: use proper endian convertors! */ -static uint16_t le16(uint16_t v) -{ - uint8_t *p = (uint8_t *)&v; - return p[0] | (p[1] << 8); -} - -static void ide_xlate_errno(struct ide_taskfile *t, int len) -{ - t->status |= ST_ERR; - if (len == -1) { - if (errno == EIO) - t->error = ERR_UNC; - else - t->error = ERR_AMNF; - } else - t->error = ERR_AMNF; -} - -static void ide_fault(struct ide_drive *d, const char *p) -{ - fprintf(stderr, "ide: %s: %d: %s\n", d->controller->name, - (int)(d - d->controller->drive), p); -} - -/* Disk translation */ -static off_t xlate_block(struct ide_taskfile *t) -{ - struct ide_drive *d = t->drive; - uint16_t cyl; - - 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 ((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->drive->controller->lba1 == 0) { - fprintf(stderr, "[Bug: request for sector offset 0].\n"); - t->drive->controller->lba1 = 1; - } - 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->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 */ - //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 ready(struct ide_taskfile *tf) -{ - tf->status &= ~(ST_BSY|ST_DRQ); - tf->status |= ST_DRDY; - tf->drive->state = IDE_IDLE; -} - -/* Return to idle state, completing a command */ -static void completed(struct ide_taskfile *tf) -{ - ready(tf); - tf->drive->intrq = 1; -} - -static void drive_failed(struct ide_taskfile *tf) -{ - tf->status |= ST_ERR; - tf->error = ERR_IDNF; - ready(tf); -} - -static void data_in_state(struct ide_taskfile *tf) -{ - struct ide_drive *d = tf->drive; - d->state = IDE_DATA_IN; - d->dptr = d->data + 512; - /* We don't clear DRDY here, drives may well accept a command at this - point and at least one firmware for RC2014 assumes this */ - tf->status &= ~ST_BSY; - tf->status |= ST_DRQ; - d->intrq = 1; /* Double check */ -} - -static void data_out_state(struct ide_taskfile *tf) -{ - struct ide_drive *d = tf->drive; - d->state = IDE_DATA_OUT; - d->dptr = d->data; - tf->status &= ~ (ST_BSY|ST_DRDY); - tf->status |= ST_DRQ; - d->intrq = 1; /* Double check */ -} - -static void edd_setup(struct ide_taskfile *tf) -{ - tf->error = 0x01; /* All good */ - 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); -} - -void ide_reset(struct ide_controller *c) -{ - if (c->drive[0].present) { - edd_setup(&c->drive[0].taskfile); - /* A drive could clear busy then set DRDY up to 2 minutes later if its - mindnumbingly slow to start up ! We don't emulate any of that */ - c->drive[0].taskfile.status = ST_DRDY; - c->drive[0].eightbit = 0; - } - if (c->drive[1].present) { - edd_setup(&c->drive[1].taskfile); - c->drive[1].taskfile.status = ST_DRDY; - c->drive[1].eightbit = 0; - } - if (c->selected != 0) { - } - c->selected = 0; -} - -void ide_reset_begin(struct ide_controller *c) -{ - if (c->drive[0].present) - c->drive[0].taskfile.status |= ST_BSY; - if (c->drive[1].present) - c->drive[1].taskfile.status |= ST_BSY; - /* Ought to be a time delay relative to reset or power on */ - ide_reset(c); -} - -static void ide_srst_begin(struct ide_controller *c) -{ - ide_reset(c); - if (c->drive[0].present) - c->drive[0].taskfile.status |= ST_BSY; - if (c->drive[1].present) - c->drive[1].taskfile.status |= ST_BSY; -} - -static void ide_srst_end(struct ide_controller *c) -{ - /* Could be time delays here */ - ready(&c->drive[0].taskfile); - ready(&c->drive[1].taskfile); -} - -static void cmd_edd_complete(struct ide_taskfile *tf) -{ - struct ide_controller *c = tf->drive->controller; - if (c->drive[0].present) - edd_setup(&c->drive[0].taskfile); - if (c->drive[1].present) - edd_setup(&c->drive[1].taskfile); - c->selected = 0; -} - -static void cmd_identify_complete(struct ide_taskfile *tf) -{ - struct ide_drive *d = tf->drive; - memcpy(d->data, d->identify, 512); - data_in_state(tf); - /* Arrange to copy just the identify buffer */ - d->dptr = d->data; - d->length = 1; -} - -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->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 */ -/* fprintf(stderr, "geo is %d %d, asked for %d %d\n", - d->sectors, d->heads, tf->count, (tf->lba4 & DEVH_HEAD) + 1); */ - ide_fault(d, "invalid geometry"); - } else if (tf->drive->failed == 1) - tf->drive->failed = 0; /* Valid translation */ - completed(tf); -} - -static void cmd_readsectors_complete(struct ide_taskfile *tf) -{ - struct ide_drive *d = tf->drive; - /* Move to data xfer */ - if (d->failed) { - drive_failed(tf); - return; - } - d->offset = xlate_block(tf); - /* DRDY is not guaranteed here but at least one buggy RC2014 firmware - expects it */ - tf->status |= ST_DRQ | ST_DSC | ST_DRDY; - tf->status &= ~ST_BSY; - /* 0 = 256 sectors */ - d->length = tf->count ? tf->count : 256; - /* fprintf(stderr, "READ %d SECTORS @ %ld\n", d->length, d->offset); */ - if (d->offset == -1 || lseek(d->fd, 512 * d->offset, SEEK_SET) == -1) { - tf->status |= ST_ERR; - tf->status &= ~ST_DSC; - tf->error |= ERR_IDNF; - /* return null data */ - completed(tf); - return; - } - /* do the xfer */ - data_in_state(tf); -} - -static void cmd_verifysectors_complete(struct ide_taskfile *tf) -{ - struct ide_drive *d = tf->drive; - /* Move to data xfer */ - if (d->failed) { - drive_failed(tf); - return; - } - d->offset = xlate_block(tf); - /* 0 = 256 sectors */ - d->length = tf->count ? tf->count : 256; - if (d->offset == -1 || lseek(d->fd, 512 * (d->offset + d->length - 1), SEEK_SET) == -1) { - tf->status &= ~ST_DSC; - tf->status |= ST_ERR; - tf->error |= ERR_IDNF; - } - tf->status |= ST_DSC; - completed(tf); -} - -static void cmd_recalibrate_complete(struct ide_taskfile *tf) -{ - struct ide_drive *d = tf->drive; - if (d->failed) - drive_failed(tf); - if (d->offset == -1 || xlate_block(tf) != 0L) { - tf->status &= ~ST_DSC; - tf->status |= ST_ERR; - tf->error |= ERR_ABRT; - } - tf->status |= ST_DSC; - completed(tf); -} - -static void cmd_seek_complete(struct ide_taskfile *tf) -{ - struct ide_drive *d = tf->drive; - if (d->failed) - drive_failed(tf); - d->offset = xlate_block(tf); - if (d->offset == -1 || lseek(d->fd, 512 * d->offset, SEEK_SET) == -1) { - tf->status &= ~ST_DSC; - tf->status |= ST_ERR; - tf->error |= ERR_IDNF; - } - tf->status |= ST_DSC; - completed(tf); -} - -static void cmd_setfeatures_complete(struct ide_taskfile *tf) -{ - struct ide_drive *d = tf->drive; - switch(tf->feature) { - case 0x01: - d->eightbit = 1; - break; - case 0x03: - if ((tf->count & 0xF0) >= 0x20) { - tf->status |= ST_ERR; - tf->error |= ERR_ABRT; - } - /* Silently accept PIO mode settings */ - break; - case 0x81: - d->eightbit = 0; - break; - default: - tf->status |= ST_ERR; - tf->error |= ERR_ABRT; - } - completed(tf); -} - -static void cmd_writesectors_complete(struct ide_taskfile *tf) -{ - struct ide_drive *d = tf->drive; - /* Move to data xfer */ - if (d->failed) { - drive_failed(tf); - return; - } - d->offset = xlate_block(tf); - tf->status |= ST_DRQ; - /* 0 = 256 sectors */ - d->length = tf->count ? tf->count : 256; -/* fprintf(stderr, "WRITE %d SECTORS @ %ld\n", d->length, d->offset); */ - if (d->offset == -1 || lseek(d->fd, 512 * d->offset, SEEK_SET) == -1) { - tf->status |= ST_ERR; - tf->error |= ERR_IDNF; - tf->status &= ~ST_DSC; - /* return null data */ - completed(tf); - return; - } - /* do the xfer */ - data_out_state(tf); -} - -static void ide_set_error(struct ide_drive *d) -{ - d->controller->lba4 &= ~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->controller->lba1 = d->offset % d->sectors + 1; - d->offset /= d->sectors; - d->controller->lba4 |= d->offset / (d->cylinders * d->sectors); - d->offset %= (d->cylinders * d->sectors); - d->controller->lba2 = d->offset & 0xFF; - d->controller->lba3 = (d->offset >> 8) & 0xFF; - } - d->taskfile.count = d->length; - d->taskfile.status |= ST_ERR; - d->state = IDE_IDLE; - completed(&d->taskfile); -} - -static int ide_read_sector(struct ide_drive *d) -{ - int len; - - d->dptr = d->data; - if ((len = read(d->fd, d->data, 512)) != 512) { - perror("ide_read_sector"); - d->taskfile.status |= ST_ERR; - d->taskfile.status &= ~ST_DSC; - ide_xlate_errno(&d->taskfile, len); - return -1; - } -// hexdump(d->data); - d->offset += 512; - return 0; -} - -static int ide_write_sector(struct ide_drive *d) -{ - int len; - - d->dptr = d->data; - if ((len = write(d->fd, d->data, 512)) != 512) { - d->taskfile.status |= ST_ERR; - d->taskfile.status &= ~ST_DSC; - ide_xlate_errno(&d->taskfile, len); - return -1; - } -// hexdump(d->data); - d->offset += 512; - return 0; -} - -static uint16_t ide_data_in(struct ide_drive *d, int len) -{ - uint16_t v; - if (d->state == IDE_DATA_IN) { - if (d->dptr == d->data + 512) { - if (ide_read_sector(d) < 0) { - ide_set_error(d); /* Set the LBA or CHS etc */ - return 0xFFFF; /* and error bits set by read_sector */ - } - } - v = *d->dptr; - if (!d->eightbit) { - if (len == 2) - v |= (d->dptr[1] << 8); - d->dptr+=2; - } else - d->dptr++; - d->taskfile.data = v; - if (d->dptr == d->data + 512) { - d->length--; - d->intrq = 1; /* we don't yet emulate multimode */ - if (d->length == 0) { - d->state = IDE_IDLE; - completed(&d->taskfile); - } - } - } else - ide_fault(d, "bad data read"); - - if (len == 1) - return d->taskfile.data & 0xFF; - return d->taskfile.data; -} - -static void ide_data_out(struct ide_drive *d, uint16_t v, int len) -{ - (void)len; - if (d->state != IDE_DATA_OUT) { - ide_fault(d, "bad data write"); - d->taskfile.data = v; - } else { - if (d->eightbit) - v &= 0xFF; - *d->dptr++ = v; - d->taskfile.data = v; - if (!d->eightbit) { - *d->dptr++ = v >> 8; - d->taskfile.data = v >> 8; - } - if (d->dptr == d->data + 512) { - if (ide_write_sector(d) < 0) { - ide_set_error(d); - return; - } - d->length--; - d->intrq = 1; - if (d->length == 0) { - d->state = IDE_IDLE; - d->taskfile.status |= ST_DSC; - completed(&d->taskfile); - } - } - } -} - -static void ide_issue_command(struct ide_taskfile *t) -{ - t->status &= ~(ST_ERR|ST_DRDY); - t->status |= ST_BSY; - t->error = 0; - t->drive->state = IDE_CMD; - - /* We could complete with delays but don't do so yet */ - switch(t->command) { - case IDE_CMD_EDD: /* 0x90 */ - cmd_edd_complete(t); - break; - case IDE_CMD_IDENTIFY: /* 0xEC */ - cmd_identify_complete(t); - break; - case IDE_CMD_INTPARAMS: /* 0x91 */ - cmd_initparam_complete(t); - break; - case IDE_CMD_READ: /* 0x20 */ - case IDE_CMD_READ_NR: /* 0x21 */ - cmd_readsectors_complete(t); - break; - case IDE_CMD_SETFEATURES: /* 0xEF */ - cmd_setfeatures_complete(t); - break; - case IDE_CMD_VERIFY: /* 0x40 */ - case IDE_CMD_VERIFY_NR: /* 0x41 */ - cmd_verifysectors_complete(t); - break; - case IDE_CMD_WRITE: /* 0x30 */ - case IDE_CMD_WRITE_NR: /* 0x31 */ - cmd_writesectors_complete(t); - break; - default: - if ((t->command & 0xF0) == IDE_CMD_CALIB) /* 1x */ - cmd_recalibrate_complete(t); - else if ((t->command & 0xF0) == IDE_CMD_SEEK) /* 7x */ - cmd_seek_complete(t); - else { - /* Unknown */ - t->status |= ST_ERR; - t->error |= ERR_ABRT; - completed(t); - } - } -} - -/* - * 8bit IDE controller emulation - */ - -uint8_t ide_read8(struct ide_controller *c, uint8_t r) -{ - struct ide_drive *d = &c->drive[c->selected]; - struct ide_taskfile *t = &d->taskfile; - switch(r) { - case ide_data: - return ide_data_in(d, 1); - case ide_error_r: - return t->error; - case ide_sec_count: - return t->count; - case ide_lba_low: - return c->lba1; - case ide_lba_mid: - return c->lba2; - case ide_lba_hi: - return c->lba3; - case ide_lba_top: - return c->lba4 | ((c->selected) ? 0x10 : 0x00); - case ide_status_r: - d->intrq = 0; /* Acked */ - /* Fallthrough */ - /* no break */ - case ide_altst_r: - return t->status; - default: - ide_fault(d, "bogus register"); - return 0xFF; - } -} - -void ide_write8(struct ide_controller *c, uint8_t r, uint8_t v) -{ - struct ide_drive *d = &c->drive[c->selected]; - struct ide_taskfile *t = &d->taskfile; - - if (r != ide_devctrl_w) { - if (t->status & ST_BSY) { - ide_fault(d, "command written while busy"); - return; - } - /* Not clear this is the right emulation */ - if (d->present == 0 && r != ide_lba_top) { - ide_fault(d, "not present"); - return; - } - } - -// uint8_t ve; - - switch(r) { - case ide_data: - ide_data_out(d, v, 1); - break; - case ide_feature_w: - t->feature = v; - break; - case ide_sec_count: - t->count = v; - break; - case ide_lba_low: - c->lba1 = v; - break; - case ide_lba_mid: - c->lba2 = v; - break; - case ide_lba_hi: - c->lba3 = v; - break; - case ide_lba_top: - c->selected = (v & DEVH_DEV) ? 1 : 0; - c->lba4 = v & (DEVH_HEAD|/*DEVH_DEV|*/DEVH_LBA); - break; - case ide_command_w: - t->command = v; - ide_issue_command(t); - break; - case ide_devctrl_w: - /* ATA: "When the Device Control register is written, both devices - respond to the write regardless of which device is selected" */ - if ((v ^ t->devctrl) & DCL_SRST) { - if (v & DCL_SRST) - ide_srst_begin(c); - else - ide_srst_end(c); - } - c->drive[0].taskfile.devctrl = v; /* Check versus real h/w does this end up cleared */ - c->drive[1].taskfile.devctrl = v; - break; - } -} - -/* - * 16bit IDE controller emulation - */ - -uint16_t ide_read16(struct ide_controller *c, uint8_t r) -{ - struct ide_drive *d = &c->drive[c->selected]; - if (r == ide_data) - return htons(ide_data_in(d,2)); - return ide_read8(c, r); -} - -void ide_write16(struct ide_controller *c, uint8_t r, uint16_t v) -{ - struct ide_drive *d = &c->drive[c->selected]; - struct ide_taskfile *t = &d->taskfile; - - if (r != ide_devctrl_w && (t->status & ST_BSY)) { - ide_fault(d, "command written while busy"); - return; - } - if (r == ide_data) - ide_data_out(d, ntohs(v), 2); - else - ide_write8(c, r, v); -} - -/* - * Allocate a new IDE controller emulation - */ -struct ide_controller *ide_allocate(const char *name) -{ - struct ide_controller *c = calloc(1, sizeof(*c)); - if (c == NULL) - return NULL; - c->name = strdup(name); - if (c->name == NULL) { - free(c); - return NULL; - } - c->drive[0].controller = c; - c->drive[1].controller = c; - c->drive[0].taskfile.drive = &c->drive[0]; - c->drive[1].taskfile.drive = &c->drive[1]; - return c; -} - -/* - * Attach a file to a device on the controller - */ -int ide_attach(struct ide_controller *c, int drive, int fd) -{ - struct ide_drive *d = &c->drive[drive]; - if (d->present) { - ide_fault(d, "double attach"); - return -1; - } - d->fd = fd; - if (read(d->fd, d->data, 512) != 512 || - read(d->fd, d->identify, 512) != 512) { - ide_fault(d, "i/o error on attach"); - return -1; - } - if (memcmp(d->data, ide_magic, 8)) { - ide_fault(d, "bad magic"); - return -1; - } - d->fd = fd; - d->present = 1; - 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 - d->lba = 0; - 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 < 504 * SIZE_MEGA) { - d->heads = 16; - } - else if (file_size < 1008 * SIZE_MEGA) { - d->heads = 32; - } - else if (file_size < 2016 * SIZE_MEGA) { - d->heads = 64; - } - else if (file_size < (uint64_t)4032 * 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) - */ -void ide_detach(struct ide_drive *d) -{ - close(d->fd); - d->fd = -1; - d->present = 0; -} - -/* - * Free up and release and IDE controller - */ -void ide_free(struct ide_controller *c) -{ - if (c->drive[0].present) - ide_detach(&c->drive[0]); - if (c->drive[1].present) - ide_detach(&c->drive[1]); - free((void *)c->name); - free(c); -} - -/* - * Emulation interface for an 8bit controller using latches on the - * data register - */ -uint8_t ide_read_latched(struct ide_controller *c, uint8_t reg) -{ - uint16_t v; - if (reg == ide_data_latch) - return c->data_latch; - v = ide_read16(c, reg); - if (reg == ide_data) { - c->data_latch = v >> 8; - v &= 0xFF; - } - return v; -} - -void ide_write_latched(struct ide_controller *c, uint8_t reg, uint8_t v) -{ - uint16_t d = v; - - if (reg == ide_data_latch) { - c->data_latch = v; - return; - } - if (reg == ide_data) - d |= (c->data_latch << 8); - ide_write16(c, reg, d); -} - -static void make_ascii(uint16_t *p, const char *t, int len) -{ - int i; - char *d = (char *)p; -// strncpy(d, t, len); -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstringop-truncation" - strncpy(d, t, len); -#pragma GCC diagnostic pop - - for (i = 0; i < len; i += 2) { - char c = *d; - *d = d[1]; - d[1] = c; - d += 2; - } -} - -static void make_serial(uint16_t *p) -{ - char buf[21]; - srand(getpid()^time(NULL)); - snprintf(buf, 21, "%08d%08d%04d", rand(), rand(), rand()); - 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; - uint16_t c; - uint32_t sectors; - uint16_t ident[256]; - - if (type < 1 || type > MAX_DRIVE_TYPE) - return -2; - - memset(ident, 0, 512); - memcpy(ident, ide_magic, 8); - if (write(fd, ident, 512) != 512) - return -1; - - 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 */ - - switch(type) { - case ACME_ROADRUNNER: - /* 504MB drive with LBA support */ - c = 1024; - h = 16; - s = 63; - make_ascii(ident + 23, "A001.001", 8); - make_ascii(ident + 27, "ACME ROADRUNNER v0.1", 40); - ident[49] = le16(1 << 9); /* LBA */ - break; - case ACME_ULTRASONICUS: - /* 40MB drive with LBA support */ - c = 977; - h = 5; - s = 16; - ident[49] = le16(1 << 9); /* LBA */ - make_ascii(ident + 23, "A001.001", 8); - make_ascii(ident + 27, "ACME ULTRASONICUS AD INFINITUM v0.1", 40); - break; - case ACME_NEMESIS: - /* 20MB drive with LBA support */ - c = 615; - h = 4; - s = 16; - ident[49] = le16(1 << 9); /* LBA */ - make_ascii(ident + 23, "A001.001", 8); - make_ascii(ident + 27, "ACME NEMESIS RIDICULII v0.1", 40); - break; - case ACME_COYOTE: - /* 20MB drive without LBA support */ - c = 615; - h = 4; - s = 16; - make_ascii(ident + 23, "A001.001", 8); - make_ascii(ident + 27, "ACME COYOTE v0.1", 40); - break; - case ACME_ACCELLERATTI: - c = 1024; - h = 16; - s = 16; - ident[49] = le16(1 << 9); /* LBA */ - make_ascii(ident + 23, "A001.001", 8); - make_ascii(ident + 27, "ACME ACCELLERATTI INCREDIBILUS v0.1", 40); - break; - case ACME_ZIPPIBUS: - c = 1024; - h = 16; - s = 32; - ident[49] = le16(1 << 9); /* LBA */ - make_ascii(ident + 23, "A001.001", 8); - make_ascii(ident + 27, "ACME ZIPPIBUS v0.1", 40); - break; - } - 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]; - if (write(fd, ident, 512) != 512) - return -1; - - memset(ident, 0xE5, 512); - while(sectors--) - if (write(fd, ident, 512) != 512) - return -1; - return 0; -} diff --git a/platforms/amiga/gayle-ide/ide.h b/platforms/amiga/gayle-ide/ide.h deleted file mode 100644 index 29598ec..0000000 --- a/platforms/amiga/gayle-ide/ide.h +++ /dev/null @@ -1,86 +0,0 @@ -#include - -#define ACME_ROADRUNNER 1 /* 504MB classic IDE drive */ -#define ACME_COYOTE 2 /* 20MB early IDE drive */ -#define ACME_NEMESIS 3 /* 20MB LBA capable drive */ -#define ACME_ULTRASONICUS 4 /* 40MB LBA capable drive */ -#define ACME_ACCELLERATTI 5 /* 128MB LBA capable drive */ -#define ACME_ZIPPIBUS 6 /* 256MB LBA capable drive */ - -#define MAX_DRIVE_TYPE 6 - -#define ide_data 0 -#define ide_error_r 1 -#define ide_feature_w 1 -#define ide_sec_count 2 -#define ide_sec_num 3 -#define ide_lba_low 3 -#define ide_cyl_low 4 -#define ide_lba_mid 4 -#define ide_cyl_hi 5 -#define ide_lba_hi 5 -#define ide_dev_head 6 -#define ide_lba_top 6 -#define ide_status_r 7 -#define ide_command_w 7 -#define ide_altst_r 8 -#define ide_devctrl_w 8 -#define ide_data_latch 9 - -struct ide_taskfile { - uint16_t data; - uint8_t error; - uint8_t feature; - uint8_t count; - uint8_t status; - uint8_t command; - uint8_t devctrl; - struct ide_drive *drive; -}; - -struct ide_drive { - struct ide_controller *controller; - struct ide_taskfile taskfile; - unsigned int present:1, intrq:1, failed:1, lba:1, eightbit:1; - uint16_t cylinders; - uint8_t heads, sectors; - uint8_t data[512]; - uint16_t identify[256]; - uint8_t *dptr; - int state; - int fd; - off_t offset; - int length; - uint8_t header_present; -}; - -struct ide_controller { - struct ide_drive drive[2]; - int selected; - const char *name; - uint16_t data_latch; - uint8_t lba1; - uint8_t lba2; - uint8_t lba3; - uint8_t lba4; -}; - -//extern ide_controller idectrl; -extern const uint8_t ide_magic[9]; - -void ide_reset_begin(struct ide_controller *c); -uint8_t ide_read8(struct ide_controller *c, uint8_t r); -void ide_write8(struct ide_controller *c, uint8_t r, uint8_t v); -uint16_t ide_read16(struct ide_controller *c, uint8_t r); -void ide_write16(struct ide_controller *c, uint8_t r, uint16_t v); -uint8_t ide_read_latched(struct ide_controller *c, uint8_t r); -void ide_write_latched(struct ide_controller *c, uint8_t r, uint8_t v); - -struct ide_controller *ide_allocate(const char *name); -int ide_attach(struct ide_controller *c, int drive, int fd); -int ide_attach_hdf(struct ide_controller *c, int drive, int fd); -int ide_make_ident(uint16_t c, uint8_t h, uint8_t s, char *name, uint16_t *target); -void ide_detach(struct ide_drive *d); -void ide_free(struct ide_controller *c); - -int ide_make_drive(uint8_t type, int fd); -- 2.39.2