Better ACPI implementation (currently only on PIIX4/PIIX4E/SMSC southbridges), finished the SMSC southbridge (but the Atrend BIOS still hangs, need to figure out why), and fixed Tandy EEPROM saving.

This commit is contained in:
OBattler
2020-04-13 20:01:47 +02:00
parent 0045874d71
commit 61f0ae7954
17 changed files with 472 additions and 331 deletions

View File

@@ -1101,8 +1101,6 @@ i4x0_reset(void *priv)
for (i = 0; i <= dev->max_func; i++) for (i = 0; i <= dev->max_func; i++)
memset(dev->regs_locked[i], 0x00, 256 * sizeof(uint8_t)); memset(dev->regs_locked[i], 0x00, 256 * sizeof(uint8_t));
} }
// smbase = 0xa0000;
} }
@@ -1315,8 +1313,6 @@ static void
i4x0_write(regs[0x5f], 0x5f, 0x00, dev); i4x0_write(regs[0x5f], 0x5f, 0x00, dev);
i4x0_write(regs[0x72], 0x72, 0x00, dev); i4x0_write(regs[0x72], 0x72, 0x00, dev);
// smbase = 0xa0000;
if (((dev->type == INTEL_440BX) || (dev->type == INTEL_440ZX)) && (dev->max_func == 1)) { if (((dev->type == INTEL_440BX) || (dev->type == INTEL_440ZX)) && (dev->max_func == 1)) {
regs = (uint8_t *) dev->regs[1]; regs = (uint8_t *) dev->regs[1];

View File

@@ -1077,6 +1077,9 @@ enter_smm(int in_hlt)
smm_in_hlt = in_hlt; smm_in_hlt = in_hlt;
CPU_BLOCK_END(); CPU_BLOCK_END();
// if (smbase == 0x000a0000)
// leave_smm();
} }
@@ -1132,6 +1135,10 @@ leave_smm(void)
else if (is_p6) /* Intel P6 (Pentium Pro, Pentium II, Celeron) */ else if (is_p6) /* Intel P6 (Pentium Pro, Pentium II, Celeron) */
smram_restore_state_p6(saved_state); smram_restore_state_p6(saved_state);
/* Maybe we need this? */
if (smbase == 0x00030000)
smbase = 0x000a0000;
in_smm = 0; in_smm = 0;
mem_mapping_recalc(0x00030000, 0x00020000); mem_mapping_recalc(0x00030000, 0x00020000);
mem_mapping_recalc(0x000a0000, 0x00060000); mem_mapping_recalc(0x000a0000, 0x00060000);

View File

@@ -2202,9 +2202,15 @@ cpu_CPUID(void)
EAX = CPUID; EAX = CPUID;
EBX = ECX = 0; EBX = ECX = 0;
EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_CMPXCHG8B | CPUID_MTRR/* | CPUID_SEP*/ | CPUID_CMOV; EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_CMPXCHG8B | CPUID_MTRR/* | CPUID_SEP*/ | CPUID_CMOV;
#ifdef USE_SEP
EDX |= CPUID_SEP;
#endif
} }
else if (EAX == 2) else if (EAX == 2)
{ {
EAX = 0x00000001;
EBX = ECX = 0;
EDX = 0x00000000;
} }
else else
EAX = EBX = ECX = EDX = 0; EAX = EBX = ECX = EDX = 0;
@@ -2223,12 +2229,15 @@ cpu_CPUID(void)
EAX = CPUID; EAX = CPUID;
EBX = ECX = 0; EBX = ECX = 0;
EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_MTRR/* | CPUID_SEP*/ | CPUID_CMOV; EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_MTRR/* | CPUID_SEP*/ | CPUID_CMOV;
#ifdef USE_SEP
EDX |= CPUID_SEP;
#endif
} }
else if (EAX == 2) else if (EAX == 2)
{ {
EAX = 0x03020101; EAX = 0x00000001;
EBX = ECX = 0; EBX = ECX = 0;
EDX = 0x0C040843; EDX = 0x00000000;
} }
else else
EAX = EBX = ECX = EDX = 0; EAX = EBX = ECX = EDX = 0;
@@ -2247,12 +2256,15 @@ cpu_CPUID(void)
EAX = CPUID; EAX = CPUID;
EBX = ECX = 0; EBX = ECX = 0;
EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_MTRR/* | CPUID_SEP*/ | CPUID_FXSR | CPUID_CMOV; EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_MTRR/* | CPUID_SEP*/ | CPUID_FXSR | CPUID_CMOV;
#ifdef USE_SEP
EDX |= CPUID_SEP;
#endif
} }
else if (EAX == 2) else if (EAX == 2)
{ {
EAX = 0x03020101; EAX = 0x00000001;
EBX = ECX = 0; EBX = ECX = 0;
EDX = 0x0C040844; EDX = 0x00000000;
} }
else else
EAX = EBX = ECX = EDX = 0; EAX = EBX = ECX = EDX = 0;

View File

@@ -374,17 +374,21 @@ sff_bus_master_set_irq(int channel, void *priv)
channel &= 0x01; channel &= 0x01;
if (dev->status & 0x04) { if (dev->status & 0x04) {
sff_log("SFF8038i: Channel %i IRQ raise\n", channel); sff_log("SFF8038i: Channel %i IRQ raise\n", channel);
if ((dev->irq_mode == 2) && channel && pci_use_mirq(0)) if (dev->irq_mode[channel] == 3)
picintlevel(1 << dev->irq_line);
else if ((dev->irq_mode[channel] == 2) && channel && pci_use_mirq(0))
pci_set_mirq(0, 0); pci_set_mirq(0, 0);
else if (dev->irq_mode == 1) else if (dev->irq_mode[channel] == 1)
pci_set_irq(dev->slot, dev->irq_pin); pci_set_irq(dev->slot, dev->irq_pin);
else else
picint(1 << (14 + channel)); picint(1 << (14 + channel));
} else { } else {
sff_log("SFF8038i: Channel %i IRQ lower\n", channel); sff_log("SFF8038i: Channel %i IRQ lower\n", channel);
if ((dev->irq_mode == 2) && channel && pci_use_mirq(0)) if (dev->irq_mode[channel] == 3)
picintc(1 << dev->irq_line);
else if ((dev->irq_mode[channel] == 2) && channel && pci_use_mirq(0))
pci_clear_mirq(0, 0); pci_clear_mirq(0, 0);
else if (dev->irq_mode == 1) else if (dev->irq_mode[channel] == 1)
pci_clear_irq(dev->slot, dev->irq_pin); pci_clear_irq(dev->slot, dev->irq_pin);
else else
picintc(1 << (14 + channel)); picintc(1 << (14 + channel));
@@ -449,9 +453,16 @@ sff_set_slot(sff8038i_t *dev, int slot)
void void
sff_set_irq_mode(sff8038i_t *dev, int irq_mode) sff_set_irq_line(sff8038i_t *dev, int irq_line)
{ {
dev->irq_mode = irq_mode; dev->irq_line = irq_line;
}
void
sff_set_irq_mode(sff8038i_t *dev, int channel, int irq_mode)
{
dev->irq_mode[channel] = irq_mode;
} }
@@ -488,8 +499,9 @@ static void
ide_set_bus_master(next_id, sff_bus_master_dma, sff_bus_master_set_irq, dev); ide_set_bus_master(next_id, sff_bus_master_dma, sff_bus_master_set_irq, dev);
dev->slot = 7; dev->slot = 7;
dev->irq_mode = 2; dev->irq_mode[0] = dev->irq_mode[1] = 2;
dev->irq_pin = PCI_INTA; dev->irq_pin = PCI_INTA;
dev->irq_line = 14;
next_id++; next_id++;

View File

@@ -25,7 +25,8 @@ typedef struct
addr; addr;
int count, eot, int count, eot,
slot, slot,
irq_mode, irq_pin; irq_mode[2], irq_pin,
irq_line;
} sff8038i_t; } sff8038i_t;
@@ -42,5 +43,7 @@ extern void sff_bus_master_reset(sff8038i_t *dev, uint16_t old_base);
extern void sff_set_slot(sff8038i_t *dev, int slot); extern void sff_set_slot(sff8038i_t *dev, int slot);
extern void sff_set_irq_mode(sff8038i_t *dev, int irq_mode); 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_pin(sff8038i_t *dev, int irq_pin); extern void sff_set_irq_pin(sff8038i_t *dev, int irq_pin);

View File

@@ -112,6 +112,7 @@ extern int nvr_get_days(int month, int year);
extern void nvr_time_get(struct tm *); extern void nvr_time_get(struct tm *);
extern void nvr_time_set(struct tm *); extern void nvr_time_set(struct tm *);
extern void nvr_reg_write(uint16_t reg, uint8_t val, void *priv);
extern void nvr_at_handler(int set, uint16_t base, nvr_t *nvr); extern void nvr_at_handler(int set, uint16_t base, nvr_t *nvr);
extern void nvr_at_sec_handler(int set, uint16_t base, nvr_t *nvr); extern void nvr_at_sec_handler(int set, uint16_t base, nvr_t *nvr);
extern void nvr_wp_set(int set, int h, nvr_t *nvr); extern void nvr_wp_set(int set, int h, nvr_t *nvr);

View File

@@ -57,7 +57,7 @@ extern uint64_t PITCONST, ISACONST,
HERCCONST, HERCCONST,
VGACONST1, VGACONST1,
VGACONST2, VGACONST2,
RTCCONST; RTCCONST, ACPICONST;
/* Gets a counter's count. */ /* Gets a counter's count. */

View File

@@ -39,6 +39,7 @@
#include <86box/mem.h> #include <86box/mem.h>
#include <86box/timer.h> #include <86box/timer.h>
#include <86box/nvr.h> #include <86box/nvr.h>
#include <86box/acpi.h>
#include <86box/pci.h> #include <86box/pci.h>
#include <86box/pic.h> #include <86box/pic.h>
#include <86box/port_92.h> #include <86box/port_92.h>
@@ -51,24 +52,6 @@
#include <86box/piix.h> #include <86box/piix.h>
#define ACPI_TIMER_FREQ 3579545
#define PM_FREQ ACPI_TIMER_FREQ
#define RSM_STS (1 << 15)
#define PWRBTN_STS (1 << 8)
#define RTC_EN (1 << 10)
#define PWRBTN_EN (1 << 8)
#define GBL_EN (1 << 5)
#define TMROF_EN (1 << 0)
#define SCI_EN (1 << 0)
#define SUS_EN (1 << 13)
#define ACPI_ENABLE 0xf1
#define ACPI_DISABLE 0xf0
typedef struct typedef struct
{ {
uint16_t io_base; uint16_t io_base;
@@ -76,17 +59,6 @@ typedef struct
} ddma_t; } ddma_t;
typedef struct
{
uint8_t gpireg[3], gporeg[4];
uint16_t pmsts, pmen,
pmcntrl;
uint32_t glbctl;
uint64_t tmr_overflow_time;
int timer_index;
} power_t;
typedef struct typedef struct
{ {
uint8_t cur_readout_reg, rev, uint8_t cur_readout_reg, rev,
@@ -96,15 +68,16 @@ typedef struct
readout_regs[256], board_config[2]; readout_regs[256], board_config[2];
uint16_t func0_id, uint16_t func0_id,
nvr_io_base, nvr_io_base,
usb_io_base, power_io_base; usb_io_base, acpi_io_base;
uint8_t *usb_smsc_mmio; uint8_t *usb_smsc_mmio;
mem_mapping_t *usb_smsc_mmio_mapping; mem_mapping_t usb_smsc_mmio_mapping;
sff8038i_t *bm[2]; sff8038i_t *bm[2];
ddma_t ddma[2]; ddma_t ddma[2];
power_t power;
smbus_piix4_t * smbus; smbus_piix4_t * smbus;
apm_t * apm; apm_t * apm;
nvr_t * nvr; nvr_t * nvr;
acpi_t * acpi;
port_92_t * port_92;
} piix_t; } piix_t;
@@ -128,28 +101,88 @@ piix_log(const char *fmt, ...)
#endif #endif
static static void
void do_irq(piix_t *dev, int func, int level) smsc_ide_handlers(piix_t *dev)
{ {
if ((dev == NULL) || (func > dev->max_func) /*|| uint16_t main, side;
(dev->regs[func][0x3d] < PCI_INTA) || (dev->regs[func][0x3d] < PCI_INTD)*/)
return;
if (level) { ide_pri_disable();
#ifdef WRONG_SPEC ide_sec_disable();
pci_set_irq(dev->pci_slot, dev->regs[func][0x3d]);
#else if (dev->regs[1][0x09] & 0x01) {
picintlevel(1 << 9); main = (dev->regs[1][0x11] << 8) | (dev->regs[1][0x10] & 0xf8);
#endif side = ((dev->regs[1][0x15] << 8) | (dev->regs[1][0x14] & 0xfc)) + 2;
piix_log("Raising IRQ...\n");
} else { } else {
#ifdef WRONG_SPEC main = 0x1f0;
pci_clear_irq(dev->pci_slot, dev->regs[func][0x3d]); side = 0x3f6;
#else
picintc(1 << 9);
#endif
piix_log("Lowering IRQ...\n");
} }
ide_set_base(0, main);
ide_set_side(0, side);
if (dev->regs[1][0x09] & 0x04) {
main = (dev->regs[1][0x19] << 8) | (dev->regs[1][0x18] & 0xf8);
side = ((dev->regs[1][0x1d] << 8) | (dev->regs[1][0x1c] & 0xfc)) + 2;
} else {
main = 0x170;
side = 0x376;
}
ide_set_base(1, main);
ide_set_side(1, side);
if (dev->regs[1][0x04] & PCI_COMMAND_IO) {
if (dev->regs[1][0x41] & 0x80)
ide_pri_enable();
if (dev->regs[1][0x43] & 0x80)
ide_sec_enable();
}
}
static void
smsc_ide_irqs(piix_t *dev)
{
int irq_line = 3, irq_mode[2] = { 0, 0 };
if (dev->regs[1][0x09] & 0x01)
irq_mode[0] = (dev->regs[0][0xe0] & 0x01) ? 3 : 1;
if (dev->regs[1][0x09] & 0x04)
irq_mode[1] = (dev->regs[0][0xe0] & 0x01) ? 3 : 1;
switch ((dev->regs[0][0xe0] >> 1) & 0x07) {
case 0x00:
irq_line = 3;
break;
case 0x01:
irq_line = 5;
break;
case 0x02:
irq_line = 7;
break;
case 0x03:
irq_line = 8;
break;
case 0x04:
irq_line = 11;
break;
case 0x05:
irq_line = 12;
break;
case 0x06:
irq_line = 14;
break;
case 0x07:
irq_line = 15;
break;
}
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_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]);
} }
@@ -356,23 +389,14 @@ usb_update_io_mapping(piix_t *dev)
static void static void
usb_smsc_update_mem_mapping(piix_t *dev) usb_smsc_update_mem_mapping(piix_t *dev)
{ {
uint8_t *fregs;
uint32_t usb_bar; uint32_t usb_bar;
if (!dev->usb_smsc_mmio_mapping) mem_mapping_disable(&dev->usb_smsc_mmio_mapping);
return;
mem_mapping_disable(dev->usb_smsc_mmio_mapping); usb_bar = ((dev->regs[2][0x11] << 8) | (dev->regs[2][0x12] << 16) | (dev->regs[2][0x13] << 24)) & 0xfffff000;
if (!dev->usb_smsc_mmio) if ((dev->regs[2][0x04] & 0x02) && (usb_bar != 0x00000000))
return; mem_mapping_set_addr(&dev->usb_smsc_mmio_mapping, usb_bar, 0x1000);
fregs = (uint8_t *) dev->regs[2];
usb_bar = fregs[0x10] | (fregs[0x11] << 8) | (fregs[0x12] << 16) | (fregs[0x13] << 24);
piix_log("smsc usb bar %08x\n", usb_bar);
if ((usb_bar != 0x00000000) && (usb_bar < 0xFF000000))
mem_mapping_set_addr(dev->usb_smsc_mmio_mapping, usb_bar, 0x1000);
} }
@@ -380,10 +404,12 @@ static uint8_t
usb_smsc_mmio_read(uint32_t addr, void *p) usb_smsc_mmio_read(uint32_t addr, void *p)
{ {
piix_t *dev = (piix_t *) p; piix_t *dev = (piix_t *) p;
uint8_t ret; uint8_t ret = 0x00;
ret = dev->usb_smsc_mmio[addr & 0xFFF];
/* addr &= 0x00000fff;
ret = dev->usb_smsc_mmio[addr]; */
piix_log("usb_smsc_mmio_read(%08x) = %02x\n", addr, ret);
return ret; return ret;
} }
@@ -393,127 +419,22 @@ usb_smsc_mmio_write(uint32_t addr, uint8_t val, void *p)
{ {
piix_t *dev = (piix_t *) p; piix_t *dev = (piix_t *) p;
switch (addr & 0xFFF) { addr &= 0x00000fff;
switch (addr) {
case 0x08: /* HCCOMMANDSTATUS */ case 0x08: /* HCCOMMANDSTATUS */
/* bit HostControllerReset must be cleared for the controller to be seen as initialized */ /* bit HostControllerReset must be cleared for the controller to be seen as initialized */
val = val & ~(0x01); val &= ~0x01;
/* bit OwnershipChangeRequest triggers an ownership change (SMM <-> OS) */ /* bit OwnershipChangeRequest triggers an ownership change (SMM <-> OS) */
if (val & 0x0F) { if (val & 0x0f) {
dev->usb_smsc_mmio[0x0F] = 0x40; dev->usb_smsc_mmio[0x0f] = 0x40;
dev->usb_smsc_mmio[0x05] &= ~(dev->usb_smsc_mmio[0x05] & 0x01); dev->usb_smsc_mmio[0x05] &= ~(dev->usb_smsc_mmio[0x05] & 0x01);
} }
break; break;
} }
dev->usb_smsc_mmio[addr & 0xFFF] = val; dev->usb_smsc_mmio[addr] = val;
piix_log("usb_smsc_mmio_write(%08x, %02x)\n", addr, val);
}
static uint32_t
power_reg_readl(uint16_t addr, void *p)
{
piix_t *dev = (piix_t *) p;
uint32_t timer;
uint32_t ret = 0xffffffff;
switch (addr & 0x3c) {
case 0x08:
/* ACPI timer */
timer = (tsc * ACPI_TIMER_FREQ) / machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed;
timer &= 0x00ffffff;
ret = timer;
break;
}
piix_log("ACPI: Read L %08X from %04X\n", ret, addr);
return ret;
}
static uint16_t
power_reg_readw(uint16_t addr, void *p)
{
piix_t *dev = (piix_t *) p;
uint16_t ret = 0xffff;
uint32_t ret32;
switch (addr & 0x3c) {
case 0x00:
break;
default:
ret32 = power_reg_readl(addr, p);
if (addr & 0x02)
ret = (ret32 >> 16) & 0xffff;
else
ret = ret32 & 0xffff;
break;
}
piix_log("ACPI: Read W %08X from %04X\n", ret, addr);
return ret;
}
static uint8_t
power_reg_read(uint16_t addr, void *p)
{
piix_t *dev = (piix_t *) p;
uint32_t timer;
uint8_t ret = 0xff;
uint16_t ret16;
switch (addr & 0x3f) {
case 0x30: case 0x31: case 0x32:
ret = dev->power.gporeg[addr & 0x03];
piix_log("ACPI: Read B %02X from GPIREG %01X\n", ret, addr & 0x03);
break;
case 0x34: case 0x35: case 0x36: case 0x37:
ret = dev->power.gporeg[addr & 0x03];
piix_log("ACPI: Read B %02X from GPOREG %01X\n", ret, addr & 0x03);
break;
default:
ret16 = power_reg_readw(addr, p);
if (addr & 0x01)
ret = (ret16 >> 8) & 0xff;
else
ret = ret16 & 0xff;
break;
}
return ret;
}
static void
power_reg_write(uint16_t addr, uint8_t val, void *p)
{
piix_t *dev = (piix_t *) p;
piix_log("ACPI: Write %02X to %04X\n", val, addr);
switch (addr & 0x3f) {
case 0x34: case 0x35: case 0x36: case 0x37:
dev->power.gporeg[addr & 0x03] = val;
break;
}
}
static void
power_update_io_mapping(piix_t *dev)
{
if (dev->power_io_base != 0x0000)
io_removehandler(dev->power_io_base, 0x40, power_reg_read, NULL, NULL, power_reg_write, NULL, NULL, dev);
dev->power_io_base = (dev->regs[3][0x41] << 8) | (dev->regs[3][0x40] & 0xc0);
if ((dev->regs[3][0x80] & 0x01) && (dev->power_io_base != 0x0000))
io_sethandler(dev->power_io_base, 0x40, power_reg_read, NULL, NULL, power_reg_write, NULL, NULL, dev);
} }
@@ -527,24 +448,29 @@ smbus_update_io_mapping(piix_t *dev)
static void static void
nvr_update_io_mapping(piix_t *dev) nvr_update_io_mapping(piix_t *dev)
{ {
int enabled2 = 1;
if (dev->nvr_io_base != 0x0000) { if (dev->nvr_io_base != 0x0000) {
nvr_at_handler(0, dev->nvr_io_base, dev->nvr); nvr_at_handler(0, dev->nvr_io_base, dev->nvr);
nvr_at_handler(0, dev->nvr_io_base + 0x0002, dev->nvr); nvr_at_handler(0, dev->nvr_io_base + 0x0002, dev->nvr);
nvr_at_handler(0, dev->nvr_io_base + 0x0004, dev->nvr); nvr_at_handler(0, dev->nvr_io_base + 0x0004, dev->nvr);
nvr_at_handler(0, dev->nvr_io_base + 0x0006, dev->nvr);
} }
if (dev->type == 5) if (dev->type == 5)
dev->power_io_base = (dev->regs[0][0xd5] << 8) | (dev->regs[3][0xd4] & 0xf0); dev->nvr_io_base = (dev->regs[0][0xd5] << 8) | (dev->regs[0][0xd4] & 0xf0);
else else
dev->power_io_base = 0x70; dev->nvr_io_base = 0x70;
pclog("New NVR I/O base: %04X\n", dev->nvr_io_base);
if ((dev->regs[0][0xcb] & 0x01) && (dev->regs[2][0xff] & 0x10)) /* if (dev->type == 4)
enabled2 = (dev->regs[2][0xff] & 0x10); */
if ((dev->regs[0][0xcb] & 0x01) && enabled2) {
nvr_at_handler(1, dev->nvr_io_base, dev->nvr); nvr_at_handler(1, dev->nvr_io_base, dev->nvr);
nvr_at_handler(1, dev->nvr_io_base + 0x0004, dev->nvr);
}
if (dev->regs[0][0xcb] & 0x04) if (dev->regs[0][0xcb] & 0x04)
nvr_at_handler(1, dev->nvr_io_base + 0x0002, dev->nvr); nvr_at_handler(1, dev->nvr_io_base + 0x0002, dev->nvr);
nvr_at_handler(1, dev->nvr_io_base + 0x0004, dev->nvr);
nvr_at_handler(1, dev->nvr_io_base + 0x0006, dev->nvr);
} }
@@ -563,6 +489,10 @@ piix_write(int func, int addr, uint8_t val, void *priv)
return; return;
} }
/* Ignore the new IDE BAR's on the Intel chips. */
if ((dev->type < 5) && (func == 1) && (addr >= 0x10) && (addr <= 0x1f))
return;
piix_log("PIIX function %i write: %02X to %02X\n", func, val, addr); piix_log("PIIX function %i write: %02X to %02X\n", func, val, addr);
fregs = (uint8_t *) dev->regs[func]; fregs = (uint8_t *) dev->regs[func];
@@ -628,9 +558,9 @@ piix_write(int func, int addr, uint8_t val, void *priv)
if (dev->type > 4) if (dev->type > 4)
fregs[0x65] = val; fregs[0x65] = val;
break; break;
case 0x68: case 0x66:
if (dev->type > 4) if (dev->type > 4)
fregs[0x68] = val & 0x81; fregs[0x66] = val & 0x81;
break; break;
case 0x69: case 0x69:
if (dev->type > 1) if (dev->type > 1)
@@ -791,15 +721,23 @@ piix_write(int func, int addr, uint8_t val, void *priv)
break; break;
case 0xe1: case 0xe4: case 0xe5: case 0xe6: case 0xe7: case 0xe1: case 0xe4: case 0xe5: case 0xe6: case 0xe7:
case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xe8: case 0xe9: case 0xea: case 0xeb:
if (dev->type > 4) if (dev->type > 4) {
fregs[addr] = val; fregs[addr] = val;
if ((dev->type == 5) && (addr == 0xe1)) {
smsc_ide_irqs(dev);
port_92_set_features(dev->port_92, !!(val & 0x40), !!(val & 0x40));
}
}
break; break;
} else if (func == 1) switch(addr) { /* IDE */ } else if (func == 1) switch(addr) { /* IDE */
case 0x04: case 0x04:
fregs[0x04] = (val & 5); fregs[0x04] = (val & 5);
if (dev->type < 3) if (dev->type < 3)
fregs[0x04] |= 0x02; fregs[0x04] |= 0x02;
piix_ide_legacy_handlers(dev, 0x03); if (dev->type == 5)
smsc_ide_handlers(dev);
else
piix_ide_legacy_handlers(dev, 0x03);
piix_ide_bm_handlers(dev); piix_ide_bm_handlers(dev);
break; break;
case 0x07: case 0x07:
@@ -810,9 +748,48 @@ piix_write(int func, int addr, uint8_t val, void *priv)
if (val & 0x08) if (val & 0x08)
fregs[0x07] &= 0xf7; fregs[0x07] &= 0xf7;
break; break;
case 0x09:
if (dev->type == 5) {
fregs[0x09] = (fregs[0x09] & 0xfa) | (val & 0x05);
smsc_ide_handlers(dev);
smsc_ide_irqs(dev);
}
break;
case 0x0d: case 0x0d:
fregs[0x0d] = val & 0xf0; fregs[0x0d] = val & 0xf0;
break; break;
case 0x10:
fregs[0x10] = (val & 0xf8) | 1;
smsc_ide_handlers(dev);
break;
case 0x11:
fregs[0x11] = val;
smsc_ide_handlers(dev);
break;
case 0x14:
fregs[0x14] = (val & 0xfc) | 1;
smsc_ide_handlers(dev);
break;
case 0x15:
fregs[0x15] = val;
smsc_ide_handlers(dev);
break;
case 0x18:
fregs[0x18] = (val & 0xf8) | 1;
smsc_ide_handlers(dev);
break;
case 0x19:
fregs[0x19] = val;
smsc_ide_handlers(dev);
break;
case 0x1c:
fregs[0x1c] = (val & 0xfc) | 1;
smsc_ide_handlers(dev);
break;
case 0x1d:
fregs[0x1d] = val;
smsc_ide_handlers(dev);
break;
case 0x20: case 0x20:
fregs[0x20] = (val & 0xf0) | 1; fregs[0x20] = (val & 0xf0) | 1;
piix_ide_bm_handlers(dev); piix_ide_bm_handlers(dev);
@@ -822,7 +799,6 @@ piix_write(int func, int addr, uint8_t val, void *priv)
piix_ide_bm_handlers(dev); piix_ide_bm_handlers(dev);
break; break;
case 0x3c: case 0x3c:
piix_log("IDE IRQ write: %02X\n", val);
fregs[0x3c] = val; fregs[0x3c] = val;
break; break;
case 0x40: case 0x42: case 0x40: case 0x42:
@@ -830,26 +806,52 @@ piix_write(int func, int addr, uint8_t val, void *priv)
break; break;
case 0x41: case 0x43: case 0x41: case 0x43:
fregs[addr] = val & ((dev->type > 1) ? 0xf3 : 0xb3); fregs[addr] = val & ((dev->type > 1) ? 0xf3 : 0xb3);
piix_ide_legacy_handlers(dev, 1 << !!(addr & 0x02)); if (dev->type == 5)
smsc_ide_handlers(dev);
else
piix_ide_legacy_handlers(dev, 1 << !!(addr & 0x02));
break; break;
case 0x44: case 0x44:
if (dev->type > 1) if (dev->type > 1)
fregs[0x44] = val; fregs[0x44] = val;
break; break;
case 0x45:
if (dev->type > 4)
fregs[0x45] = val;
break;
case 0x46:
if (dev->type > 4)
fregs[0x46] = val & 0x03;
break;
case 0x48: case 0x48:
if (dev->type > 3) if (dev->type > 3)
fregs[0x48] = val & 0x0f; fregs[0x48] = val & 0x0f;
break; break;
case 0x4a: case 0x4b: case 0x4a: case 0x4b:
if (dev->type > 4) if (dev->type > 3)
fregs[addr] = val & 0x33; fregs[addr] = val & 0x33;
break; break;
case 0x5c: case 0x5d:
if (dev->type > 4)
fregs[addr] = val;
break;
} else if (func == 2) switch(addr) { /* USB */ } else if (func == 2) switch(addr) { /* USB */
case 0x04: case 0x04:
fregs[0x04] = (val & 5); if (dev->type > 4) {
usb_update_io_mapping(dev); fregs[0x04] = (val & 7);
usb_smsc_update_mem_mapping(dev);
} else {
fregs[0x04] = (val & 5);
usb_update_io_mapping(dev);
}
break; break;
case 0x07: case 0x07:
if (dev->type > 4) {
if (val & 0x80)
fregs[0x07] &= 0x7f;
if (val & 0x40)
fregs[0x07] &= 0xbf;
}
if (val & 0x20) if (val & 0x20)
fregs[0x07] &= 0xdf; fregs[0x07] &= 0xdf;
if (val & 0x10) if (val & 0x10)
@@ -857,40 +859,68 @@ piix_write(int func, int addr, uint8_t val, void *priv)
if (val & 0x08) if (val & 0x08)
fregs[0x07] &= 0xf7; fregs[0x07] &= 0xf7;
break; break;
case 0x0c:
if (dev->type > 4)
fregs[0x0c] = val;
break;
case 0x0d: case 0x0d:
fregs[0x0d] = val & 0xf0; if (dev->type <= 4)
fregs[0x0d] = val & 0xf0;
break; break;
case 0x11: case 0x11:
fregs[addr] = val & ~(0x10); if (dev->type > 4) {
usb_smsc_update_mem_mapping(dev); fregs[addr] = val & 0xf0;
usb_smsc_update_mem_mapping(dev);
}
break; break;
case 0x12: case 0x13: case 0x12: case 0x13:
fregs[addr] = val; if (dev->type > 4) {
usb_smsc_update_mem_mapping(dev); fregs[addr] = val;
usb_smsc_update_mem_mapping(dev);
}
break; break;
case 0x20: case 0x20:
fregs[0x20] = (val & 0xe0) | 1; if (dev->type < 5) {
usb_update_io_mapping(dev); fregs[0x20] = (val & 0xe0) | 1;
usb_update_io_mapping(dev);
}
break; break;
case 0x21: case 0x21:
fregs[0x21] = val; if (dev->type < 5) {
usb_update_io_mapping(dev); fregs[0x21] = val;
usb_update_io_mapping(dev);
}
break; break;
case 0x3c: case 0x3c:
fregs[0x3c] = val; fregs[0x3c] = val;
break; break;
case 0x3e: case 0x3f:
case 0x40: case 0x41: case 0x43:
if (dev->type > 4)
fregs[addr] = val;
break;
case 0x42:
if (dev->type > 4)
fregs[addr] = val & 0x8f;
break;
case 0x44: case 0x45:
if (dev->type > 4)
fregs[addr] = val & 0x01;
break;
case 0x6a: case 0x6a:
if (dev->type < 4) if (dev->type == 4)
fregs[0x6a] = val & 0x01; fregs[0x6a] = val & 0x01;
break; break;
case 0xc0: case 0xc0:
fregs[0xc0] = val; if (dev->type == 4)
fregs[0xc0] = val;
break; break;
case 0xc1: case 0xc1:
fregs[0xc1] = val & 0xbf; if (dev->type == 4)
fregs[0xc1] = val & 0xbf;
break; break;
case 0xff: case 0xff:
if (dev->type >= 4) { if (dev->type == 4) {
fregs[addr] = val & 0x10; fregs[addr] = val & 0x10;
nvr_at_handler(0, 0x0070, dev->nvr); nvr_at_handler(0, 0x0070, dev->nvr);
if ((dev->regs[0][0xcb] & 0x01) && (dev->regs[2][0xff] & 0x10)) if ((dev->regs[0][0xcb] & 0x01) && (dev->regs[2][0xff] & 0x10))
@@ -900,7 +930,6 @@ piix_write(int func, int addr, uint8_t val, void *priv)
} else if (func == 3) switch(addr) { /* Power Management */ } else if (func == 3) switch(addr) { /* Power Management */
case 0x04: case 0x04:
fregs[0x04] = (val & 0x01); fregs[0x04] = (val & 0x01);
power_update_io_mapping(dev);
smbus_update_io_mapping(dev); smbus_update_io_mapping(dev);
apm_set_do_smi(dev->apm, !!(fregs[0x5b] & 0x02) && !!(val & 0x01)); apm_set_do_smi(dev->apm, !!(fregs[0x5b] & 0x02) && !!(val & 0x01));
break; break;
@@ -915,11 +944,13 @@ piix_write(int func, int addr, uint8_t val, void *priv)
#endif #endif
case 0x40: case 0x40:
fregs[0x40] = (val & 0xc0) | 1; fregs[0x40] = (val & 0xc0) | 1;
power_update_io_mapping(dev); dev->acpi_io_base = (dev->regs[3][0x41] << 8) | (dev->regs[3][0x40] & 0xc0);
acpi_update_io_mapping(dev->acpi, dev->acpi_io_base, (dev->regs[3][0x80] & 0x01));
break; break;
case 0x41: case 0x41:
fregs[0x41] = val; fregs[0x41] = val;
power_update_io_mapping(dev); dev->acpi_io_base = (dev->regs[3][0x41] << 8) | (dev->regs[3][0x40] & 0xc0);
acpi_update_io_mapping(dev->acpi, dev->acpi_io_base, (dev->regs[3][0x80] & 0x01));
break; break;
case 0x44: case 0x45: case 0x46: case 0x47: case 0x44: case 0x45: case 0x46: case 0x47:
case 0x48: case 0x49: case 0x48: case 0x49:
@@ -947,7 +978,7 @@ piix_write(int func, int addr, uint8_t val, void *priv)
case 0x4f: case 0x80: case 0xd2: case 0x4f: case 0x80: case 0xd2:
fregs[addr] = val & 0x0f; fregs[addr] = val & 0x0f;
if (addr == 0x80) if (addr == 0x80)
power_update_io_mapping(dev); acpi_update_io_mapping(dev->acpi, dev->acpi_io_base, (dev->regs[3][0x80] & 0x01));
else if (addr == 0xd2) else if (addr == 0xd2)
smbus_update_io_mapping(dev); smbus_update_io_mapping(dev);
break; break;
@@ -1056,8 +1087,17 @@ piix_reset_hard(piix_t *dev)
sff_bus_master_reset(dev->bm[1], old_base + 8); sff_bus_master_reset(dev->bm[1], old_base + 8);
if (dev->type >= 4) { if (dev->type >= 4) {
sff_set_irq_mode(dev->bm[0], 0); sff_set_slot(dev->bm[0], dev->pci_slot);
sff_set_irq_mode(dev->bm[1], 0); 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_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);
} }
#ifdef ENABLE_PIIX_LOG #ifdef ENABLE_PIIX_LOG
@@ -1071,7 +1111,6 @@ piix_reset_hard(piix_t *dev)
nvr_wp_set(0, 0, dev->nvr); nvr_wp_set(0, 0, dev->nvr);
nvr_wp_set(0, 1, dev->nvr); nvr_wp_set(0, 1, dev->nvr);
nvr_at_handler(1, 0x0074, dev->nvr); nvr_at_handler(1, 0x0074, dev->nvr);
nvr_at_handler(1, 0x0076, dev->nvr);
dev->nvr_io_base = 0x0070; dev->nvr_io_base = 0x0070;
} }
@@ -1140,9 +1179,16 @@ piix_reset_hard(piix_t *dev)
fregs[0x08] = dev->rev & 0x07; fregs[0x08] = dev->rev & 0x07;
else else
fregs[0x08] = dev->rev; fregs[0x08] = dev->rev;
fregs[0x09] = 0x80; if (dev->type == 5)
fregs[0x09] = 0x8a;
else
fregs[0x09] = 0x80;
fregs[0x0a] = 0x01; fregs[0x0b] = 0x01; fregs[0x0a] = 0x01; fregs[0x0b] = 0x01;
fregs[0x20] = 0x01; fregs[0x20] = 0x01;
if (dev->type == 5) {
fregs[0x3c] = 0x0e;
fregs[0x3d] = 0x01;
}
dev->max_func = 0; /* It starts with IDE disabled, then enables it. */ dev->max_func = 0; /* It starts with IDE disabled, then enables it. */
/* Function 2: USB */ /* Function 2: USB */
@@ -1153,8 +1199,10 @@ piix_reset_hard(piix_t *dev)
fregs[0x06] = 0x80; fregs[0x07] = 0x02; fregs[0x06] = 0x80; fregs[0x07] = 0x02;
if (dev->type == 4) if (dev->type == 4)
fregs[0x08] = dev->rev & 0x07; fregs[0x08] = dev->rev & 0x07;
else else if (dev->type < 4)
fregs[0x08] = dev->rev; fregs[0x08] = dev->rev;
else
fregs[0x08] = 0x02;
if (dev->type == 5) if (dev->type == 5)
fregs[0x09] = 0x10; /* SMSC has OHCI rather than UHCI */ fregs[0x09] = 0x10; /* SMSC has OHCI rather than UHCI */
fregs[0x0a] = 0x03; fregs[0x0b] = 0x0c; fregs[0x0a] = 0x03; fregs[0x0b] = 0x0c;
@@ -1180,11 +1228,15 @@ piix_reset_hard(piix_t *dev)
fregs = (uint8_t *) dev->regs[3]; fregs = (uint8_t *) dev->regs[3];
piix_log("PIIX Function 3: %02X%02X:%02X%02X\n", fregs[0x01], fregs[0x00], fregs[0x03], fregs[0x02]); piix_log("PIIX Function 3: %02X%02X:%02X%02X\n", fregs[0x01], fregs[0x00], fregs[0x03], fregs[0x02]);
fregs[0x06] = 0x80; fregs[0x07] = 0x02; fregs[0x06] = 0x80; fregs[0x07] = 0x02;
fregs[0x08] = (dev->rev & 0x08) ? 0x02 : (dev->rev & 0x07); if (dev->type > 4)
fregs[0x08] = 0x02;
else
fregs[0x08] = (dev->rev & 0x08) ? 0x02 : (dev->rev & 0x07);
fregs[0x0a] = 0x80; fregs[0x0b] = 0x06; fregs[0x0a] = 0x80; fregs[0x0b] = 0x06;
/* NOTE: The Specification Update says this should default to 0x00 and be read-only. */ /* NOTE: The Specification Update says this should default to 0x00 and be read-only. */
#ifdef WRONG_SPEC #ifdef WRONG_SPEC
fregs[0x3d] = 0x01; if (dev->type == 4)
fregs[0x3d] = 0x01;
#endif #endif
fregs[0x40] = 0x01; fregs[0x40] = 0x01;
fregs[0x90] = 0x01; fregs[0x90] = 0x01;
@@ -1201,12 +1253,8 @@ piix_reset_hard(piix_t *dev)
if (dev->type < 3) if (dev->type < 3)
pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED);
if (dev->type == 4) { if (dev->type >= 4)
dev->power.gporeg[0] = 0xff; acpi_init_gporeg(dev->acpi, 0xff, 0xbf, 0xff, 0x7f);
dev->power.gporeg[1] = 0xbf;
dev->power.gporeg[2] = 0xff;
dev->power.gporeg[3] = 0x7f;
}
} }
@@ -1222,7 +1270,6 @@ piix_close(void *p)
static void static void
*piix_init(const device_t *info) *piix_init(const device_t *info)
{ {
int i;
CPU *cpu_s = &machines[machine].cpu[cpu_manufacturer].cpus[cpu]; CPU *cpu_s = &machines[machine].cpu[cpu_manufacturer].cpus[cpu];
piix_t *dev = (piix_t *) malloc(sizeof(piix_t)); piix_t *dev = (piix_t *) malloc(sizeof(piix_t));
@@ -1240,26 +1287,30 @@ static void
dev->bm[0] = device_add_inst(&sff8038i_device, 1); dev->bm[0] = device_add_inst(&sff8038i_device, 1);
dev->bm[1] = device_add_inst(&sff8038i_device, 2); dev->bm[1] = device_add_inst(&sff8038i_device, 2);
if (dev->type > 3) if (dev->type > 3) {
dev->nvr = device_add(&piix4_nvr_device); dev->nvr = device_add(&piix4_nvr_device);
dev->smbus = device_add(&piix4_smbus_device);
dev->acpi = device_add(&acpi_device);
acpi_set_slot(dev->acpi, dev->pci_slot);
acpi_set_nvr(dev->acpi, dev->nvr);
}
if (dev->type == 5) { if (dev->type == 5) {
dev->usb_smsc_mmio = malloc(4096); dev->usb_smsc_mmio = (uint8_t *) malloc(4096);
memset(dev->usb_smsc_mmio, 0x00, 4096);
dev->usb_smsc_mmio_mapping = malloc(sizeof(mem_mapping_t)); mem_mapping_add(&dev->usb_smsc_mmio_mapping, 0, 0,
mem_mapping_add(dev->usb_smsc_mmio_mapping, 0, 0,
usb_smsc_mmio_read, NULL, NULL, usb_smsc_mmio_read, NULL, NULL,
usb_smsc_mmio_write, NULL, NULL, usb_smsc_mmio_write, NULL, NULL,
NULL, MEM_MAPPING_EXTERNAL, dev); NULL, MEM_MAPPING_EXTERNAL, dev);
mem_mapping_disable(dev->usb_smsc_mmio_mapping); mem_mapping_disable(&dev->usb_smsc_mmio_mapping);
} }
piix_reset_hard(dev); piix_reset_hard(dev);
dev->smbus = device_add(&piix4_smbus_device);
dev->apm = device_add(&apm_device); dev->apm = device_add(&apm_device);
device_add(&port_92_pci_device); dev->port_92 = device_add(&port_92_pci_device);
dma_alias_set(); dma_alias_set();
@@ -1299,7 +1350,7 @@ static void
dev->readout_regs[1] |= 0x80; dev->readout_regs[1] |= 0x80;
io_sethandler(0x0078, 0x0002, board_read, NULL, NULL, board_write, NULL, NULL, dev); io_sethandler(0x0078, 0x0002, board_read, NULL, NULL, board_write, NULL, NULL, dev);
// io_sethandler(0x00e0, 0x0002, board_read, NULL, NULL, board_write, NULL, NULL, dev); io_sethandler(0x00e0, 0x0002, board_read, NULL, NULL, board_write, NULL, NULL, dev);
dev->board_config[0] = 0xff; dev->board_config[0] = 0xff;
dev->board_config[0] = 0x00; dev->board_config[0] = 0x00;

View File

@@ -97,7 +97,7 @@ machine_at_p2bls_init(const machine_t *model)
device_add(&i440bx_device); device_add(&i440bx_device);
device_add(&piix4e_device); device_add(&piix4e_device);
device_add(&keyboard_ps2_pci_device); device_add(&keyboard_ps2_pci_device);
device_add(&w83977ef_device); // device_add(&w83977ef_device);
device_add(&sst_flash_39sf020_device); device_add(&sst_flash_39sf020_device);
spd_register(SPD_TYPE_SDRAM, 0xF, 256); spd_register(SPD_TYPE_SDRAM, 0xF, 256);

View File

@@ -1309,7 +1309,7 @@ eep_close(void *priv)
t1keep_t *eep = (t1keep_t *)priv; t1keep_t *eep = (t1keep_t *)priv;
FILE *f = NULL; FILE *f = NULL;
f = nvr_fopen(eep->path, L"rb"); f = nvr_fopen(eep->path, L"wb");
if (f != NULL) { if (f != NULL) {
(void)fwrite(eep->store, 128, 1, f); (void)fwrite(eep->store, 128, 1, f);
(void)fclose(f); (void)fclose(f);

View File

@@ -553,78 +553,89 @@ timer_tick(nvr_t *nvr)
} }
/* This must be exposed because ACPI uses it. */
void
nvr_reg_write(uint16_t reg, uint8_t val, void *priv)
{
nvr_t *nvr = (nvr_t *)priv;
local_t *local = (local_t *)nvr->data;
struct tm tm;
uint8_t old, i;
uint16_t checksum = 0x0000;
old = nvr->regs[reg];
switch(reg) {
case RTC_REGA:
nvr->regs[RTC_REGA] = val;
timer_load_count(nvr);
break;
case RTC_REGB:
nvr->regs[RTC_REGB] = val;
if (((old^val) & REGB_SET) && (val&REGB_SET)) {
/* According to the datasheet... */
nvr->regs[RTC_REGA] &= ~REGA_UIP;
nvr->regs[RTC_REGB] &= ~REGB_UIE;
}
break;
case RTC_REGC: /* R/O */
case RTC_REGD: /* R/O */
break;
case 0x2e:
case 0x2f:
if (local->flags & FLAG_LS_HACK) {
/* 2E and 2F are a simple sum of the values of 0E to 2D. */
for (i = 0x0e; i < 0x2e; i++)
checksum += (uint16_t) nvr->regs[i];
nvr->regs[0x2e] = checksum >> 8;
nvr->regs[0x2f] = checksum & 0xff;
break;
}
/*FALLTHROUGH*/
default: /* non-RTC registers are just NVRAM */
if ((reg >= 0x38) && (reg <= 0x3f) && local->wp[0])
break;
if ((reg >= 0xb8) && (reg <= 0xbf) && local->wp[1])
break;
if (local->lock[reg])
break;
if (nvr->regs[reg] != val) {
nvr->regs[reg] = val;
nvr_dosave = 1;
}
break;
}
if ((reg < RTC_REGA) || ((local->cent != 0xff) && (reg == local->cent))) {
if ((reg != 1) && (reg != 3) && (reg != 5)) {
if ((old != val) && !(time_sync & TIME_SYNC_ENABLED)) {
/* Update internal clock. */
time_get(nvr, &tm);
nvr_time_set(&tm);
nvr_dosave = 1;
}
}
}
}
/* Write to one of the NVR registers. */ /* Write to one of the NVR registers. */
static void static void
nvr_write(uint16_t addr, uint8_t val, void *priv) nvr_write(uint16_t addr, uint8_t val, void *priv)
{ {
nvr_t *nvr = (nvr_t *)priv; nvr_t *nvr = (nvr_t *)priv;
local_t *local = (local_t *)nvr->data; local_t *local = (local_t *)nvr->data;
struct tm tm;
uint8_t old, i;
uint8_t addr_id = (addr & 0x0e) >> 1; uint8_t addr_id = (addr & 0x0e) >> 1;
uint16_t checksum = 0x0000;
sub_cycles(ISA_CYCLES(8)); sub_cycles(ISA_CYCLES(8));
if (addr & 1) { if (addr & 1) {
if (local->bank[addr_id] == 0xff) if (local->bank[addr_id] == 0xff)
return; return;
old = nvr->regs[local->addr[addr_id]]; nvr_reg_write(local->addr[addr_id], val, priv);
switch(local->addr[addr_id]) {
case RTC_REGA:
nvr->regs[RTC_REGA] = val;
timer_load_count(nvr);
break;
case RTC_REGB:
nvr->regs[RTC_REGB] = val;
if (((old^val) & REGB_SET) && (val&REGB_SET)) {
/* According to the datasheet... */
nvr->regs[RTC_REGA] &= ~REGA_UIP;
nvr->regs[RTC_REGB] &= ~REGB_UIE;
}
break;
case RTC_REGC: /* R/O */
case RTC_REGD: /* R/O */
break;
case 0x2e:
case 0x2f:
if (local->flags & FLAG_LS_HACK) {
/* 2E and 2F are a simple sum of the values of 0E to 2D. */
for (i = 0x0e; i < 0x2e; i++)
checksum += (uint16_t) nvr->regs[i];
nvr->regs[0x2e] = checksum >> 8;
nvr->regs[0x2f] = checksum & 0xff;
break;
}
/*FALLTHROUGH*/
default: /* non-RTC registers are just NVRAM */
if ((local->addr[addr_id] >= 0x38) && (local->addr[addr_id] <= 0x3f) && local->wp[0])
break;
if ((local->addr[addr_id] >= 0xb8) && (local->addr[addr_id] <= 0xbf) && local->wp[1])
break;
if (local->lock[local->addr[addr_id]])
break;
if (nvr->regs[local->addr[addr_id]] != val) {
nvr->regs[local->addr[addr_id]] = val;
nvr_dosave = 1;
}
break;
}
if ((local->addr[addr_id] < RTC_REGA) || ((local->cent != 0xff) && (local->addr[addr_id] == local->cent))) {
if ((local->addr[addr_id] != 1) && (local->addr[addr_id] != 3) && (local->addr[addr_id] != 5)) {
if ((old != val) && !(time_sync & TIME_SYNC_ENABLED)) {
/* Update internal clock. */
time_get(nvr, &tm);
nvr_time_set(&tm);
nvr_dosave = 1;
}
}
}
} else { } else {
local->addr[addr_id] = (val & (nvr->size - 1)); local->addr[addr_id] = (val & (nvr->size - 1));
/* Some chipsets use a 256 byte NVRAM but ports 70h and 71h always access only 128 bytes. */ /* Some chipsets use a 256 byte NVRAM but ports 70h and 71h always access only 128 bytes. */

View File

@@ -50,7 +50,7 @@ uint64_t PITCONST, ISACONST,
CGACONST, CGACONST,
MDACONST, HERCCONST, MDACONST, HERCCONST,
VGACONST1, VGACONST2, VGACONST1, VGACONST2,
RTCCONST; RTCCONST, ACPICONST;
int io_delay = 5; int io_delay = 5;
@@ -1021,6 +1021,7 @@ pit_set_clock(int clock)
VGACONST1 = (uint64_t) (cpuclock / 25175000.0 * (double)(1ull << 32)); VGACONST1 = (uint64_t) (cpuclock / 25175000.0 * (double)(1ull << 32));
VGACONST2 = (uint64_t) (cpuclock / 28322000.0 * (double)(1ull << 32)); VGACONST2 = (uint64_t) (cpuclock / 28322000.0 * (double)(1ull << 32));
RTCCONST = (uint64_t) (cpuclock / 32768.0 * (double)(1ull << 32)); RTCCONST = (uint64_t) (cpuclock / 32768.0 * (double)(1ull << 32));
ACPICONST = (uint64_t) (cpuclock / 3579545.0 * (double)(1ull << 32));
TIMER_USEC = (uint64_t)((cpuclock / 1000000.0) * (double)(1ull << 32)); TIMER_USEC = (uint64_t)((cpuclock / 1000000.0) * (double)(1ull << 32));

View File

@@ -810,14 +810,16 @@ sb_exec_command(sb_dsp_t *dsp)
break; break;
case 0x09: /*AZTECH mode set*/ case 0x09: /*AZTECH mode set*/
if (dsp->sb_data[0] == 0x00) { if (IS_AZTECH(dsp)) {
sb_dsp_log("AZT2316A: WSS MODE!\n"); if (dsp->sb_data[0] == 0x00) {
azt2316a_enable_wss(1, dsp->parent); sb_dsp_log("AZT2316A: WSS MODE!\n");
} else if (dsp->sb_data[0] == 0x01) { azt2316a_enable_wss(1, dsp->parent);
sb_dsp_log("AZT2316A: SB8PROV2 MODE!\n"); } else if (dsp->sb_data[0] == 0x01) {
azt2316a_enable_wss(0, dsp->parent); sb_dsp_log("AZT2316A: SB8PROV2 MODE!\n");
} else azt2316a_enable_wss(0, dsp->parent);
sb_dsp_log("AZT2316A: UNKNOWN MODE! = %02x\n", dsp->sb_data[0]); // sequences 0x02->0xFF, 0x04->0xFF seen } else
sb_dsp_log("AZT2316A: UNKNOWN MODE! = %02x\n", dsp->sb_data[0]); // sequences 0x02->0xFF, 0x04->0xFF seen
}
break; break;
/* TODO: Some more data about the DSP registeres /* TODO: Some more data about the DSP registeres

View File

@@ -220,6 +220,25 @@ via_vt82c586b_ide_handlers(via_vt82c586b_t *dev)
} }
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 static void
via_vt82c586b_bus_master_handlers(via_vt82c586b_t *dev) via_vt82c586b_bus_master_handlers(via_vt82c586b_t *dev)
{ {
@@ -466,6 +485,7 @@ via_vt82c586b_write(int func, int addr, uint8_t val, void *priv)
case 0x09: case 0x09:
dev->ide_regs[0x09] = (val & 0x05) | 0x8a; dev->ide_regs[0x09] = (val & 0x05) | 0x8a;
via_vt82c586b_ide_handlers(dev); via_vt82c586b_ide_handlers(dev);
via_vt82c586b_ide_irqs(dev);
break; break;
case 0x10: case 0x10:
@@ -514,8 +534,8 @@ via_vt82c586b_write(int func, int addr, uint8_t val, void *priv)
break; break;
case 0x3d: case 0x3d:
sff_set_irq_mode(dev->bm[0], val); dev->ide_regs[0x3d] = val & 0x01;
sff_set_irq_mode(dev->bm[1], val); via_vt82c586b_ide_irqs(dev);
break; break;
case 0x40: case 0x40:
@@ -591,12 +611,14 @@ static void
dev->bm[0] = device_add_inst(&sff8038i_device, 1); dev->bm[0] = device_add_inst(&sff8038i_device, 1);
sff_set_slot(dev->bm[0], dev->slot); sff_set_slot(dev->bm[0], dev->slot);
sff_set_irq_mode(dev->bm[0], 0); 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); sff_set_irq_pin(dev->bm[0], PCI_INTA);
dev->bm[1] = device_add_inst(&sff8038i_device, 2); dev->bm[1] = device_add_inst(&sff8038i_device, 2);
sff_set_slot(dev->bm[1], dev->slot); sff_set_slot(dev->bm[1], dev->slot);
sff_set_irq_mode(dev->bm[1], 0); 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); sff_set_irq_pin(dev->bm[1], PCI_INTA);
dev->nvr = device_add(&via_nvr_device); dev->nvr = device_add(&via_nvr_device);

View File

@@ -263,6 +263,7 @@ via_vt82c596b_reset(void *priv)
ide_sec_disable(); ide_sec_disable();
} }
// IDE CONTROLLER // IDE CONTROLLER
static void static void
ide_handlers(via_vt82c596b_t *dev) ide_handlers(via_vt82c596b_t *dev)
@@ -307,6 +308,25 @@ ide_handlers(via_vt82c596b_t *dev)
} }
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 static void
bus_master_handlers(via_vt82c596b_t *dev) bus_master_handlers(via_vt82c596b_t *dev)
{ {
@@ -581,6 +601,7 @@ via_vt82c596b_write(int func, int addr, uint8_t val, void *priv)
case 0x09: case 0x09:
dev->ide_regs[0x09] = (val & 0x05) | 0x8a; dev->ide_regs[0x09] = (val & 0x05) | 0x8a;
ide_handlers(dev); ide_handlers(dev);
ide_irqs(dev);
break; break;
case 0x10: case 0x10:
@@ -629,8 +650,8 @@ via_vt82c596b_write(int func, int addr, uint8_t val, void *priv)
break; break;
case 0x3d: case 0x3d:
sff_set_irq_mode(dev->bm[0], val); dev->ide_regs[0x3d] = val & 0x01;
sff_set_irq_mode(dev->bm[1], val); ide_irqs(dev);
break; break;
case 0x40: case 0x40:
@@ -717,12 +738,14 @@ via_vt82c596b_init(const device_t *info)
dev->bm[0] = device_add_inst(&sff8038i_device, 1); dev->bm[0] = device_add_inst(&sff8038i_device, 1);
sff_set_slot(dev->bm[0], dev->slot); sff_set_slot(dev->bm[0], dev->slot);
sff_set_irq_mode(dev->bm[0], 0); 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); sff_set_irq_pin(dev->bm[0], PCI_INTA);
dev->bm[1] = device_add_inst(&sff8038i_device, 2); dev->bm[1] = device_add_inst(&sff8038i_device, 2);
sff_set_slot(dev->bm[1], dev->slot); sff_set_slot(dev->bm[1], dev->slot);
sff_set_irq_mode(dev->bm[1], 0); 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); sff_set_irq_pin(dev->bm[1], PCI_INTA);
dev->nvr = device_add(&via_nvr_device); dev->nvr = device_add(&via_nvr_device);

View File

@@ -549,7 +549,7 @@ CXXFLAGS := $(CFLAGS)
######################################################################### #########################################################################
# Create the (final) list of objects to build. # # Create the (final) list of objects to build. #
######################################################################### #########################################################################
MAINOBJ := pc.o config.o random.o timer.o io.o apm.o dma.o nmi.o \ MAINOBJ := pc.o config.o random.o timer.o io.o acpi.o apm.o dma.o nmi.o \
pic.o pit.o port_92.o ppi.o pci.o mca.o mcr.o mem.o \ pic.o pit.o port_92.o ppi.o pci.o mca.o mcr.o mem.o \
rom.o device.o nvr.o nvr_at.o nvr_ps2.o sst_flash.o via_vt82c586b.o \ rom.o device.o nvr.o nvr_at.o nvr_ps2.o sst_flash.o via_vt82c586b.o \
via_vt82c596b.o $(VNCOBJ) $(RDPOBJ) via_vt82c596b.o $(VNCOBJ) $(RDPOBJ)

View File

@@ -553,7 +553,7 @@ CXXFLAGS := $(CFLAGS)
######################################################################### #########################################################################
# Create the (final) list of objects to build. # # Create the (final) list of objects to build. #
######################################################################### #########################################################################
MAINOBJ := pc.o config.o random.o timer.o io.o apm.o dma.o nmi.o \ MAINOBJ := pc.o config.o random.o timer.o io.o acpi.o apm.o dma.o nmi.o \
pic.o pit.o port_92.o ppi.o pci.o mca.o mcr.o mem.o \ pic.o pit.o port_92.o ppi.o pci.o mca.o mcr.o mem.o \
rom.o device.o nvr.o nvr_at.o nvr_ps2.o sst_flash.o via_vt82c586b.o \ rom.o device.o nvr.o nvr_at.o nvr_ps2.o sst_flash.o via_vt82c586b.o \
via_vt82c596b.o $(VNCOBJ) $(RDPOBJ) via_vt82c596b.o $(VNCOBJ) $(RDPOBJ)