From 40d724cf2090091a6c8918b400be4fb01842b77c Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 30 Oct 2023 04:48:29 +0100 Subject: [PATCH] Fixed SCSI/ATAPI hard disk timings and IDE hard disk recalibrate command timing. --- src/disk/hdc_ide.c | 15 +++++++++++---- src/include/86box/scsi_device.h | 3 +++ src/scsi/scsi.c | 15 ++++++++++++++- src/scsi/scsi_aha154x.c | 2 ++ src/scsi/scsi_buslogic.c | 5 +++-- src/scsi/scsi_disk.c | 30 +++++++++++++++++------------- src/scsi/scsi_ncr5380.c | 2 ++ src/scsi/scsi_ncr53c8xx.c | 2 ++ src/scsi/scsi_pcscsi.c | 4 ++++ src/scsi/scsi_spock.c | 9 ++++++--- 10 files changed, 64 insertions(+), 23 deletions(-) diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 336b0cfaf..2dffeeec3 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -1515,8 +1515,8 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) ide->sc->callback = 100.0 * IDE_TIME; ide_set_callback(ide, 100.0 * IDE_TIME); } else { - double seek_time = hdd_seek_get_time(&hdd[ide->hdd_num], - ide_get_sector(ide), HDD_OP_SEEK, 0, 0.0); + double seek_time = hdd_seek_get_time(&hdd[ide->hdd_num], (val & 0x60) ? + ide_get_sector(ide) : 0, HDD_OP_SEEK, 0, 0.0); ide_set_callback(ide, seek_time); } break; @@ -2062,8 +2062,6 @@ ide_callback(void *priv) switch (ide->command) { case WIN_SEEK ... 0x7F: chk_chs = !ide->lba; - fallthrough; - case WIN_RECAL ... 0x1F: if (ide->type == IDE_ATAPI) atapi_error_no_ready(ide); else { @@ -2077,6 +2075,15 @@ ide_callback(void *priv) } break; + case WIN_RECAL ... 0x1F: + if (ide->type == IDE_ATAPI) + atapi_error_no_ready(ide); + else { + ide->tf->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + } + break; + /* Initialize the Task File Registers as follows: Status = 00h, Error = 01h, Sector Count = 01h, Sector Number = 01h, Cylinder Low = 14h, Cylinder High = EBh and Drive/Head = 00h. */ diff --git a/src/include/86box/scsi_device.h b/src/include/86box/scsi_device.h index 0542ea84e..09f9ee2d9 100644 --- a/src/include/86box/scsi_device.h +++ b/src/include/86box/scsi_device.h @@ -448,4 +448,7 @@ extern void scsi_device_init(void); extern void scsi_reset(void); extern uint8_t scsi_get_bus(void); +extern void scsi_bus_set_speed(uint8_t bus, double speed); +extern double scsi_bus_get_speed(uint8_t bus); + #endif /*SCSI_DEVICE_H*/ diff --git a/src/scsi/scsi.c b/src/scsi/scsi.c index b1f358676..238fa7cb3 100644 --- a/src/scsi/scsi.c +++ b/src/scsi/scsi.c @@ -42,7 +42,8 @@ #include <86box/scsi_pcscsi.h> #include <86box/scsi_spock.h> -int scsi_card_current[SCSI_BUS_MAX] = { 0, 0 }; +int scsi_card_current[SCSI_BUS_MAX] = { 0, 0, 0, 0 }; +double scsi_bus_speed[SCSI_BUS_MAX] = { 0.0, 0.0, 0.0, 0.0 }; static uint8_t next_scsi_bus = 0; @@ -183,3 +184,15 @@ scsi_card_init(void) } } } + +void +scsi_bus_set_speed(uint8_t bus, double speed) +{ + scsi_bus_speed[bus] = speed; +} + +double +scsi_bus_get_speed(uint8_t bus) +{ + return scsi_bus_speed[bus]; +} diff --git a/src/scsi/scsi_aha154x.c b/src/scsi/scsi_aha154x.c index 5bfe854b3..05b8b2726 100644 --- a/src/scsi/scsi_aha154x.c +++ b/src/scsi/scsi_aha154x.c @@ -1101,6 +1101,8 @@ aha_init(const device_t *info) break; } + scsi_bus_set_speed(dev->bus, dev->ha_bps); + /* Initialize ROM BIOS if needed. */ aha_setbios(dev); diff --git a/src/scsi/scsi_buslogic.c b/src/scsi/scsi_buslogic.c index 4e8600ac6..ac3b464a8 100644 --- a/src/scsi/scsi_buslogic.c +++ b/src/scsi/scsi_buslogic.c @@ -1706,9 +1706,10 @@ buslogic_init(const device_t *info) break; } - if ((dev->Base != 0) && !(dev->card_bus & DEVICE_MCA) && !(dev->card_bus & DEVICE_PCI)) { + scsi_bus_set_speed(dev->bus, dev->ha_bps); + + if ((dev->Base != 0) && !(dev->card_bus & DEVICE_MCA) && !(dev->card_bus & DEVICE_PCI)) x54x_io_set(dev, dev->Base, 4); - } memset(bl->AutoSCSIROM, 0xff, 32768); diff --git a/src/scsi/scsi_disk.c b/src/scsi/scsi_disk.c index 6bca4b6d6..ee0c3fc00 100644 --- a/src/scsi/scsi_disk.c +++ b/src/scsi/scsi_disk.c @@ -12,11 +12,13 @@ * * Copyright 2017-2018 Miran Grca. */ +#include +#include +#include #include #include #include #include -#include #include #define HAVE_STDARG_H #include <86box/86box.h> @@ -433,8 +435,6 @@ scsi_disk_command_common(scsi_disk_t *dev) dev->tf->pos = 0; dev->callback = 0; - scsi_disk_log("SCSI HD %i: Current speed: %ix\n", dev->id, dev->drv->cur_speed); - if (dev->packet_status == PHASE_COMPLETE) { switch (dev->current_cdb[0]) { case GPCMD_VERIFY_6: @@ -447,12 +447,12 @@ scsi_disk_command_common(scsi_disk_t *dev) case GPCMD_WRITE_AND_VERIFY_12: case GPCMD_WRITE_SAME_10: /* Seek time is in us. */ - period = hdd_timing_write(dev->drv, dev->sector_pos, 1); + period = hdd_timing_write(dev->drv, dev->sector_pos, dev->packet_len >> 9); scsi_disk_log("SCSI HD %i: Seek period: %" PRIu64 " us\n", dev->id, (uint64_t) period); dev->callback += period; /* Account for seek time. */ - bytes_per_second = scsi_disk_bus_speed(dev); + bytes_per_second = scsi_bus_get_speed(dev->drv->scsi_id >> 4); period = 1000000.0 / bytes_per_second; scsi_disk_log("SCSI HD %i: Byte transfer period: %" PRIu64 " us\n", dev->id, @@ -472,7 +472,8 @@ scsi_disk_command_common(scsi_disk_t *dev) case 0x0b: case 0x2b: /* Seek time is in us. */ - period = hdd_timing_write(dev->drv, dev->sector_pos, 1); + period = hdd_seek_get_time(dev->drv, (dev->current_cdb[0] == GPCMD_REZERO_UNIT) ? + 0 : dev->sector_pos, HDD_OP_SEEK, 0, 0.0); scsi_disk_log("SCSI HD %i: Seek period: %" PRIu64 " us\n", dev->id, (uint64_t) period); dev->callback += period; @@ -482,15 +483,14 @@ scsi_disk_command_common(scsi_disk_t *dev) case 0x28: case 0xa8: /* Seek time is in us. */ - period = hdd_timing_write(dev->drv, dev->sector_pos, 1); + period = hdd_timing_read(dev->drv, dev->sector_pos, dev->packet_len >> 9); scsi_disk_log("SCSI HD %i: Seek period: %" PRIu64 " us\n", dev->id, (uint64_t) period); dev->callback += period; - fallthrough; - case 0x25: /* Account for seek time. */ - bytes_per_second = scsi_disk_bus_speed(dev); + bytes_per_second = scsi_bus_get_speed(dev->drv->scsi_id >> 4); break; + case 0x25: default: bytes_per_second = scsi_disk_bus_speed(dev); if (bytes_per_second == 0.0) { @@ -1684,6 +1684,8 @@ scsi_disk_hard_reset(void) valid = 1; + hdd_preset_apply(c); + if (!hdd[c].priv) hdd[c].priv = (scsi_disk_t *) calloc(1, sizeof(scsi_disk_t)); @@ -1710,17 +1712,19 @@ scsi_disk_hard_reset(void) continue; /* Make sure to ignore any SCSI disk whose image fails to load. */ - if (!hdd_image_load(c)) - continue; - /* ATAPI hard disk, attach to the IDE bus. */ id = ide_get_drive(hdd[c].ide_channel); /* If the IDE channel is initialized, we attach to it, otherwise, we do nothing - it's going to be a drive that's not attached to anything. */ if (id) { + if (!hdd_image_load(c)) + continue; + valid = 1; + hdd_preset_apply(c); + if (!hdd[c].priv) hdd[c].priv = (scsi_disk_t *) calloc(1, sizeof(scsi_disk_t)); diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index 7e4145d9a..285c65c80 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -1658,6 +1658,8 @@ ncr_init(const device_t *info) } timer_add(&ncr_dev->timer, ncr_callback, ncr_dev, 0); + scsi_bus_set_speed(ncr_dev->bus, 5000000.0); + return ncr_dev; } diff --git a/src/scsi/scsi_ncr53c8xx.c b/src/scsi/scsi_ncr53c8xx.c index d863cb6f1..42925338d 100644 --- a/src/scsi/scsi_ncr53c8xx.c +++ b/src/scsi/scsi_ncr53c8xx.c @@ -2623,6 +2623,8 @@ ncr53c8xx_init(const device_t *info) timer_add(&dev->timer, ncr53c8xx_callback, dev, 0); + scsi_bus_set_speed(dev->bus, 10000000.0); + return dev; } diff --git a/src/scsi/scsi_pcscsi.c b/src/scsi/scsi_pcscsi.c index 68f7b2011..7bf06b1c0 100644 --- a/src/scsi/scsi_pcscsi.c +++ b/src/scsi/scsi_pcscsi.c @@ -1870,6 +1870,8 @@ dc390_init(UNUSED(const device_t *info)) timer_add(&dev->timer, esp_callback, dev, 0); + scsi_bus_set_speed(dev->bus, 10000000.0); + return dev; } @@ -2040,6 +2042,8 @@ ncr53c90_mca_init(UNUSED(const device_t *info)) timer_add(&dev->timer, esp_callback, dev, 0); + scsi_bus_set_speed(dev->bus, 5000000.0); + return dev; } diff --git a/src/scsi/scsi_spock.c b/src/scsi/scsi_spock.c index 57a39a8d3..ba2817fe3 100644 --- a/src/scsi/scsi_spock.c +++ b/src/scsi/scsi_spock.c @@ -1164,15 +1164,18 @@ spock_init(const device_t *info) scsi->cmd_timer = SPOCK_TIME * 50; scsi->status = STATUS_BUSY; - for (uint8_t c = 0; c < (SCSI_ID_MAX - 1); c++) { + for (uint8_t c = 0; c < (SCSI_ID_MAX - 1); c++) scsi->dev_id[c].phys_id = -1; - } scsi->dev_id[SCSI_ID_MAX - 1].phys_id = scsi->adapter_id; timer_add(&scsi->callback_timer, spock_callback, scsi, 1); scsi->callback_timer.period = 10.0; - timer_set_delay_u64(&scsi->callback_timer, (uint64_t) (scsi->callback_timer.period * ((double) TIMER_USEC))); + + timer_set_delay_u64(&scsi->callback_timer, + (uint64_t) (scsi->callback_timer.period * ((double) TIMER_USEC))); + + scsi_bus_set_speed(scsi->bus, 5000000.0); return scsi; }