ESDI: implement HDD timings
This commit is contained in:
@@ -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));
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
||||
|
Reference in New Issue
Block a user