From 6e6436acd7090cd493ccaa1bf940bb7e2f8b0ad9 Mon Sep 17 00:00:00 2001 From: Adrien Moulin Date: Fri, 29 Jul 2022 00:47:52 +0200 Subject: [PATCH] ESDI: implement HDD timings --- src/config.c | 3 +- src/disk/hdc_esdi_at.c | 86 +++++++++++++++++++++++++--------- src/qt/qt_harddrive_common.cpp | 1 + 3 files changed, 68 insertions(+), 22 deletions(-) diff --git a/src/config.c b/src/config.c index 81bbc016f..581c250b4 100644 --- a/src/config.c +++ b/src/config.c @@ -1386,6 +1386,7 @@ load_hard_disks(void) sprintf(temp, "hdd_%02i_speed", c + 1); switch (hdd[c].bus) { case HDD_BUS_IDE: + case HDD_BUS_ESDI: sprintf(tmp2, "1997_5400rpm"); break; default: @@ -2920,7 +2921,7 @@ save_hard_disks(void) config_delete_var(cat, temp); sprintf(temp, "hdd_%02i_speed", c + 1); - if (!hdd_is_valid(c) || (hdd[c].bus != HDD_BUS_IDE)) + if (!hdd_is_valid(c) || (hdd[c].bus != HDD_BUS_IDE && hdd[c].bus != HDD_BUS_ESDI)) config_delete_var(cat, temp); else config_set_string(cat, temp, hdd_preset_get_internal_name(hdd[c].speed_preset)); diff --git a/src/disk/hdc_esdi_at.c b/src/disk/hdc_esdi_at.c index ff284b231..d0524dcdf 100644 --- a/src/disk/hdc_esdi_at.c +++ b/src/disk/hdc_esdi_at.c @@ -41,7 +41,7 @@ #include <86box/hdd.h> -#define HDC_TIME (TIMER_USEC*10LL) +#define HDC_TIME 10.0 #define BIOS_FILE "roms/hdd/esdi_at/62-000279-061.bin" #define STAT_ERR 0x01 @@ -152,6 +152,26 @@ irq_update(esdi_t *esdi) picint(1 << 14); } +static void +esdi_set_callback(esdi_t *esdi, double callback) +{ + if (!esdi) { + esdi_at_log("esdi_set_callback(NULL): Set callback failed\n"); + return; + } + + if (callback == 0.0) + timer_stop(&esdi->callback_timer); + else + timer_on_auto(&esdi->callback_timer, callback); +} + +double +esdi_get_xfer_time(esdi_t *esdi, int size) +{ + /* 390.625 us per sector at 10 Mbit/s = 1280 kB/s. */ + return (3125.0 / 8.0) * (double)size; +} /* Return the sector offset for the current register values. */ static int @@ -160,7 +180,7 @@ get_sector(esdi_t *esdi, off64_t *addr) drive_t *drive = &esdi->drives[esdi->drive_sel]; int heads = drive->cfg_hpc; int sectors = drive->cfg_spt; - int c, h, s; + int c, h, s, sector; if (esdi->head > heads) { esdi_at_log("esdi_get_sector: past end of configured heads\n"); @@ -172,9 +192,11 @@ get_sector(esdi_t *esdi, off64_t *addr) return(1); } + sector = esdi->sector ? esdi->sector : 1; + if (drive->cfg_spt==drive->real_spt && drive->cfg_hpc==drive->real_hpc) { *addr = ((((off64_t) esdi->cylinder * heads) + esdi->head) * - sectors) + (esdi->sector - 1); + sectors) + (sector - 1); } else { /* * When performing translation, the firmware seems to leave 1 @@ -182,7 +204,7 @@ get_sector(esdi_t *esdi, off64_t *addr) */ *addr = ((((off64_t) esdi->cylinder * heads) + esdi->head) * - sectors) + (esdi->sector - 1); + sectors) + (sector - 1); s = *addr % (drive->real_spt - 1); h = (*addr / (drive->real_spt - 1)) % drive->real_hpc; @@ -218,6 +240,7 @@ static void esdi_writew(uint16_t port, uint16_t val, void *priv) { esdi_t *esdi = (esdi_t *)priv; + off64_t addr; if (port > 0x01f0) { esdi_write(port, val & 0xff, priv); @@ -230,8 +253,10 @@ esdi_writew(uint16_t port, uint16_t val, void *priv) if (esdi->pos >= 512) { esdi->pos = 0; esdi->status = STAT_BUSY; - /* 390.625 us per sector at 10 Mbit/s = 1280 kB/s. */ - timer_set_delay_u64(&esdi->callback_timer, (3125 * TIMER_USEC) / 8); + get_sector(esdi, &addr); + double seek_time = hdd_timing_write(&hdd[esdi->drives[esdi->drive_sel].hdd_num], addr, 1); + double xfer_time = esdi_get_xfer_time(esdi, 1); + esdi_set_callback(esdi, seek_time + xfer_time); } } } @@ -241,6 +266,8 @@ static void esdi_write(uint16_t port, uint8_t val, void *priv) { esdi_t *esdi = (esdi_t *)priv; + double seek_time, xfer_time; + off64_t addr; esdi_at_log("WD1007 write(%04x, %02x)\n", port, val); @@ -289,20 +316,22 @@ esdi_write(uint16_t port, uint8_t val, void *priv) case CMD_RESTORE: esdi->command &= ~0x0f; /*mask off step rate*/ esdi->status = STAT_BUSY; - timer_set_delay_u64(&esdi->callback_timer, 200 * HDC_TIME); + esdi_set_callback(esdi, 200 * HDC_TIME); break; case CMD_SEEK: esdi->command &= ~0x0f; /*mask off step rate*/ esdi->status = STAT_BUSY; - timer_set_delay_u64(&esdi->callback_timer, 200 * HDC_TIME); + get_sector(esdi, &addr); + seek_time = hdd_seek_get_time(&hdd[esdi->drives[esdi->drive_sel].hdd_num], addr, HDD_OP_SEEK, 0, 0.0); + esdi_set_callback(esdi, seek_time); break; default: switch (val) { case CMD_NOP: esdi->status = STAT_BUSY; - timer_set_delay_u64(&esdi->callback_timer, 200 * HDC_TIME); + esdi_set_callback(esdi, 200 * HDC_TIME); break; case CMD_READ: @@ -316,7 +345,10 @@ esdi_write(uint16_t port, uint8_t val, void *priv) case 0xa0: esdi->status = STAT_BUSY; - timer_set_delay_u64(&esdi->callback_timer, 200 * HDC_TIME); + get_sector(esdi, &addr); + seek_time = hdd_timing_read(&hdd[esdi->drives[esdi->drive_sel].hdd_num], addr, 1); + xfer_time = esdi_get_xfer_time(esdi, 1); + esdi_set_callback(esdi, seek_time + xfer_time); break; case CMD_WRITE: @@ -334,7 +366,10 @@ esdi_write(uint16_t port, uint8_t val, void *priv) case CMD_VERIFY+1: esdi->command &= ~0x01; esdi->status = STAT_BUSY; - timer_set_delay_u64(&esdi->callback_timer, 200 * HDC_TIME); + get_sector(esdi, &addr); + seek_time = hdd_timing_read(&hdd[esdi->drives[esdi->drive_sel].hdd_num], addr, 1); + xfer_time = esdi_get_xfer_time(esdi, 1); + esdi_set_callback(esdi, seek_time + xfer_time); break; case CMD_FORMAT: @@ -344,18 +379,18 @@ esdi_write(uint16_t port, uint8_t val, void *priv) case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */ esdi->status = STAT_BUSY; - timer_set_delay_u64(&esdi->callback_timer, 30 * HDC_TIME); + esdi_set_callback(esdi, 30 * HDC_TIME); break; case CMD_DIAGNOSE: /* Execute Drive Diagnostics */ esdi->status = STAT_BUSY; - timer_set_delay_u64(&esdi->callback_timer, 200 * HDC_TIME); + esdi_set_callback(esdi, 200 * HDC_TIME); break; case 0xe0: /*???*/ case CMD_READ_PARAMETERS: esdi->status = STAT_BUSY; - timer_set_delay_u64(&esdi->callback_timer, 200 * HDC_TIME); + esdi_set_callback(esdi, 200 * HDC_TIME); break; default: @@ -363,7 +398,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv) /*FALLTHROUGH*/ case 0xe8: /*???*/ esdi->status = STAT_BUSY; - timer_set_delay_u64(&esdi->callback_timer, 200 * HDC_TIME); + esdi_set_callback(esdi, 200 * HDC_TIME); break; } } @@ -371,14 +406,14 @@ esdi_write(uint16_t port, uint8_t val, void *priv) case 0x3f6: /* Device control */ if ((esdi->fdisk & 0x04) && !(val & 0x04)) { - timer_set_delay_u64(&esdi->callback_timer, 500 * HDC_TIME); + esdi_set_callback(esdi, 500 * HDC_TIME); esdi->reset = 1; esdi->status = STAT_BUSY; } if (val & 0x04) { /* Drive held in reset. */ - timer_disable(&esdi->callback_timer); + esdi_set_callback(esdi, 0); esdi->status = STAT_BUSY; } esdi->fdisk = val; @@ -393,6 +428,7 @@ esdi_readw(uint16_t port, void *priv) { esdi_t *esdi = (esdi_t *)priv; uint16_t temp; + off64_t addr; if (port > 0x01f0) { temp = esdi_read(port, priv); @@ -412,8 +448,11 @@ esdi_readw(uint16_t port, void *priv) if (esdi->secount) { next_sector(esdi); esdi->status = STAT_BUSY; + get_sector(esdi, &addr); + double seek_time = hdd_timing_read(&hdd[esdi->drives[esdi->drive_sel].hdd_num], addr, 1); + double xfer_time = esdi_get_xfer_time(esdi, 1); /* 390.625 us per sector at 10 Mbit/s = 1280 kB/s. */ - timer_set_delay_u64(&esdi->callback_timer, (3125 * TIMER_USEC) / 8); + esdi_set_callback(esdi, seek_time + xfer_time); } else ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 0); } @@ -477,6 +516,7 @@ esdi_callback(void *priv) esdi_t *esdi = (esdi_t *)priv; drive_t *drive = &esdi->drives[esdi->drive_sel]; off64_t addr; + double seek_time; if (esdi->reset) { esdi->status = STAT_READY|STAT_DSC; @@ -580,9 +620,11 @@ esdi_callback(void *priv) ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 1); next_sector(esdi); esdi->secount = (esdi->secount - 1) & 0xff; - if (esdi->secount) - timer_set_delay_u64(&esdi->callback_timer, 6 * HDC_TIME); - else { + if (esdi->secount) { + get_sector(esdi, &addr); + seek_time = hdd_timing_read(&hdd[esdi->drives[esdi->drive_sel].hdd_num], addr, 1); + esdi_set_callback(esdi, seek_time + HDC_TIME); + } else { esdi->pos = 0; esdi->status = STAT_READY|STAT_DSC; irq_raise(esdi); @@ -752,6 +794,8 @@ loadhd(esdi_t *esdi, int hdd_num, int d, const char *fn) return; } + hdd_preset_apply(d); + drive->cfg_spt = drive->real_spt = hdd[d].spt; drive->cfg_hpc = drive->real_hpc = hdd[d].hpc; drive->real_tracks = hdd[d].tracks; diff --git a/src/qt/qt_harddrive_common.cpp b/src/qt/qt_harddrive_common.cpp index 5ac46dd42..661e7992c 100644 --- a/src/qt/qt_harddrive_common.cpp +++ b/src/qt/qt_harddrive_common.cpp @@ -59,6 +59,7 @@ void Harddrives::populateSpeeds(QAbstractItemModel *model, int bus) { switch (bus) { case HDD_BUS_IDE: + case HDD_BUS_ESDI: num_preset = hdd_preset_get_num(); break;