diff --git a/src/chipset/ali1543.c b/src/chipset/ali1543.c index ccdaf0c46..4d8dea3ce 100644 --- a/src/chipset/ali1543.c +++ b/src/chipset/ali1543.c @@ -197,8 +197,7 @@ ali1533_write(int func, int addr, uint8_t val, void *priv) case 0x44: /* Set IRQ Line for Primary IDE if it's on native mode */ dev->pci_conf[addr] = val & 0xdf; soft_reset_pci = !!(val & 0x80); - sff_set_irq_level(dev->ide_controller[0], 0, !(val & 0x10)); - sff_set_irq_level(dev->ide_controller[1], 0, !(val & 0x10)); + pci_set_mirq_level(PCI_MIRQ2, !(val & 0x10)); ali1543_log("INTAJ = IRQ %i\n", ali1533_irq_routing[val & 0x0f]); pci_set_mirq_routing(PCI_MIRQ0, ali1533_irq_routing[val & 0x0f]); pci_set_mirq_routing(PCI_MIRQ2, ali1533_irq_routing[val & 0x0f]); @@ -418,8 +417,7 @@ ali1533_write(int func, int addr, uint8_t val, void *priv) case 0x75: /* Set IRQ Line for Secondary IDE if it's on native mode */ dev->pci_conf[addr] = val & 0x1f; - sff_set_irq_level(dev->ide_controller[0], 1, !(val & 0x10)); - sff_set_irq_level(dev->ide_controller[1], 1, !(val & 0x10)); + pci_set_mirq_level(PCI_MIRQ3, !(val & 0x10)); ali1543_log("INTBJ = IRQ %i\n", ali1533_irq_routing[val & 0x0f]); pci_set_mirq_routing(PCI_MIRQ1, ali1533_irq_routing[val & 0x0f]); pci_set_mirq_routing(PCI_MIRQ3, ali1533_irq_routing[val & 0x0f]); @@ -503,34 +501,29 @@ ali5229_ide_irq_handler(ali1543_t *dev) if (dev->ide_conf[0x09] & (1 ^ bit)) { /* Primary IDE is native. */ ali1543_log("Primary IDE IRQ mode: Native, Native\n"); - sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 4); - sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 4); + sff_set_irq_mode(dev->ide_controller[ctl], IRQ_MODE_ALI_ALADDIN); } else { /* Primary IDE is legacy. */ switch (dev->pci_conf[0x58] & 0x03) { case 0x00: /* SIRQI, SIRQII */ ali1543_log("Primary IDE IRQ mode: SIRQI, SIRQII\n"); - sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 2); - sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 5); + sff_set_irq_mode(dev->ide_controller[ctl], ctl ? IRQ_MODE_MIRQ_1 : IRQ_MODE_MIRQ_0); break; case 0x01: /* IRQ14, IRQ15 */ ali1543_log("Primary IDE IRQ mode: IRQ14, IRQ15\n"); - sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 0); - sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 0); + sff_set_irq_mode(dev->ide_controller[ctl], IRQ_MODE_LEGACY); break; case 0x02: /* IRQ14, SIRQII */ ali1543_log("Primary IDE IRQ mode: IRQ14, SIRQII\n"); - sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 0); - sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 5); + sff_set_irq_mode(dev->ide_controller[ctl], ctl ? IRQ_MODE_MIRQ_1 : IRQ_MODE_LEGACY); break; case 0x03: /* IRQ14, SIRQI */ ali1543_log("Primary IDE IRQ mode: IRQ14, SIRQI\n"); - sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 0); - sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 2); + sff_set_irq_mode(dev->ide_controller[ctl], ctl ? IRQ_MODE_MIRQ_0 : IRQ_MODE_LEGACY); break; default: @@ -543,34 +536,29 @@ ali5229_ide_irq_handler(ali1543_t *dev) if (dev->ide_conf[0x09] & (4 ^ bit)) { /* Secondary IDE is native. */ ali1543_log("Secondary IDE IRQ mode: Native, Native\n"); - sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 4); - sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 4); + sff_set_irq_mode(dev->ide_controller[ctl], IRQ_MODE_ALI_ALADDIN); } else { /* Secondary IDE is legacy. */ switch (dev->pci_conf[0x58] & 0x03) { case 0x00: /* SIRQI, SIRQII */ ali1543_log("Secondary IDE IRQ mode: SIRQI, SIRQII\n"); - sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 2); - sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 5); + sff_set_irq_mode(dev->ide_controller[ctl], ctl ? IRQ_MODE_MIRQ_1 : IRQ_MODE_MIRQ_0); break; case 0x01: /* IRQ14, IRQ15 */ ali1543_log("Secondary IDE IRQ mode: IRQ14, IRQ15\n"); - sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 0); - sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 0); + sff_set_irq_mode(dev->ide_controller[ctl], IRQ_MODE_LEGACY); break; case 0x02: /* IRQ14, SIRQII */ ali1543_log("Secondary IDE IRQ mode: IRQ14, SIRQII\n"); - sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 0); - sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 5); + sff_set_irq_mode(dev->ide_controller[ctl], ctl ? IRQ_MODE_MIRQ_1 : IRQ_MODE_LEGACY); break; case 0x03: /* IRQ14, SIRQI */ ali1543_log("Secondary IDE IRQ mode: IRQ14, SIRQI\n"); - sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 0); - sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 2); + sff_set_irq_mode(dev->ide_controller[ctl], ctl ? IRQ_MODE_MIRQ_0 : IRQ_MODE_LEGACY); break; default: @@ -636,7 +624,6 @@ ali5229_ide_handler(ali1543_t *dev) ali1543_log("ali5229_ide_handler(): Enabling primary IDE...\n"); ide_pri_enable(); - sff_bus_master_handler(dev->ide_controller[0], dev->ide_conf[0x04] & 0x01, ((dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)) + (0 ^ ch)); ali1543_log("M5229 PRI: BASE %04x SIDE %04x\n", current_pri_base, current_pri_side); } @@ -650,13 +637,14 @@ ali5229_ide_handler(ali1543_t *dev) ali1543_log("ali5229_ide_handler(): Enabling secondary IDE...\n"); ide_sec_enable(); - sff_bus_master_handler(dev->ide_controller[1], dev->ide_conf[0x04] & 0x01, ((dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)) + (8 ^ ch)); ali1543_log("M5229 SEC: BASE %04x SIDE %04x\n", current_sec_base, current_sec_side); } - } else { - sff_bus_master_handler(dev->ide_controller[0], dev->ide_conf[0x04] & 0x01, (dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)); - sff_bus_master_handler(dev->ide_controller[1], dev->ide_conf[0x04] & 0x01, ((dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)) + 8); } + + sff_bus_master_handler(dev->ide_controller[0], dev->ide_conf[0x04] & 0x01, + ((dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)) + (0 ^ ch)); + sff_bus_master_handler(dev->ide_controller[1], dev->ide_conf[0x04] & 0x01, + ((dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)) + (8 ^ ch)); } static void @@ -722,8 +710,8 @@ ali5229_chip_reset(ali1543_t *dev) sff_set_slot(dev->ide_controller[0], dev->ide_slot); sff_set_slot(dev->ide_controller[1], dev->ide_slot); - sff_bus_master_reset(dev->ide_controller[0], (dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)); - sff_bus_master_reset(dev->ide_controller[1], ((dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)) + 8); + sff_bus_master_reset(dev->ide_controller[0]); + sff_bus_master_reset(dev->ide_controller[1]); ali5229_ide_handler(dev); } @@ -844,8 +832,8 @@ ali5229_write(int func, int addr, uint8_t val, void *priv) if (val & 0x80) ali5229_chip_reset(dev); else if (val & 0x40) { - sff_bus_master_reset(dev->ide_controller[0], (dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)); - sff_bus_master_reset(dev->ide_controller[1], ((dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)) + 8); + sff_bus_master_reset(dev->ide_controller[0]); + sff_bus_master_reset(dev->ide_controller[1]); } break; diff --git a/src/chipset/intel_piix.c b/src/chipset/intel_piix.c index f588910f5..53ed617d2 100644 --- a/src/chipset/intel_piix.c +++ b/src/chipset/intel_piix.c @@ -106,13 +106,13 @@ static void smsc_ide_irqs(piix_t *dev) { int irq_line = 3; - uint8_t irq_mode[2] = { 0, 0 }; + uint8_t irq_mode[2] = { IRQ_MODE_LEGACY, IRQ_MODE_LEGACY }; if (dev->regs[1][0x09] & 0x01) - irq_mode[0] = (dev->regs[0][0xe1] & 0x01) ? 3 : 1; + irq_mode[0] = (dev->regs[0][0xe1] & 0x01) ? IRQ_MODE_PCI_IRQ_LINE : IRQ_MODE_PCI_IRQ_PIN; if (dev->regs[1][0x09] & 0x04) - irq_mode[1] = (dev->regs[0][0xe1] & 0x01) ? 3 : 1; + irq_mode[1] = (dev->regs[0][0xe1] & 0x01) ? IRQ_MODE_PCI_IRQ_LINE : IRQ_MODE_PCI_IRQ_PIN; switch ((dev->regs[0][0xe1] >> 1) & 0x07) { case 0x00: @@ -144,12 +144,10 @@ smsc_ide_irqs(piix_t *dev) } sff_set_irq_line(dev->bm[0], irq_line); - 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[0], irq_mode[0]); sff_set_irq_line(dev->bm[1], irq_line); - sff_set_irq_mode(dev->bm[1], 0, irq_mode[0]); - sff_set_irq_mode(dev->bm[1], 1, irq_mode[1]); + sff_set_irq_mode(dev->bm[1], irq_mode[1]); } static void @@ -1213,23 +1211,19 @@ piix_reset_hard(piix_t *dev) { uint8_t *fregs; - uint16_t old_base = (dev->regs[1][0x20] & 0xf0) | (dev->regs[1][0x21] << 8); - - sff_bus_master_reset(dev->bm[0], old_base); - sff_bus_master_reset(dev->bm[1], old_base + 8); + sff_bus_master_reset(dev->bm[0]); + sff_bus_master_reset(dev->bm[1]); if (dev->type >= 4) { sff_set_slot(dev->bm[0], dev->pci_slot); sff_set_irq_pin(dev->bm[0], PCI_INTA); sff_set_irq_line(dev->bm[0], 14); - sff_set_irq_mode(dev->bm[0], 0, 0); - sff_set_irq_mode(dev->bm[0], 1, 0); + sff_set_irq_mode(dev->bm[0], IRQ_MODE_LEGACY); sff_set_slot(dev->bm[1], dev->pci_slot); sff_set_irq_pin(dev->bm[1], PCI_INTA); sff_set_irq_line(dev->bm[1], 14); - sff_set_irq_mode(dev->bm[1], 0, 0); - sff_set_irq_mode(dev->bm[1], 1, 0); + sff_set_irq_mode(dev->bm[1], IRQ_MODE_LEGACY); } #ifdef ENABLE_PIIX_LOG @@ -1504,16 +1498,12 @@ piix_reset(void *priv) piix_write(3, 0xd2, 0x00, priv); } - sff_set_irq_mode(dev->bm[0], 0, 0); - sff_set_irq_mode(dev->bm[1], 0, 0); + sff_set_irq_mode(dev->bm[0], IRQ_MODE_LEGACY); - if (dev->no_mirq0 || (dev->type >= 4)) { - sff_set_irq_mode(dev->bm[0], 1, 0); - sff_set_irq_mode(dev->bm[1], 1, 0); - } else { - sff_set_irq_mode(dev->bm[0], 1, 2); - sff_set_irq_mode(dev->bm[1], 1, 2); - } + if (dev->no_mirq0 || (dev->type >= 4)) + sff_set_irq_mode(dev->bm[1], IRQ_MODE_LEGACY); + else + sff_set_irq_mode(dev->bm[1], IRQ_MODE_MIRQ_0); } static void @@ -1567,16 +1557,12 @@ piix_init(const device_t *info) ide_board_set_force_ata3(1, 1); } - sff_set_irq_mode(dev->bm[0], 0, 0); - sff_set_irq_mode(dev->bm[1], 0, 0); + sff_set_irq_mode(dev->bm[0], IRQ_MODE_LEGACY); - if (dev->no_mirq0 || (dev->type >= 4)) { - sff_set_irq_mode(dev->bm[0], 1, 0); - sff_set_irq_mode(dev->bm[1], 1, 0); - } else { - sff_set_irq_mode(dev->bm[0], 1, 2); - sff_set_irq_mode(dev->bm[1], 1, 2); - } + if (dev->no_mirq0 || (dev->type >= 4)) + sff_set_irq_mode(dev->bm[1], IRQ_MODE_LEGACY); + else + sff_set_irq_mode(dev->bm[1], IRQ_MODE_MIRQ_0); if (dev->type >= 3) dev->usb = device_add(&usb_device); diff --git a/src/chipset/sis_5511.c b/src/chipset/sis_5511.c index d30ef39ca..707545cbd 100644 --- a/src/chipset/sis_5511.c +++ b/src/chipset/sis_5511.c @@ -8,11 +8,11 @@ * * Implementation of the SiS 5511/5512/5513 Pentium PCI/ISA Chipset. * + * Authors: Miran Grca, + * Tiseno100, * - * - * Authors: Tiseno100, - * - * Copyright 2021 Tiseno100. + * Copyright 2021-2023 Miran Grca. + * Copyright 2021-2023 Tiseno100. */ #include #include @@ -27,26 +27,23 @@ #include <86box/timer.h> #include <86box/mem.h> +#include <86box/nvr.h> #include <86box/hdd.h> #include <86box/hdc.h> #include <86box/hdc_ide.h> #include <86box/hdc_ide_sff8038i.h> #include <86box/pci.h> +#include <86box/pic.h> +#include <86box/pit.h> +#include <86box/pit_fast.h> +#include <86box/plat.h> #include <86box/plat_unused.h> #include <86box/port_92.h> #include <86box/smram.h> +#include <86box/spd.h> #include <86box/chipset.h> -/* IDE Flags (1 Native / 0 Compatibility)*/ -#define PRIMARY_COMP_NAT_SWITCH (dev->pci_conf_sb[1][9] & 1) -#define SECONDARY_COMP_NAT_SWITCH (dev->pci_conf_sb[1][9] & 4) -#define PRIMARY_NATIVE_BASE (dev->pci_conf_sb[1][0x11] << 8) | (dev->pci_conf_sb[1][0x10] & 0xf8) -#define PRIMARY_NATIVE_SIDE (((dev->pci_conf_sb[1][0x15] << 8) | (dev->pci_conf_sb[1][0x14] & 0xfc)) + 2) -#define SECONDARY_NATIVE_BASE (dev->pci_conf_sb[1][0x19] << 8) | (dev->pci_conf_sb[1][0x18] & 0xf8) -#define SECONDARY_NATIVE_SIDE (((dev->pci_conf_sb[1][0x1d] << 8) | (dev->pci_conf_sb[1][0x1c] & 0xfc)) + 2) -#define BUS_MASTER_BASE ((dev->pci_conf_sb[1][0x20] & 0xf0) | (dev->pci_conf_sb[1][0x21] << 8)) - #ifdef ENABLE_SIS_5511_LOG int sis_5511_do_log = ENABLE_SIS_5511_LOG; @@ -72,14 +69,22 @@ typedef struct sis_5511_t { uint8_t pad; uint8_t regs[16]; + uint8_t states[7]; + + uint8_t slic_regs[4096]; uint8_t pci_conf[256]; uint8_t pci_conf_sb[2][256]; - sff8038i_t *ide_drive[2]; + mem_mapping_t slic_mapping; + + sff8038i_t *bm[2]; smram_t *smram; port_92_t *port_92; + void *pit; + nvr_t *nvr; + uint8_t (*pit_read_reg)(void *priv, uint8_t reg); } sis_5511_t; static void @@ -90,23 +95,31 @@ sis_5511_shadow_recalc(sis_5511_t *dev) for (uint8_t i = 0x80; i <= 0x86; i++) { if (i == 0x86) { - state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; - mem_set_mem_state_both(0xf0000, 0x10000, state); - pclog("000F0000-000FFFFF\n"); + if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) { + state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_both(0xf0000, 0x10000, state); + sis_5511_log("000F0000-000FFFFF\n"); + } } else { base = ((i & 0x07) << 15) + 0xc0000; - state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; - mem_set_mem_state_both(base, 0x4000, state); - pclog("%08X-%08X\n", base, base + 0x3fff); + if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) { + state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_both(base, 0x4000, state); + sis_5511_log("%08X-%08X\n", base, base + 0x3fff); + } - state = (dev->pci_conf[i] & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - state |= (dev->pci_conf[i] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; - mem_set_mem_state_both(base + 0x4000, 0x4000, state); - pclog("%08X-%08X\n", base + 0x4000, base + 0x7fff); + if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0x0a) { + state = (dev->pci_conf[i] & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (dev->pci_conf[i] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_both(base + 0x4000, 0x4000, state); + sis_5511_log("%08X-%08X\n", base + 0x4000, base + 0x7fff); + } } + + dev->states[i & 0x0f] = dev->pci_conf[i]; } flushmmucache_nopc(); @@ -135,38 +148,14 @@ sis_5511_smram_recalc(sis_5511_t *dev) flushmmucache(); } -void -sis_5513_ide_handler(sis_5511_t *dev) -{ - ide_pri_disable(); - ide_sec_disable(); - if (dev->pci_conf_sb[1][4] & 1) { - if (dev->pci_conf_sb[1][0x4a] & 4) { - ide_set_base(0, PRIMARY_COMP_NAT_SWITCH ? PRIMARY_NATIVE_BASE : 0x1f0); - ide_set_side(0, PRIMARY_COMP_NAT_SWITCH ? PRIMARY_NATIVE_SIDE : 0x3f6); - ide_pri_enable(); - } - if (dev->pci_conf_sb[1][0x4a] & 2) { - ide_set_base(1, SECONDARY_COMP_NAT_SWITCH ? SECONDARY_NATIVE_BASE : 0x170); - ide_set_side(1, SECONDARY_COMP_NAT_SWITCH ? SECONDARY_NATIVE_SIDE : 0x376); - ide_sec_enable(); - } - } -} - -void -sis_5513_bm_handler(sis_5511_t *dev) -{ - sff_bus_master_handler(dev->ide_drive[0], dev->pci_conf_sb[1][4] & 4, BUS_MASTER_BASE); - sff_bus_master_handler(dev->ide_drive[1], dev->pci_conf_sb[1][4] & 4, BUS_MASTER_BASE + 8); -} - static void sis_5511_write(UNUSED(int func), int addr, uint8_t val, void *priv) { sis_5511_t *dev = (sis_5511_t *) priv; - switch (addr) { + sis_5511_log("SiS 5511: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + if (func == 0x00) switch (addr) { case 0x07: /* Status - High Byte */ dev->pci_conf[addr] &= 0xb0; break; @@ -266,106 +255,120 @@ sis_5511_write(UNUSED(int func), int addr, uint8_t val, void *priv) break; case 0x70: /* DRAM Bank Register 0-0 */ - case 0x71: /* DRAM Bank Register 0-0 */ case 0x72: /* DRAM Bank Register 0-1 */ - dev->pci_conf[addr] = val; - break; - - case 0x73: /* DRAM Bank Register 0-1 */ - dev->pci_conf[addr] = val & 0x83; - break; - case 0x74: /* DRAM Bank Register 1-0 */ + case 0x76: /* DRAM Bank Register 1-1 */ + case 0x78: /* DRAM Bank Register 2-0 */ + case 0x7a: /* DRAM Bank Register 2-1 */ + case 0x7c: /* DRAM Bank Register 3-0 */ + case 0x7e: /* DRAM Bank Register 3-1 */ + spd_write_drbs(dev->regs, 0x70, 0x7e, 0x82); + break; + + case 0x71: /* DRAM Bank Register 0-0 */ dev->pci_conf[addr] = val; break; case 0x75: /* DRAM Bank Register 1-0 */ - dev->pci_conf[addr] = val & 0x7f; - break; - - case 0x76: /* DRAM Bank Register 1-1 */ - dev->pci_conf[addr] = val; - break; - - case 0x77: /* DRAM Bank Register 1-1 */ - dev->pci_conf[addr] = val & 0x83; - break; - - case 0x78: /* DRAM Bank Register 2-0 */ - dev->pci_conf[addr] = val; - break; - case 0x79: /* DRAM Bank Register 2-0 */ - dev->pci_conf[addr] = val & 0x7f; - break; - - case 0x7a: /* DRAM Bank Register 2-1 */ - dev->pci_conf[addr] = val; - break; - - case 0x7b: /* DRAM Bank Register 2-1 */ - dev->pci_conf[addr] = val & 0x83; - break; - - case 0x7c: /* DRAM Bank Register 3-0 */ - dev->pci_conf[addr] = val; - break; - case 0x7d: /* DRAM Bank Register 3-0 */ dev->pci_conf[addr] = val & 0x7f; break; - case 0x7e: /* DRAM Bank Register 3-1 */ - dev->pci_conf[addr] = val; - break; - + case 0x73: /* DRAM Bank Register 0-1 */ + case 0x77: /* DRAM Bank Register 1-1 */ + case 0x7b: /* DRAM Bank Register 2-1 */ case 0x7f: /* DRAM Bank Register 3-1 */ dev->pci_conf[addr] = val & 0x83; break; - case 0x80: - case 0x81: - case 0x82: - case 0x83: - case 0x84: - case 0x85: + case 0x80 ... 0x85: + dev->pci_conf[addr] = val & 0xee; + sis_5511_shadow_recalc(dev); + break; case 0x86: - dev->pci_conf[addr] = val & ((addr == 0x86) ? 0xe8 : 0xee); + dev->pci_conf[addr] = val & 0xe8; sis_5511_shadow_recalc(dev); break; - case 0x90: /* 5512 General Purpose Register Index */ - case 0x91: /* 5512 General Purpose Register Index */ - case 0x92: /* 5512 General Purpose Register Index */ - case 0x93: /* 5512 General Purpose Register Index */ + case 0x90 ... 0x93: /* 5512 General Purpose Register Index */ dev->pci_conf[addr] = val; break; default: break; } - sis_5511_log("SiS 5511: dev->pci_conf[%02x] = %02x POST: %02x\n", addr, dev->pci_conf[addr], inb(0x80)); +} + +static void +sis_5511_slic_write(uint32_t addr, uint8_t val, void *priv) +{ + sis_5511_t *dev = (sis_5511_t *) priv; + + addr &= 0x00000fff; + + switch (addr) { + case 0x00000000: + case 0x00000008: /* 0x00000008 is a SiS 5512 register. */ + dev->slic_regs[addr] = val; + break; + case 0x00000010: + case 0x00000018: + case 0x00000028: + case 0x00000038: + dev->slic_regs[addr] = val & 0x01; + break; + case 0x00000030: + dev->slic_regs[addr] = val & 0x0f; + mem_mapping_set_addr(&dev->slic_mapping, + (((uint32_t) (val & 0x0f)) << 28) | 0x0fc00000, 0x00001000); + break; + } } static uint8_t sis_5511_read(UNUSED(int func), int addr, void *priv) { const sis_5511_t *dev = (sis_5511_t *) priv; + uint8_t ret = 0xff; - sis_5511_log("SiS 5511: dev->pci_conf[%02x] (%02x) POST %02x\n", addr, dev->pci_conf[addr], inb(0x80)); - return dev->pci_conf[addr]; + if (func == 0x00) + ret = dev->pci_conf[addr]; + + sis_5511_log("SiS 5511: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; +} + +static uint8_t +sis_5511_slic_read(uint32_t addr, void *priv) +{ + sis_5511_t *dev = (sis_5511_t *) priv; + uint8_t ret = 0xff; + + addr &= 0x00000fff; + + switch (addr) { + case 0x00000008: /* 0x00000008 is a SiS 5512 register. */ + ret = dev->slic_regs[addr]; + break; + } + + return ret; } void sis_5513_pci_to_isa_write(int addr, uint8_t val, sis_5511_t *dev) { + sis_5511_log("SiS 5513 P2I: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + switch (addr) { case 0x04: /* Command */ - dev->pci_conf_sb[0][addr] = val & 7; + dev->pci_conf_sb[0][addr] = val & 0x0f; break; case 0x07: /* Status */ - dev->pci_conf_sb[0][addr] &= val & 0x36; + dev->pci_conf_sb[0][addr] = (dev->pci_conf_sb[0][addr] & 0x06) & ~(val & 0x30); break; case 0x40: /* BIOS Control Register */ @@ -377,40 +380,24 @@ sis_5513_pci_to_isa_write(int addr, uint8_t val, sis_5511_t *dev) case 0x43: /* INTC# Remapping Control Register */ case 0x44: /* INTD# Remapping Control Register */ dev->pci_conf_sb[0][addr] = val & 0x8f; - pci_set_irq_routing(addr & 7, (val & 0x80) ? (val & 0x80) : PCI_IRQ_DISABLED); + pci_set_irq_routing(addr & 0x07, (val & 0x80) ? PCI_IRQ_DISABLED : (val & 0x0f)); break; case 0x48: /* ISA Master/DMA Memory Cycle Control Register 1 */ case 0x49: /* ISA Master/DMA Memory Cycle Control Register 2 */ case 0x4a: /* ISA Master/DMA Memory Cycle Control Register 3 */ case 0x4b: /* ISA Master/DMA Memory Cycle Control Register 4 */ - case 0x4c: - case 0x4d: - case 0x4e: - case 0x4f: - case 0x50: - case 0x51: - case 0x52: - case 0x53: - case 0x54: - case 0x55: - case 0x56: - case 0x57: - case 0x58: - case 0x59: - case 0x5a: - case 0x5b: - case 0x5c: - case 0x5d: - case 0x5e: - case 0x5f: dev->pci_conf_sb[0][addr] = val; break; case 0x60: /* MIRQ0 Remapping Control Register */ case 0x61: /* MIRQ1 Remapping Control Register */ + sis_5511_log("Set MIRQ routing: MIRQ%i -> %02X\n", addr & 0x01, val); dev->pci_conf_sb[0][addr] = val & 0xcf; - pci_set_mirq_routing(addr & 1, (val & 0x80) ? (val & 0x0f) : PCI_IRQ_DISABLED); + if (val & 0x80) + pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), val & 0xf); break; case 0x62: /* On-board Device DMA Control Register */ @@ -418,11 +405,12 @@ sis_5513_pci_to_isa_write(int addr, uint8_t val, sis_5511_t *dev) break; case 0x63: /* IDEIRQ Remapping Control Register */ + sis_5511_log("Set MIRQ routing: IDEIRQ -> %02X\n", val); dev->pci_conf_sb[0][addr] = val & 0x8f; - if (val & 0x80) { - sff_set_irq_line(dev->ide_drive[0], (val & 0x80) ? (val & 0x0f) : PCI_IRQ_DISABLED); - sff_set_irq_line(dev->ide_drive[1], (val & 0x80) ? (val & 0x0f) : PCI_IRQ_DISABLED); - } + if (val & 0x80) + pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ2, val & 0xf); break; case 0x64: /* GPIO0 Control Register */ @@ -439,7 +427,8 @@ sis_5513_pci_to_isa_write(int addr, uint8_t val, sis_5511_t *dev) break; case 0x6a: /* GPIO Status Register */ - dev->pci_conf_sb[0][addr] &= val & 0x15; + dev->pci_conf_sb[0][addr] |= (val & 0x10); + dev->pci_conf_sb[0][addr] &= ~(val & 0x01); break; default: @@ -447,52 +436,139 @@ sis_5513_pci_to_isa_write(int addr, uint8_t val, sis_5511_t *dev) } } +static void +sis_5513_ide_irq_handler(sis_5511_t *dev) +{ + if (dev->pci_conf_sb[1][0x09] & 0x01) { + /* Primary IDE is native. */ + sis_5511_log("Primary IDE IRQ mode: Native, Native\n"); + sff_set_irq_mode(dev->bm[0], IRQ_MODE_SIS_551X); + } else { + /* Primary IDE is legacy. */ + sis_5511_log("Primary IDE IRQ mode: IRQ14, IRQ15\n"); + sff_set_irq_mode(dev->bm[0], IRQ_MODE_LEGACY); + } + + if (dev->pci_conf_sb[1][0x09] & 0x04) { + /* Secondary IDE is native. */ + sis_5511_log("Secondary IDE IRQ mode: Native, Native\n"); + sff_set_irq_mode(dev->bm[0], IRQ_MODE_SIS_551X); + } else { + /* Secondary IDE is legacy. */ + sis_5511_log("Secondary IDE IRQ mode: IRQ14, IRQ15\n"); + sff_set_irq_mode(dev->bm[0], IRQ_MODE_LEGACY); + } +} + +static void +sis_5513_ide_handler(sis_5511_t *dev) +{ + uint8_t ide_io_on = dev->pci_conf_sb[1][0x04] & 0x01; + + uint16_t native_base_pri_addr = (dev->pci_conf_sb[1][0x11] | dev->pci_conf_sb[1][0x10] << 8) & 0xfffe; + uint16_t native_side_pri_addr = (dev->pci_conf_sb[1][0x15] | dev->pci_conf_sb[1][0x14] << 8) & 0xfffe; + uint16_t native_base_sec_addr = (dev->pci_conf_sb[1][0x19] | dev->pci_conf_sb[1][0x18] << 8) & 0xfffe; + uint16_t native_side_sec_addr = (dev->pci_conf_sb[1][0x1c] | dev->pci_conf_sb[1][0x1b] << 8) & 0xfffe; + + uint16_t current_pri_base; + uint16_t current_pri_side; + uint16_t current_sec_base; + uint16_t current_sec_side; + + /* Primary Channel Programming */ + current_pri_base = (!(dev->pci_conf_sb[1][0x09] & 1)) ? 0x01f0 : native_base_pri_addr; + current_pri_side = (!(dev->pci_conf_sb[1][0x09] & 1)) ? 0x03f6 : native_side_pri_addr; + + /* Secondary Channel Programming */ + current_sec_base = (!(dev->pci_conf_sb[1][0x09] & 4)) ? 0x0170 : native_base_sec_addr; + current_sec_side = (!(dev->pci_conf_sb[1][0x09] & 4)) ? 0x0376 : native_side_sec_addr; + + sis_5511_log("sis_5513_ide_handler(): Disabling primary IDE...\n"); + ide_pri_disable(); + sis_5511_log("sis_5513_ide_handler(): Disabling secondary IDE...\n"); + ide_sec_disable(); + + if (ide_io_on) { + /* Primary Channel Setup */ + if (dev->pci_conf_sb[1][0x4a] & 0x02) { + sis_5511_log("sis_5513_ide_handler(): Primary IDE base now %04X...\n", current_pri_base); + ide_set_base(0, current_pri_base); + sis_5511_log("sis_5513_ide_handler(): Primary IDE side now %04X...\n", current_pri_side); + ide_set_side(0, current_pri_side); + + sis_5511_log("sis_5513_ide_handler(): Enabling primary IDE...\n"); + ide_pri_enable(); + + sis_5511_log("SiS 5513 PRI: BASE %04x SIDE %04x\n", current_pri_base, current_pri_side); + } + + /* Secondary Channel Setup */ + if (dev->pci_conf_sb[1][0x4a] & 0x04) { + sis_5511_log("sis_5513_ide_handler(): Secondary IDE base now %04X...\n", current_sec_base); + ide_set_base(1, current_sec_base); + sis_5511_log("sis_5513_ide_handler(): Secondary IDE side now %04X...\n", current_sec_side); + ide_set_side(1, current_sec_side); + + sis_5511_log("sis_5513_ide_handler(): Enabling secondary IDE...\n"); + ide_sec_enable(); + + sis_5511_log("SiS 5513: BASE %04x SIDE %04x\n", current_sec_base, current_sec_side); + } + } + + sff_bus_master_handler(dev->bm[0], ide_io_on, + ((dev->pci_conf_sb[1][0x20] & 0xf0) | (dev->pci_conf_sb[1][0x21] << 8)) + 0); + sff_bus_master_handler(dev->bm[1], ide_io_on, + ((dev->pci_conf_sb[1][0x20] & 0xf0) | (dev->pci_conf_sb[1][0x21] << 8)) + 8); +} + void sis_5513_ide_write(int addr, uint8_t val, sis_5511_t *dev) { + sis_5511_log("SiS 5513 IDE: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + switch (addr) { case 0x04: /* Command low byte */ - dev->pci_conf_sb[1][addr] = val & 5; + dev->pci_conf_sb[1][addr] = val & 0x05; sis_5513_ide_handler(dev); - sis_5513_bm_handler(dev); + break; + case 0x06: /* Status low byte */ + dev->pci_conf_sb[1][addr] = val & 0x20; break; case 0x07: /* Status high byte */ - dev->pci_conf_sb[1][addr] &= val & 0x3f; + dev->pci_conf_sb[1][addr] = (dev->pci_conf_sb[1][addr] & 0x06) & ~(val & 0x38); break; case 0x09: /* Programming Interface Byte */ - dev->pci_conf_sb[1][addr] = val; + dev->pci_conf_sb[1][addr] = (dev->pci_conf_sb[1][addr] & 0x8a) | (val & 0x05); + sis_5513_ide_irq_handler(dev); sis_5513_ide_handler(dev); break; case 0x0d: /* Latency Timer */ dev->pci_conf_sb[1][addr] = val; break; - case 0x10: /* Primary Channel Base Address Register */ - case 0x11: /* Primary Channel Base Address Register */ - case 0x12: /* Primary Channel Base Address Register */ - case 0x13: /* Primary Channel Base Address Register */ - case 0x14: /* Primary Channel Base Address Register */ - case 0x15: /* Primary Channel Base Address Register */ - case 0x16: /* Primary Channel Base Address Register */ - case 0x17: /* Primary Channel Base Address Register */ - case 0x18: /* Secondary Channel Base Address Register */ - case 0x19: /* Secondary Channel Base Address Register */ - case 0x1a: /* Secondary Channel Base Address Register */ - case 0x1b: /* Secondary Channel Base Address Register */ - case 0x1c: /* Secondary Channel Base Address Register */ - case 0x1d: /* Secondary Channel Base Address Register */ - case 0x1e: /* Secondary Channel Base Address Register */ - case 0x1f: /* Secondary Channel Base Address Register */ - dev->pci_conf_sb[1][addr] = val; - sis_5513_ide_handler(dev); - break; + /* Primary Base Address */ + case 0x10: + case 0x11: + case 0x14: + case 0x15: + fallthrough; - case 0x20: /* Bus Master IDE Control Register Base Address */ - case 0x21: /* Bus Master IDE Control Register Base Address */ - case 0x22: /* Bus Master IDE Control Register Base Address */ - case 0x23: /* Bus Master IDE Control Register Base Address */ - dev->pci_conf_sb[1][addr] = val; - sis_5513_bm_handler(dev); + /* Secondary Base Address */ + case 0x18: + case 0x19: + case 0x1c: + case 0x1d: + fallthrough; + + /* Bus Mastering Base Address */ + case 0x20: + case 0x21: + if (addr == 0x20) + dev->pci_conf_sb[1][addr] = (val & 0xe0) | 0x01; + else + dev->pci_conf_sb[1][addr] = val; + sis_5513_ide_handler(dev); break; case 0x30: /* Expansion ROM Base Address */ @@ -516,7 +592,7 @@ sis_5513_ide_write(int addr, uint8_t val, sis_5511_t *dev) break; case 0x4a: /* IDE General Control Register 0 */ - dev->pci_conf_sb[1][addr] = val & 0x9f; + dev->pci_conf_sb[1][addr] = val & 0x9e; sis_5513_ide_handler(dev); break; @@ -540,30 +616,55 @@ static void sis_5513_write(int func, int addr, uint8_t val, void *priv) { sis_5511_t *dev = (sis_5511_t *) priv; + switch (func) { + default: + break; case 0: sis_5513_pci_to_isa_write(addr, val, dev); break; case 1: sis_5513_ide_write(addr, val, dev); break; - - default: - break; } - sis_5511_log("SiS 5513: dev->pci_conf[%02x][%02x] = %02x POST: %02x\n", func, addr, dev->pci_conf_sb[func][addr], inb(0x80)); } static uint8_t sis_5513_read(int func, int addr, void *priv) { const sis_5511_t *dev = (sis_5511_t *) priv; + uint8_t ret = 0xff; - sis_5511_log("SiS 5513: dev->pci_conf[%02x][%02x] = %02x POST %02x\n", func, addr, dev->pci_conf_sb[func][addr], inb(0x80)); - if ((func >= 0) && (func <= 1)) - return dev->pci_conf_sb[func][addr]; - else - return 0xff; + if (func == 0x00) { + switch (addr) { + default: + ret = dev->pci_conf_sb[func][addr]; + break; + case 0x4c ... 0x4f: + ret = pic_read_icw(0, addr & 0x03); + break; + case 0x50 ... 0x53: + ret = pic_read_icw(1, addr & 0x03); + break; + case 0x54 ... 0x55: + ret = pic_read_ocw(0, addr & 0x01); + break; + case 0x56 ... 0x57: + ret = pic_read_ocw(1, addr & 0x01); + break; + case 0x58 ... 0x5f: + ret = dev->pit_read_reg(dev->pit, addr & 0x07); + break; + } + + sis_5511_log("SiS 5513 P2I: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + } else if (func == 0x01) { + ret = dev->pci_conf_sb[func][addr]; + + sis_5511_log("SiS 5513 IDE: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + } + + return ret; } static void @@ -576,6 +677,8 @@ sis_5513_isa_write(uint16_t addr, uint8_t val, void *priv) dev->index = val - 0x50; break; case 0x23: + sis_5511_log("SiS 5513 ISA: [W] dev->regs[%02X] = %02X\n", dev->index + 0x50, val); + switch (dev->index) { case 0x00: dev->regs[dev->index] = val & 0xed; @@ -593,6 +696,7 @@ sis_5513_isa_write(uint16_t addr, uint8_t val, void *priv) default: break; } + nvr_bank_set(0, !!(val & 0x08), dev->nvr); break; case 0x01: dev->regs[dev->index] = val & 0xf4; @@ -604,7 +708,8 @@ sis_5513_isa_write(uint16_t addr, uint8_t val, void *priv) dev->regs[dev->index] = val; break; case 0x05: - dev->regs[dev->index] = inb(0x70); + dev->regs[dev->index] = val; + outb(0x70, val); break; case 0x08: case 0x09: @@ -628,12 +733,18 @@ static uint8_t sis_5513_isa_read(uint16_t addr, void *priv) { const sis_5511_t *dev = (sis_5511_t *) priv; + uint8_t ret = 0xff; if (addr == 0x23) { - sis_5511_log("SiS 5513-ISA: dev->regs[%02x] (%02x) POST: %02x\n", dev->index + 0x50, dev->regs[dev->index], inb(0x80)); - return dev->regs[dev->index]; - } else - return 0xff; + if (dev->index == 0x05) + ret = inb(0x70); + else + ret = dev->regs[dev->index]; + + sis_5511_log("SiS 5513 ISA: [R] dev->regs[%02X] = %02X\n", dev->index + 0x50, ret); + } + + return ret; } static void @@ -667,58 +778,108 @@ sis_5511_reset(void *priv) dev->pci_conf[0x66] = 0x00; dev->pci_conf[0x67] = 0xff; dev->pci_conf[0x68] = dev->pci_conf[0x69] = 0x00; - dev->pci_conf[0x6a] = dev->pci_conf[0x6b] = 0x00; - dev->pci_conf[0x6c] = dev->pci_conf[0x6d] = 0x00; - dev->pci_conf[0x6e] = dev->pci_conf[0x6f] = 0x00; + dev->pci_conf[0x6a] = 0x00; + dev->pci_conf[0x6b] = dev->pci_conf[0x6c] = 0xff; + dev->pci_conf[0x6d] = dev->pci_conf[0x6e] = 0xff; + dev->pci_conf[0x6f] = 0x00; + dev->pci_conf[0x70] = dev->pci_conf[0x72] = 0x04; + dev->pci_conf[0x74] = dev->pci_conf[0x76] = 0x04; + dev->pci_conf[0x78] = dev->pci_conf[0x7a] = 0x04; + dev->pci_conf[0x7c] = dev->pci_conf[0x7e] = 0x04; + dev->pci_conf[0x73] = dev->pci_conf[0x77] = 0x80; + dev->pci_conf[0x7b] = dev->pci_conf[0x7f] = 0x80; + dev->pci_conf[0x80] = dev->pci_conf[0x81] = 0x00; + dev->pci_conf[0x82] = dev->pci_conf[0x83] = 0x00; + dev->pci_conf[0x84] = dev->pci_conf[0x85] = 0x00; + dev->pci_conf[0x86] = 0x00; cpu_cache_ext_enabled = 0; cpu_update_waitstates(); - dev->pci_conf[0x6b] = 0xff; - dev->pci_conf[0x6c] = 0xff; - dev->pci_conf[0x70] = 4; - dev->pci_conf[0x72] = 4; - dev->pci_conf[0x73] = 0x80; - dev->pci_conf[0x74] = 4; - dev->pci_conf[0x76] = 4; - dev->pci_conf[0x77] = 0x80; - dev->pci_conf[0x78] = 4; - dev->pci_conf[0x7a] = 4; - dev->pci_conf[0x7b] = 0x80; - dev->pci_conf[0x7c] = 4; - dev->pci_conf[0x7e] = 4; - dev->pci_conf[0x7f] = 0x80; - dev->pci_conf[0x80] = 0x00; - dev->pci_conf[0x81] = 0x00; - dev->pci_conf[0x82] = 0x00; - dev->pci_conf[0x83] = 0x00; - dev->pci_conf[0x84] = 0x00; - dev->pci_conf[0x85] = 0x00; - dev->pci_conf[0x86] = 0x00; sis_5511_smram_recalc(dev); sis_5511_shadow_recalc(dev); + flushmmucache(); + + memset(dev->slic_regs, 0x00, 4096 * sizeof(uint8_t)); + dev->slic_regs[0x18] = 0x0f; + + mem_mapping_set_addr(&dev->slic_mapping, 0xffc00000, 0x00001000); + /* SiS 5513 */ dev->pci_conf_sb[0][0x00] = 0x39; dev->pci_conf_sb[0][0x01] = 0x10; - dev->pci_conf_sb[0][0x02] = 8; - dev->pci_conf_sb[0][0x04] = 7; - dev->pci_conf_sb[0][0x0a] = 1; - dev->pci_conf_sb[0][0x0b] = 6; + dev->pci_conf_sb[0][0x02] = 0x08; + dev->pci_conf_sb[0][0x03] = 0x00; + dev->pci_conf_sb[0][0x04] = 0x07; + dev->pci_conf_sb[0][0x05] = dev->pci_conf_sb[0][0x06] = 0x00; + dev->pci_conf_sb[0][0x07] = 0x02; + dev->pci_conf_sb[0][0x08] = dev->pci_conf_sb[0][0x09] = 0x00; + dev->pci_conf_sb[0][0x0a] = 0x01; + dev->pci_conf_sb[0][0x0b] = 0x06; dev->pci_conf_sb[0][0x0e] = 0x80; + dev->pci_conf_sb[0][0x40] = 0x00; + dev->pci_conf_sb[0][0x41] = dev->pci_conf_sb[0][0x42] = 0x80; + dev->pci_conf_sb[0][0x43] = dev->pci_conf_sb[0][0x44] = 0x80; + dev->pci_conf_sb[0][0x48] = dev->pci_conf_sb[0][0x49] = 0x80; + dev->pci_conf_sb[0][0x4a] = dev->pci_conf_sb[0][0x4b] = 0x80; + dev->pci_conf_sb[0][0x60] = dev->pci_conf_sb[0][0x51] = 0x80; + dev->pci_conf_sb[0][0x62] = 0x00; + dev->pci_conf_sb[0][0x63] = 0x80; + dev->pci_conf_sb[0][0x64] = 0x00; + dev->pci_conf_sb[0][0x65] = 0x80; + dev->pci_conf_sb[0][0x66] = dev->pci_conf_sb[0][0x67] = 0x00; + dev->pci_conf_sb[0][0x68] = dev->pci_conf_sb[0][0x69] = 0x00; + dev->pci_conf_sb[0][0x6a] = 0x04; + + 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); + + dev->regs[0x00] = dev->regs[0x01] = 0x00; + dev->regs[0x03] = dev->regs[0x04] = 0x00; + dev->regs[0x05] = 0x00; + dev->regs[0x08] = dev->regs[0x09] = 0x00; + dev->regs[0x0a] = dev->regs[0x0b] = 0x00; + + cpu_set_isa_speed(7159091); + nvr_bank_set(0, 0, dev->nvr); /* SiS 5513 IDE Controller */ dev->pci_conf_sb[1][0x00] = 0x39; dev->pci_conf_sb[1][0x01] = 0x10; dev->pci_conf_sb[1][0x02] = 0x13; dev->pci_conf_sb[1][0x03] = 0x55; - dev->pci_conf_sb[1][0x0a] = 1; - dev->pci_conf_sb[1][0x0b] = 1; + dev->pci_conf_sb[1][0x04] = dev->pci_conf_sb[1][0x05] = 0x00; + dev->pci_conf_sb[1][0x06] = dev->pci_conf_sb[1][0x07] = 0x00; + dev->pci_conf_sb[1][0x08] = 0x00; + dev->pci_conf_sb[1][0x09] = 0x8a; + dev->pci_conf_sb[1][0x0a] = dev->pci_conf_sb[1][0x0b] = 0x01; + dev->pci_conf_sb[1][0x0c] = dev->pci_conf_sb[1][0x0d] = 0x00; dev->pci_conf_sb[1][0x0e] = 0x80; - sff_set_slot(dev->ide_drive[0], dev->sb_slot); - sff_set_slot(dev->ide_drive[1], dev->sb_slot); - sff_bus_master_reset(dev->ide_drive[0], BUS_MASTER_BASE); - sff_bus_master_reset(dev->ide_drive[1], BUS_MASTER_BASE + 8); + dev->pci_conf_sb[1][0x0f] = 0x00; + dev->pci_conf_sb[1][0x10] = 0xf1; + dev->pci_conf_sb[1][0x11] = 0x01; + dev->pci_conf_sb[1][0x14] = 0xf5; + dev->pci_conf_sb[1][0x15] = 0x03; + dev->pci_conf_sb[1][0x18] = 0x71; + dev->pci_conf_sb[1][0x19] = 0x01; + dev->pci_conf_sb[1][0x1c] = 0x75; + dev->pci_conf_sb[1][0x1d] = 0x03; + dev->pci_conf_sb[1][0x20] = 0x01; + dev->pci_conf_sb[1][0x21] = 0xf0; + dev->pci_conf_sb[1][0x22] = dev->pci_conf_sb[1][0x23] = 0x00; + + sis_5513_ide_irq_handler(dev); + sis_5513_ide_handler(dev); + + sff_bus_master_reset(dev->bm[0]); + sff_bus_master_reset(dev->bm[1]); } static void @@ -733,27 +894,55 @@ sis_5511_close(void *priv) static void * sis_5511_init(UNUSED(const device_t *info)) { - sis_5511_t *dev = (sis_5511_t *) malloc(sizeof(sis_5511_t)); + sis_5511_t *dev = (sis_5511_t *) calloc(1, sizeof(sis_5511_t)); + uint8_t pit_is_fast = (((pit_mode == -1) && is486) || (pit_mode == 1)); + memset(dev, 0, sizeof(sis_5511_t)); - pci_add_card(PCI_ADD_NORTHBRIDGE, sis_5511_read, sis_5511_write, dev, &dev->nb_slot); /* Device 0: SiS 5511 */ - pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5513_read, sis_5513_write, dev, &dev->sb_slot); /* Device 1: SiS 5513 */ - io_sethandler(0x0022, 0x0002, sis_5513_isa_read, NULL, NULL, sis_5513_isa_write, NULL, NULL, dev); /* Ports 22h-23h: SiS 5513 ISA */ + /* Device 0: SiS 5511 */ + pci_add_card(PCI_ADD_NORTHBRIDGE, sis_5511_read, sis_5511_write, dev, &dev->nb_slot); + /* Device 1: SiS 5513 */ + pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5513_read, sis_5513_write, dev, &dev->sb_slot); + + /* SLiC Memory Mapped Registers */ + mem_mapping_add(&dev->slic_mapping, + 0xffc00000, 0x00001000, + sis_5511_slic_read, + NULL, + NULL, + sis_5511_slic_write, + NULL, + NULL, + NULL, MEM_MAPPING_EXTERNAL, + dev); + + /* Ports 22h-23h: SiS 5513 ISA */ + io_sethandler(0x0022, 0x0002, sis_5513_isa_read, NULL, NULL, sis_5513_isa_write, NULL, NULL, dev); /* MIRQ */ pci_enable_mirq(0); pci_enable_mirq(1); + /* IDEIRQ */ + pci_enable_mirq(2); + /* Port 92h */ dev->port_92 = device_add(&port_92_device); /* SFF IDE */ - dev->ide_drive[0] = device_add_inst(&sff8038i_device, 1); - dev->ide_drive[1] = device_add_inst(&sff8038i_device, 2); + dev->bm[0] = device_add_inst(&sff8038i_device, 1); + dev->bm[1] = device_add_inst(&sff8038i_device, 2); /* SMRAM */ dev->smram = smram_add(); + /* PIT */ + dev->pit = device_find_first_priv(DEVICE_PIT); + dev->pit_read_reg = pit_is_fast ? pitf_read_reg : pit_read_reg; + + /* NVR */ + dev->nvr = device_add(&at_mb_nvr_device); + sis_5511_reset(dev); return dev; diff --git a/src/chipset/sis_5571.c b/src/chipset/sis_5571.c index 0761e4865..f130ecd8a 100644 --- a/src/chipset/sis_5571.c +++ b/src/chipset/sis_5571.c @@ -703,8 +703,8 @@ sis_5571_reset(void *priv) dev->pci_conf_sb[1][0x4a] = 0x06; sff_set_slot(dev->ide_drive[0], dev->sb_slot); sff_set_slot(dev->ide_drive[1], dev->sb_slot); - sff_bus_master_reset(dev->ide_drive[0], BUS_MASTER_BASE); - sff_bus_master_reset(dev->ide_drive[1], BUS_MASTER_BASE + 8); + sff_bus_master_reset(dev->ide_drive[0]); + sff_bus_master_reset(dev->ide_drive[1]); /* USB Controller */ dev->pci_conf_sb[2][0x00] = 0x39; diff --git a/src/chipset/stpc.c b/src/chipset/stpc.c index aa5e1fb8b..dbe39ec5c 100644 --- a/src/chipset/stpc.c +++ b/src/chipset/stpc.c @@ -929,11 +929,9 @@ stpc_init(const device_t *info) dev->bm[0] = device_add_inst(&sff8038i_device, 1); dev->bm[1] = device_add_inst(&sff8038i_device, 2); - sff_set_irq_mode(dev->bm[0], 0, 0); - sff_set_irq_mode(dev->bm[0], 1, 0); + sff_set_irq_mode(dev->bm[0], IRQ_MODE_LEGACY); - sff_set_irq_mode(dev->bm[1], 0, 0); - sff_set_irq_mode(dev->bm[1], 1, 0); + sff_set_irq_mode(dev->bm[1], IRQ_MODE_LEGACY); stpc_setup(dev); stpc_reset(dev); diff --git a/src/chipset/via_pipc.c b/src/chipset/via_pipc.c index a8e0f9ff2..1f153092b 100644 --- a/src/chipset/via_pipc.c +++ b/src/chipset/via_pipc.c @@ -210,10 +210,9 @@ pipc_reset_hard(void *priv) 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); + sff_bus_master_reset(dev->bm[0]); + sff_bus_master_reset(dev->bm[1]); memset(dev->pci_isa_regs, 0, 256); memset(dev->ide_regs, 0, 256); @@ -237,7 +236,8 @@ pipc_reset_hard(void *priv) dev->pci_isa_regs[0x4a] = 0x04; dev->pci_isa_regs[0x4f] = 0x03; - dev->pci_isa_regs[0x50] = (dev->local >= VIA_PIPC_686A) ? 0x0e : 0x24; /* 686A/B default value does not line up with default bits */ + /* 686A/B default value does not line up with default bits */ + dev->pci_isa_regs[0x50] = (dev->local >= VIA_PIPC_686A) ? 0x0e : 0x24; dev->pci_isa_regs[0x59] = 0x04; if (dev->local >= VIA_PIPC_686A) dev->pci_isa_regs[0x5a] = dev->pci_isa_regs[0x5f] = 0x04; @@ -566,19 +566,17 @@ pipc_ide_handlers(pipc_t *dev) static void pipc_ide_irqs(pipc_t *dev) { - int irq_mode[2] = { 0, 0 }; + int irq_mode[2] = { IRQ_MODE_LEGACY, IRQ_MODE_LEGACY }; if (dev->ide_regs[0x09] & 0x01) - irq_mode[0] = (dev->ide_regs[0x3d] & 0x01); + irq_mode[0] = (dev->ide_regs[0x3d] & 0x01) ? IRQ_MODE_PCI_IRQ_PIN : IRQ_MODE_LEGACY; if (dev->ide_regs[0x09] & 0x04) - irq_mode[1] = (dev->ide_regs[0x3d] & 0x01); + irq_mode[1] = (dev->ide_regs[0x3d] & 0x01) ? IRQ_MODE_PCI_IRQ_PIN : IRQ_MODE_LEGACY; - 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[0], irq_mode[0]); - sff_set_irq_mode(dev->bm[1], 0, irq_mode[0]); - sff_set_irq_mode(dev->bm[1], 1, irq_mode[1]); + sff_set_irq_mode(dev->bm[1], irq_mode[1]); } static void @@ -1638,22 +1636,20 @@ pipc_init(const device_t *info) pci_add_card(PCI_ADD_SOUTHBRIDGE, pipc_read, pipc_write, dev, &dev->pci_slot); dev->bm[0] = device_add_inst(&sff8038i_device, 1); - sff_set_irq_mode(dev->bm[0], 0, 0); - sff_set_irq_mode(dev->bm[0], 1, 0); + sff_set_irq_mode(dev->bm[0], IRQ_MODE_LEGACY); sff_set_irq_pin(dev->bm[0], PCI_INTA); dev->bm[1] = device_add_inst(&sff8038i_device, 2); - sff_set_irq_mode(dev->bm[1], 0, 0); - sff_set_irq_mode(dev->bm[1], 1, 0); + sff_set_irq_mode(dev->bm[1], IRQ_MODE_LEGACY); sff_set_irq_pin(dev->bm[1], PCI_INTA); - dev->nvr = device_add(&via_nvr_device); - if (dev->local == VIA_PIPC_686B) dev->smbus = device_add(&via_smbus_device); else if (dev->local >= VIA_PIPC_596A) dev->smbus = device_add(&piix4_smbus_device); + dev->nvr = device_add(&via_nvr_device); + if (dev->local >= VIA_PIPC_596A) { dev->acpi = device_add(&acpi_via_596b_device); acpi_set_trap_update(dev->acpi, pipc_trap_update_596, dev); diff --git a/src/device.c b/src/device.c index 8190b856d..088d8c3e6 100644 --- a/src/device.c +++ b/src/device.c @@ -332,6 +332,23 @@ device_reset_all(uint32_t match_flags) } } +void * +device_find_first_priv(uint32_t match_flags) +{ + void *ret = NULL; + + for (uint16_t c = 0; c < DEVICE_MAX; c++) { + if (devices[c] != NULL) { + if ((device_priv[c] != NULL) && (devices[c]->flags & match_flags)) { + ret = device_priv[c]; + break; + } + } + } + + return ret; +} + void * device_get_priv(const device_t *dev) { diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index dbbc1161b..279414491 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -124,8 +124,8 @@ typedef struct ide_board_t { } ide_board_t; typedef struct ide_bm_t { - int (*dma)(int channel, uint8_t *data, int transfer_length, int out, void *priv); - void (*set_irq)(int channel, void *priv); + int (*dma)(uint8_t *data, int transfer_length, int out, void *priv); + void (*set_irq)(uint8_t status, void *priv); void *priv; } ide_bm_t; @@ -342,7 +342,7 @@ ide_irq_raise(ide_t *ide) if (!(ide->fdisk & 2) && ide->selected) { if (!ide_boards[ide->board]->force_ata3 && ide_bm[ide->board] && ide_bm[ide->board]->set_irq) - ide_bm[ide->board]->set_irq(ide->board | 0x40, ide_bm[ide->board]->priv); + ide_bm[ide->board]->set_irq(0x04, ide_bm[ide->board]->priv); else if (ide_boards[ide->board]->irq != -1) picint(1 << ide_boards[ide->board]->irq); } @@ -363,7 +363,7 @@ ide_irq_lower(ide_t *ide) if (ide->irqstat && ide->selected) { if (!ide_boards[ide->board]->force_ata3 && ide_bm[ide->board] && ide_bm[ide->board]->set_irq) - ide_bm[ide->board]->set_irq(ide->board, ide_bm[ide->board]->priv); + ide_bm[ide->board]->set_irq(0x00, ide_bm[ide->board]->priv); else if (ide_boards[ide->board]->irq != -1) picintc(1 << ide_boards[ide->board]->irq); } @@ -382,8 +382,8 @@ ide_irq_update(ide_t *ide) if (!(ide->fdisk & 2) && ide->irqstat) { ide_log("IDE %i: IRQ update raise\n", ide->board); if (!ide_boards[ide->board]->force_ata3 && ide_bm[ide->board] && ide_bm[ide->board]->set_irq) { - ide_bm[ide->board]->set_irq(ide->board, ide_bm[ide->board]->priv); - ide_bm[ide->board]->set_irq(ide->board | 0x40, ide_bm[ide->board]->priv); + ide_bm[ide->board]->set_irq(0x00, ide_bm[ide->board]->priv); + ide_bm[ide->board]->set_irq(0x04, ide_bm[ide->board]->priv); } else if (ide_boards[ide->board]->irq != -1) { picintc(1 << ide_boards[ide->board]->irq); picint(1 << ide_boards[ide->board]->irq); @@ -391,7 +391,7 @@ ide_irq_update(ide_t *ide) } else if ((ide->fdisk & 2) || !ide->irqstat) { ide_log("IDE %i: IRQ update lower\n", ide->board); if (!ide_boards[ide->board]->force_ata3 && ide_bm[ide->board] && ide_bm[ide->board]->set_irq) - ide_bm[ide->board]->set_irq(ide->board, ide_bm[ide->board]->priv); + ide_bm[ide->board]->set_irq(0x00, ide_bm[ide->board]->priv); else if (ide_boards[ide->board]->irq != -1) picintc(1 << ide_boards[ide->board]->irq); } @@ -1022,9 +1022,9 @@ ide_atapi_callback(ide_t *ide) #endif out = (ide->sc->packet_status & 0x01); - if (!ide->sc->pad0 && !ide_boards[ide->board]->force_ata3 && ide_bm[ide->board] && ide_bm[ide->board]->dma) { - ret = ide_bm[ide->board]->dma(ide->board, - ide->sc->temp_buffer, ide->sc->packet_len, + if (!ide->sc->pad0 && !ide_boards[ide->board]->force_ata3 && + ide_bm[ide->board] && ide_bm[ide->board]->dma) { + ret = ide_bm[ide->board]->dma(ide->sc->temp_buffer, ide->sc->packet_len, out, ide_bm[ide->board]->priv); } else { /* DMA command without a bus master. */ @@ -2333,8 +2333,7 @@ ide_callback(void *priv) if (!ide_boards[ide->board]->force_ata3 && ide_bm[ide->board] && ide_bm[ide->board]->dma) { /* We should not abort - we should simply wait for the host to start DMA. */ - ret = ide_bm[ide->board]->dma(ide->board, - ide->sector_buffer, ide->sector_pos * 512, + ret = ide_bm[ide->board]->dma(ide->sector_buffer, ide->sector_pos * 512, 0, ide_bm[ide->board]->priv); if (ret == 2) { /* Bus master DMA disabled, simply wait for the host to enable DMA. */ @@ -2431,8 +2430,7 @@ ide_callback(void *priv) else ide->sector_pos = 256; - ret = ide_bm[ide->board]->dma(ide->board, - ide->sector_buffer, ide->sector_pos * 512, + ret = ide_bm[ide->board]->dma(ide->sector_buffer, ide->sector_pos * 512, 1, ide_bm[ide->board]->priv); if (ret == 2) { @@ -3041,8 +3039,8 @@ ide_xtide_close(void) void ide_set_bus_master(int board, - int (*dma)(int channel, uint8_t *data, int transfer_length, int out, void *priv), - void (*set_irq)(int channel, void *priv), void *priv) + int (*dma)(uint8_t *data, int transfer_length, int out, void *priv), + void (*set_irq)(uint8_t status, void *priv), void *priv) { if (ide_bm[board] == NULL) ide_bm[board] = (ide_bm_t *) malloc(sizeof(ide_bm_t)); diff --git a/src/disk/hdc_ide_cmd640.c b/src/disk/hdc_ide_cmd640.c index 2d203f3f8..3e77730a2 100644 --- a/src/disk/hdc_ide_cmd640.c +++ b/src/disk/hdc_ide_cmd640.c @@ -74,38 +74,52 @@ cmd640_log(const char *fmt, ...) #endif void -cmd640_set_irq(int channel, void *priv) +cmd640_set_irq_0(uint8_t status, void *priv) { cmd640_t *dev = (cmd640_t *) priv; - int irq = !!(channel & 0x40); + int irq = !!(status & 0x04); - if (channel & 0x01) { - if (!(dev->regs[0x57] & 0x10) || (channel & 0x40)) { - dev->regs[0x57] &= ~0x10; - dev->regs[0x57] |= (channel >> 2); - } - } else { - if (!(dev->regs[0x50] & 0x04) || (channel & 0x40)) { - dev->regs[0x50] &= ~0x04; - dev->regs[0x50] |= (channel >> 4); - } - } + if (!(dev->regs[0x50] & 0x04) || (status & 0x04)) + dev->regs[0x50] = (dev->regs[0x50] & ~0x04) | status; - channel &= 0x01; - - if (!(dev->channels & (1 << channel))) + if (!(dev->channels & 1)) return; if (irq) { - if (dev->irq_mode[channel] == 1) + if (dev->irq_mode[0] == 1) pci_set_irq(dev->pci_slot, dev->irq_pin, &dev->irq_state); else - picint(1 << (14 + channel)); + picint(1 << 14); } else { - if (dev->irq_mode[channel] == 1) + if (dev->irq_mode[0] == 1) pci_clear_irq(dev->pci_slot, dev->irq_pin, &dev->irq_state); else - picintc(1 << (14 + channel)); + picintc(1 << 14); + } +} + +void +cmd640_set_irq_1(uint8_t status, void *priv) +{ + cmd640_t *dev = (cmd640_t *) priv; + int irq = !!(status & 0x04); + + if (!(dev->regs[0x57] & 0x10) || (status & 0x04)) + dev->regs[0x57] = (dev->regs[0x57] & ~0x10) | (status << 2); + + if (!(dev->channels & 2)) + return; + + if (irq) { + if (dev->irq_mode[1] == 1) + pci_set_irq(dev->pci_slot, dev->irq_pin, &dev->irq_state); + else + picint(1 << 15); + } else { + if (dev->irq_mode[1] == 1) + pci_clear_irq(dev->pci_slot, dev->irq_pin, &dev->irq_state); + else + picintc(1 << 15); } } @@ -415,10 +429,10 @@ cmd640_reset(void *priv) } if (dev->channels & 0x01) - cmd640_set_irq(0x00, priv); + cmd640_set_irq_0(0x00, priv); if (dev->channels & 0x02) - cmd640_set_irq(0x01, priv); + cmd640_set_irq_1(0x00, priv); memset(dev->regs, 0x00, sizeof(dev->regs)); @@ -509,10 +523,10 @@ cmd640_init(const device_t *info) pci_add_card(PCI_ADD_IDE, cmd640_pci_read, cmd640_pci_write, dev, &dev->pci_slot); if (dev->channels & 0x01) - ide_set_bus_master(0, NULL, cmd640_set_irq, dev); + ide_set_bus_master(0, NULL, cmd640_set_irq_0, dev); if (dev->channels & 0x02) - ide_set_bus_master(1, NULL, cmd640_set_irq, dev); + ide_set_bus_master(1, NULL, cmd640_set_irq_1, dev); /* The CMD PCI-0640B IDE controller has no DMA capability, so set our devices IDE devices to force ATA-3 (no DMA). */ diff --git a/src/disk/hdc_ide_cmd646.c b/src/disk/hdc_ide_cmd646.c index 397329010..8367b9a41 100644 --- a/src/disk/hdc_ide_cmd646.c +++ b/src/disk/hdc_ide_cmd646.c @@ -73,31 +73,41 @@ cmd646_log(const char *fmt, ...) #endif static void -cmd646_set_irq(int channel, void *priv) +cmd646_set_irq_0(uint8_t status, void *priv) { cmd646_t *dev = (cmd646_t *) priv; - if (channel & 0x01) { - if (!(dev->regs[0x57] & 0x10) || (channel & 0x40)) { - dev->regs[0x57] &= ~0x10; - dev->regs[0x57] |= (channel >> 2); - } - } else { - if (!(dev->regs[0x50] & 0x04) || (channel & 0x40)) { - dev->regs[0x50] &= ~0x04; - dev->regs[0x50] |= (channel >> 4); - } - } + if (!(dev->regs[0x50] & 0x04) || (status & 0x04)) + dev->regs[0x50] = (dev->regs[0x50] & ~0x04) | status; - sff_bus_master_set_irq(channel, dev->bm[channel & 0x01]); + sff_bus_master_set_irq(status, dev->bm[0]); +} + +static void +cmd646_set_irq_1(uint8_t status, void *priv) +{ + cmd646_t *dev = (cmd646_t *) priv; + + if (!(dev->regs[0x57] & 0x10) || (status & 0x04)) + dev->regs[0x57] = (dev->regs[0x57] & ~0x10) | (status << 2); + + sff_bus_master_set_irq(status, dev->bm[1]); } static int -cmd646_bus_master_dma(int channel, uint8_t *data, int transfer_length, int out, void *priv) +cmd646_bus_master_dma_0(uint8_t *data, int transfer_length, int out, void *priv) { const cmd646_t *dev = (cmd646_t *) priv; - return sff_bus_master_dma(channel, data, transfer_length, out, dev->bm[channel & 0x01]); + return sff_bus_master_dma(data, transfer_length, out, dev->bm[0]); +} + +static int +cmd646_bus_master_dma_1(uint8_t *data, int transfer_length, int out, void *priv) +{ + const cmd646_t *dev = (cmd646_t *) priv; + + return sff_bus_master_dma(data, transfer_length, out, dev->bm[1]); } static void @@ -105,7 +115,7 @@ cmd646_ide_handlers(cmd646_t *dev) { uint16_t main; uint16_t side; - int irq_mode[2] = { 0, 0 }; + int irq_mode[2] = { IRQ_MODE_LEGACY, IRQ_MODE_LEGACY }; sff_set_slot(dev->bm[0], dev->pci_slot); sff_set_slot(dev->bm[1], dev->pci_slot); @@ -124,10 +134,9 @@ cmd646_ide_handlers(cmd646_t *dev) ide_set_side(0, side); if (dev->regs[0x09] & 0x01) - irq_mode[0] = 1; + irq_mode[0] = IRQ_MODE_PCI_IRQ_PIN; - 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[0], irq_mode[0]); if (dev->regs[0x04] & 0x01) ide_pri_enable(); @@ -151,8 +160,7 @@ cmd646_ide_handlers(cmd646_t *dev) if (dev->regs[0x09] & 0x04) irq_mode[1] = 1; - sff_set_irq_mode(dev->bm[1], 0, irq_mode[0]); - sff_set_irq_mode(dev->bm[1], 1, irq_mode[1]); + sff_set_irq_mode(dev->bm[1], irq_mode[1]); if ((dev->regs[0x04] & 0x01) && (dev->regs[0x51] & 0x08)) ide_sec_enable(); @@ -321,8 +329,8 @@ cmd646_reset(void *priv) mo_reset((scsi_common_t *) mo_drives[i].priv); } - cmd646_set_irq(0x00, priv); - cmd646_set_irq(0x01, priv); + cmd646_set_irq_0(0x00, priv); + cmd646_set_irq_1(0x00, priv); memset(dev->regs, 0x00, sizeof(dev->regs)); @@ -401,17 +409,14 @@ cmd646_init(const device_t *info) if (!dev->single_channel) dev->bm[1] = device_add_inst(&sff8038i_device, 2); - ide_set_bus_master(0, cmd646_bus_master_dma, cmd646_set_irq, dev); + ide_set_bus_master(0, cmd646_bus_master_dma_0, cmd646_set_irq_0, dev); if (!dev->single_channel) - ide_set_bus_master(1, cmd646_bus_master_dma, cmd646_set_irq, dev); + ide_set_bus_master(1, cmd646_bus_master_dma_1, cmd646_set_irq_1, dev); - sff_set_irq_mode(dev->bm[0], 0, 0); - sff_set_irq_mode(dev->bm[0], 1, 0); + sff_set_irq_mode(dev->bm[0], IRQ_MODE_LEGACY); - if (!dev->single_channel) { - sff_set_irq_mode(dev->bm[1], 0, 0); - sff_set_irq_mode(dev->bm[1], 1, 0); - } + if (!dev->single_channel) + sff_set_irq_mode(dev->bm[1], IRQ_MODE_LEGACY); cmd646_reset(dev); diff --git a/src/disk/hdc_ide_sff8038i.c b/src/disk/hdc_ide_sff8038i.c index fd6bee29d..40cca95a9 100644 --- a/src/disk/hdc_ide_sff8038i.c +++ b/src/disk/hdc_ide_sff8038i.c @@ -74,7 +74,7 @@ sff_log(const char *fmt, ...) void sff_bus_master_handler(sff8038i_t *dev, int enabled, uint16_t base) { - if (dev->base != 0x0000) { + if (dev->enabled && (dev->base != 0x0000)) { io_removehandler(dev->base, 0x08, sff_bus_master_read, sff_bus_master_readw, sff_bus_master_readl, sff_bus_master_write, sff_bus_master_writew, sff_bus_master_writel, @@ -314,7 +314,7 @@ sff_bus_master_readl(uint16_t port, void *priv) } int -sff_bus_master_dma(UNUSED(int channel), uint8_t *data, int transfer_length, int out, void *priv) +sff_bus_master_dma(uint8_t *data, int transfer_length, int out, void *priv) { sff8038i_t *dev = (sff8038i_t *) priv; #ifdef ENABLE_SFF_LOG @@ -385,64 +385,72 @@ sff_bus_master_dma(UNUSED(int channel), uint8_t *data, int transfer_length, int } void -sff_bus_master_set_irq(int channel, void *priv) +sff_bus_master_set_irq(uint8_t status, void *priv) { sff8038i_t *dev = (sff8038i_t *) priv; - uint8_t irq = !!(channel & 0x40); + uint8_t irq = !!(status & 0x04); + int irq_shift = 0; - if (!(dev->status & 0x04) || (channel & 0x40)) { - dev->status &= ~0x04; - dev->status |= (channel >> 4); - } + if (!(dev->status & 0x04) || (status & 0x04)) + dev->status = (dev->status & ~0x04) | status; - channel &= 0x01; - - switch (dev->irq_mode[channel]) { + switch (dev->irq_mode) { default: - case 0: + case IRQ_MODE_LEGACY: /* Legacy IRQ mode. */ if (irq) - picint(1 << (14 + channel)); + picint(1 << dev->irq_line); else - picintc(1 << (14 + channel)); + picintc(1 << dev->irq_line); break; - case 1: + case IRQ_MODE_PCI_IRQ_PIN: /* Native PCI IRQ mode with interrupt pin. */ if (irq) pci_set_irq(dev->slot, dev->irq_pin, &dev->irq_state); else pci_clear_irq(dev->slot, dev->irq_pin, &dev->irq_state); break; - case 2: - case 5: + case IRQ_MODE_MIRQ_0: + case IRQ_MODE_MIRQ_1: /* MIRQ 0 or 1. */ + case IRQ_MODE_MIRQ_2: + case IRQ_MODE_MIRQ_3: + /* MIRQ 2 or 3. */ if (irq) - pci_set_mirq((dev->irq_mode[channel] & 1), 0, &dev->irq_state); + pci_set_mirq((dev->irq_mode & 3) + irq_shift, 0, &dev->irq_state); else - pci_clear_mirq((dev->irq_mode[channel] & 1), 0, &dev->irq_state); + pci_clear_mirq((dev->irq_mode & 3) + irq_shift, 0, &dev->irq_state); break; - case 3: + /* TODO: Redo this as a MIRQ. */ + case IRQ_MODE_PCI_IRQ_LINE: /* Native PCI IRQ mode with specified interrupt line. */ if (irq) - picintlevel(1 << dev->irq_line, &dev->irq_state); + pci_set_dirq(dev->pci_irq_line, &dev->irq_state); else - picintclevel(1 << dev->irq_line, &dev->irq_state); + pci_clear_dirq(dev->pci_irq_line, &dev->irq_state); break; - case 4: + case IRQ_MODE_ALI_ALADDIN: /* ALi Aladdin Native PCI INTAJ mode. */ if (irq) - pci_set_mirq((channel + 2), dev->irq_level[channel], &dev->irq_state); + pci_set_mirq((dev->channel + 2), pci_get_mirq_level(dev->channel + 2), &dev->irq_state); else - pci_clear_mirq((channel + 2), dev->irq_level[channel], &dev->irq_state); + pci_clear_mirq((dev->channel + 2), pci_get_mirq_level(dev->channel + 2), &dev->irq_state); + break; + case IRQ_MODE_SIS_551X: + /* SiS 551x mode. */ + if (irq) + pci_set_mirq(2, 1, &dev->irq_state); + else + pci_clear_mirq(2, 1, &dev->irq_state); break; } } void -sff_bus_master_reset(sff8038i_t *dev, uint16_t old_base) +sff_bus_master_reset(sff8038i_t *dev) { - if (dev->enabled) { - io_removehandler(old_base, 0x08, + if (dev->enabled && (dev->base != 0x0000)) { + io_removehandler(dev->base, 0x08, sff_bus_master_read, sff_bus_master_readw, sff_bus_master_readl, sff_bus_master_write, sff_bus_master_writew, sff_bus_master_writel, dev); @@ -493,44 +501,54 @@ sff_set_slot(sff8038i_t *dev, int slot) } void -sff_set_irq_line(sff8038i_t *dev, int irq_line) +sff_set_irq_line(sff8038i_t *dev, int pci_irq_line) { - dev->irq_line = irq_line; + dev->pci_irq_line = pci_irq_line; +} + +/* TODO: Why does this always set the level to 0, regardless of the parameter?! */ +void +sff_set_irq_level(sff8038i_t *dev, UNUSED(int irq_level)) +{ + dev->irq_level = 0; } void -sff_set_irq_level(sff8038i_t *dev, int channel, UNUSED(int irq_level)) +sff_set_irq_mode(sff8038i_t *dev, int irq_mode) { - dev->irq_level[channel] = 0; -} + dev->irq_mode = irq_mode; -void -sff_set_irq_mode(sff8038i_t *dev, int channel, int irq_mode) -{ - dev->irq_mode[channel] = irq_mode; - - switch (dev->irq_mode[channel]) { + switch (dev->irq_mode) { default: - case 0: + case IRQ_MODE_LEGACY: /* Legacy IRQ mode. */ - sff_log("[%08X] Setting channel %i to legacy IRQ %i\n", dev, channel, 14 + channel); + sff_log("[%08X] Setting IRQ mode to legacy IRQ %i\n", dev, 14 + channel); break; - case 1: + case IRQ_MODE_PCI_IRQ_PIN: /* Native PCI IRQ mode with interrupt pin. */ - sff_log("[%08X] Setting channel %i to native PCI INT%c\n", dev, channel, '@' + dev->irq_pin); + sff_log("[%08X] Setting IRQ mode to native PCI INT%c\n", dev, 0x40 + dev->irq_pin); break; - case 2: - case 5: + case IRQ_MODE_MIRQ_0: + case IRQ_MODE_MIRQ_1: /* MIRQ 0 or 1. */ - sff_log("[%08X] Setting channel %i to PCI MIRQ%i\n", dev, channel, irq_mode & 1); + sff_log("[%08X] Setting IRQ mode to PCI MIRQ%i\n", dev, irq_mode & 1); break; - case 3: + case IRQ_MODE_MIRQ_2: + case IRQ_MODE_MIRQ_3: + /* MIRQ 0 or 1. */ + sff_log("[%08X] Setting IRQ mode to PCI MIRQ%i\n", dev, (irq_mode & 1) + 1); + break; + case IRQ_MODE_PCI_IRQ_LINE: /* Native PCI IRQ mode with specified interrupt line. */ - sff_log("[%08X] Setting channel %i to native PCI IRQ %i\n", dev, channel, dev->irq_line); + sff_log("[%08X] Setting IRQ mode to native PCI IRQ %i\n", dev, dev->pci_irq_line); break; - case 4: + case IRQ_MODE_ALI_ALADDIN: /* ALi Aladdin Native PCI INTAJ mode. */ - sff_log("[%08X] Setting channel %i to INT%cJ\n", dev, channel, 'A' + channel); + sff_log("[%08X] Setting IRQ mode to INT%cJ\n", dev, 'A' + dev->channel); + break; + case IRQ_MODE_SIS_551X: + /* SiS 551x mode. */ + sff_log("[%08X] Setting IRQ mode to PCI MIRQ2\n", dev); break; } } @@ -566,13 +584,15 @@ sff_init(UNUSED(const device_t *info)) ide_set_bus_master(next_id, sff_bus_master_dma, sff_bus_master_set_irq, dev); dev->slot = 7; - dev->irq_mode[0] = 0; /* Channel 0 goes to IRQ 14. */ - dev->irq_mode[1] = 2; /* Channel 1 goes to MIRQ0. */ + /* Channel 0 goes to IRQ 14, channel 1 goes to MIRQ0. */ + dev->irq_mode = next_id ? IRQ_MODE_MIRQ_0 : IRQ_MODE_LEGACY; dev->irq_pin = PCI_INTA; - dev->irq_line = 14; - dev->irq_level[0] = dev->irq_level[1] = 0; + dev->irq_line = 14 + next_id; + dev->pci_irq_line = 14; + dev->irq_level = 0; dev->irq_state = 0; + dev->channel = next_id; next_id++; return dev; diff --git a/src/include/86box/device.h b/src/include/86box/device.h index a297abd1b..b2d7a05ed 100644 --- a/src/include/86box/device.h +++ b/src/include/86box/device.h @@ -86,6 +86,8 @@ enum { DEVICE_ONBOARD = 0x20000000, /* is on-board */ DEVICE_EXTPARAMS = 0x40000000, /* accepts extended parameters */ + DEVICE_PIT = 0x80000000, /* device is a PIT */ + DEVICE_ALL = 0xffffffff /* match all devices */ }; @@ -188,6 +190,7 @@ extern void device_cadd_inst_ex(const device_t *dev, const device_t *cd, void * extern void device_cadd_inst_ex_parameters(const device_t *dev, const device_t *cd, void *priv, int inst, void *params); extern void device_close_all(void); extern void device_reset_all(uint32_t match_flags); +extern void *device_find_first_priv(uint32_t match_flags); extern void *device_get_priv(const device_t *dev); extern int device_available(const device_t *dev); extern int device_poll(const device_t *dev); diff --git a/src/include/86box/hdc_ide.h b/src/include/86box/hdc_ide.h index 7ecb188e6..37b11da85 100644 --- a/src/include/86box/hdc_ide.h +++ b/src/include/86box/hdc_ide.h @@ -149,8 +149,8 @@ extern uint8_t ide_read_alt_status(uint16_t addr, void *priv); extern uint16_t ide_readw(uint16_t addr, void *priv); extern void ide_set_bus_master(int board, - int (*dma)(int channel, uint8_t *data, int transfer_length, int out, void *priv), - void (*set_irq)(int channel, void *priv), void *priv); + int (*dma)(uint8_t *data, int transfer_length, int out, void *priv), + void (*set_irq)(uint8_t status, void *priv), void *priv); extern void win_cdrom_eject(uint8_t id); extern void win_cdrom_reload(uint8_t id); @@ -180,10 +180,6 @@ extern void ide_set_board_callback(uint8_t board, double callback); extern void ide_padstr(char *str, const char *src, int len); extern void ide_padstr8(uint8_t *buf, int buf_size, const char *src); -extern int (*ide_bus_master_dma)(int channel, uint8_t *data, int transfer_length, int out, void *priv); -extern void (*ide_bus_master_set_irq)(int channel, void *priv); -extern void *ide_bus_master_priv[2]; - extern uint8_t ide_read_ali_75(void); extern uint8_t ide_read_ali_76(void); diff --git a/src/include/86box/hdc_ide_sff8038i.h b/src/include/86box/hdc_ide_sff8038i.h index f9c40e29a..2283497bb 100644 --- a/src/include/86box/hdc_ide_sff8038i.h +++ b/src/include/86box/hdc_ide_sff8038i.h @@ -20,52 +20,62 @@ #ifndef EMU_HDC_IDE_SFF8038I_H #define EMU_HDC_IDE_SFF8038I_H -typedef struct sff8038i_t { +enum +{ + IRQ_MODE_LEGACY = 0, + IRQ_MODE_PCI_IRQ_PIN, + IRQ_MODE_PCI_IRQ_LINE, + IRQ_MODE_ALI_ALADDIN, + IRQ_MODE_MIRQ_0, + IRQ_MODE_MIRQ_1, + IRQ_MODE_MIRQ_2, + IRQ_MODE_MIRQ_3, + IRQ_MODE_SIS_551X +}; + +typedef struct sff8038i_t +{ uint8_t command; uint8_t status; uint8_t ptr0; uint8_t enabled; uint8_t dma_mode; uint8_t irq_state; - uint8_t pad; - uint8_t pad0; + uint8_t channel; + uint8_t irq_line; uint16_t base; - uint16_t pad1; + uint16_t pad; uint32_t ptr; uint32_t ptr_cur; uint32_t addr; int count; int eot; int slot; - int irq_mode[2]; - int irq_level[2]; + int irq_mode; + int irq_level; int irq_pin; - int irq_line; + int pci_irq_line; } sff8038i_t; extern const device_t sff8038i_device; extern void sff_bus_master_handler(sff8038i_t *dev, int enabled, uint16_t base); -extern int sff_bus_master_dma_read(int channel, uint8_t *data, int transfer_length, void *priv); -extern int sff_bus_master_dma_write(int channel, uint8_t *data, int transfer_length, void *priv); - -extern void sff_bus_master_set_irq(int channel, void *priv); - -extern int sff_bus_master_dma(int channel, uint8_t *data, int transfer_length, int out, void *priv); +extern void sff_bus_master_set_irq(uint8_t status, void *priv); +extern int sff_bus_master_dma(uint8_t *data, int transfer_length, int out, void *priv); extern void sff_bus_master_write(uint16_t port, uint8_t val, void *priv); extern uint8_t sff_bus_master_read(uint16_t port, void *priv); -extern void sff_bus_master_reset(sff8038i_t *dev, uint16_t old_base); +extern void sff_bus_master_reset(sff8038i_t *dev); extern void sff_set_slot(sff8038i_t *dev, int slot); extern void sff_set_irq_line(sff8038i_t *dev, int irq_line); -extern void sff_set_irq_mode(sff8038i_t *dev, int channel, int irq_mode); +extern void sff_set_irq_mode(sff8038i_t *dev, int irq_mode); extern void sff_set_irq_pin(sff8038i_t *dev, int irq_pin); -extern void sff_set_irq_level(sff8038i_t *dev, int channel, int irq_level); +extern void sff_set_irq_level(sff8038i_t *dev, int irq_level); #endif /*EMU_HDC_IDE_SFF8038I_H*/ diff --git a/src/include/86box/pci.h b/src/include/86box/pci.h index c5ddfe4df..17f9f6687 100644 --- a/src/include/86box/pci.h +++ b/src/include/86box/pci.h @@ -147,10 +147,14 @@ #define pci_set_mirq(mirq, level, irq_state) \ pci_irq(PCI_MIRQ_BASE | (mirq), 0, level, 1, irq_state) +#define pci_set_dirq(irq, irq_state) \ + pci_irq(PCI_DIRQ_BASE | (irq), 0, 1, 1, irq_state) #define pci_set_irq(slot, pci_int, irq_state) \ pci_irq(slot, pci_int, 0, 1, irq_state) #define pci_clear_mirq(mirq, level, irq_state) \ pci_irq(PCI_MIRQ_BASE | (mirq), 0, level, 0, irq_state) +#define pci_clear_dirq(dirq, irq_state) \ + pci_irq(PCI_DIRQ_BASE | (irq), 0, 1, 0, irq_state) #define pci_clear_irq(slot, pci_int, irq_state) \ pci_irq(slot, pci_int, 0, 0, irq_state) @@ -216,7 +220,9 @@ extern uint32_t pci_size; extern void pci_set_irq_routing(int pci_int, int irq); extern void pci_set_irq_level(int pci_int, int level); extern void pci_enable_mirq(int mirq); -extern void pci_set_mirq_routing(int mirq, int irq); +extern void pci_set_mirq_routing(int mirq, uint8_t irq); +extern uint8_t pci_get_mirq_level(int mirq); +extern void pci_set_mirq_level(int mirq, uint8_t irq); /* PCI raise IRQ: the first parameter is slot if < PCI_MIRQ_BASE, MIRQ if >= PCI_MIRQ_BASE and < PCI_DIRQ_BASE, and direct IRQ line if >= PCI_DIRQ_BASE (RichardG's diff --git a/src/include/86box/pic.h b/src/include/86box/pic.h index a66e511b8..798cc3357 100644 --- a/src/include/86box/pic.h +++ b/src/include/86box/pic.h @@ -81,9 +81,11 @@ extern void pic_init_pcjr(void); extern void pic2_init(void); extern void pic_reset(void); -extern int picint_is_level(int irq); -extern void picint_common(uint16_t num, int level, int set, uint8_t *irq_state); -extern int picinterrupt(void); +extern uint8_t pic_read_icw(uint8_t pic_id, uint8_t icw); +extern uint8_t pic_read_ocw(uint8_t pic_id, uint8_t ocw); +extern int picint_is_level(int irq); +extern void picint_common(uint16_t num, int level, int set, uint8_t *irq_state); +extern int picinterrupt(void); #define PIC_IRQ_EDGE 0 #define PIC_IRQ_LEVEL 1 diff --git a/src/include/86box/pit.h b/src/include/86box/pit.h index af9142625..d288b7e6c 100644 --- a/src/include/86box/pit.h +++ b/src/include/86box/pit.h @@ -131,6 +131,8 @@ extern void pit_nmi_timer_ps2(int new_out, int old_out); extern void pit_set_clock(uint32_t clock); extern void pit_handler(int set, uint16_t base, int size, void *priv); +extern uint8_t pit_read_reg(void *priv, uint8_t reg); + #ifdef EMU_DEVICE_H extern const device_t i8253_device; extern const device_t i8254_device; diff --git a/src/include/86box/pit_fast.h b/src/include/86box/pit_fast.h index a7caeabe7..2485a360c 100644 --- a/src/include/86box/pit_fast.h +++ b/src/include/86box/pit_fast.h @@ -69,6 +69,8 @@ typedef struct pitf_t { uint8_t ctrl; } pitf_t; +extern uint8_t pitf_read_reg(void *priv, uint8_t reg); + extern const pit_intf_t pit_fast_intf; #ifdef EMU_DEVICE_H diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c index 06974a96d..d7e1eb025 100644 --- a/src/machine/m_at_socket7_3v.c +++ b/src/machine/m_at_socket7_3v.c @@ -716,18 +716,18 @@ machine_at_ap5s_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init(model); + 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(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 4, 2, 1); - pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 3, 2, 1); + pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); device_add(&sis_5511_device); - device_add(&keyboard_ps2_ami_pci_device); + device_add(&keyboard_ps2_ami_device); device_add(&fdc37c665_device); device_add(&sst_flash_29ee010_device); @@ -745,18 +745,18 @@ machine_at_ms5124_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init(model); + 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(0x01, PCI_CARD_SOUTHBRIDGE, 0xFE, 0xFF, 0, 0); - pci_register_slot(0x10, PCI_CARD_NORMAL, 0x41, 0x42, 0x43, 0x44); - pci_register_slot(0x11, PCI_CARD_NORMAL, 0x44, 0x41, 0x42, 0x43); - pci_register_slot(0x12, PCI_CARD_NORMAL, 0x43, 0x44, 0x41, 0x42); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 0x42, 0x43, 0x44, 0x41); + pci_register_slot(0x10, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); device_add(&sis_5511_device); - device_add(&keyboard_ps2_ami_pci_device); + device_add(&keyboard_ps2_ami_device); device_add(&w83787f_device); device_add(&sst_flash_29ee010_device); diff --git a/src/mem/spd.c b/src/mem/spd.c index cbc9ac2b7..b2d0f7f16 100644 --- a/src/mem/spd.c +++ b/src/mem/spd.c @@ -349,9 +349,12 @@ spd_write_drbs(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit uint8_t dimm; uint8_t drb; uint8_t apollo = 0; + uint8_t two_step = !!(drb_unit & 0x80); uint16_t size; uint16_t rows[SPD_MAX_SLOTS]; + drb_unit &= 0x7f; + /* Special case for VIA Apollo Pro family, which jumps from 5F to 56. */ if (reg_max < reg_min) { apollo = reg_max; @@ -384,7 +387,10 @@ spd_write_drbs(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit } /* Determine the DRB register to write. */ - drb = reg_min + row; + if (two_step) + drb = reg_min + row; + else + drb = reg_min + (row << 1); if (apollo && ((drb & 0xf) < 0xa)) drb = apollo + (drb & 0xf); diff --git a/src/pci.c b/src/pci.c index 2220d24f4..7c61545b2 100644 --- a/src/pci.c +++ b/src/pci.c @@ -56,6 +56,8 @@ typedef struct pci_card_desc_t { typedef struct pci_mirq_t { uint8_t enabled; uint8_t irq_line; + uint8_t irq_level; + uint8_t pad; } pci_mirq_t; int pci_burst_time; @@ -131,11 +133,23 @@ pci_enable_mirq(int mirq) } void -pci_set_mirq_routing(int mirq, int irq) +pci_set_mirq_routing(int mirq, uint8_t irq) { pci_mirqs[mirq].irq_line = irq; } +uint8_t +pci_get_mirq_level(int mirq) +{ + return pci_mirqs[mirq].irq_level; +} + +void +pci_set_mirq_level(int mirq, uint8_t level) +{ + pci_mirqs[mirq].irq_level = level; +} + /* PCI raise IRQ: the first parameter is slot if < PCI_MIRQ_BASE, MIRQ if >= PCI_MIRQ_BASE and < PCI_DIRQ_BASE, and direct IRQ line if >= PCI_DIRQ_BASE (RichardG's hack that may no longer be needed). */ diff --git a/src/pic.c b/src/pic.c index 2e59dda10..82905261a 100644 --- a/src/pic.c +++ b/src/pic.c @@ -408,6 +408,48 @@ pic_latch_read(UNUSED(uint16_t addr), UNUSED(void *priv)) return ret; } +uint8_t +pic_read_icw(uint8_t pic_id, uint8_t icw) +{ + pic_t *dev = pic_id ? &pic2 : &pic; + uint8_t ret = 0xff; + + switch (icw) { + case 0x00: + ret = dev->icw1; + break; + case 0x01: + ret = dev->icw2; + break; + case 0x02: + ret = dev->icw3; + break; + case 0x03: + ret = dev->icw4; + break; + } + + return ret; +} + +uint8_t +pic_read_ocw(uint8_t pic_id, uint8_t ocw) +{ + pic_t *dev = pic_id ? &pic2 : &pic; + uint8_t ret = 0xff; + + switch (ocw) { + case 0x00: + ret = dev->ocw2; + break; + case 0x01: + ret = dev->ocw3; + break; + } + + return ret; +} + uint8_t pic_read(uint16_t addr, void *priv) { diff --git a/src/pit.c b/src/pit.c index fc65839a3..f5816aaf5 100644 --- a/src/pit.c +++ b/src/pit.c @@ -637,6 +637,41 @@ pit_write(uint16_t addr, uint8_t val, void *priv) extern uint8_t *ram; +uint8_t +pit_read_reg(void *priv, uint8_t reg) +{ + pit_t *dev = (pit_t *) priv; + uint8_t ret = 0xff; + + switch (reg) { + case 0x00: + case 0x02: + case 0x04: + ret = dev->counters[reg >> 1].l & 0xff; + break; + case 0x01: + case 0x03: + case 0x05: + ret = (dev->counters[reg >> 1].l >> 8) & 0xff; + break; + case 0x06: + ret = dev->ctrl; + break; + case 0x07: + /* The SiS 551x datasheet is unclear about how exactly + this register is structured. */ + ret = (dev->counters[0].rm & 0x80) ? 0x01 : 0x00; + ret = (dev->counters[0].wm & 0x80) ? 0x02 : 0x00; + ret = (dev->counters[1].rm & 0x80) ? 0x04 : 0x00; + ret = (dev->counters[1].wm & 0x80) ? 0x08 : 0x00; + ret = (dev->counters[2].rm & 0x80) ? 0x10 : 0x00; + ret = (dev->counters[2].wm & 0x80) ? 0x20 : 0x00; + break; + } + + return ret; +} + static uint8_t pit_read(uint16_t addr, void *priv) { @@ -852,7 +887,7 @@ pit_init(const device_t *info) const device_t i8253_device = { .name = "Intel 8253/8253-5 Programmable Interval Timer", .internal_name = "i8253", - .flags = DEVICE_ISA, + .flags = DEVICE_ISA | DEVICE_PIT, .local = PIT_8253, .init = pit_init, .close = pit_close, @@ -866,7 +901,7 @@ const device_t i8253_device = { const device_t i8254_device = { .name = "Intel 8254 Programmable Interval Timer", .internal_name = "i8254", - .flags = DEVICE_ISA, + .flags = DEVICE_ISA | DEVICE_PIT, .local = PIT_8254, .init = pit_init, .close = pit_close, @@ -1126,4 +1161,4 @@ const pit_intf_t pit_classic_intf = { &pit_ctr_set_load_func, &ctr_clock, NULL, -}; \ No newline at end of file +}; diff --git a/src/pit_fast.c b/src/pit_fast.c index 80e359eee..20633de80 100644 --- a/src/pit_fast.c +++ b/src/pit_fast.c @@ -498,6 +498,41 @@ pitf_write(uint16_t addr, uint8_t val, void *priv) } } +uint8_t +pitf_read_reg(void *priv, uint8_t reg) +{ + pitf_t *dev = (pitf_t *) priv; + uint8_t ret = 0xff; + + switch (reg) { + case 0x00: + case 0x02: + case 0x04: + ret = dev->counters[reg >> 1].l & 0xff; + break; + case 0x01: + case 0x03: + case 0x05: + ret = (dev->counters[reg >> 1].l >> 8) & 0xff; + break; + case 0x06: + ret = dev->ctrl; + break; + case 0x07: + /* The SiS 551x datasheet is unclear about how exactly + this register is structured. */ + ret = (dev->counters[0].rm & 0x80) ? 0x01 : 0x00; + ret = (dev->counters[0].wm & 0x80) ? 0x02 : 0x00; + ret = (dev->counters[1].rm & 0x80) ? 0x04 : 0x00; + ret = (dev->counters[1].wm & 0x80) ? 0x08 : 0x00; + ret = (dev->counters[2].rm & 0x80) ? 0x10 : 0x00; + ret = (dev->counters[2].wm & 0x80) ? 0x20 : 0x00; + break; + } + + return ret; +} + static uint8_t pitf_read(uint16_t addr, void *priv) { @@ -654,7 +689,7 @@ pitf_init(const device_t *info) const device_t i8253_fast_device = { .name = "Intel 8253/8253-5 Programmable Interval Timer", .internal_name = "i8253_fast", - .flags = DEVICE_ISA, + .flags = DEVICE_ISA | DEVICE_PIT, .local = PIT_8253, .init = pitf_init, .close = pitf_close, @@ -668,7 +703,7 @@ const device_t i8253_fast_device = { const device_t i8254_fast_device = { .name = "Intel 8254 Programmable Interval Timer", .internal_name = "i8254_fast", - .flags = DEVICE_ISA, + .flags = DEVICE_ISA | DEVICE_PIT, .local = PIT_8254, .init = pitf_init, .close = pitf_close, @@ -731,4 +766,4 @@ const pit_intf_t pit_fast_intf = { &pitf_ctr_set_load_func, &pitf_ctr_clock, NULL, -}; \ No newline at end of file +};