Fix FDC's on MCA IBM PS/2 machines fixes #4962.

This commit is contained in:
OBattler
2024-12-03 02:07:02 +01:00
parent 2e8bdaf587
commit 75fda2f046
7 changed files with 104 additions and 78 deletions

View File

@@ -184,8 +184,6 @@ fdc_ctrl_reset(void *priv)
fdc->head = 0; fdc->head = 0;
fdc->step = 0; fdc->step = 0;
fdc->power_down = 0; fdc->power_down = 0;
if (!(fdc->flags & FDC_FLAG_AT))
fdc->rate = 2;
} }
sector_id_t sector_id_t
@@ -1211,7 +1209,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
if (!(fdc->flags & FDC_FLAG_TOSHIBA) && !(fdc->flags & FDC_FLAG_AT) && !(fdc->flags & FDC_FLAG_UMC)) if (!(fdc->flags & FDC_FLAG_TOSHIBA) && !(fdc->flags & FDC_FLAG_AT) && !(fdc->flags & FDC_FLAG_UMC))
return; return;
fdc->rate = val & 0x03; fdc->rate = val & 0x03;
if (fdc->flags & FDC_FLAG_PS1) if (fdc->flags & FDC_FLAG_PS2)
fdc->noprec = !!(val & 0x04); fdc->noprec = !!(val & 0x04);
return; return;
@@ -1231,7 +1229,7 @@ fdc_read(uint16_t addr, void *priv)
if (!fdc->power_down || ((addr & 7) == 2)) switch (addr & 7) { if (!fdc->power_down || ((addr & 7) == 2)) switch (addr & 7) {
case 0: /* STA */ case 0: /* STA */
if (fdc->flags & FDC_FLAG_PS1) { if (fdc->flags & FDC_FLAG_PS2) {
drive = real_drive(fdc, fdc->dor & 3); drive = real_drive(fdc, fdc->dor & 3);
ret = 0x00; ret = 0x00;
/* TODO: /* TODO:
@@ -1251,18 +1249,36 @@ fdc_read(uint16_t addr, void *priv)
ret |= 0x40; ret |= 0x40;
if (fdc->fintr || fdc->reset_stat) /* INTR */ if (fdc->fintr || fdc->reset_stat) /* INTR */
ret |= 0x80; ret |= 0x80;
} else if (fdc->flags & FDC_FLAG_PS2_MCA) {
drive = real_drive(fdc, fdc->dor & 3);
ret = 0x04;
/* TODO:
Bit 2: nINDEX (best return always 1 as it goes by very fast)
*/
if (!fdc->seek_dir) /* DIRECTION */
ret |= 0x01;
if (!writeprot[drive]) /* nWRITEPROT */
ret |= 0x02;
if (fdd_get_head(drive)) /* HDSEL */
ret |= 0x08;
if (!fdd_track0(drive)) /* nTRK0 */
ret |= 0x10;
if (fdc->step) /* STEP */
ret |= 0x20;
if (!fdd_get_type(1)) /* -Drive 2 Installed */
ret |= 0x40;
if (fdc->fintr || fdc->reset_stat) /* INTR */
ret |= 0x80;
} else } else
ret = 0xff; ret = 0xff;
break; break;
case 1: /* STB */ case 1: /* STB */
if (fdc->flags & FDC_FLAG_PS1) { if (fdc->flags & FDC_FLAG_PS2) {
drive = real_drive(fdc, fdc->dor & 3); drive = real_drive(fdc, fdc->dor & 3);
ret = 0x00; ret = 0x00;
/* -Drive 2 Installed */ if (!fdd_get_type(1)) /* -Drive 2 Installed */
if (!fdd_get_type(1))
ret |= 0x80; ret |= 0x80;
/* -Drive Select 1,0 */ switch (drive) { /* -Drive Select 1,0 */
switch (drive) {
case 0: case 0:
ret |= 0x43; ret |= 0x43;
break; break;
@@ -1279,6 +1295,11 @@ fdc_read(uint16_t addr, void *priv)
default: default:
break; break;
} }
} else if (fdc->flags & FDC_FLAG_PS2_MCA) {
drive = real_drive(fdc, fdc->dor & 3);
ret = 0xc0;
ret |= (fdc->dor & 0x01) << 5; /* Drive Select 0 */
ret |= (fdc->dor & 0x30) >> 4; /* Motor Select 1, 0 */
} else { } else {
if (is486 || !fdc->enable_3f1) if (is486 || !fdc->enable_3f1)
ret = 0xff; ret = 0xff;
@@ -1287,19 +1308,12 @@ fdc_read(uint16_t addr, void *priv)
drive = real_drive(fdc, fdc->dor & 1); drive = real_drive(fdc, fdc->dor & 1);
ret = !fdd_is_dd(drive) ? ((fdc->dor & 1) ? 2 : 1) : 0; ret = !fdd_is_dd(drive) ? ((fdc->dor & 1) ? 2 : 1) : 0;
} else { } else {
ret = 0x70; /* TODO: What is this and what is it used for?
It's almost identical to the PS/2 MCA mode. */
drive = real_drive(fdc, fdc->dor & 3); drive = real_drive(fdc, fdc->dor & 3);
ret = 0x70;
if (drive) ret &= ~(drive ? 0x40 : 0x20);
ret &= ~0x40; ret |= (fdc->dor & 0x30) >> 4; /* Motor Select 1, 0 */
else
ret &= ~0x20;
if (fdc->dor & 0x10)
ret |= 1;
if (fdc->dor & 0x20)
ret |= 2;
} }
} }
} }
@@ -1309,7 +1323,8 @@ fdc_read(uint16_t addr, void *priv)
break; break;
case 3: case 3:
drive = real_drive(fdc, fdc->dor & 3); drive = real_drive(fdc, fdc->dor & 3);
if (fdc->flags & FDC_FLAG_PS1) { /* TODO: FDC_FLAG_PS2_TDR? */
if ((fdc->flags & FDC_FLAG_PS2) || (fdc->flags & FDC_FLAG_PS2_MCA)) {
/* PS/1 Model 2121 seems return drive type in port /* PS/1 Model 2121 seems return drive type in port
* 0x3f3, despite the 82077AA fdc_t not implementing * 0x3f3, despite the 82077AA fdc_t not implementing
* this. This is presumably implemented outside the * this. This is presumably implemented outside the
@@ -1371,7 +1386,7 @@ fdc_read(uint16_t addr, void *priv)
case 7: /*Disk change*/ case 7: /*Disk change*/
drive = real_drive(fdc, fdc->dor & 3); drive = real_drive(fdc, fdc->dor & 3);
if (fdc->flags & FDC_FLAG_PS1) { if (fdc->flags & FDC_FLAG_PS2) {
if (fdc->dor & (0x10 << drive)) { if (fdc->dor & (0x10 << drive)) {
ret = (fdd_changed[drive] || drive_empty[drive]) ? 0x00 : 0x80; ret = (fdd_changed[drive] || drive_empty[drive]) ? 0x00 : 0x80;
ret |= (fdc->dor & 0x08); ret |= (fdc->dor & 0x08);
@@ -1379,6 +1394,14 @@ fdc_read(uint16_t addr, void *priv)
ret |= (fdc->rate & 0x03); ret |= (fdc->rate & 0x03);
} else } else
ret = 0x00; ret = 0x00;
} else if (fdc->flags & FDC_FLAG_PS2_MCA) {
if (fdc->dor & (0x10 << drive)) {
ret = (fdd_changed[drive] || drive_empty[drive]) ? 0x80 : 0x00;
ret |= ((fdc->rate & 0x03) << 1);
ret |= fdc_get_densel(fdc, drive);
ret |= 0x78;
} else
ret = 0xf9;
} else { } else {
if (fdc->dor & (0x10 << drive)) { if (fdc->dor & (0x10 << drive)) {
if ((drive == 1) && (fdc->flags & FDC_FLAG_TOSHIBA)) if ((drive == 1) && (fdc->flags & FDC_FLAG_TOSHIBA))
@@ -1411,7 +1434,7 @@ static void
fdc_poll_common_finish(fdc_t *fdc, int compare, int st5) fdc_poll_common_finish(fdc_t *fdc, int compare, int st5)
{ {
fdc_int(fdc, 1); fdc_int(fdc, 1);
if (!(fdc->flags & FDC_FLAG_PS1)) if (!(fdc->flags & FDC_FLAG_FINTR))
fdc->fintr = 0; fdc->fintr = 0;
fdc->stat = 0xD0; fdc->stat = 0xD0;
fdc->st0 = fdc->res[4] = (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->rw_drive; fdc->st0 = fdc->res[4] = (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->rw_drive;
@@ -1712,7 +1735,7 @@ fdc_callback(void *priv)
} else { } else {
fdc->interrupt = -2; fdc->interrupt = -2;
fdc_int(fdc, 1); fdc_int(fdc, 1);
if (!(fdc->flags & FDC_FLAG_PS1)) if (!(fdc->flags & FDC_FLAG_FINTR))
fdc->fintr = 0; fdc->fintr = 0;
fdc->stat = 0xD0; fdc->stat = 0xD0;
fdc->st0 = fdc->res[4] = (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->drive; fdc->st0 = fdc->res[4] = (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->drive;
@@ -1804,7 +1827,7 @@ fdc_error(fdc_t *fdc, int st5, int st6)
timer_disable(&fdc->timer); timer_disable(&fdc->timer);
fdc_int(fdc, 1); fdc_int(fdc, 1);
if (!(fdc->flags & FDC_FLAG_PS1)) if (!(fdc->flags & FDC_FLAG_FINTR))
fdc->fintr = 0; fdc->fintr = 0;
fdc->stat = 0xD0; fdc->stat = 0xD0;
fdc->st0 = fdc->res[4] = 0x40 | (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->rw_drive; fdc->st0 = fdc->res[4] = 0x40 | (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->rw_drive;
@@ -2213,7 +2236,7 @@ fdc_reset(void *priv)
fdc->enable_3f1 = 1; fdc->enable_3f1 = 1;
fdc_update_enh_mode(fdc, 0); fdc_update_enh_mode(fdc, 0);
if (fdc->flags & FDC_FLAG_PS1) if (fdc->flags & FDC_FLAG_DENSEL_INVERT)
fdc_update_densel_polarity(fdc, 0); fdc_update_densel_polarity(fdc, 0);
else else
fdc_update_densel_polarity(fdc, 1); fdc_update_densel_polarity(fdc, 1);
@@ -2259,6 +2282,9 @@ fdc_reset(void *priv)
fdc_ctrl_reset(fdc); fdc_ctrl_reset(fdc);
if (!(fdc->flags & FDC_FLAG_AT))
fdc->rate = 2;
fdc->max_track = (fdc->flags & FDC_FLAG_MORE_TRACKS) ? 85 : 79; fdc->max_track = (fdc->flags & FDC_FLAG_MORE_TRACKS) ? 85 : 79;
fdc_remove(fdc); fdc_remove(fdc);
@@ -2443,6 +2469,20 @@ const device_t fdc_xt_tandy_device = {
.config = NULL .config = NULL
}; };
const device_t fdc_xt_umc_um8398_device = {
.name = "PC/XT Floppy Drive Controller (UMC UM8398)",
.internal_name = "fdc_xt_umc_um8398",
.flags = 0,
.local = FDC_FLAG_UMC,
.init = fdc_init,
.close = fdc_close,
.reset = fdc_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t fdc_pcjr_device = { const device_t fdc_pcjr_device = {
.name = "PCjr Floppy Drive Controller", .name = "PCjr Floppy Drive Controller",
.internal_name = "fdc_pcjr", .internal_name = "fdc_pcjr",
@@ -2527,34 +2567,6 @@ const device_t fdc_at_actlow_device = {
.config = NULL .config = NULL
}; };
const device_t fdc_at_ps1_device = {
.name = "PC/AT Floppy Drive Controller (PS/1, PS/2 ISA)",
.internal_name = "fdc_at_ps1",
.flags = 0,
.local = FDC_FLAG_DISKCHG_ACTLOW | FDC_FLAG_AT | FDC_FLAG_PS1,
.init = fdc_init,
.close = fdc_close,
.reset = fdc_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t fdc_at_ps1_2121_device = {
.name = "PC/AT Floppy Drive Controller (PS/1, PS/2 ISA)",
.internal_name = "fdc_at_ps1",
.flags = 0,
.local = FDC_FLAG_NO_DSR_RESET | FDC_FLAG_DISKCHG_ACTLOW | FDC_FLAG_AT | FDC_FLAG_PS1,
.init = fdc_init,
.close = fdc_close,
.reset = fdc_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t fdc_at_smc_device = { const device_t fdc_at_smc_device = {
.name = "PC/AT Floppy Drive Controller (SM(s)C FDC37Cxxx)", .name = "PC/AT Floppy Drive Controller (SM(s)C FDC37Cxxx)",
.internal_name = "fdc_at_smc", .internal_name = "fdc_at_smc",
@@ -2611,9 +2623,9 @@ const device_t fdc_at_nsc_device = {
.config = NULL .config = NULL
}; };
const device_t fdc_dp8473_device = { const device_t fdc_at_nsc_dp8473_device = {
.name = "NS DP8473 Floppy Drive Controller", .name = "PC/AT Floppy Drive Controller (NSC DP8473)",
.internal_name = "fdc_dp8473", .internal_name = "fdc_at_nsc_dp8473",
.flags = 0, .flags = 0,
.local = FDC_FLAG_AT | FDC_FLAG_NEC | FDC_FLAG_NO_DSR_RESET, .local = FDC_FLAG_AT | FDC_FLAG_NEC | FDC_FLAG_NO_DSR_RESET,
.init = fdc_init, .init = fdc_init,
@@ -2625,11 +2637,27 @@ const device_t fdc_dp8473_device = {
.config = NULL .config = NULL
}; };
const device_t fdc_um8398_device = { const device_t fdc_ps2_device = {
.name = "UMC UM8398 Floppy Drive Controller", .name = "PS/2 Model 25/30 Floppy Drive Controller",
.internal_name = "fdc_um8398", .internal_name = "fdc_ps2",
.flags = 0, .flags = 0,
.local = FDC_FLAG_UMC, .local = FDC_FLAG_FINTR | FDC_FLAG_DENSEL_INVERT | FDC_FLAG_NO_DSR_RESET | FDC_FLAG_DISKCHG_ACTLOW |
FDC_FLAG_AT | FDC_FLAG_PS2,
.init = fdc_init,
.close = fdc_close,
.reset = fdc_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t fdc_ps2_mca_device = {
.name = "PS/2 MCA Floppy Drive Controller",
.internal_name = "fdc_ps2_mca",
.flags = 0,
.local = FDC_FLAG_FINTR | FDC_FLAG_DENSEL_INVERT | FDC_FLAG_NO_DSR_RESET | FDC_FLAG_AT |
FDC_FLAG_PS2_MCA,
.init = fdc_init, .init = fdc_init,
.close = fdc_close, .close = fdc_close,
.reset = fdc_reset, .reset = fdc_reset,

View File

@@ -95,7 +95,7 @@ b215_init(UNUSED(const device_t *info))
rom_init(&dev->rom, ROM_B215, ROM_ADDR, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); rom_init(&dev->rom, ROM_B215, ROM_ADDR, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL);
dev->fdc_controller = device_add(&fdc_um8398_device); dev->fdc_controller = device_add(&fdc_xt_umc_um8398_device);
io_sethandler(FDC_PRIMARY_ADDR, 1, b215_read, NULL, NULL, NULL, NULL, NULL, dev); io_sethandler(FDC_PRIMARY_ADDR, 1, b215_read, NULL, NULL, NULL, NULL, NULL, dev);
return dev; return dev;

View File

@@ -75,7 +75,7 @@ MiniMicro 4 also won't work with the XT FDC which the Zilog claims to be.
#include <86box/fdc_ext.h> #include <86box/fdc_ext.h>
#define DTK_VARIANT ((info->local == 158) ? ROM_PII_158B : ROM_PII_151B) #define DTK_VARIANT ((info->local == 158) ? ROM_PII_158B : ROM_PII_151B)
#define DTK_CHIP ((info->local == 158) ? &fdc_xt_device : &fdc_dp8473_device) #define DTK_CHIP ((info->local == 158) ? &fdc_xt_device : &fdc_at_nsc_dp8473_device)
#define BIOS_ADDR (uint32_t)(device_get_config_hex20("bios_addr") & 0x000fffff) #define BIOS_ADDR (uint32_t)(device_get_config_hex20("bios_addr") & 0x000fffff)
#define ROM_PII_151B "roms/floppy/dtk/pii-151b.rom" #define ROM_PII_151B "roms/floppy/dtk/pii-151b.rom"
#define ROM_PII_158B "roms/floppy/dtk/pii-158b.rom" #define ROM_PII_158B "roms/floppy/dtk/pii-158b.rom"

View File

@@ -294,7 +294,7 @@ fdd_type_invert_densel(int type)
int ret; int ret;
if (drive_types[type].flags & FLAG_PS2) if (drive_types[type].flags & FLAG_PS2)
ret = !strstr(machine_getname(), "PS/2"); ret = !!strstr(machine_getname(), "PS/");
else else
ret = drive_types[type].flags & FLAG_INVERT_DENSEL; ret = drive_types[type].flags & FLAG_INVERT_DENSEL;

View File

@@ -323,6 +323,8 @@ ps1_setup(int model)
device_add(&ps_nvr_device); device_add(&ps_nvr_device);
device_add(&fdc_ps2_device);
if (model == 2011) { if (model == 2011) {
if (!strcmp("english_us", device_get_config_bios("bios_language"))) { if (!strcmp("english_us", device_get_config_bios("bios_language"))) {
/* US English */ /* US English */
@@ -350,8 +352,6 @@ ps1_setup(int model)
device_add(&ps1snd_device); device_add(&ps1snd_device);
device_add(&fdc_at_ps1_device);
/* Enable the builtin HDC. */ /* Enable the builtin HDC. */
if (hdc_current[0] == HDC_INTERNAL) { if (hdc_current[0] == HDC_INTERNAL) {
priv = device_add(&ps1_hdc_device); priv = device_add(&ps1_hdc_device);
@@ -378,8 +378,6 @@ ps1_setup(int model)
if (gfxcard[0] == VID_INTERNAL) if (gfxcard[0] == VID_INTERNAL)
device_add(&ibm_ps1_2121_device); device_add(&ibm_ps1_2121_device);
device_add(&fdc_at_ps1_2121_device);
device_add(&ide_isa_device); device_add(&ide_isa_device);
device_add(&ps1snd_device); device_add(&ps1snd_device);

View File

@@ -176,7 +176,7 @@ ps2_isa_setup(int model, int cpu_type)
device_add(&ps_nvr_device); device_add(&ps_nvr_device);
device_add(&fdc_at_ps1_device); device_add(&fdc_ps2_device);
/* Enable the builtin HDC. */ /* Enable the builtin HDC. */
if (hdc_current[0] == HDC_INTERNAL) { if (hdc_current[0] == HDC_INTERNAL) {

View File

@@ -1396,7 +1396,7 @@ machine_ps2_common_init(const machine_t *model)
machine_common_init(model); machine_common_init(model);
if (fdc_current[0] == FDC_INTERNAL) if (fdc_current[0] == FDC_INTERNAL)
device_add(&fdc_at_device); device_add(&fdc_ps2_mca_device);
dma16_init(); dma16_init();
ps2_dma_init(); ps2_dma_init();