diff --git a/src/chipset/via_pipc.c b/src/chipset/via_pipc.c new file mode 100644 index 000000000..dfbb49c50 --- /dev/null +++ b/src/chipset/via_pipc.c @@ -0,0 +1,737 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * Emulation of the VIA PIPC southbridges. + * + * + * + * Authors: Sarah Walker, + * Miran Grca, + * Melissa Goad, + * RichardG, + * + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2020 Melissa Goad. + * Copyright 2020 RichardG. + */ + +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/cdrom.h> +#include "cpu.h" +#include <86box/scsi_device.h> +#include <86box/scsi_cdrom.h> +#include <86box/dma.h> +#include <86box/io.h> +#include <86box/device.h> +#include <86box/apm.h> +#include <86box/keyboard.h> +#include <86box/mem.h> +#include <86box/timer.h> +#include <86box/nvr.h> +#include <86box/acpi.h> +#include <86box/pci.h> +#include <86box/pic.h> +#include <86box/port_92.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/hdc_ide_sff8038i.h> +#include <86box/usb.h> +#include <86box/zip.h> +#include <86box/machine.h> +#include <86box/smbus_piix4.h> +#include <86box/chipset.h> + + +#define VIA_PIPC_586A 0x05862000 +#define VIA_PIPC_586B 0x05864700 +#define VIA_PIPC_596B 0x05961200 +#define VIA_PIPC_686A 0x06861400 +#define VIA_PIPC_686B 0x06864000 + +#define VIA_PIPC_586(x) (((x) >> 16) == 0x0586) + + +typedef struct +{ + uint32_t local; + uint8_t max_func; + + uint8_t pci_isa_regs[256]; + uint8_t ide_regs[256]; + uint8_t usb_regs[2][256]; + uint8_t power_regs[256]; + sff8038i_t *bm[2]; + nvr_t *nvr; + int nvr_enabled, slot; + smbus_piix4_t *smbus; + usb_t *usb[2]; + acpi_t *acpi; +} pipc_t; + +//#define ENABLE_PIPC_LOG 1 +#ifdef ENABLE_PIPC_LOG +int pipc_do_log = ENABLE_PIPC_LOG; + + +static void +pipc_log(const char *fmt, ...) +{ + va_list ap; + + if (pipc_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define pipc_log(fmt, ...) +#endif + + +static void +pipc_reset_hard(void *priv) +{ + int i; + + pipc_log("PIPC: reset_hard()\n"); + + pipc_t *dev = (pipc_t *) priv; + uint16_t old_base = (dev->ide_regs[0x20] & 0xf0) | (dev->ide_regs[0x21] << 8); + + sff_bus_master_reset(dev->bm[0], old_base); + sff_bus_master_reset(dev->bm[1], old_base + 8); + + memset(dev->pci_isa_regs, 0, 256); + memset(dev->ide_regs, 0, 256); + memset(dev->usb_regs, 0, 512); + memset(dev->power_regs, 0, 256); + + dev->pci_isa_regs[0x00] = 0x06; dev->pci_isa_regs[0x01] = 0x11; + dev->pci_isa_regs[0x02] = dev->local >> 16; + dev->pci_isa_regs[0x03] = dev->local >> 24; + dev->pci_isa_regs[0x04] = (dev->local <= VIA_PIPC_586B) ? 0x0f : 0x87; + dev->pci_isa_regs[0x07] = 0x02; + dev->pci_isa_regs[0x08] = dev->local >> 8; + dev->pci_isa_regs[0x0a] = 0x01; + dev->pci_isa_regs[0x0b] = 0x06; + dev->pci_isa_regs[0x0e] = 0x80; + + dev->pci_isa_regs[0x48] = 0x01; + dev->pci_isa_regs[0x4a] = 0x04; + dev->pci_isa_regs[0x4f] = 0x03; + + dev->pci_isa_regs[0x50] = (dev->local >= VIA_PIPC_686A) ? 0x2d : 0x24; + dev->pci_isa_regs[0x59] = 0x04; + if (dev->local >= VIA_PIPC_686A) + dev->pci_isa_regs[0x5a] = dev->pci_isa_regs[0x5f] = 0x04; + + dma_e = 0x00; + for (i = 0; i < 8; i++) { + dma[i].ab &= 0xffff000f; + dma[i].ac &= 0xffff000f; + } + + pic_set_shadow(0); + + /* IDE registers */ + dev->max_func++; + dev->ide_regs[0x00] = 0x06; dev->ide_regs[0x01] = 0x11; + dev->ide_regs[0x02] = 0x71; dev->ide_regs[0x03] = 0x05; + dev->ide_regs[0x04] = 0x80; + dev->ide_regs[0x06] = (dev->local == VIA_PIPC_686A) ? 0x90 : 0x80; dev->ide_regs[0x07] = 0x02; + dev->ide_regs[0x08] = 0x06; + dev->ide_regs[0x09] = 0x85; + dev->ide_regs[0x0a] = 0x01; + dev->ide_regs[0x0b] = 0x01; + + dev->ide_regs[0x10] = 0xf1; dev->ide_regs[0x11] = 0x01; + dev->ide_regs[0x14] = 0xf5; dev->ide_regs[0x15] = 0x03; + dev->ide_regs[0x18] = 0x71; dev->ide_regs[0x19] = 0x01; + dev->ide_regs[0x1c] = 0x75; dev->ide_regs[0x1d] = 0x03; + dev->ide_regs[0x20] = 0x01; dev->ide_regs[0x21] = 0xcc; + if (dev->local >= VIA_PIPC_686A) + dev->ide_regs[0x34] = 0xc0; + dev->ide_regs[0x3c] = 0x0e; + + if (dev->local < VIA_PIPC_686A) + dev->ide_regs[0x40] = 0x08; + dev->ide_regs[0x41] = 0x02; + dev->ide_regs[0x42] = 0x09; + dev->ide_regs[0x43] = (dev->local >= VIA_PIPC_686A) ? 0x0a : 0x3a; + dev->ide_regs[0x44] = 0x68; + dev->ide_regs[0x46] = 0xc0; + dev->ide_regs[0x48] = 0xa8; dev->ide_regs[0x49] = 0xa8; + dev->ide_regs[0x4a] = 0xa8; dev->ide_regs[0x4b] = 0xa8; + dev->ide_regs[0x4c] = 0xff; + dev->ide_regs[0x4e] = 0xff; + dev->ide_regs[0x4f] = 0xff; + dev->ide_regs[0x50] = 0x03; dev->ide_regs[0x51] = 0x03; + dev->ide_regs[0x52] = 0x03; dev->ide_regs[0x53] = 0x03; + if (dev->local >= VIA_PIPC_596B) + dev->ide_regs[0x54] = 0x06; + + dev->ide_regs[0x61] = 0x02; + dev->ide_regs[0x69] = 0x02; + + if (dev->local >= VIA_PIPC_686A) { + dev->ide_regs[0xc0] = 0x01; + dev->ide_regs[0xc2] = 0x02; + } + + for (uint8_t i = 0; i <= (dev->local >= VIA_PIPC_686A); i++) { + dev->max_func++; + dev->usb_regs[i][0x00] = 0x06; dev->usb_regs[i][0x01] = 0x11; + dev->usb_regs[i][0x02] = 0x38; dev->usb_regs[i][0x03] = 0x30; + dev->usb_regs[i][0x04] = 0x00; dev->usb_regs[i][0x05] = 0x00; + dev->usb_regs[i][0x06] = 0x00; dev->usb_regs[i][0x07] = 0x02; + if (dev->local >= VIA_PIPC_686A) + dev->usb_regs[i][0x08] = 0x16; + else if (dev->local >= VIA_PIPC_596B) + dev->usb_regs[i][0x08] = 0x08; + else + dev->usb_regs[i][0x08] = 0x02; + dev->usb_regs[i][0x0a] = 0x03; + dev->usb_regs[i][0x0b] = 0x0c; + dev->usb_regs[i][0x0d] = 0x16; + dev->usb_regs[i][0x20] = 0x01; + dev->usb_regs[i][0x21] = 0x03; + dev->usb_regs[i][0x3d] = 0x04; + + dev->usb_regs[i][0x60] = 0x10; + if (dev->local >= VIA_PIPC_686A) { + dev->usb_regs[i][0x80] = 0x01; + dev->usb_regs[i][0x82] = 0x02; + } + dev->usb_regs[i][0xc1] = 0x20; + } + + if (dev->local >= VIA_PIPC_586B) { + dev->max_func++; + dev->power_regs[0x00] = 0x06; dev->power_regs[0x01] = 0x11; + if (dev->local <= VIA_PIPC_586B) + dev->power_regs[0x02] = 0x40; + else if (dev->local <= VIA_PIPC_596B) + dev->power_regs[0x02] = 0x50; + else + dev->power_regs[0x02] = 0x57; + dev->power_regs[0x03] = 0x30; + dev->power_regs[0x04] = 0x00; dev->power_regs[0x05] = 0x00; + dev->power_regs[0x06] = (dev->local == VIA_PIPC_686B) ? 0x90 : 0x80; dev->power_regs[0x07] = 0x02; + if (dev->local >= VIA_PIPC_686A) + dev->power_regs[0x08] = 0x40; + else if (dev->local >= VIA_PIPC_596B) + dev->power_regs[0x08] = 0x20; + else + dev->power_regs[0x08] = 0x10; + dev->power_regs[0x48] = 0x01; + + if (dev->local >= VIA_PIPC_596B) + dev->power_regs[0x90] = 0x01; + } + + pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); + + pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED); + + ide_pri_disable(); + ide_sec_disable(); +} + + +static void +pipc_ide_handlers(pipc_t *dev) +{ + uint16_t main, side; + + ide_pri_disable(); + ide_sec_disable(); + + if (dev->ide_regs[0x09] & 0x01) { + main = (dev->ide_regs[0x11] << 8) | (dev->ide_regs[0x10] & 0xf8); + side = ((dev->ide_regs[0x15] << 8) | (dev->ide_regs[0x14] & 0xfc)) + 2; + } else { + main = 0x1f0; + side = 0x3f6; + } + ide_set_base(0, main); + ide_set_side(0, side); + + if (dev->ide_regs[0x09] & 0x04) { + main = (dev->ide_regs[0x19] << 8) | (dev->ide_regs[0x18] & 0xf8); + side = ((dev->ide_regs[0x1d] << 8) | (dev->ide_regs[0x1c] & 0xfc)) + 2; + } else { + main = 0x170; + side = 0x376; + } + ide_set_base(1, main); + ide_set_side(1, side); + + if (dev->ide_regs[0x04] & PCI_COMMAND_IO) { + if (dev->ide_regs[0x40] & 0x02) + ide_pri_enable(); + if (dev->ide_regs[0x40] & 0x01) + ide_sec_enable(); + } +} + + +static void +pipc_ide_irqs(pipc_t *dev) +{ + int irq_mode[2] = { 0, 0 }; + + if (dev->ide_regs[0x09] & 0x01) + irq_mode[0] = (dev->ide_regs[0x3d] & 0x01); + + if (dev->ide_regs[0x09] & 0x04) + irq_mode[1] = (dev->ide_regs[0x3d] & 0x01); + + sff_set_irq_mode(dev->bm[0], 0, irq_mode[0]); + sff_set_irq_mode(dev->bm[0], 1, irq_mode[1]); + + sff_set_irq_mode(dev->bm[1], 0, irq_mode[0]); + sff_set_irq_mode(dev->bm[1], 1, irq_mode[1]); +} + + +static void +pipc_bus_master_handlers(pipc_t *dev) +{ + uint16_t base = (dev->ide_regs[0x20] & 0xf0) | (dev->ide_regs[0x21] << 8); + + sff_bus_master_handler(dev->bm[0], (dev->ide_regs[0x04] & 1), base); + sff_bus_master_handler(dev->bm[1], (dev->ide_regs[0x04] & 1), base + 8); +} + + +static uint8_t +pipc_read(int func, int addr, void *priv) +{ + pipc_t *dev = (pipc_t *) priv; + uint8_t ret = 0xff; + int c; + uint8_t pm_func = (dev->local >= VIA_PIPC_686A) ? 4 : 3; + + if (func > dev->max_func) + return ret; + else if (func == 0) { /* PCI-ISA bridge */ + if ((addr >= 0x60) && (addr <= 0x6f)) { + c = (addr & 0x0e) >> 1; + if (addr & 0x01) + ret = (dma[c].ab & 0x0000ff00) >> 8; + else { + ret = (dma[c].ab & 0x000000f0); + ret |= (!!(dma_e & (1 << c)) << 3); + } + } else + ret = dev->pci_isa_regs[addr]; + } + else if (func == 1) /* IDE */ + ret = dev->ide_regs[addr]; + else if (func < pm_func) /* USB */ + ret = dev->usb_regs[func - 2][addr]; + else if (func == pm_func) /* Power */ + ret = dev->power_regs[addr]; + + pipc_log("PIPC: read(%d, %02X) = %02X\n", func, addr, ret); + + return ret; +} + + +static void +nvr_update_io_mapping(pipc_t *dev) +{ + if (dev->nvr_enabled) + nvr_at_handler(0, 0x0074, dev->nvr); + + if ((dev->pci_isa_regs[0x5b] & 0x02) && (dev->pci_isa_regs[0x48] & 0x08)) + nvr_at_handler(1, 0x0074, dev->nvr); +} + + +static void +usb_update_io_mapping(pipc_t *dev, int func) +{ + uhci_update_io_mapping(dev->usb[func - 2], dev->usb_regs[func - 2][0x20] & ~0x1f, dev->usb_regs[func - 2][0x21], dev->usb_regs[func - 2][PCI_REG_COMMAND] & PCI_COMMAND_IO); +} + + +static void +pipc_write(int func, int addr, uint8_t val, void *priv) +{ + pipc_t *dev = (pipc_t *) priv; + int c; + uint8_t pm_func = (dev->local >= VIA_PIPC_686A) ? 4 : 3; + + if (func > dev->max_func) + return; + + pipc_log("PIPC: write(%d, %02X, %02X)\n", func, addr, val); + + if (func == 0) { /* PCI-ISA bridge */ + /* Read-only addresses */ + if ((addr < 4) || (addr == 5) || ((addr >= 8) && (addr < 0x40)) || (addr == 0x49) || (addr == 0x4b) || + (addr == 0x53) || ((addr >= 0x5d) && (addr < 0x5f)) || ((addr >= 0x71) && (addr < 0x74)) || (addr >= 0x90)) + return; + + if ((dev->local <= VIA_PIPC_586B) && (addr >= 0x74)) + return; + + if ((dev->local <= VIA_PIPC_596B) && ((addr == 0x51) || (addr == 0x52) || (addr == 0x5f) || (addr == 0x85) || + (addr == 0x86) || ((addr >= 0x8a) && (addr < 0x90)))) + return; + + switch (addr) { + case 0x04: + dev->pci_isa_regs[0x04] = (val & 8) | 7; + break; + case 0x07: + dev->pci_isa_regs[0x07] &= ~(val & 0xb0); + break; + + case 0x47: + if ((val & 0x81) == 0x81) { + /* Trigger TRC reset. */ + outb(0xcf9, 0x00); + outb(0xcf9, 0xff); + return; + } + pic_set_shadow(!!(val & 0x10)); + pci_elcr_set_enabled(!!(val & 0x20)); + dev->pci_isa_regs[0x47] = val & 0xfe; + break; + case 0x48: + dev->pci_isa_regs[0x48] = val; + nvr_update_io_mapping(dev); + break; + + case 0x54: + pci_set_irq_level(PCI_INTA, !(val & 8)); + pci_set_irq_level(PCI_INTB, !(val & 4)); + pci_set_irq_level(PCI_INTC, !(val & 2)); + pci_set_irq_level(PCI_INTD, !(val & 1)); + break; + case 0x55: + pci_set_irq_routing((dev->local >= VIA_PIPC_596B) ? PCI_INTA : PCI_INTD, (val & 0xf0) ? (val >> 4) : PCI_IRQ_DISABLED); + if (dev->local < VIA_PIPC_686A) + pci_set_mirq_routing(PCI_MIRQ0, (val & 0x0f) ? (val & 0x0f) : PCI_IRQ_DISABLED); + dev->pci_isa_regs[0x55] = val; + break; + case 0x56: + pci_set_irq_routing((dev->local >= VIA_PIPC_596B) ? PCI_INTC : PCI_INTA, (val & 0xf0) ? (val >> 4) : PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTB, (val & 0x0f) ? (val & 0x0f) : PCI_IRQ_DISABLED); + dev->pci_isa_regs[0x56] = val; + break; + case 0x57: + pci_set_irq_routing((dev->local >= VIA_PIPC_596B) ? PCI_INTD : PCI_INTC, (val & 0xf0) ? (val >> 4) : PCI_IRQ_DISABLED); + if (dev->local < VIA_PIPC_686A) + pci_set_mirq_routing(PCI_MIRQ1, (val & 0x0f) ? (val & 0x0f) : PCI_IRQ_DISABLED); + dev->pci_isa_regs[0x57] = val; + break; + case 0x58: + if (dev->local < VIA_PIPC_686A) + pci_set_mirq_routing(PCI_MIRQ2, (val & 0x0f) ? (val & 0x0f) : PCI_IRQ_DISABLED); + dev->pci_isa_regs[0x58] = val; + break; + case 0x5b: + dev->pci_isa_regs[0x5b] = val; + nvr_update_io_mapping(dev); + break; + + case 0x60: case 0x62: case 0x64: case 0x66: + case 0x6a: case 0x6c: case 0x6e: + c = (addr & 0x0e) >> 1; + dma[c].ab = (dma[c].ab & 0xffffff0f) | (val & 0xf0); + dma[c].ac = (dma[c].ac & 0xffffff0f) | (val & 0xf0); + if (val & 0x08) + dma_e |= (1 << c); + else + dma_e &= ~(1 << c); + break; + case 0x61: case 0x63: case 0x65: case 0x67: + case 0x6b: case 0x6d: case 0x6f: + c = (addr & 0x0e) >> 1; + dma[c].ab = (dma[c].ab & 0xffff00ff) | (val << 8); + dma[c].ac = (dma[c].ac & 0xffff00ff) | (val << 8); + break; + + case 0x70: case 0x71: case 0x72: case 0x73: + dev->pci_isa_regs[(addr - 0x44)] = val; + break; + + case 0x74: + dev->pci_isa_regs[addr] = val; + break; + + case 0x80: case 0x86: case 0x87: + dev->pci_isa_regs[addr] &= ~(val); + break; + + default: + dev->pci_isa_regs[addr] = val; + break; + } + } else if (func == 1) { /* IDE */ + /* Read-only addresses */ + if ((addr < 4) || (addr == 5) || (addr == 8) || ((addr >= 0xa) && (addr < 0x0d)) || + ((addr >= 0x0e) && (addr < 0x10)) || ((addr >= 0x12) && (addr < 0x13)) || + ((addr >= 0x16) && (addr < 0x17)) || ((addr >= 0x1a) && (addr < 0x1b)) || + ((addr >= 0x1e) && (addr < 0x1f)) || ((addr >= 0x22) && (addr < 0x3c)) || + ((addr >= 0x3e) && (addr < 0x40)) || ((addr >= 0x55) && (addr < 0x60)) || + ((addr >= 0x62) && (addr < 0x68)) || ((addr >= 0x6a) && (addr < 0x70)) || + (addr == 0x72) || (addr == 0x73) || (addr == 0x76) || (addr == 0x77) || + (addr == 0x7a) || (addr == 0x7b) || (addr == 0x7e) || (addr == 0x7f) || + ((addr >= 0x84) && (addr < 0x88)) || (addr >= 0x8c)) + return; + + if ((dev->local <= VIA_PIPC_586B) && ((addr == 0x54) || (addr >= 0x70))) + return; + + switch (addr) { + case 0x04: + dev->ide_regs[0x04] = val & 0x85; + pipc_ide_handlers(dev); + pipc_bus_master_handlers(dev); + break; + case 0x07: + dev->ide_regs[0x07] &= ~(val & 0xf1); + break; + + case 0x09: + dev->ide_regs[0x09] = (val & 0x05) | 0x8a; + pipc_ide_handlers(dev); + pipc_ide_irqs(dev); + break; + + case 0x10: + dev->ide_regs[0x10] = (val & 0xf8) | 1; + pipc_ide_handlers(dev); + break; + case 0x11: + dev->ide_regs[0x11] = val; + pipc_ide_handlers(dev); + break; + + case 0x14: + dev->ide_regs[0x14] = (val & 0xfc) | 1; + pipc_ide_handlers(dev); + break; + case 0x15: + dev->ide_regs[0x15] = val; + pipc_ide_handlers(dev); + break; + + case 0x18: + dev->ide_regs[0x18] = (val & 0xf8) | 1; + pipc_ide_handlers(dev); + break; + case 0x19: + dev->ide_regs[0x19] = val; + pipc_ide_handlers(dev); + break; + + case 0x1c: + dev->ide_regs[0x1c] = (val & 0xfc) | 1; + pipc_ide_handlers(dev); + break; + case 0x1d: + dev->ide_regs[0x1d] = val; + pipc_ide_handlers(dev); + break; + + case 0x20: + dev->ide_regs[0x20] = (val & 0xf0) | 1; + pipc_bus_master_handlers(dev); + break; + case 0x21: + dev->ide_regs[0x21] = val; + pipc_bus_master_handlers(dev); + break; + + case 0x3d: + dev->ide_regs[0x3d] = val & 0x01; + pipc_ide_irqs(dev); + break; + + case 0x40: + dev->ide_regs[0x40] = val; + pipc_ide_handlers(dev); + break; + + case 0x70: case 0x71: case 0x74: case 0x75: case 0x78: case 0x79: case 0x7c: case 0x7d: case 0x80: case 0x81: case 0x82: case 0x83: case 0x88: case 0x89: case 0x8a: case 0x8b: + pclog("them ide registers... %02X %02X\n", addr, val); + break; + + default: + dev->ide_regs[addr] = val; + break; + } + } else if (func < pm_func) { /* USB */ + /* Read-only addresses */ + if ((addr < 4) || (addr == 5) || (addr == 6) || ((addr >= 8) && (addr < 0xd)) || + ((addr >= 0xe) && (addr < 0x20)) || ((addr >= 0x22) && (addr < 0x3c)) || + ((addr >= 0x3e) && (addr < 0x40)) || ((addr >= 0x42) && (addr < 0x44)) || + ((addr >= 0x46) && (addr < 0xc0)) || (addr >= 0xc2)) + return; + + switch (addr) { + case 0x04: + dev->usb_regs[func - 2][0x04] = val & 0x97; + usb_update_io_mapping(dev, func); + break; + case 0x07: + dev->usb_regs[func - 2][0x07] &= ~(val & 0x78); + break; + + case 0x20: + dev->usb_regs[func - 2][0x20] = (val & ~0x1f) | 1; + usb_update_io_mapping(dev, func); + break; + case 0x21: + dev->usb_regs[func - 2][0x21] = val; + usb_update_io_mapping(dev, func); + break; + + default: + dev->usb_regs[func - 2][addr] = val; + break; + } + } else if (func == pm_func) { /* Power */ + /* Read-only addresses */ + if ((addr < 0xd) || ((addr >= 0xe) && (addr < 0x40)) || (addr == 0x43) || (addr == 0x48) || + (addr == 0x4e) || (addr == 0x4f) || (addr == 0x56) || (addr == 0x57) || ((addr >= 0x5c) && (addr < 0x61)) || + ((addr >= 0x64) && (addr < 0x70)) || (addr == 0x72) || (addr == 0x73) || ((addr >= 0x75) && (addr < 0x90)) || + ((addr >= 0x92) && (addr < 0xd2)) || (addr >= 0xd7)) + return; + + if ((dev->local <= VIA_PIPC_586B) && ((addr == 0x4c) || (addr == 0x4d) || (addr >= 0x54))) + return; + + if ((dev->local <= VIA_PIPC_596B) && ((addr >= 0x64) && (addr < 0x90))) + return; + + switch (addr) { + case 0x41: case 0x49: + dev->power_regs[addr] = val; + acpi_update_io_mapping(dev->acpi, dev->power_regs[0x49] << 8, dev->power_regs[0x41] & 0x80); + break; + + case 0x61: case 0x62: case 0x63: + dev->power_regs[(addr - 0x58)] = val; + break; + + case 0x90: case 0x91: + dev->power_regs[addr] = val; + smbus_piix4_remap(dev->smbus, (dev->power_regs[0x91] << 8) | (dev->power_regs[0x90] & 0xf0), dev->power_regs[0xd2] & 0x01); + break; + + default: + dev->power_regs[addr] = val; + break; + } + } +} + + +static void * +pipc_init(const device_t *info) +{ + pipc_t *dev = (pipc_t *) malloc(sizeof(pipc_t)); + memset(dev, 0, sizeof(pipc_t)); + + pipc_log("PIPC: init()\n"); + + dev->local = info->local; + dev->slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, pipc_read, pipc_write, dev); + + dev->bm[0] = device_add_inst(&sff8038i_device, 1); + sff_set_slot(dev->bm[0], dev->slot); + sff_set_irq_mode(dev->bm[0], 0, 0); + sff_set_irq_mode(dev->bm[0], 1, 0); + sff_set_irq_pin(dev->bm[0], PCI_INTA); + + dev->bm[1] = device_add_inst(&sff8038i_device, 2); + sff_set_slot(dev->bm[1], dev->slot); + sff_set_irq_mode(dev->bm[1], 0, 0); + sff_set_irq_mode(dev->bm[1], 1, 0); + sff_set_irq_pin(dev->bm[1], PCI_INTA); + + dev->nvr = device_add(&via_nvr_device); + + dev->smbus = device_add(&piix4_smbus_device); + + dev->acpi = device_add(&acpi_via_device); + + dev->usb[0] = device_add_inst(&usb_device, 1); + if (dev->local >= VIA_PIPC_686A) + dev->usb[1] = device_add_inst(&usb_device, 2); + + pipc_reset_hard(dev); + + device_add(&port_92_pci_device); + + dma_alias_set(); + + pci_enable_mirq(0); + pci_enable_mirq(1); + pci_enable_mirq(2); + + return dev; +} + +static void +pipc_close(void *p) +{ + pipc_t *pipc = (pipc_t *) p; + + pipc_log("PIPC: close()\n"); + + free(pipc); +} + + +const device_t via_vt82c586b_device = +{ + "VIA VT82C586B", + DEVICE_PCI, + VIA_PIPC_586B, + pipc_init, + pipc_close, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +const device_t via_vt82c596b_device = +{ + "VIA VT82C596B", + DEVICE_PCI, + VIA_PIPC_596B, + pipc_init, + pipc_close, + NULL, + NULL, + NULL, + NULL, + NULL +}; diff --git a/src/chipset/via_vt82c586b.c b/src/chipset/via_vt82c586b.c deleted file mode 100644 index 3524ed30b..000000000 --- a/src/chipset/via_vt82c586b.c +++ /dev/null @@ -1,659 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * Emulation of the VIA Apollo MVP3 southbridge - * - * - * - * Authors: Sarah Walker, - * Miran Grca, - * Melissa Goad, - * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - * Copyright 2020 Melissa Goad. - */ - -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include <86box/86box.h> -#include <86box/cdrom.h> -#include "cpu.h" -#include <86box/scsi_device.h> -#include <86box/scsi_cdrom.h> -#include <86box/dma.h> -#include <86box/io.h> -#include <86box/device.h> -#include <86box/apm.h> -#include <86box/keyboard.h> -#include <86box/mem.h> -#include <86box/timer.h> -#include <86box/nvr.h> -#include <86box/pci.h> -#include <86box/pic.h> -#include <86box/port_92.h> -#include <86box/hdc.h> -#include <86box/hdc_ide.h> -#include <86box/hdc_ide_sff8038i.h> -#include <86box/zip.h> -#include <86box/machine.h> -#include <86box/chipset.h> - - -#define ACPI_TIMER_FREQ 3579545 - -#define ACPI_IO_ENABLE (1 << 7) -#define ACPI_TIMER_32BIT (1 << 3) - - -typedef struct -{ - uint8_t pci_isa_regs[256]; - uint8_t ide_regs[256]; - uint8_t usb_regs[256]; - uint8_t power_regs[256]; - sff8038i_t * bm[2]; - nvr_t * nvr; - int nvr_enabled, slot; - - struct - { - uint16_t io_base; - } usb; - - struct - { - uint16_t io_base; - } power; -} via_vt82c586b_t; - - -static void -via_vt82c586b_reset_hard(void *priv) -{ - int i; - - via_vt82c586b_t *via_vt82c586b = (via_vt82c586b_t *) priv; - uint16_t old_base = (via_vt82c586b->ide_regs[0x20] & 0xf0) | (via_vt82c586b->ide_regs[0x21] << 8); - - sff_bus_master_reset(via_vt82c586b->bm[0], old_base); - sff_bus_master_reset(via_vt82c586b->bm[1], old_base + 8); - - memset(via_vt82c586b->pci_isa_regs, 0, 256); - memset(via_vt82c586b->ide_regs, 0, 256); - memset(via_vt82c586b->usb_regs, 0, 256); - memset(via_vt82c586b->power_regs, 0, 256); - - via_vt82c586b->pci_isa_regs[0x00] = 0x06; via_vt82c586b->pci_isa_regs[0x01] = 0x11; /*VIA*/ - via_vt82c586b->pci_isa_regs[0x02] = 0x86; via_vt82c586b->pci_isa_regs[0x03] = 0x05; /*VT82C586B*/ - via_vt82c586b->pci_isa_regs[0x04] = 0x0f; - via_vt82c586b->pci_isa_regs[0x07] = 0x02; - via_vt82c586b->pci_isa_regs[0x0a] = 0x01; - via_vt82c586b->pci_isa_regs[0x0b] = 0x06; - via_vt82c586b->pci_isa_regs[0x0e] = 0x80; - - via_vt82c586b->pci_isa_regs[0x48] = 0x01; - via_vt82c586b->pci_isa_regs[0x4a] = 0x04; - via_vt82c586b->pci_isa_regs[0x4f] = 0x03; - - via_vt82c586b->pci_isa_regs[0x50] = 0x24; - via_vt82c586b->pci_isa_regs[0x59] = 0x04; - - dma_e = 0x00; - for (i = 0; i < 8; i++) { - dma[i].ab &= 0xffff000f; - dma[i].ac &= 0xffff000f; - } - - pic_set_shadow(0); - - /* IDE registers */ - via_vt82c586b->ide_regs[0x00] = 0x06; via_vt82c586b->ide_regs[0x01] = 0x11; /*VIA*/ - via_vt82c586b->ide_regs[0x02] = 0x71; via_vt82c586b->ide_regs[0x03] = 0x05; /*VT82C586B*/ - via_vt82c586b->ide_regs[0x04] = 0x80; - via_vt82c586b->ide_regs[0x06] = 0x80; via_vt82c586b->ide_regs[0x07] = 0x02; - via_vt82c586b->ide_regs[0x09] = 0x85; - via_vt82c586b->ide_regs[0x0a] = 0x01; - via_vt82c586b->ide_regs[0x0b] = 0x01; - - via_vt82c586b->ide_regs[0x10] = 0xf1; via_vt82c586b->ide_regs[0x11] = 0x01; - via_vt82c586b->ide_regs[0x14] = 0xf5; via_vt82c586b->ide_regs[0x15] = 0x03; - via_vt82c586b->ide_regs[0x18] = 0x71; via_vt82c586b->ide_regs[0x19] = 0x01; - via_vt82c586b->ide_regs[0x1c] = 0x75; via_vt82c586b->ide_regs[0x1d] = 0x03; - via_vt82c586b->ide_regs[0x20] = 0x01; via_vt82c586b->ide_regs[0x21] = 0xcc; - via_vt82c586b->ide_regs[0x3c] = 0x0e; - - via_vt82c586b->ide_regs[0x40] = 0x08; - via_vt82c586b->ide_regs[0x41] = 0x02; - via_vt82c586b->ide_regs[0x42] = 0x09; - via_vt82c586b->ide_regs[0x43] = 0x3a; - via_vt82c586b->ide_regs[0x44] = 0x68; - via_vt82c586b->ide_regs[0x46] = 0xc0; - via_vt82c586b->ide_regs[0x48] = 0xa8; via_vt82c586b->ide_regs[0x49] = 0xa8; - via_vt82c586b->ide_regs[0x4a] = 0xa8; via_vt82c586b->ide_regs[0x4b] = 0xa8; - via_vt82c586b->ide_regs[0x4c] = 0xff; - via_vt82c586b->ide_regs[0x4e] = 0xff; - via_vt82c586b->ide_regs[0x4f] = 0xff; - via_vt82c586b->ide_regs[0x50] = 0x03; via_vt82c586b->ide_regs[0x51] = 0x03; - via_vt82c586b->ide_regs[0x52] = 0x03; via_vt82c586b->ide_regs[0x53] = 0x03; - - via_vt82c586b->ide_regs[0x61] = 0x02; - via_vt82c586b->ide_regs[0x69] = 0x02; - - via_vt82c586b->usb_regs[0x00] = 0x06; via_vt82c586b->usb_regs[0x01] = 0x11; /*VIA*/ - via_vt82c586b->usb_regs[0x02] = 0x38; via_vt82c586b->usb_regs[0x03] = 0x30; - via_vt82c586b->usb_regs[0x04] = 0x00; via_vt82c586b->usb_regs[0x05] = 0x00; - via_vt82c586b->usb_regs[0x06] = 0x00; via_vt82c586b->usb_regs[0x07] = 0x02; - via_vt82c586b->usb_regs[0x0a] = 0x03; - via_vt82c586b->usb_regs[0x0b] = 0x0c; - via_vt82c586b->usb_regs[0x0d] = 0x16; - via_vt82c586b->usb_regs[0x20] = 0x01; - via_vt82c586b->usb_regs[0x21] = 0x03; - via_vt82c586b->usb_regs[0x3d] = 0x04; - - via_vt82c586b->usb_regs[0x60] = 0x10; - via_vt82c586b->usb_regs[0xc1] = 0x20; - - via_vt82c586b->power_regs[0x00] = 0x06; via_vt82c586b->power_regs[0x01] = 0x11; /*VIA*/ - via_vt82c586b->power_regs[0x02] = 0x40; via_vt82c586b->power_regs[0x03] = 0x30; - via_vt82c586b->power_regs[0x04] = 0x00; via_vt82c586b->power_regs[0x05] = 0x00; - via_vt82c586b->power_regs[0x06] = 0x80; via_vt82c586b->power_regs[0x07] = 0x02; - via_vt82c586b->power_regs[0x08] = 0x10; /*Production version (3041)*/ - via_vt82c586b->power_regs[0x48] = 0x01; - - pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); - pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); - pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); - pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); - - pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); - pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); - pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED); - - ide_pri_disable(); - ide_sec_disable(); -} - - -static void -via_vt82c586b_ide_handlers(via_vt82c586b_t *dev) -{ - uint16_t main, side; - - ide_pri_disable(); - ide_sec_disable(); - - if (dev->ide_regs[0x09] & 0x01) { - main = (dev->ide_regs[0x11] << 8) | (dev->ide_regs[0x10] & 0xf8); - side = ((dev->ide_regs[0x15] << 8) | (dev->ide_regs[0x14] & 0xfc)) + 2; - } else { - main = 0x1f0; - side = 0x3f6; - } - ide_set_base(0, main); - ide_set_side(0, side); - - if (dev->ide_regs[0x09] & 0x04) { - main = (dev->ide_regs[0x19] << 8) | (dev->ide_regs[0x18] & 0xf8); - side = ((dev->ide_regs[0x1d] << 8) | (dev->ide_regs[0x1c] & 0xfc)) + 2; - } else { - main = 0x170; - side = 0x376; - } - ide_set_base(1, main); - ide_set_side(1, side); - - if (dev->ide_regs[0x04] & PCI_COMMAND_IO) { - if (dev->ide_regs[0x40] & 0x02) - ide_pri_enable(); - if (dev->ide_regs[0x40] & 0x01) - ide_sec_enable(); - } -} - - -static void -via_vt82c586b_ide_irqs(via_vt82c586b_t *dev) -{ - int irq_mode[2] = { 0, 0 }; - - if (dev->ide_regs[0x09] & 0x01) - irq_mode[0] = (dev->ide_regs[0x3d] & 0x01); - - if (dev->ide_regs[0x09] & 0x04) - irq_mode[1] = (dev->ide_regs[0x3d] & 0x01); - - sff_set_irq_mode(dev->bm[0], 0, irq_mode[0]); - sff_set_irq_mode(dev->bm[0], 1, irq_mode[1]); - - sff_set_irq_mode(dev->bm[1], 0, irq_mode[0]); - sff_set_irq_mode(dev->bm[1], 1, irq_mode[1]); -} - - -static void -via_vt82c586b_bus_master_handlers(via_vt82c586b_t *dev) -{ - uint16_t base = (dev->ide_regs[0x20] & 0xf0) | (dev->ide_regs[0x21] << 8); - - sff_bus_master_handler(dev->bm[0], (dev->ide_regs[0x04] & 1), base); - sff_bus_master_handler(dev->bm[1], (dev->ide_regs[0x04] & 1), base + 8); -} - - -static uint8_t -via_vt82c586b_read(int func, int addr, void *priv) -{ - via_vt82c586b_t *dev = (via_vt82c586b_t *) priv; - - uint8_t ret = 0xff; - int c; - - switch(func) { - case 0: - if ((addr >= 0x60) && (addr <= 0x6f)) { - c = (addr & 0x0e) >> 1; - if (addr & 0x01) - ret = (dma[c].ab & 0x0000ff00) >> 8; - else { - ret = (dma[c].ab & 0x000000f0); - ret |= (!!(dma_e & (1 << c)) << 3); - } - } else - ret = dev->pci_isa_regs[addr]; - break; - case 1: - ret = dev->ide_regs[addr]; - break; - case 2: - ret = dev->usb_regs[addr]; - break; - case 3: - ret = dev->power_regs[addr]; - break; - } - - return ret; -} - - -static uint8_t -usb_reg_read(uint16_t addr, void *p) -{ - uint8_t ret = 0xff; - - switch (addr & 0x1f) { - case 0x10: case 0x11: case 0x12: case 0x13: - /* Port status */ - ret = 0x00; - break; - } - - return ret; -} - - -static void -usb_reg_write(uint16_t addr, uint8_t val, void *p) -{ -} - - -static void -nvr_update_io_mapping(via_vt82c586b_t *dev) -{ - if (dev->nvr_enabled) - nvr_at_handler(0, 0x0074, dev->nvr); - - if ((dev->pci_isa_regs[0x5b] & 0x02) && (dev->pci_isa_regs[0x48] & 0x08)) - nvr_at_handler(1, 0x0074, dev->nvr); -} - - -static void -usb_update_io_mapping(via_vt82c586b_t *dev) -{ - if (dev->usb.io_base != 0x0000) - io_removehandler(dev->usb.io_base, 0x20, usb_reg_read, NULL, NULL, usb_reg_write, NULL, NULL, dev); - - dev->usb.io_base = (dev->usb_regs[0x20] & ~0x1f) | (dev->usb_regs[0x21] << 8); - - if ((dev->usb_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) && (dev->usb.io_base != 0x0000)) - io_sethandler(dev->usb.io_base, 0x20, usb_reg_read, NULL, NULL, usb_reg_write, NULL, NULL, dev); -} - - -static uint8_t -power_reg_read(uint16_t addr, void *p) -{ - via_vt82c586b_t *dev = (via_vt82c586b_t *) p; - - uint32_t timer; - uint8_t ret = 0xff; - - switch (addr & 0xff) { - case 0x08: case 0x09: case 0x0a: case 0x0b: - /* ACPI timer */ - timer = (tsc * ACPI_TIMER_FREQ) / machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed; - if (!(dev->power_regs[0x41] & ACPI_TIMER_32BIT)) - timer &= 0x00ffffff; - ret = (timer >> (8 * (addr & 3))) & 0xff; - break; - } - - return ret; -} - - -static void -power_reg_write(uint16_t addr, uint8_t val, void *p) -{ -} - - -static void -power_update_io_mapping(via_vt82c586b_t *dev) -{ - if (dev->power.io_base != 0x0000) - io_removehandler(dev->power.io_base, 0x100, power_reg_read, NULL, NULL, power_reg_write, NULL, NULL, dev); - - dev->power.io_base = (dev->power_regs[0x49] << 8); - - if ((dev->power_regs[0x41] & ACPI_IO_ENABLE) && (dev->power.io_base != 0x0000)) - io_sethandler(dev->power.io_base, 0x100, power_reg_read, NULL, NULL, power_reg_write, NULL, NULL, dev); -} - - -static void -via_vt82c586b_write(int func, int addr, uint8_t val, void *priv) -{ - via_vt82c586b_t *dev = (via_vt82c586b_t *) priv; - int c; - - if (func > 3) - return; - - switch(func) { - case 0: /* PCI-ISA bridge */ - /* Read-only addresses */ - if ((addr < 4) || (addr == 5) || ((addr >= 8) && (addr < 0x40)) || - (addr == 0x49) || (addr == 0x4b) || ((addr >= 0x51) && (addr < 0x54)) || ((addr >= 0x5d) && (addr < 0x60)) || - ((addr >= 0x68) && (addr < 0x6a)) || (addr >= 0x73)) - return; - - switch (addr) { - case 0x04: - dev->pci_isa_regs[0x04] = (val & 8) | 7; - break; - case 0x07: - dev->pci_isa_regs[0x07] &= ~(val & 0xb0); - break; - - case 0x47: - if ((val & 0x81) == 0x81) - resetx86(); - pic_set_shadow(!!(val & 0x10)); - pci_elcr_set_enabled(!!(val & 0x20)); - dev->pci_isa_regs[0x47] = val & 0xfe; - break; - case 0x48: - dev->pci_isa_regs[0x48] = val; - nvr_update_io_mapping(dev); - break; - - case 0x54: - pci_set_irq_level(PCI_INTA, !(val & 8)); - pci_set_irq_level(PCI_INTB, !(val & 4)); - pci_set_irq_level(PCI_INTC, !(val & 2)); - pci_set_irq_level(PCI_INTD, !(val & 1)); - break; - case 0x55: - pci_set_irq_routing(PCI_INTD, (val & 0xf0) ? (val >> 4) : PCI_IRQ_DISABLED); - pci_set_mirq_routing(PCI_MIRQ0, (val & 0x0f) ? (val & 0x0f) : PCI_IRQ_DISABLED); - dev->pci_isa_regs[0x55] = val; - break; - case 0x56: - pci_set_irq_routing(PCI_INTA, (val & 0xf0) ? (val >> 4) : PCI_IRQ_DISABLED); - pci_set_irq_routing(PCI_INTB, (val & 0x0f) ? (val & 0x0f) : PCI_IRQ_DISABLED); - dev->pci_isa_regs[0x56] = val; - break; - case 0x57: - pci_set_irq_routing(PCI_INTC, (val & 0xf0) ? (val >> 4) : PCI_IRQ_DISABLED); - pci_set_mirq_routing(PCI_MIRQ1, (val & 0x0f) ? (val & 0x0f) : PCI_IRQ_DISABLED); - dev->pci_isa_regs[0x57] = val; - break; - case 0x58: - pci_set_mirq_routing(PCI_MIRQ2, (val & 0x0f) ? (val & 0x0f) : PCI_IRQ_DISABLED); - dev->pci_isa_regs[0x58] = val; - break; - case 0x5b: - dev->pci_isa_regs[0x5b] = val; - nvr_update_io_mapping(dev); - break; - - case 0x60: case 0x62: case 0x64: case 0x66: - case 0x6a: case 0x6c: case 0x6e: - c = (addr & 0x0e) >> 1; - dma[c].ab = (dma[c].ab & 0xffffff0f) | (val & 0xf0); - dma[c].ac = (dma[c].ac & 0xffffff0f) | (val & 0xf0); - if (val & 0x08) - dma_e |= (1 << c); - else - dma_e &= ~(1 << c); - break; - case 0x61: case 0x63: case 0x65: case 0x67: - case 0x6b: case 0x6d: case 0x6f: - c = (addr & 0x0e) >> 1; - dma[c].ab = (dma[c].ab & 0xffff00ff) | (val << 8); - dma[c].ac = (dma[c].ac & 0xffff00ff) | (val << 8); - break; - - case 0x70: case 0x71: case 0x72: case 0x73: - dev->pci_isa_regs[(addr - 0x44)] = val; - break; - } - break; - - case 1: /* IDE regs */ - /* Read-only addresses */ - if ((addr < 4) || (addr == 5) || (addr == 8) || ((addr >= 0xa) && (addr < 0x0d)) || - ((addr >= 0x0e) && (addr < 0x10)) || ((addr >= 0x12) && (addr < 0x13)) || - ((addr >= 0x16) && (addr < 0x17)) || ((addr >= 0x1a) && (addr < 0x1b)) || - ((addr >= 0x1e) && (addr < 0x1f)) || ((addr >= 0x22) && (addr < 0x3c)) || - ((addr >= 0x3e) && (addr < 0x40)) || ((addr >= 0x54) && (addr < 0x60)) || - ((addr >= 0x52) && (addr < 0x68)) || (addr >= 0x62)) - return; - - switch (addr) { - case 0x04: - dev->ide_regs[0x04] = val & 0x85; - via_vt82c586b_ide_handlers(dev); - via_vt82c586b_bus_master_handlers(dev); - break; - case 0x07: - dev->ide_regs[0x07] &= ~(val & 0xf1); - break; - - case 0x09: - dev->ide_regs[0x09] = (val & 0x05) | 0x8a; - via_vt82c586b_ide_handlers(dev); - via_vt82c586b_ide_irqs(dev); - break; - - case 0x10: - dev->ide_regs[0x10] = (val & 0xf8) | 1; - via_vt82c586b_ide_handlers(dev); - break; - case 0x11: - dev->ide_regs[0x11] = val; - via_vt82c586b_ide_handlers(dev); - break; - - case 0x14: - dev->ide_regs[0x14] = (val & 0xfc) | 1; - via_vt82c586b_ide_handlers(dev); - break; - case 0x15: - dev->ide_regs[0x15] = val; - via_vt82c586b_ide_handlers(dev); - break; - - case 0x18: - dev->ide_regs[0x18] = (val & 0xf8) | 1; - via_vt82c586b_ide_handlers(dev); - break; - case 0x19: - dev->ide_regs[0x19] = val; - via_vt82c586b_ide_handlers(dev); - break; - - case 0x1c: - dev->ide_regs[0x1c] = (val & 0xfc) | 1; - via_vt82c586b_ide_handlers(dev); - break; - case 0x1d: - dev->ide_regs[0x1d] = val; - via_vt82c586b_ide_handlers(dev); - break; - - case 0x20: - dev->ide_regs[0x20] = (val & 0xf0) | 1; - via_vt82c586b_bus_master_handlers(dev); - break; - case 0x21: - dev->ide_regs[0x21] = val; - via_vt82c586b_bus_master_handlers(dev); - break; - - case 0x3d: - dev->ide_regs[0x3d] = val & 0x01; - via_vt82c586b_ide_irqs(dev); - break; - - case 0x40: - dev->ide_regs[0x40] = val; - via_vt82c586b_ide_handlers(dev); - break; - - default: - dev->ide_regs[addr] = val; - break; - } - break; - - case 2: - /* Read-only addresses */ - if ((addr < 4) || (addr == 5) || (addr == 6) || ((addr >= 8) && (addr < 0xd)) || - ((addr >= 0xe) && (addr < 0x20)) || ((addr >= 0x22) && (addr < 0x3c)) || - ((addr >= 0x3e) && (addr < 0x40)) || ((addr >= 0x42) && (addr < 0x44)) || - ((addr >= 0x46) && (addr < 0xc0)) || (addr >= 0xc2)) - return; - - switch (addr) { - case 0x04: - dev->usb_regs[0x04] = val & 0x97; - usb_update_io_mapping(dev); - break; - case 0x07: - dev->usb_regs[0x07] &= ~(val & 0x78); - break; - - case 0x20: - dev->usb_regs[0x20] = (val & ~0x1f) | 1; - usb_update_io_mapping(dev); - break; - case 0x21: - dev->usb_regs[0x21] = val; - usb_update_io_mapping(dev); - break; - - default: - dev->usb_regs[addr] = val; - break; - } - break; - - case 3: - /* Read-only addresses */ - if ((addr < 0xd) || ((addr >= 0xe) && (addr < 0x40)) || (addr == 0x43) || (addr == 0x48) || - ((addr >= 0x4a) && (addr < 0x50)) || (addr >= 0x54)) - return; - - switch (addr) { - case 0x41: case 0x49: - dev->power_regs[addr] = val; - power_update_io_mapping(dev); - break; - - default: - dev->power_regs[addr] = val; - break; - } - } -} - - -static void -*via_vt82c586b_init(const device_t *info) -{ - via_vt82c586b_t *dev = (via_vt82c586b_t *) malloc(sizeof(via_vt82c586b_t)); - memset(dev, 0, sizeof(via_vt82c586b_t)); - - dev->slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, via_vt82c586b_read, via_vt82c586b_write, dev); - - dev->bm[0] = device_add_inst(&sff8038i_device, 1); - sff_set_slot(dev->bm[0], dev->slot); - sff_set_irq_mode(dev->bm[0], 0, 0); - sff_set_irq_mode(dev->bm[0], 1, 0); - sff_set_irq_pin(dev->bm[0], PCI_INTA); - - dev->bm[1] = device_add_inst(&sff8038i_device, 2); - sff_set_slot(dev->bm[1], dev->slot); - sff_set_irq_mode(dev->bm[1], 0, 0); - sff_set_irq_mode(dev->bm[1], 1, 0); - sff_set_irq_pin(dev->bm[1], PCI_INTA); - - dev->nvr = device_add(&via_nvr_device); - - via_vt82c586b_reset_hard(dev); - - device_add(&port_92_pci_device); - - dma_alias_set(); - - pci_enable_mirq(0); - pci_enable_mirq(1); - pci_enable_mirq(2); - - return dev; -} - -static void -via_vt82c586b_close(void *p) -{ - via_vt82c586b_t *via_vt82c586b = (via_vt82c586b_t *)p; - - free(via_vt82c586b); -} - -const device_t via_vt82c586b_device = -{ - "VIA VT82C586B", - DEVICE_PCI, - 0, - via_vt82c586b_init, - via_vt82c586b_close, - NULL, - NULL, - NULL, - NULL, - NULL -}; diff --git a/src/chipset/via_vt82c596b.c b/src/chipset/via_vt82c596b.c deleted file mode 100644 index 5cc9a2e4e..000000000 --- a/src/chipset/via_vt82c596b.c +++ /dev/null @@ -1,789 +0,0 @@ -/* - - 86Box A hypervisor and IBM PC system emulator that specializes in - running old operating systems and software designed for IBM - PC systems and compatibles from 1981 through fairly recent - system designs based on the PCI bus. - - - Implementation of the VT82C596B. Based on VT82C586B + PIIX4 - - Authors: Sarah Walker, - - Copyright 2020 Tiseno100 - Copyright 2020 Sarah Walker
- Copyright 2020 Miran Grca - Copyright 2020 Melissa Goad - - TODO: - - The SMBus must be checked and implemented properly - - Fix Documentation errors - -*/ - -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include <86box/86box.h> -#include <86box/cdrom.h> -#include "cpu.h" -#include <86box/scsi_device.h> -#include <86box/scsi_cdrom.h> -#include <86box/dma.h> -#include <86box/io.h> -#include <86box/device.h> -#include <86box/apm.h> -#include <86box/keyboard.h> -#include <86box/mem.h> -#include <86box/timer.h> -#include <86box/nvr.h> -#include <86box/pci.h> -#include <86box/pic.h> -#include <86box/port_92.h> -#include <86box/hdc.h> -#include <86box/hdc_ide.h> -#include <86box/hdc_ide_sff8038i.h> -#include <86box/zip.h> -#include <86box/machine.h> -#include <86box/chipset.h> - -// As of now -#include <86box/smbus_piix4.h> - -#define ACPI_TIMER_FREQ 3579545 // Probably Emulator related - -#define ACPI_IO_ENABLE (1 << 7) -#define ACPI_TIMER_32BIT (1 << 3) - -#if defined(DEV_BRANCH) && defined(USE_596B) - -typedef struct -{ - uint8_t pci_to_isa_regs[256]; // PCI-to-ISA (Same as 586B) - uint8_t ide_regs[256]; // Common VIA IDE controller - uint8_t usb_regs[256]; // Common VIA USB controller - uint8_t power_regs[256]; // VT82C596B Power Managment Device(Same as 586B + SMBus) - sff8038i_t * bm[2]; - - nvr_t * nvr; - int nvr_enabled, slot; - - struct - { - uint16_t io_base; - }usb; - - struct - { - uint16_t io_base; - }power; - - smbus_piix4_t * smbus; - -} via_vt82c596b_t; - -static void -via_vt82c596b_reset(void *priv) -{ - - via_vt82c596b_t *via_vt82c596b = (via_vt82c596b_t *) priv; - uint16_t old_base = (via_vt82c596b->ide_regs[0x20] & 0xf0) | (via_vt82c596b->ide_regs[0x21] << 8); - - sff_bus_master_reset(via_vt82c596b->bm[0], old_base); - sff_bus_master_reset(via_vt82c596b->bm[1], old_base + 8); - - memset(via_vt82c596b->pci_to_isa_regs, 0, 256); - memset(via_vt82c596b->ide_regs, 0, 256); - memset(via_vt82c596b->usb_regs, 0, 256); - memset(via_vt82c596b->power_regs, 0, 256); - - - //PCI-to-ISA registers - via_vt82c596b->pci_to_isa_regs[0x00] = 0x06; //VIA - via_vt82c596b->pci_to_isa_regs[0x01] = 0x11; - - via_vt82c596b->pci_to_isa_regs[0x02] = 0x96; //VT82C596B - via_vt82c596b->pci_to_isa_regs[0x03] = 0x05; - - via_vt82c596b->pci_to_isa_regs[0x04] = 0x0f; //Control - - via_vt82c596b->pci_to_isa_regs[0x07] = 2; //Status - - via_vt82c596b->pci_to_isa_regs[0x09] = 0; //Program Interface - - via_vt82c596b->pci_to_isa_regs[0x0A] = 1; //Sub-Class code - via_vt82c596b->pci_to_isa_regs[0x0B] = 6; //Class code - - via_vt82c596b->pci_to_isa_regs[0x0E] = 0x80; //Header Type - - via_vt82c596b->pci_to_isa_regs[0x2C] = 0x73; //Subsystem ID - via_vt82c596b->pci_to_isa_regs[0x2D] = 0x72; - via_vt82c596b->pci_to_isa_regs[0x2E] = 0x71; - via_vt82c596b->pci_to_isa_regs[0x2F] = 0x70; - - via_vt82c596b->pci_to_isa_regs[0x48] = 1; //Miscellaneous control 3 - via_vt82c596b->pci_to_isa_regs[0x4A] = 4; - via_vt82c596b->pci_to_isa_regs[0x4F] = 3; - - via_vt82c596b->pci_to_isa_regs[0x50] = 0x24; //Reserved(?) - via_vt82c596b->pci_to_isa_regs[0x59] = 4; //PIRQ Pin Configuration - - //Resetting the DMA - dma_e = 0x00; - for (int i = 0; i < 8; i++) { - dma[i].ab &= 0xffff000f; - dma[i].ac &= 0xffff000f; - } - - pic_set_shadow(0); - - //IDE registers - via_vt82c596b->ide_regs[0x00] = 0x06; //VIA - via_vt82c596b->ide_regs[0x01] = 0x11; - - via_vt82c596b->ide_regs[0x02] = 0x71; //Common VIA IDE Controller - via_vt82c596b->ide_regs[0x03] = 0x05; - - via_vt82c596b->ide_regs[0x04] = 0x80; //Command - - via_vt82c596b->ide_regs[0x06] = 0x80; //Status - via_vt82c596b->ide_regs[0x07] = 0x02; - - via_vt82c596b->ide_regs[0x09] = 0x85; //Programming Interface - - via_vt82c596b->ide_regs[0x0A] = 0x01; //Sub class code - via_vt82c596b->ide_regs[0x0B] = 0x01; //Base class code - - //Base address control commands - via_vt82c596b->ide_regs[0x10] = 0xF0; - via_vt82c596b->ide_regs[0x11] = 0x01; - - via_vt82c596b->ide_regs[0x14] = 0xF4; - via_vt82c596b->ide_regs[0x15] = 0x03; - - via_vt82c596b->ide_regs[0x18] = 0x70; - via_vt82c596b->ide_regs[0x19] = 0x01; - - via_vt82c596b->ide_regs[0x1C] = 0x74; - via_vt82c596b->ide_regs[0x1D] = 0x03; - - via_vt82c596b->ide_regs[0x20] = 0x01; - via_vt82c596b->ide_regs[0x21] = 0xCC; - //// - - via_vt82c596b->ide_regs[0x3C] = 0x0E; //Interrupt line - - via_vt82c596b->ide_regs[0x40] = 0x08; //Chip Enable - - via_vt82c596b->ide_regs[0x41] = 0x02; //IDE Configuration - - via_vt82c596b->ide_regs[0x42] = 0x09; //Reserved - - via_vt82c596b->ide_regs[0x43] = 0x3A; //FIFO Configuration - - via_vt82c596b->ide_regs[0x44] = 0x68; //Miscellaneous Control 1 - - via_vt82c596b->ide_regs[0x46] = 0xC0; //Miscellaneous Control 3 - - via_vt82c596b->ide_regs[0x48] = 0xA8; //Driver Timing Control - via_vt82c596b->ide_regs[0x49] = 0xA8; - via_vt82c596b->ide_regs[0x4A] = 0xA8; - via_vt82c596b->ide_regs[0x4B] = 0xA8; - - via_vt82c596b->ide_regs[0x4C] = 0xFF; //Address Setup Time - - via_vt82c596b->ide_regs[0x4E] = 0xFF; //Sec Non-1F0 Port Access Timing - via_vt82c596b->ide_regs[0x4F] = 0xFF; //Pri Non-1F0 Port Access Timing - - via_vt82c596b->ide_regs[0x50] = 0x03; //UltraDMA33 Extended Timing Control - via_vt82c596b->ide_regs[0x51] = 0x03; - via_vt82c596b->ide_regs[0x52] = 0x03; - via_vt82c596b->ide_regs[0x53] = 0x03; - - via_vt82c596b->ide_regs[0x61] = 0x02; //IDE Primary Sector Size - via_vt82c596b->ide_regs[0x69] = 0x02; //IDE Secondary Sector Size - - via_vt82c596b->usb_regs[0x00] = 0x06; //VIA USB Common Controller - via_vt82c596b->usb_regs[0x01] = 0x11; - via_vt82c596b->usb_regs[0x02] = 0x38; - via_vt82c596b->usb_regs[0x03] = 0x30; - - //USB Registers - via_vt82c596b->usb_regs[0x04] = 0; //Control - via_vt82c596b->usb_regs[0x05] = 0; - - via_vt82c596b->usb_regs[0x06] = 0; - via_vt82c596b->usb_regs[0x07] = 2; //Status - - via_vt82c596b->usb_regs[0x0A] = 3; //Sub Class Code - via_vt82c596b->usb_regs[0x0B] = 0x0C; //Base Class Code - - via_vt82c596b->usb_regs[0x0D] = 0x16; //Latency Timer - - via_vt82c596b->usb_regs[0x20] = 1; //Base address - via_vt82c596b->usb_regs[0x21] = 3; - - via_vt82c596b->usb_regs[0x3D] = 4; //Interrupt Pin - - via_vt82c596b->usb_regs[0x60] = 0x10; //Serial Bus Release Number(USB 1.0) - via_vt82c596b->usb_regs[0xC1] = 0x20; //Legacy Support - - //Power Management Registers - via_vt82c596b->power_regs[0x00] = 0x06; //VT82C596B Power Managment Controller - via_vt82c596b->power_regs[0x01] = 0x11; - via_vt82c596b->power_regs[0x02] = 0x50; - via_vt82c596b->power_regs[0x03] = 0x30; - - via_vt82c596b->power_regs[0x04] = 0; //Control - via_vt82c596b->power_regs[0x05] = 0; - - via_vt82c596b->power_regs[0x06] = 0x80; //Status - via_vt82c596b->power_regs[0x07] = 2; - - via_vt82c596b->power_regs[0x48] = 1; //Power Managment IO Base - - via_vt82c596b->power_regs[0x90] = 1; //SMBus IO Base - - //Setting up Routing - pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); - pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); - pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); - pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); - - pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); - pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); - pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED); - - //Disabling the Primary & Secondary controller(?) - ide_pri_disable(); - ide_sec_disable(); -} - - -// IDE CONTROLLER -static void -ide_handlers(via_vt82c596b_t *dev) -{ - uint16_t main, side; - - ide_pri_disable(); - ide_sec_disable(); - - //On Bitfield 0(0x01) Primary Channel operating mode - if (dev->ide_regs[0x09] & 0x01) { - main = (dev->ide_regs[0x11] << 8) | (dev->ide_regs[0x10] & 0xf8); - side = ((dev->ide_regs[0x15] << 8) | (dev->ide_regs[0x14] & 0xfc)) + 2; - } else { - main = 0x1f0; - side = 0x3f6; - } - ide_set_base(0, main); - ide_set_side(0, side); - - //On Bitfield 2(0x04) Secondary Channel operating mode - if (dev->ide_regs[0x09] & 0x04) { - main = (dev->ide_regs[0x19] << 8) | (dev->ide_regs[0x18] & 0xf8); - side = ((dev->ide_regs[0x1d] << 8) | (dev->ide_regs[0x1c] & 0xfc)) + 2; - } else { - main = 0x170; - side = 0x376; - } - ide_set_base(1, main); - ide_set_side(1, side); - - //Enable the Primary & Secondary Controllers - if (dev->ide_regs[0x04] & PCI_COMMAND_IO) { - - //On Bitfield 0(0x01) Enable the Secondary Controller - //On Bitfield 1(0x02) Enable the Primary Controller - if (dev->ide_regs[0x40] & 0x02) - ide_pri_enable(); - if (dev->ide_regs[0x40] & 0x01) - ide_sec_enable(); - } -} - - -static void -ide_irqs(via_vt82c596b_t *dev) -{ - int irq_mode[2] = { 0, 0 }; - - if (dev->ide_regs[0x09] & 0x01) - irq_mode[0] = (dev->ide_regs[0x3d] & 0x01); - - if (dev->ide_regs[0x09] & 0x04) - irq_mode[1] = (dev->ide_regs[0x3d] & 0x01); - - sff_set_irq_mode(dev->bm[0], 0, irq_mode[0]); - sff_set_irq_mode(dev->bm[0], 1, irq_mode[1]); - - sff_set_irq_mode(dev->bm[1], 0, irq_mode[0]); - sff_set_irq_mode(dev->bm[1], 1, irq_mode[1]); -} - - -static void -bus_master_handlers(via_vt82c596b_t *dev) -{ - uint16_t base = (dev->ide_regs[0x20] & 0xf0) | (dev->ide_regs[0x21] << 8); - - //On Bitfield 0(0x01) I/O Space - sff_bus_master_handler(dev->bm[0], (dev->ide_regs[0x04] & 1), base); - sff_bus_master_handler(dev->bm[1], (dev->ide_regs[0x04] & 1), base + 8); -} -//// - -// USB CONTROLLER - -static uint8_t -usb_reg_read(uint16_t addr, void *p) -{ - uint8_t ret = 0xff; - - switch (addr & 0x1f) { - case 0x10: case 0x11: case 0x12: case 0x13: - // Return 0 on port status - ret = 0x00; - break; - } - - return ret; -} - -static void -usb_reg_write(uint16_t addr, uint8_t val, void *p) {} - -static void -usb_update_io_mapping(via_vt82c596b_t *dev) -{ - if (dev->usb.io_base != 0x0000) - io_removehandler(dev->usb.io_base, 0x20, usb_reg_read, NULL, NULL, usb_reg_write, NULL, NULL, dev); - - //On Bitfield 31 defaults to zero (0x20) - dev->usb.io_base = (dev->usb_regs[0x20] & ~0x1f) | (dev->usb_regs[0x21] << 8); - - //0x20 - //Master Interrupt Control(?) - //TODO: Find the exact meaning - if ((dev->usb_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) && (dev->usb.io_base != 0x0000)) - io_sethandler(dev->usb.io_base, 0x20, usb_reg_read, NULL, NULL, usb_reg_write, NULL, NULL, dev); -} - -//// - -// NVR -static void -nvr_update_io_mapping(via_vt82c596b_t *dev) -{ - - //0x74 CMOS Memory Address - //0x75 CMOS Memory Data - - //Ports 74-75 may be used to access CMOS if the internal RTC is disabled. - - if (dev->nvr_enabled) - nvr_at_handler(0, 0x0074, dev->nvr); - - //In case of we are set on 5B bitfield 1(0x02)(RTC SRAM Access Enable) and 48 bitfield 3(0x08) - //(Extra RTC Port 74/75 Enable) - if ((dev->pci_to_isa_regs[0x5b] & 0x02) && (dev->pci_to_isa_regs[0x48] & 0x08)) - nvr_at_handler(1, 0x0074, dev->nvr); -} -//// - -// POWER MANAGMENT - -// Need excessive documentation -static uint8_t -power_reg_read(uint16_t addr, void *p) -{ - via_vt82c596b_t *dev = (via_vt82c596b_t *) p; - - uint32_t timer; - uint8_t ret = 0xff; - - switch (addr & 0xff) { - case 0x08: case 0x09: case 0x0a: case 0x0b: - - //ACPI Timer - timer = (tsc * ACPI_TIMER_FREQ) / machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed; - - if (!(dev->power_regs[0x41] & ACPI_TIMER_32BIT)) - timer &= 0x00ffffff; - ret = (timer >> (8 * (addr & 3))) & 0xff; - - break; - } - - return ret; -} - -static void -power_reg_write(uint16_t addr, uint8_t val, void *p) {} - -static void -power_update_io_mapping(via_vt82c596b_t *dev) -{ - if (dev->power.io_base != 0x0000) - io_removehandler(dev->power.io_base, 0x100, power_reg_read, NULL, NULL, power_reg_write, NULL, NULL, dev); - - dev->power.io_base = (dev->power_regs[0x49] << 8); - - if ((dev->power_regs[0x41] & ACPI_IO_ENABLE) && (dev->power.io_base != 0x0000)) - io_sethandler(dev->power.io_base, 0x100, power_reg_read, NULL, NULL, power_reg_write, NULL, NULL, dev); -} - -static void -smbus_update_io_mapping(via_vt82c596b_t *dev) -{ - smbus_piix4_remap(dev->smbus, (dev->power_regs[0x91] << 8) | (dev->power_regs[0x90] & 0xf0), (dev->power_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) && (dev->power_regs[0xD2] & 0x01)); -} -//// - - -static uint8_t -via_vt82c596b_read(int func, int addr, void *priv) -{ - via_vt82c596b_t *dev = (via_vt82c596b_t *) priv; - - uint8_t ret = 0xff; - int c; - - switch(func) { - case 0: - //By System I/O Map, setting up the Keyboard Controller - //60-6F Keyboard Controller [0000 0000 0110] xnxn - if ((addr >= 0x60) && (addr <= 0x6f)) { - c = (addr & 0x0e) >> 1; - if (addr & 0x01) //If Enabled - ret = (dma[c].ab & 0x0000ff00) >> 8; - else { - ret = (dma[c].ab & 0x000000f0); - ret |= (!!(dma_e & (1 << c)) << 3); - } - } else - ret = dev->pci_to_isa_regs[addr]; - break; - case 1: - ret = dev->ide_regs[addr]; - break; - case 2: - ret = dev->usb_regs[addr]; - break; - case 3: - ret = dev->power_regs[addr]; - break; - } - - return ret; -} - -static void -via_vt82c596b_write(int func, int addr, uint8_t val, void *priv) -{ - via_vt82c596b_t *dev = (via_vt82c596b_t *) priv; - int c; - - //Excessive Documentation is needed!! - - if (func > 3) - return; - - switch(func) { - //PCI-to-ISA - case 0: - //Read-only addresses - if ((addr < 4) || (addr == 5) || ((addr >= 8) && (addr < 0x40)) || - (addr == 0x49) || (addr == 0x4b) || ((addr >= 0x51) && (addr < 0x54)) || - ((addr >= 0x5d) && (addr < 0x60)) || - ((addr >= 0x68) && (addr < 0x6a)) || (addr >= 0x73)) - return; - - switch (addr) { - case 0x04: - dev->pci_to_isa_regs[0x04] = (val & 8) | 7; - break; - case 0x07: - dev->pci_to_isa_regs[0x07] &= ~(val & 0xb0); - break; - - case 0x47: - if ((val & 0x81) == 0x81) - resetx86(); - pic_set_shadow(!!(val & 0x10)); - pci_elcr_set_enabled(!!(val & 0x20)); - dev->pci_to_isa_regs[0x47] = val & 0xfe; - break; - case 0x48: - dev->pci_to_isa_regs[0x48] = val; - nvr_update_io_mapping(dev); - break; - - case 0x54: - pci_set_irq_level(PCI_INTA, !(val & 8)); - pci_set_irq_level(PCI_INTB, !(val & 4)); - pci_set_irq_level(PCI_INTC, !(val & 2)); - pci_set_irq_level(PCI_INTD, !(val & 1)); - break; - case 0x55: - pci_set_irq_routing(PCI_INTD, (val & 0xf0) ? (val >> 4) : PCI_IRQ_DISABLED); - pci_set_mirq_routing(PCI_MIRQ0, (val & 0x0f) ? (val & 0x0f) : PCI_IRQ_DISABLED); - dev->pci_to_isa_regs[0x55] = val; - break; - case 0x56: - pci_set_irq_routing(PCI_INTA, (val & 0xf0) ? (val >> 4) : PCI_IRQ_DISABLED); - pci_set_irq_routing(PCI_INTB, (val & 0x0f) ? (val & 0x0f) : PCI_IRQ_DISABLED); - dev->pci_to_isa_regs[0x56] = val; - break; - case 0x57: - pci_set_irq_routing(PCI_INTC, (val & 0xf0) ? (val >> 4) : PCI_IRQ_DISABLED); - pci_set_mirq_routing(PCI_MIRQ1, (val & 0x0f) ? (val & 0x0f) : PCI_IRQ_DISABLED); - dev->pci_to_isa_regs[0x57] = val; - break; - case 0x58: - pci_set_mirq_routing(PCI_MIRQ2, (val & 0x0f) ? (val & 0x0f) : PCI_IRQ_DISABLED); - dev->pci_to_isa_regs[0x58] = val; - break; - case 0x5b: - dev->pci_to_isa_regs[0x5b] = val; - nvr_update_io_mapping(dev); - break; - - case 0x60: case 0x62: case 0x64: case 0x66: - case 0x6a: case 0x6c: case 0x6e: - c = (addr & 0x0e) >> 1; - dma[c].ab = (dma[c].ab & 0xffffff0f) | (val & 0xf0); - dma[c].ac = (dma[c].ac & 0xffffff0f) | (val & 0xf0); - if (val & 0x08) - dma_e |= (1 << c); - else - dma_e &= ~(1 << c); - break; - case 0x61: case 0x63: case 0x65: case 0x67: - case 0x6b: case 0x6d: case 0x6f: - c = (addr & 0x0e) >> 1; - dma[c].ab = (dma[c].ab & 0xffff00ff) | (val << 8); - dma[c].ac = (dma[c].ac & 0xffff00ff) | (val << 8); - break; - - case 0x70: case 0x71: case 0x72: case 0x73: - dev->pci_to_isa_regs[(addr - 0x44)] = val; - break; - } - break; - - //IDE Controller - case 1: - //Read-only addresses - if ((addr < 4) || (addr == 5) || (addr == 8) || ((addr >= 0xa) && (addr < 0x0d)) || - ((addr >= 0x0e) && (addr < 0x10)) || ((addr >= 0x12) && (addr < 0x13)) || - ((addr >= 0x16) && (addr < 0x17)) || ((addr >= 0x1a) && (addr < 0x1b)) || - ((addr >= 0x1e) && (addr < 0x1f)) || ((addr >= 0x22) && (addr < 0x3c)) || - ((addr >= 0x3e) && (addr < 0x40)) || ((addr >= 0x54) && (addr < 0x60)) || - ((addr >= 0x52) && (addr < 0x68)) || (addr >= 0x62)) - return; - - switch (addr) { - case 0x04: - dev->ide_regs[0x04] = val & 0x85; - ide_handlers(dev); - bus_master_handlers(dev); - break; - case 0x07: - dev->ide_regs[0x07] &= ~(val & 0xf1); - break; - - case 0x09: - dev->ide_regs[0x09] = (val & 0x05) | 0x8a; - ide_handlers(dev); - ide_irqs(dev); - break; - - case 0x10: - dev->ide_regs[0x10] = (val & 0xf8) | 1; - ide_handlers(dev); - break; - case 0x11: - dev->ide_regs[0x11] = val; - ide_handlers(dev); - break; - - case 0x14: - dev->ide_regs[0x14] = (val & 0xfc) | 1; - ide_handlers(dev); - break; - case 0x15: - dev->ide_regs[0x15] = val; - ide_handlers(dev); - break; - - case 0x18: - dev->ide_regs[0x18] = (val & 0xf8) | 1; - ide_handlers(dev); - break; - case 0x19: - dev->ide_regs[0x19] = val; - ide_handlers(dev); - break; - - case 0x1c: - dev->ide_regs[0x1c] = (val & 0xfc) | 1; - ide_handlers(dev); - break; - case 0x1d: - dev->ide_regs[0x1d] = val; - ide_handlers(dev); - break; - - case 0x20: - dev->ide_regs[0x20] = (val & 0xf0) | 1; - bus_master_handlers(dev); - break; - case 0x21: - dev->ide_regs[0x21] = val; - bus_master_handlers(dev); - break; - - case 0x3d: - dev->ide_regs[0x3d] = val & 0x01; - ide_irqs(dev); - break; - - case 0x40: - dev->ide_regs[0x40] = val; - ide_handlers(dev); - break; - - default: - dev->ide_regs[addr] = val; - break; - } - break; - - //USB Controller - case 2: - //Read-only addresses - if ((addr < 4) || (addr == 5) || (addr == 6) || ((addr >= 8) && (addr < 0xd)) || - ((addr >= 0xe) && (addr < 0x20)) || ((addr >= 0x22) && (addr < 0x3c)) || - ((addr >= 0x3e) && (addr < 0x40)) || ((addr >= 0x42) && (addr < 0x44)) || - ((addr >= 0x46) && (addr < 0xc0)) || (addr >= 0xc2)) - return; - - switch (addr) { - case 0x04: - dev->usb_regs[0x04] = val & 0x97; - usb_update_io_mapping(dev); - break; - case 0x07: - dev->usb_regs[0x07] &= ~(val & 0x78); - break; - - case 0x20: - dev->usb_regs[0x20] = (val & ~0x1f) | 1; - usb_update_io_mapping(dev); - break; - case 0x21: - dev->usb_regs[0x21] = val; - usb_update_io_mapping(dev); - break; - - default: - dev->usb_regs[addr] = val; - break; - } - break; - - //Power Management - case 3: - //Read-Only Addresses - if ((addr < 0xd) || ((addr >= 0xe) && (addr < 0x40)) || (addr == 0x43) || (addr == 0x48) || - ((addr >= 0x4a) && (addr < 0x50)) || (addr >= 0x54)) - return; - - switch (addr) { - case 0x41: case 0x49: - dev->power_regs[addr] = val; - power_update_io_mapping(dev); - smbus_update_io_mapping(dev); - break; - - case 0x90: - dev->power_regs[0x90] = (val & 0xf0) | 1; - smbus_update_io_mapping(dev); - break; - case 0x91: - dev->power_regs[0x91] = val; - smbus_update_io_mapping(dev); - break; - - default: - dev->power_regs[addr] = val; - break; - } - } -} - -static void * -via_vt82c596b_init(const device_t *info) -{ - via_vt82c596b_t *dev = (via_vt82c596b_t *) malloc(sizeof(via_vt82c596b_t)); - memset(dev, 0, sizeof(via_vt82c596b_t)); - - dev->slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, via_vt82c596b_read, via_vt82c596b_write, dev); - - dev->bm[0] = device_add_inst(&sff8038i_device, 1); - sff_set_slot(dev->bm[0], dev->slot); - sff_set_irq_mode(dev->bm[0], 0, 0); - sff_set_irq_mode(dev->bm[0], 1, 0); - sff_set_irq_pin(dev->bm[0], PCI_INTA); - - dev->bm[1] = device_add_inst(&sff8038i_device, 2); - sff_set_slot(dev->bm[1], dev->slot); - sff_set_irq_mode(dev->bm[1], 0, 0); - sff_set_irq_mode(dev->bm[1], 1, 0); - sff_set_irq_pin(dev->bm[1], PCI_INTA); - - dev->nvr = device_add(&via_nvr_device); - - via_vt82c596b_reset(dev); - - dev->smbus = device_add(&piix4_smbus_device); - - device_add(&port_92_pci_device); - - dma_alias_set(); - - pci_enable_mirq(0); - pci_enable_mirq(1); - pci_enable_mirq(2); - - return dev; -} - -static void -via_vt82c596b_close(void *p) -{ - via_vt82c596b_t *via_vt82c596b = (via_vt82c596b_t *)p; - - free(via_vt82c596b); -} - -const device_t via_vt82c596b_device = -{ - "VIA VT82C596B", - DEVICE_PCI, - 0, - via_vt82c596b_init, - via_vt82c596b_close, - NULL, - NULL, - NULL, - NULL, - NULL -}; -#endif \ No newline at end of file diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index c0bc68eaa..836cbdbe4 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -423,6 +423,7 @@ extern int machine_at_ax6bc_init(const machine_t *); extern int machine_at_atc6310bxii_init(const machine_t *); extern int machine_at_tsunamiatx_init(const machine_t *); extern int machine_at_p6sba_init(const machine_t *); +extern int machine_at_6vx_init(const machine_t *); #ifdef EMU_DEVICE_H extern const device_t *at_tsunamiatx_get_device(void); diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c index eb135d6cc..130c73ad9 100644 --- a/src/machine/m_at_slot1.c +++ b/src/machine/m_at_slot1.c @@ -567,6 +567,39 @@ machine_at_tsunamiatx_init(const machine_t *model) } +int +machine_at_6vx_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/6vx/6vx.f1a", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x01, PCI_CARD_SPECIAL, 0, 0, 3, 4); + device_add(&via_apro_device); + device_add(&via_vt82c596b_device); + device_add(&w83877f_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&sst_flash_39sf020_device); + spd_register(SPD_TYPE_SDRAM, 0x7, 256); + + return ret; +} + + const device_t * at_tsunamiatx_get_device(void) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 5e12c6c6a..d8ea04109 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -363,6 +363,7 @@ const machine_t machines[] = { { "[i440BX] A-Trend ATC6310BXII", "atc6310bxii", MACHINE_TYPE_SLOT1, {{"Intel", cpus_PentiumII}, {"Intel/PGA370", cpus_Celeron},{"VIA", cpus_Cyrix3},{"", NULL},{"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 255, machine_at_atc6310bxii_init, NULL }, { "[i440BX] Tyan Tsunami ATX", "tsunamiatx", MACHINE_TYPE_SLOT1, {{"Intel", cpus_PentiumII}, {"Intel/PGA370", cpus_Celeron},{"VIA", cpus_Cyrix3},{"", NULL},{"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_SOUND, 8, 1024, 8, 255, machine_at_tsunamiatx_init, at_tsunamiatx_get_device }, { "[i440BX] SuperMicro Super P6SBA", "p6sba", MACHINE_TYPE_SLOT1, {{"Intel", cpus_PentiumII}, {"Intel/PGA370", cpus_Celeron},{"VIA", cpus_Cyrix3},{"", NULL},{"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 255, machine_at_p6sba_init, NULL }, + { "[VIA Apollo Pro] Gigabyte GA-6VX", "6vx", MACHINE_TYPE_SLOT1, {{"Intel", cpus_PentiumII}, {"Intel/PGA370", cpus_Celeron},{"VIA", cpus_Cyrix3},{"", NULL},{"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 255, machine_at_6vx_init, NULL }, /* Slot 2 machines(Including Slot 1/2 Hybrids) */ /* 440GX */ diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index fcd35a524..544d85d5d 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -630,7 +630,7 @@ CHIPSETOBJ := acc2168.o cs8230.o ali1429.o headland.o intel_82335.o cs4031.o \ intel_420ex.o intel_4x0.o intel_sio.o intel_piix.o ioapic.o \ neat.o opti495.o opti895.o opti5x7.o scamp.o scat.o via_vt82c49x.o via_vt82c505.o \ sis_85c310.o sis_85c471.o sis_85c496.o opti283.o opti291.o umc491.o \ - via_apollo.o via_vpx.o via_vt82c586b.o via_vt82c596b.o wd76c10.o vl82c480.o \ + via_apollo.o via_vpx.o via_pipc.o wd76c10.o vl82c480.o \ amd640.o MCHOBJ := machine.o machine_table.o \