From 87c37650716ce7975f07ffc43ce4e646a2bfccaf Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 2 Aug 2025 17:44:16 +0200 Subject: [PATCH] SM(S)C FDC73c93x and NSC PC87309 fixes. --- src/device/serial.c | 8 ++++++ src/floppy/fdc.c | 38 ++++++++++++++++++++++++++++ src/include/86box/fdc.h | 5 ++++ src/include/86box/serial.h | 1 + src/include/86box/sio.h | 1 - src/machine/m_at_slot1.c | 3 +-- src/sio/sio_fdc37c93x.c | 52 ++++++++++++++++++++++++++++++-------- src/sio/sio_pc87309.c | 2 +- 8 files changed, 95 insertions(+), 15 deletions(-) diff --git a/src/device/serial.c b/src/device/serial.c index 71be924c1..8e2071064 100644 --- a/src/device/serial.c +++ b/src/device/serial.c @@ -746,6 +746,14 @@ serial_read(uint16_t addr, void *priv) return ret; } +uint8_t +serial_get_shadow(serial_t *dev) +{ + uint8_t ret = dev->fcr; + + return ret; +} + void serial_remove(serial_t *dev) { diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 6f23eea9d..28e3b150f 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -438,6 +438,44 @@ fdc_set_media_id(fdc_t *fdc, int id, int set) fdc->media_id = (fdc->media_id & ~(1 << id)) | (set << id); } +void +fdc_set_flags(fdc_t *fdc, int flags) +{ + fdc->flags |= flags; +} + +void +fdc_clear_flags(fdc_t *fdc, int flags) +{ + fdc->flags &= ~flags; +} + +void +fdc_set_fdd_changed(int drive, int changed) +{ + if (changed) + fdd_changed[drive] = 1; +} + +uint8_t +fdc_get_fdd_changed(int drive) +{ + uint8_t ret = !!fdd_changed[drive]; + + return ret; +} + +uint8_t +fdc_get_shadow(fdc_t *fdc) +{ + uint8_t ret = (fdc->rate & 0x03) | + ((fdc->pretrk & 0x07) << 2) | + (fdc->power_down ? 0x40 : 0x00) | + ((fdc_read(0x03f2, fdc) & 0x04) ? 0x80 : 0x00); + + return ret; +} + int fdc_get_boot_drive(fdc_t *fdc) { diff --git a/src/include/86box/fdc.h b/src/include/86box/fdc.h index c98a03f67..cd1e58db7 100644 --- a/src/include/86box/fdc.h +++ b/src/include/86box/fdc.h @@ -223,6 +223,11 @@ extern uint8_t fdc_get_diswr(fdc_t *fdc); extern void fdc_set_diswr(fdc_t *fdc, uint8_t diswr); extern uint8_t fdc_get_swap(fdc_t *fdc); extern void fdc_set_swap(fdc_t *fdc, uint8_t swap); +extern void fdc_set_flags(fdc_t *fdc, int flags); +extern void fdc_clear_flags(fdc_t *fdc, int flags); +extern void fdc_set_fdd_changed(int drive, int changed); +extern uint8_t fdc_get_fdd_changed(int drive); +extern uint8_t fdc_get_shadow(fdc_t *fdc); extern void fdc_finishcompare(fdc_t *fdc, int satisfying); extern void fdc_finishread(fdc_t *fdc); diff --git a/src/include/86box/serial.h b/src/include/86box/serial.h index 31c77ce5a..f35c7e36e 100644 --- a/src/include/86box/serial.h +++ b/src/include/86box/serial.h @@ -151,6 +151,7 @@ extern void serial_set_dsr(serial_t *dev, uint8_t enabled); extern void serial_set_dcd(serial_t *dev, uint8_t enabled); extern void serial_set_ri(serial_t *dev, uint8_t enabled); extern int serial_get_ri(serial_t *dev); +extern uint8_t serial_get_shadow(serial_t *dev); extern const device_t ns8250_device; extern const device_t ns8250_pcjr_device; diff --git a/src/include/86box/sio.h b/src/include/86box/sio.h index 27ad27fe3..9866a11ff 100644 --- a/src/include/86box/sio.h +++ b/src/include/86box/sio.h @@ -65,7 +65,6 @@ extern const device_t fdc37c67x_device; extern const device_t fdc37c93x_device; extern const device_t fdc37m60x_device; -extern const device_t fdc37m60x_370_device; /* ITE */ extern const device_t it8661f_device; diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c index 4a5f4cb17..3c00c33f7 100644 --- a/src/machine/m_at_slot1.c +++ b/src/machine/m_at_slot1.c @@ -798,8 +798,7 @@ machine_at_vei8_init(const machine_t *model) pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); device_add(&i440zx_device); device_add(&piix4e_device); - device_add(&fdc37m60x_370_device); - device_add(&kbc_ps2_ami_pci_device); + device_add_params(&fdc37m60x_device, (void *) (FDC37C932 | FDC37C93X_370)); device_add(ics9xxx_get(ICS9250_08)); device_add(&sst_flash_39sf020_device); spd_register(SPD_TYPE_SDRAM, 0x3, 512); diff --git a/src/sio/sio_fdc37c93x.c b/src/sio/sio_fdc37c93x.c index 70f234fc1..c4ae535ad 100644 --- a/src/sio/sio_fdc37c93x.c +++ b/src/sio/sio_fdc37c93x.c @@ -824,6 +824,7 @@ fdc37c93x_serial_handler(fdc37c93x_t *dev, const int uart) const uint8_t global_enable = !!(dev->regs[0x22] & (1 << uart_no)); const uint8_t local_enable = !!dev->ld_regs[uart_no][0x30]; const uint16_t old_base = dev->uart_base[uart]; + double clock_src = 24000000.0 / 13.0; dev->uart_base[uart] = 0x0000; @@ -838,13 +839,34 @@ fdc37c93x_serial_handler(fdc37c93x_t *dev, const int uart) serial_setup(dev->uart[uart], dev->uart_base[uart], dev->ld_regs[uart_no][0x70]); } + switch (dev->ld_regs[uart_no][0xf0] & 0x03) { + case 0x00: + clock_src = 24000000.0 / 13.0; + break; + case 0x01: + clock_src = 24000000.0 / 12.0; + break; + case 0x02: + clock_src = 24000000.0 / 1.0; + break; + case 0x03: + clock_src = 24000000.0 / 1.625; + break; + + default: + break; + } + + serial_set_clock_src(dev->uart[uart], clock_src); + /* TODO: If UART 2's own IRQ pin is also enabled when shared, it should also be asserted. */ - if ((dev->chip_id >= FDC37C93X_FR) && (dev->ld_regs[4][0xf0] & 0x80)) - serial_irq(dev->uart[uart], dev->ld_regs[4][0x70]); - else + if ((dev->chip_id >= FDC37C93X_FR) && (dev->ld_regs[4][0xf0] & 0x80)) { + serial_irq(dev->uart[0], dev->ld_regs[4][0x70]); + serial_irq(dev->uart[1], dev->ld_regs[4][0x70]); + } else serial_irq(dev->uart[uart], dev->ld_regs[uart_no][0x70]); } @@ -1117,6 +1139,18 @@ fdc37c93x_write(uint16_t port, uint8_t val, void *priv) if (valxor & 0x01) fdc_update_enh_mode(dev->fdc, val & 0x01); + if (valxor & 0x0c) { + fdc_clear_flags(dev->fdc, FDC_FLAG_PS2 | FDC_FLAG_PS2_MCA); + switch (val & 0x0c) { + case 0x00: + fdc_set_flags(dev->fdc, FDC_FLAG_PS2); + break; + case 0x04: + fdc_set_flags(dev->fdc, FDC_FLAG_PS2_MCA); + break; + } + fdc_update_enh_mode(dev->fdc, val & 0x01); + } if (valxor & 0x10) fdc_set_swap(dev->fdc, (val & 0x10) >> 4); break; @@ -1522,8 +1556,6 @@ fdc37c93x_read(uint16_t port, void *priv) if ((dev->regs[7] == 0x00) && (dev->cur_reg == 0xf2)) ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2) | (fdc_get_rwc(dev->fdc, 2) << 4) | (fdc_get_rwc(dev->fdc, 3) << 6)); - else if ((dev->regs[7] != 0x06) || (dev->cur_reg != 0xf3)) - ret = dev->ld_regs[dev->regs[7]][dev->cur_reg]; else if ((dev->regs[7] == 0x08) && (dev->cur_reg >= 0xf6) && (dev->cur_reg <= 0xfb) && (dev->chip_id >= FDC37C93X_FR)) switch (dev->cur_reg) { @@ -1569,7 +1601,8 @@ fdc37c93x_read(uint16_t port, void *priv) ret |= fdc37c93x_read_gp(dev, 7, i); } break; - } + } else if ((dev->regs[7] != 0x06) || (dev->cur_reg != 0xf3)) + ret = dev->ld_regs[dev->regs[7]][dev->cur_reg]; } } } @@ -1702,7 +1735,9 @@ fdc37c93x_reset(fdc37c93x_t *dev) if (dev->is_apm) fdc37c93x_acpi_handler(dev); + fdc_clear_flags(dev->fdc, FDC_FLAG_PS2 | FDC_FLAG_PS2_MCA); fdc_reset(dev->fdc); + fdc37c93x_fdc_handler(dev); if (dev->has_nvr) { @@ -1722,11 +1757,6 @@ fdc37c93x_reset(fdc37c93x_t *dev) if (dev->chip_id != 0x02) fdc37c93x_superio_handler(dev); - if (dev->chip_id >= FDC37C93X_FR) { - serial_set_clock_src(dev->uart[0], 24000000.0); - serial_set_clock_src(dev->uart[1], 24000000.0); - } - memset(dev->gpio_regs, 0xff, 256); memset(dev->gpio_pulldn, 0xff, 8); diff --git a/src/sio/sio_pc87309.c b/src/sio/sio_pc87309.c index e5fe99426..19a18af81 100644 --- a/src/sio/sio_pc87309.c +++ b/src/sio/sio_pc87309.c @@ -50,7 +50,7 @@ typedef struct pc87309_t { void *kbc; fdc_t *fdc; serial_t *uart[2]; - lpt_t *lpt + lpt_t *lpt; } pc87309_t; enum {