From af786bec0a597b9b6e893f7aa3eee496bb588fa3 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Fri, 1 Mar 2024 22:54:31 +0100 Subject: [PATCH] IDE changes (now for MCA). Added McIDE (MCA IDE) controller for MCA machines that don't have it (PS/2 models 50+). --- src/disk/hdc.c | 1 + src/disk/hdc_ide.c | 298 ++++++++++++++++++++++++++++++++++++++-- src/include/86box/hdc.h | 2 + 3 files changed, 292 insertions(+), 9 deletions(-) diff --git a/src/disk/hdc.c b/src/disk/hdc.c index 7bfb7e05a..034b8890e 100644 --- a/src/disk/hdc.c +++ b/src/disk/hdc.c @@ -109,6 +109,7 @@ static const struct { { &ide_pci_2ch_device }, { &ide_vlb_device }, { &ide_vlb_2ch_device }, + { &mcide_device }, { NULL } // clang-format on }; diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 39031138f..dbb283407 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -30,8 +30,10 @@ #include "cpu.h" #include <86box/machine.h> #include <86box/io.h> +#include <86box/mca.h> #include <86box/mem.h> #include <86box/pic.h> +#include <86box/rom.h> #include <86box/pci.h> #include <86box/rom.h> #include <86box/timer.h> @@ -112,6 +114,8 @@ #define IDE_ATAPI_IS_EARLY ide->sc->pad0 +#define ROM_PATH_MCIDE "roms/hdd/xtide/ide_ps2 R1.1.bin" + typedef struct ide_bm_t { int (*dma)(uint8_t *data, int transfer_length, int out, void *priv); void (*set_irq)(uint8_t status, void *priv); @@ -135,6 +139,12 @@ typedef struct ide_board_t { ide_bm_t *bm; } ide_board_t; +typedef struct mcide_t { + uint8_t pos_regs[8]; + uint32_t bios_addr; + rom_t bios_rom; +} mcide_t; + ide_board_t *ide_boards[IDE_BUS_MAX]; static uint8_t ide_ter_pnp_rom[] = { @@ -2764,9 +2774,9 @@ ide_board_setup(int board) } static void -ide_board_init(int board, int irq, int base_main, int side_main, int type) +ide_board_init(int board, int irq, int base_main, int side_main, int type, int bus) { - ide_log("ide_board_init(%i, %i, %04X, %04X, %i)\n", board, irq, base_main, side_main, type); + ide_log("ide_board_init(%i, %i, %04X, %04X, %i, %i)\n", board, irq, base_main, side_main, type, bus); if ((ide_boards[board] != NULL) && ide_boards[board]->inited) return; @@ -2782,6 +2792,7 @@ ide_board_init(int board, int irq, int base_main, int side_main, int type) ide_boards[board]->bit32 = 1; ide_boards[board]->base[0] = base_main; ide_boards[board]->base[1] = side_main; + ide_set_handlers(board); timer_add(&ide_boards[board]->timer, ide_board_callback, ide_boards[board], 0); @@ -2834,12 +2845,12 @@ ide_ter_init(const device_t *info) irq = device_get_config_int("irq"); if (irq < 0) { - ide_board_init(2, -1, 0, 0, 0); + ide_board_init(2, -1, 0, 0, 0, 0); if (irq == -1) isapnp_add_card(ide_ter_pnp_rom, sizeof(ide_ter_pnp_rom), ide_pnp_config_changed, NULL, NULL, NULL, (void *) 2); } else { - ide_board_init(2, irq, HDC_TERTIARY_BASE, HDC_TERTIARY_SIDE, 0); + ide_board_init(2, irq, HDC_TERTIARY_BASE, HDC_TERTIARY_SIDE, 0, 0); } return (ide_boards[2]); @@ -2866,12 +2877,12 @@ ide_qua_init(const device_t *info) irq = device_get_config_int("irq"); if (irq < 0) { - ide_board_init(3, -1, 0, 0, 0); + ide_board_init(3, -1, 0, 0, 0, 0); if (irq == -1) isapnp_add_card(ide_qua_pnp_rom, sizeof(ide_qua_pnp_rom), ide_pnp_config_changed, NULL, NULL, NULL, (void *) 3); } else - ide_board_init(3, irq, HDC_QUATERNARY_BASE, HDC_QUATERNARY_SIDE, 0); + ide_board_init(3, irq, HDC_QUATERNARY_BASE, HDC_QUATERNARY_SIDE, 0, 0); return (ide_boards[3]); } @@ -2886,7 +2897,7 @@ ide_qua_close(UNUSED(void *priv)) void * ide_xtide_init(void) { - ide_board_init(0, -1, 0, 0, 0); + ide_board_init(0, -1, 0, 0, 0, 0); return ide_boards[0]; } @@ -2922,10 +2933,10 @@ ide_init(const device_t *info) switch (info->local) { case 0 ... 5: - ide_board_init(0, 14, 0x1f0, 0x3f6, info->local); + ide_board_init(0, 14, 0x1f0, 0x3f6, info->local, info->flags); if (info->local & 1) - ide_board_init(1, 15, 0x170, 0x376, info->local); + ide_board_init(1, 15, 0x170, 0x376, info->local, info->flags); break; default: @@ -3026,6 +3037,260 @@ ide_close(UNUSED(void *priv)) } } +static uint8_t +mcide_mca_read(int port, void *priv) +{ + const mcide_t *dev = (mcide_t *) priv; + + ide_log("IDE: mcard(%04x)\n", port); + + return (dev->pos_regs[port & 7]); +} + +static void +mcide_mca_write(int port, uint8_t val, void *priv) +{ + mcide_t *dev = (mcide_t *) priv; + + ide_log("IDE: mcawr(%04x, %02x) pos[2]=%02x pos[3]=%02x\n", + port, val, dev->pos_regs[2], dev->pos_regs[3]); + + if (port < 0x102) + return; + + /* Save the new value. */ + dev->pos_regs[port & 7] = val; + + io_handler(0, ide_boards[0]->base[0], 8, + ide_readb, ide_readw, ide_readl, + ide_writeb, ide_writew, ide_writel, + ide_boards[0]); + io_handler(0, ide_boards[1]->base[0], 8, + ide_readb, ide_readw, ide_readl, + ide_writeb, ide_writew, ide_writel, + ide_boards[1]); + mem_mapping_disable(&dev->bios_rom.mapping); + + if (dev->pos_regs[2] & 0x80) { + switch ((dev->pos_regs[2] >> 4) & 7) { + case 0: + dev->bios_addr = 0xc0000; + break; + case 1: + dev->bios_addr = 0xc4000; + break; + case 2: + dev->bios_addr = 0xc8000; + break; + case 3: + dev->bios_addr = 0xcc000; + break; + case 4: + dev->bios_addr = 0xd0000; + break; + case 5: + dev->bios_addr = 0xd4000; + break; + case 6: + dev->bios_addr = 0xd8000; + break; + case 7: + dev->bios_addr = 0xd8000; + break; + default: + break; + } + } else { + dev->bios_addr = 0; + } + + if (dev->pos_regs[3] & 0x08) { + switch ((dev->pos_regs[3] & 3)) { + case 0: + ide_boards[0]->base[0] = 0x1f0; + break; + case 1: + ide_boards[0]->base[0] = 0x170; + break; + case 2: + ide_boards[0]->base[0] = 0x1e8; + break; + case 3: + ide_boards[0]->base[0] = 0x168; + break; + default: + break; + } + } else + ide_boards[0]->base[0] = 0; + + if (dev->pos_regs[3] & 0x80) { + switch ((dev->pos_regs[3] >> 5) & 3) { + case 0: + ide_boards[0]->irq = 10; + break; + case 1: + ide_boards[0]->irq = 11; + break; + case 2: + ide_boards[0]->irq = 14; + break; + case 3: + ide_boards[0]->irq = 15; + break; + + default: + break; + } + } else + ide_boards[0]->irq = -1; + + if (dev->pos_regs[4] & 0x08) { + switch ((dev->pos_regs[4] & 3)) { + case 0: + ide_boards[1]->base[0] = 0x1f0; + break; + case 1: + ide_boards[1]->base[0] = 0x170; + break; + case 2: + ide_boards[1]->base[0] = 0x1e8; + break; + case 3: + ide_boards[1]->base[0] = 0x168; + break; + default: + break; + } + } else + ide_boards[1]->base[0] = 0; + + if (dev->pos_regs[4] & 0x80) { + switch ((dev->pos_regs[4] >> 5) & 3) { + case 0: + ide_boards[1]->irq = 10; + break; + case 1: + ide_boards[1]->irq = 11; + break; + case 2: + ide_boards[1]->irq = 14; + break; + case 3: + ide_boards[1]->irq = 15; + break; + + default: + break; + } + } else + ide_boards[1]->irq = -1; + + if (dev->pos_regs[2] & 1) { + if ((dev->pos_regs[3] & 0x88) == 0x88) + io_handler(1, ide_boards[0]->base[0], 8, + ide_readb, ide_readw, ide_readl, + ide_writeb, ide_writew, ide_writel, + ide_boards[0]); + + if ((dev->pos_regs[4] & 0x88) == 0x88) + io_handler(1, ide_boards[1]->base[0], 8, + ide_readb, ide_readw, ide_readl, + ide_writeb, ide_writew, ide_writel, + ide_boards[1]); + + if (dev->pos_regs[2] & 0x80) { + mem_mapping_enable(&dev->bios_rom.mapping); + mem_mapping_set_addr(&dev->bios_rom.mapping, + dev->bios_addr, 0x2000); + } + + /* Say hello. */ + ide_log("McIDE: Primary I/O=%03x, Primary IRQ=%i, Secondary I/O=%03x, Secondary IRQ=%d, BIOS @%05X\n", + ide_boards[0]->base[0], ide_boards[0]->irq, ide_boards[1]->base[0], ide_boards[1]->irq, dev->bios_addr); + } +} + +static uint8_t +mcide_mca_feedb(void *priv) +{ + const mcide_t *dev = (mcide_t *) priv; + + return (dev->pos_regs[2] & 1); +} + +static void +mcide_mca_reset(void *priv) +{ + mcide_t *dev = (mcide_t *) priv; + + for (uint8_t i = 0; i < 2; i++) { + if (ide_boards[i] != NULL) + ide_board_reset(i); + } + + ide_log("McIDE: MCA Reset.\n"); + mem_mapping_disable(&dev->bios_rom.mapping); + mcide_mca_write(0x102, 0, dev); +} + +static void +mcide_reset(void *priv) +{ + mcide_t *dev = (mcide_t *) priv; + + for (uint8_t i = 0; i < 2; i++) { + if (ide_boards[i] != NULL) + ide_board_reset(i); + } + + ide_log("McIDE: Reset.\n"); +} + +static void * +mcide_init(const device_t *info) +{ + ide_log("Initializing McIDE...\n"); + mcide_t *dev = (mcide_t *) calloc(1, sizeof(mcide_t)); + + ide_board_init(0, -1, 0, 0, info->local, info->flags); + ide_board_init(1, -1, 0, 0, info->local, info->flags); + + rom_init(&dev->bios_rom, ROM_PATH_MCIDE, + 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); + mem_mapping_disable(&dev->bios_rom.mapping); + + /* Set the MCA ID for this controller, 0xF171. */ + dev->pos_regs[0] = 0xf1; + dev->pos_regs[1] = 0x71; + + /* Enable the device. */ + mca_add(mcide_mca_read, mcide_mca_write, mcide_mca_feedb, mcide_mca_reset, dev); + + return dev; +} + +static int +mcide_available(void) +{ + return (rom_present(ROM_PATH_MCIDE)); +} + +static void +mcide_close(void *priv) +{ + mcide_t *dev = (mcide_t *) priv; + + for (uint8_t i = 0; i < 2; i++) { + if (ide_boards[i] != NULL) { + ide_board_close(i); + ide_boards[i] = NULL; + } + } + + free(dev); +} + const device_t ide_isa_device = { .name = "ISA PC/AT IDE Controller", .internal_name = "ide_isa", @@ -3110,6 +3375,21 @@ const device_t ide_pci_2ch_device = { .config = NULL }; +const device_t mcide_device = { + .name = "MCA McIDE Controller", + .internal_name = "mcide", + .flags = DEVICE_MCA, + .local = 0, + .init = mcide_init, + .close = mcide_close, + .reset = mcide_reset, + { .available = mcide_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + + // clang-format off static const device_config_t ide_ter_config[] = { { diff --git a/src/include/86box/hdc.h b/src/include/86box/hdc.h index a3d562b62..4f65399bb 100644 --- a/src/include/86box/hdc.h +++ b/src/include/86box/hdc.h @@ -93,6 +93,8 @@ extern const device_t ide_ter_pnp_device; extern const device_t ide_qua_device; extern const device_t ide_qua_pnp_device; +extern const device_t mcide_device; + extern const device_t xta_wdxt150_device; /* xta_wdxt150 */ extern const device_t xta_hd20_device; /* EuroPC internal */