XTA fixes for both the regular and IBM PS/1 variants.
This commit is contained in:
@@ -102,7 +102,7 @@
|
||||
#include <86box/hdc.h>
|
||||
#include <86box/hdd.h>
|
||||
|
||||
#define HDC_TIME (50 * TIMER_USEC)
|
||||
#define HDC_TIME (250 * TIMER_USEC)
|
||||
|
||||
#define WD_REV_1_BIOS_FILE "roms/hdd/xta/idexywd2.bin"
|
||||
#define WD_REV_2_BIOS_FILE "roms/hdd/xta/infowdbios.rom"
|
||||
@@ -248,7 +248,6 @@ typedef struct hdc_t {
|
||||
uint8_t sense; /* current SENSE ERROR value */
|
||||
uint8_t status; /* current operational status */
|
||||
uint8_t intr;
|
||||
uint64_t callback;
|
||||
pc_timer_t timer;
|
||||
|
||||
/* Data transfer. */
|
||||
@@ -343,22 +342,6 @@ next_sector(hdc_t *dev, drive_t *drive)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
xta_set_callback(hdc_t *dev, uint64_t callback)
|
||||
{
|
||||
if (!dev) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
dev->callback = callback;
|
||||
timer_set_delay_u64(&dev->timer, dev->callback);
|
||||
} else {
|
||||
dev->callback = 0;
|
||||
timer_disable(&dev->timer);
|
||||
}
|
||||
}
|
||||
|
||||
/* Perform the seek operation. */
|
||||
static void
|
||||
do_seek(hdc_t *dev, drive_t *drive, int cyl)
|
||||
@@ -457,9 +440,6 @@ hdc_callback(void *priv)
|
||||
int no_data = 0;
|
||||
int val;
|
||||
|
||||
/* Cancel timer. */
|
||||
xta_set_callback(dev, 0);
|
||||
|
||||
drive = &dev->drives[dcb->drvsel];
|
||||
dev->comp = (dcb->drvsel) ? COMP_DRIVE : 0x00;
|
||||
dev->status |= STAT_DCB;
|
||||
@@ -558,12 +538,12 @@ do_send:
|
||||
dev->buf_idx = 0;
|
||||
if (no_data) {
|
||||
/* Delay a bit, no actual transfer. */
|
||||
xta_set_callback(dev, HDC_TIME);
|
||||
timer_advance_u64(&dev->timer, HDC_TIME);
|
||||
} else {
|
||||
if (dev->intr & DMA_ENA) {
|
||||
/* DMA enabled. */
|
||||
dev->buf_ptr = dev->sector_buf;
|
||||
xta_set_callback(dev, HDC_TIME);
|
||||
timer_advance_u64(&dev->timer, HDC_TIME);
|
||||
} else {
|
||||
/* Copy from sector to data. */
|
||||
memcpy(dev->data,
|
||||
@@ -586,14 +566,14 @@ do_send:
|
||||
xta_log("%s: CMD_READ_SECTORS out of data (idx=%d, len=%d)!\n", dev->name, dev->buf_idx, dev->buf_len);
|
||||
|
||||
dev->status |= (STAT_CD | STAT_IO | STAT_REQ);
|
||||
xta_set_callback(dev, HDC_TIME);
|
||||
timer_advance_u64(&dev->timer, HDC_TIME);
|
||||
return;
|
||||
}
|
||||
dev->buf_ptr++;
|
||||
dev->buf_idx++;
|
||||
}
|
||||
}
|
||||
xta_set_callback(dev, HDC_TIME);
|
||||
timer_advance_u64(&dev->timer, HDC_TIME);
|
||||
dev->state = STATE_SDONE;
|
||||
break;
|
||||
|
||||
@@ -654,7 +634,7 @@ do_recv:
|
||||
if (dev->intr & DMA_ENA) {
|
||||
/* DMA enabled. */
|
||||
dev->buf_ptr = dev->sector_buf;
|
||||
xta_set_callback(dev, HDC_TIME);
|
||||
timer_advance_u64(&dev->timer, HDC_TIME);
|
||||
} else {
|
||||
/* No DMA, do PIO. */
|
||||
dev->buf_ptr = dev->data;
|
||||
@@ -673,7 +653,7 @@ do_recv:
|
||||
|
||||
xta_log("%s: CMD_WRITE_SECTORS out of data!\n", dev->name);
|
||||
dev->status |= (STAT_CD | STAT_IO | STAT_REQ);
|
||||
xta_set_callback(dev, HDC_TIME);
|
||||
timer_advance_u64(&dev->timer, HDC_TIME);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -681,7 +661,7 @@ do_recv:
|
||||
dev->buf_idx++;
|
||||
}
|
||||
dev->state = STATE_RDONE;
|
||||
xta_set_callback(dev, HDC_TIME);
|
||||
timer_advance_u64(&dev->timer, HDC_TIME);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -785,7 +765,7 @@ do_recv:
|
||||
dev->state = STATE_RDATA;
|
||||
if (dev->intr & DMA_ENA) {
|
||||
dev->buf_ptr = dev->sector_buf;
|
||||
xta_set_callback(dev, HDC_TIME);
|
||||
timer_advance_u64(&dev->timer, HDC_TIME);
|
||||
} else {
|
||||
dev->buf_ptr = dev->data;
|
||||
dev->status |= STAT_REQ;
|
||||
@@ -800,7 +780,7 @@ do_recv:
|
||||
if (val == DMA_NODATA) {
|
||||
xta_log("%s: CMD_WRITE_BUFFER out of data!\n", dev->name);
|
||||
dev->status |= (STAT_CD | STAT_IO | STAT_REQ);
|
||||
xta_set_callback(dev, HDC_TIME);
|
||||
timer_advance_u64(&dev->timer, HDC_TIME);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -808,7 +788,7 @@ do_recv:
|
||||
dev->buf_idx++;
|
||||
}
|
||||
dev->state = STATE_RDONE;
|
||||
xta_set_callback(dev, HDC_TIME);
|
||||
timer_advance_u64(&dev->timer, HDC_TIME);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -828,7 +808,7 @@ do_recv:
|
||||
switch (dev->state) {
|
||||
case STATE_IDLE:
|
||||
dev->state = STATE_RDONE;
|
||||
xta_set_callback(dev, 5 * HDC_TIME);
|
||||
timer_advance_u64(&dev->timer, 5 * HDC_TIME);
|
||||
break;
|
||||
|
||||
case STATE_RDONE:
|
||||
@@ -845,7 +825,7 @@ do_recv:
|
||||
case STATE_IDLE:
|
||||
if (drive->present) {
|
||||
dev->state = STATE_RDONE;
|
||||
xta_set_callback(dev, 5 * HDC_TIME);
|
||||
timer_advance_u64(&dev->timer, 5 * HDC_TIME);
|
||||
} else {
|
||||
dev->comp |= COMP_ERR;
|
||||
dev->sense = ERR_NOTRDY;
|
||||
@@ -866,7 +846,7 @@ do_recv:
|
||||
switch (dev->state) {
|
||||
case STATE_IDLE:
|
||||
dev->state = STATE_RDONE;
|
||||
xta_set_callback(dev, 10 * HDC_TIME);
|
||||
timer_advance_u64(&dev->timer, 10 * HDC_TIME);
|
||||
break;
|
||||
|
||||
case STATE_RDONE:
|
||||
@@ -911,7 +891,7 @@ hdc_read(uint16_t port, void *priv)
|
||||
/* All data sent. */
|
||||
dev->status &= ~STAT_REQ;
|
||||
dev->state = STATE_SDONE;
|
||||
xta_set_callback(dev, HDC_TIME);
|
||||
timer_set_delay_u64(&dev->timer, HDC_TIME);
|
||||
}
|
||||
} else if (dev->state == STATE_COMPL) {
|
||||
xta_log("DCB=%02X status=%02X comp=%02X\n", dev->dcb.cmd, dev->status, dev->comp);
|
||||
@@ -969,7 +949,7 @@ hdc_write(uint16_t port, uint8_t val, void *priv)
|
||||
else
|
||||
dev->state = STATE_IDLE;
|
||||
dev->status &= ~STAT_CD;
|
||||
xta_set_callback(dev, HDC_TIME);
|
||||
timer_set_delay_u64(&dev->timer, HDC_TIME);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@@ -99,7 +99,7 @@
|
||||
#include <86box/ui.h>
|
||||
#include <86box/machine.h>
|
||||
|
||||
#define HDC_TIME (50 * TIMER_USEC)
|
||||
#define HDC_TIME (250 * TIMER_USEC)
|
||||
#define HDC_TYPE_USER 47 /* user drive type */
|
||||
|
||||
enum {
|
||||
@@ -380,7 +380,6 @@ typedef struct hdc_t {
|
||||
uint8_t *reg_91; /* handle to system board's register 0x91 */
|
||||
|
||||
/* Controller state. */
|
||||
uint64_t callback;
|
||||
pc_timer_t timer;
|
||||
int8_t state; /* controller state */
|
||||
int8_t reset; /* reset state counter */
|
||||
@@ -463,6 +462,7 @@ static const geom_t ibm_type_table[] = {
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
#define ENABLE_PS1_HDC_LOG 1
|
||||
#ifdef ENABLE_PS1_HDC_LOG
|
||||
int ps1_hdc_do_log = ENABLE_PS1_HDC_LOG;
|
||||
|
||||
@@ -481,22 +481,6 @@ ps1_hdc_log(const char *fmt, ...)
|
||||
# define ps1_hdc_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
static void
|
||||
hdc_set_callback(hdc_t *dev, uint64_t callback)
|
||||
{
|
||||
if (!dev) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
dev->callback = callback;
|
||||
timer_set_delay_u64(&dev->timer, dev->callback);
|
||||
} else {
|
||||
dev->callback = 0;
|
||||
timer_disable(&dev->timer);
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: we should use the disk/hdd_table.c code with custom tables! */
|
||||
static int
|
||||
ibm_drive_type(drive_t *drive)
|
||||
@@ -633,7 +617,7 @@ do_format(hdc_t *dev, drive_t *drive, ccb_t *ccb)
|
||||
/* Enable for PIO or DMA, as needed. */
|
||||
#if NOT_USED
|
||||
if (dev->ctrl & ACR_DMA_EN)
|
||||
hdc_set_callback(dev, HDC_TIME);
|
||||
timer_advance_u64(&dev->timer, HDC_TIME);
|
||||
else
|
||||
#endif
|
||||
dev->status |= ASR_DATA_REQ;
|
||||
@@ -653,7 +637,7 @@ do_format(hdc_t *dev, drive_t *drive, ccb_t *ccb)
|
||||
dev->buf_idx++;
|
||||
}
|
||||
dev->state = STATE_RDONE;
|
||||
hdc_set_callback(dev, HDC_TIME);
|
||||
timer_advance_u64(&dev->timer, HDC_TIME);
|
||||
break;
|
||||
|
||||
case STATE_RDONE:
|
||||
@@ -737,9 +721,7 @@ hdc_callback(void *priv)
|
||||
off64_t addr;
|
||||
int no_data = 0;
|
||||
int val;
|
||||
|
||||
/* Cancel timer. */
|
||||
dev->callback = 0;
|
||||
uint8_t cmd = ccb->cmd & 0x0f;
|
||||
|
||||
/* Clear the SSB error bits. */
|
||||
dev->ssb.track_0 = 0;
|
||||
@@ -758,6 +740,8 @@ hdc_callback(void *priv)
|
||||
/* We really only support one drive, but ohwell. */
|
||||
drive = &dev->drives[0];
|
||||
|
||||
ps1_hdc_log("hdc_callback(): %02X\n", cmd);
|
||||
|
||||
switch (ccb->cmd) {
|
||||
case CMD_READ_VERIFY:
|
||||
no_data = 1;
|
||||
@@ -812,12 +796,12 @@ do_send:
|
||||
dev->buf_idx = 0;
|
||||
if (no_data) {
|
||||
/* Delay a bit, no actual transfer. */
|
||||
hdc_set_callback(dev, HDC_TIME);
|
||||
timer_advance_u64(&dev->timer, HDC_TIME);
|
||||
} else {
|
||||
if (dev->ctrl & ACR_DMA_EN) {
|
||||
/* DMA enabled. */
|
||||
dev->buf_ptr = dev->sector_buf;
|
||||
hdc_set_callback(dev, HDC_TIME);
|
||||
timer_advance_u64(&dev->timer, HDC_TIME);
|
||||
} else {
|
||||
/* No DMA, do PIO. */
|
||||
dev->status |= (ASR_DATA_REQ | ASR_DIR);
|
||||
@@ -852,7 +836,7 @@ do_send:
|
||||
}
|
||||
}
|
||||
dev->state = STATE_SDONE;
|
||||
hdc_set_callback(dev, HDC_TIME);
|
||||
timer_advance_u64(&dev->timer, HDC_TIME);
|
||||
break;
|
||||
|
||||
case STATE_SDONE:
|
||||
@@ -880,7 +864,6 @@ do_send:
|
||||
}
|
||||
break;
|
||||
|
||||
case CMD_READ_EXT: /* READ_EXT */
|
||||
case CMD_READ_ID: /* READ_ID */
|
||||
if (!drive->present) {
|
||||
dev->ssb.not_ready = 1;
|
||||
@@ -888,6 +871,56 @@ do_send:
|
||||
return;
|
||||
}
|
||||
|
||||
switch (dev->state) {
|
||||
case STATE_IDLE:
|
||||
/* Seek to cylinder if requested. */
|
||||
if (ccb->auto_seek) {
|
||||
if (do_seek(dev, drive,
|
||||
(ccb->cyl_low | (ccb->cyl_high << 8)))) {
|
||||
do_finish(dev);
|
||||
return;
|
||||
}
|
||||
}
|
||||
dev->head = ccb->head;
|
||||
|
||||
/* Get sector count and size. */
|
||||
dev->count = (int) ccb->count;
|
||||
dev->buf_len = (128 << dev->ssb.sect_size);
|
||||
|
||||
/* Activate the status icon. */
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 1);
|
||||
|
||||
/* Ready to transfer the data out. */
|
||||
dev->state = STATE_SDONE;
|
||||
dev->buf_idx = 0;
|
||||
/* Delay a bit, no actual transfer. */
|
||||
timer_advance_u64(&dev->timer, HDC_TIME);
|
||||
break;
|
||||
|
||||
case STATE_SDONE:
|
||||
dev->buf_idx = 0;
|
||||
|
||||
/* De-activate the status icon. */
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 0);
|
||||
|
||||
if (!(dev->ctrl & ACR_DMA_EN))
|
||||
dev->status &= ~(ASR_DATA_REQ | ASR_DIR);
|
||||
dev->ssb.cmd_syndrome = 0x14;
|
||||
do_finish(dev);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case CMD_READ_EXT: /* READ_EXT */
|
||||
if (!drive->present) {
|
||||
dev->ssb.not_ready = 1;
|
||||
do_finish(dev);
|
||||
return;
|
||||
}
|
||||
|
||||
dev->intstat |= ISR_INVALID_CMD;
|
||||
do_finish(dev);
|
||||
break;
|
||||
@@ -943,12 +976,12 @@ do_recv:
|
||||
dev->buf_idx = 0;
|
||||
if (no_data) {
|
||||
/* Delay a bit, no actual transfer. */
|
||||
hdc_set_callback(dev, HDC_TIME);
|
||||
timer_advance_u64(&dev->timer, HDC_TIME);
|
||||
} else {
|
||||
if (dev->ctrl & ACR_DMA_EN) {
|
||||
/* DMA enabled. */
|
||||
dev->buf_ptr = dev->sector_buf;
|
||||
hdc_set_callback(dev, HDC_TIME);
|
||||
timer_advance_u64(&dev->timer, HDC_TIME);
|
||||
} else {
|
||||
/* No DMA, do PIO. */
|
||||
dev->buf_ptr = dev->data;
|
||||
@@ -978,7 +1011,7 @@ do_recv:
|
||||
}
|
||||
}
|
||||
dev->state = STATE_RDONE;
|
||||
hdc_set_callback(dev, HDC_TIME);
|
||||
timer_advance_u64(&dev->timer, HDC_TIME);
|
||||
break;
|
||||
|
||||
case STATE_RDONE:
|
||||
@@ -1140,6 +1173,8 @@ hdc_read(uint16_t port, void *priv)
|
||||
break;
|
||||
}
|
||||
|
||||
ps1_hdc_log("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, port, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1148,6 +1183,8 @@ hdc_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
hdc_t *dev = (hdc_t *) priv;
|
||||
|
||||
ps1_hdc_log("[%04X:%08X] [W] %04X = %02X\n", CS, cpu_state.pc, port, val);
|
||||
|
||||
/* TRM: tell system board we are alive. */
|
||||
*dev->reg_91 |= 0x01;
|
||||
|
||||
@@ -1164,6 +1201,7 @@ hdc_write(uint16_t port, uint8_t val, void *priv)
|
||||
|
||||
/* Store the data into the buffer. */
|
||||
dev->buf_ptr[dev->buf_idx] = val;
|
||||
ps1_hdc_log("dev->buf_ptr[%02X] = %02X\n", dev->buf_idx, val);
|
||||
if (++dev->buf_idx == dev->buf_len) {
|
||||
/* We got all the data we need. */
|
||||
dev->status &= ~ASR_DATA_REQ;
|
||||
@@ -1182,7 +1220,7 @@ hdc_write(uint16_t port, uint8_t val, void *priv)
|
||||
dev->status |= ASR_BUSY;
|
||||
|
||||
/* Schedule command execution. */
|
||||
hdc_set_callback(dev, HDC_TIME);
|
||||
timer_set_delay_u64(&dev->timer, HDC_TIME);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user