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++)
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[0x72], 0x72, 0x00, dev);
// smbase = 0xa0000;
if (((dev->type == INTEL_440BX) || (dev->type == INTEL_440ZX)) && (dev->max_func == 1)) {
regs = (uint8_t *) dev->regs[1];

View File

@@ -1077,6 +1077,9 @@ enter_smm(int in_hlt)
smm_in_hlt = in_hlt;
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) */
smram_restore_state_p6(saved_state);
/* Maybe we need this? */
if (smbase == 0x00030000)
smbase = 0x000a0000;
in_smm = 0;
mem_mapping_recalc(0x00030000, 0x00020000);
mem_mapping_recalc(0x000a0000, 0x00060000);

View File

@@ -2202,9 +2202,15 @@ cpu_CPUID(void)
EAX = CPUID;
EBX = ECX = 0;
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)
{
EAX = 0x00000001;
EBX = ECX = 0;
EDX = 0x00000000;
}
else
EAX = EBX = ECX = EDX = 0;
@@ -2223,12 +2229,15 @@ cpu_CPUID(void)
EAX = CPUID;
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;
#ifdef USE_SEP
EDX |= CPUID_SEP;
#endif
}
else if (EAX == 2)
{
EAX = 0x03020101;
EAX = 0x00000001;
EBX = ECX = 0;
EDX = 0x0C040843;
EDX = 0x00000000;
}
else
EAX = EBX = ECX = EDX = 0;
@@ -2247,12 +2256,15 @@ cpu_CPUID(void)
EAX = CPUID;
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;
#ifdef USE_SEP
EDX |= CPUID_SEP;
#endif
}
else if (EAX == 2)
{
EAX = 0x03020101;
EAX = 0x00000001;
EBX = ECX = 0;
EDX = 0x0C040844;
EDX = 0x00000000;
}
else
EAX = EBX = ECX = EDX = 0;

View File

@@ -374,17 +374,21 @@ sff_bus_master_set_irq(int channel, void *priv)
channel &= 0x01;
if (dev->status & 0x04) {
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);
else if (dev->irq_mode == 1)
else if (dev->irq_mode[channel] == 1)
pci_set_irq(dev->slot, dev->irq_pin);
else
picint(1 << (14 + channel));
} else {
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);
else if (dev->irq_mode == 1)
else if (dev->irq_mode[channel] == 1)
pci_clear_irq(dev->slot, dev->irq_pin);
else
picintc(1 << (14 + channel));
@@ -449,9 +453,16 @@ sff_set_slot(sff8038i_t *dev, int slot)
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);
dev->slot = 7;
dev->irq_mode = 2;
dev->irq_mode[0] = dev->irq_mode[1] = 2;
dev->irq_pin = PCI_INTA;
dev->irq_line = 14;
next_id++;

View File

@@ -25,7 +25,8 @@ typedef struct
addr;
int count, eot,
slot,
irq_mode, irq_pin;
irq_mode[2], irq_pin,
irq_line;
} 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_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);

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_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_sec_handler(int set, uint16_t base, 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,
VGACONST1,
VGACONST2,
RTCCONST;
RTCCONST, ACPICONST;
/* Gets a counter's count. */

View File

@@ -39,6 +39,7 @@
#include <86box/mem.h>
#include <86box/timer.h>
#include <86box/nvr.h>
#include <86box/acpi.h>
#include <86box/pci.h>
#include <86box/pic.h>
#include <86box/port_92.h>
@@ -51,24 +52,6 @@
#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
{
uint16_t io_base;
@@ -76,17 +59,6 @@ typedef struct
} 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
{
uint8_t cur_readout_reg, rev,
@@ -96,15 +68,16 @@ typedef struct
readout_regs[256], board_config[2];
uint16_t func0_id,
nvr_io_base,
usb_io_base, power_io_base;
usb_io_base, acpi_io_base;
uint8_t *usb_smsc_mmio;
mem_mapping_t *usb_smsc_mmio_mapping;
mem_mapping_t usb_smsc_mmio_mapping;
sff8038i_t *bm[2];
ddma_t ddma[2];
power_t power;
smbus_piix4_t * smbus;
apm_t * apm;
nvr_t * nvr;
acpi_t * acpi;
port_92_t * port_92;
} piix_t;
@@ -128,28 +101,88 @@ piix_log(const char *fmt, ...)
#endif
static
void do_irq(piix_t *dev, int func, int level)
static void
smsc_ide_handlers(piix_t *dev)
{
if ((dev == NULL) || (func > dev->max_func) /*||
(dev->regs[func][0x3d] < PCI_INTA) || (dev->regs[func][0x3d] < PCI_INTD)*/)
return;
uint16_t main, side;
if (level) {
#ifdef WRONG_SPEC
pci_set_irq(dev->pci_slot, dev->regs[func][0x3d]);
#else
picintlevel(1 << 9);
#endif
piix_log("Raising IRQ...\n");
ide_pri_disable();
ide_sec_disable();
if (dev->regs[1][0x09] & 0x01) {
main = (dev->regs[1][0x11] << 8) | (dev->regs[1][0x10] & 0xf8);
side = ((dev->regs[1][0x15] << 8) | (dev->regs[1][0x14] & 0xfc)) + 2;
} else {
#ifdef WRONG_SPEC
pci_clear_irq(dev->pci_slot, dev->regs[func][0x3d]);
#else
picintc(1 << 9);
#endif
piix_log("Lowering IRQ...\n");
main = 0x1f0;
side = 0x3f6;
}
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
usb_smsc_update_mem_mapping(piix_t *dev)
{
uint8_t *fregs;
uint32_t usb_bar;
if (!dev->usb_smsc_mmio_mapping)
return;
mem_mapping_disable(&dev->usb_smsc_mmio_mapping);
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)
return;
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);
if ((dev->regs[2][0x04] & 0x02) && (usb_bar != 0x00000000))
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)
{
piix_t *dev = (piix_t *) p;
uint8_t ret;
ret = dev->usb_smsc_mmio[addr & 0xFFF];
uint8_t ret = 0x00;
/* addr &= 0x00000fff;
ret = dev->usb_smsc_mmio[addr]; */
piix_log("usb_smsc_mmio_read(%08x) = %02x\n", addr, 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;
switch (addr & 0xFFF) {
addr &= 0x00000fff;
switch (addr) {
case 0x08: /* HCCOMMANDSTATUS */
/* 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) */
if (val & 0x0F) {
dev->usb_smsc_mmio[0x0F] = 0x40;
if (val & 0x0f) {
dev->usb_smsc_mmio[0x0f] = 0x40;
dev->usb_smsc_mmio[0x05] &= ~(dev->usb_smsc_mmio[0x05] & 0x01);
}
break;
}
dev->usb_smsc_mmio[addr & 0xFFF] = 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);
dev->usb_smsc_mmio[addr] = val;
}
@@ -527,24 +448,29 @@ smbus_update_io_mapping(piix_t *dev)
static void
nvr_update_io_mapping(piix_t *dev)
{
int enabled2 = 1;
if (dev->nvr_io_base != 0x0000) {
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 + 0x0004, dev->nvr);
nvr_at_handler(0, dev->nvr_io_base + 0x0006, dev->nvr);
}
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
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 + 0x0004, dev->nvr);
}
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 + 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;
}
/* 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);
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)
fregs[0x65] = val;
break;
case 0x68:
case 0x66:
if (dev->type > 4)
fregs[0x68] = val & 0x81;
fregs[0x66] = val & 0x81;
break;
case 0x69:
if (dev->type > 1)
@@ -791,14 +721,22 @@ piix_write(int func, int addr, uint8_t val, void *priv)
break;
case 0xe1: case 0xe4: case 0xe5: case 0xe6: case 0xe7:
case 0xe8: case 0xe9: case 0xea: case 0xeb:
if (dev->type > 4)
if (dev->type > 4) {
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;
} else if (func == 1) switch(addr) { /* IDE */
case 0x04:
fregs[0x04] = (val & 5);
if (dev->type < 3)
fregs[0x04] |= 0x02;
if (dev->type == 5)
smsc_ide_handlers(dev);
else
piix_ide_legacy_handlers(dev, 0x03);
piix_ide_bm_handlers(dev);
break;
@@ -810,9 +748,48 @@ piix_write(int func, int addr, uint8_t val, void *priv)
if (val & 0x08)
fregs[0x07] &= 0xf7;
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:
fregs[0x0d] = val & 0xf0;
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:
fregs[0x20] = (val & 0xf0) | 1;
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);
break;
case 0x3c:
piix_log("IDE IRQ write: %02X\n", val);
fregs[0x3c] = val;
break;
case 0x40: case 0x42:
@@ -830,26 +806,52 @@ piix_write(int func, int addr, uint8_t val, void *priv)
break;
case 0x41: case 0x43:
fregs[addr] = val & ((dev->type > 1) ? 0xf3 : 0xb3);
if (dev->type == 5)
smsc_ide_handlers(dev);
else
piix_ide_legacy_handlers(dev, 1 << !!(addr & 0x02));
break;
case 0x44:
if (dev->type > 1)
fregs[0x44] = val;
break;
case 0x45:
if (dev->type > 4)
fregs[0x45] = val;
break;
case 0x46:
if (dev->type > 4)
fregs[0x46] = val & 0x03;
break;
case 0x48:
if (dev->type > 3)
fregs[0x48] = val & 0x0f;
break;
case 0x4a: case 0x4b:
if (dev->type > 4)
if (dev->type > 3)
fregs[addr] = val & 0x33;
break;
case 0x5c: case 0x5d:
if (dev->type > 4)
fregs[addr] = val;
break;
} else if (func == 2) switch(addr) { /* USB */
case 0x04:
if (dev->type > 4) {
fregs[0x04] = (val & 7);
usb_smsc_update_mem_mapping(dev);
} else {
fregs[0x04] = (val & 5);
usb_update_io_mapping(dev);
}
break;
case 0x07:
if (dev->type > 4) {
if (val & 0x80)
fregs[0x07] &= 0x7f;
if (val & 0x40)
fregs[0x07] &= 0xbf;
}
if (val & 0x20)
fregs[0x07] &= 0xdf;
if (val & 0x10)
@@ -857,40 +859,68 @@ piix_write(int func, int addr, uint8_t val, void *priv)
if (val & 0x08)
fregs[0x07] &= 0xf7;
break;
case 0x0c:
if (dev->type > 4)
fregs[0x0c] = val;
break;
case 0x0d:
if (dev->type <= 4)
fregs[0x0d] = val & 0xf0;
break;
case 0x11:
fregs[addr] = val & ~(0x10);
if (dev->type > 4) {
fregs[addr] = val & 0xf0;
usb_smsc_update_mem_mapping(dev);
}
break;
case 0x12: case 0x13:
if (dev->type > 4) {
fregs[addr] = val;
usb_smsc_update_mem_mapping(dev);
}
break;
case 0x20:
if (dev->type < 5) {
fregs[0x20] = (val & 0xe0) | 1;
usb_update_io_mapping(dev);
}
break;
case 0x21:
if (dev->type < 5) {
fregs[0x21] = val;
usb_update_io_mapping(dev);
}
break;
case 0x3c:
fregs[0x3c] = val;
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:
if (dev->type < 4)
if (dev->type == 4)
fregs[0x6a] = val & 0x01;
break;
case 0xc0:
if (dev->type == 4)
fregs[0xc0] = val;
break;
case 0xc1:
if (dev->type == 4)
fregs[0xc1] = val & 0xbf;
break;
case 0xff:
if (dev->type >= 4) {
if (dev->type == 4) {
fregs[addr] = val & 0x10;
nvr_at_handler(0, 0x0070, dev->nvr);
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 */
case 0x04:
fregs[0x04] = (val & 0x01);
power_update_io_mapping(dev);
smbus_update_io_mapping(dev);
apm_set_do_smi(dev->apm, !!(fregs[0x5b] & 0x02) && !!(val & 0x01));
break;
@@ -915,11 +944,13 @@ piix_write(int func, int addr, uint8_t val, void *priv)
#endif
case 0x40:
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;
case 0x41:
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;
case 0x44: case 0x45: case 0x46: case 0x47:
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:
fregs[addr] = val & 0x0f;
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)
smbus_update_io_mapping(dev);
break;
@@ -1056,8 +1087,17 @@ piix_reset_hard(piix_t *dev)
sff_bus_master_reset(dev->bm[1], old_base + 8);
if (dev->type >= 4) {
sff_set_irq_mode(dev->bm[0], 0);
sff_set_irq_mode(dev->bm[1], 0);
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_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
@@ -1071,7 +1111,6 @@ piix_reset_hard(piix_t *dev)
nvr_wp_set(0, 0, dev->nvr);
nvr_wp_set(0, 1, dev->nvr);
nvr_at_handler(1, 0x0074, dev->nvr);
nvr_at_handler(1, 0x0076, dev->nvr);
dev->nvr_io_base = 0x0070;
}
@@ -1140,9 +1179,16 @@ piix_reset_hard(piix_t *dev)
fregs[0x08] = dev->rev & 0x07;
else
fregs[0x08] = dev->rev;
if (dev->type == 5)
fregs[0x09] = 0x8a;
else
fregs[0x09] = 0x80;
fregs[0x0a] = 0x01; fregs[0x0b] = 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. */
/* Function 2: USB */
@@ -1153,8 +1199,10 @@ piix_reset_hard(piix_t *dev)
fregs[0x06] = 0x80; fregs[0x07] = 0x02;
if (dev->type == 4)
fregs[0x08] = dev->rev & 0x07;
else
else if (dev->type < 4)
fregs[0x08] = dev->rev;
else
fregs[0x08] = 0x02;
if (dev->type == 5)
fregs[0x09] = 0x10; /* SMSC has OHCI rather than UHCI */
fregs[0x0a] = 0x03; fregs[0x0b] = 0x0c;
@@ -1180,10 +1228,14 @@ piix_reset_hard(piix_t *dev)
fregs = (uint8_t *) dev->regs[3];
piix_log("PIIX Function 3: %02X%02X:%02X%02X\n", fregs[0x01], fregs[0x00], fregs[0x03], fregs[0x02]);
fregs[0x06] = 0x80; fregs[0x07] = 0x02;
if (dev->type > 4)
fregs[0x08] = 0x02;
else
fregs[0x08] = (dev->rev & 0x08) ? 0x02 : (dev->rev & 0x07);
fregs[0x0a] = 0x80; fregs[0x0b] = 0x06;
/* NOTE: The Specification Update says this should default to 0x00 and be read-only. */
#ifdef WRONG_SPEC
if (dev->type == 4)
fregs[0x3d] = 0x01;
#endif
fregs[0x40] = 0x01;
@@ -1201,12 +1253,8 @@ piix_reset_hard(piix_t *dev)
if (dev->type < 3)
pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED);
if (dev->type == 4) {
dev->power.gporeg[0] = 0xff;
dev->power.gporeg[1] = 0xbf;
dev->power.gporeg[2] = 0xff;
dev->power.gporeg[3] = 0x7f;
}
if (dev->type >= 4)
acpi_init_gporeg(dev->acpi, 0xff, 0xbf, 0xff, 0x7f);
}
@@ -1222,7 +1270,6 @@ piix_close(void *p)
static void
*piix_init(const device_t *info)
{
int i;
CPU *cpu_s = &machines[machine].cpu[cpu_manufacturer].cpus[cpu];
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[1] = device_add_inst(&sff8038i_device, 2);
if (dev->type > 3)
if (dev->type > 3) {
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) {
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_write, NULL, NULL,
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);
dev->smbus = device_add(&piix4_smbus_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();
@@ -1299,7 +1350,7 @@ static void
dev->readout_regs[1] |= 0x80;
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] = 0x00;

View File

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

View File

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

View File

@@ -553,24 +553,18 @@ timer_tick(nvr_t *nvr)
}
/* Write to one of the NVR registers. */
static void
nvr_write(uint16_t addr, uint8_t val, void *priv)
/* 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;
uint8_t addr_id = (addr & 0x0e) >> 1;
uint16_t checksum = 0x0000;
sub_cycles(ISA_CYCLES(8));
if (addr & 1) {
if (local->bank[addr_id] == 0xff)
return;
old = nvr->regs[local->addr[addr_id]];
switch(local->addr[addr_id]) {
old = nvr->regs[reg];
switch(reg) {
case RTC_REGA:
nvr->regs[RTC_REGA] = val;
timer_load_count(nvr);
@@ -602,21 +596,21 @@ nvr_write(uint16_t addr, uint8_t val, void *priv)
/*FALLTHROUGH*/
default: /* non-RTC registers are just NVRAM */
if ((local->addr[addr_id] >= 0x38) && (local->addr[addr_id] <= 0x3f) && local->wp[0])
if ((reg >= 0x38) && (reg <= 0x3f) && local->wp[0])
break;
if ((local->addr[addr_id] >= 0xb8) && (local->addr[addr_id] <= 0xbf) && local->wp[1])
if ((reg >= 0xb8) && (reg <= 0xbf) && local->wp[1])
break;
if (local->lock[local->addr[addr_id]])
if (local->lock[reg])
break;
if (nvr->regs[local->addr[addr_id]] != val) {
nvr->regs[local->addr[addr_id]] = val;
if (nvr->regs[reg] != val) {
nvr->regs[reg] = 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 ((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);
@@ -625,6 +619,23 @@ nvr_write(uint16_t addr, uint8_t val, void *priv)
}
}
}
}
/* Write to one of the NVR registers. */
static void
nvr_write(uint16_t addr, uint8_t val, void *priv)
{
nvr_t *nvr = (nvr_t *)priv;
local_t *local = (local_t *)nvr->data;
uint8_t addr_id = (addr & 0x0e) >> 1;
sub_cycles(ISA_CYCLES(8));
if (addr & 1) {
if (local->bank[addr_id] == 0xff)
return;
nvr_reg_write(local->addr[addr_id], val, priv);
} else {
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. */

View File

@@ -50,7 +50,7 @@ uint64_t PITCONST, ISACONST,
CGACONST,
MDACONST, HERCCONST,
VGACONST1, VGACONST2,
RTCCONST;
RTCCONST, ACPICONST;
int io_delay = 5;
@@ -1021,6 +1021,7 @@ pit_set_clock(int clock)
VGACONST1 = (uint64_t) (cpuclock / 25175000.0 * (double)(1ull << 32));
VGACONST2 = (uint64_t) (cpuclock / 28322000.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));

View File

@@ -810,6 +810,7 @@ sb_exec_command(sb_dsp_t *dsp)
break;
case 0x09: /*AZTECH mode set*/
if (IS_AZTECH(dsp)) {
if (dsp->sb_data[0] == 0x00) {
sb_dsp_log("AZT2316A: WSS MODE!\n");
azt2316a_enable_wss(1, dsp->parent);
@@ -818,6 +819,7 @@ sb_exec_command(sb_dsp_t *dsp)
azt2316a_enable_wss(0, dsp->parent);
} else
sb_dsp_log("AZT2316A: UNKNOWN MODE! = %02x\n", dsp->sb_data[0]); // sequences 0x02->0xFF, 0x04->0xFF seen
}
break;
/* 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
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:
dev->ide_regs[0x09] = (val & 0x05) | 0x8a;
via_vt82c586b_ide_handlers(dev);
via_vt82c586b_ide_irqs(dev);
break;
case 0x10:
@@ -514,8 +534,8 @@ via_vt82c586b_write(int func, int addr, uint8_t val, void *priv)
break;
case 0x3d:
sff_set_irq_mode(dev->bm[0], val);
sff_set_irq_mode(dev->bm[1], val);
dev->ide_regs[0x3d] = val & 0x01;
via_vt82c586b_ide_irqs(dev);
break;
case 0x40:
@@ -591,12 +611,14 @@ static void
dev->bm[0] = device_add_inst(&sff8038i_device, 1);
sff_set_slot(dev->bm[0], dev->slot);
sff_set_irq_mode(dev->bm[0], 0);
sff_set_irq_mode(dev->bm[0], 0, 0);
sff_set_irq_mode(dev->bm[0], 1, 0);
sff_set_irq_pin(dev->bm[0], PCI_INTA);
dev->bm[1] = device_add_inst(&sff8038i_device, 2);
sff_set_slot(dev->bm[1], dev->slot);
sff_set_irq_mode(dev->bm[1], 0);
sff_set_irq_mode(dev->bm[1], 0, 0);
sff_set_irq_mode(dev->bm[1], 1, 0);
sff_set_irq_pin(dev->bm[1], PCI_INTA);
dev->nvr = device_add(&via_nvr_device);

View File

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

View File

@@ -549,7 +549,7 @@ CXXFLAGS := $(CFLAGS)
#########################################################################
# 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 \
rom.o device.o nvr.o nvr_at.o nvr_ps2.o sst_flash.o via_vt82c586b.o \
via_vt82c596b.o $(VNCOBJ) $(RDPOBJ)

View File

@@ -553,7 +553,7 @@ CXXFLAGS := $(CFLAGS)
#########################################################################
# 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 \
rom.o device.o nvr.o nvr_at.o nvr_ps2.o sst_flash.o via_vt82c586b.o \
via_vt82c596b.o $(VNCOBJ) $(RDPOBJ)