From 6e6436acd7090cd493ccaa1bf940bb7e2f8b0ad9 Mon Sep 17 00:00:00 2001 From: Adrien Moulin Date: Fri, 29 Jul 2022 00:47:52 +0200 Subject: [PATCH 1/2] 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; From e0dfb6d1837cea6ebff6393cbb8ad9b820ed967c Mon Sep 17 00:00:00 2001 From: Adrien Moulin Date: Fri, 29 Jul 2022 01:17:36 +0200 Subject: [PATCH 2/2] ESDI: fix drive status icon updating --- src/disk/hdc_esdi_at.c | 60 ++++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/src/disk/hdc_esdi_at.c b/src/disk/hdc_esdi_at.c index d0524dcdf..59d8308a8 100644 --- a/src/disk/hdc_esdi_at.c +++ b/src/disk/hdc_esdi_at.c @@ -253,9 +253,9 @@ esdi_writew(uint16_t port, uint16_t val, void *priv) if (esdi->pos >= 512) { esdi->pos = 0; esdi->status = STAT_BUSY; - 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); + 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); } } @@ -317,6 +317,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv) esdi->command &= ~0x0f; /*mask off step rate*/ esdi->status = STAT_BUSY; esdi_set_callback(esdi, 200 * HDC_TIME); + ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 1); break; case CMD_SEEK: @@ -325,6 +326,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv) 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); + ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 1); break; default: @@ -345,10 +347,11 @@ esdi_write(uint16_t port, uint8_t val, void *priv) case 0xa0: esdi->status = STAT_BUSY; - 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); + 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); + ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 1); break; case CMD_WRITE: @@ -360,21 +363,24 @@ esdi_write(uint16_t port, uint8_t val, void *priv) fatal("Write with ECC\n"); esdi->status = STAT_READY | STAT_DRQ | STAT_DSC; esdi->pos = 0; + ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 1); break; case CMD_VERIFY: case CMD_VERIFY+1: esdi->command &= ~0x01; esdi->status = STAT_BUSY; - 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); + 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); + ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 1); break; case CMD_FORMAT: esdi->status = STAT_DRQ; esdi->pos = 0; + ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 1); break; case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */ @@ -385,6 +391,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv) case CMD_DIAGNOSE: /* Execute Drive Diagnostics */ esdi->status = STAT_BUSY; esdi_set_callback(esdi, 200 * HDC_TIME); + ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 1); break; case 0xe0: /*???*/ @@ -448,9 +455,9 @@ 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); + 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. */ esdi_set_callback(esdi, seek_time + xfer_time); } else @@ -543,6 +550,7 @@ esdi_callback(void *priv) esdi->status = STAT_READY|STAT_DSC; } irq_raise(esdi); + ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 0); break; case CMD_SEEK: @@ -552,6 +560,7 @@ esdi_callback(void *priv) } else esdi->status = STAT_READY|STAT_DSC; irq_raise(esdi); + ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 0); break; case CMD_READ: @@ -571,7 +580,6 @@ esdi_callback(void *priv) esdi->pos = 0; esdi->status = STAT_DRQ|STAT_READY|STAT_DSC; irq_raise(esdi); - ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 1); } break; @@ -580,12 +588,14 @@ esdi_callback(void *priv) esdi->status = STAT_READY|STAT_ERR|STAT_DSC; esdi->error = ERR_ABRT; irq_raise(esdi); + ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 0); break; } else { if (get_sector(esdi, &addr)) { esdi->error = ERR_ID_NOT_FOUND; esdi->status = STAT_READY|STAT_DSC|STAT_ERR; irq_raise(esdi); + ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 0); break; } @@ -596,9 +606,11 @@ esdi_callback(void *priv) esdi->status = STAT_DRQ|STAT_READY|STAT_DSC; esdi->pos = 0; next_sector(esdi); - } else + ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 1); + } else { esdi->status = STAT_READY|STAT_DSC; - ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 1); + ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 0); + } } break; @@ -607,12 +619,14 @@ esdi_callback(void *priv) esdi->status = STAT_READY|STAT_ERR|STAT_DSC; esdi->error = ERR_ABRT; irq_raise(esdi); + ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 0); break; } else { if (get_sector(esdi, &addr)) { esdi->error = ERR_ID_NOT_FOUND; esdi->status = STAT_READY|STAT_DSC|STAT_ERR; irq_raise(esdi); + ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 0); break; } @@ -621,18 +635,20 @@ esdi_callback(void *priv) next_sector(esdi); esdi->secount = (esdi->secount - 1) & 0xff; if (esdi->secount) { - get_sector(esdi, &addr); - seek_time = hdd_timing_read(&hdd[esdi->drives[esdi->drive_sel].hdd_num], addr, 1); + 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); + ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 0); } } break; case CMD_FORMAT: + ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 0); if (! drive->present) { esdi->status = STAT_READY|STAT_ERR|STAT_DSC; esdi->error = ERR_ABRT; @@ -649,7 +665,6 @@ esdi_callback(void *priv) hdd_image_zero(drive->hdd_num, addr, esdi->secount); esdi->status = STAT_READY|STAT_DSC; irq_raise(esdi); - ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 1); } break; @@ -662,9 +677,11 @@ esdi_callback(void *priv) esdi->error = 1; /*no error detected*/ esdi->status = STAT_READY|STAT_DSC; irq_raise(esdi); + ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 0); break; case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */ + ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 0); if (! drive->present) { esdi->status = STAT_READY|STAT_ERR|STAT_DSC; esdi->error = ERR_ABRT; @@ -686,9 +703,11 @@ esdi_callback(void *priv) esdi->status = STAT_READY|STAT_ERR|STAT_DSC; esdi->error = ERR_ABRT; irq_raise(esdi); + ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 0); break; case 0xe0: + ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 0); if (! drive->present) { esdi->status = STAT_READY|STAT_ERR|STAT_DSC; esdi->error = ERR_ABRT; @@ -731,6 +750,7 @@ esdi_callback(void *priv) esdi->status = STAT_DRQ|STAT_READY|STAT_DSC; } irq_raise(esdi); + ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 0); break; case CMD_READ_PARAMETERS: @@ -766,6 +786,7 @@ esdi_callback(void *priv) esdi->status = STAT_DRQ|STAT_READY|STAT_DSC; irq_raise(esdi); } + ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 0); break; default: @@ -776,10 +797,9 @@ esdi_callback(void *priv) esdi->status = STAT_READY|STAT_ERR|STAT_DSC; esdi->error = ERR_ABRT; irq_raise(esdi); + ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 0); break; } - - ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 0); }